git: 324150d6dab8 - main - ufs: Avoid subobject overflow in snapshot expunge code
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sun, 02 Jan 2022 20:56:17 UTC
The branch main has been updated by jrtc27: URL: https://cgit.FreeBSD.org/src/commit/?id=324150d6dab8a5fcde98c6cc1869da0becb7c3bb commit 324150d6dab8a5fcde98c6cc1869da0becb7c3bb Author: Jessica Clarke <jrtc27@FreeBSD.org> AuthorDate: 2022-01-02 20:55:49 +0000 Commit: Jessica Clarke <jrtc27@FreeBSD.org> CommitDate: 2022-01-02 20:55:49 +0000 ufs: Avoid subobject overflow in snapshot expunge code The code here tries to be smart and zeroes out both di_db and di_ib with a single bzero call, thereby overrunning the di_db subobject. This is fine on most architectures, if a little dodgy. However, on CHERI, the compiler can optionally restrict the bounds on pointers to subobjects to just that subobject, in order to mitigate intra-object buffer overflows, and this is enabled in CheriBSD's pure-capability kernels. Instead, use separate bzero calls for each array, and let the compiler optimise it as it sees fit; even if it's not generating inline zeroing code, Clang will happily optimise two consecutive bzero's to a single larger call. Reviewed by: mckusick Differential Revision: https://reviews.freebsd.org/D33651 --- sys/ufs/ffs/ffs_snapshot.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/ufs/ffs/ffs_snapshot.c b/sys/ufs/ffs/ffs_snapshot.c index 59e5012c0019..c5063bf5f747 100644 --- a/sys/ufs/ffs/ffs_snapshot.c +++ b/sys/ufs/ffs/ffs_snapshot.c @@ -1084,7 +1084,8 @@ expunge_ufs1(snapvp, cancelip, fs, acctfunc, expungetype, clearmode) dip->di_size = 0; dip->di_blocks = 0; dip->di_flags &= ~SF_SNAPSHOT; - bzero(&dip->di_db[0], (UFS_NDADDR + UFS_NIADDR) * sizeof(ufs1_daddr_t)); + bzero(dip->di_db, UFS_NDADDR * sizeof(ufs1_daddr_t)); + bzero(dip->di_ib, UFS_NIADDR * sizeof(ufs1_daddr_t)); bdwrite(bp); /* * Now go through and expunge all the blocks in the file @@ -1366,7 +1367,8 @@ expunge_ufs2(snapvp, cancelip, fs, acctfunc, expungetype, clearmode) dip->di_size = 0; dip->di_blocks = 0; dip->di_flags &= ~SF_SNAPSHOT; - bzero(&dip->di_db[0], (UFS_NDADDR + UFS_NIADDR) * sizeof(ufs2_daddr_t)); + bzero(dip->di_db, UFS_NDADDR * sizeof(ufs2_daddr_t)); + bzero(dip->di_ib, UFS_NIADDR * sizeof(ufs2_daddr_t)); if (clearmode || cancelip->i_effnlink == 0) dip->di_mode = 0; else