Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/kernel/emulation/linux/elfcalls_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,15 @@ void __dserver_per_thread_socket_refresh(void) {
void __dserver_close_socket(int socket) {
return elfcalls()->dserver_close_socket(socket);
};

int __dserver_get_process_lifetime_pipe() {
return elfcalls()->dserver_get_process_lifetime_pipe();
}

int __dserver_process_lifetime_pipe_refresh(void) {
return elfcalls()->dserver_process_lifetime_pipe_refresh();
};

void __dserver_close_process_lifetime_pipe(int* fds) {
return elfcalls()->dserver_close_process_lifetime_pipe(fds);
};
4 changes: 4 additions & 0 deletions src/kernel/emulation/linux/elfcalls_wrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ int __dserver_per_thread_socket(void);
void __dserver_per_thread_socket_refresh(void);
void __dserver_close_socket(int socket);

int __dserver_get_process_lifetime_pipe(void);
int __dserver_process_lifetime_pipe_refresh(void);
void __dserver_close_process_lifetime_pipe(int* fds);

#ifdef __cplusplus
}
#endif
Expand Down
39 changes: 23 additions & 16 deletions src/kernel/emulation/linux/process/execve.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "../simple.h"

#include <darlingserver/rpc.h>
#include "../elfcalls_wrapper.h"
#include "../unistd/write.h"
#include <mach-o/loader.h>
#include <mach-o/fat.h>
Expand Down Expand Up @@ -48,7 +49,7 @@ long sys_execve(const char* fname, const char** argvp, const char** envp)

vc.flags = VCHROOT_FOLLOW;
vc.dfd = get_perthread_wd();

strcpy(vc.path, fname);

ret = vchroot_expand(&vc);
Expand All @@ -60,7 +61,7 @@ long sys_execve(const char* fname, const char** argvp, const char** envp)
int fd = sys_open(fname, BSD_O_RDONLY, 0);
if (fd < 0)
return fd;

ret = sys_read(fd, shebang, sizeof(shebang));
if (ret < 0)
return ret;
Expand Down Expand Up @@ -99,19 +100,19 @@ long sys_execve(const char* fname, const char** argvp, const char** envp)
nl = memchr(shebang, '\n', ret);
if (!nl)
return -ENOEXEC;

*nl = '\0';
for (i = 2; isspace(shebang[i]); i++);

interp = &shebang[i];

for (i = 0; !isspace(interp[i]) && interp[i]; i++);

if (interp[i] == '\0')
arg = NULL;
else
arg = &interp[i];

if (arg != NULL)
{
*arg = '\0'; // terminate interp
Expand All @@ -121,24 +122,24 @@ long sys_execve(const char* fname, const char** argvp, const char** envp)
if (*arg == '\0')
arg = NULL; // no argument, just whitespace
}

// Count original arguments
while (argvp[len++]);

// Allocate a new argvp
modargvp = (const char**) __builtin_alloca(sizeof(void*) * (len+3));

i = 0;
modargvp[i++] = mldr_path;
modargvp[i++] = vc.path; // expanded later
if (arg != NULL)
modargvp[i++] = arg;
modargvp[i] = fname;

// Append original arguments
for (j = 1; j < len+1; j++)
modargvp[i+j] = argvp[j];

argvp = modargvp;
strcpy(vc.path, interp);

Expand Down Expand Up @@ -181,21 +182,27 @@ long sys_execve(const char* fname, const char** argvp, const char** envp)
struct linux_sockaddr_un* server_socket_address = dserver_rpc_hooks_get_server_address();
const char* server_socket_path = server_socket_address->sun_path;

char mldr_lifetime_pipe_env[32] = { '\0' };
__simple_snprintf(mldr_lifetime_pipe_env, sizeof(mldr_lifetime_pipe_env) - 1, "__mldr_lifetime_pipe=%d", __dserver_get_process_lifetime_pipe());

// count original env vars
while (envp[len++]);

// allocate a new envp and env0
modenvp = (const char**)__builtin_alloca(sizeof(void*) * (len + 1));
const int new_env_count = 2;

// allocate a new envp and env0, env1
modenvp = (const char**)__builtin_alloca(sizeof(void*) * (len + new_env_count));
buf = __builtin_alloca(strlen(server_socket_path) + sizeof("__mldr_sockpath="));

