From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pa0-f54.google.com (mail-pa0-f54.google.com [209.85.220.54]) by mail.openembedded.org (Postfix) with ESMTP id 72BF860034 for ; Fri, 30 Jan 2015 04:26:43 +0000 (UTC) Received: by mail-pa0-f54.google.com with SMTP id eu11so47401704pac.13 for ; Thu, 29 Jan 2015 20:26:44 -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=L/suLNXgMqzpWThZVklzc40NZbyX1jp8QmwOINfPCxw=; b=Q/tbU/cQOfWKhhlHY94HcbSSSDEkhgFna9STk+rFPLqIRFGMR57x1P74Zk9wAHUZa8 RAmlC4+qrXBH7fHRXUVT0ZBnWV5Bfec/QFt0jTrkDo5Bn/WTN9msO2XLH5zaENZB+a+J QepR0I7nhOZx7F5v9CGBRAdrWqvO7ohLaYFDU/t6RdR3jeX6ftJ9AkN+VXYa0MUOO85O eFhvkcByeMrf6gq0U1zYfV+jhz5j4BbWG7BvKfLwRySpm+3MmuIhwyDLzWVbkuiz5d/c dx/ei5uivY1HFjTOnLLWDaHeahfNt5qRZJw+28Nebq1662PEPnVknDugqlmiHE8KzWug jcUw== X-Received: by 10.66.187.237 with SMTP id fv13mr1796323pac.47.1422592004770; Thu, 29 Jan 2015 20:26:44 -0800 (PST) Received: from ?IPv6:2601:c:a700:272f:eda6:338:1977:847? ([2601:c:a700:272f:eda6:338:1977:847]) by mx.google.com with ESMTPSA id sy2sm1392208pbc.8.2015.01.29.20.26.42 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 29 Jan 2015 20:26:43 -0800 (PST) Message-ID: <54CB0800.80808@gmail.com> Date: Thu, 29 Jan 2015 20:26:40 -0800 From: akuster808 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.4.0 MIME-Version: 1.0 To: Chong Lu , openembedded-core@lists.openembedded.org References: <1422237365-25379-1-git-send-email-Chong.Lu@windriver.com> <54CADBBC.20905@windriver.com> In-Reply-To: <54CADBBC.20905@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: Fri, 30 Jan 2015 04:26:50 -0000 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit I have it merge in my staging repo. Will make a pull request soon. thanks for the reminder. - armin On 01/29/2015 05:17 PM, Chong Lu wrote: > ping > > //Chong > > On 01/26/2015 09:56 AM, Chong Lu wrote: >> CVE-2014-9620: >> Limit the number of ELF notes processed - DoS >> CVE-2014-9621: >> Limit string printing to 100 chars - DoS >> >> The patch comes from: >> https://github.com/file/file/commit/6ce24f35cd4a43c4bdd249e8e0c4952c1f8eac67 >> >> https://github.com/file/file/commit/0056ec32255de1de973574b0300161a1568767d6 >> >> https://github.com/file/file/commit/09e41625c999a2e5b51e1092f0ef2432a99b5c33 >> >> https://github.com/file/file/commit/af444af0738468393f40f9d2261b1ea10fc4b2ba >> >> https://github.com/file/file/commit/68bd8433c7e11a8dbe100deefdfac69138ee7cd9 >> >> https://github.com/file/file/commit/dddd3cdb95210a765dd90f7d722cb8b5534daee7 >> >> https://github.com/file/file/commit/445c8fb0ebff85195be94cd9f7e1df89cade5c7f >> >> https://github.com/file/file/commit/ce90e05774dd77d86cfc8dfa6da57b32816841c4 >> >> https://github.com/file/file/commit/65437cee25199dbd385fb35901bc0011e164276c >> >> >> [YOCTO #7178] >> >> Signed-off-by: Chong Lu >> --- >> .../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" >