Re: [PATCH v5] overflow: Introduce overflows_type() and castable_to_type()
On Wed, Nov 02, 2022 at 12:52:32PM +0100, Rasmus Villemoes wrote: > On 24/10/2022 22.11, Gwan-gyeong Mun wrote: > > From: Kees Cook > > > > Implement a robust overflows_type() macro to test if a variable or > > constant value would overflow another variable or type. This can be > > used as a constant expression for static_assert() (which requires a > > constant expression[1][2]) when used on constant values. This must be > > constructed manually, since __builtin_add_overflow() does not produce > > a constant expression[3]. > > > > Additionally adds castable_to_type(), similar to __same_type(), but for > > checking if a constant value would overflow if cast to a given type. > > > > > +#define __overflows_type_constexpr(x, T) ( \ > > + is_unsigned_type(typeof(x)) ? \ > > + (x) > type_max(typeof(T)) ? 1 : 0 \ > > + : is_unsigned_type(typeof(T)) ? \ > > + (x) < 0 || (x) > type_max(typeof(T)) ? 1 : 0\ > > + : (x) < type_min(typeof(T)) || \ > > + (x) > type_max(typeof(T)) ? 1 : 0) > > + > > Can't all these instances of "foo ? 1 : 0" be simplified to "foo"? That > would improve the readability of this thing somewhat IMO. Oh, good point. :P I'll fix these. -- Kees Cook
Re: [PATCH v5] overflow: Introduce overflows_type() and castable_to_type()
On 24/10/2022 22.11, Gwan-gyeong Mun wrote: > From: Kees Cook > > Implement a robust overflows_type() macro to test if a variable or > constant value would overflow another variable or type. This can be > used as a constant expression for static_assert() (which requires a > constant expression[1][2]) when used on constant values. This must be > constructed manually, since __builtin_add_overflow() does not produce > a constant expression[3]. > > Additionally adds castable_to_type(), similar to __same_type(), but for > checking if a constant value would overflow if cast to a given type. > > +#define __overflows_type_constexpr(x, T) ( \ > + is_unsigned_type(typeof(x)) ? \ > + (x) > type_max(typeof(T)) ? 1 : 0 \ > + : is_unsigned_type(typeof(T)) ? \ > + (x) < 0 || (x) > type_max(typeof(T)) ? 1 : 0\ > + : (x) < type_min(typeof(T)) || \ > + (x) > type_max(typeof(T)) ? 1 : 0) > + Can't all these instances of "foo ? 1 : 0" be simplified to "foo"? That would improve the readability of this thing somewhat IMO. Rasmus
Re: [PATCH v5] overflow: Introduce overflows_type() and castable_to_type()
On 11/2/22 1:06 AM, Kees Cook wrote: On Sat, Oct 29, 2022 at 11:01:38AM +0300, Gwan-gyeong Mun wrote: On 10/29/22 10:32 AM, Kees Cook wrote: On Sat, Oct 29, 2022 at 08:55:43AM +0300, Gwan-gyeong Mun wrote: Hi Kees, Hi! :) I've updated to v5 with the last comment of Nathan. Could you please kindly review what more is needed as we move forward with this patch? It looks fine to me -- I assume it'll go via the drm tree? Would you rather I carry the non-drm changes in my tree instead? Hi! Yes, I think it would be better to run this patch on your tree. this patch moves the macro of i915 to overflows.h and modifies one part of drm's driver code, but I think this part can be easily applied when merging into the drm tree. I've rebased it to the hardening tree, and it should appear in -next shortly: https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/commit/?h=for-next/hardening=5904fcb776d0b518be96bca43f258db90f26ba9a Thanks for making this patch go forward. G.G.
Re: [PATCH v5] overflow: Introduce overflows_type() and castable_to_type()
On Sat, Oct 29, 2022 at 11:01:38AM +0300, Gwan-gyeong Mun wrote: > > > On 10/29/22 10:32 AM, Kees Cook wrote: > > On Sat, Oct 29, 2022 at 08:55:43AM +0300, Gwan-gyeong Mun wrote: > > > Hi Kees, > > > > Hi! :) > > > > > I've updated to v5 with the last comment of Nathan. > > > Could you please kindly review what more is needed as we move forward with > > > this patch? > > > > It looks fine to me -- I assume it'll go via the drm tree? Would you > > rather I carry the non-drm changes in my tree instead? > > > Hi! > Yes, I think it would be better to run this patch on your tree. > this patch moves the macro of i915 to overflows.h and modifies one part of > drm's driver code, but I think this part can be easily applied when merging > into the drm tree. I've rebased it to the hardening tree, and it should appear in -next shortly: https://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git/commit/?h=for-next/hardening=5904fcb776d0b518be96bca43f258db90f26ba9a -- Kees Cook
Re: [PATCH v5] overflow: Introduce overflows_type() and castable_to_type()
On 10/29/22 10:32 AM, Kees Cook wrote: On Sat, Oct 29, 2022 at 08:55:43AM +0300, Gwan-gyeong Mun wrote: Hi Kees, Hi! :) I've updated to v5 with the last comment of Nathan. Could you please kindly review what more is needed as we move forward with this patch? It looks fine to me -- I assume it'll go via the drm tree? Would you rather I carry the non-drm changes in my tree instead? Hi! Yes, I think it would be better to run this patch on your tree. this patch moves the macro of i915 to overflows.h and modifies one part of drm's driver code, but I think this part can be easily applied when merging into the drm tree. Many thanks, G.G.
Re: [PATCH v5] overflow: Introduce overflows_type() and castable_to_type()
On Sat, Oct 29, 2022 at 08:55:43AM +0300, Gwan-gyeong Mun wrote: > Hi Kees, Hi! :) > I've updated to v5 with the last comment of Nathan. > Could you please kindly review what more is needed as we move forward with > this patch? It looks fine to me -- I assume it'll go via the drm tree? Would you rather I carry the non-drm changes in my tree instead? > -- Kees Cook
Re: [PATCH v5] overflow: Introduce overflows_type() and castable_to_type()
Hi Kees, I've updated to v5 with the last comment of Nathan. Could you please kindly review what more is needed as we move forward with this patch? Br, G.G. On 10/24/22 11:11 PM, Gwan-gyeong Mun wrote: From: Kees Cook Implement a robust overflows_type() macro to test if a variable or constant value would overflow another variable or type. This can be used as a constant expression for static_assert() (which requires a constant expression[1][2]) when used on constant values. This must be constructed manually, since __builtin_add_overflow() does not produce a constant expression[3]. Additionally adds castable_to_type(), similar to __same_type(), but for checking if a constant value would overflow if cast to a given type. Add unit tests for overflows_type(), __same_type(), and castable_to_type() to the existing KUnit "overflow" test. [1] https://en.cppreference.com/w/c/language/_Static_assert [2] C11 standard (ISO/IEC 9899:2011): 6.7.10 Static assertions [3] https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html 6.56 Built-in Functions to Perform Arithmetic with Overflow Checking Built-in Function: bool __builtin_add_overflow (type1 a, type2 b, Cc: Luc Van Oostenryck Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Tom Rix Cc: Daniel Latypov Cc: Vitor Massaru Iha Cc: "Gustavo A. R. Silva" Cc: Jani Nikula Cc: Mauro Carvalho Chehab Cc: linux-harden...@vger.kernel.org Cc: l...@lists.linux.dev Co-developed-by: Gwan-gyeong Mun Signed-off-by: Gwan-gyeong Mun Signed-off-by: Kees Cook --- v5: drop the cc-disable-warning and just disable the warning directly (Nathan) v4: - move version v2 changelog commit message to under the --- marker (Mauro) - remove the #pragma addition in the code and modify the Makefile to handle the same feature (Jani) v3: - chagne to use uintptr_t type when checking for overflow of pointer type variable v2: - fix comment typo - wrap clang pragma to avoid GCC warnings - style nit cleanups - rename __castable_to_type() to castable_to_type() - remove prior overflows_type() definition v1: https://lore.kernel.org/lkml/20220926003743.409911-1-keesc...@chromium.org --- drivers/gpu/drm/i915/i915_user_extensions.c | 2 +- drivers/gpu/drm/i915/i915_utils.h | 4 - include/linux/compiler.h| 1 + include/linux/overflow.h| 48 +++ lib/Makefile| 4 + lib/overflow_kunit.c| 383 +++- 6 files changed, 436 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_user_extensions.c b/drivers/gpu/drm/i915/i915_user_extensions.c index c822d0aafd2d..e3f808372c47 100644 --- a/drivers/gpu/drm/i915/i915_user_extensions.c +++ b/drivers/gpu/drm/i915/i915_user_extensions.c @@ -51,7 +51,7 @@ int i915_user_extensions(struct i915_user_extension __user *ext, return err; if (get_user(next, >next_extension) || - overflows_type(next, ext)) + overflows_type(next, uintptr_t)) return -EFAULT; ext = u64_to_user_ptr(next); diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 6c14d13364bf..67a66d4d5c70 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -111,10 +111,6 @@ bool i915_error_injected(void); #define range_overflows_end_t(type, start, size, max) \ range_overflows_end((type)(start), (type)(size), (type)(max)) -/* Note we don't consider signbits :| */ -#define overflows_type(x, T) \ - (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) - #define ptr_mask_bits(ptr, n) ({ \ unsigned long __v = (unsigned long)(ptr); \ (typeof(ptr))(__v & -BIT(n)); \ diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 973a1bfd7ef5..947a60b801db 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -236,6 +236,7 @@ static inline void *offset_to_ptr(const int *off) * bool and also pointer types. */ #define is_signed_type(type) (((type)(-1)) < (__force type)1) +#define is_unsigned_type(type) (!is_signed_type(type)) /* * This is needed in functions which generate the stack canary, see diff --git a/include/linux/overflow.h b/include/linux/overflow.h index 19dfdd74835e..58eb34aa2af9 100644 --- a/include/linux/overflow.h +++ b/include/linux/overflow.h @@ -127,6 +127,54 @@ static inline bool __must_check __must_check_overflow(bool overflow) (*_d >> _to_shift) != _a);\ })) +#define __overflows_type_constexpr(x, T) ( \ + is_unsigned_type(typeof(x)) ? \ + (x) > type_max(typeof(T)) ? 1 : 0\ + : is_unsigned_type(typeof(T)) ? \ +
[PATCH v5] overflow: Introduce overflows_type() and castable_to_type()
From: Kees Cook Implement a robust overflows_type() macro to test if a variable or constant value would overflow another variable or type. This can be used as a constant expression for static_assert() (which requires a constant expression[1][2]) when used on constant values. This must be constructed manually, since __builtin_add_overflow() does not produce a constant expression[3]. Additionally adds castable_to_type(), similar to __same_type(), but for checking if a constant value would overflow if cast to a given type. Add unit tests for overflows_type(), __same_type(), and castable_to_type() to the existing KUnit "overflow" test. [1] https://en.cppreference.com/w/c/language/_Static_assert [2] C11 standard (ISO/IEC 9899:2011): 6.7.10 Static assertions [3] https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html 6.56 Built-in Functions to Perform Arithmetic with Overflow Checking Built-in Function: bool __builtin_add_overflow (type1 a, type2 b, Cc: Luc Van Oostenryck Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Tom Rix Cc: Daniel Latypov Cc: Vitor Massaru Iha Cc: "Gustavo A. R. Silva" Cc: Jani Nikula Cc: Mauro Carvalho Chehab Cc: linux-harden...@vger.kernel.org Cc: l...@lists.linux.dev Co-developed-by: Gwan-gyeong Mun Signed-off-by: Gwan-gyeong Mun Signed-off-by: Kees Cook --- v5: drop the cc-disable-warning and just disable the warning directly (Nathan) v4: - move version v2 changelog commit message to under the --- marker (Mauro) - remove the #pragma addition in the code and modify the Makefile to handle the same feature (Jani) v3: - chagne to use uintptr_t type when checking for overflow of pointer type variable v2: - fix comment typo - wrap clang pragma to avoid GCC warnings - style nit cleanups - rename __castable_to_type() to castable_to_type() - remove prior overflows_type() definition v1: https://lore.kernel.org/lkml/20220926003743.409911-1-keesc...@chromium.org --- drivers/gpu/drm/i915/i915_user_extensions.c | 2 +- drivers/gpu/drm/i915/i915_utils.h | 4 - include/linux/compiler.h| 1 + include/linux/overflow.h| 48 +++ lib/Makefile| 4 + lib/overflow_kunit.c| 383 +++- 6 files changed, 436 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_user_extensions.c b/drivers/gpu/drm/i915/i915_user_extensions.c index c822d0aafd2d..e3f808372c47 100644 --- a/drivers/gpu/drm/i915/i915_user_extensions.c +++ b/drivers/gpu/drm/i915/i915_user_extensions.c @@ -51,7 +51,7 @@ int i915_user_extensions(struct i915_user_extension __user *ext, return err; if (get_user(next, >next_extension) || - overflows_type(next, ext)) + overflows_type(next, uintptr_t)) return -EFAULT; ext = u64_to_user_ptr(next); diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 6c14d13364bf..67a66d4d5c70 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -111,10 +111,6 @@ bool i915_error_injected(void); #define range_overflows_end_t(type, start, size, max) \ range_overflows_end((type)(start), (type)(size), (type)(max)) -/* Note we don't consider signbits :| */ -#define overflows_type(x, T) \ - (sizeof(x) > sizeof(T) && (x) >> BITS_PER_TYPE(T)) - #define ptr_mask_bits(ptr, n) ({ \ unsigned long __v = (unsigned long)(ptr); \ (typeof(ptr))(__v & -BIT(n)); \ diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 973a1bfd7ef5..947a60b801db 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h @@ -236,6 +236,7 @@ static inline void *offset_to_ptr(const int *off) * bool and also pointer types. */ #define is_signed_type(type) (((type)(-1)) < (__force type)1) +#define is_unsigned_type(type) (!is_signed_type(type)) /* * This is needed in functions which generate the stack canary, see diff --git a/include/linux/overflow.h b/include/linux/overflow.h index 19dfdd74835e..58eb34aa2af9 100644 --- a/include/linux/overflow.h +++ b/include/linux/overflow.h @@ -127,6 +127,54 @@ static inline bool __must_check __must_check_overflow(bool overflow) (*_d >> _to_shift) != _a); \ })) +#define __overflows_type_constexpr(x, T) ( \ + is_unsigned_type(typeof(x)) ? \ + (x) > type_max(typeof(T)) ? 1 : 0 \ + : is_unsigned_type(typeof(T)) ? \ + (x) < 0 || (x) > type_max(typeof(T)) ? 1 : 0\ + : (x) < type_min(typeof(T)) || \ + (x) > type_max(typeof(T)) ? 1 : 0) + +#define __overflows_type(x, T)