[OE-core] [dizzy][PATCH] file: CVE-2014-9620 and CVE-2014-9621
Chong Lu
Chong.Lu at windriver.com
Fri Jan 30 01:17:48 UTC 2015
ping
//Chong
On 01/26/2015 09:56 AM, Chong Lu wrote:
> 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 at 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.Lu at 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, ¬ecount) == -1)
> + return -1;
> + break;
> + #endif
> + case ET_EXEC:
> + case ET_DYN:
> ++ phnum = elf_getu16(swap, elfhdr.e_phnum);
> ++ if (phnum > ms->elf_phnum_max)
> ++ return toomany(ms, "program", phnum);
> ++ shnum = elf_getu16(swap, elfhdr.e_shnum);
> ++ if (shnum > ms->elf_shnum_max)
> ++ return toomany(ms, "section", shnum);
> + if (dophn_exec(ms, clazz, swap, fd,
> +- (off_t)elf_getu(swap, elfhdr.e_phoff),
> +- elf_getu16(swap, elfhdr.e_phnum),
> ++ (off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
> + (size_t)elf_getu16(swap, elfhdr.e_phentsize),
> +- fsize, &flags, elf_getu16(swap, elfhdr.e_shnum))
> +- == -1)
> ++ fsize, shnum, &flags, ¬ecount) == -1)
> + return -1;
> + /*FALLTHROUGH*/
> + case ET_REL:
> ++ shnum = elf_getu16(swap, elfhdr.e_shnum);
> ++ if (shnum > ms->elf_shnum_max)
> ++ return toomany(ms, "section headers", shnum);
> + if (doshn(ms, clazz, swap, fd,
> +- (off_t)elf_getu(swap, elfhdr.e_shoff),
> +- elf_getu16(swap, elfhdr.e_shnum),
> ++ (off_t)elf_getu(swap, elfhdr.e_shoff), shnum,
> + (size_t)elf_getu16(swap, elfhdr.e_shentsize),
> +- fsize, &flags, elf_getu16(swap, elfhdr.e_machine),
> +- (int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1)
> ++ fsize, elf_getu16(swap, elfhdr.e_machine),
> ++ (int)elf_getu16(swap, elfhdr.e_shstrndx),
> ++ &flags, ¬ecount) == -1)
> + return -1;
> + break;
> +
> + default:
> + break;
> + }
> ++ if (notecount == 0)
> ++ return toomany(ms, "notes", ms->elf_notes_max);
> + return 1;
> +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"
More information about the Openembedded-core
mailing list