From: Mark Rutland <mark.rutland@arm.com>
To: Kees Cook <keescook@chromium.org>
Cc: Andy Shevchenko <andy@kernel.org>,
Rasmus Villemoes <rasmus.villemoes@prevas.dk>,
Marco Elver <elver@google.com>,
Eric Biggers <ebiggers@kernel.org>,
linux-hardening@vger.kernel.org,
"Gustavo A . R . Silva" <gustavoars@kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH v6 2/3] overflow: Introduce wrapping_add(), wrapping_sub(), and wrapping_mul()
Date: Wed, 14 Feb 2024 11:58:35 +0000 [thread overview]
Message-ID: <Zcyq6_Eh6excL4RB@FVFF77S0Q05N> (raw)
In-Reply-To: <20240213221100.3556356-2-keescook@chromium.org>
On Tue, Feb 13, 2024 at 02:10:58PM -0800, Kees Cook wrote:
> Provide helpers that will perform wrapping addition, subtraction, or
> multiplication without tripping the arithmetic wrap-around sanitizers. The
> first argument is the type under which the wrap-around should happen
> with. In other words, these two calls will get very different results:
>
> wrapping_mul(int, 50, 50) == 2500
> wrapping_mul(u8, 50, 50) == 196
>
> Add to the selftests to validate behavior and lack of side-effects.
>
> Cc: Rasmus Villemoes <rasmus.villemoes@prevas.dk>
> Cc: Marco Elver <elver@google.com>
> Cc: Eric Biggers <ebiggers@kernel.org>
> Cc: Mark Rutland <mark.rutland@arm.com>
> Cc: linux-hardening@vger.kernel.org
> Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org>
> Reviewed-by: Marco Elver <elver@google.com>
> Signed-off-by: Kees Cook <keescook@chromium.org>
Acked-by: Mark Rutland <mark.rutland@arm.com>
Mark.
> ---
> include/linux/overflow.h | 48 ++++++++++++++++++++++++++++++++++++++++
> lib/overflow_kunit.c | 24 ++++++++++++++++----
> 2 files changed, 68 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/overflow.h b/include/linux/overflow.h
> index 4e741ebb8005..849a49fb496e 100644
> --- a/include/linux/overflow.h
> +++ b/include/linux/overflow.h
> @@ -64,6 +64,22 @@ static inline bool __must_check __must_check_overflow(bool overflow)
> #define check_add_overflow(a, b, d) \
> __must_check_overflow(__builtin_add_overflow(a, b, d))
>
> +/**
> + * wrapping_add() - Intentionally perform a wrapping addition
> + * @type: type for result of calculation
> + * @a: first addend
> + * @b: second addend
> + *
> + * Return the potentially wrapped-around addition without
> + * tripping any wrap-around sanitizers that may be enabled.
> + */
> +#define wrapping_add(type, a, b) \
> + ({ \
> + type __val; \
> + __builtin_add_overflow(a, b, &__val); \
> + __val; \
> + })
> +
> /**
> * check_sub_overflow() - Calculate subtraction with overflow checking
> * @a: minuend; value to subtract from
> @@ -77,6 +93,22 @@ static inline bool __must_check __must_check_overflow(bool overflow)
> #define check_sub_overflow(a, b, d) \
> __must_check_overflow(__builtin_sub_overflow(a, b, d))
>
> +/**
> + * wrapping_sub() - Intentionally perform a wrapping subtraction
> + * @type: type for result of calculation
> + * @a: minuend; value to subtract from
> + * @b: subtrahend; value to subtract from @a
> + *
> + * Return the potentially wrapped-around subtraction without
> + * tripping any wrap-around sanitizers that may be enabled.
> + */
> +#define wrapping_sub(type, a, b) \
> + ({ \
> + type __val; \
> + __builtin_sub_overflow(a, b, &__val); \
> + __val; \
> + })
> +
> /**
> * check_mul_overflow() - Calculate multiplication with overflow checking
> * @a: first factor
> @@ -90,6 +122,22 @@ static inline bool __must_check __must_check_overflow(bool overflow)
> #define check_mul_overflow(a, b, d) \
> __must_check_overflow(__builtin_mul_overflow(a, b, d))
>
> +/**
> + * wrapping_mul() - Intentionally perform a wrapping multiplication
> + * @type: type for result of calculation
> + * @a: first factor
> + * @b: second factor
> + *
> + * Return the potentially wrapped-around multiplication without
> + * tripping any wrap-around sanitizers that may be enabled.
> + */
> +#define wrapping_mul(type, a, b) \
> + ({ \
> + type __val; \
> + __builtin_mul_overflow(a, b, &__val); \
> + __val; \
> + })
> +
> /**
> * check_shl_overflow() - Calculate a left-shifted value and check overflow
> * @a: Value to be shifted
> diff --git a/lib/overflow_kunit.c b/lib/overflow_kunit.c
> index c527f6b75789..d3fdb906d3fe 100644
> --- a/lib/overflow_kunit.c
> +++ b/lib/overflow_kunit.c
> @@ -258,20 +258,36 @@ DEFINE_TEST_ARRAY(s64) = {
> \
> _of = check_ ## op ## _overflow(a, b, &_r); \
> KUNIT_EXPECT_EQ_MSG(test, _of, of, \
> - "expected "fmt" "sym" "fmt" to%s overflow (type %s)\n", \
> + "expected check "fmt" "sym" "fmt" to%s overflow (type %s)\n", \
> a, b, of ? "" : " not", #t); \
> KUNIT_EXPECT_EQ_MSG(test, _r, r, \
> - "expected "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \
> + "expected check "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_EQ_MSG(test, _a_orig, _a_bump, \
> + "Unexpected check " #op " macro side-effect!\n"); \
> + KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, \
> + "Unexpected check " #op " macro side-effect!\n"); \
> + \
> + _r = wrapping_ ## op(t, a, b); \
> + KUNIT_EXPECT_TRUE_MSG(test, _r == r, \
> + "expected wrap "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \
> + a, b, r, _r, #t); \
> + /* Check for internal macro side-effects. */ \
> + _a_orig = a; \
> + _b_orig = b; \
> + _r = wrapping_ ## op(t, _a_orig++, _b_orig++); \
> + KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump, \
> + "Unexpected wrap " #op " macro side-effect!\n"); \
> + KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, \
> + "Unexpected wrap " #op " macro side-effect!\n"); \
> } while (0)
>
> #define DEFINE_TEST_FUNC_TYPED(n, t, fmt) \
> static void do_test_ ## n(struct kunit *test, const struct test_ ## n *p) \
> { \
> + /* check_{add,sub,mul}_overflow() and wrapping_{add,sub,mul} */ \
> check_one_op(t, fmt, add, "+", p->a, p->b, p->sum, p->s_of); \
> check_one_op(t, fmt, add, "+", p->b, p->a, p->sum, p->s_of); \
> check_one_op(t, fmt, sub, "-", p->a, p->b, p->diff, p->d_of); \
> --
> 2.34.1
>
next prev parent reply other threads:[~2024-02-14 11:58 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-13 22:10 [PATCH v6 0/3] overflow: Introduce wrapping helpers Kees Cook
2024-02-13 22:10 ` [PATCH v6 1/3] overflow: Adjust check_*_overflow() kern-doc to reflect results Kees Cook
2024-02-14 11:57 ` Mark Rutland
2024-02-14 19:38 ` Kees Cook
2024-02-13 22:10 ` [PATCH v6 2/3] overflow: Introduce wrapping_add(), wrapping_sub(), and wrapping_mul() Kees Cook
2024-02-14 11:58 ` Mark Rutland [this message]
2024-02-13 22:10 ` [PATCH v6 3/3] overflow: Introduce wrapping_assign_add() and wrapping_assign_sub() Kees Cook
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Zcyq6_Eh6excL4RB@FVFF77S0Q05N \
--to=mark.rutland@arm.com \
--cc=akpm@linux-foundation.org \
--cc=andy@kernel.org \
--cc=ebiggers@kernel.org \
--cc=elver@google.com \
--cc=gustavoars@kernel.org \
--cc=keescook@chromium.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rasmus.villemoes@prevas.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.