On Tue, Jun 09, 2026 at 04:13:38PM +0100, David Laight wrote: > My aim is to get to the point where the calling strcpy() is invalid > unless it is used to copy a string literal into an array. > If/when all the .c files are changed the .h file change can be committed > to stop any new potential unbounded copies being added.
Here's what I did a while ago in a test tree of mine, but for strlcat: --- >From d09759b1e51dbf784b503c9b9f5136b81b58560c Mon Sep 17 00:00:00 2001 From: Kees Cook <[email protected]> Date: Fri, 5 Apr 2024 11:08:41 -0700 Subject: [PATCH] fortify: Refuse to use strcat() on dynamically sized strings Limit the use of strcat() to things we can determine at compile time to be safe. Signed-off-by: Kees Cook <[email protected]> --- include/linux/fortify-string.h | 6 ++++++ lib/string_helpers.c | 2 ++ 2 files changed, 8 insertions(+) diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h index 171982e53c9a..8797c06b46e1 100644 --- a/include/linux/fortify-string.h +++ b/include/linux/fortify-string.h @@ -57,6 +57,7 @@ void __read_overflow2(void) __compiletime_error("detected read beyond size of ob void __read_overflow2_field(size_t avail, size_t wanted) __compiletime_warning("detected read beyond size of field (2nd parameter); maybe use struct_group()?"); void __write_overflow(void) __compiletime_error("detected write beyond size of object (1st parameter)"); void __write_overflow_field(size_t avail, size_t wanted) __compiletime_warning("detected write beyond size of field (1st parameter); maybe use struct_group()?"); +void __fortify_refuse_strcat(void) __compiletime_warning("Do not use strcat() on dynamically sized destination or source strings"); #define __compiletime_strlen(p) \ ({ \ @@ -411,8 +412,13 @@ __FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2) char *strcat(char * const POS p, const char *q) { const size_t p_size = __member_size(p); + const size_t q_size = __member_size(q); const size_t wanted = strlcat(p, q, p_size); + if (!__builtin_constant_p(p_size) || !__builtin_constant_p(q_size) || + p_size == SIZE_MAX || q_size == SIZE_MAX) + __fortify_refuse_strcat(); + if (p_size <= wanted) fortify_panic(FORTIFY_FUNC_strcat, FORTIFY_WRITE, p_size, wanted + 1, p); return p; diff --git a/lib/string_helpers.c b/lib/string_helpers.c index 169eaf583494..27b9d97c60c5 100644 --- a/lib/string_helpers.c +++ b/lib/string_helpers.c @@ -1019,6 +1019,8 @@ void __read_overflow2_field(size_t avail, size_t wanted) { } EXPORT_SYMBOL(__read_overflow2_field); void __write_overflow_field(size_t avail, size_t wanted) { } EXPORT_SYMBOL(__write_overflow_field); +void __fortify_refuse_strcat(void) { } +EXPORT_SYMBOL(__fortify_refuse_strcat); static const char * const fortify_func_name[] = { #define MAKE_FORTIFY_FUNC_NAME(func) [MAKE_FORTIFY_FUNC(func)] = #func -- 2.34.1 -- Kees Cook

