132e8eaf2SBenjamin Berg #include <sys/ptrace.h> 232e8eaf2SBenjamin Berg #include <sys/prctl.h> 332e8eaf2SBenjamin Berg #include <asm/unistd.h> 432e8eaf2SBenjamin Berg #include <sysdep/stub.h> 532e8eaf2SBenjamin Berg #include <stub-data.h> 632e8eaf2SBenjamin Berg 732e8eaf2SBenjamin Berg void _start(void); 832e8eaf2SBenjamin Berg 932e8eaf2SBenjamin Berg noinline static void real_init(void) 1032e8eaf2SBenjamin Berg { 1132e8eaf2SBenjamin Berg struct stub_init_data init_data; 1232e8eaf2SBenjamin Berg unsigned long res; 1332e8eaf2SBenjamin Berg struct { 1432e8eaf2SBenjamin Berg void *ss_sp; 1532e8eaf2SBenjamin Berg int ss_flags; 1632e8eaf2SBenjamin Berg size_t ss_size; 1732e8eaf2SBenjamin Berg } stack = { 1832e8eaf2SBenjamin Berg .ss_size = STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, 1932e8eaf2SBenjamin Berg }; 2032e8eaf2SBenjamin Berg struct { 2132e8eaf2SBenjamin Berg void *sa_handler_; 2232e8eaf2SBenjamin Berg unsigned long sa_flags; 2332e8eaf2SBenjamin Berg void *sa_restorer; 2432e8eaf2SBenjamin Berg unsigned long long sa_mask; 2532e8eaf2SBenjamin Berg } sa = { 2632e8eaf2SBenjamin Berg /* Need to set SA_RESTORER (but the handler never returns) */ 2732e8eaf2SBenjamin Berg .sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO | 0x04000000, 2832e8eaf2SBenjamin Berg /* no need to mask any signals */ 2932e8eaf2SBenjamin Berg .sa_mask = 0, 3032e8eaf2SBenjamin Berg }; 3132e8eaf2SBenjamin Berg 3232e8eaf2SBenjamin Berg /* set a nice name */ 3332e8eaf2SBenjamin Berg stub_syscall2(__NR_prctl, PR_SET_NAME, (unsigned long)"uml-userspace"); 3432e8eaf2SBenjamin Berg 35*801e00d3SBenjamin Berg /* Make sure this process dies if the kernel dies */ 36*801e00d3SBenjamin Berg stub_syscall2(__NR_prctl, PR_SET_PDEATHSIG, SIGKILL); 37*801e00d3SBenjamin Berg 3832e8eaf2SBenjamin Berg /* read information from STDIN and close it */ 3932e8eaf2SBenjamin Berg res = stub_syscall3(__NR_read, 0, 4032e8eaf2SBenjamin Berg (unsigned long)&init_data, sizeof(init_data)); 4132e8eaf2SBenjamin Berg if (res != sizeof(init_data)) 4232e8eaf2SBenjamin Berg stub_syscall1(__NR_exit, 10); 4332e8eaf2SBenjamin Berg 4432e8eaf2SBenjamin Berg stub_syscall1(__NR_close, 0); 4532e8eaf2SBenjamin Berg 4632e8eaf2SBenjamin Berg /* map stub code + data */ 4732e8eaf2SBenjamin Berg res = stub_syscall6(STUB_MMAP_NR, 4832e8eaf2SBenjamin Berg init_data.stub_start, UM_KERN_PAGE_SIZE, 4932e8eaf2SBenjamin Berg PROT_READ | PROT_EXEC, MAP_FIXED | MAP_SHARED, 5032e8eaf2SBenjamin Berg init_data.stub_code_fd, init_data.stub_code_offset); 5132e8eaf2SBenjamin Berg if (res != init_data.stub_start) 5232e8eaf2SBenjamin Berg stub_syscall1(__NR_exit, 11); 5332e8eaf2SBenjamin Berg 5432e8eaf2SBenjamin Berg res = stub_syscall6(STUB_MMAP_NR, 5532e8eaf2SBenjamin Berg init_data.stub_start + UM_KERN_PAGE_SIZE, 5632e8eaf2SBenjamin Berg STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, 5732e8eaf2SBenjamin Berg PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, 5832e8eaf2SBenjamin Berg init_data.stub_data_fd, init_data.stub_data_offset); 5932e8eaf2SBenjamin Berg if (res != init_data.stub_start + UM_KERN_PAGE_SIZE) 6032e8eaf2SBenjamin Berg stub_syscall1(__NR_exit, 12); 6132e8eaf2SBenjamin Berg 6232e8eaf2SBenjamin Berg /* setup signal stack inside stub data */ 6332e8eaf2SBenjamin Berg stack.ss_sp = (void *)init_data.stub_start + UM_KERN_PAGE_SIZE; 6432e8eaf2SBenjamin Berg stub_syscall2(__NR_sigaltstack, (unsigned long)&stack, 0); 6532e8eaf2SBenjamin Berg 6632e8eaf2SBenjamin Berg /* register SIGSEGV handler */ 6732e8eaf2SBenjamin Berg sa.sa_handler_ = (void *) init_data.segv_handler; 6832e8eaf2SBenjamin Berg res = stub_syscall4(__NR_rt_sigaction, SIGSEGV, (unsigned long)&sa, 0, 6932e8eaf2SBenjamin Berg sizeof(sa.sa_mask)); 7032e8eaf2SBenjamin Berg if (res != 0) 7132e8eaf2SBenjamin Berg stub_syscall1(__NR_exit, 13); 7232e8eaf2SBenjamin Berg 7332e8eaf2SBenjamin Berg stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0); 7432e8eaf2SBenjamin Berg 7532e8eaf2SBenjamin Berg stub_syscall2(__NR_kill, stub_syscall0(__NR_getpid), SIGSTOP); 7632e8eaf2SBenjamin Berg 7732e8eaf2SBenjamin Berg stub_syscall1(__NR_exit, 14); 7832e8eaf2SBenjamin Berg 7932e8eaf2SBenjamin Berg __builtin_unreachable(); 8032e8eaf2SBenjamin Berg } 8132e8eaf2SBenjamin Berg 8232e8eaf2SBenjamin Berg void _start(void) 8332e8eaf2SBenjamin Berg { 8432e8eaf2SBenjamin Berg char *alloc; 8532e8eaf2SBenjamin Berg 8632e8eaf2SBenjamin Berg /* Make enough space for the stub (including space for alignment) */ 8732e8eaf2SBenjamin Berg alloc = __builtin_alloca((1 + 2 * STUB_DATA_PAGES - 1) * UM_KERN_PAGE_SIZE); 8832e8eaf2SBenjamin Berg asm volatile("" : "+r,m"(alloc) : : "memory"); 8932e8eaf2SBenjamin Berg 9032e8eaf2SBenjamin Berg real_init(); 9132e8eaf2SBenjamin Berg } 92