overflow: Refactor open-coded arithmetic wrap-around
Subsystems (78)
cover overflow: Refactor open-coded arithmetic wrap-around
Hi,
In our continuing effort to eliminate root causes of flaws in the kernel, this series is the start to providing a way to have sensible coverage for catching unexpected arithmetic wrap-around.
A quick word on language: while discussing[1] the finer details of the C standard's view on arithmetic, I was disabused of using the term "overflow" when what I really mean is "wrap-around". When describing security vulnerabilities, "overflow" is the common term and often used interchangeably with "wrap-around". Strictly speaking, though, "overflow" applies only to signed[2] and pointer[3] types, and "wrap-around" is for unsigned[4]. An arithmetic "overflow" is considered undefined behavior, which has caused our builds pain in the past, since "impossible" conditions might get elided by the compiler. As a result, we build with -fno-strict-overflow which coverts all "overflow" conditions into "wrap-around" (i.e. 2s complement), regardless of type.
All this is to say I am discussing arithmetic wrap-around, which is the condition where the value exceeds a type's maximum value (or goes below its minimum value) and wraps around. I'm not interested in the narrow definition of "undefined behavior" -- we need to stamp out the _unexpected_ behavior, where the kernel operates on a pathological value that wrapped around without the code author's intent.
As always, this is about being able disambiguate the intent of arithmetic in the kernel. We intentionally use wrapping arithmetic in all kinds of places, but we need to be able to annotate it as such going forward so the compiler can distinguish when it needs to perform instrumentation (when such instrumentation is enabled).
Getting back to my earlier mention of -fno-strict-overflow, the bulk of the series is refactoring for a common code pattern in the kernel where to test for potentially overflowing addition, the addition is performed, and wrap-around is tested for. This is what originally[5] caused us to enable -fno-strict-overflow:
var + offset < var
For these cases we can use either check_add_overflow() or add_would_overflow(). These helpers will not trip the wrap-around instrumentation, and do not depend on the whims of the compiler options. (Note that I have no intention of removing -fno-strict-overflow any time soon, if ever. As with all these kinds of changes, we need to evolve our support for it, and we can't introduce undefined behavior into the kernel.)
This series is mainly 3 parts:
- documentation, a coccinelle script, and new/improved helpers
- (re)introduction of the overflow sanitizers
- refactoring the "please wrap around to see if I wrapped around" tests
While this work is underway in the kernel, there will be complementary work happening in GCC and Clang to expand the existing sanitizers to behave correctly with -fno-strict-overflow. In the meantime, the sanitizers are excluded from CONFIG_COMPILE_TEST.
-Kees
[1] https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630578.html
[2] https://github.com/KSPP/linux/issues/26
[3] https://github.com/KSPP/linux/issues/344
[4] https://github.com/KSPP/linux/issues/27
[5] https://bugzilla.kernel.org/show_bug.cgi?id=12597
Kees Cook (82):
overflow: Expand check_add_overflow() for pointer addition
overflow: Introduce add_would_overflow()
overflow: Introduce add_wrap()
docs: deprecated.rst: deprecate open-coded arithmetic wrap-around
cocci: Refactor open-coded arithmetic wrap-around
overflow: Reintroduce signed and unsigned overflow sanitizers
overflow: Introduce CONFIG_UBSAN_POINTER_WRAP
iov_iter: Avoid wrap-around instrumentation in
copy_compat_iovec_from_user
select: Avoid wrap-around instrumentation in do_sys_poll() locking/atomic/x86: Silence intentional wrapping addition
arm64: atomics: lse: Silence intentional wrapping addition
ipv4: Silence intentional wrapping addition
btrfs: Refactor intentional wrap-around calculation
smb: client: Refactor intentional wrap-around calculation
dma-buf: Refactor intentional wrap-around calculation drm/nouveau/mmu: Refactor intentional wrap-around calculation drm/vc4: Refactor intentional wrap-around calculation
ext4: Refactor intentional wrap-around calculation
fs: Refactor intentional wrap-around calculation
fpga: dfl: Refactor intentional wrap-around calculation drivers/fsi: Refactor intentional wrap-around calculation x86/sgx: Refactor intentional wrap-around calculation
KVM: Refactor intentional wrap-around calculation
KVM: arm64: vgic: Refactor intentional wrap-around calculation
KVM: SVM: Refactor intentional wrap-around calculation
buildid: Refactor intentional wrap-around calculation
m68k: Refactor intentional wrap-around calculation
niu: Refactor intentional wrap-around calculation
rds: Refactor intentional wrap-around calculation s390/kexec_file: Refactor intentional wrap-around calculation
ARC: dw2 unwind: Refactor intentional wrap-around calculation
vringh: Refactor intentional wrap-around calculation mm/vmalloc: Refactor intentional wrap-around calculation
ipc: Refactor intentional wrap-around calculation
ACPI: custom_method: Refactor intentional wrap-around test
agp: Refactor intentional wrap-around test
aio: Refactor intentional wrap-around test
arm: 3117/1: Refactor intentional wrap-around test
crypto: Refactor intentional wrap-around test
arm64: stacktrace: Refactor intentional wrap-around test
wil6210: Refactor intentional wrap-around test
bcachefs: Refactor intentional wrap-around test
bpf: Refactor intentional wrap-around test
btrfs: Refactor intentional wrap-around test
cifs: Refactor intentional wrap-around test
crypto: Refactor intentional wrap-around test
dm verity: Refactor intentional wrap-around test drm/nouveau/mmu: Refactor intentional wrap-around test drm/i915: Refactor intentional wrap-around test drm/vc4: Refactor intentional wrap-around test
ext4: Refactor intentional wrap-around test
f2fs: Refactor intentional wrap-around test
fs: Refactor intentional wrap-around test
hpfs: Refactor intentional wrap-around test
kasan: Refactor intentional wrap-around test
usercopy: Refactor intentional wrap-around test
KVM: arm64: vgic-v3: Refactor intentional wrap-around test s390/mm: Refactor intentional wrap-around test lib/scatterlist: Refactor intentional wrap-around test
powerpc: Refactor intentional wrap-around test
scsi: mpt3sas: Refactor intentional wrap-around test
mwifiex: pcie: Refactor intentional wrap-around test
mm: Refactor intentional wrap-around test
netfilter: Refactor intentional wrap-around test
nios2: Refactor intentional wrap-around test
fs/ntfs3: Refactor intentional wrap-around test
ocfs2: Refactor intentional wrap-around test
PCI: Refactor intentional wrap-around test
perf tools: Refactor intentional wrap-around test
remoteproc: Refactor intentional wrap-around test s390/mm: Refactor intentional wrap-around test
scsi: sd_zbc: Refactor intentional wrap-around test
sh: Refactor intentional wrap-around test
ARC: dw2 unwind: Refactor intentional wrap-around test
timekeeping: Refactor intentional wrap-around test
udf: Refactor intentional wrap-around test
virtio: Refactor intentional wrap-around test mm/vmalloc: Refactor intentional wrap-around test
staging: vme_user: Refactor intentional wrap-around test
xen-netback: Refactor intentional wrap-around test
lib: zstd: Refactor intentional wrap-around test
mqueue: Refactor intentional wrap-around test
Documentation/process/deprecated.rst | 36 ++++++++ arch/arc/kernel/unwind.c | 7 +- arch/arm/nwfpe/softfloat.c | 2 +- arch/arm64/include/asm/atomic_lse.h | 8 +- arch/arm64/include/asm/stacktrace/common.h | 2 +- arch/arm64/kvm/vgic/vgic-kvm-device.c | 6 +- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 +- arch/arm64/kvm/vgic/vgic-v2.c | 10 ++- arch/m68k/kernel/sys_m68k.c | 5 +- arch/nios2/kernel/sys_nios2.c | 2 +- arch/powerpc/platforms/powernv/opal-prd.c | 2 +- arch/powerpc/xmon/xmon.c | 2 +- arch/s390/include/asm/stacktrace.h | 6 +- arch/s390/kernel/machine_kexec_file.c | 5 +- arch/s390/mm/gmap.c | 4 +- arch/s390/mm/vmem.c | 2 +- arch/sh/kernel/sys_sh.c | 2 +- arch/x86/include/asm/atomic.h | 2 +- arch/x86/kernel/cpu/sgx/ioctl.c | 6 +- arch/x86/kvm/svm/sev.c | 5 +- crypto/adiantum.c | 2 +- drivers/acpi/custom_method.c | 2 +- drivers/char/agp/generic.c | 2 +- drivers/crypto/amcc/crypto4xx_alg.c | 2 +- drivers/crypto/axis/artpec6_crypto.c | 2 +- drivers/dma-buf/dma-buf.c | 7 +- drivers/fpga/dfl.c | 5 +- drivers/fsi/fsi-core.c | 6 +- drivers/gpu/drm/i915/i915_vma.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 8 +- drivers/gpu/drm/vc4/vc4_validate.c | 7 +- drivers/md/dm-switch.c | 2 +- drivers/md/dm-verity-target.c | 2 +- drivers/md/dm-writecache.c | 2 +- drivers/net/ethernet/sun/niu.c | 5 +- drivers/net/wireless/ath/wil6210/wmi.c | 2 +- drivers/net/wireless/marvell/mwifiex/pcie.c | 6 +- drivers/net/xen-netback/hash.c | 2 +- drivers/pci/pci.c | 2 +- drivers/remoteproc/pru_rproc.c | 2 +- drivers/remoteproc/remoteproc_elf_loader.c | 2 +- drivers/remoteproc/remoteproc_virtio.c | 4 +- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 2 +- drivers/scsi/sd_zbc.c | 2 +- drivers/staging/vme_user/vme.c | 2 +- drivers/vhost/vringh.c | 8 +- drivers/virtio/virtio_pci_modern_dev.c | 4 +- fs/aio.c | 2 +- fs/bcachefs/bkey.c | 4 +- fs/bcachefs/fs.c | 2 +- fs/bcachefs/quota.c | 2 +- fs/bcachefs/util.c | 2 +- fs/btrfs/extent_map.c | 6 +- fs/btrfs/extent_map.h | 6 +- fs/btrfs/ordered-data.c | 2 +- fs/ext4/block_validity.c | 2 +- fs/ext4/extents.c | 5 +- fs/ext4/resize.c | 2 +- fs/f2fs/file.c | 2 +- fs/f2fs/verity.c | 2 +- fs/hpfs/alloc.c | 2 +- fs/ntfs3/record.c | 4 +- fs/ocfs2/resize.c | 2 +- fs/read_write.c | 8 +- fs/remap_range.c | 2 +- fs/select.c | 13 +-- fs/smb/client/readdir.c | 5 +- fs/smb/client/smb2pdu.c | 4 +- fs/udf/balloc.c | 4 +- include/linux/compiler_types.h | 29 +++++- include/linux/overflow.h | 76 +++++++++++++++- ipc/mqueue.c | 2 +- ipc/shm.c | 6 +- kernel/bpf/verifier.c | 12 +-- kernel/time/timekeeping.c | 2 +- lib/Kconfig.ubsan | 27 ++++++ lib/buildid.c | 6 +- lib/iov_iter.c | 5 +- lib/overflow_kunit.c | 77 ++++++++++++++-- lib/scatterlist.c | 2 +- lib/test_ubsan.c | 82 +++++++++++++++++ lib/ubsan.c | 89 +++++++++++++++++++ lib/ubsan.h | 5 ++ lib/zstd/decompress/zstd_decompress.c | 4 +- mm/kasan/generic.c | 2 +- mm/kasan/sw_tags.c | 2 +- mm/memory.c | 4 +- mm/mmap.c | 2 +- mm/mremap.c | 2 +- mm/nommu.c | 4 +- mm/usercopy.c | 2 +- mm/util.c | 2 +- mm/vmalloc.c | 7 +- net/ipv4/route.c | 8 +- net/netfilter/xt_u32.c | 4 +- net/rds/info.c | 6 +- scripts/Makefile.ubsan | 3 + .../coccinelle/misc/add_would_overflow.cocci | 70 +++++++++++++++ tools/perf/util/dso.c | 2 +- tools/perf/util/unwind-libdw.c | 2 +- tools/perf/util/unwind-libunwind-local.c | 2 +- virt/kvm/coalesced_mmio.c | 6 +- 102 files changed, 680 insertions(+), 167 deletions(-) create mode 100644 scripts/coccinelle/misc/add_would_overflow.cocci
Signature · 1 line
2.34.1
PATCH 1/82 overflow: Expand check_add_overflow() for pointer addition
The check_add_overflow() helper is mostly a wrapper around __builtin_add_overflow(), but GCC and Clang refuse to operate on pointer arguments that would normally be allowed if the addition were open-coded.
For example, we have many places where pointer overflow is tested:
struct foo *ptr; ... /* Check for overflow */ if (ptr + count < ptr) ...
And in order to avoid running into the overflow sanitizers in the future, we need to rewrite these "intended" overflow checks:
if (check_add_overflow(ptr, count, &result)) ...
Frustratingly the argument type validation for __builtin_add_overflow() is done before evaluating __builtin_choose_expr(), so for arguments to be valid simultaneously for sizeof(*p) (when p may not be a pointer), and __builtin_add_overflow(a, ...) (when a may be a pointer), we must introduce wrappers that always produce a specific type (but they are only used in the places where the bogus arguments will be ignored).
To test whether a variable is a pointer or not, introduce the __is_ptr() helper, which uses __builtin_classify_type() to find arrays and pointers (via the new __is_ptr_or_array() helper), and then decays arrays into pointers (via the new __decay() helper), to distinguish pointers from arrays.
Additionally update the unit tests to cover pointer addition.
--- include/linux/compiler_types.h | 10 +++++ include/linux/overflow.h | 44 ++++++++++++++++++- lib/overflow_kunit.c | 77 ++++++++++++++++++++++++++++++---- 3 files changed, 121 insertions(+), 10 deletions(-)
include/linux/compiler_types.h +10 -0
@@ -375,6 +375,16 @@ struct ftrace_likely_data {/* Are two types/vars the same type (ignoring qualifiers)? */ #define __same_type (a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) +/* Is variable addressable? */ +#define __is_ptr_or_array (p) (__builtin_classify_type(p) == 5) + +/* Return an array decayed to a pointer. */ +#define __decay (p) \ + (&*__builtin_choose_expr(__is_ptr_or_array(p), p, NULL)) + +/* Report if variable is a pointer type. */ +#define __is_ptr (p) __same_type(p, __decay(p)) +/* * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving * non-scalar types unchanged.
include/linux/overflow.h +43 -1
56 lines not on this page · raw message
lib/overflow_kunit.c +68 -9
114 lines not on this page · raw message
Signature · 1 line
2.34.1
Re: [PATCH 01/82] overflow: Expand check_add_overflow() for pointer addition
Hi,
Quoted 51 lines · Kees Cook
The
check_add_overflow()helper is mostly a wrapper around__builtin_add_overflow(), but GCC and Clang refuse to operate on pointer arguments that would normally be allowed if the addition were open-coded.For example, we have many places where pointer overflow is tested:
struct foo *ptr; ... /* Check for overflow */ if (ptr + count < ptr) ...And in order to avoid running into the overflow sanitizers in the future, we need to rewrite these "intended" overflow checks:
if (
check_add_overflow(ptr, count, &result)) ...Frustratingly the argument type validation for
__builtin_add_overflow()is done before evaluating__builtin_choose_expr(), so for arguments to be valid simultaneously forsizeof(*p)(when p may not be a pointer), and__builtin_add_overflow(a, ...)(when a may be a pointer), we must introduce wrappers that always produce a specific type (but they are only used in the places where the bogus arguments will be ignored).To test whether a variable is a pointer or not, introduce the
__is_ptr()helper, which uses__builtin_classify_type()to find arrays and pointers (via the new__is_ptr_or_array()helper), and then decays arrays into pointers (via the new__decay()helper), to distinguish pointers from arrays.Additionally update the unit tests to cover pointer addition.
Cc "Gustavo A. R. Silva" <[email protected]>Cc Andrew Morton <[email protected]>Cc Nathan Chancellor <[email protected]>Cc Nick Desaulniers <[email protected]>Cc Bill Wendling <[email protected]>Cc Justin Stitt <[email protected]>Signed-off-by Kees Cook <[email protected]>--- include/linux/compiler_types.h | 10 +++++ include/linux/overflow.h | 44 ++++++++++++++++++- lib/overflow_kunit.c | 77 ++++++++++++++++++++++++++++++---- 3 files changed, 121 insertions(+), 10 deletions(-)include/linux/compiler_types.h +0
-0
include/linux/compiler_types.h struct ftrace_likely_data { · line 383
Quoted 9 lines
include/linux/compiler_types.h +6
-0@@ -375,6 +375,16 @@ struct ftrace_likely_data {/* Are two types/vars the same type (ignoring qualifiers)? */ #define __same_type (a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) +/* Is variable addressable? */ +#define __is_ptr_or_array (p) (__builtin_classify_type(p) == 5) + +/* Return an array decayed to a pointer. */ +#define __decay (p) \ + (&*__builtin_choose_expr(__is_ptr_or_array(p), p, NULL))
Initially, I thought this __decay could dereference a NULL which would be UB.
According to the C std 6.5.3.2 (4):
| The unary * operator denotes indirection. If the operand points to a | function, the result is a function designator; if it points to an | object, the result is an lvalue designating the object. If the operand | has type ‘‘pointer to type’’, the result has type ‘‘type’’. If an | invalid value has been assigned to the pointer, the behavior of the | unary * operator is undefined^(84)
With footnote 84 mentioning NULL:
| Among the invalid values for dereferencing a pointer by the unary * | operator are a null pointer, an address inappropriately aligned for the | type of object pointed to, and the address of an object after the end of | its lifetime.
However, in this very same footnote it mentions:
| &*E is equivalent to E (even if E is a null pointer)
So, yeah this is OK ( and new to me :>] )
Quoted 59 lines
include/linux/compiler_types.h +4
-0+ +/* Report if variable is a pointer type. */ +#define __is_ptr (p) __same_type(p, __decay(p)) +/* * __unqual_scalar_typeof(x) - Declare an unqualified scalar type, leaving * non-scalar types unchanged. include/linux/overflow.h +39
-0@@ -51,6 +51,45 @@ static inline bool __must_check __must_check_overflow(bool overflow)return unlikely (overflow); } +/* Always produce an integral variable expression. */ +#define __filter_integral (x) \ + __builtin_choose_expr(!__is_ptr(x), (x), 0) + +/* Always produce a pointer value. */ +#define __filter_ptr (x) \ + __builtin_choose_expr(__is_ptr(x), (x), NULL) + +/* Always produce a pointer to an integral value. */ +#define __filter_ptrint (x) \ + __builtin_choose_expr(!__is_ptr(*(x)), x, &(int){ 0 }) + +/** +* __check_ptr_add_overflow() - Calculate pointer addition with overflow checking +* @a: pointer addend +* @b: numeric addend +* @d: pointer to store sum +* +* Returns 0 on success. +* +* Do not use this function directly, use check_add_overflow() instead. +* +* *@d holds the results of the attempted addition, but is not considered +* "safe for use" on a non-zero return value, which indicates that the +* sum has overflowed or been truncated. +*/ +#define __check_ptr_add_overflow (a, b, d) \ + ({ \ + typeof(a) __a = (a); \ + typeof(b) __b = (b); \ + size_t __bytes; \ + bool __overflow; \ + \ +/* we want to perform the wrap-around, but retain the result */ \ + __overflow =__builtin_mul_overflow (sizeof (*(__a)), __b, &__bytes); \ +__builtin_add_overflow ((unsigned long )(__a), __bytes, (unsigned long *)(d)) || \ + __overflow; \ + }) +/** * check_add_overflow() - Calculate addition with overflow checking * @a: first addend @@ -64,7 +103,10 @@ static inline bool __must_check __must_check_overflow(bool overflow)* sum has overflowed or been truncated.
include/linux/overflow.h static inline bool __must_check __must_check_overflow(bool overflow) · line 112
Quoted 10 lines
include/linux/overflow.h +4
-1*/ #define check_add_overflow (a, b, d) \ - __must_check_overflow(__builtin_add_overflow(a, b, d)) + __must_check_overflow(__builtin_choose_expr(__is_ptr(a), \ + __check_ptr_add_overflow(__filter_ptr(a), b, d), \ + __builtin_add_overflow(__filter_integral(a), b, \ + __filter_ptrint(d))))/** * check_sub_overflow() - Calculate subtraction with overflow checking
Does check_sub_overflow() deserve some more love in the future? I imagine "under"-flowing pointers is not at all common, though.
Nonetheless, this all looks good to me.
Quoted 124 lines
lib/overflow_kunit.c +68
-10@@ -45,13 +45,18 @@# define SKIP_64_ON_32 (t) do { } while (0)#endif -#define DEFINE_TEST_ARRAY_TYPED (t1, t2, t) \ - static const struct test_ ## t1 ## _ ## t2 ## __ ## t { \ +#define DEFINE_TEST_ARRAY_NAMED_TYPED (n1, n2, n, t1, t2, t) \ + static const struct test_ ## n1 ## _ ## n2 ## __ ## n { \ t1 a; \ t2 b; \ - t sum, diff, prod; \ + t sum; \ + t diff; \ + t prod; \ bool s_of, d_of, p_of; \ - } t1 ## _ ## t2 ## __ ## t ## _tests[] + } n1 ## _ ## n2 ## __ ## n ## _tests[] + +#define DEFINE_TEST_ARRAY_TYPED (t1, t2, t) \ + DEFINE_TEST_ARRAY_NAMED_TYPED(t1, t2, t, t1, t2, t)#define DEFINE_TEST_ARRAY (t) DEFINE_TEST_ARRAY_TYPED(t, t, t)@@ -251,8 +256,10 @@ DEFINE_TEST_ARRAY(s64) = { };#define check_one_op (t, fmt, op, sym, a, b, r, of) do { \ - int _a_orig = a, _a_bump = a + 1; \ - int _b_orig = b, _b_bump = b + 1; \ + typeof(a + 0) _a_orig = a; \ + typeof(a + 0) _a_bump = a + 1; \ + typeof(b + 0) _b_orig = b; \ + typeof(b + 0) _b_bump = b + 1; \ bool _of; \ t _r; \ \@@ -260,13 +267,13 @@ DEFINE_TEST_ARRAY(s64) = { KUNIT_EXPECT_EQ_MSG(test, _of, of, \ "expected "fmt" "sym" "fmt" to%s overflow (type %s)\n", \ a, b, of ? "" : " not", #t); \ - KUNIT_EXPECT_EQ_MSG(test, _r, r, \ + KUNIT_EXPECT_TRUE_MSG(test, _r == r, \ "expected "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \ a, b, r, _r, #t); \ /* Check for internal macro side-effects. */ \ _of = check_ ## op ## _overflow(_a_orig++, _b_orig++, &_r); \ - KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump, "Unexpected " #op " macro side-effect!\n"); \ - KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, "Unexpected " #op " macro side-effect!\n"); \ + KUNIT_EXPECT_TRUE_MSG(test, _a_orig == _a_bump, "Unexpected " #op " macro side-effect!\n"); \ + KUNIT_EXPECT_TRUE_MSG(test, _b_orig == _b_bump, "Unexpected " #op " macro side-effect!\n"); \ } while (0)#define DEFINE_TEST_FUNC_TYPED (n, t, fmt) \@@ -333,6 +340,55 @@ DEFINE_TEST_ARRAY_TYPED(int, int, u8) = { };DEFINE_TEST_FUNC_TYPED (int_int__u8, u8,"%d" ); +#define DEFINE_TEST_PTR_FUNC_TYPED (n, t, fmt) \ +static void do_ptr_test_ ## n(struct kunit *test, const struct test_ ## n *p) \ +{ \ +/* we're only doing single-direction sums, no product or division */ \ +check_one_op (t, fmt, add,"+" , p->a, p->b, p->sum, p->s_of);\ +} \ + \ +static void n ## _overflow_test(struct kunit *test) { \ +unsigned i; \ + \ + for (i = 0; i < ARRAY_SIZE(n ## _tests); ++i) \ + do_ptr_test_ ## n(test, &n ## _tests[i]); \ + kunit_info(test, "%zu %s arithmetic tests finished\n", \ + ARRAY_SIZE(n ## _tests), #n); \ +} + +DEFINE_TEST_ARRAY_NAMED_TYPED(void, int, void, void *, int, void *) = { + {NULL, 0, NULL, NULL, NULL, false, false, false}, + {(void *)0x30, 0x10, (void *)0x40, NULL, NULL, false, false, false}, + {(void *)ULONG_MAX, 0, (void *)ULONG_MAX, NULL, NULL, false, false, false}, + {(void *)ULONG_MAX, 1, NULL, NULL, NULL, true, false, false}, + {(void *)ULONG_MAX, INT_MAX, (void *)(INT_MAX - 1), NULL, NULL, true, false, false}, +}; +DEFINE_TEST_PTR_FUNC_TYPED(void_int__void, void *, "%lx"); + +struct _sized { +int a; +char b; +}; + +DEFINE_TEST_ARRAY_NAMED_TYPED(sized, int, sized, struct _sized *, int, struct _sized *) = { + {NULL, 0, NULL, NULL, NULL, false, false, false}, + {NULL, 1, (struct _sized *)(sizeof(struct _sized)), NULL, NULL, false, false, false}, + {NULL, 0x10, (struct _sized *)(sizeof(struct _sized) * 0x10), NULL, NULL, false, false, false}, + {(void *)(ULONG_MAX - sizeof(struct _sized)), 1, (struct _sized *)ULONG_MAX, NULL, NULL, false, false, false}, + {(void *)(ULONG_MAX - sizeof(struct _sized) + 1), 1, NULL, NULL, NULL, true, false, false}, + {(void *)(ULONG_MAX - sizeof(struct _sized) + 1), 2, (struct _sized *)(sizeof(struct _sized)), NULL, NULL, true, false, false}, + {(void *)(ULONG_MAX - sizeof(struct _sized) + 1), 3, (struct _sized *)(sizeof(struct _sized) * 2), NULL, NULL, true, false, false}, +}; +DEFINE_TEST_PTR_FUNC_TYPED(sized_int__sized, struct _sized *, "%lx"); + +DEFINE_TEST_ARRAY_NAMED_TYPED(sized, size_t, sized, struct _sized *, size_t, struct _sized *) = { + {NULL, 0, NULL, NULL, NULL, false, false, false}, + {NULL, 1, (struct _sized *)(sizeof(struct _sized)), NULL, NULL, false, false, false}, + {NULL, 0x10, (struct _sized *)(sizeof(struct _sized) * 0x10), NULL, NULL, false, false, false}, + {NULL, SIZE_MAX - 10, (struct _sized *)18446744073709551528UL, NULL, NULL, true, false, false}, +}; +DEFINE_TEST_PTR_FUNC_TYPED(sized_size_t__sized, struct _sized *, "%zu"); +/* Args are: value, shift, type, expected result, overflow expected */ #define TEST_ONE_SHIFT (a, s, t, expect, of) do { \ typeof(a) __a = (a); \@@ -1122,6 +1178,9 @@ static struct kunit_case overflow_test_cases[] = {KUNIT_CASE (s32_s32__s32_overflow_test),KUNIT_CASE (u64_u64__u64_overflow_test),KUNIT_CASE (s64_s64__s64_overflow_test), +KUNIT_CASE (void_int__void_overflow_test), +KUNIT_CASE (sized_int__sized_overflow_test), +KUNIT_CASE (sized_size_t__sized_overflow_test),KUNIT_CASE (u32_u32__int_overflow_test),KUNIT_CASE (u32_u32__u8_overflow_test), KUNIT_CASE(u8_u8__int_overflow_test), --
Quoted 2 lines
2.34.1
Thanks
Justin
Re: [PATCH 01/82] overflow: Expand check_add_overflow() for pointer addition
Quoted 6 lines · Justin Stitt
[...]
Quoted 2 lines
/**
*check_sub_overflow()- Calculate subtraction with overflow checkingDoes
check_sub_overflow()deserve some more love in the future? I imagine "under"-flowing pointers is not at all common, though.
Yes, though I hadn't found any cases of it yet in the code, so I didn't want to add a helper that would go unused. :)
Quoted 3 lines
Nonetheless, this all looks good to me.
Reviewed-by Justin Stitt <[email protected]>
Thanks!
Signature · 1 line
Kees Cook
PATCH 2/82 overflow: Introduce add_would_overflow()
In reply to Kees CookFor instances where only the overflow needs to be checked (and the sum isn't used), provide the new helper add_would_overflow(), which is a wrapper for check_add_overflow().
--- include/linux/overflow.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
include/linux/overflow.h +16 -0
@@ -108,6 +108,22 @@ static inline bool __must_check __must_check_overflow(bool overflow) __builtin_add_overflow(__filter_integral(a), b, \ __filter_ptrint(d)))) +/** +* add_would_overflow() - Check if an addition would overflow +* @a: first addend +* @b: second addend +* +* Returns true if the sum would overflow. +* +* To keep a copy of the sum when the addition doesn't overflow, use +* check_add_overflow() instead. +*/ +#define add_would_overflow (a, b) \ + __must_check_overflow(({ \ + size_t __result; \ + check_add_overflow(a, b, &__result);\ + })) +/** * check_sub_overflow() - Calculate subtraction with overflow checking * @a: minuend; value to subtract from
Signature · 1 line
2.34.1
Re: [PATCH 02/82] overflow: Introduce add_would_overflow()
Quoted 24 lines · Kees Cook
For instances where only the overflow needs to be checked (and the sum isn't used), provide the new helper
add_would_overflow(), which is a wrapper forcheck_add_overflow().Cc "Gustavo A. R. Silva" <[email protected]>Signed-off-by Kees Cook <[email protected]>--- include/linux/overflow.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)include/linux/overflow.h +5
-0@@ -108,6 +108,22 @@ static inline bool __must_check __must_check_overflow(bool overflow)__builtin_add_overflow (__filter_integral (a), b, \ __filter_ptrint(d)))) +/** +* add_would_overflow() - Check if an addition would overflow +* @a: first addend +* @b: second addend +*
include/linux/overflow.h static inline bool __must_check __must_check_overflow(bool overflow) · line 125
Quoted 10 lines
include/linux/overflow.h +10
-0+* Returns true if the sum would overflow. +* +* To keep a copy of the sum when the addition doesn't overflow, use +* check_add_overflow() instead. +*/ +#define add_would_overflow (a, b) \ + __must_check_overflow(({ \ + size_t __result; \ + check_add_overflow(a, b, &__result);\ + }))
Hm, I think this is a bit too ill-defined. Why is the target type hard-coded as size_t? What if a and b are u64, and we're on a 32 bit target? Then a+b might not overflow but this helper would claim it did.
But we also cannot just use typeof(a+b) instead of size_t, since that breaks when a and b are narrower than int (adding two u16 never overflows since they get promoted to int, but then if assigning the result to a u16 one truncates...).
Perhaps the target type must be explicit? sum_fits_in_type(T, a, b) ? IDK, I just don't think size_t is the right thing to use in something that is otherwise supposed to be type-generic.
Rasmus
Re: [PATCH 02/82] overflow: Introduce add_would_overflow()
Quoted 31 lines · Rasmus Villemoes
Quoted 30 lines · Kees Cook
For instances where only the overflow needs to be checked (and the sum isn't used), provide the new helper
add_would_overflow(), which is a wrapper forcheck_add_overflow().Cc "Gustavo A. R. Silva" <[email protected]>Signed-off-by Kees Cook <[email protected]>--- include/linux/overflow.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)include/linux/overflow.h +11
-0@@ -108,6 +108,22 @@ static inline bool __must_check __must_check_overflow(bool overflow) __builtin_add_overflow(__filter_integral(a), b, \ __filter_ptrint(d)))) +/** +* add_would_overflow() - Check if an addition would overflow +* @a: first addend +* @b: second addend +* +* Returns true if the sum would overflow. +* +* To keep a copy of the sum when the addition doesn't overflow, use +* check_add_overflow() instead. +*/ +#define add_would_overflow (a, b) \
Quoted 8 lines
include/linux/overflow.h static inline bool __must_check __must_check_overflow(bool overflow) · line 125
Quoted 4 lines
include/linux/overflow.h +4
-0+__must_check_overflow (({ \ +size_t __result; \ +check_add_overflow (a, b, &__result);\ + }))Hm, I think this is a bit too ill-defined. Why is the target type hard-coded as
size_t? What if a and b are u64, and we're on a 32 bit target? Then a+b might not overflow but this helper would claim it did.
Oooh, yes. That's no good. Thanks.
Quoted 4 lines
But we also cannot just use typeof(a+b) instead of
size_t, since that breaks when a and b are narrower than int (adding two u16 never overflows since they get promoted to int, but then if assigning the result to a u16 one truncates...).
The add_would_overflow() is aimed at replacing the "v + o < v" pattern, so perhaps use typeof(a) ?
Quoted 3 lines
Perhaps the target type must be explicit?
sum_fits_in_type(T, a, b)? IDK, I just don't thinksize_tis the right thing to use in something that is otherwise supposed to be type-generic.
I will use typeof(a) and check binary differences to see if there are any places doing something unexpected...
-Kees
Signature · 1 line
Kees Cook
PATCH 3/82 overflow: Introduce add_wrap()
In reply to Kees CookProvide a helper that will perform wrapping addition without tripping the arithmetic wrap-around sanitizers.
--- include/linux/overflow.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
include/linux/overflow.h +16 -0
@@ -124,6 +124,22 @@ static inline bool __must_check __must_check_overflow(bool overflow)check_add_overflow (a, b, &__result);\ })) +/** +* add_wrap() - Intentionally perform a wrapping addition +* @a: first addend +* @b: second addend +* +* Return the potentially wrapped-around addition without +* tripping any overflow sanitizers that may be enabled. +*/ +#define add_wrap (a, b) \ + ({ \ + typeof(a) __sum; \ + if (check_add_overflow(a, b, &__sum)) \ +/* do nothing */ ; \ + __sum; \ + }) +/** * check_sub_overflow() - Calculate subtraction with overflow checking * @a: minuend; value to subtract from
Signature · 1 line
2.34.1
Re: [PATCH 03/82] overflow: Introduce add_wrap()
Quoted 24 lines · Kees Cook
Provide a helper that will perform wrapping addition without tripping the arithmetic wrap-around sanitizers.
Cc "Gustavo A. R. Silva" <[email protected]>Signed-off-by Kees Cook <[email protected]>--- include/linux/overflow.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)include/linux/overflow.h +6
-0@@ -124,6 +124,22 @@ static inline bool __must_check __must_check_overflow(bool overflow)check_add_overflow (a, b, &__result);\ })) +/** +* add_wrap() - Intentionally perform a wrapping addition +* @a: first addend +* @b: second addend +* +* Return the potentially wrapped-around addition without
include/linux/overflow.h static inline bool __must_check __must_check_overflow(bool overflow) · line 142
Quoted 10 lines
include/linux/overflow.h +10
-0+* tripping any overflow sanitizers that may be enabled. +*/ +#define add_wrap (a, b) \ + ({ \ + typeof(a) __sum; \ + if (check_add_overflow(a, b, &__sum)) \ +/* do nothing */ ; \ + __sum; \ + }) +
I don't know where this is supposed to be used, but at first glance this seems to introduce a footgun. This is not symmetric in a and b, so both the type and value of the result may differ between add_wrap(a, b) and add_wrap(b, a). That seems dangerous.
Rasmus
Re: [PATCH 03/82] overflow: Introduce add_wrap()
Quoted 32 lines · Rasmus Villemoes
Quoted 31 lines · Kees Cook
Provide a helper that will perform wrapping addition without tripping the arithmetic wrap-around sanitizers.
Cc "Gustavo A. R. Silva" <[email protected]>Signed-off-by Kees Cook <[email protected]>--- include/linux/overflow.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)include/linux/overflow.h +13
-0@@ -124,6 +124,22 @@ static inline bool __must_check __must_check_overflow(bool overflow)check_add_overflow (a, b, &__result);\ })) +/** +* add_wrap() - Intentionally perform a wrapping addition +* @a: first addend +* @b: second addend +* +* Return the potentially wrapped-around addition without +* tripping any overflow sanitizers that may be enabled. +*/ +#define add_wrap (a, b) \ + ({ \ + typeof(a) __sum; \ + if (check_add_overflow(a, b, &__sum)) \ +/* do nothing */ ; \
Quoted 8 lines
include/linux/overflow.h static inline bool __must_check __must_check_overflow(bool overflow) · line 142
Quoted 3 lines
include/linux/overflow.h +3
-0+ __sum; \ + }) +I don't know where this is supposed to be used, but at first glance this seems to introduce a footgun. This is not symmetric in a and b, so both the type and value of the result may differ between
add_wrap(a, b)andadd_wrap(b, a). That seems dangerous.
I see three options here (and for add_would_overflow()):
1- document that it is typed to the first argument (but this seems weak) 2- require a and b have the same type, and use typeof(a) (but is possibly
inflexible, like the problems we've had with min()/max())
3- explicitly require a result type (this seems overly verbose, and might
have problems like we've had with min_t()/max_t())
In the one place this series uses add_wrap(), I have these arguments:
int segs
u32 delta
and the result type is expected to be int:
return atomic_add_return(add_wrap(segs, delta), p_id) - segs;
So as written (option 1) it's (accidentally?) correct.
It would be rejected with option 2, which seems a strong signal that it's not a good option.
So, your idea about explicit typing is probably best, since I can't examine the lvalue type within the macro.
return atomic_add_return(add_wrap(int, segs, delta), p_id) - segs;
I'll give this a try and check for binary differences.
-Kees
Signature · 1 line
Kees Cook
Mark Rutland
reviewerRe: [PATCH 03/82] overflow: Introduce add_wrap()
In reply to Kees CookQuoted 23 lines · Kees Cook
Provide a helper that will perform wrapping addition without tripping the arithmetic wrap-around sanitizers.
Cc "Gustavo A. R. Silva" <[email protected]>Signed-off-by Kees Cook <[email protected]>--- include/linux/overflow.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)include/linux/overflow.h +5
-0@@ -124,6 +124,22 @@ static inline bool __must_check __must_check_overflow(bool overflow)check_add_overflow (a, b, &__result);\ })) +/** +* add_wrap() - Intentionally perform a wrapping addition +* @a: first addend +* @b: second addend +*
include/linux/overflow.h static inline bool __must_check __must_check_overflow(bool overflow) · line 141
Quoted 10 lines
include/linux/overflow.h +10
-0+* Return the potentially wrapped-around addition without +* tripping any overflow sanitizers that may be enabled. +*/ +#define add_wrap (a, b) \ + ({ \ + typeof(a) __sum; \ + if (check_add_overflow(a, b, &__sum)) \ +/* do nothing */ ; \ + __sum; \ + })
It's really difficult to see the semicolon for the empty statement here; could we make that part:
if ((check_add_overflow(a, b, &__sum)) { \
/* do nothing */ \
} \... to be a little clearer (and less at risk of breakage in a refactoring)?
I realise coding style says not to use braces for a single statement, but IMO it's far clearer in this instance with the braces.
Mark.
Quoted 8 lines
include/linux/overflow.h +1
-0+/** * check_sub_overflow() - Calculate subtraction with overflow checking * @a: minuend; value to subtract from Signature · 1 line
2.34.1
Re: [PATCH 03/82] overflow: Introduce add_wrap()
Quoted 38 lines · Mark Rutland
Quoted 23 lines · Kees Cook
Provide a helper that will perform wrapping addition without tripping the arithmetic wrap-around sanitizers.
Cc "Gustavo A. R. Silva" <[email protected]>Signed-off-by Kees Cook <[email protected]>--- include/linux/overflow.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)include/linux/overflow.h +5
-0@@ -124,6 +124,22 @@ static inline bool __must_check __must_check_overflow(bool overflow)check_add_overflow (a, b, &__result);\ })) +/** +* add_wrap() - Intentionally perform a wrapping addition +* @a: first addend +* @b: second addend +* include/linux/overflow.h static inline bool __must_check __must_check_overflow(bool overflow) · line 141
Quoted 10 lines
include/linux/overflow.h +10
-0+* Return the potentially wrapped-around addition without +* tripping any overflow sanitizers that may be enabled. +*/ +#define add_wrap (a, b) \ + ({ \ + typeof(a) __sum; \ + if (check_add_overflow(a, b, &__sum)) \ +/* do nothing */ ; \ + __sum; \ + })It's really difficult to see the semicolon for the empty statement here; could we make that part:
Quoted 5 lines
if ((check_add_overflow(a, b, &__sum)) { \ /* do nothing */ \ } \... to be a little clearer (and less at risk of breakage in a refactoring)?
Yeah, agreed -- that stands out more clearly.
-Kees
Signature · 1 line
Kees Cook
PATCH 4/82 docs: deprecated.rst: deprecate open-coded arithmetic wrap-around
In reply to Kees CookIn pursuit of gaining full kernel instrumentation for signed[1], unsigned[2], and pointer[3] arithmetic overflow, we need to replace the handful of instances in the kernel where we intentionally depend on arithmetic wrap-around. Document this goal and provide an example for the most common code pattern, checking for simple overflow:
if (VAR + OFFSET < VAR) ...
--- Documentation/process/deprecated.rst | 32 ++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+)
Documentation/process/deprecated.rst +32 -0
@@ -109,6 +109,38 @@ For more details, also see array3_size() and flex_array_size(), as well as the related check_mul_overflow(), check_add_overflow(), check_sub_overflow(), and check_shl_overflow() family of functions. +open-coded intentional arithmetic wrap-around +--------------------------------------------- +Depending on arithmetic wrap-around without annotations means the +kernel cannot distinguish between intentional wrap-around and accidental +wrap-around (when using things like the overflow sanitizers). + +For example, where an addition is intended to wrap around:: + + magic = counter + rotation; + +please use the add_wrap() helper:: + + magic = add_wrap(counter, rotation); + +Another common code pattern in the kernel open coded testing for overflow +by performing an overflow and looking for wrap-around:: + + if (var + offset < var) ... + +Instead, use either check_add_overflow() (when you want to use the +resulting sum when it doesn't overflow) or add_would_overflow():: + + if (add_would_overflow(var, offset)) ... + +In rare cases where helpers aren't available (e.g. in early boot code, +etc) but overflow instrumentation still needs to be avoided, it can be +replaced with a type max subtraction test instead:: + + int var; + ... + if (INT_MAX - var < offset) ... + simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() ---------------------------------------------------------------------- The simple_strtol(), simple_strtoll(),
Signature · 1 line
2.34.1
PATCH 5/82 cocci: Refactor open-coded arithmetic wrap-around
In reply to Kees CookIn pursuit of gaining full kernel instrumentation for signed[1], unsigned[2], and pointer[3] arithmetic overflow, we need to replace the handful of instances in the kernel where we intentionally depend on arithmetic wrap-around. Introduce Coccinelle script for finding these and replacing them with the new add_would_overflow() helper, for this common code pattern:
if (VAR + OFFSET < VAR) ...
--- .../coccinelle/misc/add_would_overflow.cocci | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 scripts/coccinelle/misc/add_would_overflow.cocci
scripts/coccinelle/misc/add_would_overflow.cocci new file +70 -0
@@ -0,0 +1,70 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// +/// Replace intentional wrap-around addition with calls to +/// check_add_overflow() and add_would_overflow(), see +/// Documentation/process/deprecated.rst +/// +// +// Confidence: High +// Comments: +// Options: --no-includes --include-headers + +virtual context +virtual report +virtual org +virtual patch + +@report_wrap_sum depends on !patch@ +type RESULT; +RESULT VAR; +expression OFFSET; +@@ + + { + RESULT sum; + ... + ( +* VAR + OFFSET < VAR + ) + ... + ( + VAR + OFFSET + ) + ... + } + +@wrap_sum depends on patch@ +type RESULT; +RESULT VAR; +expression OFFSET; +@@ + + { ++ RESULT sum; + ... + ( +- VAR + OFFSET < VAR ++ check_add_overflow(VAR, OFFSET, &sum) + ) + ... + ( +- VAR + OFFSET ++ sum + ) + ... + } + +@report_wrap depends on !patch && !report_wrap_sum@ +identifier PTR; +expression OFFSET; +@@ + +* PTR + OFFSET < PTR + +@patch_wrap depends on patch && !wrap_sum@ +identifier PTR; +expression OFFSET; +@@ + +- PTR + OFFSET < PTR ++ add_would_overflow(PTR, OFFSET)
Signature · 1 line
2.34.1
PATCH 6/82 overflow: Reintroduce signed and unsigned overflow sanitizers
In reply to Kees CookEffectively revert commit 6aaa31aeb9cf ("ubsan: remove overflow checks"), to allow the kernel to be built with the "*-overflow" sanitizers again. This gives developers a chance to experiment[1][2][3] with the instrumentation again, while dealing with the impact of -fno-strict-oveflow.
Notably, the naming of the options is adjusted to use the name "WRAP" instead of "OVERFLOW". In the strictest sense, arithmetic "overflow" happens when a result exceeds the storage of the type, and is considered by the C standard and compilers to be undefined behavior for signed and pointer types (without -fno-strict-overflow). Unsigned arithmetic overflow is defined as always wrapping around.
Because the kernel is built with -fno-strict-overflow, signed and pointer arithmetic is defined to always wrap around instead of "overflowing" (which would either be elided due to being undefined behavior or would wrap around, which led to very weird bugs in the kernel).
So, the config options are added back as CONFIG_UBSAN_SIGNED_WRAP and CONFIG_UBSAN_UNSIGNED_WRAP. Since the kernel has several places that explicitly depend on wrap-around behavior (e.g. counters, atomics, etc), also introduce the __signed_wrap and __unsigned_wrap function attributes for annotating functions where wrapping is expected and should not be caught. This will allow us to distinguish in the kernel between intentional and unintentional cases of arithmetic wrap-around.
Additionally keep these disabled under CONFIG_COMPILE_TEST for now.
--- Documentation/process/deprecated.rst | 4 ++ include/linux/compiler_types.h | 14 +++++- lib/Kconfig.ubsan | 19 ++++++++ lib/test_ubsan.c | 49 ++++++++++++++++++++ lib/ubsan.c | 68 ++++++++++++++++++++++++++++ lib/ubsan.h | 4 ++ scripts/Makefile.ubsan | 2 + 7 files changed, 159 insertions(+), 1 deletion(-)
Documentation/process/deprecated.rst +4 -0
@@ -141,6 +141,10 @@ replaced with a type max subtraction test instead:: ... if (INT_MAX - var < offset) ... +For inline helpers that are performing wrapping arithmetic, the entire +function can be annotated as intentionally wrapping by adding the +`__signed_wrap` or `__unsigned_wrap` function attribute. + simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() ---------------------------------------------------------------------- The simple_strtol(), simple_strtoll(),
include/linux/compiler_types.h +13 -1
@@ -282,11 +282,23 @@ struct ftrace_likely_data {#define __no_sanitize_or_inline __always_inline#endif +/* Allow wrapping arithmetic within an annotated function. */ +#ifdef CONFIG_UBSAN_SIGNED_WRAP +# define __signed_wrap __attribute__((no_sanitize("signed-integer-overflow"))) +#else +# define __signed_wrap +#endif +#ifdef CONFIG_UBSAN_UNSIGNED_WRAP +# define __unsigned_wrap __attribute__((no_sanitize("unsigned-integer-overflow"))) +#else +# define __unsigned_wrap +#endif +/* Section for code which can't be instrumented at all */ #define __noinstr_section (section) \ noinline notrace __attribute((__section__(section))) \ __no_kcsan __no_sanitize_address __no_profile __no_sanitize_coverage \ - __no_sanitize_memory + __no_sanitize_memory __signed_wrap __unsigned_wrap#define noinstr __noinstr_section(".noinstr.text")
lib/Kconfig.ubsan +19 -0
@@ -116,6 +116,25 @@ config UBSAN_UNREACHABLE This option enables -fsanitize=unreachable which checks for control flow reaching an expected-to-be-unreachable position. +config UBSAN_SIGNED_WRAP + bool "Perform checking for signed arithmetic wrap-around" + default UBSAN + depends on !COMPILE_TEST + depends on $(cc-option,-fsanitize=signed-integer-overflow) + help + This option enables -fsanitize=signed-integer-overflow which checks + for wrap-around of any arithmetic operations with signed integers. + +config UBSAN_UNSIGNED_WRAP + bool "Perform checking for unsigned arithmetic wrap-around" + depends on $(cc-option,-fsanitize=unsigned-integer-overflow) + depends on !X86_32 # avoid excessive stack usage on x86-32/clang + depends on !COMPILE_TEST + help + This option enables -fsanitize=unsigned-integer-overflow which checks + for wrap-around of any arithmetic operations with unsigned integers. This + currently causes x86 to fail to boot. + config UBSAN_BOOL bool "Perform checking for non-boolean values used as boolean" default UBSAN
lib/test_ubsan.c +49 -0
61 lines not on this page · raw message
lib/ubsan.c +68 -0
74 lines not on this page · raw message
lib/ubsan.h +4 -0
@@ -124,6 +124,10 @@ typedef s64 s_max;typedef u64 u_max ;#endif +void __ubsan_handle_add_overflow (void *data,void *lhs,void *rhs); +void __ubsan_handle_sub_overflow (void *data,void *lhs,void *rhs); +void __ubsan_handle_mul_overflow (void *data,void *lhs,void *rhs); +void __ubsan_handle_negate_overflow (void *_data,void *old_val);void __ubsan_handle_divrem_overflow (void *_data,void *lhs,void *rhs);void __ubsan_handle_type_mismatch (struct type_mismatch_data *data,void *ptr);void __ubsan_handle_type_mismatch_v1 (void *_data,void *ptr);
scripts/Makefile.ubsan +2 -0
@@ -8,6 +8,8 @@ ubsan-cflags-$(CONFIG_UBSAN_LOCAL_BOUNDS) += -fsanitize=local-bounds ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift ubsan-cflags-$(CONFIG_UBSAN_DIV_ZERO) += -fsanitize=integer-divide-by-zero ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable +ubsan-cflags-$(CONFIG_UBSAN_SIGNED_WRAP) += -fsanitize=signed-integer-overflow +ubsan-cflags-$(CONFIG_UBSAN_UNSIGNED_WRAP) += -fsanitize=unsigned-integer-overflow ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error
Signature · 1 line
2.34.1
Re: [PATCH 06/82] overflow: Reintroduce signed and unsigned overflow sanitizers
Quoted 5 lines · Kees Cook
Because the kernel is built with -fno-strict-overflow, signed and pointer arithmetic is defined to always wrap around instead of "overflowing" (which would either be elided due to being undefined behavior or would wrap around, which led to very weird bugs in the kernel).
By elided I guess you also mean assumed to not happen and thus the usual chain-of-logic magic?
Quoted 7 lines
So, the config options are added back as
CONFIG_UBSAN_SIGNED_WRAPandCONFIG_UBSAN_UNSIGNED_WRAP. Since the kernel has several places that explicitly depend on wrap-around behavior (e.g. counters, atomics, etc), also introduce the__signed_wrapand__unsigned_wrapfunction attributes for annotating functions where wrapping is expected and should not be caught. This will allow us to distinguish in the kernel between intentional and unintentional cases of arithmetic wrap-around.
Sounds good -- it seems to go in the direction of Rust, i.e. to have a way to mark expected wrap-arounds so that we can start catching the unintended ones.
lib/Kconfig.ubsan config UBSAN_UNREACHABLE · line 123
Quoted 2 lines
lib/Kconfig.ubsan +2
-0+ depends on !COMPILE_TEST + depends on $(cc-option,-fsanitize=signed-integer-overflow)
Maybe this line goes above the other, to be consistent with the unsigned case? (or the other way around)
lib/Kconfig.ubsan config UBSAN_UNREACHABLE · line 136
Quoted 6 lines
lib/Kconfig.ubsan +6
-0+ depends on !X86_32 # avoid excessive stack usage on x86-32/clang + depends on !COMPILE_TEST + help + This option enables -fsanitize=unsigned-integer-overflow which checks + for wrap-around of any arithmetic operations with unsigned integers. This + currently causes x86 to fail to boot.
Is it related to the excessive stack usage? In that case, users would not reach the point to see this description, right? If so, I guess it could be removed from the help and moved into the comment above or similar.
lib/test_ubsan.c typedef void(*test_ubsan_fp)(void); · line 30
Quoted 5 lines
lib/test_ubsan.c +5
-0+static void test_ubsan_sub_overflow (void ) +{ +volatile int val =INT_MIN ; +volatile unsigned int uval =0 ; +volatile int val2 =2 ;
In the other tests you use a constant instead of val2, I am curious if there is a reason for it?
Thanks!
Cheers,
Miguel
Kees Cook
maintainerRe: [PATCH 06/82] overflow: Reintroduce signed and unsigned overflow sanitizers
Quoted 9 lines · Miguel Ojeda
Quoted 5 lines · Kees Cook
Because the kernel is built with -fno-strict-overflow, signed and pointer arithmetic is defined to always wrap around instead of "overflowing" (which would either be elided due to being undefined behavior or would wrap around, which led to very weird bugs in the kernel).
By elided I guess you also mean assumed to not happen and thus the usual chain-of-logic magic?
Yes. We removed this bad behavior by using -fno-strict-overflow, and we will want to keep it enabled.
Quoted 9 lines
Quoted 8 lines
So, the config options are added back as
CONFIG_UBSAN_SIGNED_WRAPandCONFIG_UBSAN_UNSIGNED_WRAP. Since the kernel has several places that explicitly depend on wrap-around behavior (e.g. counters, atomics, etc), also introduce the__signed_wrapand__unsigned_wrapfunction attributes for annotating functions where wrapping is expected and should not be caught. This will allow us to distinguish in the kernel between intentional and unintentional cases of arithmetic wrap-around.
Quoted 3 lines
Sounds good -- it seems to go in the direction of Rust, i.e. to have a way to mark expected wrap-arounds so that we can start catching the unintended ones.
Yup! That's the plan.
Quoted 6 lines
lib/Kconfig.ubsan config UBSAN_UNREACHABLE · line 123
Quoted 3 lines
lib/Kconfig.ubsan +2
-0+ depends on !COMPILE_TEST + depends on $(cc-option,-fsanitize=signed-integer-overflow)Maybe this line goes above the other, to be consistent with the unsigned case? (or the other way around)
Sure, I can move it around.
Quoted 8 lines
lib/Kconfig.ubsan config UBSAN_UNREACHABLE · line 136
Quoted 7 lines
lib/Kconfig.ubsan +6
-0+ depends on !X86_32 # avoid excessive stack usage on x86-32/clang + depends on !COMPILE_TEST + help + This option enables -fsanitize=unsigned-integer-overflow which checks + for wrap-around of any arithmetic operations with unsigned integers. This + currently causes x86 to fail to boot.
Quoted 4 lines
Is it related to the excessive stack usage? In that case, users would not reach the point to see this description, right? If so, I guess it could be removed from the
helpand moved into the comment above or similar.
The stack usage is separate. (This may even be fixed in modern Clang; this comes from the original version of this Kconfig.) The not booting part is separate and has not been tracked down yet.
Quoted 9 lines
lib/test_ubsan.c typedef void(*test_ubsan_fp)(void); · line 30
Quoted 6 lines
lib/test_ubsan.c +5
-0+static void test_ubsan_sub_overflow (void ) +{ +volatile int val =INT_MIN ; +volatile unsigned int uval =0 ; +volatile int val2 =2 ;In the other tests you use a constant instead of
val2, I am curious if there is a reason for it?
I wondered the same -- they were this way when they were removed, so I just restored them as they were. :)
-Kees
Signature · 1 line
Kees Cook
Re: [PATCH 06/82] overflow: Reintroduce signed and unsigned overflow sanitizers
Quoted 2 lines · Kees Cook
Yes. We removed this bad behavior by using -fno-strict-overflow, and we will want to keep it enabled.
Yeah, I only meant that the wording of the commit seems to say there is something special about the "overflowing behavior", i.e. I was expecting just UB with the usual implications, but given the extra text in the parenthesis, I wondered while reading it if there was something different/special going on.
Quoted 1 line
The stack usage is separate. (This may even be fixed in modern Clang; this comes from the original version of this
Kconfig.) The not booting part is separate and has not been tracked down yet.
I see. Thanks! In any case, if the sentence means only 32-bit x86, users couldn't still see it. But since this was already in the revert now that I take a look, I guess ignore this :)
Quoted 1 line
I wondered the same -- they were this way when they were removed, so I just restored them as they were. :)
Makes sense :)
Cheers,
Miguel
PATCH 7/82 overflow: Introduce CONFIG_UBSAN_POINTER_WRAP
In reply to Kees CookGain coverage for pointer wrap-around checking. Adds support for -fsanitize=pointer-overflow, and introduces the __pointer_wrap function attribute to match the signed and unsigned attributes. Also like the others, it is currently disabled under CONFIG_COMPILE_TEST.
--- Documentation/process/deprecated.rst | 2 +- include/linux/compiler_types.h | 7 +++++- lib/Kconfig.ubsan | 8 +++++++ lib/test_ubsan.c | 33 ++++++++++++++++++++++++++++ lib/ubsan.c | 21 ++++++++++++++++++ lib/ubsan.h | 1 + scripts/Makefile.ubsan | 1 + 7 files changed, 71 insertions(+), 2 deletions(-)
Documentation/process/deprecated.rst +1 -1
@@ -143,7 +143,7 @@ replaced with a type max subtraction test instead:: For inline helpers that are performing wrapping arithmetic, the entire function can be annotated as intentionally wrapping by adding the -`__signed_wrap` or `__unsigned_wrap` function attribute. +`__signed_wrap`, `__unsigned_wrap`, or `__pointer_wrap` function attribute. simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() ----------------------------------------------------------------------
include/linux/compiler_types.h +6 -1
@@ -293,12 +293,17 @@ struct ftrace_likely_data {#else # define __unsigned_wrap#endif +#ifdef CONFIG_UBSAN_POINTER_WRAP +# define __pointer_wrap __attribute__((no_sanitize("pointer-overflow"))) +#else +# define __pointer_wrap +#endif /* Section for code which can't be instrumented at all */ #define __noinstr_section (section) \ noinline notrace __attribute((__section__(section))) \ __no_kcsan __no_sanitize_address __no_profile __no_sanitize_coverage \ - __no_sanitize_memory __signed_wrap __unsigned_wrap + __no_sanitize_memory __signed_wrap __unsigned_wrap __pointer_wrap#define noinstr __noinstr_section(".noinstr.text")
lib/Kconfig.ubsan +8 -0
@@ -135,6 +135,14 @@ config UBSAN_UNSIGNED_WRAP for wrap-around of any arithmetic operations with unsigned integers. This currently causes x86 to fail to boot. +config UBSAN_POINTER_WRAP + bool "Perform checking for pointer arithmetic wrap-around" + depends on !COMPILE_TEST + depends on $(cc-option,-fsanitize=pointer-overflow) + help + This option enables -fsanitize=pointer-overflow which checks + for wrap-around of any arithmetic operations with pointers. + config UBSAN_BOOL bool "Perform checking for non-boolean values used as boolean" default UBSAN
lib/test_ubsan.c +33 -0
@@ -56,6 +56,36 @@ static void test_ubsan_negate_overflow(void) val = -val; } +static void test_ubsan_pointer_overflow_add (void ) +{ +volatile void *top = (void *)ULONG_MAX ; + +UBSAN_TEST (CONFIG_UBSAN_POINTER_WRAP ); + top +=2 ; +} + +static void test_ubsan_pointer_overflow_sub (void ) +{ +volatile void *bottom = (void *)1 ; + +UBSAN_TEST (CONFIG_UBSAN_POINTER_WRAP ); + bottom -=3 ; +} + +struct ptr_wrap { +int a; +int b; +}; + +static void test_ubsan_pointer_overflow_mul (void ) +{ +volatile struct ptr_wrap *half = (void *)(ULONG_MAX -128 ); +volatile int bump =128 ; + +UBSAN_TEST (CONFIG_UBSAN_POINTER_WRAP ); + half += bump; +} +static void test_ubsan_divrem_overflow (void ) {volatile int val =16 ;
@@ -139,6 +169,9 @@ static const test_ubsan_fp test_ubsan_array[] = { test_ubsan_sub_overflow, test_ubsan_mul_overflow, test_ubsan_negate_overflow, + test_ubsan_pointer_overflow_add, + test_ubsan_pointer_overflow_sub, + test_ubsan_pointer_overflow_mul, test_ubsan_shift_out_of_bounds, test_ubsan_out_of_bounds, test_ubsan_load_invalid_value,
lib/ubsan.c +21 -0
@@ -289,6 +289,27 @@ void __ubsan_handle_negate_overflow(void *_data, void *old_val) }EXPORT_SYMBOL (__ubsan_handle_negate_overflow); +void __ubsan_handle_pointer_overflow (void *_data,void *lhs,void *rhs) +{ +struct overflow_data *data = _data; +unsigned long before = (unsigned long )lhs; +unsigned long after = (unsigned long )rhs; + +if (suppress_report (&data->location)) +return ; + +ubsan_prologue (&data->location,"pointer-overflow" ); + +if (after ==0 ) +pr_err ("overflow wrapped to NULL\n" ); +else if (after < before) +pr_err ("overflow wrap-around\n" ); +else +pr_err ("underflow wrap-around\n" ); + +ubsan_epilogue (); +} +EXPORT_SYMBOL (__ubsan_handle_pointer_overflow);void __ubsan_handle_divrem_overflow (void *_data,void *lhs,void *rhs) {
lib/ubsan.h +1 -0
@@ -128,6 +128,7 @@ void __ubsan_handle_add_overflow(void *data, void *lhs, void *rhs);void __ubsan_handle_sub_overflow (void *data,void *lhs,void *rhs);void __ubsan_handle_mul_overflow (void *data,void *lhs,void *rhs);void __ubsan_handle_negate_overflow (void *_data,void *old_val); +void __ubsan_handle_pointer_overflow (void *_data,void *lhs,void *rhs);void __ubsan_handle_divrem_overflow (void *_data,void *lhs,void *rhs);void __ubsan_handle_type_mismatch (struct type_mismatch_data *data,void *ptr);void __ubsan_handle_type_mismatch_v1 (void *_data,void *ptr);
scripts/Makefile.ubsan +1 -0
@@ -10,6 +10,7 @@ ubsan-cflags-$(CONFIG_UBSAN_DIV_ZERO) += -fsanitize=integer-divide-by-zero ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable ubsan-cflags-$(CONFIG_UBSAN_SIGNED_WRAP) += -fsanitize=signed-integer-overflow ubsan-cflags-$(CONFIG_UBSAN_UNSIGNED_WRAP) += -fsanitize=unsigned-integer-overflow +ubsan-cflags-$(CONFIG_UBSAN_POINTER_WRAP) += -fsanitize=pointer-overflow ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error
Signature · 1 line
2.34.1
PATCH 8/82 iov_iter: Avoid wrap-around instrumentation in copy_compat_iovec_from_user
In reply to Kees CookThe loop counter "i" in copy_compat_iovec_from_user() is an int, but because the nr_segs argument is unsigned long, the signed overflow sanitizer got worried "i" could wrap around. Instead of making "i" an unsigned long (which may enlarge the type size), switch both nr_segs and i to u32. There is no truncation with nr_segs since its is never larger than UIO_MAXIOV anyway. This keeps sanitizer instrumentation[1] out of a UACCESS path:
vmlinux.o: warning: objtool: copy_compat_iovec_from_user+0xa9: call to __ubsan_handle_add_overflow() with UACCESS enabled
--- lib/iov_iter.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
lib/iov_iter.c +3 -2
@@ -1166,11 +1166,12 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)EXPORT_SYMBOL (dup_iter);static __noclone int copy_compat_iovec_from_user (struct iovec *iov, -const struct iovec __user *uvec,unsigned long nr_segs) +const struct iovec __user *uvec,u32 nr_segs) {const struct compat_iovec __user *uiov = (const struct compat_iovec __user *)uvec; -int ret = -EFAULT , i; +int ret = -EFAULT ; +u32 i;if (!user_access_begin (uiov, nr_segs *sizeof (*uiov)))return -EFAULT ;
Signature · 1 line
2.34.1
PATCH 9/82 select: Avoid wrap-around instrumentation in do_sys_poll()
In reply to Kees CookThe mix of int, unsigned int, and unsigned long used by struct poll_list::len, todo, len, and j meant that the signed overflow sanitizer got worried it needed to instrument several places where arithmetic happens between these variables. Since all of the variables are always positive and bounded by unsigned int, use a single type in all places. Additionally expand the zero-test into an explicit range check before updating "todo".
This keeps sanitizer instrumentation[1] out of a UACCESS path:
vmlinux.o: warning: objtool: do_sys_poll+0x285: call to __ubsan_handle_sub_overflow() with UACCESS enabled
--- fs/select.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
fs/select.c +7 -6
@@ -839,7 +839,7 @@ SYSCALL_DEFINE1(old_select, struct sel_arg_struct __user *, arg)struct poll_list {struct poll_list *next; -int len; +unsigned int len;struct pollfd entries[]; };
@@ -975,14 +975,15 @@ static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, struct timespec64 *end_time) {struct poll_wqueues table; -int err = -EFAULT , fdcount, len; +int err = -EFAULT , fdcount;/* Allocate small arguments on the stack to save memory and be faster - use long to make sure the buffer is aligned properly on 64 bit archs to avoid unaligned access */ long stack_pps[POLL_STACK_ALLOC /sizeof (long )];struct poll_list *const head = (struct poll_list *)stack_pps;struct poll_list *walk = head; -unsigned long todo = nfds; +unsigned int todo = nfds; +unsigned int len;if (nfds >rlimit (RLIMIT_NOFILE ))return -EINVAL ;
@@ -998,9 +999,9 @@ static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, sizeof(struct pollfd) * walk->len)) goto out_fds; - todo -= walk->len; -if (!todo) +if (walk->len >= todo)break ; + todo -= walk->len; len =min (todo,POLLFD_PER_PAGE ); walk = walk->next = kmalloc(struct_size(walk, entries, len),
@@ -1020,7 +1021,7 @@ static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,for (walk = head; walk; walk = walk->next) {struct pollfd *fds = walk->entries; -int j; +unsigned int j;for (j = walk->len; j; fds++, ufds++, j--)unsafe_put_user (fds->revents, &ufds->revents, Efault);
Signature · 1 line
2.34.1
Re: [PATCH 09/82] select: Avoid wrap-around instrumentation in do_sys_poll()
Quoted 10 lines · Kees Cook
The mix of int, unsigned int, and unsigned long used by struct
poll_list::len, todo, len, and j meant that the signed overflow sanitizer got worried it needed to instrument several places where arithmetic happens between these variables. Since all of the variables are always positive and bounded by unsigned int, use a single type in all places. Additionally expand the zero-test into an explicit range check before updating "todo".This keeps sanitizer instrumentation[1] out of a UACCESS path:
Quoted 7 lines
vmlinux.o: warning: objtool:
do_sys_poll+0x285: call to__ubsan_handle_sub_overflow()with UACCESS enabledCc Alexander Viro <[email protected]>Cc Christian Brauner <[email protected]>Cc Jan Kara <[email protected]>Signed-off-by Kees Cook <[email protected]>
Looks good. Feel free to add:
Honza
Quoted 59 lines
--- fs/select.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)fs/select.c +7
-6@@ -839,7 +839,7 @@ SYSCALL_DEFINE1(old_select, struct sel_arg_struct __user *, arg)struct poll_list {struct poll_list *next; -int len; +unsigned int len;struct pollfd entries[]; };@@ -975,14 +975,15 @@ static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, struct timespec64 *end_time) {struct poll_wqueues table; -int err = -EFAULT , fdcount, len; +int err = -EFAULT , fdcount;/* Allocate small arguments on the stack to save memory and be faster - use long to make sure the buffer is aligned properly on 64 bit archs to avoid unaligned access */ long stack_pps[POLL_STACK_ALLOC /sizeof (long )];struct poll_list *const head = (struct poll_list *)stack_pps;struct poll_list *walk = head; -unsigned long todo = nfds; +unsigned int todo = nfds; +unsigned int len;if (nfds >rlimit (RLIMIT_NOFILE ))return -EINVAL ;@@ -998,9 +999,9 @@ static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds, sizeof(struct pollfd) * walk->len)) goto out_fds; - todo -= walk->len; -if (!todo) +if (walk->len >= todo)break ; + todo -= walk->len; len =min (todo,POLLFD_PER_PAGE ); walk = walk->next = kmalloc(struct_size(walk, entries, len),@@ -1020,7 +1021,7 @@ static int do_sys_poll(struct pollfd __user *ufds, unsigned int nfds,for (walk = head; walk; walk = walk->next) {struct pollfd *fds = walk->entries; -int j; +unsigned int j;for (j = walk->len; j; fds++, ufds++, j--)unsafe_put_user (fds->revents, &ufds->revents, Efault);Signature · 1 line
2.34.1
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
PATCH 10/82 locking/atomic/x86: Silence intentional wrapping addition
In reply to Kees CookAnnotate atomic_add_return() to avoid signed overflow instrumentation. It is expected to wrap around.
--- arch/x86/include/asm/atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/include/asm/atomic.h +1 -1
@@ -80,7 +80,7 @@ static __always_inline bool arch_atomic_add_negative(int i, atomic_t *v) }#define arch_atomic_add_negative arch_atomic_add_negative -static __always_inline int arch_atomic_add_return(int i, atomic_t *v) +static __always_inline __signed_wrap int arch_atomic_add_return(int i, atomic_t *v) {return i +xadd (&v->counter, i); }
Signature · 1 line
2.34.1
Mark Rutland
reviewerRe: [PATCH 10/82] locking/atomic/x86: Silence intentional wrapping addition
Quoted 23 lines · Kees Cook
Annotate
atomic_add_return()to avoid signed overflow instrumentation. It is expected to wrap around.Cc Will Deacon <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Boqun Feng <[email protected]>Cc Mark Rutland <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Ingo Molnar <[email protected]>Cc Borislav Petkov <[email protected]>Cc Dave Hansen <[email protected]>Cc "H. Peter Anvin" <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/x86/include/asm/atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/x86/include/asm/atomic.h +0
-0
arch/x86/include/asm/atomic.h static __always_inline bool arch_atomic_add_negative(int i, atomic_t *v) · line 86
Quoted 8 lines
arch/x86/include/asm/atomic.h +1
-1@@ -80,7 +80,7 @@ static __always_inline bool arch_atomic_add_negative(int i, atomic_t *v) }#define arch_atomic_add_negative arch_atomic_add_negative -static __always_inline int arch_atomic_add_return(int i, atomic_t *v) +static __always_inline __signed_wrap int arch_atomic_add_return(int i, atomic_t *v) {return i +xadd (&v->counter, i); }
I think that here (and in the arm64 patch) it'd be better to use add_wrap() on the specific statement, i.e. have:
static __always_inline int arch_atomic_add_return(int i, atomic_t *v)
{
return add_wrap(i, xadd(&v->counter, i));
}... since otherwise the annotation could applly to the '+' or something else (e.g. if the 'xadd() part is a special macro), and the annotation might unexpectedly hide things if we add other statements here in future.
Mark.
Quoted 3 lines
Signature · 1 line
2.34.1
Re: [PATCH 10/82] locking/atomic/x86: Silence intentional wrapping addition
Quoted 36 lines · Mark Rutland
Quoted 23 lines · Kees Cook
Annotate
atomic_add_return()to avoid signed overflow instrumentation. It is expected to wrap around.Cc Will Deacon <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Boqun Feng <[email protected]>Cc Mark Rutland <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Ingo Molnar <[email protected]>Cc Borislav Petkov <[email protected]>Cc Dave Hansen <[email protected]>Cc "H. Peter Anvin" <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/x86/include/asm/atomic.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/x86/include/asm/atomic.h +0
-0arch/x86/include/asm/atomic.h static __always_inline bool arch_atomic_add_negative(int i, atomic_t *v) · line 86
Quoted 8 lines
arch/x86/include/asm/atomic.h +1
-1@@ -80,7 +80,7 @@ static __always_inline bool arch_atomic_add_negative(int i, atomic_t *v) }#define arch_atomic_add_negative arch_atomic_add_negative -static __always_inline int arch_atomic_add_return(int i, atomic_t *v) +static __always_inline __signed_wrap int arch_atomic_add_return(int i, atomic_t *v) {return i +xadd (&v->counter, i); }I think that here (and in the arm64 patch) it'd be better to use
add_wrap()on the specific statement, i.e. have:
Quoted 8 lines
static
__always_inlineintarch_atomic_add_return(int i, atomic_t *v){ return add_wrap(i, xadd(&v->counter, i)); }... since otherwise the annotation could applly to the '+' or something else (e.g. if the '
xadd()part is a special macro), and the annotation might unexpectedly hide things if we add other statements here in future.
Okay, sure, I can do that. I may have some header inclusion problems, but I'll give it a shot.
Signature · 1 line
Kees Cook
PATCH 11/82 arm64: atomics: lse: Silence intentional wrapping addition
In reply to Kees CookAnnotate atomic_add_return() and atomic_sub_return() to avoid signed overflow instrumentation. They are expected to wrap around.
--- arch/arm64/include/asm/atomic_lse.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/include/asm/atomic_lse.h +4 -4
@@ -79,13 +79,13 @@ ATOMIC_FETCH_OP_SUB( )#undef ATOMIC_FETCH_OP_SUB#define ATOMIC_OP_ADD_SUB_RETURN (name) \ -static __always_inline int \ +static __always_inline __signed_wrap int \ __lse_atomic_add_return##name(int i, atomic_t *v) \ { \ return __lse_atomic_fetch_add##name(i, v) + i; \ } \ \ -static __always_inline int \ +static __always_inline __signed_wrap int \ __lse_atomic_sub_return##name(int i, atomic_t *v) \ { \ return __lse_atomic_fetch_sub(i, v) - i; \
@@ -186,13 +186,13 @@ ATOMIC64_FETCH_OP_SUB( )#undef ATOMIC64_FETCH_OP_SUB#define ATOMIC64_OP_ADD_SUB_RETURN (name) \ -static __always_inline long \ +static __always_inline __signed_wrap long \ __lse_atomic64_add_return##name(s64 i, atomic64_t *v) \ { \ return __lse_atomic64_fetch_add##name(i, v) + i; \ } \ \ -static __always_inline long \ +static __always_inline __signed_wrap long \ __lse_atomic64_sub_return##name(s64 i, atomic64_t *v) \ { \ return __lse_atomic64_fetch_sub##name(i, v) - i; \
Signature · 1 line
2.34.1
Mark Rutland
reviewerRe: [PATCH 11/82] arm64: atomics: lse: Silence intentional wrapping addition
Quoted 19 lines · Kees Cook
Annotate
atomic_add_return()andatomic_sub_return()to avoid signed overflow instrumentation. They are expected to wrap around.Cc Will Deacon <[email protected]>Cc Peter Zijlstra <[email protected]>Cc Boqun Feng <[email protected]>Cc Mark Rutland <[email protected]>Cc Catalin Marinas <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/arm64/include/asm/atomic_lse.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)arch/arm64/include/asm/atomic_lse.h +0
-0
arch/arm64/include/asm/atomic_lse.h ATOMIC_FETCH_OP_SUB( ) · line 86
Quoted 9 lines
arch/arm64/include/asm/atomic_lse.h +1
-1@@ -79,13 +79,13 @@ ATOMIC_FETCH_OP_SUB( )#undef ATOMIC_FETCH_OP_SUB#define ATOMIC_OP_ADD_SUB_RETURN (name) \ -static __always_inline int \ +static __always_inline __signed_wrap int \ __lse_atomic_add_return##name(int i, atomic_t *v) \ { \ return __lse_atomic_fetch_add##name(i, v) + i; \ } \
I'd strongly prefer using add_wrap() rather than annotating the function, i.e. make this:
static __always_inline int \
__lse_atomic_add_return##name(int i, atomic_t *v) \
{ \
return add_wrap(__lse_atomic_fetch_add##name(i, v), i); \
} \Likewise for the other instances below.
With that, this looks fine to me.
Mark.
Quoted 25 lines
arch/arm64/include/asm/atomic_lse.h +3
-3\ -static __always_inline int \ +static __always_inline __signed_wrap int \ __lse_atomic_sub_return##name(int i, atomic_t *v) \ { \ return __lse_atomic_fetch_sub(i, v) - i; \@@ -186,13 +186,13 @@ ATOMIC64_FETCH_OP_SUB( )#undef ATOMIC64_FETCH_OP_SUB#define ATOMIC64_OP_ADD_SUB_RETURN (name) \ -static __always_inline long \ +static __always_inline __signed_wrap long \ __lse_atomic64_add_return##name(s64 i, atomic64_t *v) \ { \ return __lse_atomic64_fetch_add##name(i, v) + i; \ } \ \ -static __always_inline long \ +static __always_inline __signed_wrap long \ __lse_atomic64_sub_return##name(s64 i, atomic64_t *v) \ { \ return __lse_atomic64_fetch_sub##name(i, v) - i; \Signature · 1 line
2.34.1
PATCH 12/82 ipv4: Silence intentional wrapping addition
In reply to Kees CookThe overflow sanitizer quickly noticed what appears to have been an old sore spot involving intended wrap around:
[ 22.192362] ------------[ cut here ]------------ [ 22.193329] UBSAN: signed-integer-overflow in ../arch/x86/include/asm/atomic.h:85:11 [ 22.194844] 1469769800 + 1671667352 cannot be represented in type 'int' [ 22.195975] CPU: 2 PID: 2260 Comm: nmbd Not tainted 6.7.0 #1 [ 22.196927] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 0.0.0 02/06/2015 [ 22.198231] Call Trace: [ 22.198641] <TASK> [ 22.198641] dump_stack_lvl+0x64/0x80 [ 22.199533] handle_overflow+0x152/0x1a0 [ 22.200382] __ip_select_ident+0xe3/0x100
Explicitly perform a wrapping addition to solve for the needed -fno-strict-overflow behavior but still allow the sanitizers to operate correctly.
To see the (unchanged) assembly results more clearly, see:
https://godbolt.org/z/EhYhz6zTT
--- net/ipv4/route.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/ipv4/route.c +4 -4
@@ -473,11 +473,11 @@ static u32 ip_idents_reserve(u32 hash, int segs)if (old != now &&cmpxchg (p_tstamp, old, now) == old) delta =get_random_u32_below (now - old); -/* If UBSAN reports an error there, please make sure your compiler -* supports -fno-strict-overflow before reporting it that was a bug -* in UBSAN, and it has been fixed in GCC-8. +/* If UBSAN reports an error there, please make sure your arch's +* atomic_add_return() implementation has been annotated with +* __signed_wrap. */ -return atomic_add_return (segs + delta, p_id) - segs; +return atomic_add_return (add_wrap (segs, delta), p_id) - segs; }void __ip_select_ident (struct net *net,struct iphdr *iph,int segs)
Signature · 1 line
2.34.1
PATCH 13/82 btrfs: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizer in the future.
--- fs/btrfs/extent_map.c | 6 ++++-- fs/btrfs/extent_map.h | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-)
fs/btrfs/extent_map.c +4 -2
@@ -73,9 +73,11 @@ void free_extent_map(struct extent_map *em)/* Do the math around the end of an extent, handling wrapping. */ static u64 range_end (u64 start,u64 len) { -if (start + len < start) +u64 sum; + +if (check_add_overflow (start, len, &sum))return (u64)-1 ; -return start + len; +return sum; }static int tree_insert (struct rb_root_cached *root,struct extent_map *em)
fs/btrfs/extent_map.h +4 -2
@@ -108,9 +108,11 @@ static inline int extent_map_in_tree(const struct extent_map *em)static inline u64 extent_map_end (const struct extent_map *em) { -if (em->start + em->len < em->start) +u64 sum; + +if (check_add_overflow (em->start, em->len, &sum))return (u64)-1 ; -return em->start + em->len; +return sum; }void extent_map_tree_init (struct extent_map_tree *tree);
Signature · 1 line
2.34.1
Re: [PATCH 13/82] btrfs: Refactor intentional wrap-around calculation
Quoted 19 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizer in the future.
Quoted 9 lines
Cc Chris Mason <[email protected]>Cc Josef Bacik <[email protected]>Cc David Sterba <[email protected]>Signed-off-by Kees Cook <[email protected]>
PATCH 14/82 smb: client: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 pointer wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizer in the future.
--- fs/smb/client/readdir.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/smb/client/readdir.c +3 -2
@@ -467,12 +467,13 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) pfData->FileNameLength; }else {u32 next_offset =le32_to_cpu (pDirInfo->NextEntryOffset); +char *sum; -if (old_entry + next_offset < old_entry) { +if (check_add_overflow (old_entry, next_offset, &sum)) {cifs_dbg (VFS ,"Invalid offset %u\n" , next_offset);return NULL ; } - new_entry = old_entry + next_offset; + new_entry = sum; }cifs_dbg (FYI ,"new entry %p old entry %p\n" , new_entry, old_entry);/* validate that new_entry is not past end of SMB */
Signature · 1 line
2.34.1
PATCH 15/82 dma-buf: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
--- drivers/dma-buf/dma-buf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/dma-buf/dma-buf.c +4 -3
@@ -1458,6 +1458,8 @@ EXPORT_SYMBOL_NS_GPL(dma_buf_end_cpu_access, DMA_BUF);int dma_buf_mmap (struct dma_buf *dmabuf,struct vm_area_struct *vma,unsigned long pgoff) { +unsigned long sum; +if (WARN_ON (!dmabuf || !vma))return -EINVAL ;
@@ -1466,12 +1468,11 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,return -EINVAL ;/* check for offset overflow */ -if (pgoff +vma_pages (vma) < pgoff) +if (check_add_overflow (pgoff,vma_pages (vma), &sum))return -EOVERFLOW ;/* check for overflowing the buffer's size */ -if (pgoff +vma_pages (vma) > - dmabuf->size >>PAGE_SHIFT ) +if (sum > dmabuf->size >>PAGE_SHIFT )return -EINVAL ;/* readjust the vma */
Signature · 1 line
2.34.1
PATCH 16/82 drm/nouveau/mmu: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
--- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c +4 -2
@@ -1149,13 +1149,15 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, vmm->root =RB_ROOT ;if (managed) { +u64 sum; +/* Address-space will be managed by the client for the most * part, except for a specified area where NVKM allocations * are allowed to be placed. */ vmm->start =0 ; vmm->limit =1ULL << bits; -if (addr + size < addr || addr + size > vmm->limit) +if (check_add_overflow (addr, size, &sum) || sum > vmm->limit)return -EINVAL ;/* Client-managed area before the NVKM-managed area. */
@@ -1174,7 +1176,7 @@ nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, }/* Client-managed area after the NVKM-managed area. */ - addr = addr + size; + addr = sum; size = vmm->limit - addr;if (size && (ret =nvkm_vmm_ctor_managed (vmm, addr, size)))return ret;
Signature · 1 line
2.34.1
PATCH 17/82 drm/vc4: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
--- drivers/gpu/drm/vc4/vc4_validate.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/vc4/vc4_validate.c +3 -2
@@ -305,6 +305,7 @@ validate_gl_array_primitive(VALIDATE_ARGS)uint32_t length = *(uint32_t *)(untrusted +1 );uint32_t base_index = *(uint32_t *)(untrusted +5 );uint32_t max_index; +uint32_t sum;struct vc4_shader_state *shader_state;/* Check overflow condition */
@@ -314,11 +315,11 @@ validate_gl_array_primitive(VALIDATE_ARGS) } shader_state = &exec->shader_state[exec->shader_state_count -1 ]; -if (length + base_index < length) { +if (check_add_overflow (length, base_index, &sum)) {DRM_DEBUG ("primitive vertex count overflow\n" );return -EINVAL ; } - max_index = length + base_index -1 ; + max_index = sum -1 ;if (max_index > shader_state->max_index) shader_state->max_index = max_index;
Signature · 1 line
2.34.1
PATCH 18/82 ext4: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
--- fs/ext4/extents.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/ext4/extents.c +3 -2
@@ -1920,6 +1920,7 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi,struct ext4_extent *newext, struct ext4_ext_path *path) { + ext4_lblk_t sum;ext4_lblk_t b1, b2;unsigned int depth, len1;unsigned int ret =0 ;
@@ -1943,14 +1944,14 @@ static unsigned int ext4_ext_check_overlap(struct ext4_sb_info *sbi, }/* check for wrap through zero on extent logical start block*/ -if (b1 + len1 < b1) { +if (check_add_overflow (b1, len1, &sum)) { len1 =EXT_MAX_BLOCKS - b1; newext->ee_len =cpu_to_le16 (len1); ret =1 ; }/* check for overlap */ -if (b1 + len1 > b2) { +if (sum > b2) { newext->ee_len =cpu_to_le16 (b2 - b1); ret =1 ; }
Signature · 1 line
2.34.1
PATCH 19/82 fs: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
--- fs/read_write.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
fs/read_write.c +5 -3
@@ -1417,6 +1417,7 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,struct inode *inode_out =file_inode (file_out);uint64_t count = *req_count;loff_t size_in; +loff_t sum_in, sum_out;int ret; ret =generic_file_rw_checks (file_in, file_out);
@@ -1451,7 +1452,8 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,return -ETXTBSY ;/* Ensure offsets don't wrap. */ -if (pos_in + count < pos_in || pos_out + count < pos_out) +if (check_add_overflow (pos_in, count, &sum_in) || +check_add_overflow (pos_out, count, &sum_out))return -EOVERFLOW ;/* Shorten the copy to EOF */
@@ -1467,8 +1469,8 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,/* Don't allow overlapped copying within the same file. */ if (inode_in == inode_out && - pos_out + count > pos_in && - pos_out < pos_in + count) + sum_out > pos_in && + pos_out < sum_in)return -EINVAL ; *req_count = count;
Signature · 1 line
2.34.1
Re: [PATCH 19/82] fs: Refactor intentional wrap-around calculation
Quoted 19 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
Quoted 9 lines
Cc Alexander Viro <[email protected]>Cc Christian Brauner <[email protected]>Cc Jan Kara <[email protected]>Signed-off-by Kees Cook <[email protected]>
Looks good. Feel free to add:
Honza
Quoted 40 lines
--- fs/read_write.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)fs/read_write.c +5
-3@@ -1417,6 +1417,7 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,struct inode *inode_out =file_inode (file_out);uint64_t count = *req_count;loff_t size_in; +loff_t sum_in, sum_out;int ret; ret =generic_file_rw_checks (file_in, file_out);@@ -1451,7 +1452,8 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,return -ETXTBSY ;/* Ensure offsets don't wrap. */ -if (pos_in + count < pos_in || pos_out + count < pos_out) +if (check_add_overflow (pos_in, count, &sum_in) || +check_add_overflow (pos_out, count, &sum_out))return -EOVERFLOW ;/* Shorten the copy to EOF */ @@ -1467,8 +1469,8 @@ static int generic_copy_file_checks(struct file *file_in, loff_t pos_in,/* Don't allow overlapped copying within the same file. */ if (inode_in == inode_out && - pos_out + count > pos_in && - pos_out < pos_in + count) + sum_out > pos_in && + pos_out < sum_in)return -EINVAL ; *req_count = count;Signature · 1 line
2.34.1
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
PATCH 20/82 fpga: dfl: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
--- drivers/fpga/dfl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/fpga/dfl.c +3 -2
@@ -1939,15 +1939,16 @@ static int do_set_irq_trigger(struct dfl_feature *feature, unsigned int idx,int dfl_fpga_set_irq_triggers (struct dfl_feature *feature,unsigned int start,unsigned int count,int32_t *fds) { +unsigned int sum;unsigned int i;int ret =0 ;/* overflow */ -if (unlikely (start + count < start)) +if (unlikely (check_add_overflow (start, count, &sum)))return -EINVAL ;/* exceeds nr_irqs */ -if (start + count > feature->nr_irqs) +if (sum > feature->nr_irqs)return -EINVAL ;for (i =0 ; i < count; i++) {
Signature · 1 line
2.34.1
PATCH 21/82 drivers/fsi: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
--- drivers/fsi/fsi-core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/fsi/fsi-core.c +4 -2
@@ -381,10 +381,12 @@ EXPORT_SYMBOL_GPL(fsi_slave_write);int fsi_slave_claim_range (struct fsi_slave *slave,uint32_t addr,uint32_t size) { -if (addr + size < addr) +uint32_t sum; + +if (check_add_overflow (addr, size, &sum))return -EINVAL ; -if (addr + size > slave->size) +if (sum > slave->size)return -EINVAL ;/* todo: check for overlapping claims */
Signature · 1 line
2.34.1
PATCH 22/82 x86/sgx: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
--- arch/x86/kernel/cpu/sgx/ioctl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/sgx/ioctl.c +4 -2
@@ -350,16 +350,18 @@ static int sgx_validate_offset_length(struct sgx_encl *encl, unsigned long offset, unsigned long length) { +unsigned long sum; +if (!IS_ALIGNED (offset,PAGE_SIZE ))return -EINVAL ;if (!length || !IS_ALIGNED (length,PAGE_SIZE ))return -EINVAL ; -if (offset + length < offset) +if (check_add_overflow (offset, length, &sum))return -EINVAL ; -if (offset + length -PAGE_SIZE >= encl->size) +if (sum -PAGE_SIZE >= encl->size)return -EINVAL ;return 0 ;
Signature · 1 line
2.34.1
Re: [PATCH 22/82] x86/sgx: Refactor intentional wrap-around calculation
Quoted 51 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.Cc Jarkko Sakkinen <[email protected]>Cc Dave Hansen <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Ingo Molnar <[email protected]>Cc Borislav Petkov <[email protected]>Cc "H. Peter Anvin" <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/x86/kernel/cpu/sgx/ioctl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)arch/x86/kernel/cpu/sgx/ioctl.c +2
-0@@ -350,16 +350,18 @@ static int sgx_validate_offset_length(struct sgx_encl *encl, unsigned long offset, unsigned long length) { +unsigned long sum; +if (!IS_ALIGNED (offset,PAGE_SIZE ))return -EINVAL ;if (!length || !IS_ALIGNED (length,PAGE_SIZE ))return -EINVAL ;
arch/x86/kernel/cpu/sgx/ioctl.c static int sgx_validate_offset_length(struct sgx_encl *encl, · line 367
Quoted 10 lines
arch/x86/kernel/cpu/sgx/ioctl.c +2
-2-if (offset + length < offset) +if (check_add_overflow (offset, length, &sum))return -EINVAL ; -if (offset + length -PAGE_SIZE >= encl->size) +if (sum -PAGE_SIZE >= encl->size)return -EINVAL ;return 0 ;
BR, Jarkko
PATCH 23/82 KVM: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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
Notable, 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, unsigned, or pointer types.
Refactor open-coded unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
--- virt/kvm/coalesced_mmio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
virt/kvm/coalesced_mmio.c +4 -2
@@ -25,17 +25,19 @@ static inline struct kvm_coalesced_mmio_dev *to_mmio(struct kvm_io_device *dev)static int coalesced_mmio_in_range (struct kvm_coalesced_mmio_dev *dev,gpa_t addr,int len) { +gpa_t sum; +/* is it in a batchable area ? * (addr,len) is fully included in * (zone->addr, zone->size) */ if (len <0 )return 0 ; -if (addr + len < addr) +if (check_add_overflow (addr, len, &sum))return 0 ;if (addr < dev->zone.addr)return 0 ; -if (addr + len > dev->zone.addr + dev->zone.size) +if (sum > dev->zone.addr + dev->zone.size)return 0 ;return 1 ; }
Signature · 1 line
2.34.1
Sean Christopherson
maintainerRe: [PATCH 23/82] KVM: Refactor intentional wrap-around calculation
Quoted 33 lines · Kees Cook
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
Notable, 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, unsigned, or pointer types.
Refactor open-coded unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.Cc Paolo Bonzini <[email protected]>Signed-off-by Kees Cook <[email protected]>--- virt/kvm/coalesced_mmio.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)virt/kvm/coalesced_mmio.c +0
-0
virt/kvm/coalesced_mmio.c static inline struct kvm_coalesced_mmio_dev *to_mmio(struct kvm_io_device *dev) · line 28
Quoted 4 lines
virt/kvm/coalesced_mmio.c +1
-0@@ -25,17 +25,19 @@ static inline struct kvm_coalesced_mmio_dev *to_mmio(struct kvm_io_device *dev)static int coalesced_mmio_in_range (struct kvm_coalesced_mmio_dev *dev,gpa_t addr,int len) { +gpa_t sum;
s/sum/end?
Also, given that your're fixing a gpa_t, which is a u64, presumably that means that this code in __kvm_set_memory_region() also needs to be fixed:
if (mem->guest_phys_addr + mem->memory_size < mem->guest_phys_addr) return -EINVAL;
and for that one I'd really like to avoid an ignored output parameter (KVM converts the incoming mem->memory_size to pages, so the "sum" is never used directly).
Would it make sense to add an API that feeds a dummy "sum" value? I assume UBSAN won't fire on the usage of the known good value, i.e. using the output parameter isn't necessary for functional correctness. Having an API that does just the check would trim down the size of many of these patches and avoid having to come up with names for the local variables. And IMO, the existing code is a wee bit more intuitive, it'd be nice to give developers the flexibility to choose which flavor yields the "best" code on a case-by-case basis.
Quoted 20 lines
virt/kvm/coalesced_mmio.c +3
-2+/* is it in a batchable area ? * (addr,len) is fully included in * (zone->addr, zone->size) */ if (len <0 )return 0 ; -if (addr + len < addr) +if (check_add_overflow (addr, len, &sum))return 0 ;if (addr < dev->zone.addr)return 0 ; -if (addr + len > dev->zone.addr + dev->zone.size) +if (sum > dev->zone.addr + dev->zone.size)return 0 ;return 1 ; }Signature · 1 line
2.34.1
PATCH 24/82 KVM: arm64: vgic: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
--- arch/arm64/kvm/vgic/vgic-kvm-device.c | 6 ++++-- arch/arm64/kvm/vgic/vgic-v2.c | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-)
arch/arm64/kvm/vgic/vgic-kvm-device.c +4 -2
@@ -18,17 +18,19 @@ int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr, phys_addr_t addr, phys_addr_t alignment, phys_addr_t size) { + phys_addr_t sum; +if (!IS_VGIC_ADDR_UNDEF (ioaddr))return -EEXIST ;if (!IS_ALIGNED (addr, alignment) || !IS_ALIGNED (size, alignment))return -EINVAL ; -if (addr + size < addr) +if (check_add_overflow (addr, size, &sum))return -EINVAL ;if (addr & ~kvm_phys_mask (&kvm->arch.mmu) || - (addr + size) >kvm_phys_size (&kvm->arch.mmu)) + sum >kvm_phys_size (&kvm->arch.mmu))return -E2BIG ;return 0 ;
arch/arm64/kvm/vgic/vgic-v2.c +6 -4
@@ -273,14 +273,16 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)/* check for overlapping regions and for regions crossing the end of memory */ static bool vgic_v2_check_base (gpa_t dist_base,gpa_t cpu_base) { -if (dist_base +KVM_VGIC_V2_DIST_SIZE < dist_base) +gpa_t dist_sum, cpu_sum; + +if (check_add_overflow (dist_base,KVM_VGIC_V2_DIST_SIZE , &dist_sum))return false; -if (cpu_base +KVM_VGIC_V2_CPU_SIZE < cpu_base) +if (check_add_overflow (cpu_base,KVM_VGIC_V2_CPU_SIZE , &cpu_sum))return false; -if (dist_base +KVM_VGIC_V2_DIST_SIZE <= cpu_base) +if (dist_sum <= cpu_base)return true; -if (cpu_base +KVM_VGIC_V2_CPU_SIZE <= dist_base) +if (cpu_sum <= dist_base)return true;return false;
Signature · 1 line
2.34.1
Re: [PATCH 24/82] KVM: arm64: vgic: Refactor intentional wrap-around calculation
Quoted 58 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.Cc Marc Zyngier <[email protected]>Cc Oliver Upton <[email protected]>Cc James Morse <[email protected]>Cc Suzuki K Poulose <[email protected]>Cc Zenghui Yu <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Reiji Watanabe <[email protected]>Cc Eric Auger <[email protected]>Cc Ricardo Koller <[email protected]>Cc Raghavendra Rao Ananta <[email protected]>Cc Quentin Perret <[email protected]>Cc Jean-Philippe Brucker <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/arm64/kvm/vgic/vgic-kvm-device.c | 6 ++++-- arch/arm64/kvm/vgic/vgic-v2.c | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-)arch/arm64/kvm/vgic/vgic-kvm-device.c +2
-0@@ -18,17 +18,19 @@ int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr, phys_addr_t addr, phys_addr_t alignment, phys_addr_t size) { + phys_addr_t sum; +if (!IS_VGIC_ADDR_UNDEF (ioaddr))return -EEXIST ;
arch/arm64/kvm/vgic/vgic-kvm-device.c int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr, · line 33
Quoted 10 lines
arch/arm64/kvm/vgic/vgic-kvm-device.c +2
-2if (!IS_ALIGNED (addr, alignment) || !IS_ALIGNED (size, alignment))return -EINVAL ; -if (addr + size < addr) +if (check_add_overflow (addr, size, &sum))return -EINVAL ;if (addr & ~kvm_phys_mask (&kvm->arch.mmu) || - (addr + size) >kvm_phys_size (&kvm->arch.mmu)) + sum >kvm_phys_size (&kvm->arch.mmu))
nit: 'sum' doesn't mean much in this context. Something like 'end' would be much more descriptive.
arch/arm64/kvm/vgic/vgic-v2.c void vgic_v2_enable(struct kvm_vcpu *vcpu) · line 276
Quoted 13 lines
arch/arm64/kvm/vgic/vgic-kvm-device.c +0
-0return -E2BIG ;return 0 ;arch/arm64/kvm/vgic/vgic-v2.c +1
-1@@ -273,14 +273,16 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)/* check for overlapping regions and for regions crossing the end of memory */ static bool vgic_v2_check_base (gpa_t dist_base,gpa_t cpu_base) { -if (dist_base +KVM_VGIC_V2_DIST_SIZE < dist_base) +gpa_t dist_sum, cpu_sum;
Same here: dist_end, cpu_end.
Quoted 5 lines
arch/arm64/kvm/vgic/vgic-v2.c +3
-1+ +if (check_add_overflow (dist_base,KVM_VGIC_V2_DIST_SIZE , &dist_sum))return false; -if (cpu_base +KVM_VGIC_V2_CPU_SIZE < cpu_base) +if (check_add_overflow (cpu_base,KVM_VGIC_V2_CPU_SIZE , &cpu_sum))
arch/arm64/kvm/vgic/vgic-v2.c void vgic_v2_enable(struct kvm_vcpu *vcpu) · line 288
Quoted 10 lines
arch/arm64/kvm/vgic/vgic-v2.c +2
-2return false; -if (dist_base +KVM_VGIC_V2_DIST_SIZE <= cpu_base) +if (dist_sum <= cpu_base)return true; -if (cpu_base +KVM_VGIC_V2_CPU_SIZE <= dist_base) +if (cpu_sum <= dist_base)return true;return false;
With these nits addressed, and assuming you intend to merge the whole series yourself:
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Eric Auger
Reviewed-byRe: [PATCH 24/82] KVM: arm64: vgic: Refactor intentional wrap-around calculation
Quoted 74 lines · Marc Zyngier
Quoted 57 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.Cc Marc Zyngier <[email protected]>Cc Oliver Upton <[email protected]>Cc James Morse <[email protected]>Cc Suzuki K Poulose <[email protected]>Cc Zenghui Yu <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Reiji Watanabe <[email protected]>Cc Eric Auger <[email protected]>Cc Ricardo Koller <[email protected]>Cc Raghavendra Rao Ananta <[email protected]>Cc Quentin Perret <[email protected]>Cc Jean-Philippe Brucker <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/arm64/kvm/vgic/vgic-kvm-device.c | 6 ++++-- arch/arm64/kvm/vgic/vgic-v2.c | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-)arch/arm64/kvm/vgic/vgic-kvm-device.c +2
-0@@ -18,17 +18,19 @@ int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr, phys_addr_t addr, phys_addr_t alignment, phys_addr_t size) { + phys_addr_t sum; +if (!IS_VGIC_ADDR_UNDEF (ioaddr))return -EEXIST ;arch/arm64/kvm/vgic/vgic-kvm-device.c int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr, · line 33
Quoted 10 lines
arch/arm64/kvm/vgic/vgic-kvm-device.c +2
-2if (!IS_ALIGNED (addr, alignment) || !IS_ALIGNED (size, alignment))return -EINVAL ; -if (addr + size < addr) +if (check_add_overflow (addr, size, &sum))return -EINVAL ;if (addr & ~kvm_phys_mask (&kvm->arch.mmu) || - (addr + size) >kvm_phys_size (&kvm->arch.mmu)) + sum >kvm_phys_size (&kvm->arch.mmu))nit: 'sum' doesn't mean much in this context. Something like 'end' would be much more descriptive.
Quoted 2 lines
arch/arm64/kvm/vgic/vgic-kvm-device.c +0
-0return -E2BIG ;
Quoted 12 lines
arch/arm64/kvm/vgic/vgic-v2.c void vgic_v2_enable(struct kvm_vcpu *vcpu) · line 276
Quoted 11 lines
arch/arm64/kvm/vgic/vgic-kvm-device.c +0
-0return 0 ;arch/arm64/kvm/vgic/vgic-v2.c +1
-1@@ -273,14 +273,16 @@ void vgic_v2_enable(struct kvm_vcpu *vcpu)/* check for overlapping regions and for regions crossing the end of memory */ static bool vgic_v2_check_base (gpa_t dist_base,gpa_t cpu_base) { -if (dist_base +KVM_VGIC_V2_DIST_SIZE < dist_base) +gpa_t dist_sum, cpu_sum;Same here:
dist_end,cpu_end.
I do agree.
Quoted 15 lines
Quoted 15 lines
arch/arm64/kvm/vgic/vgic-v2.c +5
-3+ +if (check_add_overflow (dist_base,KVM_VGIC_V2_DIST_SIZE , &dist_sum))return false; -if (cpu_base +KVM_VGIC_V2_CPU_SIZE < cpu_base) +if (check_add_overflow (cpu_base,KVM_VGIC_V2_CPU_SIZE , &cpu_sum))return false; -if (dist_base +KVM_VGIC_V2_DIST_SIZE <= cpu_base) +if (dist_sum <= cpu_base)return true; -if (cpu_base +KVM_VGIC_V2_CPU_SIZE <= dist_base) +if (cpu_sum <= dist_base)return true;
Quoted 5 lines
arch/arm64/kvm/vgic/vgic-v2.c void vgic_v2_enable(struct kvm_vcpu *vcpu) · line 288
Quoted 1 line
arch/arm64/kvm/vgic/vgic-v2.c +0
-0return false;With these nits addressed, and assuming you intend to merge the whole series yourself:
Acked-by Marc Zyngier <[email protected]>
assuming above suggested changes,
Eric
Quoted 3 lines
M.
PATCH 25/82 KVM: SVM: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
--- arch/x86/kvm/svm/sev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/kvm/svm/sev.c +3 -2
@@ -400,16 +400,17 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,unsigned long locked, lock_limit;struct page **pages;unsigned long first, last; +unsigned long sum;int ret;lockdep_assert_held (&kvm->lock); -if (ulen ==0 || uaddr + ulen < uaddr) +if (ulen ==0 ||check_add_overflow (uaddr, ulen, &sum))return ERR_PTR (-EINVAL );/* Calculate number of pages. */ first = (uaddr &PAGE_MASK ) >>PAGE_SHIFT ; - last = ((uaddr + ulen -1 ) &PAGE_MASK ) >>PAGE_SHIFT ; + last = ((sum -1 ) &PAGE_MASK ) >>PAGE_SHIFT ; npages = (last - first +1 ); locked = sev->pages_locked + npages;
Signature · 1 line
2.34.1
Sean Christopherson
maintainerRe: [PATCH 25/82] KVM: SVM: Refactor intentional wrap-around calculation
Quoted 14 lines · Kees Cook
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.
Quoted 4 lines
Refactor open-coded unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the wrap-around sanitizers in the future.
IIUC, the plan is to get UBSAN to detect unexpected overflow, at which point an explicit annotation will be needed to avoid false positives. If that's correct, can you put something like that in these changelogs? Nothing in the changelog actually says _why_ open coded wrap-around checks will be problematic.
Quoted 23 lines
Cc Sean Christopherson <[email protected]>Cc Paolo Bonzini <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Ingo Molnar <[email protected]>Cc Borislav Petkov <[email protected]>Cc Dave Hansen <[email protected]>Cc "H. Peter Anvin" <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/x86/kvm/svm/sev.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)arch/x86/kvm/svm/sev.c +0
-0
arch/x86/kvm/svm/sev.c static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr, · line 403
Quoted 4 lines
arch/x86/kvm/svm/sev.c +1
-0@@ -400,16 +400,17 @@ static struct page **sev_pin_memory(struct kvm *kvm, unsigned long uaddr,unsigned long locked, lock_limit;struct page **pages;unsigned long first, last; +unsigned long sum;
Similar to Marc's comments, I would much prefer to call this uaddr_last.
Quoted 18 lines
arch/x86/kvm/svm/sev.c +2
-2int ret;lockdep_assert_held (&kvm->lock); -if (ulen ==0 || uaddr + ulen < uaddr) +if (ulen ==0 ||check_add_overflow (uaddr, ulen, &sum))return ERR_PTR (-EINVAL );/* Calculate number of pages. */ first = (uaddr &PAGE_MASK ) >>PAGE_SHIFT ; - last = ((uaddr + ulen -1 ) &PAGE_MASK ) >>PAGE_SHIFT ; + last = ((sum -1 ) &PAGE_MASK ) >>PAGE_SHIFT ; npages = (last - first +1 ); locked = sev->pages_locked + npages;Signature · 1 line
2.34.1
PATCH 26/82 buildid: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 pointer wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
--- lib/buildid.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
lib/buildid.c +4 -2
@@ -54,12 +54,14 @@ static inline int parse_build_id(const void *page_addr,const void *note_start, Elf32_Word note_size) { + const void *sum; +/* check for overflow */ - if (note_start < page_addr || note_start + note_size < note_start) +if (note_start < page_addr ||check_add_overflow (note_start, note_size, &sum))return -EINVAL ;/* only supports note that fits in the first page */ -if (note_start + note_size > page_addr +PAGE_SIZE ) +if (sum > page_addr +PAGE_SIZE )return -EINVAL ;return parse_build_id_buf (build_id, size, note_start, note_size);
Signature · 1 line
2.34.1
PATCH 27/82 m68k: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
--- arch/m68k/kernel/sys_m68k.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/m68k/kernel/sys_m68k.c +3 -2
@@ -391,10 +391,11 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)mmap_read_lock (current->mm); }else { +unsigned long sum;struct vm_area_struct *vma;/* Check for overflow. */ -if (addr + len < addr) +if (check_add_overflow (addr, len, &sum)) goto out;/*
@@ -403,7 +404,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)*/ mmap_read_lock (current->mm); vma =vma_lookup (current->mm, addr); -if (!vma || addr + len > vma->vm_end) +if (!vma || sum > vma->vm_end) goto out_unlock; }
Signature · 1 line
2.34.1
Re: [PATCH 27/82] m68k: Refactor intentional wrap-around calculation
Quoted 40 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.Cc Geert Uytterhoeven <[email protected]>Cc Andrew Morton <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Liam Howlett <[email protected]>Cc "Matthew Wilcox (Oracle)" <[email protected]>Cc Hugh Dickins <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/m68k/kernel/sys_m68k.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)arch/m68k/kernel/sys_m68k.c +0
-0
arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 397
Quoted 7 lines
arch/m68k/kernel/sys_m68k.c +1
-0@@ -391,10 +391,11 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)mmap_read_lock (current->mm); }else { +unsigned long sum;struct vm_area_struct *vma;/* Check for overflow. */
With your nice self-documenting code, you can probably drop that comment.
With or without the change,
Quoted 17 lines
arch/m68k/kernel/sys_m68k.c +2
-2-if (addr + len < addr) +if (check_add_overflow (addr, len, &sum)) goto out;/* @@ -403,7 +404,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)*/ mmap_read_lock (current->mm); vma =vma_lookup (current->mm, addr); -if (!vma || addr + len > vma->vm_end) +if (!vma || sum > vma->vm_end) goto out_unlock; }Signature · 1 line
2.34.1
Re: [PATCH 27/82] m68k: Refactor intentional wrap-around calculation
In reply to Kees CookHi Kees,
Quoted 19 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
Quoted 12 lines
Cc Geert Uytterhoeven <[email protected]>Cc Andrew Morton <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Liam Howlett <[email protected]>Cc "Matthew Wilcox (Oracle)" <[email protected]>Cc Hugh Dickins <[email protected]>Signed-off-by Kees Cook <[email protected]>
Thanks for your patch!
arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 394
Quoted 7 lines
arch/m68k/kernel/sys_m68k.c +1
-0@@ -391,10 +391,11 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)mmap_read_lock (current->mm); }else { +unsigned long sum;
"sum" sounds like this is a dummy variable, to please the third parameter of check_add_overflow()...
arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 397
Quoted 3 lines
arch/m68k/kernel/sys_m68k.c +0
-0struct vm_area_struct *vma;/* Check for overflow. */
I agree with Liam: please drop the comment.
arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 407
Quoted 11 lines
arch/m68k/kernel/sys_m68k.c +2
-2-if (addr + len < addr) +if (check_add_overflow (addr, len, &sum)) goto out;/* @@ -403,7 +404,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)*/ mmap_read_lock (current->mm); vma =vma_lookup (current->mm, addr); -if (!vma || addr + len > vma->vm_end) +if (!vma || sum > vma->vm_end)
... Oh, it is actually used. What about renaming it to "end" instead?
arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 409
Quoted 2 lines
arch/m68k/kernel/sys_m68k.c +0
-0goto out_unlock; }
With the above fixed:
If you want me to take this through the m68k tree (for v6.9), please let me know.
Thanks!
Gr{oetje,eeting}s,
Geert
Signature · 5 lines
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected] In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH 27/82] m68k: Refactor intentional wrap-around calculation
Hi,
Quoted 56 lines · Geert Uytterhoeven
Quoted 19 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.Quoted 12 lines
Cc Geert Uytterhoeven <[email protected]>Cc Andrew Morton <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Liam Howlett <[email protected]>Cc "Matthew Wilcox (Oracle)" <[email protected]>Cc Hugh Dickins <[email protected]>Signed-off-by Kees Cook <[email protected]>Thanks for your patch!
arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 394
Quoted 7 lines
arch/m68k/kernel/sys_m68k.c +1
-0@@ -391,10 +391,11 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)mmap_read_lock (current->mm); }else { +unsigned long sum;"sum" sounds like this is a dummy variable, to please the third parameter of
check_add_overflow()...arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 397
Quoted 3 lines
arch/m68k/kernel/sys_m68k.c +0
-0struct vm_area_struct *vma;/* Check for overflow. */ I agree with Liam: please drop the comment.
Quoted 4 lines
arch/m68k/kernel/sys_m68k.c +1
-1-if (addr + len < addr) +if (check_add_overflow (addr, len, &sum)) goto out;
Quoted 9 lines
arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 407
Quoted 7 lines
arch/m68k/kernel/sys_m68k.c +1
-1/* @@ -403,7 +404,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)*/ mmap_read_lock (current->mm); vma =vma_lookup (current->mm, addr); -if (!vma || addr + len > vma->vm_end) +if (!vma || sum > vma->vm_end)... Oh, it is actually used. What about renaming it to "end" instead?
IMHO this is more descriptive:
+ if (check_add_overflow(addr, len, &sum))
than this:
+ if (check_add_overflow(addr, len, &end))
"sum" is IMHO quite obviously sum of the preceding args, whereas I do not know what "end" would be.
- Eero
Quoted 16 lines
arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 409
Quoted 2 lines
arch/m68k/kernel/sys_m68k.c +0
-0goto out_unlock; }With the above fixed:
Reviewed-by Geert Uytterhoeven <[email protected]>If you want me to take this through the m68k tree (for v6.9), please let me know.
Thanks!Gr{oetje,eeting}s,
Geert
Geert Uytterhoeven
maintainerRe: [PATCH 27/82] m68k: Refactor intentional wrap-around calculation
Hi Eero,
Quoted 67 lines · Eero Tamminen
Quoted 56 lines · Geert Uytterhoeven
Quoted 19 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.Quoted 12 lines
Cc Geert Uytterhoeven <[email protected]>Cc Andrew Morton <[email protected]>Cc Arnd Bergmann <[email protected]>Cc Liam Howlett <[email protected]>Cc "Matthew Wilcox (Oracle)" <[email protected]>Cc Hugh Dickins <[email protected]>Signed-off-by Kees Cook <[email protected]>Thanks for your patch!
arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 394
Quoted 7 lines
arch/m68k/kernel/sys_m68k.c +1
-0@@ -391,10 +391,11 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)mmap_read_lock (current->mm); }else { +unsigned long sum;"sum" sounds like this is a dummy variable, to please the third parameter of
check_add_overflow()...arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 397
Quoted 3 lines
arch/m68k/kernel/sys_m68k.c +0
-0struct vm_area_struct *vma;/* Check for overflow. */ I agree with Liam: please drop the comment.
Quoted 4 lines
arch/m68k/kernel/sys_m68k.c +1
-1-if (addr + len < addr) +if (check_add_overflow (addr, len, &sum)) goto out;Quoted 9 lines
arch/m68k/kernel/sys_m68k.c sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len) · line 407
Quoted 7 lines
arch/m68k/kernel/sys_m68k.c +1
-1/* @@ -403,7 +404,7 @@ sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)*/ mmap_read_lock (current->mm); vma =vma_lookup (current->mm, addr); -if (!vma || addr + len > vma->vm_end) +if (!vma || sum > vma->vm_end)... Oh, it is actually used. What about renaming it to "end" instead?
Quoted 8 lines
IMHO this is more descriptive:
+ if (check_add_overflow(addr, len, &sum))than this:
+ if (check_add_overflow(addr, len, &end))"sum" is IMHO quite obviously sum of the preceding args, whereas I do not know what "end" would be.
"end" is the end of the block of size "len" pointed to by "addr".
IMHO "if (sum > vma->vm_end)" is less descriptive...
Gr{oetje,eeting}s,
Geert
Signature · 5 lines
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- [email protected] In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
PATCH 28/82 niu: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
--- drivers/net/ethernet/sun/niu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/ethernet/sun/niu.c +3 -2
@@ -6877,15 +6877,16 @@ static int niu_get_eeprom(struct net_device *dev, {struct niu *np =netdev_priv (dev);u32 offset, len, val; +u32 sum; offset = eeprom->offset; len = eeprom->len; -if (offset + len < offset) +if (check_add_overflow (offset, len, &sum))return -EINVAL ;if (offset >= np->eeprom_len)return -EINVAL ; -if (offset + len > np->eeprom_len) +if (sum > np->eeprom_len) len = eeprom->len = np->eeprom_len - offset;if (offset &3 ) {
Signature · 1 line
2.34.1
PATCH 29/82 rds: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
--- net/rds/info.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/rds/info.c +4 -2
@@ -163,6 +163,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,unsigned long nr_pages =0 ;unsigned long start;rds_info_func func; +unsigned long sum;struct page **pages =NULL ;int ret;int len;
@@ -175,7 +176,8 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,/* check for all kinds of wrapping and the like */ start = (unsigned long )optval; -if (len <0 || len >INT_MAX -PAGE_SIZE +1 || start + len < start) { +if (len <0 || len >INT_MAX -PAGE_SIZE +1 || +check_add_overflow (start, len, &sum)) { ret = -EINVAL ; goto out; }
@@ -184,7 +186,7 @@ int rds_info_getsockopt(struct socket *sock, int optname, char __user *optval,if (len ==0 ) goto call_func; - nr_pages = (PAGE_ALIGN (start + len) - (start &PAGE_MASK )) + nr_pages = (PAGE_ALIGN (sum) - (start &PAGE_MASK )) >>PAGE_SHIFT ; pages =kmalloc_array (nr_pages,sizeof (struct page *),GFP_KERNEL );
Signature · 1 line
2.34.1
PATCH 30/82 s390/kexec_file: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
--- arch/s390/include/asm/stacktrace.h | 6 ++++-- arch/s390/kernel/machine_kexec_file.c | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-)
arch/s390/include/asm/stacktrace.h +4 -2
@@ -34,11 +34,13 @@ int get_stack_info(unsigned long sp, struct task_struct *task,static inline bool on_stack (struct stack_info *info,unsigned long addr,size_t len) { +unsigned long sum; +if (info->type ==STACK_TYPE_UNKNOWN )return false; -if (addr + len < addr) +if (check_add_overflow (addr, len, &sum))return false; -return addr >= info->begin && addr + len <= info->end; +return addr >= info->begin && sum <= info->end; }/*
arch/s390/kernel/machine_kexec_file.c +3 -2
@@ -238,6 +238,7 @@ void *kexec_file_add_components(struct kimage *image,unsigned long max_command_line_size =LEGACY_COMMAND_LINE_SIZE ;struct s390_load_data data = {0 };unsigned long minsize; +unsigned long sum;int ret; data.report =ipl_report_init (&ipl_block);
@@ -256,10 +257,10 @@ void *kexec_file_add_components(struct kimage *image,if (data.parm->max_command_line_size) max_command_line_size = data.parm->max_command_line_size; -if (minsize + max_command_line_size < minsize) +if (check_add_overflow (minsize, max_command_line_size, &sum)) goto out; -if (image->kernel_buf_len < minsize + max_command_line_size) +if (image->kernel_buf_len < sum) goto out;if (image->cmdline_buf_len >= max_command_line_size)
Signature · 1 line
2.34.1
Alexander Gordeev
maintainerRe: [PATCH 30/82] s390/kexec_file: Refactor intentional wrap-around calculation
On Mon, Jan 22, 2024 at 04:27:05PM -0800, Kees Cook wrote:
Hi Kees,
...
Quoted 2 lines
arch/s390/include/asm/stacktrace.h | 6 ++++-- arch/s390/kernel/machine_kexec_file.c | 5 +++--
Subject does not match. These need to be two separate commits.
Quoted 7 lines
2 files changed, 7 insertions(+), 4 deletions(-)arch/s390/include/asm/stacktrace.h +0
-0
arch/s390/include/asm/stacktrace.h int get_stack_info(unsigned long sp, struct task_struct *task, · line 41
Quoted 9 lines
arch/s390/include/asm/stacktrace.h +3
-1@@ -34,11 +34,13 @@ int get_stack_info(unsigned long sp, struct task_struct *task,static inline bool on_stack (struct stack_info *info,unsigned long addr,size_t len) { +unsigned long sum; +if (info->type ==STACK_TYPE_UNKNOWN )return false; -if (addr + len < addr) +if (check_add_overflow (addr, len, &sum))
Why not add_would_overflow()?
Quoted 11 lines
arch/s390/include/asm/stacktrace.h +1
-1return false; -return addr >= info->begin && addr + len <= info->end; +return addr >= info->begin && sum <= info->end; }/* arch/s390/kernel/machine_kexec_file.c +0
-0
arch/s390/kernel/machine_kexec_file.c void *kexec_file_add_components(struct kimage *image, · line 241
Quoted 4 lines
arch/s390/kernel/machine_kexec_file.c +1
-0@@ -238,6 +238,7 @@ void *kexec_file_add_components(struct kimage *image,unsigned long max_command_line_size =LEGACY_COMMAND_LINE_SIZE ;struct s390_load_data data = {0 };unsigned long minsize; +unsigned long sum;
Please, use min_kernel_buf_len instead of sum.
@Sven, could you please correct me if (minsize + max_command_line_size) means something else.
Quoted 6 lines
arch/s390/kernel/machine_kexec_file.c +0
-0int ret; data.report =ipl_report_init (&ipl_block);@@ -256,10 +257,10 @@ void *kexec_file_add_components(struct kimage *image,if (data.parm->max_command_line_size) max_command_line_size = data.parm->max_command_line_size;
arch/s390/kernel/machine_kexec_file.c void *kexec_file_add_components(struct kimage *image, · line 266
Quoted 10 lines
arch/s390/kernel/machine_kexec_file.c +2
-2-if (minsize + max_command_line_size < minsize) +if (check_add_overflow (minsize, max_command_line_size, &sum)) goto out; -if (image->kernel_buf_len < minsize + max_command_line_size) +if (image->kernel_buf_len < sum) goto out;if (image->cmdline_buf_len >= max_command_line_size)
Thanks!
Sven Schnelle
reviewerRe: [PATCH 30/82] s390/kexec_file: Refactor intentional wrap-around calculation
Quoted 13 lines · Alexander Gordeev
arch/s390/kernel/machine_kexec_file.c void *kexec_file_add_components(struct kimage *image, · line 241
Quoted 9 lines · Kees Cook
arch/s390/kernel/machine_kexec_file.c +1
-0@@ -238,6 +238,7 @@ void *kexec_file_add_components(struct kimage *image,unsigned long max_command_line_size =LEGACY_COMMAND_LINE_SIZE ;struct s390_load_data data = {0 };unsigned long minsize; +unsigned long sum;Please, use
min_kernel_buf_leninstead of sum.
Quoted 2 lines
@Sven, could you please correct me if (minsize +
max_command_line_size) means something else.
Your understanding is correct, minsize + max_command_line_size is the minimum required size of the kernel image.
PATCH 31/82 ARC: dw2 unwind: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 pointer wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
--- arch/arc/kernel/unwind.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
arch/arc/kernel/unwind.c +3 -2
@@ -612,6 +612,7 @@ static signed fde_pointer_type(const u32 *cie)const char *aug;const u8 *end = (const u8 *)(cie +1 ) + *cie;uleb128_t len; +const u8 *sum;/* check if augmentation size is first (and thus present) */ if (*ptr !='z' )
@@ -630,10 +631,10 @@ static signed fde_pointer_type(const u32 *cie) version <=1 ? (void ) ++ptr : (void )get_uleb128 (&ptr, end); len =get_uleb128 (&ptr, end);/* augmentation length */ -if (ptr + len < ptr || ptr + len > end) +if (check_add_overflow (ptr, len, &sum) || sum > end)return -1 ; - end = ptr + len; + end = sum;while (*++aug) {if (ptr >= end)return -1 ;
Signature · 1 line
2.34.1
PATCH 32/82 vringh: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
--- drivers/vhost/vringh.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/vhost/vringh.c +5 -3
@@ -145,6 +145,8 @@ static inline bool range_check(struct vringh *vrh, u64 addr, size_t *len,bool (*getrange)(struct vringh *, u64, struct vringh_range *)) { +u64 sum; +if (addr < range->start || addr > range->end_incl) {if (!getrange (vrh, addr, range))return false;
@@ -152,20 +154,20 @@ static inline bool range_check(struct vringh *vrh, u64 addr, size_t *len,BUG_ON (addr < range->start || addr > range->end_incl);/* To end of memory? */ -if (unlikely (addr + *len ==0 )) { +if (unlikely (U64_MAX - addr == *len)) {if (range->end_incl ==-1ULL )return true; goto truncate; }/* Otherwise, don't wrap. */ -if (addr + *len < addr) { +if (check_add_overflow (addr, *len, &sum)) {vringh_bad ("Wrapping descriptor %zu@0x%llx" , *len, (unsigned long long )addr);return false; } -if (unlikely (addr + *len -1 > range->end_incl)) +if (unlikely (sum -1 > range->end_incl)) goto truncate;return true;
Signature · 1 line
2.34.1
Re: [PATCH 32/82] vringh: Refactor intentional wrap-around calculation
Quoted 39 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.Cc "Michael S. Tsirkin" <[email protected]>Cc Jason Wang <[email protected]>Signed-off-by Kees Cook <[email protected]>--- drivers/vhost/vringh.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)drivers/vhost/vringh.c +0
-0
drivers/vhost/vringh.c static inline bool range_check(struct vringh *vrh, u64 addr, size_t *len, · line 148
Quoted 4 lines
drivers/vhost/vringh.c +1
-0@@ -145,6 +145,8 @@ static inline bool range_check(struct vringh *vrh, u64 addr, size_t *len,bool (*getrange)(struct vringh *, u64, struct vringh_range *)) { +u64 sum;
I understand this is part of a bulk change so little time to think about names :). But what about "end" or similar?
Either way,
Quoted 32 lines
drivers/vhost/vringh.c +4
-4+if (addr < range->start || addr > range->end_incl) {if (!getrange (vrh, addr, range))return false;@@ -152,20 +154,20 @@ static inline bool range_check(struct vringh *vrh, u64 addr, size_t *len,BUG_ON (addr < range->start || addr > range->end_incl);/* To end of memory? */ -if (unlikely (addr + *len ==0 )) { +if (unlikely (U64_MAX - addr == *len)) {if (range->end_incl ==-1ULL )return true; goto truncate; }/* Otherwise, don't wrap. */ -if (addr + *len < addr) { +if (check_add_overflow (addr, *len, &sum)) {vringh_bad ("Wrapping descriptor %zu@0x%llx" , *len, (unsigned long long )addr);return false; } -if (unlikely (addr + *len -1 > range->end_incl)) +if (unlikely (sum -1 > range->end_incl)) goto truncate;return true; --2.34.1
Re: [PATCH 32/82] vringh: Refactor intentional wrap-around calculation
Quoted 48 lines · Eugenio Perez Martin
Quoted 39 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.Cc "Michael S. Tsirkin" <[email protected]>Cc Jason Wang <[email protected]>Signed-off-by Kees Cook <[email protected]>--- drivers/vhost/vringh.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)drivers/vhost/vringh.c +0
-0drivers/vhost/vringh.c static inline bool range_check(struct vringh *vrh, u64 addr, size_t *len, · line 148
Quoted 4 lines
drivers/vhost/vringh.c +1
-0@@ -145,6 +145,8 @@ static inline bool range_check(struct vringh *vrh, u64 addr, size_t *len,bool (*getrange)(struct vringh *, u64, struct vringh_range *)) { +u64 sum;I understand this is part of a bulk change so little time to think about names :). But what about "end" or similar?
Quoted 2 lines
Either way,
Acked-by Eugenio Pérez <[email protected]>
Thanks! Yeah, you are not alone in suggesting "end" in a several of these patches. :)
-Kees
Signature · 1 line
Kees Cook
PATCH 33/82 mm/vmalloc: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
--- mm/vmalloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
mm/vmalloc.c +3 -2
@@ -1223,6 +1223,7 @@ is_within_this_va(struct vmap_area *va, unsigned long size, unsigned long align, unsigned long vstart) {unsigned long nva_start_addr; +unsigned long sum;if (va->va_start > vstart) nva_start_addr =ALIGN (va->va_start, align);
@@ -1230,11 +1231,11 @@ is_within_this_va(struct vmap_area *va, unsigned long size, nva_start_addr =ALIGN (vstart, align);/* Can be overflowed due to big size or alignment. */ -if (nva_start_addr + size < nva_start_addr || +if (check_add_overflow (nva_start_addr, size, &sum) || nva_start_addr < vstart)return false; -return (nva_start_addr + size <= va->va_end); +return (sum <= va->va_end); }/*
Signature · 1 line
2.34.1
Re: [PATCH 33/82] mm/vmalloc: Refactor intentional wrap-around calculation
Quoted 60 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.Cc Andrew Morton <[email protected]>Cc Uladzislau Rezki <[email protected]>Cc Christoph Hellwig <[email protected]>Cc Lorenzo Stoakes <[email protected]>Signed-off-by Kees Cook <[email protected]>--- mm/vmalloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)mm/vmalloc.c +3
-3@@ -1223,6 +1223,7 @@ is_within_this_va(struct vmap_area *va, unsigned long size, unsigned long align, unsigned long vstart) {unsigned long nva_start_addr; +unsigned long sum;if (va->va_start > vstart) nva_start_addr =ALIGN (va->va_start, align);@@ -1230,11 +1231,11 @@ is_within_this_va(struct vmap_area *va, unsigned long size, nva_start_addr =ALIGN (vstart, align);/* Can be overflowed due to big size or alignment. */ -if (nva_start_addr + size < nva_start_addr || +if (check_add_overflow (nva_start_addr, size, &sum) || nva_start_addr < vstart)return false; -return (nva_start_addr + size <= va->va_end); +return (sum <= va->va_end); }/* --
Quoted 2 lines
2.34.1
Looks good to me,
Uladzislau Rezki
maintainerRe: [PATCH 33/82] mm/vmalloc: Refactor intentional wrap-around calculation
Quoted 59 lines · Lorenzo Stoakes
Quoted 58 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.Cc Andrew Morton <[email protected]>Cc Uladzislau Rezki <[email protected]>Cc Christoph Hellwig <[email protected]>Cc Lorenzo Stoakes <[email protected]>Signed-off-by Kees Cook <[email protected]>--- mm/vmalloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)mm/vmalloc.c +3
-2@@ -1223,6 +1223,7 @@ is_within_this_va(struct vmap_area *va, unsigned long size, unsigned long align, unsigned long vstart) {unsigned long nva_start_addr; +unsigned long sum;if (va->va_start > vstart) nva_start_addr =ALIGN (va->va_start, align);@@ -1230,11 +1231,11 @@ is_within_this_va(struct vmap_area *va, unsigned long size, nva_start_addr =ALIGN (vstart, align);/* Can be overflowed due to big size or alignment. */ -if (nva_start_addr + size < nva_start_addr || +if (check_add_overflow (nva_start_addr, size, &sum) || nva_start_addr < vstart)return false; -return (nva_start_addr + size <= va->va_end); +return (sum <= va->va_end); }
Quoted 9 lines
Quoted 4 lines
mm/vmalloc.c +0
-1/* -- 2.34.1
Looks good to me,
Reviewed-by Lorenzo Stoakes <[email protected]>
Same here. One small nit though. The "sum" variable is not something that it suits for. IMO, we should use a better name and replace it:
"nva_offset"?
--
Uladzislau Rezki
Re: [PATCH 33/82] mm/vmalloc: Refactor intentional wrap-around calculation
Quoted 67 lines · Uladzislau Rezki
Quoted 66 lines · Lorenzo Stoakes
Quoted 60 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.Cc Andrew Morton <[email protected]>Cc Uladzislau Rezki <[email protected]>Cc Christoph Hellwig <[email protected]>Cc Lorenzo Stoakes <[email protected]>Signed-off-by Kees Cook <[email protected]>--- mm/vmalloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)mm/vmalloc.c +3
-3@@ -1223,6 +1223,7 @@ is_within_this_va(struct vmap_area *va, unsigned long size, unsigned long align, unsigned long vstart) {unsigned long nva_start_addr; +unsigned long sum;if (va->va_start > vstart) nva_start_addr =ALIGN (va->va_start, align);@@ -1230,11 +1231,11 @@ is_within_this_va(struct vmap_area *va, unsigned long size, nva_start_addr =ALIGN (vstart, align);/* Can be overflowed due to big size or alignment. */ -if (nva_start_addr + size < nva_start_addr || +if (check_add_overflow (nva_start_addr, size, &sum) || nva_start_addr < vstart)return false; -return (nva_start_addr + size <= va->va_end); +return (sum <= va->va_end); }/* -- Quoted 2 lines
2.34.1
Looks good to me,
Quoted 6 lines
Quoted 2 lines
Reviewed-by Lorenzo Stoakes <[email protected]>Same here. One small nit though. The "sum" variable is not something that it suits for. IMO, we should use a better name and replace it:
"
nva_offset"?
Sure, I can use that. Other folks in other patches have suggested "end", so maybe nva_end or nva_end_addr ?
-Kees
Signature · 1 line
Kees Cook
Uladzislau Rezki
maintainerRe: [PATCH 33/82] mm/vmalloc: Refactor intentional wrap-around calculation
Quoted 70 lines · Kees Cook
Quoted 69 lines · Uladzislau Rezki
Quoted 68 lines · Lorenzo Stoakes
Quoted 60 lines · Kees Cook
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 unsigned wrap-around addition test to use
check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.Cc Andrew Morton <[email protected]>Cc Uladzislau Rezki <[email protected]>Cc Christoph Hellwig <[email protected]>Cc Lorenzo Stoakes <[email protected]>Signed-off-by Kees Cook <[email protected]>--- mm/vmalloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)mm/vmalloc.c +3
-3@@ -1223,6 +1223,7 @@ is_within_this_va(struct vmap_area *va, unsigned long size, unsigned long align, unsigned long vstart) {unsigned long nva_start_addr; +unsigned long sum;if (va->va_start > vstart) nva_start_addr =ALIGN (va->va_start, align);@@ -1230,11 +1231,11 @@ is_within_this_va(struct vmap_area *va, unsigned long size, nva_start_addr =ALIGN (vstart, align);/* Can be overflowed due to big size or alignment. */ -if (nva_start_addr + size < nva_start_addr || +if (check_add_overflow (nva_start_addr, size, &sum) || nva_start_addr < vstart)return false; -return (nva_start_addr + size <= va->va_end); +return (sum <= va->va_end); }/* -- Quoted 2 lines
2.34.1
Looks good to me,
Reviewed-by Lorenzo Stoakes <[email protected]>
Quoted 8 lines
Quoted 4 lines
Same here. One small nit though. The "sum" variable is not something that it suits for. IMO, we should use a better name and replace it:
"
nva_offset"?Sure, I can use that. Other folks in other patches have suggested "end", so maybe
nva_endornva_end_addr?
nva_end_addr is probably the best fit.
--
Uladzislau Rezki
PATCH 34/82 ipc: Refactor intentional wrap-around calculation
In reply to Kees CookIn 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 unsigned wrap-around addition test to use check_add_overflow(), retaining the result for later usage (which removes the redundant open-coded addition). This paves the way to enabling the unsigned wrap-around sanitizer[2] in the future.
--- ipc/shm.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
ipc/shm.c +4 -2
@@ -1650,11 +1650,13 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, }if (addr && !(shmflg &SHM_REMAP )) { +unsigned long sum; + err = -EINVAL ; -if (addr + size < addr) +if (check_add_overflow (addr, size, &sum)) goto invalid; -if (find_vma_intersection (current->mm, addr, addr + size)) +if (find_vma_intersection (current->mm, addr, sum)) goto invalid; }
Signature · 1 line
2.34.1
Linus Torvalds
NAKRe: [PATCH 34/82] ipc: Refactor intentional wrap-around calculation
Quoted 3 lines · Kees Cook
Refactor open-coded unsigned wrap-around addition test to use
check_add_overflow(),
NAK.
First off, none of this has anything to do with -fno-strict-overflow. We do that, because without it gcc ends up doing various odd and surprising things, the same way it does with strict-aliasing.
IOW, you should think of -fno-strict-overflow as a hardening thing. Any optimization that depends on "this can overflow, so I can do anything I want" is just a dangerous optimization for the kernel.
It matches -fno-strict-aliasing and -fno-delete-null-pointer-checks, in other words.
And I do not understand why you mention it in the first place, since this code USES UNSIGNED INTEGER ARITHMETIC, and thus has absolutely nothing to do with that no-strict-overflow flag.
So the commit message is actively misleading and broken. Unsigned arithmetic has very well-defined behavior, and the code uses that with a very traditional and valid test.
The comment about "redundant open-coded addition" is also PURE GARBAGE, since the compiler will trivially do the CSE - and on the source code level your modified code is actively bigger and uglier.
So your patch improves neither code generation or source code.
And if there's some unsigned wrap-around checker that doesn't understand this traditional way of doing overflow checking, that piece of crap needs fixing.
I don't want to see mindless conversion patches that work around some broken tooling.
I want to see them even less when pretty much EVERY SINGLE WORD in the commit message seems to be actively misleading and irrelevant garbage.
Stop making the world a worse place.
Linus
Re: [PATCH 34/82] ipc: Refactor intentional wrap-around calculation
Quoted 8 lines · Linus Torvalds
First off, none of this has anything to do with -fno-strict-overflow. We do that, because without it gcc ends up doing various odd and surprising things, the same way it does with strict-aliasing.
IOW, you should think of -fno-strict-overflow as a hardening thing. Any optimization that depends on "this can overflow, so I can do anything I want" is just a dangerous optimization for the kernel.
Quoted 6 lines
It matches -fno-strict-aliasing and -fno-delete-null-pointer-checks, in other words.
And I do not understand why you mention it in the first place, since this code USES UNSIGNED INTEGER ARITHMETIC, and thus has absolutely nothing to do with that no-strict-overflow flag.
I've tried to find the right balance between not enough details and too much. I guess I got it wrong. I go into more detail in the cover letter:
https://lore.kernel.org/linux-hardening/[email protected]/
Basically, this isn't about -fno-strict-overflow -- that's just a wrinkle on the compiler side. I completely agree: we have to keep the "undefined behavior" junk as far away from the kernel as possible.
This is about disambiguating the intent of C arithmetic so we can be in the position to instrument the kernel to catch unexpected wrap-arounds. We can't use C++ tricks with operator overloading and the introduction of wrapping vs trapping types, so we have to annotate things directly.
And we have sanitizers for signed, unsigned, and pointers. Hence, the need to adjust these open-coded wrap tests. It's not about removing UB:
-fno-strict-overflow already does that. This is about let us trap unexpected wrap-around, regardless of type.
Quoted 1 line
Stop making the world a worse place.
Rude. I'll leave that to ice storms.
Signature · 1 line
Kees Cook
Re: [PATCH 34/82] ipc: Refactor intentional wrap-around calculation
Quoted 3 lines · Kees Cook
I've tried to find the right balance between not enough details and too much. I guess I got it wrong.
My complaint isn't about the level of detail.
My complaint is about how the commit log IS ACTIVELY MISLEADING GARBAGE and does not match the actual patch in any way, shape, or form.
It talks about completely irrelevant issues that simply have nothing to do with it.
It talks about undefined behavior and about a "unsigned wrap-around sanitizer[2]", which is nonsensical, since there is no undefined behavior to sanitize. It literally gives a link to a github "issue" for that claim, but when you follow the link, it's actually about *signed* overflow, which is something entirely different.
And honestly, the patch itself is garbage. The code is fine. Any "sanitizer" that complains about that code is pure and utter shite.
Really.
If you actually have some real "detect unsigned wraparound" tool (NOTE: that is *NOT* undefined behavior, and that is *NOT* a "sanitizer", it's at most some helpful checker), then such a tool had better recognize the perfectly fine traditional idiom for this, which is to do the addition and check that the result is smaller. Like the code does.
See what I'm saying? The patch is garbage. Any sanitizer that would complain about the old code is garbage. And the commit message is worse than garbage, it is actively misleading to the point that I'd call it lying, trying to confuse the issues by bringing up things that are utterly and entirely irrelevant to the patch.
So:
- get rid of that commit message that is lying garbage
- fix the so-called "sanitizer".
- stop calling the unsigned wrap-around a "sanitizer" and talking
about "undefined behavior" in the same sentence, since it's neither.
Do you really not see why I think that thing is actively *WRONG*?
Linus
Re: [PATCH 34/82] ipc: Refactor intentional wrap-around calculation
Quoted 10 lines · Linus Torvalds
So:
- get rid of that commit message that is lying garbage
- fix the so-called "sanitizer".
- stop calling the unsigned wrap-around a "sanitizer" and talking
about "undefined behavior" in the same sentence, since it's neither.Do you really not see why I think that thing is actively *WRONG*?
Yes -- I was trying to head off the confusion about what the larger goal is (trapping unexpected wrap-around) so that people don't assume I'm talking about Undefined Behavior (we don't have any UB arithmetic in the kernel, very intentionally). I did not succeed! I'll rewrite it all.
Signature · 1 line
Kees Cook
PATCH 35/82 ACPI: custom_method: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/acpi/custom_method.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/custom_method.c +1 -1
@@ -54,7 +54,7 @@ static ssize_t cm_write(struct file *file, const char __user *user_buf,if ((*ppos > max_size) || (*ppos + count > max_size) || - (*ppos + count < count) || + (add_would_overflow (count, *ppos)) || (count > uncopied_bytes)) {kfree (buf); buf =NULL ;
Signature · 1 line
2.34.1
Rafael J. Wysocki
maintainerRe: [PATCH 35/82] ACPI: custom_method: Refactor intentional wrap-around test
Quoted 26 lines · Kees Cook
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.Cc "Rafael J. Wysocki" <[email protected]>Cc Len Brown <[email protected]>Signed-off-by Kees Cook <[email protected]>
Quoted 2 lines
--- drivers/acpi/custom_method.c | 2 +-
I may attempt to drop custom_method.c in this cycle, is there a problem if I take this into my tree for now?
Quoted 18 lines
1 file changed, 1 insertion(+), 1 deletion(-)drivers/acpi/custom_method.c +1
-2@@ -54,7 +54,7 @@ static ssize_t cm_write(struct file *file, const char __user *user_buf,if ((*ppos > max_size) || (*ppos + count > max_size) || - (*ppos + count < count) || + (add_would_overflow (count, *ppos)) || (count > uncopied_bytes)) {kfree (buf); buf =NULL ; --2.34.1
Re: [PATCH 35/82] ACPI: custom_method: Refactor intentional wrap-around test
Quoted 30 lines · Rafael J. Wysocki
Quoted 26 lines · Kees Cook
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.Cc "Rafael J. Wysocki" <[email protected]>Cc Len Brown <[email protected]>Signed-off-by Kees Cook <[email protected]>Quoted 2 lines
--- drivers/acpi/custom_method.c | 2 +-
Quoted 2 lines
I may attempt to drop
custom_method.cin this cycle, is there a problem if I take this into my tree for now?
The helper doesn't exist in tree yet, but it may be a bit before these refactors land, so if custom_method vanishes before then, that's great! :)
-Kees
Signature · 1 line
Kees Cook
PATCH 36/82 agp: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/char/agp/generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/char/agp/generic.c +1 -1
@@ -228,7 +228,7 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, cur_memory =atomic_read (&bridge->current_memory_agp);if ((cur_memory + page_count > bridge->max_memory_agp) || - (cur_memory + page_count < page_count)) + (add_would_overflow (page_count, cur_memory)))return NULL ;if (type >=AGP_USER_TYPES ) {
Signature · 1 line
2.34.1
PATCH 37/82 aio: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- fs/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/aio.c +1 -1
@@ -796,7 +796,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)/* limit the number of system wide aios */ spin_lock (&aio_nr_lock);if (aio_nr + ctx->max_reqs > aio_max_nr || - aio_nr + ctx->max_reqs < aio_nr) { +add_would_overflow (aio_nr, ctx->max_reqs)) {spin_unlock (&aio_nr_lock); err = -EAGAIN ; goto err_ctx;
Signature · 1 line
2.34.1
Christian Brauner
maintainerRe: [PATCH 37/82] aio: Refactor intentional wrap-around test
Quoted 28 lines · Kees Cook
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.Cc Benjamin LaHaise <[email protected]>Cc Alexander Viro <[email protected]>Cc Christian Brauner <[email protected]>Cc Jan Kara <[email protected]>Signed-off-by Kees Cook <[email protected]>
Quoted 1 line
---
What's the plan?
Merge the generic infrastructure and we can pick the individual patches?
Re: [PATCH 37/82] aio: Refactor intentional wrap-around test
In reply to Kees CookQuoted 17 lines · Kees Cook
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.
Quoted 11 lines
Cc Benjamin LaHaise <[email protected]>Cc Alexander Viro <[email protected]>Cc Christian Brauner <[email protected]>Cc Jan Kara <[email protected]>Signed-off-by Kees Cook <[email protected]>
Looks good. Feel free to add:
Honza
Quoted 20 lines
--- fs/aio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)fs/aio.c +1
-1@@ -796,7 +796,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)/* limit the number of system wide aios */ spin_lock (&aio_nr_lock);if (aio_nr + ctx->max_reqs > aio_max_nr || - aio_nr + ctx->max_reqs < aio_nr) { +add_would_overflow (aio_nr, ctx->max_reqs)) {spin_unlock (&aio_nr_lock); err = -EAGAIN ; goto err_ctx;Signature · 1 line
2.34.1
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
PATCH 38/82 arm: 3117/1: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- arch/arm/nwfpe/softfloat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/nwfpe/softfloat.c +1 -1
@@ -603,7 +603,7 @@ static floatx80 roundBits = zSig0 & roundMask;if (0x7FFD <= (bits32) ( zExp -1 ) ) {if ( (0x7FFE < zExp ) - || ( ( zExp ==0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) ) + || ( ( zExp ==0x7FFE ) && (add_would_overflow (zSig0, roundIncrement)) ) ) { goto overflow; }
Signature · 1 line
2.34.1
Mark Rutland
reviewerRe: [PATCH 38/82] arm: 3117/1: Refactor intentional wrap-around test
The commit title is odd here; '3117/1' is the patch tracker name for the last patch. The title should probably be:
arm: nwfpe: Refactor intentional wrap-around test
Mark.
Quoted 45 lines · Kees Cook
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.Cc Russell King <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/arm/nwfpe/softfloat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/arm/nwfpe/softfloat.c +1
-1@@ -603,7 +603,7 @@ static floatx80 roundBits = zSig0 & roundMask;if (0x7FFD <= (bits32) ( zExp -1 ) ) {if ( (0x7FFE < zExp ) - || ( ( zExp ==0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) ) + || ( ( zExp ==0x7FFE ) && (add_would_overflow (zSig0, roundIncrement)) ) ) { goto overflow; }Signature · 1 line
2.34.1
Re: [PATCH 38/82] arm: 3117/1: Refactor intentional wrap-around test
Quoted 4 lines · Mark Rutland
The commit title is odd here; '3117/1' is the patch tracker name for the last patch. The title should probably be:
arm: nwfpe: Refactor intentional wrap-around test
Whoops, yes. I need to teach my prefix-guessing script to drop the ARM patch tracker numbers...
-Kees
Quoted 49 lines
Mark.
Quoted 45 lines · Kees Cook
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.Cc Russell King <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/arm/nwfpe/softfloat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/arm/nwfpe/softfloat.c +1
-1@@ -603,7 +603,7 @@ static floatx80 roundBits = zSig0 & roundMask;if (0x7FFD <= (bits32) ( zExp -1 ) ) {if ( (0x7FFE < zExp ) - || ( ( zExp ==0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) ) + || ( ( zExp ==0x7FFE ) && (add_would_overflow (zSig0, roundIncrement)) ) ) { goto overflow; }Signature · 1 line
2.34.1
Signature · 1 line
Kees Cook
PATCH 39/82 crypto: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/crypto/axis/artpec6_crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/crypto/axis/artpec6_crypto.c +1 -1
@@ -1190,7 +1190,7 @@ artpec6_crypto_ctr_crypt(struct skcipher_request *req, bool encrypt)* the whole IV is a counter. So fallback if the counter is going to * overlow. */ -if (counter + nblks < counter) { +if (add_would_overflow (counter, nblks)) {int ret; pr_debug("counter %x will overflow (nblks %u), falling back\n",
Signature · 1 line
2.34.1
PATCH 40/82 arm64: stacktrace: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- arch/arm64/include/asm/stacktrace/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/include/asm/stacktrace/common.h +1 -1
@@ -49,7 +49,7 @@ static inline bool stackinfo_on_stack(const struct stack_info *info,if (!info->low)return false; -if (sp < info->low || sp + size < sp || sp + size > info->high) +if (sp < info->low ||add_would_overflow (sp, size) || sp + size > info->high)return false;return true;
Signature · 1 line
2.34.1
Re: [PATCH 40/82] arm64: stacktrace: Refactor intentional wrap-around test
Quoted 40 lines · Kees Cook
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.Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Kalesh Singh <[email protected]>Cc Fuad Tabba <[email protected]>Cc Mark Brown <[email protected]>Cc "Madhavan T. Venkataraman" <[email protected]>Cc Marc Zyngier <[email protected]>Cc Mark Rutland <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/arm64/include/asm/stacktrace/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/arm64/include/asm/stacktrace/common.h +0
-0
arch/arm64/include/asm/stacktrace/common.h static inline bool stackinfo_on_stack(const struct stack_info *info, · line 53
Quoted 6 lines
arch/arm64/include/asm/stacktrace/common.h +1
-1@@ -49,7 +49,7 @@ static inline bool stackinfo_on_stack(const struct stack_info *info,if (!info->low)return false; -if (sp < info->low || sp + size < sp || sp + size > info->high) +if (sp < info->low ||add_would_overflow (sp, size) || sp + size > info->high)return false;
This looks fine to me, so FWIW:
Mark.
Quoted 5 lines
arch/arm64/include/asm/stacktrace/common.h +0
-0return true;Signature · 1 line
2.34.1
PATCH 41/82 wil6210: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/net/wireless/ath/wil6210/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/ath/wil6210/wmi.c +1 -1
@@ -286,7 +286,7 @@ void __iomem *wmi_buffer_block(struct wil6210_priv *wil, __le32 ptr_, u32 size) off =HOSTADDR (ptr);if (off > wil->bar_size -4 )return NULL ; -if (size && ((off + size > wil->bar_size) || (off + size < off))) +if (size && ((off + size > wil->bar_size) || (add_would_overflow (off, size))))return NULL ;return wil->csr + off;
Signature · 1 line
2.34.1
Re: [PATCH 41/82] wil6210: Refactor intentional wrap-around test
Quoted 17 lines · Kees Cook
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.
Quoted 10 lines
Cc Kalle Valo <[email protected]>Cc Johannes Berg <[email protected]>Cc Max Chen <[email protected]>Cc Yang Shen <[email protected]>Signed-off-by Kees Cook <[email protected]>
I assume this goes via some other tree than wireless-next so:
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/list/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Re: [PATCH 41/82] wil6210: Refactor intentional wrap-around test
In reply to Kees CookQuoted 17 lines · Kees Cook
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.
Quoted 11 lines
Cc Kalle Valo <[email protected]>Cc Johannes Berg <[email protected]>Cc Max Chen <[email protected]>Cc Yang Shen <[email protected]>Signed-off-by Kees Cook <[email protected]>Acked-by Kalle Valo <[email protected]>
If you can edit before commit please add "wifi:" prefix to the wireless patches:
ERROR: 'wifi:' prefix missing: '[PATCH 41/82] wil6210: Refactor intentional wrap-around test'
ERROR: 'wifi:' prefix missing: '[PATCH 62/82] mwifiex: pcie: Refactor intentional wrap-around test'
2 patches set to Not Applicable.
13526631 [41/82] wil6210: Refactor intentional wrap-around test 13526632 [62/82] mwifiex: pcie: Refactor intentional wrap-around test
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Re: [PATCH 41/82] wil6210: Refactor intentional wrap-around test
Quoted 31 lines · Kalle Valo
Quoted 17 lines · Kees Cook
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.Quoted 11 lines
Cc Kalle Valo <[email protected]>Cc Johannes Berg <[email protected]>Cc Max Chen <[email protected]>Cc Yang Shen <[email protected]>Signed-off-by Kees Cook <[email protected]>Acked-by Kalle Valo <[email protected]>
Quoted 4 lines
If you can edit before commit please add "wifi:" prefix to the wireless patches:
ERROR: 'wifi:' prefix missing: '[PATCH 41/82] wil6210: Refactor intentional wrap-around test'
ERROR: 'wifi:' prefix missing: '[PATCH 62/82] mwifiex: pcie: Refactor intentional wrap-around test'
Ah yes, thank you! I will adjust them.
-Kees
Quoted 11 lines
2 patches set to Not Applicable.
13526631 [41/82] wil6210: Refactor intentional wrap-around test 13526632 [62/82] mwifiex: pcie: Refactor intentional wrap-around test
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/patch/[email protected]/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Signature · 1 line
Kees Cook
PATCH 42/82 bcachefs: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- 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(-)
fs/bcachefs/bkey.c +2 -2
@@ -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);
fs/bcachefs/fs.c +1 -1
@@ -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 ;
fs/bcachefs/quota.c +1 -1
@@ -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;
fs/bcachefs/util.c +1 -1
@@ -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;
Signature · 1 line
2.34.1
Re: [PATCH 42/82] bcachefs: Refactor intentional wrap-around test
Quoted 17 lines · Kees Cook
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.
Quoted 8 lines
Cc Kent Overstreet <[email protected]>Cc Brian Foster <[email protected]>Signed-off-by Kees Cook <[email protected]>
PATCH 43/82 bpf: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- kernel/bpf/verifier.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
kernel/bpf/verifier.c +6 -6
@@ -12901,8 +12901,8 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, dst_reg->smin_value = smin_ptr + smin_val; dst_reg->smax_value = smax_ptr + smax_val; } -if (umin_ptr + umin_val < umin_ptr || - umax_ptr + umax_val < umax_ptr) { +if (add_would_overflow (umin_ptr, umin_val) || +add_would_overflow (umax_ptr, umax_val)) { dst_reg->umin_value =0 ; dst_reg->umax_value =U64_MAX ; }else {
@@ -13023,8 +13023,8 @@ static void scalar32_min_max_add(struct bpf_reg_state *dst_reg, dst_reg->s32_min_value += smin_val; dst_reg->s32_max_value += smax_val; } -if (dst_reg->u32_min_value + umin_val < umin_val || - dst_reg->u32_max_value + umax_val < umax_val) { +if (add_would_overflow (umin_val, dst_reg->u32_min_value) || +add_would_overflow (umax_val, dst_reg->u32_max_value)) { dst_reg->u32_min_value =0 ; dst_reg->u32_max_value =U32_MAX ; }else {
@@ -13049,8 +13049,8 @@ static void scalar_min_max_add(struct bpf_reg_state *dst_reg, dst_reg->smin_value += smin_val; dst_reg->smax_value += smax_val; } -if (dst_reg->umin_value + umin_val < umin_val || - dst_reg->umax_value + umax_val < umax_val) { +if (add_would_overflow (umin_val, dst_reg->umin_value) || +add_would_overflow (umax_val, dst_reg->umax_value)) { dst_reg->umin_value =0 ; dst_reg->umax_value =U64_MAX ; }else {
Signature · 1 line
2.34.1
Yonghong Song
reviewerRe: [PATCH 43/82] bpf: Refactor intentional wrap-around test
Quoted 43 lines · Kees Cook
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.Cc Alexei Starovoitov <[email protected]>Cc Daniel Borkmann <[email protected]>Cc John Fastabend <[email protected]>Cc Andrii Nakryiko <[email protected]>Cc Martin KaFai Lau <[email protected]>Cc Song Liu <[email protected]>Cc Yonghong Song <[email protected]>Cc KP Singh <[email protected]>Cc Stanislav Fomichev <[email protected]>Cc Hao Luo <[email protected]>Cc Jiri Olsa <[email protected]>Signed-off-by Kees Cook <[email protected]>--- kernel/bpf/verifier.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)kernel/bpf/verifier.c +0
-0
kernel/bpf/verifier.c static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · line 12905
Quoted 7 lines
kernel/bpf/verifier.c +2
-2@@ -12901,8 +12901,8 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, dst_reg->smin_value = smin_ptr + smin_val; dst_reg->smax_value = smax_ptr + smax_val; } -if (umin_ptr + umin_val < umin_ptr || - umax_ptr + umax_val < umax_ptr) { +if (add_would_overflow (umin_ptr, umin_val) || +add_would_overflow (umax_ptr, umax_val)) {
Maybe you could give a reference to the definition of add_would_overflow()? A link or a patch with add_would_overflow() defined cc'ed to bpf program. The patch itselfs looks good to me.
Quoted 25 lines
kernel/bpf/verifier.c +4
-4dst_reg->umin_value =0 ; dst_reg->umax_value =U64_MAX ; }else {@@ -13023,8 +13023,8 @@ static void scalar32_min_max_add(struct bpf_reg_state *dst_reg, dst_reg->s32_min_value += smin_val; dst_reg->s32_max_value += smax_val; } -if (dst_reg->u32_min_value + umin_val < umin_val || - dst_reg->u32_max_value + umax_val < umax_val) { +if (add_would_overflow (umin_val, dst_reg->u32_min_value) || +add_would_overflow (umax_val, dst_reg->u32_max_value)) { dst_reg->u32_min_value =0 ; dst_reg->u32_max_value =U32_MAX ; }else {@@ -13049,8 +13049,8 @@ static void scalar_min_max_add(struct bpf_reg_state *dst_reg, dst_reg->smin_value += smin_val; dst_reg->smax_value += smax_val; } -if (dst_reg->umin_value + umin_val < umin_val || - dst_reg->umax_value + umax_val < umax_val) { +if (add_would_overflow (umin_val, dst_reg->umin_value) || +add_would_overflow (umax_val, dst_reg->umax_value)) { dst_reg->umin_value =0 ; dst_reg->umax_value =U64_MAX ; }else {
Kees Cook
maintainerRe: [PATCH 43/82] bpf: Refactor intentional wrap-around test
Quoted 40 lines · Yonghong Song
Quoted 38 lines · Kees Cook
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.Cc Alexei Starovoitov <[email protected]>Cc Daniel Borkmann <[email protected]>Cc John Fastabend <[email protected]>Cc Andrii Nakryiko <[email protected]>Cc Martin KaFai Lau <[email protected]>Cc Song Liu <[email protected]>Cc Yonghong Song <[email protected]>Cc KP Singh <[email protected]>Cc Stanislav Fomichev <[email protected]>Cc Hao Luo <[email protected]>Cc Jiri Olsa <[email protected]>Signed-off-by Kees Cook <[email protected]>--- kernel/bpf/verifier.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
Quoted 15 lines
kernel/bpf/verifier.c static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · line 12905
Quoted 12 lines
kernel/bpf/verifier.c +2
-2@@ -12901,8 +12901,8 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, dst_reg->smin_value = smin_ptr + smin_val; dst_reg->smax_value = smax_ptr + smax_val; } -if (umin_ptr + umin_val < umin_ptr || - umax_ptr + umax_val < umax_ptr) { +if (add_would_overflow (umin_ptr, umin_val) || +add_would_overflow (umax_ptr, umax_val)) {Maybe you could give a reference to the definition of
add_would_overflow()? A link or a patch withadd_would_overflow()defined cc'ed to bpf program.
Sure! It was earlier in the series:
https://lore.kernel.org/linux-hardening/[email protected]/
The cover letter also has more details:
https://lore.kernel.org/linux-hardening/[email protected]/
Quoted 1 line
The patch itselfs looks good to me.
Thanks!
-Kees
Signature · 1 line
Kees Cook
Re: [PATCH 43/82] bpf: Refactor intentional wrap-around test
Quoted 55 lines · Kees Cook
Quoted 39 lines · Yonghong Song
Quoted 38 lines · Kees Cook
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.Cc Alexei Starovoitov <[email protected]>Cc Daniel Borkmann <[email protected]>Cc John Fastabend <[email protected]>Cc Andrii Nakryiko <[email protected]>Cc Martin KaFai Lau <[email protected]>Cc Song Liu <[email protected]>Cc Yonghong Song <[email protected]>Cc KP Singh <[email protected]>Cc Stanislav Fomichev <[email protected]>Cc Hao Luo <[email protected]>Cc Jiri Olsa <[email protected]>Signed-off-by Kees Cook <[email protected]>--- kernel/bpf/verifier.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)Quoted 14 lines
kernel/bpf/verifier.c static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, · line 12905
Quoted 12 lines
kernel/bpf/verifier.c +2
-2@@ -12901,8 +12901,8 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, dst_reg->smin_value = smin_ptr + smin_val; dst_reg->smax_value = smax_ptr + smax_val; } -if (umin_ptr + umin_val < umin_ptr || - umax_ptr + umax_val < umax_ptr) { +if (add_would_overflow (umin_ptr, umin_val) || +add_would_overflow (umax_ptr, umax_val)) {Maybe you could give a reference to the definition of
add_would_overflow()? A link or a patch withadd_would_overflow()defined cc'ed to bpf program.
Quoted 5 lines
Sure! It was earlier in the series:
https://lore.kernel.org/linux-hardening/[email protected]/The cover letter also has more details:
https://lore.kernel.org/linux-hardening/[email protected]/
Thanks for the pointer.
Quoted 6 lines
Quoted 2 lines
The patch itselfs looks good to me.
Thanks!
-Kees
PATCH 44/82 btrfs: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- fs/btrfs/ordered-data.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/ordered-data.c +1 -1
@@ -813,7 +813,7 @@ int btrfs_wait_ordered_range(struct inode *inode, u64 start, u64 len)u64 orig_end;struct btrfs_ordered_extent *ordered; -if (start + len < start) { +if (add_would_overflow (start, len)) { orig_end =OFFSET_MAX ; }else { orig_end = start + len -1 ;
Signature · 1 line
2.34.1
Re: [PATCH 44/82] btrfs: Refactor intentional wrap-around test
Quoted 17 lines · Kees Cook
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.
Quoted 9 lines
Cc Chris Mason <[email protected]>Cc Josef Bacik <[email protected]>Cc David Sterba <[email protected]>Signed-off-by Kees Cook <[email protected]>
PATCH 45/82 cifs: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- fs/smb/client/smb2pdu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/smb/client/smb2pdu.c +2 -2
@@ -5007,7 +5007,7 @@ num_entries(int infotype, char *bufstart, char *end_of_buf, char **lastentry, entryptr = bufstart;while (1 ) { -if (entryptr + next_offset < entryptr || +if (add_would_overflow (entryptr, next_offset) || entryptr + next_offset > end_of_buf || entryptr + next_offset + size > end_of_buf) {cifs_dbg (VFS ,"malformed search entry would overflow\n" );
@@ -5023,7 +5023,7 @@ num_entries(int infotype, char *bufstart, char *end_of_buf, char **lastentry, len =le32_to_cpu (dir_info->FileNameLength);if (len <0 || - entryptr + len < entryptr || +add_would_overflow (entryptr, len) || entryptr + len > end_of_buf || entryptr + len + size > end_of_buf) { cifs_dbg(VFS, "directory entry name would overflow frame end of buf %p\n",
Signature · 1 line
2.34.1
PATCH 46/82 crypto: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- crypto/adiantum.c | 2 +- drivers/crypto/amcc/crypto4xx_alg.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
crypto/adiantum.c +1 -1
@@ -190,7 +190,7 @@ static inline void le128_add(le128 *r, const le128 *v1, const le128 *v2) r->b =cpu_to_le64 (x + y); r->a =cpu_to_le64 (le64_to_cpu (v1->a) +le64_to_cpu (v2->a) + - (x + y < x)); + (add_would_overflow (x, y))); }/* Subtraction in Z/(2^{128}Z) */
drivers/crypto/amcc/crypto4xx_alg.c +1 -1
@@ -251,7 +251,7 @@ crypto4xx_ctr_crypt(struct skcipher_request *req, bool encrypt)* the whole IV is a counter. So fallback if the counter is going to * overlow. */ -if (counter + nblks < counter) { +if (add_would_overflow (counter, nblks)) {SYNC_SKCIPHER_REQUEST_ON_STACK (subreq, ctx->sw_cipher.cipher);int ret;
Signature · 1 line
2.34.1
Re: [PATCH 46/82] crypto: Refactor intentional wrap-around test
Quoted 50 lines · Kees Cook
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.Cc Herbert Xu <[email protected]>Cc "David S. Miller" <[email protected]>Cc Aditya Srivastava <[email protected]>Cc Randy Dunlap <[email protected]>Signed-off-by Kees Cook <[email protected]>--- crypto/adiantum.c | 2 +- drivers/crypto/amcc/crypto4xx_alg.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)crypto/adiantum.c +1
-1@@ -190,7 +190,7 @@ static inline void le128_add(le128 *r, const le128 *v1, const le128 *v2) r->b =cpu_to_le64 (x + y); r->a =cpu_to_le64 (le64_to_cpu (v1->a) +le64_to_cpu (v2->a) + - (x + y < x)); + (add_would_overflow (x, y))); }/* Subtraction in Z/(2^{128}Z) */ drivers/crypto/amcc/crypto4xx_alg.c +0
-0
drivers/crypto/amcc/crypto4xx_alg.c crypto4xx_ctr_crypt(struct skcipher_request *req, bool encrypt) · line 256
Quoted 7 lines
drivers/crypto/amcc/crypto4xx_alg.c +1
-1@@ -251,7 +251,7 @@ crypto4xx_ctr_crypt(struct skcipher_request *req, bool encrypt)* the whole IV is a counter. So fallback if the counter is going to * overlow. */ -if (counter + nblks < counter) { +if (add_would_overflow (counter, nblks)) {SYNC_SKCIPHER_REQUEST_ON_STACK (subreq, ctx->sw_cipher.cipher);int ret;
Just to double check, you really intend to forbid *unsigned* integer wraparound? This patch's commit message focuses on signed, and barely mentions unsigned. The actual code changes in this patch only deals with unsigned.
Also, what's the motivation for addressing the 'x + y < x' case but not other cases in the same file? For example, the le128_add() function which this patch modifies has two other intentional wraparounds, which this patch doesn't touch. Also, the le128_sub() function just below le128_add() is very similar but does wraparound in the other direction. That's 6 cases in 20 lines of code, but this patch only addresses 1. And of course, lots of other crypto code relies on unsigned wraparounds too, which this patch overlooks. So I'm a bit confused about the point of this patch. If we really wanted to explicitly annotate all the intentional wraparounds in a particular piece of code, so that the code can be run with the corresponding sanitizer enabled, wouldn't it be necessary to actually test the code with that sanitizer enabled to find all the cases?
- Eric
Kees Cook
maintainerRe: [PATCH 46/82] crypto: Refactor intentional wrap-around test
Quoted 3 lines · Eric Biggers
Just to double check, you really intend to forbid *unsigned* integer wraparound? This patch's commit message focuses on signed, and barely mentions unsigned. The actual code changes in this patch only deals with unsigned.
I don't mean to forbid wrap-around; we just need to annotate it. I can see how this commit log didn't do a great job explaining this. I hope the cover letter is more sensible:
https://lore.kernel.org/linux-hardening/[email protected]/
Quoted 2 lines
Also, what's the motivation for addressing the 'x + y < x' case but not other cases in the same file?
It's a code pattern we could find easily. It's working from the instances found via Coccinelle earlier in the series:
https://lore.kernel.org/linux-hardening/[email protected]/
Quoted 2 lines
For example, the
le128_add()function which this patch
modifies has two other intentional wraparounds, which this patch doesn't touch.
For dedicated wrapping functions we can mark them with __unsigned_wrap:
https://lore.kernel.org/linux-hardening/[email protected]/
Quoted 4 lines
Also, the
le128_sub()function just belowle128_add()is very similar but does wraparound in the other direction. That's 6 cases in 20 lines of code, but this patch only addresses 1. And of course, lots of other crypto code relies on unsigned wraparounds too, which this patch overlooks.
Right -- finding these kinds of things is where a lot of time will be spent in the future, I suspect. :)
Quoted 5 lines
So I'm a bit confused
about the point of this patch. If we really wanted to explicitly annotate all the intentional wraparounds in a particular piece of code, so that the code can be run with the corresponding sanitizer enabled, wouldn't it be necessary to actually test the code with that sanitizer enabled to find all the cases?
Yes, but there's a lot of code to test -- I'm trying to get the first steps done. And then once the sanitizers are in good shape, the fuzzers can grind. (I'm trying to add some parallelism to this project; this code pattern was known so I figured we could address it now.)
-Kees
Signature · 1 line
Kees Cook
PATCH 47/82 dm verity: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/md/dm-switch.c | 2 +- drivers/md/dm-verity-target.c | 2 +- drivers/md/dm-writecache.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
drivers/md/dm-switch.c +1 -1
@@ -410,7 +410,7 @@ static int process_set_region_mappings(struct switch_ctx *sctx, cycle_length - 1, region_index);return -EINVAL ; } -if (unlikely (region_index + num_write < region_index) || +if (unlikely (add_would_overflow (region_index, num_write)) ||unlikely (region_index + num_write >= sctx->nr_regions)) {DMWARN ("invalid set_region_mappings region number: %lu + %lu >= %lu" , region_index, num_write, sctx->nr_regions);
drivers/md/dm-verity-target.c +1 -1
@@ -1392,7 +1392,7 @@ static int verity_ctr(struct dm_target *ti, unsigned int argc, char **argv) v->hash_level_block[i] = hash_position; s = (v->data_blocks + ((sector_t )1 << ((i +1 ) * v->hash_per_block_bits)) -1 ) >> ((i +1 ) * v->hash_per_block_bits); -if (hash_position + s < hash_position) { +if (add_would_overflow (hash_position, s)) { ti->error ="Hash device offset overflow" ; r = -E2BIG ; goto bad;
drivers/md/dm-writecache.c +1 -1
@@ -2631,7 +2631,7 @@ static int writecache_ctr(struct dm_target *ti, unsigned int argc, char **argv) offset = (offset + wc->block_size -1 ) & ~(size_t )(wc->block_size -1 ); data_size = wc->n_blocks * (size_t )wc->block_size;if (!offset || (data_size / wc->block_size != wc->n_blocks) || - (offset + data_size < offset)) + (add_would_overflow (offset, data_size))) goto overflow;if (offset + data_size > wc->memory_map_size) { ti->error ="Memory area is too small" ;
Signature · 1 line
2.34.1
Re: [PATCH 47/82] dm verity: Refactor intentional wrap-around test
Quoted 17 lines · Kees Cook
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.
Quoted 9 lines
Cc Alasdair Kergon <[email protected]>Cc Mike Snitzer <[email protected]>Cc Mikulas Patocka <[email protected]>Signed-off-by Kees Cook <[email protected]>
Please change subject to:
"dm: Refactor intentional wrap-around test in a few targets"
PATCH 48/82 drm/nouveau/mmu: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c +1 -1
@@ -1291,7 +1291,7 @@ nvkm_vmm_pfn_map(struct nvkm_vmm *vmm, u8 shift, u64 addr, u64 size, u64 *pfn)if (!page->shift || !IS_ALIGNED (addr,1ULL << shift) || !IS_ALIGNED (size,1ULL << shift) || - addr + size < addr || addr + size > vmm->limit) { +add_would_overflow (addr, size) || addr + size > vmm->limit) {VMM_DEBUG (vmm,"paged map %d %d %016llx %016llx\n" , shift, page->shift, addr, size);return -EINVAL ;
Signature · 1 line
2.34.1
PATCH 49/82 drm/i915: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/gpu/drm/i915/i915_vma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_vma.c +1 -1
@@ -1535,7 +1535,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, goto err_remove;/* There should only be at most 2 active bindings (user, global) */ -GEM_BUG_ON (bound +I915_VMA_PAGES_ACTIVE < bound); +GEM_BUG_ON (add_would_overflow (bound,I915_VMA_PAGES_ACTIVE ));atomic_add (I915_VMA_PAGES_ACTIVE , &vma->pages_count);list_move_tail (&vma->vm_link, &vma->vm->bound_list);
Signature · 1 line
2.34.1
PATCH 50/82 drm/vc4: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/gpu/drm/vc4/vc4_validate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/vc4/vc4_validate.c +1 -1
@@ -206,7 +206,7 @@ vc4_check_tex_size(struct vc4_exec_info *exec, struct drm_gem_dma_object *fbo, stride = aligned_width * cpp; size = stride * aligned_height; -if (size + offset < size || +if (add_would_overflow (size, offset) || size + offset > fbo->base.size) { DRM_DEBUG("Overflow in %dx%d (%dx%d) fbo size (%d + %d > %zd)\n", width, height,
Signature · 1 line
2.34.1
PATCH 51/82 ext4: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- fs/ext4/block_validity.c | 2 +- fs/ext4/resize.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
fs/ext4/block_validity.c +1 -1
@@ -302,7 +302,7 @@ int ext4_sb_block_valid(struct super_block *sb, struct inode *inode,int ret =1 ;if ((start_blk <=le32_to_cpu (sbi->s_es->s_first_data_block)) || - (start_blk + count < start_blk) || + (add_would_overflow (start_blk, count)) || (start_blk + count >ext4_blocks_count (sbi->s_es)))return 0 ;
fs/ext4/resize.c +1 -1
@@ -1871,7 +1871,7 @@ int ext4_group_extend(struct super_block *sb, struct ext4_super_block *es, add =EXT4_BLOCKS_PER_GROUP (sb) - last; -if (o_blocks_count + add < o_blocks_count) { +if (add_would_overflow (o_blocks_count, add)) {ext4_warning (sb,"blocks_count overflow" );return -EINVAL ; }
Signature · 1 line
2.34.1
PATCH 52/82 f2fs: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- fs/f2fs/file.c | 2 +- fs/f2fs/verity.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
fs/f2fs/file.c +1 -1
@@ -2819,7 +2819,7 @@ static int f2fs_move_file_range(struct file *file_in, loff_t pos_in, } ret = -EINVAL ; -if (pos_in + len > src->i_size || pos_in + len < pos_in) +if (pos_in + len > src->i_size ||add_would_overflow (pos_in, len)) goto out_unlock;if (len ==0 ) olen = len = src->i_size - pos_in;
fs/f2fs/verity.c +1 -1
@@ -237,7 +237,7 @@ static int f2fs_get_verity_descriptor(struct inode *inode, void *buf, pos =le64_to_cpu (dloc.pos);/* Get the descriptor */ -if (pos + size < pos || pos + size > inode->i_sb->s_maxbytes || +if (add_would_overflow (pos, size) || pos + size > inode->i_sb->s_maxbytes || pos <f2fs_verity_metadata_pos (inode) || size >INT_MAX ) {f2fs_warn (F2FS_I_SB (inode),"invalid verity xattr" ); f2fs_handle_error(F2FS_I_SB(inode),
Signature · 1 line
2.34.1
PATCH 53/82 fs: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- fs/remap_range.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/remap_range.c +1 -1
@@ -45,7 +45,7 @@ static int generic_remap_checks(struct file *file_in, loff_t pos_in,return -EINVAL ;/* Ensure offsets don't wrap. */ -if (pos_in + count < pos_in || pos_out + count < pos_out) +if (add_would_overflow (pos_in, count) ||add_would_overflow (pos_out, count))return -EINVAL ; size_in =i_size_read (inode_in);
Signature · 1 line
2.34.1
Re: [PATCH 53/82] fs: Refactor intentional wrap-around test
Quoted 17 lines · Kees Cook
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.
Quoted 9 lines
Cc Alexander Viro <[email protected]>Cc Christian Brauner <[email protected]>Cc Jan Kara <[email protected]>Signed-off-by Kees Cook <[email protected]>
Looks good atlhough I'd prefer wrapping the line to not overflow 80 chars. Anyway feel free to add:
Honza
Quoted 20 lines
--- fs/remap_range.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)fs/remap_range.c +1
-1@@ -45,7 +45,7 @@ static int generic_remap_checks(struct file *file_in, loff_t pos_in,return -EINVAL ;/* Ensure offsets don't wrap. */ -if (pos_in + count < pos_in || pos_out + count < pos_out) +if (add_would_overflow (pos_in, count) ||add_would_overflow (pos_out, count))return -EINVAL ; size_in =i_size_read (inode_in);Signature · 1 line
2.34.1
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
PATCH 54/82 hpfs: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- fs/hpfs/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/hpfs/alloc.c +1 -1
@@ -99,7 +99,7 @@ static int chk_if_allocated(struct super_block *s, secno sec, char *msg)int hpfs_chk_sectors (struct super_block *s,secno start,int len,char *msg) { -if (start + len < start || start <0x12 || +if (add_would_overflow (start, len) || start <0x12 || start + len >hpfs_sb (s)->sb_fs_size) {hpfs_error (s,"sector(s) '%s' badly placed at %08x" , msg, start);return 1 ;
Signature · 1 line
2.34.1
PATCH 55/82 kasan: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- mm/kasan/generic.c | 2 +- mm/kasan/sw_tags.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
mm/kasan/generic.c +1 -1
@@ -171,7 +171,7 @@ static __always_inline bool check_region_inline(const void *addr,if (unlikely (size ==0 ))return true; -if (unlikely (addr + size < addr)) +if (unlikely (add_would_overflow (addr, size)))return !kasan_report (addr, size, write, ret_ip);if (unlikely (!addr_has_metadata (addr)))
mm/kasan/sw_tags.c +1 -1
@@ -80,7 +80,7 @@ bool kasan_check_range(const void *addr, size_t size, bool write,if (unlikely (size ==0 ))return true; -if (unlikely (addr + size < addr)) +if (unlikely (add_would_overflow (addr, size)))return !kasan_report (addr, size, write, ret_ip); tag =get_tag ((const void *)addr);
Signature · 1 line
2.34.1
Re: [PATCH 55/82] kasan: Refactor intentional wrap-around test
Quoted 63 lines · Kees Cook
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.Cc Andrey Ryabinin <[email protected]>Cc Alexander Potapenko <[email protected]>Cc Andrey Konovalov <[email protected]>Cc Dmitry Vyukov <[email protected]>Cc Vincenzo Frascino <[email protected]>Cc Andrew Morton <[email protected]>Signed-off-by Kees Cook <[email protected]>--- mm/kasan/generic.c | 2 +- mm/kasan/sw_tags.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)mm/kasan/generic.c +1
-1@@ -171,7 +171,7 @@ static __always_inline bool check_region_inline(const void *addr,if (unlikely (size ==0 ))return true; -if (unlikely (addr + size < addr)) +if (unlikely (add_would_overflow (addr, size)))return !kasan_report (addr, size, write, ret_ip);if (unlikely (!addr_has_metadata (addr)))mm/kasan/sw_tags.c +1
-2@@ -80,7 +80,7 @@ bool kasan_check_range(const void *addr, size_t size, bool write,if (unlikely (size ==0 ))return true; -if (unlikely (addr + size < addr)) +if (unlikely (add_would_overflow (addr, size)))return !kasan_report (addr, size, write, ret_ip); tag =get_tag ((const void *)addr); --
Quoted 2 lines
2.34.1
Thanks!
PATCH 56/82 usercopy: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- mm/usercopy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/usercopy.c +1 -1
@@ -151,7 +151,7 @@ static inline void check_bogus_address(const unsigned long ptr, unsigned long n, bool to_user) {/* Reject if object wraps past end of memory. */ -if (ptr + (n -1 ) < ptr) +if (add_would_overflow (ptr, (n -1 )))usercopy_abort ("wrapped address" ,NULL , to_user,0 , ptr + n);/* Reject if NULL or ZERO-allocation. */
Signature · 1 line
2.34.1
PATCH 57/82 KVM: arm64: vgic-v3: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kvm/vgic/vgic-mmio-v3.c +1 -1
@@ -863,7 +863,7 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index,int ret;/* cross the end of memory ? */ -if (base + size < base) +if (add_would_overflow (base, size))return -EINVAL ;if (list_empty (rd_regions)) {
Signature · 1 line
2.34.1
Re: [PATCH 57/82] KVM: arm64: vgic-v3: Refactor intentional wrap-around test
Quoted 42 lines · Kees Cook
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.Cc Marc Zyngier <[email protected]>Cc Oliver Upton <[email protected]>Cc James Morse <[email protected]>Cc Suzuki K Poulose <[email protected]>Cc Zenghui Yu <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Eric Auger <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/arm64/kvm/vgic/vgic-mmio-v3.c +0
-0
arch/arm64/kvm/vgic/vgic-mmio-v3.c static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index, · line 869
Quoted 8 lines
arch/arm64/kvm/vgic/vgic-mmio-v3.c +1
-1@@ -863,7 +863,7 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index,int ret;/* cross the end of memory ? */ -if (base + size < base) +if (add_would_overflow (base, size))return -EINVAL ;if (list_empty (rd_regions)) {
M.
Signature · 1 line
Without deviation from the norm, progress is not possible.
Re: [PATCH 57/82] KVM: arm64: vgic-v3: Refactor intentional wrap-around test
In reply to Kees CookQuoted 17 lines · Kees Cook
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.
Quoted 15 lines
Cc Marc Zyngier <[email protected]>Cc Oliver Upton <[email protected]>Cc James Morse <[email protected]>Cc Suzuki K Poulose <[email protected]>Cc Zenghui Yu <[email protected]>Cc Catalin Marinas <[email protected]>Cc Will Deacon <[email protected]>Cc Eric Auger <[email protected]>Signed-off-by Kees Cook <[email protected]>
Eric
Quoted 17 lines
--- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/arm64/kvm/vgic/vgic-mmio-v3.c +1
-1@@ -863,7 +863,7 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index,int ret;/* cross the end of memory ? */ -if (base + size < base) +if (add_would_overflow (base, size))return -EINVAL ;if (list_empty (rd_regions)) {
PATCH 58/82 s390/mm: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- arch/s390/mm/gmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/s390/mm/gmap.c +2 -2
@@ -411,7 +411,7 @@ int gmap_unmap_segment(struct gmap *gmap, unsigned long to, unsigned long len)BUG_ON (gmap_is_shadow (gmap));if ((to | len) & (PMD_SIZE -1 ))return -EINVAL ; -if (len ==0 || to + len < to) +if (len ==0 ||add_would_overflow (to, len))return -EINVAL ; flush =0 ;
@@ -443,7 +443,7 @@ int gmap_map_segment(struct gmap *gmap, unsigned long from,BUG_ON (gmap_is_shadow (gmap));if ((from | to | len) & (PMD_SIZE -1 ))return -EINVAL ; -if (len ==0 || from + len < from || to + len < to || +if (len ==0 ||add_would_overflow (from, len) ||add_would_overflow (to, len) || from + len -1 >TASK_SIZE_MAX || to + len -1 > gmap->asce_end)return -EINVAL ;
Signature · 1 line
2.34.1
PATCH 59/82 lib/scatterlist: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- lib/scatterlist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/scatterlist.c +1 -1
@@ -624,7 +624,7 @@ struct scatterlist *sgl_alloc_order(unsigned long long length, nalloc = nent;if (chainable) {/* Check for integer overflow */ -if (nalloc +1 < nalloc) +if (add_would_overflow (nalloc,1 ))return NULL ; nalloc++; }
Signature · 1 line
2.34.1
PATCH 60/82 powerpc: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- arch/powerpc/platforms/powernv/opal-prd.c | 2 +- arch/powerpc/xmon/xmon.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
arch/powerpc/platforms/powernv/opal-prd.c +1 -1
@@ -51,7 +51,7 @@ static bool opal_prd_range_is_valid(uint64_t addr, uint64_t size)struct device_node *parent, *node;bool found; -if (addr + size < addr) +if (add_would_overflow (addr, size))return false; parent =of_find_node_by_path ("/reserved-memory" );
arch/powerpc/xmon/xmon.c +1 -1
@@ -3252,7 +3252,7 @@ memzcan(void) }else if (!ok && ook)printf ("%.8lx\n" , a - mskip); ook = ok; -if (a + mskip < a) +if (add_would_overflow (a, mskip))break ; }if (ook)
Signature · 1 line
2.34.1
Re: [PATCH 60/82] powerpc: Refactor intentional wrap-around test
Quoted 33 lines · Kees Cook
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.Cc Michael Ellerman <[email protected]>Cc Nicholas Piggin <[email protected]>Cc Christophe Leroy <[email protected]>Cc "Aneesh Kumar K.V" <[email protected]>Cc "Naveen N. Rao" <[email protected]>Cc Mahesh Salgaonkar <[email protected]>Cc Vasant Hegde <[email protected]>Cc dingsenjie <[email protected]>Cc Aneesh Kumar K.V <[email protected]>Cc Naveen N. Rao <[email protected]>Signed-off-by Kees Cook <[email protected]>
Quoted 4 lines
--- arch/powerpc/platforms/powernv/opal-prd.c | 2 +- arch/powerpc/xmon/xmon.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
cheers
PATCH 61/82 scsi: mpt3sas: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/mpt3sas/mpt3sas_ctl.c +1 -1
@@ -2382,7 +2382,7 @@ _ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg) karg.bytes_to_read));/* Truncate data on requests that are too large */ -if ((diag_data + karg.bytes_to_read < diag_data) || +if ((add_would_overflow (diag_data, karg.bytes_to_read)) || (diag_data + karg.bytes_to_read > request_data + request_size)) copy_size = request_size - karg.starting_offset;else
Signature · 1 line
2.34.1
PATCH 62/82 mwifiex: pcie: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/net/wireless/marvell/mwifiex/pcie.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/wireless/marvell/mwifiex/pcie.c +3 -3
@@ -2086,7 +2086,7 @@ static int mwifiex_extract_wifi_fw(struct mwifiex_adapter *adapter,switch (dnld_cmd) {case MWIFIEX_FW_DNLD_CMD_1 : -if (offset + data_len < data_len) { +if (add_would_overflow (data_len, offset)) {mwifiex_dbg (adapter,ERROR ,"bad FW parse\n" ); ret =-1 ; goto done;
@@ -2110,7 +2110,7 @@ static int mwifiex_extract_wifi_fw(struct mwifiex_adapter *adapter,case MWIFIEX_FW_DNLD_CMD_5 : first_cmd = true;/* Check for integer overflow */ -if (offset + data_len < data_len) { +if (add_would_overflow (data_len, offset)) {mwifiex_dbg (adapter,ERROR ,"bad FW parse\n" ); ret =-1 ; goto done;
@@ -2120,7 +2120,7 @@ static int mwifiex_extract_wifi_fw(struct mwifiex_adapter *adapter,case MWIFIEX_FW_DNLD_CMD_6 : first_cmd = true;/* Check for integer overflow */ -if (offset + data_len < data_len) { +if (add_would_overflow (data_len, offset)) {mwifiex_dbg (adapter,ERROR ,"bad FW parse\n" ); ret =-1 ; goto done;
Signature · 1 line
2.34.1
Re: [PATCH 62/82] mwifiex: pcie: Refactor intentional wrap-around test
Quoted 17 lines · Kees Cook
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.
Quoted 11 lines
Cc Brian Norris <[email protected]>Cc Kalle Valo <[email protected]>Cc "Jonas Dreßler" <[email protected]>Cc Dmitry Antipov <[email protected]>Cc Tsuchiya Yuto <[email protected]>Signed-off-by Kees Cook <[email protected]>
I assume this goes via some other tree than wireless-next so:
Signature · 3 lines
https://patchwork.kernel.org/project/linux-wireless/list/ https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
PATCH 63/82 mm: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- mm/memory.c | 4 ++-- mm/mmap.c | 2 +- mm/mremap.c | 2 +- mm/nommu.c | 4 ++-- mm/util.c | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-)
mm/memory.c +2 -2
@@ -2559,7 +2559,7 @@ int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned longunsigned long vm_len, pfn, pages;/* Check that the physical memory area passed in looks valid */ -if (start + len < start) +if (add_would_overflow (start, len))return -EINVAL ;/* * You *really* shouldn't map things that aren't page-aligned,
@@ -2569,7 +2569,7 @@ int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len += start & ~PAGE_MASK ; pfn = start >>PAGE_SHIFT ; pages = (len + ~PAGE_MASK ) >>PAGE_SHIFT ; -if (pfn + pages < pfn) +if (add_would_overflow (pfn, pages))return -EINVAL ;/* We start the mapping 'vm_pgoff' pages into the area */
mm/mmap.c +1 -1
@@ -3023,7 +3023,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,return ret;/* Does pgoff wrap? */ -if (pgoff + (size >>PAGE_SHIFT ) < pgoff) +if (add_would_overflow (pgoff, (size >>PAGE_SHIFT )))return ret;if (mmap_write_lock_killable (mm))
mm/mremap.c +1 -1
@@ -848,7 +848,7 @@ static struct vm_area_struct *vma_to_resize(unsigned long addr,/* Need to be careful about a growing mapping */ pgoff = (addr - vma->vm_start) >>PAGE_SHIFT ; pgoff += vma->vm_pgoff; -if (pgoff + (new_len >>PAGE_SHIFT ) < pgoff) +if (add_would_overflow (pgoff, (new_len >>PAGE_SHIFT )))return ERR_PTR (-EINVAL );if (vma->vm_flags & (VM_DONTEXPAND |VM_PFNMAP ))
mm/nommu.c +2 -2
@@ -202,7 +202,7 @@ EXPORT_SYMBOL(vmalloc_to_pfn);long vread_iter (struct iov_iter *iter,const char *addr,size_t count) {/* Don't allow overflow */ -if ((unsigned long ) addr + count < count) +if (add_would_overflow (count, (unsigned long )addr)) count = -(unsigned long ) addr;return copy_to_iter (addr, count, iter);
@@ -1705,7 +1705,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in {struct mm_struct *mm; -if (addr + len < addr) +if (add_would_overflow (addr, len))return 0 ; mm =get_task_mm (tsk);
mm/util.c +1 -1
@@ -567,7 +567,7 @@ unsigned long vm_mmap(struct file *file, unsigned long addr, unsigned long len, unsigned long prot, unsigned long flag, unsigned long offset) { - if (unlikely(offset + PAGE_ALIGN(len) < offset)) + if (unlikely(add_would_overflow(offset, PAGE_ALIGN(len)))) return -EINVAL;if (unlikely (offset_in_page (offset)))return -EINVAL ;
Signature · 1 line
2.34.1
PATCH 64/82 netfilter: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- net/netfilter/xt_u32.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/xt_u32.c +2 -2
@@ -58,11 +58,11 @@ static bool u32_match_it(const struct xt_u32 *data, val >>= number;break ;case XT_U32_AT : -if (at + val < at) +if (add_would_overflow (at, val))return false; at += val; pos = number; -if (at +4 < at || skb->len < at +4 || +if (add_would_overflow (at,4 ) || skb->len < at +4 || pos > skb->len - at -4 )return false;
Signature · 1 line
2.34.1
Re: [PATCH 64/82] netfilter: Refactor intentional wrap-around test
Quoted 5 lines · Kees Cook
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
PATCH 65/82 nios2: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- arch/nios2/kernel/sys_nios2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/nios2/kernel/sys_nios2.c +1 -1
@@ -32,7 +32,7 @@ asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len,return -EINVAL ;/* Check for overflow */ -if (addr + len < addr) +if (add_would_overflow (addr, len))return -EFAULT ;if (mmap_read_lock_killable (mm))
Signature · 1 line
2.34.1
Re: [PATCH 65/82] nios2: Refactor intentional wrap-around test
Quoted 25 lines · Kees Cook
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.Cc Dinh Nguyen <[email protected]>Cc Jann Horn <[email protected]>Cc Ley Foon Tan <[email protected]>Signed-off-by Kees Cook <[email protected]>
Quoted 4 lines
--- arch/nios2/kernel/sys_nios2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
PATCH 66/82 fs/ntfs3: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- fs/ntfs3/record.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/ntfs3/record.c +2 -2
@@ -235,7 +235,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr) }/* Overflow check. */ -if (off + asize < off) +if (add_would_overflow (off, asize))return NULL ; prev_type =le32_to_cpu (attr->type);
@@ -266,7 +266,7 @@ struct ATTRIB *mi_enum_attr(struct mft_inode *mi, struct ATTRIB *attr)return NULL ;/* Check overflow and boundary. */ -if (off + asize < off || off + asize > used) +if (add_would_overflow (off, asize) || off + asize > used)return NULL ;/* Check size of attribute. */
Signature · 1 line
2.34.1
PATCH 67/82 ocfs2: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- fs/ocfs2/resize.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ocfs2/resize.c +1 -1
@@ -423,7 +423,7 @@ static int ocfs2_verify_group_and_input(struct inode *inode,else if (next_free != cl_count && next_free != input->chain)mlog (ML_ERROR ,"the add group should be in chain %u\n" , next_free); -else if (total_clusters + input->clusters < total_clusters) +else if (add_would_overflow (total_clusters, input->clusters))mlog (ML_ERROR ,"add group's clusters overflow.\n" );else if (input->clusters > cl_cpg)mlog (ML_ERROR ,"the cluster exceeds the maximum of a group\n" );
Signature · 1 line
2.34.1
PATCH 68/82 PCI: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/pci/pci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/pci.c +1 -1
@@ -4251,7 +4251,7 @@ int pci_register_io_range(struct fwnode_handle *fwnode, phys_addr_t addr,#ifdef PCI_IOBASE struct logic_pio_hwaddr *range; -if (!size || addr + size < addr) +if (!size ||add_would_overflow (addr, size))return -EINVAL ; range =kzalloc (sizeof (*range),GFP_ATOMIC );
Signature · 1 line
2.34.1
PATCH 69/82 perf tools: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- tools/perf/util/dso.c | 2 +- tools/perf/util/unwind-libdw.c | 2 +- tools/perf/util/unwind-libunwind-local.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
tools/perf/util/dso.c +1 -1
@@ -1122,7 +1122,7 @@ static ssize_t data_read_write_offset(struct dso *dso, struct machine *machine,if (offset > dso->data.file_size)return -1 ; -if (offset + size < offset) +if (add_would_overflow (offset, size))return -1 ;return cached_io (dso, machine, offset, data, size, out);
tools/perf/util/unwind-libdw.c +1 -1
@@ -198,7 +198,7 @@ static bool memory_read(Dwfl *dwfl __maybe_unused, Dwarf_Addr addr, Dwarf_Word * end = start + stack->size;/* Check overflow. */ -if (addr +sizeof (Dwarf_Word) < addr) +if (add_would_overflow (addr,sizeof (Dwarf_Word)))return false;if (addr < start || addr +sizeof (Dwarf_Word) > end) {
tools/perf/util/unwind-libunwind-local.c +1 -1
@@ -587,7 +587,7 @@ static int access_mem(unw_addr_space_t __maybe_unused as, end = start + stack->size;/* Check overflow. */ -if (addr +sizeof (unw_word_t) < addr) +if (add_would_overflow (addr,sizeof (unw_word_t)))return -EINVAL ;if (addr < start || addr +sizeof (unw_word_t) >= end) {
Signature · 1 line
2.34.1
Adrian Hunter
reviewerRe: [PATCH 69/82] perf tools: Refactor intentional wrap-around test
Quoted 45 lines · Kees Cook
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.Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Cc Mark Rutland <[email protected]>Cc Alexander Shishkin <[email protected]>Cc Jiri Olsa <[email protected]>Cc Namhyung Kim <[email protected]>Cc Ian Rogers <[email protected]>Cc Adrian Hunter <[email protected]>Cc John Garry <[email protected]>Cc Fangrui Song <[email protected]>Signed-off-by Kees Cook <[email protected]>--- tools/perf/util/dso.c | 2 +- tools/perf/util/unwind-libdw.c | 2 +- tools/perf/util/unwind-libunwind-local.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)tools/perf/util/dso.c +0
-0
tools/perf/util/dso.c static ssize_t data_read_write_offset(struct dso *dso, struct machine *machine, · line 1125
Quoted 5 lines
tools/perf/util/dso.c +1
-1@@ -1122,7 +1122,7 @@ static ssize_t data_read_write_offset(struct dso *dso, struct machine *machine,if (offset > dso->data.file_size)return -1 ; -if (offset + size < offset) +if (add_would_overflow (offset, size))
perf tools has separate includes to the kernel, so does not seem to include add_would_overflow() in any of its include files at this point. Need to update tools/include/linux/overflow.h first.
Re: [PATCH 69/82] perf tools: Refactor intentional wrap-around test
Quoted 4 lines · Adrian Hunter
perf tools has separate includes to the kernel, so does not seem to include
add_would_overflow()in any of its include files at this point. Need to updatetools/include/linux/overflow.hfirst.
Oops, thank you! I will adjust this.
Signature · 1 line
Kees Cook
PATCH 70/82 remoteproc: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/remoteproc/pru_rproc.c | 2 +- drivers/remoteproc/remoteproc_elf_loader.c | 2 +- drivers/remoteproc/remoteproc_virtio.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-)
drivers/remoteproc/pru_rproc.c +1 -1
@@ -893,7 +893,7 @@ pru_rproc_find_interrupt_map(struct device *dev, const struct firmware *fw)continue ;/* make sure we have the entire irq map */ -if (offset + size > fw->size || offset + size < size) { +if (offset + size > fw->size ||add_would_overflow (size, offset)) {dev_err (dev,".pru_irq_map section truncated\n" );return ERR_PTR (-EINVAL ); }
drivers/remoteproc/remoteproc_elf_loader.c +1 -1
@@ -278,7 +278,7 @@ find_table(struct device *dev, const struct firmware *fw) table = (struct resource_table *)(elf_data + offset);/* make sure we have the entire table */ -if (offset + size > fw_size || offset + size < size) { +if (offset + size > fw_size ||add_would_overflow (size, offset)) {dev_err (dev,"resource table truncated\n" );return NULL ; }
drivers/remoteproc/remoteproc_virtio.c +2 -2
@@ -298,7 +298,7 @@ static void rproc_virtio_get(struct virtio_device *vdev, unsigned int offset, rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; cfg = &rsc->vring[rsc->num_of_vrings]; -if (offset + len > rsc->config_len || offset + len < len) { +if (offset + len > rsc->config_len ||add_would_overflow (len, offset)) {dev_err (&vdev->dev,"rproc_virtio_get: access out of bounds\n" );return ; }
@@ -316,7 +316,7 @@ static void rproc_virtio_set(struct virtio_device *vdev, unsigned int offset, rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; cfg = &rsc->vring[rsc->num_of_vrings]; -if (offset + len > rsc->config_len || offset + len < len) { +if (offset + len > rsc->config_len ||add_would_overflow (len, offset)) {dev_err (&vdev->dev,"rproc_virtio_set: access out of bounds\n" );return ; }
Signature · 1 line
2.34.1
Re: [PATCH 70/82] remoteproc: Refactor intentional wrap-around test
Quoted 14 lines · Kees Cook
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.
Quoted 8 lines
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.Cc Bjorn Andersson <[email protected]>
Regards,
Bjorn
Quoted 60 lines
Cc Mathieu Poirier <[email protected]>Signed-off-by Kees Cook <[email protected]>--- drivers/remoteproc/pru_rproc.c | 2 +- drivers/remoteproc/remoteproc_elf_loader.c | 2 +- drivers/remoteproc/remoteproc_virtio.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-)drivers/remoteproc/pru_rproc.c +1
-1@@ -893,7 +893,7 @@ pru_rproc_find_interrupt_map(struct device *dev, const struct firmware *fw)continue ;/* make sure we have the entire irq map */ -if (offset + size > fw->size || offset + size < size) { +if (offset + size > fw->size ||add_would_overflow (size, offset)) {dev_err (dev,".pru_irq_map section truncated\n" );return ERR_PTR (-EINVAL ); }drivers/remoteproc/remoteproc_elf_loader.c +1
-1@@ -278,7 +278,7 @@ find_table(struct device *dev, const struct firmware *fw) table = (struct resource_table *)(elf_data + offset);/* make sure we have the entire table */ -if (offset + size > fw_size || offset + size < size) { +if (offset + size > fw_size ||add_would_overflow (size, offset)) {dev_err (dev,"resource table truncated\n" );return NULL ; }drivers/remoteproc/remoteproc_virtio.c +2
-2@@ -298,7 +298,7 @@ static void rproc_virtio_get(struct virtio_device *vdev, unsigned int offset, rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; cfg = &rsc->vring[rsc->num_of_vrings]; -if (offset + len > rsc->config_len || offset + len < len) { +if (offset + len > rsc->config_len ||add_would_overflow (len, offset)) {dev_err (&vdev->dev,"rproc_virtio_get: access out of bounds\n" );return ; }@@ -316,7 +316,7 @@ static void rproc_virtio_set(struct virtio_device *vdev, unsigned int offset, rsc = (void *)rvdev->rproc->table_ptr + rvdev->rsc_offset; cfg = &rsc->vring[rsc->num_of_vrings]; -if (offset + len > rsc->config_len || offset + len < len) { +if (offset + len > rsc->config_len ||add_would_overflow (len, offset)) {dev_err (&vdev->dev,"rproc_virtio_set: access out of bounds\n" );return ; }Signature · 1 line
2.34.1
PATCH 71/82 s390/mm: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- arch/s390/mm/vmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/mm/vmem.c +1 -1
@@ -538,7 +538,7 @@ int vmem_add_mapping(unsigned long start, unsigned long size)if (start < range.start || start + size > range.end +1 || - start + size < start) +add_would_overflow (start, size))return -ERANGE ;mutex_lock (&vmem_mutex);
Signature · 1 line
2.34.1
PATCH 72/82 scsi: sd_zbc: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/scsi/sd_zbc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/sd_zbc.c +1 -1
@@ -295,7 +295,7 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector, (lba < start_lba || lba >= start_lba + zone_length)) || (zone_idx > 0 && start_lba != lba) || - start_lba + zone_length < start_lba) { + add_would_overflow(start_lba, zone_length)) {sd_printk (KERN_ERR , sdkp,"Zone %d at LBA %llu is invalid: %llu + %llu\n" , zone_idx, lba, start_lba, zone_length);
Signature · 1 line
2.34.1
PATCH 73/82 sh: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- arch/sh/kernel/sys_sh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/sh/kernel/sys_sh.c +1 -1
@@ -66,7 +66,7 @@ asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op)* Verify that the specified address region actually belongs * to this process. */ -if (addr + len < addr) +if (add_would_overflow (addr, len))return -EFAULT ;mmap_read_lock (current->mm);
Signature · 1 line
2.34.1
Re: [PATCH 73/82] sh: Refactor intentional wrap-around test
Hello Kees,
Quoted 35 lines · Kees Cook
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.Cc Yoshinori Sato <[email protected]>Cc Rich Felker <[email protected]>Cc John Paul Adrian Glaubitz <[email protected]>Signed-off-by Kees Cook <[email protected]>--- arch/sh/kernel/sys_sh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)arch/sh/kernel/sys_sh.c +0
-0
arch/sh/kernel/sys_sh.c asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op) · line 72
Quoted 8 lines
arch/sh/kernel/sys_sh.c +1
-1@@ -66,7 +66,7 @@ asmlinkage int sys_cacheflush(unsigned long addr, unsigned long len, int op)* Verify that the specified address region actually belongs * to this process. */ -if (addr + len < addr) +if (add_would_overflow (addr, len))return -EFAULT ;mmap_read_lock (current->mm);
Sounds like a very sensible change to me.
Adrian
Signature · 4 lines
.''`. John Paul Adrian Glaubitz : :' : Debian Developer `. `' Physicist `- GPG: 62FF 8A75 84E0 2956 9546 0006 7426 3B37 F5B5 F913
PATCH 74/82 ARC: dw2 unwind: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- arch/arc/kernel/unwind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arc/kernel/unwind.c +1 -1
@@ -1278,7 +1278,7 @@ int arc_unwind(struct unwind_frame_info *frame)if ((state.regs[i].value * state.dataAlign) %sizeof (unsigned long ) || addr < startLoc - || addr +sizeof (unsigned long ) < addr + ||add_would_overflow (addr,sizeof (unsigned long )) || addr +sizeof (unsigned long ) > endLoc)return -EIO ;
Signature · 1 line
2.34.1
PATCH 75/82 timekeeping: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- kernel/time/timekeeping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/timekeeping.c +1 -1
@@ -1984,7 +1984,7 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,* Which simplifies to: * xtime_nsec -= offset */ -if ((mult_adj >0 ) && (tk->tkr_mono.mult + mult_adj < mult_adj)) { +if ((mult_adj >0 ) && (add_would_overflow (mult_adj, tk->tkr_mono.mult))) {/* NTP adjustment caused clocksource mult overflow */ WARN_ON_ONCE (1 );return ;
Signature · 1 line
2.34.1
Re: [PATCH 75/82] timekeeping: Refactor intentional wrap-around test
Quoted 35 lines · Kees Cook
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.Cc John Stultz <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Stephen Boyd <[email protected]>Signed-off-by Kees Cook <[email protected]>--- kernel/time/timekeeping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)kernel/time/timekeeping.c +0
-0
kernel/time/timekeeping.c static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk, · line 1990
Quoted 8 lines
kernel/time/timekeeping.c +1
-1@@ -1984,7 +1984,7 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,* Which simplifies to: * xtime_nsec -= offset */ -if ((mult_adj >0 ) && (tk->tkr_mono.mult + mult_adj < mult_adj)) { +if ((mult_adj >0 ) && (add_would_overflow (mult_adj, tk->tkr_mono.mult))) {/* NTP adjustment caused clocksource mult overflow */ WARN_ON_ONCE (1 );return ;
Re: [PATCH 75/82] timekeeping: Refactor intentional wrap-around test
In reply to Kees CookQuoted 17 lines · Kees Cook
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.
Quoted 8 lines
Cc John Stultz <[email protected]>Cc Thomas Gleixner <[email protected]>Cc Stephen Boyd <[email protected]>Signed-off-by Kees Cook <[email protected]>
PATCH 76/82 udf: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- fs/udf/balloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/udf/balloc.c +2 -2
@@ -139,7 +139,7 @@ static void udf_bitmap_free_blocks(struct super_block *sb,mutex_lock (&sbi->s_alloc_mutex); partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; -if (bloc->logicalBlockNum + count < count || +if (add_would_overflow (count, bloc->logicalBlockNum) || (bloc->logicalBlockNum + count) > partmap->s_partition_len) { udf_debug("%u < %d || %u + %u > %u\n", bloc->logicalBlockNum, 0,
@@ -390,7 +390,7 @@ static void udf_table_free_blocks(struct super_block *sb,mutex_lock (&sbi->s_alloc_mutex); partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; -if (bloc->logicalBlockNum + count < count || +if (add_would_overflow (count, bloc->logicalBlockNum) || (bloc->logicalBlockNum + count) > partmap->s_partition_len) { udf_debug("%u < %d || %u + %u > %u\n", bloc->logicalBlockNum, 0,
Signature · 1 line
2.34.1
Re: [PATCH 76/82] udf: Refactor intentional wrap-around test
Quoted 17 lines · Kees Cook
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.
Quoted 6 lines
Cc Jan Kara <[email protected]>Signed-off-by Kees Cook <[email protected]>
Looks good. Feel free to add:
Honza
Quoted 29 lines
--- fs/udf/balloc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)fs/udf/balloc.c +2
-2@@ -139,7 +139,7 @@ static void udf_bitmap_free_blocks(struct super_block *sb,mutex_lock (&sbi->s_alloc_mutex); partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; -if (bloc->logicalBlockNum + count < count || +if (add_would_overflow (count, bloc->logicalBlockNum) || (bloc->logicalBlockNum + count) > partmap->s_partition_len) { udf_debug("%u < %d || %u + %u > %u\n", bloc->logicalBlockNum, 0,@@ -390,7 +390,7 @@ static void udf_table_free_blocks(struct super_block *sb,mutex_lock (&sbi->s_alloc_mutex); partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; -if (bloc->logicalBlockNum + count < count || +if (add_would_overflow (count, bloc->logicalBlockNum) || (bloc->logicalBlockNum + count) > partmap->s_partition_len) { udf_debug("%u < %d || %u + %u > %u\n", bloc->logicalBlockNum, 0,Signature · 1 line
2.34.1
Signature · 2 lines
Jan Kara <[email protected]> SUSE Labs, CR
PATCH 77/82 virtio: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/virtio/virtio_pci_modern_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/virtio/virtio_pci_modern_dev.c +2 -2
@@ -59,7 +59,7 @@ vp_modern_map_capability(struct virtio_pci_modern_device *mdev, int off, length -= start; -if (start + offset < offset) { +if (add_would_overflow (offset, start)) {dev_err (&dev->dev,"virtio_pci: map wrap-around %u+%u\n" , start, offset);
@@ -81,7 +81,7 @@ vp_modern_map_capability(struct virtio_pci_modern_device *mdev, int off,if (len) *len = length; -if (minlen + offset < minlen || +if (add_would_overflow (minlen, offset) || minlen + offset >pci_resource_len (dev, bar)) {dev_err (&dev->dev, "virtio_pci: map virtio %zu@%u "
Signature · 1 line
2.34.1
Re: [PATCH 77/82] virtio: Refactor intentional wrap-around test
Quoted 18 lines · Kees Cook
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.
Quoted 9 lines
Cc "Michael S. Tsirkin" <[email protected]>Cc Jason Wang <[email protected]>Cc Xuan Zhuo <[email protected]>Signed-off-by Kees Cook <[email protected]>
Quoted 30 lines
--- drivers/virtio/virtio_pci_modern_dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/virtio/virtio_pci_modern_dev.c +2
-3@@ -59,7 +59,7 @@ vp_modern_map_capability(struct virtio_pci_modern_device *mdev, int off, length -= start; -if (start + offset < offset) { +if (add_would_overflow (offset, start)) {dev_err (&dev->dev,"virtio_pci: map wrap-around %u+%u\n" , start, offset);@@ -81,7 +81,7 @@ vp_modern_map_capability(struct virtio_pci_modern_device *mdev, int off,if (len) *len = length; -if (minlen + offset < minlen || +if (add_would_overflow (minlen, offset) || minlen + offset >pci_resource_len (dev, bar)) {dev_err (&dev->dev, "virtio_pci: map virtio %zu@%u " --2.34.1
PATCH 78/82 mm/vmalloc: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- mm/vmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/vmalloc.c +1 -1
@@ -3750,7 +3750,7 @@ long vread_iter(struct iov_iter *iter, const char *addr, size_t count) addr =kasan_reset_tag (addr);/* Don't allow overflow */ -if ((unsigned long ) addr + count < count) +if (add_would_overflow (count, (unsigned long )addr)) count = -(unsigned long ) addr; remains = count;
Signature · 1 line
2.34.1
Re: [PATCH 78/82] mm/vmalloc: Refactor intentional wrap-around test
Quoted 45 lines · Kees Cook
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.Cc Andrew Morton <[email protected]>Cc Uladzislau Rezki <[email protected]>Cc Christoph Hellwig <[email protected]>Cc Lorenzo Stoakes <[email protected]>Signed-off-by Kees Cook <[email protected]>--- mm/vmalloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)mm/vmalloc.c +1
-2@@ -3750,7 +3750,7 @@ long vread_iter(struct iov_iter *iter, const char *addr, size_t count) addr =kasan_reset_tag (addr);/* Don't allow overflow */ -if ((unsigned long ) addr + count < count) +if (add_would_overflow (count, (unsigned long )addr)) count = -(unsigned long ) addr; remains = count; --
Quoted 2 lines
2.34.1
Looks good to me,
PATCH 79/82 staging: vme_user: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/staging/vme_user/vme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/vme_user/vme.c +1 -1
@@ -165,7 +165,7 @@ int vme_check_window(struct vme_bridge *bridge, u32 aspace, {int retval =0 ; -if (vme_base + size < size) +if (add_would_overflow (size, vme_base))return -EINVAL ;switch (aspace) {
Signature · 1 line
2.34.1
PATCH 80/82 xen-netback: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- drivers/net/xen-netback/hash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/xen-netback/hash.c +1 -1
@@ -345,7 +345,7 @@ u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len, .flags = GNTCOPY_source_gref }}; -if ((off + len < off) || (off + len > vif->hash.size) || +if ((add_would_overflow (off, len)) || (off + len > vif->hash.size) || len >XEN_PAGE_SIZE /sizeof (*mapping))return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER ;
Signature · 1 line
2.34.1
Re: [PATCH 80/82] xen-netback: Refactor intentional wrap-around test
drivers/net/xen-netback/hash.c u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len, · line 348
Quoted 8 lines · Kees Cook
drivers/net/xen-netback/hash.c +1
-1@@ -345,7 +345,7 @@ u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len, .flags = GNTCOPY_source_gref }}; - if ((off + len < off) || (off + len > vif->hash.size) || + if ((add_would_overflow(off, len)) || (off + len > vif->hash.size) ||
I'm not maintainer of this code, but if I was I would ask that the excess parentheses be removed, to improve readability.
Jan
Re: [PATCH 80/82] xen-netback: Refactor intentional wrap-around test
Quoted 7 lines · Jan Beulich
Quoted 6 lines · Kees Cook
drivers/net/xen-netback/hash.c +0
-0@@ -345,7 +345,7 @@ u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len, .flags = GNTCOPY_source_gref }};
Quoted 5 lines
drivers/net/xen-netback/hash.c u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len, · line 348
Quoted 2 lines
drivers/net/xen-netback/hash.c +1
-1- if ((off + len < off) || (off + len > vif->hash.size) || + if ((add_would_overflow(off, len)) || (off + len > vif->hash.size) ||I'm not maintainer of this code, but if I was I would ask that the excess parentheses be removed, to improve readability.
Good call. I will adjust that. Thanks!
-Kees
Signature · 1 line
Kees Cook
PATCH 81/82 lib: zstd: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
Switch to a more regular type for a 64-bit value and refactor the open-coded wrap-around addition test to use subtraction from the type max (since add_would_overflow() may not be defined in early boot code). This paves the way to enabling the wrap-around sanitizers in the future.
--- lib/zstd/decompress/zstd_decompress.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
lib/zstd/decompress/zstd_decompress.c +2 -2
@@ -585,7 +585,7 @@ ZSTDLIB_API size_t ZSTD_readSkippableFrame(void* dst, size_t dstCapacity, unsign* @return : decompressed size of the frames contained */ unsigned long long ZSTD_findDecompressedSize (const void * src,size_t srcSize) { -unsigned long long totalDstSize =0 ; +U64 totalDstSize =0 ;while (srcSize >=ZSTD_startingInputLength (ZSTD_f_zstd1)) {U32 const magicNumber =MEM_readLE32 (src);
@@ -606,7 +606,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize)if (ret >=ZSTD_CONTENTSIZE_ERROR )return ret;/* check for overflow */ -if (totalDstSize + ret < totalDstSize)return ZSTD_CONTENTSIZE_ERROR ; +if (U64_MAX - totalDstSize < ret)return ZSTD_CONTENTSIZE_ERROR ; totalDstSize += ret; } {size_t const frameSrcSize =ZSTD_findFrameCompressedSize (src, srcSize);
Signature · 1 line
2.34.1
PATCH 82/82 mqueue: Refactor intentional wrap-around test
In reply to Kees CookIn 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.
--- ipc/mqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
ipc/mqueue.c +1 -1
@@ -366,7 +366,7 @@ static struct inode *mqueue_get_inode(struct super_block *sb, min_t(unsigned int, info->attr.mq_maxmsg, MQ_PRIO_MAX) *sizeof (struct posix_msg_tree_node ); mq_bytes = info->attr.mq_maxmsg * info->attr.mq_msgsize; -if (mq_bytes + mq_treesize < mq_bytes) +if (add_would_overflow (mq_bytes, mq_treesize)) goto out_inode; mq_bytes += mq_treesize; info->ucounts =get_ucounts (current_ucounts ());
Signature · 1 line
2.34.1
Quoted 47 lines · Kees Cook
Hi,
In our continuing effort to eliminate root causes of flaws in the kernel, this series is the start to providing a way to have sensible coverage for catching unexpected arithmetic wrap-around.
A quick word on language: while discussing[1] the finer details of the C standard's view on arithmetic, I was disabused of using the term "overflow" when what I really mean is "wrap-around". When describing security vulnerabilities, "overflow" is the common term and often used interchangeably with "wrap-around". Strictly speaking, though, "overflow" applies only to signed[2] and pointer[3] types, and "wrap-around" is for unsigned[4]. An arithmetic "overflow" is considered undefined behavior, which has caused our builds pain in the past, since "impossible" conditions might get elided by the compiler. As a result, we build with -fno-strict-overflow which coverts all "overflow" conditions into "wrap-around" (i.e. 2s complement), regardless of type.
All this is to say I am discussing arithmetic wrap-around, which is the condition where the value exceeds a type's maximum value (or goes below its minimum value) and wraps around. I'm not interested in the narrow definition of "undefined behavior" -- we need to stamp out the _unexpected_ behavior, where the kernel operates on a pathological value that wrapped around without the code author's intent.
As always, this is about being able disambiguate the intent of arithmetic in the kernel. We intentionally use wrapping arithmetic in all kinds of places, but we need to be able to annotate it as such going forward so the compiler can distinguish when it needs to perform instrumentation (when such instrumentation is enabled).
Getting back to my earlier mention of -fno-strict-overflow, the bulk of the series is refactoring for a common code pattern in the kernel where to test for potentially overflowing addition, the addition is performed, and wrap-around is tested for. This is what originally[5] caused us to enable -fno-strict-overflow:
var + offset < var
For these cases we can use either
check_add_overflow()oradd_would_overflow(). These helpers will not trip the wrap-around instrumentation, and do not depend on the whims of the compiler options. (Note that I have no intention of removing -fno-strict-overflow any time soon, if ever. As with all these kinds of changes, we need to evolve our support for it, and we can't introduce undefined behavior into the kernel.)
Quoted 1 line
This series is mainly 3 parts:
This all seems fine, but... Rust already has this at the type system level....
I know you're not one of the people bringing bickering into the Rust threads, so I'm wondering if perhaps your secret plan is to annoy the die hard "I want everything to be fast with razor blades everywhere" C programmers enough to finally get onboard the "let's just switch to a language with less razor wire" train.
Kees Cook
maintainerQuoted 5 lines · Kent Overstreet
Quoted 4 lines · Kees Cook
In our continuing effort to eliminate root causes of flaws in the kernel, this series is the start to providing a way to have sensible coverage for catching unexpected arithmetic wrap-around.
Quoted 8 lines
This all seems fine, but... Rust already has this at the type system level....
I know you're not one of the people bringing bickering into the Rust threads, so I'm wondering if perhaps your secret plan is to annoy the die hard "I want everything to be fast with razor blades everywhere" C programmers enough to finally get onboard the "let's just switch to a language with less razor wire" train.
I don't want to annoy anyone, but yeah, in the process of getting rid of dangerous stuff we do end up asking people to make changes they're not used to. I hope to make it as easy as possible, though.
I'm a big fan of Rust, but I know it's not going to happen over night; there is a LOT of C code in Linux. :) I look at making the kernel safer by removing as many C foot-guns as possible. As we remove the ambiguities in C that lead to vulnerabilities, we'll eventually meet halfway with the new Rust code.
-Kees
Signature · 1 line
Kees Cook
Mark Rutland
reviewerQuoted 1 line · Kees Cook
Hi,
Hi Kees,
Quoted 16 lines
In our continuing effort to eliminate root causes of flaws in the kernel, this series is the start to providing a way to have sensible coverage for catching unexpected arithmetic wrap-around.
A quick word on language: while discussing[1] the finer details of the C standard's view on arithmetic, I was disabused of using the term "overflow" when what I really mean is "wrap-around". When describing security vulnerabilities, "overflow" is the common term and often used interchangeably with "wrap-around". Strictly speaking, though, "overflow" applies only to signed[2] and pointer[3] types, and "wrap-around" is for unsigned[4]. An arithmetic "overflow" is considered undefined behavior, which has caused our builds pain in the past, since "impossible" conditions might get elided by the compiler. As a result, we build with -fno-strict-overflow which coverts all "overflow" conditions into "wrap-around" (i.e. 2s complement), regardless of type.
Quoted 6 lines
All this is to say I am discussing arithmetic wrap-around, which is the condition where the value exceeds a type's maximum value (or goes below its minimum value) and wraps around. I'm not interested in the narrow definition of "undefined behavior" -- we need to stamp out the _unexpected_ behavior, where the kernel operates on a pathological value that wrapped around without the code author's intent.
With that in mind, I note that this patch primarily modifies addition operations, but leaves subtraction operations unchanged (even though those permit the value to go below the minimum, or above the maximum if a negative value is used as the subtrahend).
Shouldn't we address both at the same time? I'll note that in many places the same logic is used for both the add and sub, and can legitimately overflow or underflow; I hope that whatever we use to suppress overflow warnings also ignores underflow.
[...]
Looking at the diffstat, I think you've missed a few places:
Quoted 62 lines
Documentation/process/deprecated.rst | 36 ++++++++ arch/arc/kernel/unwind.c | 7 +- arch/arm/nwfpe/softfloat.c | 2 +- arch/arm64/include/asm/atomic_lse.h | 8 +- arch/arm64/include/asm/stacktrace/common.h | 2 +- arch/arm64/kvm/vgic/vgic-kvm-device.c | 6 +- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 2 +- arch/arm64/kvm/vgic/vgic-v2.c | 10 ++- arch/m68k/kernel/sys_m68k.c | 5 +- arch/nios2/kernel/sys_nios2.c | 2 +- arch/powerpc/platforms/powernv/opal-prd.c | 2 +- arch/powerpc/xmon/xmon.c | 2 +- arch/s390/include/asm/stacktrace.h | 6 +- arch/s390/kernel/machine_kexec_file.c | 5 +- arch/s390/mm/gmap.c | 4 +- arch/s390/mm/vmem.c | 2 +- arch/sh/kernel/sys_sh.c | 2 +- arch/x86/include/asm/atomic.h | 2 +- arch/x86/kernel/cpu/sgx/ioctl.c | 6 +- arch/x86/kvm/svm/sev.c | 5 +- crypto/adiantum.c | 2 +- drivers/acpi/custom_method.c | 2 +- drivers/char/agp/generic.c | 2 +- drivers/crypto/amcc/crypto4xx_alg.c | 2 +- drivers/crypto/axis/artpec6_crypto.c | 2 +- drivers/dma-buf/dma-buf.c | 7 +- drivers/fpga/dfl.c | 5 +- drivers/fsi/fsi-core.c | 6 +- drivers/gpu/drm/i915/i915_vma.c | 2 +- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 8 +- drivers/gpu/drm/vc4/vc4_validate.c | 7 +- drivers/md/dm-switch.c | 2 +- drivers/md/dm-verity-target.c | 2 +- drivers/md/dm-writecache.c | 2 +- drivers/net/ethernet/sun/niu.c | 5 +- drivers/net/wireless/ath/wil6210/wmi.c | 2 +- drivers/net/wireless/marvell/mwifiex/pcie.c | 6 +- drivers/net/xen-netback/hash.c | 2 +- drivers/pci/pci.c | 2 +- drivers/remoteproc/pru_rproc.c | 2 +- drivers/remoteproc/remoteproc_elf_loader.c | 2 +- drivers/remoteproc/remoteproc_virtio.c | 4 +- drivers/scsi/mpt3sas/mpt3sas_ctl.c | 2 +- drivers/scsi/sd_zbc.c | 2 +- drivers/staging/vme_user/vme.c | 2 +- drivers/vhost/vringh.c | 8 +- drivers/virtio/virtio_pci_modern_dev.c | 4 +- fs/aio.c | 2 +- fs/bcachefs/bkey.c | 4 +- fs/bcachefs/fs.c | 2 +- fs/bcachefs/quota.c | 2 +- fs/bcachefs/util.c | 2 +- fs/btrfs/extent_map.c | 6 +- fs/btrfs/extent_map.h | 6 +- fs/btrfs/ordered-data.c | 2 +- fs/ext4/block_validity.c | 2 +- fs/ext4/extents.c | 5 +- fs/ext4/resize.c | 2 +- fs/f2fs/file.c | 2 +- fs/f2fs/verity.c | 2 +- fs/hpfs/alloc.c | 2 +- fs/ntfs3/record.c | 4 +-
Quoted 8 lines
fs/ocfs2/resize.c | 2 +- fs/read_write.c | 8 +- fs/remap_range.c | 2 +- fs/select.c | 13 +-- fs/smb/client/readdir.c | 5 +- fs/smb/client/smb2pdu.c | 4 +- fs/udf/balloc.c | 4 +- include/linux/compiler_types.h | 29 +++++-
This misses the include/asm-generic/{atomic,atomic64}.h implementations.
This also misses the include/linux/atomic/atomic-arch-fallback.h implementations. Those are generated from the scripts/atomic/fallbacks/* templates, and you'll need to adjust at least fetch_add_unless and inc_unless_negative. As noted on other patches, my preference is to use add_wrap() in those.
Quoted 6 lines
include/linux/overflow.h | 76 +++++++++++++++- ipc/mqueue.c | 2 +- ipc/shm.c | 6 +- kernel/bpf/verifier.c | 12 +-- kernel/time/timekeeping.c | 2 +- lib/Kconfig.ubsan | 27 ++++++
This misses lib/atomic64.c.
Thanks,
Mark.
Quoted 4 lines · Mark Rutland
With that in mind, I note that this patch primarily modifies addition operations, but leaves subtraction operations unchanged (even though those permit the value to go below the minimum, or above the maximum if a negative value is used as the subtrahend).
Right, this was kind of a "first pass" on what I'd found so far.
Quoted 13 lines
Shouldn't we address both at the same time? I'll note that in many places the same logic is used for both the add and sub, and can legitimately overflow or underflow; I hope that whatever we use to suppress overflow warnings also ignores underflow.
[...]
Looking at the diffstat, I think you've missed a few places:
[...]
This misses the
include/asm-generic/{atomic,atomic64}.himplementations.
Quoted 7 lines
This also misses the
include/linux/atomic/atomic-arch-fallback.himplementations. Those are generated from thescripts/atomic/fallbacks/*templates, and you'll need to adjust at leastfetch_add_unlessandinc_unless_negative. As noted on other patches, my preference is to useadd_wrap()in those.
[...]
This misseslib/atomic64.c.
Thanks! I'll take a closer look at places we can use the helpers on the atomics.
-Kees
Signature · 1 line
Kees Cook
Quoted 5 lines · Mark Rutland
This also misses the
include/linux/atomic/atomic-arch-fallback.himplementations. Those are generated from thescripts/atomic/fallbacks/*templates, and you'll need to adjust at leastfetch_add_unlessandinc_unless_negative. As noted on other patches, my preference is to useadd_wrap()in those.
How do I regenerate the header files using the templates? I found a script, but its use eluded me, and it doesn't seem wired up to the top-level Makefile? Maybe I missed something obvious...
Signature · 1 line
Kees Cook