public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*()
@ 2025-02-06 18:11 Kees Cook
  2025-02-06 18:11 ` [PATCH 1/3] compiler.h: Move C string helpers into C-only kernel section Kees Cook
                   ` (3 more replies)
  0 siblings, 4 replies; 18+ messages in thread
From: Kees Cook @ 2025-02-06 18:11 UTC (permalink / raw)
  To: Suren Baghdasaryan
  Cc: Kees Cook, Kent Overstreet, Andy Shevchenko, Luc Van Oostenryck,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Philipp Reisner, Miguel Ojeda, linux-kernel, linux-hardening,
	llvm

Work around a Clang 14 bug by switching to ARRAY_SIZE() (with the
added benefit of explicitly checking for char array arguments) in
memtostr*/strtomem*().

-Kees

Kees Cook (3):
  compiler.h: Move C string helpers into C-only kernel section
  compiler.h: Introduce __must_be_char_array()
  string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*()

 include/linux/compiler.h | 32 +++++++++++++++++++-------------
 include/linux/string.h   | 12 ++++++++----
 2 files changed, 27 insertions(+), 17 deletions(-)

-- 
2.34.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/3] compiler.h: Move C string helpers into C-only kernel section
  2025-02-06 18:11 [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*() Kees Cook
@ 2025-02-06 18:11 ` Kees Cook
  2025-02-06 20:07   ` Miguel Ojeda
  2025-02-06 18:11 ` [PATCH 2/3] compiler.h: Introduce __must_be_char_array() Kees Cook
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 18+ messages in thread
From: Kees Cook @ 2025-02-06 18:11 UTC (permalink / raw)
  To: Suren Baghdasaryan
  Cc: Kees Cook, Kent Overstreet, Andy Shevchenko, Luc Van Oostenryck,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Philipp Reisner, Miguel Ojeda, linux-kernel, linux-hardening,
	llvm

The C kernel helpers for evaluating C Strings were placed outside of the
assembly ifdef. Move them to the correct place so future changes won't
confuse the assembler.

Fixes: d7a516c6eeae ("compiler.h: Fix undefined BUILD_BUG_ON_ZERO()")
Fixes: 559048d156ff ("string: Check for "nonstring" attribute on strscpy() arguments")
Signed-off-by: Kees Cook <kees@kernel.org>
---
 include/linux/compiler.h | 26 +++++++++++++-------------
 1 file changed, 13 insertions(+), 13 deletions(-)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 240c632c5b95..7af999a131cb 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -214,6 +214,19 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 	__v;								\
 })
 
+#ifdef __CHECKER__
+#define __BUILD_BUG_ON_ZERO_MSG(e, msg) (0)
+#else /* __CHECKER__ */
+#define __BUILD_BUG_ON_ZERO_MSG(e, msg) ((int)sizeof(struct {_Static_assert(!(e), msg);}))
+#endif /* __CHECKER__ */
+
+/* &a[0] degrades to a pointer: a different type from an array */
+#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")
+
+/* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */
+#define __must_be_cstr(p) \
+	__BUILD_BUG_ON_ZERO_MSG(__annotated(p, nonstring), "must be cstr (NUL-terminated)")
+
 #endif /* __KERNEL__ */
 
 /**
@@ -254,19 +267,6 @@ static inline void *offset_to_ptr(const int *off)
 
 #define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym))
 
-#ifdef __CHECKER__
-#define __BUILD_BUG_ON_ZERO_MSG(e, msg) (0)
-#else /* __CHECKER__ */
-#define __BUILD_BUG_ON_ZERO_MSG(e, msg) ((int)sizeof(struct {_Static_assert(!(e), msg);}))
-#endif /* __CHECKER__ */
-
-/* &a[0] degrades to a pointer: a different type from an array */
-#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")
-
-/* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */
-#define __must_be_cstr(p) \
-	__BUILD_BUG_ON_ZERO_MSG(__annotated(p, nonstring), "must be cstr (NUL-terminated)")
-
 /*
  * This returns a constant expression while determining if an argument is
  * a constant expression, most importantly without evaluating the argument.
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 2/3] compiler.h: Introduce __must_be_char_array()
  2025-02-06 18:11 [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*() Kees Cook
  2025-02-06 18:11 ` [PATCH 1/3] compiler.h: Move C string helpers into C-only kernel section Kees Cook
@ 2025-02-06 18:11 ` Kees Cook
  2025-02-06 19:56   ` David Laight
                     ` (3 more replies)
  2025-02-06 18:11 ` [PATCH 3/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*() Kees Cook
  2025-02-06 18:41 ` [PATCH 0/3] " Andy Shevchenko
  3 siblings, 4 replies; 18+ messages in thread
From: Kees Cook @ 2025-02-06 18:11 UTC (permalink / raw)
  To: Suren Baghdasaryan
  Cc: Kees Cook, Kent Overstreet, Andy Shevchenko, Luc Van Oostenryck,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Philipp Reisner, Miguel Ojeda, linux-kernel, linux-hardening,
	llvm

In preparation for adding stricter type checking to the str/mem*()
helpers, provide a way to check that a variable is a character array
via __must_be_char_array().

Signed-off-by: Kees Cook <kees@kernel.org>
---
 include/linux/compiler.h | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 7af999a131cb..a577fe0b1f8a 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -221,7 +221,13 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 #endif /* __CHECKER__ */
 
 /* &a[0] degrades to a pointer: a different type from an array */
-#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")
+#define __is_array(a)		(!__same_type((a), &(a)[0]))
+#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_array(a), \
+							"must be array")
+
+#define __is_char_array(a)	(__is_array(a) && sizeof((a)[0]) == 1)
+#define __must_be_char_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_char_array(a), \
+							"must be byte array")
 
 /* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */
 #define __must_be_cstr(p) \
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH 3/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*()
  2025-02-06 18:11 [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*() Kees Cook
  2025-02-06 18:11 ` [PATCH 1/3] compiler.h: Move C string helpers into C-only kernel section Kees Cook
  2025-02-06 18:11 ` [PATCH 2/3] compiler.h: Introduce __must_be_char_array() Kees Cook
@ 2025-02-06 18:11 ` Kees Cook
  2025-02-06 18:41 ` [PATCH 0/3] " Andy Shevchenko
  3 siblings, 0 replies; 18+ messages in thread
From: Kees Cook @ 2025-02-06 18:11 UTC (permalink / raw)
  To: Suren Baghdasaryan
  Cc: Kees Cook, kernel test robot, Kent Overstreet, nathan,
	Andy Shevchenko, linux-hardening, Luc Van Oostenryck,
	Nick Desaulniers, Bill Wendling, Justin Stitt, Philipp Reisner,
	Miguel Ojeda, linux-kernel, llvm

The destination argument of memtostr*() and strtomem*() must be a
fixed-size char array at compile time, so there is no need to use
__builtin_object_size() (which is useful for when an argument is
either a pointer or unknown). Instead use ARRAY_SIZE(), which has the
benefit of working around a bug in Clang (fixed[1] in 15+) that got
__builtin_object_size() wrong sometimes.

Reported-by: kernel test robot <lkp@intel.com>
Closes: https://lore.kernel.org/oe-kbuild-all/202501310832.kiAeOt2z-lkp@intel.com/
Suggested-by: Kent Overstreet <kent.overstreet@linux.dev>
Link: https://github.com/llvm/llvm-project/commit/d8e0a6d5e9dd2311641f9a8a5d2bf90829951ddc [1]
Signed-off-by: Kees Cook <kees@kernel.org>
---
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: nathan@kernel.org
Cc: Andy Shevchenko <andy@kernel.org>
Cc: linux-hardening@vger.kernel.org
---
 include/linux/string.h | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/include/linux/string.h b/include/linux/string.h
index 493ac4862c77..01ac26be274d 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -411,7 +411,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
  * must be discoverable by the compiler.
  */
 #define strtomem_pad(dest, src, pad)	do {				\
-	const size_t _dest_len = __builtin_object_size(dest, 1);	\
+	const size_t _dest_len = __must_be_char_array(dest) +		\
+				ARRAY_SIZE(dest);			\
 	const size_t _src_len = __builtin_object_size(src, 1);		\
 									\
 	BUILD_BUG_ON(!__builtin_constant_p(_dest_len) ||		\
@@ -434,7 +435,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
  * must be discoverable by the compiler.
  */
 #define strtomem(dest, src)	do {					\
-	const size_t _dest_len = __builtin_object_size(dest, 1);	\
+	const size_t _dest_len = __must_be_char_array(dest) +		\
+				ARRAY_SIZE(dest);			\
 	const size_t _src_len = __builtin_object_size(src, 1);		\
 									\
 	BUILD_BUG_ON(!__builtin_constant_p(_dest_len) ||		\
@@ -453,7 +455,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
  * Note that sizes of @dest and @src must be known at compile-time.
  */
 #define memtostr(dest, src)	do {					\
-	const size_t _dest_len = __builtin_object_size(dest, 1);	\
+	const size_t _dest_len = __must_be_char_array(dest) +		\
+				ARRAY_SIZE(dest);			\
 	const size_t _src_len = __builtin_object_size(src, 1);		\
 	const size_t _src_chars = strnlen(src, _src_len);		\
 	const size_t _copy_len = min(_dest_len - 1, _src_chars);	\
@@ -478,7 +481,8 @@ void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
  * Note that sizes of @dest and @src must be known at compile-time.
  */
 #define memtostr_pad(dest, src)		do {				\
-	const size_t _dest_len = __builtin_object_size(dest, 1);	\
+	const size_t _dest_len = __must_be_char_array(dest) +		\
+				ARRAY_SIZE(dest);			\
 	const size_t _src_len = __builtin_object_size(src, 1);		\
 	const size_t _src_chars = strnlen(src, _src_len);		\
 	const size_t _copy_len = min(_dest_len - 1, _src_chars);	\
-- 
2.34.1


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*()
  2025-02-06 18:11 [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*() Kees Cook
                   ` (2 preceding siblings ...)
  2025-02-06 18:11 ` [PATCH 3/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*() Kees Cook
@ 2025-02-06 18:41 ` Andy Shevchenko
  2025-02-06 18:44   ` Miguel Ojeda
  3 siblings, 1 reply; 18+ messages in thread
From: Andy Shevchenko @ 2025-02-06 18:41 UTC (permalink / raw)
  To: Kees Cook
  Cc: Suren Baghdasaryan, Kent Overstreet, Andy Shevchenko,
	Luc Van Oostenryck, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, Philipp Reisner, Miguel Ojeda,
	linux-kernel, linux-hardening, llvm

On Thu, Feb 6, 2025 at 8:11 PM Kees Cook <kees@kernel.org> wrote:
>
> Work around a Clang 14 bug by switching to ARRAY_SIZE() (with the
> added benefit of explicitly checking for char array arguments) in
> memtostr*/strtomem*().

What's the minimum Clang version we build kernel with? 12?

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*()
  2025-02-06 18:41 ` [PATCH 0/3] " Andy Shevchenko
@ 2025-02-06 18:44   ` Miguel Ojeda
  2025-02-06 18:45     ` Andy Shevchenko
  0 siblings, 1 reply; 18+ messages in thread
From: Miguel Ojeda @ 2025-02-06 18:44 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Kees Cook, Suren Baghdasaryan, Kent Overstreet, Andy Shevchenko,
	Luc Van Oostenryck, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, Philipp Reisner, Miguel Ojeda,
	linux-kernel, linux-hardening, llvm

On Thu, Feb 6, 2025 at 7:42 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
>
> What's the minimum Clang version we build kernel with? 12?

13.0.1 for most architectures according to `scripts/min-tool-version.sh`.

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*()
  2025-02-06 18:44   ` Miguel Ojeda
@ 2025-02-06 18:45     ` Andy Shevchenko
  2025-02-06 18:52       ` Kees Cook
  0 siblings, 1 reply; 18+ messages in thread
From: Andy Shevchenko @ 2025-02-06 18:45 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Kees Cook, Suren Baghdasaryan, Kent Overstreet, Andy Shevchenko,
	Luc Van Oostenryck, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, Philipp Reisner, Miguel Ojeda,
	linux-kernel, linux-hardening, llvm

On Thu, Feb 6, 2025 at 8:44 PM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> On Thu, Feb 6, 2025 at 7:42 PM Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
> >
> > What's the minimum Clang version we build kernel with? 12?
>
> 13.0.1 for most architectures according to `scripts/min-tool-version.sh`.

Okay, does it mean 13 has no such a bug?
Otherwise the commit message and other comments might be clearer...

-- 
With Best Regards,
Andy Shevchenko

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*()
  2025-02-06 18:45     ` Andy Shevchenko
@ 2025-02-06 18:52       ` Kees Cook
  2025-02-06 19:12         ` Andy Shevchenko
  0 siblings, 1 reply; 18+ messages in thread
From: Kees Cook @ 2025-02-06 18:52 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Miguel Ojeda, Suren Baghdasaryan, Kent Overstreet,
	Andy Shevchenko, Luc Van Oostenryck, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt, Philipp Reisner,
	Miguel Ojeda, linux-kernel, linux-hardening, llvm

On Thu, Feb 06, 2025 at 08:45:41PM +0200, Andy Shevchenko wrote:
> On Thu, Feb 6, 2025 at 8:44 PM Miguel Ojeda
> <miguel.ojeda.sandonis@gmail.com> wrote:
> >
> > On Thu, Feb 6, 2025 at 7:42 PM Andy Shevchenko
> > <andy.shevchenko@gmail.com> wrote:
> > >
> > > What's the minimum Clang version we build kernel with? 12?
> >
> > 13.0.1 for most architectures according to `scripts/min-tool-version.sh`.
> 
> Okay, does it mean 13 has no such a bug?

It probably did, but Clang 13 didn't support compile-time error messages
(added in 14). Regardless, this fixes it there and makes the API more
robust.

> Otherwise the commit message and other comments might be clearer...

How should I rephrase things? I mention the bug and when it was fixed
in patch 3:

  ...
  benefit of working around a bug in Clang (fixed[1] in 15+) that got
  ...

-Kees

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*()
  2025-02-06 18:52       ` Kees Cook
@ 2025-02-06 19:12         ` Andy Shevchenko
  0 siblings, 0 replies; 18+ messages in thread
From: Andy Shevchenko @ 2025-02-06 19:12 UTC (permalink / raw)
  To: Kees Cook
  Cc: Miguel Ojeda, Suren Baghdasaryan, Kent Overstreet,
	Luc Van Oostenryck, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, Philipp Reisner, Miguel Ojeda,
	linux-kernel, linux-hardening, llvm

On Thu, Feb 06, 2025 at 10:52:18AM -0800, Kees Cook wrote:
> On Thu, Feb 06, 2025 at 08:45:41PM +0200, Andy Shevchenko wrote:
> > On Thu, Feb 6, 2025 at 8:44 PM Miguel Ojeda
> > <miguel.ojeda.sandonis@gmail.com> wrote:
> > > On Thu, Feb 6, 2025 at 7:42 PM Andy Shevchenko
> > > <andy.shevchenko@gmail.com> wrote:
> > > >
> > > > What's the minimum Clang version we build kernel with? 12?
> > >
> > > 13.0.1 for most architectures according to `scripts/min-tool-version.sh`.
> > 
> > Okay, does it mean 13 has no such a bug?
> 
> It probably did, but Clang 13 didn't support compile-time error messages
> (added in 14). Regardless, this fixes it there and makes the API more
> robust.
> 
> > Otherwise the commit message and other comments might be clearer...
> 
> How should I rephrase things? I mention the bug and when it was fixed
> in patch 3:
> 
>   ...
>   benefit of working around a bug in Clang (fixed[1] in 15+) that got
>   ...

Ah, the version is mentioned only in cover letter. So, the patch's commit
message seems good to me.

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/3] compiler.h: Introduce __must_be_char_array()
  2025-02-06 18:11 ` [PATCH 2/3] compiler.h: Introduce __must_be_char_array() Kees Cook
@ 2025-02-06 19:56   ` David Laight
  2025-02-06 21:34     ` Kees Cook
  2025-02-06 20:50   ` Kent Overstreet
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 18+ messages in thread
From: David Laight @ 2025-02-06 19:56 UTC (permalink / raw)
  To: Kees Cook
  Cc: Suren Baghdasaryan, Kent Overstreet, Andy Shevchenko,
	Luc Van Oostenryck, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, Philipp Reisner, Miguel Ojeda,
	linux-kernel, linux-hardening, llvm

On Thu,  6 Feb 2025 10:11:29 -0800
Kees Cook <kees@kernel.org> wrote:

> In preparation for adding stricter type checking to the str/mem*()
> helpers, provide a way to check that a variable is a character array
> via __must_be_char_array().
> 
...
> +#define __is_char_array(a)	(__is_array(a) && sizeof((a)[0]) == 1)
> +#define __must_be_char_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_char_array(a), \
> +							"must be byte array")

