readelf.c (276415) | readelf.c (277592) |
---|---|
1/* 2 * Copyright (c) Christos Zoulas 2003. 3 * All Rights Reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 13 unchanged lines hidden (view full) --- 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27#include "file.h" 28 29#ifndef lint | 1/* 2 * Copyright (c) Christos Zoulas 2003. 3 * All Rights Reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 13 unchanged lines hidden (view full) --- 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27#include "file.h" 28 29#ifndef lint |
30FILE_RCSID("@(#)$File: readelf.c,v 1.111 2014/12/09 02:47:45 christos Exp $") | 30FILE_RCSID("@(#)$File: readelf.c,v 1.117 2014/12/16 23:29:42 christos Exp $") |
31#endif 32 33#ifdef BUILTIN_ELF 34#include <string.h> 35#include <ctype.h> 36#include <stdlib.h> 37#ifdef HAVE_UNISTD_H 38#include <unistd.h> 39#endif 40 41#include "readelf.h" 42#include "magic.h" 43 44#ifdef ELFCORE 45private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t, | 31#endif 32 33#ifdef BUILTIN_ELF 34#include <string.h> 35#include <ctype.h> 36#include <stdlib.h> 37#ifdef HAVE_UNISTD_H 38#include <unistd.h> 39#endif 40 41#include "readelf.h" 42#include "magic.h" 43 44#ifdef ELFCORE 45private int dophn_core(struct magic_set *, int, int, int, off_t, int, size_t, |
46 off_t, int *); | 46 off_t, int *, uint16_t *); |
47#endif 48private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t, | 47#endif 48private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t, |
49 off_t, int *, int); | 49 off_t, int, int *, uint16_t *); |
50private int doshn(struct magic_set *, int, int, int, off_t, int, size_t, | 50private int doshn(struct magic_set *, int, int, int, off_t, int, size_t, |
51 off_t, int *, int, int); | 51 off_t, int, int, int *, uint16_t *); |
52private size_t donote(struct magic_set *, void *, size_t, size_t, int, | 52private size_t donote(struct magic_set *, void *, size_t, size_t, int, |
53 int, size_t, int *); | 53 int, size_t, int *, uint16_t *); |
54 55#define ELF_ALIGN(a) ((((a) + align - 1) / align) * align) 56 57#define isquote(c) (strchr("'\"`", (c)) != NULL) 58 59private uint16_t getu16(int, uint16_t); 60private uint32_t getu32(int, uint32_t); 61private uint64_t getu64(int, uint64_t); 62 63#define MAX_PHNUM 128 64#define MAX_SHNUM 32768 65#define SIZE_UNKNOWN ((off_t)-1) 66 67private int 68toomany(struct magic_set *ms, const char *name, uint16_t num) 69{ | 54 55#define ELF_ALIGN(a) ((((a) + align - 1) / align) * align) 56 57#define isquote(c) (strchr("'\"`", (c)) != NULL) 58 59private uint16_t getu16(int, uint16_t); 60private uint32_t getu32(int, uint32_t); 61private uint64_t getu64(int, uint64_t); 62 63#define MAX_PHNUM 128 64#define MAX_SHNUM 32768 65#define SIZE_UNKNOWN ((off_t)-1) 66 67private int 68toomany(struct magic_set *ms, const char *name, uint16_t num) 69{ |
70 if (file_printf(ms, ", too many %s header sections (%u)", name, num | 70 if (file_printf(ms, ", too many %s (%u)", name, num |
71 ) == -1) 72 return -1; 73 return 0; 74} 75 76private uint16_t 77getu16(int swap, uint16_t value) 78{ --- 209 unchanged lines hidden (view full) --- 288#define OS_STYLE_NETBSD 2 289 290private const char os_style_names[][8] = { 291 "SVR4", 292 "FreeBSD", 293 "NetBSD", 294}; 295 | 71 ) == -1) 72 return -1; 73 return 0; 74} 75 76private uint16_t 77getu16(int swap, uint16_t value) 78{ --- 209 unchanged lines hidden (view full) --- 288#define OS_STYLE_NETBSD 2 289 290private const char os_style_names[][8] = { 291 "SVR4", 292 "FreeBSD", 293 "NetBSD", 294}; 295 |
296#define FLAGS_DID_CORE 0x01 297#define FLAGS_DID_NOTE 0x02 298#define FLAGS_DID_BUILD_ID 0x04 299#define FLAGS_DID_CORE_STYLE 0x08 300#define FLAGS_IS_CORE 0x10 | 296#define FLAGS_DID_CORE 0x001 297#define FLAGS_DID_OS_NOTE 0x002 298#define FLAGS_DID_BUILD_ID 0x004 299#define FLAGS_DID_CORE_STYLE 0x008 300#define FLAGS_DID_NETBSD_PAX 0x010 301#define FLAGS_DID_NETBSD_MARCH 0x020 302#define FLAGS_DID_NETBSD_CMODEL 0x040 303#define FLAGS_DID_NETBSD_UNKNOWN 0x080 304#define FLAGS_IS_CORE 0x100 |
301 302private int 303dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, | 305 306private int 307dophn_core(struct magic_set *ms, int clazz, int swap, int fd, off_t off, |
304 int num, size_t size, off_t fsize, int *flags) | 308 int num, size_t size, off_t fsize, int *flags, uint16_t *notecount) |
305{ 306 Elf32_Phdr ph32; 307 Elf64_Phdr ph64; 308 size_t offset, len; 309 unsigned char nbuf[BUFSIZ]; 310 ssize_t bufsize; 311 312 if (size != xph_sizeof) { 313 if (file_printf(ms, ", corrupted program header size") == -1) 314 return -1; 315 return 0; 316 } 317 318 /* 319 * Loop through all the program headers. 320 */ 321 for ( ; num; num--) { | 309{ 310 Elf32_Phdr ph32; 311 Elf64_Phdr ph64; 312 size_t offset, len; 313 unsigned char nbuf[BUFSIZ]; 314 ssize_t bufsize; 315 316 if (size != xph_sizeof) { 317 if (file_printf(ms, ", corrupted program header size") == -1) 318 return -1; 319 return 0; 320 } 321 322 /* 323 * Loop through all the program headers. 324 */ 325 for ( ; num; num--) { |
322 if (pread(fd, xph_addr, xph_sizeof, off) == -1) { | 326 if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { |
323 file_badread(ms); 324 return -1; 325 } 326 off += size; 327 328 if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { 329 /* Perhaps warn here */ 330 continue; --- 11 unchanged lines hidden (view full) --- 342 file_badread(ms); 343 return -1; 344 } 345 offset = 0; 346 for (;;) { 347 if (offset >= (size_t)bufsize) 348 break; 349 offset = donote(ms, nbuf, offset, (size_t)bufsize, | 327 file_badread(ms); 328 return -1; 329 } 330 off += size; 331 332 if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { 333 /* Perhaps warn here */ 334 continue; --- 11 unchanged lines hidden (view full) --- 346 file_badread(ms); 347 return -1; 348 } 349 offset = 0; 350 for (;;) { 351 if (offset >= (size_t)bufsize) 352 break; 353 offset = donote(ms, nbuf, offset, (size_t)bufsize, |
350 clazz, swap, 4, flags); | 354 clazz, swap, 4, flags, notecount); |
351 if (offset == 0) 352 break; 353 354 } 355 } 356 return 0; 357} 358#endif --- 113 unchanged lines hidden (view full) --- 472 return; 473 } else if (desc / 10 % 10 > 0) { 474 if (file_printf(ms, ".%d", desc / 10 % 10) == -1) 475 return; 476 } 477 } 478} 479 | 355 if (offset == 0) 356 break; 357 358 } 359 } 360 return 0; 361} 362#endif --- 113 unchanged lines hidden (view full) --- 476 return; 477 } else if (desc / 10 % 10 > 0) { 478 if (file_printf(ms, ".%d", desc / 10 % 10) == -1) 479 return; 480 } 481 } 482} 483 |
480private size_t 481donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, 482 int clazz, int swap, size_t align, int *flags) | 484private int 485do_bid_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, 486 int swap __attribute__((__unused__)), uint32_t namesz, uint32_t descsz, 487 size_t noff, size_t doff, int *flags) |
483{ | 488{ |
484 Elf32_Nhdr nh32; 485 Elf64_Nhdr nh64; 486 size_t noff, doff; 487#ifdef ELFCORE 488 int os_style = -1; 489#endif 490 uint32_t namesz, descsz; 491 unsigned char *nbuf = CAST(unsigned char *, vbuf); 492 493 if (xnh_sizeof + offset > size) { 494 /* 495 * We're out of note headers. 496 */ 497 return xnh_sizeof + offset; | 489 if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && 490 type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) { 491 uint8_t desc[20]; 492 uint32_t i; 493 *flags |= FLAGS_DID_BUILD_ID; 494 if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" : 495 "sha1") == -1) 496 return 1; 497 (void)memcpy(desc, &nbuf[doff], descsz); 498 for (i = 0; i < descsz; i++) 499 if (file_printf(ms, "%02x", desc[i]) == -1) 500 return 1; 501 return 1; |
498 } | 502 } |
503 return 0; 504} |
|
499 | 505 |
500 (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); 501 offset += xnh_sizeof; 502 503 namesz = xnh_namesz; 504 descsz = xnh_descsz; 505 if ((namesz == 0) && (descsz == 0)) { 506 /* 507 * We're out of note headers. 508 */ 509 return (offset >= size) ? offset : size; 510 } 511 512 if (namesz & 0x80000000) { 513 (void)file_printf(ms, ", bad note name size 0x%lx", 514 (unsigned long)namesz); 515 return 0; 516 } 517 518 if (descsz & 0x80000000) { 519 (void)file_printf(ms, ", bad note description size 0x%lx", 520 (unsigned long)descsz); 521 return 0; 522 } 523 524 525 noff = offset; 526 doff = ELF_ALIGN(offset + namesz); 527 528 if (offset + namesz > size) { 529 /* 530 * We're past the end of the buffer. 531 */ 532 return doff; 533 } 534 535 offset = ELF_ALIGN(doff + descsz); 536 if (doff + descsz > size) { 537 /* 538 * We're past the end of the buffer. 539 */ 540 return (offset >= size) ? offset : size; 541 } 542 543 if ((*flags & (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID)) == 544 (FLAGS_DID_NOTE|FLAGS_DID_BUILD_ID)) 545 goto core; 546 | 506private int 507do_os_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, 508 int swap, uint32_t namesz, uint32_t descsz, 509 size_t noff, size_t doff, int *flags) 510{ |
547 if (namesz == 5 && strcmp((char *)&nbuf[noff], "SuSE") == 0 && | 511 if (namesz == 5 && strcmp((char *)&nbuf[noff], "SuSE") == 0 && |
548 xnh_type == NT_GNU_VERSION && descsz == 2) { | 512 type == NT_GNU_VERSION && descsz == 2) { 513 *flags |= FLAGS_DID_OS_NOTE; |
549 file_printf(ms, ", for SuSE %d.%d", nbuf[doff], nbuf[doff + 1]); | 514 file_printf(ms, ", for SuSE %d.%d", nbuf[doff], nbuf[doff + 1]); |
515 return 1; |
|
550 } | 516 } |
517 |
|
551 if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && | 518 if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && |
552 xnh_type == NT_GNU_VERSION && descsz == 16) { | 519 type == NT_GNU_VERSION && descsz == 16) { |
553 uint32_t desc[4]; 554 (void)memcpy(desc, &nbuf[doff], sizeof(desc)); 555 | 520 uint32_t desc[4]; 521 (void)memcpy(desc, &nbuf[doff], sizeof(desc)); 522 |
523 *flags |= FLAGS_DID_OS_NOTE; |
|
556 if (file_printf(ms, ", for GNU/") == -1) | 524 if (file_printf(ms, ", for GNU/") == -1) |
557 return size; | 525 return 1; |
558 switch (elf_getu32(swap, desc[0])) { 559 case GNU_OS_LINUX: 560 if (file_printf(ms, "Linux") == -1) | 526 switch (elf_getu32(swap, desc[0])) { 527 case GNU_OS_LINUX: 528 if (file_printf(ms, "Linux") == -1) |
561 return size; | 529 return 1; |
562 break; 563 case GNU_OS_HURD: 564 if (file_printf(ms, "Hurd") == -1) | 530 break; 531 case GNU_OS_HURD: 532 if (file_printf(ms, "Hurd") == -1) |
565 return size; | 533 return 1; |
566 break; 567 case GNU_OS_SOLARIS: 568 if (file_printf(ms, "Solaris") == -1) | 534 break; 535 case GNU_OS_SOLARIS: 536 if (file_printf(ms, "Solaris") == -1) |
569 return size; | 537 return 1; |
570 break; 571 case GNU_OS_KFREEBSD: 572 if (file_printf(ms, "kFreeBSD") == -1) | 538 break; 539 case GNU_OS_KFREEBSD: 540 if (file_printf(ms, "kFreeBSD") == -1) |
573 return size; | 541 return 1; |
574 break; 575 case GNU_OS_KNETBSD: 576 if (file_printf(ms, "kNetBSD") == -1) | 542 break; 543 case GNU_OS_KNETBSD: 544 if (file_printf(ms, "kNetBSD") == -1) |
577 return size; | 545 return 1; |
578 break; 579 default: 580 if (file_printf(ms, "<unknown>") == -1) | 546 break; 547 default: 548 if (file_printf(ms, "<unknown>") == -1) |
581 return size; | 549 return 1; |
582 } 583 if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]), 584 elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1) | 550 } 551 if (file_printf(ms, " %d.%d.%d", elf_getu32(swap, desc[1]), 552 elf_getu32(swap, desc[2]), elf_getu32(swap, desc[3])) == -1) |
585 return size; 586 *flags |= FLAGS_DID_NOTE; 587 return size; | 553 return 1; 554 return 1; |
588 } 589 | 555 } 556 |
590 if (namesz == 4 && strcmp((char *)&nbuf[noff], "GNU") == 0 && 591 xnh_type == NT_GNU_BUILD_ID && (descsz == 16 || descsz == 20)) { 592 uint8_t desc[20]; 593 uint32_t i; 594 if (file_printf(ms, ", BuildID[%s]=", descsz == 16 ? "md5/uuid" : 595 "sha1") == -1) 596 return size; 597 (void)memcpy(desc, &nbuf[doff], descsz); 598 for (i = 0; i < descsz; i++) 599 if (file_printf(ms, "%02x", desc[i]) == -1) 600 return size; 601 *flags |= FLAGS_DID_BUILD_ID; | 557 if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { 558 if (type == NT_NETBSD_VERSION && descsz == 4) { 559 *flags |= FLAGS_DID_OS_NOTE; 560 do_note_netbsd_version(ms, swap, &nbuf[doff]); 561 return 1; 562 } |
602 } 603 | 563 } 564 |
565 if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { 566 if (type == NT_FREEBSD_VERSION && descsz == 4) { 567 *flags |= FLAGS_DID_OS_NOTE; 568 do_note_freebsd_version(ms, swap, &nbuf[doff]); 569 return 1; 570 } 571 } 572 573 if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && 574 type == NT_OPENBSD_VERSION && descsz == 4) { 575 *flags |= FLAGS_DID_OS_NOTE; 576 if (file_printf(ms, ", for OpenBSD") == -1) 577 return 1; 578 /* Content of note is always 0 */ 579 return 1; 580 } 581 582 if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 && 583 type == NT_DRAGONFLY_VERSION && descsz == 4) { 584 uint32_t desc; 585 *flags |= FLAGS_DID_OS_NOTE; 586 if (file_printf(ms, ", for DragonFly") == -1) 587 return 1; 588 (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); 589 desc = elf_getu32(swap, desc); 590 if (file_printf(ms, " %d.%d.%d", desc / 100000, 591 desc / 10000 % 10, desc % 10000) == -1) 592 return 1; 593 return 1; 594 } 595 return 0; 596} 597 598private int 599do_pax_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, 600 int swap, uint32_t namesz, uint32_t descsz, 601 size_t noff, size_t doff, int *flags) 602{ |
|
604 if (namesz == 4 && strcmp((char *)&nbuf[noff], "PaX") == 0 && | 603 if (namesz == 4 && strcmp((char *)&nbuf[noff], "PaX") == 0 && |
605 xnh_type == NT_NETBSD_PAX && descsz == 4) { | 604 type == NT_NETBSD_PAX && descsz == 4) { |
606 static const char *pax[] = { 607 "+mprotect", 608 "-mprotect", 609 "+segvguard", 610 "-segvguard", 611 "+ASLR", 612 "-ASLR", 613 }; 614 uint32_t desc; 615 size_t i; 616 int did = 0; 617 | 605 static const char *pax[] = { 606 "+mprotect", 607 "-mprotect", 608 "+segvguard", 609 "-segvguard", 610 "+ASLR", 611 "-ASLR", 612 }; 613 uint32_t desc; 614 size_t i; 615 int did = 0; 616 |
617 *flags |= FLAGS_DID_NETBSD_PAX; |
|
618 (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); 619 desc = elf_getu32(swap, desc); 620 621 if (desc && file_printf(ms, ", PaX: ") == -1) | 618 (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); 619 desc = elf_getu32(swap, desc); 620 621 if (desc && file_printf(ms, ", PaX: ") == -1) |
622 return size; | 622 return 1; |
623 624 for (i = 0; i < __arraycount(pax); i++) { 625 if (((1 << i) & desc) == 0) 626 continue; 627 if (file_printf(ms, "%s%s", did++ ? "," : "", 628 pax[i]) == -1) | 623 624 for (i = 0; i < __arraycount(pax); i++) { 625 if (((1 << i) & desc) == 0) 626 continue; 627 if (file_printf(ms, "%s%s", did++ ? "," : "", 628 pax[i]) == -1) |
629 return size; | 629 return 1; |
630 } | 630 } |
631 return 1; |
|
631 } | 632 } |
633 return 0; 634} |
|
632 | 635 |
633 if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { 634 switch (xnh_type) { 635 case NT_NETBSD_VERSION: 636 if (descsz == 4) { 637 do_note_netbsd_version(ms, swap, &nbuf[doff]); 638 *flags |= FLAGS_DID_NOTE; 639 return size; 640 } 641 break; 642 case NT_NETBSD_MARCH: 643 if (file_printf(ms, ", compiled for: %.*s", (int)descsz, 644 (const char *)&nbuf[doff]) == -1) 645 return size; 646 break; 647 case NT_NETBSD_CMODEL: 648 if (file_printf(ms, ", compiler model: %.*s", 649 (int)descsz, (const char *)&nbuf[doff]) == -1) 650 return size; 651 break; 652 default: 653 if (file_printf(ms, ", note=%u", xnh_type) == -1) 654 return size; 655 break; 656 } 657 return size; 658 } 659 660 if (namesz == 8 && strcmp((char *)&nbuf[noff], "FreeBSD") == 0) { 661 if (xnh_type == NT_FREEBSD_VERSION && descsz == 4) { 662 do_note_freebsd_version(ms, swap, &nbuf[doff]); 663 *flags |= FLAGS_DID_NOTE; 664 return size; 665 } 666 } 667 668 if (namesz == 8 && strcmp((char *)&nbuf[noff], "OpenBSD") == 0 && 669 xnh_type == NT_OPENBSD_VERSION && descsz == 4) { 670 if (file_printf(ms, ", for OpenBSD") == -1) 671 return size; 672 /* Content of note is always 0 */ 673 *flags |= FLAGS_DID_NOTE; 674 return size; 675 } 676 677 if (namesz == 10 && strcmp((char *)&nbuf[noff], "DragonFly") == 0 && 678 xnh_type == NT_DRAGONFLY_VERSION && descsz == 4) { 679 uint32_t desc; 680 if (file_printf(ms, ", for DragonFly") == -1) 681 return size; 682 (void)memcpy(&desc, &nbuf[doff], sizeof(desc)); 683 desc = elf_getu32(swap, desc); 684 if (file_printf(ms, " %d.%d.%d", desc / 100000, 685 desc / 10000 % 10, desc % 10000) == -1) 686 return size; 687 *flags |= FLAGS_DID_NOTE; 688 return size; 689 } 690 691core: | 636private int 637do_core_note(struct magic_set *ms, unsigned char *nbuf, uint32_t type, 638 int swap, uint32_t namesz, uint32_t descsz, 639 size_t noff, size_t doff, int *flags, size_t size, int clazz) 640{ 641#ifdef ELFCORE 642 int os_style = -1; |
692 /* 693 * Sigh. The 2.0.36 kernel in Debian 2.1, at 694 * least, doesn't correctly implement name 695 * sections, in core dumps, as specified by 696 * the "Program Linking" section of "UNIX(R) System 697 * V Release 4 Programmer's Guide: ANSI C and 698 * Programming Support Tools", because my copy 699 * clearly says "The first 'namesz' bytes in 'name' --- 12 unchanged lines hidden (view full) --- 712 os_style = OS_STYLE_FREEBSD; 713 } 714 715 if ((namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11) 716 == 0)) { 717 os_style = OS_STYLE_NETBSD; 718 } 719 | 643 /* 644 * Sigh. The 2.0.36 kernel in Debian 2.1, at 645 * least, doesn't correctly implement name 646 * sections, in core dumps, as specified by 647 * the "Program Linking" section of "UNIX(R) System 648 * V Release 4 Programmer's Guide: ANSI C and 649 * Programming Support Tools", because my copy 650 * clearly says "The first 'namesz' bytes in 'name' --- 12 unchanged lines hidden (view full) --- 663 os_style = OS_STYLE_FREEBSD; 664 } 665 666 if ((namesz >= 11 && strncmp((char *)&nbuf[noff], "NetBSD-CORE", 11) 667 == 0)) { 668 os_style = OS_STYLE_NETBSD; 669 } 670 |
720#ifdef ELFCORE 721 if ((*flags & FLAGS_DID_CORE) != 0) 722 return size; 723 | |
724 if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) { 725 if (file_printf(ms, ", %s-style", os_style_names[os_style]) 726 == -1) | 671 if (os_style != -1 && (*flags & FLAGS_DID_CORE_STYLE) == 0) { 672 if (file_printf(ms, ", %s-style", os_style_names[os_style]) 673 == -1) |
727 return size; | 674 return 1; |
728 *flags |= FLAGS_DID_CORE_STYLE; 729 } 730 731 switch (os_style) { 732 case OS_STYLE_NETBSD: | 675 *flags |= FLAGS_DID_CORE_STYLE; 676 } 677 678 switch (os_style) { 679 case OS_STYLE_NETBSD: |
733 if (xnh_type == NT_NETBSD_CORE_PROCINFO) { | 680 if (type == NT_NETBSD_CORE_PROCINFO) { 681 char sbuf[512]; |
734 uint32_t signo; 735 /* 736 * Extract the program name. It is at 737 * offset 0x7c, and is up to 32-bytes, 738 * including the terminating NUL. 739 */ 740 if (file_printf(ms, ", from '%.31s'", | 682 uint32_t signo; 683 /* 684 * Extract the program name. It is at 685 * offset 0x7c, and is up to 32-bytes, 686 * including the terminating NUL. 687 */ 688 if (file_printf(ms, ", from '%.31s'", |
741 &nbuf[doff + 0x7c]) == -1) 742 return size; | 689 file_printable(sbuf, sizeof(sbuf), 690 (const char *)&nbuf[doff + 0x7c])) == -1) 691 return 1; |
743 744 /* 745 * Extract the signal number. It is at 746 * offset 0x08. 747 */ 748 (void)memcpy(&signo, &nbuf[doff + 0x08], 749 sizeof(signo)); 750 if (file_printf(ms, " (signal %u)", 751 elf_getu32(swap, signo)) == -1) | 692 693 /* 694 * Extract the signal number. It is at 695 * offset 0x08. 696 */ 697 (void)memcpy(&signo, &nbuf[doff + 0x08], 698 sizeof(signo)); 699 if (file_printf(ms, " (signal %u)", 700 elf_getu32(swap, signo)) == -1) |
752 return size; | 701 return 1; |
753 *flags |= FLAGS_DID_CORE; | 702 *flags |= FLAGS_DID_CORE; |
754 return size; | 703 return 1; |
755 } 756 break; 757 758 default: | 704 } 705 break; 706 707 default: |
759 if (xnh_type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { | 708 if (type == NT_PRPSINFO && *flags & FLAGS_IS_CORE) { |
760 size_t i, j; 761 unsigned char c; 762 /* 763 * Extract the program name. We assume 764 * it to be 16 characters (that's what it 765 * is in SunOS 5.x and Linux). 766 * 767 * Unfortunately, it's at a different offset --- 51 unchanged lines hidden (view full) --- 819 /* 820 * Well, that worked. 821 */ 822 823 /* 824 * Try next offsets, in case this match is 825 * in the middle of a string. 826 */ | 709 size_t i, j; 710 unsigned char c; 711 /* 712 * Extract the program name. We assume 713 * it to be 16 characters (that's what it 714 * is in SunOS 5.x and Linux). 715 * 716 * Unfortunately, it's at a different offset --- 51 unchanged lines hidden (view full) --- 768 /* 769 * Well, that worked. 770 */ 771 772 /* 773 * Try next offsets, in case this match is 774 * in the middle of a string. 775 */ |
827 for (k = i + 1 ; k < NOFFSETS ; k++) { | 776 for (k = i + 1 ; k < NOFFSETS; k++) { |
828 size_t no; 829 int adjust = 1; 830 if (prpsoffsets(k) >= prpsoffsets(i)) 831 continue; 832 for (no = doff + prpsoffsets(k); 833 no < doff + prpsoffsets(i); no++) 834 adjust = adjust 835 && isprint(nbuf[no]); --- 8 unchanged lines hidden (view full) --- 844 /* 845 * Linux apparently appends a space at the end 846 * of the command line: remove it. 847 */ 848 while (cp > cname && isspace(cp[-1])) 849 cp--; 850 if (file_printf(ms, ", from '%.*s'", 851 (int)(cp - cname), cname) == -1) | 777 size_t no; 778 int adjust = 1; 779 if (prpsoffsets(k) >= prpsoffsets(i)) 780 continue; 781 for (no = doff + prpsoffsets(k); 782 no < doff + prpsoffsets(i); no++) 783 adjust = adjust 784 && isprint(nbuf[no]); --- 8 unchanged lines hidden (view full) --- 793 /* 794 * Linux apparently appends a space at the end 795 * of the command line: remove it. 796 */ 797 while (cp > cname && isspace(cp[-1])) 798 cp--; 799 if (file_printf(ms, ", from '%.*s'", 800 (int)(cp - cname), cname) == -1) |
852 return size; | 801 return 1; |
853 *flags |= FLAGS_DID_CORE; | 802 *flags |= FLAGS_DID_CORE; |
854 return size; | 803 return 1; |
855 856 tryanother: 857 ; 858 } 859 } 860 break; 861 } 862#endif | 804 805 tryanother: 806 ; 807 } 808 } 809 break; 810 } 811#endif |
812 return 0; 813} 814 815private size_t 816donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size, 817 int clazz, int swap, size_t align, int *flags, uint16_t *notecount) 818{ 819 Elf32_Nhdr nh32; 820 Elf64_Nhdr nh64; 821 size_t noff, doff; 822 uint32_t namesz, descsz; 823 unsigned char *nbuf = CAST(unsigned char *, vbuf); 824 825 if (*notecount == 0) 826 return 0; 827 --*notecount; 828 829 if (xnh_sizeof + offset > size) { 830 /* 831 * We're out of note headers. 832 */ 833 return xnh_sizeof + offset; 834 } 835 836 (void)memcpy(xnh_addr, &nbuf[offset], xnh_sizeof); 837 offset += xnh_sizeof; 838 839 namesz = xnh_namesz; 840 descsz = xnh_descsz; 841 if ((namesz == 0) && (descsz == 0)) { 842 /* 843 * We're out of note headers. 844 */ 845 return (offset >= size) ? offset : size; 846 } 847 848 if (namesz & 0x80000000) { 849 (void)file_printf(ms, ", bad note name size 0x%lx", 850 (unsigned long)namesz); 851 return 0; 852 } 853 854 if (descsz & 0x80000000) { 855 (void)file_printf(ms, ", bad note description size 0x%lx", 856 (unsigned long)descsz); 857 return 0; 858 } 859 860 noff = offset; 861 doff = ELF_ALIGN(offset + namesz); 862 863 if (offset + namesz > size) { 864 /* 865 * We're past the end of the buffer. 866 */ 867 return doff; 868 } 869 870 offset = ELF_ALIGN(doff + descsz); 871 if (doff + descsz > size) { 872 /* 873 * We're past the end of the buffer. 874 */ 875 return (offset >= size) ? offset : size; 876 } 877 878 if ((*flags & FLAGS_DID_OS_NOTE) == 0) { 879 if (do_os_note(ms, nbuf, xnh_type, swap, 880 namesz, descsz, noff, doff, flags)) 881 return size; 882 } 883 884 if ((*flags & FLAGS_DID_BUILD_ID) == 0) { 885 if (do_bid_note(ms, nbuf, xnh_type, swap, 886 namesz, descsz, noff, doff, flags)) 887 return size; 888 } 889 890 if ((*flags & FLAGS_DID_NETBSD_PAX) == 0) { 891 if (do_pax_note(ms, nbuf, xnh_type, swap, 892 namesz, descsz, noff, doff, flags)) 893 return size; 894 } 895 896 if ((*flags & FLAGS_DID_CORE) == 0) { 897 if (do_core_note(ms, nbuf, xnh_type, swap, 898 namesz, descsz, noff, doff, flags, size, clazz)) 899 return size; 900 } 901 902 if (namesz == 7 && strcmp((char *)&nbuf[noff], "NetBSD") == 0) { 903 if (descsz > 100) 904 descsz = 100; 905 switch (xnh_type) { 906 case NT_NETBSD_VERSION: 907 return size; 908 case NT_NETBSD_MARCH: 909 if (*flags & FLAGS_DID_NETBSD_MARCH) 910 return size; 911 *flags |= FLAGS_DID_NETBSD_MARCH; 912 if (file_printf(ms, ", compiled for: %.*s", 913 (int)descsz, (const char *)&nbuf[doff]) == -1) 914 return size; 915 break; 916 case NT_NETBSD_CMODEL: 917 if (*flags & FLAGS_DID_NETBSD_CMODEL) 918 return size; 919 *flags |= FLAGS_DID_NETBSD_CMODEL; 920 if (file_printf(ms, ", compiler model: %.*s", 921 (int)descsz, (const char *)&nbuf[doff]) == -1) 922 return size; 923 break; 924 default: 925 if (*flags & FLAGS_DID_NETBSD_UNKNOWN) 926 return size; 927 *flags |= FLAGS_DID_NETBSD_UNKNOWN; 928 if (file_printf(ms, ", note=%u", xnh_type) == -1) 929 return size; 930 break; 931 } 932 return size; 933 } 934 |
|
863 return offset; 864} 865 866/* SunOS 5.x hardware capability descriptions */ 867typedef struct cap_desc { 868 uint64_t cd_mask; 869 const char *cd_name; 870} cap_desc_t; --- 39 unchanged lines hidden (view full) --- 910 { AV_386_SSSE3, "SSSE3" }, 911 { AV_386_SSE4_1, "SSE4.1" }, 912 { AV_386_SSE4_2, "SSE4.2" }, 913 { 0, NULL } 914}; 915 916private int 917doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, | 935 return offset; 936} 937 938/* SunOS 5.x hardware capability descriptions */ 939typedef struct cap_desc { 940 uint64_t cd_mask; 941 const char *cd_name; 942} cap_desc_t; --- 39 unchanged lines hidden (view full) --- 982 { AV_386_SSSE3, "SSSE3" }, 983 { AV_386_SSE4_1, "SSE4.1" }, 984 { AV_386_SSE4_2, "SSE4.2" }, 985 { 0, NULL } 986}; 987 988private int 989doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num, |
918 size_t size, off_t fsize, int *flags, int mach, int strtab) | 990 size_t size, off_t fsize, int mach, int strtab, int *flags, 991 uint16_t *notecount) |
919{ 920 Elf32_Shdr sh32; 921 Elf64_Shdr sh64; 922 int stripped = 1; 923 size_t nbadcap = 0; 924 void *nbuf; 925 off_t noff, coff, name_off; 926 uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */ 927 uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilites */ 928 char name[50]; | 992{ 993 Elf32_Shdr sh32; 994 Elf64_Shdr sh64; 995 int stripped = 1; 996 size_t nbadcap = 0; 997 void *nbuf; 998 off_t noff, coff, name_off; 999 uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */ 1000 uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilites */ 1001 char name[50]; |
1002 ssize_t namesize; |
|
929 930 if (size != xsh_sizeof) { 931 if (file_printf(ms, ", corrupted section header size") == -1) 932 return -1; 933 return 0; 934 } 935 936 /* Read offset of name section to be able to read section names later */ | 1003 1004 if (size != xsh_sizeof) { 1005 if (file_printf(ms, ", corrupted section header size") == -1) 1006 return -1; 1007 return 0; 1008 } 1009 1010 /* Read offset of name section to be able to read section names later */ |
937 if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) == -1) { | 1011 if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) < (ssize_t)xsh_sizeof) { |
938 file_badread(ms); 939 return -1; 940 } 941 name_off = xsh_offset; 942 943 for ( ; num; num--) { 944 /* Read the name of this section. */ | 1012 file_badread(ms); 1013 return -1; 1014 } 1015 name_off = xsh_offset; 1016 1017 for ( ; num; num--) { 1018 /* Read the name of this section. */ |
945 if (pread(fd, name, sizeof(name), name_off + xsh_name) == -1) { | 1019 if ((namesize = pread(fd, name, sizeof(name) - 1, name_off + xsh_name)) == -1) { |
946 file_badread(ms); 947 return -1; 948 } | 1020 file_badread(ms); 1021 return -1; 1022 } |
949 name[sizeof(name) - 1] = '\0'; | 1023 name[namesize] = '\0'; |
950 if (strcmp(name, ".debug_info") == 0) 951 stripped = 0; 952 | 1024 if (strcmp(name, ".debug_info") == 0) 1025 stripped = 0; 1026 |
953 if (pread(fd, xsh_addr, xsh_sizeof, off) == -1) { | 1027 if (pread(fd, xsh_addr, xsh_sizeof, off) < (ssize_t)xsh_sizeof) { |
954 file_badread(ms); 955 return -1; 956 } 957 off += size; 958 959 /* Things we can determine before we seek */ 960 switch (xsh_type) { 961 case SHT_SYMTAB: --- 13 unchanged lines hidden (view full) --- 975 /* Things we can determine when we seek */ 976 switch (xsh_type) { 977 case SHT_NOTE: 978 if ((nbuf = malloc(xsh_size)) == NULL) { 979 file_error(ms, errno, "Cannot allocate memory" 980 " for note"); 981 return -1; 982 } | 1028 file_badread(ms); 1029 return -1; 1030 } 1031 off += size; 1032 1033 /* Things we can determine before we seek */ 1034 switch (xsh_type) { 1035 case SHT_SYMTAB: --- 13 unchanged lines hidden (view full) --- 1049 /* Things we can determine when we seek */ 1050 switch (xsh_type) { 1051 case SHT_NOTE: 1052 if ((nbuf = malloc(xsh_size)) == NULL) { 1053 file_error(ms, errno, "Cannot allocate memory" 1054 " for note"); 1055 return -1; 1056 } |
983 if (pread(fd, nbuf, xsh_size, xsh_offset) == -1) { | 1057 if (pread(fd, nbuf, xsh_size, xsh_offset) < (ssize_t)xsh_size) { |
984 file_badread(ms); 985 free(nbuf); 986 return -1; 987 } 988 989 noff = 0; 990 for (;;) { 991 if (noff >= (off_t)xsh_size) 992 break; 993 noff = donote(ms, nbuf, (size_t)noff, | 1058 file_badread(ms); 1059 free(nbuf); 1060 return -1; 1061 } 1062 1063 noff = 0; 1064 for (;;) { 1065 if (noff >= (off_t)xsh_size) 1066 break; 1067 noff = donote(ms, nbuf, (size_t)noff, |
994 xsh_size, clazz, swap, 4, flags); | 1068 xsh_size, clazz, swap, 4, flags, notecount); |
995 if (noff == 0) 996 break; 997 } 998 free(nbuf); 999 break; 1000 case SHT_SUNW_cap: 1001 switch (mach) { 1002 case EM_SPARC: --- 150 unchanged lines hidden (view full) --- 1153 1154/* 1155 * Look through the program headers of an executable image, searching 1156 * for a PT_INTERP section; if one is found, it's dynamically linked, 1157 * otherwise it's statically linked. 1158 */ 1159private int 1160dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, | 1069 if (noff == 0) 1070 break; 1071 } 1072 free(nbuf); 1073 break; 1074 case SHT_SUNW_cap: 1075 switch (mach) { 1076 case EM_SPARC: --- 150 unchanged lines hidden (view full) --- 1227 1228/* 1229 * Look through the program headers of an executable image, searching 1230 * for a PT_INTERP section; if one is found, it's dynamically linked, 1231 * otherwise it's statically linked. 1232 */ 1233private int 1234dophn_exec(struct magic_set *ms, int clazz, int swap, int fd, off_t off, |
1161 int num, size_t size, off_t fsize, int *flags, int sh_num) | 1235 int num, size_t size, off_t fsize, int sh_num, int *flags, 1236 uint16_t *notecount) |
1162{ 1163 Elf32_Phdr ph32; 1164 Elf64_Phdr ph64; 1165 const char *linking_style = "statically"; | 1237{ 1238 Elf32_Phdr ph32; 1239 Elf64_Phdr ph64; 1240 const char *linking_style = "statically"; |
1166 const char *shared_libraries = ""; | 1241 const char *interp = ""; |
1167 unsigned char nbuf[BUFSIZ]; | 1242 unsigned char nbuf[BUFSIZ]; |
1243 char ibuf[BUFSIZ]; |
|
1168 ssize_t bufsize; 1169 size_t offset, align, len; 1170 1171 if (size != xph_sizeof) { 1172 if (file_printf(ms, ", corrupted program header size") == -1) 1173 return -1; 1174 return 0; 1175 } 1176 1177 for ( ; num; num--) { | 1244 ssize_t bufsize; 1245 size_t offset, align, len; 1246 1247 if (size != xph_sizeof) { 1248 if (file_printf(ms, ", corrupted program header size") == -1) 1249 return -1; 1250 return 0; 1251 } 1252 1253 for ( ; num; num--) { |
1178 if (pread(fd, xph_addr, xph_sizeof, off) == -1) { | 1254 if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) { |
1179 file_badread(ms); 1180 return -1; 1181 } 1182 1183 off += size; | 1255 file_badread(ms); 1256 return -1; 1257 } 1258 1259 off += size; |
1260 bufsize = 0; 1261 align = 4; |
|
1184 1185 /* Things we can determine before we seek */ 1186 switch (xph_type) { 1187 case PT_DYNAMIC: 1188 linking_style = "dynamically"; 1189 break; | 1262 1263 /* Things we can determine before we seek */ 1264 switch (xph_type) { 1265 case PT_DYNAMIC: 1266 linking_style = "dynamically"; 1267 break; |
1268 case PT_NOTE: 1269 if (sh_num) /* Did this through section headers */ 1270 continue; 1271 if (((align = xph_align) & 0x80000000UL) != 0 || 1272 align < 4) { 1273 if (file_printf(ms, 1274 ", invalid note alignment 0x%lx", 1275 (unsigned long)align) == -1) 1276 return -1; 1277 align = 4; 1278 } 1279 /*FALLTHROUGH*/ |
|
1190 case PT_INTERP: | 1280 case PT_INTERP: |
1191 shared_libraries = " (uses shared libs)"; | 1281 len = xph_filesz < sizeof(nbuf) ? xph_filesz 1282 : sizeof(nbuf); 1283 bufsize = pread(fd, nbuf, len, xph_offset); 1284 if (bufsize == -1) { 1285 file_badread(ms); 1286 return -1; 1287 } |
1192 break; 1193 default: 1194 if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { 1195 /* Maybe warn here? */ 1196 continue; 1197 } 1198 break; 1199 } 1200 1201 /* Things we can determine when we seek */ 1202 switch (xph_type) { | 1288 break; 1289 default: 1290 if (fsize != SIZE_UNKNOWN && xph_offset > fsize) { 1291 /* Maybe warn here? */ 1292 continue; 1293 } 1294 break; 1295 } 1296 1297 /* Things we can determine when we seek */ 1298 switch (xph_type) { |
1299 case PT_INTERP: 1300 if (bufsize && nbuf[0]) { 1301 nbuf[bufsize - 1] = '\0'; 1302 interp = (const char *)nbuf; 1303 } else 1304 interp = "*empty*"; 1305 break; |
|
1203 case PT_NOTE: | 1306 case PT_NOTE: |
1204 if (((align = xph_align) & 0x80000000UL) != 0 || 1205 align < 4) { 1206 if (file_printf(ms, 1207 ", invalid note alignment 0x%lx", 1208 (unsigned long)align) == -1) 1209 return -1; 1210 align = 4; 1211 } 1212 if (sh_num) 1213 break; | |
1214 /* 1215 * This is a PT_NOTE section; loop through all the notes 1216 * in the section. 1217 */ | 1307 /* 1308 * This is a PT_NOTE section; loop through all the notes 1309 * in the section. 1310 */ |
1218 len = xph_filesz < sizeof(nbuf) ? xph_filesz 1219 : sizeof(nbuf); 1220 bufsize = pread(fd, nbuf, len, xph_offset); 1221 if (bufsize == -1) { 1222 file_badread(ms); 1223 return -1; 1224 } | |
1225 offset = 0; 1226 for (;;) { 1227 if (offset >= (size_t)bufsize) 1228 break; 1229 offset = donote(ms, nbuf, offset, 1230 (size_t)bufsize, clazz, swap, align, | 1311 offset = 0; 1312 for (;;) { 1313 if (offset >= (size_t)bufsize) 1314 break; 1315 offset = donote(ms, nbuf, offset, 1316 (size_t)bufsize, clazz, swap, align, |
1231 flags); | 1317 flags, notecount); |
1232 if (offset == 0) 1233 break; 1234 } 1235 break; 1236 default: 1237 break; 1238 } 1239 } | 1318 if (offset == 0) 1319 break; 1320 } 1321 break; 1322 default: 1323 break; 1324 } 1325 } |
1240 if (file_printf(ms, ", %s linked%s", linking_style, shared_libraries) | 1326 if (file_printf(ms, ", %s linked", linking_style) |
1241 == -1) | 1327 == -1) |
1242 return -1; | 1328 return -1; 1329 if (interp[0]) 1330 if (file_printf(ms, ", interpreter %s", 1331 file_printable(ibuf, sizeof(ibuf), interp)) == -1) 1332 return -1; |
1243 return 0; 1244} 1245 1246 1247protected int 1248file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf, 1249 size_t nbytes) 1250{ 1251 union { 1252 int32_t l; 1253 char c[sizeof (int32_t)]; 1254 } u; 1255 int clazz; 1256 int swap; 1257 struct stat st; 1258 off_t fsize; 1259 int flags = 0; 1260 Elf32_Ehdr elf32hdr; 1261 Elf64_Ehdr elf64hdr; | 1333 return 0; 1334} 1335 1336 1337protected int 1338file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf, 1339 size_t nbytes) 1340{ 1341 union { 1342 int32_t l; 1343 char c[sizeof (int32_t)]; 1344 } u; 1345 int clazz; 1346 int swap; 1347 struct stat st; 1348 off_t fsize; 1349 int flags = 0; 1350 Elf32_Ehdr elf32hdr; 1351 Elf64_Ehdr elf64hdr; |
1262 uint16_t type, phnum, shnum; | 1352 uint16_t type, phnum, shnum, notecount; |
1263 1264 if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) 1265 return 0; 1266 /* 1267 * ELF executables have multiple section headers in arbitrary 1268 * file locations and thus file(1) cannot determine it from easily. 1269 * Instead we traverse thru all section headers until a symbol table 1270 * one is found or else the binary is stripped. --- 45 unchanged lines hidden --- | 1353 1354 if (ms->flags & (MAGIC_MIME|MAGIC_APPLE)) 1355 return 0; 1356 /* 1357 * ELF executables have multiple section headers in arbitrary 1358 * file locations and thus file(1) cannot determine it from easily. 1359 * Instead we traverse thru all section headers until a symbol table 1360 * one is found or else the binary is stripped. --- 45 unchanged lines hidden --- |