summaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch')
-rw-r--r--meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch1414
1 files changed, 1414 insertions, 0 deletions
diff --git a/meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch b/meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch
new file mode 100644
index 0000000000..2482de3998
--- /dev/null
+++ b/meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch
@@ -0,0 +1,1414 @@
1file: CVE-2014-9620 and CVE-2014-9621
2
3CVE-2014-9620:
4Limit the number of ELF notes processed - DoS
5CVE-2014-9621:
6Limit string printing to 100 chars - DoS
7
8The patch comes from:
9https://github.com/file/file/commit/6ce24f35cd4a43c4bdd249e8e0c4952c1f8eac67
10https://github.com/file/file/commit/0056ec32255de1de973574b0300161a1568767d6
11https://github.com/file/file/commit/09e41625c999a2e5b51e1092f0ef2432a99b5c33
12https://github.com/file/file/commit/af444af0738468393f40f9d2261b1ea10fc4b2ba
13https://github.com/file/file/commit/68bd8433c7e11a8dbe100deefdfac69138ee7cd9
14https://github.com/file/file/commit/dddd3cdb95210a765dd90f7d722cb8b5534daee7
15https://github.com/file/file/commit/445c8fb0ebff85195be94cd9f7e1df89cade5c7f
16https://github.com/file/file/commit/ce90e05774dd77d86cfc8dfa6da57b32816841c4
17https://github.com/file/file/commit/65437cee25199dbd385fb35901bc0011e164276c
18
19Upstream-Status: Backport
20
21Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
22---
23 src/apprentice.c | 5 +
24 src/ascmagic.c | 3 +-
25 src/elfclass.h | 34 ++--
26 src/file.c | 59 ++++++-
27 src/file.h | 20 ++-
28 src/file_opts.h | 6 +
29 src/funcs.c | 42 ++++-
30 src/magic.c | 50 ++++++
31 src/magic.h | 9 ++
32 src/magic.h.in | 9 ++
33 src/readelf.c | 471 +++++++++++++++++++++++++++++++++----------------------
34 src/softmagic.c | 93 ++++++-----
35 12 files changed, 566 insertions(+), 235 deletions(-)
36
37diff --git a/src/apprentice.c b/src/apprentice.c
38index 7400c57..231dc7e 100644
39--- a/src/apprentice.c
40+++ b/src/apprentice.c
41@@ -506,6 +506,11 @@ file_ms_alloc(int flags)
42 ms->mlist[i] = NULL;
43 ms->file = "unknown";
44 ms->line = 0;
45+ ms->indir_max = FILE_INDIR_MAX;
46+ ms->name_max = FILE_NAME_MAX;
47+ ms->elf_shnum_max = FILE_ELF_SHNUM_MAX;
48+ ms->elf_phnum_max = FILE_ELF_PHNUM_MAX;
49+ ms->elf_notes_max = FILE_ELF_NOTES_MAX;
50 return ms;
51 free:
52 free(ms);
53diff --git a/src/ascmagic.c b/src/ascmagic.c
54index ca26665..0a4cd10 100644
55--- a/src/ascmagic.c
56+++ b/src/ascmagic.c
57@@ -147,7 +147,8 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf,
58 == NULL)
59 goto done;
60 if ((rv = file_softmagic(ms, utf8_buf,
61- (size_t)(utf8_end - utf8_buf), 0, TEXTTEST, text)) == 0)
62+ (size_t)(utf8_end - utf8_buf), 0, NULL,
63+ TEXTTEST, text)) == 0)
64 rv = -1;
65 }
66
67diff --git a/src/elfclass.h b/src/elfclass.h
68index 010958a..5360b0b 100644
69--- a/src/elfclass.h
70+++ b/src/elfclass.h
71@@ -32,39 +32,51 @@
72 swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA];
73
74 type = elf_getu16(swap, elfhdr.e_type);
75+ notecount = ms->elf_notes_max;
76 switch (type) {
77 #ifdef ELFCORE
78 case ET_CORE:
79+ phnum = elf_getu16(swap, elfhdr.e_phnum);
80+ if (phnum > ms->elf_phnum_max)
81+ return toomany(ms, "program headers", phnum);
82 flags |= FLAGS_IS_CORE;
83 if (dophn_core(ms, clazz, swap, fd,
84- (off_t)elf_getu(swap, elfhdr.e_phoff),
85- elf_getu16(swap, elfhdr.e_phnum),
86+ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
87 (size_t)elf_getu16(swap, elfhdr.e_phentsize),
88- fsize, &flags) == -1)
89+ fsize, &flags, &notecount) == -1)
90 return -1;
91 break;
92 #endif
93 case ET_EXEC:
94 case ET_DYN:
95+ phnum = elf_getu16(swap, elfhdr.e_phnum);
96+ if (phnum > ms->elf_phnum_max)
97+ return toomany(ms, "program", phnum);
98+ shnum = elf_getu16(swap, elfhdr.e_shnum);
99+ if (shnum > ms->elf_shnum_max)
100+ return toomany(ms, "section", shnum);
101 if (dophn_exec(ms, clazz, swap, fd,
102- (off_t)elf_getu(swap, elfhdr.e_phoff),
103- elf_getu16(swap, elfhdr.e_phnum),
104+ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
105 (size_t)elf_getu16(swap, elfhdr.e_phentsize),
106- fsize, &flags, elf_getu16(swap, elfhdr.e_shnum))
107- == -1)
108+ fsize, shnum, &flags, &notecount) == -1)
109 return -1;
110 /*FALLTHROUGH*/
111 case ET_REL:
112+ shnum = elf_getu16(swap, elfhdr.e_shnum);
113+ if (shnum > ms->elf_shnum_max)
114+ return toomany(ms, "section headers", shnum);
115 if (doshn(ms, clazz, swap, fd,
116- (off_t)elf_getu(swap, elfhdr.e_shoff),
117- elf_getu16(swap, elfhdr.e_shnum),
118+ (off_t)elf_getu(swap, elfhdr.e_shoff), shnum,
119 (size_t)elf_getu16(swap, elfhdr.e_shentsize),
120- fsize, &flags, elf_getu16(swap, elfhdr.e_machine),
121- (int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1)
122+ fsize, elf_getu16(swap, elfhdr.e_machine),
123+ (int)elf_getu16(swap, elfhdr.e_shstrndx),
124+ &flags, &notecount) == -1)
125 return -1;
126 break;
127
128 default:
129 break;
130 }
131+ if (notecount == 0)
132+ return toomany(ms, "notes", ms->elf_notes_max);
133 return 1;
134diff --git a/src/file.c b/src/file.c
135index 370da91..b69b725 100644
136--- a/src/file.c
137+++ b/src/file.c
138@@ -101,7 +101,7 @@ private const struct option long_options[] = {
139 #undef OPT_LONGONLY
140 {0, 0, NULL, 0}
141 };
142-#define OPTSTRING "bcCde:Ef:F:hiklLm:nNprsvz0"
143+#define OPTSTRING "bcCde:Ef:F:hiklLm:nNpP:rsvz0"
144
145 private const struct {
146 const char *name;
147@@ -119,6 +119,18 @@ private const struct {
148 { "tokens", MAGIC_NO_CHECK_TOKENS }, /* OBSOLETE: ignored for backwards compatibility */
149 };
150
151+private struct {
152+ const char *name;
153+ int tag;
154+ size_t value;
155+} pm[] = {
156+ { "indir", MAGIC_PARAM_INDIR_MAX, 0 },
157+ { "name", MAGIC_PARAM_NAME_MAX, 0 },
158+ { "elf_phnum", MAGIC_PARAM_ELF_PHNUM_MAX, 0 },
159+ { "elf_shnum", MAGIC_PARAM_ELF_SHNUM_MAX, 0 },
160+ { "elf_notes", MAGIC_PARAM_ELF_NOTES_MAX, 0 },
161+};
162+
163 private char *progname; /* used throughout */
164
165 private void usage(void);
166@@ -128,6 +140,8 @@ private void help(void);
167 private int unwrap(struct magic_set *, const char *);
168 private int process(struct magic_set *ms, const char *, int);
169 private struct magic_set *load(const char *, int);
170+private void setparam(const char *);
171+private void applyparam(magic_t);
172
173
174 /*
175@@ -243,9 +257,13 @@ main(int argc, char *argv[])
176 flags |= MAGIC_PRESERVE_ATIME;
177 break;
178 #endif
179+ case 'P':
180+ setparam(optarg);
181+ break;
182 case 'r':
183 flags |= MAGIC_RAW;
184 break;
185+ break;
186 case 's':
187 flags |= MAGIC_DEVICES;
188 break;
189@@ -298,6 +316,8 @@ main(int argc, char *argv[])
190 strerror(errno));
191 return 1;
192 }
193+
194+
195 switch(action) {
196 case FILE_CHECK:
197 c = magic_check(magic, magicfile);
198@@ -321,7 +341,7 @@ main(int argc, char *argv[])
199 if (magic == NULL)
200 if ((magic = load(magicfile, flags)) == NULL)
201 return 1;
202- break;
203+ applyparam(magic);
204 }
205
206 if (optind == argc) {
207@@ -351,6 +371,41 @@ main(int argc, char *argv[])
208 return e;
209 }
210
211+private void
212+applyparam(magic_t magic)
213+{
214+ size_t i;
215+
216+ for (i = 0; i < __arraycount(pm); i++) {
217+ if (pm[i].value == 0)
218+ continue;
219+ if (magic_setparam(magic, pm[i].tag, &pm[i].value) == -1) {
220+ (void)fprintf(stderr, "%s: Can't set %s %s\n", progname,
221+ pm[i].name, strerror(errno));
222+ exit(1);
223+ }
224+ }
225+}
226+
227+private void
228+setparam(const char *p)
229+{
230+ size_t i;
231+ char *s;
232+
233+ if ((s = strchr(p, '=')) == NULL)
234+ goto badparm;
235+
236+ for (i = 0; i < __arraycount(pm); i++) {
237+ if (strncmp(p, pm[i].name, s - p) != 0)
238+ continue;
239+ pm[i].value = atoi(s + 1);
240+ return;
241+ }
242+badparm:
243+ (void)fprintf(stderr, "%s: Unknown param %s\n", progname, p);
244+ exit(1);
245+}
246
247 private struct magic_set *
248 /*ARGSUSED*/
249diff --git a/src/file.h b/src/file.h
250index 5c67ddd..88da1d1 100644
251--- a/src/file.h
252+++ b/src/file.h
253@@ -400,6 +400,16 @@ struct magic_set {
254 /* FIXME: Make the string dynamically allocated so that e.g.
255 strings matched in files can be longer than MAXstring */
256 union VALUETYPE ms_value; /* either number or string */
257+ uint16_t indir_max;
258+ uint16_t name_max;
259+ uint16_t elf_shnum_max;
260+ uint16_t elf_phnum_max;
261+ uint16_t elf_notes_max;
262+#define FILE_INDIR_MAX 15
263+#define FILE_NAME_MAX 30
264+#define FILE_ELF_SHNUM_MAX 32768
265+#define FILE_ELF_PHNUM_MAX 128
266+#define FILE_ELF_NOTES_MAX 256
267 };
268
269 /* Type for Unicode characters */
270@@ -439,7 +449,7 @@ protected int file_encoding(struct magic_set *, const unsigned char *, size_t,
271 unichar **, size_t *, const char **, const char **, const char **);
272 protected int file_is_tar(struct magic_set *, const unsigned char *, size_t);
273 protected int file_softmagic(struct magic_set *, const unsigned char *, size_t,
274- size_t, int, int);
275+ uint16_t, uint16_t *, int, int);
276 protected int file_apprentice(struct magic_set *, const char *, int);
277 protected int file_magicfind(struct magic_set *, const char *, struct mlist *);
278 protected uint64_t file_signextend(struct magic_set *, struct magic *,
279@@ -469,6 +479,14 @@ protected int file_os2_apptype(struct magic_set *, const char *, const void *,
280 #endif /* __EMX__ */
281
282
283+typedef struct {
284+ char *buf;
285+ uint32_t offset;
286+} file_pushbuf_t;
287+
288+protected file_pushbuf_t *file_push_buffer(struct magic_set *);
289+protected char *file_pop_buffer(struct magic_set *, file_pushbuf_t *);
290+
291 #ifndef COMPILE_ONLY
292 extern const char *file_names[];
293 extern const size_t file_nnames;
294diff --git a/src/file_opts.h b/src/file_opts.h
295index db34eb7..3286ac6 100644
296--- a/src/file_opts.h
297+++ b/src/file_opts.h
298@@ -43,6 +43,12 @@ OPT('0', "print0", 0, " terminate filenames with ASCII NUL\n")
299 #if defined(HAVE_UTIME) || defined(HAVE_UTIMES)
300 OPT('p', "preserve-date", 0, " preserve access times on files\n")
301 #endif
302+OPT('P', "parameter", 0, " set file engine parameter limits\n"
303+ " indir 15 recursion limit for indirection\n"
304+ " name 30 use limit for name/use magic\n"
305+ " elf_notes 256 max ELF notes processed\n"
306+ " elf_phnum 128 max ELF prog sections processed\n"
307+ " elf_shnum 32768 max ELF sections processed\n")
308 OPT('r', "raw", 0, " don't translate unprintable chars to \\ooo\n")
309 OPT('s', "special-files", 0, " treat special (block/char devices) files as\n"
310 " ordinary ones\n")
311diff --git a/src/funcs.c b/src/funcs.c
312index a9624a2..c3cf2be 100644
313--- a/src/funcs.c
314+++ b/src/funcs.c
315@@ -230,7 +230,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((unu
316
317 /* try soft magic tests */
318 if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0)
319- if ((m = file_softmagic(ms, ubuf, nb, 0, BINTEST,
320+ if ((m = file_softmagic(ms, ubuf, nb, 0, NULL, BINTEST,
321 looks_text)) != 0) {
322 if ((ms->flags & MAGIC_DEBUG) != 0)
323 (void)fprintf(stderr, "softmagic %d\n", m);
324@@ -459,3 +459,43 @@ out:
325 free(old_lc_ctype);
326 return rv;
327 }
328+
329+protected file_pushbuf_t *
330+file_push_buffer(struct magic_set *ms)
331+{
332+ file_pushbuf_t *pb;
333+
334+ if (ms->event_flags & EVENT_HAD_ERR)
335+ return NULL;
336+
337+ if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL)
338+ return NULL;
339+
340+ pb->buf = ms->o.buf;
341+ pb->offset = ms->offset;
342+
343+ ms->o.buf = NULL;
344+ ms->offset = 0;
345+
346+ return pb;
347+}
348+
349+protected char *
350+file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb)
351+{
352+ char *rbuf;
353+
354+ if (ms->event_flags & EVENT_HAD_ERR) {
355+ free(pb->buf);
356+ free(pb);
357+ return NULL;
358+ }
359+
360+ rbuf = ms->o.buf;
361+
362+ ms->o.buf = pb->buf;
363+ ms->offset = pb->offset;
364+
365+ free(pb);
366+ return rbuf;
367+}
368diff --git a/src/magic.c b/src/magic.c
369index 22174b8..a89647c 100644
370--- a/src/magic.c
371+++ b/src/magic.c
372@@ -490,3 +490,53 @@ magic_version(void)
373 {
374 return MAGIC_VERSION;
375 }
376+
377+public int
378+magic_setparam(struct magic_set *ms, int param, const void *val)
379+{
380+ switch (param) {
381+ case MAGIC_PARAM_INDIR_MAX:
382+ ms->indir_max = *(const size_t *)val;
383+ return 0;
384+ case MAGIC_PARAM_NAME_MAX:
385+ ms->name_max = *(const size_t *)val;
386+ return 0;
387+ case MAGIC_PARAM_ELF_PHNUM_MAX:
388+ ms->elf_phnum_max = *(const size_t *)val;
389+ return 0;
390+ case MAGIC_PARAM_ELF_SHNUM_MAX:
391+ ms->elf_shnum_max = *(const size_t *)val;
392+ return 0;
393+ case MAGIC_PARAM_ELF_NOTES_MAX:
394+ ms->elf_notes_max = *(const size_t *)val;
395+ return 0;
396+ default:
397+ errno = EINVAL;
398+ return -1;
399+ }
400+}
401+
402+public int
403+magic_getparam(struct magic_set *ms, int param, void *val)
404+{
405+ switch (param) {
406+ case MAGIC_PARAM_INDIR_MAX:
407+ *(size_t *)val = ms->indir_max;
408+ return 0;
409+ case MAGIC_PARAM_NAME_MAX:
410+ *(size_t *)val = ms->name_max;
411+ return 0;
412+ case MAGIC_PARAM_ELF_PHNUM_MAX:
413+ *(size_t *)val = ms->elf_phnum_max;
414+ return 0;
415+ case MAGIC_PARAM_ELF_SHNUM_MAX:
416+ *(size_t *)val = ms->elf_shnum_max;
417+ return 0;
418+ case MAGIC_PARAM_ELF_NOTES_MAX:
419+ *(size_t *)val = ms->elf_notes_max;
420+ return 0;
421+ default:
422+ errno = EINVAL;
423+ return -1;
424+ }
425+}
426diff --git a/src/magic.h b/src/magic.h
427index 535a177..89bfe4b 100644
428--- a/src/magic.h
429+++ b/src/magic.h
430@@ -101,6 +101,15 @@ int magic_check(magic_t, const char *);
431 int magic_list(magic_t, const char *);
432 int magic_errno(magic_t);
433
434+#define MAGIC_PARAM_INDIR_MAX 0
435+#define MAGIC_PARAM_NAME_MAX 1
436+#define MAGIC_PARAM_ELF_PHNUM_MAX 2
437+#define MAGIC_PARAM_ELF_SHNUM_MAX 3
438+#define MAGIC_PARAM_ELF_NOTES_MAX 4
439+
440+int magic_setparam(magic_t, int, const void *);
441+int magic_getparam(magic_t, int, void *);
442+
443 #ifdef __cplusplus
444 };
445 #endif
446diff --git a/src/magic.h.in b/src/magic.h.in
447index 86fc41b..2efc7bc 100644
448--- a/src/magic.h.in
449+++ b/src/magic.h.in
450@@ -101,6 +101,15 @@ int magic_check(magic_t, const char *);
451 int magic_list(magic_t, const char *);
452 int magic_errno(magic_t);
453
454+#define MAGIC_PARAM_INDIR_MAX 0
455+#define MAGIC_PARAM_NAME_MAX 1
456+#define MAGIC_PARAM_ELF_PHNUM_MAX 2
457+#define MAGIC_PARAM_ELF_SHNUM_MAX 3
458+#define MAGIC_PARAM_ELF_NOTES_MAX 4
459+
460+int magic_setparam(magic_t, int, const void *);
461+int magic_getparam(magic_t, int, void *);
462+
463 #ifdef __cplusplus
464 };
465 #endif
466diff --git a/src/readelf.c b/src/readelf.c
467index cbed129..87df727 100644
468--- a/src/readelf.c
469+++ b/src/readelf.c
470@@ -43,14 +43,14 @@ FILE_RCSID("@(#)$File: readelf.c,v 1.102 2014/03/11 21:00:13 christos Exp $")
471
472 #ifdef ELFCORE
473 private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t,
474- off_t, int *);
475+ off_t, int *, uint16_t *);
476 #endif
477 private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t,
478- off_t, int *, int);
479+ off_t, int, int *, uint16_t *);
480 private int doshn(struct magic_set *, int, int, int, off_t, int, size_t,
481- off_t, int *, int, int);
482+ off_t, int, int, int *, uint16_t *);
483 private size_t donote(struct magic_set *, void *, size_t, size_t, int,
484- int, size_t, int *);
485+ int, size_t, int *, uint16_t *);
486
487 #define ELF_ALIGN(a) ((((a) + align - 1) / align) * align)
488
489@@ -60,6 +60,19 @@ private uint16_t getu16(int, uint16_t);
490 private uint32_t getu32(int, uint32_t);
491 private uint64_t getu64(int, uint64_t);
492
493+#define MAX_PHNUM 128
494+#define MAX_SHNUM 32768
495+#define SIZE_UNKNOWN ((off_t)-1)
496+
497+private int
498+toomany(struct magic_set *ms, const char *name, uint16_t num)
499+{
500+ if (file_printf(ms, ", too many %s (%u)", name, num
501+ ) == -1)
502+ return -1;
503+ return 0;
504+}
505+
506 private uint16_t
507 getu16(int swap, uint16_t value)
508 {
509@@ -280,15 +293,19 @@ private const char os_style_names[][8] = {
510 "NetBSD",
511 };
512
513-#define FLAGS_DID_CORE 0x01
514-#define FLAGS_DID_NOTE 0x02
515-#define FLAGS_DID_BUILD_ID 0x04
516-#define FLAGS_DID_CORE_STYLE 0x08
517-#define FLAGS_IS_CORE 0x10
518+#define FLAGS_DID_CORE 0x001
519+#define FLAGS_DID_OS_NOTE 0x002
520+#define FLAGS_DID_BUILD_ID 0x004
521+#define FLAGS_DID_CORE_STYLE 0x008
522+#define FLAGS_DID_NETBSD_PAX 0x010
523+#define FLAGS_DID_NETBSD_MARCH 0x020
524+#define FLAGS_DID_NETBSD_CMODEL 0x040
525+#define FLAGS_DID_NETBSD_UNKNOWN 0x080
526+#define FLAGS_IS_CORE 0x100
527
528 private int
529 dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
530- int num, size_t size, off_t fsize, int *flags)
531+ int num, size_t size, off_t fsize, int *flags, uint16_t *notecount)
532 {
533 Elf32_Phdr ph32;
534 Elf64_Phdr ph64;
535@@ -306,13 +323,13 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
536 * Loop through all the program headers.
537 */
538 for ( ; num; num--) {
539- if (pread(fd, xph_addr, xph_sizeof, off) == -1) {
540+ if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) {
541 file_badread(ms);
542 return -1;
543 }
544 off += size;
545
546- if (xph_offset > fsize) {
547+ if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
548 /* Perhaps warn here */
549 continue;
550 }
551@@ -334,7 +351,7 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
552 if (offset >= (size_t)bufsize)
553 break;
554 offset = donote(ms, nbuf, offset, (size_t)bufsize,
555- clazz, swap, 4, flags);
556+ clazz, swap, 4, flags, notecount);
557 if (offset == 0)
558 break;
559
560@@ -464,125 +481,128 @@ do_note_freebsd_version(struct magic_set *ms, int swap, void *v)
561 }
562 }
563
564-private size_t
565-donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
566- int clazz, int swap, size_t align, int *flags)
567+private int
568+do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
569+ int swap __attribute__((__unused__)), uint32_t namesz, uint32_t descsz,
570+ size_t noff, size_t doff, int *flags)
571 {
572- Elf32_Nhdr nh32;
573- Elf64_Nhdr nh64;
574- size_t noff, doff;
575-#ifdef ELFCORE
576- int os_style = -1;
577-#endif
578- uint32_t namesz, descsz;
579- unsigned char *nbuf = CAST(unsigned char *, vbuf);
580-
581- (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
582- offset += xnh_sizeof;
583-
584- namesz = xnh_namesz;
585- descsz = xnh_descsz;
586- if ((namesz == 0) && (descsz == 0)) {
587- /*
588- * We're out of note headers.
589- */
590- return (offset >= size) ? offset : size;
591- }
592-
593- if (namesz & 0x80000000) {
594- (void)file_printf(ms, ", bad note name size 0x%lx",
595- (unsigned long)namesz);
596- return offset;
597- }
598-
599- if (descsz & 0x80000000) {
600- (void)file_printf(ms, ", bad note description size 0x%lx",
601- (unsigned long)descsz);
602- return offset;
603- }
604-
605-
606- noff = offset;
607- doff = ELF_ALIGN(offset + namesz);
608-
609- if (offset + namesz > size) {
610- /*
611- * We're past the end of the buffer.
612- */
613- return doff;
614- }
615-
616- offset = ELF_ALIGN(doff + descsz);
617- if (doff + descsz > size) {
618- /*
619- * We're past the end of the buffer.
620- */
621- return (offset >= size) ? offset : size;
622+ if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
623+ type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) {
624+ uint8_t desc[20];
625+ uint32_t i;
626+ *flags |= FLAGS_DID_BUILD_ID;
627+ if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" :
628+ "sha1") == -1)
629+ return 1;
630+ (void)memcpy(desc, &nbuf[doff], descsz);
631+ for (i = 0; i < descsz; i++)
632+ if (file_printf(ms, "%02x", desc[i]) == -1)
633+ return 1;
634+ return 1;
635 }
636-
637- if ((*flags & (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID)) ==
638- (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID))
639- goto core;
640-
641+ return 0;
642+}
643+
644+private int
645+do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
646+ int swap, uint32_t namesz, uint32_t descsz,
647+ size_t noff, size_t doff, int *flags)
648+{
649 if (namesz == 5 && strcmp((char *)&nbuf[noff], "SuSE") == 0 &&
650- xnh_type == NT_GNU_VERSION && descsz == 2) {
651+ type == NT_GNU_VERSION && descsz == 2) {
652+ *flags |= FLAGS_DID_OS_NOTE;
653 file_printf(ms, ", for SuSE %d.%d", nbuf[doff], nbuf[doff + 1]);
654+ return 1;
655 }
656+
657 if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
658- xnh_type == NT_GNU_VERSION && descsz == 16) {
659+ type == NT_GNU_VERSION && descsz == 16) {
660 uint32_t desc[4];
661 (void)memcpy(desc, &nbuf[doff], sizeof(desc));
662
663+ *flags |= FLAGS_DID_OS_NOTE;
664 if (file_printf(ms, ", for GNU/") == -1)
665- return size;
666+ return 1;
667 switch (elf_getu32(swap, desc[0])) {
668 case GNU_OS_LINUX:
669 if (file_printf(ms, "Linux") == -1)
670- return size;
671+ return 1;
672 break;
673 case GNU_OS_HURD:
674 if (file_printf(ms, "Hurd") == -1)
675- return size;
676+ return 1;
677 break;
678 case GNU_OS_SOLARIS:
679 if (file_printf(ms, "Solaris") == -1)
680- return size;
681+ return 1;
682 break;
683 case GNU_OS_KFREEBSD:
684 if (file_printf(ms, "kFreeBSD") == -1)
685- return size;
686+ return 1;
687 break;
688 case GNU_OS_KNETBSD:
689 if (file_printf(ms, "kNetBSD") == -1)
690- return size;
691+ return 1;
692 break;
693 default:
694 if (file_printf(ms, "<unknown>") == -1)
695- return size;
696+ return 1;
697 }
698 if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]),
699 elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1)
700- return size;
701- *flags |= FLAGS_DID_NOTE;
702- return size;
703+ return 1;
704+ return 1;
705 }
706
707- if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 &&
708- xnh_type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) {
709- uint8_t desc[20];
710- uint32_t i;
711- if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" :
712- "sha1") == -1)
713- return size;
714- (void)memcpy(desc, &nbuf[doff], descsz);
715- for (i = 0; i < descsz; i++)
716- if (file_printf(ms, "%02x", desc[i]) == -1)
717- return size;
718- *flags |= FLAGS_DID_BUILD_ID;
719+ if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) {
720+ if (type == NT_NETBSD_VERSION && descsz == 4) {
721+ *flags |= FLAGS_DID_OS_NOTE;
722+ do_note_netbsd_version(ms, swap, &nbuf[doff]);
723+ return 1;
724+ }
725+ }
726+
727+ if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) {
728+ if (type == NT_FREEBSD_VERSION && descsz == 4) {
729+ *flags |= FLAGS_DID_OS_NOTE;
730+ do_note_freebsd_version(ms, swap, &nbuf[doff]);
731+ return 1;
732+ }
733+ }
734+
735+ if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
736+ type == NT_OPENBSD_VERSION && descsz == 4) {
737+ *flags |= FLAGS_DID_OS_NOTE;
738+ if (file_printf(ms, ", for OpenBSD") == -1)
739+ return 1;
740+ /* Content of note is always 0 */
741+ return 1;
742+ }
743+
744+ if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 &&
745+ type == NT_DRAGONFLY_VERSION && descsz == 4) {
746+ uint32_t desc;
747+ *flags |= FLAGS_DID_OS_NOTE;
748+ if (file_printf(ms, ", for DragonFly") == -1)
749+ return 1;
750+ (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
751+ desc = elf_getu32(swap, desc);
752+ if (file_printf(ms, " %d.%d.%d", desc / 100000,
753+ desc / 10000 % 10, desc % 10000) == -1)
754+ return 1;
755+ return 1;
756 }
757+ return 0;
758+}
759+
760+private int
761+do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
762+ int swap, uint32_t namesz, uint32_t descsz,
763+ size_t noff, size_t doff, int *flags)
764+{
765
766 if (namesz == 4 && strcmp((char *)&nbuf[noff], "PaX") == 0 &&
767- xnh_type == NT_NETBSD_PAX && descsz == 4) {
768+ type == NT_NETBSD_PAX && descsz == 4) {
769 static const char *pax[] = {
770 "+mprotect",
771 "-mprotect",
772@@ -595,80 +615,32 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
773 size_t i;
774 int did = 0;
775
776+ *flags |= FLAGS_DID_NETBSD_PAX;
777 (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
778 desc = elf_getu32(swap, desc);
779
780 if (desc && file_printf(ms, ", PaX: ") == -1)
781- return size;
782+ return 1;
783
784 for (i = 0; i < __arraycount(pax); i++) {
785 if (((1 << i) & desc) == 0)
786 continue;
787 if (file_printf(ms, "%s%s", did++ ? "," : "",
788 pax[i]) == -1)
789- return size;
790- }
791- }
792-
793- if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) {
794- switch (xnh_type) {
795- case NT_NETBSD_VERSION:
796- if (descsz == 4) {
797- do_note_netbsd_version(ms, swap, &nbuf[doff]);
798- *flags |= FLAGS_DID_NOTE;
799- return size;
800- }
801- break;
802- case NT_NETBSD_MARCH:
803- if (file_printf(ms, ", compiled for: %.*s", (int)descsz,
804- (const char *)&nbuf[doff]) == -1)
805- return size;
806- break;
807- case NT_NETBSD_CMODEL:
808- if (file_printf(ms, ", compiler model: %.*s",
809- (int)descsz, (const char *)&nbuf[doff]) == -1)
810- return size;
811- break;
812- default:
813- if (file_printf(ms, ", note=%u", xnh_type) == -1)
814- return size;
815- break;
816- }
817- return size;
818- }
819-
820- if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) {
821- if (xnh_type == NT_FREEBSD_VERSION && descsz == 4) {
822- do_note_freebsd_version(ms, swap, &nbuf[doff]);
823- *flags |= FLAGS_DID_NOTE;
824- return size;
825+ return 1;
826 }
827+ return 1;
828 }
829+ return 0;
830+}
831
832- if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 &&
833- xnh_type == NT_OPENBSD_VERSION && descsz == 4) {
834- if (file_printf(ms, ", for OpenBSD") == -1)
835- return size;
836- /* Content of note is always 0 */
837- *flags |= FLAGS_DID_NOTE;
838- return size;
839- }
840-
841- if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 &&
842- xnh_type == NT_DRAGONFLY_VERSION && descsz == 4) {
843- uint32_t desc;
844- if (file_printf(ms, ", for DragonFly") == -1)
845- return size;
846- (void)memcpy(&desc, &nbuf[doff], sizeof(desc));
847- desc = elf_getu32(swap, desc);
848- if (file_printf(ms, " %d.%d.%d", desc / 100000,
849- desc / 10000 % 10, desc % 10000) == -1)
850- return size;
851- *flags |= FLAGS_DID_NOTE;
852- return size;
853- }
854-
855-core:
856+private int
857+do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type,
858+ int swap, uint32_t namesz, uint32_t descsz,
859+ size_t noff, size_t doff, int *flags, size_t size, int clazz)
860+{
861+#ifdef ELFCORE
862+ int os_style = -1;
863 /*
864 * Sigh. The 2.0.36 kernel in Debian 2.1, at
865 * least, doesn't correctly implement name
866@@ -697,20 +669,17 @@ core:
867 os_style = OS_STYLE_NETBSD;
868 }
869
870-#ifdef ELFCORE
871- if ((*flags & FLAGS_DID_CORE) != 0)
872- return size;
873-
874 if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) {
875 if (file_printf(ms, ", %s-style", os_style_names[os_style])
876 == -1)
877- return size;
878+ return 1;
879 *flags |= FLAGS_DID_CORE_STYLE;
880 }
881
882 switch (os_style) {
883 case OS_STYLE_NETBSD:
884- if (xnh_type == NT_NETBSD_CORE_PROCINFO) {
885+ if (type == NT_NETBSD_CORE_PROCINFO) {
886+ char sbuf[512];
887 uint32_t signo;
888 /*
889 * Extract the program name. It is at
890@@ -719,7 +688,7 @@ core:
891 */
892 if (file_printf(ms, ", from '%.31s'",
893 &nbuf[doff + 0x7c]) == -1)
894- return size;
895+ return 1;
896
897 /*
898 * Extract the signal number. It is at
899@@ -729,14 +698,14 @@ core:
900 sizeof(signo));
901 if (file_printf(ms, " (signal %u)",
902 elf_getu32(swap, signo)) == -1)
903- return size;
904+ return 1;
905 *flags |= FLAGS_DID_CORE;
906- return size;
907+ return 1;
908 }
909 break;
910
911 default:
912- if (xnh_type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
913+ if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
914 size_t i, j;
915 unsigned char c;
916 /*
917@@ -804,7 +773,7 @@ core:
918 * Try next offsets, in case this match is
919 * in the middle of a string.
920 */
921- for (k = i + 1 ; k < NOFFSETS ; k++) {
922+ for (k = i + 1 ; k < NOFFSETS; k++) {
923 size_t no;
924 int adjust = 1;
925 if (prpsoffsets(k) >= prpsoffsets(i))
926@@ -829,9 +798,9 @@ core:
927 cp--;
928 if (file_printf(ms, ", from '%.*s'",
929 (int)(cp - cname), cname) == -1)
930- return size;
931+ return 1;
932 *flags |= FLAGS_DID_CORE;
933- return size;
934+ return 1;
935
936 tryanother:
937 ;
938@@ -840,6 +809,129 @@ core:
939 break;
940 }
941 #endif
942+ return 0;
943+}
944+
945+private size_t
946+donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
947+ int clazz, int swap, size_t align, int *flags, uint16_t *notecount)
948+{
949+ Elf32_Nhdr nh32;
950+ Elf64_Nhdr nh64;
951+ size_t noff, doff;
952+ uint32_t namesz, descsz;
953+ unsigned char *nbuf = CAST(unsigned char *, vbuf);
954+
955+ if (*notecount == 0)
956+ return 0;
957+ --*notecount;
958+
959+ if (xnh_sizeof + offset > size) {
960+ /*
961+ * We're out of note headers.
962+ */
963+ return xnh_sizeof + offset;
964+ }
965+
966+ (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
967+ offset += xnh_sizeof;
968+
969+ namesz = xnh_namesz;
970+ descsz = xnh_descsz;
971+ if ((namesz == 0) && (descsz == 0)) {
972+ /*
973+ * We're out of note headers.
974+ */
975+ return (offset >= size) ? offset : size;
976+ }
977+
978+ if (namesz & 0x80000000) {
979+ (void)file_printf(ms, ", bad note name size 0x%lx",
980+ (unsigned long)namesz);
981+ return 0;
982+ }
983+
984+ if (descsz & 0x80000000) {
985+ (void)file_printf(ms, ", bad note description size 0x%lx",
986+ (unsigned long)descsz);
987+ return 0;
988+ }
989+
990+ noff = offset;
991+ doff = ELF_ALIGN(offset + namesz);
992+
993+ if (offset + namesz > size) {
994+ /*
995+ * We're past the end of the buffer.
996+ */
997+ return doff;
998+ }
999+
1000+ offset = ELF_ALIGN(doff + descsz);
1001+ if (doff + descsz > size) {
1002+ /*
1003+ * We're past the end of the buffer.
1004+ */
1005+ return (offset >= size) ? offset : size;
1006+ }
1007+
1008+ if ((*flags & FLAGS_DID_OS_NOTE) == 0) {
1009+ if (do_os_note(ms, nbuf, xnh_type, swap,
1010+ namesz, descsz, noff, doff, flags))
1011+ return size;
1012+ }
1013+
1014+ if ((*flags & FLAGS_DID_BUILD_ID) == 0) {
1015+ if (do_bid_note(ms, nbuf, xnh_type, swap,
1016+ namesz, descsz, noff, doff, flags))
1017+ return size;
1018+ }
1019+
1020+ if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) {
1021+ if (do_pax_note(ms, nbuf, xnh_type, swap,
1022+ namesz, descsz, noff, doff, flags))
1023+ return size;
1024+ }
1025+
1026+ if ((*flags & FLAGS_DID_CORE) == 0) {
1027+ if (do_core_note(ms, nbuf, xnh_type, swap,
1028+ namesz, descsz, noff, doff, flags, size, clazz))
1029+ return size;
1030+ }
1031+
1032+ if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) {
1033+ if (descsz > 100)
1034+ descsz = 100;
1035+ switch (xnh_type) {
1036+ case NT_NETBSD_VERSION:
1037+ return size;
1038+ case NT_NETBSD_MARCH:
1039+ if (*flags & FLAGS_DID_NETBSD_MARCH)
1040+ return size;
1041+ *flags |= FLAGS_DID_NETBSD_MARCH;
1042+ if (file_printf(ms, ", compiled for: %.*s",
1043+ (int)descsz, (const char *)&nbuf[doff]) == -1)
1044+ return size;
1045+ break;
1046+ case NT_NETBSD_CMODEL:
1047+ if (*flags & FLAGS_DID_NETBSD_CMODEL)
1048+ return size;
1049+ *flags |= FLAGS_DID_NETBSD_CMODEL;
1050+ if (file_printf(ms, ", compiler model: %.*s",
1051+ (int)descsz, (const char *)&nbuf[doff]) == -1)
1052+ return size;
1053+ break;
1054+ default:
1055+ if (*flags & FLAGS_DID_NETBSD_UNKNOWN)
1056+ return size;
1057+ *flags |= FLAGS_DID_NETBSD_UNKNOWN;
1058+ if (file_printf(ms, ", note=%u", xnh_type) == -1)
1059+ return size;
1060+ break;
1061+ }
1062+ return size;
1063+ }
1064+
1065 return offset;
1066 }
1067
1068@@ -895,16 +987,19 @@ static const cap_desc_t cap_desc_386[] = {
1069
1070 private int
1071 doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1072- size_t size, off_t fsize, int *flags, int mach, int strtab)
1073+ size_t size, off_t fsize, int mach, int strtab, int *flags,
1074+ uint16_t *notecount)
1075 {
1076 Elf32_Shdr sh32;
1077 Elf64_Shdr sh64;
1078 int stripped = 1;
1079+ size_t nbadcap = 0;
1080 void *nbuf;
1081 off_t noff, coff, name_off;
1082 uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */
1083 uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilites */
1084 char name[50];
1085+ ssize_t namesize;
1086
1087 if (size != xsh_sizeof) {
1088 if (file_printf(ms, ", corrupted section header size") == -1)
1089@@ -913,7 +1008,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1090 }
1091
1092 /* Read offset of name section to be able to read section names later */
1093- if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) == -1) {
1094+ if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) < (ssize_t)xsh_sizeof) {
1095 file_badread(ms);
1096 return -1;
1097 }
1098@@ -921,15 +1016,15 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1099
1100 for ( ; num; num--) {
1101 /* Read the name of this section. */
1102- if (pread(fd, name, sizeof(name), name_off + xsh_name) == -1) {
1103+ if ((namesize = pread(fd, name, sizeof(name) - 1, name_off + xsh_name)) == -1) {
1104 file_badread(ms);
1105 return -1;
1106 }
1107- name[sizeof(name) - 1] = '\0';
1108+ name[namesize] = '\0';
1109 if (strcmp(name, ".debug_info") == 0)
1110 stripped = 0;
1111
1112- if (pread(fd, xsh_addr, xsh_sizeof, off) == -1) {
1113+ if (pread(fd, xsh_addr, xsh_sizeof, off) < (ssize_t)xsh_sizeof) {
1114 file_badread(ms);
1115 return -1;
1116 }
1117@@ -944,7 +1039,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1118 stripped = 0;
1119 break;
1120 default:
1121- if (xsh_offset > fsize) {
1122+ if (fsize != SIZE_UNKNOWN && xsh_offset > fsize) {
1123 /* Perhaps warn here */
1124 continue;
1125 }
1126@@ -959,7 +1054,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1127 " for note");
1128 return -1;
1129 }
1130- if (pread(fd, nbuf, xsh_size, xsh_offset) == -1) {
1131+ if (pread(fd, nbuf, xsh_size, xsh_offset) < (ssize_t)xsh_size) {
1132 file_badread(ms);
1133 free(nbuf);
1134 return -1;
1135@@ -970,7 +1065,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1136 if (noff >= (off_t)xsh_size)
1137 break;
1138 noff = donote(ms, nbuf, (size_t)noff,
1139- xsh_size, clazz, swap, 4, flags);
1140+ xsh_size, clazz, swap, 4, flags, notecount);
1141 if (noff == 0)
1142 break;
1143 }
1144@@ -988,6 +1083,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1145 goto skip;
1146 }
1147
1148+ if (nbadcap > 5)
1149+ break;
1150 if (lseek(fd, xsh_offset, SEEK_SET) == (off_t)-1) {
1151 file_badseek(ms);
1152 return -1;
1153@@ -1023,6 +1120,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1154 (unsigned long long)xcap_tag,
1155 (unsigned long long)xcap_val) == -1)
1156 return -1;
1157+ if (nbadcap++ > 2)
1158+ coff = xsh_size;
1159 break;
1160 }
1161 }
1162@@ -1103,7 +1202,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
1163 */
1164 private int
1165 dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
1166- int num, size_t size, off_t fsize, int *flags, int sh_num)
1167+ int num, size_t size, off_t fsize, int sh_num, int *flags,
1168+ uint16_t *notecount)
1169 {
1170 Elf32_Phdr ph32;
1171 Elf64_Phdr ph64;
1172@@ -1120,7 +1220,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
1173 }
1174
1175 for ( ; num; num--) {
1176- if (pread(fd, xph_addr, xph_sizeof, off) == -1) {
1177+ if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) {
1178 file_badread(ms);
1179 return -1;
1180 }
1181@@ -1136,7 +1236,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
1182 shared_libraries = " (uses shared libs)";
1183 break;
1184 default:
1185- if (xph_offset > fsize) {
1186+ if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
1187 /* Maybe warn here? */
1188 continue;
1189 }
1190@@ -1172,7 +1272,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off,
1191 break;
1192 offset = donote(ms, nbuf, offset,
1193 (size_t)bufsize, clazz, swap, align,
1194- flags);
1195+ flags, notecount);
1196 if (offset == 0)
1197 break;
1198 }
1199@@ -1203,7 +1303,7 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
1200 int flags = 0;
1201 Elf32_Ehdr elf32hdr;
1202 Elf64_Ehdr elf64hdr;
1203- uint16_t type;
1204+ uint16_t type, phnum, shnum, notecount;
1205
1206 if (ms->flags & (MAGIC_MIME|MAGIC_APPLE))
1207 return 0;
1208@@ -1229,7 +1329,10 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
1209 file_badread(ms);
1210 return -1;
1211 }
1212- fsize = st.st_size;
1213+ if (S_ISREG(st.st_mode))
1214+ fsize = st.st_size;
1215+ else
1216+ fsize = SIZE_UNKNOWN;
1217
1218 clazz = buf[EI_CLASS];
1219
1220diff --git a/src/softmagic.c b/src/softmagic.c
1221index eaa0f6b..9b11b93 100644
1222--- a/src/softmagic.c
1223+++ b/src/softmagic.c
1224@@ -48,11 +48,11 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.180 2014/03/15 21:47:40 christos Exp $")
1225
1226
1227 private int match(struct magic_set *, struct magic *, uint32_t,
1228- const unsigned char *, size_t, size_t, int, int, int, int, int *, int *,
1229- int *);
1230+ const unsigned char *, size_t, size_t, int, int, int, uint16_t,
1231+ uint16_t *, int *, int *, int *);
1232 private int mget(struct magic_set *, const unsigned char *,
1233- struct magic *, size_t, size_t, unsigned int, int, int, int, int, int *,
1234- int *, int *);
1235+ struct magic *, size_t, size_t, unsigned int, int, int, int, uint16_t,
1236+ uint16_t *, int *, int *, int *);
1237 private int magiccheck(struct magic_set *, struct magic *);
1238 private int32_t mprint(struct magic_set *, struct magic *);
1239 private int32_t moffset(struct magic_set *, struct magic *);
1240@@ -68,6 +68,7 @@ private void cvt_32(union VALUETYPE *, const struct magic *);
1241 private void cvt_64(union VALUETYPE *, const struct magic *);
1242
1243 #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o)))
1244+
1245 /*
1246 * softmagic - lookup one file in parsed, in-memory copy of database
1247 * Passed the name and FILE * of one file to be typed.
1248@@ -75,14 +76,20 @@ private void cvt_64(union VALUETYPE *, const struct magic *);
1249 /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */
1250 protected int
1251 file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
1252- size_t level, int mode, int text)
1253+ uint16_t indir_level, uint16_t *name_count, int mode, int text)
1254 {
1255 struct mlist *ml;
1256 int rv, printed_something = 0, need_separator = 0;
1257+ uint16_t nc;
1258+
1259+ if (name_count == NULL) {
1260+ nc = 0;
1261+ name_count = &nc;
1262+ }
1263 for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next)
1264 if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode,
1265- text, 0, level, &printed_something, &need_separator,
1266- NULL)) != 0)
1267+ text, 0, indir_level, name_count,
1268+ &printed_something, &need_separator, NULL)) != 0)
1269 return rv;
1270
1271 return 0;
1272@@ -118,8 +125,8 @@ file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
1273 private int
1274 match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
1275 const unsigned char *s, size_t nbytes, size_t offset, int mode, int text,
1276- int flip, int recursion_level, int *printed_something, int *need_separator,
1277- int *returnval)
1278+ int flip, uint16_t indir_level, uint16_t *name_count,
1279+ int *printed_something, int *need_separator, int *returnval)
1280 {
1281 uint32_t magindex = 0;
1282 unsigned int cont_level = 0;
1283@@ -156,8 +163,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
1284
1285 /* if main entry matches, print it... */
1286 switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text,
1287- flip, recursion_level + 1, printed_something,
1288- need_separator, returnval)) {
1289+ flip, indir_level, name_count,
1290+ printed_something, need_separator, returnval)) {
1291 case -1:
1292 return -1;
1293 case 0:
1294@@ -245,8 +252,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
1295 }
1296 #endif
1297 switch (mget(ms, s, m, nbytes, offset, cont_level, mode,
1298- text, flip, recursion_level + 1, printed_something,
1299- need_separator, returnval)) {
1300+ text, flip, indir_level, name_count,
1301+ printed_something, need_separator, returnval)) {
1302 case -1:
1303 return -1;
1304 case 0:
1305@@ -1155,18 +1162,26 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir,
1306 private int
1307 mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
1308 size_t nbytes, size_t o, unsigned int cont_level, int mode, int text,
1309- int flip, int recursion_level, int *printed_something,
1310- int *need_separator, int *returnval)
1311+ int flip, uint16_t indir_level, uint16_t *name_count,
1312+ int *printed_something, int *need_separator, int *returnval)
1313 {
1314- uint32_t soffset, offset = ms->offset;
1315+ uint32_t offset = ms->offset;
1316 uint32_t count = m->str_range;
1317+ file_pushbuf_t *pb;
1318 int rv, oneed_separator, in_type;
1319- char *sbuf, *rbuf;
1320+ char *rbuf;
1321 union VALUETYPE *p = &ms->ms_value;
1322 struct mlist ml;
1323
1324- if (recursion_level >= 20) {
1325- file_error(ms, 0, "recursion nesting exceeded");
1326+ if (indir_level >= ms->indir_max) {
1327+ file_error(ms, 0, "indirect recursion nesting (%hu) exceeded",
1328+ indir_level);
1329+ return -1;
1330+ }
1331+
1332+ if (*name_count >= ms->name_max) {
1333+ file_error(ms, 0, "name use count (%hu) exceeded",
1334+ *name_count);
1335 return -1;
1336 }
1337
1338@@ -1678,6 +1693,10 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
1339 ms->offset = offset;
1340
1341 if ((ms->flags & MAGIC_DEBUG) != 0) {
1342+ fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%zu, "
1343+ "nbytes=%zu, il=%hu, nc=%hu)\n",
1344+ m->type, m->flag, offset, o, nbytes,
1345+ indir_level, *name_count);
1346 mdebug(offset, (char *)(void *)p,
1347 sizeof(union VALUETYPE));
1348 #ifndef COMPILE_ONLY
1349@@ -1741,19 +1760,23 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
1350 case FILE_INDIRECT:
1351 if (offset == 0)
1352 return 0;
1353+
1354 if (nbytes < offset)
1355 return 0;
1356- sbuf = ms->o.buf;
1357- soffset = ms->offset;
1358- ms->o.buf = NULL;
1359- ms->offset = 0;
1360+
1361+ if ((pb = file_push_buffer(ms)) == NULL)
1362+ return -1;
1363+
1364 rv = file_softmagic(ms, s + offset, nbytes - offset,
1365- recursion_level, BINTEST, text);
1366+ indir_level + 1, name_count, BINTEST, text);
1367+
1368 if ((ms->flags & MAGIC_DEBUG) != 0)
1369 fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
1370- rbuf = ms->o.buf;
1371- ms->o.buf = sbuf;
1372- ms->offset = soffset;
1373+
1374+ rbuf = file_pop_buffer(ms, pb);
1375+ if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR)
1376+ return -1;
1377+
1378 if (rv == 1) {
1379 if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
1380 file_printf(ms, F(m->desc, "%u"), offset) == -1) {
1381@@ -1771,22 +1794,22 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
1382 case FILE_USE:
1383 if (nbytes < offset)
1384 return 0;
1385- sbuf = m->value.s;
1386- if (*sbuf == '^') {
1387- sbuf++;
1388+ rbuf = m->value.s;
1389+ if (*rbuf == '^') {
1390+ rbuf++;
1391 flip = !flip;
1392 }
1393- if (file_magicfind(ms, sbuf, &ml) == -1) {
1394- file_error(ms, 0, "cannot find entry `%s'", sbuf);
1395+ if (file_magicfind(ms, rbuf, &ml) == -1) {
1396+ file_error(ms, 0, "cannot find entry `%s'", rbuf);
1397 return -1;
1398 }
1399-
1400+ (*name_count)++;
1401 oneed_separator = *need_separator;
1402 if (m->flag & NOSPACE)
1403 *need_separator = 0;
1404 rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o,
1405- mode, text, flip, recursion_level, printed_something,
1406- need_separator, returnval);
1407+ mode, text, flip, indir_level, name_count,
1408+ printed_something, need_separator, returnval);
1409 if (rv != 1)
1410 *need_separator = oneed_separator;
1411 return rv;
1412--
14131.9.1
1414