If you are only checking the size, perhaps __is_byte_array() would
be a better name.
(You've even used 'byte' in the error message.)

	David

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/3] compiler.h: Move C string helpers into C-only kernel section
  2025-02-06 18:11 ` [PATCH 1/3] compiler.h: Move C string helpers into C-only kernel section Kees Cook
@ 2025-02-06 20:07   ` Miguel Ojeda
  2025-02-06 21:28     ` Kees Cook
  0 siblings, 1 reply; 18+ messages in thread
From: Miguel Ojeda @ 2025-02-06 20:07 UTC (permalink / raw)
  To: Kees Cook
  Cc: Suren Baghdasaryan, Kent Overstreet, Andy Shevchenko,
	Luc Van Oostenryck, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, Philipp Reisner, Miguel Ojeda,
	linux-kernel, linux-hardening, llvm

On Thu, Feb 6, 2025 at 7:11 PM Kees Cook <kees@kernel.org> wrote:
>
> The C kernel helpers for evaluating C Strings were placed outside of the
> assembly ifdef. Move them to the correct place so future changes won't
> confuse the assembler.

This moves it also into the kernel ifdef too -- I assume that is
intentional. (Perhaps mention ifndef instead of ifdef?)

I checked that this is indeed a pure move, so:

Reviewed-by: Miguel Ojeda <ojeda@kernel.org>

Cheers,
Miguel

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/3] compiler.h: Introduce __must_be_char_array()
  2025-02-06 18:11 ` [PATCH 2/3] compiler.h: Introduce __must_be_char_array() Kees Cook
  2025-02-06 19:56   ` David Laight
@ 2025-02-06 20:50   ` Kent Overstreet
  2025-02-06 21:26     ` Kees Cook
  2025-02-07  8:55   ` Rasmus Villemoes
  2025-02-07 13:58   ` Kent Overstreet
  3 siblings, 1 reply; 18+ messages in thread
From: Kent Overstreet @ 2025-02-06 20:50 UTC (permalink / raw)
  To: Kees Cook
  Cc: Suren Baghdasaryan, Andy Shevchenko, Luc Van Oostenryck,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Philipp Reisner, Miguel Ojeda, linux-kernel, linux-hardening,
	llvm

On Thu, Feb 06, 2025 at 10:11:29AM -0800, Kees Cook wrote:
> In preparation for adding stricter type checking to the str/mem*()
> helpers, provide a way to check that a variable is a character array
> via __must_be_char_array().
> 
> Signed-off-by: Kees Cook <kees@kernel.org>

Suggested-by? :)

> ---
>  include/linux/compiler.h | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index 7af999a131cb..a577fe0b1f8a 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -221,7 +221,13 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
>  #endif /* __CHECKER__ */
>  
>  /* &a[0] degrades to a pointer: a different type from an array */
> -#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")
> +#define __is_array(a)		(!__same_type((a), &(a)[0]))
> +#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_array(a), \
> +							"must be array")
> +
> +#define __is_char_array(a)	(__is_array(a) && sizeof((a)[0]) == 1)
> +#define __must_be_char_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_char_array(a), \
> +							"must be byte array")
>  
>  /* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */
>  #define __must_be_cstr(p) \
> -- 
> 2.34.1
> 

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/3] compiler.h: Introduce __must_be_char_array()
  2025-02-06 20:50   ` Kent Overstreet
