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
49Usage49Usage
50-----50-----
51 51
52To enable UBSAN configure kernel with::52To enable UBSAN, configure the kernel with::
53 53
54 CONFIG_UBSAN=y54 CONFIG_UBSAN=y
55 55
56and to check the entire kernel::56To exclude files from being instrumented use::
57
58 CONFIG_UBSAN_SANITIZE_ALL=y
59
60To enable instrumentation for specific files or directories, add a line
61similar 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
71To exclude files from being instrumented even if
72``CONFIG_UBSAN_SANITIZE_ALL=y``, use::
73 57
74 UBSAN_SANITIZE_main.o := n58 UBSAN_SANITIZE_main.o := n
75 59
76and::60and to exclude all targets in one directory use::
77 61
78 UBSAN_SANITIZE := n62 UBSAN_SANITIZE := n
79 63
64When disabled for all targets, specific files can be enabled using::
65
66 UBSAN_SANITIZE_main.o := y
67
80Detection of unaligned accesses controlled through the separate option -68Detection of unaligned accesses controlled through the separate option -
81CONFIG_UBSAN_ALIGNMENT. It's off by default on architectures that support69CONFIG_UBSAN_ALIGNMENT. It's off by default on architectures that support
82unaligned accesses (CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y). One could70unaligned accesses (CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS=y). One could
MAINTAINERS+22−4
@@ -8989,9 +8989,10 @@ F: include/linux/string.h · 8988 unmodified lines
8989F: include/linux/string_choices.h8989F: include/linux/string_choices.h
8990F: include/linux/string_helpers.h8990F: include/linux/string_helpers.h
8991F: lib/string.c8991F: lib/string.c
8992F: lib/string_kunit.c
8992F: lib/string_helpers.c8993F: lib/string_helpers.c
8993F: lib/test-string_helpers.c8994F: lib/string_helpers_kunit.c
8994F: lib/test_string.c8995F: scripts/coccinelle/api/string_choices.cocci
8995 8996
8996GENERIC UIO DRIVER FOR PCI DEVICES8997GENERIC UIO DRIVER FOR PCI DEVICES
8997M: "Michael S. Tsirkin" <mst@redhat.com>8998M: "Michael S. Tsirkin" <mst@redhat.com>
@@ -12178,11 +12179,11 @@ F: Documentation/scsi/53c700.rst · 3180 unmodified lines
12178F: drivers/scsi/53c700*12179F: drivers/scsi/53c700*
12179 12180
12180LEAKING_ADDRESSES12181LEAKING_ADDRESSES
12181M: Tobin C. Harding <me@tobin.cc>
12182M: Tycho Andersen <tycho@tycho.pizza>12182M: Tycho Andersen <tycho@tycho.pizza>
12183R: Kees Cook <keescook@chromium.org>
12183L: linux-hardening@vger.kernel.org12184L: linux-hardening@vger.kernel.org
12184S: Maintained12185S: Maintained
12185T: git git://git.kernel.org/pub/scm/linux/kernel/git/tobin/leaks.git12186T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
12186F: scripts/leaking_addresses.pl12187F: scripts/leaking_addresses.pl
12187 12188
12188LED SUBSYSTEM12189LED SUBSYSTEM
@@ -22503,6 +22504,23 @@ F: Documentation/block/ublk.rst · 10314 unmodified lines
22503F: drivers/block/ublk_drv.c22504F: drivers/block/ublk_drv.c
22504F: include/uapi/linux/ublk_cmd.h22505F: include/uapi/linux/ublk_cmd.h
22505 22506
22507UBSAN
22508M: Kees Cook <keescook@chromium.org>
22509R: Marco Elver <elver@google.com>
22510R: Andrey Konovalov <andreyknvl@gmail.com>
22511R: Andrey Ryabinin <ryabinin.a.a@gmail.com>
22512L: kasan-dev@googlegroups.com
22513L: linux-hardening@vger.kernel.org
22514S: Supported
22515T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git for-next/hardening
22516F: Documentation/dev-tools/ubsan.rst
22517F: include/linux/ubsan.h
22518F: lib/Kconfig.ubsan
22519F: lib/test_ubsan.c
22520F: lib/ubsan.c
22521F: scripts/Makefile.ubsan
22522K: \bARCH_HAS_UBSAN\b
22523
22506UCLINUX (M68KNOMMU AND COLDFIRE)22524UCLINUX (M68KNOMMU AND COLDFIRE)
22507M: Greg Ungerer <gerg@linux-m68k.org>22525M: Greg Ungerer <gerg@linux-m68k.org>
22508L: linux-m68k@lists.linux-m68k.org22526L: linux-m68k@lists.linux-m68k.org
arch/arm/Kconfig+1−1
@@ -29,7 +29,7 @@ config ARM · 28 unmodified lines
29 select ARCH_HAVE_NMI_SAFE_CMPXCHG if CPU_V7 || CPU_V7M || CPU_V6K29 select ARCH_HAVE_NMI_SAFE_CMPXCHG if CPU_V7 || CPU_V7M || CPU_V6K
30 select ARCH_HAS_GCOV_PROFILE_ALL30 select ARCH_HAS_GCOV_PROFILE_ALL
31 select ARCH_KEEP_MEMBLOCK31 select ARCH_KEEP_MEMBLOCK
32 select ARCH_HAS_UBSAN_SANITIZE_ALL32 select ARCH_HAS_UBSAN
33 select ARCH_MIGHT_HAVE_PC_PARPORT33 select ARCH_MIGHT_HAVE_PC_PARPORT
34 select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX34 select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX
35 select ARCH_OPTIONAL_KERNEL_RWX_DEFAULT if CPU_V735 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
154 putstr(" done, booting the kernel.\n");154 putstr(" done, booting the kernel.\n");
155}155}
156 156
157void fortify_panic(const char *name)157void __fortify_panic(const u8 reason, size_t avail, size_t size)
158{158{
159 error("detected buffer overflow");159 error("detected buffer overflow");
160}160}
arch/arm/boot/compressed/misc.h+1−1
@@ -10,7 +10,7 @@ void __div0(void); · 9 unmodified lines
10void10void
11decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,11decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p,
12 unsigned long free_mem_ptr_end_p, int arch_id);12 unsigned long free_mem_ptr_end_p, int arch_id);
13void fortify_panic(const char *name);13void __fortify_panic(const u8 reason, size_t avail, size_t size);
14int atags_to_fdt(void *atag_list, void *fdt, int total_space);14int atags_to_fdt(void *atag_list, void *fdt, int total_space);
15uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt);15uint32_t fdt_check_mem_start(uint32_t mem_start, const void *fdt);
16int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x));16int 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
8 * Little-endian word-at-a-time zero byte handling.8 * Little-endian word-at-a-time zero byte handling.
9 * Heavily based on the x86 algorithm.9 * Heavily based on the x86 algorithm.
10 */10 */
11#include <linux/kernel.h>11#include <linux/bitops.h>
12#include <linux/wordpart.h>
12 13
13struct word_at_a_time {14struct word_at_a_time {
14 const unsigned long one_bits, high_bits;15 const unsigned long one_bits, high_bits;
arch/arm64/Kconfig+1−1
@@ -107,7 +107,7 @@ config ARM64 · 106 unmodified lines
107 select ARCH_WANT_LD_ORPHAN_WARN107 select ARCH_WANT_LD_ORPHAN_WARN
108 select ARCH_WANTS_NO_INSTR108 select ARCH_WANTS_NO_INSTR
109 select ARCH_WANTS_THP_SWAP if ARM64_4K_PAGES109 select ARCH_WANTS_THP_SWAP if ARM64_4K_PAGES
110 select ARCH_HAS_UBSAN_SANITIZE_ALL110 select ARCH_HAS_UBSAN
111 select ARM_AMBA111 select ARM_AMBA
112 select ARM_ARCH_TIMER112 select ARM_ARCH_TIMER
113 select ARM_GIC113 select ARM_GIC
arch/arm64/include/asm/word-at-a-time.h+2−1
@@ -9,7 +9,8 @@ · 8 unmodified lines
9 9
10#ifndef __AARCH64EB__10#ifndef __AARCH64EB__
11 11
12#include <linux/kernel.h>12#include <linux/bitops.h>
13#include <linux/wordpart.h>
13 14
14struct word_at_a_time {15struct word_at_a_time {
15 const unsigned long one_bits, high_bits;16 const unsigned long one_bits, high_bits;
arch/mips/Kconfig+1−1
@@ -14,7 +14,7 @@ config MIPS · 13 unmodified lines
14 select ARCH_HAS_STRNCPY_FROM_USER14 select ARCH_HAS_STRNCPY_FROM_USER
15 select ARCH_HAS_STRNLEN_USER15 select ARCH_HAS_STRNLEN_USER
16 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST16 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
17 select ARCH_HAS_UBSAN_SANITIZE_ALL17 select ARCH_HAS_UBSAN
18 select ARCH_HAS_GCOV_PROFILE_ALL18 select ARCH_HAS_GCOV_PROFILE_ALL
19 select ARCH_KEEP_MEMBLOCK19 select ARCH_KEEP_MEMBLOCK
20 select ARCH_USE_BUILTIN_BSWAP20 select ARCH_USE_BUILTIN_BSWAP
arch/parisc/Kconfig+1−1
@@ -12,7 +12,7 @@ config PARISC · 11 unmodified lines
12 select ARCH_HAS_ELF_RANDOMIZE12 select ARCH_HAS_ELF_RANDOMIZE
13 select ARCH_HAS_STRICT_KERNEL_RWX13 select ARCH_HAS_STRICT_KERNEL_RWX
14 select ARCH_HAS_STRICT_MODULE_RWX14 select ARCH_HAS_STRICT_MODULE_RWX
15 select ARCH_HAS_UBSAN_SANITIZE_ALL15 select ARCH_HAS_UBSAN
16 select ARCH_HAS_PTE_SPECIAL16 select ARCH_HAS_PTE_SPECIAL
17 select ARCH_NO_SG_CHAIN17 select ARCH_NO_SG_CHAIN
18 select ARCH_SUPPORTS_HUGETLBFS if PA2018 select ARCH_SUPPORTS_HUGETLBFS if PA20
arch/powerpc/Kconfig+1−1
@@ -154,7 +154,7 @@ config PPC · 153 unmodified lines
154 select ARCH_HAS_SYSCALL_WRAPPER if !SPU_BASE && !COMPAT154 select ARCH_HAS_SYSCALL_WRAPPER if !SPU_BASE && !COMPAT
155 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST155 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
156 select ARCH_HAS_UACCESS_FLUSHCACHE156 select ARCH_HAS_UACCESS_FLUSHCACHE
157 select ARCH_HAS_UBSAN_SANITIZE_ALL157 select ARCH_HAS_UBSAN
158 select ARCH_HAVE_NMI_SAFE_CMPXCHG158 select ARCH_HAVE_NMI_SAFE_CMPXCHG
159 select ARCH_KEEP_MEMBLOCK159 select ARCH_KEEP_MEMBLOCK
160 select ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE if PPC_RADIX_MMU160 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
4/*4/*
5 * Word-at-a-time interfaces for PowerPC.5 * Word-at-a-time interfaces for PowerPC.
6 */6 */
7 7#include <linux/bitops.h>
8#include <linux/kernel.h>8#include <linux/wordpart.h>
9#include <asm/asm-compat.h>9#include <asm/asm-compat.h>
10#include <asm/extable.h>10#include <asm/extable.h>
11 11
arch/riscv/Kconfig+1−1
@@ -37,7 +37,7 @@ config RISCV · 36 unmodified lines
37 select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL37 select ARCH_HAS_STRICT_MODULE_RWX if MMU && !XIP_KERNEL
38 select ARCH_HAS_SYSCALL_WRAPPER38 select ARCH_HAS_SYSCALL_WRAPPER
39 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST39 select ARCH_HAS_TICK_BROADCAST if GENERIC_CLOCKEVENTS_BROADCAST
40 select ARCH_HAS_UBSAN_SANITIZE_ALL40 select ARCH_HAS_UBSAN
41 select ARCH_HAS_VDSO_DATA41 select ARCH_HAS_VDSO_DATA
42 select ARCH_KEEP_MEMBLOCK if ACPI42 select ARCH_KEEP_MEMBLOCK if ACPI
43 select ARCH_OPTIONAL_KERNEL_RWX if ARCH_HAS_STRICT_KERNEL_RWX43 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
10 10
11 11
12#include <asm/asm-extable.h>12#include <asm/asm-extable.h>
13#include <linux/kernel.h>13#include <linux/bitops.h>
14#include <linux/wordpart.h>
14 15
15struct word_at_a_time {16struct word_at_a_time {
16 const unsigned long one_bits, high_bits;17 const unsigned long one_bits, high_bits;
arch/s390/Kconfig+1−1
@@ -82,7 +82,7 @@ config S390 · 81 unmodified lines
82 select ARCH_HAS_STRICT_KERNEL_RWX82 select ARCH_HAS_STRICT_KERNEL_RWX
83 select ARCH_HAS_STRICT_MODULE_RWX83 select ARCH_HAS_STRICT_MODULE_RWX
84 select ARCH_HAS_SYSCALL_WRAPPER84 select ARCH_HAS_SYSCALL_WRAPPER
85 select ARCH_HAS_UBSAN_SANITIZE_ALL85 select ARCH_HAS_UBSAN
86 select ARCH_HAS_VDSO_DATA86 select ARCH_HAS_VDSO_DATA
87 select ARCH_HAVE_NMI_SAFE_CMPXCHG87 select ARCH_HAVE_NMI_SAFE_CMPXCHG
88 select ARCH_INLINE_READ_LOCK88 select ARCH_INLINE_READ_LOCK
arch/s390/include/asm/word-at-a-time.h+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
2#ifndef _ASM_WORD_AT_A_TIME_H2#ifndef _ASM_WORD_AT_A_TIME_H
3#define _ASM_WORD_AT_A_TIME_H3#define _ASM_WORD_AT_A_TIME_H
4 4
5#include <linux/kernel.h>5#include <linux/bitops.h>
6#include <linux/wordpart.h>
6#include <asm/asm-extable.h>7#include <asm/asm-extable.h>
7#include <asm/bitsperlong.h>8#include <asm/bitsperlong.h>
8 9
arch/sh/boot/compressed/Makefile+1−0
@@ -12,6 +12,7 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \ · 11 unmodified lines
12 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo $(OBJECTS)12 vmlinux.bin.lzma vmlinux.bin.xz vmlinux.bin.lzo $(OBJECTS)
13 13
14GCOV_PROFILE := n14GCOV_PROFILE := n
15UBSAN_SANITIZE := n
15 16
16#17#
17# IMAGE_OFFSET is the load offset of the compression loader18# 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
5#ifdef CONFIG_CPU_BIG_ENDIAN5#ifdef CONFIG_CPU_BIG_ENDIAN
6# include <asm-generic/word-at-a-time.h>6# include <asm-generic/word-at-a-time.h>
7#else7#else
8#include <linux/bitops.h>
9#include <linux/wordpart.h>
8/*10/*
9 * Little-endian version cribbed from x86.11 * Little-endian version cribbed from x86.
10 */12 */
arch/sparc/vdso/Makefile+1−0
@@ -2,6 +2,7 @@ · 1 unmodified line
2#2#
3# Building vDSO images for sparc.3# Building vDSO images for sparc.
4#4#
5UBSAN_SANITIZE := n
5 6
6# files to link into the vdso7# files to link into the vdso
7vobjs-y := vdso-note.o vclock_gettime.o8vobjs-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
265static void uml_net_get_drvinfo(struct net_device *dev,265static void uml_net_get_drvinfo(struct net_device *dev,
266 struct ethtool_drvinfo *info)266 struct ethtool_drvinfo *info)
267{267{
268 strscpy(info->driver, DRIVER_NAME, sizeof(info->driver));268 strscpy(info->driver, DRIVER_NAME);
269}269}
270 270
271static const struct ethtool_ops uml_net_ethtool_ops = {271static 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
1373static void vector_net_get_drvinfo(struct net_device *dev,1373static void vector_net_get_drvinfo(struct net_device *dev,
1374 struct ethtool_drvinfo *info)1374 struct ethtool_drvinfo *info)
1375{1375{
1376 strscpy(info->driver, DRIVER_NAME, sizeof(info->driver));1376 strscpy(info->driver, DRIVER_NAME);
1377}1377}
1378 1378
1379static int vector_net_load_bpf_flash(struct net_device *dev,1379static 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
141 }141 }
142 memset(&ifr, 0, sizeof(ifr));142 memset(&ifr, 0, sizeof(ifr));
143 ifr.ifr_flags = IFF_TAP | IFF_NO_PI | IFF_VNET_HDR;143 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);
145 145
146 err = ioctl(fd, TUNSETIFF, (void *) &ifr);146 err = ioctl(fd, TUNSETIFF, (void *) &ifr);
147 if (err != 0) {147 if (err != 0) {
@@ -171,7 +171,7 @@ static int create_raw_fd(char *iface, int flags, int proto) · 23 unmodified lines
171 goto raw_fd_cleanup;171 goto raw_fd_cleanup;
172 }172 }
173 memset(&ifr, 0, sizeof(ifr));173 memset(&ifr, 0, sizeof(ifr));
174 strscpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));174 strscpy(ifr.ifr_name, iface);
175 if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {175 if (ioctl(fd, SIOCGIFINDEX, (void *) &ifr) < 0) {
176 err = -errno;176 err = -errno;
177 goto raw_fd_cleanup;177 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
51 51
52extern int in_aton(char *str);52extern int in_aton(char *str);
53extern size_t strlcat(char *, const char *, size_t);53extern size_t strlcat(char *, const char *, size_t);
54extern size_t strscpy(char *, const char *, size_t);54extern size_t sized_strscpy(char *, const char *, size_t);
55#define strscpy(dst, src) sized_strscpy(dst, src, sizeof(dst))
55 56
56/* Copied from linux/compiler-gcc.h since we can't include it directly */57/* Copied from linux/compiler-gcc.h since we can't include it directly */
57#define barrier() __asm__ __volatile__("": : :"memory")58#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
105 sprintf(data_fd_buf, "%d", data_remote);105 sprintf(data_fd_buf, "%d", data_remote);
106 sprintf(version_buf, "%d", UML_NET_VERSION);106 sprintf(version_buf, "%d", UML_NET_VERSION);
107 if (gate != NULL) {107 if (gate != NULL) {
108 strscpy(gate_buf, gate, sizeof(gate_buf));108 strscpy(gate_buf, gate);
109 args = setup_args;109 args = setup_args;
110 }110 }
111 else args = nosetup_args;111 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
146 }146 }
147 memset(&ifr, 0, sizeof(ifr));147 memset(&ifr, 0, sizeof(ifr));
148 ifr.ifr_flags = IFF_TAP | IFF_NO_PI;148 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);
150 if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) {150 if (ioctl(pri->fd, TUNSETIFF, &ifr) < 0) {
151 err = -errno;151 err = -errno;
152 printk(UM_KERN_ERR "TUNSETIFF failed, errno = %d\n",152 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
40 __func__);40 __func__);
41 goto err;41 goto err;
42 }42 }
43 strscpy(dir, home, sizeof(dir));43 strscpy(dir, home);
44 uml_dir++;44 uml_dir++;
45 }45 }
46 strlcat(dir, uml_dir, sizeof(dir));46 strlcat(dir, uml_dir, sizeof(dir));
@@ -243,7 +243,7 @@ int __init set_umid(char *name) · 196 unmodified lines
243 if (strlen(name) > UMID_LEN - 1)243 if (strlen(name) > UMID_LEN - 1)
244 return -E2BIG;244 return -E2BIG;
245 245
246 strscpy(umid, name, sizeof(umid));246 strscpy(umid, name);
247 247
248 return 0;248 return 0;
249}249}
@@ -262,7 +262,7 @@ static int __init make_umid(void) · 12 unmodified lines
262 make_uml_dir();262 make_uml_dir();
263 263
264 if (*umid == '\0') {264 if (*umid == '\0') {
265 strscpy(tmp, uml_dir, sizeof(tmp));265 strscpy(tmp, uml_dir);
266 strlcat(tmp, "XXXXXX", sizeof(tmp));266 strlcat(tmp, "XXXXXX", sizeof(tmp));
267 fd = mkstemp(tmp);267 fd = mkstemp(tmp);
268 if (fd < 0) {268 if (fd < 0) {
arch/x86/Kconfig+1−1
@@ -100,7 +100,7 @@ config X86 · 99 unmodified lines
100 select ARCH_HAS_STRICT_MODULE_RWX100 select ARCH_HAS_STRICT_MODULE_RWX
101 select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE101 select ARCH_HAS_SYNC_CORE_BEFORE_USERMODE
102 select ARCH_HAS_SYSCALL_WRAPPER102 select ARCH_HAS_SYSCALL_WRAPPER
103 select ARCH_HAS_UBSAN_SANITIZE_ALL103 select ARCH_HAS_UBSAN
104 select ARCH_HAS_DEBUG_WX104 select ARCH_HAS_DEBUG_WX
105 select ARCH_HAS_ZONE_DMA_SET if EXPERT105 select ARCH_HAS_ZONE_DMA_SET if EXPERT
106 select ARCH_HAVE_NMI_SAFE_CMPXCHG106 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
531 return output + entry_offset;531 return output + entry_offset;
532}532}
533 533
534void fortify_panic(const char *name)534void __fortify_panic(const u8 reason, size_t avail, size_t size)
535{535{
536 error("detected buffer overflow");536 error("detected buffer overflow");
537}537}
arch/x86/include/asm/word-at-a-time.h+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
2#ifndef _ASM_WORD_AT_A_TIME_H2#ifndef _ASM_WORD_AT_A_TIME_H
3#define _ASM_WORD_AT_A_TIME_H3#define _ASM_WORD_AT_A_TIME_H
4 4
5#include <linux/kernel.h>5#include <linux/bitops.h>
6#include <linux/wordpart.h>
6 7
7/*8/*
8 * This is largely generic for little-endian machines, but the9 * 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
47#include <linux/kern_levels.h>47#include <linux/kern_levels.h>
48#include <linux/kstrtox.h>48#include <linux/kstrtox.h>
49#include <linux/kthread.h>49#include <linux/kthread.h>
50#include <linux/wordpart.h>
50 51
51#include <asm/page.h>52#include <asm/page.h>
52#include <asm/memtype.h>53#include <asm/memtype.h>
arch/x86/tools/relocs.c+8−0
@@ -653,6 +653,14 @@ static void print_absolute_relocs(void) · 652 unmodified lines
653 if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {653 if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
654 continue;654 continue;
655 }655 }
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 }
656 sh_symtab = sec_symtab->symtab;664 sh_symtab = sec_symtab->symtab;
657 sym_strtab = sec_symtab->link->strtab;665 sym_strtab = sec_symtab->link->strtab;
658 for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {666 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
294 __release(&lock_me_up);294 __release(&lock_me_up);
295}295}
296 296
297static void lkdtm_HUNG_TASK(void)297static void __noreturn lkdtm_HUNG_TASK(void)
298{298{
299 set_current_state(TASK_UNINTERRUPTIBLE);299 set_current_state(TASK_UNINTERRUPTIBLE);
300 schedule();300 schedule();
301 BUG();
301}302}
302 303
303static volatile unsigned int huge = INT_MAX - 2;304static 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
153/*153/*
154 * This is forced noinline just so it distinctly shows up in the stackdump154 * This is forced noinline just so it distinctly shows up in the stackdump
155 * which makes validation of expected lkdtm crashes easier.155 * 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.
156 */159 */
157static noinline void lkdtm_do_action(const struct crashtype *crashtype)160static noinline int lkdtm_do_action(const struct crashtype *crashtype)
158{161{
159 if (WARN_ON(!crashtype || !crashtype->func))162 if (WARN_ON(!crashtype || !crashtype->func))
160 return;163 return -EINVAL;
161 crashtype->func();164 crashtype->func();
165
166 return 0;
162}167}
163 168
164static int lkdtm_register_cpoint(struct crashpoint *crashpoint,169static int lkdtm_register_cpoint(struct crashpoint *crashpoint,
@@ -167,10 +172,8 @@ static int lkdtm_register_cpoint(struct crashpoint *crashpoint, · 2 unmodified lines
167 int ret;172 int ret;
168 173
169 /* If this doesn't have a symbol, just call immediately. */174 /* If this doesn't have a symbol, just call immediately. */
170 if (!crashpoint->kprobe.symbol_name) {175 if (!crashpoint->kprobe.symbol_name)
171 lkdtm_do_action(crashtype);176 return lkdtm_do_action(crashtype);
172 return 0;
173 }
174 177
175 if (lkdtm_kprobe != NULL)178 if (lkdtm_kprobe != NULL)
176 unregister_kprobe(lkdtm_kprobe);179 unregister_kprobe(lkdtm_kprobe);
@@ -216,7 +219,7 @@ static int lkdtm_kprobe_handler(struct kprobe *kp, struct pt_regs *regs) · 39 unmodified lines
216 spin_unlock_irqrestore(&crash_count_lock, flags);219 spin_unlock_irqrestore(&crash_count_lock, flags);
217 220
218 if (do_it)221 if (do_it)
219 lkdtm_do_action(lkdtm_crashtype);222 return lkdtm_do_action(lkdtm_crashtype);
220 223
221 return 0;224 return 0;
222}225}
@@ -303,6 +306,7 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf, · 80 unmodified lines
303{306{
304 const struct crashtype *crashtype;307 const struct crashtype *crashtype;
305 char *buf;308 char *buf;
309 int err;
306 310
307 if (count >= PAGE_SIZE)311 if (count >= PAGE_SIZE)
308 return -EINVAL;312 return -EINVAL;
@@ -326,9 +330,11 @@ static ssize_t direct_entry(struct file *f, const char __user *user_buf, · 17 unmodified lines
326 return -EINVAL;330 return -EINVAL;
327 331
328 pr_info("Performing direct entry %s\n", crashtype->name);332 pr_info("Performing direct entry %s\n", crashtype->name);
329 lkdtm_do_action(crashtype);333 err = lkdtm_do_action(crashtype);
330 *off += count;334 *off += count;
331 335
336 if (err)
337 return err;
332 return count;338 return count;
333}339}
334 340
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
224 return VMCI_ERROR_NO_MEM;224 return VMCI_ERROR_NO_MEM;
225 }225 }
226 226
227 dg_info = kmalloc(sizeof(*dg_info) +227 dg_info = kmalloc(struct_size(dg_info, msg_payload, dg->payload_size),
228 (size_t) dg->payload_size, GFP_ATOMIC);228 GFP_ATOMIC);
229 if (!dg_info) {229 if (!dg_info) {
230 atomic_dec(&delayed_dg_host_queue_size);230 atomic_dec(&delayed_dg_host_queue_size);
231 vmci_resource_put(resource);231 vmci_resource_put(resource);
@@ -234,7 +234,8 @@ static int dg_dispatch_as_host(u32 context_id, struct vmci_datagram *dg) · 2 unmodified lines
234 234
235 dg_info->in_dg_host_queue = true;235 dg_info->in_dg_host_queue = true;
236 dg_info->entry = dst_entry;236 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);
238 239
239 INIT_WORK(&dg_info->work, dg_delayed_dispatch);240 INIT_WORK(&dg_info->work, dg_delayed_dispatch);
240 schedule_work(&dg_info->work);241 schedule_work(&dg_info->work);
@@ -377,7 +378,8 @@ int vmci_datagram_invoke_guest_handler(struct vmci_datagram *dg) · 136 unmodified lines
377 378
378 dg_info->in_dg_host_queue = false;379 dg_info->in_dg_host_queue = false;
379 dg_info->entry = dst_entry;380 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);
381 383
382 INIT_WORK(&dg_info->work, dg_delayed_dispatch);384 INIT_WORK(&dg_info->work, dg_delayed_dispatch);
383 schedule_work(&dg_info->work);385 schedule_work(&dg_info->work);
fs/namei.c+1−1
@@ -17,8 +17,8 @@ · 16 unmodified lines
17 17
18#include <linux/init.h>18#include <linux/init.h>
19#include <linux/export.h>19#include <linux/export.h>
20#include <linux/kernel.h>
21#include <linux/slab.h>20#include <linux/slab.h>
21#include <linux/wordpart.h>
22#include <linux/fs.h>22#include <linux/fs.h>
23#include <linux/filelock.h>23#include <linux/filelock.h>
24#include <linux/namei.h>24#include <linux/namei.h>
include/asm-generic/word-at-a-time.h+2−1
@@ -2,7 +2,8 @@ · 1 unmodified line
2#ifndef _ASM_WORD_AT_A_TIME_H2#ifndef _ASM_WORD_AT_A_TIME_H
3#define _ASM_WORD_AT_A_TIME_H3#define _ASM_WORD_AT_A_TIME_H
4 4
5#include <linux/kernel.h>5#include <linux/bitops.h>
6#include <linux/wordpart.h>
6#include <asm/byteorder.h>7#include <asm/byteorder.h>
7 8
8#ifdef __BIG_ENDIAN9#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
231 * This returns a constant expression while determining if an argument is231 * This returns a constant expression while determining if an argument is
232 * a constant expression, most importantly without evaluating the argument.232 * a constant expression, most importantly without evaluating the argument.
233 * Glory to Martin Uecker <Martin.Uecker@med.uni-goettingen.de>233 * 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
234 */273 */
235#define __is_constexpr(x) \274#define __is_constexpr(x) \
236 (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8)))275 (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
282#define __no_sanitize_or_inline __always_inline282#define __no_sanitize_or_inline __always_inline
283#endif283#endif
284 284
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
285/* Section for code which can't be instrumented at all */292/* Section for code which can't be instrumented at all */
286#define __noinstr_section(section) \293#define __noinstr_section(section) \
287 noinline notrace __attribute((__section__(section))) \294 noinline notrace __attribute((__section__(section))) \
288 __no_kcsan __no_sanitize_address __no_profile __no_sanitize_coverage \295 __no_kcsan __no_sanitize_address __no_profile __no_sanitize_coverage \
289 __no_sanitize_memory296 __no_sanitize_memory __signed_wrap
290 297
291#define noinstr __noinstr_section(".noinstr.text")298#define noinstr __noinstr_section(".noinstr.text")
292 299
include/linux/fortify-string.h+75−47
@@ -2,6 +2,7 @@ · 1 unmodified line
2#ifndef _LINUX_FORTIFY_STRING_H_2#ifndef _LINUX_FORTIFY_STRING_H_
3#define _LINUX_FORTIFY_STRING_H_3#define _LINUX_FORTIFY_STRING_H_
4 4
5#include <linux/bitfield.h>
5#include <linux/bug.h>6#include <linux/bug.h>
6#include <linux/const.h>7#include <linux/const.h>
7#include <linux/limits.h>8#include <linux/limits.h>
@@ -9,7 +10,46 @@ · 1 unmodified line
9#define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable10#define __FORTIFY_INLINE extern __always_inline __gnu_inline __overloadable
10#define __RENAME(x) __asm__(#x)11#define __RENAME(x) __asm__(#x)
11 12
12void 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
47enum fortify_func {
48 EACH_FORTIFY_FUNC(MAKE_FORTIFY_FUNC)
49};
50
51void __fortify_report(const u8 reason, const size_t avail, const size_t size);
52void __fortify_panic(const u8 reason, const size_t avail, const size_t size) __cold __noreturn;
13void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)");53void __read_overflow(void) __compiletime_error("detected read beyond size of object (1st parameter)");
14void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)");54void __read_overflow2(void) __compiletime_error("detected read beyond size of object (2nd parameter)");
15void __read_overflow2_field(size_t avail, size_t wanted) __compiletime_warning("detected read beyond size of field (2nd parameter); maybe use struct_group()?");55void __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
143 if (__compiletime_lessthan(p_size, size))183 if (__compiletime_lessthan(p_size, size))
144 __write_overflow();184 __write_overflow();
145 if (p_size < size)185 if (p_size < size)
146 fortify_panic(__func__);186 fortify_panic(FORTIFY_FUNC_strncpy, FORTIFY_WRITE, p_size, size, p);
147 return __underlying_strncpy(p, q, size);187 return __underlying_strncpy(p, q, size);
148}188}
149 189
@@ -174,7 +214,7 @@ __FORTIFY_INLINE __kernel_size_t strnlen(const char * const POS p, __kernel_size · 24 unmodified lines
174 /* Do not check characters beyond the end of p. */214 /* Do not check characters beyond the end of p. */
175 ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);215 ret = __real_strnlen(p, maxlen < p_size ? maxlen : p_size);
176 if (p_size <= ret && maxlen != ret)216 if (p_size <= ret && maxlen != ret)
177 fortify_panic(__func__);217 fortify_panic(FORTIFY_FUNC_strnlen, FORTIFY_READ, p_size, ret + 1, ret);
178 return ret;218 return ret;
179}219}
180 220
@@ -210,31 +250,13 @@ __kernel_size_t __fortify_strlen(const char * const POS p) · 29 unmodified lines
210 return __underlying_strlen(p);250 return __underlying_strlen(p);
211 ret = strnlen(p, p_size);251 ret = strnlen(p, p_size);
212 if (p_size <= ret)252 if (p_size <= ret)
213 fortify_panic(__func__);253 fortify_panic(FORTIFY_FUNC_strlen, FORTIFY_READ, p_size, ret + 1, ret);
214 return ret;254 return ret;
215}255}
216 256
217/* Defined after fortified strnlen() to reuse it. */257/* Defined after fortified strnlen() to reuse it. */
218extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(strscpy);258extern ssize_t __real_strscpy(char *, const char *, size_t) __RENAME(sized_strscpy);
219/**259__FORTIFY_INLINE ssize_t sized_strscpy(char * const POS p, const char * const POS q, size_t size)
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)
238{260{
239 /* Use string size rather than possible enclosing struct size. */261 /* Use string size rather than possible enclosing struct size. */
240 const size_t p_size = __member_size(p);262 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
278 * Generate a runtime write overflow error if len is greater than300 * Generate a runtime write overflow error if len is greater than
279 * p_size.301 * p_size.
280 */302 */
281 if (len > p_size)303 if (p_size < len)
282 fortify_panic(__func__);304 fortify_panic(FORTIFY_FUNC_strscpy, FORTIFY_WRITE, p_size, len, -E2BIG);
283 305
284 /*306 /*
285 * We can now safely call vanilla strscpy because we are protected from:307 * 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
337 359
338 /* Give up if string is already overflowed. */360 /* Give up if string is already overflowed. */
339 if (p_size <= p_len)361 if (p_size <= p_len)
340 fortify_panic(__func__);362 fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_READ, p_size, p_len + 1, wanted);
341 363
342 if (actual >= avail) {364 if (actual >= avail) {
343 copy_len = avail - p_len - 1;365 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
346 368
347 /* Give up if copy will overflow. */369 /* Give up if copy will overflow. */
348 if (p_size <= actual)370 if (p_size <= actual)
349 fortify_panic(__func__);371 fortify_panic(FORTIFY_FUNC_strlcat, FORTIFY_WRITE, p_size, actual + 1, wanted);
350 __underlying_memcpy(p + p_len, q, copy_len);372 __underlying_memcpy(p + p_len, q, copy_len);
351 p[actual] = '\0';373 p[actual] = '\0';
352 374
@@ -373,9 +395,10 @@ __FORTIFY_INLINE __diagnose_as(__builtin_strcat, 1, 2) · 20 unmodified lines
373char *strcat(char * const POS p, const char *q)395char *strcat(char * const POS p, const char *q)
374{396{
375 const size_t p_size = __member_size(p);397 const size_t p_size = __member_size(p);
398 const size_t wanted = strlcat(p, q, p_size);
376 399
377 if (strlcat(p, q, p_size) >= p_size)400 if (p_size <= wanted)
378 fortify_panic(__func__);401 fortify_panic(FORTIFY_FUNC_strcat, FORTIFY_WRITE, p_size, wanted + 1, p);
379 return p;402 return p;
380}403}
381 404
@@ -404,20 +427,21 @@ char *strncat(char * const POS p, const char * const POS q, __kernel_size_t coun · 22 unmodified lines
404{427{
405 const size_t p_size = __member_size(p);428 const size_t p_size = __member_size(p);
406 const size_t q_size = __member_size(q);429 const size_t q_size = __member_size(q);
407 size_t p_len, copy_len;430 size_t p_len, copy_len, total;
408 431
409 if (p_size == SIZE_MAX && q_size == SIZE_MAX)432 if (p_size == SIZE_MAX && q_size == SIZE_MAX)
410 return __underlying_strncat(p, q, count);433 return __underlying_strncat(p, q, count);
411 p_len = strlen(p);434 p_len = strlen(p);
412 copy_len = strnlen(q, count);435 copy_len = strnlen(q, count);
413 if (p_size < p_len + copy_len + 1)436 total = p_len + copy_len + 1;
414 fortify_panic(__func__);437 if (p_size < total)
438 fortify_panic(FORTIFY_FUNC_strncat, FORTIFY_WRITE, p_size, total, p);
415 __underlying_memcpy(p + p_len, q, copy_len);439 __underlying_memcpy(p + p_len, q, copy_len);
416 p[p_len + copy_len] = '\0';440 p[p_len + copy_len] = '\0';
417 return p;441 return p;
418}442}
419 443
420__FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size,444__FORTIFY_INLINE bool fortify_memset_chk(__kernel_size_t size,
421 const size_t p_size,445 const size_t p_size,
422 const size_t p_size_field)446 const size_t p_size_field)
423{447{
@@ -452,7 +476,8 @@ __FORTIFY_INLINE void fortify_memset_chk(__kernel_size_t size, · 28 unmodified lines
452 * lengths are unknown.)476 * lengths are unknown.)
453 */477 */
454 if (p_size != SIZE_MAX && p_size < size)478 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;
456}481}
457 482
458#define __fortify_memset_chk(p, c, size, p_size, p_size_field) ({ \483#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
506 const size_t q_size,531 const size_t q_size,
507 const size_t p_size_field,532 const size_t p_size_field,
508 const size_t q_size_field,533 const size_t q_size_field,
509 const char *func)534 const u8 func)
510{535{
511 if (__builtin_constant_p(size)) {536 if (__builtin_constant_p(size)) {
512 /*537 /*
@@ -550,9 +575,10 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, · 37 unmodified lines
550 * (The SIZE_MAX test is to optimize away checks where the buffer575 * (The SIZE_MAX test is to optimize away checks where the buffer
551 * lengths are unknown.)576 * lengths are unknown.)
552 */577 */
553 if ((p_size != SIZE_MAX && p_size < size) ||578 if (p_size != SIZE_MAX && p_size < size)
554 (q_size != SIZE_MAX && q_size < size))579 fortify_panic(func, FORTIFY_WRITE, p_size, size, true);
555 fortify_panic(func);580 else if (q_size != SIZE_MAX && q_size < size)
581 fortify_panic(func, FORTIFY_READ, p_size, size, true);
556 582
557 /*583 /*
558 * Warn when writing beyond destination field size.584 * Warn when writing beyond destination field size.
@@ -585,7 +611,7 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size, · 26 unmodified lines
585 const size_t __q_size_field = (q_size_field); \611 const size_t __q_size_field = (q_size_field); \
586 WARN_ONCE(fortify_memcpy_chk(__fortify_size, __p_size, \612 WARN_ONCE(fortify_memcpy_chk(__fortify_size, __p_size, \
587 __q_size, __p_size_field, \613 __q_size, __p_size_field, \
588 __q_size_field, #op), \614 __q_size_field, FORTIFY_FUNC_ ##op), \
589 #op ": detected field-spanning write (size %zu) of single %s (size %zu)\n", \615 #op ": detected field-spanning write (size %zu) of single %s (size %zu)\n", \
590 __fortify_size, \616 __fortify_size, \
591 "field \"" #p "\" at " FILE_LINE, \617 "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
652 if (__compiletime_lessthan(p_size, size))678 if (__compiletime_lessthan(p_size, size))
653 __read_overflow();679 __read_overflow();
654 if (p_size < size)680 if (p_size < size)
655 fortify_panic(__func__);681 fortify_panic(FORTIFY_FUNC_memscan, FORTIFY_READ, p_size, size, NULL);
656 return __real_memscan(p, c, size);682 return __real_memscan(p, c, size);
657}683}
658 684
@@ -668,8 +694,10 @@ int memcmp(const void * const POS0 p, const void * const POS0 q, __kernel_size_t · 9 unmodified lines
668 if (__compiletime_lessthan(q_size, size))694 if (__compiletime_lessthan(q_size, size))
669 __read_overflow2();695 __read_overflow2();
670 }696 }
671 if (p_size < size || q_size < size)697 if (p_size < size)
672 fortify_panic(__func__);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);
673 return __underlying_memcmp(p, q, size);701 return __underlying_memcmp(p, q, size);
674}702}
675 703
@@ -681,7 +709,7 @@ void *memchr(const void * const POS0 p, int c, __kernel_size_t size) · 5 unmodified lines
681 if (__compiletime_lessthan(p_size, size))709 if (__compiletime_lessthan(p_size, size))
682 __read_overflow();710 __read_overflow();
683 if (p_size < size)711 if (p_size < size)
684 fortify_panic(__func__);712 fortify_panic(FORTIFY_FUNC_memchr, FORTIFY_READ, p_size, size, NULL);
685 return __underlying_memchr(p, c, size);713 return __underlying_memchr(p, c, size);
686}714}
687 715
@@ -693,7 +721,7 @@ __FORTIFY_INLINE void *memchr_inv(const void * const POS0 p, int c, size_t size) · 5 unmodified lines
693 if (__compiletime_lessthan(p_size, size))721 if (__compiletime_lessthan(p_size, size))
694 __read_overflow();722 __read_overflow();
695 if (p_size < size)723 if (p_size < size)
696 fortify_panic(__func__);724 fortify_panic(FORTIFY_FUNC_memchr_inv, FORTIFY_READ, p_size, size, NULL);
697 return __real_memchr_inv(p, c, size);725 return __real_memchr_inv(p, c, size);
698}726}
699 727
@@ -706,7 +734,7 @@ __FORTIFY_INLINE void *kmemdup(const void * const POS0 p, size_t size, gfp_t gfp · 6 unmodified lines
706 if (__compiletime_lessthan(p_size, size))734 if (__compiletime_lessthan(p_size, size))
707 __read_overflow();735 __read_overflow();
708 if (p_size < size)736 if (p_size < size)
709 fortify_panic(__func__);737 fortify_panic(FORTIFY_FUNC_kmemdup, FORTIFY_READ, p_size, size, NULL);
710 return __real_kmemdup(p, size, gfp);738 return __real_kmemdup(p, size, gfp);
711}739}
712 740
@@ -743,7 +771,7 @@ char *strcpy(char * const POS p, const char * const POS q) · 30 unmodified lines
743 __write_overflow();771 __write_overflow();
744 /* Run-time check for dynamic size overflow. */772 /* Run-time check for dynamic size overflow. */
745 if (p_size < size)773 if (p_size < size)
746 fortify_panic(__func__);774 fortify_panic(FORTIFY_FUNC_strcpy, FORTIFY_WRITE, p_size, size, p);
747 __underlying_memcpy(p, q, size);775 __underlying_memcpy(p, q, size);
748 return p;776 return p;
749}777}
include/linux/kernel.h+2−42
@@ -33,20 +33,14 @@ · 32 unmodified lines
33#include <linux/sprintf.h>33#include <linux/sprintf.h>
34#include <linux/static_call_types.h>34#include <linux/static_call_types.h>
35#include <linux/instruction_pointer.h>35#include <linux/instruction_pointer.h>
36#include <linux/wordpart.h>
37
36#include <asm/byteorder.h>38#include <asm/byteorder.h>
37 39
38#include <uapi/linux/kernel.h>40#include <uapi/linux/kernel.h>
39 41
40#define STACK_MAGIC 0xdeadbeef42#define STACK_MAGIC 0xdeadbeef
41 43
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
50/* generic data direction definitions */44/* generic data direction definitions */
51#define READ 045#define READ 0
52#define WRITE 146#define WRITE 1
@@ -60,34 +54,6 @@ · 7 unmodified lines
60} \54} \
61)55)
62 56
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
91struct completion;57struct completion;
92struct user;58struct user;
93 59
@@ -199,12 +165,6 @@ static inline void might_fault(void) { } · 105 unmodified lines
199 165
200void do_exit(long error_code) __noreturn;166void do_exit(long error_code) __noreturn;
201 167
202extern int get_option(char **str, int *pint);
203extern char *get_options(const char *str, int nints, int *ints);
204extern unsigned long long memparse(const char *ptr, char **retptr);
205extern bool parse_option_str(const char *str, const char *option);
206extern char *next_arg(char *args, char **param, char **val);
207
208extern int core_kernel_text(unsigned long addr);168extern int core_kernel_text(unsigned long addr);
209extern int __kernel_text_address(unsigned long addr);169extern int __kernel_text_address(unsigned long addr);
210extern int kernel_text_address(unsigned long addr);170extern int kernel_text_address(unsigned long addr);
include/linux/overflow.h+97−18
@@ -31,8 +31,10 @@ · 30 unmodified lines
31 * credit to Christian Biere.31 * credit to Christian Biere.
32 */32 */
33#define __type_half_max(type) ((type)1 << (8*sizeof(type) - 1 - is_signed_type(type)))33#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)))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))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))
36 38
37/*39/*
38 * Avoids triggering -Wtype-limits compilation warning,40 * Avoids triggering -Wtype-limits compilation warning,
@@ -57,45 +59,122 @@ static inline bool __must_check __must_check_overflow(bool overflow) · 18 unmodified lines
57 * @b: second addend59 * @b: second addend
58 * @d: pointer to store sum60 * @d: pointer to store sum
59 *61 *
60 * Returns 0 on success.62 * Returns true on wrap-around, false otherwise.
61 *63 *
62 * *@d holds the results of the attempted addition, but is not considered64 * *@d holds the results of the attempted addition, regardless of whether
63 * "safe for use" on a non-zero return value, which indicates that the65 * wrap-around occurred.
64 * sum has overflowed or been truncated.
65 */66 */
66#define check_add_overflow(a, b, d) \67#define check_add_overflow(a, b, d) \
67 __must_check_overflow(__builtin_add_overflow(a, b, d))68 __must_check_overflow(__builtin_add_overflow(a, b, d))
68 69
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
69/**102/**
70 * check_sub_overflow() - Calculate subtraction with overflow checking103 * check_sub_overflow() - Calculate subtraction with overflow checking
71 * @a: minuend; value to subtract from104 * @a: minuend; value to subtract from
72 * @b: subtrahend; value to subtract from @a105 * @b: subtrahend; value to subtract from @a
73 * @d: pointer to store difference106 * @d: pointer to store difference
74 *107 *
75 * Returns 0 on success.108 * Returns true on wrap-around, false otherwise.
76 *109 *
77 * *@d holds the results of the attempted subtraction, but is not considered110 * *@d holds the results of the attempted subtraction, regardless of whether
78 * "safe for use" on a non-zero return value, which indicates that the111 * wrap-around occurred.
79 * difference has underflowed or been truncated.
80 */112 */
81#define check_sub_overflow(a, b, d) \113#define check_sub_overflow(a, b, d) \
82 __must_check_overflow(__builtin_sub_overflow(a, b, d))114 __must_check_overflow(__builtin_sub_overflow(a, b, d))
83 115
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
84/**148/**
85 * check_mul_overflow() - Calculate multiplication with overflow checking149 * check_mul_overflow() - Calculate multiplication with overflow checking
86 * @a: first factor150 * @a: first factor
87 * @b: second factor151 * @b: second factor
88 * @d: pointer to store product152 * @d: pointer to store product
89 *153 *
90 * Returns 0 on success.154 * Returns true on wrap-around, false otherwise.
91 *155 *
92 * *@d holds the results of the attempted multiplication, but is not156 * *@d holds the results of the attempted multiplication, regardless of whether
93 * considered "safe for use" on a non-zero return value, which indicates157 * wrap-around occurred.
94 * that the product has overflowed or been truncated.
95 */158 */
96#define check_mul_overflow(a, b, d) \159#define check_mul_overflow(a, b, d) \
97 __must_check_overflow(__builtin_mul_overflow(a, b, d))160 __must_check_overflow(__builtin_mul_overflow(a, b, d))
98 161
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
99/**178/**
100 * check_shl_overflow() - Calculate a left-shifted value and check overflow179 * check_shl_overflow() - Calculate a left-shifted value and check overflow
101 * @a: Value to be shifted180 * @a: Value to be shifted
@@ -120,7 +199,7 @@ static inline bool __must_check __must_check_overflow(bool overflow) · 18 unmodified lines
120 typeof(a) _a = a; \199 typeof(a) _a = a; \
121 typeof(s) _s = s; \200 typeof(s) _s = s; \
122 typeof(d) _d = d; \201 typeof(d) _d = d; \
123 u64 _a_full = _a; \202 unsigned long long _a_full = _a; \
124 unsigned int _to_shift = \203 unsigned int _to_shift = \
125 is_non_negative(_s) && _s < 8 * sizeof(*d) ? _s : 0; \204 is_non_negative(_s) && _s < 8 * sizeof(*d) ? _s : 0; \
126 *_d = (_a_full << _to_shift); \205 *_d = (_a_full << _to_shift); \
@@ -130,10 +209,10 @@ static inline bool __must_check __must_check_overflow(bool overflow) · 3 unmodified lines
130 209
131#define __overflows_type_constexpr(x, T) ( \210#define __overflows_type_constexpr(x, T) ( \
132 is_unsigned_type(typeof(x)) ? \211 is_unsigned_type(typeof(x)) ? \
133 (x) > type_max(typeof(T)) : \212 (x) > type_max(T) : \
134 is_unsigned_type(typeof(T)) ? \213 is_unsigned_type(typeof(T)) ? \
135 (x) < 0 || (x) > type_max(typeof(T)) : \214 (x) < 0 || (x) > type_max(T) : \
136 (x) < type_min(typeof(T)) || (x) > type_max(typeof(T)))215 (x) < type_min(T) || (x) > type_max(T))
137 216
138#define __overflows_type(x, T) ({ \217#define __overflows_type(x, T) ({ \
139 typeof(T) v = 0; \218 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
136 return atomic_read(&r->refs);136 return atomic_read(&r->refs);
137}137}
138 138
139static inline __must_check bool __refcount_add_not_zero(int i, refcount_t *r, int *oldp)139static inline __must_check __signed_wrap
140bool __refcount_add_not_zero(int i, refcount_t *r, int *oldp)
140{141{
141 int old = refcount_read(r);142 int old = refcount_read(r);
142 143
@@ -177,7 +178,8 @@ static inline __must_check bool refcount_add_not_zero(int i, refcount_t *r) · 34 unmodified lines
177 return __refcount_add_not_zero(i, r, NULL);178 return __refcount_add_not_zero(i, r, NULL);
178}179}
179 180
180static inline void __refcount_add(int i, refcount_t *r, int *oldp)181static inline __signed_wrap
182void __refcount_add(int i, refcount_t *r, int *oldp)
181{183{
182 int old = atomic_fetch_add_relaxed(i, &r->refs);184 int old = atomic_fetch_add_relaxed(i, &r->refs);
183 185
@@ -256,7 +258,8 @@ static inline void refcount_inc(refcount_t *r) · 72 unmodified lines
256 __refcount_inc(r, NULL);258 __refcount_inc(r, NULL);
257}259}
258 260
259static inline __must_check bool __refcount_sub_and_test(int i, refcount_t *r, int *oldp)261static inline __must_check __signed_wrap
262bool __refcount_sub_and_test(int i, refcount_t *r, int *oldp)
260{263{
261 int old = atomic_fetch_sub_release(i, &r->refs);264 int old = atomic_fetch_sub_release(i, &r->refs);
262 265
include/linux/string.h+81−5
@@ -2,6 +2,7 @@ · 1 unmodified line
2#ifndef _LINUX_STRING_H_2#ifndef _LINUX_STRING_H_
3#define _LINUX_STRING_H_3#define _LINUX_STRING_H_
4 4
5#include <linux/args.h>
5#include <linux/array_size.h>6#include <linux/array_size.h>
6#include <linux/compiler.h> /* for inline */7#include <linux/compiler.h> /* for inline */
7#include <linux/types.h> /* for size_t */8#include <linux/types.h> /* for size_t */
@@ -66,12 +67,79 @@ extern char * strcpy(char *,const char *); · 58 unmodified lines
66#ifndef __HAVE_ARCH_STRNCPY67#ifndef __HAVE_ARCH_STRNCPY
67extern char * strncpy(char *,const char *, __kernel_size_t);68extern char * strncpy(char *,const char *, __kernel_size_t);
68#endif69#endif
69#ifndef __HAVE_ARCH_STRSCPY70ssize_t sized_strscpy(char *, const char *, size_t);
70ssize_t strscpy(char *, const char *, size_t);71
71#endif72/*
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})
72 120
73/* Wraps calls to strscpy()/memset(), no arch specific code required */121/**
74ssize_t strscpy_pad(char *dest, const char *src, size_t count);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__)
75 143
76#ifndef __HAVE_ARCH_STRCAT144#ifndef __HAVE_ARCH_STRCAT
77extern char * strcat(char *, const char *);145extern 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
219extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp);287extern char *kmemdup_nul(const char *s, size_t len, gfp_t gfp);
220extern void *kmemdup_array(const void *src, size_t element_size, size_t count, gfp_t gfp);288extern void *kmemdup_array(const void *src, size_t element_size, size_t count, gfp_t gfp);
221 289
290/* lib/argv_split.c */
222extern char **argv_split(gfp_t gfp, const char *str, int *argcp);291extern char **argv_split(gfp_t gfp, const char *str, int *argcp);
223extern void argv_free(char **argv);292extern void argv_free(char **argv);
224 293
294/* lib/cmdline.c */
295extern int get_option(char **str, int *pint);
296extern char *get_options(const char *str, int nints, int *ints);
297extern unsigned long long memparse(const char *ptr, char **retptr);
298extern bool parse_option_str(const char *str, const char *option);
299extern char *next_arg(char *args, char **param, char **val);
300
225extern bool sysfs_streq(const char *s1, const char *s2);301extern bool sysfs_streq(const char *s1, const char *s2);
226int match_string(const char * const *array, size_t n, const char *string);302int match_string(const char * const *array, size_t n, const char *string);
227int __sysfs_match_string(const char * const *array, size_t n, const char *s);303int __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
42 return v ? "yes" : "no";42 return v ? "yes" : "no";
43}43}
44 44
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 */
51static inline const char *str_plural(size_t num)
52{
53 return num == 1 ? "" : "s";
54}
55
45#endif56#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
17 return memchr(s, '\0', len) ? true : false;17 return memchr(s, '\0', len) ? true : false;
18}18}
19 19
20/* Descriptions of the types of units to20/* Descriptions of the types of units to print in */
21 * print in */
22enum string_size_units {21enum string_size_units {
23 STRING_UNITS_10, /* use powers of 10^3 (standard SI) */22 STRING_UNITS_10, /* use powers of 10^3 (standard SI) */
24 STRING_UNITS_2, /* use binary powers of 2^10 */23 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),
25};29};
26 30
27int string_get_size(u64 size, u64 blk_size, enum string_size_units units,31int string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
28 char *buf, int len);32 char *buf, int len);
29 33
30int parse_int_array_user(const char __user *from, size_t count, int **array);34int 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
44# CONFIG_UBSAN_BOOL44# CONFIG_UBSAN_BOOL
45# CONFIG_UBSAN_ENUM45# CONFIG_UBSAN_ENUM
46# CONFIG_UBSAN_ALIGNMENT46# CONFIG_UBSAN_ALIGNMENT
47CONFIG_UBSAN_SANITIZE_ALL=y47
48# Sampling-based heap out-of-bounds and use-after-free detection.
49CONFIG_KFENCE=y
48 50
49# Linked list integrity checking.51# Linked list integrity checking.
50CONFIG_LIST_HARDENED=y52CONFIG_LIST_HARDENED=y
@@ -93,6 +95,3 @@ CONFIG_SYN_COOKIES=y · 42 unmodified lines
93 95
94# Attack surface reduction: Use the modern PTY interface (devpts) only.96# Attack surface reduction: Use the modern PTY interface (devpts) only.
95# CONFIG_LEGACY_PTYS is not set97# 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
598 if (syslog_action_restricted(type)) {598 if (syslog_action_restricted(type)) {
599 if (capable(CAP_SYSLOG))599 if (capable(CAP_SYSLOG))
600 goto ok;600 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 }
612 return -EPERM;601 return -EPERM;
613 }602 }
614ok:603ok:
lib/Kconfig.debug+9−5
@@ -2353,11 +2353,15 @@ config ASYNC_RAID6_TEST · 2352 unmodified lines
2353config TEST_HEXDUMP2353config TEST_HEXDUMP
2354 tristate "Test functions located in the hexdump module at runtime"2354 tristate "Test functions located in the hexdump module at runtime"
2355 2355
2356config STRING_SELFTEST2356config STRING_KUNIT_TEST
2357 tristate "Test string functions at runtime"2357 tristate "KUnit test string functions at runtime" if !KUNIT_ALL_TESTS
2358 depends on KUNIT
2359 default KUNIT_ALL_TESTS
2358 2360
2359config TEST_STRING_HELPERS2361config STRING_HELPERS_KUNIT_TEST
2360 tristate "Test functions located in the string_helpers module at runtime"2362 tristate "KUnit test string helpers at runtime" if !KUNIT_ALL_TESTS
2363 depends on KUNIT
2364 default KUNIT_ALL_TESTS
2361 2365
2362config TEST_KSTRTOX2366config TEST_KSTRTOX
2363 tristate "Test kstrto*() family of functions at runtime"2367 tristate "Test kstrto*() family of functions at runtime"
@@ -2749,7 +2753,7 @@ config STACKINIT_KUNIT_TEST · 385 unmodified lines
2749 2753
2750config FORTIFY_KUNIT_TEST2754config FORTIFY_KUNIT_TEST
2751 tristate "Test fortified str*() and mem*() function internals at runtime" if !KUNIT_ALL_TESTS2755 tristate "Test fortified str*() and mem*() function internals at runtime" if !KUNIT_ALL_TESTS
2752 depends on KUNIT && FORTIFY_SOURCE2756 depends on KUNIT
2753 default KUNIT_ALL_TESTS2757 default KUNIT_ALL_TESTS
2754 help2758 help
2755 Builds unit tests for checking internals of FORTIFY_SOURCE as used2759 Builds unit tests for checking internals of FORTIFY_SOURCE as used
lib/Kconfig.ubsan+15−13
@@ -1,5 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2config ARCH_HAS_UBSAN_SANITIZE_ALL2config ARCH_HAS_UBSAN
3 bool3 bool
4 4
5menuconfig UBSAN5menuconfig UBSAN
@@ -87,7 +87,6 @@ config UBSAN_LOCAL_BOUNDS · 81 unmodified lines
87 87
88config UBSAN_SHIFT88config UBSAN_SHIFT
89 bool "Perform checking for bit-shift overflows"89 bool "Perform checking for bit-shift overflows"
90 default UBSAN
91 depends on $(cc-option,-fsanitize=shift)90 depends on $(cc-option,-fsanitize=shift)
92 help91 help
93 This option enables -fsanitize=shift which checks for bit-shift92 This option enables -fsanitize=shift which checks for bit-shift
@@ -116,6 +115,20 @@ config UBSAN_UNREACHABLE · 22 unmodified lines
116 This option enables -fsanitize=unreachable which checks for control115 This option enables -fsanitize=unreachable which checks for control
117 flow reaching an expected-to-be-unreachable position.116 flow reaching an expected-to-be-unreachable position.
118 117
118config 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
119config UBSAN_BOOL132config UBSAN_BOOL
120 bool "Perform checking for non-boolean values used as boolean"133 bool "Perform checking for non-boolean values used as boolean"
121 default UBSAN134 default UBSAN
@@ -142,17 +155,6 @@ config UBSAN_ALIGNMENT · 20 unmodified lines
142 Enabling this option on architectures that support unaligned155 Enabling this option on architectures that support unaligned
143 accesses may produce a lot of false positives.156 accesses may produce a lot of false positives.
144 157
145config 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
156config TEST_UBSAN158config TEST_UBSAN
157 tristate "Module for testing for undefined behavior detection"159 tristate "Module for testing for undefined behavior detection"
158 depends on m160 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
49 percpu-refcount.o rhashtable.o base64.o \49 percpu-refcount.o rhashtable.o base64.o \
50 once.o refcount.o rcuref.o usercopy.o errseq.o bucket_locks.o \50 once.o refcount.o rcuref.o usercopy.o errseq.o bucket_locks.o \
51 generic-radix-tree.o bitmap-str.o51 generic-radix-tree.o bitmap-str.o
52obj-$(CONFIG_STRING_SELFTEST) += test_string.o52obj-$(CONFIG_STRING_KUNIT_TEST) += string_kunit.o
53obj-y += string_helpers.o53obj-y += string_helpers.o
54obj-$(CONFIG_TEST_STRING_HELPERS) += test-string_helpers.o54obj-$(CONFIG_STRING_HELPERS_KUNIT_TEST) += string_helpers_kunit.o
55obj-y += hexdump.o55obj-y += hexdump.o
56obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o56obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
57obj-y += kstrtox.o57obj-y += kstrtox.o
@@ -69,6 +69,7 @@ obj-$(CONFIG_HASH_KUNIT_TEST) += test_hash.o · 11 unmodified lines
69obj-$(CONFIG_TEST_IDA) += test_ida.o69obj-$(CONFIG_TEST_IDA) += test_ida.o
70obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o70obj-$(CONFIG_TEST_UBSAN) += test_ubsan.o
71CFLAGS_test_ubsan.o += $(call cc-disable-warning, vla)71CFLAGS_test_ubsan.o += $(call cc-disable-warning, vla)
72CFLAGS_test_ubsan.o += $(call cc-disable-warning, unused-but-set-variable)
72UBSAN_SANITIZE_test_ubsan.o := y73UBSAN_SANITIZE_test_ubsan.o := y
73obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o74obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
74obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o75obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o
@@ -399,6 +400,8 @@ obj-$(CONFIG_OVERFLOW_KUNIT_TEST) += overflow_kunit.o · 324 unmodified lines
399CFLAGS_stackinit_kunit.o += $(call cc-disable-warning, switch-unreachable)400CFLAGS_stackinit_kunit.o += $(call cc-disable-warning, switch-unreachable)
400obj-$(CONFIG_STACKINIT_KUNIT_TEST) += stackinit_kunit.o401obj-$(CONFIG_STACKINIT_KUNIT_TEST) += stackinit_kunit.o
401CFLAGS_fortify_kunit.o += $(call cc-disable-warning, unsequenced)402CFLAGS_fortify_kunit.o += $(call cc-disable-warning, unsequenced)
403CFLAGS_fortify_kunit.o += $(call cc-disable-warning, stringop-overread)
404CFLAGS_fortify_kunit.o += $(call cc-disable-warning, stringop-truncation)
402CFLAGS_fortify_kunit.o += $(DISABLE_STRUCTLEAK_PLUGIN)405CFLAGS_fortify_kunit.o += $(DISABLE_STRUCTLEAK_PLUGIN)
403obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o406obj-$(CONFIG_FORTIFY_KUNIT_TEST) += fortify_kunit.o
404obj-$(CONFIG_STRCAT_KUNIT_TEST) += strcat_kunit.o407obj-$(CONFIG_STRCAT_KUNIT_TEST) += strcat_kunit.o
lib/fortify_kunit.c+660−2
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: GPL-2.01// SPDX-License-Identifier: GPL-2.0
2/*2/*
3 * Runtime test cases for CONFIG_FORTIFY_SOURCE that aren't expected to3 * Runtime test cases for CONFIG_FORTIFY_SOURCE. For testing memcpy(),
4 * Oops the kernel on success. (For those, see drivers/misc/lkdtm/fortify.c)4 * see FORTIFY_MEM_* tests in LKDTM (drivers/misc/lkdtm/fortify.c).
5 *5 *
6 * For corner cases with UBSAN, try testing with:6 * For corner cases with UBSAN, try testing with:
7 *7 *
@@ -15,17 +15,55 @@ · 7 unmodified lines
15 */15 */
16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt16#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
17 17
18/* Redefine fortify_panic() to track failures. */
19void 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
18#include <kunit/device.h>26#include <kunit/device.h>
19#include <kunit/test.h>27#include <kunit/test.h>
28#include <kunit/test-bug.h>
20#include <linux/device.h>29#include <linux/device.h>
21#include <linux/slab.h>30#include <linux/slab.h>
22#include <linux/string.h>31#include <linux/string.h>
23#include <linux/vmalloc.h>32#include <linux/vmalloc.h>
24 33
34/* Handle being built without CONFIG_FORTIFY_SOURCE */
35#ifndef __compiletime_strlen
36# define __compiletime_strlen __builtin_strlen
37#endif
38
39static struct kunit_resource read_resource;
40static struct kunit_resource write_resource;
41static int fortify_read_overflows;
42static int fortify_write_overflows;
43
25static const char array_of_10[] = "this is 10";44static const char array_of_10[] = "this is 10";
26static const char *ptr_of_11 = "this is 11!";45static const char *ptr_of_11 = "this is 11!";
27static char array_unknown[] = "compiler thinks I might change";46static char array_unknown[] = "compiler thinks I might change";
28 47
48void 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
29static void known_sizes_test(struct kunit *test)67static void known_sizes_test(struct kunit *test)
30{68{
31 KUNIT_EXPECT_EQ(test, __compiletime_strlen("88888888"), 8);69 KUNIT_EXPECT_EQ(test, __compiletime_strlen("88888888"), 8);
@@ -308,6 +346,610 @@ DEFINE_ALLOC_SIZE_TEST_PAIR(kvmalloc) · 276 unmodified lines
308} while (0)346} while (0)
309DEFINE_ALLOC_SIZE_TEST_PAIR(devm_kmalloc)347DEFINE_ALLOC_SIZE_TEST_PAIR(devm_kmalloc)
310 348
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 */
356struct 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. */
362static volatile int unconst;
363
364static 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
387static 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
425static 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
483static 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
542static 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
599static 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
656static 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
729static 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
814static 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
833static 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
852static 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
872static 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
894static 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
937static 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
311static struct kunit_case fortify_test_cases[] = {953static struct kunit_case fortify_test_cases[] = {
312 KUNIT_CASE(known_sizes_test),954 KUNIT_CASE(known_sizes_test),
313 KUNIT_CASE(control_flow_split_test),955 KUNIT_CASE(control_flow_split_test),
@@ -319,11 +961,27 @@ static struct kunit_case fortify_test_cases[] = { · 5 unmodified lines
319 KUNIT_CASE(alloc_size_kvmalloc_dynamic_test),961 KUNIT_CASE(alloc_size_kvmalloc_dynamic_test),
320 KUNIT_CASE(alloc_size_devm_kmalloc_const_test),962 KUNIT_CASE(alloc_size_devm_kmalloc_const_test),
321 KUNIT_CASE(alloc_size_devm_kmalloc_dynamic_test),963 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),
322 {}979 {}
323};980};
324 981
325static struct kunit_suite fortify_test_suite = {982static struct kunit_suite fortify_test_suite = {
326 .name = "fortify",983 .name = "fortify",
984 .init = fortify_test_init,
327 .test_cases = fortify_test_cases,985 .test_cases = fortify_test_cases,
328};986};
329 987
lib/overflow_kunit.c+63−4
@@ -258,25 +258,84 @@ DEFINE_TEST_ARRAY(s64) = { · 257 unmodified lines
258 \258 \
259 _of = check_ ## op ## _overflow(a, b, &_r); \259 _of = check_ ## op ## _overflow(a, b, &_r); \
260 KUNIT_EXPECT_EQ_MSG(test, _of, of, \260 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", \
262 a, b, of ? "" : " not", #t); \262 a, b, of ? "" : " not", #t); \
263 KUNIT_EXPECT_EQ_MSG(test, _r, r, \263 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", \
265 a, b, r, _r, #t); \265 a, b, r, _r, #t); \
266 /* Check for internal macro side-effects. */ \266 /* Check for internal macro side-effects. */ \
267 _of = check_ ## op ## _overflow(_a_orig++, _b_orig++, &_r); \267 _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"); \268 KUNIT_EXPECT_EQ_MSG(test, _a_orig, _a_bump, \
269 KUNIT_EXPECT_EQ_MSG(test, _b_orig, _b_bump, "Unexpected " #op " macro side-effect!\n"); \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
287static int global_counter;
288static void bump_counter(void)
289{
290 global_counter++;
291}
292
293static 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"); \
270} while (0)324} while (0)
271 325
272#define DEFINE_TEST_FUNC_TYPED(n, t, fmt) \326#define DEFINE_TEST_FUNC_TYPED(n, t, fmt) \
273static void do_test_ ## n(struct kunit *test, const struct test_ ## n *p) \327static void do_test_ ## n(struct kunit *test, const struct test_ ## n *p) \
274{ \328{ \
329 /* check_{add,sub,mul}_overflow() and wrapping_{add,sub,mul} */ \
275 check_one_op(t, fmt, add, "+", p->a, p->b, p->sum, p->s_of); \330 check_one_op(t, fmt, add, "+", p->a, p->b, p->sum, p->s_of); \
276 check_one_op(t, fmt, add, "+", p->b, p->a, p->sum, p->s_of); \331 check_one_op(t, fmt, add, "+", p->b, p->a, p->sum, p->s_of); \
277 check_one_op(t, fmt, sub, "-", p->a, p->b, p->diff, p->d_of); \332 check_one_op(t, fmt, sub, "-", p->a, p->b, p->diff, p->d_of); \
278 check_one_op(t, fmt, mul, "*", p->a, p->b, p->prod, p->p_of); \333 check_one_op(t, fmt, mul, "*", p->a, p->b, p->prod, p->p_of); \
279 check_one_op(t, fmt, mul, "*", p->b, p->a, p->prod, p->p_of); \334 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); \
280} \339} \
281 \340 \
282static void n ## _overflow_test(struct kunit *test) { \341static 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
63#define FETCH_ARG_STRING(var) var63#define FETCH_ARG_STRING(var) var
64#define FETCH_ARG_STRUCT(var) &var64#define FETCH_ARG_STRUCT(var) &var
65 65
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
66#define FILL_SIZE_STRING 1674#define FILL_SIZE_STRING 16
75#endif
67 76
68#define INIT_CLONE_SCALAR /**/77#define INIT_CLONE_SCALAR /**/
69#define INIT_CLONE_STRING [FILL_SIZE_STRING]78#define INIT_CLONE_STRING [FILL_SIZE_STRING]
@@ -165,19 +174,23 @@ static noinline void test_ ## name (struct kunit *test) \ · 95 unmodified lines
165 /* Verify all bytes overwritten with 0xFF. */ \174 /* Verify all bytes overwritten with 0xFF. */ \
166 for (sum = 0, i = 0; i < target_size; i++) \175 for (sum = 0, i = 0; i < target_size; i++) \
167 sum += (check_buf[i] != 0xFF); \176 sum += (check_buf[i] != 0xFF); \
168 KUNIT_ASSERT_EQ_MSG(test, sum, 0, \
169 "leaf fill was not 0xFF!?\n"); \
170 /* Clear entire check buffer for later bit tests. */ \177 /* Clear entire check buffer for later bit tests. */ \
171 memset(check_buf, 0x00, sizeof(check_buf)); \178 memset(check_buf, 0x00, sizeof(check_buf)); \
172 /* Extract stack-defined variable contents. */ \179 /* Extract stack-defined variable contents. */ \
173 ignored = leaf_ ##name((unsigned long)&ignored, 0, \180 ignored = leaf_ ##name((unsigned long)&ignored, 0, \
174 FETCH_ARG_ ## which(zero)); \181 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"); \
175 \188 \
176 /* Validate that compiler lined up fill and target. */ \189 /* Validate that compiler lined up fill and target. */ \
177 KUNIT_ASSERT_TRUE_MSG(test, \190 KUNIT_ASSERT_TRUE_MSG(test, \
178 stackinit_range_contains(fill_start, fill_size, \191 stackinit_range_contains(fill_start, fill_size, \
179 target_start, target_size), \192 target_start, target_size), \
180 "stack fill missed target!? " \193 "stackframe was not the same between calls!? " \
181 "(fill %zu wide, target offset by %d)\n", \194 "(fill %zu wide, target offset by %d)\n", \
182 fill_size, \195 fill_size, \
183 (int)((ssize_t)(uintptr_t)fill_start - \196 (int)((ssize_t)(uintptr_t)fill_start - \
lib/string.c+11−12
@@ -15,19 +15,20 @@ · 14 unmodified lines
15 */15 */
16 16
17#define __NO_FORTIFY17#define __NO_FORTIFY
18#include <linux/types.h>18#include <linux/bits.h>
19#include <linux/string.h>
20#include <linux/ctype.h>
21#include <linux/kernel.h>
22#include <linux/export.h>
23#include <linux/bug.h>19#include <linux/bug.h>
20#include <linux/ctype.h>
24#include <linux/errno.h>21#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>
26 27
28#include <asm/page.h>
29#include <asm/rwonce.h>
27#include <asm/unaligned.h>30#include <asm/unaligned.h>
28#include <asm/byteorder.h>
29#include <asm/word-at-a-time.h>31#include <asm/word-at-a-time.h>
30#include <asm/page.h>
31 32
32#ifndef __HAVE_ARCH_STRNCASECMP33#ifndef __HAVE_ARCH_STRNCASECMP
33/**34/**
@@ -103,8 +104,7 @@ char *strncpy(char *dest, const char *src, size_t count) · 69 unmodified lines
103EXPORT_SYMBOL(strncpy);104EXPORT_SYMBOL(strncpy);
104#endif105#endif
105 106
106#ifndef __HAVE_ARCH_STRSCPY107ssize_t sized_strscpy(char *dest, const char *src, size_t count)
107ssize_t strscpy(char *dest, const char *src, size_t count)
108{108{
109 const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;109 const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
110 size_t max = count;110 size_t max = count;
@@ -170,8 +170,7 @@ ssize_t strscpy(char *dest, const char *src, size_t count) · 59 unmodified lines
170 170
171 return -E2BIG;171 return -E2BIG;
172}172}
173EXPORT_SYMBOL(strscpy);173EXPORT_SYMBOL(sized_strscpy);
174#endif
175 174
176/**175/**
177 * stpcpy - copy a string from src to dest returning a pointer to the new end176 * 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
18#include <linux/slab.h>18#include <linux/slab.h>
19#include <linux/string.h>19#include <linux/string.h>
20#include <linux/string_helpers.h>20#include <linux/string_helpers.h>
21#include <kunit/test.h>
22#include <kunit/test-bug.h>
21 23
22/**24/**
23 * string_get_size - get the size in the specified units25 * string_get_size - get the size in the specified units
24 * @size: The size to be converted in blocks26 * @size: The size to be converted in blocks
25 * @blk_size: Size of the block (use 1 for size in bytes)27 * @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
27 * @buf: buffer to format to29 * @buf: buffer to format to
28 * @len: length of buffer30 * @len: length of buffer
29 *31 *
@@ -37,11 +39,12 @@ · 7 unmodified lines
37int string_get_size(u64 size, u64 blk_size, const enum string_size_units units,39int string_get_size(u64 size, u64 blk_size, const enum string_size_units units,
38 char *buf, int len)40 char *buf, int len)
39{41{
42 enum string_size_units units_base = units & STRING_UNITS_MASK;
40 static const char *const units_10[] = {43 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",
42 };45 };
43 static const char *const units_2[] = {46 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",
45 };48 };
46 static const char *const *const units_str[] = {49 static const char *const *const units_str[] = {
47 [STRING_UNITS_10] = units_10,50 [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
66 69
67 /* This is Napier's algorithm. Reduce the original block size to70 /* This is Napier's algorithm. Reduce the original block size to
68 *71 *
69 * coefficient * divisor[units]^i72 * coefficient * divisor[units_base]^i
70 *73 *
71 * we do the reduction so both coefficients are just under 32 bits so74 * we do the reduction so both coefficients are just under 32 bits so
72 * that multiplying them together won't overflow 64 bits and we keep75 * 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
76 * precision is in the coefficients.79 * precision is in the coefficients.
77 */80 */
78 while (blk_size >> 32) {81 while (blk_size >> 32) {
79 do_div(blk_size, divisor[units]);82 do_div(blk_size, divisor[units_base]);
80 i++;83 i++;
81 }84 }
82 85
83 while (size >> 32) {86 while (size >> 32) {
84 do_div(size, divisor[units]);87 do_div(size, divisor[units_base]);
85 i++;88 i++;
86 }89 }
87 90
@@ -90,8 +93,8 @@ int string_get_size(u64 size, u64 blk_size, const enum string_size_units units, · 2 unmodified lines
90 size *= blk_size;93 size *= blk_size;
91 94
92 /* and logarithmically reduce it until it's just under the divisor */95 /* and logarithmically reduce it until it's just under the divisor */
93 while (size >= divisor[units]) {96 while (size >= divisor[units_base]) {
94 remainder = do_div(size, divisor[units]);97 remainder = do_div(size, divisor[units_base]);
95 i++;98 i++;
96 }99 }
97 100
@@ -101,10 +104,10 @@ int string_get_size(u64 size, u64 blk_size, const enum string_size_units units, · 3 unmodified lines
101 for (j = 0; sf_cap*10 < 1000; j++)104 for (j = 0; sf_cap*10 < 1000; j++)
102 sf_cap *= 10;105 sf_cap *= 10;
103 106
104 if (units == STRING_UNITS_2) {107 if (units_base == STRING_UNITS_2) {
105 /* express the remainder as a decimal. It's currently the108 /* express the remainder as a decimal. It's currently the
106 * numerator of a fraction whose denominator is109 * 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 */
108 remainder *= 1000;111 remainder *= 1000;
109 remainder >>= 10;112 remainder >>= 10;
110 }113 }
@@ -126,10 +129,12 @@ int string_get_size(u64 size, u64 blk_size, const enum string_size_units units, · 15 unmodified lines
126 if (i >= ARRAY_SIZE(units_2))129 if (i >= ARRAY_SIZE(units_2))
127 unit = "UNK";130 unit = "UNK";
128 else131 else
129 unit = units_str[units][i];132 unit = units_str[units_base][i];
130 133
131 return snprintf(buf, len, "%u%s %s", (u32)size,134 return snprintf(buf, len, "%u%s%s%s%s", (u32)size, tmp,
132 tmp, unit);135 (units & STRING_UNITS_NO_SPACE) ? "" : " ",
136 unit,
137 (units & STRING_UNITS_NO_BYTES) ? "" : "B");
133}138}
134EXPORT_SYMBOL(string_get_size);139EXPORT_SYMBOL(string_get_size);
135 140
@@ -825,40 +830,6 @@ char **devm_kasprintf_strarray(struct device *dev, const char *prefix, size_t n) · 689 unmodified lines
825}830}
826EXPORT_SYMBOL_GPL(devm_kasprintf_strarray);831EXPORT_SYMBOL_GPL(devm_kasprintf_strarray);
827 832
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 */
848ssize_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}
860EXPORT_SYMBOL(strscpy_pad);
861
862/**833/**
863 * skip_spaces - Removes leading whitespace from @str.834 * skip_spaces - Removes leading whitespace from @str.
864 * @str: The string to be stripped.835 * @str: The string to be stripped.
@@ -1042,10 +1013,28 @@ EXPORT_SYMBOL(__read_overflow2_field); · 177 unmodified lines
1042void __write_overflow_field(size_t avail, size_t wanted) { }1013void __write_overflow_field(size_t avail, size_t wanted) { }
1043EXPORT_SYMBOL(__write_overflow_field);1014EXPORT_SYMBOL(__write_overflow_field);
1044 1015
1045void fortify_panic(const char *name)1016static 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
1022void __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}
1032EXPORT_SYMBOL(__fortify_report);
1033
1034void __fortify_panic(const u8 reason, const size_t avail, const size_t size)
1046{1035{
1047 pr_emerg("detected buffer overflow in %s\n", name);1036 __fortify_report(reason, avail, size);
1048 BUG();1037 BUG();
1049}1038}
1050EXPORT_SYMBOL(fortify_panic);1039EXPORT_SYMBOL(__fortify_panic);
1051#endif /* CONFIG_FORTIFY_SOURCE */1040#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
1/*2/*
2 * Test cases for lib/string_helpers.c module.3 * Test cases for lib/string_helpers.c module.
3 */4 */
4#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt5#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
5 6
6#include <linux/init.h>7#include <kunit/test.h>
8#include <linux/array_size.h>
7#include <linux/kernel.h>9#include <linux/kernel.h>
8#include <linux/slab.h>
9#include <linux/module.h>
10#include <linux/random.h>10#include <linux/random.h>
11#include <linux/string.h>11#include <linux/string.h>
12#include <linux/string_helpers.h>12#include <linux/string_helpers.h>
13 13
14static __init bool test_string_check_buf(const char *name, unsigned int flags,14static void test_string_check_buf(struct kunit *test,
15 char *in, size_t p,15 const char *name, unsigned int flags,
16 char *out_real, size_t q_real,16 char *in, size_t p,
17 char *out_test, size_t q_test)17 char *out_real, size_t q_real,
18 char *out_test, size_t q_test)
18{19{
19 if (q_real == q_test && !memcmp(out_test, out_real, q_test))20 KUNIT_ASSERT_EQ_MSG(test, q_real, q_test, "name:%s", name);
20 return true;21 KUNIT_EXPECT_MEMEQ_MSG(test, out_test, out_real, q_test,
21 22 "name:%s", name);
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;
32}23}
33 24
34struct test_string {25struct test_string {
@@ -37,7 +28,7 @@ struct test_string { · 2 unmodified lines
37 unsigned int flags;28 unsigned int flags;
38};29};
39 30
40static const struct test_string strings[] __initconst = {31static const struct test_string strings[] = {
41 {32 {
42 .in = "\\f\\ \\n\\r\\t\\v",33 .in = "\\f\\ \\n\\r\\t\\v",
43 .out = "\f\\ \n\r\t\v",34 .out = "\f\\ \n\r\t\v",
@@ -60,17 +51,19 @@ static const struct test_string strings[] __initconst = { · 16 unmodified lines
60 },51 },
61};52};
62 53
63static void __init test_string_unescape(const char *name, unsigned int flags,54static void test_string_unescape(struct kunit *test,
64 bool inplace)55 const char *name, unsigned int flags,
56 bool inplace)
65{57{
66 int q_real = 256;58 int q_real = 256;
67 char *in = kmalloc(q_real, GFP_KERNEL);59 char *in = kunit_kzalloc(test, q_real, GFP_KERNEL);
68 char *out_test = kmalloc(q_real, GFP_KERNEL);60 char *out_test = kunit_kzalloc(test, q_real, GFP_KERNEL);
69 char *out_real = kmalloc(q_real, GFP_KERNEL);61 char *out_real = kunit_kzalloc(test, q_real, GFP_KERNEL);
70 int i, p = 0, q_test = 0;62 int i, p = 0, q_test = 0;
71 63
72 if (!in || !out_test || !out_real)64 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, in);
73 goto out;65 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_test);
66 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_real);
74 67
75 for (i = 0; i < ARRAY_SIZE(strings); i++) {68 for (i = 0; i < ARRAY_SIZE(strings); i++) {
76 const char *s = strings[i].in;69 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
103 q_real = string_unescape(in, out_real, q_real, flags);96 q_real = string_unescape(in, out_real, q_real, flags);
104 }97 }
105 98
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,
107 out_test, q_test);100 out_test, q_test);
108out:
109 kfree(out_real);
110 kfree(out_test);
111 kfree(in);
112}101}
113 102
114struct test_string_1 {103struct test_string_1 {
@@ -123,7 +112,7 @@ struct test_string_2 { · 8 unmodified lines
123};112};
124 113
125#define TEST_STRING_2_DICT_0 NULL114#define TEST_STRING_2_DICT_0 NULL
126static const struct test_string_2 escape0[] __initconst = {{115static const struct test_string_2 escape0[] = {{
127 .in = "\f\\ \n\r\t\v",116 .in = "\f\\ \n\r\t\v",
128 .s1 = {{117 .s1 = {{
129 .out = "\\f\\ \\n\\r\\t\\v",118 .out = "\\f\\ \\n\\r\\t\\v",
@@ -221,7 +210,7 @@ static const struct test_string_2 escape0[] __initconst = {{ · 91 unmodified lines
221}};210}};
222 211
223#define TEST_STRING_2_DICT_1 "b\\ \t\r\xCF"212#define TEST_STRING_2_DICT_1 "b\\ \t\r\xCF"
224static const struct test_string_2 escape1[] __initconst = {{213static const struct test_string_2 escape1[] = {{
225 .in = "\f\\ \n\r\t\v",214 .in = "\f\\ \n\r\t\v",
226 .s1 = {{215 .s1 = {{
227 .out = "\f\\134\\040\n\\015\\011\v",216 .out = "\f\\134\\040\n\\015\\011\v",
@@ -358,7 +347,7 @@ static const struct test_string_2 escape1[] __initconst = {{ · 130 unmodified lines
358 /* terminator */347 /* terminator */
359}};348}};
360 349
361static const struct test_string strings_upper[] __initconst = {350static const struct test_string strings_upper[] = {
362 {351 {
363 .in = "abcdefgh1234567890test",352 .in = "abcdefgh1234567890test",
364 .out = "ABCDEFGH1234567890TEST",353 .out = "ABCDEFGH1234567890TEST",
@@ -369,7 +358,7 @@ static const struct test_string strings_upper[] __initconst = { · 4 unmodified lines
369 },358 },
370};359};
371 360
372static const struct test_string strings_lower[] __initconst = {361static const struct test_string strings_lower[] = {
373 {362 {
374 .in = "ABCDEFGH1234567890TEST",363 .in = "ABCDEFGH1234567890TEST",
375 .out = "abcdefgh1234567890test",364 .out = "abcdefgh1234567890test",
@@ -380,8 +369,8 @@ static const struct test_string strings_lower[] __initconst = { · 4 unmodified lines
380 },369 },
381};370};
382 371
383static __init const char *test_string_find_match(const struct test_string_2 *s2,372static const char *test_string_find_match(const struct test_string_2 *s2,
384 unsigned int flags)373 unsigned int flags)
385{374{
386 const struct test_string_1 *s1 = s2->s1;375 const struct test_string_1 *s1 = s2->s1;
387 unsigned int i;376 unsigned int i;
@@ -402,31 +391,31 @@ static __init const char *test_string_find_match(const struct test_string_2 *s2, · 14 unmodified lines
402 return NULL;391 return NULL;
403}392}
404 393
405static __init void394static void
406test_string_escape_overflow(const char *in, int p, unsigned int flags, const char *esc,395test_string_escape_overflow(struct kunit *test,
396 const char *in, int p, unsigned int flags, const char *esc,
407 int q_test, const char *name)397 int q_test, const char *name)
408{398{
409 int q_real;399 int q_real;
410 400
411 q_real = string_escape_mem(in, p, NULL, 0, flags, esc);401 q_real = string_escape_mem(in, p, NULL, 0, flags, esc);
412 if (q_real != q_test)402 KUNIT_EXPECT_EQ_MSG(test, q_real, q_test, "name:%s: flags:%#x", name, flags);
413 pr_warn("Test '%s' failed: flags = %#x, osz = 0, expected %d, got %d\n",
414 name, flags, q_test, q_real);
415}403}
416 404
417static __init void test_string_escape(const char *name,405static void test_string_escape(struct kunit *test, const char *name,
418 const struct test_string_2 *s2,406 const struct test_string_2 *s2,
419 unsigned int flags, const char *esc)407 unsigned int flags, const char *esc)
420{408{
421 size_t out_size = 512;409 size_t out_size = 512;
422 char *out_test = kmalloc(out_size, GFP_KERNEL);410 char *out_test = kunit_kzalloc(test, out_size, GFP_KERNEL);
423 char *out_real = kmalloc(out_size, GFP_KERNEL);411 char *out_real = kunit_kzalloc(test, out_size, GFP_KERNEL);
424 char *in = kmalloc(256, GFP_KERNEL);412 char *in = kunit_kzalloc(test, 256, GFP_KERNEL);
425 int p = 0, q_test = 0;413 int p = 0, q_test = 0;
426 int q_real;414 int q_real;
427 415
428 if (!out_test || !out_real || !in)416 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_test);
429 goto out;417 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, out_real);
418 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, in);
430 419
431 for (; s2->in; s2++) {420 for (; s2->in; s2++) {
432 const char *out;421 const char *out;
@@ -462,62 +451,99 @@ static __init void test_string_escape(const char *name, · 29 unmodified lines
462 451
463 q_real = string_escape_mem(in, p, out_real, out_size, flags, esc);452 q_real = string_escape_mem(in, p, out_real, out_size, flags, esc);
464 453
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,
466 q_test);455 q_test);
467 456
468 test_string_escape_overflow(in, p, flags, esc, q_test, name);457 test_string_escape_overflow(test, in, p, flags, esc, q_test, name);
469
470out:
471 kfree(in);
472 kfree(out_real);
473 kfree(out_test);
474}458}
475 459
476#define string_get_size_maxbuf 16460#define string_get_size_maxbuf 16
477#define test_string_get_size_one(size, blk_size, exp_result10, exp_result2) \461#define test_string_get_size_one(size, blk_size, exp_result10, exp_result2) \
478 do { \462 do { \
479 BUILD_BUG_ON(sizeof(exp_result10) >= string_get_size_maxbuf); \463 BUILD_BUG_ON(sizeof(exp_result10) >= string_get_size_maxbuf); \
480 BUILD_BUG_ON(sizeof(exp_result2) >= string_get_size_maxbuf); \464 BUILD_BUG_ON(sizeof(exp_result2) >= string_get_size_maxbuf); \
481 __test_string_get_size((size), (blk_size), (exp_result10), \465 __test_string_get_size(test, (size), (blk_size), (exp_result10), \
482 (exp_result2)); \466 (exp_result2)); \
483 } while (0)467 } while (0)
484 468
485 469
486static __init void test_string_get_size_check(const char *units,470static void test_string_get_size_check(struct kunit *test,
487 const char *exp,471 const char *units,
488 char *res,472 const char *exp,
489 const u64 size,473 char *res,
490 const u64 blk_size)474 const u64 size,
475 const u64 blk_size)
491{476{
492 if (!memcmp(res, exp, strlen(exp) + 1))477 KUNIT_EXPECT_MEMEQ_MSG(test, res, exp, strlen(exp) + 1,
493 return;478 "string_get_size(size = %llu, blk_size = %llu, units = %s)",
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",
499 size, blk_size, units);479 size, blk_size, units);
500 pr_warn("expected: '%s', got '%s'\n", exp, res);
501}480}
502 481
503static __init void __test_string_get_size(const u64 size, const u64 blk_size,482static void __strchrcut(char *dst, const char *src, const char *cut)
504 const char *exp_result10,483{
505 const char *exp_result2)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
496static 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)
506{502{
507 char buf10[string_get_size_maxbuf];503 char buf10[string_get_size_maxbuf];
508 char buf2[string_get_size_maxbuf];504 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);
509 515
510 string_get_size(size, blk_size, STRING_UNITS_10, buf10, sizeof(buf10));516 string_get_size(size, blk_size, STRING_UNITS_10 | units, buf10, sizeof(buf10));
511 string_get_size(size, blk_size, STRING_UNITS_2, buf2, sizeof(buf2));517 string_get_size(size, blk_size, STRING_UNITS_2 | units, buf2, sizeof(buf2));
512 518
513 test_string_get_size_check("STRING_UNITS_10", exp_result10, buf10,519 test_string_get_size_check(test, prefix10, exp10, buf10, size, blk_size);
514 size, blk_size);520 test_string_get_size_check(test, prefix2, exp2, buf2, size, blk_size);
521}
522
523static 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;
515 538
516 test_string_get_size_check("STRING_UNITS_2", exp_result2, buf2,539 for (i = 0; i < ARRAY_SIZE(get_size_test_cases); i++)
517 size, blk_size);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);
518}544}
519 545
520static __init void test_string_get_size(void)546static void test_get_size(struct kunit *test)
521{547{
522 /* small values */548 /* small values */
523 test_string_get_size_one(0, 512, "0 B", "0 B");549 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
537 test_string_get_size_one(4096, U64_MAX, "75.6 ZB", "64.0 ZiB");563 test_string_get_size_one(4096, U64_MAX, "75.6 ZB", "64.0 ZiB");
538}564}
539 565
540static void __init test_string_upper_lower(void)566static void test_upper_lower(struct kunit *test)
541{567{
542 char *dst;568 char *dst;
543 int i;569 int i;
@@ -547,16 +573,10 @@ static void __init test_string_upper_lower(void) · 3 unmodified lines
547 int len = strlen(strings_upper[i].in) + 1;573 int len = strlen(strings_upper[i].in) + 1;
548 574
549 dst = kmalloc(len, GFP_KERNEL);575 dst = kmalloc(len, GFP_KERNEL);
550 if (!dst)576 KUNIT_ASSERT_NOT_NULL(test, dst);
551 return;
552 577
553 string_upper(dst, s);578 string_upper(dst, s);
554 if (memcmp(dst, strings_upper[i].out, len)) {579 KUNIT_EXPECT_STREQ(test, dst, strings_upper[i].out);
555 pr_warn("Test 'string_upper' failed : expected %s, got %s!\n",
556 strings_upper[i].out, dst);
557 kfree(dst);
558 return;
559 }
560 kfree(dst);580 kfree(dst);
561 }581 }
562 582
@@ -565,45 +585,44 @@ static void __init test_string_upper_lower(void) · 2 unmodified lines
565 int len = strlen(strings_lower[i].in) + 1;585 int len = strlen(strings_lower[i].in) + 1;
566 586
567 dst = kmalloc(len, GFP_KERNEL);587 dst = kmalloc(len, GFP_KERNEL);
568 if (!dst)588 KUNIT_ASSERT_NOT_NULL(test, dst);
569 return;
570 589
571 string_lower(dst, s);590 string_lower(dst, s);
572 if (memcmp(dst, strings_lower[i].out, len)) {591 KUNIT_EXPECT_STREQ(test, dst, strings_lower[i].out);
573 pr_warn("Test 'string_lower failed : : expected %s, got %s!\n",
574 strings_lower[i].out, dst);
575 kfree(dst);
576 return;
577 }
578 kfree(dst);592 kfree(dst);
579 }593 }
580}594}
581 595
582static int __init test_string_helpers_init(void)596static void test_unescape(struct kunit *test)
583{597{
584 unsigned int i;598 unsigned int i;
585 599
586 pr_info("Running tests...\n");
587 for (i = 0; i < UNESCAPE_ALL_MASK + 1; i++)600 for (i = 0; i < UNESCAPE_ALL_MASK + 1; i++)
588 test_string_unescape("unescape", i, false);601 test_string_unescape(test, "unescape", i, false);
589 test_string_unescape("unescape inplace",602 test_string_unescape(test, "unescape inplace",
590 get_random_u32_below(UNESCAPE_ALL_MASK + 1), true);603 get_random_u32_below(UNESCAPE_ALL_MASK + 1), true);
591 604
592 /* Without dictionary */605 /* Without dictionary */
593 for (i = 0; i < ESCAPE_ALL_MASK + 1; i++)606 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);
595 608
596 /* With dictionary */609 /* With dictionary */
597 for (i = 0; i < ESCAPE_ALL_MASK + 1; i++)610 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}
599 613
600 /* Test string_get_size() */614static struct kunit_case string_helpers_test_cases[] = {
601 test_string_get_size();615 KUNIT_CASE(test_get_size),
616 KUNIT_CASE(test_upper_lower),
617 KUNIT_CASE(test_unescape),
618 {}
619};
602 620
603 /* Test string upper(), string_lower() */621static struct kunit_suite string_helpers_test_suite = {
604 test_string_upper_lower();622 .name = "string_helpers",
623 .test_cases = string_helpers_test_cases,
624};
625
626kunit_test_suites(&string_helpers_test_suite);
605 627
606 return -EINVAL;
607}
608module_init(test_string_helpers_init);
609MODULE_LICENSE("Dual BSD/GPL");628MODULE_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
14static 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
43static 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
72static 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
101static 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
124static 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
157static 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
182static 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
192static struct kunit_suite string_test_suite = {
193 .name = "string",
194 .test_cases = string_test_cases,
195};
196
197kunit_test_suites(&string_test_suite);
198
199MODULE_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
7static __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
36fail:
37 kfree(p);
38 if (i < 256)
39 return (i << 24) | (j << 16) | k | 0x8000;
40 return 0;
41}
42
43static __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
72fail:
73 kfree(p);
74 if (i < 256)
75 return (i << 24) | (j << 16) | k | 0x8000;
76 return 0;
77}
78
79static __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
108fail:
109 kfree(p);
110 if (i < 256)
111 return (i << 24) | (j << 16) | k | 0x8000;
112 return 0;
113}
114
115static __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
143static __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
182static __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
210static __exit void string_selftest_remove(void)
211{
212}
213
214static __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;
250fail:
251 pr_crit("String selftest failure %d.%08x\n", test, subtest);
252 return 0;
253}
254
255module_init(string_selftest_init);
256module_exit(string_selftest_remove);
257MODULE_LICENSE("GPL v2");
lib/test_ubsan.c+39−2
@@ -11,6 +11,39 @@ typedef void(*test_ubsan_fp)(void); · 10 unmodified lines
11 #config, IS_ENABLED(config) ? "y" : "n"); \11 #config, IS_ENABLED(config) ? "y" : "n"); \
12 } while (0)12 } while (0)
13 13
14static 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
22static 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
31static 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
39static 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
14static void test_ubsan_divrem_overflow(void)47static void test_ubsan_divrem_overflow(void)
15{48{
16 volatile int val = 16;49 volatile int val = 16;
@@ -23,8 +56,8 @@ static void test_ubsan_divrem_overflow(void) · 6 unmodified lines
23static void test_ubsan_shift_out_of_bounds(void)56static void test_ubsan_shift_out_of_bounds(void)
24{57{
25 volatile int neg = -1, wrap = 4;58 volatile int neg = -1, wrap = 4;
26 int val1 = 10;59 volatile int val1 = 10;
27 int val2 = INT_MAX;60 volatile int val2 = INT_MAX;
28 61
29 UBSAN_TEST(CONFIG_UBSAN_SHIFT, "negative exponent");62 UBSAN_TEST(CONFIG_UBSAN_SHIFT, "negative exponent");
30 val1 <<= neg;63 val1 <<= neg;
@@ -90,6 +123,10 @@ static void test_ubsan_misaligned_access(void) · 59 unmodified lines
90}123}
91 124
92static const test_ubsan_fp test_ubsan_array[] = {125static 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,
93 test_ubsan_shift_out_of_bounds,130 test_ubsan_shift_out_of_bounds,
94 test_ubsan_out_of_bounds,131 test_ubsan_out_of_bounds,
95 test_ubsan_load_invalid_value,132 test_ubsan_load_invalid_value,
lib/ubsan.c+68−0
@@ -222,6 +222,74 @@ static void ubsan_epilogue(void) · 221 unmodified lines
222 check_panic_on_warn("UBSAN");222 check_panic_on_warn("UBSAN");
223}223}
224 224
225static 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
251void __ubsan_handle_add_overflow(void *data,
252 void *lhs, void *rhs)
253{
254
255 handle_overflow(data, lhs, rhs, '+');
256}
257EXPORT_SYMBOL(__ubsan_handle_add_overflow);
258
259void __ubsan_handle_sub_overflow(void *data,
260 void *lhs, void *rhs)
261{
262 handle_overflow(data, lhs, rhs, '-');
263}
264EXPORT_SYMBOL(__ubsan_handle_sub_overflow);
265
266void __ubsan_handle_mul_overflow(void *data,
267 void *lhs, void *rhs)
268{
269 handle_overflow(data, lhs, rhs, '*');
270}
271EXPORT_SYMBOL(__ubsan_handle_mul_overflow);
272
273void __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}
290EXPORT_SYMBOL(__ubsan_handle_negate_overflow);
291
292
225void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs)293void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs)
226{294{
227 struct overflow_data *data = _data;295 struct overflow_data *data = _data;
lib/ubsan.h+4−0
@@ -124,6 +124,10 @@ typedef s64 s_max; · 123 unmodified lines
124typedef u64 u_max;124typedef u64 u_max;
125#endif125#endif
126 126
127void __ubsan_handle_add_overflow(void *data, void *lhs, void *rhs);
128void __ubsan_handle_sub_overflow(void *data, void *lhs, void *rhs);
129void __ubsan_handle_mul_overflow(void *data, void *lhs, void *rhs);
130void __ubsan_handle_negate_overflow(void *_data, void *old_val);
127void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs);131void __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs);
128void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, void *ptr);132void __ubsan_handle_type_mismatch(struct type_mismatch_data *data, void *ptr);
129void __ubsan_handle_type_mismatch_v1(void *_data, void *ptr);133void __ubsan_handle_type_mismatch_v1(void *_data, void *ptr);
scripts/Makefile.lib+4−1
@@ -175,8 +175,11 @@ endif · 174 unmodified lines
175 175
176ifeq ($(CONFIG_UBSAN),y)176ifeq ($(CONFIG_UBSAN),y)
177_c_flags += $(if $(patsubst n%,, \177_c_flags += $(if $(patsubst n%,, \
178 $(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_SANITIZE)$(CONFIG_UBSAN_SANITIZE_ALL)), \178 $(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_SANITIZE)y), \
179 $(CFLAGS_UBSAN))179 $(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))
180endif183endif
181 184
182ifeq ($(CONFIG_KCOV),y)185ifeq ($(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
10ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable10ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable
11ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool11ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool
12ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum12ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum
13ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error13ubsan-cflags-$(CONFIG_UBSAN_TRAP) += $(call cc-option,-fsanitize-trap=undefined,-fsanitize-undefined-trap-on-error)
14 14
15export CFLAGS_UBSAN := $(ubsan-cflags-y)15export CFLAGS_UBSAN := $(ubsan-cflags-y)
16
17ubsan-signed-wrap-cflags-$(CONFIG_UBSAN_SIGNED_WRAP) += -fsanitize=signed-integer-overflow
18export 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
6virtual patch
7virtual context
8virtual report
9
10@str_plural depends on patch@
11expression 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@
25expression E;
26position 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@
37p << str_plural_r.P;
38e << str_plural_r.E;
39@@
40
41coccilib.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
10virtual patch
11virtual context
12virtual org
13virtual 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@
19identifier f = overflow_size_helpers_test;
20@@
21
22f
23
24//----------------------------------------------------------
25// For context mode
26//----------------------------------------------------------
27
28@depends on !overflow_tests && context@
29expression E1, E2;
30identifier 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@
41expression E1, E2;
42identifier 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)@
54expression E1, E2;
55identifier m;
56position p;
57@@
58(
59 (sizeof(*E1)@p + (E2 * sizeof(*E1->m)))
60)
61
62@script:python depends on org@
63p << r.p;
64@@
65
66coccilib.org.print_todo(p[0], "WARNING should use struct_size")
67
68@script:python depends on report@
69p << r.p;
70@@
71
72msg="WARNING: Use struct_size"
73coccilib.report.print_report(p[0], msg)
74
scripts/leaking_addresses.pl+74−16
@@ -23,6 +23,7 @@ use strict; · 22 unmodified lines
23use POSIX;23use POSIX;
24use File::Basename;24use File::Basename;
25use File::Spec;25use File::Spec;
26use File::Temp qw/tempfile/;
26use Cwd 'abs_path';27use Cwd 'abs_path';
27use Term::ANSIColor qw(:constants);28use Term::ANSIColor qw(:constants);
28use Getopt::Long qw(:config no_auto_abbrev);29use 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
51my $suppress_dmesg = 0; # Don't show dmesg in output.52my $suppress_dmesg = 0; # Don't show dmesg in output.
52my $squash_by_path = 0; # Summary report grouped by absolute path.53my $squash_by_path = 0; # Summary report grouped by absolute path.
53my $squash_by_filename = 0; # Summary report grouped by filename.54my $squash_by_filename = 0; # Summary report grouped by filename.
55my $kallsyms_file = ""; # Kernel symbols file.
54my $kernel_config_file = ""; # Kernel configuration file.56my $kernel_config_file = ""; # Kernel configuration file.
55my $opt_32bit = 0; # Scan 32-bit kernel.57my $opt_32bit = 0; # Scan 32-bit kernel.
56my $page_offset_32bit = 0; # Page offset for 32-bit kernel.58my $page_offset_32bit = 0; # Page offset for 32-bit kernel.
57 59
60my @kallsyms = ();
61
58# Skip these absolute paths.62# Skip these absolute paths.
59my @skip_abs = (63my @skip_abs = (
60 '/proc/kmsg',64 '/proc/kmsg',
@@ -95,6 +99,8 @@ Options: · 34 unmodified lines
95 --squash-by-path Show one result per unique path.99 --squash-by-path Show one result per unique path.
96 --squash-by-filename Show one result per unique filename.100 --squash-by-filename Show one result per unique filename.
97 --kernel-config-file=<file> Kernel configuration file (e.g /boot/config)101 --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).
98 --32-bit Scan 32-bit kernel.104 --32-bit Scan 32-bit kernel.
99 --page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).105 --page-offset-32-bit=o Page offset (for 32-bit kernel 0xABCD1234).
100 -d, --debug Display debugging output.106 -d, --debug Display debugging output.
@@ -115,6 +121,7 @@ GetOptions( · 14 unmodified lines
115 'squash-by-path' => \$squash_by_path,121 'squash-by-path' => \$squash_by_path,
116 'squash-by-filename' => \$squash_by_filename,122 'squash-by-filename' => \$squash_by_filename,
117 'raw' => \$raw,123 'raw' => \$raw,
124 'kallsyms=s' => \$kallsyms_file,
118 'kernel-config-file=s' => \$kernel_config_file,125 'kernel-config-file=s' => \$kernel_config_file,
119 '32-bit' => \$opt_32bit,126 '32-bit' => \$opt_32bit,
120 'page-offset-32-bit=o' => \$page_offset_32bit,127 'page-offset-32-bit=o' => \$page_offset_32bit,
@@ -155,6 +162,25 @@ if ($output_raw) { · 34 unmodified lines
155 select $fh;162 select $fh;
156}163}
157 164
165if ($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
158parse_dmesg();184parse_dmesg();
159walk(@DIRS);185walk(@DIRS);
160 186
@@ -221,6 +247,7 @@ sub get_kernel_config_option · 60 unmodified lines
221{247{
222 my ($option) = @_;248 my ($option) = @_;
223 my $value = "";249 my $value = "";
250 my $tmp_fh;
224 my $tmp_file = "";251 my $tmp_file = "";
225 my @config_files;252 my @config_files;
226 253
@@ -228,7 +255,8 @@ sub get_kernel_config_option · 1 unmodified line
228 if ($kernel_config_file ne "") {255 if ($kernel_config_file ne "") {
229 @config_files = ($kernel_config_file);256 @config_files = ($kernel_config_file);
230 } elsif (-R "/proc/config.gz") {257 } elsif (-R "/proc/config.gz") {
231 my $tmp_file = "/tmp/tmpkconf";258 ($tmp_fh, $tmp_file) = tempfile("config.gz-XXXXXX",
259 UNLINK => 1);
232 260
233 if (system("gunzip < /proc/config.gz > $tmp_file")) {261 if (system("gunzip < /proc/config.gz > $tmp_file")) {
234 dprint("system(gunzip < /proc/config.gz) failed\n");262 dprint("system(gunzip < /proc/config.gz) failed\n");
@@ -250,10 +278,6 @@ sub get_kernel_config_option · 15 unmodified lines
250 }278 }
251 }279 }
252 280
253 if ($tmp_file ne "") {
254 system("rm -f $tmp_file");
255 }
256
257 return $value;281 return $value;
258}282}
259 283
@@ -285,9 +309,10 @@ sub is_false_positive · 25 unmodified lines
285 return is_false_positive_32bit($match);309 return is_false_positive_32bit($match);
286 }310 }
287 311
288 # 64 bit false positives.312 # Ignore 64 bit false positives:
289 313 # 0xfffffffffffffff[0-f]
290 if ($match =~ '\b(0x)?(f|F){16}\b' or314 # 0x0000000000000000
315 if ($match =~ '\b(0x)?(f|F){15}[0-9a-f]\b' or
291 $match =~ '\b(0x)?0{16}\b') {316 $match =~ '\b(0x)?0{16}\b') {
292 return 1;317 return 1;
293 }318 }
@@ -304,7 +329,7 @@ sub is_false_positive_32bit · 10 unmodified lines
304 my ($match) = @_;329 my ($match) = @_;
305 state $page_offset = get_page_offset();330 state $page_offset = get_page_offset();
306 331
307 if ($match =~ '\b(0x)?(f|F){8}\b') {332 if ($match =~ '\b(0x)?(f|F){7}[0-9a-f]\b') {
308 return 1;333 return 1;
309 }334 }
310 335
@@ -347,18 +372,23 @@ sub is_in_vsyscall_memory_region · 36 unmodified lines
347# True if argument potentially contains a kernel address.372# True if argument potentially contains a kernel address.
348sub may_leak_address373sub may_leak_address
349{374{
350 my ($line) = @_;375 my ($path, $line) = @_;
351 my $address_re;376 my $address_re;
352 377
353 # Signal masks.378 # Ignore Signal masks.
354 if ($line =~ '^SigBlk:' or379 if ($line =~ '^SigBlk:' or
355 $line =~ '^SigIgn:' or380 $line =~ '^SigIgn:' or
356 $line =~ '^SigCgt:') {381 $line =~ '^SigCgt:') {
357 return 0;382 return 0;
358 }383 }
359 384
360 if ($line =~ '\bKEY=[[:xdigit:]]{14} [[:xdigit:]]{16} [[:xdigit:]]{16}\b' or385 # Ignore input device reporting.
361 $line =~ '\b[[:xdigit:]]{14} [[:xdigit:]]{16} [[:xdigit:]]{16}\b') {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')) {
362 return 0;392 return 0;
363 }393 }
364 394
@@ -401,7 +431,7 @@ sub parse_dmesg · 36 unmodified lines
401{431{
402 open my $cmd, '-|', 'dmesg';432 open my $cmd, '-|', 'dmesg';
403 while (<$cmd>) {433 while (<$cmd>) {
404 if (may_leak_address($_)) {434 if (may_leak_address("dmesg", $_)) {
405 print 'dmesg: ' . $_;435 print 'dmesg: ' . $_;
406 }436 }
407 }437 }
@@ -442,6 +472,25 @@ sub timed_parse_file · 34 unmodified lines
442 }472 }
443}473}
444 474
475sub 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
445sub parse_file494sub parse_file
446{495{
447 my ($file) = @_;496 my ($file) = @_;
@@ -451,13 +500,22 @@ sub parse_file · 3 unmodified lines
451 }500 }
452 501
453 if (! -T $file) {502 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 }
454 return;512 return;
455 }513 }
456 514
457 open my $fh, "<", $file or return;515 open my $fh, "<", $file or return;
458 while ( <$fh> ) {516 while ( <$fh> ) {
459 chomp;517 chomp;
460 if (may_leak_address($_)) {518 if (may_leak_address($file, $_)) {
461 printf("$file: $_\n");519 printf("$file: $_\n");
462 }520 }
463 }521 }
@@ -469,7 +527,7 @@ sub check_path_for_leaks · 5 unmodified lines
469{527{
470 my ($path) = @_;528 my ($path) = @_;
471 529
472 if (may_leak_address($path)) {530 if (may_leak_address($path, $path)) {
473 printf("Path name may contain address: $path\n");531 printf("Path name may contain address: $path\n");
474 }532 }
475}533}
tools/objtool/check.c+12−0
@@ -3620,6 +3620,18 @@ static int validate_branch(struct objtool_file *file, struct symbol *func, · 3619 unmodified lines
3620 }3620 }
3621 3621
3622 if (!save_insn->visited) {3622 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
3623 WARN_INSN(insn, "objtool isn't smart enough to handle this CFI save/restore combo");3635 WARN_INSN(insn, "objtool isn't smart enough to handle this CFI save/restore combo");
3624 return 1;3636 return 1;
3625 }3637 }
tools/objtool/noreturns.h+1−1
@@ -6,6 +6,7 @@ · 5 unmodified lines
6 *6 *
7 * Yes, this is unfortunate. A better solution is in the works.7 * Yes, this is unfortunate. A better solution is in the works.
8 */8 */
9NORETURN(__fortify_panic)
9NORETURN(__kunit_abort)10NORETURN(__kunit_abort)
10NORETURN(__module_put_and_kthread_exit)11NORETURN(__module_put_and_kthread_exit)
11NORETURN(__reiserfs_panic)12NORETURN(__reiserfs_panic)
@@ -22,7 +23,6 @@ NORETURN(do_exit) · 10 unmodified lines
22NORETURN(do_group_exit)23NORETURN(do_group_exit)
23NORETURN(do_task_dead)24NORETURN(do_task_dead)
24NORETURN(ex_handler_msr_mce)25NORETURN(ex_handler_msr_mce)
25NORETURN(fortify_panic)
26NORETURN(hlt_play_dead)26NORETURN(hlt_play_dead)
27NORETURN(hv_ghcb_terminate)27NORETURN(hv_ghcb_terminate)
28NORETURN(kthread_complete_and_exit)28NORETURN(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