diff options
| author | Chong.Lu@windriver.com <Chong.Lu@windriver.com> | 2015-01-26 09:56:05 +0800 |
|---|---|---|
| committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-02-11 17:40:06 +0000 |
| commit | 86da1430b7ce05dfbdba2e57954394fdc38600a0 (patch) | |
| tree | 0941f1899e07511fe0f3907f8943b97d01cd69d6 | |
| parent | 2a53df980d8e86cca07012b741b8f126e451d438 (diff) | |
| download | poky-86da1430b7ce05dfbdba2e57954394fdc38600a0.tar.gz | |
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
[YOCTO #7178]
(From OE-Core rev: 0e4f0f893de2c0fac444b779b2b3028fd79e6048)
Signed-off-by: Chong Lu <Chong.Lu@windriver.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
| -rw-r--r-- | meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch | 1414 | ||||
| -rw-r--r-- | meta/recipes-devtools/file/file_5.18.bb | 1 |
2 files changed, 1415 insertions, 0 deletions
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 0000000000..2482de3998 --- /dev/null +++ b/meta/recipes-devtools/file/file/file-CVE-2014-9620-and-CVE-2014-9621.patch | |||
| @@ -0,0 +1,1414 @@ | |||
| 1 | file: CVE-2014-9620 and CVE-2014-9621 | ||
| 2 | |||
| 3 | CVE-2014-9620: | ||
| 4 | Limit the number of ELF notes processed - DoS | ||
| 5 | CVE-2014-9621: | ||
| 6 | Limit string printing to 100 chars - DoS | ||
| 7 | |||
| 8 | The patch comes from: | ||
| 9 | https://github.com/file/file/commit/6ce24f35cd4a43c4bdd249e8e0c4952c1f8eac67 | ||
| 10 | https://github.com/file/file/commit/0056ec32255de1de973574b0300161a1568767d6 | ||
| 11 | https://github.com/file/file/commit/09e41625c999a2e5b51e1092f0ef2432a99b5c33 | ||
| 12 | https://github.com/file/file/commit/af444af0738468393f40f9d2261b1ea10fc4b2ba | ||
| 13 | https://github.com/file/file/commit/68bd8433c7e11a8dbe100deefdfac69138ee7cd9 | ||
| 14 | https://github.com/file/file/commit/dddd3cdb95210a765dd90f7d722cb8b5534daee7 | ||
| 15 | https://github.com/file/file/commit/445c8fb0ebff85195be94cd9f7e1df89cade5c7f | ||
| 16 | https://github.com/file/file/commit/ce90e05774dd77d86cfc8dfa6da57b32816841c4 | ||
| 17 | https://github.com/file/file/commit/65437cee25199dbd385fb35901bc0011e164276c | ||
| 18 | |||
| 19 | Upstream-Status: Backport | ||
| 20 | |||
| 21 | Signed-off-by: Chong Lu <Chong.Lu@windriver.com> | ||
| 22 | --- | ||
| 23 | src/apprentice.c | 5 + | ||
| 24 | src/ascmagic.c | 3 +- | ||
| 25 | src/elfclass.h | 34 ++-- | ||
| 26 | src/file.c | 59 ++++++- | ||
| 27 | src/file.h | 20 ++- | ||
| 28 | src/file_opts.h | 6 + | ||
| 29 | src/funcs.c | 42 ++++- | ||
| 30 | src/magic.c | 50 ++++++ | ||
| 31 | src/magic.h | 9 ++ | ||
| 32 | src/magic.h.in | 9 ++ | ||
| 33 | src/readelf.c | 471 +++++++++++++++++++++++++++++++++---------------------- | ||
| 34 | src/softmagic.c | 93 ++++++----- | ||
| 35 | 12 files changed, 566 insertions(+), 235 deletions(-) | ||
| 36 | |||
| 37 | diff --git a/src/apprentice.c b/src/apprentice.c | ||
| 38 | index 7400c57..231dc7e 100644 | ||
| 39 | --- a/src/apprentice.c | ||
| 40 | +++ b/src/apprentice.c | ||
| 41 | @@ -506,6 +506,11 @@ file_ms_alloc(int flags) | ||
| 42 | ms->mlist[i] = NULL; | ||
| 43 | ms->file = "unknown"; | ||
| 44 | ms->line = 0; | ||
| 45 | + ms->indir_max = FILE_INDIR_MAX; | ||
| 46 | + ms->name_max = FILE_NAME_MAX; | ||
| 47 | + ms->elf_shnum_max = FILE_ELF_SHNUM_MAX; | ||
| 48 | + ms->elf_phnum_max = FILE_ELF_PHNUM_MAX; | ||
| 49 | + ms->elf_notes_max = FILE_ELF_NOTES_MAX; | ||
| 50 | return ms; | ||
| 51 | free: | ||
| 52 | free(ms); | ||
| 53 | diff --git a/src/ascmagic.c b/src/ascmagic.c | ||
| 54 | index ca26665..0a4cd10 100644 | ||
| 55 | --- a/src/ascmagic.c | ||
| 56 | +++ b/src/ascmagic.c | ||
| 57 | @@ -147,7 +147,8 @@ file_ascmagic_with_encoding(struct magic_set *ms, const unsigned char *buf, | ||
| 58 | == NULL) | ||
| 59 | goto done; | ||
| 60 | if ((rv = file_softmagic(ms, utf8_buf, | ||
| 61 | - (size_t)(utf8_end - utf8_buf), 0, TEXTTEST, text)) == 0) | ||
| 62 | + (size_t)(utf8_end - utf8_buf), 0, NULL, | ||
| 63 | + TEXTTEST, text)) == 0) | ||
| 64 | rv = -1; | ||
| 65 | } | ||
| 66 | |||
| 67 | diff --git a/src/elfclass.h b/src/elfclass.h | ||
| 68 | index 010958a..5360b0b 100644 | ||
| 69 | --- a/src/elfclass.h | ||
| 70 | +++ b/src/elfclass.h | ||
| 71 | @@ -32,39 +32,51 @@ | ||
| 72 | swap = (u.c[sizeof(int32_t) - 1] + 1) != elfhdr.e_ident[EI_DATA]; | ||
| 73 | |||
| 74 | type = elf_getu16(swap, elfhdr.e_type); | ||
| 75 | + notecount = ms->elf_notes_max; | ||
| 76 | switch (type) { | ||
| 77 | #ifdef ELFCORE | ||
| 78 | case ET_CORE: | ||
| 79 | + phnum = elf_getu16(swap, elfhdr.e_phnum); | ||
| 80 | + if (phnum > ms->elf_phnum_max) | ||
| 81 | + return toomany(ms, "program headers", phnum); | ||
| 82 | flags |= FLAGS_IS_CORE; | ||
| 83 | if (dophn_core(ms, clazz, swap, fd, | ||
| 84 | - (off_t)elf_getu(swap, elfhdr.e_phoff), | ||
| 85 | - elf_getu16(swap, elfhdr.e_phnum), | ||
| 86 | + (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, | ||
| 87 | (size_t)elf_getu16(swap, elfhdr.e_phentsize), | ||
| 88 | - fsize, &flags) == -1) | ||
| 89 | + fsize, &flags, ¬ecount) == -1) | ||
| 90 | return -1; | ||
| 91 | break; | ||
| 92 | #endif | ||
| 93 | case ET_EXEC: | ||
| 94 | case ET_DYN: | ||
| 95 | + phnum = elf_getu16(swap, elfhdr.e_phnum); | ||
| 96 | + if (phnum > ms->elf_phnum_max) | ||
| 97 | + return toomany(ms, "program", phnum); | ||
| 98 | + shnum = elf_getu16(swap, elfhdr.e_shnum); | ||
| 99 | + if (shnum > ms->elf_shnum_max) | ||
| 100 | + return toomany(ms, "section", shnum); | ||
| 101 | if (dophn_exec(ms, clazz, swap, fd, | ||
| 102 | - (off_t)elf_getu(swap, elfhdr.e_phoff), | ||
| 103 | - elf_getu16(swap, elfhdr.e_phnum), | ||
| 104 | + (off_t)elf_getu(swap, elfhdr.e_phoff), phnum, | ||
| 105 | (size_t)elf_getu16(swap, elfhdr.e_phentsize), | ||
| 106 | - fsize, &flags, elf_getu16(swap, elfhdr.e_shnum)) | ||
| 107 | - == -1) | ||
| 108 | + fsize, shnum, &flags, ¬ecount) == -1) | ||
| 109 | return -1; | ||
| 110 | /*FALLTHROUGH*/ | ||
| 111 | case ET_REL: | ||
| 112 | + shnum = elf_getu16(swap, elfhdr.e_shnum); | ||
| 113 | + if (shnum > ms->elf_shnum_max) | ||
| 114 | + return toomany(ms, "section headers", shnum); | ||
| 115 | if (doshn(ms, clazz, swap, fd, | ||
| 116 | - (off_t)elf_getu(swap, elfhdr.e_shoff), | ||
| 117 | - elf_getu16(swap, elfhdr.e_shnum), | ||
| 118 | + (off_t)elf_getu(swap, elfhdr.e_shoff), shnum, | ||
| 119 | (size_t)elf_getu16(swap, elfhdr.e_shentsize), | ||
| 120 | - fsize, &flags, elf_getu16(swap, elfhdr.e_machine), | ||
| 121 | - (int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1) | ||
| 122 | + fsize, elf_getu16(swap, elfhdr.e_machine), | ||
| 123 | + (int)elf_getu16(swap, elfhdr.e_shstrndx), | ||
| 124 | + &flags, ¬ecount) == -1) | ||
| 125 | return -1; | ||
| 126 | break; | ||
| 127 | |||
| 128 | default: | ||
| 129 | break; | ||
| 130 | } | ||
| 131 | + if (notecount == 0) | ||
| 132 | + return toomany(ms, "notes", ms->elf_notes_max); | ||
| 133 | return 1; | ||
| 134 | diff --git a/src/file.c b/src/file.c | ||
| 135 | index 370da91..b69b725 100644 | ||
| 136 | --- a/src/file.c | ||
| 137 | +++ b/src/file.c | ||
| 138 | @@ -101,7 +101,7 @@ private const struct option long_options[] = { | ||
| 139 | #undef OPT_LONGONLY | ||
| 140 | {0, 0, NULL, 0} | ||
| 141 | }; | ||
| 142 | -#define OPTSTRING "bcCde:Ef:F:hiklLm:nNprsvz0" | ||
| 143 | +#define OPTSTRING "bcCde:Ef:F:hiklLm:nNpP:rsvz0" | ||
| 144 | |||
| 145 | private const struct { | ||
| 146 | const char *name; | ||
| 147 | @@ -119,6 +119,18 @@ private const struct { | ||
| 148 | { "tokens", MAGIC_NO_CHECK_TOKENS }, /* OBSOLETE: ignored for backwards compatibility */ | ||
| 149 | }; | ||
| 150 | |||
| 151 | +private struct { | ||
| 152 | + const char *name; | ||
| 153 | + int tag; | ||
| 154 | + size_t value; | ||
| 155 | +} pm[] = { | ||
| 156 | + { "indir", MAGIC_PARAM_INDIR_MAX, 0 }, | ||
| 157 | + { "name", MAGIC_PARAM_NAME_MAX, 0 }, | ||
| 158 | + { "elf_phnum", MAGIC_PARAM_ELF_PHNUM_MAX, 0 }, | ||
| 159 | + { "elf_shnum", MAGIC_PARAM_ELF_SHNUM_MAX, 0 }, | ||
| 160 | + { "elf_notes", MAGIC_PARAM_ELF_NOTES_MAX, 0 }, | ||
| 161 | +}; | ||
| 162 | + | ||
| 163 | private char *progname; /* used throughout */ | ||
| 164 | |||
| 165 | private void usage(void); | ||
| 166 | @@ -128,6 +140,8 @@ private void help(void); | ||
| 167 | private int unwrap(struct magic_set *, const char *); | ||
| 168 | private int process(struct magic_set *ms, const char *, int); | ||
| 169 | private struct magic_set *load(const char *, int); | ||
| 170 | +private void setparam(const char *); | ||
| 171 | +private void applyparam(magic_t); | ||
| 172 | |||
| 173 | |||
| 174 | /* | ||
| 175 | @@ -243,9 +257,13 @@ main(int argc, char *argv[]) | ||
| 176 | flags |= MAGIC_PRESERVE_ATIME; | ||
| 177 | break; | ||
| 178 | #endif | ||
| 179 | + case 'P': | ||
| 180 | + setparam(optarg); | ||
| 181 | + break; | ||
| 182 | case 'r': | ||
| 183 | flags |= MAGIC_RAW; | ||
| 184 | break; | ||
| 185 | + break; | ||
| 186 | case 's': | ||
| 187 | flags |= MAGIC_DEVICES; | ||
| 188 | break; | ||
| 189 | @@ -298,6 +316,8 @@ main(int argc, char *argv[]) | ||
| 190 | strerror(errno)); | ||
| 191 | return 1; | ||
| 192 | } | ||
| 193 | + | ||
| 194 | + | ||
| 195 | switch(action) { | ||
| 196 | case FILE_CHECK: | ||
| 197 | c = magic_check(magic, magicfile); | ||
| 198 | @@ -321,7 +341,7 @@ main(int argc, char *argv[]) | ||
| 199 | if (magic == NULL) | ||
| 200 | if ((magic = load(magicfile, flags)) == NULL) | ||
| 201 | return 1; | ||
| 202 | - break; | ||
| 203 | + applyparam(magic); | ||
| 204 | } | ||
| 205 | |||
| 206 | if (optind == argc) { | ||
| 207 | @@ -351,6 +371,41 @@ main(int argc, char *argv[]) | ||
| 208 | return e; | ||
| 209 | } | ||
| 210 | |||
| 211 | +private void | ||
| 212 | +applyparam(magic_t magic) | ||
| 213 | +{ | ||
| 214 | + size_t i; | ||
| 215 | + | ||
| 216 | + for (i = 0; i < __arraycount(pm); i++) { | ||
| 217 | + if (pm[i].value == 0) | ||
| 218 | + continue; | ||
| 219 | + if (magic_setparam(magic, pm[i].tag, &pm[i].value) == -1) { | ||
| 220 | + (void)fprintf(stderr, "%s: Can't set %s %s\n", progname, | ||
| 221 | + pm[i].name, strerror(errno)); | ||
| 222 | + exit(1); | ||
| 223 | + } | ||
| 224 | + } | ||
| 225 | +} | ||
| 226 | + | ||
| 227 | +private void | ||
| 228 | +setparam(const char *p) | ||
| 229 | +{ | ||
| 230 | + size_t i; | ||
| 231 | + char *s; | ||
| 232 | + | ||
| 233 | + if ((s = strchr(p, '=')) == NULL) | ||
| 234 | + goto badparm; | ||
| 235 | + | ||
| 236 | + for (i = 0; i < __arraycount(pm); i++) { | ||
| 237 | + if (strncmp(p, pm[i].name, s - p) != 0) | ||
| 238 | + continue; | ||
| 239 | + pm[i].value = atoi(s + 1); | ||
| 240 | + return; | ||
| 241 | + } | ||
| 242 | +badparm: | ||
| 243 | + (void)fprintf(stderr, "%s: Unknown param %s\n", progname, p); | ||
| 244 | + exit(1); | ||
| 245 | +} | ||
| 246 | |||
| 247 | private struct magic_set * | ||
| 248 | /*ARGSUSED*/ | ||
| 249 | diff --git a/src/file.h b/src/file.h | ||
| 250 | index 5c67ddd..88da1d1 100644 | ||
| 251 | --- a/src/file.h | ||
| 252 | +++ b/src/file.h | ||
| 253 | @@ -400,6 +400,16 @@ struct magic_set { | ||
| 254 | /* FIXME: Make the string dynamically allocated so that e.g. | ||
| 255 | strings matched in files can be longer than MAXstring */ | ||
| 256 | union VALUETYPE ms_value; /* either number or string */ | ||
| 257 | + uint16_t indir_max; | ||
| 258 | + uint16_t name_max; | ||
| 259 | + uint16_t elf_shnum_max; | ||
| 260 | + uint16_t elf_phnum_max; | ||
| 261 | + uint16_t elf_notes_max; | ||
| 262 | +#define FILE_INDIR_MAX 15 | ||
| 263 | +#define FILE_NAME_MAX 30 | ||
| 264 | +#define FILE_ELF_SHNUM_MAX 32768 | ||
| 265 | +#define FILE_ELF_PHNUM_MAX 128 | ||
| 266 | +#define FILE_ELF_NOTES_MAX 256 | ||
| 267 | }; | ||
| 268 | |||
| 269 | /* Type for Unicode characters */ | ||
| 270 | @@ -439,7 +449,7 @@ protected int file_encoding(struct magic_set *, const unsigned char *, size_t, | ||
| 271 | unichar **, size_t *, const char **, const char **, const char **); | ||
| 272 | protected int file_is_tar(struct magic_set *, const unsigned char *, size_t); | ||
| 273 | protected int file_softmagic(struct magic_set *, const unsigned char *, size_t, | ||
| 274 | - size_t, int, int); | ||
| 275 | + uint16_t, uint16_t *, int, int); | ||
| 276 | protected int file_apprentice(struct magic_set *, const char *, int); | ||
| 277 | protected int file_magicfind(struct magic_set *, const char *, struct mlist *); | ||
| 278 | protected uint64_t file_signextend(struct magic_set *, struct magic *, | ||
| 279 | @@ -469,6 +479,14 @@ protected int file_os2_apptype(struct magic_set *, const char *, const void *, | ||
| 280 | #endif /* __EMX__ */ | ||
| 281 | |||
| 282 | |||
| 283 | +typedef struct { | ||
| 284 | + char *buf; | ||
| 285 | + uint32_t offset; | ||
| 286 | +} file_pushbuf_t; | ||
| 287 | + | ||
| 288 | +protected file_pushbuf_t *file_push_buffer(struct magic_set *); | ||
| 289 | +protected char *file_pop_buffer(struct magic_set *, file_pushbuf_t *); | ||
| 290 | + | ||
| 291 | #ifndef COMPILE_ONLY | ||
| 292 | extern const char *file_names[]; | ||
| 293 | extern const size_t file_nnames; | ||
| 294 | diff --git a/src/file_opts.h b/src/file_opts.h | ||
| 295 | index db34eb7..3286ac6 100644 | ||
| 296 | --- a/src/file_opts.h | ||
| 297 | +++ b/src/file_opts.h | ||
| 298 | @@ -43,6 +43,12 @@ OPT('0', "print0", 0, " terminate filenames with ASCII NUL\n") | ||
| 299 | #if defined(HAVE_UTIME) || defined(HAVE_UTIMES) | ||
| 300 | OPT('p', "preserve-date", 0, " preserve access times on files\n") | ||
| 301 | #endif | ||
| 302 | +OPT('P', "parameter", 0, " set file engine parameter limits\n" | ||
| 303 | + " indir 15 recursion limit for indirection\n" | ||
| 304 | + " name 30 use limit for name/use magic\n" | ||
| 305 | + " elf_notes 256 max ELF notes processed\n" | ||
| 306 | + " elf_phnum 128 max ELF prog sections processed\n" | ||
| 307 | + " elf_shnum 32768 max ELF sections processed\n") | ||
| 308 | OPT('r', "raw", 0, " don't translate unprintable chars to \\ooo\n") | ||
| 309 | OPT('s', "special-files", 0, " treat special (block/char devices) files as\n" | ||
| 310 | " ordinary ones\n") | ||
| 311 | diff --git a/src/funcs.c b/src/funcs.c | ||
| 312 | index a9624a2..c3cf2be 100644 | ||
| 313 | --- a/src/funcs.c | ||
| 314 | +++ b/src/funcs.c | ||
| 315 | @@ -230,7 +230,7 @@ file_buffer(struct magic_set *ms, int fd, const char *inname __attribute__ ((unu | ||
| 316 | |||
| 317 | /* try soft magic tests */ | ||
| 318 | if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) | ||
| 319 | - if ((m = file_softmagic(ms, ubuf, nb, 0, BINTEST, | ||
| 320 | + if ((m = file_softmagic(ms, ubuf, nb, 0, NULL, BINTEST, | ||
| 321 | looks_text)) != 0) { | ||
| 322 | if ((ms->flags & MAGIC_DEBUG) != 0) | ||
| 323 | (void)fprintf(stderr, "softmagic %d\n", m); | ||
| 324 | @@ -459,3 +459,43 @@ out: | ||
| 325 | free(old_lc_ctype); | ||
| 326 | return rv; | ||
| 327 | } | ||
| 328 | + | ||
| 329 | +protected file_pushbuf_t * | ||
| 330 | +file_push_buffer(struct magic_set *ms) | ||
| 331 | +{ | ||
| 332 | + file_pushbuf_t *pb; | ||
| 333 | + | ||
| 334 | + if (ms->event_flags & EVENT_HAD_ERR) | ||
| 335 | + return NULL; | ||
| 336 | + | ||
| 337 | + if ((pb = (CAST(file_pushbuf_t *, malloc(sizeof(*pb))))) == NULL) | ||
| 338 | + return NULL; | ||
| 339 | + | ||
| 340 | + pb->buf = ms->o.buf; | ||
| 341 | + pb->offset = ms->offset; | ||
| 342 | + | ||
| 343 | + ms->o.buf = NULL; | ||
| 344 | + ms->offset = 0; | ||
| 345 | + | ||
| 346 | + return pb; | ||
| 347 | +} | ||
| 348 | + | ||
| 349 | +protected char * | ||
| 350 | +file_pop_buffer(struct magic_set *ms, file_pushbuf_t *pb) | ||
| 351 | +{ | ||
| 352 | + char *rbuf; | ||
| 353 | + | ||
| 354 | + if (ms->event_flags & EVENT_HAD_ERR) { | ||
| 355 | + free(pb->buf); | ||
| 356 | + free(pb); | ||
| 357 | + return NULL; | ||
| 358 | + } | ||
| 359 | + | ||
| 360 | + rbuf = ms->o.buf; | ||
| 361 | + | ||
| 362 | + ms->o.buf = pb->buf; | ||
| 363 | + ms->offset = pb->offset; | ||
| 364 | + | ||
| 365 | + free(pb); | ||
| 366 | + return rbuf; | ||
| 367 | +} | ||
| 368 | diff --git a/src/magic.c b/src/magic.c | ||
| 369 | index 22174b8..a89647c 100644 | ||
| 370 | --- a/src/magic.c | ||
| 371 | +++ b/src/magic.c | ||
| 372 | @@ -490,3 +490,53 @@ magic_version(void) | ||
| 373 | { | ||
| 374 | return MAGIC_VERSION; | ||
| 375 | } | ||
| 376 | + | ||
| 377 | +public int | ||
| 378 | +magic_setparam(struct magic_set *ms, int param, const void *val) | ||
| 379 | +{ | ||
| 380 | + switch (param) { | ||
| 381 | + case MAGIC_PARAM_INDIR_MAX: | ||
| 382 | + ms->indir_max = *(const size_t *)val; | ||
| 383 | + return 0; | ||
| 384 | + case MAGIC_PARAM_NAME_MAX: | ||
| 385 | + ms->name_max = *(const size_t *)val; | ||
| 386 | + return 0; | ||
| 387 | + case MAGIC_PARAM_ELF_PHNUM_MAX: | ||
| 388 | + ms->elf_phnum_max = *(const size_t *)val; | ||
| 389 | + return 0; | ||
| 390 | + case MAGIC_PARAM_ELF_SHNUM_MAX: | ||
| 391 | + ms->elf_shnum_max = *(const size_t *)val; | ||
| 392 | + return 0; | ||
| 393 | + case MAGIC_PARAM_ELF_NOTES_MAX: | ||
| 394 | + ms->elf_notes_max = *(const size_t *)val; | ||
| 395 | + return 0; | ||
| 396 | + default: | ||
| 397 | + errno = EINVAL; | ||
| 398 | + return -1; | ||
| 399 | + } | ||
| 400 | +} | ||
| 401 | + | ||
| 402 | +public int | ||
| 403 | +magic_getparam(struct magic_set *ms, int param, void *val) | ||
| 404 | +{ | ||
| 405 | + switch (param) { | ||
| 406 | + case MAGIC_PARAM_INDIR_MAX: | ||
| 407 | + *(size_t *)val = ms->indir_max; | ||
| 408 | + return 0; | ||
| 409 | + case MAGIC_PARAM_NAME_MAX: | ||
| 410 | + *(size_t *)val = ms->name_max; | ||
| 411 | + return 0; | ||
| 412 | + case MAGIC_PARAM_ELF_PHNUM_MAX: | ||
| 413 | + *(size_t *)val = ms->elf_phnum_max; | ||
| 414 | + return 0; | ||
| 415 | + case MAGIC_PARAM_ELF_SHNUM_MAX: | ||
| 416 | + *(size_t *)val = ms->elf_shnum_max; | ||
| 417 | + return 0; | ||
| 418 | + case MAGIC_PARAM_ELF_NOTES_MAX: | ||
| 419 | + *(size_t *)val = ms->elf_notes_max; | ||
| 420 | + return 0; | ||
| 421 | + default: | ||
| 422 | + errno = EINVAL; | ||
| 423 | + return -1; | ||
| 424 | + } | ||
| 425 | +} | ||
| 426 | diff --git a/src/magic.h b/src/magic.h | ||
| 427 | index 535a177..89bfe4b 100644 | ||
| 428 | --- a/src/magic.h | ||
| 429 | +++ b/src/magic.h | ||
| 430 | @@ -101,6 +101,15 @@ int magic_check(magic_t, const char *); | ||
| 431 | int magic_list(magic_t, const char *); | ||
| 432 | int magic_errno(magic_t); | ||
| 433 | |||
| 434 | +#define MAGIC_PARAM_INDIR_MAX 0 | ||
| 435 | +#define MAGIC_PARAM_NAME_MAX 1 | ||
| 436 | +#define MAGIC_PARAM_ELF_PHNUM_MAX 2 | ||
| 437 | +#define MAGIC_PARAM_ELF_SHNUM_MAX 3 | ||
| 438 | +#define MAGIC_PARAM_ELF_NOTES_MAX 4 | ||
| 439 | + | ||
| 440 | +int magic_setparam(magic_t, int, const void *); | ||
| 441 | +int magic_getparam(magic_t, int, void *); | ||
| 442 | + | ||
| 443 | #ifdef __cplusplus | ||
| 444 | }; | ||
| 445 | #endif | ||
| 446 | diff --git a/src/magic.h.in b/src/magic.h.in | ||
| 447 | index 86fc41b..2efc7bc 100644 | ||
| 448 | --- a/src/magic.h.in | ||
| 449 | +++ b/src/magic.h.in | ||
| 450 | @@ -101,6 +101,15 @@ int magic_check(magic_t, const char *); | ||
| 451 | int magic_list(magic_t, const char *); | ||
| 452 | int magic_errno(magic_t); | ||
| 453 | |||
| 454 | +#define MAGIC_PARAM_INDIR_MAX 0 | ||
| 455 | +#define MAGIC_PARAM_NAME_MAX 1 | ||
| 456 | +#define MAGIC_PARAM_ELF_PHNUM_MAX 2 | ||
| 457 | +#define MAGIC_PARAM_ELF_SHNUM_MAX 3 | ||
| 458 | +#define MAGIC_PARAM_ELF_NOTES_MAX 4 | ||
| 459 | + | ||
| 460 | +int magic_setparam(magic_t, int, const void *); | ||
| 461 | +int magic_getparam(magic_t, int, void *); | ||
| 462 | + | ||
| 463 | #ifdef __cplusplus | ||
| 464 | }; | ||
| 465 | #endif | ||
| 466 | diff --git a/src/readelf.c b/src/readelf.c | ||
| 467 | index cbed129..87df727 100644 | ||
| 468 | --- a/src/readelf.c | ||
| 469 | +++ b/src/readelf.c | ||
| 470 | @@ -43,14 +43,14 @@ FILE_RCSID("@(#)$File: readelf.c,v 1.102 2014/03/11 21:00:13 christos Exp $") | ||
| 471 | |||
| 472 | #ifdef ELFCORE | ||
| 473 | private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t, | ||
| 474 | - off_t, int *); | ||
| 475 | + off_t, int *, uint16_t *); | ||
| 476 | #endif | ||
| 477 | private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t, | ||
| 478 | - off_t, int *, int); | ||
| 479 | + off_t, int, int *, uint16_t *); | ||
| 480 | private int doshn(struct magic_set *, int, int, int, off_t, int, size_t, | ||
| 481 | - off_t, int *, int, int); | ||
| 482 | + off_t, int, int, int *, uint16_t *); | ||
| 483 | private size_t donote(struct magic_set *, void *, size_t, size_t, int, | ||
| 484 | - int, size_t, int *); | ||
| 485 | + int, size_t, int *, uint16_t *); | ||
| 486 | |||
| 487 | #define ELF_ALIGN(a) ((((a) + align - 1) / align) * align) | ||
| 488 | |||
| 489 | @@ -60,6 +60,19 @@ private uint16_t getu16(int, uint16_t); | ||
| 490 | private uint32_t getu32(int, uint32_t); | ||
| 491 | private uint64_t getu64(int, uint64_t); | ||
| 492 | |||
| 493 | +#define MAX_PHNUM 128 | ||
| 494 | +#define MAX_SHNUM 32768 | ||
| 495 | +#define SIZE_UNKNOWN ((off_t)-1) | ||
| 496 | + | ||
| 497 | +private int | ||
| 498 | +toomany(struct magic_set *ms, const char *name, uint16_t num) | ||
| 499 | +{ | ||
| 500 | + if (file_printf(ms, ", too many %s (%u)", name, num | ||
| 501 | + ) == -1) | ||
| 502 | + return -1; | ||
| 503 | + return 0; | ||
| 504 | +} | ||
| 505 | + | ||
| 506 | private uint16_t | ||
| 507 | getu16(int swap, uint16_t value) | ||
| 508 | { | ||
| 509 | @@ -280,15 +293,19 @@ private const char os_style_names[][8] = { | ||
| 510 | "NetBSD", | ||
| 511 | }; | ||
| 512 | |||
| 513 | -#define FLAGS_DID_CORE 0x01 | ||
| 514 | -#define FLAGS_DID_NOTE 0x02 | ||
| 515 | -#define FLAGS_DID_BUILD_ID 0x04 | ||
| 516 | -#define FLAGS_DID_CORE_STYLE 0x08 | ||
| 517 | -#define FLAGS_IS_CORE 0x10 | ||
| 518 | +#define FLAGS_DID_CORE 0x001 | ||
| 519 | +#define FLAGS_DID_OS_NOTE 0x002 | ||
| 520 | +#define FLAGS_DID_BUILD_ID 0x004 | ||
| 521 | +#define FLAGS_DID_CORE_STYLE 0x008 | ||
| 522 | +#define FLAGS_DID_NETBSD_PAX 0x010 | ||
| 523 | +#define FLAGS_DID_NETBSD_MARCH 0x020 | ||
| 524 | +#define FLAGS_DID_NETBSD_CMODEL 0x040 | ||
| 525 | +#define FLAGS_DID_NETBSD_UNKNOWN 0x080 | ||
| 526 | +#define FLAGS_IS_CORE 0x100 | ||
| 527 | |||
| 528 | private int | ||
| 529 | dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, | ||
| 530 | - int num, size_t size, off_t fsize, int *flags) | ||
| 531 | + int num, size_t size, off_t fsize, int *flags, uint16_t *notecount) | ||
| 532 | { | ||
| 533 | Elf32_Phdr ph32; | ||
| 534 | Elf64_Phdr ph64; | ||
| 535 | @@ -306,13 +323,13 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, | ||
| 536 | * Loop through all the program headers. | ||
| 537 | */ | ||
| 538 | for ( ; num; num--) { | ||
| 539 | - if (pread(fd, xph_addr, xph_sizeof, off) == -1) { | ||
| 540 | + if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { | ||
| 541 | file_badread(ms); | ||
| 542 | return -1; | ||
| 543 | } | ||
| 544 | off += size; | ||
| 545 | |||
| 546 | - if (xph_offset > fsize) { | ||
| 547 | + if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { | ||
| 548 | /* Perhaps warn here */ | ||
| 549 | continue; | ||
| 550 | } | ||
| 551 | @@ -334,7 +351,7 @@ dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, | ||
| 552 | if (offset >= (size_t)bufsize) | ||
| 553 | break; | ||
| 554 | offset = donote(ms, nbuf, offset, (size_t)bufsize, | ||
| 555 | - clazz, swap, 4, flags); | ||
| 556 | + clazz, swap, 4, flags, notecount); | ||
| 557 | if (offset == 0) | ||
| 558 | break; | ||
| 559 | |||
| 560 | @@ -464,125 +481,128 @@ do_note_freebsd_version(struct magic_set *ms, int swap, void *v) | ||
| 561 | } | ||
| 562 | } | ||
| 563 | |||
| 564 | -private size_t | ||
| 565 | -donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, | ||
| 566 | - int clazz, int swap, size_t align, int *flags) | ||
| 567 | +private int | ||
| 568 | +do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, | ||
| 569 | + int swap __attribute__((__unused__)), uint32_t namesz, uint32_t descsz, | ||
| 570 | + size_t noff, size_t doff, int *flags) | ||
| 571 | { | ||
| 572 | - Elf32_Nhdr nh32; | ||
| 573 | - Elf64_Nhdr nh64; | ||
| 574 | - size_t noff, doff; | ||
| 575 | -#ifdef ELFCORE | ||
| 576 | - int os_style = -1; | ||
| 577 | -#endif | ||
| 578 | - uint32_t namesz, descsz; | ||
| 579 | - unsigned char *nbuf = CAST(unsigned char *, vbuf); | ||
| 580 | - | ||
| 581 | - (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); | ||
| 582 | - offset += xnh_sizeof; | ||
| 583 | - | ||
| 584 | - namesz = xnh_namesz; | ||
| 585 | - descsz = xnh_descsz; | ||
| 586 | - if ((namesz == 0) && (descsz == 0)) { | ||
| 587 | - /* | ||
| 588 | - * We're out of note headers. | ||
| 589 | - */ | ||
| 590 | - return (offset >= size) ? offset : size; | ||
| 591 | - } | ||
| 592 | - | ||
| 593 | - if (namesz & 0x80000000) { | ||
| 594 | - (void)file_printf(ms, ", bad note name size 0x%lx", | ||
| 595 | - (unsigned long)namesz); | ||
| 596 | - return offset; | ||
| 597 | - } | ||
| 598 | - | ||
| 599 | - if (descsz & 0x80000000) { | ||
| 600 | - (void)file_printf(ms, ", bad note description size 0x%lx", | ||
| 601 | - (unsigned long)descsz); | ||
| 602 | - return offset; | ||
| 603 | - } | ||
| 604 | - | ||
| 605 | - | ||
| 606 | - noff = offset; | ||
| 607 | - doff = ELF_ALIGN(offset + namesz); | ||
| 608 | - | ||
| 609 | - if (offset + namesz > size) { | ||
| 610 | - /* | ||
| 611 | - * We're past the end of the buffer. | ||
| 612 | - */ | ||
| 613 | - return doff; | ||
| 614 | - } | ||
| 615 | - | ||
| 616 | - offset = ELF_ALIGN(doff + descsz); | ||
| 617 | - if (doff + descsz > size) { | ||
| 618 | - /* | ||
| 619 | - * We're past the end of the buffer. | ||
| 620 | - */ | ||
| 621 | - return (offset >= size) ? offset : size; | ||
| 622 | + if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && | ||
| 623 | + type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) { | ||
| 624 | + uint8_t desc[20]; | ||
| 625 | + uint32_t i; | ||
| 626 | + *flags |= FLAGS_DID_BUILD_ID; | ||
| 627 | + if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" : | ||
| 628 | + "sha1") == -1) | ||
| 629 | + return 1; | ||
| 630 | + (void)memcpy(desc, &nbuf[doff], descsz); | ||
| 631 | + for (i = 0; i < descsz; i++) | ||
| 632 | + if (file_printf(ms, "%02x", desc[i]) == -1) | ||
| 633 | + return 1; | ||
| 634 | + return 1; | ||
| 635 | } | ||
| 636 | - | ||
| 637 | - if ((*flags & (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID)) == | ||
| 638 | - (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID)) | ||
| 639 | - goto core; | ||
| 640 | - | ||
| 641 | + return 0; | ||
| 642 | +} | ||
| 643 | + | ||
| 644 | +private int | ||
| 645 | +do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, | ||
| 646 | + int swap, uint32_t namesz, uint32_t descsz, | ||
| 647 | + size_t noff, size_t doff, int *flags) | ||
| 648 | +{ | ||
| 649 | if (namesz == 5 && strcmp((char *)&nbuf[noff], "SuSE") == 0 && | ||
| 650 | - xnh_type == NT_GNU_VERSION && descsz == 2) { | ||
| 651 | + type == NT_GNU_VERSION && descsz == 2) { | ||
| 652 | + *flags |= FLAGS_DID_OS_NOTE; | ||
| 653 | file_printf(ms, ", for SuSE %d.%d", nbuf[doff], nbuf[doff + 1]); | ||
| 654 | + return 1; | ||
| 655 | } | ||
| 656 | + | ||
| 657 | if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && | ||
| 658 | - xnh_type == NT_GNU_VERSION && descsz == 16) { | ||
| 659 | + type == NT_GNU_VERSION && descsz == 16) { | ||
| 660 | uint32_t desc[4]; | ||
| 661 | (void)memcpy(desc, &nbuf[doff], sizeof(desc)); | ||
| 662 | |||
| 663 | + *flags |= FLAGS_DID_OS_NOTE; | ||
| 664 | if (file_printf(ms, ", for GNU/") == -1) | ||
| 665 | - return size; | ||
| 666 | + return 1; | ||
| 667 | switch (elf_getu32(swap, desc[0])) { | ||
| 668 | case GNU_OS_LINUX: | ||
| 669 | if (file_printf(ms, "Linux") == -1) | ||
| 670 | - return size; | ||
| 671 | + return 1; | ||
| 672 | break; | ||
| 673 | case GNU_OS_HURD: | ||
| 674 | if (file_printf(ms, "Hurd") == -1) | ||
| 675 | - return size; | ||
| 676 | + return 1; | ||
| 677 | break; | ||
| 678 | case GNU_OS_SOLARIS: | ||
| 679 | if (file_printf(ms, "Solaris") == -1) | ||
| 680 | - return size; | ||
| 681 | + return 1; | ||
| 682 | break; | ||
| 683 | case GNU_OS_KFREEBSD: | ||
| 684 | if (file_printf(ms, "kFreeBSD") == -1) | ||
| 685 | - return size; | ||
| 686 | + return 1; | ||
| 687 | break; | ||
| 688 | case GNU_OS_KNETBSD: | ||
| 689 | if (file_printf(ms, "kNetBSD") == -1) | ||
| 690 | - return size; | ||
| 691 | + return 1; | ||
| 692 | break; | ||
| 693 | default: | ||
| 694 | if (file_printf(ms, "<unknown>") == -1) | ||
| 695 | - return size; | ||
| 696 | + return 1; | ||
| 697 | } | ||
| 698 | if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]), | ||
| 699 | elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1) | ||
| 700 | - return size; | ||
| 701 | - *flags |= FLAGS_DID_NOTE; | ||
| 702 | - return size; | ||
| 703 | + return 1; | ||
| 704 | + return 1; | ||
| 705 | } | ||
| 706 | |||
| 707 | - if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && | ||
| 708 | - xnh_type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) { | ||
| 709 | - uint8_t desc[20]; | ||
| 710 | - uint32_t i; | ||
| 711 | - if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" : | ||
| 712 | - "sha1") == -1) | ||
| 713 | - return size; | ||
| 714 | - (void)memcpy(desc, &nbuf[doff], descsz); | ||
| 715 | - for (i = 0; i < descsz; i++) | ||
| 716 | - if (file_printf(ms, "%02x", desc[i]) == -1) | ||
| 717 | - return size; | ||
| 718 | - *flags |= FLAGS_DID_BUILD_ID; | ||
| 719 | + if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { | ||
| 720 | + if (type == NT_NETBSD_VERSION && descsz == 4) { | ||
| 721 | + *flags |= FLAGS_DID_OS_NOTE; | ||
| 722 | + do_note_netbsd_version(ms, swap, &nbuf[doff]); | ||
| 723 | + return 1; | ||
| 724 | + } | ||
| 725 | + } | ||
| 726 | + | ||
| 727 | + if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { | ||
| 728 | + if (type == NT_FREEBSD_VERSION && descsz == 4) { | ||
| 729 | + *flags |= FLAGS_DID_OS_NOTE; | ||
| 730 | + do_note_freebsd_version(ms, swap, &nbuf[doff]); | ||
| 731 | + return 1; | ||
| 732 | + } | ||
| 733 | + } | ||
| 734 | + | ||
| 735 | + if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && | ||
| 736 | + type == NT_OPENBSD_VERSION && descsz == 4) { | ||
| 737 | + *flags |= FLAGS_DID_OS_NOTE; | ||
| 738 | + if (file_printf(ms, ", for OpenBSD") == -1) | ||
| 739 | + return 1; | ||
| 740 | + /* Content of note is always 0 */ | ||
| 741 | + return 1; | ||
| 742 | + } | ||
| 743 | + | ||
| 744 | + if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 && | ||
| 745 | + type == NT_DRAGONFLY_VERSION && descsz == 4) { | ||
| 746 | + uint32_t desc; | ||
| 747 | + *flags |= FLAGS_DID_OS_NOTE; | ||
| 748 | + if (file_printf(ms, ", for DragonFly") == -1) | ||
| 749 | + return 1; | ||
| 750 | + (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); | ||
| 751 | + desc = elf_getu32(swap, desc); | ||
| 752 | + if (file_printf(ms, " %d.%d.%d", desc / 100000, | ||
| 753 | + desc / 10000 % 10, desc % 10000) == -1) | ||
| 754 | + return 1; | ||
| 755 | + return 1; | ||
| 756 | } | ||
| 757 | + return 0; | ||
| 758 | +} | ||
| 759 | + | ||
| 760 | +private int | ||
| 761 | +do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, | ||
| 762 | + int swap, uint32_t namesz, uint32_t descsz, | ||
| 763 | + size_t noff, size_t doff, int *flags) | ||
| 764 | +{ | ||
| 765 | |||
| 766 | if (namesz == 4 && strcmp((char *)&nbuf[noff], "PaX") == 0 && | ||
| 767 | - xnh_type == NT_NETBSD_PAX && descsz == 4) { | ||
| 768 | + type == NT_NETBSD_PAX && descsz == 4) { | ||
| 769 | static const char *pax[] = { | ||
| 770 | "+mprotect", | ||
| 771 | "-mprotect", | ||
| 772 | @@ -595,80 +615,32 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, | ||
| 773 | size_t i; | ||
| 774 | int did = 0; | ||
| 775 | |||
| 776 | + *flags |= FLAGS_DID_NETBSD_PAX; | ||
| 777 | (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); | ||
| 778 | desc = elf_getu32(swap, desc); | ||
| 779 | |||
| 780 | if (desc && file_printf(ms, ", PaX: ") == -1) | ||
| 781 | - return size; | ||
| 782 | + return 1; | ||
| 783 | |||
| 784 | for (i = 0; i < __arraycount(pax); i++) { | ||
| 785 | if (((1 << i) & desc) == 0) | ||
| 786 | continue; | ||
| 787 | if (file_printf(ms, "%s%s", did++ ? "," : "", | ||
| 788 | pax[i]) == -1) | ||
| 789 | - return size; | ||
| 790 | - } | ||
| 791 | - } | ||
| 792 | - | ||
| 793 | - if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { | ||
| 794 | - switch (xnh_type) { | ||
| 795 | - case NT_NETBSD_VERSION: | ||
| 796 | - if (descsz == 4) { | ||
| 797 | - do_note_netbsd_version(ms, swap, &nbuf[doff]); | ||
| 798 | - *flags |= FLAGS_DID_NOTE; | ||
| 799 | - return size; | ||
| 800 | - } | ||
| 801 | - break; | ||
| 802 | - case NT_NETBSD_MARCH: | ||
| 803 | - if (file_printf(ms, ", compiled for: %.*s", (int)descsz, | ||
| 804 | - (const char *)&nbuf[doff]) == -1) | ||
| 805 | - return size; | ||
| 806 | - break; | ||
| 807 | - case NT_NETBSD_CMODEL: | ||
| 808 | - if (file_printf(ms, ", compiler model: %.*s", | ||
| 809 | - (int)descsz, (const char *)&nbuf[doff]) == -1) | ||
| 810 | - return size; | ||
| 811 | - break; | ||
| 812 | - default: | ||
| 813 | - if (file_printf(ms, ", note=%u", xnh_type) == -1) | ||
| 814 | - return size; | ||
| 815 | - break; | ||
| 816 | - } | ||
| 817 | - return size; | ||
| 818 | - } | ||
| 819 | - | ||
| 820 | - if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { | ||
| 821 | - if (xnh_type == NT_FREEBSD_VERSION && descsz == 4) { | ||
| 822 | - do_note_freebsd_version(ms, swap, &nbuf[doff]); | ||
| 823 | - *flags |= FLAGS_DID_NOTE; | ||
| 824 | - return size; | ||
| 825 | + return 1; | ||
| 826 | } | ||
| 827 | + return 1; | ||
| 828 | } | ||
| 829 | + return 0; | ||
| 830 | +} | ||
| 831 | |||
| 832 | - if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && | ||
| 833 | - xnh_type == NT_OPENBSD_VERSION && descsz == 4) { | ||
| 834 | - if (file_printf(ms, ", for OpenBSD") == -1) | ||
| 835 | - return size; | ||
| 836 | - /* Content of note is always 0 */ | ||
| 837 | - *flags |= FLAGS_DID_NOTE; | ||
| 838 | - return size; | ||
| 839 | - } | ||
| 840 | - | ||
| 841 | - if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 && | ||
| 842 | - xnh_type == NT_DRAGONFLY_VERSION && descsz == 4) { | ||
| 843 | - uint32_t desc; | ||
| 844 | - if (file_printf(ms, ", for DragonFly") == -1) | ||
| 845 | - return size; | ||
| 846 | - (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); | ||
| 847 | - desc = elf_getu32(swap, desc); | ||
| 848 | - if (file_printf(ms, " %d.%d.%d", desc / 100000, | ||
| 849 | - desc / 10000 % 10, desc % 10000) == -1) | ||
| 850 | - return size; | ||
| 851 | - *flags |= FLAGS_DID_NOTE; | ||
| 852 | - return size; | ||
| 853 | - } | ||
| 854 | - | ||
| 855 | -core: | ||
| 856 | +private int | ||
| 857 | +do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, | ||
| 858 | + int swap, uint32_t namesz, uint32_t descsz, | ||
| 859 | + size_t noff, size_t doff, int *flags, size_t size, int clazz) | ||
| 860 | +{ | ||
| 861 | +#ifdef ELFCORE | ||
| 862 | + int os_style = -1; | ||
| 863 | /* | ||
| 864 | * Sigh. The 2.0.36 kernel in Debian 2.1, at | ||
| 865 | * least, doesn't correctly implement name | ||
| 866 | @@ -697,20 +669,17 @@ core: | ||
| 867 | os_style = OS_STYLE_NETBSD; | ||
| 868 | } | ||
| 869 | |||
| 870 | -#ifdef ELFCORE | ||
| 871 | - if ((*flags & FLAGS_DID_CORE) != 0) | ||
| 872 | - return size; | ||
| 873 | - | ||
| 874 | if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) { | ||
| 875 | if (file_printf(ms, ", %s-style", os_style_names[os_style]) | ||
| 876 | == -1) | ||
| 877 | - return size; | ||
| 878 | + return 1; | ||
| 879 | *flags |= FLAGS_DID_CORE_STYLE; | ||
| 880 | } | ||
| 881 | |||
| 882 | switch (os_style) { | ||
| 883 | case OS_STYLE_NETBSD: | ||
| 884 | - if (xnh_type == NT_NETBSD_CORE_PROCINFO) { | ||
| 885 | + if (type == NT_NETBSD_CORE_PROCINFO) { | ||
| 886 | + char sbuf[512]; | ||
| 887 | uint32_t signo; | ||
| 888 | /* | ||
| 889 | * Extract the program name. It is at | ||
| 890 | @@ -719,7 +688,7 @@ core: | ||
| 891 | */ | ||
| 892 | if (file_printf(ms, ", from '%.31s'", | ||
| 893 | &nbuf[doff + 0x7c]) == -1) | ||
| 894 | - return size; | ||
| 895 | + return 1; | ||
| 896 | |||
| 897 | /* | ||
| 898 | * Extract the signal number. It is at | ||
| 899 | @@ -729,14 +698,14 @@ core: | ||
| 900 | sizeof(signo)); | ||
| 901 | if (file_printf(ms, " (signal %u)", | ||
| 902 | elf_getu32(swap, signo)) == -1) | ||
| 903 | - return size; | ||
| 904 | + return 1; | ||
| 905 | *flags |= FLAGS_DID_CORE; | ||
| 906 | - return size; | ||
| 907 | + return 1; | ||
| 908 | } | ||
| 909 | break; | ||
| 910 | |||
| 911 | default: | ||
| 912 | - if (xnh_type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { | ||
| 913 | + if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { | ||
| 914 | size_t i, j; | ||
| 915 | unsigned char c; | ||
| 916 | /* | ||
| 917 | @@ -804,7 +773,7 @@ core: | ||
| 918 | * Try next offsets, in case this match is | ||
| 919 | * in the middle of a string. | ||
| 920 | */ | ||
| 921 | - for (k = i + 1 ; k < NOFFSETS ; k++) { | ||
| 922 | + for (k = i + 1 ; k < NOFFSETS; k++) { | ||
| 923 | size_t no; | ||
| 924 | int adjust = 1; | ||
| 925 | if (prpsoffsets(k) >= prpsoffsets(i)) | ||
| 926 | @@ -829,9 +798,9 @@ core: | ||
| 927 | cp--; | ||
| 928 | if (file_printf(ms, ", from '%.*s'", | ||
| 929 | (int)(cp - cname), cname) == -1) | ||
| 930 | - return size; | ||
| 931 | + return 1; | ||
| 932 | *flags |= FLAGS_DID_CORE; | ||
| 933 | - return size; | ||
| 934 | + return 1; | ||
| 935 | |||
| 936 | tryanother: | ||
| 937 | ; | ||
| 938 | @@ -840,6 +809,129 @@ core: | ||
| 939 | break; | ||
| 940 | } | ||
| 941 | #endif | ||
| 942 | + return 0; | ||
| 943 | +} | ||
| 944 | + | ||
| 945 | +private size_t | ||
| 946 | +donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, | ||
| 947 | + int clazz, int swap, size_t align, int *flags, uint16_t *notecount) | ||
| 948 | +{ | ||
| 949 | + Elf32_Nhdr nh32; | ||
| 950 | + Elf64_Nhdr nh64; | ||
| 951 | + size_t noff, doff; | ||
| 952 | + uint32_t namesz, descsz; | ||
| 953 | + unsigned char *nbuf = CAST(unsigned char *, vbuf); | ||
| 954 | + | ||
| 955 | + if (*notecount == 0) | ||
| 956 | + return 0; | ||
| 957 | + --*notecount; | ||
| 958 | + | ||
| 959 | + if (xnh_sizeof + offset > size) { | ||
| 960 | + /* | ||
| 961 | + * We're out of note headers. | ||
| 962 | + */ | ||
| 963 | + return xnh_sizeof + offset; | ||
| 964 | + } | ||
| 965 | + | ||
| 966 | + (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); | ||
| 967 | + offset += xnh_sizeof; | ||
| 968 | + | ||
| 969 | + namesz = xnh_namesz; | ||
| 970 | + descsz = xnh_descsz; | ||
| 971 | + if ((namesz == 0) && (descsz == 0)) { | ||
| 972 | + /* | ||
| 973 | + * We're out of note headers. | ||
| 974 | + */ | ||
| 975 | + return (offset >= size) ? offset : size; | ||
| 976 | + } | ||
| 977 | + | ||
| 978 | + if (namesz & 0x80000000) { | ||
| 979 | + (void)file_printf(ms, ", bad note name size 0x%lx", | ||
| 980 | + (unsigned long)namesz); | ||
| 981 | + return 0; | ||
| 982 | + } | ||
| 983 | + | ||
| 984 | + if (descsz & 0x80000000) { | ||
| 985 | + (void)file_printf(ms, ", bad note description size 0x%lx", | ||
| 986 | + (unsigned long)descsz); | ||
| 987 | + return 0; | ||
| 988 | + } | ||
| 989 | + | ||
| 990 | + noff = offset; | ||
| 991 | + doff = ELF_ALIGN(offset + namesz); | ||
| 992 | + | ||
| 993 | + if (offset + namesz > size) { | ||
| 994 | + /* | ||
| 995 | + * We're past the end of the buffer. | ||
| 996 | + */ | ||
| 997 | + return doff; | ||
| 998 | + } | ||
| 999 | + | ||
| 1000 | + offset = ELF_ALIGN(doff + descsz); | ||
| 1001 | + if (doff + descsz > size) { | ||
| 1002 | + /* | ||
| 1003 | + * We're past the end of the buffer. | ||
| 1004 | + */ | ||
| 1005 | + return (offset >= size) ? offset : size; | ||
| 1006 | + } | ||
| 1007 | + | ||
| 1008 | + if ((*flags & FLAGS_DID_OS_NOTE) == 0) { | ||
| 1009 | + if (do_os_note(ms, nbuf, xnh_type, swap, | ||
| 1010 | + namesz, descsz, noff, doff, flags)) | ||
| 1011 | + return size; | ||
| 1012 | + } | ||
| 1013 | + | ||
| 1014 | + if ((*flags & FLAGS_DID_BUILD_ID) == 0) { | ||
| 1015 | + if (do_bid_note(ms, nbuf, xnh_type, swap, | ||
| 1016 | + namesz, descsz, noff, doff, flags)) | ||
| 1017 | + return size; | ||
| 1018 | + } | ||
| 1019 | + | ||
| 1020 | + if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) { | ||
| 1021 | + if (do_pax_note(ms, nbuf, xnh_type, swap, | ||
| 1022 | + namesz, descsz, noff, doff, flags)) | ||
| 1023 | + return size; | ||
| 1024 | + } | ||
| 1025 | + | ||
| 1026 | + if ((*flags & FLAGS_DID_CORE) == 0) { | ||
| 1027 | + if (do_core_note(ms, nbuf, xnh_type, swap, | ||
| 1028 | + namesz, descsz, noff, doff, flags, size, clazz)) | ||
| 1029 | + return size; | ||
| 1030 | + } | ||
| 1031 | + | ||
| 1032 | + if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { | ||
| 1033 | + if (descsz > 100) | ||
| 1034 | + descsz = 100; | ||
| 1035 | + switch (xnh_type) { | ||
| 1036 | + case NT_NETBSD_VERSION: | ||
| 1037 | + return size; | ||
| 1038 | + case NT_NETBSD_MARCH: | ||
| 1039 | + if (*flags & FLAGS_DID_NETBSD_MARCH) | ||
| 1040 | + return size; | ||
| 1041 | + *flags |= FLAGS_DID_NETBSD_MARCH; | ||
| 1042 | + if (file_printf(ms, ", compiled for: %.*s", | ||
| 1043 | + (int)descsz, (const char *)&nbuf[doff]) == -1) | ||
| 1044 | + return size; | ||
| 1045 | + break; | ||
| 1046 | + case NT_NETBSD_CMODEL: | ||
| 1047 | + if (*flags & FLAGS_DID_NETBSD_CMODEL) | ||
| 1048 | + return size; | ||
| 1049 | + *flags |= FLAGS_DID_NETBSD_CMODEL; | ||
| 1050 | + if (file_printf(ms, ", compiler model: %.*s", | ||
| 1051 | + (int)descsz, (const char *)&nbuf[doff]) == -1) | ||
| 1052 | + return size; | ||
| 1053 | + break; | ||
| 1054 | + default: | ||
| 1055 | + if (*flags & FLAGS_DID_NETBSD_UNKNOWN) | ||
| 1056 | + return size; | ||
| 1057 | + *flags |= FLAGS_DID_NETBSD_UNKNOWN; | ||
| 1058 | + if (file_printf(ms, ", note=%u", xnh_type) == -1) | ||
| 1059 | + return size; | ||
| 1060 | + break; | ||
| 1061 | + } | ||
| 1062 | + return size; | ||
| 1063 | + } | ||
| 1064 | + | ||
| 1065 | return offset; | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | @@ -895,16 +987,19 @@ static const cap_desc_t cap_desc_386[] = { | ||
| 1069 | |||
| 1070 | private int | ||
| 1071 | doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, | ||
| 1072 | - size_t size, off_t fsize, int *flags, int mach, int strtab) | ||
| 1073 | + size_t size, off_t fsize, int mach, int strtab, int *flags, | ||
| 1074 | + uint16_t *notecount) | ||
| 1075 | { | ||
| 1076 | Elf32_Shdr sh32; | ||
| 1077 | Elf64_Shdr sh64; | ||
| 1078 | int stripped = 1; | ||
| 1079 | + size_t nbadcap = 0; | ||
| 1080 | void *nbuf; | ||
| 1081 | off_t noff, coff, name_off; | ||
| 1082 | uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */ | ||
| 1083 | uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilites */ | ||
| 1084 | char name[50]; | ||
| 1085 | + ssize_t namesize; | ||
| 1086 | |||
| 1087 | if (size != xsh_sizeof) { | ||
| 1088 | if (file_printf(ms, ", corrupted section header size") == -1) | ||
| 1089 | @@ -913,7 +1008,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | /* Read offset of name section to be able to read section names later */ | ||
| 1093 | - if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) == -1) { | ||
| 1094 | + if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) < (ssize_t)xsh_sizeof) { | ||
| 1095 | file_badread(ms); | ||
| 1096 | return -1; | ||
| 1097 | } | ||
| 1098 | @@ -921,15 +1016,15 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, | ||
| 1099 | |||
| 1100 | for ( ; num; num--) { | ||
| 1101 | /* Read the name of this section. */ | ||
| 1102 | - if (pread(fd, name, sizeof(name), name_off + xsh_name) == -1) { | ||
| 1103 | + if ((namesize = pread(fd, name, sizeof(name) - 1, name_off + xsh_name)) == -1) { | ||
| 1104 | file_badread(ms); | ||
| 1105 | return -1; | ||
| 1106 | } | ||
| 1107 | - name[sizeof(name) - 1] = '\0'; | ||
| 1108 | + name[namesize] = '\0'; | ||
| 1109 | if (strcmp(name, ".debug_info") == 0) | ||
| 1110 | stripped = 0; | ||
| 1111 | |||
| 1112 | - if (pread(fd, xsh_addr, xsh_sizeof, off) == -1) { | ||
| 1113 | + if (pread(fd, xsh_addr, xsh_sizeof, off) < (ssize_t)xsh_sizeof) { | ||
| 1114 | file_badread(ms); | ||
| 1115 | return -1; | ||
| 1116 | } | ||
| 1117 | @@ -944,7 +1039,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, | ||
| 1118 | stripped = 0; | ||
| 1119 | break; | ||
| 1120 | default: | ||
| 1121 | - if (xsh_offset > fsize) { | ||
| 1122 | + if (fsize != SIZE_UNKNOWN && xsh_offset > fsize) { | ||
| 1123 | /* Perhaps warn here */ | ||
| 1124 | continue; | ||
| 1125 | } | ||
| 1126 | @@ -959,7 +1054,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, | ||
| 1127 | " for note"); | ||
| 1128 | return -1; | ||
| 1129 | } | ||
| 1130 | - if (pread(fd, nbuf, xsh_size, xsh_offset) == -1) { | ||
| 1131 | + if (pread(fd, nbuf, xsh_size, xsh_offset) < (ssize_t)xsh_size) { | ||
| 1132 | file_badread(ms); | ||
| 1133 | free(nbuf); | ||
| 1134 | return -1; | ||
| 1135 | @@ -970,7 +1065,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, | ||
| 1136 | if (noff >= (off_t)xsh_size) | ||
| 1137 | break; | ||
| 1138 | noff = donote(ms, nbuf, (size_t)noff, | ||
| 1139 | - xsh_size, clazz, swap, 4, flags); | ||
| 1140 | + xsh_size, clazz, swap, 4, flags, notecount); | ||
| 1141 | if (noff == 0) | ||
| 1142 | break; | ||
| 1143 | } | ||
| 1144 | @@ -988,6 +1083,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, | ||
| 1145 | goto skip; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | + if (nbadcap > 5) | ||
| 1149 | + break; | ||
| 1150 | if (lseek(fd, xsh_offset, SEEK_SET) == (off_t)-1) { | ||
| 1151 | file_badseek(ms); | ||
| 1152 | return -1; | ||
| 1153 | @@ -1023,6 +1120,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, | ||
| 1154 | (unsigned long long)xcap_tag, | ||
| 1155 | (unsigned long long)xcap_val) == -1) | ||
| 1156 | return -1; | ||
| 1157 | + if (nbadcap++ > 2) | ||
| 1158 | + coff = xsh_size; | ||
| 1159 | break; | ||
| 1160 | } | ||
| 1161 | } | ||
| 1162 | @@ -1103,7 +1202,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, | ||
| 1163 | */ | ||
| 1164 | private int | ||
| 1165 | dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, | ||
| 1166 | - int num, size_t size, off_t fsize, int *flags, int sh_num) | ||
| 1167 | + int num, size_t size, off_t fsize, int sh_num, int *flags, | ||
| 1168 | + uint16_t *notecount) | ||
| 1169 | { | ||
| 1170 | Elf32_Phdr ph32; | ||
| 1171 | Elf64_Phdr ph64; | ||
| 1172 | @@ -1120,7 +1220,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | for ( ; num; num--) { | ||
| 1176 | - if (pread(fd, xph_addr, xph_sizeof, off) == -1) { | ||
| 1177 | + if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { | ||
| 1178 | file_badread(ms); | ||
| 1179 | return -1; | ||
| 1180 | } | ||
| 1181 | @@ -1136,7 +1236,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, | ||
| 1182 | shared_libraries = " (uses shared libs)"; | ||
| 1183 | break; | ||
| 1184 | default: | ||
| 1185 | - if (xph_offset > fsize) { | ||
| 1186 | + if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { | ||
| 1187 | /* Maybe warn here? */ | ||
| 1188 | continue; | ||
| 1189 | } | ||
| 1190 | @@ -1172,7 +1272,7 @@ dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, | ||
| 1191 | break; | ||
| 1192 | offset = donote(ms, nbuf, offset, | ||
| 1193 | (size_t)bufsize, clazz, swap, align, | ||
| 1194 | - flags); | ||
| 1195 | + flags, notecount); | ||
| 1196 | if (offset == 0) | ||
| 1197 | break; | ||
| 1198 | } | ||
| 1199 | @@ -1203,7 +1303,7 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf, | ||
| 1200 | int flags = 0; | ||
| 1201 | Elf32_Ehdr elf32hdr; | ||
| 1202 | Elf64_Ehdr elf64hdr; | ||
| 1203 | - uint16_t type; | ||
| 1204 | + uint16_t type, phnum, shnum, notecount; | ||
| 1205 | |||
| 1206 | if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) | ||
| 1207 | return 0; | ||
| 1208 | @@ -1229,7 +1329,10 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf, | ||
| 1209 | file_badread(ms); | ||
| 1210 | return -1; | ||
| 1211 | } | ||
| 1212 | - fsize = st.st_size; | ||
| 1213 | + if (S_ISREG(st.st_mode)) | ||
| 1214 | + fsize = st.st_size; | ||
| 1215 | + else | ||
| 1216 | + fsize = SIZE_UNKNOWN; | ||
| 1217 | |||
| 1218 | clazz = buf[EI_CLASS]; | ||
| 1219 | |||
| 1220 | diff --git a/src/softmagic.c b/src/softmagic.c | ||
| 1221 | index eaa0f6b..9b11b93 100644 | ||
| 1222 | --- a/src/softmagic.c | ||
| 1223 | +++ b/src/softmagic.c | ||
| 1224 | @@ -48,11 +48,11 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.180 2014/03/15 21:47:40 christos Exp $") | ||
| 1225 | |||
| 1226 | |||
| 1227 | private int match(struct magic_set *, struct magic *, uint32_t, | ||
| 1228 | - const unsigned char *, size_t, size_t, int, int, int, int, int *, int *, | ||
| 1229 | - int *); | ||
| 1230 | + const unsigned char *, size_t, size_t, int, int, int, uint16_t, | ||
| 1231 | + uint16_t *, int *, int *, int *); | ||
| 1232 | private int mget(struct magic_set *, const unsigned char *, | ||
| 1233 | - struct magic *, size_t, size_t, unsigned int, int, int, int, int, int *, | ||
| 1234 | - int *, int *); | ||
| 1235 | + struct magic *, size_t, size_t, unsigned int, int, int, int, uint16_t, | ||
| 1236 | + uint16_t *, int *, int *, int *); | ||
| 1237 | private int magiccheck(struct magic_set *, struct magic *); | ||
| 1238 | private int32_t mprint(struct magic_set *, struct magic *); | ||
| 1239 | private int32_t moffset(struct magic_set *, struct magic *); | ||
| 1240 | @@ -68,6 +68,7 @@ private void cvt_32(union VALUETYPE *, const struct magic *); | ||
| 1241 | private void cvt_64(union VALUETYPE *, const struct magic *); | ||
| 1242 | |||
| 1243 | #define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o))) | ||
| 1244 | + | ||
| 1245 | /* | ||
| 1246 | * softmagic - lookup one file in parsed, in-memory copy of database | ||
| 1247 | * Passed the name and FILE * of one file to be typed. | ||
| 1248 | @@ -75,14 +76,20 @@ private void cvt_64(union VALUETYPE *, const struct magic *); | ||
| 1249 | /*ARGSUSED1*/ /* nbytes passed for regularity, maybe need later */ | ||
| 1250 | protected int | ||
| 1251 | file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, | ||
| 1252 | - size_t level, int mode, int text) | ||
| 1253 | + uint16_t indir_level, uint16_t *name_count, int mode, int text) | ||
| 1254 | { | ||
| 1255 | struct mlist *ml; | ||
| 1256 | int rv, printed_something = 0, need_separator = 0; | ||
| 1257 | + uint16_t nc; | ||
| 1258 | + | ||
| 1259 | + if (name_count == NULL) { | ||
| 1260 | + nc = 0; | ||
| 1261 | + name_count = &nc; | ||
| 1262 | + } | ||
| 1263 | for (ml = ms->mlist[0]->next; ml != ms->mlist[0]; ml = ml->next) | ||
| 1264 | if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, 0, mode, | ||
| 1265 | - text, 0, level, &printed_something, &need_separator, | ||
| 1266 | - NULL)) != 0) | ||
| 1267 | + text, 0, indir_level, name_count, | ||
| 1268 | + &printed_something, &need_separator, NULL)) != 0) | ||
| 1269 | return rv; | ||
| 1270 | |||
| 1271 | return 0; | ||
| 1272 | @@ -118,8 +125,8 @@ file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes, | ||
| 1273 | private int | ||
| 1274 | match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, | ||
| 1275 | const unsigned char *s, size_t nbytes, size_t offset, int mode, int text, | ||
| 1276 | - int flip, int recursion_level, int *printed_something, int *need_separator, | ||
| 1277 | - int *returnval) | ||
| 1278 | + int flip, uint16_t indir_level, uint16_t *name_count, | ||
| 1279 | + int *printed_something, int *need_separator, int *returnval) | ||
| 1280 | { | ||
| 1281 | uint32_t magindex = 0; | ||
| 1282 | unsigned int cont_level = 0; | ||
| 1283 | @@ -156,8 +163,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, | ||
| 1284 | |||
| 1285 | /* if main entry matches, print it... */ | ||
| 1286 | switch (mget(ms, s, m, nbytes, offset, cont_level, mode, text, | ||
| 1287 | - flip, recursion_level + 1, printed_something, | ||
| 1288 | - need_separator, returnval)) { | ||
| 1289 | + flip, indir_level, name_count, | ||
| 1290 | + printed_something, need_separator, returnval)) { | ||
| 1291 | case -1: | ||
| 1292 | return -1; | ||
| 1293 | case 0: | ||
| 1294 | @@ -245,8 +252,8 @@ match(struct magic_set *ms, struct magic *magic, uint32_t nmagic, | ||
| 1295 | } | ||
| 1296 | #endif | ||
| 1297 | switch (mget(ms, s, m, nbytes, offset, cont_level, mode, | ||
| 1298 | - text, flip, recursion_level + 1, printed_something, | ||
| 1299 | - need_separator, returnval)) { | ||
| 1300 | + text, flip, indir_level, name_count, | ||
| 1301 | + printed_something, need_separator, returnval)) { | ||
| 1302 | case -1: | ||
| 1303 | return -1; | ||
| 1304 | case 0: | ||
| 1305 | @@ -1155,18 +1162,26 @@ mcopy(struct magic_set *ms, union VALUETYPE *p, int type, int indir, | ||
| 1306 | private int | ||
| 1307 | mget(struct magic_set *ms, const unsigned char *s, struct magic *m, | ||
| 1308 | size_t nbytes, size_t o, unsigned int cont_level, int mode, int text, | ||
| 1309 | - int flip, int recursion_level, int *printed_something, | ||
| 1310 | - int *need_separator, int *returnval) | ||
| 1311 | + int flip, uint16_t indir_level, uint16_t *name_count, | ||
| 1312 | + int *printed_something, int *need_separator, int *returnval) | ||
| 1313 | { | ||
| 1314 | - uint32_t soffset, offset = ms->offset; | ||
| 1315 | + uint32_t offset = ms->offset; | ||
| 1316 | uint32_t count = m->str_range; | ||
| 1317 | + file_pushbuf_t *pb; | ||
| 1318 | int rv, oneed_separator, in_type; | ||
| 1319 | - char *sbuf, *rbuf; | ||
| 1320 | + char *rbuf; | ||
| 1321 | union VALUETYPE *p = &ms->ms_value; | ||
| 1322 | struct mlist ml; | ||
| 1323 | |||
| 1324 | - if (recursion_level >= 20) { | ||
| 1325 | - file_error(ms, 0, "recursion nesting exceeded"); | ||
| 1326 | + if (indir_level >= ms->indir_max) { | ||
| 1327 | + file_error(ms, 0, "indirect recursion nesting (%hu) exceeded", | ||
| 1328 | + indir_level); | ||
| 1329 | + return -1; | ||
| 1330 | + } | ||
| 1331 | + | ||
| 1332 | + if (*name_count >= ms->name_max) { | ||
| 1333 | + file_error(ms, 0, "name use count (%hu) exceeded", | ||
| 1334 | + *name_count); | ||
| 1335 | return -1; | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | @@ -1678,6 +1693,10 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, | ||
| 1339 | ms->offset = offset; | ||
| 1340 | |||
| 1341 | if ((ms->flags & MAGIC_DEBUG) != 0) { | ||
| 1342 | + fprintf(stderr, "mget(type=%d, flag=%x, offset=%u, o=%zu, " | ||
| 1343 | + "nbytes=%zu, il=%hu, nc=%hu)\n", | ||
| 1344 | + m->type, m->flag, offset, o, nbytes, | ||
| 1345 | + indir_level, *name_count); | ||
| 1346 | mdebug(offset, (char *)(void *)p, | ||
| 1347 | sizeof(union VALUETYPE)); | ||
| 1348 | #ifndef COMPILE_ONLY | ||
| 1349 | @@ -1741,19 +1760,23 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, | ||
| 1350 | case FILE_INDIRECT: | ||
| 1351 | if (offset == 0) | ||
| 1352 | return 0; | ||
| 1353 | + | ||
| 1354 | if (nbytes < offset) | ||
| 1355 | return 0; | ||
| 1356 | - sbuf = ms->o.buf; | ||
| 1357 | - soffset = ms->offset; | ||
| 1358 | - ms->o.buf = NULL; | ||
| 1359 | - ms->offset = 0; | ||
| 1360 | + | ||
| 1361 | + if ((pb = file_push_buffer(ms)) == NULL) | ||
| 1362 | + return -1; | ||
| 1363 | + | ||
| 1364 | rv = file_softmagic(ms, s + offset, nbytes - offset, | ||
| 1365 | - recursion_level, BINTEST, text); | ||
| 1366 | + indir_level + 1, name_count, BINTEST, text); | ||
| 1367 | + | ||
| 1368 | if ((ms->flags & MAGIC_DEBUG) != 0) | ||
| 1369 | fprintf(stderr, "indirect @offs=%u[%d]\n", offset, rv); | ||
| 1370 | - rbuf = ms->o.buf; | ||
| 1371 | - ms->o.buf = sbuf; | ||
| 1372 | - ms->offset = soffset; | ||
| 1373 | + | ||
| 1374 | + rbuf = file_pop_buffer(ms, pb); | ||
| 1375 | + if (rbuf == NULL && ms->event_flags & EVENT_HAD_ERR) | ||
| 1376 | + return -1; | ||
| 1377 | + | ||
| 1378 | if (rv == 1) { | ||
| 1379 | if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 && | ||
| 1380 | file_printf(ms, F(m->desc, "%u"), offset) == -1) { | ||
| 1381 | @@ -1771,22 +1794,22 @@ mget(struct magic_set *ms, const unsigned char *s, struct magic *m, | ||
| 1382 | case FILE_USE: | ||
| 1383 | if (nbytes < offset) | ||
| 1384 | return 0; | ||
| 1385 | - sbuf = m->value.s; | ||
| 1386 | - if (*sbuf == '^') { | ||
| 1387 | - sbuf++; | ||
| 1388 | + rbuf = m->value.s; | ||
| 1389 | + if (*rbuf == '^') { | ||
| 1390 | + rbuf++; | ||
| 1391 | flip = !flip; | ||
| 1392 | } | ||
| 1393 | - if (file_magicfind(ms, sbuf, &ml) == -1) { | ||
| 1394 | - file_error(ms, 0, "cannot find entry `%s'", sbuf); | ||
| 1395 | + if (file_magicfind(ms, rbuf, &ml) == -1) { | ||
| 1396 | + file_error(ms, 0, "cannot find entry `%s'", rbuf); | ||
| 1397 | return -1; | ||
| 1398 | } | ||
| 1399 | - | ||
| 1400 | + (*name_count)++; | ||
| 1401 | oneed_separator = *need_separator; | ||
| 1402 | if (m->flag & NOSPACE) | ||
| 1403 | *need_separator = 0; | ||
| 1404 | rv = match(ms, ml.magic, ml.nmagic, s, nbytes, offset + o, | ||
| 1405 | - mode, text, flip, recursion_level, printed_something, | ||
| 1406 | - need_separator, returnval); | ||
| 1407 | + mode, text, flip, indir_level, name_count, | ||
| 1408 | + printed_something, need_separator, returnval); | ||
| 1409 | if (rv != 1) | ||
| 1410 | *need_separator = oneed_separator; | ||
| 1411 | return rv; | ||
| 1412 | -- | ||
| 1413 | 1.9.1 | ||
| 1414 | |||
diff --git a/meta/recipes-devtools/file/file_5.18.bb b/meta/recipes-devtools/file/file_5.18.bb index 9068b9314a..d6e7d61d79 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" | |||
| 13 | 13 | ||
| 14 | SRC_URI = "ftp://ftp.astron.com/pub/file/file-${PV}.tar.gz \ | 14 | SRC_URI = "ftp://ftp.astron.com/pub/file/file-${PV}.tar.gz \ |
| 15 | file://debian-742262.patch \ | 15 | file://debian-742262.patch \ |
| 16 | file://file-CVE-2014-9620-and-CVE-2014-9621.patch \ | ||
| 16 | " | 17 | " |
| 17 | 18 | ||
| 18 | SRC_URI[md5sum] = "d420d8f2990cd344673acfbf8d76ff5a" | 19 | SRC_URI[md5sum] = "d420d8f2990cd344673acfbf8d76ff5a" |
