Add basic sanity checking for pathological "size" arguments to memcpy(). Besides the run-time checking benefit, this avoids GCC trying to be very smart about value range tracking[1] when CONFIG_PROFILE_ALL_BRANCHES=y but FORTIFY_SOURCE=n.
Link: https://lore.kernel.org/all/202505191117.C094A90F88@keescook/ [1] Reported-by: Randy Dunlap <[email protected]> Closes: https://lore.kernel.org/all/[email protected]/ Tested-by: Randy Dunlap <[email protected]> Signed-off-by: Kees Cook <[email protected]> --- v2: isolate this specifically to 32-bit x86 -- doing this generally is much more work v1: https://lore.kernel.org/lkml/[email protected]/ Cc: Ingo Molnar <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: Dave Hansen <[email protected]> Cc: <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Randy Dunlap <[email protected]> --- arch/x86/include/asm/string_32.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/string_32.h b/arch/x86/include/asm/string_32.h index 32c0d981a82a..6e8d100d1301 100644 --- a/arch/x86/include/asm/string_32.h +++ b/arch/x86/include/asm/string_32.h @@ -147,7 +147,14 @@ extern void *memcpy(void *, const void *, size_t); #ifndef CONFIG_FORTIFY_SOURCE -#define memcpy(t, f, n) __builtin_memcpy(t, f, n) +#define memcpy(t, f, n) \ + ({ \ + typeof(n) __n = (n); \ + /* Skip impossible sizes. */ \ + if (!(__n < 0 || __n == SIZE_MAX)) \ + __builtin_memcpy(t, f, __n); \ + (t); \ + }) #endif /* !CONFIG_FORTIFY_SOURCE */ -- 2.34.1
