DF-0887 / fix.diff
diff --git a/sys/vfs/ufs/ffs_inode.c b/sys/vfs/ufs/ffs_inode.c --- a/sys/vfs/ufs/ffs_inode.c +++ b/sys/vfs/ufs/ffs_inode.c @@ -162,7 +162,16 @@ if (length != 0) panic("ffs_truncate: partial truncate of symlink"); #endif /* DIAGNOSTIC */ - bzero((char *)&oip->i_shortlink, (uint)oip->i_size); + /* + * i_shortlink aliases di_db (ufs_daddr_t[UFS_NDADDR], 48 bytes), + * so the bzero length MUST be bounded by the buffer size: the + * di_blocks == 0 fast-path entry arm can be reached with an + * attacker-controlled di_size copied verbatim from disk + * (ffs_vfsops.c:ffs_vget), which would otherwise overflow the + * 48-byte inline buffer into the M_FFSNODE slab heap. + */ + bzero((char *)&oip->i_shortlink, + umin((uint)oip->i_size, sizeof(oip->i_shortlink))); oip->i_size = 0; oip->i_flag |= IN_CHANGE | IN_UPDATE; return (ffs_update(ovp, 1)); |