Skip to contentSkip to conversation

overflow: Refactor open-coded arithmetic wrap-around

PATCH NAK Kees Cook 38 participants 163 messages Jan 23, 2024 – Feb 12, 2024

Subsystems (78)
lore
Share & tools
lore

Kees Cook

author
#0 lore raw

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
author
#1 lore raw

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.

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]>
---
 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
index 6f1ca49306d2..d27b58fddfaa 100644
@@ -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
Reviewed-by on v1 1/82
#2 lore raw

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 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.

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]>
---
 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
index 6f1ca49306d2..d27b58fddfaa 100644

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
index 7b5cf4a5cd19..099f2e559aa8 100644
@@ -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
index c527f6b75789..2d106e880956 100644
@@ -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

author
#3 lore raw

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 checking

Does 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.

Thanks!

Signature · 1 line
Kees Cook
author
#4 lore raw

PATCH 2/82 overflow: Introduce add_would_overflow()

In reply to 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 for check_add_overflow().

Cc "Gustavo A. R. Silva" <[email protected]>
---
 include/linux/overflow.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
include/linux/overflow.h +16 -0
index 099f2e559aa8..ac088f73e0fd 100644
@@ -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
#5 lore raw

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 for check_add_overflow().

Cc "Gustavo A. R. Silva" <[email protected]>
---
 include/linux/overflow.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
include/linux/overflow.h +5 -0
index 099f2e559aa8..ac088f73e0fd 100644
@@ -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

author
#6 lore raw

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 for check_add_overflow().

Cc "Gustavo A. R. Silva" <[email protected]>
---
 include/linux/overflow.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
include/linux/overflow.h +11 -0
index 099f2e559aa8..ac088f73e0fd 100644
@@ -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 think size_t is 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
author
#7 lore raw

PATCH 3/82 overflow: Introduce add_wrap()

In reply to Kees Cook

Provide a helper that will perform wrapping addition without tripping the arithmetic wrap-around sanitizers.

Cc "Gustavo A. R. Silva" <[email protected]>
---
 include/linux/overflow.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
include/linux/overflow.h +16 -0
index ac088f73e0fd..30779905a77a 100644
@@ -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
#8 lore raw

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]>
---
 include/linux/overflow.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
include/linux/overflow.h +6 -0
index ac088f73e0fd..30779905a77a 100644
@@ -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

author
#9 lore raw

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]>
---
 include/linux/overflow.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
include/linux/overflow.h +13 -0
index ac088f73e0fd..30779905a77a 100644
@@ -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) and add_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
reviewer
#10 lore raw

Re: [PATCH 03/82] overflow: Introduce add_wrap()

In reply to Kees Cook
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]>
---
 include/linux/overflow.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
include/linux/overflow.h +5 -0
index ac088f73e0fd..30779905a77a 100644
@@ -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
author
#11 lore raw

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]>
---
 include/linux/overflow.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)
include/linux/overflow.h +5 -0
index ac088f73e0fd..30779905a77a 100644
@@ -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
author
#12 lore raw

PATCH 4/82 docs: deprecated.rst: deprecate open-coded arithmetic wrap-around

In reply to Kees Cook

In 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
index 1f7f3e6c9cda..270f3af13b86 100644
@@ -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
author
#13 lore raw

PATCH 5/82 cocci: Refactor open-coded arithmetic wrap-around

In reply to Kees Cook

In 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
new file mode 100644
index 000000000000..b9b67c9c3714
@@ -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
author
#14 lore raw

PATCH 6/82 overflow: Reintroduce signed and unsigned overflow sanitizers

In reply to Kees Cook

Effectively 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
index 270f3af13b86..aebd7c6cd2fc 100644
@@ -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
index d27b58fddfaa..d24f43fc79c6 100644
@@ -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
index 59e21bfec188..a7003e5bd2a1 100644
@@ -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
index 5d99ab81913b..0abbbac8700d 100644
@@ -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
index 4749865c1b2c..de4fc0ae448a 100644
@@ -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
#15 lore raw

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_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.

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

maintainer
#16 lore raw

