]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
string: uninline memcpy_and_pad
authorGuenter Roeck <linux@roeck-us.net>
Tue, 2 Nov 2021 14:24:20 +0000 (07:24 -0700)
committerAndrea Righi <andrea.righi@canonical.com>
Tue, 4 Jan 2022 08:48:41 +0000 (09:48 +0100)
BugLink: https://bugs.launchpad.net/bugs/1951820
commit 5c4e0a21fae877a7ef89be6dcc6263ec672372b8 upstream.

When building m68k:allmodconfig, recent versions of gcc generate the
following error if the length of UTS_RELEASE is less than 8 bytes.

  In function 'memcpy_and_pad',
    inlined from 'nvmet_execute_disc_identify' at
      drivers/nvme/target/discovery.c:268:2: arch/m68k/include/asm/string.h:72:25: error:
'__builtin_memcpy' reading 8 bytes from a region of size 7

Discussions around the problem suggest that this only happens if an
architecture does not provide strlen(), if -ffreestanding is provided as
compiler option, and if CONFIG_FORTIFY_SOURCE=n. All of this is the case
for m68k. The exact reasons are unknown, but seem to be related to the
ability of the compiler to evaluate the return value of strlen() and
the resulting execution flow in memcpy_and_pad(). It would be possible
to work around the problem by using sizeof(UTS_RELEASE) instead of
strlen(UTS_RELEASE), but that would only postpone the problem until the
function is called in a similar way. Uninline memcpy_and_pad() instead
to solve the problem for good.

Suggested-by: Linus Torvalds <torvalds@linux-foundation.org>
Reviewed-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
include/linux/string.h
lib/string_helpers.c

index 5e96d656be7ae0430af7785dc479d0e9f767d77a..d68097b4f600bb29be6754476c45f849d7c33eb6 100644 (file)
@@ -262,23 +262,8 @@ void __write_overflow(void) __compiletime_error("detected write beyond size of o
 #include <linux/fortify-string.h>
 #endif
 
-/**
- * memcpy_and_pad - Copy one buffer to another with padding
- * @dest: Where to copy to
- * @dest_len: The destination buffer size
- * @src: Where to copy from
- * @count: The number of bytes to copy
- * @pad: Character to use for padding if space is left in destination.
- */
-static inline void memcpy_and_pad(void *dest, size_t dest_len,
-                                 const void *src, size_t count, int pad)
-{
-       if (dest_len > count) {
-               memcpy(dest, src, count);
-               memset(dest + count, pad,  dest_len - count);
-       } else
-               memcpy(dest, src, dest_len);
-}
+void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
+                   int pad);
 
 /**
  * str_has_prefix - Test if a string has a given prefix
index 3806a52ce697ae091a2d9e10995c49e56a1d4f53..2ddc10bd9add65efaa4f4322bd4cfd0cf9423f23 100644 (file)
@@ -696,3 +696,23 @@ void kfree_strarray(char **array, size_t n)
        kfree(array);
 }
 EXPORT_SYMBOL_GPL(kfree_strarray);
+
+/**
+ * memcpy_and_pad - Copy one buffer to another with padding
+ * @dest: Where to copy to
+ * @dest_len: The destination buffer size
+ * @src: Where to copy from
+ * @count: The number of bytes to copy
+ * @pad: Character to use for padding if space is left in destination.
+ */
+void memcpy_and_pad(void *dest, size_t dest_len, const void *src, size_t count,
+                   int pad)
+{
+       if (dest_len > count) {
+               memcpy(dest, src, count);
+               memset(dest + count, pad,  dest_len - count);
+       } else {
+               memcpy(dest, src, dest_len);
+       }
+}
+EXPORT_SYMBOL(memcpy_and_pad);