Message ID | 20240123002814.1396804-42-keescook@chromium.org (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
Series | overflow: Refactor open-coded arithmetic wrap-around | expand |
On Mon, Jan 22, 2024 at 04:27:17PM -0800, Kees Cook wrote: > In an effort to separate intentional arithmetic wrap-around from > unexpected wrap-around, we need to refactor places that depend on this > kind of math. One of the most common code patterns of this is: > > VAR + value < VAR > > Notably, this is considered "undefined behavior" for signed and pointer > types, which the kernel works around by using the -fno-strict-overflow > option in the build[1] (which used to just be -fwrapv). Regardless, we > want to get the kernel source to the position where we can meaningfully > instrument arithmetic wrap-around conditions and catch them when they > are unexpected, regardless of whether they are signed[2], unsigned[3], > or pointer[4] types. > > Refactor open-coded wrap-around addition test to use add_would_overflow(). > This paves the way to enabling the wrap-around sanitizers in the future. > > Link: https://git.kernel.org/linus/68df3755e383e6fecf2354a67b08f92f18536594 [1] > Link: https://github.com/KSPP/linux/issues/26 [2] > Link: https://github.com/KSPP/linux/issues/27 [3] > Link: https://github.com/KSPP/linux/issues/344 [4] > Cc: Kent Overstreet <kent.overstreet@linux.dev> > Cc: Brian Foster <bfoster@redhat.com> > Cc: linux-bcachefs@vger.kernel.org > Signed-off-by: Kees Cook <keescook@chromium.org> Acked-by: Kent Overstreet <kent.overstreet@linux.dev>
diff --git a/fs/bcachefs/bkey.c b/fs/bcachefs/bkey.c index 76e79a15ba08..c68f1cfd579e 100644 --- a/fs/bcachefs/bkey.c +++ b/fs/bcachefs/bkey.c @@ -448,7 +448,7 @@ static bool bkey_format_has_too_big_fields(const struct bkey_format *f) : 0; u64 field_offset = le64_to_cpu(f->field_offset[i]); - if (packed_max + field_offset < packed_max || + if (add_would_overflow(packed_max, field_offset) || packed_max + field_offset > unpacked_max) return true; } @@ -664,7 +664,7 @@ int bch2_bkey_format_invalid(struct bch_fs *c, : 0; u64 field_offset = le64_to_cpu(f->field_offset[i]); - if (packed_max + field_offset < packed_max || + if (add_would_overflow(packed_max, field_offset) || packed_max + field_offset > unpacked_max) { prt_printf(err, "field %u too large: %llu + %llu > %llu", i, packed_max, field_offset, unpacked_max); diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index ec419b8e2c43..00a606171656 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -901,7 +901,7 @@ static int bch2_fiemap(struct inode *vinode, struct fiemap_extent_info *info, if (ret) return ret; - if (start + len < start) + if (add_would_overflow(start, len)) return -EINVAL; start >>= 9; diff --git a/fs/bcachefs/quota.c b/fs/bcachefs/quota.c index e68b34eab90a..1738b1fc1c75 100644 --- a/fs/bcachefs/quota.c +++ b/fs/bcachefs/quota.c @@ -392,7 +392,7 @@ static void __bch2_quota_transfer(struct bch_memquota *src_q, enum quota_counters counter, s64 v) { BUG_ON(v > src_q->c[counter].v); - BUG_ON(v + dst_q->c[counter].v < v); + BUG_ON(add_would_overflow(v, dst_q->c[counter].v)); src_q->c[counter].v -= v; dst_q->c[counter].v += v; diff --git a/fs/bcachefs/util.c b/fs/bcachefs/util.c index a135136adeee..2200c81edbd2 100644 --- a/fs/bcachefs/util.c +++ b/fs/bcachefs/util.c @@ -148,7 +148,7 @@ static int __bch2_strtou64_h(const char *cp, u64 *res) return -ERANGE; f_n = div_u64(f_n * b, f_d); - if (v + f_n < v) + if (add_would_overflow(v, f_n)) return -ERANGE; v += f_n;
In an effort to separate intentional arithmetic wrap-around from unexpected wrap-around, we need to refactor places that depend on this kind of math. One of the most common code patterns of this is: VAR + value < VAR Notably, this is considered "undefined behavior" for signed and pointer types, which the kernel works around by using the -fno-strict-overflow option in the build[1] (which used to just be -fwrapv). Regardless, we want to get the kernel source to the position where we can meaningfully instrument arithmetic wrap-around conditions and catch them when they are unexpected, regardless of whether they are signed[2], unsigned[3], or pointer[4] types. Refactor open-coded wrap-around addition test to use add_would_overflow(). This paves the way to enabling the wrap-around sanitizers in the future. Link: https://git.kernel.org/linus/68df3755e383e6fecf2354a67b08f92f18536594 [1] Link: https://github.com/KSPP/linux/issues/26 [2] Link: https://github.com/KSPP/linux/issues/27 [3] Link: https://github.com/KSPP/linux/issues/344 [4] Cc: Kent Overstreet <kent.overstreet@linux.dev> Cc: Brian Foster <bfoster@redhat.com> Cc: linux-bcachefs@vger.kernel.org Signed-off-by: Kees Cook <keescook@chromium.org> --- fs/bcachefs/bkey.c | 4 ++-- fs/bcachefs/fs.c | 2 +- fs/bcachefs/quota.c | 2 +- fs/bcachefs/util.c | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-)