Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
 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
 7void _start(void);
 8
 9noinline 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}