// set up the new env0
strcpy(buf, "__mldr_sockpath=");
strcat(buf, server_socket_path);
modenvp[0] = buf;
modenvp[1] = mldr_lifetime_pipe_env;

// append original env vars
for (int i = 1; i < len+1; i++)
modenvp[i] = envp[i-1];
for (int i = new_env_count; i < len + new_env_count; i++)
modenvp[i] = envp[i-new_env_count];

envp = modenvp;
}
Expand Down
7 changes: 6 additions & 1 deletion src/kernel/emulation/linux/process/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,24 @@ long sys_fork(void)

// create a new dserver RPC socket
__dserver_per_thread_socket_refresh();
int newReadFd = __dserver_process_lifetime_pipe_refresh();

// guard it
guard_entry_options_t options;
options.close = __dserver_close_socket;
guard_table_add(__dserver_per_thread_socket(), guard_flag_prevent_close | guard_flag_close_on_fork, &options);

if (dserver_rpc_checkin(true) < 0) {
int dummy_stack_variable;
if (dserver_rpc_checkin(true, &dummy_stack_variable, newReadFd) < 0) {
// we can't do ANYTHING if darlingserver fails to acknowledge us
__simple_printf("Failed to checkin with darlingserver after fork\n");
__simple_abort();
}
if (wdfd >= 0)
sys_fchdir(wdfd);

int pipe[2] = { newReadFd, -1 };
__dserver_close_process_lifetime_pipe(pipe);
}

return ret;
Expand Down
26 changes: 26 additions & 0 deletions src/startup/mldr/elfcalls/elfcalls.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,28 @@ static const void* __dserver_socket_address(void) {

extern void __mldr_close_rpc_socket(int socket);

extern int __mldr_create_process_lifetime_pipe(int* fds);
extern void __mldr_close_process_lifetime_pipe(int* fds);
extern int __dserver_process_lifetime_pipe_fd;

static int __dserver_get_process_lifetime_pipe() {
return __dserver_process_lifetime_pipe_fd;
}

static int __dserver_process_lifetime_pipe_refresh() {
// the read end has already been closed.
int pipe[2] = { -1, __dserver_process_lifetime_pipe_fd };
__mldr_close_process_lifetime_pipe(pipe);

if (__mldr_create_process_lifetime_pipe(pipe) == -1) {
fprintf(stderr, "Failed to create process lifetime pipe: %d (%s)\n", errno, strerror(errno));
abort();
}

__dserver_process_lifetime_pipe_fd = pipe[1];
return pipe[0];
}

void elfcalls_make(struct elf_calls* calls)
{
calls->dlopen = dlopen_simple;
Expand Down Expand Up @@ -98,4 +120,8 @@ void elfcalls_make(struct elf_calls* calls)
calls->dserver_per_thread_socket = __darling_thread_rpc_socket;
calls->dserver_per_thread_socket_refresh = __darling_thread_rpc_socket_refresh;
calls->dserver_close_socket = __mldr_close_rpc_socket;

calls->dserver_get_process_lifetime_pipe = __dserver_get_process_lifetime_pipe;
calls->dserver_process_lifetime_pipe_refresh = __dserver_process_lifetime_pipe_refresh;
calls->dserver_close_process_lifetime_pipe = __mldr_close_process_lifetime_pipe;
}
5 changes: 5 additions & 0 deletions src/startup/mldr/elfcalls/elfcalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ struct elf_calls
int (*dserver_per_thread_socket)(void);
void (*dserver_per_thread_socket_refresh)(void);
void (*dserver_close_socket)(int socket);

// darlingserver process lifetime pipe info
int (*dserver_get_process_lifetime_pipe)(void);
int (*dserver_process_lifetime_pipe_refresh)(void);
void (*dserver_close_process_lifetime_pipe)(int* fds);
};

#endif
Expand Down
12 changes: 7 additions & 5 deletions src/startup/mldr/elfcalls/threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ void* __darling_thread_create(unsigned long stack_size, unsigned long pth_obj_si
}

args.stack_bottom = args.stack_addr - stack_size;

