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
real_init(void)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
35801e00d3SBenjamin Berg /* Make sure this process dies if the kernel dies */
36801e00d3SBenjamin Berg stub_syscall2(__NR_prctl, PR_SET_PDEATHSIG, SIGKILL);
37801e00d3SBenjamin 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
_start(void)828508a5e0SDavid Gow __attribute__((naked)) void _start(void)
8332e8eaf2SBenjamin Berg {
84*14d4a7b5SJohannes Berg /*
85*14d4a7b5SJohannes Berg * Since the stack after exec() starts at the top-most address,
86*14d4a7b5SJohannes Berg * but that's exactly where we also want to map the stub data
87*14d4a7b5SJohannes Berg * and code, this must:
88*14d4a7b5SJohannes Berg * - push the stack by 1 code and STUB_DATA_PAGES data pages
89*14d4a7b5SJohannes Berg * - call real_init()
90*14d4a7b5SJohannes Berg * This way, real_init() can use the stack normally, while the
91*14d4a7b5SJohannes Berg * original stack further down (higher address) will become
92*14d4a7b5SJohannes Berg * inaccessible after the mmap() calls above.
93*14d4a7b5SJohannes Berg */
94*14d4a7b5SJohannes Berg stub_start(real_init);
9532e8eaf2SBenjamin Berg }
96