From 46e8377c42030eb04972940cd022a8d214d477c7 Mon Sep 17 00:00:00 2001 From: Chong Lu Date: Thu, 22 Jan 2015 17:28:34 +0800 Subject: file: CVE-2014-9620 and CVE-2014-9621 CVE-2014-9620: Limit the number of ELF notes processed - DoS CVE-2014-9621: Limit string printing to 100 chars - DoS The patch comes from: https://github.com/file/file/commit/6ce24f35cd4a43c4bdd249e8e0c4952c1f8eac67 https://github.com/file/file/commit/0056ec32255de1de973574b0300161a1568767d6 https://github.com/file/file/commit/09e41625c999a2e5b51e1092f0ef2432a99b5c33 https://github.com/file/file/commit/af444af0738468393f40f9d2261b1ea10fc4b2ba https://github.com/file/file/commit/68bd8433c7e11a8dbe100deefdfac69138ee7cd9 https://github.com/file/file/commit/dddd3cdb95210a765dd90f7d722cb8b5534daee7 https://github.com/file/file/commit/445c8fb0ebff85195be94cd9f7e1df89cade5c7f https://github.com/file/file/commit/ce90e05774dd77d86cfc8dfa6da57b32816841c4 https://github.com/file/file/commit/65437cee25199dbd385fb35901bc0011e164276c [YOCTO #7178] (From OE-Core rev: ee78555fe54e98c6296566b5e701ef268d77db61) Signed-off-by: Chong Lu [sgw - Fixed magic.h.in to match magic.h] Signed-off-by: Saul Wold Signed-off-by: Richard Purdie --- .../file-CVE-2014-9620-and-CVE-2014-9621.patch | 1359 ++++++++++++++++++++ meta/recipes-devtools/file/file_5.16.bb | 1 + 2 files changed, 1360 insertions(+) create mode 100644 meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch 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..af02b995b7 --- /dev/null +++ b/meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch @@ -0,0 +1,1359 @@ +file: CVE-2014-9620 and CVE-2014-9621 + +The patch comes from: +https://github.com/file/file/commit/6ce24f35cd4a43c4bdd249e8e0c4952c1f8eac67 +https://github.com/file/file/commit/0056ec32255de1de973574b0300161a1568767d6 +https://github.com/file/file/commit/09e41625c999a2e5b51e1092f0ef2432a99b5c33 +https://github.com/file/file/commit/af444af0738468393f40f9d2261b1ea10fc4b2ba +https://github.com/file/file/commit/68bd8433c7e11a8dbe100deefdfac69138ee7cd9 +https://github.com/file/file/commit/dddd3cdb95210a765dd90f7d722cb8b5534daee7 +https://github.com/file/file/commit/445c8fb0ebff85195be94cd9f7e1df89cade5c7f +https://github.com/file/file/commit/ce90e05774dd77d86cfc8dfa6da57b32816841c4 +https://github.com/file/file/commit/65437cee25199dbd385fb35901bc0011e164276c + +Upstream-Status: Backport + +Signed-off-by: Chong Lu +--- + src/apprentice.c | 5 + + src/ascmagic.c | 3 +- + src/elfclass.h | 34 ++-- + src/file.c | 58 ++++++- + src/file.h | 20 ++- + src/file_opts.h | 6 + + src/funcs.c | 42 ++++- + src/magic.c | 50 ++++++ + src/magic.h | 9 ++ + src/magic.h.in | 4 + + src/readelf.c | 467 +++++++++++++++++++++++++++++++++--------------------- + src/softmagic.c | 70 ++++---- + 12 files changed, 541 insertions(+), 227 deletions(-) + +Index: file-5.16/src/apprentice.c +=================================================================== +--- file-5.16.orig/src/apprentice.c ++++ file-5.16/src/apprentice.c +@@ -494,6 +494,11 @@ file_ms_alloc(int flags) + ms->mlist[i] = NULL; + ms->file = "unknown"; + ms->line = 0; ++ ms->indir_max = FILE_INDIR_MAX; ++ ms->name_max = FILE_NAME_MAX; ++ ms->elf_shnum_max = FILE_ELF_SHNUM_MAX; ++ ms->elf_phnum_max = FILE_ELF_PHNUM_MAX; ++ ms->elf_notes_max = FILE_ELF_NOTES_MAX; + return ms; + free: + free(ms); +Index: file-5.16/src/ascmagic.c +=================================================================== +--- file-5.16.orig/src/ascmagic.c ++++ file-5.16/src/ascmagic.c +@@ -147,7 +147,8 @@ file_ascmagic_with_encoding(struct magic + == NULL) + goto done; + if ((rv = file_softmagic(ms, utf8_buf, +- (size_t)(utf8_end - utf8_buf), TEXTTEST, text)) == 0) ++ (size_t)(utf8_end - utf8_buf), 0, NULL, ++ TEXTTEST, text)) == 0) + rv = -1; + } + +Index: file-5.16/src/elfclass.h +=================================================================== +--- file-5.16.orig/src/elfclass.h ++++ file-5.16/src/elfclass.h +@@ -32,39 +32,51 @@ + swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA]; + + type = elf_getu16(swap, elfhdr.e_type); ++ notecount = ms->elf_notes_max; + switch (type) { + #ifdef ELFCORE + case ET_CORE: ++ phnum = elf_getu16(swap, elfhdr.e_phnum); ++ if (phnum > ms->elf_phnum_max) ++ return toomany(ms, "program headers", phnum); + flags |= FLAGS_IS_CORE; + if (dophn_core(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_phoff), +- elf_getu16(swap, elfhdr.e_phnum), ++ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, + (size_t)elf_getu16(swap, elfhdr.e_phentsize), +- fsize, &flags) == -1) ++ fsize, &flags, ¬ecount) == -1) + return -1; + break; + #endif + case ET_EXEC: + case ET_DYN: ++ phnum = elf_getu16(swap, elfhdr.e_phnum); ++ if (phnum > ms->elf_phnum_max) ++ return toomany(ms, "program", phnum); ++ shnum = elf_getu16(swap, elfhdr.e_shnum); ++ if (shnum > ms->elf_shnum_max) ++ return toomany(ms, "section", shnum); + if (dophn_exec(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_phoff), +- elf_getu16(swap, elfhdr.e_phnum), ++ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, + (size_t)elf_getu16(swap, elfhdr.e_phentsize), +- fsize, &flags, elf_getu16(swap, elfhdr.e_shnum)) +- == -1) ++ fsize, shnum, &flags, ¬ecount) == -1) + return -1; + /*FALLTHROUGH*/ + case ET_REL: ++ shnum = elf_getu16(swap, elfhdr.e_shnum); ++ if (shnum > ms->elf_shnum_max) ++ return toomany(ms, "section headers", shnum); + if (doshn(ms, clazz, swap, fd, +- (off_t)elf_getu(swap, elfhdr.e_shoff), +- elf_getu16(swap, elfhdr.e_shnum), ++ (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, + (size_t)elf_getu16(swap, elfhdr.e_shentsize), +- fsize, &flags, elf_getu16(swap, elfhdr.e_machine), +- (int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1) ++ fsize, elf_getu16(swap, elfhdr.e_machine), ++ (int)elf_getu16(swap, elfhdr.e_shstrndx), ++ &flags, ¬ecount) == -1) + return -1; + break; + + default: + break; + } ++ if (notecount == 0) ++ return toomany(ms, "notes", ms->elf_notes_max); + return 1; +Index: file-5.16/src/file.c +=================================================================== +--- file-5.16.orig/src/file.c ++++ file-5.16/src/file.c +@@ -101,7 +101,7 @@ private const struct option long_options + #undef OPT_LONGONLY + {0, 0, NULL, 0} + }; +-#define OPTSTRING "bcCde:f:F:hiklLm:nNprsvz0" ++#define OPTSTRING "bcCde:f:F:hiklLm:nNpP:rsvz0" + + private const struct { + const char *name; +@@ -119,6 +119,18 @@ private const struct { + { "tokens", MAGIC_NO_CHECK_TOKENS }, /* OBSOLETE: ignored for backwards compatibility */ + }; + ++private struct { ++ const char *name; ++ int tag; ++ size_t value; ++} pm[] = { ++ { "indir", MAGIC_PARAM_INDIR_MAX, 0 }, ++ { "name", MAGIC_PARAM_NAME_MAX, 0 }, ++ { "elf_phnum", MAGIC_PARAM_ELF_PHNUM_MAX, 0 }, ++ { "elf_shnum", MAGIC_PARAM_ELF_SHNUM_MAX, 0 }, ++ { "elf_notes", MAGIC_PARAM_ELF_NOTES_MAX, 0 }, ++}; ++ + private char *progname; /* used throughout */ + + private void usage(void); +@@ -128,6 +140,8 @@ private void help(void); + private int unwrap(struct magic_set *, const char *); + private int process(struct magic_set *ms, const char *, int); + private struct magic_set *load(const char *, int); ++private void setparam(const char *); ++private void applyparam(magic_t); + + + /* +@@ -240,6 +254,9 @@ main(int argc, char *argv[]) + flags |= MAGIC_PRESERVE_ATIME; + break; + #endif ++ case 'P': ++ setparam(optarg); ++ break; + case 'r': + flags |= MAGIC_RAW; + break; +@@ -295,6 +312,8 @@ main(int argc, char *argv[]) + strerror(errno)); + return 1; + } ++ ++ + switch(action) { + case FILE_CHECK: + c = magic_check(magic, magicfile); +@@ -318,7 +337,7 @@ main(int argc, char *argv[]) + if (magic == NULL) + if ((magic = load(magicfile, flags)) == NULL) + return 1; +- break; ++ applyparam(magic); + } + + if (optind == argc) { +@@ -348,6 +367,41 @@ main(int argc, char *argv[]) + return e; + } + ++private void ++applyparam(magic_t magic) ++{ ++ size_t i; ++ ++ for (i = 0; i < __arraycount(pm); i++) { ++ if (pm[i].value == 0) ++ continue; ++ if (magic_setparam(magic, pm[i].tag, &pm[i].value) == -1) { ++ (void)fprintf(stderr, "%s: Can't set %s %s\n", progname, ++ pm[i].name, strerror(errno)); ++ exit(1); ++ } ++ } ++} ++ ++private void ++setparam(const char *p) ++{ ++ size_t i; ++ char *s; ++ ++ if ((s = strchr(p, '=')) == NULL) ++ goto badparm; ++ ++ for (i = 0; i < __arraycount(pm); i++) { ++ if (strncmp(p, pm[i].name, s - p) != 0) ++ continue; ++ pm[i].value = atoi(s + 1); ++ return; ++ } ++badparm: ++ (void)fprintf(stderr, "%s: Unknown param %s\n", progname, p); ++ exit(1); ++} + + private struct magic_set * + /*ARGSUSED*/ +Index: file-5.16/src/file.h +=================================================================== +--- file-5.16.orig/src/file.h ++++ file-5.16/src/file.h +@@ -400,6 +400,16 @@ struct magic_set { + /* FIXME: Make the string dynamically allocated so that e.g. + strings matched in files can be longer than MAXstring */ + union VALUETYPE ms_value; /* either number or string */ ++ uint16_t indir_max; ++ uint16_t name_max; ++ uint16_t elf_shnum_max; ++ uint16_t elf_phnum_max; ++ uint16_t elf_notes_max; ++#define FILE_INDIR_MAX 15 ++#define FILE_NAME_MAX 30 ++#define FILE_ELF_SHNUM_MAX 32768 ++#define FILE_ELF_PHNUM_MAX 128 ++#define FILE_ELF_NOTES_MAX 256 + }; + + /* Type for Unicode characters */ +@@ -438,7 +448,7 @@ protected int file_encoding(struct magic + unichar **, size_t *, const char **, const char **, const char **); + protected int file_is_tar(struct magic_set *, const unsigned char *, size_t); + protected int file_softmagic(struct magic_set *, const unsigned char *, size_t, +- int, int); ++ uint16_t, uint16_t *, int, int); + protected int file_apprentice(struct magic_set *, const char *, int); + protected int file_magicfind(struct magic_set *, const char *, struct mlist *); + protected uint64_t file_signextend(struct magic_set *, struct magic *, +@@ -468,6 +478,14 @@ protected int file_os2_apptype(struct ma + #endif /* __EMX__ */ + + ++typedef struct { ++ char *buf; ++ uint32_t offset; ++} file_pushbuf_t; ++ ++protected file_pushbuf_t *file_push_buffer(struct magic_set *); ++protected char *file_pop_buffer(struct magic_set *, file_pushbuf_t *); ++ + #ifndef COMPILE_ONLY + extern const char *file_names[]; + extern const size_t file_nnames; +Index: file-5.16/src/file_opts.h +=================================================================== +--- file-5.16.orig/src/file_opts.h ++++ file-5.16/src/file_opts.h +@@ -43,6 +43,12 @@ OPT('0', "print0", 0, " te + #if defined(HAVE_UTIME) || defined(HAVE_UTIMES) + OPT('p', "preserve-date", 0, " preserve access times on files\n") + #endif ++OPT('P', "parameter", 0, " set file engine parameter limits\n" ++ " indir 15 recursion limit for indirection\n" ++ " name 30 use limit for name/use magic\n" ++ " elf_notes 256 max ELF notes processed\n" ++ " elf_phnum 128 max ELF prog sections processed\n" ++ " elf_shnum 32768 max ELF sections processed\n") + OPT('r', "raw", 0, " don't translate unprintable chars to \\ooo\n") + OPT('s', "special-files", 0, " treat special (block/char devices) files as\n" + " ordinary ones\n") +Index: file-5.16/src/funcs.c +=================================================================== +--- file-5.16.orig/src/funcs.c ++++ file-5.16/src/funcs.c +@@ -226,7 +226,7 @@ file_buffer(struct magic_set *ms, int fd + + /* try soft magic tests */ + if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) +- if ((m = file_softmagic(ms, ubuf, nb, BINTEST, ++ if ((m = file_softmagic(ms, ubuf, nb, 0, NULL, BINTEST, + looks_text)) != 0) { + if ((ms->flags & MAGIC_DEBUG) != 0) + (void)fprintf(stderr, "softmagic %d\n", m); +@@ -459,3 +459,43 @@ file_replace(struct magic_set *ms, const + return nm; + } + } ++ ++protected file_pushbuf_t * ++file_push_buffer(struct magic_set *ms) ++{ ++ file_pushbuf_t *pb; ++ ++ if (ms->event_flags & EVENT_HAD_ERR) ++ return NULL; ++ ++ if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL) ++ return NULL; ++ ++ pb->buf = ms->o.buf; ++ pb->offset = ms->offset; ++ ++ ms->o.buf = NULL; ++ ms->offset = 0; ++ ++ return pb; ++} ++ ++protected char * ++file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb) ++{ ++ char *rbuf; ++ ++ if (ms->event_flags & EVENT_HAD_ERR) { ++ free(pb->buf); ++ free(pb); ++ return NULL; ++ } ++ ++ rbuf = ms->o.buf; ++ ++ ms->o.buf = pb->buf; ++ ms->offset = pb->offset; ++ ++ free(pb); ++ return rbuf; ++} +Index: file-5.16/src/magic.c +=================================================================== +--- file-5.16.orig/src/magic.c ++++ file-5.16/src/magic.c +@@ -490,3 +490,53 @@ magic_version(void) + { + return MAGIC_VERSION; + } ++ ++public int ++magic_setparam(struct magic_set *ms, int param, const void *val) ++{ ++ switch (param) { ++ case MAGIC_PARAM_INDIR_MAX: ++ ms->indir_max = *(const size_t *)val; ++ return 0; ++ case MAGIC_PARAM_NAME_MAX: ++ ms->name_max = *(const size_t *)val; ++ return 0; ++ case MAGIC_PARAM_ELF_PHNUM_MAX: ++ ms->elf_phnum_max = *(const size_t *)val; ++ return 0; ++ case MAGIC_PARAM_ELF_SHNUM_MAX: ++ ms->elf_shnum_max = *(const size_t *)val; ++ return 0; ++ case MAGIC_PARAM_ELF_NOTES_MAX: ++ ms->elf_notes_max = *(const size_t *)val; ++ return 0; ++ default: ++ errno = EINVAL; ++ return -1; ++ } ++} ++ ++public int ++magic_getparam(struct magic_set *ms, int param, void *val) ++{ ++ switch (param) { ++ case MAGIC_PARAM_INDIR_MAX: ++ *(size_t *)val = ms->indir_max; ++ return 0; ++ case MAGIC_PARAM_NAME_MAX: ++ *(size_t *)val = ms->name_max; ++ return 0; ++ case MAGIC_PARAM_ELF_PHNUM_MAX: ++ *(size_t *)val = ms->elf_phnum_max; ++ return 0; ++ case MAGIC_PARAM_ELF_SHNUM_MAX: ++ *(size_t *)val = ms->elf_shnum_max; ++ return 0; ++ case MAGIC_PARAM_ELF_NOTES_MAX: ++ *(size_t *)val = ms->elf_notes_max; ++ return 0; ++ default: ++ errno = EINVAL; ++ return -1; ++ } ++} +Index: file-5.16/src/magic.h +=================================================================== +--- file-5.16.orig/src/magic.h ++++ file-5.16/src/magic.h +@@ -101,6 +101,15 @@ int magic_check(magic_t, const char *); + int magic_list(magic_t, const char *); + int magic_errno(magic_t); + ++#define MAGIC_PARAM_INDIR_MAX 0 ++#define MAGIC_PARAM_NAME_MAX 1 ++#define MAGIC_PARAM_ELF_PHNUM_MAX 2 ++#define MAGIC_PARAM_ELF_SHNUM_MAX 3 ++#define MAGIC_PARAM_ELF_NOTES_MAX 4 ++ ++int magic_setparam(magic_t, int, const void *); ++int magic_getparam(magic_t, int, void *); ++ + #ifdef __cplusplus + }; + #endif +Index: file-5.16/src/magic.h.in +=================================================================== +--- file-5.16.orig/src/magic.h.in ++++ file-5.16/src/magic.h.in +@@ -101,6 +101,15 @@ int magic_check(magic_t, const char *); + int magic_list(magic_t, const char *); + int magic_errno(magic_t); + ++#define MAGIC_PARAM_INDIR_MAX 0 ++#define MAGIC_PARAM_NAME_MAX 1 ++#define MAGIC_PARAM_ELF_PHNUM_MAX 2 ++#define MAGIC_PARAM_ELF_SHNUM_MAX 3 ++#define MAGIC_PARAM_ELF_NOTES_MAX 4 ++ ++int magic_setparam(magic_t, int, const void *); ++int magic_getparam(magic_t, int, void *); ++ + #ifdef __cplusplus + }; + #endif +Index: file-5.16/src/readelf.c +=================================================================== +--- file-5.16.orig/src/readelf.c ++++ file-5.16/src/readelf.c +@@ -43,14 +43,14 @@ FILE_RCSID("@(#)$File: readelf.c,v 1.99 + + #ifdef ELFCORE + private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t, +- off_t, int *); ++ off_t, int *, uint16_t *); + #endif + private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t, +- off_t, int *, int); ++ off_t, int, int *, uint16_t *); + private int doshn(struct magic_set *, int, int, int, off_t, int, size_t, +- off_t, int *, int, int); ++ off_t, int, int, int *, uint16_t *); + private size_t donote(struct magic_set *, void *, size_t, size_t, int, +- int, size_t, int *); ++ int, size_t, int *, uint16_t *); + + #define ELF_ALIGN(a) ((((a) + align - 1) / align) * align) + +@@ -60,6 +60,19 @@ private uint16_t getu16(int, uint16_t); + private uint32_t getu32(int, uint32_t); + private uint64_t getu64(int, uint64_t); + ++#define MAX_PHNUM 128 ++#define MAX_SHNUM 32768 ++#define SIZE_UNKNOWN ((off_t)-1) ++ ++private int ++toomany(struct magic_set *ms, const char *name, uint16_t num) ++{ ++ if (file_printf(ms, ", too many %s (%u)", name, num ++ ) == -1) ++ return -1; ++ return 0; ++} ++ + private uint16_t + getu16(int swap, uint16_t value) + { +@@ -280,15 +293,19 @@ private const char os_style_names[][8] = + "NetBSD", + }; + +-#define FLAGS_DID_CORE 0x01 +-#define FLAGS_DID_NOTE 0x02 +-#define FLAGS_DID_BUILD_ID 0x04 +-#define FLAGS_DID_CORE_STYLE 0x08 +-#define FLAGS_IS_CORE 0x10 ++#define FLAGS_DID_CORE 0x001 ++#define FLAGS_DID_OS_NOTE 0x002 ++#define FLAGS_DID_BUILD_ID 0x004 ++#define FLAGS_DID_CORE_STYLE 0x008 ++#define FLAGS_DID_NETBSD_PAX 0x010 ++#define FLAGS_DID_NETBSD_MARCH 0x020 ++#define FLAGS_DID_NETBSD_CMODEL 0x040 ++#define FLAGS_DID_NETBSD_UNKNOWN 0x080 ++#define FLAGS_IS_CORE 0x100 + + private int + dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, +- int num, size_t size, off_t fsize, int *flags) ++ int num, size_t size, off_t fsize, int *flags, uint16_t *notecount) + { + Elf32_Phdr ph32; + Elf64_Phdr ph64; +@@ -306,13 +323,13 @@ dophn_core(struct magic_set *ms, int cla + * Loop through all the program headers. + */ + for ( ; num; num--) { +- if (pread(fd, xph_addr, xph_sizeof, off) == -1) { ++ if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { + file_badread(ms); + return -1; + } + off += size; + +- if (xph_offset > fsize) { ++ if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { + /* Perhaps warn here */ + continue; + } +@@ -334,7 +351,7 @@ dophn_core(struct magic_set *ms, int cla + if (offset >= (size_t)bufsize) + break; + offset = donote(ms, nbuf, offset, (size_t)bufsize, +- clazz, swap, 4, flags); ++ clazz, swap, 4, flags, notecount); + if (offset == 0) + break; + +@@ -464,125 +481,127 @@ do_note_freebsd_version(struct magic_set + } + } + +-private size_t +-donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, +- int clazz, int swap, size_t align, int *flags) ++private int ++do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, ++ int swap __attribute__((__unused__)), uint32_t namesz, uint32_t descsz, ++ size_t noff, size_t doff, int *flags) + { +- Elf32_Nhdr nh32; +- Elf64_Nhdr nh64; +- size_t noff, doff; +-#ifdef ELFCORE +- int os_style = -1; +-#endif +- uint32_t namesz, descsz; +- unsigned char *nbuf = CAST(unsigned char *, vbuf); +- +- (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); +- offset += xnh_sizeof; +- +- namesz = xnh_namesz; +- descsz = xnh_descsz; +- if ((namesz == 0) && (descsz == 0)) { +- /* +- * We're out of note headers. +- */ +- return (offset >= size) ? offset : size; +- } +- +- if (namesz & 0x80000000) { +- (void)file_printf(ms, ", bad note name size 0x%lx", +- (unsigned long)namesz); +- return offset; +- } +- +- if (descsz & 0x80000000) { +- (void)file_printf(ms, ", bad note description size 0x%lx", +- (unsigned long)descsz); +- return offset; +- } +- +- +- noff = offset; +- doff = ELF_ALIGN(offset + namesz); +- +- if (offset + namesz > size) { +- /* +- * We're past the end of the buffer. +- */ +- return doff; +- } +- +- offset = ELF_ALIGN(doff + descsz); +- if (doff + descsz > size) { +- /* +- * We're past the end of the buffer. +- */ +- return (offset >= size) ? offset : size; ++ if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && ++ type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) { ++ uint8_t desc[20]; ++ uint32_t i; ++ *flags |= FLAGS_DID_BUILD_ID; ++ if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" : ++ "sha1") == -1) ++ return 1; ++ (void)memcpy(desc, &nbuf[doff], descsz); ++ for (i = 0; i < descsz; i++) ++ if (file_printf(ms, "%02x", desc[i]) == -1) ++ return 1; ++ return 1; + } +- +- if ((*flags & (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID)) == +- (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID)) +- goto core; +- ++ return 0; ++} ++ ++private int ++do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, ++ int swap, uint32_t namesz, uint32_t descsz, ++ size_t noff, size_t doff, int *flags) ++{ + if (namesz == 5 && strcmp((char *)&nbuf[noff], "SuSE") == 0 && +- xnh_type == NT_GNU_VERSION && descsz == 2) { ++ type == NT_GNU_VERSION && descsz == 2) { ++ *flags |= FLAGS_DID_OS_NOTE; + file_printf(ms, ", for SuSE %d.%d", nbuf[doff], nbuf[doff + 1]); ++ return 1; + } ++ + if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && +- xnh_type == NT_GNU_VERSION && descsz == 16) { ++ type == NT_GNU_VERSION && descsz == 16) { + uint32_t desc[4]; + (void)memcpy(desc, &nbuf[doff], sizeof(desc)); + ++ *flags |= FLAGS_DID_OS_NOTE; + if (file_printf(ms, ", for GNU/") == -1) +- return size; ++ return 1; + switch (elf_getu32(swap, desc[0])) { + case GNU_OS_LINUX: + if (file_printf(ms, "Linux") == -1) +- return size; ++ return 1; + break; + case GNU_OS_HURD: + if (file_printf(ms, "Hurd") == -1) +- return size; ++ return 1; + break; + case GNU_OS_SOLARIS: + if (file_printf(ms, "Solaris") == -1) +- return size; ++ return 1; + break; + case GNU_OS_KFREEBSD: + if (file_printf(ms, "kFreeBSD") == -1) +- return size; ++ return 1; + break; + case GNU_OS_KNETBSD: + if (file_printf(ms, "kNetBSD") == -1) +- return size; ++ return 1; + break; + default: + if (file_printf(ms, "") == -1) +- return size; ++ return 1; + } + if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]), + elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1) +- return size; +- *flags |= FLAGS_DID_NOTE; +- return size; ++ return 1; ++ return 1; + } + +- if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && +- xnh_type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) { +- uint8_t desc[20]; +- uint32_t i; +- if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" : +- "sha1") == -1) +- return size; +- (void)memcpy(desc, &nbuf[doff], descsz); +- for (i = 0; i < descsz; i++) +- if (file_printf(ms, "%02x", desc[i]) == -1) +- return size; +- *flags |= FLAGS_DID_BUILD_ID; ++ if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { ++ if (type == NT_NETBSD_VERSION && descsz == 4) { ++ *flags |= FLAGS_DID_OS_NOTE; ++ do_note_netbsd_version(ms, swap, &nbuf[doff]); ++ return 1; ++ } ++ } ++ ++ if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { ++ if (type == NT_FREEBSD_VERSION && descsz == 4) { ++ *flags |= FLAGS_DID_OS_NOTE; ++ do_note_freebsd_version(ms, swap, &nbuf[doff]); ++ return 1; ++ } ++ } ++ ++ if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && ++ type == NT_OPENBSD_VERSION && descsz == 4) { ++ *flags |= FLAGS_DID_OS_NOTE; ++ if (file_printf(ms, ", for OpenBSD") == -1) ++ return 1; ++ /* Content of note is always 0 */ ++ return 1; ++ } ++ ++ if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 && ++ type == NT_DRAGONFLY_VERSION && descsz == 4) { ++ uint32_t desc; ++ *flags |= FLAGS_DID_OS_NOTE; ++ if (file_printf(ms, ", for DragonFly") == -1) ++ return 1; ++ (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); ++ desc = elf_getu32(swap, desc); ++ if (file_printf(ms, " %d.%d.%d", desc / 100000, ++ desc / 10000 % 10, desc % 10000) == -1) ++ return 1; ++ return 1; + } ++ return 0; ++} + ++private int ++do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, ++ int swap, uint32_t namesz, uint32_t descsz, ++ size_t noff, size_t doff, int *flags) ++{ + if (namesz == 4 && strcmp((char *)&nbuf[noff], "PaX") == 0 && +- xnh_type == NT_NETBSD_PAX && descsz == 4) { ++ type == NT_NETBSD_PAX && descsz == 4) { + static const char *pax[] = { + "+mprotect", + "-mprotect", +@@ -595,80 +614,32 @@ donote(struct magic_set *ms, void *vbuf, + size_t i; + int did = 0; + ++ *flags |= FLAGS_DID_NETBSD_PAX; + (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); + desc = elf_getu32(swap, desc); + + if (desc && file_printf(ms, ", PaX: ") == -1) +- return size; ++ return 1; + + for (i = 0; i < __arraycount(pax); i++) { + if (((1 << i) & desc) == 0) + continue; + if (file_printf(ms, "%s%s", did++ ? "," : "", + pax[i]) == -1) +- return size; +- } +- } +- +- if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { +- switch (xnh_type) { +- case NT_NETBSD_VERSION: +- if (descsz == 4) { +- do_note_netbsd_version(ms, swap, &nbuf[doff]); +- *flags |= FLAGS_DID_NOTE; +- return size; +- } +- break; +- case NT_NETBSD_MARCH: +- if (file_printf(ms, ", compiled for: %.*s", (int)descsz, +- (const char *)&nbuf[doff]) == -1) +- return size; +- break; +- case NT_NETBSD_CMODEL: +- if (file_printf(ms, ", compiler model: %.*s", +- (int)descsz, (const char *)&nbuf[doff]) == -1) +- return size; +- break; +- default: +- if (file_printf(ms, ", note=%u", xnh_type) == -1) +- return size; +- break; +- } +- return size; +- } +- +- if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { +- if (xnh_type == NT_FREEBSD_VERSION && descsz == 4) { +- do_note_freebsd_version(ms, swap, &nbuf[doff]); +- *flags |= FLAGS_DID_NOTE; +- return size; ++ return 1; + } ++ return 1; + } ++ return 0; ++} + +- if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && +- xnh_type == NT_OPENBSD_VERSION && descsz == 4) { +- if (file_printf(ms, ", for OpenBSD") == -1) +- return size; +- /* Content of note is always 0 */ +- *flags |= FLAGS_DID_NOTE; +- return size; +- } +- +- if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 && +- xnh_type == NT_DRAGONFLY_VERSION && descsz == 4) { +- uint32_t desc; +- if (file_printf(ms, ", for DragonFly") == -1) +- return size; +- (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); +- desc = elf_getu32(swap, desc); +- if (file_printf(ms, " %d.%d.%d", desc / 100000, +- desc / 10000 % 10, desc % 10000) == -1) +- return size; +- *flags |= FLAGS_DID_NOTE; +- return size; +- } +- +-core: ++private int ++do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, ++ int swap, uint32_t namesz, uint32_t descsz, ++ size_t noff, size_t doff, int *flags, size_t size, int clazz) ++{ ++#ifdef ELFCORE ++ int os_style = -1; + /* + * Sigh. The 2.0.36 kernel in Debian 2.1, at + * least, doesn't correctly implement name +@@ -697,20 +668,17 @@ core: + os_style = OS_STYLE_NETBSD; + } + +-#ifdef ELFCORE +- if ((*flags & FLAGS_DID_CORE) != 0) +- return size; +- + if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) { + if (file_printf(ms, ", %s-style", os_style_names[os_style]) + == -1) +- return size; ++ return 1; + *flags |= FLAGS_DID_CORE_STYLE; + } + + switch (os_style) { + case OS_STYLE_NETBSD: +- if (xnh_type == NT_NETBSD_CORE_PROCINFO) { ++ if (type == NT_NETBSD_CORE_PROCINFO) { ++ char sbuf[512]; + uint32_t signo; + /* + * Extract the program name. It is at +@@ -719,7 +687,7 @@ core: + */ + if (file_printf(ms, ", from '%.31s'", + &nbuf[doff + 0x7c]) == -1) +- return size; ++ return 1; + + /* + * Extract the signal number. It is at +@@ -736,8 +704,7 @@ core: + break; + + default: +- if (xnh_type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { +-/*###709 [cc] warning: declaration of 'i' shadows previous non-variable%%%*/ ++ if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { + size_t i, j; + unsigned char c; + /* +@@ -805,7 +772,7 @@ core: + * Try next offsets, in case this match is + * in the middle of a string. + */ +- for (k = i + 1 ; k < NOFFSETS ; k++) { ++ for (k = i + 1 ; k < NOFFSETS; k++) { + size_t no; + int adjust = 1; + if (prpsoffsets(k) >= prpsoffsets(i)) +@@ -830,9 +797,9 @@ core: + cp--; + if (file_printf(ms, ", from '%.*s'", + (int)(cp - cname), cname) == -1) +- return size; ++ return 1; + *flags |= FLAGS_DID_CORE; +- return size; ++ return 1; + + tryanother: + ; +@@ -841,6 +808,129 @@ core: + break; + } + #endif ++ return 0; ++} ++ ++private size_t ++donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, ++ int clazz, int swap, size_t align, int *flags, uint16_t *notecount) ++{ ++ Elf32_Nhdr nh32; ++ Elf64_Nhdr nh64; ++ size_t noff, doff; ++ uint32_t namesz, descsz; ++ unsigned char *nbuf = CAST(unsigned char *, vbuf); ++ ++ if (*notecount == 0) ++ return 0; ++ --*notecount; ++ ++ if (xnh_sizeof + offset > size) { ++ /* ++ * We're out of note headers. ++ */ ++ return xnh_sizeof + offset; ++ } ++ ++ (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); ++ offset += xnh_sizeof; ++ ++ namesz = xnh_namesz; ++ descsz = xnh_descsz; ++ if ((namesz == 0) && (descsz == 0)) { ++ /* ++ * We're out of note headers. ++ */ ++ return (offset >= size) ? offset : size; ++ } ++ ++ if (namesz & 0x80000000) { ++ (void)file_printf(ms, ", bad note name size 0x%lx", ++ (unsigned long)namesz); ++ return 0; ++ } ++ ++ if (descsz & 0x80000000) { ++ (void)file_printf(ms, ", bad note description size 0x%lx", ++ (unsigned long)descsz); ++ return 0; ++ } ++ ++ noff = offset; ++ doff = ELF_ALIGN(offset + namesz); ++ ++ if (offset + namesz > size) { ++ /* ++ * We're past the end of the buffer. ++ */ ++ return doff; ++ } ++ ++ offset = ELF_ALIGN(doff + descsz); ++ if (doff + descsz > size) { ++ /* ++ * We're past the end of the buffer. ++ */ ++ return (offset >= size) ? offset : size; ++ } ++ ++ if ((*flags & FLAGS_DID_OS_NOTE) == 0) { ++ if (do_os_note(ms, nbuf, xnh_type, swap, ++ namesz, descsz, noff, doff, flags)) ++ return size; ++ } ++ ++ if ((*flags & FLAGS_DID_BUILD_ID) == 0) { ++ if (do_bid_note(ms, nbuf, xnh_type, swap, ++ namesz, descsz, noff, doff, flags)) ++ return size; ++ } ++ ++ if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) { ++ if (do_pax_note(ms, nbuf, xnh_type, swap, ++ namesz, descsz, noff, doff, flags)) ++ return size; ++ } ++ ++ if ((*flags & FLAGS_DID_CORE) == 0) { ++ if (do_core_note(ms, nbuf, xnh_type, swap, ++ namesz, descsz, noff, doff, flags, size, clazz)) ++ return size; ++ } ++ ++ if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { ++ if (descsz > 100) ++ descsz = 100; ++ switch (xnh_type) { ++ case NT_NETBSD_VERSION: ++ return size; ++ case NT_NETBSD_MARCH: ++ if (*flags & FLAGS_DID_NETBSD_MARCH) ++ return size; ++ *flags |= FLAGS_DID_NETBSD_MARCH; ++ if (file_printf(ms, ", compiled for: %.*s", ++ (int)descsz, (const char *)&nbuf[doff]) == -1) ++ return size; ++ break; ++ case NT_NETBSD_CMODEL: ++ if (*flags & FLAGS_DID_NETBSD_CMODEL) ++ return size; ++ *flags |= FLAGS_DID_NETBSD_CMODEL; ++ if (file_printf(ms, ", compiler model: %.*s", ++ (int)descsz, (const char *)&nbuf[doff]) == -1) ++ return size; ++ break; ++ default: ++ if (*flags & FLAGS_DID_NETBSD_UNKNOWN) ++ return size; ++ *flags |= FLAGS_DID_NETBSD_UNKNOWN; ++ if (file_printf(ms, ", note=%u", xnh_type) == -1) ++ return size; ++ break; ++ } ++ return size; ++ } ++ + return offset; + } + +@@ -896,16 +986,19 @@ static const cap_desc_t cap_desc_386[] = + + private int + doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, +- size_t size, off_t fsize, int *flags, int mach, int strtab) ++ size_t size, off_t fsize, int mach, int strtab, int *flags, ++ uint16_t *notecount) + { + Elf32_Shdr sh32; + Elf64_Shdr sh64; + int stripped = 1; ++ size_t nbadcap = 0; + void *nbuf; + off_t noff, coff, name_off; + uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */ + uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilites */ + char name[50]; ++ ssize_t namesize; + + if (size != xsh_sizeof) { + if (file_printf(ms, ", corrupted section header size") == -1) +@@ -914,7 +1007,7 @@ doshn(struct magic_set *ms, int clazz, i + } + + /* Read offset of name section to be able to read section names later */ +- if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) == -1) { ++ if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) < (ssize_t)xsh_sizeof) { + file_badread(ms); + return -1; + } +@@ -922,15 +1015,15 @@ doshn(struct magic_set *ms, int clazz, i + + for ( ; num; num--) { + /* Read the name of this section. */ +- if (pread(fd, name, sizeof(name), name_off + xsh_name) == -1) { ++ if ((namesize = pread(fd, name, sizeof(name) - 1, name_off + xsh_name)) == -1) { + file_badread(ms); + return -1; + } +- name[sizeof(name) - 1] = '\0'; ++ name[namesize] = '\0'; + if (strcmp(name, ".debug_info") == 0) + stripped = 0; + +- if (pread(fd, xsh_addr, xsh_sizeof, off) == -1) { ++ if (pread(fd, xsh_addr, xsh_sizeof, off) < (ssize_t)xsh_sizeof) { + file_badread(ms); + return -1; + } +@@ -945,7 +1038,7 @@ doshn(struct magic_set *ms, int clazz, i + stripped = 0; + break; + default: +- if (xsh_offset > fsize) { ++ if (fsize != SIZE_UNKNOWN && xsh_offset > fsize) { + /* Perhaps warn here */ + continue; + } +@@ -960,7 +1053,7 @@ doshn(struct magic_set *ms, int clazz, i + " for note"); + return -1; + } +- if (pread(fd, nbuf, xsh_size, xsh_offset) == -1) { ++ if (pread(fd, nbuf, xsh_size, xsh_offset) < (ssize_t)xsh_size) { + file_badread(ms); + free(nbuf); + return -1; +@@ -971,7 +1064,7 @@ doshn(struct magic_set *ms, int clazz, i + if (noff >= (off_t)xsh_size) + break; + noff = donote(ms, nbuf, (size_t)noff, +- xsh_size, clazz, swap, 4, flags); ++ xsh_size, clazz, swap, 4, flags, notecount); + if (noff == 0) + break; + } +@@ -989,6 +1082,8 @@ doshn(struct magic_set *ms, int clazz, i + goto skip; + } + ++ if (nbadcap > 5) ++ break; + if (lseek(fd, xsh_offset, SEEK_SET) == (off_t)-1) { + file_badseek(ms); + return -1; +@@ -1024,6 +1119,8 @@ doshn(struct magic_set *ms, int clazz, i + (unsigned long long)xcap_tag, + (unsigned long long)xcap_val) == -1) + return -1; ++ if (nbadcap++ > 2) ++ coff = xsh_size; + break; + } + } +@@ -1104,7 +1201,8 @@ doshn(struct magic_set *ms, int clazz, i + */ + private int + dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, +- int num, size_t size, off_t fsize, int *flags, int sh_num) ++ int num, size_t size, off_t fsize, int sh_num, int *flags, ++ uint16_t *notecount) + { + Elf32_Phdr ph32; + Elf64_Phdr ph64; +@@ -1121,7 +1219,7 @@ dophn_exec(struct magic_set *ms, int cla + } + + for ( ; num; num--) { +- if (pread(fd, xph_addr, xph_sizeof, off) == -1) { ++ if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { + file_badread(ms); + return -1; + } +@@ -1137,7 +1235,7 @@ dophn_exec(struct magic_set *ms, int cla + shared_libraries = " (uses shared libs)"; + break; + default: +- if (xph_offset > fsize) { ++ if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { + /* Maybe warn here? */ + continue; + } +@@ -1173,7 +1271,7 @@ dophn_exec(struct magic_set *ms, int cla + break; + offset = donote(ms, nbuf, offset, + (size_t)bufsize, clazz, swap, align, +- flags); ++ flags, notecount); + if (offset == 0) + break; + } +@@ -1204,7 +1302,7 @@ file_tryelf(struct magic_set *ms, int fd + int flags = 0; + Elf32_Ehdr elf32hdr; + Elf64_Ehdr elf64hdr; +- uint16_t type; ++ uint16_t type, phnum, shnum, notecount; + + if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) + return 0; +@@ -1230,7 +1328,10 @@ file_tryelf(struct magic_set *ms, int fd + file_badread(ms); + return -1; + } +- fsize = st.st_size; ++ if (S_ISREG(st.st_mode)) ++ fsize = st.st_size; ++ else ++ fsize = SIZE_UNKNOWN; + + clazz = buf[EI_CLASS]; + +Index: file-5.16/src/softmagic.c +=================================================================== +--- file-5.16.orig/src/softmagic.c ++++ file-5.16/src/softmagic.c +@@ -43,11 +43,11 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.1 + + + private int match(struct magic_set *, struct magic *, uint32_t, +- const unsigned char *, size_t, size_t, int, int, int, int, int *, int *, +- int *); ++ const unsigned char *, size_t, size_t, int, int, int, uint16_t, ++ uint16_t *, int *, int *, int *); + private int mget(struct magic_set *, const unsigned char *, +- struct magic *, size_t, size_t, unsigned int, int, int, int, int, int *, +- int *, int *); ++ struct magic *, size_t, size_t, unsigned int, int, int, int, uint16_t, ++ uint16_t *, int *, int *, int *); + private int magiccheck(struct magic_set *, struct magic *); + private int32_t mprint(struct magic_set *, struct magic *); + private int32_t moffset(struct magic_set *, struct magic *); +@@ -69,14 +69,20 @@ private void cvt_64(union VALUETYPE *, c + /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */ + protected int + file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, +- int mode, int text) ++ uint16_t indir_level, uint16_t *name_count, int mode, int text) + { + struct mlist *ml; + int rv, printed_something = 0, need_separator = 0; ++ uint16_t nc; ++ ++ if (name_count == NULL) { ++ nc = 0; ++ name_count = &nc; ++ } + for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) + if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode, +- text, 0, 0, &printed_something, &need_separator, +- NULL)) != 0) ++ text, 0, indir_level, name_count, ++ &printed_something, &need_separator, NULL)) != 0) + return rv; + + return 0; +@@ -112,8 +118,8 @@ file_softmagic(struct magic_set *ms, con + private int + match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, + const unsigned char *s, size_t nbytes, size_t offset, int mode, int text, +- int flip, int recursion_level, int *printed_something, int *need_separator, +- int *returnval) ++ int flip, uint16_t indir_level, uint16_t *name_count, ++ int *printed_something, int *need_separator, int *returnval) + { + uint32_t magindex = 0; + unsigned int cont_level = 0; +@@ -150,8 +156,8 @@ match(struct magic_set *ms, struct magic + + /* if main entry matches, print it... */ + switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text, +- flip, recursion_level + 1, printed_something, +- need_separator, returnval)) { ++ flip, indir_level, name_count, ++ printed_something, need_separator, returnval)) { + case -1: + return -1; + case 0: +@@ -237,8 +243,8 @@ match(struct magic_set *ms, struct magic + } + #endif + switch (mget(ms, s, m, nbytes, offset, cont_level, mode, +- text, flip, recursion_level + 1, printed_something, +- need_separator, returnval)) { ++ text, flip, indir_level, name_count, ++ printed_something, need_separator, returnval)) { + case -1: + return -1; + case 0: +@@ -1120,8 +1126,8 @@ mcopy(struct magic_set *ms, union VALUET + private int + mget(struct magic_set *ms, const unsigned char *s, struct magic *m, + size_t nbytes, size_t o, unsigned int cont_level, int mode, int text, +- int flip, int recursion_level, int *printed_something, +- int *need_separator, int *returnval) ++ int flip, uint16_t indir_level, uint16_t *name_count, ++ int *printed_something, int *need_separator, int *returnval) + { + uint32_t soffset, offset = ms->offset; + uint32_t count = m->str_range; +@@ -1130,8 +1136,15 @@ mget(struct magic_set *ms, const unsigne + union VALUETYPE *p = &ms->ms_value; + struct mlist ml; + +- if (recursion_level >= 20) { +- file_error(ms, 0, "recursion nesting exceeded"); ++ if (indir_level >= ms->indir_max) { ++ file_error(ms, 0, "indirect recursion nesting (%hu) exceeded", ++ indir_level); ++ return -1; ++ } ++ ++ if (*name_count >= ms->name_max) { ++ file_error(ms, 0, "name use count (%hu) exceeded", ++ *name_count); + return -1; + } + +@@ -1141,8 +1154,9 @@ mget(struct magic_set *ms, const unsigne + + if ((ms->flags & MAGIC_DEBUG) != 0) { + fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%zu, " +- "nbytes=%zu, count=%u)\n", m->type, m->flag, offset, o, +- nbytes, count); ++ "nbytes=%zu, il=%hu, nc=%hu)\n", ++ m->type, m->flag, offset, o, nbytes, ++ indir_level, *name_count); + mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); + #ifndef COMPILE_ONLY + file_mdump(m); +@@ -1711,7 +1725,7 @@ mget(struct magic_set *ms, const unsigne + ms->o.buf = NULL; + ms->offset = 0; + rv = file_softmagic(ms, s + offset, nbytes - offset, +- BINTEST, text); ++ indir_level + 1, name_count, BINTEST, text); + if ((ms->flags & MAGIC_DEBUG) != 0) + fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); + rbuf = ms->o.buf; +@@ -1730,22 +1744,22 @@ mget(struct magic_set *ms, const unsigne + case FILE_USE: + if (nbytes < offset) + return 0; +- sbuf = m->value.s; +- if (*sbuf == '^') { +- sbuf++; ++ rbuf = m->value.s; ++ if (*rbuf == '^') { ++ rbuf++; + flip = !flip; + } +- if (file_magicfind(ms, sbuf, &ml) == -1) { +- file_error(ms, 0, "cannot find entry `%s'", sbuf); ++ if (file_magicfind(ms, rbuf, &ml) == -1) { ++ file_error(ms, 0, "cannot find entry `%s'", rbuf); + return -1; + } +- ++ (*name_count)++; + oneed_separator = *need_separator; + if (m->flag & NOSPACE) + *need_separator = 0; + rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o, +- mode, text, flip, recursion_level, printed_something, +- need_separator, returnval); ++ mode, text, flip, indir_level, name_count, ++ printed_something, need_separator, returnval); + if (rv != 1) + *need_separator = oneed_separator; + return rv; diff --git a/meta/recipes-devtools/file/file_5.16.bb b/meta/recipes-devtools/file/file_5.16.bb index a15d952e3d..f231a55059 100644 --- a/meta/recipes-devtools/file/file_5.16.bb +++ b/meta/recipes-devtools/file/file_5.16.bb @@ -12,6 +12,7 @@ DEPENDS = "zlib file-native" DEPENDS_class-native = "zlib-native" SRC_URI = "ftp://ftp.astron.com/pub/file/file-${PV}.tar.gz \ + file://file-CVE-2014-9620-and-CVE-2014-9621.patch \ file://dump \ file://filesystems" -- cgit v1.2.3-54-g00ecf