Browse Source

Fix partial reads in readelf.c [CVE-2014-9653]. Closes: #777585

Christoph Biedl 10 years ago
parent
commit
bf7f1a126a

+ 245 - 0
debian/patches/CVE-2014-9653.1.1231e6e.patch

@@ -0,0 +1,245 @@
+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;

+ 328 - 0
debian/patches/CVE-2014-9653.2.d68a455.patch

@@ -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;

+ 41 - 0
debian/patches/CVE-2014-9653.3.4c948c0.patch

@@ -0,0 +1,41 @@
+Subject: Fix previous, reading section name
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Fri Feb 22 01:35:49 2013 +0000
+Origin: FILE5_12-68-g4c948c0
+Last-Update: 2015-04-19
+
+(prequisite for CVE-2014-9653)
+
+--- a/src/readelf.c
++++ b/src/readelf.c
+@@ -859,18 +859,23 @@
+ 		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) {
++	/* Read offset of name section to be able to read section names later */
++	if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) == -1) {
+ 		file_badread(ms);
+ 		return -1;
+ 	}
+-	name[sizeof(name) - 1] = '\0';
+-	if (strcmp(name, ".debug_info") == 0)
+-		stripped = 0;
++	name_off = xsh_offset;
+ 
+ 	for ( ; num; num--) {
++		/* 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;
++
+ 		if (pread(fd, xsh_addr, xsh_sizeof, off) == -1) {
+ 			file_badread(ms);
+ 			return -1;

+ 19 - 0
debian/patches/CVE-2014-9653.4.a9aef15.patch

@@ -0,0 +1,19 @@
+Subject: Fix stray return -1; from glen at delfi dot ee
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Tue Feb 26 16:20:42 2013 +0000
+Origin: FILE5_13-1-ga9aef15
+Last-Update: 2015-04-19
+
+(prequisite for CVE-2014-9653)
+
+--- a/src/cdf.c
++++ b/src/cdf.c
+@@ -298,8 +298,6 @@
+ 	if (info->i_fd == -1)
+ 		return -1;
+ 
+-		return -1;
+-
+ 	if (pread(info->i_fd, buf, len, off) != (ssize_t)len)
+ 		return -1;
+ 

+ 72 - 0
debian/patches/CVE-2014-9653.5.445c8fb.patch

@@ -0,0 +1,72 @@
+Subject: Bail out on partial reads, from Alexander Cherepanov
+ID: CVE-2014-9653
+Upstream-Author: Christos Zoulas <christos@zoulas.com>
+Date: Tue Dec 16 20:53:05 2014 +0000
+Origin: FILE5_21-10-g445c8fb
+Last-Update: 2015-04-19
+
+--- a/src/readelf.c
++++ b/src/readelf.c
+@@ -324,7 +324,7 @@
+ 	 * Loop through all the program headers.
+ 	 */
+ 	for ( ; num; num--) {
+-		if (pread(fd, xph_addr, xph_sizeof, off) == -1) {
++		if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) {
+ 			file_badread(ms);
+ 			return -1;
+ 		}
+@@ -852,6 +852,7 @@
+ 	uint64_t cap_hw1 = 0;	/* SunOS 5.x hardware capabilites */
+ 	uint64_t cap_sf1 = 0;	/* SunOS 5.x software capabilites */
+ 	char name[50];
++	ssize_t namesize;
+ 
+ 	if (size != xsh_sizeof) {
+ 		if (file_printf(ms, ", corrupted section header size") == -1)
+@@ -860,7 +861,7 @@
+ 	}
+ 
+ 	/* Read offset of name section to be able to read section names later */
+-	if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) == -1) {
++	if (pread(fd, xsh_addr, xsh_sizeof, off + size * strtab) < (ssize_t)xsh_sizeof) {
+ 		file_badread(ms);
+ 		return -1;
+ 	}
+@@ -868,15 +869,15 @@
+ 
+ 	for ( ; num; num--) {
+ 		/* Read the name of this section. */
+-		if (pread(fd, name, sizeof(name), name_off + xsh_name) == -1) {
++		if ((namesize = pread(fd, name, sizeof(name) - 1, name_off + xsh_name)) == -1) {
+ 			file_badread(ms);
+ 			return -1;
+ 		}
+-		name[sizeof(name) - 1] = '\0';
++		name[namesize] = '\0';
+ 		if (strcmp(name, ".debug_info") == 0)
+ 			stripped = 0;
+ 
+-		if (pread(fd, xsh_addr, xsh_sizeof, off) == -1) {
++		if (pread(fd, xsh_addr, xsh_sizeof, off) < (ssize_t)xsh_sizeof) {
+ 			file_badread(ms);
+ 			return -1;
+ 		}
+@@ -900,7 +901,7 @@
+ 				    " for note");
+ 				return -1;
+ 			}
+-			if (pread(fd, nbuf, xsh_size, xsh_offset) == -1) {
++			if (pread(fd, nbuf, xsh_size, xsh_offset) < (ssize_t)xsh_size) {
+ 				file_badread(ms);
+ 				free(nbuf);
+ 				return -1;
+@@ -1056,7 +1057,7 @@
+ 	}
+ 
+   	for ( ; num; num--) {
+-		if (pread(fd, xph_addr, xph_sizeof, off) == -1) {
++		if (pread(fd, xph_addr, xph_sizeof, off) < (ssize_t)xph_sizeof) {
+ 			file_badread(ms);
+ 			return -1;
+ 		}

+ 6 - 0
debian/patches/series

@@ -109,3 +109,9 @@ CVE-2014-8117.3.6f737dd.patch
 CVE-2014-8117.4.90018fe.patch
 CVE-2014-8117.5.5063ca3.patch
 CVE-2014-8117.6.6bf4527.patch
+
+CVE-2014-9653.1.1231e6e.patch
+CVE-2014-9653.2.d68a455.patch
+CVE-2014-9653.3.4c948c0.patch
+CVE-2014-9653.4.a9aef15.patch
+CVE-2014-9653.5.445c8fb.patch