Allow a read-only data PT_LOAD segment at the start of the executable, containing...
[nativeclient.git] / service_runtime / nacl_app.c
bloba9fc214acbb9fa188bc300f3180a7602b61608b4
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * NaCl run time.
35 #include <fcntl.h>
36 #include <stdlib.h>
38 #include "native_client/service_runtime/nacl_config.h"
39 #include "native_client/service_runtime/nacl_check.h"
40 #include "native_client/service_runtime/dyn_array.h"
41 #include "native_client/service_runtime/sel_ldr.h"
42 #include "native_client/service_runtime/sel_rt.h"
43 #include "native_client/service_runtime/nacl_app_thread.h"
44 #include "native_client/service_runtime/nacl_ldt.h"
45 #include "native_client/service_runtime/nacl_log.h"
46 #include "native_client/service_runtime/nacl_desc_base.h"
49 * Allocate ldt for app, without creating the main thread.
51 NaClErrorCode NaClAppPrepareToLaunch(struct NaClApp *nap)
53 uintptr_t code_start;
54 size_t code_bytes;
55 size_t code_pages;
57 uintptr_t data_start;
58 size_t data_pages;
60 uint16_t cs;
61 uint16_t des_seg;
63 int i;
64 struct NaClHostDesc *nhdp;
66 data_start = nap->data_mem_start;
67 CHECK(nap->addr_bits > NACL_PAGESHIFT);
68 data_pages = 1 << (nap->addr_bits - NACL_PAGESHIFT);
71 * Determine what region of memory can be accessed as code.
73 code_start = nap->code_mem_start;
74 if (nap->data_mem_start == nap->code_mem_start)
76 code_bytes = nap->text_region_end;
77 VCHECK((code_bytes & ((1 << NACL_PAGESHIFT)-1)) == 0,
78 ("code_bytes (0x%08x) is not page aligned\n",
79 code_bytes));
80 code_pages = code_bytes >> NACL_PAGESHIFT;
82 else
83 code_pages = data_pages;
85 if (code_pages < 1) {
86 NaClLog(LOG_FATAL, "NaClAppPrepareToLaunch: fewer than one code pages?\n");
88 NaClLog(2, "NaClLdtAllocatePageSelector(code, 1, 0x%08x, 0x%x\n",
89 code_start, code_pages);
90 cs = NaClLdtAllocatePageSelector(NACL_LDT_DESCRIPTOR_CODE,
92 (void *) code_start,
93 code_pages);
94 NaClLog(2, "got 0x%x\n", cs);
95 if (0 == cs) {
96 return SRT_NO_SEG_SEL;
100 * Determine what region of memory can be accessed as data.
102 * NB: in our memory model, we roughly follow standard 7th edition
103 * unix but with a >16-bit address space: data and code overlap, and
104 * the start of the data segment is the same as the start of the
105 * code region; and the data segment actually includes the memory
106 * hole between the break and the top of the stack, as well as the
107 * stack and environment variables and other things in memory above
108 * the stack.
110 * The code pages, which is marked read-only via the page protection
111 * mechanism, could be viewed as read-only data. Nothing prevents a
112 * NaCl application from looking at its own code.
114 * The same segment selector is used for ds, es, and ss, and thus
115 * "des_seg". Nuthin' to do with the old Data Encryption Standard.
118 if (data_pages < 1) {
119 NaClLog(LOG_FATAL,
120 "NaClAppPrepareToLaunch: address space is fewer than one page?\n");
122 NaClLog(2, "NaClLdtAllocatePageSelector(data, 1, 0x%08x, 0x%x\n",
123 data_start, data_pages - 1);
124 des_seg = NaClLdtAllocatePageSelector(NACL_LDT_DESCRIPTOR_DATA,
126 (void *) data_start,
127 data_pages);
129 NaClLog(2, "got 0x%x\n", des_seg);
130 if (0 == des_seg) {
131 NaClLdtDeleteSelector(cs);
132 return SRT_NO_SEG_SEL;
134 nap->code_seg_sel = cs;
135 nap->data_seg_sel = des_seg;
137 * Note that gs is thread-specific and not global, so that is allocated
138 * elsewhere. See nacl_app_thread.c.
142 * We dup the stdin, stdout, and stderr descriptors and wrap them in
143 * NaClHostDesc objects. Those in turn are wrapped by the
144 * NaClDescIoDesc subclass of NaClDesc, and then put into the
145 * open-file table. NaCl app I/O operations will use these shared
146 * descriptors, and if they close one of these descriptors it will
147 * only be a duplicated descriptor. NB: some fcntl/ioctl flags
148 * apply to the descriptor (e.g., O_CLOEXEC) and some apply to the
149 * underlying open file entry (e.g., O_NONBLOCK), so changes by the
150 * NaCl app could affect the service runtime.
152 for (i = 0; i < 3; ++i) {
153 nhdp = malloc(sizeof *nhdp);
154 if (NULL == nhdp) {
155 NaClLog(LOG_FATAL,
156 "NaClAppPrepareToLaunch: no memory for abstract descriptor %d\n",
159 NaClHostDescPosixDup(nhdp, i, (0 == i) ? O_RDONLY : O_WRONLY);
160 NaClSetDesc(nap, i, (struct NaClDesc *) NaClDescIoDescMake(nhdp));
163 return LOAD_OK;