Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / native_client / src / trusted / service_runtime / sel_ldr_standard.c
1 /*
2  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6
7 /*
8  * NaCl Simple/secure ELF loader (NaCl SEL).
9  */
10
11 #include "native_client/src/include/portability.h"
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16
17 #include "native_client/src/include/elf_constants.h"
18 #include "native_client/src/include/elf.h"
19 #include "native_client/src/include/nacl_macros.h"
20 #include "native_client/src/include/win/mman.h"
21 #include "native_client/src/shared/platform/nacl_check.h"
22 #include "native_client/src/shared/platform/nacl_log.h"
23 #include "native_client/src/shared/platform/nacl_sync_checked.h"
24 #include "native_client/src/shared/platform/nacl_time.h"
25
26 #include "native_client/src/shared/srpc/nacl_srpc.h"
27
28 #include "native_client/src/trusted/perf_counter/nacl_perf_counter.h"
29
30 #include "native_client/src/trusted/reverse_service/reverse_control_rpc.h"
31
32 #include "native_client/src/trusted/service_runtime/include/sys/errno.h"
33 #include "native_client/src/trusted/service_runtime/include/sys/fcntl.h"
34
35 #include "native_client/src/trusted/service_runtime/arch/sel_ldr_arch.h"
36 #include "native_client/src/trusted/service_runtime/elf_util.h"
37 #include "native_client/src/trusted/service_runtime/nacl_app_thread.h"
38 #include "native_client/src/trusted/service_runtime/nacl_kernel_service.h"
39 #include "native_client/src/trusted/service_runtime/nacl_runtime_host_interface.h"
40 #include "native_client/src/trusted/service_runtime/nacl_signal.h"
41 #include "native_client/src/trusted/service_runtime/nacl_switch_to_app.h"
42 #include "native_client/src/trusted/service_runtime/nacl_syscall_common.h"
43 #include "native_client/src/trusted/service_runtime/nacl_text.h"
44 #include "native_client/src/trusted/service_runtime/sel_memory.h"
45 #include "native_client/src/trusted/service_runtime/sel_ldr.h"
46 #include "native_client/src/trusted/service_runtime/sel_ldr_thread_interface.h"
47 #include "native_client/src/trusted/service_runtime/sel_util.h"
48 #include "native_client/src/trusted/service_runtime/sel_addrspace.h"
49
50 #if !defined(SIZE_T_MAX)
51 # define SIZE_T_MAX     (~(size_t) 0)
52 #endif
53
54
55 /*
56  * Fill from static_text_end to end of that page with halt
57  * instruction, which is at least NACL_HALT_LEN in size when no
58  * dynamic text is present.  Does not touch dynamic text region, which
59  * should be pre-filled with HLTs.
60  *
61  * By adding NACL_HALT_SLED_SIZE, we ensure that the code region ends
62  * with HLTs, just in case the CPU has a bug in which it fails to
63  * check for running off the end of the x86 code segment.
64  */
65 void NaClFillEndOfTextRegion(struct NaClApp *nap) {
66   size_t page_pad;
67
68   /*
69    * NOTE: make sure we are not silently overwriting data.  It is the
70    * toolchain's responsibility to ensure that a NACL_HALT_SLED_SIZE
71    * gap exists.
72    */
73   if (0 != nap->data_start &&
74       nap->static_text_end + NACL_HALT_SLED_SIZE >
75       NaClTruncAllocPage(nap->data_start)) {
76     NaClLog(LOG_FATAL, "Missing gap between text and data for halt_sled\n");
77   }
78   if (0 != nap->rodata_start &&
79       nap->static_text_end + NACL_HALT_SLED_SIZE > nap->rodata_start) {
80     NaClLog(LOG_FATAL, "Missing gap between text and rodata for halt_sled\n");
81   }
82
83   if (NULL == nap->text_shm) {
84     /*
85      * No dynamic text exists.  Space for NACL_HALT_SLED_SIZE must
86      * exist.
87      */
88     page_pad = (NaClRoundAllocPage(nap->static_text_end + NACL_HALT_SLED_SIZE)
89                 - nap->static_text_end);
90     CHECK(page_pad >= NACL_HALT_SLED_SIZE);
91     CHECK(page_pad < NACL_MAP_PAGESIZE + NACL_HALT_SLED_SIZE);
92   } else {
93     /*
94      * Dynamic text exists; the halt sled resides in the dynamic text
95      * region, so all we need to do here is to round out the last
96      * static text page with HLT instructions.  It doesn't matter if
97      * the size of this region is smaller than NACL_HALT_SLED_SIZE --
98      * this is just to fully initialize the page, rather than (later)
99      * decoding/validating zero-filled memory as instructions.
100      */
101     page_pad = NaClRoundAllocPage(nap->static_text_end) - nap->static_text_end;
102   }
103
104   NaClLog(4,
105           "Filling with halts: %08"NACL_PRIxPTR", %08"NACL_PRIxS" bytes\n",
106           nap->mem_start + nap->static_text_end,
107           page_pad);
108
109   NaClFillMemoryRegionWithHalt((void *)(nap->mem_start + nap->static_text_end),
110                                page_pad);
111
112   nap->static_text_end += page_pad;
113 }
114
115 /*
116  * Basic address space layout sanity check.
117  */
118 NaClErrorCode NaClCheckAddressSpaceLayoutSanity(struct NaClApp *nap,
119                                                 uintptr_t rodata_end,
120                                                 uintptr_t data_end,
121                                                 uintptr_t max_vaddr) {
122   if (0 != nap->data_start) {
123     if (data_end != max_vaddr) {
124       NaClLog(LOG_INFO, "data segment is not last\n");
125       return LOAD_DATA_NOT_LAST_SEGMENT;
126     }
127   } else if (0 != nap->rodata_start) {
128     if (NaClRoundAllocPage(rodata_end) != max_vaddr) {
129       /*
130        * This should be unreachable, but we include it just for
131        * completeness.
132        *
133        * Here is why it is unreachable:
134        *
135        * NaClPhdrChecks checks the test segment starting address.  The
136        * only allowed loaded segments are text, data, and rodata.
137        * Thus unless the rodata is in the trampoline region, it must
138        * be after the text.  And NaClElfImageValidateProgramHeaders
139        * ensures that all segments start after the trampoline region.
140        */
141       NaClLog(LOG_INFO, "no data segment, but rodata segment is not last\n");
142       return LOAD_NO_DATA_BUT_RODATA_NOT_LAST_SEGMENT;
143     }
144   }
145   if (0 != nap->rodata_start && 0 != nap->data_start) {
146     if (rodata_end > NaClTruncAllocPage(nap->data_start)) {
147       NaClLog(LOG_INFO, "rodata_overlaps data.\n");
148       return LOAD_RODATA_OVERLAPS_DATA;
149     }
150   }
151   if (0 != nap->rodata_start) {
152     if (NaClRoundAllocPage(NaClEndOfStaticText(nap)) > nap->rodata_start) {
153       return LOAD_TEXT_OVERLAPS_RODATA;
154     }
155   } else if (0 != nap->data_start) {
156     if (NaClRoundAllocPage(NaClEndOfStaticText(nap)) >
157         NaClTruncAllocPage(nap->data_start)) {
158       return LOAD_TEXT_OVERLAPS_DATA;
159     }
160   }
161   if (0 != nap->rodata_start &&
162       NaClRoundAllocPage(nap->rodata_start) != nap->rodata_start) {
163     NaClLog(LOG_INFO, "rodata_start not a multiple of allocation size\n");
164     return LOAD_BAD_RODATA_ALIGNMENT;
165   }
166 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_mips
167   /*
168    * This check is necessary to make MIPS sandbox secure, as there is no NX page
169    * protection support on MIPS.
170    */
171   if (nap->rodata_start < NACL_DATA_SEGMENT_START) {
172     NaClLog(LOG_INFO,
173             "rodata_start is below NACL_DATA_SEGMENT_START (0x%X) address\n",
174             NACL_DATA_SEGMENT_START);
175     return LOAD_SEGMENT_BAD_LOC;
176   }
177 #endif
178   return LOAD_OK;
179 }
180
181 void NaClLogAddressSpaceLayout(struct NaClApp *nap) {
182   NaClLog(2, "NaClApp addr space layout:\n");
183   NaClLog(2, "nap->static_text_end    = 0x%016"NACL_PRIxPTR"\n",
184           nap->static_text_end);
185   NaClLog(2, "nap->dynamic_text_start = 0x%016"NACL_PRIxPTR"\n",
186           nap->dynamic_text_start);
187   NaClLog(2, "nap->dynamic_text_end   = 0x%016"NACL_PRIxPTR"\n",
188           nap->dynamic_text_end);
189   NaClLog(2, "nap->rodata_start       = 0x%016"NACL_PRIxPTR"\n",
190           nap->rodata_start);
191   NaClLog(2, "nap->data_start         = 0x%016"NACL_PRIxPTR"\n",
192           nap->data_start);
193   NaClLog(2, "nap->data_end           = 0x%016"NACL_PRIxPTR"\n",
194           nap->data_end);
195   NaClLog(2, "nap->break_addr         = 0x%016"NACL_PRIxPTR"\n",
196           nap->break_addr);
197   NaClLog(2, "nap->initial_entry_pt   = 0x%016"NACL_PRIxPTR"\n",
198           nap->initial_entry_pt);
199   NaClLog(2, "nap->user_entry_pt      = 0x%016"NACL_PRIxPTR"\n",
200           nap->user_entry_pt);
201   NaClLog(2, "nap->bundle_size        = 0x%x\n", nap->bundle_size);
202 }
203
204
205 NaClErrorCode NaClAppLoadFileAslr(struct NaClDesc *ndp,
206                                   struct NaClApp *nap,
207                                   enum NaClAslrMode aslr_mode) {
208   NaClErrorCode       ret = LOAD_INTERNAL;
209   NaClErrorCode       subret = LOAD_INTERNAL;
210   uintptr_t           rodata_end;
211   uintptr_t           data_end;
212   uintptr_t           max_vaddr;
213   struct NaClElfImage *image = NULL;
214   struct NaClPerfCounter  time_load_file;
215   struct NaClElfImageInfo info;
216
217   NaClPerfCounterCtor(&time_load_file, "NaClAppLoadFile");
218
219   /* NACL_MAX_ADDR_BITS < 32 */
220   if (nap->addr_bits > NACL_MAX_ADDR_BITS) {
221     ret = LOAD_ADDR_SPACE_TOO_BIG;
222     goto done;
223   }
224
225   nap->stack_size = NaClRoundAllocPage(nap->stack_size);
226
227   /* temporay object will be deleted at end of function */
228   image = NaClElfImageNew(ndp, &subret);
229   if (NULL == image || LOAD_OK != subret) {
230     ret = subret;
231     goto done;
232   }
233
234   subret = NaClElfImageValidateProgramHeaders(image,
235                                               nap->addr_bits,
236                                               &info);
237   if (LOAD_OK != subret) {
238     ret = subret;
239     goto done;
240   }
241
242   if (nap->initial_nexe_max_code_bytes != 0) {
243     size_t code_segment_size = info.static_text_end - NACL_TRAMPOLINE_END;
244     if (code_segment_size > nap->initial_nexe_max_code_bytes) {
245       NaClLog(LOG_ERROR, "NaClAppLoadFileAslr: "
246               "Code segment size (%"NACL_PRIdS" bytes) exceeds limit (%"
247               NACL_PRId32" bytes)\n",
248               code_segment_size, nap->initial_nexe_max_code_bytes);
249       ret = LOAD_CODE_SEGMENT_TOO_LARGE;
250       goto done;
251     }
252   }
253
254   nap->static_text_end = info.static_text_end;
255   nap->rodata_start = info.rodata_start;
256   rodata_end = info.rodata_end;
257   nap->data_start = info.data_start;
258   data_end = info.data_end;
259   max_vaddr = info.max_vaddr;
260
261   if (0 == nap->data_start) {
262     if (0 == nap->rodata_start) {
263       if (NaClRoundAllocPage(max_vaddr) - max_vaddr < NACL_HALT_SLED_SIZE) {
264         /*
265          * if no rodata and no data, we make sure that there is space for
266          * the halt sled.
267          */
268         max_vaddr += NACL_MAP_PAGESIZE;
269       }
270     } else {
271       /*
272        * no data, but there is rodata.  this means max_vaddr is just
273        * where rodata ends.  this might not be at an allocation
274        * boundary, and in this the page would not be writable.  round
275        * max_vaddr up to the next allocation boundary so that bss will
276        * be at the next writable region.
277        */
278       ;
279     }
280     max_vaddr = NaClRoundAllocPage(max_vaddr);
281   }
282   /*
283    * max_vaddr -- the break or the boundary between data (initialized
284    * and bss) and the address space hole -- does not have to be at a
285    * page boundary.
286    *
287    * Memory allocation will use NaClRoundPage(nap->break_addr), but
288    * the system notion of break is always an exact address.  Even
289    * though we must allocate and make accessible multiples of pages,
290    * the linux-style brk system call (which returns current break on
291    * failure) permits a non-aligned address as argument.
292    */
293   nap->break_addr = max_vaddr;
294   nap->data_end = max_vaddr;
295
296   NaClLog(4, "Values from NaClElfImageValidateProgramHeaders:\n");
297   NaClLog(4, "rodata_start = 0x%08"NACL_PRIxPTR"\n", nap->rodata_start);
298   NaClLog(4, "rodata_end   = 0x%08"NACL_PRIxPTR"\n", rodata_end);
299   NaClLog(4, "data_start   = 0x%08"NACL_PRIxPTR"\n", nap->data_start);
300   NaClLog(4, "data_end     = 0x%08"NACL_PRIxPTR"\n", data_end);
301   NaClLog(4, "max_vaddr    = 0x%08"NACL_PRIxPTR"\n", max_vaddr);
302
303   /* We now support only one bundle size.  */
304   nap->bundle_size = NACL_INSTR_BLOCK_SIZE;
305
306   nap->initial_entry_pt = NaClElfImageGetEntryPoint(image);
307   NaClLogAddressSpaceLayout(nap);
308
309   if (!NaClAddrIsValidEntryPt(nap, nap->initial_entry_pt)) {
310     ret = LOAD_BAD_ENTRY;
311     goto done;
312   }
313
314   subret = NaClCheckAddressSpaceLayoutSanity(nap, rodata_end, data_end,
315                                              max_vaddr);
316   if (LOAD_OK != subret) {
317     ret = subret;
318     goto done;
319   }
320
321   NaClLog(2, "Allocating address space\n");
322   NaClPerfCounterMark(&time_load_file, "PreAllocAddrSpace");
323   NaClPerfCounterIntervalLast(&time_load_file);
324   subret = NaClAllocAddrSpaceAslr(nap, aslr_mode);
325   NaClPerfCounterMark(&time_load_file,
326                       NACL_PERF_IMPORTANT_PREFIX "AllocAddrSpace");
327   NaClPerfCounterIntervalLast(&time_load_file);
328   if (LOAD_OK != subret) {
329     ret = subret;
330     goto done;
331   }
332
333   /*
334    * Make sure the static image pages are marked writable before we try
335    * to write them.
336    */
337   NaClLog(2, "Loading into memory\n");
338   ret = NaClMprotect((void *) (nap->mem_start + NACL_TRAMPOLINE_START),
339                      NaClRoundAllocPage(nap->data_end) - NACL_TRAMPOLINE_START,
340                      PROT_READ | PROT_WRITE);
341   if (0 != ret) {
342     NaClLog(LOG_FATAL,
343             "NaClAppLoadFile: Failed to make image pages writable. "
344             "Error code 0x%x\n",
345             ret);
346   }
347   subret = NaClElfImageLoad(image, ndp, nap);
348   if (LOAD_OK != subret) {
349     ret = subret;
350     goto done;
351   }
352
353   /*
354    * NB: mem_map object has been initialized, but is empty.
355    * NaClMakeDynamicTextShared does not touch it.
356    *
357    * NaClMakeDynamicTextShared also fills the dynamic memory region
358    * with the architecture-specific halt instruction.  If/when we use
359    * memory mapping to save paging space for the dynamic region and
360    * lazily halt fill the memory as the pages become
361    * readable/executable, we must make sure that the *last*
362    * NACL_MAP_PAGESIZE chunk is nonetheless mapped and written with
363    * halts.
364    */
365   NaClLog(2,
366           ("Replacing gap between static text and"
367            " (ro)data with shareable memory\n"));
368   subret = NaClMakeDynamicTextShared(nap);
369   NaClPerfCounterMark(&time_load_file,
370                       NACL_PERF_IMPORTANT_PREFIX "MakeDynText");
371   NaClPerfCounterIntervalLast(&time_load_file);
372   if (LOAD_OK != subret) {
373     ret = subret;
374     goto done;
375   }
376
377   /*
378    * NaClFillEndOfTextRegion will fill with halt instructions the
379    * padding space after the static text region.
380    *
381    * Shm-backed dynamic text space was filled with halt instructions
382    * in NaClMakeDynamicTextShared.  This extends to the rodata.  For
383    * non-shm-backed text space, this extend to the next page (and not
384    * allocation page).  static_text_end is updated to include the
385    * padding.
386    */
387   NaClFillEndOfTextRegion(nap);
388
389   if (nap->main_exe_prevalidated) {
390     NaClLog(2, "Main executable segment hit validation cache and mapped in,"
391             " skipping validation.\n");
392     subret = LOAD_OK;
393   } else {
394     NaClLog(2, "Validating image\n");
395     subret = NaClValidateImage(nap);
396   }
397   NaClPerfCounterMark(&time_load_file,
398                       NACL_PERF_IMPORTANT_PREFIX "ValidateImg");
399   NaClPerfCounterIntervalLast(&time_load_file);
400   if (LOAD_OK != subret) {
401     ret = subret;
402     goto done;
403   }
404
405   NaClLog(2, "Initializing arch switcher\n");
406   NaClInitSwitchToApp(nap);
407
408   NaClLog(2, "Installing trampoline\n");
409   NaClLoadTrampoline(nap);
410
411   NaClLog(2, "Installing springboard\n");
412   NaClLoadSpringboard(nap);
413
414   /*
415    * NaClMemoryProtection also initializes the mem_map w/ information
416    * about the memory pages and their current protection value.
417    *
418    * The contents of the dynamic text region will get remapped as
419    * non-writable.
420    */
421   NaClLog(2, "Applying memory protection\n");
422   subret = NaClMemoryProtection(nap);
423   if (LOAD_OK != subret) {
424     ret = subret;
425     goto done;
426   }
427
428   NaClLog(2, "NaClAppLoadFile done; ");
429   NaClLogAddressSpaceLayout(nap);
430   ret = LOAD_OK;
431 done:
432   NaClElfImageDelete(image);
433
434   NaClPerfCounterMark(&time_load_file, "EndLoadFile");
435   NaClPerfCounterIntervalTotal(&time_load_file);
436   return ret;
437 }
438
439 NaClErrorCode NaClAppLoadFile(struct NaClDesc *ndp,
440                               struct NaClApp *nap) {
441   return NaClAppLoadFileAslr(ndp, nap, NACL_ENABLE_ASLR);
442 }
443
444 NaClErrorCode NaClAppLoadFileDynamically(
445     struct NaClApp *nap,
446     struct NaClDesc *ndp,
447     struct NaClValidationMetadata *metadata) {
448   struct NaClElfImage *image = NULL;
449   NaClErrorCode ret = LOAD_INTERNAL;
450
451   image = NaClElfImageNew(ndp, &ret);
452   if (NULL == image || LOAD_OK != ret) {
453     goto done;
454   }
455   ret = NaClElfImageLoadDynamically(image, nap, ndp, metadata);
456   if (LOAD_OK != ret) {
457     goto done;
458   }
459   nap->user_entry_pt = nap->initial_entry_pt;
460   nap->initial_entry_pt = NaClElfImageGetEntryPoint(image);
461
462  done:
463   NaClElfImageDelete(image);
464   return ret;
465 }
466
467 int NaClAddrIsValidEntryPt(struct NaClApp *nap,
468                            uintptr_t      addr) {
469   if (0 != (addr & (nap->bundle_size - 1))) {
470     return 0;
471   }
472
473   return addr < nap->static_text_end;
474 }
475
476 int NaClAppLaunchServiceThreads(struct NaClApp *nap) {
477   struct NaClKernelService  *kernel_service = NULL;
478   int                       rv = 0;
479
480   NaClLog(4, "NaClAppLaunchServiceThreads: Entered, nap 0x%"NACL_PRIxPTR"\n",
481           (uintptr_t) nap);
482
483   NaClNameServiceLaunch(nap->name_service);
484
485   if (LOAD_OK != NaClWaitForStartModuleCommand(nap)) {
486     return rv;
487   }
488
489   NaClXMutexLock(&nap->mu);
490   if (NULL == nap->runtime_host_interface) {
491     nap->runtime_host_interface = malloc(sizeof *nap->runtime_host_interface);
492     if (NULL == nap->runtime_host_interface ||
493         !NaClRuntimeHostInterfaceCtor_protected(nap->runtime_host_interface)) {
494       NaClLog(LOG_ERROR, "NaClAppLaunchServiceThreads:"
495               " Failed to initialise runtime host interface\n");
496       goto done;
497     }
498   }
499   NaClXMutexUnlock(&nap->mu);
500
501   kernel_service = (struct NaClKernelService *) malloc(sizeof *kernel_service);
502   if (NULL == kernel_service) {
503     NaClLog(LOG_ERROR,
504             "NaClAppLaunchServiceThreads: No memory for kern service\n");
505     goto done;
506   }
507
508   if (!NaClKernelServiceCtor(kernel_service,
509                              NaClAddrSpSquattingThreadIfFactoryFunction,
510                              (void *) nap,
511                              nap->runtime_host_interface)) {
512     NaClLog(LOG_ERROR,
513             "NaClAppLaunchServiceThreads: KernServiceCtor failed\n");
514     free(kernel_service);
515     kernel_service = NULL;
516     goto done;
517   }
518
519   if (!NaClSimpleServiceStartServiceThread((struct NaClSimpleService *)
520                                            kernel_service)) {
521     NaClLog(LOG_ERROR,
522             "NaClAppLaunchServiceThreads: KernService start service failed\n");
523     goto done;
524   }
525   /*
526    * NB: StartServiceThread grabbed another reference to kernel_service,
527    * used by the service thread.  Closing the connection capability
528    * should cause the service thread to shut down and in turn release
529    * that reference.
530    */
531
532   NaClXMutexLock(&nap->mu);
533   CHECK(NULL == nap->kernel_service);
534
535   nap->kernel_service = kernel_service;
536   kernel_service = NULL;
537   NaClXMutexUnlock(&nap->mu);
538   rv = 1;
539
540 done:
541   NaClXMutexLock(&nap->mu);
542   if (NULL != nap->kernel_service) {
543     NaClLog(3,
544             ("NaClAppLaunchServiceThreads: adding kernel service to"
545              " name service\n"));
546     (*NACL_VTBL(NaClNameService, nap->name_service)->
547      CreateDescEntry)(nap->name_service,
548                       "KernelService", NACL_ABI_O_RDWR,
549                       NaClDescRef(nap->kernel_service->base.bound_and_cap[1]));
550   }
551   NaClXMutexUnlock(&nap->mu);
552
553   /*
554    * Single exit path.
555    *
556    * Error cleanup invariant.  No service thread should be running
557    * (modulo asynchronous shutdown).  Automatic variables refer to
558    * fully constructed objects if non-NULL, and when ownership is
559    * transferred to the NaClApp object the corresponding automatic
560    * variable is set to NULL.
561    */
562   NaClRefCountSafeUnref((struct NaClRefCount *) kernel_service);
563   return rv;
564 }
565
566 int NaClReportExitStatus(struct NaClApp *nap, int exit_status) {
567   int rv = 0;
568
569   NaClXMutexLock(&nap->mu);
570   /*
571    * If several threads are exiting/reporting signals at once, we should
572    * let only one thread to pass through. This way we can use exit code
573    * without synchronization once we know that running==0.
574    */
575   if (!nap->running) {
576     NaClXMutexUnlock(&nap->mu);
577     return 0;
578   }
579
580   if (NULL != nap->runtime_host_interface) {
581     /* TODO(halyavin) update NaCl plugin to accept full exit_status value */
582     if (NACL_ABI_WIFEXITED(exit_status)) {
583     rv = (*NACL_VTBL(NaClRuntimeHostInterface, nap->runtime_host_interface)->
584           ReportExitStatus)(nap->runtime_host_interface,
585                             NACL_ABI_WEXITSTATUS(exit_status));
586     }
587     /*
588      * Due to cross-repository checkins, the Cr-side might not yet
589      * implement this RPC.  We return whether shutdown was reported.
590      */
591   }
592   nap->exit_status = exit_status;
593   nap->running = 0;
594   NaClXCondVarSignal(&nap->cv);
595
596   NaClXMutexUnlock(&nap->mu);
597
598   return rv;
599 }
600
601 uintptr_t NaClGetInitialStackTop(struct NaClApp *nap) {
602   /*
603    * We keep the top of useful memory a page below the top of the
604    * sandbox region so that compilers can do tricks like computing a
605    * base register of sp + constant and then using a
606    * register-minus-constant addressing mode, which comes up at least
607    * on ARM where the compiler is trying to optimize given the limited
608    * size of immediate offsets available.  The maximum such negative
609    * constant on ARM will be -4095, but we use page size (64k) for
610    * good measure and do it on all machines just for uniformity.
611    */
612   return ((uintptr_t) 1U << nap->addr_bits) - NACL_MAP_PAGESIZE;
613 }
614
615 /*
616  * preconditions:
617  *  * argc is the length of the argv array
618  *  * envv may be NULL (this happens on MacOS/Cocoa and in tests)
619  *  * if envv is non-NULL it is 'consistent', null terminated etc.
620  */
621 int NaClCreateMainThread(struct NaClApp     *nap,
622                          int                argc,
623                          char               **argv,
624                          char const *const  *envv) {
625   /*
626    * Compute size of string tables for argv and envv
627    */
628   int                   retval;
629   int                   envc;
630   size_t                size;
631   int                   auxv_entries;
632   size_t                ptr_tbl_size;
633   int                   i;
634   uint32_t              *p;
635   char                  *strp;
636   size_t                *argv_len;
637   size_t                *envv_len;
638   uintptr_t             stack_ptr;
639
640   retval = 0;  /* fail */
641   CHECK(argc >= 0);
642   CHECK(NULL != argv || 0 == argc);
643
644   envc = 0;
645   if (NULL != envv) {
646     char const *const *pp;
647     for (pp = envv; NULL != *pp; ++pp) {
648       ++envc;
649     }
650   }
651   envv_len = 0;
652   argv_len = malloc(argc * sizeof argv_len[0]);
653   envv_len = malloc(envc * sizeof envv_len[0]);
654   if (NULL == argv_len) {
655     goto cleanup;
656   }
657   if (NULL == envv_len && 0 != envc) {
658     goto cleanup;
659   }
660
661   size = 0;
662
663   /*
664    * The following two loops cannot overflow.  The reason for this is
665    * that they are counting the number of bytes used to hold the
666    * NUL-terminated strings that comprise the argv and envv tables.
667    * If the entire address space consisted of just those strings, then
668    * the size variable would overflow; however, since there's the code
669    * space required to hold the code below (and we are not targetting
670    * Harvard architecture machines), at least one page holds code, not
671    * data.  We are assuming that the caller is non-adversarial and the
672    * code does not look like string data....
673    */
674   for (i = 0; i < argc; ++i) {
675     argv_len[i] = strlen(argv[i]) + 1;
676     size += argv_len[i];
677   }
678   for (i = 0; i < envc; ++i) {
679     envv_len[i] = strlen(envv[i]) + 1;
680     size += envv_len[i];
681   }
682
683   /*
684    * NaCl modules are ILP32, so the argv, envv pointers, as well as
685    * the terminating NULL pointers at the end of the argv/envv tables,
686    * are 32-bit values.  We also have the auxv to take into account.
687    *
688    * The argv and envv pointer tables came from trusted code and is
689    * part of memory.  Thus, by the same argument above, adding in
690    * "ptr_tbl_size" cannot possibly overflow the "size" variable since
691    * it is a size_t object.  However, the extra pointers for auxv and
692    * the space for argv could cause an overflow.  The fact that we
693    * used stack to get here etc means that ptr_tbl_size could not have
694    * overflowed.
695    *
696    * NB: the underlying OS would have limited the amount of space used
697    * for argv and envv -- on linux, it is ARG_MAX, or 128KB -- and
698    * hence the overflow check is for obvious auditability rather than
699    * for correctness.
700    */
701   auxv_entries = 1;
702   if (0 != nap->user_entry_pt) {
703     auxv_entries++;
704   }
705   ptr_tbl_size = (((NACL_STACK_GETS_ARG ? 1 : 0) +
706                    (3 + argc + 1 + envc + 1 + auxv_entries * 2)) *
707                   sizeof(uint32_t));
708
709   if (SIZE_T_MAX - size < ptr_tbl_size) {
710     NaClLog(LOG_WARNING,
711             "NaClCreateMainThread: ptr_tbl_size cause size of"
712             " argv / environment copy to overflow!?!\n");
713     retval = 0;
714     goto cleanup;
715   }
716   size += ptr_tbl_size;
717
718   size = (size + NACL_STACK_ALIGN_MASK) & ~NACL_STACK_ALIGN_MASK;
719
720   if (size > nap->stack_size) {
721     retval = 0;
722     goto cleanup;
723   }
724
725   /*
726    * Write strings and char * arrays to stack.
727    */
728   stack_ptr = NaClUserToSysAddrRange(nap, NaClGetInitialStackTop(nap) - size,
729                                      size);
730   if (stack_ptr == kNaClBadAddress) {
731     retval = 0;
732     goto cleanup;
733   }
734
735   NaClLog(2, "setting stack to : %016"NACL_PRIxPTR"\n", stack_ptr);
736
737   VCHECK(0 == (stack_ptr & NACL_STACK_ALIGN_MASK),
738          ("stack_ptr not aligned: %016"NACL_PRIxPTR"\n", stack_ptr));
739
740   p = (uint32_t *) stack_ptr;
741   strp = (char *) stack_ptr + ptr_tbl_size;
742
743   /*
744    * For x86-32, we push an initial argument that is the address of
745    * the main argument block.  For other machines, this is passed
746    * in a register and that's set in NaClStartThreadInApp.
747    */
748   if (NACL_STACK_GETS_ARG) {
749     uint32_t *argloc = p++;
750     *argloc = (uint32_t) NaClSysToUser(nap, (uintptr_t) p);
751   }
752
753   *p++ = 0;  /* Cleanup function pointer, always NULL.  */
754   *p++ = envc;
755   *p++ = argc;
756
757   for (i = 0; i < argc; ++i) {
758     *p++ = (uint32_t) NaClSysToUser(nap, (uintptr_t) strp);
759     NaClLog(2, "copying arg %d  %p -> %p\n",
760             i, argv[i], strp);
761     strcpy(strp, argv[i]);
762     strp += argv_len[i];
763   }
764   *p++ = 0;  /* argv[argc] is NULL.  */
765
766   for (i = 0; i < envc; ++i) {
767     *p++ = (uint32_t) NaClSysToUser(nap, (uintptr_t) strp);
768     NaClLog(2, "copying env %d  %p -> %p\n",
769             i, envv[i], strp);
770     strcpy(strp, envv[i]);
771     strp += envv_len[i];
772   }
773   *p++ = 0;  /* envp[envc] is NULL.  */
774
775   /* Push an auxv */
776   if (0 != nap->user_entry_pt) {
777     *p++ = AT_ENTRY;
778     *p++ = (uint32_t) nap->user_entry_pt;
779   }
780   *p++ = AT_NULL;
781   *p++ = 0;
782
783   CHECK((char *) p == (char *) stack_ptr + ptr_tbl_size);
784
785   /* now actually spawn the thread */
786   NaClXMutexLock(&nap->mu);
787   nap->running = 1;
788   NaClXMutexUnlock(&nap->mu);
789
790   NaClVmHoleWaitToStartThread(nap);
791
792   /*
793    * For x86, we adjust the stack pointer down to push a dummy return
794    * address.  This happens after the stack pointer alignment.
795    * We avoid the otherwise harmless call for the zero case because
796    * _FORTIFY_SOURCE memset can warn about zero-length calls.
797    */
798   if (NACL_STACK_PAD_BELOW_ALIGN != 0) {
799     stack_ptr -= NACL_STACK_PAD_BELOW_ALIGN;
800     memset((void *) stack_ptr, 0, NACL_STACK_PAD_BELOW_ALIGN);
801   }
802
803   NaClLog(2, "system stack ptr : %016"NACL_PRIxPTR"\n", stack_ptr);
804   NaClLog(2, "  user stack ptr : %016"NACL_PRIxPTR"\n",
805           NaClSysToUserStackAddr(nap, stack_ptr));
806
807   /* e_entry is user addr */
808   retval = NaClAppThreadSpawn(nap,
809                               nap->initial_entry_pt,
810                               NaClSysToUserStackAddr(nap, stack_ptr),
811                               /* user_tls1= */ (uint32_t) nap->break_addr,
812                               /* user_tls2= */ 0);
813
814 cleanup:
815   free(argv_len);
816   free(envv_len);
817
818   return retval;
819 }
820
821 int NaClWaitForMainThreadToExit(struct NaClApp  *nap) {
822   NaClLog(3, "NaClWaitForMainThreadToExit: taking NaClApp lock\n");
823   NaClXMutexLock(&nap->mu);
824   NaClLog(3, " waiting for exit status\n");
825   while (nap->running) {
826     NaClXCondVarWait(&nap->cv, &nap->mu);
827     NaClLog(3, " wakeup, nap->running %d, nap->exit_status %d\n",
828             nap->running, nap->exit_status);
829   }
830   NaClXMutexUnlock(&nap->mu);
831   /*
832    * Some thread invoked the exit (exit_group) syscall.
833    */
834
835   if (NULL != nap->debug_stub_callbacks) {
836     nap->debug_stub_callbacks->process_exit_hook();
837   }
838
839   return NACL_ABI_WEXITSTATUS(nap->exit_status);
840 }
841
842 /*
843  * stack_ptr is from syscall, so a 32-bit address.
844  */
845 int32_t NaClCreateAdditionalThread(struct NaClApp *nap,
846                                    uintptr_t      prog_ctr,
847                                    uintptr_t      sys_stack_ptr,
848                                    uint32_t       user_tls1,
849                                    uint32_t       user_tls2) {
850   if (!NaClAppThreadSpawn(nap,
851                           prog_ctr,
852                           NaClSysToUserStackAddr(nap, sys_stack_ptr),
853                           user_tls1,
854                           user_tls2)) {
855     NaClLog(LOG_WARNING,
856             ("NaClCreateAdditionalThread: could not allocate thread."
857              "  Returning EAGAIN per POSIX specs.\n"));
858     return -NACL_ABI_EAGAIN;
859   }
860   return 0;
861 }