From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.windriver.com (mail.windriver.com [147.11.1.11]) by mail.openembedded.org (Postfix) with ESMTP id 940F96E65B for ; Tue, 3 Feb 2015 01:23:32 +0000 (UTC) Received: from ALA-HCA.corp.ad.wrs.com (ala-hca.corp.ad.wrs.com [147.11.189.40]) by mail.windriver.com (8.14.9/8.14.5) with ESMTP id t131NXYk014161 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=FAIL); Mon, 2 Feb 2015 17:23:33 -0800 (PST) Received: from [128.224.162.204] (128.224.162.204) by ALA-HCA.corp.ad.wrs.com (147.11.189.50) with Microsoft SMTP Server (TLS) id 14.3.174.1; Mon, 2 Feb 2015 17:23:33 -0800 Message-ID: <54D02312.2020009@windriver.com> Date: Tue, 3 Feb 2015 09:23:30 +0800 From: Chong Lu User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.0 MIME-Version: 1.0 To: Saul Wold , References: <1421918914-28508-1-git-send-email-Chong.Lu@windriver.com> <54CF81CC.4060107@linux.intel.com> In-Reply-To: <54CF81CC.4060107@linux.intel.com> X-Originating-IP: [128.224.162.204] Subject: Re: [daisy][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: Tue, 03 Feb 2015 01:23:32 -0000 Content-Type: text/plain; charset="windows-1252"; format=flowed Content-Transfer-Encoding: 7bit On 02/02/2015 09:55 PM, Saul Wold wrote: > > I had some issues with this patch on the Autobuilder, it failed in > some cases for nativesdk-file on some, but not all machines of the > autobuilder. > > See: > https://autobuilder.yoctoproject.org/main/builders/nightly-arm/builds/178/steps/Building%20Toolchain%20Images/logs/stdio > > That's one example of the failure. OK. I will fix and resend one. Best Regards Chong > > Sau! > > > > On 01/22/2015 01:28 AM, Chong Lu wrote: >> CVE-2014-9620: >> Limit the number of ELF notes processed - DoS >> CVE-2014-9621: >> Limit string printing to 100 chars - DoS >> >> The patch comes from: >> https://github.com/file/file/commit/6ce24f35cd4a43c4bdd249e8e0c4952c1f8eac67 >> >> https://github.com/file/file/commit/0056ec32255de1de973574b0300161a1568767d6 >> >> https://github.com/file/file/commit/09e41625c999a2e5b51e1092f0ef2432a99b5c33 >> >> https://github.com/file/file/commit/af444af0738468393f40f9d2261b1ea10fc4b2ba >> >> https://github.com/file/file/commit/68bd8433c7e11a8dbe100deefdfac69138ee7cd9 >> >> https://github.com/file/file/commit/dddd3cdb95210a765dd90f7d722cb8b5534daee7 >> >> https://github.com/file/file/commit/445c8fb0ebff85195be94cd9f7e1df89cade5c7f >> >> https://github.com/file/file/commit/ce90e05774dd77d86cfc8dfa6da57b32816841c4 >> >> https://github.com/file/file/commit/65437cee25199dbd385fb35901bc0011e164276c >> >> >> [YOCTO #7178] >> >> Signed-off-by: Chong Lu >> --- >> .../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 >> +--- >> + 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, ¬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 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, "") == -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" >> >> > >