All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chong Lu <Chong.Lu@windriver.com>
To: <openembedded-core@lists.openembedded.org>
Subject: Re: [daisy][PATCH] file: CVE-2014-9620 and CVE-2014-9621
Date: Fri, 30 Jan 2015 09:18:30 +0800	[thread overview]
Message-ID: <54CADBE6.2030201@windriver.com> (raw)
In-Reply-To: <1421918914-28508-1-git-send-email-Chong.Lu@windriver.com>

ping

//Chong

On 01/22/2015 05:28 PM, 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@windriver.com>
> ---
>   .../file-CVE-2014-9620-and-CVE-2014-9621.patch     | 1357 ++++++++++++++++++++
>   meta/recipes-devtools/file/file_5.16.bb            |    1 +
>   2 files changed, 1358 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..bd5944e
> --- /dev/null
> +++ b/meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch
> @@ -0,0 +1,1357 @@
> +file: CVE-2014-9620 and CVE-2014-9621
> +
> +The patch comes from:
> +https://github.com/file/file/commit/6ce24f35cd4a43c4bdd249e8e0c4952c1f8eac67
> +https://github.com/file/file/commit/0056ec32255de1de973574b0300161a1568767d6
> +https://github.com/file/file/commit/09e41625c999a2e5b51e1092f0ef2432a99b5c33
> +https://github.com/file/file/commit/af444af0738468393f40f9d2261b1ea10fc4b2ba
> +https://github.com/file/file/commit/68bd8433c7e11a8dbe100deefdfac69138ee7cd9
> +https://github.com/file/file/commit/dddd3cdb95210a765dd90f7d722cb8b5534daee7
> +https://github.com/file/file/commit/445c8fb0ebff85195be94cd9f7e1df89cade5c7f
> +https://github.com/file/file/commit/ce90e05774dd77d86cfc8dfa6da57b32816841c4
> +https://github.com/file/file/commit/65437cee25199dbd385fb35901bc0011e164276c
> +
> +Upstream-Status: Backport
> +
> +Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
> +---
> + src/apprentice.c |    5 +
> + src/ascmagic.c   |    3 +-
> + src/elfclass.h   |   34 ++--
> + src/file.c       |   58 ++++++-
> + src/file.h       |   20 ++-
> + src/file_opts.h  |    6 +
> + src/funcs.c      |   42 ++++-
> + src/magic.c      |   50 ++++++
> + src/magic.h      |    9 ++
> + src/magic.h.in   |    4 +
> + src/readelf.c    |  467 +++++++++++++++++++++++++++++++++---------------------
> + src/softmagic.c  |   70 ++++----
> + 12 files changed, 541 insertions(+), 227 deletions(-)
> +
> +diff --git a/src/apprentice.c b/src/apprentice.c
> +index 2df60d9..d906f7b 100644
> +--- a/src/apprentice.c
> ++++ b/src/apprentice.c
> +@@ -494,6 +494,11 @@ file_ms_alloc(int flags)
> + 		ms->mlist[i] = NULL;
> + 	ms->file = "unknown";
> + 	ms->line = 0;
> ++	ms->indir_max = FILE_INDIR_MAX;
> ++	ms->name_max = FILE_NAME_MAX;
> ++	ms->elf_shnum_max = FILE_ELF_SHNUM_MAX;
> ++	ms->elf_phnum_max = FILE_ELF_PHNUM_MAX;
> ++	ms->elf_notes_max = FILE_ELF_NOTES_MAX;
> + 	return ms;
> + free:
> + 	free(ms);
> +diff --git a/src/ascmagic.c b/src/ascmagic.c
> +index 28ebadc..7a22328 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), 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 ac773ea..ee1edcd 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:f:F:hiklLm:nNprsvz0"
> ++#define OPTSTRING	"bcCde:f:F:hiklLm:nNpP:rsvz0"
> +
> + private const struct {
> + 	const char *name;
> +@@ -119,6 +119,18 @@ private const struct {
> + 	{ "tokens",	MAGIC_NO_CHECK_TOKENS }, /* OBSOLETE: ignored for backwards compatibility */
> + };
> +
> ++private struct {
> ++	const char *name;
> ++	int tag;
> ++	size_t value;
> ++} pm[] = {
> ++	{ "indir",	MAGIC_PARAM_INDIR_MAX, 0 },
> ++	{ "name",	MAGIC_PARAM_NAME_MAX, 0 },
> ++	{ "elf_phnum",	MAGIC_PARAM_ELF_PHNUM_MAX, 0 },
> ++	{ "elf_shnum",	MAGIC_PARAM_ELF_SHNUM_MAX, 0 },
> ++	{ "elf_notes",	MAGIC_PARAM_ELF_NOTES_MAX, 0 },
> ++};
> ++
> + private char *progname;		/* used throughout 		*/
> +
> + private void usage(void);
> +@@ -128,6 +140,8 @@ private void help(void);
> + private int unwrap(struct magic_set *, const char *);
> + private int process(struct magic_set *ms, const char *, int);
> + private struct magic_set *load(const char *, int);
> ++private void setparam(const char *);
> ++private void applyparam(magic_t);
> +
> +
> + /*
> +@@ -240,6 +254,9 @@ main(int argc, char *argv[])
> + 			flags |= MAGIC_PRESERVE_ATIME;
> + 			break;
> + #endif
> ++		case 'P':
> ++			setparam(optarg);
> ++			break;
> + 		case 'r':
> + 			flags |= MAGIC_RAW;
> + 			break;
> +@@ -295,6 +312,8 @@ main(int argc, char *argv[])
> + 			    strerror(errno));
> + 			return 1;
> + 		}
> ++
> ++
> + 		switch(action) {
> + 		case FILE_CHECK:
> + 			c = magic_check(magic, magicfile);
> +@@ -318,7 +337,7 @@ main(int argc, char *argv[])
> + 		if (magic == NULL)
> + 			if ((magic = load(magicfile, flags)) == NULL)
> + 				return 1;
> +-		break;
> ++		applyparam(magic);
> + 	}
> +
> + 	if (optind == argc) {
> +@@ -348,6 +367,41 @@ main(int argc, char *argv[])
> + 	return e;
> + }
> +
> ++private void
> ++applyparam(magic_t magic)
> ++{
> ++	size_t i;
> ++
> ++	for (i = 0; i < __arraycount(pm); i++) {
> ++		if (pm[i].value == 0)
> ++			continue;
> ++		if (magic_setparam(magic, pm[i].tag, &pm[i].value) == -1) {
> ++			(void)fprintf(stderr, "%s: Can't set %s %s\n", progname,
> ++				pm[i].name, strerror(errno));
> ++			exit(1);
> ++		}
> ++	}
> ++}
> ++
> ++private void
> ++setparam(const char *p)
> ++{
> ++	size_t i;
> ++	char *s;
> ++
> ++	if ((s = strchr(p, '=')) == NULL)
> ++		goto badparm;
> ++
> ++	for (i = 0; i < __arraycount(pm); i++) {
> ++		if (strncmp(p, pm[i].name, s - p) != 0)
> ++			continue;
> ++		pm[i].value = atoi(s + 1);
> ++		return;
> ++	}
> ++badparm:
> ++	(void)fprintf(stderr, "%s: Unknown param %s\n", progname, p);
> ++	exit(1);
> ++}
> +
> + private struct magic_set *
> + /*ARGSUSED*/
> +diff --git a/src/file.h b/src/file.h
> +index e910a2b..57e7307 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 */
> +@@ -438,7 +448,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,
> +-    int, int);
> ++    uint16_t, uint16_t *, int, int);
> + protected int file_apprentice(struct magic_set *, const char *, int);
> + protected int file_magicfind(struct magic_set *, const char *, struct mlist *);
> + protected uint64_t file_signextend(struct magic_set *, struct magic *,
> +@@ -468,6 +478,14 @@ protected int file_os2_apptype(struct 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 b798e44..50c38e5 100644
> +--- a/src/funcs.c
> ++++ b/src/funcs.c
> +@@ -226,7 +226,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, BINTEST,
> ++		if ((m = file_softmagic(ms, ubuf, nb, 0, NULL, BINTEST,
> + 		    looks_text)) != 0) {
> + 			if ((ms->flags & MAGIC_DEBUG) != 0)
> + 				(void)fprintf(stderr, "softmagic %d\n", m);
> +@@ -459,3 +459,43 @@ file_replace(struct magic_set *ms, const char *pat, const char *rep)
> + 		return nm;
> + 	}
> + }
> ++
> ++protected file_pushbuf_t *
> ++file_push_buffer(struct magic_set *ms)
> ++{
> ++	file_pushbuf_t *pb;
> ++
> ++	if (ms->event_flags & EVENT_HAD_ERR)
> ++		return NULL;
> ++
> ++	if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL)
> ++		return NULL;
> ++
> ++	pb->buf = ms->o.buf;
> ++	pb->offset = ms->offset;
> ++
> ++	ms->o.buf = NULL;
> ++	ms->offset = 0;
> ++
> ++	return pb;
> ++}
> ++
> ++protected char *
> ++file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb)
> ++{
> ++	char *rbuf;
> ++
> ++	if (ms->event_flags & EVENT_HAD_ERR) {
> ++		free(pb->buf);
> ++		free(pb);
> ++		return NULL;
> ++	}
> ++
> ++	rbuf = ms->o.buf;
> ++
> ++	ms->o.buf = pb->buf;
> ++	ms->offset = pb->offset;
> ++
> ++	free(pb);
> ++	return rbuf;
> ++}
> +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 cc8ed68..2938a20 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..a256cf0 100644
> +--- a/src/magic.h.in
> ++++ b/src/magic.h.in
> +@@ -101,6 +101,10 @@ int magic_check(magic_t, const char *);
> + int magic_list(magic_t, const char *);
> + int magic_errno(magic_t);
> +
> ++#define MAGIC_PARAM_MAX_RECURSION	0
> ++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 f8b8bbc..a7b2ba4 100644
> +--- a/src/readelf.c
> ++++ b/src/readelf.c
> +@@ -43,14 +43,14 @@ FILE_RCSID("@(#)$File: readelf.c,v 1.99 2013/11/05 15:44:01 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,127 @@ 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 +614,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 +668,17 @@ core:
> + 		os_style = OS_STYLE_NETBSD;
> + 	}
> +
> +-#ifdef ELFCORE
> +-	if ((*flags & FLAGS_DID_CORE) != 0)
> +-		return size;
> +-
> + 	if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) {
> + 		if (file_printf(ms, ", %s-style", os_style_names[os_style])
> + 		    == -1)
> +-			return size;
> ++			return 1;
> + 		*flags |= FLAGS_DID_CORE_STYLE;
> + 	}
> +
> + 	switch (os_style) {
> + 	case OS_STYLE_NETBSD:
> +-		if (xnh_type == NT_NETBSD_CORE_PROCINFO) {
> ++		if (type == NT_NETBSD_CORE_PROCINFO) {
> ++			char sbuf[512];
> + 			uint32_t signo;
> + 			/*
> + 			 * Extract the program name.  It is at
> +@@ -719,7 +687,7 @@ core:
> + 			 */
> + 			if (file_printf(ms, ", from '%.31s'",
> + 			    &nbuf[doff + 0x7c]) == -1)
> +-				return size;
> ++				return 1;
> + 			
> + 			/*
> + 			 * Extract the signal number.  It is at
> +@@ -736,8 +704,7 @@ core:
> + 		break;
> +
> + 	default:
> +-		if (xnh_type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
> +-/*###709 [cc] warning: declaration of 'i' shadows previous non-variable%%%*/
> ++		if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) {
> + 			size_t i, j;
> + 			unsigned char c;
> + 			/*
> +@@ -805,7 +772,7 @@ core:
> + 				 * Try next offsets, in case this match is
> + 				 * in the middle of a string.
> + 				 */
> +-				for (k = i + 1 ; k < NOFFSETS ; k++) {
> ++				for (k = i + 1 ; k < NOFFSETS; k++) {
> + 					size_t no;
> + 					int adjust = 1;
> + 					if (prpsoffsets(k) >= prpsoffsets(i))
> +@@ -830,9 +797,9 @@ core:
> + 					cp--;
> + 				if (file_printf(ms, ", from '%.*s'",
> + 				    (int)(cp - cname), cname) == -1)
> +-					return size;
> ++					return 1;
> + 				*flags |= FLAGS_DID_CORE;
> +-				return size;
> ++				return 1;
> +
> + 			tryanother:
> + 				;
> +@@ -841,6 +808,129 @@ core:
> + 		break;
> + 	}
> + #endif
> ++	return 0;
> ++}
> ++
> ++private size_t
> ++donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
> ++    int clazz, int swap, size_t align, int *flags, uint16_t *notecount)
> ++{
> ++	Elf32_Nhdr nh32;
> ++	Elf64_Nhdr nh64;
> ++	size_t noff, doff;
> ++	uint32_t namesz, descsz;
> ++	unsigned char *nbuf = CAST(unsigned char *, vbuf);
> ++
> ++	if (*notecount == 0)
> ++		return 0;
> ++	--*notecount;
> ++
> ++	if (xnh_sizeof + offset > size) {
> ++		/*
> ++		 * We're out of note headers.
> ++		 */
> ++		return xnh_sizeof + offset;
> ++	}
> ++
> ++	(void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof);
> ++	offset += xnh_sizeof;
> ++
> ++	namesz = xnh_namesz;
> ++	descsz = xnh_descsz;
> ++	if ((namesz == 0) && (descsz == 0)) {
> ++		/*
> ++		 * We're out of note headers.
> ++		 */
> ++		return (offset >= size) ? offset : size;
> ++	}
> ++
> ++	if (namesz & 0x80000000) {
> ++	    (void)file_printf(ms, ", bad note name size 0x%lx",
> ++		(unsigned long)namesz);
> ++	    return 0;
> ++	}
> ++
> ++	if (descsz & 0x80000000) {
> ++	    (void)file_printf(ms, ", bad note description size 0x%lx",
> ++		(unsigned long)descsz);
> ++	    return 0;
> ++	}
> ++
> ++	noff = offset;
> ++	doff = ELF_ALIGN(offset + namesz);
> ++
> ++	if (offset + namesz > size) {
> ++		/*
> ++		 * We're past the end of the buffer.
> ++		 */
> ++		return doff;
> ++	}
> ++
> ++	offset = ELF_ALIGN(doff + descsz);
> ++	if (doff + descsz > size) {
> ++		/*
> ++		 * We're past the end of the buffer.
> ++		 */
> ++		return (offset >= size) ? offset : size;
> ++	}
> ++
> ++	if ((*flags & FLAGS_DID_OS_NOTE) == 0) {
> ++		if (do_os_note(ms, nbuf, xnh_type, swap,
> ++		    namesz, descsz, noff, doff, flags))
> ++			return size;
> ++	}
> ++
> ++	if ((*flags & FLAGS_DID_BUILD_ID) == 0) {
> ++		if (do_bid_note(ms, nbuf, xnh_type, swap,
> ++		    namesz, descsz, noff, doff, flags))
> ++			return size;
> ++	}
> ++		
> ++	if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) {
> ++		if (do_pax_note(ms, nbuf, xnh_type, swap,
> ++		    namesz, descsz, noff, doff, flags))
> ++			return size;
> ++	}
> ++
> ++	if ((*flags & FLAGS_DID_CORE) == 0) {
> ++		if (do_core_note(ms, nbuf, xnh_type, swap,
> ++		    namesz, descsz, noff, doff, flags, size, clazz))
> ++			return size;
> ++	}
> ++
> ++	if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) {
> ++		if (descsz > 100)
> ++			descsz = 100;
> ++		switch (xnh_type) {
> ++	    	case NT_NETBSD_VERSION:
> ++			return size;
> ++		case NT_NETBSD_MARCH:
> ++			if (*flags & FLAGS_DID_NETBSD_MARCH)
> ++				return size;
> ++			*flags |= FLAGS_DID_NETBSD_MARCH;
> ++			if (file_printf(ms, ", compiled for: %.*s",
> ++			    (int)descsz, (const char *)&nbuf[doff]) == -1)
> ++				return size;
> ++			break;
> ++		case NT_NETBSD_CMODEL:
> ++			if (*flags & FLAGS_DID_NETBSD_CMODEL)
> ++				return size;
> ++			*flags |= FLAGS_DID_NETBSD_CMODEL;
> ++			if (file_printf(ms, ", compiler model: %.*s",
> ++			    (int)descsz, (const char *)&nbuf[doff]) == -1)
> ++				return size;
> ++			break;
> ++		default:
> ++			if (*flags & FLAGS_DID_NETBSD_UNKNOWN)
> ++				return size;
> ++			*flags |= FLAGS_DID_NETBSD_UNKNOWN;
> ++			if (file_printf(ms, ", note=%u", xnh_type) == -1)
> ++				return size;
> ++			break;
> ++		}
> ++		return size;
> ++	}
> ++
> + 	return offset;
> + }
> +
> +@@ -896,16 +986,19 @@ static const cap_desc_t cap_desc_386[] = {
> +
> + private int
> + doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
> +-    size_t size, off_t fsize, int *flags, int mach, int strtab)
> ++    size_t size, off_t fsize, int mach, int strtab, int *flags,
> ++    uint16_t *notecount)
> + {
> + 	Elf32_Shdr sh32;
> + 	Elf64_Shdr sh64;
> + 	int stripped = 1;
> ++	size_t nbadcap = 0;
> + 	void *nbuf;
> + 	off_t noff, coff, name_off;
> + 	uint64_t cap_hw1 = 0;	/* SunOS 5.x hardware capabilites */
> + 	uint64_t cap_sf1 = 0;	/* SunOS 5.x software capabilites */
> + 	char name[50];
> ++	ssize_t namesize;
> +
> + 	if (size != xsh_sizeof) {
> + 		if (file_printf(ms, ", corrupted section header size") == -1)
> +@@ -914,7 +1007,7 @@ doshn(struct magic_set *ms, int clazz, 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;
> + 	}
> +@@ -922,15 +1015,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;
> + 		}
> +@@ -945,7 +1038,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;
> + 			}
> +@@ -960,7 +1053,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;
> +@@ -971,7 +1064,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;
> + 			}
> +@@ -989,6 +1082,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;
> +@@ -1024,6 +1119,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;
> + 				}
> + 			}
> +@@ -1104,7 +1201,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;
> +@@ -1121,7 +1219,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;
> + 		}
> +@@ -1137,7 +1235,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;
> + 			}
> +@@ -1173,7 +1271,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;
> + 			}
> +@@ -1204,7 +1302,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;
> +@@ -1230,7 +1328,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 dc7928b..b1f5779 100644
> +--- a/src/softmagic.c
> ++++ b/src/softmagic.c
> +@@ -43,11 +43,11 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.168 2013/05/30 15:53:33 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 *);
> +@@ -69,14 +69,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,
> +-    int mode, int text)
> ++    uint16_t indir_level, uint16_t *name_count, int mode, int text)
> + {
> + 	struct mlist *ml;
> + 	int rv, printed_something = 0, need_separator = 0;
> ++	uint16_t nc;
> ++
> ++	if (name_count == NULL) {
> ++		nc = 0;
> ++		name_count = &nc;
> ++	}
> + 	for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next)
> + 		if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode,
> +-		    text, 0, 0, &printed_something, &need_separator,
> +-		    NULL)) != 0)
> ++		    text, 0, indir_level, name_count,
> ++		    &printed_something, &need_separator, NULL)) != 0)
> + 			return rv;
> +
> + 	return 0;
> +@@ -112,8 +118,8 @@ file_softmagic(struct magic_set *ms, 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;
> +@@ -150,8 +156,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:
> +@@ -237,8 +243,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:
> +@@ -1120,8 +1126,8 @@ 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 count = m->str_range;
> +@@ -1130,8 +1136,15 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
> + 	union VALUETYPE *p = &ms->ms_value;
> + 	struct mlist ml;
> +
> +-	if (recursion_level >= 20) {
> +-		file_error(ms, 0, "recursion nesting exceeded");
> ++	if (indir_level >= ms->indir_max) {
> ++		file_error(ms, 0, "indirect recursion nesting (%hu) exceeded",
> ++		    indir_level);
> ++		return -1;
> ++	}
> ++
> ++	if (*name_count >= ms->name_max) {
> ++		file_error(ms, 0, "name use count (%hu) exceeded",
> ++		    *name_count);
> + 		return -1;
> + 	}
> +
> +@@ -1141,8 +1154,9 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
> +
> + 	if ((ms->flags & MAGIC_DEBUG) != 0) {
> + 		fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%zu, "
> +-		    "nbytes=%zu, count=%u)\n", m->type, m->flag, offset, o,
> +-		    nbytes, count);
> ++		    "nbytes=%zu, il=%hu, nc=%hu)\n",
> ++		    m->type, m->flag, offset, o, nbytes,
> ++		    indir_level, *name_count);
> + 		mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE));
> + #ifndef COMPILE_ONLY
> + 		file_mdump(m);
> +@@ -1711,7 +1725,7 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m,
> + 		ms->o.buf = NULL;
> + 		ms->offset = 0;
> + 		rv = file_softmagic(ms, s + offset, nbytes - offset,
> +-		    BINTEST, text);
> ++		    indir_level + 1, name_count, BINTEST, text);
> + 		if ((ms->flags & MAGIC_DEBUG) != 0)
> + 			fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv);
> + 		rbuf = ms->o.buf;
> +@@ -1730,22 +1744,22 @@ mget(struct magic_set *ms, const 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.7.9.5
> +
> diff --git a/meta/recipes-devtools/file/file_5.16.bb b/meta/recipes-devtools/file/file_5.16.bb
> index a15d952..f231a55 100644
> --- a/meta/recipes-devtools/file/file_5.16.bb
> +++ b/meta/recipes-devtools/file/file_5.16.bb
> @@ -12,6 +12,7 @@ DEPENDS = "zlib file-native"
>   DEPENDS_class-native = "zlib-native"
>   
>   SRC_URI = "ftp://ftp.astron.com/pub/file/file-${PV}.tar.gz \
> +           file://file-CVE-2014-9620-and-CVE-2014-9621.patch \
>              file://dump \
>              file://filesystems"
>   



  reply	other threads:[~2015-01-30  1:18 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-01-22  9:28 [daisy][PATCH] file: CVE-2014-9620 and CVE-2014-9621 Chong Lu
2015-01-30  1:18 ` Chong Lu [this message]
2015-01-30  3:57   ` Saul Wold
2015-02-02 13:55 ` Saul Wold
2015-02-03  1:23   ` Chong Lu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=54CADBE6.2030201@windriver.com \
    --to=chong.lu@windriver.com \
    --cc=openembedded-core@lists.openembedded.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.