Fix file permissions: set executable bit
[nativeclient.git] / service_runtime / sel_addrspace.c
blobf7a731456f918360519fc3e0e73a187f1cb07dae
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.
32 /* NaCl Simple/secure ELF loader (NaCl SEL).
35 #include "native_client/include/portability.h"
36 #include "native_client/include/nacl_platform.h"
38 #include "native_client/service_runtime/nacl_log.h"
39 #include "native_client/service_runtime/sel_addrspace.h"
40 #include "native_client/service_runtime/sel_util.h"
41 #include "native_client/service_runtime/sel_memory.h"
44 NaClErrorCode NaClAllocAddrSpace(struct NaClApp *nap)
46 void *mem;
47 uintptr_t hole_start;
48 size_t hole_size;
49 uintptr_t stack_start;
51 NaClLog(2, "NaClAllocAddrSpace: calling NaCl_page_alloc(*,0x%x)\n",
52 (1U << nap->addr_bits));
53 if (NaCl_page_alloc(&mem,
54 (1U << nap->addr_bits)) != 0) {
55 NaClLog(2, "NaClAllocAddrSpace: NaCl_page_alloc failed\n");
56 return LOAD_NO_MEMORY;
58 nap->mem_start = (uintptr_t) mem;
59 nap->xlate_base = nap->mem_start;
60 NaClLog(2, "allocated memory at 0x%08x\n", nap->mem_start);
62 hole_start = NaClRoundAllocPage(nap->data_end);
64 /* TODO: check for underflow? only trusted code can set stack_size */
65 stack_start = (1U << nap->addr_bits) - nap->stack_size;
66 stack_start = NaClTruncAllocPage(stack_start);
68 if (stack_start < hole_start) {
69 return LOAD_DATA_OVERLAPS_STACK_SECTION;
72 hole_size = stack_start - hole_start;
73 hole_size = NaClTruncAllocPage(hole_size);
76 * mprotect and madvise unused data space to "free" it up, but
77 * retain mapping so no other memory can be mapped into those
78 * addresses.
80 if (hole_size == 0) {
81 NaClLog(2, ("NaClAllocAddrSpace: hole between end of data and"
82 " the beginning of stack is zero size.\n"));
83 } else {
84 NaClLog(2,
85 "madvising 0x%08x, 0x%08x, PROT_NONE\n",
86 nap->mem_start + hole_start, hole_size);
87 if (NaCl_madvise((void *) (nap->mem_start + hole_start),
88 hole_size,
89 MADV_DONTNEED) != 0) {
90 return LOAD_MADVISE_FAIL;
93 NaClLog(2,
94 "mprotecting 0x%08x, 0x%08x, PROT_NONE\n",
95 nap->mem_start + hole_start, hole_size);
96 if (NaCl_mprotect((void *) (nap->mem_start + hole_start),
97 hole_size,
98 PROT_NONE) != 0) {
99 return LOAD_MPROTECT_FAIL;
103 return LOAD_OK;
107 * Apply memory protection to memory regions.
109 NaClErrorCode NaClMemoryProtection(struct NaClApp *nap)
111 uintptr_t start_addr;
112 uint32_t region_size;
113 int err;
115 start_addr = nap->mem_start;
117 * The first NACL_SYSCALL_START_ADDR bytes are mapped as PROT_NONE.
118 * This enables NULL pointer checking. Since NACL_SYSCALL_START_ADDR
119 * is a multiple of the page size, we don't need to round it to be so.
121 NaClLog(3, "NULL detection region start 0x%08x, size 0x%08x, end 0x%08x\n",
122 start_addr, NACL_SYSCALL_START_ADDR,
123 start_addr + NACL_SYSCALL_START_ADDR);
124 if ((err = NaCl_mprotect((void *) start_addr,
125 NACL_SYSCALL_START_ADDR,
126 PROT_NONE)) != 0) {
127 NaClLog(LOG_ERROR, ("NaClMemoryProtection:"
128 " NaCl_mprotect(0x%08x, 0x%08x, 0x%x) failed,"
129 " error %d (NULL pointer guard page)\n"),
130 (uintptr_t) start_addr, NACL_SYSCALL_START_ADDR, PROT_NONE,
131 err);
132 return LOAD_MPROTECT_FAIL;
134 if (!NaClVmmapAdd(&nap->mem_map,
135 (start_addr - nap->mem_start) >> NACL_PAGESHIFT,
136 NACL_SYSCALL_START_ADDR >> NACL_PAGESHIFT,
137 PROT_NONE,
138 (struct NaClMemObj *) NULL)) {
139 NaClLog(LOG_ERROR, ("NaClMemoryProtection: NaClVmmapAdd failed"
140 " (NULL pointer guard page)\n"));
141 return LOAD_MPROTECT_FAIL;
144 start_addr = nap->mem_start + NACL_SYSCALL_START_ADDR;
146 * The next pages up to NACL_TRAMPOLINE_SIZE are the trampolines.
147 * Immediately following that is the loaded text section.
148 * These are collectively marked as PROT_READ | PROT_EXEC.
150 region_size = NaClRoundPage(NACL_TRAMPOLINE_SIZE - NACL_SYSCALL_START_ADDR
151 + nap->text_region_bytes);
152 NaClLog(3, "Trampoline/text region start 0x%08x, size 0x%08x, end 0x%08x\n",
153 start_addr, region_size,
154 start_addr + region_size);
155 if ((err = NaCl_mprotect((void *) start_addr,
156 region_size,
157 PROT_READ | PROT_EXEC)) != 0) {
158 NaClLog(LOG_ERROR, ("NaClMemoryProtection:"
159 " NaCl_mprotect(0x%08x, 0x%08x, 0x%x) failed,"
160 " error %d (trampoline)\n"),
161 (uintptr_t) start_addr, region_size, PROT_READ | PROT_EXEC,
162 err);
163 return LOAD_MPROTECT_FAIL;
165 if (!NaClVmmapAdd(&nap->mem_map,
166 (start_addr - nap->mem_start) >> NACL_PAGESHIFT,
167 region_size >> NACL_PAGESHIFT,
168 PROT_READ | PROT_EXEC,
169 (struct NaClMemObj *) NULL)) {
170 NaClLog(LOG_ERROR, ("NaClMemoryProtection: NaClVmmapAdd failed"
171 " (trampoline)\n"));
172 return LOAD_MPROTECT_FAIL;
175 start_addr = NaClRoundPage(start_addr + region_size);
177 * data_end is max virtual addr seen, so start_addr <= data_end
178 * must hold.
181 region_size = NaClRoundPage(NaClRoundAllocPage(nap->data_end)
182 + nap->mem_start - start_addr);
183 NaClLog(3, "RW data region start 0x%08x, size 0x%08x, end 0x%08x\n",
184 start_addr, region_size,
185 start_addr + region_size);
186 if ((err = NaCl_mprotect((void *) start_addr,
187 region_size,
188 PROT_READ | PROT_WRITE)) != 0) {
189 NaClLog(LOG_ERROR, ("NaClMemoryProtection:"
190 " NaCl_mprotect(0x%08x, 0x%08x, 0x%x) failed,"
191 " error %d (data)\n"),
192 (uintptr_t) start_addr, region_size, PROT_READ | PROT_WRITE,
193 err);
194 return LOAD_MPROTECT_FAIL;
196 if (!NaClVmmapAdd(&nap->mem_map,
197 (start_addr - nap->mem_start) >> NACL_PAGESHIFT,
198 region_size >> NACL_PAGESHIFT,
199 PROT_READ | PROT_WRITE,
200 (struct NaClMemObj *) NULL)) {
201 NaClLog(LOG_ERROR, ("NaClMemoryProtection: NaClVmmapAdd failed"
202 " (data)\n"));
203 return LOAD_MPROTECT_FAIL;
206 /* stack is read/write but not execute */
207 region_size = nap->stack_size;
208 start_addr = (nap->mem_start
209 + NaClTruncAllocPage((1U << nap->addr_bits)
210 - nap->stack_size));
211 NaClLog(3, "RW stack region start 0x%08x, size 0x%08x, end 0x%08x\n",
212 start_addr, region_size,
213 start_addr + region_size);
214 if ((err = NaCl_mprotect((void *) start_addr,
215 NaClRoundAllocPage(nap->stack_size),
216 PROT_READ | PROT_WRITE)) != 0) {
217 NaClLog(LOG_ERROR, ("NaClMemoryProtection:"
218 " NaCl_mprotect(0x%08x, 0x%08x, 0x%x) failed,"
219 " error %d (stack)\n"),
220 (uintptr_t) start_addr, region_size, PROT_READ | PROT_WRITE,
221 err);
222 return LOAD_MPROTECT_FAIL;
225 if (!NaClVmmapAdd(&nap->mem_map,
226 (start_addr - nap->mem_start) >> NACL_PAGESHIFT,
227 nap->stack_size >> NACL_PAGESHIFT,
228 PROT_READ | PROT_WRITE,
229 (struct NaClMemObj *) NULL)) {
230 NaClLog(LOG_ERROR, ("NaClMemoryProtection: NaClVmmapAdd failed"
231 " (stack)\n"));
232 return LOAD_MPROTECT_FAIL;
234 return LOAD_OK;