Print this page
5535 libelf should check for e_phoff overflow
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/libelf/common/clscook.c
+++ new/usr/src/cmd/sgs/libelf/common/clscook.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 /* Copyright (c) 1988 AT&T */
28 28 /* All Rights Reserved */
29 29
30 30 /*
31 31 * This stuff used to live in cook.c, but was moved out to
32 32 * facilitate dual (Elf32 and Elf64) compilation. See block
33 33 * comment in cook.c for more info.
34 34 */
35 35
36 36 #include <string.h>
37 37 #include <ar.h>
38 38 #include <stdlib.h>
39 39 #include <errno.h>
40 40 #include <sys/sysmacros.h>
41 41 #include "decl.h"
42 42 #include "member.h"
43 43 #include "msg.h"
44 44
45 45 /*
46 46 * This module is compiled twice, the second time having
47 47 * -D_ELF64 defined. The following set of macros, along
48 48 * with machelf.h, represent the differences between the
49 49 * two compilations. Be careful *not* to add any class-
50 50 * dependent code (anything that has elf32 or elf64 in the
51 51 * name) to this code without hiding it behind a switch-
52 52 * able macro like these.
53 53 */
54 54 #if defined(_ELF64)
55 55 #define Snode Snode64
56 56 #define ELFCLASS ELFCLASS64
57 57 #define ElfField Elf64
58 58 #define _elf_snode_init _elf64_snode_init
59 59 #define _elf_prepscan _elf64_prepscan
60 60 #define _elf_cookscn _elf64_cookscn
61 61 #define _elf_mtype _elf64_mtype
62 62 #define _elf_msize _elf64_msize
63 63 #define elf_fsize elf64_fsize
64 64 #define _elf_snode _elf64_snode
65 65 #define _elf_ehdr _elf64_ehdr
66 66 #define elf_xlatetom elf64_xlatetom
67 67 #define _elf_phdr _elf64_phdr
68 68 #define _elf_shdr _elf64_shdr
69 69 #define _elf_prepscn _elf64_prepscn
70 70
71 71 #else /* Elf32 */
72 72 #define Snode Snode32
73 73 #define ELFCLASS ELFCLASS32
74 74 #define ElfField Elf32
75 75 #define _elf_snode_init _elf32_snode_init
76 76 #define _elf_prepscan _elf32_prepscan
77 77 #define _elf_cookscn _elf32_cookscn
78 78 #define _elf_mtype _elf32_mtype
79 79 #define _elf_msize _elf32_msize
80 80 #define elf_fsize elf32_fsize
81 81 #define _elf_snode _elf32_snode
82 82 #define _elf_ehdr _elf32_ehdr
83 83 #define elf_xlatetom elf32_xlatetom
84 84 #define _elf_phdr _elf32_phdr
85 85 #define _elf_shdr _elf32_shdr
86 86 #define _elf_prepscn _elf32_prepscn
87 87
88 88 #endif /* _ELF64 */
89 89
90 90
91 91 static Okay
92 92 _elf_prepscn(Elf *elf, size_t cnt)
93 93 {
94 94 NOTE(ASSUMING_PROTECTED(*elf))
95 95 Elf_Scn * s;
96 96 Elf_Scn * end;
97 97
98 98 if (cnt == 0)
99 99 return (OK_YES);
100 100
101 101 if ((s = malloc(cnt * sizeof (Elf_Scn))) == 0) {
102 102 _elf_seterr(EMEM_SCN, errno);
103 103 return (OK_NO);
104 104 }
105 105 NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*s))
106 106 elf->ed_scntabsz = cnt;
107 107 end = s + cnt;
108 108 elf->ed_hdscn = s;
109 109 do {
110 110 *s = _elf_snode_init.sb_scn;
111 111 s->s_elf = elf;
112 112 s->s_next = s + 1;
113 113 s->s_index = s - elf->ed_hdscn;
114 114 s->s_shdr = (Shdr*)s->s_elf->ed_shdr + s->s_index;
115 115 ELFMUTEXINIT(&s->s_mutex);
116 116
117 117 /*
118 118 * Section has not yet been cooked!
119 119 *
120 120 * We don't cook a section until it's data is actually
121 121 * referenced.
122 122 */
123 123 s->s_myflags = 0;
124 124 } while (++s < end);
125 125
126 126 elf->ed_tlscn = --s;
127 127 s->s_next = 0;
128 128
129 129 /*
130 130 * Section index SHN_UNDEF (0) does not and cannot
131 131 * have a data buffer. Fix it here. Also mark the
132 132 * initial section as being allocated for the block
133 133 */
134 134
135 135 s = elf->ed_hdscn;
136 136 s->s_myflags = SF_ALLOC;
137 137 s->s_hdnode = 0;
138 138 s->s_tlnode = 0;
139 139 NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*s))
140 140 return (OK_YES);
141 141 }
142 142
143 143
144 144 Okay
145 145 _elf_cookscn(Elf_Scn * s)
146 146 {
147 147 NOTE(ASSUMING_PROTECTED(*s, *(s->s_elf)))
148 148 Elf * elf;
149 149 Shdr * sh;
150 150 register Dnode * d = &s->s_dnode;
151 151 size_t fsz, msz;
152 152 unsigned work;
153 153
154 154 NOTE(NOW_INVISIBLE_TO_OTHER_THREADS(*d))
155 155 s->s_hdnode = s->s_tlnode = d;
156 156 s->s_err = 0;
157 157 s->s_shflags = 0;
158 158 s->s_uflags = 0;
159 159
160 160
161 161 /*
162 162 * Prepare d_data for inspection, but don't actually
163 163 * translate data until needed. Leave the READY
164 164 * flag off. NOBITS sections see zero size.
165 165 */
166 166 elf = s->s_elf;
167 167 sh = s->s_shdr;
168 168
169 169 d->db_scn = s;
170 170 d->db_off = sh->sh_offset;
171 171 d->db_data.d_align = sh->sh_addralign;
172 172 d->db_data.d_version = elf->ed_version;
173 173 ELFACCESSDATA(work, _elf_work)
174 174 d->db_data.d_type = _elf_mtype(elf, sh->sh_type, work);
175 175 d->db_data.d_buf = 0;
176 176 d->db_data.d_off = 0;
177 177 fsz = elf_fsize(d->db_data.d_type, 1, elf->ed_version);
178 178 msz = _elf_msize(d->db_data.d_type, elf->ed_version);
179 179 d->db_data.d_size = MAX(sh->sh_size, (sh->sh_size / fsz) * msz);
180 180 d->db_shsz = sh->sh_size;
181 181 d->db_raw = 0;
182 182 d->db_buf = 0;
183 183 d->db_uflags = 0;
184 184 d->db_myflags = 0;
185 185 d->db_next = 0;
186 186
187 187 if (sh->sh_type != SHT_NOBITS)
188 188 d->db_fsz = sh->sh_size;
189 189 else
190 190 d->db_fsz = 0;
191 191
192 192 s->s_myflags |= SF_READY;
193 193
194 194 NOTE(NOW_VISIBLE_TO_OTHER_THREADS(*d))
195 195 return (OK_YES);
196 196 }
197 197
198 198
199 199
200 200 Snode *
201 201 _elf_snode()
202 202 {
203 203 register Snode *s;
204 204
205 205 if ((s = malloc(sizeof (Snode))) == 0) {
206 206 _elf_seterr(EMEM_SNODE, errno);
207 207 return (0);
208 208 }
209 209 *s = _elf_snode_init;
210 210 ELFMUTEXINIT(&s->sb_scn.s_mutex);
211 211 s->sb_scn.s_myflags = SF_ALLOC | SF_READY;
212 212 s->sb_scn.s_shdr = &s->sb_shdr;
213 213 return (s);
214 214 }
215 215
216 216
217 217
218 218 int
219 219 _elf_ehdr(Elf * elf, int inplace)
220 220 {
221 221 NOTE(ASSUMING_PROTECTED(*elf))
222 222 register size_t fsz; /* field size */
223 223 Elf_Data dst, src;
224 224
225 225 fsz = elf_fsize(ELF_T_EHDR, 1, elf->ed_version);
226 226 if (fsz > elf->ed_fsz) {
227 227 _elf_seterr(EFMT_EHDRSZ, 0);
228 228 return (-1);
229 229 }
230 230 if (inplace && (fsz >= sizeof (Ehdr))) {
231 231 /*
232 232 * The translated Ehdr will fit over the original Ehdr.
233 233 */
234 234 /* LINTED */
235 235 elf->ed_ehdr = (Ehdr *)elf->ed_ident;
236 236 elf->ed_status = ES_COOKED;
237 237 } else {
238 238 elf->ed_ehdr = malloc(sizeof (Ehdr));
239 239 if (elf->ed_ehdr == 0) {
240 240 _elf_seterr(EMEM_EHDR, errno);
241 241 return (-1);
242 242 }
243 243 elf->ed_myflags |= EDF_EHALLOC;
244 244 }
245 245
246 246 /*
247 247 * Memory size >= fsz, because otherwise the memory version
248 248 * loses information and cannot accurately implement the
249 249 * file.
250 250 */
251 251
252 252 src.d_buf = (Elf_Void *)elf->ed_ident;
253 253 src.d_type = ELF_T_EHDR;
254 254 src.d_size = fsz;
255 255 src.d_version = elf->ed_version;
256 256 dst.d_buf = (Elf_Void *)elf->ed_ehdr;
257 257 dst.d_size = sizeof (Ehdr);
258 258 dst.d_version = EV_CURRENT;
259 259
260 260 if ((_elf_vm(elf, (size_t)0, fsz) != OK_YES) ||
261 261 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
262 262 if (elf->ed_myflags & EDF_EHALLOC) {
263 263 elf->ed_myflags &= ~EDF_EHALLOC;
264 264 free(elf->ed_ehdr);
265 265 }
266 266 elf->ed_ehdr = 0;
267 267 return (-1);
268 268 }
269 269
270 270 if (((Ehdr*)elf->ed_ehdr)->e_ident[EI_CLASS] != ELFCLASS) {
271 271 _elf_seterr(EREQ_CLASS, 0);
272 272 if (elf->ed_myflags & EDF_EHALLOC) {
273 273 elf->ed_myflags &= ~EDF_EHALLOC;
274 274 free(elf->ed_ehdr);
275 275 }
276 276 elf->ed_ehdr = 0;
277 277 return (-1);
278 278 }
279 279
280 280 if (((Ehdr*)elf->ed_ehdr)->e_version != elf->ed_version) {
281 281 _elf_seterr(EFMT_VER2, 0);
282 282 if (elf->ed_myflags & EDF_EHALLOC) {
283 283 elf->ed_myflags &= ~EDF_EHALLOC;
284 284 free(elf->ed_ehdr);
285 285 }
286 286 elf->ed_ehdr = 0;
287 287 return (-1);
288 288 }
289 289
290 290 return (0);
291 291 }
292 292
293 293
294 294
295 295 int
296 296 _elf_phdr(Elf * elf, int inplace)
297 297 {
298 298 NOTE(ASSUMING_PROTECTED(*elf))
299 299 register size_t fsz, msz;
300 300 Elf_Data dst, src;
301 301 Ehdr * eh = elf->ed_ehdr; /* must be present */
302 302 unsigned work;
303 303
304 304 if (eh->e_phnum == 0)
305 305 return (0);
306 306
↓ open down ↓ |
306 lines elided |
↑ open up ↑ |
307 307 fsz = elf_fsize(ELF_T_PHDR, 1, elf->ed_version);
308 308 if (eh->e_phentsize != fsz) {
309 309 _elf_seterr(EFMT_PHDRSZ, 0);
310 310 return (-1);
311 311 }
312 312
313 313 fsz *= eh->e_phnum;
314 314 ELFACCESSDATA(work, _elf_work)
315 315 msz = _elf_msize(ELF_T_PHDR, work) * eh->e_phnum;
316 316 if ((eh->e_phoff == 0) ||
317 - ((fsz + eh->e_phoff) > elf->ed_fsz)) {
317 + (elf->ed_fsz <= eh->e_phoff) ||
318 + (elf->ed_fsz - eh->e_phoff < fsz)) {
318 319 _elf_seterr(EFMT_PHTAB, 0);
319 320 return (-1);
320 321 }
321 322
322 323 if (inplace && fsz >= msz && eh->e_phoff % sizeof (ElfField) == 0) {
323 324 elf->ed_phdr = (Elf_Void *)(elf->ed_ident + eh->e_phoff);
324 325 elf->ed_status = ES_COOKED;
325 326 } else {
326 327 if ((elf->ed_phdr = malloc(msz)) == 0) {
327 328 _elf_seterr(EMEM_PHDR, errno);
328 329 return (-1);
329 330 }
330 331 elf->ed_myflags |= EDF_PHALLOC;
331 332 }
332 333 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_phoff);
333 334 src.d_type = ELF_T_PHDR;
334 335 src.d_size = fsz;
335 336 src.d_version = elf->ed_version;
336 337 dst.d_buf = elf->ed_phdr;
337 338 dst.d_size = msz;
338 339 dst.d_version = work;
339 340 if ((_elf_vm(elf, (size_t)eh->e_phoff, fsz) != OK_YES) ||
340 341 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
341 342 if (elf->ed_myflags & EDF_PHALLOC) {
342 343 elf->ed_myflags &= ~EDF_PHALLOC;
343 344 free(elf->ed_phdr);
344 345 }
345 346 elf->ed_phdr = 0;
346 347 return (-1);
347 348 }
348 349 elf->ed_phdrsz = msz;
349 350 return (0);
350 351 }
351 352
352 353
353 354
354 355 int
355 356 _elf_shdr(Elf * elf, int inplace)
356 357 {
357 358 NOTE(ASSUMING_PROTECTED(*elf))
358 359 register size_t fsz, msz;
359 360 size_t scncnt;
360 361 Elf_Data dst, src;
361 362 register Ehdr *eh = elf->ed_ehdr; /* must be present */
362 363
363 364 if ((eh->e_shnum == 0) && (eh->e_shoff == 0))
364 365 return (0);
365 366
366 367 fsz = elf_fsize(ELF_T_SHDR, 1, elf->ed_version);
367 368 if (eh->e_shentsize != fsz) {
368 369 _elf_seterr(EFMT_SHDRSZ, 0);
369 370 return (-1);
370 371 }
371 372 /*
372 373 * If we are dealing with a file with 'extended section
373 374 * indexes' - then we need to load the first section
374 375 * header. The actual section count is stored in
375 376 * Shdr[0].sh_size.
376 377 */
377 378 if ((scncnt = eh->e_shnum) == 0) {
378 379 Shdr sh;
379 380 if ((eh->e_shoff == 0) ||
380 381 (elf->ed_fsz <= eh->e_shoff) ||
381 382 (elf->ed_fsz - eh->e_shoff < fsz)) {
382 383 _elf_seterr(EFMT_SHTAB, 0);
383 384 return (-1);
384 385 }
385 386 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff);
386 387 src.d_type = ELF_T_SHDR;
387 388 src.d_size = fsz;
388 389 src.d_version = elf->ed_version;
389 390 dst.d_buf = (Elf_Void *)&sh;
390 391 dst.d_size = sizeof (Shdr);
391 392 dst.d_version = EV_CURRENT;
392 393 if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) ||
393 394 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0)) {
394 395 return (-1);
395 396 }
396 397 scncnt = sh.sh_size;
397 398 }
398 399
399 400 fsz *= scncnt;
400 401 msz = scncnt * sizeof (Shdr);
401 402 if ((eh->e_shoff == 0) ||
402 403 (elf->ed_fsz <= eh->e_shoff) ||
403 404 (elf->ed_fsz - eh->e_shoff < fsz)) {
404 405 _elf_seterr(EFMT_SHTAB, 0);
405 406 return (-1);
406 407 }
407 408
408 409 if (inplace && (fsz >= msz) &&
409 410 ((eh->e_shoff % sizeof (ElfField)) == 0)) {
410 411 /* LINTED */
411 412 elf->ed_shdr = (Shdr *)(elf->ed_ident + eh->e_shoff);
412 413 elf->ed_status = ES_COOKED;
413 414 } else {
414 415 if ((elf->ed_shdr = malloc(msz)) == 0) {
415 416 _elf_seterr(EMEM_SHDR, errno);
416 417 return (-1);
417 418 }
418 419 elf->ed_myflags |= EDF_SHALLOC;
419 420 }
420 421 src.d_buf = (Elf_Void *)(elf->ed_ident + eh->e_shoff);
421 422 src.d_type = ELF_T_SHDR;
422 423 src.d_size = fsz;
423 424 src.d_version = elf->ed_version;
424 425 dst.d_buf = (Elf_Void *)elf->ed_shdr;
425 426 dst.d_size = msz;
426 427 dst.d_version = EV_CURRENT;
427 428 if ((_elf_vm(elf, (size_t)eh->e_shoff, fsz) != OK_YES) ||
428 429 (elf_xlatetom(&dst, &src, elf->ed_encode) == 0) ||
429 430 (_elf_prepscn(elf, scncnt) != OK_YES)) {
430 431 if (elf->ed_myflags & EDF_SHALLOC) {
431 432 elf->ed_myflags &= ~EDF_SHALLOC;
432 433 free(elf->ed_shdr);
433 434 }
434 435 elf->ed_shdr = 0;
435 436 return (-1);
436 437 }
437 438 return (0);
438 439 }
↓ open down ↓ |
111 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX