svn commit: r267827 - in head/contrib/file: . Magdir

Xin LI delphij at FreeBSD.org
Tue Jun 24 19:04:34 UTC 2014


Author: delphij
Date: Tue Jun 24 19:04:32 2014
New Revision: 267827
URL: http://svnweb.freebsd.org/changeset/base/267827

Log:
  Fix multiple vulnerabilities in file(1) and libmagic(3).
  
  Security:	FreeBSD-SA-14:16.file
  Approved by:	so

Modified:
  head/contrib/file/Magdir/commands
  head/contrib/file/ascmagic.c
  head/contrib/file/file.h
  head/contrib/file/funcs.c
  head/contrib/file/softmagic.c

Modified: head/contrib/file/Magdir/commands
==============================================================================
--- head/contrib/file/Magdir/commands	Tue Jun 24 18:56:45 2014	(r267826)
+++ head/contrib/file/Magdir/commands	Tue Jun 24 19:04:32 2014	(r267827)
@@ -49,7 +49,8 @@
 !:mime	text/x-awk
 0	string/wt	#!\ /usr/bin/awk	awk script text executable
 !:mime	text/x-awk
-0	regex		=^\\s*BEGIN\\s*[{]	awk script text
+0	regex		=^\\s{0,100}BEGIN\\s{0,100}[{]	awk script text
+!:strength - 12
 
 # AT&T Bell Labs' Plan 9 shell
 0	string/wt	#!\ /bin/rc	Plan 9 rc shell script text executable

Modified: head/contrib/file/ascmagic.c
==============================================================================
--- head/contrib/file/ascmagic.c	Tue Jun 24 18:56:45 2014	(r267826)
+++ head/contrib/file/ascmagic.c	Tue Jun 24 19:04:32 2014	(r267827)
@@ -147,7 +147,7 @@ file_ascmagic_with_encoding(struct magic
 		    == NULL)
 			goto done;
 		if ((rv = file_softmagic(ms, utf8_buf,
-		    (size_t)(utf8_end - utf8_buf), TEXTTEST, text)) == 0)
+		    (size_t)(utf8_end - utf8_buf), 0, TEXTTEST, text)) == 0)
 			rv = -1;
 	}
 

Modified: head/contrib/file/file.h
==============================================================================
--- head/contrib/file/file.h	Tue Jun 24 18:56:45 2014	(r267826)
+++ head/contrib/file/file.h	Tue Jun 24 19:04:32 2014	(r267827)
@@ -414,7 +414,7 @@ protected int file_encoding(struct magic
     unichar **, size_t *, const char **, const char **, const char **);
 protected int file_is_tar(struct magic_set *, const unsigned char *, size_t);
 protected int file_softmagic(struct magic_set *, const unsigned char *, size_t,
-    int, int);
+    size_t, int, int);
 protected struct mlist *file_apprentice(struct magic_set *, const char *, int);
 protected uint64_t file_signextend(struct magic_set *, struct magic *,
     uint64_t);

Modified: head/contrib/file/funcs.c
==============================================================================
--- head/contrib/file/funcs.c	Tue Jun 24 18:56:45 2014	(r267826)
+++ head/contrib/file/funcs.c	Tue Jun 24 19:04:32 2014	(r267827)
@@ -228,7 +228,7 @@ file_buffer(struct magic_set *ms, int fd
 
 	/* try soft magic tests */
 	if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0)
