1*32e8eaf2SBenjamin Berg #include <sys/ptrace.h> 2*32e8eaf2SBenjamin Berg #include <sys/prctl.h> 3*32e8eaf2SBenjamin Berg #include <asm/unistd.h> 4*32e8eaf2SBenjamin Berg #include <sysdep/stub.h> 5*32e8eaf2SBenjamin Berg #include <stub-data.h> 6*32e8eaf2SBenjamin Berg 7*32e8eaf2SBenjamin Berg void _start(void); 8*32e8eaf2SBenjamin Berg 9*32e8eaf2SBenjamin Berg noinline static void real_init(void) 10*32e8eaf2SBenjamin Berg { 11*32e8eaf2SBenjamin Berg struct stub_init_data init_data; 12*32e8eaf2SBenjamin Berg unsigned long res; 13*32e8eaf2SBenjamin Berg struct { 14*32e8eaf2SBenjamin Berg void *ss_sp; 15*32e8eaf2SBenjamin Berg int ss_flags; 16*32e8eaf2SBenjamin Berg size_t ss_size; 17*32e8eaf2SBenjamin Berg } stack = { 18*32e8eaf2SBenjamin Berg .ss_size = STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, 19*32e8eaf2SBenjamin Berg }; 20*32e8eaf2SBenjamin Berg struct { 21*32e8eaf2SBenjamin Berg void *sa_handler_; 22*32e8eaf2SBenjamin Berg unsigned long sa_flags; 23*32e8eaf2SBenjamin Berg void *sa_restorer; 24*32e8eaf2SBenjamin Berg unsigned long long sa_mask; 25*32e8eaf2SBenjamin Berg } sa = { 26*32e8eaf2SBenjamin Berg /* Need to set SA_RESTORER (but the handler never returns) */ 27*32e8eaf2SBenjamin Berg .sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO | 0x04000000, 28*32e8eaf2SBenjamin Berg /* no need to mask any signals */ 29*32e8eaf2SBenjamin Berg .sa_mask = 0, 30*32e8eaf2SBenjamin Berg }; 31*32e8eaf2SBenjamin Berg 32*32e8eaf2SBenjamin Berg /* set a nice name */ 33*32e8eaf2SBenjamin Berg stub_syscall2(__NR_prctl, PR_SET_NAME, (unsigned long)"uml-userspace"); 34*32e8eaf2SBenjamin Berg 35*32e8eaf2SBenjamin Berg /* read information from STDIN and close it */ 36*32e8eaf2SBenjamin Berg res = stub_syscall3(__NR_read, 0, 37*32e8eaf2SBenjamin Berg (unsigned long)&init_data, sizeof(init_data)); 38*32e8eaf2SBenjamin Berg if (res != sizeof(init_data)) 39*32e8eaf2SBenjamin Berg stub_syscall1(__NR_exit, 10); 40*32e8eaf2SBenjamin Berg 41*32e8eaf2SBenjamin Berg stub_syscall1(__NR_close, 0); 42*32e8eaf2SBenjamin Berg 43*32e8eaf2SBenjamin Berg /* map stub code + data */ 44*32e8eaf2SBenjamin Berg res = stub_syscall6(STUB_MMAP_NR, 45*32e8eaf2SBenjamin Berg init_data.stub_start, UM_KERN_PAGE_SIZE, 46*32e8eaf2SBenjamin Berg PROT_READ | PROT_EXEC, MAP_FIXED | MAP_SHARED, 47*32e8eaf2SBenjamin Berg init_data.stub_code_fd, init_data.stub_code_offset); 48*32e8eaf2SBenjamin Berg if (res != init_data.stub_start) 49*32e8eaf2SBenjamin Berg stub_syscall1(__NR_exit, 11); 50*32e8eaf2SBenjamin Berg 51*32e8eaf2SBenjamin Berg res = stub_syscall6(STUB_MMAP_NR, 52*32e8eaf2SBenjamin Berg init_data.stub_start + UM_KERN_PAGE_SIZE, 53*32e8eaf2SBenjamin Berg STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, 54*32e8eaf2SBenjamin Berg PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, 55*32e8eaf2SBenjamin Berg init_data.stub_data_fd, init_data.stub_data_offset); 56*32e8eaf2SBenjamin Berg if (res != init_data.stub_start + UM_KERN_PAGE_SIZE) 57*32e8eaf2SBenjamin Berg stub_syscall1(__NR_exit, 12); 58*32e8eaf2SBenjamin Berg 59*32e8eaf2SBenjamin Berg /* setup signal stack inside stub data */ 60*32e8eaf2SBenjamin Berg stack.ss_sp = (void *)init_data.stub_start + UM_KERN_PAGE_SIZE; 61*32e8eaf2SBenjamin Berg stub_syscall2(__NR_sigaltstack, (unsigned long)&stack, 0); 62*32e8eaf2SBenjamin Berg 63*32e8eaf2SBenjamin Berg /* register SIGSEGV handler */ 64*32e8eaf2SBenjamin Berg sa.sa_handler_ = (void *) init_data.segv_handler; 65*32e8eaf2SBenjamin Berg res = stub_syscall4(__NR_rt_sigaction, SIGSEGV, (unsigned long)&sa, 0, 66*32e8eaf2SBenjamin Berg sizeof(sa.sa_mask)); 67*32e8eaf2SBenjamin Berg if (res != 0) 68*32e8eaf2SBenjamin Berg stub_syscall1(__NR_exit, 13); 69*32e8eaf2SBenjamin Berg 70*32e8eaf2SBenjamin Berg stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0); 71*32e8eaf2SBenjamin Berg 72*32e8eaf2SBenjamin Berg stub_syscall2(__NR_kill, stub_syscall0(__NR_getpid), SIGSTOP); 73*32e8eaf2SBenjamin Berg 74*32e8eaf2SBenjamin Berg stub_syscall1(__NR_exit, 14); 75*32e8eaf2SBenjamin Berg 76*32e8eaf2SBenjamin Berg __builtin_unreachable(); 77*32e8eaf2SBenjamin Berg } 78*32e8eaf2SBenjamin Berg 79*32e8eaf2SBenjamin Berg void _start(void) 80*32e8eaf2SBenjamin Berg { 81*32e8eaf2SBenjamin Berg char *alloc; 82*32e8eaf2SBenjamin Berg 83*32e8eaf2SBenjamin Berg /* Make enough space for the stub (including space for alignment) */ 84*32e8eaf2SBenjamin Berg alloc = __builtin_alloca((1 + 2 * STUB_DATA_PAGES - 1) * UM_KERN_PAGE_SIZE); 85*32e8eaf2SBenjamin Berg asm volatile("" : "+r,m"(alloc) : : "memory"); 86*32e8eaf2SBenjamin Berg 87*32e8eaf2SBenjamin Berg real_init(); 88*32e8eaf2SBenjamin Berg } 89