
 Thomas Jarosch of Intra2net AG reported a denial of service issue (resource 
 consumption) in the ELF parser used by file(1). 
 Using file(1) on a specially-crafted ELF binary could lead to a denial of 
 service (resource consumption).
 
 Patch: Stop reporting bad capabilities after the first few. 
        https://github.com/file/file/commit/d7cdad007c507e6c79f51f058dd77fab70ceb9f6
 Patch: Don't bail if there was no error, buf could have been NULL on entry. 
	https://github.com/file/file/commit/6bf45271eb8e0e6577b92042ce2003ba998d1686
	(!!! not needed, as code vulnerable code was introduced later !!!)
 Patch: limit the number of program and section header number of sections
	https://github.com/file/file/commit/b4c01141e5367f247b84dcaf6aefbb4e741842b8
	but use adapted values from:
   	 https://github.com/file/file/commit/8a905717660395b38ec4966493f6f1cf2f33946c
 Patch: limit recursion level
	CVE-2014-8117
	set recursion level to 10 as done in:
	 https://github.com/file/file/commit/6f737ddfadb596d7d4a993f7ed2141ffd664a81c
	bump to 15 as done in:
	 https://github.com/file/file/commit/90018fe22ff8b74a22fcd142225b0a00f3f12677
	
Index: php5-5.3.3/ext/fileinfo/libmagic/readelf.c
===================================================================
--- php5-5.3.3.orig/ext/fileinfo/libmagic/readelf.c	2015-01-21 13:54:56.000000000 +0100
+++ php5-5.3.3/ext/fileinfo/libmagic/readelf.c	2015-01-21 15:58:20.000000000 +0100
@@ -60,6 +60,17 @@
 private uint32_t getu32(int, uint32_t);
 private uint64_t getu64(int, uint64_t);
 
+#define MAX_PHNUM 256
+#define MAX_SHNUM 1024
+
+private int
+toomany(struct magic_set *ms, const char *name, uint16_t num)
+{
+ if (file_printf(ms, ", too many %s header sections (%u)", name, num) == -1)
+	 return -1;
+ return 0;
+}
+
 private uint16_t
 getu16(int swap, uint16_t value)
 {
@@ -397,13 +408,13 @@
 	if (namesz & 0x80000000) {
 	    (void)file_printf(ms, ", bad note name size 0x%lx",
 		(unsigned long)namesz);
-	    return offset;
+	    return 0;
 	}
 
 	if (descsz & 0x80000000) {
 	    (void)file_printf(ms, ", bad note description size 0x%lx",
 		(unsigned long)descsz);
-	    return offset;
+	    return 0;
 	}
 
 
@@ -827,6 +838,7 @@
 	Elf32_Shdr sh32;
 	Elf64_Shdr sh64;
 	int stripped = 1;
+	size_t nbadcap = 0;
 	void *nbuf;
 	off_t noff;
 	uint64_t cap_hw1 = 0;	/* SunOS 5.x hardware capabilites */
@@ -895,6 +907,9 @@
 		case SHT_SUNW_cap:
 		    {
 			off_t coff;
+
+			if (nbadcap > 5)
+				break;
 			if ((off = lseek(fd, (off_t)0, SEEK_CUR)) ==
 			    (off_t)-1) {
 				file_badread(ms);
@@ -935,6 +950,8 @@
 					    (unsigned long long)xcap_tag,
 					    (unsigned long long)xcap_val) == -1)
 						return -1;
+					if (nbadcap++ > 2)
+						coff = xsh_size;
 					break;
 				}
 			}
@@ -1141,7 +1158,7 @@
 	int flags = 0;
 	Elf32_Ehdr elf32hdr;
 	Elf64_Ehdr elf64hdr;
-	uint16_t type;
+	uint16_t type, phnum, shnum;
 
 	if (ms->flags & (MAGIC_MIME|MAGIC_APPLE))
 		return 0;
Index: php5-5.3.3/ext/fileinfo/libmagic/elfclass.h
===================================================================
--- php5-5.3.3.orig/ext/fileinfo/libmagic/elfclass.h	2008-11-02 17:13:49.000000000 +0100
+++ php5-5.3.3/ext/fileinfo/libmagic/elfclass.h	2015-01-21 15:54:42.000000000 +0100
@@ -35,9 +35,11 @@
 	switch (type) {
 #ifdef ELFCORE
 	case ET_CORE:
+		phnum = elf_getu16(swap, elfhdr.e_phnum);
+		if (phnum > MAX_PHNUM)
+			return toomany(ms, "program", phnum);
 		if (dophn_core(ms, clazz, swap, fd,
-		    (off_t)elf_getu(swap, elfhdr.e_phoff),
-		    elf_getu16(swap, elfhdr.e_phnum), 
+		    (off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
 		    (size_t)elf_getu16(swap, elfhdr.e_phentsize),
 		    fsize, &flags) == -1)
 			return -1;
@@ -45,18 +47,25 @@
 #endif
 	case ET_EXEC:
 	case ET_DYN:
+		phnum = elf_getu16(swap, elfhdr.e_phnum);
+		if (phnum > MAX_PHNUM)
+			return toomany(ms, "program", phnum);
+		shnum = elf_getu16(swap, elfhdr.e_shnum);
+		if (shnum > MAX_SHNUM)
+			return toomany(ms, "section", shnum);
 		if (dophn_exec(ms, clazz, swap, fd,
-		    (off_t)elf_getu(swap, elfhdr.e_phoff),
-		    elf_getu16(swap, elfhdr.e_phnum), 
+		    (off_t)elf_getu(swap, elfhdr.e_phoff), phnum,
 		    (size_t)elf_getu16(swap, elfhdr.e_phentsize),
-		    fsize, &flags, elf_getu16(swap, elfhdr.e_shnum))
+		    fsize, &flags, shnum))
 		    == -1)
 			return -1;
 		/*FALLTHROUGH*/
 	case ET_REL:
+		shnum = elf_getu16(swap, elfhdr.e_shnum);
+		if (shnum > MAX_SHNUM)
+			return toomany(ms, "section", shnum);
 		if (doshn(ms, clazz, swap, fd,
-		    (off_t)elf_getu(swap, elfhdr.e_shoff),
-		    elf_getu16(swap, elfhdr.e_shnum),
+		    (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)
Index: php5-5.3.3/ext/fileinfo/libmagic/softmagic.c
===================================================================
--- php5-5.3.3.orig/ext/fileinfo/libmagic/softmagic.c	2015-01-21 14:40:10.000000000 +0100
+++ php5-5.3.3/ext/fileinfo/libmagic/softmagic.c	2015-01-21 16:01:47.000000000 +0100
@@ -1017,7 +1017,7 @@
 	uint32_t offset = ms->offset;
 	union VALUETYPE *p = &ms->ms_value;
 
-	if (recursion_level >= 20) {
+	if (recursion_level >= 15) {
 		file_error(ms, 0, "recursion nesting exceeded");
 		return -1;
 	}
