imcplugin demo: Extend to support stat() call
[nativeclient.git] / service_runtime / nacl_app.c
blob49b5396f7046898c106d0da2f47f2a1c2fc033b7
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/dyn_array.h"
39 #include "native_client/service_runtime/nacl_app_thread.h"
40 #include "native_client/service_runtime/nacl_check.h"
41 #include "native_client/service_runtime/nacl_config.h"
42 #include "native_client/service_runtime/nacl_desc_base.h"
43 #include "native_client/service_runtime/nacl_ldt.h"
44 #include "native_client/service_runtime/nacl_log.h"
45 #include "native_client/service_runtime/nacl_sync_checked.h"
46 #include "native_client/service_runtime/sel_ldr.h"
47 #include "native_client/service_runtime/sel_rt.h"
50 * Allocate ldt for app, without creating the main thread.
52 NaClErrorCode NaClAppPrepareToLaunch(struct NaClApp *nap,
53 int in_desc,
54 int out_desc,
55 int err_desc)
57 uintptr_t code_start;
58 size_t code_bytes;
59 size_t code_pages;
61 uintptr_t data_start;
62 size_t data_pages;
64 uint16_t cs;
65 uint16_t des_seg;
67 int i;
68 struct NaClHostDesc *nhdp;
70 int descs[3];
72 NaClErrorCode retval = LOAD_INTERNAL;
74 descs[0] = in_desc;
75 descs[1] = out_desc;
76 descs[2] = err_desc;
78 NaClXMutexLock(&nap->mu);
80 data_start = nap->data_mem_start;
81 CHECK(nap->addr_bits > NACL_PAGESHIFT);
82 data_pages = 1 << (nap->addr_bits - NACL_PAGESHIFT);
85 * Determine what region of memory can be accessed as code.
87 code_start = nap->code_mem_start;
88 if (nap->data_mem_start == nap->code_mem_start)
90 code_bytes = nap->text_region_end;
91 VCHECK((code_bytes & ((1 << NACL_PAGESHIFT)-1)) == 0,
92 ("code_bytes (0x%08"PRIxS") is not page aligned\n",
93 code_bytes));
94 code_pages = code_bytes >> NACL_PAGESHIFT;
96 else
97 code_pages = data_pages;
99 if (code_pages < 1) {
100 NaClLog(LOG_FATAL, "NaClAppPrepareToLaunch: fewer than one code pages?\n");
102 NaClLog(2,
103 "NaClLdtAllocatePageSelector(code, 1, 0x%08"PRIxPTR", 0x%"PRIxS"\n",
104 code_start, code_pages);
105 cs = NaClLdtAllocatePageSelector(NACL_LDT_DESCRIPTOR_CODE,
107 (void *) code_start,
108 code_pages);
109 NaClLog(2, "got 0x%x\n", cs);
110 if (0 == cs) {
111 retval = SRT_NO_SEG_SEL;
112 goto done;
116 * Determine what region of memory can be accessed as data.
118 * NB: in our memory model, we roughly follow standard 7th edition
119 * unix but with a >16-bit address space: data and code overlap, and
120 * the start of the data segment is the same as the start of the
121 * code region; and the data segment actually includes the memory
122 * hole between the break and the top of the stack, as well as the
123 * stack and environment variables and other things in memory above
124 * the stack.
126 * The code pages, which is marked read-only via the page protection
127 * mechanism, could be viewed as read-only data. Nothing prevents a
128 * NaCl application from looking at its own code.
130 * The same segment selector is used for ds, es, and ss, and thus
131 * "des_seg". Nuthin' to do with the old Data Encryption Standard.
134 if (data_pages < 1) {
135 NaClLog(LOG_FATAL,
136 "NaClAppPrepareToLaunch: address space is fewer than one page?\n");
138 NaClLog(2,
139 "NaClLdtAllocatePageSelector(data, 1, 0x%08"PRIxPTR", 0x%"PRIxS"\n",
140 data_start, data_pages - 1);
141 des_seg = NaClLdtAllocatePageSelector(NACL_LDT_DESCRIPTOR_DATA,
143 (void *) data_start,
144 data_pages);
146 NaClLog(2, "got 0x%x\n", des_seg);
147 if (0 == des_seg) {
148 NaClLdtDeleteSelector(cs);
149 retval = SRT_NO_SEG_SEL;
150 goto done;
152 nap->code_seg_sel = cs;
153 nap->data_seg_sel = des_seg;
155 * Note that gs is thread-specific and not global, so that is allocated
156 * elsewhere. See nacl_app_thread.c.
160 * We dup the stdin, stdout, and stderr descriptors and wrap them in
161 * NaClHostDesc objects. Those in turn are wrapped by the
162 * NaClDescIoDesc subclass of NaClDesc, and then put into the
163 * open-file table. NaCl app I/O operations will use these shared
164 * descriptors, and if they close one of these descriptors it will
165 * only be a duplicated descriptor. NB: some fcntl/ioctl flags
166 * apply to the descriptor (e.g., O_CLOEXEC) and some apply to the
167 * underlying open file entry (e.g., O_NONBLOCK), so changes by the
168 * NaCl app could affect the service runtime.
170 for (i = 0; i < 3; ++i) {
171 nhdp = malloc(sizeof *nhdp);
172 if (NULL == nhdp) {
173 NaClLog(LOG_FATAL,
174 "NaClAppPrepareToLaunch: no memory for abstract descriptor %d\n",
177 NaClHostDescPosixDup(nhdp, descs[i], (0 == i) ? O_RDONLY : O_WRONLY);
178 NaClSetDesc(nap, i, (struct NaClDesc *) NaClDescIoDescMake(nhdp));
180 retval = LOAD_OK;
181 done:
182 NaClXMutexUnlock(&nap->mu);
183 return retval;