DragonFlyBSD Kernel Audit
DF-0880 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/udf/udf_vfsops.c b/sys/vfs/udf/udf_vfsops.c
--- a/sys/vfs/udf/udf_vfsops.c
+++ b/sys/vfs/udf/udf_vfsops.c
@@ -525,6 +525,22 @@
 		return(ENOMEM);
 	}
 	size = UDF_FENTRY_SIZE + fe->l_ea + fe->l_ad;
+	/*
+	 * A file entry occupies exactly one block (ECMA-167 [4/14.9]).
+	 * l_ea and l_ad are attacker-controlled uint32s read off disk and
+	 * must not drive `size` past the bsize bytes we read into bp->b_data,
+	 * otherwise the bcopy below over-reads the buffer.  The size < check
+	 * also catches uint32 overflow wrapping the int back below the
+	 * header size.
+	 */
+	if (size > udfmp->bsize || size < (int)UDF_FENTRY_SIZE) {
+		kprintf("udf_vget: file entry too large (%d > %d)\n",
+			size, udfmp->bsize);
+		error = EINVAL;
+		brelse(bp);
+		kfree(unode, M_UDFNODE);
+		return(error);
+	}
 	unode->fentry = kmalloc(size, M_UDFFENTRY, M_WAITOK | M_ZERO);
 
 	bcopy(bp->b_data, unode->fentry, size);