@ 2025-02-06 21:26     ` Kees Cook
  0 siblings, 0 replies; 18+ messages in thread
From: Kees Cook @ 2025-02-06 21:26 UTC (permalink / raw)
  To: Kent Overstreet
  Cc: Suren Baghdasaryan, Andy Shevchenko, Luc Van Oostenryck,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Philipp Reisner, Miguel Ojeda, linux-kernel, linux-hardening,
	llvm

On Thu, Feb 06, 2025 at 03:50:47PM -0500, Kent Overstreet wrote:
> On Thu, Feb 06, 2025 at 10:11:29AM -0800, Kees Cook wrote:
> > In preparation for adding stricter type checking to the str/mem*()
> > helpers, provide a way to check that a variable is a character array
> > via __must_be_char_array().
> > 
> > Signed-off-by: Kees Cook <kees@kernel.org>
> 
> Suggested-by? :)

Sure, I'll add that. I did it for the ARRAY_SIZE() and forgot which
pieces came from where when I split up the patches. :)

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/3] compiler.h: Move C string helpers into C-only kernel section
  2025-02-06 20:07   ` Miguel Ojeda
@ 2025-02-06 21:28     ` Kees Cook
  0 siblings, 0 replies; 18+ messages in thread
From: Kees Cook @ 2025-02-06 21:28 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Suren Baghdasaryan, Kent Overstreet, Andy Shevchenko,
	Luc Van Oostenryck, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, Philipp Reisner, Miguel Ojeda,
	linux-kernel, linux-hardening, llvm

On Thu, Feb 06, 2025 at 09:07:05PM +0100, Miguel Ojeda wrote:
> On Thu, Feb 6, 2025 at 7:11 PM Kees Cook <kees@kernel.org> wrote:
> >
> > The C kernel helpers for evaluating C Strings were placed outside of the
> > assembly ifdef. Move them to the correct place so future changes won't
> > confuse the assembler.
> 
> This moves it also into the kernel ifdef too -- I assume that is
> intentional. (Perhaps mention ifndef instead of ifdef?)

Right, yeah. I guess I only mentioned that in the Subject. I'll clarify.

> 
> I checked that this is indeed a pure move, so:
> 
> Reviewed-by: Miguel Ojeda <ojeda@kernel.org>

Thanks!

-Kees

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/3] compiler.h: Introduce __must_be_char_array()
  2025-02-06 19:56   ` David Laight
