1 /*
2 * Copyright (c) Christos Zoulas 2003.
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
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice immediately at the beginning of the file, without modification,
10 * this list of conditions, and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27 #include "file.h"
28
29 #ifndef lint
30 FILE_RCSID("@(#)$File: readelf.c,v 1.196 2024/11/11 15:49:11 christos Exp $")
31 #endif
32
33 #ifdef BUILTIN_ELF
34 #include <string.h>
35 #include <ctype.h>
36 #include <stdlib.h>
37 #ifdef HAVE_UNISTD_H
38 #include <unistd.h>
39 #endif
40
41 #include "readelf.h"
42 #include "magic.h"
43
44 #ifdef ELFCORE
45 file_private int dophn_core(struct magic_set *, int, int, int, off_t, int,
46 size_t, off_t, int *, uint16_t *);
47 #endif
48 file_private int dophn_exec(struct magic_set *, int, int, int, off_t, int,
49 size_t, off_t, int, int *, uint16_t *);
50 file_private int doshn(struct magic_set *, int, int, int, off_t, int, size_t,
51 off_t, int, int, int *, uint16_t *);
52 file_private size_t donote(struct magic_set *, void *, size_t, size_t, int,
53 int, size_t, int *, uint16_t *, int, off_t, int, off_t);
54
55 #define ELF_ALIGN(a) ((((a) + align - 1) / align) * align)
56
57 #define isquote(c) (strchr("'\"`", (c)) != NULL)
58
59 file_private uint16_t getu16(int, uint16_t);
60 file_private uint32_t getu32(int, uint32_t);
61 file_private uint64_t getu64(int, uint64_t);
62
63 #define NBUFSIZE 2024
64 #define SIZE_UNKNOWN CAST(off_t, -1)
65 #define NAMEEQUALS(n, v) \
66 (namesz == sizeof(v) && memcmp(n, v, namesz) == 0)
67
68 file_private int
toomany(struct magic_set * ms,const char * name,uint16_t num)69 toomany(struct magic_set *ms, const char *name, uint16_t num)
70 {
71 if (ms->flags & MAGIC_MIME)
72 return 1;
73 if (file_printf(ms, ", too many %s (%u)", name, num) == -1)
74 return -1;
75 return 1;
76 }
77
78 file_private uint16_t
getu16(int swap,uint16_t value)79 getu16(int swap, uint16_t value)
80 {
81 union {
82 uint16_t ui;
83 char c[2];
84 } retval, tmpval;
85
86 if (swap) {
87 tmpval.ui = value;
88
89 retval.c[0] = tmpval.c[1];
90 retval.c[1] = tmpval.c[0];
91
92 return retval.ui;
93 } else
94 return value;
95 }
96
97 file_private uint32_t
getu32(int swap,uint32_t value)98 getu32(int swap, uint32_t value)
99 {
100 union {
101 uint32_t ui;
102 char c[4];
103 } retval, tmpval;
104
105 if (swap) {
106 tmpval.ui = value;
107
108 retval.c[0] = tmpval.c[3];
109 retval.c[1] = tmpval.c[2];
110 retval.c[2] = tmpval.c[1];
111 retval.c[3] = tmpval.c[0];
112
113 return retval.ui;
114 } else
115 return value;
116 }
117
118 file_private uint64_t
getu64(int swap,uint64_t value)119 getu64(int swap, uint64_t value)
120 {
121 union {
122 uint64_t ui;
123 char c[8];
124 } retval, tmpval;
125
126 if (swap) {
127 tmpval.ui = value;
128
129 retval.c[0] = tmpval.c[7];
130 retval.c[1] = tmpval.c[6];
131 retval.c[2] = tmpval.c[5];
132 retval.c[3] = tmpval.c[4];
133 retval.c[4] = tmpval.c[3];
134 retval.c[5] = tmpval.c[2];
135 retval.c[6] = tmpval.c[1];
136 retval.c[7] = tmpval.c[0];
137
138 return retval.ui;
139 } else
140 return value;
141 }
142
143 #define elf_getu16(swap, value) getu16(swap, value)
144 #define elf_getu32(swap, value) getu32(swap, value)
145 #define elf_getu64(swap, value) getu64(swap, value)
146
147 #define xsh_addr (clazz == ELFCLASS32 \
148 ? CAST(void *, &sh32) \
149 : CAST(void *, &sh64))
150 #define xsh_sizeof (clazz == ELFCLASS32 \
151 ? sizeof(sh32) \
152 : sizeof(sh64))
153 #define xsh_size CAST(size_t, (clazz == ELFCLASS32 \
154 ? elf_getu32(swap, sh32.sh_size) \
155 : elf_getu64(swap, sh64.sh_size)))
156 #define xsh_offset CAST(off_t, (clazz == ELFCLASS32 \
157 ? elf_getu32(swap, sh32.sh_offset) \
158 : elf_getu64(swap, sh64.sh_offset)))
159 #define xsh_type (clazz == ELFCLASS32 \
160 ? elf_getu32(swap, sh32.sh_type) \
161 : elf_getu32(swap, sh64.sh_type))
162 #define xsh_name (clazz == ELFCLASS32 \
163 ? elf_getu32(swap, sh32.sh_name) \
164 : elf_getu32(swap, sh64.sh_name))
165
166 #define xph_addr (clazz == ELFCLASS32 \
167 ? CAST(void *, &ph32) \
168 : CAST(void *, &ph64))
169 #define xph_sizeof (clazz == ELFCLASS32 \
170 ? sizeof(ph32) \
171 : sizeof(ph64))
172 #define xph_type (clazz == ELFCLASS32 \
173 ? elf_getu32(swap, ph32.p_type) \
174 : elf_getu32(swap, ph64.p_type))
175 #define xph_offset CAST(off_t, (clazz == ELFCLASS32 \
176 ? elf_getu32(swap, ph32.p_offset) \
177 : elf_getu64(swap, ph64.p_offset)))
178 #define xph_align CAST(size_t, (clazz == ELFCLASS32 \
179 ? CAST(off_t, (ph32.p_align ? \
180 elf_getu32(swap, ph32.p_align) : 4))\
181 : CAST(off_t, (ph64.p_align ? \
182 elf_getu64(swap, ph64.p_align) : 4))))
183 #define xph_vaddr CAST(size_t, (clazz == ELFCLASS32 \
184 ? CAST(off_t, (ph32.p_vaddr ? \
185 elf_getu32(swap, ph32.p_vaddr) : 4))\
186 : CAST(off_t, (ph64.p_vaddr ? \
187 elf_getu64(swap, ph64.p_vaddr) : 4))))
188 #define xph_filesz CAST(size_t, (clazz == ELFCLASS32 \
189 ? elf_getu32(swap, ph32.p_filesz) \
190 : elf_getu64(swap, ph64.p_filesz)))
191 #define xph_memsz CAST(size_t, ((clazz == ELFCLASS32 \
192 ? elf_getu32(swap, ph32.p_memsz) \
193 : elf_getu64(swap, ph64.p_memsz))))
194 #define xnh_addr (clazz == ELFCLASS32 \
195 ? CAST(void *, &nh32) \
196 : CAST(void *, &nh64))
197 #define xnh_sizeof (clazz == ELFCLASS32 \
198 ? sizeof(nh32) \
199 : sizeof(nh64))
200 #define xnh_type (clazz == ELFCLASS32 \
201 ? elf_getu32(swap, nh32.n_type) \
202 : elf_getu32(swap, nh64.n_type))
203 #define xnh_namesz (clazz == ELFCLASS32 \
204 ? elf_getu32(swap, nh32.n_namesz) \
205 : elf_getu32(swap, nh64.n_namesz))
206 #define xnh_descsz (clazz == ELFCLASS32 \
207 ? elf_getu32(swap, nh32.n_descsz) \
208 : elf_getu32(swap, nh64.n_descsz))
209
210 #define xdh_addr (clazz == ELFCLASS32 \
211 ? CAST(void *, &dh32) \
212 : CAST(void *, &dh64))
213 #define xdh_sizeof (clazz == ELFCLASS32 \
214 ? sizeof(dh32) \
215 : sizeof(dh64))
216 #define xdh_tag (clazz == ELFCLASS32 \
217 ? elf_getu32(swap, dh32.d_tag) \
218 : elf_getu64(swap, dh64.d_tag))
219 #define xdh_val (clazz == ELFCLASS32 \
220 ? elf_getu32(swap, dh32.d_un.d_val) \
221 : elf_getu64(swap, dh64.d_un.d_val))
222
223 #define xcap_addr (clazz == ELFCLASS32 \
224 ? CAST(void *, &cap32) \
225 : CAST(void *, &cap64))
226 #define xcap_sizeof (clazz == ELFCLASS32 \
227 ? sizeof(cap32) \
228 : sizeof(cap64))
229 #define xcap_tag (clazz == ELFCLASS32 \
230 ? elf_getu32(swap, cap32.c_tag) \
231 : elf_getu64(swap, cap64.c_tag))
232 #define xcap_val (clazz == ELFCLASS32 \
233 ? elf_getu32(swap, cap32.c_un.c_val) \
234 : elf_getu64(swap, cap64.c_un.c_val))
235
236 #define xauxv_addr (clazz == ELFCLASS32 \
237 ? CAST(void *, &auxv32) \
238 : CAST(void *, &auxv64))
239 #define xauxv_sizeof (clazz == ELFCLASS32 \
240 ? sizeof(auxv32) \
241 : sizeof(auxv64))
242 #define xauxv_type (clazz == ELFCLASS32 \
243 ? elf_getu32(swap, auxv32.a_type) \
244 : elf_getu64(swap, auxv64.a_type))
245 #define xauxv_val (clazz == ELFCLASS32 \
246 ? elf_getu32(swap, auxv32.a_v) \
247 : elf_getu64(swap, auxv64.a_v))
248
249 #define prpsoffsets(i) (clazz == ELFCLASS32 \
250 ? prpsoffsets32[i] \
251 : prpsoffsets64[i])
252
253 #ifdef ELFCORE
254 /*
255 * Try larger offsets first to avoid false matches
256 * from earlier data that happen to look like strings.
257 */
258 static const size_t prpsoffsets32[] = {
259 #ifdef USE_NT_PSINFO
260 104, /* SunOS 5.x (command line) */
261 88, /* SunOS 5.x (short name) */
262 #endif /* USE_NT_PSINFO */
263
264 100, /* SunOS 5.x (command line) */
265 84, /* SunOS 5.x (short name) */
266
267 44, /* Linux (command line) */
268 28, /* Linux (short name) */
269
270 48, /* Linux PowerPC (command line) */
271 32, /* Linux PowerPC (short name) */
272
273 8, /* FreeBSD */
274 };
275
276 static const size_t prpsoffsets64[] = {
277 #ifdef USE_NT_PSINFO
278 152, /* SunOS 5.x (command line) */
279 136, /* SunOS 5.x (short name) */
280 #endif /* USE_NT_PSINFO */
281
282 136, /* SunOS 5.x, 64-bit (command line) */
283 120, /* SunOS 5.x, 64-bit (short name) */
284
285 56, /* Linux (command line) */
286 40, /* Linux (tested on core from 2.4.x, short name) */
287
288 16, /* FreeBSD, 64-bit */
289 };
290
291 #define NOFFSETS32 __arraycount(prpsoffsets32)
292 #define NOFFSETS64 __arraycount(prpsoffsets64)
293
294 #define NOFFSETS (clazz == ELFCLASS32 ? NOFFSETS32 : NOFFSETS64)
295
296 /*
297 * Look through the program headers of an executable image, searching
298 * for a PT_NOTE section of type NT_PRPSINFO, with a name "CORE" or
299 * "FreeBSD"; if one is found, try looking in various places in its
300 * contents for a 16-character string containing only printable
301 * characters - if found, that string should be the name of the program
302 * that dropped core. Note: right after that 16-character string is,
303 * at least in SunOS 5.x (and possibly other SVR4-flavored systems) and
304 * Linux, a longer string (80 characters, in 5.x, probably other
305 * SVR4-flavored systems, and Linux) containing the start of the
306 * command line for that program.
307 *
308 * SunOS 5.x core files contain two PT_NOTE sections, with the types
309 * NT_PRPSINFO (old) and NT_PSINFO (new). These structs contain the
310 * same info about the command name and command line, so it probably
311 * isn't worthwhile to look for NT_PSINFO, but the offsets are provided
312 * above (see USE_NT_PSINFO), in case we ever decide to do so. The
313 * NT_PRPSINFO and NT_PSINFO sections are always in order and adjacent;
314 * the SunOS 5.x file command relies on this (and prefers the latter).
315 *
316 * The signal number probably appears in a section of type NT_PRSTATUS,
317 * but that's also rather OS-dependent, in ways that are harder to
318 * dissect with heuristics, so I'm not bothering with the signal number.
319 * (I suppose the signal number could be of interest in situations where
320 * you don't have the binary of the program that dropped core; if you
321 * *do* have that binary, the debugger will probably tell you what
322 * signal it was.)
323 */
324
325 #define OS_STYLE_SVR4 0
326 #define OS_STYLE_FREEBSD 1
327 #define OS_STYLE_NETBSD 2
328
329 file_private const char os_style_names[][8] = {
330 "SVR4",
331 "FreeBSD",
332 "NetBSD",
333 };
334
335 #define FLAGS_CORE_STYLE 0x0003
336
337 #define FLAGS_DID_CORE 0x0004
338 #define FLAGS_DID_OS_NOTE 0x0008
339 #define FLAGS_DID_BUILD_ID 0x0010
340 #define FLAGS_DID_CORE_STYLE 0x0020
341 #define FLAGS_DID_NETBSD_PAX 0x0040
342 #define FLAGS_DID_NETBSD_MARCH 0x0080
343 #define FLAGS_DID_NETBSD_CMODEL 0x0100
344 #define FLAGS_DID_NETBSD_EMULATION 0x0200
345 #define FLAGS_DID_NETBSD_UNKNOWN 0x0400
346 #define FLAGS_DID_ANDROID_MEMTAG 0x0800
347 #define FLAGS_IS_CORE 0x1000
348 #define FLAGS_DID_AUXV 0x2000
349
350 file_private int
dophn_core(struct magic_set * ms,int clazz,int swap,int fd,off_t off,int num,size_t size,off_t fsize,int * flags,uint16_t * notecount)351 dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
352 int num, size_t size, off_t fsize, int *flags, uint16_t *notecount)
353 {
354 Elf32_Phdr ph32;
355 Elf64_Phdr ph64;
356 size_t offset, len;
357 unsigned char nbuf[NBUFSIZE];
358 ssize_t bufsize;
359 off_t ph_off = off, offs;
360 int ph_num = num;
361
362 if (ms->flags & MAGIC_MIME)
363 return 0;
364
365 if (num == 0) {
366 if (file_printf(ms, ", no program header") == -1)
367 return -1;
368 return 0;
369 }
370 if (size != xph_sizeof) {
371 if (file_printf(ms, ", corrupted program header size") == -1)
372 return -1;
373 return 0;
374 }
375
376 /*
377 * Loop through all the program headers.
378 */
379 for ( ; num; num--) {
380 if (pread(fd, xph_addr, xph_sizeof, off) <
381 CAST(ssize_t, xph_sizeof)) {
382 if (file_printf(ms,
383 ", can't read elf program headers at %jd",
384 (intmax_t)off) == -1)
385 return -1;
386 return 0;
387 }
388 off += size;
389
390 if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
391 /* Perhaps warn here */
392 continue;
393 }
394
395 if (xph_type != PT_NOTE)
396 continue;
397
398 /*
399 * This is a PT_NOTE section; loop through all the notes
400 * in the section.
401 */
402 len = xph_filesz < sizeof(nbuf) ? xph_filesz : sizeof(nbuf);
403 offs = xph_offset;
404 if ((bufsize = pread(fd, nbuf, len, offs)) == -1) {
405 if (file_printf(ms, " can't read note section at %jd",
406 (intmax_t)offs) == -1)
407 return -1;
408 return 0;
409 }
410 offset = 0;
411 for (;;) {
412 if (offset >= CAST(size_t, bufsize))
413 break;
414 offset = donote(ms, nbuf, offset, CAST(size_t, bufsize),
415 clazz, swap, 4, flags, notecount, fd, ph_off,
416 ph_num, fsize);
417 if (offset == 0)
418 break;
419
420 }
421 }
422 return 0;
423 }
424 #endif
425
426 static int
do_note_netbsd_version(struct magic_set * ms,int swap,void * v)427 do_note_netbsd_version(struct magic_set *ms, int swap, void *v)
428 {
429 uint32_t desc;
430 memcpy(&desc, v, sizeof(desc));
431 desc = elf_getu32(swap, desc);
432
433 if (file_printf(ms, ", for NetBSD") == -1)
434 return -1;
435 /*
436 * The version number used to be stuck as 199905, and was thus
437 * basically content-free. Newer versions of NetBSD have fixed
438 * this and now use the encoding of __NetBSD_Version__:
439 *
440 * MMmmrrpp00
441 *
442 * M = major version
443 * m = minor version
444 * r = release ["",A-Z,Z[A-Z] but numeric]
445 * p = patchlevel
446 */
447 if (desc > 100000000U) {
448 uint32_t ver_patch = (desc / 100) % 100;
449 uint32_t ver_rel = (desc / 10000) % 100;
450 uint32_t ver_min = (desc / 1000000) % 100;
451 uint32_t ver_maj = desc / 100000000;
452
453 if (file_printf(ms, " %u.%u", ver_maj, ver_min) == -1)
454 return -1;
455 if (ver_maj >= 9) {
456 ver_patch += 100 * ver_rel;
457 ver_rel = 0;
458 }
459 if (ver_rel == 0 && ver_patch != 0) {
460 if (file_printf(ms, ".%u", ver_patch) == -1)
461 return -1;
462 } else if (ver_rel != 0) {
463 while (ver_rel > 26) {
464 if (file_printf(ms, "Z") == -1)
465 return -1;
466 ver_rel -= 26;
467 }
468 if (file_printf(ms, "%c", 'A' + ver_rel - 1) == -1)
469 return -1;
470 }
471 }
472 return 0;
473 }
474
475 static int
do_note_freebsd_version(struct magic_set * ms,int swap,void * v)476 do_note_freebsd_version(struct magic_set *ms, int swap, void *v)
477 {
478 uint32_t desc;
479
480 memcpy(&desc, v, sizeof(desc));
481 desc = elf_getu32(swap, desc);
482 if (file_printf(ms, ", for FreeBSD") == -1)
483 return -1;
484
485 /*
486 * Contents is __FreeBSD_version, whose relation to OS
487 * versions is defined by a huge table in the Porter's
488 * Handbook. This is the general scheme:
489 *
490 * Releases:
491 * Mmp000 (before 4.10)
492 * Mmi0p0 (before 5.0)
493 * Mmm0p0
494 *
495 * Development branches:
496 * Mmpxxx (before 4.6)
497 * Mmp1xx (before 4.10)
498 * Mmi1xx (before 5.0)
499 * M000xx (pre-M.0)
500 * Mmm1xx
501 *
502 * M = major version
503 * m = minor version
504 * i = minor version increment (491000 -> 4.10)
505 * p = patchlevel
506 * x = revision
507 *
508 * The first release of FreeBSD to use ELF by default
509 * was version 3.0.
510 */
511 if (desc == 460002) {
512 if (file_printf(ms, " 4.6.2") == -1)
513 return -1;
514 } else if (desc < 460100) {
515 if (file_printf(ms, " %d.%d", desc / 100000,
516 desc / 10000 % 10) == -1)
517 return -1;
518 if (desc / 1000 % 10 > 0)
519 if (file_printf(ms, ".%d", desc / 1000 % 10) == -1)
520 return -1;
521 if ((desc % 1000 > 0) || (desc % 100000 == 0))
522 if (file_printf(ms, " (%d)", desc) == -1)
523 return -1;
524 } else if (desc < 500000) {
525 if (file_printf(ms, " %d.%d", desc / 100000,
526 desc / 10000 % 10 + desc / 1000 % 10) == -1)
527 return -1;
528 if (desc / 100 % 10 > 0) {
529 if (file_printf(ms, " (%d)", desc) == -1)
530 return -1;
531 } else if (desc / 10 % 10 > 0) {
532 if (file_printf(ms, ".%d", desc / 10 % 10) == -1)
533 return -1;
534 }
535 } else {
536 if (file_printf(ms, " %d.%d", desc / 100000,
537 desc / 1000 % 100) == -1)
538 return -1;
539 if ((desc / 100 % 10 > 0) ||
540 (desc % 100000 / 100 == 0)) {
541 if (file_printf(ms, " (%d)", desc) == -1)
542 return -1;
543 } else if (desc / 10 % 10 > 0) {
544 if (file_printf(ms, ".%d", desc / 10 % 10) == -1)
545 return -1;
546 }
547 }
548 return 0;
549 }
550
551 file_private int
552 /*ARGSUSED*/
do_bid_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags)553 do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
554 int swap __attribute__((__unused__)), uint32_t namesz, uint32_t descsz,
555 size_t noff, size_t doff, int *flags)
556 {
557 if (NAMEEQUALS(RCAST(char *, &nbuf[noff]), "GNU") &&
558 type == NT_GNU_BUILD_ID && (descsz >= 4 && descsz <= 20)) {
559 uint8_t desc[20];
560 const char *btype;
561 uint32_t i;
562 *flags |= FLAGS_DID_BUILD_ID;
563 switch (descsz) {
564 case 8:
565 btype = "xxHash";
566 break;
567 case 16:
568 btype = "md5/uuid";
569 break;
570 case 20:
571 btype = "sha1";
572 break;
573 default:
574 btype = "unknown";
575 break;
576 }
577 if (file_printf(ms, ", BuildID[%s]=", btype) == -1)
578 return -1;
579 memcpy(desc, &nbuf[doff], descsz);
580 for (i = 0; i < descsz; i++)
581 if (file_printf(ms, "%02x", desc[i]) == -1)
582 return -1;
583 return 1;
584 }
585 if (namesz == 4 && memcmp(RCAST(char *, &nbuf[noff]), "Go", 3) == 0 &&
586 type == NT_GO_BUILD_ID && descsz < 128) {
587 char buf[256];
588 if (file_printf(ms, ", Go BuildID=%s",
589 file_copystr(buf, sizeof(buf), descsz,
590 RCAST(const char *, &nbuf[doff]))) == -1)
591 return -1;
592 return 1;
593 }
594 return 0;
595 }
596
597 file_private int
do_os_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags)598 do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
599 int swap, uint32_t namesz, uint32_t descsz,
600 size_t noff, size_t doff, int *flags)
601 {
602 const char *name = RCAST(const char *, &nbuf[noff]);
603
604 if (NAMEEQUALS(name, "SuSE") && type == NT_GNU_VERSION && descsz == 2) {
605 *flags |= FLAGS_DID_OS_NOTE;
606 if (file_printf(ms, ", for SuSE %d.%d", nbuf[doff],
607 nbuf[doff + 1]) == -1)
608 return -1;
609 return 1;
610 }
611
612 if (NAMEEQUALS(name, "GNU") && type == NT_GNU_VERSION && descsz == 16) {
613 uint32_t desc[4];
614 memcpy(desc, &nbuf[doff], sizeof(desc));
615
616 *flags |= FLAGS_DID_OS_NOTE;
617 if (file_printf(ms, ", for GNU/") == -1)
618 return -1;
619 switch (elf_getu32(swap, desc[0])) {
620 case GNU_OS_LINUX:
621 if (file_printf(ms, "Linux") == -1)
622 return -1;
623 break;
624 case GNU_OS_HURD:
625 if (file_printf(ms, "Hurd") == -1)
626 return -1;
627 break;
628 case GNU_OS_SOLARIS:
629 if (file_printf(ms, "Solaris") == -1)
630 return -1;
631 break;
632 case GNU_OS_KFREEBSD:
633 if (file_printf(ms, "kFreeBSD") == -1)
634 return -1;
635 break;
636 case GNU_OS_KNETBSD:
637 if (file_printf(ms, "kNetBSD") == -1)
638 return -1;
639 break;
640 default:
641 if (file_printf(ms, "<unknown>") == -1)
642 return -1;
643 }
644 if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]),
645 elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1)
646 return -1;
647 return 1;
648 }
649
650 if (NAMEEQUALS(name, "NetBSD") &&
651 type == NT_NETBSD_VERSION && descsz == 4) {
652 *flags |= FLAGS_DID_OS_NOTE;
653 if (do_note_netbsd_version(ms, swap, &nbuf[doff]) == -1)
654 return -1;
655 return 1;
656 }
657
658 if (NAMEEQUALS(name, "FreeBSD") &&
659 type == NT_FREEBSD_VERSION && descsz == 4) {
660 *flags |= FLAGS_DID_OS_NOTE;
661 if (do_note_freebsd_version(ms, swap, &nbuf[doff])
662 == -1)
663 return -1;
664 return 1;
665 }
666
667 if (NAMEEQUALS(name, "OpenBSD") &&
668 type == NT_OPENBSD_VERSION && descsz == 4) {
669 *flags |= FLAGS_DID_OS_NOTE;
670 if (file_printf(ms, ", for OpenBSD") == -1)
671 return -1;
672 /* Content of note is always 0 */
673 return 1;
674 }
675
676 if (NAMEEQUALS(name, "DragonFly") &&
677 type == NT_DRAGONFLY_VERSION && descsz == 4) {
678 uint32_t desc;
679 *flags |= FLAGS_DID_OS_NOTE;
680 if (file_printf(ms, ", for DragonFly") == -1)
681 return -1;
682 memcpy(&desc, &nbuf[doff], sizeof(desc));
683 desc = elf_getu32(swap, desc);
684 if (file_printf(ms, " %d.%d.%d", desc / 100000,
685 desc / 10000 % 10, desc % 10000) == -1)
686 return -1;
687 return 1;
688 }
689
690 if (NAMEEQUALS(name, "Android") &&
691 type == NT_ANDROID_VERSION && descsz >= 4) {
692 uint32_t api_level;
693 *flags |= FLAGS_DID_OS_NOTE;
694 memcpy(&api_level, &nbuf[doff], sizeof(api_level));
695 api_level = elf_getu32(swap, api_level);
696 if (file_printf(ms, ", for Android %d", api_level) == -1)
697 return -1;
698 /*
699 * NDK r14 and later also include details of the NDK that
700 * built the binary. OS binaries (or binaries built by older
701 * NDKs) don't have this. The NDK release and build number
702 * are both 64-byte strings.
703 */
704 if (descsz >= 4 + 64 + 64) {
705 if (file_printf(ms, ", built by NDK %.64s (%.64s)",
706 &nbuf[doff + 4], &nbuf[doff + 4 + 64]) == -1)
707 return -1;
708 }
709 }
710
711 return 0;
712 }
713
714 file_private int
do_pax_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags)715 do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
716 int swap, uint32_t namesz, uint32_t descsz,
717 size_t noff, size_t doff, int *flags)
718 {
719 const char *name = RCAST(const char *, &nbuf[noff]);
720
721 if (NAMEEQUALS(name, "PaX") && type == NT_NETBSD_PAX && descsz == 4) {
722 static const char *pax[] = {
723 "+mprotect",
724 "-mprotect",
725 "+segvguard",
726 "-segvguard",
727 "+ASLR",
728 "-ASLR",
729 };
730 uint32_t desc;
731 size_t i;
732 int did = 0;
733
734 *flags |= FLAGS_DID_NETBSD_PAX;
735 memcpy(&desc, &nbuf[doff], sizeof(desc));
736 desc = elf_getu32(swap, desc);
737
738 if (desc && file_printf(ms, ", PaX: ") == -1)
739 return -1;
740
741 for (i = 0; i < __arraycount(pax); i++) {
742 if (((1 << CAST(int, i)) & desc) == 0)
743 continue;
744 if (file_printf(ms, "%s%s", did++ ? "," : "",
745 pax[i]) == -1)
746 return -1;
747 }
748 return 1;
749 }
750 return 0;
751 }
752
753 file_private int
do_memtag_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags)754 do_memtag_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
755 int swap, uint32_t namesz, uint32_t descsz,
756 size_t noff, size_t doff, int *flags)
757 {
758 const char *name = RCAST(const char *, &nbuf[noff]);
759
760 if (NAMEEQUALS(name, "Android") &&
761 type == NT_ANDROID_MEMTAG && descsz == 4) {
762 static const char *memtag[] = {
763 "none",
764 "async",
765 "sync",
766 "heap",
767 "stack",
768 };
769 uint32_t desc;
770 size_t i;
771 int did = 0;
772
773 *flags |= FLAGS_DID_ANDROID_MEMTAG;
774 memcpy(&desc, &nbuf[doff], sizeof(desc));
775 desc = elf_getu32(swap, desc);
776
777 if (desc && file_printf(ms, ", Android Memtag: ") == -1)
778 return -1;
779
780 for (i = 0; i < __arraycount(memtag); i++) {
781 if (((1 << CAST(int, i)) & desc) == 0)
782 continue;
783 if (file_printf(ms, "%s%s", did++ ? "," : "",
784 memtag[i]) == -1)
785 return -1;
786 }
787 return 1;
788 }
789 return 0;
790 }
791
792 file_private int
do_core_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags,size_t size,int clazz)793 do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
794 int swap, uint32_t namesz, uint32_t descsz,
795 size_t noff, size_t doff, int *flags, size_t size, int clazz)
796 {
797 #ifdef ELFCORE
798 char buf[256];
799 const char *name = RCAST(const char *, &nbuf[noff]);
800
801 int os_style = -1;
802 /*
803 * Sigh. The 2.0.36 kernel in Debian 2.1, at
804 * least, doesn't correctly implement name
805 * sections, in core dumps, as specified by
806 * the "Program Linking" section of "UNIX(R) System
807 * V Release 4 Programmer's Guide: ANSI C and
808 * Programming Support Tools", because my copy
809 * clearly says "The first 'namesz' bytes in 'name'
810 * contain a *null-terminated* [emphasis mine]
811 * character representation of the entry's owner
812 * or originator", but the 2.0.36 kernel code
813 * doesn't include the terminating null in the
814 * name....
815 */
816 if ((namesz == 4 && memcmp(name, "CORE", 4) == 0) ||
817 NAMEEQUALS(name, "CORE")) {
818 os_style = OS_STYLE_SVR4;
819 }
820
821 if (NAMEEQUALS(name, "FreeBSD")) {
822 os_style = OS_STYLE_FREEBSD;
823 }
824
825 if ((namesz >= 11 && memcmp(name, "NetBSD-CORE", 11) == 0)) {
826 os_style = OS_STYLE_NETBSD;
827 }
828
829 if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) {
830 if (file_printf(ms, ", %s-style", os_style_names[os_style])
831 == -1)
832 return -1;
833 *flags |= FLAGS_DID_CORE_STYLE;
834 *flags |= os_style;
835 }
836
837 switch (os_style) {
838 case OS_STYLE_NETBSD:
839 if (type == NT_NETBSD_CORE_PROCINFO) {
840 char sbuf[512];
841 struct NetBSD_elfcore_procinfo pi;
842 memset(&pi, 0, sizeof(pi));
843 memcpy(&pi, nbuf + doff, MIN(descsz, sizeof(pi)));
844
845 if (file_printf(ms, ", from '%.31s', pid=%u, uid=%u, "
846 "gid=%u, nlwps=%u, lwp=%u (signal %u/code %u)",
847 file_printable(ms, sbuf, sizeof(sbuf),
848 RCAST(char *, pi.cpi_name), sizeof(pi.cpi_name)),
849 elf_getu32(swap, CAST(uint32_t, pi.cpi_pid)),
850 elf_getu32(swap, pi.cpi_euid),
851 elf_getu32(swap, pi.cpi_egid),
852 elf_getu32(swap, pi.cpi_nlwps),
853 elf_getu32(swap, CAST(uint32_t, pi.cpi_siglwp)),
854 elf_getu32(swap, pi.cpi_signo),
855 elf_getu32(swap, pi.cpi_sigcode)) == -1)
856 return -1;
857
858 *flags |= FLAGS_DID_CORE;
859 return 1;
860 }
861 break;
862
863 case OS_STYLE_FREEBSD:
864 if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
865 size_t argoff, pidoff;
866
867 if (clazz == ELFCLASS32)
868 argoff = 4 + 4 + 17;
869 else
870 argoff = 4 + 4 + 8 + 17;
871 if (file_printf(ms, ", from '%.80s'", nbuf + doff +
872 argoff) == -1)
873 return -1;
874 pidoff = argoff + 81 + 2;
875 if (doff + pidoff + 4 <= size) {
876 if (file_printf(ms, ", pid=%u",
877 elf_getu32(swap, *RCAST(uint32_t *, (nbuf +
878 doff + pidoff)))) == -1)
879 return -1;
880 }
881 *flags |= FLAGS_DID_CORE;
882 }
883 break;
884
885 default:
886 if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
887 size_t i, j;
888 unsigned char c;
889 /*
890 * Extract the program name. We assume
891 * it to be 16 characters (that's what it
892 * is in SunOS 5.x and Linux).
893 *
894 * Unfortunately, it's at a different offset
895 * in various OSes, so try multiple offsets.
896 * If the characters aren't all printable,
897 * reject it.
898 */
899 for (i = 0; i < NOFFSETS; i++) {
900 unsigned char *cname, *cp;
901 size_t reloffset = prpsoffsets(i);
902 size_t noffset = doff + reloffset;
903 size_t k;
904 for (j = 0; j < 16; j++, noffset++,
905 reloffset++) {
906 /*
907 * Make sure we're not past
908 * the end of the buffer; if
909 * we are, just give up.
910 */
911 if (noffset >= size)
912 goto tryanother;
913
914 /*
915 * Make sure we're not past
916 * the end of the contents;
917 * if we are, this obviously
918 * isn't the right offset.
919 */
920 if (reloffset >= descsz)
921 goto tryanother;
922
923 c = nbuf[noffset];
924 if (c == '\0') {
925 /*
926 * A '\0' at the
927 * beginning is
928 * obviously wrong.
929 * Any other '\0'
930 * means we're done.
931 */
932 if (j == 0)
933 goto tryanother;
934 else
935 break;
936 } else {
937 /*
938 * A nonprintable
939 * character is also
940 * wrong.
941 */
942 if (!isprint(c) || isquote(c))
943 goto tryanother;
944 }
945 }
946 /*
947 * Well, that worked.
948 */
949
950 /*
951 * Try next offsets, in case this match is
952 * in the middle of a string.
953 */
954 for (k = i + 1 ; k < NOFFSETS; k++) {
955 size_t no;
956 int adjust = 1;
957 if (prpsoffsets(k) >= prpsoffsets(i))
958 continue;
959 /*
960 * pr_fname == pr_psargs - 16 &&
961 * non-nul-terminated fname (qemu)
962 */
963 if (prpsoffsets(k) ==
964 prpsoffsets(i) - 16 && j == 16)
965 continue;
966 for (no = doff + prpsoffsets(k);
967 no < doff + prpsoffsets(i); no++)
968 adjust = adjust
969 && isprint(nbuf[no]);
970 if (adjust)
971 i = k;
972 }
973
974 cname = CAST(unsigned char *,
975 &nbuf[doff + prpsoffsets(i)]);
976 for (cp = cname; cp < nbuf + size && *cp
977 && isprint(*cp); cp++)
978 continue;
979 /*
980 * Linux apparently appends a space at the end
981 * of the command line: remove it.
982 */
983 while (cp > cname && isspace(cp[-1]))
984 cp--;
985 if (file_printf(ms, ", from '%s'",
986 file_copystr(buf, sizeof(buf),
987 CAST(size_t, cp - cname),
988 RCAST(char *, cname))) == -1)
989 return -1;
990 *flags |= FLAGS_DID_CORE;
991 return 1;
992
993 tryanother:
994 ;
995 }
996 }
997 break;
998 }
999 #endif
1000 return 0;
1001 }
1002
1003 file_private off_t
get_offset_from_virtaddr(struct magic_set * ms,int swap,int clazz,int fd,off_t off,int num,off_t fsize,uint64_t virtaddr)1004 get_offset_from_virtaddr(struct magic_set *ms, int swap, int clazz, int fd,
1005 off_t off, int num, off_t fsize, uint64_t virtaddr)
1006 {
1007 Elf32_Phdr ph32;
1008 Elf64_Phdr ph64;
1009
1010 /*
1011 * Loop through all the program headers and find the header with
1012 * virtual address in which the "virtaddr" belongs to.
1013 */
1014 for ( ; num; num--) {
1015 if (pread(fd, xph_addr, xph_sizeof, off) <
1016 CAST(ssize_t, xph_sizeof)) {
1017 if (file_printf(ms,
1018 ", can't read elf program header at %jd",
1019 (intmax_t)off) == -1)
1020 return -1;
1021 return 0;
1022
1023 }
1024 off += xph_sizeof;
1025
1026 if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
1027 /* Perhaps warn here */
1028 continue;
1029 }
1030
1031 if (virtaddr >= xph_vaddr && virtaddr < xph_vaddr + xph_filesz)
1032 return xph_offset + (virtaddr - xph_vaddr);
1033 }
1034 return 0;
1035 }
1036
1037 file_private size_t
get_string_on_virtaddr(struct magic_set * ms,int swap,int clazz,int fd,off_t ph_off,int ph_num,off_t fsize,uint64_t virtaddr,char * buf,ssize_t buflen)1038 get_string_on_virtaddr(struct magic_set *ms,
1039 int swap, int clazz, int fd, off_t ph_off, int ph_num,
1040 off_t fsize, uint64_t virtaddr, char *buf, ssize_t buflen)
1041 {
1042 char *bptr;
1043 off_t offset;
1044
1045 if (buflen == 0)
1046 return 0;
1047
1048 offset = get_offset_from_virtaddr(ms, swap, clazz, fd, ph_off, ph_num,
1049 fsize, virtaddr);
1050 if (offset < 0 ||
1051 (buflen = pread(fd, buf, CAST(size_t, buflen), offset)) <= 0) {
1052 (void)file_printf(ms, ", can't read elf string at %jd",
1053 (intmax_t)offset);
1054 return 0;
1055 }
1056
1057 buf[buflen - 1] = '\0';
1058
1059 /* We expect only printable characters, so return if buffer contains
1060 * non-printable character before the '\0' or just '\0'. */
1061 for (bptr = buf; *bptr && isprint(CAST(unsigned char, *bptr)); bptr++)
1062 continue;
1063 if (*bptr != '\0')
1064 return 0;
1065
1066 return bptr - buf;
1067 }
1068
1069
1070 /*ARGSUSED*/
1071 file_private int
do_auxv_note(struct magic_set * ms,unsigned char * nbuf,uint32_t type,int swap,uint32_t namesz,uint32_t descsz,size_t noff,size_t doff,int * flags,size_t size,int clazz,int fd,off_t ph_off,int ph_num,off_t fsize)1072 do_auxv_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
1073 int swap, uint32_t namesz __attribute__((__unused__)),
1074 uint32_t descsz __attribute__((__unused__)),
1075 size_t noff __attribute__((__unused__)), size_t doff,
1076 int *flags, size_t size __attribute__((__unused__)), int clazz,
1077 int fd, off_t ph_off, int ph_num, off_t fsize)
1078 {
1079 #ifdef ELFCORE
1080 Aux32Info auxv32;
1081 Aux64Info auxv64;
1082 size_t elsize = xauxv_sizeof;
1083 const char *tag;
1084 int is_string;
1085 size_t nval, off;
1086
1087 if ((*flags & (FLAGS_IS_CORE|FLAGS_DID_CORE_STYLE)) !=
1088 (FLAGS_IS_CORE|FLAGS_DID_CORE_STYLE))
1089 return 0;
1090
1091 switch (*flags & FLAGS_CORE_STYLE) {
1092 case OS_STYLE_SVR4:
1093 if (type != NT_AUXV)
1094 return 0;
1095 break;
1096 #ifdef notyet
1097 case OS_STYLE_NETBSD:
1098 if (type != NT_NETBSD_CORE_AUXV)
1099 return 0;
1100 break;
1101 case OS_STYLE_FREEBSD:
1102 if (type != NT_FREEBSD_PROCSTAT_AUXV)
1103 return 0;
1104 break;
1105 #endif
1106 default:
1107 return 0;
1108 }
1109
1110 *flags |= FLAGS_DID_AUXV;
1111
1112 nval = 0;
1113 for (off = 0; off + elsize <= descsz; off += elsize) {
1114 memcpy(xauxv_addr, &nbuf[doff + off], xauxv_sizeof);
1115 /* Limit processing to 50 vector entries to prevent DoS */
1116 if (nval++ >= 50) {
1117 file_error(ms, 0, "Too many ELF Auxv elements");
1118 return 1;
1119 }
1120
1121 switch(xauxv_type) {
1122 case AT_LINUX_EXECFN:
1123 is_string = 1;
1124 tag = "execfn";
1125 break;
1126 case AT_LINUX_PLATFORM:
1127 is_string = 1;
1128 tag = "platform";
1129 break;
1130 case AT_LINUX_UID:
1131 is_string = 0;
1132 tag = "real uid";
1133 break;
1134 case AT_LINUX_GID:
1135 is_string = 0;
1136 tag = "real gid";
1137 break;
1138 case AT_LINUX_EUID:
1139 is_string = 0;
1140 tag = "effective uid";
1141 break;
1142 case AT_LINUX_EGID:
1143 is_string = 0;
1144 tag = "effective gid";
1145 break;
1146 default:
1147 is_string = 0;
1148 tag = NULL;
1149 break;
1150 }
1151
1152 if (tag == NULL)
1153 continue;
1154
1155 if (is_string) {
1156 char buf[256];
1157 ssize_t buflen;
1158 buflen = get_string_on_virtaddr(ms, swap, clazz, fd,
1159 ph_off, ph_num, fsize, xauxv_val, buf, sizeof(buf));
1160
1161 if (buflen == 0)
1162 continue;
1163
1164 if (file_printf(ms, ", %s: '%s'", tag, buf) == -1)
1165 return -1;
1166 } else {
1167 if (file_printf(ms, ", %s: %d", tag,
1168 CAST(int, xauxv_val)) == -1)
1169 return -1;
1170 }
1171 }
1172 return 1;
1173 #else
1174 return 0;
1175 #endif
1176 }
1177
1178 file_private size_t
dodynamic(struct magic_set * ms,void * vbuf,size_t offset,size_t size,int clazz,int swap,int * pie,size_t * need)1179 dodynamic(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
1180 int clazz, int swap, int *pie, size_t *need)
1181 {
1182 Elf32_Dyn dh32;
1183 Elf64_Dyn dh64;
1184 unsigned char *dbuf = CAST(unsigned char *, vbuf);
1185
1186 if (xdh_sizeof + offset > size) {
1187 /*
1188 * We're out of note headers.
1189 */
1190 return xdh_sizeof + offset;
1191 }
1192
1193 memcpy(xdh_addr, &dbuf[offset], xdh_sizeof);
1194 offset += xdh_sizeof;
1195
1196 switch (xdh_tag) {
1197 case DT_FLAGS_1:
1198 if (xdh_val & DF_1_PIE) {
1199 *pie = 1;
1200 ms->mode |= 0111;
1201 } else
1202 ms->mode &= ~0111;
1203 break;
1204 case DT_NEEDED:
1205 (*need)++;
1206 break;
1207 default:
1208 break;
1209 }
1210 return offset;
1211 }
1212
1213
1214 file_private size_t
donote(struct magic_set * ms,void * vbuf,size_t offset,size_t size,int clazz,int swap,size_t align,int * flags,uint16_t * notecount,int fd,off_t ph_off,int ph_num,off_t fsize)1215 donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
1216 int clazz, int swap, size_t align, int *flags, uint16_t *notecount,
1217 int fd, off_t ph_off, int ph_num, off_t fsize)
1218 {
1219 Elf32_Nhdr nh32;
1220 Elf64_Nhdr nh64;
1221 size_t noff, doff;
1222 uint32_t namesz, descsz;
1223 char buf[256];
1224 unsigned char *nbuf = CAST(unsigned char *, vbuf);
1225
1226 if (*notecount == 0)
1227 return 0;
1228 --*notecount;
1229
1230 if (xnh_sizeof + offset > size) {
1231 /*
1232 * We're out of note headers.
1233 */
1234 return xnh_sizeof + offset;
1235 }
1236 /*XXX: GCC */
1237 memset(&nh32, 0, sizeof(nh32));
1238 memset(&nh64, 0, sizeof(nh64));
1239
1240 memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
1241 offset += xnh_sizeof;
1242
1243 namesz = xnh_namesz;
1244 descsz = xnh_descsz;
1245
1246 if ((namesz == 0) && (descsz == 0)) {
1247 /*
1248 * We're out of note headers.
1249 */
1250 return (offset >= size) ? offset : size;
1251 }
1252
1253 if (namesz & 0x80000000) {
1254 (void)file_printf(ms, ", bad note name size %#lx",
1255 CAST(unsigned long, namesz));
1256 return 0;
1257 }
1258
1259 if (descsz & 0x80000000) {
1260 (void)file_printf(ms, ", bad note description size %#lx",
1261 CAST(unsigned long, descsz));
1262 return 0;
1263 }
1264
1265 noff = offset;
1266 doff = ELF_ALIGN(offset + namesz);
1267
1268 if (offset + namesz > size) {
1269 /*
1270 * We're past the end of the buffer.
1271 */
1272 return doff;
1273 }
1274
1275 offset = ELF_ALIGN(doff + descsz);
1276 if (doff + descsz > size) {
1277 /*
1278 * We're past the end of the buffer.
1279 */
1280 return (offset >= size) ? offset : size;
1281 }
1282
1283
1284 if ((*flags & FLAGS_DID_OS_NOTE) == 0) {
1285 if (do_os_note(ms, nbuf, xnh_type, swap,
1286 namesz, descsz, noff, doff, flags))
1287 return offset;
1288 }
1289
1290 if ((*flags & FLAGS_DID_BUILD_ID) == 0) {
1291 if (do_bid_note(ms, nbuf, xnh_type, swap,
1292 namesz, descsz, noff, doff, flags))
1293 return offset;
1294 }
1295
1296 if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) {
1297 if (do_pax_note(ms, nbuf, xnh_type, swap,
1298 namesz, descsz, noff, doff, flags))
1299 return offset;
1300 }
1301 if ((*flags & FLAGS_DID_ANDROID_MEMTAG) == 0) {
1302 if (do_memtag_note(ms, nbuf, xnh_type, swap,
1303 namesz, descsz, noff, doff, flags))
1304 return offset;
1305 }
1306
1307 if ((*flags & FLAGS_DID_CORE) == 0) {
1308 if (do_core_note(ms, nbuf, xnh_type, swap,
1309 namesz, descsz, noff, doff, flags, size, clazz))
1310 return offset;
1311 }
1312
1313 if ((*flags & FLAGS_DID_AUXV) == 0) {
1314 if (do_auxv_note(ms, nbuf, xnh_type, swap,
1315 namesz, descsz, noff, doff, flags, size, clazz,
1316 fd, ph_off, ph_num, fsize))
1317 return offset;
1318 }
1319
1320 if (NAMEEQUALS(RCAST(char *, &nbuf[noff]), "NetBSD")) {
1321 int descw, flag;
1322 const char *str, *tag;
1323 if (descsz > 100)
1324 descsz = 100;
1325 switch (xnh_type) {
1326 case NT_NETBSD_VERSION:
1327 return offset;
1328 case NT_NETBSD_MARCH:
1329 flag = FLAGS_DID_NETBSD_MARCH;
1330 tag = "compiled for";
1331 break;
1332 case NT_NETBSD_CMODEL:
1333 flag = FLAGS_DID_NETBSD_CMODEL;
1334 tag = "compiler model";
1335 break;
1336 case NT_NETBSD_EMULATION:
1337 flag = FLAGS_DID_NETBSD_EMULATION;
1338 tag = "emulation:";
1339 break;
1340 default:
1341 if (*flags & FLAGS_DID_NETBSD_UNKNOWN)
1342 return offset;
1343 *flags |= FLAGS_DID_NETBSD_UNKNOWN;
1344 if (file_printf(ms, ", note=%u", xnh_type) == -1)
1345 return offset;
1346 return offset;
1347 }
1348
1349 if (*flags & flag)
1350 return offset;
1351 str = RCAST(const char *, &nbuf[doff]);
1352 descw = CAST(int, descsz);
1353 *flags |= flag;
1354 file_printf(ms, ", %s: %s", tag,
1355 file_copystr(buf, sizeof(buf), descw, str));
1356 return offset;
1357 }
1358
1359 return offset;
1360 }
1361
1362 /* SunOS 5.x hardware capability descriptions */
1363 typedef struct cap_desc {
1364 uint64_t cd_mask;
1365 const char *cd_name;
1366 } cap_desc_t;
1367
1368 static const cap_desc_t cap_desc_sparc[] = {
1369 { AV_SPARC_MUL32, "MUL32" },
1370 { AV_SPARC_DIV32, "DIV32" },
1371 { AV_SPARC_FSMULD, "FSMULD" },
1372 { AV_SPARC_V8PLUS, "V8PLUS" },
1373 { AV_SPARC_POPC, "POPC" },
1374 { AV_SPARC_VIS, "VIS" },
1375 { AV_SPARC_VIS2, "VIS2" },
1376 { AV_SPARC_ASI_BLK_INIT, "ASI_BLK_INIT" },
1377 { AV_SPARC_FMAF, "FMAF" },
1378 { AV_SPARC_FJFMAU, "FJFMAU" },
1379 { AV_SPARC_IMA, "IMA" },
1380 { 0, NULL }
1381 };
1382
1383 static const cap_desc_t cap_desc_386[] = {
1384 { AV_386_FPU, "FPU" },
1385 { AV_386_TSC, "TSC" },
1386 { AV_386_CX8, "CX8" },
1387 { AV_386_SEP, "SEP" },
1388 { AV_386_AMD_SYSC, "AMD_SYSC" },
1389 { AV_386_CMOV, "CMOV" },
1390 { AV_386_MMX, "MMX" },
1391 { AV_386_AMD_MMX, "AMD_MMX" },
1392 { AV_386_AMD_3DNow, "AMD_3DNow" },
1393 { AV_386_AMD_3DNowx, "AMD_3DNowx" },
1394 { AV_386_FXSR, "FXSR" },
1395 { AV_386_SSE, "SSE" },
1396 { AV_386_SSE2, "SSE2" },
1397 { AV_386_PAUSE, "PAUSE" },
1398 { AV_386_SSE3, "SSE3" },
1399 { AV_386_MON, "MON" },
1400 { AV_386_CX16, "CX16" },
1401 { AV_386_AHF, "AHF" },
1402 { AV_386_TSCP, "TSCP" },
1403 { AV_386_AMD_SSE4A, "AMD_SSE4A" },
1404 { AV_386_POPCNT, "POPCNT" },
1405 { AV_386_AMD_LZCNT, "AMD_LZCNT" },
1406 { AV_386_SSSE3, "SSSE3" },
1407 { AV_386_SSE4_1, "SSE4.1" },
1408 { AV_386_SSE4_2, "SSE4.2" },
1409 { 0, NULL }
1410 };
1411
1412 file_private int
doshn(struct magic_set * ms,int clazz,int swap,int fd,off_t off,int num,size_t size,off_t fsize,int mach,int strtab,int * flags,uint16_t * notecount)1413 doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1414 size_t size, off_t fsize, int mach, int strtab, int *flags,
1415 uint16_t *notecount)
1416 {
1417 Elf32_Shdr sh32;
1418 Elf64_Shdr sh64;
1419 int stripped = 1, has_debug_info = 0;
1420 size_t nbadcap = 0;
1421 void *nbuf;
1422 off_t noff, coff, name_off, offs;
1423 uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilities */
1424 uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilities */
1425 char name[50];
1426 ssize_t namesize;
1427
1428 if (ms->flags & MAGIC_MIME)
1429 return 0;
1430
1431 if (num == 0) {
1432 if (file_printf(ms, ", no section header") == -1)
1433 return -1;
1434 return 0;
1435 }
1436 if (size != xsh_sizeof) {
1437 if (file_printf(ms, ", corrupted section header size") == -1)
1438 return -1;
1439 return 0;
1440 }
1441
1442 /* Read offset of name section to be able to read section names later */
1443 offs = CAST(off_t, (off + size * strtab));
1444 if (pread(fd, xsh_addr, xsh_sizeof, offs) < CAST(ssize_t, xsh_sizeof)) {
1445 if (file_printf(ms, ", missing section headers at %jd",
1446 (intmax_t)offs) == -1)
1447 return -1;
1448 return 0;
1449 }
1450 name_off = xsh_offset;
1451
1452 if (fsize != SIZE_UNKNOWN && fsize < name_off) {
1453 if (file_printf(ms, ", too large section header offset %jd",
1454 (intmax_t)name_off) == -1)
1455 return -1;
1456 return 0;
1457 }
1458
1459 for ( ; num; num--) {
1460 /* Read the name of this section. */
1461 offs = name_off + xsh_name;
1462 if ((namesize = pread(fd, name, sizeof(name) - 1, offs))
1463 == -1) {
1464 if (file_printf(ms,
1465 ", can't read name of elf section at %jd",
1466 (intmax_t)offs) == -1)
1467 return -1;
1468 return 0;
1469 }
1470 name[namesize] = '\0';
1471 if (strcmp(name, ".debug_info") == 0) {
1472 has_debug_info = 1;
1473 stripped = 0;
1474 }
1475
1476 if (pread(fd, xsh_addr, xsh_sizeof, off) <
1477 CAST(ssize_t, xsh_sizeof)) {
1478 if (file_printf(ms, ", can't read elf section at %jd",
1479 (intmax_t)off) == -1)
1480 return -1;
1481 return 0;
1482 }
1483 off += size;
1484
1485 /* Things we can determine before we seek */
1486 switch (xsh_type) {
1487 case SHT_SYMTAB:
1488 #if 0
1489 case SHT_DYNSYM:
1490 #endif
1491 stripped = 0;
1492 break;
1493 default:
1494 if (fsize != SIZE_UNKNOWN && xsh_offset > fsize) {
1495 /* Perhaps warn here */
1496 continue;
1497 }
1498 break;
1499 }
1500
1501
1502 /* Things we can determine when we seek */
1503 switch (xsh_type) {
1504 case SHT_NOTE:
1505 if (CAST(uintmax_t, (xsh_size + xsh_offset)) >
1506 CAST(uintmax_t, fsize)) {
1507 if (file_printf(ms,
1508 ", note offset/size %#" INTMAX_T_FORMAT
1509 "x+%#" INTMAX_T_FORMAT "x exceeds"
1510 " file size %#" INTMAX_T_FORMAT "x",
1511 CAST(uintmax_t, xsh_offset),
1512 CAST(uintmax_t, xsh_size),
1513 CAST(uintmax_t, fsize)) == -1)
1514 return -1;
1515 return 0;
1516 }
1517 if (xsh_size > ms->elf_shsize_max) {
1518 file_error(ms, errno, "Note section size too "
1519 "big (%ju > %zu)", (uintmax_t)xsh_size,
1520 ms->elf_shsize_max);
1521 return -1;
1522 }
1523 if ((nbuf = malloc(xsh_size)) == NULL) {
1524 file_error(ms, errno, "Cannot allocate memory"
1525 " for note");
1526 return -1;
1527 }
1528 offs = xsh_offset;
1529 if (pread(fd, nbuf, xsh_size, offs) <
1530 CAST(ssize_t, xsh_size)) {
1531 free(nbuf);
1532 if (file_printf(ms,
1533 ", can't read elf note at %jd",
1534 (intmax_t)offs) == -1)
1535 return -1;
1536 return 0;
1537 }
1538
1539 noff = 0;
1540 for (;;) {
1541 if (noff >= CAST(off_t, xsh_size))
1542 break;
1543 noff = donote(ms, nbuf, CAST(size_t, noff),
1544 xsh_size, clazz, swap, 4, flags, notecount,
1545 fd, 0, 0, 0);
1546 if (noff == 0)
1547 break;
1548 }
1549 free(nbuf);
1550 break;
1551 case SHT_SUNW_cap:
1552 switch (mach) {
1553 case EM_SPARC:
1554 case EM_SPARCV9:
1555 case EM_IA_64:
1556 case EM_386:
1557 case EM_AMD64:
1558 break;
1559 default:
1560 goto skip;
1561 }
1562
1563 if (nbadcap > 5)
1564 break;
1565 if (lseek(fd, xsh_offset, SEEK_SET)
1566 == CAST(off_t, -1)) {
1567 file_badseek(ms);
1568 return -1;
1569 }
1570 coff = 0;
1571 for (;;) {
1572 Elf32_Cap cap32;
1573 Elf64_Cap cap64;
1574 cap32.c_un.c_val = 0;
1575 cap64.c_un.c_val = 0;
1576 char cbuf[/*CONSTCOND*/
1577 MAX(sizeof(cap32), sizeof(cap64))];
1578 if ((coff += xcap_sizeof) >
1579 CAST(off_t, xsh_size))
1580 break;
1581 if (read(fd, cbuf, CAST(size_t, xcap_sizeof)) !=
1582 CAST(ssize_t, xcap_sizeof)) {
1583 file_badread(ms);
1584 return -1;
1585 }
1586 if (cbuf[0] == 'A') {
1587 #ifdef notyet
1588 char *p = cbuf + 1;
1589 uint32_t len, tag;
1590 memcpy(&len, p, sizeof(len));
1591 p += 4;
1592 len = getu32(swap, len);
1593 if (memcmp("gnu", p, 3) != 0) {
1594 if (file_printf(ms,
1595 ", unknown capability %.3s", p)
1596 == -1)
1597 return -1;
1598 break;
1599 }
1600 p += strlen(p) + 1;
1601 tag = *p++;
1602 memcpy(&len, p, sizeof(len));
1603 p += 4;
1604 len = getu32(swap, len);
1605 if (tag != 1) {
1606 if (file_printf(ms, ", unknown gnu"
1607 " capability tag %d", tag)
1608 == -1)
1609 return -1;
1610 break;
1611 }
1612 // gnu attributes
1613 #endif
1614 break;
1615 }
1616 memcpy(xcap_addr, cbuf, xcap_sizeof);
1617 switch (xcap_tag) {
1618 case CA_SUNW_NULL:
1619 break;
1620 case CA_SUNW_HW_1:
1621 cap_hw1 |= xcap_val;
1622 break;
1623 case CA_SUNW_SF_1:
1624 cap_sf1 |= xcap_val;
1625 break;
1626 default:
1627 if (file_printf(ms,
1628 ", with unknown capability "
1629 "%#" INT64_T_FORMAT "x = %#"
1630 INT64_T_FORMAT "x",
1631 CAST(unsigned long long, xcap_tag),
1632 CAST(unsigned long long, xcap_val))
1633 == -1)
1634 return -1;
1635 if (nbadcap++ > 2)
1636 coff = xsh_size;
1637 break;
1638 }
1639 }
1640 /*FALLTHROUGH*/
1641 skip:
1642 default:
1643 break;
1644 }
1645 }
1646
1647 if (has_debug_info) {
1648 if (file_printf(ms, ", with debug_info") == -1)
1649 return -1;
1650 }
1651 if (file_printf(ms, ", %sstripped", stripped ? "" : "not ") == -1)
1652 return -1;
1653 if (cap_hw1) {
1654 const cap_desc_t *cdp;
1655 switch (mach) {
1656 case EM_SPARC:
1657 case EM_SPARC32PLUS:
1658 case EM_SPARCV9:
1659 cdp = cap_desc_sparc;
1660 break;
1661 case EM_386:
1662 case EM_IA_64:
1663 case EM_AMD64:
1664 cdp = cap_desc_386;
1665 break;
1666 default:
1667 cdp = NULL;
1668 break;
1669 }
1670 if (file_printf(ms, ", uses") == -1)
1671 return -1;
1672 if (cdp) {
1673 while (cdp->cd_name) {
1674 if (cap_hw1 & cdp->cd_mask) {
1675 if (file_printf(ms,
1676 " %s", cdp->cd_name) == -1)
1677 return -1;
1678 cap_hw1 &= ~cdp->cd_mask;
1679 }
1680 ++cdp;
1681 }
1682 if (cap_hw1)
1683 if (file_printf(ms,
1684 " unknown hardware capability %#"
1685 INT64_T_FORMAT "x",
1686 CAST(unsigned long long, cap_hw1)) == -1)
1687 return -1;
1688 } else {
1689 if (file_printf(ms,
1690 " hardware capability %#" INT64_T_FORMAT "x",
1691 CAST(unsigned long long, cap_hw1)) == -1)
1692 return -1;
1693 }
1694 }
1695 if (cap_sf1) {
1696 if (cap_sf1 & SF1_SUNW_FPUSED) {
1697 if (file_printf(ms,
1698 (cap_sf1 & SF1_SUNW_FPKNWN)
1699 ? ", uses frame pointer"
1700 : ", not known to use frame pointer") == -1)
1701 return -1;
1702 }
1703 cap_sf1 &= ~SF1_SUNW_MASK;
1704 if (cap_sf1)
1705 if (file_printf(ms,
1706 ", with unknown software capability %#"
1707 INT64_T_FORMAT "x",
1708 CAST(unsigned long long, cap_sf1)) == -1)
1709 return -1;
1710 }
1711 return 0;
1712 }
1713
1714 /*
1715 * Look through the program headers of an executable image, to determine
1716 * if it is statically or dynamically linked. If it has a dynamic section,
1717 * it is pie, and does not have an interpreter or needed libraries, we
1718 * call it static pie.
1719 */
1720 file_private int
dophn_exec(struct magic_set * ms,int clazz,int swap,int fd,off_t off,int num,size_t size,off_t fsize,int sh_num,int * flags,uint16_t * notecount)1721 dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
1722 int num, size_t size, off_t fsize, int sh_num, int *flags,
1723 uint16_t *notecount)
1724 {
1725 Elf32_Phdr ph32;
1726 Elf64_Phdr ph64;
1727 const char *linking_style;
1728 unsigned char nbuf[NBUFSIZE];
1729 char interp[128];
1730 ssize_t bufsize;
1731 size_t offset, align, need = 0;
1732 int pie = 0, dynamic = 0;
1733
1734 if (num == 0) {
1735 if (file_printf(ms, ", no program header") == -1)
1736 return -1;
1737 return 0;
1738 }
1739 if (size != xph_sizeof) {
1740 if (file_printf(ms, ", corrupted program header size") == -1)
1741 return -1;
1742 return 0;
1743 }
1744
1745 interp[0] = '\0';
1746 for ( ; num; num--) {
1747 int doread;
1748 if (pread(fd, xph_addr, xph_sizeof, off) <
1749 CAST(ssize_t, xph_sizeof)) {
1750 if (file_printf(ms,
1751 ", can't read elf program headers at %jd",
1752 (intmax_t)off) == -1)
1753 return -1;
1754 return 0;
1755 }
1756
1757 off += size;
1758 bufsize = 0;
1759 align = 4;
1760
1761 /* Things we can determine before we seek */
1762 switch (xph_type) {
1763 case PT_DYNAMIC:
1764 doread = 1;
1765 break;
1766 case PT_NOTE:
1767 if (sh_num) /* Did this through section headers */
1768 continue;
1769 if (((align = xph_align) & 0x80000000UL) != 0 ||
1770 align < 4) {
1771 if (file_printf(ms,
1772 ", invalid note alignment %#lx",
1773 CAST(unsigned long, align)) == -1)
1774 return -1;
1775 align = 4;
1776 }
1777 /*FALLTHROUGH*/
1778 case PT_INTERP:
1779 doread = 1;
1780 break;
1781 default:
1782 doread = 0;
1783 if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
1784 /* Maybe warn here? */
1785 continue;
1786 }
1787 break;
1788 }
1789
1790 if (doread) {
1791 size_t len = xph_filesz < sizeof(nbuf) ? xph_filesz
1792 : sizeof(nbuf);
1793 off_t offs = xph_offset;
1794 bufsize = pread(fd, nbuf, len, offs);
1795 if (bufsize == -1) {
1796 if (file_printf(ms,
1797 ", can't read section at %jd",
1798 (intmax_t)offs) == -1)
1799 return -1;
1800 return 0;
1801 }
1802 }
1803
1804 /* Things we can determine when we seek */
1805 switch (xph_type) {
1806 case PT_DYNAMIC:
1807 dynamic = 1;
1808 offset = 0;
1809 // Let DF_1 determine if we are PIE or not.
1810 ms->mode &= ~0111;
1811 for (;;) {
1812 if (offset >= CAST(size_t, bufsize))
1813 break;
1814 offset = dodynamic(ms, nbuf, offset,
1815 CAST(size_t, bufsize), clazz, swap,
1816 &pie, &need);
1817 if (offset == 0)
1818 break;
1819 }
1820 if (ms->flags & MAGIC_MIME)
1821 continue;
1822 break;
1823
1824 case PT_INTERP:
1825 need++;
1826 if (ms->flags & MAGIC_MIME)
1827 continue;
1828 if (bufsize && nbuf[0]) {
1829 nbuf[bufsize - 1] = '\0';
1830 memcpy(interp, nbuf, CAST(size_t, bufsize));
1831 } else
1832 strlcpy(interp, "*empty*", sizeof(interp));
1833 break;
1834 case PT_NOTE:
1835 if (ms->flags & MAGIC_MIME)
1836 return 0;
1837 /*
1838 * This is a PT_NOTE section; loop through all the notes
1839 * in the section.
1840 */
1841 offset = 0;
1842 for (;;) {
1843 if (offset >= CAST(size_t, bufsize))
1844 break;
1845 offset = donote(ms, nbuf, offset,
1846 CAST(size_t, bufsize), clazz, swap, align,
1847 flags, notecount, fd, 0, 0, 0);
1848 if (offset == 0)
1849 break;
1850 }
1851 break;
1852 default:
1853 if (ms->flags & MAGIC_MIME)
1854 continue;
1855 break;
1856 }
1857 }
1858 if (ms->flags & MAGIC_MIME)
1859 return 0;
1860 if (dynamic) {
1861 if (pie && need == 0)
1862 linking_style = "static-pie";
1863 else
1864 linking_style = "dynamically";
1865 } else {
1866 linking_style = "statically";
1867 }
1868 if (file_printf(ms, ", %s linked", linking_style) == -1)
1869 return -1;
1870 if (interp[0])
1871 if (file_printf(ms, ", interpreter %s", file_printable(ms,
1872 CAST(char *, nbuf), sizeof(nbuf),
1873 interp, sizeof(interp))) == -1)
1874 return -1;
1875 return 0;
1876 }
1877
1878
1879 file_protected int
file_tryelf(struct magic_set * ms,const struct buffer * b)1880 file_tryelf(struct magic_set *ms, const struct buffer *b)
1881 {
1882 int fd = b->fd;
1883 const unsigned char *buf = CAST(const unsigned char *, b->fbuf);
1884 size_t nbytes = b->flen;
1885 union {
1886 int32_t l;
1887 char c[sizeof(int32_t)];
1888 } u;
1889 int clazz;
1890 int swap;
1891 struct stat st;
1892 const struct stat *stp;
1893 off_t fsize;
1894 int flags = 0;
1895 Elf32_Ehdr elf32hdr;
1896 Elf64_Ehdr elf64hdr;
1897 uint16_t type, phnum, shnum, notecount;
1898
1899 if (ms->flags & (MAGIC_APPLE|MAGIC_EXTENSION))
1900 return 0;
1901 /*
1902 * ELF executables have multiple section headers in arbitrary
1903 * file locations and thus file(1) cannot determine it from easily.
1904 * Instead we traverse thru all section headers until a symbol table
1905 * one is found or else the binary is stripped.
1906 * Return immediately if it's not ELF (so we avoid pipe2file unless
1907 * needed).
1908 */
1909 if (buf[EI_MAG0] != ELFMAG0
1910 || (buf[EI_MAG1] != ELFMAG1 && buf[EI_MAG1] != OLFMAG1)
1911 || buf[EI_MAG2] != ELFMAG2 || buf[EI_MAG3] != ELFMAG3)
1912 return 0;
1913
1914 /*
1915 * If we cannot seek, it must be a pipe, socket or fifo.
1916 */
1917 if((lseek(fd, CAST(off_t, 0), SEEK_SET) == CAST(off_t, -1))
1918 && (errno == ESPIPE))
1919 fd = file_pipe2file(ms, fd, buf, nbytes);
1920
1921 if (fd == -1) {
1922 file_badread(ms);
1923 return -1;
1924 }
1925
1926 stp = &b->st;
1927 /*
1928 * b->st.st_size != 0 if previous fstat() succeeded,
1929 * which is likely, we can avoid extra stat() call.
1930 */
1931 if (b->st.st_size == 0) {
1932 stp = &st;
1933 if (fstat(fd, &st) == -1) {
1934 file_badread(ms);
1935 return -1;
1936 }
1937 }
1938 if (S_ISREG(stp->st_mode) || stp->st_size != 0)
1939 fsize = stp->st_size;
1940 else
1941 fsize = SIZE_UNKNOWN;
1942
1943 clazz = buf[EI_CLASS];
1944
1945 switch (clazz) {
1946 case ELFCLASS32:
1947 #undef elf_getu
1948 #define elf_getu(a, b) elf_getu32(a, b)
1949 #undef elfhdr
1950 #define elfhdr elf32hdr
1951 #include "elfclass.h"
1952 case ELFCLASS64:
1953 #undef elf_getu
1954 #define elf_getu(a, b) elf_getu64(a, b)
1955 #undef elfhdr
1956 #define elfhdr elf64hdr
1957 #include "elfclass.h"
1958 default:
1959 if (file_printf(ms, ", unknown class %d", clazz) == -1)
1960 return -1;
1961 break;
1962 }
1963 return 0;
1964 }
1965 #endif
1966