1 #include "libc.h"
2 #include "threads_impl.h"
3 #include "setjmp_impl.h"
4 #include "zircon_impl.h"
5 #include <elf.h>
6 #include <stdatomic.h>
7 #include <string.h>
8
9 #include <zircon/sanitizer.h>
10 #include <zircon/syscalls.h>
11 #include <runtime/message.h>
12 #include <runtime/processargs.h>
13 #include <runtime/thread.h>
14
15 struct start_params {
16 int (*main)(int, char**, char**);
17 thrd_t td;
18 uint8_t* buffer;
19 zx_proc_args_t* procargs;
20 zx_handle_t* handles;
21 uint32_t* handle_info;
22 uint32_t nbytes, nhandles;
23 };
24
25 // This gets called via inline assembly below, after switching onto
26 // the newly-allocated (safe) stack.
27 static _Noreturn void start_main(const struct start_params*)
28 __asm__("start_main") __attribute__((used));
start_main(const struct start_params * p)29 static void start_main(const struct start_params* p) {
30 uint32_t argc = p->procargs->args_num;
31 uint32_t envc = p->procargs->environ_num;
32 uint32_t namec = p->procargs->names_num;
33
34 // Use a single contiguous buffer for argv and envp, with two
35 // extra words of terminator on the end. In traditional Unix
36 // process startup, the stack contains argv followed immediately
37 // by envp and that's followed immediately by the auxiliary vector
38 // (auxv), which is in two-word pairs and terminated by zero
39 // words. Some crufty programs might assume some of that layout,
40 // and it costs us nothing to stay consistent with it here.
41 char* args_and_environ[argc + 1 + envc + 1 + 2];
42 char** argv = &args_and_environ[0];
43 __environ = &args_and_environ[argc + 1];
44 char** dummy_auxv = &args_and_environ[argc + 1 + envc + 1];
45 dummy_auxv[0] = dummy_auxv[1] = 0;
46
47 char* names[namec + 1];
48 zx_status_t status = zxr_processargs_strings(p->buffer, p->nbytes,
49 argv, __environ, names);
50 if (status != ZX_OK) {
51 argc = namec = 0;
52 argv = __environ = NULL;
53 }
54
55 __sanitizer_startup_hook(argc, argv, __environ,
56 p->td->safe_stack.iov_base,
57 p->td->safe_stack.iov_len);
58
59 // Allow companion libraries a chance to claim handles, zeroing out
60 // handles[i] and handle_info[i] for handles they claim.
61 if (&__libc_extensions_init != NULL) {
62 __libc_extensions_init(p->nhandles, p->handles, p->handle_info,
63 namec, names);
64 }
65
66 // Give any unclaimed handles to zx_take_startup_handle(). This function
67 // takes ownership of the data, but not the memory: it assumes that the
68 // arrays are valid as long as the process is alive.
69 __libc_startup_handles_init(p->nhandles, p->handles, p->handle_info);
70
71 // Run static constructors et al.
72 __libc_start_init();
73
74 // Pass control to the application.
75 exit((*p->main)(argc, argv, __environ));
76 }
77
__libc_start_main(void * arg,int (* main)(int,char **,char **))78 __NO_SAFESTACK _Noreturn void __libc_start_main(
79 void* arg, int (*main)(int, char**, char**)) {
80
81 // Initialize stack-protector canary value first thing. Do the setjmp
82 // manglers in the same call to avoid the overhead of two system calls.
83 // That means we need a temporary buffer on the stack, which we then
84 // want to clear out so the values don't leak there.
85 struct randoms {
86 uintptr_t stack_guard;
87 struct setjmp_manglers setjmp_manglers;
88 } randoms;
89 static_assert(sizeof(randoms) <= ZX_CPRNG_DRAW_MAX_LEN, "");
90 _zx_cprng_draw(&randoms, sizeof(randoms));
91 __stack_chk_guard = randoms.stack_guard;
92 __setjmp_manglers = randoms.setjmp_manglers;
93 // Zero the stack temporaries.
94 randoms = (struct randoms) {};
95 // Tell the compiler that the value is used, so it doesn't optimize
96 // out the zeroing as dead stores.
97 __asm__("# keepalive %0" :: "m"(randoms));
98
99 // extract process startup information from channel in arg
100 zx_handle_t bootstrap = (uintptr_t)arg;
101
102 struct start_params p = { .main = main };
103 zx_status_t status = zxr_message_size(bootstrap, &p.nbytes, &p.nhandles);
104 if (status != ZX_OK) {
105 p.nbytes = p.nhandles = 0;
106 }
107 ZXR_PROCESSARGS_BUFFER(buffer, p.nbytes);
108 zx_handle_t handles[p.nhandles];
109 p.buffer = buffer;
110 p.handles = handles;
111 if (status == ZX_OK) {
112 status = zxr_processargs_read(bootstrap, buffer, p.nbytes,
113 handles, p.nhandles,
114 &p.procargs, &p.handle_info);
115 }
116
117 // Find the handles we're interested in among what we were given.
118 zx_handle_t main_thread_handle = ZX_HANDLE_INVALID;
119 for (uint32_t i = 0; i < p.nhandles; ++i) {
120 switch (PA_HND_TYPE(p.handle_info[i])) {
121 case PA_PROC_SELF:
122 // The handle will have been installed already by dynamic
123 // linker startup, but now we have another one. They
124 // should of course be handles to the same process, but
125 // just for cleanliness switch to the "main" one.
126 if (__zircon_process_self != ZX_HANDLE_INVALID)
127 _zx_handle_close(__zircon_process_self);
128 __zircon_process_self = handles[i];
129 handles[i] = ZX_HANDLE_INVALID;
130 p.handle_info[i] = 0;
131 break;
132
133 case PA_JOB_DEFAULT:
134 // The default job provided to the process to use for
135 // creation of additional processes. It may or may not
136 // be the job this process is a child of. It may not
137 // be provided at all.
138 if (__zircon_job_default != ZX_HANDLE_INVALID)
139 _zx_handle_close(__zircon_job_default);
140 __zircon_job_default = handles[i];
141 handles[i] = ZX_HANDLE_INVALID;
142 p.handle_info[i] = 0;
143 break;
144
145 case PA_VMAR_ROOT:
146 // As above for PROC_SELF
147 if (__zircon_vmar_root_self != ZX_HANDLE_INVALID)
148 _zx_handle_close(__zircon_vmar_root_self);
149 __zircon_vmar_root_self = handles[i];
150 handles[i] = ZX_HANDLE_INVALID;
151 p.handle_info[i] = 0;
152 break;
153
154 case PA_THREAD_SELF:
155 main_thread_handle = handles[i];
156 handles[i] = ZX_HANDLE_INVALID;
157 p.handle_info[i] = 0;
158 break;
159 }
160 }
161
162 atomic_store(&libc.thread_count, 1);
163
164 // This consumes the thread handle and sets up the thread pointer.
165 p.td = __init_main_thread(main_thread_handle);
166
167 // Switch to the allocated stack and call start_main(&p) there. The
168 // original stack stays around just to hold the message buffer and handles
169 // array. The new stack is whole pages, so it's sufficiently aligned.
170
171 #ifdef __x86_64__
172 // The x86-64 ABI requires %rsp % 16 = 8 on entry. The zero word
173 // at (%rsp) serves as the return address for the outermost frame.
174 __asm__("lea -8(%[base], %[len], 1), %%rsp\n"
175 "jmp start_main\n"
176 "# Target receives %[arg]" : :
177 [base]"r"(p.td->safe_stack.iov_base),
178 [len]"r"(p.td->safe_stack.iov_len),
179 "m"(p), // Tell the compiler p's fields are all still alive.
180 [arg]"D"(&p));
181 #elif defined(__aarch64__)
182 __asm__("add sp, %[base], %[len]\n"
183 "mov x0, %[arg]\n"
184 "b start_main" : :
185 [base]"r"(p.td->safe_stack.iov_base),
186 [len]"r"(p.td->safe_stack.iov_len),
187 "m"(p), // Tell the compiler p's fields are all still alive.
188 [arg]"r"(&p));
189 #else
190 #error what architecture?
191 #endif
192
193 __builtin_unreachable();
194 }
195