Re: [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_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.

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 help and 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
#17 lore raw

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

author
#18 lore raw

PATCH 7/82 overflow: Introduce CONFIG_UBSAN_POINTER_WRAP

In reply to Kees Cook

Gain 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.

Cc Andrew Morton <[email protected]>
Cc Masahiro Yamada <[email protected]>
Cc Nathan Chancellor <[email protected]>
Cc Nicolas Schier <[email protected]>
---
 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
index aebd7c6cd2fc..15e77cbd4259 100644
@@ -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
index d24f43fc79c6..84cfd9d55453 100644
@@ -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
index a7003e5bd2a1..04222a6d7fd9 100644
@@ -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
index 84d8092d6c32..1cc049b3ef34 100644
@@ -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
index 5fc107f61934..d49580ff6aea 100644
@@ -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
index 0abbbac8700d..5dd27923b78b 100644
@@ -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
index de4fc0ae448a..37e8c31dc655 100644
@@ -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
author
#19 lore raw

PATCH 8/82 iov_iter: Avoid wrap-around instrumentation in copy_compat_iovec_from_user

In reply to Kees Cook

The 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
index e0aa6b440ca5..d797a43dca91 100644
@@ -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
author
#20 lore raw

PATCH 9/82 select: Avoid wrap-around instrumentation in do_sys_poll()

In reply to 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:

vmlinux.o: warning: objtool: do_sys_poll+0x285: call to __ubsan_handle_sub_overflow() with UACCESS enabled

Cc Alexander Viro <[email protected]>
Cc Christian Brauner <[email protected]>
Cc Jan Kara <[email protected]>
---
 fs/select.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
fs/select.c +7 -6
index 0ee55af1a55c..11a3b1312abe 100644
@@ -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
reviewer Reviewed-by on v1 9/82
#21 lore raw

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 enabled

Cc Alexander Viro <[email protected]>
Cc Christian Brauner <[email protected]>
Cc Jan Kara <[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
index 0ee55af1a55c..11a3b1312abe 100644
@@ -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
author
#22 lore raw

PATCH 10/82 locking/atomic/x86: Silence intentional wrapping addition

In reply to 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]>
---
 arch/x86/include/asm/atomic.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/include/asm/atomic.h +1 -1
index 55a55ec04350..4120cdd87da8 100644
@@ -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
reviewer
#23 lore raw

Re: [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]>
---
 arch/x86/include/asm/atomic.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/include/asm/atomic.h +0 -0
index 55a55ec04350..4120cdd87da8 100644

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
author
#24 lore raw

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]>
---
 arch/x86/include/asm/atomic.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/include/asm/atomic.h +0 -0
index 55a55ec04350..4120cdd87da8 100644

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:

Quoted 8 lines

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.

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
author
#25 lore raw

PATCH 11/82 arm64: atomics: lse: Silence intentional wrapping addition

In reply to Kees Cook

Annotate atomic_add_return() and atomic_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]>
---
 arch/arm64/include/asm/atomic_lse.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/include/asm/atomic_lse.h +4 -4
index 87f568a94e55..30572458d702 100644
@@ -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
reviewer
#26 lore raw

Re: [PATCH 11/82] arm64: atomics: lse: Silence intentional wrapping addition

Quoted 19 lines · Kees Cook

Annotate atomic_add_return() and atomic_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]>
---
 arch/arm64/include/asm/atomic_lse.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
arch/arm64/include/asm/atomic_lse.h +0 -0
index 87f568a94e55..30572458d702 100644

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
author
#27 lore raw

PATCH 12/82 ipv4: Silence intentional wrapping addition

In reply to Kees Cook

The 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

Cc Jakub Kicinski <[email protected]>
Cc "David S. Miller" <[email protected]>
Cc David Ahern <[email protected]>
Cc Eric Dumazet <[email protected]>
Cc Paolo Abeni <[email protected]>
---
 net/ipv4/route.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
net/ipv4/route.c +4 -4
index 16615d107cf0..c52e85b06fe7 100644
@@ -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
author
#28 lore raw

PATCH 13/82 btrfs: Refactor intentional wrap-around calculation

In reply to 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.

---
 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
index b61099bf97a8..29a649507857 100644
@@ -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
index e380fc08bbe4..3c4a6b977662 100644
@@ -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
Acked-by on v1 13/82
#29 lore raw

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
author
#30 lore raw

PATCH 14/82 smb: client: Refactor intentional wrap-around calculation

In reply to 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 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
index 94255401b38d..7715297359ab 100644
@@ -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
author
#31 lore raw

PATCH 15/82 dma-buf: Refactor intentional wrap-around calculation

In reply to 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.

---
 drivers/dma-buf/dma-buf.c | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/dma-buf/dma-buf.c +4 -3
index 8fe5aa67b167..3743c63a9b59 100644
@@ -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
author
#32 lore raw

PATCH 16/82 drm/nouveau/mmu: Refactor intentional wrap-around calculation

In reply to 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.

---
 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
index 9c97800fe037..6ca1a82ccbc1 100644
@@ -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
author
#33 lore raw

PATCH 17/82 drm/vc4: Refactor intentional wrap-around calculation

In reply to 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.

---
 drivers/gpu/drm/vc4/vc4_validate.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/gpu/drm/vc4/vc4_validate.c +3 -2
index 7dff3ca5af6b..9affba9c58b3 100644
@@ -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
author
#34 lore raw

PATCH 18/82 ext4: Refactor intentional wrap-around calculation

In reply to 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.

---
 fs/ext4/extents.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
