svn commit: r366005 - head/sys/fs/udf

Mark Johnston markj at FreeBSD.org
Tue Sep 22 17:05:01 UTC 2020


Author: markj
Date: Tue Sep 22 17:05:01 2020
New Revision: 366005
URL: https://svnweb.freebsd.org/changeset/base/366005

Log:
  udf: Validate the full file entry length
  
  Otherwise a corrupted file entry containing invalid extended attribute
  lengths or allocation descriptor lengths can trigger an overflow when
  the file entry is loaded.
  
  admbug:		965
  PR:		248613
  Reported by:	C Turt <ecturt at gmail.com>
  MFC after:	3 days
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/sys/fs/udf/udf_vfsops.c

Modified: head/sys/fs/udf/udf_vfsops.c
==============================================================================
--- head/sys/fs/udf/udf_vfsops.c	Tue Sep 22 16:18:31 2020	(r366004)
+++ head/sys/fs/udf/udf_vfsops.c	Tue Sep 22 17:05:01 2020	(r366005)
@@ -589,6 +589,7 @@ udf_vget(struct mount *mp, ino_t ino, int flags, struc
 	struct vnode *vp;
 	struct udf_node *unode;
 	struct file_entry *fe;
+	uint32_t lea, lad;
 	int error, sector, size;
 
 	error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL);
@@ -644,31 +645,37 @@ udf_vget(struct mount *mp, ino_t ino, int flags, struc
 	devvp = udfmp->im_devvp;
 	if ((error = RDSECTOR(devvp, sector, udfmp->bsize, &bp)) != 0) {
 		printf("Cannot read sector %d\n", sector);
-		vgone(vp);
-		vput(vp);
-		brelse(bp);
-		*vpp = NULL;
-		return (error);
+		goto error;
 	}
 
+	/*
+	 * File entry length validation.
+	 */
 	fe = (struct file_entry *)bp->b_data;
 	if (udf_checktag(&fe->tag, TAGID_FENTRY)) {
 		printf("Invalid file entry!\n");
-		vgone(vp);
-		vput(vp);
-		brelse(bp);
-		*vpp = NULL;
-		return (ENOMEM);
+		error = ENOMEM;
+		goto error;
 	}
-	size = UDF_FENTRY_SIZE + le32toh(fe->l_ea) + le32toh(fe->l_ad);
+	lea = le32toh(fe->l_ea);
+	lad = le32toh(fe->l_ad);
+	if (lea > udfmp->bsize || lad > udfmp->bsize) {
+		printf("Invalid EA and AD lengths %u, %u\n", lea, lad);
+		error = EIO;
+		goto error;
+	}
+	size = UDF_FENTRY_SIZE + lea + lad;
+	if (size > udfmp->bsize) {
+		printf("Invalid file entry size %u\n", size);
+		error = EIO;
+		goto error;
+	}
+
 	unode->fentry = malloc(size, M_UDFFENTRY, M_NOWAIT | M_ZERO);
 	if (unode->fentry == NULL) {
 		printf("Cannot allocate file entry block\n");
-		vgone(vp);
-		vput(vp);
-		brelse(bp);
-		*vpp = NULL;
-		return (ENOMEM);
+		error = ENOMEM;
+		goto error;
 	}
 
 	bcopy(bp->b_data, unode->fentry, size);
@@ -713,6 +720,13 @@ udf_vget(struct mount *mp, ino_t ino, int flags, struc
 	*vpp = vp;
 
 	return (0);
+
+error:
+	vgone(vp);
+	vput(vp);
+	brelse(bp);
+	*vpp = NULL;
+	return (error);
 }
 
 static int


More information about the svn-src-all mailing list