|
@@ -0,0 +1,328 @@
|
|
|
+Subject: Use pread (...)
|
|
|
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
|
|
|
+Date: Mon Feb 18 15:40:59 2013 +0000
|
|
|
+Origin: FILE5_12-64-gd68a455
|
|
|
+Last-Update: 2015-04-19
|
|
|
+
|
|
|
+ - use pread
|
|
|
+ - add reading of section header names to determine if an ELF file is stripped
|
|
|
+ (Jan Kaluza)
|
|
|
+
|
|
|
+(prequisite for CVE-2014-9653)
|
|
|
+
|
|
|
+--- a/configure.ac
|
|
|
++++ b/configure.ac
|
|
|
+@@ -145,7 +145,7 @@
|
|
|
+ AC_CHECK_FUNCS(mmap strerror strndup strtoul mbrtowc mkstemp utimes utime wcwidth strtof)
|
|
|
+
|
|
|
+ dnl Provide implementation of some required functions if necessary
|
|
|
+-AC_REPLACE_FUNCS(getopt_long asprintf vasprintf strlcpy strlcat)
|
|
|
++AC_REPLACE_FUNCS(getopt_long asprintf vasprintf strlcpy strlcat pread)
|
|
|
+
|
|
|
+ dnl Checks for libraries
|
|
|
+ AC_CHECK_LIB(z,gzopen)
|
|
|
+--- a/src/cdf.c
|
|
|
++++ b/src/cdf.c
|
|
|
+@@ -298,10 +298,9 @@
|
|
|
+ if (info->i_fd == -1)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+- if (lseek(info->i_fd, off, SEEK_SET) == (off_t)-1)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+- if (read(info->i_fd, buf, len) != (ssize_t)len)
|
|
|
++ if (pread(info->i_fd, buf, len, off) != (ssize_t)len)
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ return (ssize_t)len;
|
|
|
+--- a/src/elfclass.h
|
|
|
++++ b/src/elfclass.h
|
|
|
+@@ -66,7 +66,8 @@
|
|
|
+ if (doshn(ms, clazz, swap, fd,
|
|
|
+ (off_t)elf_getu(swap, elfhdr.e_shoff), shnum,
|
|
|
+ (size_t)elf_getu16(swap, elfhdr.e_shentsize),
|
|
|
+- fsize, &flags, elf_getu16(swap, elfhdr.e_machine)) == -1)
|
|
|
++ fsize, &flags, elf_getu16(swap, elfhdr.e_machine),
|
|
|
++ (int)elf_getu16(swap, elfhdr.e_shstrndx)) == -1)
|
|
|
+ return -1;
|
|
|
+ break;
|
|
|
+
|
|
|
+--- a/src/file.h
|
|
|
++++ b/src/file.h
|
|
|
+@@ -448,6 +448,9 @@
|
|
|
+ #define strtoul(a, b, c) strtol(a, b, c)
|
|
|
+ #endif
|
|
|
+
|
|
|
++#ifndef HAVE_PREAD
|
|
|
++ssize_t pread(int, void *, size_t, off_t);
|
|
|
++#endif
|
|
|
+ #ifndef HAVE_VASPRINTF
|
|
|
+ int vasprintf(char **, const char *, va_list);
|
|
|
+ #endif
|
|
|
+--- /dev/null
|
|
|
++++ b/src/pread.c
|
|
|
+@@ -0,0 +1,14 @@
|
|
|
++#include "file.h"
|
|
|
++#ifndef lint
|
|
|
++FILE_RCSID("@(#)$File: ctime_r.c,v 1.1 2012/05/15 17:14:36 christos Exp $")
|
|
|
++#endif /* lint */
|
|
|
++#include <fcntl.h>
|
|
|
++#include <unistd.h>
|
|
|
++
|
|
|
++ssize_t
|
|
|
++pread(int fd, void *buf, ssize_t len, off_t off) {
|
|
|
++ if (lseek(fd, off, SEEK_SET) == (off_t)-1)
|
|
|
++ return -1;
|
|
|
++
|
|
|
++ return read(fd, buf, len);
|
|
|
++}
|
|
|
+--- a/src/readelf.c
|
|
|
++++ b/src/readelf.c
|
|
|
+@@ -48,7 +48,7 @@
|
|
|
+ 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,
|
|
|
+- off_t, int *, int);
|
|
|
++ off_t, int *, int, int);
|
|
|
+ private size_t donote(struct magic_set *, void *, size_t, size_t, int,
|
|
|
+ int, size_t, int *);
|
|
|
+
|
|
|
+@@ -141,19 +141,21 @@
|
|
|
+ #define elf_getu32(swap, value) getu32(swap, value)
|
|
|
+ #ifdef USE_ARRAY_FOR_64BIT_TYPES
|
|
|
+ # define elf_getu64(swap, array) \
|
|
|
+- ((swap ? ((uint64_t)elf_getu32(swap, array[0])) << 32 : elf_getu32(swap, array[0])) + \
|
|
|
+- (swap ? elf_getu32(swap, array[1]) : ((uint64_t)elf_getu32(swap, array[1]) << 32)))
|
|
|
++ ((swap ? ((uint64_t)elf_getu32(swap, array[0])) << 32 \
|
|
|
++ : elf_getu32(swap, array[0])) + \
|
|
|
++ (swap ? elf_getu32(swap, array[1]) : \
|
|
|
++ ((uint64_t)elf_getu32(swap, array[1]) << 32)))
|
|
|
+ #else
|
|
|
+ # define elf_getu64(swap, value) getu64(swap, value)
|
|
|
+ #endif
|
|
|
+
|
|
|
+ #define xsh_addr (clazz == ELFCLASS32 \
|
|
|
+- ? (void *) &sh32 \
|
|
|
+- : (void *) &sh64)
|
|
|
++ ? (void *)&sh32 \
|
|
|
++ : (void *)&sh64)
|
|
|
+ #define xsh_sizeof (clazz == ELFCLASS32 \
|
|
|
+- ? sizeof sh32 \
|
|
|
+- : sizeof sh64)
|
|
|
+-#define xsh_size (clazz == ELFCLASS32 \
|
|
|
++ ? sizeof(sh32) \
|
|
|
++ : sizeof(sh64))
|
|
|
++#define xsh_size (size_t)(clazz == ELFCLASS32 \
|
|
|
+ ? elf_getu32(swap, sh32.sh_size) \
|
|
|
+ : elf_getu64(swap, sh64.sh_size))
|
|
|
+ #define xsh_offset (off_t)(clazz == ELFCLASS32 \
|
|
|
+@@ -162,12 +164,15 @@
|
|
|
+ #define xsh_type (clazz == ELFCLASS32 \
|
|
|
+ ? elf_getu32(swap, sh32.sh_type) \
|
|
|
+ : elf_getu32(swap, sh64.sh_type))
|
|
|
++#define xsh_name (clazz == ELFCLASS32 \
|
|
|
++ ? elf_getu32(swap, sh32.sh_name) \
|
|
|
++ : elf_getu32(swap, sh64.sh_name))
|
|
|
+ #define xph_addr (clazz == ELFCLASS32 \
|
|
|
+ ? (void *) &ph32 \
|
|
|
+ : (void *) &ph64)
|
|
|
+ #define xph_sizeof (clazz == ELFCLASS32 \
|
|
|
+- ? sizeof ph32 \
|
|
|
+- : sizeof ph64)
|
|
|
++ ? sizeof(ph32) \
|
|
|
++ : sizeof(ph64))
|
|
|
+ #define xph_type (clazz == ELFCLASS32 \
|
|
|
+ ? elf_getu32(swap, ph32.p_type) \
|
|
|
+ : elf_getu32(swap, ph64.p_type))
|
|
|
+@@ -183,8 +188,8 @@
|
|
|
+ ? elf_getu32(swap, ph32.p_filesz) \
|
|
|
+ : elf_getu64(swap, ph64.p_filesz)))
|
|
|
+ #define xnh_addr (clazz == ELFCLASS32 \
|
|
|
+- ? (void *) &nh32 \
|
|
|
+- : (void *) &nh64)
|
|
|
++ ? (void *)&nh32 \
|
|
|
++ : (void *)&nh64)
|
|
|
+ #define xph_memsz (size_t)((clazz == ELFCLASS32 \
|
|
|
+ ? elf_getu32(swap, ph32.p_memsz) \
|
|
|
+ : elf_getu64(swap, ph64.p_memsz)))
|
|
|
+@@ -204,8 +209,8 @@
|
|
|
+ ? prpsoffsets32[i] \
|
|
|
+ : prpsoffsets64[i])
|
|
|
+ #define xcap_addr (clazz == ELFCLASS32 \
|
|
|
+- ? (void *) &cap32 \
|
|
|
+- : (void *) &cap64)
|
|
|
++ ? (void *)&cap32 \
|
|
|
++ : (void *)&cap64)
|
|
|
+ #define xcap_sizeof (clazz == ELFCLASS32 \
|
|
|
+ ? sizeof cap32 \
|
|
|
+ : sizeof cap64)
|
|
|
+@@ -305,7 +310,7 @@
|
|
|
+ {
|
|
|
+ Elf32_Phdr ph32;
|
|
|
+ Elf64_Phdr ph64;
|
|
|
+- size_t offset;
|
|
|
++ size_t offset, len;
|
|
|
+ unsigned char nbuf[BUFSIZ];
|
|
|
+ ssize_t bufsize;
|
|
|
+
|
|
|
+@@ -319,11 +324,7 @@
|
|
|
+ * Loop through all the program headers.
|
|
|
+ */
|
|
|
+ for ( ; num; num--) {
|
|
|
+- if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
|
|
|
+- file_badseek(ms);
|
|
|
+- return -1;
|
|
|
+- }
|
|
|
+- if (read(fd, xph_addr, xph_sizeof) == -1) {
|
|
|
++ if (pread(fd, xph_addr, xph_sizeof, off) == -1) {
|
|
|
+ file_badread(ms);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+@@ -341,13 +342,8 @@
|
|
|
+ * This is a PT_NOTE section; loop through all the notes
|
|
|
+ * in the section.
|
|
|
+ */
|
|
|
+- if (lseek(fd, xph_offset, SEEK_SET) == (off_t)-1) {
|
|
|
+- file_badseek(ms);
|
|
|
+- return -1;
|
|
|
+- }
|
|
|
+- bufsize = read(fd, nbuf,
|
|
|
+- ((xph_filesz < sizeof(nbuf)) ? xph_filesz : sizeof(nbuf)));
|
|
|
+- if (bufsize == -1) {
|
|
|
++ len = xph_filesz < sizeof(nbuf) ? xph_filesz : sizeof(nbuf);
|
|
|
++ if ((bufsize = pread(fd, nbuf, len, xph_offset)) == -1) {
|
|
|
+ file_badread(ms);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+@@ -845,16 +841,17 @@
|
|
|
+
|
|
|
+ private int
|
|
|
+ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
|
|
|
+- size_t size, off_t fsize, int *flags, int mach)
|
|
|
++ size_t size, off_t fsize, int *flags, int mach, int strtab)
|
|
|
+ {
|
|
|
+ Elf32_Shdr sh32;
|
|
|
+ Elf64_Shdr sh64;
|
|
|
+ int stripped = 1;
|
|
|
+ size_t nbadcap = 0;
|
|
|
+ void *nbuf;
|
|
|
+- off_t noff;
|
|
|
++ off_t noff, name_off;
|
|
|
+ uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */
|
|
|
+ uint64_t cap_sf1 = 0; /* SunOS 5.x software capabilites */
|
|
|
++ char name[50];
|
|
|
+
|
|
|
+ if (size != xsh_sizeof) {
|
|
|
+ if (file_printf(ms, ", corrupted section header size") == -1)
|
|
|
+@@ -862,12 +859,19 @@
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
++ /* Save offset of name section to be able to read section names later */
|
|
|
++ name_off = off * size * strtab;
|
|
|
++ /* Read the name of this section. */
|
|
|
++ if (pread(fd, name, sizeof(name), name_off + xsh_name) == -1) {
|
|
|
++ file_badread(ms);
|
|
|
++ return -1;
|
|
|
++ }
|
|
|
++ name[sizeof(name) - 1] = '\0';
|
|
|
++ if (strcmp(name, ".debug_info") == 0)
|
|
|
++ stripped = 0;
|
|
|
++
|
|
|
+ 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) {
|
|
|
++ if (pread(fd, xsh_addr, xsh_sizeof, off) == -1) {
|
|
|
+ file_badread(ms);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+@@ -886,31 +890,23 @@
|
|
|
+ stripped = 0;
|
|
|
+ break;
|
|
|
+ case SHT_NOTE:
|
|
|
+- if ((nbuf = malloc((size_t)xsh_size)) == NULL) {
|
|
|
++ if ((nbuf = malloc(xsh_size)) == NULL) {
|
|
|
+ file_error(ms, errno, "Cannot allocate memory"
|
|
|
+ " for note");
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+- if ((noff = lseek(fd, (off_t)xsh_offset, SEEK_SET)) ==
|
|
|
+- (off_t)-1) {
|
|
|
++ if (pread(fd, nbuf, xsh_size, xsh_offset) == -1) {
|
|
|
+ file_badread(ms);
|
|
|
+ free(nbuf);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+- if (read(fd, nbuf, (size_t)xsh_size) !=
|
|
|
+- (ssize_t)xsh_size) {
|
|
|
+- free(nbuf);
|
|
|
+- file_badread(ms);
|
|
|
+- return -1;
|
|
|
+- }
|
|
|
+
|
|
|
+ noff = 0;
|
|
|
+ for (;;) {
|
|
|
+ if (noff >= (off_t)xsh_size)
|
|
|
+ break;
|
|
|
+ noff = donote(ms, nbuf, (size_t)noff,
|
|
|
+- (size_t)xsh_size, clazz, swap, 4,
|
|
|
+- flags);
|
|
|
++ xsh_size, clazz, swap, 4, flags);
|
|
|
+ if (noff == 0)
|
|
|
+ break;
|
|
|
+ }
|
|
|
+@@ -926,8 +922,8 @@
|
|
|
+ }
|
|
|
+ if (nbadcap > 5)
|
|
|
+ break;
|
|
|
+- if (lseek(fd, (off_t)xsh_offset, SEEK_SET) ==
|
|
|
+- (off_t)-1) {
|
|
|
++
|
|
|
++ if (lseek(fd, xsh_offset, SEEK_SET) == (off_t)-1) {
|
|
|
+ file_badseek(ms);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+@@ -1046,7 +1042,7 @@
|
|
|
+ const char *shared_libraries = "";
|
|
|
+ unsigned char nbuf[BUFSIZ];
|
|
|
+ ssize_t bufsize;
|
|
|
+- size_t offset, align;
|
|
|
++ size_t offset, align, len;
|
|
|
+
|
|
|
+ if (size != xph_sizeof) {
|
|
|
+ if (file_printf(ms, ", corrupted program header size") == -1)
|
|
|
+@@ -1055,13 +1051,8 @@
|
|
|
+ }
|
|
|
+
|
|
|
+ for ( ; num; num--) {
|
|
|
+- if (lseek(fd, off, SEEK_SET) == (off_t)-1) {
|
|
|
+- file_badseek(ms);
|
|
|
+- return -1;
|
|
|
+- }
|
|
|
+-
|
|
|
+- if (read(fd, xph_addr, xph_sizeof) == -1) {
|
|
|
+- file_badread(ms);
|
|
|
++ if (pread(fd, xph_addr, xph_sizeof, off) == -1) {
|
|
|
++ file_badread(ms);
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+@@ -1092,12 +1083,9 @@
|
|
|
+ * This is a PT_NOTE section; loop through all the notes
|
|
|
+ * in the section.
|
|
|
+ */
|
|
|
+- if (lseek(fd, xph_offset, SEEK_SET) == (off_t)-1) {
|
|
|
+- file_badseek(ms);
|
|
|
+- return -1;
|
|
|
+- }
|
|
|
+- bufsize = read(fd, nbuf, ((xph_filesz < sizeof(nbuf)) ?
|
|
|
+- xph_filesz : sizeof(nbuf)));
|
|
|
++ len = xph_filesz < sizeof(nbuf) ? xph_filesz
|
|
|
++ : sizeof(nbuf);
|
|
|
++ bufsize = pread(fd, nbuf, len, xph_offset);
|
|
|
+ if (bufsize == -1) {
|
|
|
+ file_badread(ms);
|
|
|
+ return -1;
|