diff options
-rw-r--r-- | usr/src/cmd/file/elf_read.c | 72 | ||||
-rw-r--r-- | usr/src/cmd/file/elf_read.h | 2 |
2 files changed, 52 insertions, 22 deletions
diff --git a/usr/src/cmd/file/elf_read.c b/usr/src/cmd/file/elf_read.c index 905c37b586..544137b5a5 100644 --- a/usr/src/cmd/file/elf_read.c +++ b/usr/src/cmd/file/elf_read.c @@ -65,9 +65,12 @@ static int xlatetom_nhdr(Elf_Nhdr *); static int get_phdr(Elf_Info *, int); static int get_shdr(Elf_Info *, int); -static Elf_Ehdr EI_Ehdr; /* Elf_Ehdr to be stored */ -static Elf_Shdr EI_Shdr; /* recent Elf_Shdr to be stored */ -static Elf_Phdr EI_Phdr; /* recent Elf_Phdr to be stored */ +static Elf_Ehdr EI_Ehdr; /* Elf_Ehdr to be stored */ +static Elf_Word EI_Ehdr_shnum; /* # section headers */ +static Elf_Word EI_Ehdr_phnum; /* # program headers */ +static Elf_Word EI_Ehdr_shstrndx; /* Index of section hdr string table */ +static Elf_Shdr EI_Shdr; /* recent Elf_Shdr to be stored */ +static Elf_Phdr EI_Phdr; /* recent Elf_Phdr to be stored */ static int @@ -161,12 +164,32 @@ elf_read(int fd, Elf_Info *EI) if (pread64(EI->elffd, (void*)ehdr, size, 0) != size) ret = 0; + if (file_xlatetom(ELF_T_EHDR, (char *)ehdr) == ELF_READ_FAIL) ret = 0; if (EI->file == NULL) return (ELF_READ_FAIL); + /* + * Extended section or program indexes in use? If so, special + * values in the ELF header redirect us to get the real values + * from shdr[0]. + */ + EI_Ehdr_shnum = EI_Ehdr.e_shnum; + EI_Ehdr_phnum = EI_Ehdr.e_phnum; + EI_Ehdr_shstrndx = EI_Ehdr.e_shstrndx; + if (((EI_Ehdr_shnum == 0) || (EI_Ehdr_phnum == PN_XNUM)) && + (EI_Ehdr.e_shoff != 0)) { + get_shdr(EI, 0); + if (EI_Ehdr_shnum == 0) + EI_Ehdr_shnum = EI_Shdr.sh_size; + if ((EI_Ehdr_phnum == PN_XNUM) && (EI_Shdr.sh_info != 0)) + EI_Ehdr_phnum = EI_Shdr.sh_info; + if (EI_Ehdr_shstrndx == SHN_XINDEX) + EI_Ehdr_shstrndx = EI_Shdr.sh_link; + } + EI->type = ehdr->e_type; EI->machine = ehdr->e_machine; EI->flags = ehdr->e_flags; @@ -195,13 +218,12 @@ get_phdr(Elf_Info *EI, int inx) { off_t off = 0; size_t size; - Elf_Ehdr *ehdr = &EI_Ehdr; - if (inx >= ehdr->e_phnum) + if (inx >= EI_Ehdr_phnum) return (ELF_READ_FAIL); size = sizeof (Elf_Phdr); - off = (off_t)ehdr->e_phoff + (inx * size); + off = (off_t)EI_Ehdr.e_phoff + (inx * size); if (pread64(EI->elffd, (void *)&EI_Phdr, size, off) != size) return (ELF_READ_FAIL); @@ -219,13 +241,21 @@ get_shdr(Elf_Info *EI, int inx) { off_t off = 0; size_t size; - Elf_Ehdr *ehdr = &EI_Ehdr; - if (inx >= ehdr->e_shnum) + /* + * Prevent access to non-existent section headers. + * + * A value of 0 for e_shoff means that there is no section header + * array in the file. A value of 0 for e_shndx does not necessarily + * mean this - there can still be a 1-element section header array + * to support extended section or program header indexes that + * exceed the 16-bit fields used in the ELF header to represent them. + */ + if ((EI_Ehdr.e_shoff == 0) || ((inx > 0) && (inx >= EI_Ehdr_shnum))) return (ELF_READ_FAIL); size = sizeof (Elf_Shdr); - off = (off_t)ehdr->e_shoff + (inx * size); + off = (off_t)EI_Ehdr.e_shoff + (inx * size); if (pread64(EI->elffd, (void *)&EI_Shdr, size, off) != size) return (ELF_READ_FAIL); @@ -259,7 +289,7 @@ process_phdr(Elf_Info *EI) nsz = sizeof (Elf_Nhdr); nhdr = &Nhdr; class = get_class(); - for (inx = 0; inx < EI_Ehdr.e_phnum; inx++) { + for (inx = 0; inx < EI_Ehdr_phnum; inx++) { if (get_phdr(EI, inx) == ELF_READ_FAIL) return (ELF_READ_FAIL); @@ -278,7 +308,7 @@ process_phdr(Elf_Info *EI) } offset = phdr->p_offset; if (pread64(EI->elffd, (void *)nhdr, nsz, offset) - != nsz) + != nsz) return (ELF_READ_FAIL); /* Translate the ELF note header */ @@ -332,7 +362,7 @@ process_phdr(Elf_Info *EI) fname = psinfo + 120; } EI->core_type = (ntype == NT_PRPSINFO)? - EC_OLDCORE : EC_NEWCORE; + EC_OLDCORE : EC_NEWCORE; (void) memcpy(EI->fname, fname, strlen(fname)); free(psinfo); } @@ -367,11 +397,11 @@ process_shdr(Elf_Info *EI) mac = EI_Ehdr.e_machine; /* if there are no sections, return success anyway */ - if (EI_Ehdr.e_shoff == 0 && EI_Ehdr.e_shnum == 0) + if (EI_Ehdr.e_shoff == 0 && EI_Ehdr_shnum == 0) return (ELF_READ_OKAY); /* read section names from String Section */ - if (get_shdr(EI, EI_Ehdr.e_shstrndx) == ELF_READ_FAIL) + if (get_shdr(EI, EI_Ehdr_shstrndx) == ELF_READ_FAIL) return (ELF_READ_FAIL); if ((section_name = malloc(shdr->sh_size)) == NULL) @@ -382,7 +412,7 @@ process_shdr(Elf_Info *EI) return (ELF_READ_FAIL); /* read all the sections and process them */ - for (idx = 1, i = 0; i < EI_Ehdr.e_shnum; idx++, i++) { + for (idx = 1, i = 0; i < EI_Ehdr_shnum; idx++, i++) { char *str; if (get_shdr(EI, i) == ELF_READ_FAIL) @@ -406,9 +436,9 @@ process_shdr(Elf_Info *EI) * read cap and xlate the values */ if (pread64(EI->elffd, &Chdr, csize, cap_off) - != csize || - file_xlatetom(ELF_T_CAP, (char *)&Chdr) - == 0) { + != csize || + file_xlatetom(ELF_T_CAP, (char *)&Chdr) + == 0) { (void) fprintf(stderr, ELF_ERR_ELFCAP2, File, EI->file); return (ELF_READ_FAIL); @@ -416,10 +446,8 @@ process_shdr(Elf_Info *EI) if (Chdr.c_tag != CA_SUNW_NULL) { (void) cap_val2str(Chdr.c_tag, - Chdr.c_un.c_val, - EI->cap_str, - sizeof (EI->cap_str), - 0, mac); + Chdr.c_un.c_val, EI->cap_str, + sizeof (EI->cap_str), 0, mac); } cap_off += csize; } diff --git a/usr/src/cmd/file/elf_read.h b/usr/src/cmd/file/elf_read.h index 3d05464e7c..90bf209abf 100644 --- a/usr/src/cmd/file/elf_read.h +++ b/usr/src/cmd/file/elf_read.h @@ -71,6 +71,7 @@ extern int is_in_list(char *str); #define Elf_Phdr Elf64_Phdr #define Elf_Cap Elf64_Cap #define Elf_Nhdr Elf64_Nhdr +#define Elf_Word Elf64_Word #define elf_read elf_read64 #define elf_xlatetom elf64_xlatetom @@ -86,6 +87,7 @@ extern int is_in_list(char *str); #define Elf_Phdr Elf32_Phdr #define Elf_Cap Elf32_Cap #define Elf_Nhdr Elf32_Nhdr +#define Elf_Word Elf32_Word #define elf_read elf_read32 #define elf_xlatetom elf32_xlatetom |