From 3776e014ddd64ff8e148f3a95e203884d7c8314f Mon Sep 17 00:00:00 2001 From: Isaku Yamahata Date: Tue, 23 Apr 2019 16:51:16 -0700 Subject: [PATCH] [Pal/FreeBSD] specify loaded address of exec in child process This is the FreeBSD version of https://reviewable.io/reviews/oscarlab/graphene/372 I haven't tested this PR. Signed-off-by: Isaku Yamahata --- Pal/src/host/FreeBSD/db_files.c | 11 +++++++++++ Pal/src/host/FreeBSD/db_main.c | 4 ++++ Pal/src/host/FreeBSD/db_process.c | 15 +++++++++++++++ Pal/src/host/FreeBSD/pal_host.h | 6 ++++++ 4 files changed, 36 insertions(+) diff --git a/Pal/src/host/FreeBSD/db_files.c b/Pal/src/host/FreeBSD/db_files.c index 69890ef0..576e18a3 100644 --- a/Pal/src/host/FreeBSD/db_files.c +++ b/Pal/src/host/FreeBSD/db_files.c @@ -63,6 +63,7 @@ static int file_open (PAL_HANDLE * handle, const char * type, const char * uri, hdl->file.offset = 0; hdl->file.append = 0; hdl->file.pass = 0; + hdl->file.map_start = NULL; char * path = (void *) hdl + HANDLE_SIZE(file); memcpy(path, uri, len + 1); hdl->file.realpath = path; @@ -154,6 +155,16 @@ static int file_map (PAL_HANDLE handle, void ** addr, int prot, { int fd = handle->file.fd; void * mem = *addr; + /* + * work around for fork emulation + * the first exec image to be loaded has to be at same address + * as parent. + */ + if (mem == NULL && handle->file.map_start != NULL) { + mem = (PAL_PTR)handle->file.map_start; + /* this address is used. don't over-map it later */ + handle->file.map_start = NULL; + } int flags = MAP_FILE|HOST_FLAGS(0, prot)|(mem ? MAP_FIXED : 0); prot = HOST_PROT(prot); diff --git a/Pal/src/host/FreeBSD/db_main.c b/Pal/src/host/FreeBSD/db_main.c index 70a4fc86..9368b344 100644 --- a/Pal/src/host/FreeBSD/db_main.c +++ b/Pal/src/host/FreeBSD/db_main.c @@ -242,6 +242,10 @@ void pal_bsd_main (void * args) SET_HANDLE_TYPE(file, file); file->hdr.flags |= RFD(0)|WFD(0)|WRITEABLE(0); file->file.fd = fd; + file->file.offset = 0; + file->file.append = false; + file->file.pass = false; + file->file.map_start = NULL; char * path = (void *) file + HANDLE_SIZE(file); get_norm_path(argv[0], path, 0, len + 1); file->file.realpath = path; diff --git a/Pal/src/host/FreeBSD/db_process.c b/Pal/src/host/FreeBSD/db_process.c index 8f202085..d1d03b7d 100644 --- a/Pal/src/host/FreeBSD/db_process.c +++ b/Pal/src/host/FreeBSD/db_process.c @@ -36,6 +36,7 @@ #include "pal_debug.h" #include "pal_error.h" #include "pal_security.h" +#include "pal_rtld.h" #include "api.h" #include @@ -169,6 +170,20 @@ int _DkProcessCreate (PAL_HANDLE * handle, const char * uri, const char ** args) return ret; handle_set_cloexec(exec, true); + + /* If this process creation is for fork emulation, + * map address of executable is already determined. + * tell its address to forked process. + */ + size_t len; + const char * file_uri = "file:"; + if (exec_map && exec_map->l_name && + (len = strlen(uri)) >= 5 && !memcmp(uri, file_uri, 5) && + /* skip "file:"*/ + strlen(exec_map->l_name) == len - 5 && + /* + 1 for lasting * NUL */ + !memcmp(exec_map->l_name, uri + 5, len - 5 + 1)) + exec->file.map_start = (PAL_PTR)exec_map->l_map_start; } /* step 2: create parant and child process handle */ diff --git a/Pal/src/host/FreeBSD/pal_host.h b/Pal/src/host/FreeBSD/pal_host.h index 0c01b0c0..dd0ba6cc 100644 --- a/Pal/src/host/FreeBSD/pal_host.h +++ b/Pal/src/host/FreeBSD/pal_host.h @@ -76,6 +76,12 @@ typedef union pal_handle PAL_BOL append; PAL_BOL pass; PAL_STR realpath; + /* + * map_start is to request this file should be mapped to this + * address. When fork is emulated, the address is already + * determined by parent process. + */ + PAL_PTR map_start; } file; struct {