diff --git a/LibOS/shim/include/shim_tls.h b/LibOS/shim/include/shim_tls.h index a2c34ad0..60ec3ad6 100644 --- a/LibOS/shim/include/shim_tls.h +++ b/LibOS/shim/include/shim_tls.h @@ -93,6 +93,8 @@ typedef struct #include +void init_tcb (shim_tcb_t * tcb); + static inline bool shim_tls_check_canary(void) { uint64_t __canary; diff --git a/LibOS/shim/src/bookkeep/shim_thread.c b/LibOS/shim/src/bookkeep/shim_thread.c index 947dbb68..df8203ad 100644 --- a/LibOS/shim/src/bookkeep/shim_thread.c +++ b/LibOS/shim/src/bookkeep/shim_thread.c @@ -713,7 +713,7 @@ int resume_wrapper (void * param) struct shim_thread * thread = (struct shim_thread *) param; assert(thread); - __libc_tcb_t * libc_tcb = (__libc_tcb_t *) thread->tcb; + __libc_tcb_t * libc_tcb = thread->tcb; assert(libc_tcb); shim_tcb_t * tcb = &libc_tcb->shim_tcb; assert(tcb->context.sp); @@ -738,6 +738,12 @@ BEGIN_RS_FUNC(running_thread) if (!thread->user_tcb) CP_REBASE(thread->tcb); + if (thread->set_child_tid) { + /* CLONE_CHILD_SETTID */ + *thread->set_child_tid = thread->tid; + thread->set_child_tid = NULL; + } + thread->signal_logs = malloc(sizeof(struct shim_signal_log) * NUM_SIGS); @@ -760,6 +766,16 @@ BEGIN_RS_FUNC(running_thread) debug_setprefix(tcb); debug("after resume, set tcb to %p\n", libc_tcb); } else { + /* + * In execve case, the following holds: + * stack = NULL + * stack_top = NULL + * frameptr = NULL + * tcb = NULL + * user_tcb = false + * in_vm = false + */ + init_tcb(shim_libc_tcb()->tcb); set_cur_thread(thread); } diff --git a/LibOS/shim/src/sys/shim_clone.c b/LibOS/shim/src/sys/shim_clone.c index 21247243..54eef8a4 100644 --- a/LibOS/shim/src/sys/shim_clone.c +++ b/LibOS/shim/src/sys/shim_clone.c @@ -138,11 +138,11 @@ int clone_implementation_wrapper(struct clone_args * arg) debug_setbuf(tcb, true); debug("set tcb to %p (stack allocated? %d)\n", my_thread->tcb, stack_allocated); - struct shim_regs regs; - regs = *arg->parent->tcb->shim_tcb.context.regs; - - if (my_thread->set_child_tid) + struct shim_regs regs = *arg->parent->tcb->shim_tcb.context.regs; + if (my_thread->set_child_tid) { *(my_thread->set_child_tid) = my_thread->tid; + my_thread->set_child_tid = NULL; + } void * stack = arg->stack; void * return_pc = arg->return_pc; @@ -221,6 +221,49 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr, if (!(flags & CLONE_SYSVSEM)) debug("clone without CLONE_SYSVSEM is not yet implemented\n"); + /* currently unsupported flags. + * Please update this once you added new flags support. + */ + const int unsupported_flags = +#ifdef CLONE_PIDFD + CLONE_PIDFD | +#endif + CLONE_VFORK | /* vfork is handled above */ + CLONE_PARENT | + CLONE_NEWNS | + CLONE_UNTRACED | + CLONE_NEWCGROUP | + CLONE_NEWUTS | + CLONE_NEWIPC | + CLONE_NEWUSER | + CLONE_NEWPID | + CLONE_NEWNET | + CLONE_IO; + if (flags & unsupported_flags) + debug("clone with flags 0x%x is not yet implemented\n", + flags & unsupported_flags); + + if ((flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) + return -EINVAL; + if ((flags & (CLONE_NEWUSER|CLONE_FS)) == (CLONE_NEWUSER|CLONE_FS)) + return -EINVAL; + if ((flags & CLONE_THREAD) && !(flags & CLONE_SIGHAND)) + return -EINVAL; + if ((flags & CLONE_SIGHAND) && !(flags & CLONE_VM)) + return -EINVAL; + if (flags & CLONE_THREAD && (flags & (CLONE_NEWUSER | CLONE_NEWPID))) + return -EINVAL; +#ifdef CLONE_PIDFD + if (flags & CLONE_PIDFD) { + if (flags & (CLONE_DETACHED | CLONE_PARENT_SETTID | CLONE_THREAD)) + return -EINVAL; + if (test_user_memory(parent_tidptr, sizeof(*parent_tidptr), false)) + return -EFAULT; + if (*parent_tidptr != 0) + return -EINVAL; + } +#endif + if (flags & CLONE_PARENT_SETTID) { if (!parent_tidptr) return -EINVAL; @@ -286,6 +329,7 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr, thread->tcb = tcb = self->tcb; old_shim_tcb = __alloca(sizeof(shim_tcb_t)); memcpy(old_shim_tcb, &tcb->shim_tcb, sizeof(shim_tcb_t)); + thread->user_tcb = self->user_tcb; } if (user_stack_addr) { @@ -302,16 +346,17 @@ int shim_do_clone (int flags, void * user_stack_addr, int * parent_tidptr, add_thread(thread); set_as_child(self, thread); - if ((ret = do_migrate_process(&migrate_fork, NULL, NULL, thread)) < 0) - goto failed; - + ret = do_migrate_process(&migrate_fork, NULL, NULL, thread); if (old_shim_tcb) - memcpy(&tcb->shim_tcb, old_shim_tcb, sizeof(shim_tcb_t)); + memcpy(&tcb->shim_tcb, old_shim_tcb, sizeof(tcb->shim_tcb)); + if (ret < 0) + goto failed; lock(thread->lock); handle_map = thread->handle_map; thread->handle_map = NULL; unlock(thread->lock); + if (handle_map) put_handle_map(handle_map);