123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- Subject: PR/134: Don't seek all overr the place when reading elf files, homogenize (...)
- Upstream-Author: Christos Zoulas <christos@zoulas.com>
- Date: Wed Aug 17 11:34:39 2011 +0000
- Origin: FILE5_08-7-g1231e6e
- Last-Update: 2015-04-19
- PR/134: Don't seek all overr the place when reading elf files, homogenize
- the seeking to seek to the proper offset for each header structure reading
- instead of saving and restoring offsets in random places.
- (prequisite for CVE-2014-9653)
- --- a/src/elfclass.h
- +++ b/src/elfclass.h
- @@ -66,8 +66,7 @@
- if (doshn(ms, clazz, swap, fd,
- (off_t)elf_getu(swap, elfhdr.e_shoff), shnum,
- (size_t)elf_getu16(swap, elfhdr.e_shentsize),
- - &flags,
- - elf_getu16(swap, elfhdr.e_machine)) == -1)
- + fsize, &flags, elf_getu16(swap, elfhdr.e_machine)) == -1)
- return -1;
- break;
-
- --- a/src/readelf.c
- +++ b/src/readelf.c
- @@ -47,8 +47,8 @@
- #endif
- private int dophn_exec(struct magic_set *, int, int, int, off_t, int, size_t,
- off_t, int *, int);
- -private int doshn(struct magic_set *, int, int, int, off_t, int, size_t, int *,
- - int);
- +private int doshn(struct magic_set *, int, int, int, off_t, int, size_t,
- + off_t, int *, int);
- private size_t donote(struct magic_set *, void *, size_t, size_t, int,
- int, size_t, int *);
-
- @@ -156,7 +156,7 @@
- #define xsh_size (clazz == ELFCLASS32 \
- ? elf_getu32(swap, sh32.sh_size) \
- : elf_getu64(swap, sh64.sh_size))
- -#define xsh_offset (clazz == ELFCLASS32 \
- +#define xsh_offset (off_t)(clazz == ELFCLASS32 \
- ? elf_getu32(swap, sh32.sh_offset) \
- : elf_getu64(swap, sh64.sh_offset))
- #define xsh_type (clazz == ELFCLASS32 \
- @@ -308,13 +308,6 @@
- size_t offset;
- unsigned char nbuf[BUFSIZ];
- ssize_t bufsize;
- - off_t savedoffset;
- - struct stat st;
- -
- - if (fstat(fd, &st) < 0) {
- - file_badread(ms);
- - return -1;
- - }
-
- if (size != xph_sizeof) {
- if (file_printf(ms, ", corrupted program header size") == -1)
- @@ -326,7 +319,7 @@
- * Loop through all the program headers.
- */
- for ( ; num; num--) {
- - if ((savedoffset = lseek(fd, off, SEEK_SET)) == (off_t)-1) {
- + if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
- file_badseek(ms);
- return -1;
- }
- @@ -334,15 +327,13 @@
- file_badread(ms);
- return -1;
- }
- + off += size;
- +
- if (xph_offset > fsize) {
- - if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
- - file_badseek(ms);
- - return -1;
- - }
- + /* Perhaps warn here */
- continue;
- }
-
- - off += size;
- if (xph_type != PT_NOTE)
- continue;
-
- @@ -854,7 +845,7 @@
-
- private int
- doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
- - size_t size, int *flags, int mach)
- + size_t size, off_t fsize, int *flags, int mach)
- {
- Elf32_Shdr sh32;
- Elf64_Shdr sh64;
- @@ -871,16 +862,22 @@
- return 0;
- }
-
- - if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
- - file_badseek(ms);
- - return -1;
- - }
- -
- for ( ; num; num--) {
- + if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
- + file_badseek(ms);
- + return -1;
- + }
- if (read(fd, xsh_addr, xsh_sizeof) == -1) {
- file_badread(ms);
- return -1;
- }
- + off += size;
- +
- + if (xsh_offset > fsize) {
- + /* Perhaps warn here */
- + continue;
- + }
- +
- switch (xsh_type) {
- case SHT_SYMTAB:
- #if 0
- @@ -889,11 +886,6 @@
- stripped = 0;
- break;
- case SHT_NOTE:
- - if ((off = lseek(fd, (off_t)0, SEEK_CUR)) ==
- - (off_t)-1) {
- - file_badread(ms);
- - return -1;
- - }
- if ((nbuf = malloc((size_t)xsh_size)) == NULL) {
- file_error(ms, errno, "Cannot allocate memory"
- " for note");
- @@ -922,11 +914,6 @@
- if (noff == 0)
- break;
- }
- - if ((lseek(fd, off, SEEK_SET)) == (off_t)-1) {
- - free(nbuf);
- - file_badread(ms);
- - return -1;
- - }
- free(nbuf);
- break;
- case SHT_SUNW_cap:
- @@ -941,7 +928,7 @@
- break;
- if (lseek(fd, (off_t)xsh_offset, SEEK_SET) ==
- (off_t)-1) {
- - file_badread(ms);
- + file_badseek(ms);
- return -1;
- }
- coff = 0;
- @@ -979,10 +966,6 @@
- break;
- }
- }
- - if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
- - file_badread(ms);
- - return -1;
- - }
- break;
- }
- }
- @@ -1064,13 +1047,6 @@
- unsigned char nbuf[BUFSIZ];
- ssize_t bufsize;
- size_t offset, align;
- - off_t savedoffset = (off_t)-1;
- - struct stat st;
- -
- - if (fstat(fd, &st) < 0) {
- - file_badread(ms);
- - return -1;
- - }
-
- if (size != xph_sizeof) {
- if (file_printf(ms, ", corrupted program header size") == -1)
- @@ -1078,34 +1054,20 @@
- return 0;
- }
-
- - if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
- - file_badseek(ms);
- - return -1;
- - }
- -
- for ( ; num; num--) {
- - if (read(fd, xph_addr, xph_sizeof) == -1) {
- - file_badread(ms);
- + if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
- + file_badseek(ms);
- return -1;
- }
- - if (xph_offset > st.st_size && savedoffset != (off_t)-1) {
- - if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
- - file_badseek(ms);
- - return -1;
- - }
- - continue;
- - }
-
- - if ((savedoffset = lseek(fd, (off_t)0, SEEK_CUR)) == (off_t)-1) {
- - file_badseek(ms);
- + if (read(fd, xph_addr, xph_sizeof) == -1) {
- + file_badread(ms);
- return -1;
- }
-
- + off += size;
- if (xph_offset > fsize) {
- - if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
- - file_badseek(ms);
- - return -1;
- - }
- + /* Maybe warn here? */
- continue;
- }
-
- @@ -1130,8 +1092,7 @@
- * This is a PT_NOTE section; loop through all the notes
- * in the section.
- */
- - if (lseek(fd, xph_offset, SEEK_SET)
- - == (off_t)-1) {
- + if (lseek(fd, xph_offset, SEEK_SET) == (off_t)-1) {
- file_badseek(ms);
- return -1;
- }
- @@ -1151,10 +1112,6 @@
- if (offset == 0)
- break;
- }
- - if (lseek(fd, savedoffset, SEEK_SET) == (off_t)-1) {
- - file_badseek(ms);
- - return -1;
- - }
- break;
- default:
- break;
|