-		if ((m = file_softmagic(ms, ubuf, nb, BINTEST,
+		if ((m = file_softmagic(ms, ubuf, nb, 0, BINTEST,
 		    looks_text)) != 0) {
 			if ((ms->flags & MAGIC_DEBUG) != 0)
 				(void)fprintf(stderr, "softmagic %d\n", m);

Modified: head/contrib/file/softmagic.c
==============================================================================
--- head/contrib/file/softmagic.c	Tue Jun 24 18:56:45 2014	(r267826)
+++ head/contrib/file/softmagic.c	Tue Jun 24 19:04:32 2014	(r267827)
@@ -43,9 +43,9 @@ FILE_RCSID("@(#)$File: softmagic.c,v 1.1
 
 
 private int match(struct magic_set *, struct magic *, uint32_t,
-    const unsigned char *, size_t, int, int);
+    const unsigned char *, size_t, int, int, int);
 private int mget(struct magic_set *, const unsigned char *,
-    struct magic *, size_t, unsigned int, int);
+    struct magic *, size_t, unsigned int, int, int);
 private int magiccheck(struct magic_set *, struct magic *);
 private int32_t mprint(struct magic_set *, struct magic *);
 private int32_t moffset(struct magic_set *, struct magic *);
@@ -60,6 +60,7 @@ private void cvt_16(union VALUETYPE *, c
 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)))
 /*
  * softmagic - lookup one file in parsed, in-memory copy of database
  * Passed the name and FILE * of one file to be typed.
@@ -67,13 +68,13 @@ private void cvt_64(union VALUETYPE *, c
 /*ARGSUSED1*/		/* nbytes passed for regularity, maybe need later */
 protected int
 file_softmagic(struct magic_set *ms, const unsigned char *buf, size_t nbytes,
-    int mode, int text)
+    size_t level, int mode, int text)
 {
 	struct mlist *ml;
 	int rv;
 	for (ml = ms->mlist->next; ml != ms->mlist; ml = ml->next)
 		if ((rv = match(ms, ml->magic, ml->nmagic, buf, nbytes, mode,
-		    text)) != 0)
+		    text, level)) != 0)
 			return rv;
 
 	return 0;
