When loading an inode from disk, verify that its mode is valid.

If invalid, return EINVAL. Note that inode check-hashes greatly
reduce the chance that these errors will go undetected.

Reported by:  Christopher Krah <krah@protonmail.com>
Reported as:  FS-5-UFS-2: Denial Of Service in nmount-3 (ffs_read)
Reviewed by:  kib
MFC after:    1 week
Sponsored by: Netflix

M    sys/fs/ext2fs/ext2_vnops.c
M    sys/kern/vfs_subr.c
M    sys/ufs/ffs/ffs_snapshot.c
M    sys/ufs/ufs/ufs_vnops.c
This commit is contained in:
Kirk McKusick 2018-12-27 07:18:53 +00:00
parent af907c40da
commit c0029546f8
4 changed files with 23 additions and 9 deletions

View File

@ -1920,6 +1920,11 @@ ext2_vinit(struct mount *mntp, struct vop_vector *fifoops, struct vnode **vpp)
vp = *vpp;
ip = VTOI(vp);
vp->v_type = IFTOVT(ip->i_mode);
/*
* Only unallocated inodes should be of type VNON.
*/
if (ip->i_mode != 0 && vp->v_type == VNON)
return (EINVAL);
if (vp->v_type == VFIFO)
vp->v_op = fifoops;

View File

@ -156,7 +156,7 @@ SYSCTL_ULONG(_vfs, OID_AUTO, mnt_free_list_batch, CTLFLAG_RW,
*/
enum vtype iftovt_tab[16] = {
VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VBAD,
VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON
};
int vttoif_tab[10] = {
0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK,

View File

@ -2001,15 +2001,19 @@ ffs_snapshot_mount(mp)
continue;
}
ip = VTOI(vp);
if (!IS_SNAPSHOT(ip) || ip->i_size ==
if (vp->v_type != VREG) {
reason = "non-file snapshot";
} else if (!IS_SNAPSHOT(ip)) {
reason = "non-snapshot";
} else if (ip->i_size ==
lblktosize(fs, howmany(fs->fs_size, fs->fs_frag))) {
if (!IS_SNAPSHOT(ip)) {
reason = "non-snapshot";
} else {
reason = "old format snapshot";
(void)ffs_truncate(vp, (off_t)0, 0, NOCRED);
(void)ffs_syncvnode(vp, MNT_WAIT, 0);
}
reason = "old format snapshot";
(void)ffs_truncate(vp, (off_t)0, 0, NOCRED);
(void)ffs_syncvnode(vp, MNT_WAIT, 0);
} else {
reason = NULL;
}
if (reason != NULL) {
printf("ffs_snapshot_mount: %s inode %d\n",
reason, fs->fs_snapinum[snaploc]);
vput(vp);

View File

@ -2517,6 +2517,11 @@ ufs_vinit(mntp, fifoops, vpp)
vp = *vpp;
ip = VTOI(vp);
vp->v_type = IFTOVT(ip->i_mode);
/*
* Only unallocated inodes should be of type VNON.
*/
if (ip->i_mode != 0 && vp->v_type == VNON)
return (EINVAL);
if (vp->v_type == VFIFO)
vp->v_op = fifoops;
ASSERT_VOP_LOCKED(vp, "ufs_vinit");