// pthread_attr_setstack is buggy. The documentation states we should provide the lowest
// address of the stack, yet some versions regard it as the highest address instead.
// Therefore it's better to just make the pthread stack as small as possible and then switch
Expand All @@ -191,7 +191,7 @@ void* __darling_thread_create(unsigned long stack_size, unsigned long pth_obj_si
args.pth = pth;
pthread_create(&nativeLibcThread, &attr, darling_thread_entry, &args);
pthread_attr_destroy(&attr);

while (args.pth != NULL)
sched_yield();

Expand All @@ -202,7 +202,7 @@ static void* darling_thread_entry(void* p)
{
struct arg_struct* in_args = (struct arg_struct*) p;
struct arg_struct args;

memcpy(&args, in_args, sizeof(args));

dthread_t dthread = args.pth;
Expand All @@ -229,7 +229,9 @@ static void* darling_thread_entry(void* p)
*flags |= args.is_workqueue ? DWQ_FLAG_THREAD_TSD_BASE_SET : DTHREAD_START_TSD_BASE_SET;

// let's check-in with darlingserver on this new thread
if (dserver_rpc_explicit_checkin(t_server_socket, false) < 0) {
int dummy_stack_variable;
// the lifetime pipe fd is ignored as the proces should already have been registered
if (dserver_rpc_explicit_checkin(t_server_socket, false, &dummy_stack_variable, -1) < 0) {
// we can't do ANYTHING if darlingserver doesn't acknowledge us successfully
abort();
}
Expand Down Expand Up @@ -327,7 +329,7 @@ int __darling_thread_terminate(void* stackaddr,
// Let's just hang around forever.
sigset_t mask;
memset(&mask, 0, sizeof(mask));

while (1)
sigsuspend(&mask);
}
Expand Down
9 changes: 5 additions & 4 deletions src/startup/mldr/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
static int native_prot(int prot);
static void load(const char* path, cpu_type_t cpu, bool expect_dylinker, char** argv, struct load_results* lr);
static void setup_space(struct load_results* lr, bool is_64_bit);
static void* compatible_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

#ifndef PAGE_SIZE
# define PAGE_SIZE 4096
Expand Down Expand Up @@ -171,7 +172,7 @@ void FUNCTION_NAME(int fd, bool expect_dylinker, struct load_results* lr)
addr += slide;

// Some segments' filesize != vmsize, thus this mprotect().
rv = mmap((void*)addr, seg->vmsize, useprot, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0);
rv = compatible_mmap((void*)addr, seg->vmsize, useprot, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0);
if (rv == (void*)MAP_FAILED)
{
if (seg->vmaddr == 0 && useprot == 0) {
Expand All @@ -187,7 +188,7 @@ void FUNCTION_NAME(int fd, bool expect_dylinker, struct load_results* lr)
else
{
size_t size = seg->vmsize - seg->filesize;
rv = mmap((void*) PAGE_ALIGN(seg->vmaddr + seg->vmsize - size), PAGE_ROUNDUP(size), useprot,
rv = compatible_mmap((void*) PAGE_ALIGN(seg->vmaddr + seg->vmsize - size), PAGE_ROUNDUP(size), useprot,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE, -1, 0);
if (rv == (void*)MAP_FAILED)
{
Expand All @@ -210,7 +211,7 @@ void FUNCTION_NAME(int fd, bool expect_dylinker, struct load_results* lr)
if (seg->filesize < seg->vmsize) {
flag = MAP_FIXED;
}
rv = mmap((void*)addr, seg->filesize, useprot,
rv = compatible_mmap((void*)addr, seg->filesize, useprot,
flag | MAP_PRIVATE, fd, seg->fileoff + fat_offset);
if (rv == (void*)MAP_FAILED)
{
Expand All @@ -223,7 +224,7 @@ void FUNCTION_NAME(int fd, bool expect_dylinker, struct load_results* lr)
exit(1);
}
}

if (seg->fileoff == 0)
mappedHeader = (struct MACH_HEADER_STRUCT*) (seg->vmaddr + slide);
}
Expand Down
1 change: 1 addition & 0 deletions src/startup/mldr/loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ struct load_results {
unsigned long stack_top;
char* socket_path;
int kernfd;
int lifetime_pipe;

size_t argc;
size_t envc;
Expand Down
Loading