Coverage Report

Created: 2025-10-10 06:57

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