aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChong Lu <Chong.Lu@windriver.com>2015-01-22 17:28:34 +0800
committerRichard Purdie <richard.purdie@linuxfoundation.org>2015-02-06 14:48:58 +0000
commitee78555fe54e98c6296566b5e701ef268d77db61 (patch)
tree6cb6d0aa833fa248ae0c8588941ebefafdf2fe79
parent1cda75706d63c988a0fa9945bd320b71c8e8488a (diff)
downloadopenembedded-core-contrib-ee78555fe54e98c6296566b5e701ef268d77db61.tar.gz
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] Signed-off-by: Chong Lu <Chong.Lu@windriver.com> [sgw - Fixed magic.h.in to match magic.h] Signed-off-by: Saul Wold <sgw@linux.intel.com>
-rw-r--r--meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch1359
-rw-r--r--meta/recipes-devtools/file/file_5.16.bb1
2 files changed, 1360 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..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 <Chong.Lu@windriver.com>
+---
+ 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, &notecount) == -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, &notecount) == -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, &notecount) == -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, "<unknown>") == -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"