static long dune_clone(struct dune_tf *tf) { unsigned long fs; int rc; unsigned long pc; rdmsrl(MSR_GS_BASE, pc); if (ARG1(tf) != 0) return dune_pthread_create(tf); fs = dune_get_user_fs(); rc = syscall(SYS_clone, ARG0(tf), ARG1(tf), ARG2(tf), ARG3(tf), ARG4(tf)); if (rc < 0) return -errno; if (rc == 0) { dune_enter(); dune_set_user_fs(fs); } return rc; }
int boxer_main(int argc, char *argv[]) { int ret; uintptr_t sp; struct elf_data data; if (argc < 2) return -EINVAL; /* XXX needed. Probably does some libc stuff */ printf(" \b"); // printf("%s\n", environ[0]); ret = dune_init(0); if (ret) { printf("sandbox: failed to initialize Dune\n"); return ret; } ret = dune_enter(); if (ret) { printf("sandbox: failed to enter Dune mode\n"); return ret; } ret = load_elf(argv[1], &data); if (ret) return ret; // printf("sandbox: entry addr is %lx\n", data.entry); dune_set_user_fs(0); // default starting fs ret = trap_init(); if (ret) { printf("failed to initialize trap handlers\n"); return ret; } ret = umm_alloc_stack(&sp); if (ret) { printf("failed to alloc stack\n"); return ret; } sp = setup_arguments(sp, argv[1], &argv[2], environ, data); if (!sp) { printf("failed to setup arguments\n"); return -EINVAL; } ret = run_app(sp, data.entry); return ret; }
void *pthread_entry(void *arg) { struct thread_arg *a = arg; struct dune_tf *tf = a->ta_tf; struct dune_tf child_tf; int *tidp = NULL; pid_t tid; int flags = ARG0(tf); if (!a->dune_started) dune_enter(); tid = syscall(SYS_gettid); /* XXX validate */ /* set up tls */ if (flags & CLONE_SETTLS) dune_set_user_fs(ARG4(tf)); if (flags & CLONE_PARENT_SETTID) { tidp = (int *) ARG2(tf); *tidp = tid; } if (flags & CLONE_CHILD_CLEARTID) { tidp = (int *) ARG3(tf); syscall(SYS_set_tid_address, tidp); } /* enter thread */ memcpy(&child_tf, tf, sizeof(child_tf)); child_tf.rip = tf->rip; child_tf.rax = 0; child_tf.rsp = ARG1(tf); /* tell parent tid */ pthread_mutex_lock(&a->ta_mtx); a->ta_tid = tid; pthread_mutex_unlock(&a->ta_mtx); pthread_cond_signal(&a->ta_cnd); do_enter_thread(&child_tf); return NULL; }
static void syscall_do_foreal(struct dune_tf *tf) { switch (tf->rax) { case SYS_arch_prctl: switch (ARG0(tf)) { case ARCH_GET_FS: *((unsigned long*) ARG1(tf)) = dune_get_user_fs(); tf->rax = 0; break; case ARCH_SET_FS: dune_set_user_fs(ARG1(tf)); tf->rax = 0; break; default: tf->rax = -EINVAL; break; } break; case SYS_brk: tf->rax = umm_brk((unsigned long) ARG0(tf)); break; case SYS_mmap: tf->rax = (unsigned long) umm_mmap((void *) ARG0(tf), (size_t) ARG1(tf), (int) ARG2(tf), (int) ARG3(tf), (int) ARG4(tf), (off_t) ARG5(tf)); break; case SYS_mprotect: tf->rax = umm_mprotect((void *) ARG0(tf), (size_t) ARG1(tf), ARG2(tf)); break; case SYS_munmap: tf->rax = umm_munmap((void *) ARG0(tf), (size_t) ARG1(tf)); break; case SYS_mremap: tf->rax = (unsigned long) umm_mremap((void*) ARG0(tf), (size_t) ARG1(tf), (size_t) ARG2(tf), (int) ARG3(tf), (void*) ARG4(tf)); break; case SYS_shmat: tf->rax = (unsigned long) umm_shmat((int) ARG0(tf), (void*) ARG1(tf), (int) ARG2(tf)); break; case SYS_clone: tf->rax = dune_clone(tf); break; case SYS_execve: tf->rax = exec_execev((const char *)ARG0(tf), (char **const)ARG1(tf), (char **const)ARG2(tf)); break; /* ignore signals for now */ case SYS_rt_sigaction: case SYS_rt_sigprocmask: tf->rax = 0; break; case SYS_sigaltstack: case SYS_signalfd: case SYS_signalfd4: case SYS_rt_sigpending: case SYS_rt_sigreturn: case SYS_rt_sigsuspend: case SYS_rt_sigqueueinfo: case SYS_rt_sigtimedwait: tf->rax = -ENOSYS; break; case SYS_exit_group: case SYS_exit: dune_ret_from_user(ARG0(tf)); break; default: dune_passthrough_syscall(tf); break; } }