fs/ext4/extents.c +3 -2
index 01299b55a567..aa30b2c75959 100644
@@ -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
author
#35 lore raw

PATCH 19/82 fs: Refactor intentional wrap-around calculation

In reply to 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.

---
 fs/read_write.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
fs/read_write.c +5 -3
index d4c036e82b6c..e24b94a8937d 100644
@@ -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
reviewer Reviewed-by on v1 19/82
#36 lore raw

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

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
index d4c036e82b6c..e24b94a8937d 100644
@@ -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
author
#37 lore raw

PATCH 20/82 fpga: dfl: Refactor intentional wrap-around calculation

In reply to 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.

---
 drivers/fpga/dfl.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/fpga/dfl.c +3 -2
index e6d12fbab653..7d10780e3a98 100644
@@ -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
author
#38 lore raw

PATCH 21/82 drivers/fsi: Refactor intentional wrap-around calculation

In reply to 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.

---
 drivers/fsi/fsi-core.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/fsi/fsi-core.c +4 -2
index 097d5a780264..46b24d0aadc6 100644
@@ -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
author
#39 lore raw

PATCH 22/82 x86/sgx: Refactor intentional wrap-around calculation

In reply to 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.

---
 arch/x86/kernel/cpu/sgx/ioctl.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/sgx/ioctl.c +4 -2
index b65ab214bdf5..4b8f6c9f8ef5 100644
@@ -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
maintainer Reviewed-by on v1 22/82
#40 lore raw

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.

---
 arch/x86/kernel/cpu/sgx/ioctl.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
arch/x86/kernel/cpu/sgx/ioctl.c +2 -0
index b65ab214bdf5..4b8f6c9f8ef5 100644
@@ -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

author
#41 lore raw

PATCH 23/82 KVM: Refactor intentional wrap-around calculation

In reply to 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.

---
 virt/kvm/coalesced_mmio.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
virt/kvm/coalesced_mmio.c +4 -2
index 1b90acb6e3fe..0a3b706fbf4c 100644
@@ -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
#42 lore raw

Re: [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.

---
 virt/kvm/coalesced_mmio.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
virt/kvm/coalesced_mmio.c +0 -0
index 1b90acb6e3fe..0a3b706fbf4c 100644

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
author
#43 lore raw

PATCH 24/82 KVM: arm64: vgic: Refactor intentional wrap-around calculation

In reply to 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.

---
 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
index f48b8dab8b3d..0eec5344d203 100644
@@ -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
index 7e9cdb78f7ce..c8d1e965d3b7 100644
@@ -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
maintainer Acked-by on v1 24/82
#44 lore raw

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.

---
 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
index f48b8dab8b3d..0eec5344d203 100644
@@ -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 -2
 	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))

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 -0
 		return -E2BIG;
 
 	return 0;
arch/arm64/kvm/vgic/vgic-v2.c +1 -1
index 7e9cdb78f7ce..c8d1e965d3b7 100644
@@ -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 -2
 		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;

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.
Reviewed-by
#45 lore raw

Re: [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.

---
 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
index f48b8dab8b3d..0eec5344d203 100644
@@ -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 -2
 	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))

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 -0
 		return -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 -0
 	return 0;
arch/arm64/kvm/vgic/vgic-v2.c +1 -1
index 7e9cdb78f7ce..c8d1e965d3b7 100644
@@ -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 -0
 	return false;

With these nits addressed, and assuming you intend to merge the whole series yourself:

assuming above suggested changes,

Eric

Quoted 3 lines
	M.
author
#46 lore raw

PATCH 25/82 KVM: SVM: Refactor intentional wrap-around calculation

In reply to 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.

---
 arch/x86/kvm/svm/sev.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/kvm/svm/sev.c +3 -2
index f760106c31f8..12a6a2b1ac81 100644
@@ -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
#47 lore raw

