[LibOS] Fix clone(!CLONE_VM) used as alternative to fork()

This commit is contained in:
Isaku Yamahata
2019-05-22 03:51:40 -07:00
committed by Dmitrii Kuvaiskii
parent 086b997792
commit eecf594064
3 changed files with 72 additions and 9 deletions
+2
View File
@@ -93,6 +93,8 @@ typedef struct
#include <stddef.h>
void init_tcb (shim_tcb_t * tcb);
static inline bool shim_tls_check_canary(void)
{
uint64_t __canary;
+17 -1
View File
@@ -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);
}
+53 -8
View File
@@ -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);