Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2)

Side by Side Diff: src/trusted/validator/ncfileutil.c

Issue 8161004: Handle ELFCLASS32 files for x86-64 (Closed) Base URL: svn://svn.chromium.org/native_client/trunk/src/native_client
Patch Set: typo fixes in last iteration Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2011 The Native Client Authors. All rights reserved. 2 * Copyright (c) 2011 The Native Client Authors. All rights reserved.
3 * Use of this source code is governed by a BSD-style license that can be 3 * Use of this source code is governed by a BSD-style license that can be
4 * found in the LICENSE file. 4 * found in the LICENSE file.
5 */ 5 */
6 6
7 /* 7 /*
8 * ncfileutil.c - open an executable file. FOR TESTING ONLY. 8 * ncfileutil.c - open an executable file. FOR TESTING ONLY.
9 */ 9 */
10 10
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 if (c == ELFCLASS32) { 76 if (c == ELFCLASS32) {
77 return "(32 bit executable)"; 77 return "(32 bit executable)";
78 } else if (c == ELFCLASS64) { 78 } else if (c == ELFCLASS64) {
79 return "(64 bit executable)"; 79 return "(64 bit executable)";
80 } else { 80 } else {
81 return "(invalid class)"; 81 return "(invalid class)";
82 } 82 }
83 } 83 }
84 84
85 static int nc_load(ncfile *ncf, int fd) { 85 static int nc_load(ncfile *ncf, int fd) {
86 86 union {
87 Elf_Ehdr h; 87 Elf32_Ehdr h32;
88 #if NACL_TARGET_SUBARCH == 64
89 Elf64_Ehdr h64;
90 #endif
91 } h;
92 Elf_Half phnum;
93 Elf_Half shnum;
94 Elf_Off phoff;
95 Elf_Off shoff;
88 ssize_t nread; 96 ssize_t nread;
89 Elf_Addr vmemlo, vmemhi; 97 Elf_Addr vmemlo, vmemhi;
90 size_t shsize, phsize; 98 size_t shsize, phsize;
91 int i; 99 int i;
92 100
93 /* Read and check the ELF header */ 101 /* Read and check the ELF header */
94 nread = readat(ncf, fd, &h, sizeof(h), 0); 102 nread = readat(ncf, fd, &h, sizeof(h), 0);
95 if (nread < 0 || (size_t) nread < sizeof(h)) { 103 if (nread < 0 || (size_t) nread < sizeof(h)) {
96 ncf->error_fn("nc_load(%s): could not read ELF header", ncf->fname); 104 ncf->error_fn("nc_load(%s): could not read ELF header", ncf->fname);
97 return -1; 105 return -1;
98 } 106 }
99 107
100 /* do a bunch of sanity checks */ 108 /* do a bunch of sanity checks */
101 if (strncmp((char *)h.e_ident, ELFMAG, strlen(ELFMAG))) { 109 if (memcmp(h.h32.e_ident, ELFMAG, SELFMAG)) {
102 ncf->error_fn("nc_load(%s): bad magic number", ncf->fname); 110 ncf->error_fn("nc_load(%s): bad magic number", ncf->fname);
103 return -1; 111 return -1;
104 } 112 }
105 113
106 if (h.e_ident[EI_CLASS] != NACL_ELF_CLASS) { 114 #if NACL_TARGET_SUBARCH == 64
107 ncf->error_fn("nc_load(%s): bad EI CLASS %d %s\n", ncf->fname, 115 if (h.h32.e_ident[EI_CLASS] == ELFCLASS64) {
108 h.e_ident[EI_CLASS], GetEiClassName(h.e_ident[EI_CLASS])); 116 if (h.h64.e_phoff > 0xffffffffU) {
117 ncf->error_fn("nc_load(%s): e_phoff overflows 32 bits\n", ncf->fname);
118 return -1;
119 }
120 if (h.h64.e_shoff > 0xffffffffU) {
121 ncf->error_fn("nc_load(%s): e_shoff overflows 32 bits\n", ncf->fname);
122 return -1;
123 }
124 phoff = (Elf32_Off) h.h64.e_phoff;
125 shoff = (Elf32_Off) h.h64.e_shoff;
126 phnum = h.h64.e_phnum;
127 shnum = h.h64.e_shnum;
128 } else
129 #endif
130 {
131 if (h.h32.e_ident[EI_CLASS] == ELFCLASS32) {
132 phoff = h.h32.e_phoff;
133 shoff = h.h32.e_shoff;
134 phnum = h.h32.e_phnum;
135 shnum = h.h32.e_shnum;
136 } else {
137 ncf->error_fn("nc_load(%s): bad EI CLASS %d %s\n", ncf->fname,
138 h.h32.e_ident[EI_CLASS],
139 GetEiClassName(h.h32.e_ident[EI_CLASS]));
140 return -1;
141 }
109 } 142 }
110 143
111 /* We now support only 32-byte bundle alignment. */ 144 /* We now support only 32-byte bundle alignment. */
112 ncf->ncalign = 32; 145 ncf->ncalign = 32;
113 146
114 /* Read the program header table */ 147 /* Read the program header table */
115 if (h.e_phnum <= 0 || h.e_phnum > kMaxPhnum) { 148 if (phnum <= 0 || phnum > kMaxPhnum) {
116 ncf->error_fn("nc_load(%s): h.e_phnum %d > kMaxPhnum %d\n", 149 ncf->error_fn("nc_load(%s): e_phnum %d > kMaxPhnum %d\n",
117 ncf->fname, h.e_phnum, kMaxPhnum); 150 ncf->fname, phnum, kMaxPhnum);
118 return -1; 151 return -1;
119 } 152 }
120 ncf->phnum = h.e_phnum; 153 ncf->phnum = phnum;
121 ncf->pheaders = (Elf_Phdr *)calloc(h.e_phnum, sizeof(Elf_Phdr)); 154 ncf->pheaders = (Elf_Phdr *)calloc(phnum, sizeof(Elf_Phdr));
122 if (NULL == ncf->pheaders) { 155 if (NULL == ncf->pheaders) {
123 ncf->error_fn("nc_load(%s): calloc(%d, %"NACL_PRIdS") failed\n", 156 ncf->error_fn("nc_load(%s): calloc(%d, %"NACL_PRIdS") failed\n",
124 ncf->fname, h.e_phnum, sizeof(Elf_Phdr)); 157 ncf->fname, phnum, sizeof(Elf_Phdr));
125 return -1; 158 return -1;
126 } 159 }
127 phsize = h.e_phnum * sizeof(*ncf->pheaders); 160 phsize = phnum * sizeof(*ncf->pheaders);
128 /* TODO(karl) Remove the cast to size_t, or verify size. */ 161 #if NACL_TARGET_SUBARCH == 64
129 nread = readat(ncf, fd, ncf->pheaders, (off_t) phsize, (off_t) h.e_phoff); 162 if (h.h32.e_ident[EI_CLASS] == ELFCLASS64) {
130 if (nread < 0 || (size_t) nread < phsize) return -1; 163 /*
164 * Read 64-bit program headers and convert them.
165 */
166 Elf64_Phdr phdr64[kMaxPhnum];
167 nread = readat(ncf, fd, phdr64, (off_t) (phnum * sizeof(phdr64[0])),
168 (off_t) phoff);
169 if (nread < 0 || (size_t) nread < phsize) return -1;
170 for (i = 0; i < phnum; ++i) {
171 if (phdr64[i].p_offset > 0xffffffffU ||
172 phdr64[i].p_vaddr > 0xffffffffU ||
173 phdr64[i].p_paddr > 0xffffffffU ||
174 phdr64[i].p_filesz > 0xffffffffU ||
175 phdr64[i].p_memsz > 0xffffffffU ||
176 phdr64[i].p_align > 0xffffffffU) {
177 ncf->error_fn("nc_load(%s): phdr[%d] fields overflow 32 bits\n",
178 ncf->fname, i);
179 return -1;
180 }
181 ncf->pheaders[i].p_type = phdr64[i].p_type;
182 ncf->pheaders[i].p_flags = phdr64[i].p_flags;
183 ncf->pheaders[i].p_offset = (Elf32_Off) phdr64[i].p_offset;
184 ncf->pheaders[i].p_vaddr = (Elf32_Addr) phdr64[i].p_vaddr;
185 ncf->pheaders[i].p_paddr = (Elf32_Addr) phdr64[i].p_paddr;
186 ncf->pheaders[i].p_filesz = (Elf32_Word) phdr64[i].p_filesz;
187 ncf->pheaders[i].p_memsz = (Elf32_Word) phdr64[i].p_memsz;
188 ncf->pheaders[i].p_align = (Elf32_Word) phdr64[i].p_align;
189 }
190 } else
191 #endif
192 {
193 /* TODO(karl) Remove the cast to size_t, or verify size. */
194 nread = readat(ncf, fd, ncf->pheaders, (off_t) phsize, (off_t) phoff);
195 if (nread < 0 || (size_t) nread < phsize) return -1;
196 }
131 197
132 /* Iterate through the program headers to find the virtual */ 198 /* Iterate through the program headers to find the virtual */
133 /* size of loaded text. */ 199 /* size of loaded text. */
134 vmemlo = MAX_ELF_ADDR; 200 vmemlo = MAX_ELF_ADDR;
135 vmemhi = MIN_ELF_ADDR; 201 vmemhi = MIN_ELF_ADDR;
136 for (i = 0; i < h.e_phnum; i++) { 202 for (i = 0; i < phnum; i++) {
137 if (ncf->pheaders[i].p_type != PT_LOAD) continue; 203 if (ncf->pheaders[i].p_type != PT_LOAD) continue;
138 if (0 == (ncf->pheaders[i].p_flags & PF_X)) continue; 204 if (0 == (ncf->pheaders[i].p_flags & PF_X)) continue;
139 /* This is executable text. Check low and high addrs */ 205 /* This is executable text. Check low and high addrs */
140 if (vmemlo > ncf->pheaders[i].p_vaddr) vmemlo = ncf->pheaders[i].p_vaddr; 206 if (vmemlo > ncf->pheaders[i].p_vaddr) vmemlo = ncf->pheaders[i].p_vaddr;
141 if (vmemhi < ncf->pheaders[i].p_vaddr + ncf->pheaders[i].p_memsz) { 207 if (vmemhi < ncf->pheaders[i].p_vaddr + ncf->pheaders[i].p_memsz) {
142 vmemhi = ncf->pheaders[i].p_vaddr + ncf->pheaders[i].p_memsz; 208 vmemhi = ncf->pheaders[i].p_vaddr + ncf->pheaders[i].p_memsz;
143 } 209 }
144 } 210 }
145 ncf->size = vmemhi - vmemlo; 211 ncf->size = vmemhi - vmemlo;
146 ncf->vbase = vmemlo; 212 ncf->vbase = vmemlo;
147 /* TODO(karl) Remove the cast to size_t, or verify size. */ 213 /* TODO(karl) Remove the cast to size_t, or verify size. */
148 ncf->data = (uint8_t *)calloc(1, (size_t) ncf->size); 214 ncf->data = (uint8_t *)calloc(1, (size_t) ncf->size);
149 if (NULL == ncf->data) { 215 if (NULL == ncf->data) {
150 ncf->error_fn("nc_load(%s): calloc(1, %d) failed\n", 216 ncf->error_fn("nc_load(%s): calloc(1, %d) failed\n",
151 ncf->fname, (int)ncf->size); 217 ncf->fname, (int)ncf->size);
152 return -1; 218 return -1;
153 } 219 }
154 220
155 /* Load program text segments */ 221 /* Load program text segments */
156 for (i = 0; i < h.e_phnum; i++) { 222 for (i = 0; i < phnum; i++) {
157 const Elf_Phdr *p = &ncf->pheaders[i]; 223 const Elf_Phdr *p = &ncf->pheaders[i];
158 if (p->p_type != PT_LOAD) continue; 224 if (p->p_type != PT_LOAD) continue;
159 if (0 == (ncf->pheaders[i].p_flags & PF_X)) continue; 225 if (0 == (ncf->pheaders[i].p_flags & PF_X)) continue;
160 226
161 /* TODO(karl) Remove the cast to off_t, or verify value in range. */ 227 /* TODO(karl) Remove the cast to off_t, or verify value in range. */
162 nread = readat(ncf, fd, &(ncf->data[p->p_vaddr - ncf->vbase]), 228 nread = readat(ncf, fd, &(ncf->data[p->p_vaddr - ncf->vbase]),
163 (off_t) p->p_filesz, (off_t) p->p_offset); 229 (off_t) p->p_filesz, (off_t) p->p_offset);
164 if (nread < 0 || (size_t) nread < p->p_filesz) { 230 if (nread < 0 || (size_t) nread < p->p_filesz) {
165 ncf->error_fn( 231 ncf->error_fn(
166 "nc_load(%s): could not read segment %d (%d < %" 232 "nc_load(%s): could not read segment %d (%d < %"
167 NACL_PRIuElf_Xword")\n", 233 NACL_PRIuElf_Xword")\n",
168 ncf->fname, i, (int)nread, p->p_filesz); 234 ncf->fname, i, (int)nread, p->p_filesz);
169 return -1; 235 return -1;
170 } 236 }
171 } 237 }
238
172 /* load the section headers */ 239 /* load the section headers */
173 ncf->shnum = h.e_shnum; 240 ncf->shnum = shnum;
174 shsize = ncf->shnum * sizeof(*ncf->sheaders); 241 shsize = ncf->shnum * sizeof(*ncf->sheaders);
175 ncf->sheaders = (Elf_Shdr *)calloc(1, shsize); 242 ncf->sheaders = (Elf_Shdr *)calloc(1, shsize);
176 if (NULL == ncf->sheaders) { 243 if (NULL == ncf->sheaders) {
177 ncf->error_fn("nc_load(%s): calloc(1, %"NACL_PRIdS") failed\n", 244 ncf->error_fn("nc_load(%s): calloc(1, %"NACL_PRIdS") failed\n",
178 ncf->fname, shsize); 245 ncf->fname, shsize);
179 return -1; 246 return -1;
180 } 247 }
181 /* TODO(karl) Remove the cast to size_t, or verify value in range. */ 248 #if NACL_TARGET_SUBARCH == 64
182 nread = readat(ncf, fd, ncf->sheaders, (off_t) shsize, (off_t) h.e_shoff); 249 if (h.h32.e_ident[EI_CLASS] == ELFCLASS64) {
183 if (nread < 0 || (size_t) nread < shsize) { 250 /*
184 ncf->error_fn("nc_load(%s): could not read section headers\n", 251 * Read 64-bit section headers and convert them.
185 ncf->fname); 252 */
186 return -1; 253 Elf64_Shdr *shdr64 = (Elf64_Shdr *)calloc(shnum, sizeof(shdr64[0]));
254 if (NULL == shdr64) {
255 ncf->error_fn(
256 "nc_load(%s): calloc(%"NACL_PRIdS", %"NACL_PRIdS") failed\n",
257 ncf->fname, (size_t) shnum, sizeof(shdr64[0]));
258 return -1;
259 }
260 shsize = ncf->shnum * sizeof(shdr64[0]);
261 nread = readat(ncf, fd, shdr64, (off_t) shsize, (off_t) shoff);
262 if (nread < 0 || (size_t) nread < shsize) {
263 ncf->error_fn("nc_load(%s): could not read section headers\n",
264 ncf->fname);
265 return -1;
266 }
267 for (i = 0; i < shnum; ++i) {
268 if (shdr64[i].sh_flags > 0xffffffffU ||
269 shdr64[i].sh_size > 0xffffffffU ||
270 shdr64[i].sh_addralign > 0xffffffffU ||
271 shdr64[i].sh_entsize > 0xffffffffU) {
272 ncf->error_fn("nc_load(%s): shdr[%d] fields overflow 32 bits\n",
273 ncf->fname, i);
274 return -1;
275 }
276 ncf->sheaders[i].sh_name = shdr64[i].sh_name;
277 ncf->sheaders[i].sh_type = shdr64[i].sh_type;
278 ncf->sheaders[i].sh_flags = (Elf32_Word) shdr64[i].sh_flags;
279 ncf->sheaders[i].sh_addr = (Elf32_Addr) shdr64[i].sh_addr;
280 ncf->sheaders[i].sh_offset = (Elf32_Off) shdr64[i].sh_offset;
281 ncf->sheaders[i].sh_size = (Elf32_Word) shdr64[i].sh_size;
282 ncf->sheaders[i].sh_link = shdr64[i].sh_link;
283 ncf->sheaders[i].sh_info = shdr64[i].sh_info;
284 ncf->sheaders[i].sh_addralign = (Elf32_Word) shdr64[i].sh_addralign;
285 ncf->sheaders[i].sh_entsize = (Elf32_Word) shdr64[i].sh_entsize;
286 }
287 free(shdr64);
288 } else
289 #endif
290 {
291 /* TODO(karl) Remove the cast to size_t, or verify value in range. */
292 nread = readat(ncf, fd, ncf->sheaders, (off_t) shsize, (off_t) shoff);
293 if (nread < 0 || (size_t) nread < shsize) {
294 ncf->error_fn("nc_load(%s): could not read section headers\n",
295 ncf->fname);
296 return -1;
297 }
187 } 298 }
188 299
189 /* success! */ 300 /* success! */
190 return 0; 301 return 0;
191 } 302 }
192 303
193 ncfile *nc_loadfile_depending(const char *filename, 304 ncfile *nc_loadfile_depending(const char *filename,
194 nc_loadfile_error_fn error_fn) { 305 nc_loadfile_error_fn error_fn) {
195 ncfile *ncf; 306 ncfile *ncf;
196 int fd; 307 int fd;
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
246 for (ii = 0; ii < ncf->shnum; ii++) { 357 for (ii = 0; ii < ncf->shnum; ii++) {
247 if ((ncf->sheaders[ii].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR) { 358 if ((ncf->sheaders[ii].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR) {
248 if (ncf->sheaders[ii].sh_addr < base) base = ncf->sheaders[ii].sh_addr; 359 if (ncf->sheaders[ii].sh_addr < base) base = ncf->sheaders[ii].sh_addr;
249 if (ncf->sheaders[ii].sh_addr + ncf->sheaders[ii].sh_size > limit) 360 if (ncf->sheaders[ii].sh_addr + ncf->sheaders[ii].sh_size > limit)
250 limit = ncf->sheaders[ii].sh_addr + ncf->sheaders[ii].sh_size; 361 limit = ncf->sheaders[ii].sh_addr + ncf->sheaders[ii].sh_size;
251 } 362 }
252 } 363 }
253 *vbase = base; 364 *vbase = base;
254 *vlimit = limit; 365 *vlimit = limit;
255 } 366 }
OLDNEW
« no previous file with comments | « src/trusted/service_runtime/testdata/x86_64/text_too_big.stderr ('k') | src/trusted/validator_x86/build.scons » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698