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
This commit is contained in:
parent
58f351825a
commit
8e13d6dfb6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=366005
@ -589,6 +589,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);
|
||||
@ -644,31 +645,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;
|
||||
}
|
||||
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, struct vnode **vpp)
|
||||
*vpp = vp;
|
||||
|
||||
return (0);
|
||||
|
||||
error:
|
||||
vgone(vp);
|
||||
vput(vp);
|
||||
brelse(bp);
|
||||
*vpp = NULL;
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
|
Loading…
Reference in New Issue
Block a user