1 #include <sys/ptrace.h>
2 #include <sys/prctl.h>
3 #include <asm/unistd.h>
4 #include <sysdep/stub.h>
5 #include <stub-data.h>
6
7 void _start(void);
8
real_init(void)9 noinline static void real_init(void)
10 {
11 struct stub_init_data init_data;
12 unsigned long res;
13 struct {
14 void *ss_sp;
15 int ss_flags;
16 size_t ss_size;
17 } stack = {
18 .ss_size = STUB_DATA_PAGES * UM_KERN_PAGE_SIZE,
19 };
20 struct {
21 void *sa_handler_;
22 unsigned long sa_flags;
23 void *sa_restorer;
24 unsigned long long sa_mask;
25 } sa = {
26 /* Need to set SA_RESTORER (but the handler never returns) */
27 .sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO | 0x04000000,
28 /* no need to mask any signals */
29 .sa_mask = 0,
30 };
31
32 /* set a nice name */
33 stub_syscall2(__NR_prctl, PR_SET_NAME, (unsigned long)"uml-userspace");
34
35 /* Make sure this process dies if the kernel dies */
36 stub_syscall2(__NR_prctl, PR_SET_PDEATHSIG, SIGKILL);
37
38 /* read information from STDIN and close it */
39 res = stub_syscall3(__NR_read, 0,
40 (unsigned long)&init_data, sizeof(init_data));
41 if (res != sizeof(init_data))
42 stub_syscall1(__NR_exit, 10);
43
44 stub_syscall1(__NR_close, 0);
45
46 /* map stub code + data */
47 res = stub_syscall6(STUB_MMAP_NR,
48 init_data.stub_start, UM_KERN_PAGE_SIZE,
49 PROT_READ | PROT_EXEC, MAP_FIXED | MAP_SHARED,
50 init_data.stub_code_fd, init_data.stub_code_offset);
51 if (res != init_data.stub_start)
52 stub_syscall1(__NR_exit, 11);
53
54 res = stub_syscall6(STUB_MMAP_NR,
55 init_data.stub_start + UM_KERN_PAGE_SIZE,
56 STUB_DATA_PAGES * UM_KERN_PAGE_SIZE,
57 PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
58 init_data.stub_data_fd, init_data.stub_data_offset);
59 if (res != init_data.stub_start + UM_KERN_PAGE_SIZE)
60 stub_syscall1(__NR_exit, 12);
61
62 /* setup signal stack inside stub data */
63 stack.ss_sp = (void *)init_data.stub_start + UM_KERN_PAGE_SIZE;
64 stub_syscall2(__NR_sigaltstack, (unsigned long)&stack, 0);
65
66 /* register SIGSEGV handler */
67 sa.sa_handler_ = (void *) init_data.segv_handler;
68 res = stub_syscall4(__NR_rt_sigaction, SIGSEGV, (unsigned long)&sa, 0,
69 sizeof(sa.sa_mask));
70 if (res != 0)
71 stub_syscall1(__NR_exit, 13);
72
73 stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
74
75 stub_syscall2(__NR_kill, stub_syscall0(__NR_getpid), SIGSTOP);
76
77 stub_syscall1(__NR_exit, 14);
78
79 __builtin_unreachable();
80 }
81
_start(void)82 __attribute__((naked)) void _start(void)
83 {
84 /*
85 * Since the stack after exec() starts at the top-most address,
86 * but that's exactly where we also want to map the stub data
87 * and code, this must:
88 * - push the stack by 1 code and STUB_DATA_PAGES data pages
89 * - call real_init()
90 * This way, real_init() can use the stack normally, while the
91 * original stack further down (higher address) will become
92 * inaccessible after the mmap() calls above.
93 */
94 stub_start(real_init);
95 }
96