@@ -108,7 +109,8 @@ file_softmagic(struct magic_set *ms, con
  */
 private int
 match(struct magic_set *ms, struct magic *magic, uint32_t nmagic,
-    const unsigned char *s, size_t nbytes, int mode, int text)
+    const unsigned char *s, size_t nbytes, int mode, int text,
+    int recursion_level)
 {
 	uint32_t magindex = 0;
 	unsigned int cont_level = 0;
@@ -140,7 +142,7 @@ match(struct magic_set *ms, struct magic
 		ms->line = m->lineno;
 
 		/* if main entry matches, print it... */
-		switch (mget(ms, s, m, nbytes, cont_level, text)) {
+		switch (mget(ms, s, m, nbytes, cont_level, text, recursion_level + 1)) {
 		case -1:
 			return -1;
 		case 0:
@@ -223,7 +225,7 @@ match(struct magic_set *ms, struct magic
 					continue;
 			}
 #endif
-			switch (mget(ms, s, m, nbytes, cont_level, text)) {
+			switch (mget(ms, s, m, nbytes, cont_level, text, recursion_level + 1)) {
 			case -1:
 				return -1;
 			case 0:
@@ -1018,12 +1020,18 @@ mcopy(struct magic_set *ms, union VALUET
 
 private int
 mget(struct magic_set *ms, const unsigned char *s,
-    struct magic *m, size_t nbytes, unsigned int cont_level, int text)
+    struct magic *m, size_t nbytes, unsigned int cont_level, int text,
+    int recursion_level)
 {
 	uint32_t offset = ms->offset;
 	uint32_t count = m->str_range;
 	union VALUETYPE *p = &ms->ms_value;
 
+        if (recursion_level >= 20) {
+                file_error(ms, 0, "recursion nesting exceeded");
+                return -1;
+        }
+
 	if (mcopy(ms, p, m->type, m->flag & INDIR, s, offset, nbytes, count) == -1)
 		return -1;
 
@@ -1073,7 +1081,7 @@ mget(struct magic_set *ms, const unsigne
 		}
 		switch (m->in_type) {
 		case FILE_BYTE:
-			if (nbytes < (offset + 1))
+			if (OFFSET_OOB(nbytes, offset, 1))
 				return 0;
 			if (off) {
 				switch (m->in_op & FILE_OPS_MASK) {
@@ -1108,7 +1116,7 @@ mget(struct magic_set *ms, const unsigne
 				offset = ~offset;
 			break;
 		case FILE_BESHORT:
-			if (nbytes < (offset + 2))
+			if (OFFSET_OOB(nbytes, offset, 2))
 				return 0;
 			if (off) {
 				switch (m->in_op & FILE_OPS_MASK) {
@@ -1160,7 +1168,7 @@ mget(struct magic_set *ms, const unsigne
 				offset = ~offset;
 			break;
 		case FILE_LESHORT:
-			if (nbytes < (offset + 2))
+			if (OFFSET_OOB(nbytes, offset, 2))
 				return 0;
 			if (off) {
 				switch (m->in_op & FILE_OPS_MASK) {
@@ -1212,7 +1220,7 @@ mget(struct magic_set *ms, const unsigne
 				offset = ~offset;
 			break;
 		case FILE_SHORT:
-			if (nbytes < (offset + 2))
+			if (OFFSET_OOB(nbytes, offset, 2))
 				return 0;
 			if (off) {
 				switch (m->in_op & FILE_OPS_MASK) {
@@ -1249,7 +1257,7 @@ mget(struct magic_set *ms, const unsigne
 			break;
 		case FILE_BELONG:
 		case FILE_BEID3:
-			if (nbytes < (offset + 4))
+			if (OFFSET_OOB(nbytes, offset, 4))
 				return 0;
 			if (off) {
 				switch (m->in_op & FILE_OPS_MASK) {
@@ -1320,7 +1328,7 @@ mget(struct magic_set *ms, const unsigne
 			break;
 		case FILE_LELONG:
 		case FILE_LEID3:
-			if (nbytes < (offset + 4))
+			if (OFFSET_OOB(nbytes, offset, 4))
 				return 0;
 			if (off) {
 				switch (m->in_op & FILE_OPS_MASK) {
@@ -1390,7 +1398,7 @@ mget(struct magic_set *ms, const unsigne
 				offset = ~offset;
 			break;
 		case FILE_MELONG:
-			if (nbytes < (offset + 4))
+			if (OFFSET_OOB(nbytes, offset, 4))
 				return 0;
 			if (off) {
 				switch (m->in_op & FILE_OPS_MASK) {
@@ -1460,7 +1468,7 @@ mget(struct magic_set *ms, const unsigne
 				offset = ~offset;
 			break;
 		case FILE_LONG:
-			if (nbytes < (offset + 4))
+			if (OFFSET_OOB(nbytes, offset, 4))
 				return 0;
 			if (off) {
 				switch (m->in_op & FILE_OPS_MASK) {
@@ -1527,14 +1535,14 @@ mget(struct magic_set *ms, const unsigne
 	/* Verify we have enough data to match magic type */
 	switch (m->type) {
 	case FILE_BYTE:
-		if (nbytes < (offset + 1)) /* should alway be true */
+		if (OFFSET_OOB(nbytes, offset, 1))
 			return 0;
 		break;
 
 	case FILE_SHORT:
 	case FILE_BESHORT:
 	case FILE_LESHORT:
-		if (nbytes < (offset + 2))
+		if (OFFSET_OOB(nbytes, offset, 2))
 			return 0;
 		break;
 
@@ -1553,21 +1561,21 @@ mget(struct magic_set *ms, const unsigne
 	case FILE_FLOAT:
 	case FILE_BEFLOAT:
 	case FILE_LEFLOAT:
-		if (nbytes < (offset + 4))
+		if (OFFSET_OOB(nbytes, offset, 4))
 			return 0;
 		break;
 
 	case FILE_DOUBLE:
 	case FILE_BEDOUBLE:
 	case FILE_LEDOUBLE:
-		if (nbytes < (offset + 8))
+		if (OFFSET_OOB(nbytes, offset, 8))
 			return 0;
 		break;
 
 	case FILE_STRING:
 	case FILE_PSTRING:
 	case FILE_SEARCH:
-		if (nbytes < (offset + m->vallen))
+		if (OFFSET_OOB(nbytes, offset, m->vallen))
 			return 0;
 		break;
 
@@ -1577,13 +1585,15 @@ mget(struct magic_set *ms, const unsigne
 		break;
 
 	case FILE_INDIRECT:
+		if (offset == 0)
+			return 0;
 	  	if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 &&
 		    file_printf(ms, "%s", m->desc) == -1)
 			return -1;
 		if (nbytes < offset)
 			return 0;
 		return file_softmagic(ms, s + offset, nbytes - offset,
-		    BINTEST, text);
+		    recursion_level, BINTEST, text);
 
 	case FILE_DEFAULT:	/* nothing to check */
 	default:


More information about the svn-src-all mailing list