@ 2025-02-06 21:34     ` Kees Cook
  0 siblings, 0 replies; 18+ messages in thread
From: Kees Cook @ 2025-02-06 21:34 UTC (permalink / raw)
  To: David Laight
  Cc: Suren Baghdasaryan, Kent Overstreet, Andy Shevchenko,
	Luc Van Oostenryck, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, Philipp Reisner, Miguel Ojeda,
	linux-kernel, linux-hardening, llvm

On Thu, Feb 06, 2025 at 07:56:58PM +0000, David Laight wrote:
> On Thu,  6 Feb 2025 10:11:29 -0800
> Kees Cook <kees@kernel.org> wrote:
> 
> > In preparation for adding stricter type checking to the str/mem*()
> > helpers, provide a way to check that a variable is a character array
> > via __must_be_char_array().
> > 
> ...
> > +#define __is_char_array(a)	(__is_array(a) && sizeof((a)[0]) == 1)
> > +#define __must_be_char_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_char_array(a), \
> > +							"must be byte array")
> 
> If you are only checking the size, perhaps __is_byte_array() would
> be a better name.
> (You've even used 'byte' in the error message.)

Yeah, fair point. I went and forth on naming. Fixed for v2.

-- 
Kees Cook

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/3] compiler.h: Introduce __must_be_char_array()
  2025-02-06 18:11 ` [PATCH 2/3] compiler.h: Introduce __must_be_char_array() Kees Cook
  2025-02-06 19:56   ` David Laight
  2025-02-06 20:50   ` Kent Overstreet
@ 2025-02-07  8:55   ` Rasmus Villemoes
  2025-02-07 13:13     ` David Laight
  2025-02-07 13:58   ` Kent Overstreet
  3 siblings, 1 reply; 18+ messages in thread
From: Rasmus Villemoes @ 2025-02-07  8:55 UTC (permalink / raw)
  To: Kees Cook
  Cc: Suren Baghdasaryan, Kent Overstreet, Andy Shevchenko,
	Luc Van Oostenryck, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, Philipp Reisner, Miguel Ojeda,
	linux-kernel, linux-hardening, llvm

On Thu, Feb 06 2025, Kees Cook <kees@kernel.org> wrote:

> In preparation for adding stricter type checking to the str/mem*()
> helpers, provide a way to check that a variable is a character array
> via __must_be_char_array().
>
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
>  include/linux/compiler.h | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index 7af999a131cb..a577fe0b1f8a 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -221,7 +221,13 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
>  #endif /* __CHECKER__ */
>  
>  /* &a[0] degrades to a pointer: a different type from an array */
> -#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")
> +#define __is_array(a)		(!__same_type((a), &(a)[0]))
> +#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_array(a), \
> +							"must be array")
> +
> +#define __is_char_array(a)	(__is_array(a) && sizeof((a)[0]) == 1)
> +#define __must_be_char_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_char_array(a), \
> +							"must be byte array")
>

It's probably unlikely to ever encounter an array of _Bool or array of
structs-with-a-single-char-member in the wild, but it does seem a bit
odd to base the test on sizeof(). Why not add a

  __is_character_type(t) (__same_type(t, char) ||
                          __same_type(t, signed char) ||
                          __same_type(t, unsigned char) )

helper and write the test using __is_character_type((a)[0])?

Or if you really mean that it must be an array of char, not any of the
three "character types", simply replace the sizeof() by
__same_type(a[0], char)

Rasmus

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/3] compiler.h: Introduce __must_be_char_array()
  2025-02-07  8:55   ` Rasmus Villemoes
