From: Kees Cook <kees@kernel.org>
To: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
Cc: Nathan Chancellor <nathan@kernel.org>,
Nick Desaulniers <ndesaulniers@google.com>,
Bill Wendling <morbo@google.com>,
Justin Stitt <justinstitt@google.com>,
David Laight <david.laight@aculab.com>,
linux-hardening@vger.kernel.org, linux-kernel@vger.kernel.org,
llvm@lists.linux.dev
Subject: Re: [PATCH] fortify: turn strlen() into an inline function using __builtin_constant_p()
Date: Wed, 8 Jan 2025 13:46:50 -0800 [thread overview]
Message-ID: <202501081331.E4B6DF747@keescook> (raw)
In-Reply-To: <20250108-strlen_use_builtin_constant_p-v1-1-611b52e80a9f@wanadoo.fr>
On Wed, Jan 08, 2025 at 11:27:51PM +0900, Vincent Mailhol wrote:
> The strlen(p) function-like macro uses:
>
> __is_constexpr(__builtin_strlen(p))
>
> in which GCC would only yield true if the argument p is a string
> literal. Otherwise, GCC would return false even if p is a const
> string.
>
> In contrary, by using:
>
> __builtin_constant_p(__builtin_strlen(p))
>
> then GCC can also recognizes when p is a compile time constant string.
>
> The above is illustrated in [1].
>
> N.B.: clang is not impacted by any of this and gives the same results
> with either __is_constexpr() and __builting_constant_p().
>
> Use __builtin_constant_p() instead of __is_constexpr() so that GCC can
> do the folding on constant strings. This done, strlen() does not
> require any more to be a function-like macro, so turn it into a static
> inline function. In the process, __fortify_strlen() had to be moved
> above strlen() so that it became visible to strlen().
This is what __compiletime_strlen() ended up doing, so this seems
reasonable to me.
> On a side note, strlen() did a double expansion of its argument p.
It did? Ah, was it due to __is_constexpr() wrapping? The other
expressions should have been side-effect free:
__builtin_choose_expr(__is_constexpr(__builtin_strlen(p)), \
__builtin_strlen(p), __fortify_strlen(p))
I don't think you build-tested this with Clang, though?
CC scripts/mod/devicetable-offsets.s
In file included from ../scripts/mod/devicetable-offsets.c:3:
In file included from ../include/linux/mod_devicetable.h:14:
In file included from ../include/linux/uuid.h:11:
In file included from ../include/linux/string.h:389:
../include/linux/fortify-string.h:272:17: error: redeclaration of 'strlen' must not have the 'overloadable' attribute
272 | __kernel_size_t strlen(const char *p)
| ^
../include/linux/string.h:200:24: note: previous unmarked overload of function is here
200 | extern __kernel_size_t strlen(const char *);
| ^
The externs will need to be reworked if it's no longer depending on asm
renaming.
> Turning it into an inline function also resolved this side issue.
>
> [1] https://godbolt.org/z/rqr3YvoP4
>
> Signed-off-by: Vincent Mailhol <mailhol.vincent@wanadoo.fr>
> ---
> This patch is the successor of patch [1] which was part of a longer
> series [2]. Meanwhile, I decided to split it, so I am sending this again,
> but as a stand-alone patch.
>
> Changelog since [1]: use __builtin_constant_p() instead and turn
> strlen() into an inline function
>
> [1] https://lore.kernel.org/all/20241203-is_constexpr-refactor-v1-6-4e4cbaecc216@wanadoo.fr/
> [2] https://lore.kernel.org/all/20241203-is_constexpr-refactor-v1-0-4e4cbaecc216@wanadoo.fr/
> ---
> include/linux/fortify-string.h | 34 +++++++++++++++++++---------------
> 1 file changed, 19 insertions(+), 15 deletions(-)
>
> diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h
> index e4ce1cae03bf770047ce8a7c032b183683388cd5..bd22dd66e5f5b66ad839df42247e6436e0afd053 100644
> --- a/include/linux/fortify-string.h
> +++ b/include/linux/fortify-string.h
> @@ -4,7 +4,6 @@
>
> #include <linux/bitfield.h>
> #include <linux/bug.h>
> -#include <linux/const.h>
> #include <linux/limits.h>
>
> #define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable
> @@ -241,6 +240,21 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size
> * possible for strlen() to be used on compile-time strings for use in
> * static initializers (i.e. as a constant expression).
^^ This comment, however, is I think what sinks this patch. Please see
commit 67ebc3ab4462 ("fortify: Make sure strlen() may still be used as a
constant expression") which required that strlen() not be an inline. I'm
pretty sure the build will start failing again (though perhaps only on
older GCC versions).
The lib/test_fortify/ target still successfully builds, so that's good
though. :)
--
Kees Cook
next prev parent reply other threads:[~2025-01-08 21:46 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-01-08 14:27 [PATCH] fortify: turn strlen() into an inline function using __builtin_constant_p() Vincent Mailhol
2025-01-08 21:46 ` Kees Cook [this message]
2025-01-09 7:52 ` Vincent Mailhol
2025-01-11 14:40 ` Vincent Mailhol
2025-01-11 16:58 ` David Laight
2025-01-11 18:05 ` Vincent Mailhol
2025-01-09 14:14 ` kernel test robot
2025-01-11 2:13 ` kernel test robot
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=202501081331.E4B6DF747@keescook \
--to=kees@kernel.org \
--cc=david.laight@aculab.com \
--cc=justinstitt@google.com \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=llvm@lists.linux.dev \
--cc=mailhol.vincent@wanadoo.fr \
--cc=morbo@google.com \
--cc=nathan@kernel.org \
--cc=ndesaulniers@google.com \
/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.