On Wed, 14 Feb 2024 at 20:46, Kees Cook <keesc...@chromium.org> wrote: > > This allows replacements of the idioms "var += offset" and "var -= > offset" with the wrapping_assign_add() and wrapping_assign_sub() helpers > respectively. They will avoid wrap-around sanitizer instrumentation. > > Add to the selftests to validate behavior and lack of side-effects. > > Signed-off-by: Kees Cook <keesc...@chromium.org>
Reviewed-by: Marco Elver <el...@google.com> > --- > Cc: Rasmus Villemoes <rasmus.villem...@prevas.dk> > Cc: Marco Elver <el...@google.com> > Cc: Eric Biggers <ebigg...@kernel.org> > Cc: Mark Rutland <mark.rutl...@arm.com> > Cc: "Gustavo A. R. Silva" <gustavo...@kernel.org> > Cc: linux-hardening@vger.kernel.org > --- > include/linux/overflow.h | 32 ++++++++++++++++++++++++++++++ > lib/overflow_kunit.c | 43 ++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 75 insertions(+) > > diff --git a/include/linux/overflow.h b/include/linux/overflow.h > index d3ff8e2bec29..dede374832c9 100644 > --- a/include/linux/overflow.h > +++ b/include/linux/overflow.h > @@ -81,6 +81,22 @@ static inline bool __must_check __must_check_overflow(bool > overflow) > __val; \ > }) > > +/** > + * wrapping_assign_add() - Intentionally perform a wrapping increment > assignment > + * @var: variable to be incremented > + * @offset: amount to add > + * > + * Increments @var by @offset with wrap-around. Returns the resulting > + * value of @var. Will not trip any wrap-around sanitizers. > + * > + * Returns the new value of @var. > + */ > +#define wrapping_assign_add(var, offset) \ > + ({ \ > + typeof(var) *__ptr = &(var); \ > + *__ptr = wrapping_add(typeof(var), *__ptr, offset); \ > + }) > + > /** > * check_sub_overflow() - Calculate subtraction with overflow checking > * @a: minuend; value to subtract from > @@ -111,6 +127,22 @@ static inline bool __must_check > __must_check_overflow(bool overflow) > __val; \ > }) > > +/** > + * wrapping_assign_sub() - Intentionally perform a wrapping decrement assign > + * @var: variable to be decremented > + * @offset: amount to subtract > + * > + * Decrements @var by @offset with wrap-around. Returns the resulting > + * value of @var. Will not trip any wrap-around sanitizers. > + * > + * Returns the new value of @var. > + */ > +#define wrapping_assign_sub(var, offset) \ > + ({ \ > + typeof(var) *__ptr = &(var); \ > + *__ptr = wrapping_sub(typeof(var), *__ptr, offset); \ > + }) > + > /** > * check_mul_overflow() - Calculate multiplication with overflow checking > * @a: first factor > diff --git a/lib/overflow_kunit.c b/lib/overflow_kunit.c > index d3fdb906d3fe..65e8a72a83bf 100644 > --- a/lib/overflow_kunit.c > +++ b/lib/overflow_kunit.c [...] > + /* wrapping_assign_{add,sub}() */ \ > + check_self_op(fmt, assign_add, +=, p->a, p->b); \ > + check_self_op(fmt, assign_add, +=, p->b, p->a); \ > + check_self_op(fmt, assign_sub, -=, p->a, p->b); \ > } \ Merely a curiosity, and am not suggesting this for this patch: I wonder how much of this could be tested at compile-time. These are very primitive operations, so I suspect the compiler could either check these in a static_assert(), or if some of it isn't constexpr-friendly, after optimizations with a BUILD_BUG.