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

Reply via email to