Coverage Report

Created: 2023-09-25 06:40

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