Date: Tue, 22 Sep 2020 17:05:01 +0000 (UTC) From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r366005 - head/sys/fs/udf Message-ID: <202009221705.08MH516t053005@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
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@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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202009221705.08MH516t053005>