From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pa0-f47.google.com (mail-pa0-f47.google.com [209.85.220.47]) by mail.openembedded.org (Postfix) with ESMTP id EEEDC6AC95 for ; Mon, 26 Jan 2015 15:40:37 +0000 (UTC) Received: by mail-pa0-f47.google.com with SMTP id lj1so12352560pab.6 for ; Mon, 26 Jan 2015 07:40:38 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=message-id:date:from:user-agent:mime-version:to:subject:references :in-reply-to:content-type:content-transfer-encoding; bh=TVLk8C7XuIgQjWjm51KezwXnA8XlsSynN+pZE3ZuO5A=; b=UURG3GRxNG12tvmuf46HYPocmAnWT5oG2eZlblwjytJwdlRQb6Rkoql86rd0+MCy8t 4JkTCOCg8uWEHrBkVFgibqEv2DAFffnR86qdA54m0aoQN/IuuCj5CkoUTueK+oAkIGrg 3alnBisw84iz0dtdVoKmV4OTecDh+BEKolRvkQWQrZJ0/SHsGltFEE+411Y1Iz+JYbNK co2wlwhWUIF/RIVZzsJWa5FvsgeTplNXg42k4TGRWoYEI8QDO1PcPq++aGa6/wnRzNqD 3q48/H0Q8Lrij6FaUCP0bnLKXf6Qw1Hvz0smJa12sdVEXTCdqI/dnS/oV5HOII0LERHm VHyA== X-Received: by 10.66.138.72 with SMTP id qo8mr35767470pab.84.1422286836457; Mon, 26 Jan 2015 07:40:36 -0800 (PST) Received: from ?IPv6:2601:c:a700:272f:707b:3366:1172:a58? ([2601:c:a700:272f:707b:3366:1172:a58]) by mx.google.com with ESMTPSA id l4sm10057119pdj.47.2015.01.26.07.40.34 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 26 Jan 2015 07:40:35 -0800 (PST) Message-ID: <54C65FEF.3070801@gmail.com> Date: Mon, 26 Jan 2015 07:40:31 -0800 From: akuster808 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: Chong Lu , openembedded-core@lists.openembedded.org References: <1422237365-25379-1-git-send-email-Chong.Lu@windriver.com> In-Reply-To: <1422237365-25379-1-git-send-email-Chong.Lu@windriver.com> Subject: Re: [dizzy][PATCH] file: CVE-2014-9620 and CVE-2014-9621 X-BeenThere: openembedded-core@lists.openembedded.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: Patches and discussions about the oe-core layer List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 26 Jan 2015 15:40:41 -0000 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit thanks, Will add. Armin On 01/25/2015 05:56 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 > --- > .../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 > +--- > + 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, "") == -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" >