xref: /linux/arch/um/kernel/skas/stub_exe.c (revision c34e9ab9a612ee8b18273398ef75c207b01f516d)
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 
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 
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