diff options
author | Mark Johnston <markj@FreeBSD.org> | 2020-09-25 16:34:42 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2020-09-25 16:34:42 +0000 |
commit | 2367fca656edb8ea52e6a2f7d8ef63e3a38966d6 (patch) | |
tree | 6ee7b6af25995b940932b88138aec741ceb32546 | |
parent | e5d077535c254c3bfd597d30556365e9772aaf19 (diff) | |
download | src-test2-2367fca656edb8ea52e6a2f7d8ef63e3a38966d6.tar.gz src-test2-2367fca656edb8ea52e6a2f7d8ef63e3a38966d6.zip |
MFS r366154:
MFC r366005:
udf: Validate the full file entry length
PR: 248613
Approved by: re (gjb)
Notes
Notes:
svn path=/releng/12.2/; revision=366160
-rw-r--r-- | sys/fs/udf/udf_vfsops.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/sys/fs/udf/udf_vfsops.c b/sys/fs/udf/udf_vfsops.c index 45331dedab14..af249e91ed9d 100644 --- a/sys/fs/udf/udf_vfsops.c +++ b/sys/fs/udf/udf_vfsops.c @@ -590,6 +590,7 @@ udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) 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); @@ -645,31 +646,37 @@ udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) 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; + } + 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 + le32toh(fe->l_ea) + le32toh(fe->l_ad); + 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); @@ -714,6 +721,13 @@ udf_vget(struct mount *mp, ino_t ino, int flags, struct vnode **vpp) *vpp = vp; return (0); + +error: + vgone(vp); + vput(vp); + brelse(bp); + *vpp = NULL; + return (error); } static int |