aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXin LI <delphij@FreeBSD.org>2014-12-10 08:36:07 +0000
committerXin LI <delphij@FreeBSD.org>2014-12-10 08:36:07 +0000
commitabab1d1a2855ea9ed8856e63150f6945a3ae6cf7 (patch)
treed4ebd85c9368a985ff948d0905a9ee7340591878
parent08e611325f05ffb4d353400c0ea49f104c685f62 (diff)
downloadsrc-abab1d1a2855ea9ed8856e63150f6945a3ae6cf7.tar.gz
src-abab1d1a2855ea9ed8856e63150f6945a3ae6cf7.zip
Notes
-rw-r--r--UPDATING3
-rw-r--r--contrib/file/elfclass.h24
-rw-r--r--contrib/file/readelf.c23
-rw-r--r--contrib/file/softmagic.c5
-rw-r--r--sys/conf/newvers.sh2
5 files changed, 44 insertions, 13 deletions
diff --git a/UPDATING b/UPDATING
index 4d81f9e1d026..4527ffc972e2 100644
--- a/UPDATING
+++ b/UPDATING
@@ -16,6 +16,9 @@ from older versions of FreeBSD, try WITHOUT_CLANG to bootstrap to the tip of
stable/10, and then rebuild without this option. The bootstrap process from
older version of current is a bit fragile.
+20141210: p13 FreeBSD-SA-14:28.file
+ Fix multiple vulnerabilities in file(1) and libmagic(3).
+
20141104: p12 FreeBSD-SA-14:24.sshd
FreeBSD-SA-14:25.setlogin
FreeBSD-SA-14:26.ftp
diff --git a/contrib/file/elfclass.h b/contrib/file/elfclass.h
index 2e7741b3fc00..a3e3969d490e 100644
--- a/contrib/file/elfclass.h
+++ b/contrib/file/elfclass.h
@@ -35,10 +35,12 @@
switch (type) {
#ifdef ELFCORE
case ET_CORE:
+ phnum = elf_getu16(swap, elfhdr.e_phnum);
+ if (phnum > MAX_PHNUM)
+ return toomany(ms, "program", phnum);
flags |= FLAGS_IS_CORE;
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;
@@ -46,18 +48,24 @@
#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))
- == -1)
+ 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),
fsize, &flags, elf_getu16(swap, elfhdr.e_machine)) == -1)
return -1;
diff --git a/contrib/file/readelf.c b/contrib/file/readelf.c
index 8b141e12d405..85d28a31bcdd 100644
--- a/contrib/file/readelf.c
+++ b/contrib/file/readelf.c
@@ -60,6 +60,18 @@ private uint16_t getu16(int, uint16_t);
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)
{
@@ -384,13 +396,13 @@ donote(struct magic_set *ms, void *vbuf, size_t offset, size_t size,
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;
}
@@ -847,6 +859,7 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
Elf32_Shdr sh32;
Elf64_Shdr sh64;
int stripped = 1;
+ size_t nbadcap = 0;
void *nbuf;
off_t noff, coff;
uint64_t cap_hw1 = 0; /* SunOS 5.x hardware capabilites */
@@ -919,6 +932,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
free(nbuf);
break;
case SHT_SUNW_cap:
+ if (nbadcap > 5)
+ break;
if (lseek(fd, (off_t)xsh_offset, SEEK_SET) ==
(off_t)-1) {
file_badseek(ms);
@@ -955,6 +970,8 @@ doshn(struct magic_set *ms, int clazz, int swap, int fd, off_t off, int num,
(unsigned long long)xcap_tag,
(unsigned long long)xcap_val) == -1)
return -1;
+ if (nbadcap++ > 2)
+ coff = xsh_size;
break;
}
}
@@ -1142,7 +1159,7 @@ file_tryelf(struct magic_set *ms, int fd, const unsigned char *buf,
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;
diff --git a/contrib/file/softmagic.c b/contrib/file/softmagic.c
index 2afd9679cee6..44c8a06d893a 100644
--- a/contrib/file/softmagic.c
+++ b/contrib/file/softmagic.c
@@ -61,6 +61,9 @@ private void cvt_32(union VALUETYPE *, const struct magic *);
private void cvt_64(union VALUETYPE *, const struct magic *);
#define OFFSET_OOB(n, o, i) ((n) < (o) || (i) > ((n) - (o)))
+
+#define MAX_RECURSION_LEVEL 10
+
/*
* softmagic - lookup one file in parsed, in-memory copy of database
* Passed the name and FILE * of one file to be typed.
@@ -1027,7 +1030,7 @@ mget(struct magic_set *ms, const unsigned char *s,
uint32_t count = m->str_range;
union VALUETYPE *p = &ms->ms_value;
- if (recursion_level >= 20) {
+ if (recursion_level >= MAX_RECURSION_LEVEL) {
file_error(ms, 0, "recursion nesting exceeded");
return -1;
}
diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh
index f75037a80384..32c27da2c9cc 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -32,7 +32,7 @@
TYPE="FreeBSD"
REVISION="10.0"
-BRANCH="RELEASE-p12"
+BRANCH="RELEASE-p13"
if [ "X${BRANCH_OVERRIDE}" != "X" ]; then
BRANCH=${BRANCH_OVERRIDE}
fi