@ 2025-02-07 13:13     ` David Laight
  0 siblings, 0 replies; 18+ messages in thread
From: David Laight @ 2025-02-07 13:13 UTC (permalink / raw)
  To: Rasmus Villemoes
  Cc: Kees Cook, Suren Baghdasaryan, Kent Overstreet, Andy Shevchenko,
	Luc Van Oostenryck, Nathan Chancellor, Nick Desaulniers,
	Bill Wendling, Justin Stitt, Philipp Reisner, Miguel Ojeda,
	linux-kernel, linux-hardening, llvm

On Fri, 07 Feb 2025 09:55:00 +0100
Rasmus Villemoes <ravi@prevas.dk> wrote:

> On Thu, Feb 06 2025, Kees Cook <kees@kernel.org> wrote:
> 
> > In preparation for adding stricter type checking to the str/mem*()
> > helpers, provide a way to check that a variable is a character array
> > via __must_be_char_array().
> >
> > Signed-off-by: Kees Cook <kees@kernel.org>
> > ---
> >  include/linux/compiler.h | 8 +++++++-
> >  1 file changed, 7 insertions(+), 1 deletion(-)
> >
> > diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> > index 7af999a131cb..a577fe0b1f8a 100644
> > --- a/include/linux/compiler.h
> > +++ b/include/linux/compiler.h
> > @@ -221,7 +221,13 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
> >  #endif /* __CHECKER__ */
> >  
> >  /* &a[0] degrades to a pointer: a different type from an array */
> > -#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")
> > +#define __is_array(a)		(!__same_type((a), &(a)[0]))
> > +#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_array(a), \
> > +							"must be array")
> > +
> > +#define __is_char_array(a)	(__is_array(a) && sizeof((a)[0]) == 1)
> > +#define __must_be_char_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_char_array(a), \
> > +							"must be byte array")
> >  
> 
> It's probably unlikely to ever encounter an array of _Bool or array of
> structs-with-a-single-char-member in the wild, but it does seem a bit
> odd to base the test on sizeof(). Why not add a
> 
>   __is_character_type(t) (__same_type(t, char) ||
>                           __same_type(t, signed char) ||
>                           __same_type(t, unsigned char) )
> 
> helper and write the test using __is_character_type((a)[0])?
> 
> Or if you really mean that it must be an array of char, not any of the
> three "character types", simply replace the sizeof() by
> __same_type(a[0], char)

I'm not sure it matters enough to slow down the compilation by that much
cpp bloat.

	David



^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/3] compiler.h: Introduce __must_be_char_array()
  2025-02-06 18:11 ` [PATCH 2/3] compiler.h: Introduce __must_be_char_array() Kees Cook
                     ` (2 preceding siblings ...)
  2025-02-07  8:55   ` Rasmus Villemoes
