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