Re: [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
---
 arch/x86/kvm/svm/sev.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/x86/kvm/svm/sev.c +0 -0
index f760106c31f8..12a6a2b1ac81 100644

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 -2
 	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
author
#48 lore raw

PATCH 26/82 buildid: Refactor intentional wrap-around calculation

In reply to 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 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
index e3a7acdeef0e..d0a310cb9b57 100644
@@ -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
author
#49 lore raw

PATCH 27/82 m68k: Refactor intentional wrap-around calculation

In reply to 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.

---
 arch/m68k/kernel/sys_m68k.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/m68k/kernel/sys_m68k.c +3 -2
index 1af5e6082467..b2b9248f2566 100644
@@ -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
Reviewed-by on v1 27/82
#50 lore raw

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.

---
 arch/m68k/kernel/sys_m68k.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
arch/m68k/kernel/sys_m68k.c +0 -0
index 1af5e6082467..b2b9248f2566 100644

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
maintainer Reviewed-by Acked-by on v1 27/82
#51 lore raw

Re: [PATCH 27/82] m68k: Refactor intentional wrap-around calculation

In reply to Kees Cook

Hi 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

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 -0
                struct 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 -0
                        goto 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
#52 lore raw

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

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 -0
                 struct 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 -0
                         goto 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

#53 lore raw

Re: [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

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 -0
                 struct 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
author
#54 lore raw

PATCH 28/82 niu: Refactor intentional wrap-around calculation

In reply to 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.

---
 drivers/net/ethernet/sun/niu.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/ethernet/sun/niu.c +3 -2
index 21431f43e4c2..a4de07c6e618 100644
@@ -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
author
#55 lore raw

PATCH 29/82 rds: Refactor intentional wrap-around calculation

In reply to 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.

---
 net/rds/info.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
net/rds/info.c +4 -2
index b6b46a8214a0..87b35d07ce04 100644
@@ -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
author
#56 lore raw

PATCH 30/82 s390/kexec_file: Refactor intentional wrap-around calculation

In reply to 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.

---
 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
index 31ec4f545e03..3ce08d32a8ad 100644
@@ -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
index 8d207b82d9fe..e5e925423061 100644
@@ -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
#57 lore raw

Re: [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
index 31ec4f545e03..3ce08d32a8ad 100644

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 -1
 		return 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
index 8d207b82d9fe..e5e925423061 100644

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 -0
 	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;

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!

reviewer
#58 lore raw

Re: [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
index 8d207b82d9fe..e5e925423061 100644
@@ -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.

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.

author
#59 lore raw

PATCH 31/82 ARC: dw2 unwind: Refactor intentional wrap-around calculation

In reply to 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 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
index 9270d0a713c3..8924fa2a8f29 100644
@@ -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
author
#60 lore raw

PATCH 32/82 vringh: Refactor intentional wrap-around calculation

In reply to 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.

---
 drivers/vhost/vringh.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/vhost/vringh.c +5 -3
index 7b8fd977f71c..07442f0a52bd 100644
@@ -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
maintainer Acked-by on v1 32/82
#61 lore raw

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.

---
 drivers/vhost/vringh.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/vhost/vringh.c +0 -0
index 7b8fd977f71c..07442f0a52bd 100644

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

author
#62 lore raw

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.

---
 drivers/vhost/vringh.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/vhost/vringh.c +0 -0
index 7b8fd977f71c..07442f0a52bd 100644

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?

Quoted 2 lines

Either way,

Thanks! Yeah, you are not alone in suggesting "end" in a several of these patches. :)

-Kees

Signature · 1 line
Kees Cook
author
#63 lore raw

PATCH 33/82 mm/vmalloc: Refactor intentional wrap-around calculation

In reply to 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.

---
 mm/vmalloc.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
mm/vmalloc.c +3 -2
index d12a17fc0c17..7932ac99e9d3 100644
@@ -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
Reviewed-by on v1 33/82
#64 lore raw

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.

---
 mm/vmalloc.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
mm/vmalloc.c +3 -3
index d12a17fc0c17..7932ac99e9d3 100644
@@ -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,

maintainer
#65 lore raw

Re: [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.

---
 mm/vmalloc.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
mm/vmalloc.c +3 -2
index d12a17fc0c17..7932ac99e9d3 100644
@@ -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,

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

author
#66 lore raw

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.

---
 mm/vmalloc.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
mm/vmalloc.c +3 -3
index d12a17fc0c17..7932ac99e9d3 100644
@@ -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

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
maintainer
#67 lore raw

Re: [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.

---
 mm/vmalloc.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
mm/vmalloc.c +3 -3
index d12a17fc0c17..7932ac99e9d3 100644
@@ -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 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_end or nva_end_addr ?

nva_end_addr is probably the best fit.

--
Uladzislau Rezki

author
#68 lore raw

PATCH 34/82 ipc: Refactor intentional wrap-around calculation

In reply to 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.

---
 ipc/shm.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
ipc/shm.c +4 -2
index a89f001a8bf0..227a1610628a 100644
@@ -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
#69 lore raw

Re: [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

author
#70 lore raw

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
#71 lore raw

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

author
#72 lore raw

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
author
#73 lore raw

PATCH 35/82 ACPI: custom_method: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/acpi/custom_method.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/custom_method.c +1 -1
index d39a9b474727..0789317f4a1a 100644
@@ -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
#74 lore raw

Re: [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.

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
index d39a9b474727..0789317f4a1a 100644
@@ -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

author
#75 lore raw

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.

Quoted 2 lines
---
 drivers/acpi/custom_method.c | 2 +-
Quoted 2 lines

I may attempt to drop custom_method.c in 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
author
#76 lore raw

PATCH 36/82 agp: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/char/agp/generic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/char/agp/generic.c +1 -1
index 3ffbb1c80c5c..fc2d07654154 100644
@@ -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
author
#77 lore raw

PATCH 37/82 aio: Refactor intentional wrap-around test

In reply to 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.

---
 fs/aio.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/aio.c +1 -1
index bb2ff48991f3..edd19be3f4b1 100644
@@ -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
#78 lore raw

Re: [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.

Quoted 1 line

---

What's the plan?
Merge the generic infrastructure and we can pick the individual patches?

reviewer Reviewed-by on v1 37/82
#79 lore raw

Re: [PATCH 37/82] aio: Refactor intentional wrap-around test

In reply to Kees Cook
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

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
index bb2ff48991f3..edd19be3f4b1 100644
@@ -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
author
#80 lore raw

PATCH 38/82 arm: 3117/1: Refactor intentional wrap-around test

In reply to 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.

---
 arch/arm/nwfpe/softfloat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/nwfpe/softfloat.c +1 -1
index ffa6b438786b..0635b1eda1d3 100644
@@ -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
reviewer
#81 lore raw

Re: [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.

---
 arch/arm/nwfpe/softfloat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/nwfpe/softfloat.c +1 -1
index ffa6b438786b..0635b1eda1d3 100644
@@ -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
author
#82 lore raw

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.

---
 arch/arm/nwfpe/softfloat.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm/nwfpe/softfloat.c +1 -1
index ffa6b438786b..0635b1eda1d3 100644
@@ -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
author
#83 lore raw

PATCH 39/82 crypto: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/crypto/axis/artpec6_crypto.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/crypto/axis/artpec6_crypto.c +1 -1
index dbc1d483f2af..cbec539f0e20 100644
@@ -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
author
#84 lore raw

PATCH 40/82 arm64: stacktrace: Refactor intentional wrap-around test

In reply to 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.

---
 arch/arm64/include/asm/stacktrace/common.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/include/asm/stacktrace/common.h +1 -1
index f63dc654e545..6e0cb84961f8 100644
@@ -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
reviewer Acked-by on v1 40/82
#85 lore raw

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.

---
 arch/arm64/include/asm/stacktrace/common.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/include/asm/stacktrace/common.h +0 -0
index f63dc654e545..6e0cb84961f8 100644

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 -0
 	return true;
Signature · 1 line
2.34.1
author
#86 lore raw

PATCH 41/82 wil6210: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/net/wireless/ath/wil6210/wmi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/ath/wil6210/wmi.c +1 -1
index 6fdb77d4c59e..3b3c991f77e9 100644
@@ -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
Acked-by on v1 41/82
#87 lore raw

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

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
#88 lore raw

Re: [PATCH 41/82] wil6210: Refactor intentional wrap-around test

In reply to Kees Cook
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

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
author
#89 lore raw

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
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
author
#90 lore raw

PATCH 42/82 bcachefs: Refactor intentional wrap-around test

In reply to 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.

---
 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
index 76e79a15ba08..c68f1cfd579e 100644
@@ -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
index ec419b8e2c43..00a606171656 100644
@@ -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
index e68b34eab90a..1738b1fc1c75 100644
@@ -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
index a135136adeee..2200c81edbd2 100644
@@ -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
Acked-by on v1 42/82
#91 lore raw

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
author
#92 lore raw

PATCH 43/82 bpf: Refactor intentional wrap-around test

In reply to 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.

---
 kernel/bpf/verifier.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
kernel/bpf/verifier.c +6 -6
index 65f598694d55..21e3f30c8757 100644
@@ -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
reviewer
#93 lore raw

Re: [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.

---
  kernel/bpf/verifier.c | 12 ++++++------
  1 file changed, 6 insertions(+), 6 deletions(-)
kernel/bpf/verifier.c +0 -0
index 65f598694d55..21e3f30c8757 100644

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 -4
  			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 {
maintainer
#94 lore raw

Re: [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.

---
  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
index 65f598694d55..21e3f30c8757 100644
@@ -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.

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
reviewer Acked-by
#95 lore raw

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.

---
   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
index 65f598694d55..21e3f30c8757 100644
@@ -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.

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

author
#96 lore raw

PATCH 44/82 btrfs: Refactor intentional wrap-around test

In reply to 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.

---
 fs/btrfs/ordered-data.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/btrfs/ordered-data.c +1 -1
index 59850dc17b22..2e0865693cee 100644
@@ -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
Acked-by on v1 44/82
#97 lore raw

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
author
#98 lore raw

PATCH 45/82 cifs: Refactor intentional wrap-around test

In reply to 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.

---
 fs/smb/client/smb2pdu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/smb/client/smb2pdu.c +2 -2
index 288199f0b987..85399525f0a7 100644
@@ -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
author
#99 lore raw

PATCH 46/82 crypto: Refactor intentional wrap-around test

In reply to 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.

---
 crypto/adiantum.c                   | 2 +-
 drivers/crypto/amcc/crypto4xx_alg.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
crypto/adiantum.c +1 -1
index 60f3883b736a..c2f62ca455af 100644
@@ -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
index e0af611a95d8..33f73234ddd9 100644
@@ -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
#100 lore raw

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.

---
 crypto/adiantum.c                   | 2 +-
 drivers/crypto/amcc/crypto4xx_alg.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
crypto/adiantum.c +1 -1
index 60f3883b736a..c2f62ca455af 100644
@@ -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
index e0af611a95d8..33f73234ddd9 100644

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

maintainer
#101 lore raw

Re: [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 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.

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
author
#102 lore raw

PATCH 47/82 dm verity: Refactor intentional wrap-around test

In reply to 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.

---
 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
index dfd9fb52a6f3..9053d7e65603 100644
@@ -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
index 14e58ae70521..f2676c8c83c0 100644
@@ -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
index 074cb785eafc..45e54edd24aa 100644
@@ -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
maintainer Reviewed-by on v1 47/82
#103 lore raw

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

Please change subject to:
"dm: Refactor intentional wrap-around test in a few targets"

author
#104 lore raw

PATCH 48/82 drm/nouveau/mmu: Refactor intentional wrap-around test

In reply to 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.

---
 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
index 6ca1a82ccbc1..87c0903be9a7 100644
@@ -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
author
#105 lore raw

PATCH 49/82 drm/i915: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/gpu/drm/i915/i915_vma.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_vma.c +1 -1
index d09aad34ba37..1a4f048a5df9 100644
@@ -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
author
#106 lore raw

PATCH 50/82 drm/vc4: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/gpu/drm/vc4/vc4_validate.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/vc4/vc4_validate.c +1 -1
index 9affba9c58b3..677d9975f888 100644
@@ -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
author
#107 lore raw

PATCH 51/82 ext4: Refactor intentional wrap-around test

In reply to 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.

---
 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
index 6fe3c941b565..85f859979d2f 100644
@@ -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
index 4d4a5a32e310..fb8d3745d031 100644
@@ -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
author
#108 lore raw

PATCH 52/82 f2fs: Refactor intentional wrap-around test

In reply to 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.

---
 fs/f2fs/file.c   | 2 +-
 fs/f2fs/verity.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
fs/f2fs/file.c +1 -1
index b58ab1157b7e..6360efb98f64 100644
@@ -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
index 4fc95f353a7a..b641cb8d75e8 100644
@@ -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
author
#109 lore raw

PATCH 53/82 fs: Refactor intentional wrap-around test

In reply to 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.

---
 fs/remap_range.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/remap_range.c +1 -1
index f8c1120b8311..15e91bf2c5e3 100644
@@ -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
reviewer Reviewed-by on v1 53/82
#110 lore raw

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

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
index f8c1120b8311..15e91bf2c5e3 100644
@@ -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
author
#111 lore raw

PATCH 54/82 hpfs: Refactor intentional wrap-around test

In reply to 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.

---
 fs/hpfs/alloc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/hpfs/alloc.c +1 -1
index 66617b1557c6..e9c7cc6033b5 100644
@@ -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
author
#112 lore raw

PATCH 55/82 kasan: Refactor intentional wrap-around test

In reply to 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.

---
 mm/kasan/generic.c | 2 +-
 mm/kasan/sw_tags.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
mm/kasan/generic.c +1 -1
index df6627f62402..f9bc29ae09bd 100644
@@ -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
index 220b5d4c6876..79a3bbd66c32 100644
@@ -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
reviewer Acked-by on v1 55/82
#113 lore raw

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.

---
 mm/kasan/generic.c | 2 +-
 mm/kasan/sw_tags.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
mm/kasan/generic.c +1 -1
index df6627f62402..f9bc29ae09bd 100644
@@ -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
index 220b5d4c6876..79a3bbd66c32 100644
@@ -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!

author
#114 lore raw

PATCH 56/82 usercopy: Refactor intentional wrap-around test

In reply to 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.

---
 mm/usercopy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/usercopy.c +1 -1
index 83c164aba6e0..5141c4402903 100644
@@ -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
author
#115 lore raw

PATCH 57/82 KVM: arm64: vgic-v3: Refactor intentional wrap-around test

In reply to 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.

---
 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
index c15ee1df036a..860b774c0c13 100644
@@ -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
maintainer Acked-by on v1 57/82
#116 lore raw

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.

---
 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
index c15ee1df036a..860b774c0c13 100644

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.
Reviewed-by on v1 57/82
#117 lore raw

Re: [PATCH 57/82] KVM: arm64: vgic-v3: Refactor intentional wrap-around test

In reply to Kees Cook
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 15 lines

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
index c15ee1df036a..860b774c0c13 100644
@@ -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)) {
author
#118 lore raw

PATCH 58/82 s390/mm: Refactor intentional wrap-around test

In reply to 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.

---
 arch/s390/mm/gmap.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/s390/mm/gmap.c +2 -2
index 6f96b5a71c63..977b61ab59f2 100644
@@ -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
author
#119 lore raw

PATCH 59/82 lib/scatterlist: Refactor intentional wrap-around test

In reply to 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.

---
 lib/scatterlist.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
lib/scatterlist.c +1 -1
index 68b45c82c37a..121905119bbc 100644
@@ -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
author
#120 lore raw

PATCH 60/82 powerpc: Refactor intentional wrap-around test

In reply to 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.

---
 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
index b66b06efcef1..eaf95dc82925 100644
@@ -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
index b3b94cd37713..b91fdda49434 100644
@@ -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
reviewer Acked-by on v1 60/82
#121 lore raw

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.

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

author
#122 lore raw

PATCH 61/82 scsi: mpt3sas: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/scsi/mpt3sas/mpt3sas_ctl.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/mpt3sas/mpt3sas_ctl.c +1 -1
index 147cb7088d55..b36a9188720f 100644
@@ -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
author
#123 lore raw

PATCH 62/82 mwifiex: pcie: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/net/wireless/marvell/mwifiex/pcie.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/net/wireless/marvell/mwifiex/pcie.c +3 -3
index 5f997becdbaa..e69347e65f0e 100644
@@ -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
Acked-by on v1 62/82
#124 lore raw

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

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
author
#125 lore raw

PATCH 63/82 mm: Refactor intentional wrap-around test

In reply to 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.

---
 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
index 7e1f4849463a..d47acdff7af3 100644
@@ -2559,7 +2559,7 @@ int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long
 	unsigned 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
index b78e83d351d2..16501fcaf511 100644
@@ -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
index 38d98465f3d8..efa27019a05d 100644
@@ -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
index b6dc558d3144..299bcfe19eed 100644
@@ -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
index 5a6a9802583b..e6beeb23b48b 100644
@@ -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
author
#126 lore raw

PATCH 64/82 netfilter: Refactor intentional wrap-around test

In reply to 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.

---
 net/netfilter/xt_u32.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/xt_u32.c +2 -2
index 117d4615d668..8623fe2d97e9 100644
@@ -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
maintainer Acked-by on v1 64/82
#127 lore raw

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

author
#128 lore raw

PATCH 65/82 nios2: Refactor intentional wrap-around test

In reply to 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.

---
 arch/nios2/kernel/sys_nios2.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/nios2/kernel/sys_nios2.c +1 -1
index b1ca85699952..df53efdc96e3 100644
@@ -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
maintainer Acked-by on v1 65/82
#129 lore raw

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.

Quoted 4 lines
---
  arch/nios2/kernel/sys_nios2.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)
author
#130 lore raw

PATCH 66/82 fs/ntfs3: Refactor intentional wrap-around test

In reply to 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.

---
 fs/ntfs3/record.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/ntfs3/record.c +2 -2
index 53629b1f65e9..8cd738c1dbe6 100644
@@ -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
author
#131 lore raw

PATCH 67/82 ocfs2: Refactor intentional wrap-around test

In reply to 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.

---
 fs/ocfs2/resize.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ocfs2/resize.c +1 -1
index d65d43c61857..5cc83e1d54a7 100644
@@ -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
author
#132 lore raw

PATCH 68/82 PCI: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/pci/pci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pci/pci.c +1 -1
index d8f11a078924..ebf6d9064a59 100644
@@ -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
author
#133 lore raw

PATCH 69/82 perf tools: Refactor intentional wrap-around test

In reply to 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.

---
 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
index 22fd5fa806ed..470a86f1cdfd 100644
@@ -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
index 6013335a8dae..45a89cbb2c8d 100644
@@ -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
index dac536e28360..ac71cc7f53b9 100644
@@ -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
reviewer
#134 lore raw

Re: [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.

---
 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
index 22fd5fa806ed..470a86f1cdfd 100644

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.

author
#135 lore raw

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 update tools/include/linux/overflow.h first.

Oops, thank you! I will adjust this.

Signature · 1 line
Kees Cook
author
#136 lore raw

PATCH 70/82 remoteproc: Refactor intentional wrap-around test

In reply to 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.

---
 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
index 327f0c7ee3d6..834249ee3dd3 100644
@@ -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
index 94177e416047..b9231cf46d68 100644
@@ -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
index 83d76915a6ad..58742c666e35 100644
@@ -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
maintainer Acked-by on v1 70/82
#137 lore raw

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.

Regards,
Bjorn

Quoted 60 lines
---
 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
index 327f0c7ee3d6..834249ee3dd3 100644
@@ -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
index 94177e416047..b9231cf46d68 100644
@@ -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
index 83d76915a6ad..58742c666e35 100644
@@ -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
author
#138 lore raw

PATCH 71/82 s390/mm: Refactor intentional wrap-around test

In reply to 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.

---
 arch/s390/mm/vmem.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/mm/vmem.c +1 -1
index 186a020857cf..98a7f08141f0 100644
@@ -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
author
#139 lore raw

PATCH 72/82 scsi: sd_zbc: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/scsi/sd_zbc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/sd_zbc.c +1 -1
index 26af5ab7d7c1..2c377e4cdb2b 100644
@@ -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
author
#140 lore raw

PATCH 73/82 sh: Refactor intentional wrap-around test

In reply to 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.

---
 arch/sh/kernel/sys_sh.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/sh/kernel/sys_sh.c +1 -1
index a5a7b33ed81a..e390caeb8c00 100644
@@ -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
maintainer Acked-by on v1 73/82
#141 lore raw

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.

---
 arch/sh/kernel/sys_sh.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/sh/kernel/sys_sh.c +0 -0
index a5a7b33ed81a..e390caeb8c00 100644

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
author
#142 lore raw

PATCH 74/82 ARC: dw2 unwind: Refactor intentional wrap-around test

In reply to 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.

---
 arch/arc/kernel/unwind.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arc/kernel/unwind.c +1 -1
index 8924fa2a8f29..649b56204580 100644
@@ -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
author
#143 lore raw

PATCH 75/82 timekeeping: Refactor intentional wrap-around test

In reply to 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.

---
 kernel/time/timekeeping.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/timekeeping.c +1 -1
index 266d02809dbb..2fc7cf16584c 100644
@@ -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
maintainer Acked-by on v1 75/82
#144 lore raw

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.

---
 kernel/time/timekeeping.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/timekeeping.c +0 -0
index 266d02809dbb..2fc7cf16584c 100644

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;
Reviewed-by on v1 75/82
#145 lore raw

Re: [PATCH 75/82] timekeeping: Refactor intentional wrap-around test

In reply to Kees Cook
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
author
#146 lore raw

PATCH 76/82 udf: Refactor intentional wrap-around test

In reply to 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.

---
 fs/udf/balloc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
fs/udf/balloc.c +2 -2
index ab3ffc355949..5c88300c3de7 100644
@@ -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
reviewer Reviewed-by on v1 76/82
#147 lore raw

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

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
index ab3ffc355949..5c88300c3de7 100644
@@ -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
author
#148 lore raw

PATCH 77/82 virtio: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/virtio/virtio_pci_modern_dev.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/virtio/virtio_pci_modern_dev.c +2 -2
index 0d3dbfaf4b23..710d3bd45b4f 100644
@@ -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
maintainer Reviewed-by on v1 77/82
#149 lore raw

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
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
index 0d3dbfaf4b23..710d3bd45b4f 100644
@@ -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

author
#150 lore raw

PATCH 78/82 mm/vmalloc: Refactor intentional wrap-around test

In reply to 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.

---
 mm/vmalloc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/vmalloc.c +1 -1
index 7932ac99e9d3..3d73f2ac6957 100644
@@ -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
Reviewed-by on v1 78/82
#151 lore raw

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.

---
 mm/vmalloc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
mm/vmalloc.c +1 -2
index 7932ac99e9d3..3d73f2ac6957 100644
@@ -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,

author
#152 lore raw

PATCH 79/82 staging: vme_user: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/staging/vme_user/vme.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/staging/vme_user/vme.c +1 -1
index e9461a7a7ab8..a0acf2a295cd 100644
@@ -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
author
#153 lore raw

PATCH 80/82 xen-netback: Refactor intentional wrap-around test

In reply to 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.

---
 drivers/net/xen-netback/hash.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/xen-netback/hash.c +1 -1
index ff96f22648ef..69b03b4feba9 100644
@@ -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
#154 lore raw

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

author
#155 lore raw

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
author
#156 lore raw

PATCH 81/82 lib: zstd: Refactor intentional wrap-around test

In reply to 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.

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
index 6b3177c94711..2c87cf702ad6 100644
@@ -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
author
#157 lore raw

PATCH 82/82 mqueue: Refactor intentional wrap-around test

In reply to 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.

---
 ipc/mqueue.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
ipc/mqueue.c +1 -1
index 5eea4dc0509e..7ef9d325183a 100644
@@ -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
#158 lore raw
In reply to Kees Cook
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() 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.)

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.

maintainer
#159 lore raw
Quoted 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
reviewer
#160 lore raw
In reply to Kees Cook
Quoted 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.

author
#161 lore raw
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}.h implementations.

Quoted 7 lines

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.
[...]
This misses lib/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
author
#162 lore raw
In reply to Mark Rutland
Quoted 5 lines · Mark Rutland

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.

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