@ 2025-02-07 13:58   ` Kent Overstreet
  3 siblings, 0 replies; 18+ messages in thread
From: Kent Overstreet @ 2025-02-07 13:58 UTC (permalink / raw)
  To: Kees Cook
  Cc: Suren Baghdasaryan, Andy Shevchenko, Luc Van Oostenryck,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Philipp Reisner, Miguel Ojeda, linux-kernel, linux-hardening,
	llvm

On Thu, Feb 06, 2025 at 10:11:29AM -0800, Kees Cook wrote:
> In preparation for adding stricter type checking to the str/mem*()
> helpers, provide a way to check that a variable is a character array
> via __must_be_char_array().
> 
> Signed-off-by: Kees Cook <kees@kernel.org>
> ---
>  include/linux/compiler.h | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/compiler.h b/include/linux/compiler.h
> index 7af999a131cb..a577fe0b1f8a 100644
> --- a/include/linux/compiler.h
> +++ b/include/linux/compiler.h
> @@ -221,7 +221,13 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
>  #endif /* __CHECKER__ */
>  
>  /* &a[0] degrades to a pointer: a different type from an array */
> -#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(__same_type((a), &(a)[0]), "must be array")
> +#define __is_array(a)		(!__same_type((a), &(a)[0]))
> +#define __must_be_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_array(a), \
> +							"must be array")
> +
> +#define __is_char_array(a)	(__is_array(a) && sizeof((a)[0]) == 1)
> +#define __must_be_char_array(a)	__BUILD_BUG_ON_ZERO_MSG(!__is_char_array(a), \
> +							"must be byte array")
>  
>  /* Require C Strings (i.e. NUL-terminated) lack the "nonstring" attribute. */
>  #define __must_be_cstr(p) \
> -- 
> 2.34.1
> 

Why not just use a combination of ARRAY_SIZE() and a function call
(to verify that it's a character array) for the typechecking?

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2025-02-07 13:59 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-06 18:11 [PATCH 0/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*() Kees Cook
2025-02-06 18:11 ` [PATCH 1/3] compiler.h: Move C string helpers into C-only kernel section Kees Cook
2025-02-06 20:07   ` Miguel Ojeda
2025-02-06 21:28     ` Kees Cook
2025-02-06 18:11 ` [PATCH 2/3] compiler.h: Introduce __must_be_char_array() Kees Cook
2025-02-06 19:56   ` David Laight
2025-02-06 21:34     ` Kees Cook
2025-02-06 20:50   ` Kent Overstreet
2025-02-06 21:26     ` Kees Cook
2025-02-07  8:55   ` Rasmus Villemoes
2025-02-07 13:13     ` David Laight
2025-02-07 13:58   ` Kent Overstreet
2025-02-06 18:11 ` [PATCH 3/3] string.h: Use ARRAY_SIZE() for memtostr*()/strtomem*() Kees Cook
2025-02-06 18:41 ` [PATCH 0/3] " Andy Shevchenko
2025-02-06 18:44   ` Miguel Ojeda
2025-02-06 18:45     ` Andy Shevchenko
2025-02-06 18:52       ` Kees Cook
2025-02-06 19:12         ` Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox