History

Merge tag 'hardening-v6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux

Pull hardening updates from Kees Cook: "As is pretty normal for this tree, there are changes all over the place, especially for small fixes, selftest improvements, and improved macro usability. Some header changes ended up landing via this tree as they depended on the string header cleanups. Also, a notable set of changes is the work for the reintroduction of the UBSAN signed integer overflow sanitizer so that we can continue to make improvements on the compiler side to make this sanitizer a more viable future security hardening option. Summary: - string.h and related header cleanups (Tanzir Hasan, Andy Shevchenko) - VMCI memcpy() usage and struct_size() cleanups (Vasiliy Kovalev, Harshit Mogalapalli) - selftests/powerpc: Fix load_unaligned_zeropad build failure (Michael Ellerman) - hardened Kconfig fragment updates (Marco Elver, Lukas Bulwahn) - Handle tail call optimization better in LKDTM (Douglas Anderson) - Use long form types in overflow.h (Andy Shevchenko) - Add flags param to string_get_size() (Andy Shevchenko) - Add Coccinelle script for potential struct_size() use (Jacob Keller) - Fix objtool corner case under KCFI (Josh Poimboeuf) - Drop 13 year old backward compat CAP_SYS_ADMIN check (Jingzi Meng) - Add str_plural() helper (Michal Wajdeczko, Kees Cook) - Ignore relocations in .notes section - Add comments to explain how __is_constexpr() works - Fix m68k stack alignment expectations in stackinit Kunit test - Convert string selftests to KUnit - Add KUnit tests for fortified string functions - Improve reporting during fortified string warnings - Allow non-type arg to type_max() and type_min() - Allow strscpy() to be called with only 2 arguments - Add binary mode to leaking_addresses scanner - Various small cleanups to leaking_addresses scanner - Adding wrapping_*() arithmetic helper - Annotate initial signed integer wrap-around in refcount_t - Add explicit UBSAN section to MAINTAINERS - Fix UBSAN self-test warnings - Simplify UBSAN build via removal of CONFIG_UBSAN_SANITIZE_ALL - Reintroduce UBSAN's signed overflow sanitizer" * tag 'hardening-v6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (51 commits) selftests/powerpc: Fix load_unaligned_zeropad build failure string: Convert helpers selftest to KUnit string: Convert selftest to KUnit sh: Fix build with CONFIG_UBSAN=y compiler.h: Explain how __is_constexpr() works overflow: Allow non-type arg to type_max() and type_min() VMCI: Fix possible memcpy() run-time warning in vmci_datagram_invoke_guest_handler() lib/string_helpers: Add flags param to string_get_size() x86, relocs: Ignore relocations in .notes section objtool: Fix UNWIND_HINT_{SAVE,RESTORE} across basic blocks overflow: Use POD in check_shl_overflow() lib: stackinit: Adjust target string to 8 bytes for m68k sparc: vdso: Disable UBSAN instrumentation kernel.h: Move lib/cmdline.c prototypes to string.h leaking_addresses: Provide mechanism to scan binary files leaking_addresses: Ignore input device status lines leaking_addresses: Use File::Temp for /tmp files MAINTAINERS: Update LEAKING_ADDRESSES details fortify: Improve buffer overflow reporting fortify: Add KUnit tests for runtime overflows ...

Linus Torvalds committed 2 years ago

Commit 216532e2 parents b32273e 3fe1eb471 files · +1949 −688Browse files

Unified · Split

71 files
  1. Documentation/dev-tools/ubsan.rst +8 −20
  2. MAINTAINERS +22 −4
  3. arch/arm/Kconfig +1 −1
  4. arch/arm/boot/compressed/misc.c +1 −1
  5. arch/arm/boot/compressed/misc.h +1 −1
  6. arch/arm/include/asm/word-at-a-time.h +2 −1
  7. arch/arm64/Kconfig +1 −1
  8. arch/arm64/include/asm/word-at-a-time.h +2 −1
  9. arch/mips/Kconfig +1 −1
  10. arch/parisc/Kconfig +1 −1
  11. arch/powerpc/Kconfig +1 −1
  12. arch/powerpc/include/asm/word-at-a-time.h +2 −2
  13. arch/riscv/Kconfig +1 −1
  14. arch/riscv/include/asm/word-at-a-time.h +2 −1
  15. arch/s390/Kconfig +1 −1
  16. arch/s390/include/asm/word-at-a-time.h +2 −1
  17. arch/sh/boot/compressed/Makefile +1 −0
  18. arch/sh/include/asm/word-at-a-time.h +2 −0
  19. arch/sparc/vdso/Makefile +1 −0
  20. arch/um/drivers/net_kern.c +1 −1
  21. arch/um/drivers/vector_kern.c +1 −1
  22. arch/um/drivers/vector_user.c +2 −2
  23. arch/um/include/shared/user.h +2 −1
  24. arch/um/os-Linux/drivers/ethertap_user.c +1 −1
  25. arch/um/os-Linux/drivers/tuntap_user.c +1 −1
  26. arch/um/os-Linux/umid.c +3 −3
  27. arch/x86/Kconfig +1 −1
  28. arch/x86/boot/compressed/misc.c +1 −1
  29. arch/x86/include/asm/word-at-a-time.h +2 −1
  30. arch/x86/kvm/mmu/mmu.c +1 −0
  31. arch/x86/tools/relocs.c +8 −0
  32. drivers/misc/lkdtm/bugs.c +2 −1
  33. drivers/misc/lkdtm/core.c +14 −8
  34. drivers/misc/vmw_vmci/vmci_datagram.c +6 −4
  35. fs/namei.c +1 −1
  36. include/asm-generic/word-at-a-time.h +2 −1
  37. include/linux/compiler.h +39 −0
  38. include/linux/compiler_types.h +8 −1
  39. include/linux/fortify-string.h +75 −47
  40. include/linux/kernel.h +2 −42
  41. include/linux/overflow.h +97 −18
  42. include/linux/refcount.h +6 −3
  43. include/linux/string.h +81 −5
  44. include/linux/string_choices.h +11 −0
  45. include/linux/string_helpers.h +7 −3
  46. include/linux/wordpart.h +42 −0
  47. kernel/configs/hardening.config +3 −4
  48. kernel/printk/printk.c +0 −11
  49. lib/Kconfig.debug +9 −5
  50. lib/Kconfig.ubsan +15 −13
  51. lib/Makefile +5 −2
  52. lib/fortify_kunit.c +660 −2
  53. lib/overflow_kunit.c +63 −4
  54. lib/stackinit_kunit.c +16 −3
  55. lib/string.c +11 −12
  56. lib/string_helpers.c +39 −50
  57. lib/string_helpers_kunit.c +137 −118
  58. lib/string_kunit.c +199 −0
  59. lib/test_string.c +0 −257
  60. lib/test_ubsan.c +39 −2
  61. lib/ubsan.c +68 −0
  62. lib/ubsan.h +4 −0
  63. scripts/Makefile.lib +4 −1
  64. scripts/Makefile.ubsan +4 −1
  65. scripts/coccinelle/api/string_choices.cocci +41 −0
  66. scripts/coccinelle/misc/struct_size.cocci +74 −0
  67. scripts/leaking_addresses.pl +74 −16
  68. tools/objtool/check.c +12 −0
  69. tools/objtool/noreturns.h +1 −1
  70. tools/testing/selftests/powerpc/primitives/linux/bitops.h +0 −0
  71. tools/testing/selftests/powerpc/primitives/linux/wordpart.h +1 −0
Documentation/dev-tools/ubsan.rst+8−20
@@ -49,34 +49,22 @@ Report example · 48 unmodified lines
4949 Usage
5050 -----
5151
52−To enable UBSAN configure kernel with::
52+To enable UBSAN, configure the kernel with::
5353
54− CONFIG_UBSAN=y
54+ CONFIG_UBSAN=y
5555
56−and to check the entire kernel::
57−
58− CONFIG_UBSAN_SANITIZE_ALL=y
59−
60−To enable instrumentation for specific files or directories, add a line
61−similar to the following to the respective kernel Makefile:
62−
63−- For a single file (e.g. main.o)::
64−
65− UBSAN_SANITIZE_main.o := y
66−
67−- For all files in one directory::
68−
69− UBSAN_SANITIZE := y
70−
71−To exclude files from being instrumented even if
72−``CONFIG_UBSAN_SANITIZE_ALL=y``, use::
56+To exclude files from being instrumented use::
7357
7458 UBSAN_SANITIZE_main.o := n
7559
76−and::
60+and to exclude all targets in one directory use::
7761
7862 UBSAN_SANITIZE := n
7963
64+When disabled for all targets, specific files can be enabled using::
65+
66+ UBSAN_SANITIZE_main.o := y
67+
8068 Detection of unaligned accesses controlled through the separate option -
8169 CONFIG_UBSAN_ALIGNMENT. It's off by default on architectures that support
8270 unaligned accesses (CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y). One could
MAINTAINERS+22−4
@@ -8989,9 +8989,10 @@ F: include/linux/string.h · 8988 unmodified lines
89898989 F: include/linux/string_choices.h
89908990 F: include/linux/string_helpers.h
89918991 F: lib/string.c
8992+F: lib/string_kunit.c
89928993 F: lib/string_helpers.c
8993−F: lib/test-string_helpers.c
8994−F: lib/test_string.c
8994+F: lib/string_helpers_kunit.c
8995+F: scripts/coccinelle/api/string_choices.cocci
89958996
89968997 GENERIC UIO DRIVER FOR PCI DEVICES
89978998 M: "Michael S. Tsirkin" <mst@redhat.com>
@@ -12178,11 +12179,11 @@ F: Documentation/scsi/53c700.rst · 3180 unmodified lines
1217812179 F: drivers/scsi/53c700*
1217912180
1218012181 LEAKING_ADDRESSES
12181−M: Tobin C. Harding <me@tobin.cc>
1218212182 M: Tycho Andersen <tycho@tycho.pizza>
12183+R: Kees Cook <keescook@chromium.org>
1218312184 L: linux-hardening@vger.kernel.org
1218412185 S: Maintained
12185−T: git git://git.kernel.org/pub/scm/linux/kernel/git/tobin/leaks.git
12186+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
1218612187 F: scripts/leaking_addresses.pl
1218712188
1218812189 LED SUBSYSTEM
@@ -22503,6 +22504,23 @@ F: Documentation/block/ublk.rst · 10314 unmodified lines
2250322504 F: drivers/block/ublk_drv.c
2250422505 F: include/uapi/linux/ublk_cmd.h
2250522506
22507+UBSAN
22508+M: Kees Cook <keescook@chromium.org>
22509+R: Marco Elver <elver@google.com>
22510+R: Andrey Konovalov <andreyknvl@gmail.com>
22511+R: Andrey Ryabinin <ryabinin.a.a@gmail.com>
22512+L: kasan-dev@googlegroups.com
22513+L: linux-hardening@vger.kernel.org
22514+S: Supported
22515+T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
22516+F: Documentation/dev-tools/ubsan.rst
22517+F: include/linux/ubsan.h
22518+F: lib/Kconfig.ubsan
22519+F: lib/test_ubsan.c
22520+F: lib/ubsan.c
22521+F: scripts/Makefile.ubsan
22522+K: \bARCH_HAS_UBSAN\b
22523+
2250622524 UCLINUX (M68KNOMMU AND COLDFIRE)
2250722525 M: Greg Ungerer <gerg@linux-m68k.org>
2250822526 L: linux-m68k@lists.linux-m68k.org
arch/arm/Kconfig+1−1
@@ -29,7 +29,7 @@ config ARM · 28 unmodified lines
2929 select ARCH_HAVE_NMI_SAFE_CMPXCHG if CPU_V7 || CPU_V7M || CPU_V6K
3030 select ARCH_HAS_GCOV_PROFILE_ALL
3131 select ARCH_KEEP_MEMBLOCK
32− select ARCH_HAS_UBSAN_SANITIZE_ALL
32+ select ARCH_HAS_UBSAN
3333 select ARCH_MIGHT_HAVE_PC_PARPORT
3434 select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
3535 select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V7
arch/arm/boot/compressed/misc.c+1−1
@@ -154,7 +154,7 @@ decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, · 153 unmodified lines
154154 putstr(" done, booting the kernel.\n");
155155 }
156156
157−void fortify_panic(const char *name)
157+void __fortify_panic(const u8 reason, size_t avail, size_t size)
158158 {
159159 error("detected buffer overflow");
160160 }
arch/arm/boot/compressed/misc.h+1−1
@@ -10,7 +10,7 @@ void __div0(void); · 9 unmodified lines
1010 void
1111 decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
1212 unsigned long free_mem_ptr_end_p, int arch_id);
13−void fortify_panic(const char *name);
13+void __fortify_panic(const u8 reason, size_t avail, size_t size);
1414 int atags_to_fdt(void *atag_list, void *fdt, int total_space);
1515 uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt);
1616 int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));
arch/arm/include/asm/word-at-a-time.h+2−1
@@ -8,7 +8,8 @@ · 7 unmodified lines
88 * Little-endian word-at-a-time zero byte handling.
99 * Heavily based on the x86 algorithm.
1010 */
11−#include <linux/kernel.h>
11+#include <linux/bitops.h>
12+#include <linux/wordpart.h>
1213
1314 struct word_at_a_time {
1415 const unsigned long one_bits, high_bits;
arch/arm64/Kconfig+1−1
@@ -107,7 +107,7 @@ config ARM64 · 106 unmodified lines
107107 select ARCH_WANT_LD_ORPHAN_WARN
108108 select ARCH_WANTS_NO_INSTR
109109 select ARCH_WANTS_THP_SWAP if ARM64_4K_PAGES
110− select ARCH_HAS_UBSAN_SANITIZE_ALL
110+ select ARCH_HAS_UBSAN
111111 select ARM_AMBA
112112 select ARM_ARCH_TIMER
113113 select ARM_GIC
arch/arm64/include/asm/word-at-a-time.h+2−1
@@ -9,7 +9,8 @@ · 8 unmodified lines
99
1010 #ifndef __AARCH64EB__
1111
12−#include <linux/kernel.h>
12+#include <linux/bitops.h>
13+#include <linux/wordpart.h>
1314
1415 struct word_at_a_time {
1516 const unsigned long one_bits, high_bits;
arch/mips/Kconfig+1−1
@@ -14,7 +14,7 @@ config MIPS · 13 unmodified lines
1414 select ARCH_HAS_STRNCPY_FROM_USER
1515 select ARCH_HAS_STRNLEN_USER
1616 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
17− select ARCH_HAS_UBSAN_SANITIZE_ALL
17+ select ARCH_HAS_UBSAN
1818 select ARCH_HAS_GCOV_PROFILE_ALL
1919 select ARCH_KEEP_MEMBLOCK
2020 select ARCH_USE_BUILTIN_BSWAP
arch/parisc/Kconfig+1−1
@@ -12,7 +12,7 @@ config PARISC · 11 unmodified lines
1212 select ARCH_HAS_ELF_RANDOMIZE
1313 select ARCH_HAS_STRICT_KERNEL_RWX
1414 select ARCH_HAS_STRICT_MODULE_RWX
15− select ARCH_HAS_UBSAN_SANITIZE_ALL
15+ select ARCH_HAS_UBSAN
1616 select ARCH_HAS_PTE_SPECIAL
1717 select ARCH_NO_SG_CHAIN
1818 select ARCH_SUPPORTS_HUGETLBFS if PA20
arch/powerpc/Kconfig+1−1
@@ -154,7 +154,7 @@ config PPC · 153 unmodified lines
154154 select ARCH_HAS_SYSCALL_WRAPPER if !SPU_BASE && !COMPAT
155155 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
156156 select ARCH_HAS_UACCESS_FLUSHCACHE
157− select ARCH_HAS_UBSAN_SANITIZE_ALL
157+ select ARCH_HAS_UBSAN
158158 select ARCH_HAVE_NMI_SAFE_CMPXCHG
159159 select ARCH_KEEP_MEMBLOCK
160160 select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if PPC_RADIX_MMU
arch/powerpc/include/asm/word-at-a-time.h+2−2
@@ -4,8 +4,8 @@ · 3 unmodified lines
44 /*
55 * Word-at-a-time interfaces for PowerPC.
66 */
7−
8−#include <linux/kernel.h>
7+#include <linux/bitops.h>
8+#include <linux/wordpart.h>
99 #include <asm/asm-compat.h>
1010 #include <asm/extable.h>
1111
arch/riscv/Kconfig+1−1
@@ -37,7 +37,7 @@ config RISCV · 36 unmodified lines
3737 select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL
3838 select ARCH_HAS_SYSCALL_WRAPPER
3939 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
40− select ARCH_HAS_UBSAN_SANITIZE_ALL
40+ select ARCH_HAS_UBSAN
4141 select ARCH_HAS_VDSO_DATA
4242 select ARCH_KEEP_MEMBLOCK if ACPI
4343 select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
arch/riscv/include/asm/word-at-a-time.h+2−1
@@ -10,7 +10,8 @@ · 9 unmodified lines
1010
1111
1212 #include <asm/asm-extable.h>
13−#include <linux/kernel.h>
13+#include <linux/bitops.h>
14+#include <linux/wordpart.h>
1415
1516 struct word_at_a_time {
1617 const unsigned long one_bits, high_bits;
arch/s390/Kconfig+1−1
@@ -82,7 +82,7 @@ config S390 · 81 unmodified lines
8282 select ARCH_HAS_STRICT_KERNEL_RWX
8383 select ARCH_HAS_STRICT_MODULE_RWX
8484 select ARCH_HAS_SYSCALL_WRAPPER
85− select ARCH_HAS_UBSAN_SANITIZE_ALL
85+ select ARCH_HAS_UBSAN
8686 select ARCH_HAS_VDSO_DATA
8787 select ARCH_HAVE_NMI_SAFE_CMPXCHG
8888 select ARCH_INLINE_READ_LOCK
arch/s390/include/asm/word-at-a-time.h+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
22 #ifndef _ASM_WORD_AT_A_TIME_H
33 #define _ASM_WORD_AT_A_TIME_H
44
5−#include <linux/kernel.h>
5+#include <linux/bitops.h>
6+#include <linux/wordpart.h>
67 #include <asm/asm-extable.h>
78 #include <asm/bitsperlong.h>
89
arch/sh/boot/compressed/Makefile+1−0
@@ -12,6 +12,7 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ · 11 unmodified lines
1212 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo $(OBJECTS)
1313
1414 GCOV_PROFILE := n
15+UBSAN_SANITIZE := n
1516
1617 #
1718 # IMAGE_OFFSET is the load offset of the compression loader
arch/sh/include/asm/word-at-a-time.h+2−0
@@ -5,6 +5,8 @@ · 4 unmodified lines
55 #ifdef CONFIG_CPU_BIG_ENDIAN
66 # include <asm-generic/word-at-a-time.h>
77 #else
8+#include <linux/bitops.h>
9+#include <linux/wordpart.h>
810 /*
911 * Little-endian version cribbed from x86.
1012 */
arch/sparc/vdso/Makefile+1−0
@@ -2,6 +2,7 @@ · 1 unmodified line
22 #
33 # Building vDSO images for sparc.
44 #
5+UBSAN_SANITIZE := n
56
67 # files to link into the vdso
78 vobjs-y := vdso-note.o vclock_gettime.o
arch/um/drivers/net_kern.c+1−1
@@ -265,7 +265,7 @@ static void uml_net_poll_controller(struct net_device *dev) · 264 unmodified lines
265265 static void uml_net_get_drvinfo(struct net_device *dev,
266266 struct ethtool_drvinfo *info)
267267 {
268− strscpy(info->driver, DRIVER_NAME, sizeof(info->driver));
268+ strscpy(info->driver, DRIVER_NAME);
269269 }
270270
271271 static const struct ethtool_ops uml_net_ethtool_ops = {
arch/um/drivers/vector_kern.c+1−1
@@ -1373,7 +1373,7 @@ static void vector_net_poll_controller(struct net_device *dev) · 1372 unmodified lines
13731373 static void vector_net_get_drvinfo(struct net_device *dev,
13741374 struct ethtool_drvinfo *info)
13751375 {
1376− strscpy(info->driver, DRIVER_NAME, sizeof(info->driver));
1376+ strscpy(info->driver, DRIVER_NAME);
13771377 }
13781378
13791379 static int vector_net_load_bpf_flash(struct net_device *dev,
arch/um/drivers/vector_user.c+2−2
@@ -141,7 +141,7 @@ static int create_tap_fd(char *iface) · 140 unmodified lines
141141 }
142142 memset(&ifr, 0, sizeof(ifr));
143143 ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;
144− strscpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
144+ strscpy(ifr.ifr_name, iface);
145145
146146 err = ioctl(fd, TUNSETIFF, (void *) &ifr);
147147 if (err != 0) {
@@ -171,7 +171,7 @@ static int create_raw_fd(char *iface, int flags, int proto) · 23 unmodified lines
171171 goto raw_fd_cleanup;
172172 }
173173 memset(&ifr, 0, sizeof(ifr));
174− strscpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
174+ strscpy(ifr.ifr_name, iface);
175175 if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {
176176 err = -errno;
177177 goto raw_fd_cleanup;
arch/um/include/shared/user.h+2−1
@@ -51,7 +51,8 @@ static inline int printk(const char *fmt, ...) · 50 unmodified lines
5151
5252 extern int in_aton(char *str);
5353 extern size_t strlcat(char *, const char *, size_t);
54−extern size_t strscpy(char *, const char *, size_t);
54+extern size_t sized_strscpy(char *, const char *, size_t);
55+#define strscpy(dst, src) sized_strscpy(dst, src, sizeof(dst))
5556
5657 /* Copied from linux/compiler-gcc.h since we can't include it directly */
5758 #define barrier() __asm__ __volatile__("": : :"memory")
arch/um/os-Linux/drivers/ethertap_user.c+1−1
@@ -105,7 +105,7 @@ static int etap_tramp(char *dev, char *gate, int control_me, · 104 unmodified lines
105105 sprintf(data_fd_buf, "%d", data_remote);
106106 sprintf(version_buf, "%d", UML_NET_VERSION);
107107 if (gate != NULL) {
108− strscpy(gate_buf, gate, sizeof(gate_buf));
108+ strscpy(gate_buf, gate);
109109 args = setup_args;
110110 }
111111 else args = nosetup_args;
arch/um/os-Linux/drivers/tuntap_user.c+1−1
@@ -146,7 +146,7 @@ static int tuntap_open(void *data) · 145 unmodified lines
146146 }
147147 memset(&ifr, 0, sizeof(ifr));
148148 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
149− strscpy(ifr.ifr_name, pri->dev_name, sizeof(ifr.ifr_name));
149+ strscpy(ifr.ifr_name, pri->dev_name);
150150 if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) {
151151 err = -errno;
152152 printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n",
arch/um/os-Linux/umid.c+3−3
@@ -40,7 +40,7 @@ static int __init make_uml_dir(void) · 39 unmodified lines
4040 __func__);
4141 goto err;
4242 }
43− strscpy(dir, home, sizeof(dir));
43+ strscpy(dir, home);
4444 uml_dir++;
4545 }
4646 strlcat(dir, uml_dir, sizeof(dir));
@@ -243,7 +243,7 @@ int __init set_umid(char *name) · 196 unmodified lines
243243 if (strlen(name) > UMID_LEN - 1)
244244 return -E2BIG;
245245
246− strscpy(umid, name, sizeof(umid));
246+ strscpy(umid, name);
247247
248248 return 0;
249249 }
@@ -262,7 +262,7 @@ static int __init make_umid(void) · 12 unmodified lines
262262 make_uml_dir();
263263
264264 if (*umid == '\0') {
265− strscpy(tmp, uml_dir, sizeof(tmp));
265+ strscpy(tmp, uml_dir);
266266 strlcat(tmp, "XXXXXX", sizeof(tmp));
267267 fd = mkstemp(tmp);
268268 if (fd < 0) {
arch/x86/Kconfig+1−1
@@ -100,7 +100,7 @@ config X86 · 99 unmodified lines
100100 select ARCH_HAS_STRICT_MODULE_RWX
101101 select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
102102 select ARCH_HAS_SYSCALL_WRAPPER
103− select ARCH_HAS_UBSAN_SANITIZE_ALL
103+ select ARCH_HAS_UBSAN
104104 select ARCH_HAS_DEBUG_WX
105105 select ARCH_HAS_ZONE_DMA_SET if EXPERT
106106 select ARCH_HAVE_NMI_SAFE_CMPXCHG
arch/x86/boot/compressed/misc.c+1−1
@@ -531,7 +531,7 @@ asmlinkage __visible void *extract_kernel(void *rmode, unsigned char *output) · 530 unmodified lines
531531 return output + entry_offset;
532532 }
533533
534−void fortify_panic(const char *name)
534+void __fortify_panic(const u8 reason, size_t avail, size_t size)
535535 {
536536 error("detected buffer overflow");
537537 }
arch/x86/include/asm/word-at-a-time.h+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
22 #ifndef _ASM_WORD_AT_A_TIME_H
33 #define _ASM_WORD_AT_A_TIME_H
44
5−#include <linux/kernel.h>
5+#include <linux/bitops.h>
6+#include <linux/wordpart.h>
67
78 /*
89 * This is largely generic for little-endian machines, but the
arch/x86/kvm/mmu/mmu.c+1−0
@@ -47,6 +47,7 @@ · 46 unmodified lines
4747 #include <linux/kern_levels.h>
4848 #include <linux/kstrtox.h>
4949 #include <linux/kthread.h>
50+#include <linux/wordpart.h>
5051
5152 #include <asm/page.h>
5253 #include <asm/memtype.h>
arch/x86/tools/relocs.c+8−0
@@ -653,6 +653,14 @@ static void print_absolute_relocs(void) · 652 unmodified lines
653653 if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
654654 continue;
655655 }
656+ /*
657+ * Do not perform relocations in .notes section; any
658+ * values there are meant for pre-boot consumption (e.g.
659+ * startup_xen).
660+ */
661+ if (sec_applies->shdr.sh_type == SHT_NOTE) {
662+ continue;
663+ }
656664 sh_symtab = sec_symtab->symtab;
657665 sym_strtab = sec_symtab->link->strtab;
658666 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
drivers/misc/lkdtm/bugs.c+2−1
@@ -294,10 +294,11 @@ static void lkdtm_SPINLOCKUP(void) · 293 unmodified lines
294294 __release(&lock_me_up);
295295 }
296296
297−static void lkdtm_HUNG_TASK(void)
297+static void __noreturn lkdtm_HUNG_TASK(void)
298298 {
299299 set_current_state(TASK_UNINTERRUPTIBLE);
300300 schedule();
301+ BUG();
301302 }
302303
303304 static volatile unsigned int huge = INT_MAX - 2;
drivers/misc/lkdtm/core.c+14−8
@@ -153,12 +153,17 @@ static const struct crashtype *find_crashtype(const char *name) · 152 unmodified lines
153153 /*
154154 * This is forced noinline just so it distinctly shows up in the stackdump
155155 * which makes validation of expected lkdtm crashes easier.
156+ *
157+ * NOTE: having a valid return value helps prevent the compiler from doing
158+ * tail call optimizations and taking this out of the stack trace.
156159 */
157−static noinline void lkdtm_do_action(const struct crashtype *crashtype)
160+static noinline int lkdtm_do_action(const struct crashtype *crashtype)
158161 {
159162 if (WARN_ON(!crashtype || !crashtype->func))
160− return;
163+ return -EINVAL;
161164 crashtype->func();
165+
166+ return 0;
162167 }
163168
164169 static int lkdtm_register_cpoint(struct crashpoint *crashpoint,
@@ -167,10 +172,8 @@ static int lkdtm_register_cpoint(struct crashpoint *crashpoint, · 2 unmodified lines
167172 int ret;
168173
169174 /* If this doesn't have a symbol, just call immediately. */
170− if (!crashpoint->kprobe.symbol_name) {
171− lkdtm_do_action(crashtype);
172− return 0;
173− }
175+ if (!crashpoint->kprobe.symbol_name)
176+ return lkdtm_do_action(crashtype);
174177
175178 if (lkdtm_kprobe != NULL)
176179 unregister_kprobe(lkdtm_kprobe);
@@ -216,7 +219,7 @@ static int lkdtm_kprobe_handler(struct kprobe *kp, struct pt_regs *regs) · 39 unmodified lines
216219 spin_unlock_irqrestore(&crash_count_lock, flags);
217220
218221 if (do_it)
219− lkdtm_do_action(lkdtm_crashtype);
222+ return lkdtm_do_action(lkdtm_crashtype);
220223
221224 return 0;
222225 }
@@ -303,6 +306,7 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf, · 80 unmodified lines
303306 {
304307 const struct crashtype *crashtype;
305308 char *buf;
309+ int err;
306310
307311 if (count >= PAGE_SIZE)
308312 return -EINVAL;
@@ -326,9 +330,11 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf, · 17 unmodified lines
326330 return -EINVAL;
327331
328332 pr_info("Performing direct entry %s\n", crashtype->name);
329− lkdtm_do_action(crashtype);
333+ err = lkdtm_do_action(crashtype);
330334 *off += count;
331335
336+ if (err)
337+ return err;
332338 return count;
333339 }
334340
drivers/misc/vmw_vmci/vmci_datagram.c+6−4
@@ -224,8 +224,8 @@ static int dg_dispatch_as_host(u32 context_id, struct vmci_datagram *dg) · 223 unmodified lines
224224 return VMCI_ERROR_NO_MEM;
225225 }
226226
227− dg_info = kmalloc(sizeof(*dg_info) +
228− (size_t) dg->payload_size, GFP_ATOMIC);
227+ dg_info = kmalloc(struct_size(dg_info, msg_payload, dg->payload_size),
228+ GFP_ATOMIC);
229229 if (!dg_info) {
230230 atomic_dec(&delayed_dg_host_queue_size);
231231 vmci_resource_put(resource);
@@ -234,7 +234,8 @@ static int dg_dispatch_as_host(u32 context_id, struct vmci_datagram *dg) · 2 unmodified lines
234234
235235 dg_info->in_dg_host_queue = true;
236236 dg_info->entry = dst_entry;
237− memcpy(&dg_info->msg, dg, dg_size);
237+ dg_info->msg = *dg;
238+ memcpy(&dg_info->msg_payload, dg + 1, dg->payload_size);
238239
239240 INIT_WORK(&dg_info->work, dg_delayed_dispatch);
240241 schedule_work(&dg_info->work);
@@ -377,7 +378,8 @@ int vmci_datagram_invoke_guest_handler(struct vmci_datagram *dg) · 136 unmodified lines
377378
378379 dg_info->in_dg_host_queue = false;
379380 dg_info->entry = dst_entry;
380− memcpy(&dg_info->msg, dg, VMCI_DG_SIZE(dg));
381+ dg_info->msg = *dg;
382+ memcpy(&dg_info->msg_payload, dg + 1, dg->payload_size);
381383
382384 INIT_WORK(&dg_info->work, dg_delayed_dispatch);
383385 schedule_work(&dg_info->work);
fs/namei.c+1−1
@@ -17,8 +17,8 @@ · 16 unmodified lines
1717
1818 #include <linux/init.h>
1919 #include <linux/export.h>
20−#include <linux/kernel.h>
2120 #include <linux/slab.h>
21+#include <linux/wordpart.h>
2222 #include <linux/fs.h>
2323 #include <linux/filelock.h>
2424 #include <linux/namei.h>
include/asm-generic/word-at-a-time.h+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
22 #ifndef _ASM_WORD_AT_A_TIME_H
33 #define _ASM_WORD_AT_A_TIME_H
44
5−#include <linux/kernel.h>
5+#include <linux/bitops.h>
6+#include <linux/wordpart.h>
67 #include <asm/byteorder.h>
78
89 #ifdef __BIG_ENDIAN
include/linux/compiler.h+39−0
@@ -231,6 +231,45 @@ static inline void *offset_to_ptr(const int *off) · 230 unmodified lines
231231 * This returns a constant expression while determining if an argument is
232232 * a constant expression, most importantly without evaluating the argument.
233233 * Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>
234+ *
235+ * Details:
236+ * - sizeof() return an integer constant expression, and does not evaluate
237+ * the value of its operand; it only examines the type of its operand.
238+ * - The results of comparing two integer constant expressions is also
239+ * an integer constant expression.
240+ * - The first literal "8" isn't important. It could be any literal value.
241+ * - The second literal "8" is to avoid warnings about unaligned pointers;
242+ * this could otherwise just be "1".
243+ * - (long)(x) is used to avoid warnings about 64-bit types on 32-bit
244+ * architectures.
245+ * - The C Standard defines "null pointer constant", "(void *)0", as
246+ * distinct from other void pointers.
247+ * - If (x) is an integer constant expression, then the "* 0l" resolves
248+ * it into an integer constant expression of value 0. Since it is cast to
249+ * "void *", this makes the second operand a null pointer constant.
250+ * - If (x) is not an integer constant expression, then the second operand
251+ * resolves to a void pointer (but not a null pointer constant: the value
252+ * is not an integer constant 0).
253+ * - The conditional operator's third operand, "(int *)8", is an object
254+ * pointer (to type "int").
255+ * - The behavior (including the return type) of the conditional operator
256+ * ("operand1 ? operand2 : operand3") depends on the kind of expressions
257+ * given for the second and third operands. This is the central mechanism
258+ * of the macro:
259+ * - When one operand is a null pointer constant (i.e. when x is an integer
260+ * constant expression) and the other is an object pointer (i.e. our
261+ * third operand), the conditional operator returns the type of the
262+ * object pointer operand (i.e. "int *). Here, within the sizeof(), we
263+ * would then get:
264+ * sizeof(*((int *)(...)) == sizeof(int) == 4
265+ * - When one operand is a void pointer (i.e. when x is not an integer
266+ * constant expression) and the other is an object pointer (i.e. our
267+ * third operand), the conditional operator returns a "void *" type.
268+ * Here, within the sizeof(), we would then get:
269+ * sizeof(*((void *)(...)) == sizeof(void) == 1
270+ * - The equality comparison to "sizeof(int)" therefore depends on (x):
271+ * sizeof(int) == sizeof(int) (x) was a constant expression
272+ * sizeof(int) != sizeof(void) (x) was not a constant expression
234273 */
235274 #define __is_constexpr(x) \
236275 (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))
include/linux/compiler_types.h+8−1
@@ -282,11 +282,18 @@ struct ftrace_likely_data { · 281 unmodified lines
282282 #define __no_sanitize_or_inline __always_inline
283283 #endif
284284
285+/* Do not trap wrapping arithmetic within an annotated function. */
286+#ifdef CONFIG_UBSAN_SIGNED_WRAP
287+# define __signed_wrap __attribute__((no_sanitize("signed-integer-overflow")))
288+#else
289+# define __signed_wrap
290+#endif
291+
285292 /* Section for code which can't be instrumented at all */
286293 #define __noinstr_section(section) \
287294 noinline notrace __attribute((__section__(section))) \
288295 __no_kcsan __no_sanitize_address __no_profile __no_sanitize_coverage \
289− __no_sanitize_memory
296+ __no_sanitize_memory __signed_wrap
290297
291298 #define noinstr __noinstr_section(".noinstr.text")
292299
include/linux/fortify-string.h+75−47
@@ -2,6 +2,7 @@ · 1 unmodified line
22 #ifndef _LINUX_FORTIFY_STRING_H_
33 #define _LINUX_FORTIFY_STRING_H_
44
5+#include <linux/bitfield.h>
56 #include <linux/bug.h>
67 #include <linux/const.h>
78 #include <linux/limits.h>
@@ -9,7 +10,46 @@ · 1 unmodified line
910 #define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable
1011 #define __RENAME(x) __asm__(#x)
1112
12−void fortify_panic(const char *name) __noreturn __cold;
13+#define FORTIFY_REASON_DIR(r) FIELD_GET(BIT(0), r)
14+#define FORTIFY_REASON_FUNC(r) FIELD_GET(GENMASK(7, 1), r)
15+#define FORTIFY_REASON(func, write) (FIELD_PREP(BIT(0), write) | \
16+ FIELD_PREP(GENMASK(7, 1), func))
17+
18+#ifndef fortify_panic
19+# define fortify_panic(func, write, avail, size, retfail) \
20+ __fortify_panic(FORTIFY_REASON(func, write), avail, size)
21+#endif
22+
23+#define FORTIFY_READ 0
24+#define FORTIFY_WRITE 1
25+
26+#define EACH_FORTIFY_FUNC(macro) \
27+ macro(strncpy), \
28+ macro(strnlen), \
29+ macro(strlen), \
30+ macro(strscpy), \
31+ macro(strlcat), \
32+ macro(strcat), \
33+ macro(strncat), \
34+ macro(memset), \
35+ macro(memcpy), \
36+ macro(memmove), \
37+ macro(memscan), \
38+ macro(memcmp), \
39+ macro(memchr), \
40+ macro(memchr_inv), \
41+ macro(kmemdup), \
42+ macro(strcpy), \
43+ macro(UNKNOWN),
44+
45+#define MAKE_FORTIFY_FUNC(func) FORTIFY_FUNC_##func
46+
47+enum fortify_func {
48+ EACH_FORTIFY_FUNC(MAKE_FORTIFY_FUNC)
49+};
50+
51+void __fortify_report(const u8 reason, const size_t avail, const size_t size);
52+void __fortify_panic(const u8 reason, const size_t avail, const size_t size) __cold __noreturn;
1353 void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)");
1454 void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)");
1555 void __read_overflow2_field(size_t avail, size_t wanted) __compiletime_warning("detected read beyond size of field (2nd parameter); maybe use struct_group()?");
@@ -143,7 +183,7 @@ char *strncpy(char * const POS p, const char *q, __kernel_size_t size) · 127 unmodified lines
143183 if (__compiletime_lessthan(p_size, size))
144184 __write_overflow();
145185 if (p_size < size)
146− fortify_panic(__func__);
186+ fortify_panic(FORTIFY_FUNC_strncpy, FORTIFY_WRITE, p_size, size, p);
147187 return __underlying_strncpy(p, q, size);
148188 }
149189
@@ -174,7 +214,7 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size · 24 unmodified lines
174214 /* Do not check characters beyond the end of p. */
175215 ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
176216 if (p_size <= ret && maxlen != ret)
177− fortify_panic(__func__);
217+ fortify_panic(FORTIFY_FUNC_strnlen, FORTIFY_READ, p_size, ret + 1, ret);
178218 return ret;
179219 }
180220
@@ -210,31 +250,13 @@ __kernel_size_t __fortify_strlen(const char * const POS p) · 29 unmodified lines
210250 return __underlying_strlen(p);
211251 ret = strnlen(p, p_size);
212252 if (p_size <= ret)
213− fortify_panic(__func__);
253+ fortify_panic(FORTIFY_FUNC_strlen, FORTIFY_READ, p_size, ret + 1, ret);
214254 return ret;
215255 }
216256
217257 /* Defined after fortified strnlen() to reuse it. */
218−extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy);
219−/**
220− * strscpy - Copy a C-string into a sized buffer
221− *
222− * @p: Where to copy the string to
223− * @q: Where to copy the string from
224− * @size: Size of destination buffer
225− *
226− * Copy the source string @q, or as much of it as fits, into the destination
227− * @p buffer. The behavior is undefined if the string buffers overlap. The
228− * destination @p buffer is always NUL terminated, unless it's zero-sized.
229− *
230− * Preferred to strncpy() since it always returns a valid string, and
231− * doesn't unnecessarily force the tail of the destination buffer to be
232− * zero padded. If padding is desired please use strscpy_pad().
233− *
234− * Returns the number of characters copied in @p (not including the
235− * trailing %NUL) or -E2BIG if @size is 0 or the copy of @q was truncated.
236− */
237−__FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, size_t size)
258+extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(sized_strscpy);
259+__FORTIFY_INLINE ssize_t sized_strscpy(char * const POS p, const char * const POS q, size_t size)
238260 {
239261 /* Use string size rather than possible enclosing struct size. */
240262 const size_t p_size = __member_size(p);
@@ -278,8 +300,8 @@ __FORTIFY_INLINE ssize_t strscpy(char * const POS p, const char * const POS q, s · 37 unmodified lines
278300 * Generate a runtime write overflow error if len is greater than
279301 * p_size.
280302 */
281− if (len > p_size)
282− fortify_panic(__func__);
303+ if (p_size < len)
304+ fortify_panic(FORTIFY_FUNC_strscpy, FORTIFY_WRITE, p_size, len, -E2BIG);
283305
284306 /*
285307 * We can now safely call vanilla strscpy because we are protected from:
@@ -337,7 +359,7 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) · 51 unmodified lines
337359
338360 /* Give up if string is already overflowed. */
339361 if (p_size <= p_len)
340− fortify_panic(__func__);
362+ fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_READ, p_size, p_len + 1, wanted);
341363
342364 if (actual >= avail) {
343365 copy_len = avail - p_len - 1;
@@ -346,7 +368,7 @@ size_t strlcat(char * const POS p, const char * const POS q, size_t avail) · 2 unmodified lines
346368
347369 /* Give up if copy will overflow. */
348370 if (p_size <= actual)
349− fortify_panic(__func__);
371+ fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_WRITE, p_size, actual + 1, wanted);
350372 __underlying_memcpy(p + p_len, q, copy_len);
351373 p[actual] = '\0';
352374
@@ -373,9 +395,10 @@ __FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2) · 20 unmodified lines
373395 char *strcat(char * const POS p, const char *q)
374396 {
375397 const size_t p_size = __member_size(p);
398+ const size_t wanted = strlcat(p, q, p_size);
376399
377− if (strlcat(p, q, p_size) >= p_size)
378− fortify_panic(__func__);
400+ if (p_size <= wanted)
401+ fortify_panic(FORTIFY_FUNC_strcat, FORTIFY_WRITE, p_size, wanted + 1, p);
379402 return p;
380403 }
381404
@@ -404,20 +427,21 @@ char *strncat(char * const POS p, const char * const POS q, __kernel_size_t coun · 22 unmodified lines
404427 {
405428 const size_t p_size = __member_size(p);
406429 const size_t q_size = __member_size(q);
407− size_t p_len, copy_len;
430+ size_t p_len, copy_len, total;
408431
409432 if (p_size == SIZE_MAX && q_size == SIZE_MAX)
410433 return __underlying_strncat(p, q, count);
411434 p_len = strlen(p);
412435 copy_len = strnlen(q, count);
413− if (p_size < p_len + copy_len + 1)
414− fortify_panic(__func__);
436+ total = p_len + copy_len + 1;
437+ if (p_size < total)
438+ fortify_panic(FORTIFY_FUNC_strncat, FORTIFY_WRITE, p_size, total, p);
415439 __underlying_memcpy(p + p_len, q, copy_len);
416440 p[p_len + copy_len] = '\0';
417441 return p;
418442 }
419443
420−__FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size,
444+__FORTIFY_INLINE bool fortify_memset_chk(__kernel_size_t size,
421445 const size_t p_size,
422446 const size_t p_size_field)
423447 {
@@ -452,7 +476,8 @@ __FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size, · 28 unmodified lines
452476 * lengths are unknown.)
453477 */
454478 if (p_size != SIZE_MAX && p_size < size)
455− fortify_panic("memset");
479+ fortify_panic(FORTIFY_FUNC_memset, FORTIFY_WRITE, p_size, size, true);
480+ return false;
456481 }
457482
458483 #define __fortify_memset_chk(p, c, size, p_size, p_size_field) ({ \
@@ -506,7 +531,7 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, · 47 unmodified lines
506531 const size_t q_size,
507532 const size_t p_size_field,
508533 const size_t q_size_field,
509− const char *func)
534+ const u8 func)
510535 {
511536 if (__builtin_constant_p(size)) {
512537 /*
@@ -550,9 +575,10 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, · 37 unmodified lines
550575 * (The SIZE_MAX test is to optimize away checks where the buffer
551576 * lengths are unknown.)
552577 */
553− if ((p_size != SIZE_MAX && p_size < size) ||
554− (q_size != SIZE_MAX && q_size < size))
555− fortify_panic(func);
578+ if (p_size != SIZE_MAX && p_size < size)
579+ fortify_panic(func, FORTIFY_WRITE, p_size, size, true);
580+ else if (q_size != SIZE_MAX && q_size < size)
581+ fortify_panic(func, FORTIFY_READ, p_size, size, true);
556582
557583 /*
558584 * Warn when writing beyond destination field size.
@@ -585,7 +611,7 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, · 26 unmodified lines
585611 const size_t __q_size_field = (q_size_field); \
586612 WARN_ONCE(fortify_memcpy_chk(__fortify_size, __p_size, \
587613 __q_size, __p_size_field, \
588− __q_size_field, #op), \
614+ __q_size_field, FORTIFY_FUNC_ ##op), \
589615 #op ": detected field-spanning write (size %zu) of single %s (size %zu)\n", \
590616 __fortify_size, \
591617 "field \"" #p "\" at " FILE_LINE, \
@@ -652,7 +678,7 @@ __FORTIFY_INLINE void *memscan(void * const POS0 p, int c, __kernel_size_t size) · 60 unmodified lines
652678 if (__compiletime_lessthan(p_size, size))
653679 __read_overflow();
654680 if (p_size < size)
655− fortify_panic(__func__);
681+ fortify_panic(FORTIFY_FUNC_memscan, FORTIFY_READ, p_size, size, NULL);
656682 return __real_memscan(p, c, size);
657683 }
658684
@@ -668,8 +694,10 @@ int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t · 9 unmodified lines
668694 if (__compiletime_lessthan(q_size, size))
669695 __read_overflow2();
670696 }
671− if (p_size < size || q_size < size)
672− fortify_panic(__func__);
697+ if (p_size < size)
698+ fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ, p_size, size, INT_MIN);
699+ else if (q_size < size)
700+ fortify_panic(FORTIFY_FUNC_memcmp, FORTIFY_READ, q_size, size, INT_MIN);
673701 return __underlying_memcmp(p, q, size);
674702 }
675703
@@ -681,7 +709,7 @@ void *memchr(const void * const POS0 p, int c, __kernel_size_t size) · 5 unmodified lines
681709 if (__compiletime_lessthan(p_size, size))
682710 __read_overflow();
683711 if (p_size < size)
684− fortify_panic(__func__);
712+ fortify_panic(FORTIFY_FUNC_memchr, FORTIFY_READ, p_size, size, NULL);
685713 return __underlying_memchr(p, c, size);
686714 }
687715
@@ -693,7 +721,7 @@ __FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size) · 5 unmodified lines
693721 if (__compiletime_lessthan(p_size, size))
694722 __read_overflow();
695723 if (p_size < size)
696− fortify_panic(__func__);
724+ fortify_panic(FORTIFY_FUNC_memchr_inv, FORTIFY_READ, p_size, size, NULL);
697725 return __real_memchr_inv(p, c, size);
698726 }
699727
@@ -706,7 +734,7 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp · 6 unmodified lines
706734 if (__compiletime_lessthan(p_size, size))
707735 __read_overflow();
708736 if (p_size < size)
709− fortify_panic(__func__);
737+ fortify_panic(FORTIFY_FUNC_kmemdup, FORTIFY_READ, p_size, size, NULL);
710738 return __real_kmemdup(p, size, gfp);
711739 }
712740
@@ -743,7 +771,7 @@ char *strcpy(char * const POS p, const char * const POS q) · 30 unmodified lines
743771 __write_overflow();
744772 /* Run-time check for dynamic size overflow. */
745773 if (p_size < size)
746− fortify_panic(__func__);
774+ fortify_panic(FORTIFY_FUNC_strcpy, FORTIFY_WRITE, p_size, size, p);
747775 __underlying_memcpy(p, q, size);
748776 return p;
749777 }
include/linux/kernel.h+2−42
@@ -33,20 +33,14 @@ · 32 unmodified lines
3333 #include <linux/sprintf.h>
3434 #include <linux/static_call_types.h>
3535 #include <linux/instruction_pointer.h>
36+#include <linux/wordpart.h>
37+
3638 #include <asm/byteorder.h>
3739
3840 #include <uapi/linux/kernel.h>
3941
4042 #define STACK_MAGIC 0xdeadbeef
4143
42−/**
43− * REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value
44− * @x: value to repeat
45− *
46− * NOTE: @x is not checked for > 0xff; larger values produce odd results.
47− */
48−#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
49−
5044 /* generic data direction definitions */
5145 #define READ 0
5246 #define WRITE 1
@@ -60,34 +54,6 @@ · 7 unmodified lines
6054 } \
6155 )
6256
63−/**
64− * upper_32_bits - return bits 32-63 of a number
65− * @n: the number we're accessing
66− *
67− * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress
68− * the "right shift count >= width of type" warning when that quantity is
69− * 32-bits.
70− */
71−#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
72−
73−/**
74− * lower_32_bits - return bits 0-31 of a number
75− * @n: the number we're accessing
76− */
77−#define lower_32_bits(n) ((u32)((n) & 0xffffffff))
78−
79−/**
80− * upper_16_bits - return bits 16-31 of a number
81− * @n: the number we're accessing
82− */
83−#define upper_16_bits(n) ((u16)((n) >> 16))
84−
85−/**
86− * lower_16_bits - return bits 0-15 of a number
87− * @n: the number we're accessing
88− */
89−#define lower_16_bits(n) ((u16)((n) & 0xffff))
90−
9157 struct completion;
9258 struct user;
9359
@@ -199,12 +165,6 @@ static inline void might_fault(void) { } · 105 unmodified lines
199165
200166 void do_exit(long error_code) __noreturn;
201167
202−extern int get_option(char **str, int *pint);
203−extern char *get_options(const char *str, int nints, int *ints);
204−extern unsigned long long memparse(const char *ptr, char **retptr);
205−extern bool parse_option_str(const char *str, const char *option);
206−extern char *next_arg(char *args, char **param, char **val);
207−
208168 extern int core_kernel_text(unsigned long addr);
209169 extern int __kernel_text_address(unsigned long addr);
210170 extern int kernel_text_address(unsigned long addr);
include/linux/overflow.h+97−18
@@ -31,8 +31,10 @@ · 30 unmodified lines
3131 * credit to Christian Biere.
3232 */
3333 #define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))
34−#define type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
35−#define type_min(T) ((T)((T)-type_max(T)-(T)1))
34+#define __type_max(T) ((T)((__type_half_max(T) - 1) + __type_half_max(T)))
35+#define type_max(t) __type_max(typeof(t))
36+#define __type_min(T) ((T)((T)-type_max(T)-(T)1))
37+#define type_min(t) __type_min(typeof(t))
3638
3739 /*
3840 * Avoids triggering -Wtype-limits compilation warning,
@@ -57,45 +59,122 @@ static inline bool __must_check __must_check_overflow(bool overflow) · 18 unmodified lines
5759 * @b: second addend
5860 * @d: pointer to store sum
5961 *
60− * Returns 0 on success.
62+ * Returns true on wrap-around, false otherwise.
6163 *
62− * *@d holds the results of the attempted addition, but is not considered
63− * "safe for use" on a non-zero return value, which indicates that the
64− * sum has overflowed or been truncated.
64+ * *@d holds the results of the attempted addition, regardless of whether
65+ * wrap-around occurred.
6566 */
6667 #define check_add_overflow(a, b, d) \
6768 __must_check_overflow(__builtin_add_overflow(a, b, d))
6869
70+/**
71+ * wrapping_add() - Intentionally perform a wrapping addition
72+ * @type: type for result of calculation
73+ * @a: first addend
74+ * @b: second addend
75+ *
76+ * Return the potentially wrapped-around addition without
77+ * tripping any wrap-around sanitizers that may be enabled.
78+ */
79+#define wrapping_add(type, a, b) \
80+ ({ \
81+ type __val; \
82+ __builtin_add_overflow(a, b, &__val); \
83+ __val; \
84+ })
85+
86+/**
87+ * wrapping_assign_add() - Intentionally perform a wrapping increment assignment
88+ * @var: variable to be incremented
89+ * @offset: amount to add
90+ *
91+ * Increments @var by @offset with wrap-around. Returns the resulting
92+ * value of @var. Will not trip any wrap-around sanitizers.
93+ *
94+ * Returns the new value of @var.
95+ */
96+#define wrapping_assign_add(var, offset) \
97+ ({ \
98+ typeof(var) *__ptr = &(var); \
99+ *__ptr = wrapping_add(typeof(var), *__ptr, offset); \
100+ })
101+
69102 /**
70103 * check_sub_overflow() - Calculate subtraction with overflow checking
71104 * @a: minuend; value to subtract from
72105 * @b: subtrahend; value to subtract from @a
73106 * @d: pointer to store difference
74107 *
75− * Returns 0 on success.
108+ * Returns true on wrap-around, false otherwise.
76109 *
77− * *@d holds the results of the attempted subtraction, but is not considered
78− * "safe for use" on a non-zero return value, which indicates that the
79− * difference has underflowed or been truncated.
110+ * *@d holds the results of the attempted subtraction, regardless of whether
111+ * wrap-around occurred.
80112 */
81113 #define check_sub_overflow(a, b, d) \
82114 __must_check_overflow(__builtin_sub_overflow(a, b, d))
83115
116+/**
117+ * wrapping_sub() - Intentionally perform a wrapping subtraction
118+ * @type: type for result of calculation
119+ * @a: minuend; value to subtract from
120+ * @b: subtrahend; value to subtract from @a
121+ *
122+ * Return the potentially wrapped-around subtraction without
123+ * tripping any wrap-around sanitizers that may be enabled.
124+ */
125+#define wrapping_sub(type, a, b) \
126+ ({ \
127+ type __val; \
128+ __builtin_sub_overflow(a, b, &__val); \
129+ __val; \
130+ })
131+
132+/**
133+ * wrapping_assign_sub() - Intentionally perform a wrapping decrement assign
134+ * @var: variable to be decremented
135+ * @offset: amount to subtract
136+ *
137+ * Decrements @var by @offset with wrap-around. Returns the resulting
138+ * value of @var. Will not trip any wrap-around sanitizers.
139+ *
140+ * Returns the new value of @var.
141+ */
142+#define wrapping_assign_sub(var, offset) \
143+ ({ \
144+ typeof(var) *__ptr = &(var); \
145+ *__ptr = wrapping_sub(typeof(var), *__ptr, offset); \
146+ })
147+
84148 /**
85149 * check_mul_overflow() - Calculate multiplication with overflow checking
86150 * @a: first factor
87151 * @b: second factor
88152 * @d: pointer to store product
89153 *
90− * Returns 0 on success.
154+ * Returns true on wrap-around, false otherwise.
91155 *
92− * *@d holds the results of the attempted multiplication, but is not
93− * considered "safe for use" on a non-zero return value, which indicates
94− * that the product has overflowed or been truncated.
156+ * *@d holds the results of the attempted multiplication, regardless of whether
157+ * wrap-around occurred.
95158 */
96159 #define check_mul_overflow(a, b, d) \
97160 __must_check_overflow(__builtin_mul_overflow(a, b, d))
98161
162+/**
163+ * wrapping_mul() - Intentionally perform a wrapping multiplication
164+ * @type: type for result of calculation
165+ * @a: first factor
166+ * @b: second factor
167+ *
168+ * Return the potentially wrapped-around multiplication without
169+ * tripping any wrap-around sanitizers that may be enabled.
170+ */
171+#define wrapping_mul(type, a, b) \
172+ ({ \
173+ type __val; \
174+ __builtin_mul_overflow(a, b, &__val); \
175+ __val; \
176+ })
177+
99178 /**
100179 * check_shl_overflow() - Calculate a left-shifted value and check overflow
101180 * @a: Value to be shifted
@@ -120,7 +199,7 @@ static inline bool __must_check __must_check_overflow(bool overflow) · 18 unmodified lines
120199 typeof(a) _a = a; \
121200 typeof(s) _s = s; \
122201 typeof(d) _d = d; \
123− u64 _a_full = _a; \
202+ unsigned long long _a_full = _a; \
124203 unsigned int _to_shift = \
125204 is_non_negative(_s) && _s < 8 * sizeof(*d) ? _s : 0; \
126205 *_d = (_a_full << _to_shift); \
@@ -130,10 +209,10 @@ static inline bool __must_check __must_check_overflow(bool overflow) · 3 unmodified lines
130209
131210 #define __overflows_type_constexpr(x, T) ( \
132211 is_unsigned_type(typeof(x)) ? \
133− (x) > type_max(typeof(T)) : \
212+ (x) > type_max(T) : \
134213 is_unsigned_type(typeof(T)) ? \
135− (x) < 0 || (x) > type_max(typeof(T)) : \
136− (x) < type_min(typeof(T)) || (x) > type_max(typeof(T)))
214+ (x) < 0 || (x) > type_max(T) : \
215+ (x) < type_min(T) || (x) > type_max(T))
137216
138217 #define __overflows_type(x, T) ({ \
139218 typeof(T) v = 0; \
include/linux/refcount.h+6−3
@@ -136,7 +136,8 @@ static inline unsigned int refcount_read(const refcount_t *r) · 135 unmodified lines
136136 return atomic_read(&r->refs);
137137 }
138138
139−static inline __must_check bool __refcount_add_not_zero(int i, refcount_t *r, int *oldp)
139+static inline __must_check __signed_wrap
140+bool __refcount_add_not_zero(int i, refcount_t *r, int *oldp)
140141 {
141142 int old = refcount_read(r);
142143
@@ -177,7 +178,8 @@ static inline __must_check bool refcount_add_not_zero(int i, refcount_t *r) · 34 unmodified lines
177178 return __refcount_add_not_zero(i, r, NULL);
178179 }
179180
180−static inline void __refcount_add(int i, refcount_t *r, int *oldp)
181+static inline __signed_wrap
182+void __refcount_add(int i, refcount_t *r, int *oldp)
181183 {
182184 int old = atomic_fetch_add_relaxed(i, &r->refs);
183185
@@ -256,7 +258,8 @@ static inline void refcount_inc(refcount_t *r) · 72 unmodified lines
256258 __refcount_inc(r, NULL);
257259 }
258260
259−static inline __must_check bool __refcount_sub_and_test(int i, refcount_t *r, int *oldp)
261+static inline __must_check __signed_wrap
262+bool __refcount_sub_and_test(int i, refcount_t *r, int *oldp)
260263 {
261264 int old = atomic_fetch_sub_release(i, &r->refs);
262265
include/linux/string.h+81−5
@@ -2,6 +2,7 @@ · 1 unmodified line
22 #ifndef _LINUX_STRING_H_
33 #define _LINUX_STRING_H_
44
5+#include <linux/args.h>
56 #include <linux/array_size.h>
67 #include <linux/compiler.h> /* for inline */
78 #include <linux/types.h> /* for size_t */
@@ -66,12 +67,79 @@ extern char * strcpy(char *,const char *); · 58 unmodified lines
6667 #ifndef __HAVE_ARCH_STRNCPY
6768 extern char * strncpy(char *,const char *, __kernel_size_t);
6869 #endif
69−#ifndef __HAVE_ARCH_STRSCPY
70−ssize_t strscpy(char *, const char *, size_t);
71−#endif
70+ssize_t sized_strscpy(char *, const char *, size_t);
71+
72+/*
73+ * The 2 argument style can only be used when dst is an array with a
74+ * known size.
75+ */
76+#define __strscpy0(dst, src, ...) \
77+ sized_strscpy(dst, src, sizeof(dst) + __must_be_array(dst))
78+#define __strscpy1(dst, src, size) sized_strscpy(dst, src, size)
79+
80+#define __strscpy_pad0(dst, src, ...) \
81+ sized_strscpy_pad(dst, src, sizeof(dst) + __must_be_array(dst))
82+#define __strscpy_pad1(dst, src, size) sized_strscpy_pad(dst, src, size)
83+
84+/**
85+ * strscpy - Copy a C-string into a sized buffer
86+ * @dst: Where to copy the string to
87+ * @src: Where to copy the string from
88+ * @...: Size of destination buffer (optional)
89+ *
90+ * Copy the source string @src, or as much of it as fits, into the
91+ * destination @dst buffer. The behavior is undefined if the string
92+ * buffers overlap. The destination @dst buffer is always NUL terminated,
93+ * unless it's zero-sized.
94+ *
95+ * The size argument @... is only required when @dst is not an array, or
96+ * when the copy needs to be smaller than sizeof(@dst).
97+ *
98+ * Preferred to strncpy() since it always returns a valid string, and
99+ * doesn't unnecessarily force the tail of the destination buffer to be
100+ * zero padded. If padding is desired please use strscpy_pad().
101+ *
102+ * Returns the number of characters copied in @dst (not including the
103+ * trailing %NUL) or -E2BIG if @size is 0 or the copy from @src was
104+ * truncated.
105+ */
106+#define strscpy(dst, src, ...) \
107+ CONCATENATE(__strscpy, COUNT_ARGS(__VA_ARGS__))(dst, src, __VA_ARGS__)
108+
109+#define sized_strscpy_pad(dest, src, count) ({ \
110+ char *__dst = (dest); \
111+ const char *__src = (src); \
112+ const size_t __count = (count); \
113+ ssize_t __wrote; \
114+ \
115+ __wrote = sized_strscpy(__dst, __src, __count); \
116+ if (__wrote >= 0 && __wrote < __count) \
117+ memset(__dst + __wrote + 1, 0, __count - __wrote - 1); \
118+ __wrote; \
119+})
72120
73−/* Wraps calls to strscpy()/memset(), no arch specific code required */
74−ssize_t strscpy_pad(char *dest, const char *src, size_t count);
121+/**
122+ * strscpy_pad() - Copy a C-string into a sized buffer
123+ * @dst: Where to copy the string to
124+ * @src: Where to copy the string from
125+ * @...: Size of destination buffer
126+ *
127+ * Copy the string, or as much of it as fits, into the dest buffer. The
128+ * behavior is undefined if the string buffers overlap. The destination
129+ * buffer is always %NUL terminated, unless it's zero-sized.
130+ *
131+ * If the source string is shorter than the destination buffer, the
132+ * remaining bytes in the buffer will be filled with %NUL bytes.
133+ *
134+ * For full explanation of why you may want to consider using the
135+ * 'strscpy' functions please see the function docstring for strscpy().
136+ *
137+ * Returns:
138+ * * The number of characters copied (not including the trailing %NULs)
139+ * * -E2BIG if count is 0 or @src was truncated.
140+ */
141+#define strscpy_pad(dst, src, ...) \
142+ CONCATENATE(__strscpy_pad, COUNT_ARGS(__VA_ARGS__))(dst, src, __VA_ARGS__)
75143
76144 #ifndef __HAVE_ARCH_STRCAT
77145 extern char * strcat(char *, const char *);
@@ -219,9 +287,17 @@ extern void *kvmemdup(const void *src, size_t len, gfp_t gfp) __realloc_size(2); · 141 unmodified lines
219287 extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp);
220288 extern void *kmemdup_array(const void *src, size_t element_size, size_t count, gfp_t gfp);
221289
290+/* lib/argv_split.c */
222291 extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
223292 extern void argv_free(char **argv);
224293
294+/* lib/cmdline.c */
295+extern int get_option(char **str, int *pint);
296+extern char *get_options(const char *str, int nints, int *ints);
297+extern unsigned long long memparse(const char *ptr, char **retptr);
298+extern bool parse_option_str(const char *str, const char *option);
299+extern char *next_arg(char *args, char **param, char **val);
300+
225301 extern bool sysfs_streq(const char *s1, const char *s2);
226302 int match_string(const char * const *array, size_t n, const char *string);
227303 int __sysfs_match_string(const char * const *array, size_t n, const char *s);
include/linux/string_choices.h+11−0
@@ -42,4 +42,15 @@ static inline const char *str_yes_no(bool v) · 41 unmodified lines
4242 return v ? "yes" : "no";
4343 }
4444
45+/**
46+ * str_plural - Return the simple pluralization based on English counts
47+ * @num: Number used for deciding pluralization
48+ *
49+ * If @num is 1, returns empty string, otherwise returns "s".
50+ */
51+static inline const char *str_plural(size_t num)
52+{
53+ return num == 1 ? "" : "s";
54+}
55+
4556 #endif
include/linux/string_helpers.h+7−3
@@ -17,14 +17,18 @@ static inline bool string_is_terminated(const char *s, int len) · 16 unmodified lines
1717 return memchr(s, '\0', len) ? true : false;
1818 }
1919
20−/* Descriptions of the types of units to
21− * print in */
20+/* Descriptions of the types of units to print in */
2221 enum string_size_units {
2322 STRING_UNITS_10, /* use powers of 10^3 (standard SI) */
2423 STRING_UNITS_2, /* use binary powers of 2^10 */
24+ STRING_UNITS_MASK = BIT(0),
25+
26+ /* Modifiers */
27+ STRING_UNITS_NO_SPACE = BIT(30),
28+ STRING_UNITS_NO_BYTES = BIT(31),
2529 };
2630
27−int string_get_size(u64 size, u64 blk_size, enum string_size_units units,
31+int string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
2832 char *buf, int len);
2933
3034 int parse_int_array_user(const char __user *from, size_t count, int **array);
include/linux/wordpart.h+42−0
@@ -0,0 +1,42 @@
1+/* SPDX-License-Identifier: GPL-2.0 */
2+
3+#ifndef _LINUX_WORDPART_H
4+#define _LINUX_WORDPART_H
5+
6+/**
7+ * upper_32_bits - return bits 32-63 of a number
8+ * @n: the number we're accessing
9+ *
10+ * A basic shift-right of a 64- or 32-bit quantity. Use this to suppress
11+ * the "right shift count >= width of type" warning when that quantity is
12+ * 32-bits.
13+ */
14+#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))
15+
16+/**
17+ * lower_32_bits - return bits 0-31 of a number
18+ * @n: the number we're accessing
19+ */
20+#define lower_32_bits(n) ((u32)((n) & 0xffffffff))
21+
22+/**
23+ * upper_16_bits - return bits 16-31 of a number
24+ * @n: the number we're accessing
25+ */
26+#define upper_16_bits(n) ((u16)((n) >> 16))
27+
28+/**
29+ * lower_16_bits - return bits 0-15 of a number
30+ * @n: the number we're accessing
31+ */
32+#define lower_16_bits(n) ((u16)((n) & 0xffff))
33+
34+/**
35+ * REPEAT_BYTE - repeat the value @x multiple times as an unsigned long value
36+ * @x: value to repeat
37+ *
38+ * NOTE: @x is not checked for > 0xff; larger values produce odd results.
39+ */
40+#define REPEAT_BYTE(x) ((~0ul / 0xff) * (x))
41+
42+#endif // _LINUX_WORDPART_H
kernel/configs/hardening.config+3−4
@@ -44,7 +44,9 @@ CONFIG_UBSAN_BOUNDS=y · 43 unmodified lines
4444 # CONFIG_UBSAN_BOOL
4545 # CONFIG_UBSAN_ENUM
4646 # CONFIG_UBSAN_ALIGNMENT
47−CONFIG_UBSAN_SANITIZE_ALL=y
47+
48+# Sampling-based heap out-of-bounds and use-after-free detection.
49+CONFIG_KFENCE=y
4850
4951 # Linked list integrity checking.
5052 CONFIG_LIST_HARDENED=y
@@ -93,6 +95,3 @@ CONFIG_SYN_COOKIES=y · 42 unmodified lines
9395
9496 # Attack surface reduction: Use the modern PTY interface (devpts) only.
9597 # CONFIG_LEGACY_PTYS is not set
96−
97−# Attack surface reduction: Use only modesetting video drivers.
98−# CONFIG_DRM_LEGACY is not set
kernel/printk/printk.c+0−11
@@ -598,17 +598,6 @@ static int check_syslog_permissions(int type, int source) · 597 unmodified lines
598598 if (syslog_action_restricted(type)) {
599599 if (capable(CAP_SYSLOG))
600600 goto ok;
601− /*
602− * For historical reasons, accept CAP_SYS_ADMIN too, with
603− * a warning.
604− */
605− if (capable(CAP_SYS_ADMIN)) {
606− pr_warn_once("%s (%d): Attempt to access syslog with "
607− "CAP_SYS_ADMIN but no CAP_SYSLOG "
608− "(deprecated).\n",
609− current->comm, task_pid_nr(current));
610− goto ok;
611− }
612601 return -EPERM;
613602 }
614603 ok:
lib/Kconfig.debug+9−5
@@ -2353,11 +2353,15 @@ config ASYNC_RAID6_TEST · 2352 unmodified lines
23532353 config TEST_HEXDUMP
23542354 tristate "Test functions located in the hexdump module at runtime"
23552355
2356−config STRING_SELFTEST
2357− tristate "Test string functions at runtime"
2356+config STRING_KUNIT_TEST
2357+ tristate "KUnit test string functions at runtime" if !KUNIT_ALL_TESTS
2358+ depends on KUNIT
2359+ default KUNIT_ALL_TESTS
23582360
2359−config TEST_STRING_HELPERS
2360− tristate "Test functions located in the string_helpers module at runtime"
2361+config STRING_HELPERS_KUNIT_TEST
2362+ tristate "KUnit test string helpers at runtime" if !KUNIT_ALL_TESTS
2363+ depends on KUNIT
2364+ default KUNIT_ALL_TESTS
23612365
23622366 config TEST_KSTRTOX
23632367 tristate "Test kstrto*() family of functions at runtime"
@@ -2749,7 +2753,7 @@ config STACKINIT_KUNIT_TEST · 385 unmodified lines
27492753
27502754 config FORTIFY_KUNIT_TEST
27512755 tristate "Test fortified str*() and mem*() function internals at runtime" if !KUNIT_ALL_TESTS
2752− depends on KUNIT && FORTIFY_SOURCE
2756+ depends on KUNIT
27532757 default KUNIT_ALL_TESTS
27542758 help
27552759 Builds unit tests for checking internals of FORTIFY_SOURCE as used
lib/Kconfig.ubsan+15−13
@@ -1,5 +1,5 @@
11 # SPDX-License-Identifier: GPL-2.0-only
2−config ARCH_HAS_UBSAN_SANITIZE_ALL
2+config ARCH_HAS_UBSAN
33 bool
44
55 menuconfig UBSAN
@@ -87,7 +87,6 @@ config UBSAN_LOCAL_BOUNDS · 81 unmodified lines
8787
8888 config UBSAN_SHIFT
8989 bool "Perform checking for bit-shift overflows"
90− default UBSAN
9190 depends on $(cc-option,-fsanitize=shift)
9291 help
9392 This option enables -fsanitize=shift which checks for bit-shift
@@ -116,6 +115,20 @@ config UBSAN_UNREACHABLE · 22 unmodified lines
116115 This option enables -fsanitize=unreachable which checks for control
117116 flow reaching an expected-to-be-unreachable position.
118117
118+config UBSAN_SIGNED_WRAP
119+ bool "Perform checking for signed arithmetic wrap-around"
120+ default UBSAN
121+ depends on !COMPILE_TEST
122+ depends on $(cc-option,-fsanitize=signed-integer-overflow)
123+ help
124+ This option enables -fsanitize=signed-integer-overflow which checks
125+ for wrap-around of any arithmetic operations with signed integers.
126+ This currently performs nearly no instrumentation due to the
127+ kernel's use of -fno-strict-overflow which converts all would-be
128+ arithmetic undefined behavior into wrap-around arithmetic. Future
129+ sanitizer versions will allow for wrap-around checking (rather than
130+ exclusively undefined behavior).
131+
119132 config UBSAN_BOOL
120133 bool "Perform checking for non-boolean values used as boolean"
121134 default UBSAN
@@ -142,17 +155,6 @@ config UBSAN_ALIGNMENT · 20 unmodified lines
142155 Enabling this option on architectures that support unaligned
143156 accesses may produce a lot of false positives.
144157
145−config UBSAN_SANITIZE_ALL
146− bool "Enable instrumentation for the entire kernel"
147− depends on ARCH_HAS_UBSAN_SANITIZE_ALL
148− default y
149− help
150− This option activates instrumentation for the entire kernel.
151− If you don't enable this option, you have to explicitly specify
152− UBSAN_SANITIZE := y for the files/directories you want to check for UB.
153− Enabling this option will get kernel image size increased
154− significantly.
155−
156158 config TEST_UBSAN
157159 tristate "Module for testing for undefined behavior detection"
158160 depends on m
lib/Makefile+5−2
@@ -49,9 +49,9 @@ obj-y += bcd.o sort.o parser.o debug_locks.o random32.o \ · 48 unmodified lines
4949 percpu-refcount.o rhashtable.o base64.o \
5050 once.o refcount.o rcuref.o usercopy.o errseq.o bucket_locks.o \
5151 generic-radix-tree.o bitmap-str.o
52−obj-$(CONFIG_STRING_SELFTEST) += test_string.o
52+obj-$(CONFIG_STRING_KUNIT_TEST) += string_kunit.o
5353 obj-y += string_helpers.o
54−obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o
54+obj-$(CONFIG_STRING_HELPERS_KUNIT_TEST) += string_helpers_kunit.o
5555 obj-y += hexdump.o
5656 obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
5757 obj-y += kstrtox.o
@@ -69,6 +69,7 @@ obj-$(CONFIG_HASH_KUNIT_TEST) += test_hash.o · 11 unmodified lines
6969 obj-$(CONFIG_TEST_IDA) += test_ida.o
7070 obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o
7171 CFLAGS_test_ubsan.o += $(call cc-disable-warning, vla)
72+CFLAGS_test_ubsan.o += $(call cc-disable-warning, unused-but-set-variable)
7273 UBSAN_SANITIZE_test_ubsan.o := y
7374 obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
7475 obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o
@@ -399,6 +400,8 @@ obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o · 324 unmodified lines
399400 CFLAGS_stackinit_kunit.o += $(call cc-disable-warning, switch-unreachable)
400401 obj-$(CONFIG_STACKINIT_KUNIT_TEST) += stackinit_kunit.o
401402 CFLAGS_fortify_kunit.o += $(call cc-disable-warning, unsequenced)
403+CFLAGS_fortify_kunit.o += $(call cc-disable-warning, stringop-overread)
404+CFLAGS_fortify_kunit.o += $(call cc-disable-warning, stringop-truncation)
402405 CFLAGS_fortify_kunit.o += $(DISABLE_STRUCTLEAK_PLUGIN)
403406 obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o
404407 obj-$(CONFIG_STRCAT_KUNIT_TEST) += strcat_kunit.o
lib/fortify_kunit.c+660−2
@@ -1,7 +1,7 @@
11 // SPDX-License-Identifier: GPL-2.0
22 /*
3− * Runtime test cases for CONFIG_FORTIFY_SOURCE that aren't expected to
4− * Oops the kernel on success. (For those, see drivers/misc/lkdtm/fortify.c)
3+ * Runtime test cases for CONFIG_FORTIFY_SOURCE. For testing memcpy(),
4+ * see FORTIFY_MEM_* tests in LKDTM (drivers/misc/lkdtm/fortify.c).
55 *
66 * For corner cases with UBSAN, try testing with:
77 *
@@ -15,17 +15,55 @@ · 7 unmodified lines
1515 */
1616 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1717
18+/* Redefine fortify_panic() to track failures. */
19+void fortify_add_kunit_error(int write);
20+#define fortify_panic(func, write, avail, size, retfail) do { \
21+ __fortify_report(FORTIFY_REASON(func, write), avail, size); \
22+ fortify_add_kunit_error(write); \
23+ return (retfail); \
24+} while (0)
25+
1826 #include <kunit/device.h>
1927 #include <kunit/test.h>
28+#include <kunit/test-bug.h>
2029 #include <linux/device.h>
2130 #include <linux/slab.h>
2231 #include <linux/string.h>
2332 #include <linux/vmalloc.h>
2433
34+/* Handle being built without CONFIG_FORTIFY_SOURCE */
35+#ifndef __compiletime_strlen
36+# define __compiletime_strlen __builtin_strlen
37+#endif
38+
39+static struct kunit_resource read_resource;
40+static struct kunit_resource write_resource;
41+static int fortify_read_overflows;
42+static int fortify_write_overflows;
43+
2544 static const char array_of_10[] = "this is 10";
2645 static const char *ptr_of_11 = "this is 11!";
2746 static char array_unknown[] = "compiler thinks I might change";
2847
48+void fortify_add_kunit_error(int write)
49+{
50+ struct kunit_resource *resource;
51+ struct kunit *current_test;
52+
53+ current_test = kunit_get_current_test();
54+ if (!current_test)
55+ return;
56+
57+ resource = kunit_find_named_resource(current_test,
58+ write ? "fortify_write_overflows"
59+ : "fortify_read_overflows");
60+ if (!resource)
61+ return;
62+
63+ (*(int *)resource->data)++;
64+ kunit_put_resource(resource);
65+}
66+
2967 static void known_sizes_test(struct kunit *test)
3068 {
3169 KUNIT_EXPECT_EQ(test, __compiletime_strlen("88888888"), 8);
@@ -308,6 +346,610 @@ DEFINE_ALLOC_SIZE_TEST_PAIR(kvmalloc) · 276 unmodified lines
308346 } while (0)
309347 DEFINE_ALLOC_SIZE_TEST_PAIR(devm_kmalloc)
310348
349+/*
350+ * We can't have an array at the end of a structure or else
351+ * builds without -fstrict-flex-arrays=3 will report them as
352+ * being an unknown length. Additionally, add bytes before
353+ * and after the string to catch over/underflows if tests
354+ * fail.
355+ */
356+struct fortify_padding {
357+ unsigned long bytes_before;
358+ char buf[32];
359+ unsigned long bytes_after;
360+};
361+/* Force compiler into not being able to resolve size at compile-time. */
362+static volatile int unconst;
363+
364+static void strlen_test(struct kunit *test)
365+{
366+ struct fortify_padding pad = { };
367+ int i, end = sizeof(pad.buf) - 1;
368+
369+ /* Fill 31 bytes with valid characters. */
370+ for (i = 0; i < sizeof(pad.buf) - 1; i++)
371+ pad.buf[i] = i + '0';
372+ /* Trailing bytes are still %NUL. */
373+ KUNIT_EXPECT_EQ(test, pad.buf[end], '\0');
374+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
375+
376+ /* String is terminated, so strlen() is valid. */
377+ KUNIT_EXPECT_EQ(test, strlen(pad.buf), end);
378+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
379+
380+ /* Make string unterminated, and recount. */
381+ pad.buf[end] = 'A';
382+ end = sizeof(pad.buf);
383+ KUNIT_EXPECT_EQ(test, strlen(pad.buf), end);
384+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1);
385+}
386+
387+static void strnlen_test(struct kunit *test)
388+{
389+ struct fortify_padding pad = { };
390+ int i, end = sizeof(pad.buf) - 1;
391+
392+ /* Fill 31 bytes with valid characters. */
393+ for (i = 0; i < sizeof(pad.buf) - 1; i++)
394+ pad.buf[i] = i + '0';
395+ /* Trailing bytes are still %NUL. */
396+ KUNIT_EXPECT_EQ(test, pad.buf[end], '\0');
397+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
398+
399+ /* String is terminated, so strnlen() is valid. */
400+ KUNIT_EXPECT_EQ(test, strnlen(pad.buf, sizeof(pad.buf)), end);
401+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
402+ /* A truncated strnlen() will be safe, too. */
403+ KUNIT_EXPECT_EQ(test, strnlen(pad.buf, sizeof(pad.buf) / 2),
404+ sizeof(pad.buf) / 2);
405+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
406+
407+ /* Make string unterminated, and recount. */
408+ pad.buf[end] = 'A';
409+ end = sizeof(pad.buf);
410+ /* Reading beyond with strncpy() will fail. */
411+ KUNIT_EXPECT_EQ(test, strnlen(pad.buf, end + 1), end);
412+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1);
413+ KUNIT_EXPECT_EQ(test, strnlen(pad.buf, end + 2), end);
414+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2);
415+
416+ /* Early-truncated is safe still, though. */
417+ KUNIT_EXPECT_EQ(test, strnlen(pad.buf, end), end);
418+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2);
419+
420+ end = sizeof(pad.buf) / 2;
421+ KUNIT_EXPECT_EQ(test, strnlen(pad.buf, end), end);
422+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2);
423+}
424+
425+static void strcpy_test(struct kunit *test)
426+{
427+ struct fortify_padding pad = { };
428+ char src[sizeof(pad.buf) + 1] = { };
429+ int i;
430+
431+ /* Fill 31 bytes with valid characters. */
432+ for (i = 0; i < sizeof(src) - 2; i++)
433+ src[i] = i + '0';
434+
435+ /* Destination is %NUL-filled to start with. */
436+ KUNIT_EXPECT_EQ(test, pad.bytes_before, 0);
437+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
438+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
439+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0');
440+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
441+
442+ /* Legitimate strcpy() 1 less than of max size. */
443+ KUNIT_ASSERT_TRUE(test, strcpy(pad.buf, src)
444+ == pad.buf);
445+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
446+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
447+ /* Only last byte should be %NUL */
448+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
449+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
450+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
451+
452+ src[sizeof(src) - 2] = 'A';
453+ /* But now we trip the overflow checking. */
454+ KUNIT_ASSERT_TRUE(test, strcpy(pad.buf, src)
455+ == pad.buf);
456+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
457+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1);
458+ /* Trailing %NUL -- thanks to FORTIFY. */
459+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
460+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
461+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
462+ /* And we will not have gone beyond. */
463+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
464+
465+ src[sizeof(src) - 1] = 'A';
466+ /* And for sure now, two bytes past. */
467+ KUNIT_ASSERT_TRUE(test, strcpy(pad.buf, src)
468+ == pad.buf);
469+ /*
470+ * Which trips both the strlen() on the unterminated src,
471+ * and the resulting copy attempt.
472+ */
473+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1);
474+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2);
475+ /* Trailing %NUL -- thanks to FORTIFY. */
476+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
477+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
478+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
479+ /* And we will not have gone beyond. */
480+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
481+}
482+
483+static void strncpy_test(struct kunit *test)
484+{
485+ struct fortify_padding pad = { };
486+ char src[] = "Copy me fully into a small buffer and I will overflow!";
487+
488+ /* Destination is %NUL-filled to start with. */
489+ KUNIT_EXPECT_EQ(test, pad.bytes_before, 0);
490+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
491+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
492+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0');
493+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
494+
495+ /* Legitimate strncpy() 1 less than of max size. */
496+ KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src,
497+ sizeof(pad.buf) + unconst - 1)
498+ == pad.buf);
499+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
500+ /* Only last byte should be %NUL */
501+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
502+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
503+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
504+
505+ /* Legitimate (though unterminated) max-size strncpy. */
506+ KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src,
507+ sizeof(pad.buf) + unconst)
508+ == pad.buf);
509+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
510+ /* No trailing %NUL -- thanks strncpy API. */
511+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0');
512+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
513+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
514+ /* But we will not have gone beyond. */
515+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
516+
517+ /* Now verify that FORTIFY is working... */
518+ KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src,
519+ sizeof(pad.buf) + unconst + 1)
520+ == pad.buf);
521+ /* Should catch the overflow. */
522+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1);
523+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0');
524+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
525+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
526+ /* And we will not have gone beyond. */
527+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
528+
529+ /* And further... */
530+ KUNIT_ASSERT_TRUE(test, strncpy(pad.buf, src,
531+ sizeof(pad.buf) + unconst + 2)
532+ == pad.buf);
533+ /* Should catch the overflow. */
534+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2);
535+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0');
536+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
537+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
538+ /* And we will not have gone beyond. */
539+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
540+}
541+
542+static void strscpy_test(struct kunit *test)
543+{
544+ struct fortify_padding pad = { };
545+ char src[] = "Copy me fully into a small buffer and I will overflow!";
546+
547+ /* Destination is %NUL-filled to start with. */
548+ KUNIT_EXPECT_EQ(test, pad.bytes_before, 0);
549+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
550+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
551+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0');
552+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
553+
554+ /* Legitimate strscpy() 1 less than of max size. */
555+ KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src,
556+ sizeof(pad.buf) + unconst - 1),
557+ -E2BIG);
558+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
559+ /* Keeping space for %NUL, last two bytes should be %NUL */
560+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
561+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
562+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
563+
564+ /* Legitimate max-size strscpy. */
565+ KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src,
566+ sizeof(pad.buf) + unconst),
567+ -E2BIG);
568+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
569+ /* A trailing %NUL will exist. */
570+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
571+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
572+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
573+
574+ /* Now verify that FORTIFY is working... */
575+ KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src,
576+ sizeof(pad.buf) + unconst + 1),
577+ -E2BIG);
578+ /* Should catch the overflow. */
579+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1);
580+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
581+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
582+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
583+ /* And we will not have gone beyond. */
584+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
585+
586+ /* And much further... */
587+ KUNIT_ASSERT_EQ(test, strscpy(pad.buf, src,
588+ sizeof(src) * 2 + unconst),
589+ -E2BIG);
590+ /* Should catch the overflow. */
591+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2);
592+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
593+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
594+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
595+ /* And we will not have gone beyond. */
596+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
597+}
598+
599+static void strcat_test(struct kunit *test)
600+{
601+ struct fortify_padding pad = { };
602+ char src[sizeof(pad.buf) / 2] = { };
603+ char one[] = "A";
604+ char two[] = "BC";
605+ int i;
606+
607+ /* Fill 15 bytes with valid characters. */
608+ for (i = 0; i < sizeof(src) - 1; i++)
609+ src[i] = i + 'A';
610+
611+ /* Destination is %NUL-filled to start with. */
612+ KUNIT_EXPECT_EQ(test, pad.bytes_before, 0);
613+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
614+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
615+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0');
616+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
617+
618+ /* Legitimate strcat() using less than half max size. */
619+ KUNIT_ASSERT_TRUE(test, strcat(pad.buf, src) == pad.buf);
620+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
621+ /* Legitimate strcat() now 2 bytes shy of end. */
622+ KUNIT_ASSERT_TRUE(test, strcat(pad.buf, src) == pad.buf);
623+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
624+ /* Last two bytes should be %NUL */
625+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
626+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
627+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
628+
629+ /* Add one more character to the end. */
630+ KUNIT_ASSERT_TRUE(test, strcat(pad.buf, one) == pad.buf);
631+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
632+ /* Last byte should be %NUL */
633+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
634+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
635+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
636+
637+ /* And this one char will overflow. */
638+ KUNIT_ASSERT_TRUE(test, strcat(pad.buf, one) == pad.buf);
639+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1);
640+ /* Last byte should be %NUL thanks to FORTIFY. */
641+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
642+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
643+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
644+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
645+
646+ /* And adding two will overflow more. */
647+ KUNIT_ASSERT_TRUE(test, strcat(pad.buf, two) == pad.buf);
648+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2);
649+ /* Last byte should be %NUL thanks to FORTIFY. */
650+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
651+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
652+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
653+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
654+}
655+
656+static void strncat_test(struct kunit *test)
657+{
658+ struct fortify_padding pad = { };
659+ char src[sizeof(pad.buf)] = { };
660+ int i, partial;
661+
662+ /* Fill 31 bytes with valid characters. */
663+ partial = sizeof(src) / 2 - 1;
664+ for (i = 0; i < partial; i++)
665+ src[i] = i + 'A';
666+
667+ /* Destination is %NUL-filled to start with. */
668+ KUNIT_EXPECT_EQ(test, pad.bytes_before, 0);
669+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
670+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
671+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0');
672+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
673+
674+ /* Legitimate strncat() using less than half max size. */
675+ KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, partial) == pad.buf);
676+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
677+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
678+ /* Legitimate strncat() now 2 bytes shy of end. */
679+ KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, partial) == pad.buf);
680+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
681+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
682+ /* Last two bytes should be %NUL */
683+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
684+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
685+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
686+
687+ /* Add one more character to the end. */
688+ KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, 1) == pad.buf);
689+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
690+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
691+ /* Last byte should be %NUL */
692+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
693+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
694+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
695+
696+ /* And this one char will overflow. */
697+ KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, 1) == pad.buf);
698+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
699+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1);
700+ /* Last byte should be %NUL thanks to FORTIFY. */
701+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
702+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
703+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
704+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
705+
706+ /* And adding two will overflow more. */
707+ KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, 2) == pad.buf);
708+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
709+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2);
710+ /* Last byte should be %NUL thanks to FORTIFY. */
711+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
712+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
713+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
714+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
715+
716+ /* Force an unterminated destination, and overflow. */
717+ pad.buf[sizeof(pad.buf) - 1] = 'A';
718+ KUNIT_ASSERT_TRUE(test, strncat(pad.buf, src, 1) == pad.buf);
719+ /* This will have tripped both strlen() and strcat(). */
720+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1);
721+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 3);
722+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0');
723+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
724+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
725+ /* But we should not go beyond the end. */
726+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
727+}
728+
729+static void strlcat_test(struct kunit *test)
730+{
731+ struct fortify_padding pad = { };
732+ char src[sizeof(pad.buf)] = { };
733+ int i, partial;
734+ int len = sizeof(pad.buf) + unconst;
735+
736+ /* Fill 15 bytes with valid characters. */
737+ partial = sizeof(src) / 2 - 1;
738+ for (i = 0; i < partial; i++)
739+ src[i] = i + 'A';
740+
741+ /* Destination is %NUL-filled to start with. */
742+ KUNIT_EXPECT_EQ(test, pad.bytes_before, 0);
743+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
744+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
745+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 3], '\0');
746+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
747+
748+ /* Legitimate strlcat() using less than half max size. */
749+ KUNIT_ASSERT_EQ(test, strlcat(pad.buf, src, len), partial);
750+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
751+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
752+ /* Legitimate strlcat() now 2 bytes shy of end. */
753+ KUNIT_ASSERT_EQ(test, strlcat(pad.buf, src, len), partial * 2);
754+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
755+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
756+ /* Last two bytes should be %NUL */
757+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
758+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 2], '\0');
759+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
760+
761+ /* Add one more character to the end. */
762+ KUNIT_ASSERT_EQ(test, strlcat(pad.buf, "Q", len), partial * 2 + 1);
763+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
764+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 0);
765+ /* Last byte should be %NUL */
766+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
767+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
768+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
769+
770+ /* And this one char will overflow. */
771+ KUNIT_ASSERT_EQ(test, strlcat(pad.buf, "V", len * 2), len);
772+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
773+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 1);
774+ /* Last byte should be %NUL thanks to FORTIFY. */
775+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
776+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
777+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
778+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
779+
780+ /* And adding two will overflow more. */
781+ KUNIT_ASSERT_EQ(test, strlcat(pad.buf, "QQ", len * 2), len + 1);
782+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
783+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2);
784+ /* Last byte should be %NUL thanks to FORTIFY. */
785+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
786+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
787+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
788+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
789+
790+ /* Force an unterminated destination, and overflow. */
791+ pad.buf[sizeof(pad.buf) - 1] = 'A';
792+ KUNIT_ASSERT_EQ(test, strlcat(pad.buf, "TT", len * 2), len + 2);
793+ /* This will have tripped both strlen() and strlcat(). */
794+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2);
795+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 2);
796+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 1], '\0');
797+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 2], '\0');
798+ KUNIT_EXPECT_NE(test, pad.buf[sizeof(pad.buf) - 3], '\0');
799+ /* But we should not go beyond the end. */
800+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
801+
802+ /* Force an unterminated source, and overflow. */
803+ memset(src, 'B', sizeof(src));
804+ pad.buf[sizeof(pad.buf) - 1] = '\0';
805+ KUNIT_ASSERT_EQ(test, strlcat(pad.buf, src, len * 3), len - 1 + sizeof(src));
806+ /* This will have tripped both strlen() and strlcat(). */
807+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 3);
808+ KUNIT_EXPECT_EQ(test, fortify_write_overflows, 3);
809+ KUNIT_EXPECT_EQ(test, pad.buf[sizeof(pad.buf) - 1], '\0');
810+ /* But we should not go beyond the end. */
811+ KUNIT_EXPECT_EQ(test, pad.bytes_after, 0);
812+}
813+
814+static void memscan_test(struct kunit *test)
815+{
816+ char haystack[] = "Where oh where is my memory range?";
817+ char *mem = haystack + strlen("Where oh where is ");
818+ char needle = 'm';
819+ size_t len = sizeof(haystack) + unconst;
820+
821+ KUNIT_ASSERT_PTR_EQ(test, memscan(haystack, needle, len),
822+ mem);
823+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
824+ /* Catch too-large range. */
825+ KUNIT_ASSERT_PTR_EQ(test, memscan(haystack, needle, len + 1),
826+ NULL);
827+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1);
828+ KUNIT_ASSERT_PTR_EQ(test, memscan(haystack, needle, len * 2),
829+ NULL);
830+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2);
831+}
832+
833+static void memchr_test(struct kunit *test)
834+{
835+ char haystack[] = "Where oh where is my memory range?";
836+ char *mem = haystack + strlen("Where oh where is ");
837+ char needle = 'm';
838+ size_t len = sizeof(haystack) + unconst;
839+
840+ KUNIT_ASSERT_PTR_EQ(test, memchr(haystack, needle, len),
841+ mem);
842+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
843+ /* Catch too-large range. */
844+ KUNIT_ASSERT_PTR_EQ(test, memchr(haystack, needle, len + 1),
845+ NULL);
846+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1);
847+ KUNIT_ASSERT_PTR_EQ(test, memchr(haystack, needle, len * 2),
848+ NULL);
849+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2);
850+}
851+
852+static void memchr_inv_test(struct kunit *test)
853+{
854+ char haystack[] = "Where oh where is my memory range?";
855+ char *mem = haystack + 1;
856+ char needle = 'W';
857+ size_t len = sizeof(haystack) + unconst;
858+
859+ /* Normal search is okay. */
860+ KUNIT_ASSERT_PTR_EQ(test, memchr_inv(haystack, needle, len),
861+ mem);
862+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
863+ /* Catch too-large range. */
864+ KUNIT_ASSERT_PTR_EQ(test, memchr_inv(haystack, needle, len + 1),
865+ NULL);
866+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1);
867+ KUNIT_ASSERT_PTR_EQ(test, memchr_inv(haystack, needle, len * 2),
868+ NULL);
869+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2);
870+}
871+
872+static void memcmp_test(struct kunit *test)
873+{
874+ char one[] = "My mind is going ...";
875+ char two[] = "My mind is going ... I can feel it.";
876+ size_t one_len = sizeof(one) + unconst - 1;
877+ size_t two_len = sizeof(two) + unconst - 1;
878+
879+ /* We match the first string (ignoring the %NUL). */
880+ KUNIT_ASSERT_EQ(test, memcmp(one, two, one_len), 0);
881+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
882+ /* Still in bounds, but no longer matching. */
883+ KUNIT_ASSERT_EQ(test, memcmp(one, two, one_len + 1), -32);
884+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
885+
886+ /* Catch too-large ranges. */
887+ KUNIT_ASSERT_EQ(test, memcmp(one, two, one_len + 2), INT_MIN);
888+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1);
889+
890+ KUNIT_ASSERT_EQ(test, memcmp(two, one, two_len + 2), INT_MIN);
891+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2);
892+}
893+
894+static void kmemdup_test(struct kunit *test)
895+{
896+ char src[] = "I got Doom running on it!";
897+ char *copy;
898+ size_t len = sizeof(src) + unconst;
899+
900+ /* Copy is within bounds. */
901+ copy = kmemdup(src, len, GFP_KERNEL);
902+ KUNIT_EXPECT_NOT_NULL(test, copy);
903+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
904+ kfree(copy);
905+
906+ /* Without %NUL. */
907+ copy = kmemdup(src, len - 1, GFP_KERNEL);
908+ KUNIT_EXPECT_NOT_NULL(test, copy);
909+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
910+ kfree(copy);
911+
912+ /* Tiny bounds. */
913+ copy = kmemdup(src, 1, GFP_KERNEL);
914+ KUNIT_EXPECT_NOT_NULL(test, copy);
915+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 0);
916+ kfree(copy);
917+
918+ /* Out of bounds by 1 byte. */
919+ copy = kmemdup(src, len + 1, GFP_KERNEL);
920+ KUNIT_EXPECT_NULL(test, copy);
921+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 1);
922+ kfree(copy);
923+
924+ /* Way out of bounds. */
925+ copy = kmemdup(src, len * 2, GFP_KERNEL);
926+ KUNIT_EXPECT_NULL(test, copy);
927+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 2);
928+ kfree(copy);
929+
930+ /* Starting offset causing out of bounds. */
931+ copy = kmemdup(src + 1, len, GFP_KERNEL);
932+ KUNIT_EXPECT_NULL(test, copy);
933+ KUNIT_EXPECT_EQ(test, fortify_read_overflows, 3);
934+ kfree(copy);
935+}
936+
937+static int fortify_test_init(struct kunit *test)
938+{
939+ if (!IS_ENABLED(CONFIG_FORTIFY_SOURCE))
940+ kunit_skip(test, "Not built with CONFIG_FORTIFY_SOURCE=y");
941+
942+ fortify_read_overflows = 0;
943+ kunit_add_named_resource(test, NULL, NULL, &read_resource,
944+ "fortify_read_overflows",
945+ &fortify_read_overflows);
946+ fortify_write_overflows = 0;
947+ kunit_add_named_resource(test, NULL, NULL, &write_resource,
948+ "fortify_write_overflows",
949+ &fortify_write_overflows);
950+ return 0;
951+}
952+
311953 static struct kunit_case fortify_test_cases[] = {
312954 KUNIT_CASE(known_sizes_test),
313955 KUNIT_CASE(control_flow_split_test),
@@ -319,11 +961,27 @@ static struct kunit_case fortify_test_cases[] = { · 5 unmodified lines
319961 KUNIT_CASE(alloc_size_kvmalloc_dynamic_test),
320962 KUNIT_CASE(alloc_size_devm_kmalloc_const_test),
321963 KUNIT_CASE(alloc_size_devm_kmalloc_dynamic_test),
964+ KUNIT_CASE(strlen_test),
965+ KUNIT_CASE(strnlen_test),
966+ KUNIT_CASE(strcpy_test),
967+ KUNIT_CASE(strncpy_test),
968+ KUNIT_CASE(strscpy_test),
969+ KUNIT_CASE(strcat_test),
970+ KUNIT_CASE(strncat_test),
971+ KUNIT_CASE(strlcat_test),
972+ /* skip memset: performs bounds checking on whole structs */
973+ /* skip memcpy: still using warn-and-overwrite instead of hard-fail */
974+ KUNIT_CASE(memscan_test),
975+ KUNIT_CASE(memchr_test),
976+ KUNIT_CASE(memchr_inv_test),
977+ KUNIT_CASE(memcmp_test),
978+ KUNIT_CASE(kmemdup_test),
322979 {}
323980 };
324981
325982 static struct kunit_suite fortify_test_suite = {
326983 .name = "fortify",
984+ .init = fortify_test_init,
327985 .test_cases = fortify_test_cases,
328986 };
329987
lib/overflow_kunit.c+63−4
@@ -258,25 +258,84 @@ DEFINE_TEST_ARRAY(s64) = { · 257 unmodified lines
258258 \
259259 _of = check_ ## op ## _overflow(a, b, &_r); \
260260 KUNIT_EXPECT_EQ_MSG(test, _of, of, \
261− "expected "fmt" "sym" "fmt" to%s overflow (type %s)\n", \
261+ "expected check "fmt" "sym" "fmt" to%s overflow (type %s)\n", \
262262 a, b, of ? "" : " not", #t); \
263263 KUNIT_EXPECT_EQ_MSG(test, _r, r, \
264− "expected "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \
264+ "expected check "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \
265265 a, b, r, _r, #t); \
266266 /* Check for internal macro side-effects. */ \
267267 _of = check_ ## op ## _overflow(_a_orig++, _b_orig++, &_r); \
268− KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump, "Unexpected " #op " macro side-effect!\n"); \
269− KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, "Unexpected " #op " macro side-effect!\n"); \
268+ KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump, \
269+ "Unexpected check " #op " macro side-effect!\n"); \
270+ KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, \
271+ "Unexpected check " #op " macro side-effect!\n"); \
272+ \
273+ _r = wrapping_ ## op(t, a, b); \
274+ KUNIT_EXPECT_TRUE_MSG(test, _r == r, \
275+ "expected wrap "fmt" "sym" "fmt" == "fmt", got "fmt" (type %s)\n", \
276+ a, b, r, _r, #t); \
277+ /* Check for internal macro side-effects. */ \
278+ _a_orig = a; \
279+ _b_orig = b; \
280+ _r = wrapping_ ## op(t, _a_orig++, _b_orig++); \
281+ KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump, \
282+ "Unexpected wrap " #op " macro side-effect!\n"); \
283+ KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, \
284+ "Unexpected wrap " #op " macro side-effect!\n"); \
285+} while (0)
286+
287+static int global_counter;
288+static void bump_counter(void)
289+{
290+ global_counter++;
291+}
292+
293+static int get_index(void)
294+{
295+ volatile int index = 0;
296+ bump_counter();
297+ return index;
298+}
299+
300+#define check_self_op(fmt, op, sym, a, b) do { \
301+ typeof(a + 0) _a = a; \
302+ typeof(b + 0) _b = b; \
303+ typeof(a + 0) _a_sym = a; \
304+ typeof(a + 0) _a_orig[1] = { a }; \
305+ typeof(b + 0) _b_orig = b; \
306+ typeof(b + 0) _b_bump = b + 1; \
307+ typeof(a + 0) _r; \
308+ \
309+ _a_sym sym _b; \
310+ _r = wrapping_ ## op(_a, _b); \
311+ KUNIT_EXPECT_TRUE_MSG(test, _r == _a_sym, \
312+ "expected "fmt" "#op" "fmt" == "fmt", got "fmt"\n", \
313+ a, b, _a_sym, _r); \
314+ KUNIT_EXPECT_TRUE_MSG(test, _a == _a_sym, \
315+ "expected "fmt" "#op" "fmt" == "fmt", got "fmt"\n", \
316+ a, b, _a_sym, _a); \
317+ /* Check for internal macro side-effects. */ \
318+ global_counter = 0; \
319+ wrapping_ ## op(_a_orig[get_index()], _b_orig++); \
320+ KUNIT_EXPECT_EQ_MSG(test, global_counter, 1, \
321+ "Unexpected wrapping_" #op " macro side-effect on arg1!\n"); \
322+ KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, \
323+ "Unexpected wrapping_" #op " macro side-effect on arg2!\n"); \
270324 } while (0)
271325
272326 #define DEFINE_TEST_FUNC_TYPED(n, t, fmt) \
273327 static void do_test_ ## n(struct kunit *test, const struct test_ ## n *p) \
274328 { \
329+ /* check_{add,sub,mul}_overflow() and wrapping_{add,sub,mul} */ \
275330 check_one_op(t, fmt, add, "+", p->a, p->b, p->sum, p->s_of); \
276331 check_one_op(t, fmt, add, "+", p->b, p->a, p->sum, p->s_of); \
277332 check_one_op(t, fmt, sub, "-", p->a, p->b, p->diff, p->d_of); \
278333 check_one_op(t, fmt, mul, "*", p->a, p->b, p->prod, p->p_of); \
279334 check_one_op(t, fmt, mul, "*", p->b, p->a, p->prod, p->p_of); \
335+ /* wrapping_assign_{add,sub}() */ \
336+ check_self_op(fmt, assign_add, +=, p->a, p->b); \
337+ check_self_op(fmt, assign_add, +=, p->b, p->a); \
338+ check_self_op(fmt, assign_sub, -=, p->a, p->b); \
280339 } \
281340 \
282341 static void n ## _overflow_test(struct kunit *test) { \
lib/stackinit_kunit.c+16−3
@@ -63,7 +63,16 @@ static bool stackinit_range_contains(char *haystack_start, size_t haystack_size, · 62 unmodified lines
6363 #define FETCH_ARG_STRING(var) var
6464 #define FETCH_ARG_STRUCT(var) &var
6565
66+/*
67+ * On m68k, if the leaf function test variable is longer than 8 bytes,
68+ * the start of the stack frame moves. 8 is sufficiently large to
69+ * test m68k char arrays, but leave it at 16 for other architectures.
70+ */
71+#ifdef CONFIG_M68K
72+#define FILL_SIZE_STRING 8
73+#else
6674 #define FILL_SIZE_STRING 16
75+#endif
6776
6877 #define INIT_CLONE_SCALAR /**/
6978 #define INIT_CLONE_STRING [FILL_SIZE_STRING]
@@ -165,19 +174,23 @@ static noinline void test_ ## name (struct kunit *test) \ · 95 unmodified lines
165174 /* Verify all bytes overwritten with 0xFF. */ \
166175 for (sum = 0, i = 0; i < target_size; i++) \
167176 sum += (check_buf[i] != 0xFF); \
168− KUNIT_ASSERT_EQ_MSG(test, sum, 0, \
169− "leaf fill was not 0xFF!?\n"); \
170177 /* Clear entire check buffer for later bit tests. */ \
171178 memset(check_buf, 0x00, sizeof(check_buf)); \
172179 /* Extract stack-defined variable contents. */ \
173180 ignored = leaf_ ##name((unsigned long)&ignored, 0, \
174181 FETCH_ARG_ ## which(zero)); \
182+ /* \
183+ * Delay the sum test to here to do as little as \
184+ * possible between the two leaf function calls. \
185+ */ \
186+ KUNIT_ASSERT_EQ_MSG(test, sum, 0, \
187+ "leaf fill was not 0xFF!?\n"); \
175188 \
176189 /* Validate that compiler lined up fill and target. */ \
177190 KUNIT_ASSERT_TRUE_MSG(test, \
178191 stackinit_range_contains(fill_start, fill_size, \
179192 target_start, target_size), \
180− "stack fill missed target!? " \
193+ "stackframe was not the same between calls!? " \
181194 "(fill %zu wide, target offset by %d)\n", \
182195 fill_size, \
183196 (int)((ssize_t)(uintptr_t)fill_start - \
lib/string.c+11−12
@@ -15,19 +15,20 @@ · 14 unmodified lines
1515 */
1616
1717 #define __NO_FORTIFY
18−#include <linux/types.h>
19−#include <linux/string.h>
20−#include <linux/ctype.h>
21−#include <linux/kernel.h>
22−#include <linux/export.h>
18+#include <linux/bits.h>
2319 #include <linux/bug.h>
20+#include <linux/ctype.h>
2421 #include <linux/errno.h>
25−#include <linux/slab.h>
22+#include <linux/limits.h>
23+#include <linux/linkage.h>
24+#include <linux/stddef.h>
25+#include <linux/string.h>
26+#include <linux/types.h>
2627
28+#include <asm/page.h>
29+#include <asm/rwonce.h>
2730 #include <asm/unaligned.h>
28−#include <asm/byteorder.h>
2931 #include <asm/word-at-a-time.h>
30−#include <asm/page.h>
3132
3233 #ifndef __HAVE_ARCH_STRNCASECMP
3334 /**
@@ -103,8 +104,7 @@ char *strncpy(char *dest, const char *src, size_t count) · 69 unmodified lines
103104 EXPORT_SYMBOL(strncpy);
104105 #endif
105106
106−#ifndef __HAVE_ARCH_STRSCPY
107−ssize_t strscpy(char *dest, const char *src, size_t count)
107+ssize_t sized_strscpy(char *dest, const char *src, size_t count)
108108 {
109109 const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
110110 size_t max = count;
@@ -170,8 +170,7 @@ ssize_t strscpy(char *dest, const char *src, size_t count) · 59 unmodified lines
170170
171171 return -E2BIG;
172172 }
173−EXPORT_SYMBOL(strscpy);
174−#endif
173+EXPORT_SYMBOL(sized_strscpy);
175174
176175 /**
177176 * stpcpy - copy a string from src to dest returning a pointer to the new end
lib/string_helpers.c+39−50
@@ -18,12 +18,14 @@ · 17 unmodified lines
1818 #include <linux/slab.h>
1919 #include <linux/string.h>
2020 #include <linux/string_helpers.h>
21+#include <kunit/test.h>
22+#include <kunit/test-bug.h>
2123
2224 /**
2325 * string_get_size - get the size in the specified units
2426 * @size: The size to be converted in blocks
2527 * @blk_size: Size of the block (use 1 for size in bytes)
26− * @units: units to use (powers of 1000 or 1024)
28+ * @units: Units to use (powers of 1000 or 1024), whether to include space separator
2729 * @buf: buffer to format to
2830 * @len: length of buffer
2931 *
@@ -37,11 +39,12 @@ · 7 unmodified lines
3739 int string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
3840 char *buf, int len)
3941 {
42+ enum string_size_units units_base = units & STRING_UNITS_MASK;
4043 static const char *const units_10[] = {
41− "B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"
44+ "", "k", "M", "G", "T", "P", "E", "Z", "Y",
4245 };
4346 static const char *const units_2[] = {
44− "B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"
47+ "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi",
4548 };
4649 static const char *const *const units_str[] = {
4750 [STRING_UNITS_10] = units_10,
@@ -66,7 +69,7 @@ int string_get_size(u64 size, u64 blk_size, const enum string_size_units units, · 18 unmodified lines
6669
6770 /* This is Napier's algorithm. Reduce the original block size to
6871 *
69− * coefficient * divisor[units]^i
72+ * coefficient * divisor[units_base]^i
7073 *
7174 * we do the reduction so both coefficients are just under 32 bits so
7275 * that multiplying them together won't overflow 64 bits and we keep
@@ -76,12 +79,12 @@ int string_get_size(u64 size, u64 blk_size, const enum string_size_units units, · 3 unmodified lines
7679 * precision is in the coefficients.
7780 */
7881 while (blk_size >> 32) {
79− do_div(blk_size, divisor[units]);
82+ do_div(blk_size, divisor[units_base]);
8083 i++;
8184 }
8285
8386 while (size >> 32) {
84− do_div(size, divisor[units]);
87+ do_div(size, divisor[units_base]);
8588 i++;
8689 }
8790
@@ -90,8 +93,8 @@ int string_get_size(u64 size, u64 blk_size, const enum string_size_units units, · 2 unmodified lines
9093 size *= blk_size;
9194
9295 /* and logarithmically reduce it until it's just under the divisor */
93− while (size >= divisor[units]) {
94− remainder = do_div(size, divisor[units]);
96+ while (size >= divisor[units_base]) {
97+ remainder = do_div(size, divisor[units_base]);
9598 i++;
9699 }
97100
@@ -101,10 +104,10 @@ int string_get_size(u64 size, u64 blk_size, const enum string_size_units units, · 3 unmodified lines
101104 for (j = 0; sf_cap*10 < 1000; j++)
102105 sf_cap *= 10;
103106
104− if (units == STRING_UNITS_2) {
107+ if (units_base == STRING_UNITS_2) {
105108 /* express the remainder as a decimal. It's currently the
106109 * numerator of a fraction whose denominator is
107− * divisor[units], which is 1 << 10 for STRING_UNITS_2 */
110+ * divisor[units_base], which is 1 << 10 for STRING_UNITS_2 */
108111 remainder *= 1000;
109112 remainder >>= 10;
110113 }
@@ -126,10 +129,12 @@ int string_get_size(u64 size, u64 blk_size, const enum string_size_units units, · 15 unmodified lines
126129 if (i >= ARRAY_SIZE(units_2))
127130 unit = "UNK";
128131 else
129− unit = units_str[units][i];
132+ unit = units_str[units_base][i];
130133
131− return snprintf(buf, len, "%u%s %s", (u32)size,
132− tmp, unit);
134+ return snprintf(buf, len, "%u%s%s%s%s", (u32)size, tmp,
135+ (units & STRING_UNITS_NO_SPACE) ? "" : " ",
136+ unit,
137+ (units & STRING_UNITS_NO_BYTES) ? "" : "B");
133138 }
134139 EXPORT_SYMBOL(string_get_size);
135140
@@ -825,40 +830,6 @@ char **devm_kasprintf_strarray(struct device *dev, const char *prefix, size_t n) · 689 unmodified lines
825830 }
826831 EXPORT_SYMBOL_GPL(devm_kasprintf_strarray);
827832
828−/**
829− * strscpy_pad() - Copy a C-string into a sized buffer
830− * @dest: Where to copy the string to
831− * @src: Where to copy the string from
832− * @count: Size of destination buffer
833− *
834− * Copy the string, or as much of it as fits, into the dest buffer. The
835− * behavior is undefined if the string buffers overlap. The destination
836− * buffer is always %NUL terminated, unless it's zero-sized.
837− *
838− * If the source string is shorter than the destination buffer, zeros
839− * the tail of the destination buffer.
840− *
841− * For full explanation of why you may want to consider using the
842− * 'strscpy' functions please see the function docstring for strscpy().
843− *
844− * Returns:
845− * * The number of characters copied (not including the trailing %NUL)
846− * * -E2BIG if count is 0 or @src was truncated.
847− */
848−ssize_t strscpy_pad(char *dest, const char *src, size_t count)
849−{
850− ssize_t written;
851−
852− written = strscpy(dest, src, count);
853− if (written < 0 || written == count - 1)
854− return written;
855−
856− memset(dest + written + 1, 0, count - written - 1);
857−
858− return written;
859−}
860−EXPORT_SYMBOL(strscpy_pad);
861−
862833 /**
863834 * skip_spaces - Removes leading whitespace from @str.
864835 * @str: The string to be stripped.
@@ -1042,10 +1013,28 @@ EXPORT_SYMBOL(__read_overflow2_field); · 177 unmodified lines
10421013 void __write_overflow_field(size_t avail, size_t wanted) { }
10431014 EXPORT_SYMBOL(__write_overflow_field);
10441015
1045−void fortify_panic(const char *name)
1016+static const char * const fortify_func_name[] = {
1017+#define MAKE_FORTIFY_FUNC_NAME(func) [MAKE_FORTIFY_FUNC(func)] = #func
1018+ EACH_FORTIFY_FUNC(MAKE_FORTIFY_FUNC_NAME)
1019+#undef MAKE_FORTIFY_FUNC_NAME
1020+};
1021+
1022+void __fortify_report(const u8 reason, const size_t avail, const size_t size)
1023+{
1024+ const u8 func = FORTIFY_REASON_FUNC(reason);
1025+ const bool write = FORTIFY_REASON_DIR(reason);
1026+ const char *name;
1027+
1028+ name = fortify_func_name[umin(func, FORTIFY_FUNC_UNKNOWN)];
1029+ WARN(1, "%s: detected buffer overflow: %zu byte %s of buffer size %zu\n",
1030+ name, size, str_read_write(!write), avail);
1031+}
1032+EXPORT_SYMBOL(__fortify_report);
1033+
1034+void __fortify_panic(const u8 reason, const size_t avail, const size_t size)
10461035 {
1047− pr_emerg("detected buffer overflow in %s\n", name);
1036+ __fortify_report(reason, avail, size);
10481037 BUG();
10491038 }
1050−EXPORT_SYMBOL(fortify_panic);
1039+EXPORT_SYMBOL(__fortify_panic);
10511040 #endif /* CONFIG_FORTIFY_SOURCE */
lib/string_helpers_kunit.crenamed from lib/test-string_helpers.c+137−118
@@ -1,34 +1,25 @@
1+// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
12 /*
23 * Test cases for lib/string_helpers.c module.
34 */
45 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
56
6−#include <linux/init.h>
7+#include <kunit/test.h>
8+#include <linux/array_size.h>
79 #include <linux/kernel.h>
8−#include <linux/slab.h>
9−#include <linux/module.h>
1010 #include <linux/random.h>
1111 #include <linux/string.h>
1212 #include <linux/string_helpers.h>
1313
14−static __init bool test_string_check_buf(const char *name, unsigned int flags,
15− char *in, size_t p,
16− char *out_real, size_t q_real,
17− char *out_test, size_t q_test)
14+static void test_string_check_buf(struct kunit *test,
15+ const char *name, unsigned int flags,
16+ char *in, size_t p,
17+ char *out_real, size_t q_real,
18+ char *out_test, size_t q_test)
1819 {
19− if (q_real == q_test && !memcmp(out_test, out_real, q_test))
20− return true;
21−
22− pr_warn("Test '%s' failed: flags = %#x\n", name, flags);
23−
24− print_hex_dump(KERN_WARNING, "Input: ", DUMP_PREFIX_NONE, 16, 1,
25− in, p, true);
26− print_hex_dump(KERN_WARNING, "Expected: ", DUMP_PREFIX_NONE, 16, 1,
27− out_test, q_test, true);
28− print_hex_dump(KERN_WARNING, "Got: ", DUMP_PREFIX_NONE, 16, 1,
29− out_real, q_real, true);
30−
31− return false;
20+ KUNIT_ASSERT_EQ_MSG(test, q_real, q_test, "name:%s", name);
21+ KUNIT_EXPECT_MEMEQ_MSG(test, out_test, out_real, q_test,
22+ "name:%s", name);
3223 }
3324
3425 struct test_string {
@@ -37,7 +28,7 @@ struct test_string { · 2 unmodified lines
3728 unsigned int flags;
3829 };
3930
40−static const struct test_string strings[] __initconst = {
31+static const struct test_string strings[] = {
4132 {
4233 .in = "\\f\\ \\n\\r\\t\\v",
4334 .out = "\f\\ \n\r\t\v",
@@ -60,17 +51,19 @@ static const struct test_string strings[] __initconst = { · 16 unmodified lines
6051 },
6152 };
6253
63−static void __init test_string_unescape(const char *name, unsigned int flags,
64− bool inplace)
54+static void test_string_unescape(struct kunit *test,
55+ const char *name, unsigned int flags,
56+ bool inplace)
6557 {
6658 int q_real = 256;
67− char *in = kmalloc(q_real, GFP_KERNEL);
68− char *out_test = kmalloc(q_real, GFP_KERNEL);
69− char *out_real = kmalloc(q_real, GFP_KERNEL);
59+ char *in = kunit_kzalloc(test, q_real, GFP_KERNEL);
60+ char *out_test = kunit_kzalloc(test, q_real, GFP_KERNEL);
61+ char *out_real = kunit_kzalloc(test, q_real, GFP_KERNEL);
7062 int i, p = 0, q_test = 0;
7163
72− if (!in || !out_test || !out_real)
73− goto out;
64+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, in);
65+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_test);
66+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_real);
7467
7568 for (i = 0; i < ARRAY_SIZE(strings); i++) {
7669 const char *s = strings[i].in;
@@ -103,12 +96,8 @@ static void __init test_string_unescape(const char *name, unsigned int flags, · 26 unmodified lines
10396 q_real = string_unescape(in, out_real, q_real, flags);
10497 }
10598
106− test_string_check_buf(name, flags, in, p - 1, out_real, q_real,
99+ test_string_check_buf(test, name, flags, in, p - 1, out_real, q_real,
107100 out_test, q_test);
108−out:
109− kfree(out_real);
110− kfree(out_test);
111− kfree(in);
112101 }
113102
114103 struct test_string_1 {
@@ -123,7 +112,7 @@ struct test_string_2 { · 8 unmodified lines
123112 };
124113
125114 #define TEST_STRING_2_DICT_0 NULL
126−static const struct test_string_2 escape0[] __initconst = {{
115+static const struct test_string_2 escape0[] = {{
127116 .in = "\f\\ \n\r\t\v",
128117 .s1 = {{
129118 .out = "\\f\\ \\n\\r\\t\\v",
@@ -221,7 +210,7 @@ static const struct test_string_2 escape0[] __initconst = {{ · 91 unmodified lines
221210 }};
222211
223212 #define TEST_STRING_2_DICT_1 "b\\ \t\r\xCF"
224−static const struct test_string_2 escape1[] __initconst = {{
213+static const struct test_string_2 escape1[] = {{
225214 .in = "\f\\ \n\r\t\v",
226215 .s1 = {{
227216 .out = "\f\\134\\040\n\\015\\011\v",
@@ -358,7 +347,7 @@ static const struct test_string_2 escape1[] __initconst = {{ · 130 unmodified lines
358347 /* terminator */
359348 }};
360349
361−static const struct test_string strings_upper[] __initconst = {
350+static const struct test_string strings_upper[] = {
362351 {
363352 .in = "abcdefgh1234567890test",
364353 .out = "ABCDEFGH1234567890TEST",
@@ -369,7 +358,7 @@ static const struct test_string strings_upper[] __initconst = { · 4 unmodified lines
369358 },
370359 };
371360
372−static const struct test_string strings_lower[] __initconst = {
361+static const struct test_string strings_lower[] = {
373362 {
374363 .in = "ABCDEFGH1234567890TEST",
375364 .out = "abcdefgh1234567890test",
@@ -380,8 +369,8 @@ static const struct test_string strings_lower[] __initconst = { · 4 unmodified lines
380369 },
381370 };
382371
383−static __init const char *test_string_find_match(const struct test_string_2 *s2,
384− unsigned int flags)
372+static const char *test_string_find_match(const struct test_string_2 *s2,
373+ unsigned int flags)
385374 {
386375 const struct test_string_1 *s1 = s2->s1;
387376 unsigned int i;
@@ -402,31 +391,31 @@ static __init const char *test_string_find_match(const struct test_string_2 *s2, · 14 unmodified lines
402391 return NULL;
403392 }
404393
405−static __init void
406−test_string_escape_overflow(const char *in, int p, unsigned int flags, const char *esc,
394+static void
395+test_string_escape_overflow(struct kunit *test,
396+ const char *in, int p, unsigned int flags, const char *esc,
407397 int q_test, const char *name)
408398 {
409399 int q_real;
410400
411401 q_real = string_escape_mem(in, p, NULL, 0, flags, esc);
412− if (q_real != q_test)
413− pr_warn("Test '%s' failed: flags = %#x, osz = 0, expected %d, got %d\n",
414− name, flags, q_test, q_real);
402+ KUNIT_EXPECT_EQ_MSG(test, q_real, q_test, "name:%s: flags:%#x", name, flags);
415403 }
416404
417−static __init void test_string_escape(const char *name,
418− const struct test_string_2 *s2,
419− unsigned int flags, const char *esc)
405+static void test_string_escape(struct kunit *test, const char *name,
406+ const struct test_string_2 *s2,
407+ unsigned int flags, const char *esc)
420408 {
421409 size_t out_size = 512;
422− char *out_test = kmalloc(out_size, GFP_KERNEL);
423− char *out_real = kmalloc(out_size, GFP_KERNEL);
424− char *in = kmalloc(256, GFP_KERNEL);
410+ char *out_test = kunit_kzalloc(test, out_size, GFP_KERNEL);
411+ char *out_real = kunit_kzalloc(test, out_size, GFP_KERNEL);
412+ char *in = kunit_kzalloc(test, 256, GFP_KERNEL);
425413 int p = 0, q_test = 0;
426414 int q_real;
427415
428− if (!out_test || !out_real || !in)
429− goto out;
416+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_test);
417+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_real);
418+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, in);
430419
431420 for (; s2->in; s2++) {
432421 const char *out;
@@ -462,62 +451,99 @@ static __init void test_string_escape(const char *name, · 29 unmodified lines
462451
463452 q_real = string_escape_mem(in, p, out_real, out_size, flags, esc);
464453
465− test_string_check_buf(name, flags, in, p, out_real, q_real, out_test,
454+ test_string_check_buf(test, name, flags, in, p, out_real, q_real, out_test,
466455 q_test);
467456
468− test_string_escape_overflow(in, p, flags, esc, q_test, name);
469−
470−out:
471− kfree(in);
472− kfree(out_real);
473− kfree(out_test);
457+ test_string_escape_overflow(test, in, p, flags, esc, q_test, name);
474458 }
475459
476460 #define string_get_size_maxbuf 16
477−#define test_string_get_size_one(size, blk_size, exp_result10, exp_result2) \
478− do { \
479− BUILD_BUG_ON(sizeof(exp_result10) >= string_get_size_maxbuf); \
480− BUILD_BUG_ON(sizeof(exp_result2) >= string_get_size_maxbuf); \
481− __test_string_get_size((size), (blk_size), (exp_result10), \
482− (exp_result2)); \
461+#define test_string_get_size_one(size, blk_size, exp_result10, exp_result2) \
462+ do { \
463+ BUILD_BUG_ON(sizeof(exp_result10) >= string_get_size_maxbuf); \
464+ BUILD_BUG_ON(sizeof(exp_result2) >= string_get_size_maxbuf); \
465+ __test_string_get_size(test, (size), (blk_size), (exp_result10), \
466+ (exp_result2)); \
483467 } while (0)
484468
485469
486−static __init void test_string_get_size_check(const char *units,
487− const char *exp,
488− char *res,
489− const u64 size,
490− const u64 blk_size)
470+static void test_string_get_size_check(struct kunit *test,
471+ const char *units,
472+ const char *exp,
473+ char *res,
474+ const u64 size,
475+ const u64 blk_size)
491476 {
492− if (!memcmp(res, exp, strlen(exp) + 1))
493− return;
494−
495− res[string_get_size_maxbuf - 1] = '\0';
496−
497− pr_warn("Test 'test_string_get_size' failed!\n");
498− pr_warn("string_get_size(size = %llu, blk_size = %llu, units = %s)\n",
477+ KUNIT_EXPECT_MEMEQ_MSG(test, res, exp, strlen(exp) + 1,
478+ "string_get_size(size = %llu, blk_size = %llu, units = %s)",
499479 size, blk_size, units);
500− pr_warn("expected: '%s', got '%s'\n", exp, res);
501480 }
502481
503−static __init void __test_string_get_size(const u64 size, const u64 blk_size,
504− const char *exp_result10,
505− const char *exp_result2)
482+static void __strchrcut(char *dst, const char *src, const char *cut)
483+{
484+ const char *from = src;
485+ size_t len;
486+
487+ do {
488+ len = strcspn(from, cut);
489+ memcpy(dst, from, len);
490+ dst += len;
491+ from += len;
492+ } while (*from++);
493+ *dst = '\0';
494+}
495+
496+static void __test_string_get_size_one(struct kunit *test,
497+ const u64 size, const u64 blk_size,
498+ const char *exp_result10,
499+ const char *exp_result2,
500+ enum string_size_units units,
501+ const char *cut)
506502 {
507503 char buf10[string_get_size_maxbuf];
508504 char buf2[string_get_size_maxbuf];
505+ char exp10[string_get_size_maxbuf];
506+ char exp2[string_get_size_maxbuf];
507+ char prefix10[64];
508+ char prefix2[64];
509+
510+ sprintf(prefix10, "STRING_UNITS_10 [%s]", cut);
511+ sprintf(prefix2, "STRING_UNITS_2 [%s]", cut);
512+
513+ __strchrcut(exp10, exp_result10, cut);
514+ __strchrcut(exp2, exp_result2, cut);
509515
510− string_get_size(size, blk_size, STRING_UNITS_10, buf10, sizeof(buf10));
511− string_get_size(size, blk_size, STRING_UNITS_2, buf2, sizeof(buf2));
516+ string_get_size(size, blk_size, STRING_UNITS_10 | units, buf10, sizeof(buf10));
517+ string_get_size(size, blk_size, STRING_UNITS_2 | units, buf2, sizeof(buf2));
512518
513− test_string_get_size_check("STRING_UNITS_10", exp_result10, buf10,
514− size, blk_size);
519+ test_string_get_size_check(test, prefix10, exp10, buf10, size, blk_size);
520+ test_string_get_size_check(test, prefix2, exp2, buf2, size, blk_size);
521+}
522+
523+static void __test_string_get_size(struct kunit *test,
524+ const u64 size, const u64 blk_size,
525+ const char *exp_result10,
526+ const char *exp_result2)
527+{
528+ struct {
529+ enum string_size_units units;
530+ const char *cut;
531+ } get_size_test_cases[] = {
532+ { 0, "" },
533+ { STRING_UNITS_NO_SPACE, " " },
534+ { STRING_UNITS_NO_SPACE | STRING_UNITS_NO_BYTES, " B" },
535+ { STRING_UNITS_NO_BYTES, "B" },
536+ };
537+ int i;
515538
516− test_string_get_size_check("STRING_UNITS_2", exp_result2, buf2,
517− size, blk_size);
539+ for (i = 0; i < ARRAY_SIZE(get_size_test_cases); i++)
540+ __test_string_get_size_one(test, size, blk_size,
541+ exp_result10, exp_result2,
542+ get_size_test_cases[i].units,
543+ get_size_test_cases[i].cut);
518544 }
519545
520−static __init void test_string_get_size(void)
546+static void test_get_size(struct kunit *test)
521547 {
522548 /* small values */
523549 test_string_get_size_one(0, 512, "0 B", "0 B");
@@ -537,7 +563,7 @@ static __init void test_string_get_size(void) · 13 unmodified lines
537563 test_string_get_size_one(4096, U64_MAX, "75.6 ZB", "64.0 ZiB");
538564 }
539565
540−static void __init test_string_upper_lower(void)
566+static void test_upper_lower(struct kunit *test)
541567 {
542568 char *dst;
543569 int i;
@@ -547,16 +573,10 @@ static void __init test_string_upper_lower(void) · 3 unmodified lines
547573 int len = strlen(strings_upper[i].in) + 1;
548574
549575 dst = kmalloc(len, GFP_KERNEL);
550− if (!dst)
551− return;
576+ KUNIT_ASSERT_NOT_NULL(test, dst);
552577
553578 string_upper(dst, s);
554− if (memcmp(dst, strings_upper[i].out, len)) {
555− pr_warn("Test 'string_upper' failed : expected %s, got %s!\n",
556− strings_upper[i].out, dst);
557− kfree(dst);
558− return;
559− }
579+ KUNIT_EXPECT_STREQ(test, dst, strings_upper[i].out);
560580 kfree(dst);
561581 }
562582
@@ -565,45 +585,44 @@ static void __init test_string_upper_lower(void) · 2 unmodified lines
565585 int len = strlen(strings_lower[i].in) + 1;
566586
567587 dst = kmalloc(len, GFP_KERNEL);
568− if (!dst)
569− return;
588+ KUNIT_ASSERT_NOT_NULL(test, dst);
570589
571590 string_lower(dst, s);
572− if (memcmp(dst, strings_lower[i].out, len)) {
573− pr_warn("Test 'string_lower failed : : expected %s, got %s!\n",
574− strings_lower[i].out, dst);
575− kfree(dst);
576− return;
577− }
591+ KUNIT_EXPECT_STREQ(test, dst, strings_lower[i].out);
578592 kfree(dst);
579593 }
580594 }
581595
582−static int __init test_string_helpers_init(void)
596+static void test_unescape(struct kunit *test)
583597 {
584598 unsigned int i;
585599
586− pr_info("Running tests...\n");
587600 for (i = 0; i < UNESCAPE_ALL_MASK + 1; i++)
588− test_string_unescape("unescape", i, false);
589− test_string_unescape("unescape inplace",
601+ test_string_unescape(test, "unescape", i, false);
602+ test_string_unescape(test, "unescape inplace",
590603 get_random_u32_below(UNESCAPE_ALL_MASK + 1), true);
591604
592605 /* Without dictionary */
593606 for (i = 0; i < ESCAPE_ALL_MASK + 1; i++)
594− test_string_escape("escape 0", escape0, i, TEST_STRING_2_DICT_0);
607+ test_string_escape(test, "escape 0", escape0, i, TEST_STRING_2_DICT_0);
595608
596609 /* With dictionary */
597610 for (i = 0; i < ESCAPE_ALL_MASK + 1; i++)
598− test_string_escape("escape 1", escape1, i, TEST_STRING_2_DICT_1);
611+ test_string_escape(test, "escape 1", escape1, i, TEST_STRING_2_DICT_1);
612+}
599613
600− /* Test string_get_size() */
601− test_string_get_size();
614+static struct kunit_case string_helpers_test_cases[] = {
615+ KUNIT_CASE(test_get_size),
616+ KUNIT_CASE(test_upper_lower),
617+ KUNIT_CASE(test_unescape),
618+ {}
619+};
602620
603− /* Test string upper(), string_lower() */
604− test_string_upper_lower();
621+static struct kunit_suite string_helpers_test_suite = {
622+ .name = "string_helpers",
623+ .test_cases = string_helpers_test_cases,
624+};
625+
626+kunit_test_suites(&string_helpers_test_suite);
605627
606− return -EINVAL;
607−}
608−module_init(test_string_helpers_init);
609628 MODULE_LICENSE("Dual BSD/GPL");
lib/string_kunit.c+199−0
@@ -0,0 +1,199 @@
1+// SPDX-License-Identifier: GPL-2.0-only
2+/*
3+ * Test cases for string functions.
4+ */
5+
6+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7+
8+#include <kunit/test.h>
9+#include <linux/module.h>
10+#include <linux/printk.h>
11+#include <linux/slab.h>
12+#include <linux/string.h>
13+
14+static void test_memset16(struct kunit *test)
15+{
16+ unsigned i, j, k;
17+ u16 v, *p;
18+
19+ p = kunit_kzalloc(test, 256 * 2 * 2, GFP_KERNEL);
20+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p);
21+
22+ for (i = 0; i < 256; i++) {
23+ for (j = 0; j < 256; j++) {
24+ memset(p, 0xa1, 256 * 2 * sizeof(v));
25+ memset16(p + i, 0xb1b2, j);
26+ for (k = 0; k < 512; k++) {
27+ v = p[k];
28+ if (k < i) {
29+ KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1,
30+ "i:%d j:%d k:%d", i, j, k);
31+ } else if (k < i + j) {
32+ KUNIT_ASSERT_EQ_MSG(test, v, 0xb1b2,
33+ "i:%d j:%d k:%d", i, j, k);
34+ } else {
35+ KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1,
36+ "i:%d j:%d k:%d", i, j, k);
37+ }
38+ }
39+ }
40+ }
41+}
42+
43+static void test_memset32(struct kunit *test)
44+{
45+ unsigned i, j, k;
46+ u32 v, *p;
47+
48+ p = kunit_kzalloc(test, 256 * 2 * 4, GFP_KERNEL);
49+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p);
50+
51+ for (i = 0; i < 256; i++) {
52+ for (j = 0; j < 256; j++) {
53+ memset(p, 0xa1, 256 * 2 * sizeof(v));
54+ memset32(p + i, 0xb1b2b3b4, j);
55+ for (k = 0; k < 512; k++) {
56+ v = p[k];
57+ if (k < i) {
58+ KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1,
59+ "i:%d j:%d k:%d", i, j, k);
60+ } else if (k < i + j) {
61+ KUNIT_ASSERT_EQ_MSG(test, v, 0xb1b2b3b4,
62+ "i:%d j:%d k:%d", i, j, k);
63+ } else {
64+ KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1,
65+ "i:%d j:%d k:%d", i, j, k);
66+ }
67+ }
68+ }
69+ }
70+}
71+
72+static void test_memset64(struct kunit *test)
73+{
74+ unsigned i, j, k;
75+ u64 v, *p;
76+
77+ p = kunit_kzalloc(test, 256 * 2 * 8, GFP_KERNEL);
78+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, p);
79+
80+ for (i = 0; i < 256; i++) {
81+ for (j = 0; j < 256; j++) {
82+ memset(p, 0xa1, 256 * 2 * sizeof(v));
83+ memset64(p + i, 0xb1b2b3b4b5b6b7b8ULL, j);
84+ for (k = 0; k < 512; k++) {
85+ v = p[k];
86+ if (k < i) {
87+ KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1a1a1a1a1ULL,
88+ "i:%d j:%d k:%d", i, j, k);
89+ } else if (k < i + j) {
90+ KUNIT_ASSERT_EQ_MSG(test, v, 0xb1b2b3b4b5b6b7b8ULL,
91+ "i:%d j:%d k:%d", i, j, k);
92+ } else {
93+ KUNIT_ASSERT_EQ_MSG(test, v, 0xa1a1a1a1a1a1a1a1ULL,
94+ "i:%d j:%d k:%d", i, j, k);
95+ }
96+ }
97+ }
98+ }
99+}
100+
101+static void test_strchr(struct kunit *test)
102+{
103+ const char *test_string = "abcdefghijkl";
104+ const char *empty_string = "";
105+ char *result;
106+ int i;
107+
108+ for (i = 0; i < strlen(test_string) + 1; i++) {
109+ result = strchr(test_string, test_string[i]);
110+ KUNIT_ASSERT_EQ_MSG(test, result - test_string, i,
111+ "char:%c", 'a' + i);
112+ }
113+
114+ result = strchr(empty_string, '\0');
115+ KUNIT_ASSERT_PTR_EQ(test, result, empty_string);
116+
117+ result = strchr(empty_string, 'a');
118+ KUNIT_ASSERT_NULL(test, result);
119+
120+ result = strchr(test_string, 'z');
121+ KUNIT_ASSERT_NULL(test, result);
122+}
123+
124+static void test_strnchr(struct kunit *test)
125+{
126+ const char *test_string = "abcdefghijkl";
127+ const char *empty_string = "";
128+ char *result;
129+ int i, j;
130+
131+ for (i = 0; i < strlen(test_string) + 1; i++) {
132+ for (j = 0; j < strlen(test_string) + 2; j++) {
133+ result = strnchr(test_string, j, test_string[i]);
134+ if (j <= i) {
135+ KUNIT_ASSERT_NULL_MSG(test, result,
136+ "char:%c i:%d j:%d", 'a' + i, i, j);
137+ } else {
138+ KUNIT_ASSERT_EQ_MSG(test, result - test_string, i,
139+ "char:%c i:%d j:%d", 'a' + i, i, j);
140+ }
141+ }
142+ }
143+
144+ result = strnchr(empty_string, 0, '\0');
145+ KUNIT_ASSERT_NULL(test, result);
146+
147+ result = strnchr(empty_string, 1, '\0');
148+ KUNIT_ASSERT_PTR_EQ(test, result, empty_string);
149+
150+ result = strnchr(empty_string, 1, 'a');
151+ KUNIT_ASSERT_NULL(test, result);
152+
153+ result = strnchr(NULL, 0, '\0');
154+ KUNIT_ASSERT_NULL(test, result);
155+}
156+
157+static void test_strspn(struct kunit *test)
158+{
159+ static const struct strspn_test {
160+ const char str[16];
161+ const char accept[16];
162+ const char reject[16];
163+ unsigned a;
164+ unsigned r;
165+ } tests[] = {
166+ { "foobar", "", "", 0, 6 },
167+ { "abba", "abc", "ABBA", 4, 4 },
168+ { "abba", "a", "b", 1, 1 },
169+ { "", "abc", "abc", 0, 0},
170+ };
171+ const struct strspn_test *s = tests;
172+ size_t i;
173+
174+ for (i = 0; i < ARRAY_SIZE(tests); ++i, ++s) {
175+ KUNIT_ASSERT_EQ_MSG(test, s->a, strspn(s->str, s->accept),
176+ "i:%zu", i);
177+ KUNIT_ASSERT_EQ_MSG(test, s->r, strcspn(s->str, s->reject),
178+ "i:%zu", i);
179+ }
180+}
181+
182+static struct kunit_case string_test_cases[] = {
183+ KUNIT_CASE(test_memset16),
184+ KUNIT_CASE(test_memset32),
185+ KUNIT_CASE(test_memset64),
186+ KUNIT_CASE(test_strchr),
187+ KUNIT_CASE(test_strnchr),
188+ KUNIT_CASE(test_strspn),
189+ {}
190+};
191+
192+static struct kunit_suite string_test_suite = {
193+ .name = "string",
194+ .test_cases = string_test_cases,
195+};
196+
197+kunit_test_suites(&string_test_suite);
198+
199+MODULE_LICENSE("GPL v2");
lib/test_string.c+0−257
@@ -1,257 +0,0 @@
1−// SPDX-License-Identifier: GPL-2.0-only
2−#include <linux/module.h>
3−#include <linux/printk.h>
4−#include <linux/slab.h>
5−#include <linux/string.h>
6−
7−static __init int memset16_selftest(void)
8−{
9− unsigned i, j, k;
10− u16 v, *p;
11−
12− p = kmalloc(256 * 2 * 2, GFP_KERNEL);
13− if (!p)
14− return -1;
15−
16− for (i = 0; i < 256; i++) {
17− for (j = 0; j < 256; j++) {
18− memset(p, 0xa1, 256 * 2 * sizeof(v));
19− memset16(p + i, 0xb1b2, j);
20− for (k = 0; k < 512; k++) {
21− v = p[k];
22− if (k < i) {
23− if (v != 0xa1a1)
24− goto fail;
25− } else if (k < i + j) {
26− if (v != 0xb1b2)
27− goto fail;
28− } else {
29− if (v != 0xa1a1)
30− goto fail;
31− }
32− }
33− }
34− }
35−
36−fail:
37− kfree(p);
38− if (i < 256)
39− return (i << 24) | (j << 16) | k | 0x8000;
40− return 0;
41−}
42−
43−static __init int memset32_selftest(void)
44−{
45− unsigned i, j, k;
46− u32 v, *p;
47−
48− p = kmalloc(256 * 2 * 4, GFP_KERNEL);
49− if (!p)
50− return -1;
51−
52− for (i = 0; i < 256; i++) {
53− for (j = 0; j < 256; j++) {
54− memset(p, 0xa1, 256 * 2 * sizeof(v));
55− memset32(p + i, 0xb1b2b3b4, j);
56− for (k = 0; k < 512; k++) {
57− v = p[k];
58− if (k < i) {
59− if (v != 0xa1a1a1a1)
60− goto fail;
61− } else if (k < i + j) {
62− if (v != 0xb1b2b3b4)
63− goto fail;
64− } else {
65− if (v != 0xa1a1a1a1)
66− goto fail;
67− }
68− }
69− }
70− }
71−
72−fail:
73− kfree(p);
74− if (i < 256)
75− return (i << 24) | (j << 16) | k | 0x8000;
76− return 0;
77−}
78−
79−static __init int memset64_selftest(void)
80−{
81− unsigned i, j, k;
82− u64 v, *p;
83−
84− p = kmalloc(256 * 2 * 8, GFP_KERNEL);
85− if (!p)
86− return -1;
87−
88− for (i = 0; i < 256; i++) {
89− for (j = 0; j < 256; j++) {
90− memset(p, 0xa1, 256 * 2 * sizeof(v));
91− memset64(p + i, 0xb1b2b3b4b5b6b7b8ULL, j);
92− for (k = 0; k < 512; k++) {
93− v = p[k];
94− if (k < i) {
95− if (v != 0xa1a1a1a1a1a1a1a1ULL)
96− goto fail;
97− } else if (k < i + j) {
98− if (v != 0xb1b2b3b4b5b6b7b8ULL)
99− goto fail;
100− } else {
101− if (v != 0xa1a1a1a1a1a1a1a1ULL)
102− goto fail;
103− }
104− }
105− }
106− }
107−
108−fail:
109− kfree(p);
110− if (i < 256)
111− return (i << 24) | (j << 16) | k | 0x8000;
112− return 0;
113−}
114−
115−static __init int strchr_selftest(void)
116−{
117− const char *test_string = "abcdefghijkl";
118− const char *empty_string = "";
119− char *result;
120− int i;
121−
122− for (i = 0; i < strlen(test_string) + 1; i++) {
123− result = strchr(test_string, test_string[i]);
124− if (result - test_string != i)
125− return i + 'a';
126− }
127−
128− result = strchr(empty_string, '\0');
129− if (result != empty_string)
130− return 0x101;
131−
132− result = strchr(empty_string, 'a');
133− if (result)
134− return 0x102;
135−
136− result = strchr(test_string, 'z');
137− if (result)
138− return 0x103;
139−
140− return 0;
141−}
142−
143−static __init int strnchr_selftest(void)
144−{
145− const char *test_string = "abcdefghijkl";
146− const char *empty_string = "";
147− char *result;
148− int i, j;
149−
150− for (i = 0; i < strlen(test_string) + 1; i++) {
151− for (j = 0; j < strlen(test_string) + 2; j++) {
152− result = strnchr(test_string, j, test_string[i]);
153− if (j <= i) {
154− if (!result)
155− continue;
156− return ((i + 'a') << 8) | j;
157− }
158− if (result - test_string != i)
159− return ((i + 'a') << 8) | j;
160− }
161− }
162−
163− result = strnchr(empty_string, 0, '\0');
164− if (result)
165− return 0x10001;
166−
167− result = strnchr(empty_string, 1, '\0');
168− if (result != empty_string)
169− return 0x10002;
170−
171− result = strnchr(empty_string, 1, 'a');
172− if (result)
173− return 0x10003;
174−
175− result = strnchr(NULL, 0, '\0');
176− if (result)
177− return 0x10004;
178−
179− return 0;
180−}
181−
182−static __init int strspn_selftest(void)
183−{
184− static const struct strspn_test {
185− const char str[16];
186− const char accept[16];
187− const char reject[16];
188− unsigned a;
189− unsigned r;
190− } tests[] __initconst = {
191− { "foobar", "", "", 0, 6 },
192− { "abba", "abc", "ABBA", 4, 4 },
193− { "abba", "a", "b", 1, 1 },
194− { "", "abc", "abc", 0, 0},
195− };
196− const struct strspn_test *s = tests;
197− size_t i, res;
198−
199− for (i = 0; i < ARRAY_SIZE(tests); ++i, ++s) {
200− res = strspn(s->str, s->accept);
201− if (res != s->a)
202− return 0x100 + 2*i;
203− res = strcspn(s->str, s->reject);
204− if (res != s->r)
205− return 0x100 + 2*i + 1;
206− }
207− return 0;
208−}
209−
210−static __exit void string_selftest_remove(void)
211−{
212−}
213−
214−static __init int string_selftest_init(void)
215−{
216− int test, subtest;
217−
218− test = 1;
219− subtest = memset16_selftest();
220− if (subtest)
221− goto fail;
222−
223− test = 2;
224− subtest = memset32_selftest();
225− if (subtest)
226− goto fail;
227−
228− test = 3;
229− subtest = memset64_selftest();
230− if (subtest)
231− goto fail;
232−
233− test = 4;
234− subtest = strchr_selftest();
235− if (subtest)
236− goto fail;
237−
238− test = 5;
239− subtest = strnchr_selftest();
240− if (subtest)
241− goto fail;
242−
243− test = 6;
244− subtest = strspn_selftest();
245− if (subtest)
246− goto fail;
247−
248− pr_info("String selftests succeeded\n");
249− return 0;
250−fail:
251− pr_crit("String selftest failure %d.%08x\n", test, subtest);
252− return 0;
253−}
254−
255−module_init(string_selftest_init);
256−module_exit(string_selftest_remove);
257−MODULE_LICENSE("GPL v2");
lib/test_ubsan.c+39−2
@@ -11,6 +11,39 @@ typedef void(*test_ubsan_fp)(void); · 10 unmodified lines
1111 #config, IS_ENABLED(config) ? "y" : "n"); \
1212 } while (0)
1313
14+static void test_ubsan_add_overflow(void)
15+{
16+ volatile int val = INT_MAX;
17+
18+ UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);
19+ val += 2;
20+}
21+
22+static void test_ubsan_sub_overflow(void)
23+{
24+ volatile int val = INT_MIN;
25+ volatile int val2 = 2;
26+
27+ UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);
28+ val -= val2;
29+}
30+
31+static void test_ubsan_mul_overflow(void)
32+{
33+ volatile int val = INT_MAX / 2;
34+
35+ UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);
36+ val *= 3;
37+}
38+
39+static void test_ubsan_negate_overflow(void)
40+{
41+ volatile int val = INT_MIN;
42+
43+ UBSAN_TEST(CONFIG_UBSAN_SIGNED_WRAP);
44+ val = -val;
45+}
46+
1447 static void test_ubsan_divrem_overflow(void)
1548 {
1649 volatile int val = 16;
@@ -23,8 +56,8 @@ static void test_ubsan_divrem_overflow(void) · 6 unmodified lines
2356 static void test_ubsan_shift_out_of_bounds(void)
2457 {
2558 volatile int neg = -1, wrap = 4;
26− int val1 = 10;
27− int val2 = INT_MAX;
59+ volatile int val1 = 10;
60+ volatile int val2 = INT_MAX;
2861
2962 UBSAN_TEST(CONFIG_UBSAN_SHIFT, "negative exponent");
3063 val1 <<= neg;
@@ -90,6 +123,10 @@ static void test_ubsan_misaligned_access(void) · 59 unmodified lines
90123 }
91124
92125 static const test_ubsan_fp test_ubsan_array[] = {
126+ test_ubsan_add_overflow,
127+ test_ubsan_sub_overflow,
128+ test_ubsan_mul_overflow,
129+ test_ubsan_negate_overflow,
93130 test_ubsan_shift_out_of_bounds,
94131 test_ubsan_out_of_bounds,
95132 test_ubsan_load_invalid_value,
lib/ubsan.c+68−0
@@ -222,6 +222,74 @@ static void ubsan_epilogue(void) · 221 unmodified lines
222222 check_panic_on_warn("UBSAN");
223223 }
224224
225+static void handle_overflow(struct overflow_data *data, void *lhs,
226+ void *rhs, char op)
227+{
228+
229+ struct type_descriptor *type = data->type;
230+ char lhs_val_str[VALUE_LENGTH];
231+ char rhs_val_str[VALUE_LENGTH];
232+
233+ if (suppress_report(&data->location))
234+ return;
235+
236+ ubsan_prologue(&data->location, type_is_signed(type) ?
237+ "signed-integer-overflow" :
238+ "unsigned-integer-overflow");
239+
240+ val_to_string(lhs_val_str, sizeof(lhs_val_str), type, lhs);
241+ val_to_string(rhs_val_str, sizeof(rhs_val_str), type, rhs);
242+ pr_err("%s %c %s cannot be represented in type %s\n",
243+ lhs_val_str,
244+ op,
245+ rhs_val_str,
246+ type->type_name);
247+
248+ ubsan_epilogue();
249+}
250+
251+void __ubsan_handle_add_overflow(void *data,
252+ void *lhs, void *rhs)
253+{
254+
255+ handle_overflow(data, lhs, rhs, '+');
256+}
257+EXPORT_SYMBOL(__ubsan_handle_add_overflow);
258+
259+void __ubsan_handle_sub_overflow(void *data,
260+ void *lhs, void *rhs)
261+{
262+ handle_overflow(data, lhs, rhs, '-');
263+}
264+EXPORT_SYMBOL(__ubsan_handle_sub_overflow);
265+
266+void __ubsan_handle_mul_overflow(void *data,
267+ void *lhs, void *rhs)
268+{
269+ handle_overflow(data, lhs, rhs, '*');
270+}
271+EXPORT_SYMBOL(__ubsan_handle_mul_overflow);
272+
273+void __ubsan_handle_negate_overflow(void *_data, void *old_val)
274+{
275+ struct overflow_data *data = _data;
276+ char old_val_str[VALUE_LENGTH];
277+
278+ if (suppress_report(&data->location))
279+ return;
280+
281+ ubsan_prologue(&data->location, "negation-overflow");
282+
283+ val_to_string(old_val_str, sizeof(old_val_str), data->type, old_val);
284+
285+ pr_err("negation of %s cannot be represented in type %s:\n",
286+ old_val_str, data->type->type_name);
287+
288+ ubsan_epilogue();
289+}
290+EXPORT_SYMBOL(__ubsan_handle_negate_overflow);
291+
292+
225293 void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs)
226294 {
227295 struct overflow_data *data = _data;
lib/ubsan.h+4−0
@@ -124,6 +124,10 @@ typedef s64 s_max; · 123 unmodified lines
124124 typedef u64 u_max;
125125 #endif
126126
127+void __ubsan_handle_add_overflow(void *data, void *lhs, void *rhs);
128+void __ubsan_handle_sub_overflow(void *data, void *lhs, void *rhs);
129+void __ubsan_handle_mul_overflow(void *data, void *lhs, void *rhs);
130+void __ubsan_handle_negate_overflow(void *_data, void *old_val);
127131 void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs);
128132 void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, void *ptr);
129133 void __ubsan_handle_type_mismatch_v1(void *_data, void *ptr);
scripts/Makefile.lib+4−1
@@ -175,8 +175,11 @@ endif · 174 unmodified lines
175175
176176 ifeq ($(CONFIG_UBSAN),y)
177177 _c_flags += $(if $(patsubst n%,, \
178− $(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_SANITIZE)$(CONFIG_UBSAN_SANITIZE_ALL)), \
178+ $(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_SANITIZE)y), \
179179 $(CFLAGS_UBSAN))
180+_c_flags += $(if $(patsubst n%,, \
181+ $(UBSAN_SIGNED_WRAP_$(basetarget).o)$(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_SIGNED_WRAP)$(UBSAN_SANITIZE)y), \
182+ $(CFLAGS_UBSAN_SIGNED_WRAP))
180183 endif
181184
182185 ifeq ($(CONFIG_KCOV),y)
scripts/Makefile.ubsan+4−1
@@ -10,6 +10,9 @@ ubsan-cflags-$(CONFIG_UBSAN_DIV_ZERO) += -fsanitize=integer-divide-by-zero · 9 unmodified lines
1010 ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable
1111 ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool
1212 ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum
13−ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error
13+ubsan-cflags-$(CONFIG_UBSAN_TRAP) += $(call cc-option,-fsanitize-trap=undefined,-fsanitize-undefined-trap-on-error)
1414
1515 export CFLAGS_UBSAN := $(ubsan-cflags-y)
16+
17+ubsan-signed-wrap-cflags-$(CONFIG_UBSAN_SIGNED_WRAP) += -fsanitize=signed-integer-overflow
18+export CFLAGS_UBSAN_SIGNED_WRAP := $(ubsan-signed-wrap-cflags-y)
scripts/coccinelle/api/string_choices.cocci+41−0
@@ -0,0 +1,41 @@
1+// SPDX-License-Identifier: GPL-2.0-only
2+/// Find places to use string_choices.h's various helpers.
3+//
4+// Confidence: Medium
5+// Options: --no-includes --include-headers
6+virtual patch
7+virtual context
8+virtual report
9+
10+@str_plural depends on patch@
11+expression E;
12+@@
13+(
14+- ((E == 1) ? "" : "s")
15++ str_plural(E)
16+|
17+- ((E != 1) ? "s" : "")
18++ str_plural(E)
19+|
20+- ((E > 1) ? "s" : "")
21++ str_plural(E)
22+)
23+
24+@str_plural_r depends on !patch exists@
25+expression E;
26+position P;
27+@@
28+(
29+* ((E@P == 1) ? "" : "s")
30+|
31+* ((E@P != 1) ? "s" : "")
32+|
33+* ((E@P > 1) ? "s" : "")
34+)
35+
36+@script:python depends on report@
37+p << str_plural_r.P;
38+e << str_plural_r.E;
39+@@
40+
41+coccilib.report.print_report(p[0], "opportunity for str_plural(%s)" % e)
scripts/coccinelle/misc/struct_size.cocci+74−0
@@ -0,0 +1,74 @@
1+// SPDX-License-Identifier: GPL-2.0-only
2+///
3+/// Check for code that could use struct_size().
4+///
5+// Confidence: Medium
6+// Author: Jacob Keller <jacob.e.keller@intel.com>
7+// Copyright: (C) 2023 Intel Corporation
8+// Options: --no-includes --include-headers
9+
10+virtual patch
11+virtual context
12+virtual org
13+virtual report
14+
15+// the overflow Kunit tests have some code which intentionally does not use
16+// the macros, so we want to ignore this code when reporting potential
17+// issues.
18+@overflow_tests@
19+identifier f = overflow_size_helpers_test;
20+@@
21+
22+f
23+
24+//----------------------------------------------------------
25+// For context mode
26+//----------------------------------------------------------
27+
28+@depends on !overflow_tests && context@
29+expression E1, E2;
30+identifier m;
31+@@
32+(
33+* (sizeof(*E1) + (E2 * sizeof(*E1->m)))
34+)
35+
36+//----------------------------------------------------------
37+// For patch mode
38+//----------------------------------------------------------
39+
40+@depends on !overflow_tests && patch@
41+expression E1, E2;
42+identifier m;
43+@@
44+(
45+- (sizeof(*E1) + (E2 * sizeof(*E1->m)))
46++ struct_size(E1, m, E2)
47+)
48+
49+//----------------------------------------------------------
50+// For org and report mode
51+//----------------------------------------------------------
52+
53+@r depends on !overflow_tests && (org || report)@
54+expression E1, E2;
55+identifier m;
56+position p;
57+@@
58+(
59+ (sizeof(*E1)@p + (E2 * sizeof(*E1->m)))
60+)
61+
62+@script:python depends on org@
63+p << r.p;
64+@@
65+
66+coccilib.org.print_todo(p[0], "WARNING should use struct_size")
67+
68+@script:python depends on report@
69+p << r.p;
70+@@
71+
72+msg="WARNING: Use struct_size"
73+coccilib.report.print_report(p[0], msg)
74+
scripts/leaking_addresses.pl+74−16
@@ -23,6 +23,7 @@ use strict; · 22 unmodified lines
2323 use POSIX;
2424 use File::Basename;
2525 use File::Spec;
26+use File::Temp qw/tempfile/;
2627 use Cwd 'abs_path';
2728 use Term::ANSIColor qw(:constants);
2829 use Getopt::Long qw(:config no_auto_abbrev);
@@ -51,10 +52,13 @@ my $input_raw = ""; # Read raw results from file instead of scanning. · 22 unmodified lines
5152 my $suppress_dmesg = 0; # Don't show dmesg in output.
5253 my $squash_by_path = 0; # Summary report grouped by absolute path.
5354 my $squash_by_filename = 0; # Summary report grouped by filename.
55+my $kallsyms_file = ""; # Kernel symbols file.
5456 my $kernel_config_file = ""; # Kernel configuration file.
5557 my $opt_32bit = 0; # Scan 32-bit kernel.
5658 my $page_offset_32bit = 0; # Page offset for 32-bit kernel.
5759
60+my @kallsyms = ();
61+
5862 # Skip these absolute paths.
5963 my @skip_abs = (
6064 '/proc/kmsg',
@@ -95,6 +99,8 @@ Options: · 34 unmodified lines
9599 --squash-by-path Show one result per unique path.
96100 --squash-by-filename Show one result per unique filename.
97101 --kernel-config-file=<file> Kernel configuration file (e.g /boot/config)
102+ --kallsyms=<file> Read kernel symbol addresses from file (for
103+ scanning binary files).
98104 --32-bit Scan 32-bit kernel.
99105 --page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
100106 -d, --debug Display debugging output.
@@ -115,6 +121,7 @@ GetOptions( · 14 unmodified lines
115121 'squash-by-path' => \$squash_by_path,
116122 'squash-by-filename' => \$squash_by_filename,
117123 'raw' => \$raw,
124+ 'kallsyms=s' => \$kallsyms_file,
118125 'kernel-config-file=s' => \$kernel_config_file,
119126 '32-bit' => \$opt_32bit,
120127 'page-offset-32-bit=o' => \$page_offset_32bit,
@@ -155,6 +162,25 @@ if ($output_raw) { · 34 unmodified lines
155162 select $fh;
156163 }
157164
165+if ($kallsyms_file) {
166+ open my $fh, '<', $kallsyms_file or die "$0: $kallsyms_file: $!\n";
167+ while (<$fh>) {
168+ chomp;
169+ my @entry = split / /, $_;
170+ my $addr_text = $entry[0];
171+ if ($addr_text !~ /^0/) {
172+ # TODO: Why is hex() so impossibly slow?
173+ my $addr = hex($addr_text);
174+ my $symbol = $entry[2];
175+ # Only keep kernel text addresses.
176+ my $long = pack("J", $addr);
177+ my $entry = [$long, $symbol];
178+ push @kallsyms, $entry;
179+ }
180+ }
181+ close $fh;
182+}
183+
158184 parse_dmesg();
159185 walk(@DIRS);
160186
@@ -221,6 +247,7 @@ sub get_kernel_config_option · 60 unmodified lines
221247 {
222248 my ($option) = @_;
223249 my $value = "";
250+ my $tmp_fh;
224251 my $tmp_file = "";
225252 my @config_files;
226253
@@ -228,7 +255,8 @@ sub get_kernel_config_option · 1 unmodified line
228255 if ($kernel_config_file ne "") {
229256 @config_files = ($kernel_config_file);
230257 } elsif (-R "/proc/config.gz") {
231− my $tmp_file = "/tmp/tmpkconf";
258+ ($tmp_fh, $tmp_file) = tempfile("config.gz-XXXXXX",
259+ UNLINK => 1);
232260
233261 if (system("gunzip < /proc/config.gz > $tmp_file")) {
234262 dprint("system(gunzip < /proc/config.gz) failed\n");
@@ -250,10 +278,6 @@ sub get_kernel_config_option · 15 unmodified lines
250278 }
251279 }
252280
253− if ($tmp_file ne "") {
254− system("rm -f $tmp_file");
255− }
256−
257281 return $value;
258282 }
259283
@@ -285,9 +309,10 @@ sub is_false_positive · 25 unmodified lines
285309 return is_false_positive_32bit($match);
286310 }
287311
288− # 64 bit false positives.
289−
290− if ($match =~ '\b(0x)?(f|F){16}\b' or
312+ # Ignore 64 bit false positives:
313+ # 0xfffffffffffffff[0-f]
314+ # 0x0000000000000000
315+ if ($match =~ '\b(0x)?(f|F){15}[0-9a-f]\b' or
291316 $match =~ '\b(0x)?0{16}\b') {
292317 return 1;
293318 }
@@ -304,7 +329,7 @@ sub is_false_positive_32bit · 10 unmodified lines
304329 my ($match) = @_;
305330 state $page_offset = get_page_offset();
306331
307− if ($match =~ '\b(0x)?(f|F){8}\b') {
332+ if ($match =~ '\b(0x)?(f|F){7}[0-9a-f]\b') {
308333 return 1;
309334 }
310335
@@ -347,18 +372,23 @@ sub is_in_vsyscall_memory_region · 36 unmodified lines
347372 # True if argument potentially contains a kernel address.
348373 sub may_leak_address
349374 {
350− my ($line) = @_;
375+ my ($path, $line) = @_;
351376 my $address_re;
352377
353− # Signal masks.
378+ # Ignore Signal masks.
354379 if ($line =~ '^SigBlk:' or
355380 $line =~ '^SigIgn:' or
356381 $line =~ '^SigCgt:') {
357382 return 0;
358383 }
359384
360− if ($line =~ '\bKEY=[[:xdigit:]]{14} [[:xdigit:]]{16} [[:xdigit:]]{16}\b' or
361− $line =~ '\b[[:xdigit:]]{14} [[:xdigit:]]{16} [[:xdigit:]]{16}\b') {
385+ # Ignore input device reporting.
386+ # /proc/bus/input/devices: B: KEY=402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
387+ # /sys/devices/platform/i8042/serio0/input/input1/uevent: KEY=402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
388+ # /sys/devices/platform/i8042/serio0/input/input1/capabilities/key: 402000000 3803078f800d001 feffffdfffefffff fffffffffffffffe
389+ if ($line =~ '\bKEY=[[:xdigit:]]{9,14} [[:xdigit:]]{16} [[:xdigit:]]{16}\b' or
390+ ($path =~ '\bkey$' and
391+ $line =~ '\b[[:xdigit:]]{9,14} [[:xdigit:]]{16} [[:xdigit:]]{16}\b')) {
362392 return 0;
363393 }
364394
@@ -401,7 +431,7 @@ sub parse_dmesg · 36 unmodified lines
401431 {
402432 open my $cmd, '-|', 'dmesg';
403433 while (<$cmd>) {
404− if (may_leak_address($_)) {
434+ if (may_leak_address("dmesg", $_)) {
405435 print 'dmesg: ' . $_;
406436 }
407437 }
@@ -442,6 +472,25 @@ sub timed_parse_file · 34 unmodified lines
442472 }
443473 }
444474
475+sub parse_binary
476+{
477+ my ($file) = @_;
478+
479+ open my $fh, "<:raw", $file or return;
480+ local $/ = undef;
481+ my $bytes = <$fh>;
482+ close $fh;
483+
484+ foreach my $entry (@kallsyms) {
485+ my $addr = $entry->[0];
486+ my $symbol = $entry->[1];
487+ my $offset = index($bytes, $addr);
488+ if ($offset != -1) {
489+ printf("$file: $symbol @ $offset\n");
490+ }
491+ }
492+}
493+
445494 sub parse_file
446495 {
447496 my ($file) = @_;
@@ -451,13 +500,22 @@ sub parse_file · 3 unmodified lines
451500 }
452501
453502 if (! -T $file) {
503+ if ($file =~ m|^/sys/kernel/btf/| or
504+ $file =~ m|^/sys/devices/pci| or
505+ $file =~ m|^/sys/firmware/efi/efivars/| or
506+ $file =~ m|^/proc/bus/pci/|) {
507+ return;
508+ }
509+ if (scalar @kallsyms > 0) {
510+ parse_binary($file);
511+ }
454512 return;
455513 }
456514
457515 open my $fh, "<", $file or return;
458516 while ( <$fh> ) {
459517 chomp;
460− if (may_leak_address($_)) {
518+ if (may_leak_address($file, $_)) {
461519 printf("$file: $_\n");
462520 }
463521 }
@@ -469,7 +527,7 @@ sub check_path_for_leaks · 5 unmodified lines
469527 {
470528 my ($path) = @_;
471529
472− if (may_leak_address($path)) {
530+ if (may_leak_address($path, $path)) {
473531 printf("Path name may contain address: $path\n");
474532 }
475533 }
tools/objtool/check.c+12−0
@@ -3620,6 +3620,18 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, · 3619 unmodified lines
36203620 }
36213621
36223622 if (!save_insn->visited) {
3623+ /*
3624+ * If the restore hint insn is at the
3625+ * beginning of a basic block and was
3626+ * branched to from elsewhere, and the
3627+ * save insn hasn't been visited yet,
3628+ * defer following this branch for now.
3629+ * It will be seen later via the
3630+ * straight-line path.
3631+ */
3632+ if (!prev_insn)
3633+ return 0;
3634+
36233635 WARN_INSN(insn, "objtool isn't smart enough to handle this CFI save/restore combo");
36243636 return 1;
36253637 }
tools/objtool/noreturns.h+1−1
@@ -6,6 +6,7 @@ · 5 unmodified lines
66 *
77 * Yes, this is unfortunate. A better solution is in the works.
88 */
9+NORETURN(__fortify_panic)
910 NORETURN(__kunit_abort)
1011 NORETURN(__module_put_and_kthread_exit)
1112 NORETURN(__reiserfs_panic)
@@ -22,7 +23,6 @@ NORETURN(do_exit) · 10 unmodified lines
2223 NORETURN(do_group_exit)
2324 NORETURN(do_task_dead)
2425 NORETURN(ex_handler_msr_mce)
25−NORETURN(fortify_panic)
2626 NORETURN(hlt_play_dead)
2727 NORETURN(hv_ghcb_terminate)
2828 NORETURN(kthread_complete_and_exit)
tools/testing/selftests/powerpc/primitives/linux/bitops.h+0−0

Empty file added.

tools/testing/selftests/powerpc/primitives/linux/wordpart.h+1−0
@@ -0,0 +1 @@
1+../../../../../../include/linux/wordpart.h