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...@windriver.com>
---
 .../file-CVE-2014-9620-and-CVE-2014-9621.patch     | 1414 ++++++++++++++++++++
 meta/recipes-devtools/file/file_5.18.bb            |    1 +
 2 files changed, 1415 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 0000000..2482de3
--- /dev/null
+++ b/meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch
@@ -0,0 +1,1414 @@
+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
+
+Upstream-Status: Backport
+
+Signed-off-by: Chong Lu <chong...@windriver.com>
+---
+ src/apprentice.c |   5 +
+ src/ascmagic.c   |   3 +-
+ src/elfclass.h   |  34 ++--
+ src/file.c       |  59 ++++++-
+ 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   |   9 ++
+ src/readelf.c    | 471 +++++++++++++++++++++++++++++++++----------------------
+ src/softmagic.c  |  93 ++++++-----
+ 12 files changed, 566 insertions(+), 235 deletions(-)
+
+diff --git a/src/apprentice.c b/src/apprentice.c
+index 7400c57..231dc7e 100644
+--- a/src/apprentice.c
++++ b/src/apprentice.c
+@@ -506,6 +506,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);
+diff --git a/src/ascmagic.c b/src/ascmagic.c
+index ca26665..0a4cd10 100644
+--- a/src/ascmagic.c
++++ b/src/ascmagic.c
+@@ -147,7 +147,8 @@ file_ascmagic_with_encoding(struct magic_set *ms, const 
unsigned char *buf,
+                   == NULL)
+                       goto done;
+               if ((rv = file_softmagic(ms, utf8_buf,
+-                  (size_t)(utf8_end - utf8_buf), 0, TEXTTEST, text)) == 0)
++                  (size_t)(utf8_end - utf8_buf), 0, NULL,
++                  TEXTTEST, text)) == 0)
+                       rv = -1;
+       }
+ 
+diff --git a/src/elfclass.h b/src/elfclass.h
+index 010958a..5360b0b 100644
+--- a/src/elfclass.h
++++ b/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;
+diff --git a/src/file.c b/src/file.c
+index 370da91..b69b725 100644
+--- a/src/file.c
++++ b/src/file.c
+@@ -101,7 +101,7 @@ private const struct option long_options[] = {
+ #undef OPT_LONGONLY
+     {0, 0, NULL, 0}
+ };
+-#define OPTSTRING     "bcCde:Ef:F:hiklLm:nNprsvz0"
++#define OPTSTRING     "bcCde:Ef: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);
+ 
+ 
+ /*
+@@ -243,9 +257,13 @@ main(int argc, char *argv[])
+                       flags |= MAGIC_PRESERVE_ATIME;
+                       break;
+ #endif
++              case 'P':
++                      setparam(optarg);
++                      break;
+               case 'r':
+                       flags |= MAGIC_RAW;
+                       break;
++                      break;
+               case 's':
+                       flags |= MAGIC_DEVICES;
+                       break;
+@@ -298,6 +316,8 @@ main(int argc, char *argv[])
+                           strerror(errno));
+                       return 1;
+               }
++
++
+               switch(action) {
+               case FILE_CHECK:
+                       c = magic_check(magic, magicfile);
+@@ -321,7 +341,7 @@ main(int argc, char *argv[])
+               if (magic == NULL)
+                       if ((magic = load(magicfile, flags)) == NULL)
+                               return 1;
+-              break;
++              applyparam(magic);
+       }
+ 
+       if (optind == argc) {
+@@ -351,6 +371,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*/
+diff --git a/src/file.h b/src/file.h
+index 5c67ddd..88da1d1 100644
+--- a/src/file.h
++++ b/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 */
+@@ -439,7 +449,7 @@ protected int file_encoding(struct magic_set *, const 
unsigned char *, size_t,
+     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,
+-    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 *,
+@@ -469,6 +479,14 @@ protected int file_os2_apptype(struct magic_set *, const 
char *, const void *,
+ #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;
+diff --git a/src/file_opts.h b/src/file_opts.h
+index db34eb7..3286ac6 100644
+--- a/src/file_opts.h
++++ b/src/file_opts.h
+@@ -43,6 +43,12 @@ OPT('0', "print0", 0, "               terminate filenames 
with ASCII NUL\n")
+ #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")
+diff --git a/src/funcs.c b/src/funcs.c
+index a9624a2..c3cf2be 100644
+--- a/src/funcs.c
++++ b/src/funcs.c
+@@ -230,7 +230,7 @@ file_buffer(struct magic_set *ms, int fd, const char 
*inname __attribute__ ((unu
+ 
+       /* try soft magic tests */
+       if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0)
+-              if ((m = file_softmagic(ms, ubuf, nb, 0, 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 @@ out:
+       free(old_lc_ctype);
+       return rv;
+ }
++
++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;
++}
+diff --git a/src/magic.c b/src/magic.c
+index 22174b8..a89647c 100644
+--- a/src/magic.c
++++ b/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;
++      }
++}
+diff --git a/src/magic.h b/src/magic.h
+index 535a177..89bfe4b 100644
+--- a/src/magic.h
++++ b/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
+diff --git a/src/magic.h.in b/src/magic.h.in
+index 86fc41b..2efc7bc 100644
+--- a/src/magic.h.in
++++ b/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
+diff --git a/src/readelf.c b/src/readelf.c
+index cbed129..87df727 100644
+--- a/src/readelf.c
++++ b/src/readelf.c
+@@ -43,14 +43,14 @@ FILE_RCSID("@(#)$File: readelf.c,v 1.102 2014/03/11 
21:00:13 christos Exp $")
+ 
+ #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 clazz, int swap, 
int fd, off_t off,
+        * 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 clazz, int swap, int 
fd, off_t off,
+                       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,128 @@ do_note_freebsd_version(struct magic_set *ms, int 
swap, void *v)
+       }
+ }
+ 
+-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 +615,32 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, 
size_t size,
+               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 +669,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 +688,7 @@ core:
+                        */
+                       if (file_printf(ms, ", from '%.31s'",
+                           &nbuf[doff + 0x7c]) == -1)
+-                              return size;
++                              return 1;
+                       
+                       /*
+                        * Extract the signal number.  It is at
+@@ -729,14 +698,14 @@ core:
+                           sizeof(signo));
+                       if (file_printf(ms, " (signal %u)",
+                           elf_getu32(swap, signo)) == -1)
+-                              return size;
++                              return 1;
+                       *flags |= FLAGS_DID_CORE;
+-                      return size;
++                      return 1;
+               }
+               break;
+ 
+       default:
+-              if (xnh_type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
++              if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
+                       size_t i, j;
+                       unsigned char c;
+                       /*
+@@ -804,7 +773,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))
+@@ -829,9 +798,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:
+                               ;
+@@ -840,6 +809,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;
+ }
+ 
+@@ -895,16 +987,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)
+@@ -913,7 +1008,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, 
off_t off, int num,
+       }
+ 
+       /* 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;
+       }
+@@ -921,15 +1016,15 @@ doshn(struct magic_set *ms, int clazz, int swap, int 
fd, off_t off, int num,
+ 
+       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;
+               }
+@@ -944,7 +1039,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, 
off_t off, int num,
+                       stripped = 0;
+                       break;
+               default:
+-                      if (xsh_offset > fsize) {
++                      if (fsize != SIZE_UNKNOWN && xsh_offset > fsize) {
+                               /* Perhaps warn here */
+                               continue;
+                       }
+@@ -959,7 +1054,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, 
off_t off, int num,
+                                   " 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;
+@@ -970,7 +1065,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, 
off_t off, int num,
+                               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;
+                       }
+@@ -988,6 +1083,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, 
off_t off, int num,
+                               goto skip;
+                       }
+ 
++                      if (nbadcap > 5)
++                              break;
+                       if (lseek(fd, xsh_offset, SEEK_SET) == (off_t)-1) {
+                               file_badseek(ms);
+                               return -1;
+@@ -1023,6 +1120,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, 
off_t off, int num,
+                                           (unsigned long long)xcap_tag,
+                                           (unsigned long long)xcap_val) == -1)
+                                               return -1;
++                                      if (nbadcap++ > 2)
++                                              coff = xsh_size;
+                                       break;
+                               }
+                       }
+@@ -1103,7 +1202,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, 
off_t off, int num,
+  */
+ 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;
+@@ -1120,7 +1220,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, 
int fd, off_t off,
+       }
+ 
+       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;
+               }
+@@ -1136,7 +1236,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, 
int fd, off_t off,
+                       shared_libraries = " (uses shared libs)";
+                       break;
+               default:
+-                      if (xph_offset > fsize) {
++                      if (fsize != SIZE_UNKNOWN && xph_offset > fsize) {
+                               /* Maybe warn here? */
+                               continue;
+                       }
+@@ -1172,7 +1272,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, 
int fd, off_t off,
+                                       break;
+                               offset = donote(ms, nbuf, offset,
+                                   (size_t)bufsize, clazz, swap, align,
+-                                  flags);
++                                  flags, notecount);
+                               if (offset == 0)
+                                       break;
+                       }
+@@ -1203,7 +1303,7 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned 
char *buf,
+       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;
+@@ -1229,7 +1329,10 @@ file_tryelf(struct magic_set *ms, int fd, const 
unsigned char *buf,
+               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];
+ 
+diff --git a/src/softmagic.c b/src/softmagic.c
+index eaa0f6b..9b11b93 100644
+--- a/src/softmagic.c
++++ b/src/softmagic.c
+@@ -48,11 +48,11 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.180 2014/03/15 
21:47:40 christos Exp $")
+ 
+ 
+ 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 *);
+@@ -68,6 +68,7 @@ private void cvt_32(union VALUETYPE *, const struct magic *);
+ private void cvt_64(union VALUETYPE *, const struct magic *);
+ 
+ #define OFFSET_OOB(n, o, i)   ((n) < (o) || (i) > ((n) - (o)))
++
+ /*
+  * softmagic - lookup one file in parsed, in-memory copy of database
+  * Passed the name and FILE * of one file to be typed.
+@@ -75,14 +76,20 @@ private void cvt_64(union VALUETYPE *, const struct magic 
*);
+ /*ARGSUSED1*/         /* nbytes passed for regularity, maybe need later */
+ protected int
+ file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
+-    size_t level, 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, level, &printed_something, &need_separator,
+-                  NULL)) != 0)
++                  text, 0, indir_level, name_count,
++                  &printed_something, &need_separator, NULL)) != 0)
+                       return rv;
+ 
+       return 0;
+@@ -118,8 +125,8 @@ file_softmagic(struct magic_set *ms, const unsigned char 
*buf, size_t nbytes,
+ 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;
+@@ -156,8 +163,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t 
nmagic,
+ 
+               /* 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:
+@@ -245,8 +252,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t 
nmagic,
+                       }
+ #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:
+@@ -1155,18 +1162,26 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int 
type, int indir,
+ 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 offset = ms->offset;
+       uint32_t count = m->str_range;
++      file_pushbuf_t *pb;
+       int rv, oneed_separator, in_type;
+-      char *sbuf, *rbuf;
++      char *rbuf;
+       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;
+       }
+ 
+@@ -1678,6 +1693,10 @@ mget(struct magic_set *ms, const unsigned char *s, 
struct magic *m,
+               ms->offset = offset;
+ 
+               if ((ms->flags & MAGIC_DEBUG) != 0) {
++                      fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, 
o=%zu, "
++                      "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
+@@ -1741,19 +1760,23 @@ mget(struct magic_set *ms, const unsigned char *s, 
struct magic *m,
+       case FILE_INDIRECT:
+               if (offset == 0)
+                       return 0;
++
+               if (nbytes < offset)
+                       return 0;
+-              sbuf = ms->o.buf;
+-              soffset = ms->offset;
+-              ms->o.buf = NULL;
+-              ms->offset = 0;
++
++              if ((pb = file_push_buffer(ms)) == NULL)
++                      return -1;
++
+               rv = file_softmagic(ms, s + offset, nbytes - offset,
+-                  recursion_level, 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;
+-              ms->o.buf = sbuf;
+-              ms->offset = soffset;
++
++              rbuf = file_pop_buffer(ms, pb);
++              if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR)
++                      return -1;
++
+               if (rv == 1) {
+                       if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
+                           file_printf(ms, F(m->desc, "%u"), offset) == -1) {
+@@ -1771,22 +1794,22 @@ mget(struct magic_set *ms, const unsigned char *s, 
struct magic *m,
+       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;
+-- 
+1.9.1
+
diff --git a/meta/recipes-devtools/file/file_5.18.bb 
b/meta/recipes-devtools/file/file_5.18.bb
index 9068b93..d6e7d61 100644
--- a/meta/recipes-devtools/file/file_5.18.bb
+++ b/meta/recipes-devtools/file/file_5.18.bb
@@ -13,6 +13,7 @@ DEPENDS_class-native = "zlib-native"
 
 SRC_URI = "ftp://ftp.astron.com/pub/file/file-${PV}.tar.gz \
            file://debian-742262.patch \
+           file://file-CVE-2014-9620-and-CVE-2014-9621.patch \
           "
 
 SRC_URI[md5sum] = "d420d8f2990cd344673acfbf8d76ff5a"
-- 
1.9.1

-- 
_______________________________________________
Openembedded-core mailing list
Openembedded-core@lists.openembedded.org
http://lists.openembedded.org/mailman/listinfo/openembedded-core

Reply via email to