diff options
author | Jessica Clarke <jrtc27@FreeBSD.org> | 2022-01-02 20:55:49 +0000 |
---|---|---|
committer | Jessica Clarke <jrtc27@FreeBSD.org> | 2022-01-02 20:55:49 +0000 |
commit | 324150d6dab8a5fcde98c6cc1869da0becb7c3bb (patch) | |
tree | e169c5a18ccc0f77198bfcc9315c813e0a953c64 /sys/ufs/ffs/ffs_snapshot.c | |
parent | 5b13fa7987c13aa7b5a67cc6b465475912de2d14 (diff) | |
download | src-324150d6dab8a5fcde98c6cc1869da0becb7c3bb.tar.gz src-324150d6dab8a5fcde98c6cc1869da0becb7c3bb.zip |
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
Diffstat (limited to 'sys/ufs/ffs/ffs_snapshot.c')
-rw-r--r-- | sys/ufs/ffs/ffs_snapshot.c | 6 |
1 files 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 |