From 22c033989c3eb9731ad0c497dfab4231b8e367d6 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 19 Jan 2022 18:08:12 -0800 Subject: include/linux/unaligned: replace kernel.h with the necessary inclusions When kernel.h is used in the headers it adds a lot into dependency hell, especially when there are circular dependencies are involved. Replace kernel.h inclusion with the list of what is really being used. The rest of the changes are induced by the above and may not be split. Link: https://lkml.kernel.org/r/20211209123823.20425-1-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko Acked-by: Arend van Spriel [brcmfmac] Acked-by: Kalle Valo Cc: Arend van Spriel Cc: Franky Lin Cc: Hante Meuleman Cc: Chi-hsien Lin Cc: Wright Feng Cc: Chung-hsien Hsu Cc: Kalle Valo Cc: David S. Miller Cc: Jakub Kicinski Cc: Heikki Krogerus Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/lz4/lz4defs.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'lib') diff --git a/lib/lz4/lz4defs.h b/lib/lz4/lz4defs.h index 673bd206aa98..330aa539b46e 100644 --- a/lib/lz4/lz4defs.h +++ b/lib/lz4/lz4defs.h @@ -36,6 +36,8 @@ */ #include + +#include #include /* memset, memcpy */ #define FORCE_INLINE __always_inline -- cgit v1.2.3 From 70ac69928e9717a313a4c72647ebe80663e397a3 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 19 Jan 2022 18:08:53 -0800 Subject: kstrtox: uninline everything I've made a mistake of looking into lib/kstrtox.o code generation. The only function remotely performance critical is _parse_integer() (via /proc/*/map_files/*), everything else is not. Uninline everything, shrink lib/kstrtox.o by ~20 % ! Space savings on x86_64: add/remove: 0/0 grow/shrink: 0/23 up/down: 0/-1269 (-1269 !!!) Function old new delta kstrtoull 16 13 -3 kstrtouint 59 48 -11 kstrtou8 60 49 -11 kstrtou16 61 50 -11 _kstrtoul 46 35 -11 kstrtoull_from_user 95 83 -12 kstrtoul_from_user 95 83 -12 kstrtoll 93 80 -13 kstrtouint_from_user 124 83 -41 kstrtou8_from_user 125 83 -42 kstrtou16_from_user 126 83 -43 kstrtos8 101 50 -51 kstrtos16 102 51 -51 kstrtoint 100 49 -51 _kstrtol 93 35 -58 kstrtobool_from_user 156 75 -81 kstrtoll_from_user 165 83 -82 kstrtol_from_user 165 83 -82 kstrtoint_from_user 172 83 -89 kstrtos8_from_user 173 83 -90 kstrtos16_from_user 174 83 -91 _parse_integer 136 10 -126 _kstrtoull 308 101 -207 Total: Before=3421236, After=3419967, chg -0.04% Link: https://lkml.kernel.org/r/YZDsFDhHst4m2Pnt@localhost.localdomain Signed-off-by: Alexey Dobriyan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/kstrtox.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'lib') diff --git a/lib/kstrtox.c b/lib/kstrtox.c index 059b8b00dc53..886510d248e5 100644 --- a/lib/kstrtox.c +++ b/lib/kstrtox.c @@ -22,6 +22,7 @@ #include "kstrtox.h" +noinline const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) { if (*base == 0) { @@ -47,6 +48,7 @@ const char *_parse_integer_fixup_radix(const char *s, unsigned int *base) * * Don't you dare use this function. */ +noinline unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned long long *p, size_t max_chars) { @@ -85,6 +87,7 @@ unsigned int _parse_integer_limit(const char *s, unsigned int base, unsigned lon return rv; } +noinline unsigned int _parse_integer(const char *s, unsigned int base, unsigned long long *p) { return _parse_integer_limit(s, base, p, INT_MAX); @@ -125,6 +128,7 @@ static int _kstrtoull(const char *s, unsigned int base, unsigned long long *res) * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. * Preferred over simple_strtoull(). Return code must be checked. */ +noinline int kstrtoull(const char *s, unsigned int base, unsigned long long *res) { if (s[0] == '+') @@ -148,6 +152,7 @@ EXPORT_SYMBOL(kstrtoull); * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. * Preferred over simple_strtoll(). Return code must be checked. */ +noinline int kstrtoll(const char *s, unsigned int base, long long *res) { unsigned long long tmp; @@ -219,6 +224,7 @@ EXPORT_SYMBOL(_kstrtol); * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. * Preferred over simple_strtoul(). Return code must be checked. */ +noinline int kstrtouint(const char *s, unsigned int base, unsigned int *res) { unsigned long long tmp; @@ -249,6 +255,7 @@ EXPORT_SYMBOL(kstrtouint); * Returns 0 on success, -ERANGE on overflow and -EINVAL on parsing error. * Preferred over simple_strtol(). Return code must be checked. */ +noinline int kstrtoint(const char *s, unsigned int base, int *res) { long long tmp; @@ -264,6 +271,7 @@ int kstrtoint(const char *s, unsigned int base, int *res) } EXPORT_SYMBOL(kstrtoint); +noinline int kstrtou16(const char *s, unsigned int base, u16 *res) { unsigned long long tmp; @@ -279,6 +287,7 @@ int kstrtou16(const char *s, unsigned int base, u16 *res) } EXPORT_SYMBOL(kstrtou16); +noinline int kstrtos16(const char *s, unsigned int base, s16 *res) { long long tmp; @@ -294,6 +303,7 @@ int kstrtos16(const char *s, unsigned int base, s16 *res) } EXPORT_SYMBOL(kstrtos16); +noinline int kstrtou8(const char *s, unsigned int base, u8 *res) { unsigned long long tmp; @@ -309,6 +319,7 @@ int kstrtou8(const char *s, unsigned int base, u8 *res) } EXPORT_SYMBOL(kstrtou8); +noinline int kstrtos8(const char *s, unsigned int base, s8 *res) { long long tmp; @@ -333,6 +344,7 @@ EXPORT_SYMBOL(kstrtos8); * [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value * pointed to by res is updated upon finding a match. */ +noinline int kstrtobool(const char *s, bool *res) { if (!s) -- cgit v1.2.3 From a31f9336ed48317d61c2299d595ed14294ffe5f9 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Wed, 19 Jan 2022 18:08:59 -0800 Subject: lib/list_debug.c: print more list debugging context in __list_del_entry_valid() Currently, the entry->prev and entry->next are considered to be valid as long as they are not LIST_POISON{1|2}. However, the memory may be corrupted. The prev->next is invalid probably because 'prev' is invalid, not because prev->next's content is illegal. Unfortunately, the printk and its subfunctions will modify the registers that hold the 'prev' and 'next', and we don't see this valuable information in the BUG context. So print the contents of 'entry->prev' and 'entry->next'. Here's an example: list_del corruption. prev->next should be c0ecbf74, but was c08410dc kernel BUG at lib/list_debug.c:53! ... ... PC is at __list_del_entry_valid+0x58/0x98 LR is at __list_del_entry_valid+0x58/0x98 psr: 60000093 sp : c0ecbf30 ip : 00000000 fp : 00000001 r10: c08410d0 r9 : 00000001 r8 : c0825e0c r7 : 20000013 r6 : c08410d0 r5 : c0ecbf74 r4 : c0ecbf74 r3 : c0825d08 r2 : 00000000 r1 : df7ce6f4 r0 : 00000044 ... ... Stack: (0xc0ecbf30 to 0xc0ecc000) bf20: c0ecbf74 c0164fd0 c0ecbf70 c0165170 bf40: c0eca000 c0840c00 c0840c00 c0824500 c0825e0c c0189bbc c088f404 60000013 bf60: 60000013 c0e85100 000004ec 00000000 c0ebcdc0 c0ecbf74 c0ecbf74 c0825d08 bf80: c0e807c0 c018965c 00000000 c013f2a0 c0e807c0 c013f154 00000000 00000000 bfa0: 00000000 00000000 00000000 c01001b0 00000000 00000000 00000000 00000000 bfc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 bfe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000 (__list_del_entry_valid) from (__list_del_entry+0xc/0x20) (__list_del_entry) from (finish_swait+0x60/0x7c) (finish_swait) from (rcu_gp_kthread+0x560/0xa20) (rcu_gp_kthread) from (kthread+0x14c/0x15c) (kthread) from (ret_from_fork+0x14/0x24) At first, I thought prev->next was overwritten. Later, I carefully analyzed the RCU code and the disassembly code. The error occurred when deleting a node from the list rcu_state.gp_wq. The System.map shows that the address of rcu_state is c0840c00. Then I use gdb to obtain the offset of rcu_state.gp_wq.task_list. (gdb) p &((struct rcu_state *)0)->gp_wq.task_list $1 = (struct list_head *) 0x4dc Again: list_del corruption. prev->next should be c0ecbf74, but was c08410dc c08410dc = c0840c00 + 0x4dc = &rcu_state.gp_wq.task_list Because rcu_state.gp_wq has at most one node, so I can guess that "prev = &rcu_state.gp_wq.task_list". But for other scenes, maybe I wasn't so lucky, I cannot figure out the value of 'prev'. Link: https://lkml.kernel.org/r/20211207025835.1909-1-thunder.leizhen@huawei.com Signed-off-by: Zhen Lei Cc: "Paul E . McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/list_debug.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/list_debug.c b/lib/list_debug.c index 5d5424b51b74..9daa3fb9d1cd 100644 --- a/lib/list_debug.c +++ b/lib/list_debug.c @@ -49,11 +49,11 @@ bool __list_del_entry_valid(struct list_head *entry) "list_del corruption, %px->prev is LIST_POISON2 (%px)\n", entry, LIST_POISON2) || CHECK_DATA_CORRUPTION(prev->next != entry, - "list_del corruption. prev->next should be %px, but was %px\n", - entry, prev->next) || + "list_del corruption. prev->next should be %px, but was %px. (prev=%px)\n", + entry, prev->next, prev) || CHECK_DATA_CORRUPTION(next->prev != entry, - "list_del corruption. next->prev should be %px, but was %px\n", - entry, next->prev)) + "list_del corruption. next->prev should be %px, but was %px. (next=%px)\n", + entry, next->prev, next)) return false; return true; -- cgit v1.2.3 From fd0a1462405b087377e59b84e119fe7e2d08499a Mon Sep 17 00:00:00 2001 From: Isabella Basso Date: Wed, 19 Jan 2022 18:09:02 -0800 Subject: hash.h: remove unused define directive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch series "test_hash.c: refactor into KUnit", v3. We refactored the lib/test_hash.c file into KUnit as part of the student group LKCAMP [1] introductory hackathon for kernel development. This test was pointed to our group by Daniel Latypov [2], so its full conversion into a pure KUnit test was our goal in this patch series, but we ran into many problems relating to it not being split as unit tests, which complicated matters a bit, as the reasoning behind the original tests is quite cryptic for those unfamiliar with hash implementations. Some interesting developments we'd like to highlight are: - In patch 1/5 we noticed that there was an unused define directive that could be removed. - In patch 4/5 we noticed how stringhash and hash tests are all under the lib/test_hash.c file, which might cause some confusion, and we also broke those kernel config entries up. Overall KUnit developments have been made in the other patches in this series: In patches 2/5, 3/5 and 5/5 we refactored the lib/test_hash.c file so as to make it more compatible with the KUnit style, whilst preserving the original idea of the maintainer who designed it (i.e. George Spelvin), which might be undesirable for unit tests, but we assume it is enough for a first patch. This patch (of 5): Currently, there exist hash_32() and __hash_32() functions, which were introduced in a patch [1] targeting architecture specific optimizations. These functions can be overridden on a per-architecture basis to achieve such optimizations. They must set their corresponding define directive (HAVE_ARCH_HASH_32 and HAVE_ARCH__HASH_32, respectively) so that header files can deal with these overrides properly. As the supported 32-bit architectures that have their own hash function implementation (i.e. m68k, Microblaze, H8/300, pa-risc) have only been making use of the (more general) __hash_32() function (which only lacks a right shift operation when compared to the hash_32() function), remove the define directive corresponding to the arch-specific hash_32() implementation. [1] https://lore.kernel.org/lkml/20160525073311.5600.qmail@ns.sciencehorizons.net/ [akpm@linux-foundation.org: hash_32_generic() becomes hash_32()] Link: https://lkml.kernel.org/r/20211208183711.390454-1-isabbasso@riseup.net Link: https://lkml.kernel.org/r/20211208183711.390454-2-isabbasso@riseup.net Reviewed-by: David Gow Tested-by: David Gow Co-developed-by: Augusto Durães Camargo Signed-off-by: Augusto Durães Camargo Co-developed-by: Enzo Ferreira Signed-off-by: Enzo Ferreira Signed-off-by: Isabella Basso Cc: Geert Uytterhoeven Cc: Brendan Higgins Cc: Daniel Latypov Cc: Shuah Khan Cc: Rodrigo Siqueira Cc: kernel test robot Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/infiniband/sw/rxe/rxe_qp.c | 3 +-- include/linux/hash.h | 5 +---- lib/test_hash.c | 24 +----------------------- tools/include/linux/hash.h | 5 +---- 4 files changed, 4 insertions(+), 33 deletions(-) (limited to 'lib') diff --git a/drivers/infiniband/sw/rxe/rxe_qp.c b/drivers/infiniband/sw/rxe/rxe_qp.c index 54b8711321c1..44c9ea601bff 100644 --- a/drivers/infiniband/sw/rxe/rxe_qp.c +++ b/drivers/infiniband/sw/rxe/rxe_qp.c @@ -217,8 +217,7 @@ static int rxe_qp_init_req(struct rxe_dev *rxe, struct rxe_qp *qp, * the port number must be in the Dynamic Ports range * (0xc000 - 0xffff). */ - qp->src_port = RXE_ROCE_V2_SPORT + - (hash_32_generic(qp_num(qp), 14) & 0x3fff); + qp->src_port = RXE_ROCE_V2_SPORT + (hash_32(qp_num(qp), 14) & 0x3fff); qp->sq.max_wr = init->cap.max_send_wr; /* These caps are limited by rxe_qp_chk_cap() done by the caller */ diff --git a/include/linux/hash.h b/include/linux/hash.h index ad6fa21d977b..38edaa08f862 100644 --- a/include/linux/hash.h +++ b/include/linux/hash.h @@ -62,10 +62,7 @@ static inline u32 __hash_32_generic(u32 val) return val * GOLDEN_RATIO_32; } -#ifndef HAVE_ARCH_HASH_32 -#define hash_32 hash_32_generic -#endif -static inline u32 hash_32_generic(u32 val, unsigned int bits) +static inline u32 hash_32(u32 val, unsigned int bits) { /* High bits are more random, so use them. */ return __hash_32(val) >> (32 - bits); diff --git a/lib/test_hash.c b/lib/test_hash.c index 0ee40b4a56dd..d4b0cfdb0377 100644 --- a/lib/test_hash.c +++ b/lib/test_hash.c @@ -94,22 +94,7 @@ test_int_hash(unsigned long long h64, u32 hash_or[2][33]) pr_err("hash_32(%#x, %d) = %#x > %#x", h0, k, h1, m); return false; } -#ifdef HAVE_ARCH_HASH_32 - h2 = hash_32_generic(h0, k); -#if HAVE_ARCH_HASH_32 == 1 - if (h1 != h2) { - pr_err("hash_32(%#x, %d) = %#x != hash_32_generic() " - " = %#x", h0, k, h1, h2); - return false; - } -#else - if (h2 > m) { - pr_err("hash_32_generic(%#x, %d) = %#x > %#x", - h0, k, h1, m); - return false; - } -#endif -#endif + /* Test hash_64 */ hash_or[1][k] |= h1 = hash_64(h64, k); if (h1 > m) { @@ -227,13 +212,6 @@ test_hash_init(void) #else pr_info("__hash_32() has no arch implementation to test."); #endif -#ifdef HAVE_ARCH_HASH_32 -#if HAVE_ARCH_HASH_32 != 1 - pr_info("hash_32() is arch-specific; not compared to generic."); -#endif -#else - pr_info("hash_32() has no arch implementation to test."); -#endif #ifdef HAVE_ARCH_HASH_64 #if HAVE_ARCH_HASH_64 != 1 pr_info("hash_64() is arch-specific; not compared to generic."); diff --git a/tools/include/linux/hash.h b/tools/include/linux/hash.h index ad6fa21d977b..38edaa08f862 100644 --- a/tools/include/linux/hash.h +++ b/tools/include/linux/hash.h @@ -62,10 +62,7 @@ static inline u32 __hash_32_generic(u32 val) return val * GOLDEN_RATIO_32; } -#ifndef HAVE_ARCH_HASH_32 -#define hash_32 hash_32_generic -#endif -static inline u32 hash_32_generic(u32 val, unsigned int bits) +static inline u32 hash_32(u32 val, unsigned int bits) { /* High bits are more random, so use them. */ return __hash_32(val) >> (32 - bits); -- cgit v1.2.3 From ae7880676bc8019ff61e49126c558ad7c4b6fa21 Mon Sep 17 00:00:00 2001 From: Isabella Basso Date: Wed, 19 Jan 2022 18:09:05 -0800 Subject: test_hash.c: split test_int_hash into arch-specific functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the test_int_hash function to keep its mainloop separate from arch-specific chunks, which are only compiled as needed. This aims at improving readability. Link: https://lkml.kernel.org/r/20211208183711.390454-3-isabbasso@riseup.net Reviewed-by: David Gow Tested-by: David Gow Signed-off-by: Isabella Basso Cc: Augusto Durães Camargo Cc: Brendan Higgins Cc: Daniel Latypov Cc: Enzo Ferreira Cc: Geert Uytterhoeven Cc: kernel test robot Cc: Rodrigo Siqueira Cc: Shuah Khan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_hash.c | 91 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 29 deletions(-) (limited to 'lib') diff --git a/lib/test_hash.c b/lib/test_hash.c index d4b0cfdb0377..2b4fe4976cc4 100644 --- a/lib/test_hash.c +++ b/lib/test_hash.c @@ -56,6 +56,58 @@ fill_buf(char *buf, size_t len, u32 seed) } } +/* Holds most testing variables for the int test. */ +struct test_hash_params { + /* Pointer to integer to be hashed. */ + unsigned long long *h64; + /* Low 32-bits of integer to be hashed. */ + u32 h0; + /* Arch-specific hash result. */ + u32 h1; + /* Generic hash result. */ + u32 h2; + /* ORed hashes of given size (in bits). */ + u32 (*hash_or)[33]; +}; + +#ifdef HAVE_ARCH__HASH_32 +static bool __init +test_int__hash_32(struct test_hash_params *params) +{ + params->hash_or[1][0] |= params->h2 = __hash_32_generic(params->h0); +#if HAVE_ARCH__HASH_32 == 1 + if (params->h1 != params->h2) { + pr_err("__hash_32(%#x) = %#x != __hash_32_generic() = %#x", + params->h0, params->h1, params->h2); + return false; + } +#endif + return true; +} +#endif + +#ifdef HAVE_ARCH_HASH_64 +static bool __init +test_int_hash_64(struct test_hash_params *params, u32 const *m, int *k) +{ + params->h2 = hash_64_generic(*params->h64, *k); +#if HAVE_ARCH_HASH_64 == 1 + if (params->h1 != params->h2) { + pr_err("hash_64(%#llx, %d) = %#x != hash_64_generic() = %#x", + *params->h64, *k, params->h1, params->h2); + return false; + } +#else + if (params->h2 > *m) { + pr_err("hash_64_generic(%#llx, %d) = %#x > %#x", + *params->h64, *k, params->h1, *m); + return false; + } +#endif + return true; +} +#endif + /* * Test the various integer hash functions. h64 (or its low-order bits) * is the integer to hash. hash_or accumulates the OR of the hash values, @@ -69,19 +121,13 @@ static bool __init test_int_hash(unsigned long long h64, u32 hash_or[2][33]) { int k; - u32 h0 = (u32)h64, h1, h2; + struct test_hash_params params = { &h64, (u32)h64, 0, 0, hash_or }; /* Test __hash32 */ - hash_or[0][0] |= h1 = __hash_32(h0); + hash_or[0][0] |= params.h1 = __hash_32(params.h0); #ifdef HAVE_ARCH__HASH_32 - hash_or[1][0] |= h2 = __hash_32_generic(h0); -#if HAVE_ARCH__HASH_32 == 1 - if (h1 != h2) { - pr_err("__hash_32(%#x) = %#x != __hash_32_generic() = %#x", - h0, h1, h2); + if (!test_int__hash_32(¶ms)) return false; - } -#endif #endif /* Test k = 1..32 bits */ @@ -89,37 +135,24 @@ test_int_hash(unsigned long long h64, u32 hash_or[2][33]) u32 const m = ((u32)2 << (k-1)) - 1; /* Low k bits set */ /* Test hash_32 */ - hash_or[0][k] |= h1 = hash_32(h0, k); - if (h1 > m) { - pr_err("hash_32(%#x, %d) = %#x > %#x", h0, k, h1, m); + hash_or[0][k] |= params.h1 = hash_32(params.h0, k); + if (params.h1 > m) { + pr_err("hash_32(%#x, %d) = %#x > %#x", params.h0, k, params.h1, m); return false; } /* Test hash_64 */ - hash_or[1][k] |= h1 = hash_64(h64, k); - if (h1 > m) { - pr_err("hash_64(%#llx, %d) = %#x > %#x", h64, k, h1, m); + hash_or[1][k] |= params.h1 = hash_64(h64, k); + if (params.h1 > m) { + pr_err("hash_64(%#llx, %d) = %#x > %#x", h64, k, params.h1, m); return false; } #ifdef HAVE_ARCH_HASH_64 - h2 = hash_64_generic(h64, k); -#if HAVE_ARCH_HASH_64 == 1 - if (h1 != h2) { - pr_err("hash_64(%#llx, %d) = %#x != hash_64_generic() " - "= %#x", h64, k, h1, h2); + if (!test_int_hash_64(¶ms, &m, &k)) return false; - } -#else - if (h2 > m) { - pr_err("hash_64_generic(%#llx, %d) = %#x > %#x", - h64, k, h1, m); - return false; - } -#endif #endif } - (void)h2; /* Suppress unused variable warning */ return true; } -- cgit v1.2.3 From 5427d3d772a77a4d67fece057064832ec5cfa078 Mon Sep 17 00:00:00 2001 From: Isabella Basso Date: Wed, 19 Jan 2022 18:09:09 -0800 Subject: test_hash.c: split test_hash_init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split up test_hash_init so that it calls each test more explicitly insofar it is possible without rewriting the entire file. This aims at improving readability. Split tests performed on string_or as they don't interfere with those performed in hash_or. Also separate pr_info calls about skipped tests as they're not part of the tests themselves, but only warn about (un)defined arch-specific hash functions. Link: https://lkml.kernel.org/r/20211208183711.390454-4-isabbasso@riseup.net Reviewed-by: David Gow Tested-by: David Gow Signed-off-by: Isabella Basso Cc: Augusto Durães Camargo Cc: Brendan Higgins Cc: Daniel Latypov Cc: Enzo Ferreira Cc: Geert Uytterhoeven Cc: kernel test robot Cc: Rodrigo Siqueira Cc: Shuah Khan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_hash.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 12 deletions(-) (limited to 'lib') diff --git a/lib/test_hash.c b/lib/test_hash.c index 2b4fe4976cc4..032849a48da7 100644 --- a/lib/test_hash.c +++ b/lib/test_hash.c @@ -158,11 +158,39 @@ test_int_hash(unsigned long long h64, u32 hash_or[2][33]) #define SIZE 256 /* Run time is cubic in SIZE */ -static int __init -test_hash_init(void) +static int __init test_string_or(void) { char buf[SIZE+1]; - u32 string_or = 0, hash_or[2][33] = { { 0, } }; + u32 string_or = 0; + int i, j; + + fill_buf(buf, SIZE, 1); + + /* Test every possible non-empty substring in the buffer. */ + for (j = SIZE; j > 0; --j) { + buf[j] = '\0'; + + for (i = 0; i <= j; i++) { + u32 h0 = full_name_hash(buf+i, buf+i, j-i); + + string_or |= h0; + } /* i */ + } /* j */ + + /* The OR of all the hash values should cover all the bits */ + if (~string_or) { + pr_err("OR of all string hash results = %#x != %#x", + string_or, -1u); + return -EINVAL; + } + + return 0; +} + +static int __init test_hash_or(void) +{ + char buf[SIZE+1]; + u32 hash_or[2][33] = { { 0, } }; unsigned tests = 0; unsigned long long h64 = 0; int i, j; @@ -192,7 +220,6 @@ test_hash_init(void) return -EINVAL; } - string_or |= h0; h64 = h64 << 32 | h0; /* For use with hash_64 */ if (!test_int_hash(h64, hash_or)) return -EINVAL; @@ -200,12 +227,6 @@ test_hash_init(void) } /* i */ } /* j */ - /* The OR of all the hash values should cover all the bits */ - if (~string_or) { - pr_err("OR of all string hash results = %#x != %#x", - string_or, -1u); - return -EINVAL; - } if (~hash_or[0][0]) { pr_err("OR of all __hash_32 results = %#x != %#x", hash_or[0][0], -1u); @@ -237,6 +258,13 @@ test_hash_init(void) } } + pr_notice("%u tests passed.", tests); + + return 0; +} + +static void __init notice_skipped_tests(void) +{ /* Issue notices about skipped tests. */ #ifdef HAVE_ARCH__HASH_32 #if HAVE_ARCH__HASH_32 != 1 @@ -252,10 +280,24 @@ test_hash_init(void) #else pr_info("hash_64() has no arch implementation to test."); #endif +} - pr_notice("%u tests passed.", tests); +static int __init +test_hash_init(void) +{ + int ret; - return 0; + ret = test_string_or(); + if (ret < 0) + return ret; + + ret = test_hash_or(); + if (ret < 0) + return ret; + + notice_skipped_tests(); + + return ret; } static void __exit test_hash_exit(void) -- cgit v1.2.3 From 88168bf35c5260013daab4bddf944cd557cb6f08 Mon Sep 17 00:00:00 2001 From: Isabella Basso Date: Wed, 19 Jan 2022 18:09:12 -0800 Subject: lib/Kconfig.debug: properly split hash test kernel entries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split TEST_HASH so that each entry only has one file. Note that there's no stringhash test file, but actually tests are performed in lib/test_hash.c. Link: https://lkml.kernel.org/r/20211208183711.390454-5-isabbasso@riseup.net Reviewed-by: David Gow Tested-by: David Gow Signed-off-by: Isabella Basso Cc: Augusto Durães Camargo Cc: Brendan Higgins Cc: Daniel Latypov Cc: Enzo Ferreira Cc: Geert Uytterhoeven Cc: kernel test robot Cc: Rodrigo Siqueira Cc: Shuah Khan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.debug | 14 +++++++++++--- lib/Makefile | 3 ++- 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 5e14e32056ad..f27de2050ca0 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2210,9 +2210,17 @@ config TEST_RHASHTABLE config TEST_HASH tristate "Perform selftest on hash functions" help - Enable this option to test the kernel's integer (), - string (), and siphash () - hash functions on boot (or module load). + Enable this option to test the kernel's integer (), and + string () hash functions on boot (or module load). + + This is intended to help people writing architecture-specific + optimized versions. If unsure, say N. + +config TEST_SIPHASH + tristate "Perform selftest on siphash functions" + help + Enable this option to test the kernel's siphash () hash + functions on boot (or module load). This is intended to help people writing architecture-specific optimized versions. If unsure, say N. diff --git a/lib/Makefile b/lib/Makefile index 364c23f15578..f3a2a251471d 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -61,7 +61,8 @@ obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o obj-$(CONFIG_TEST_BITOPS) += test_bitops.o CFLAGS_test_bitops.o += -Werror obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o -obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o +obj-$(CONFIG_TEST_SIPHASH) += test_siphash.o +obj-$(CONFIG_TEST_HASH) += test_hash.o obj-$(CONFIG_TEST_IDA) += test_ida.o obj-$(CONFIG_KASAN_KUNIT_TEST) += test_kasan.o CFLAGS_test_kasan.o += -fno-builtin -- cgit v1.2.3 From 0acc968f352336a459f27ba1f23745a174933c9c Mon Sep 17 00:00:00 2001 From: Isabella Basso Date: Wed, 19 Jan 2022 18:09:15 -0800 Subject: test_hash.c: refactor into kunit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use KUnit framework to make tests more easily integrable with CIs. Even though these tests are not yet properly written as unit tests this change should help in debugging. Also remove kernel messages (i.e. through pr_info) as KUnit handles all debugging output and let it handle module init and exit details. Link: https://lkml.kernel.org/r/20211208183711.390454-6-isabbasso@riseup.net Reviewed-by: David Gow Reported-by: kernel test robot Tested-by: David Gow Co-developed-by: Augusto Durães Camargo Signed-off-by: Augusto Durães Camargo Co-developed-by: Enzo Ferreira Signed-off-by: Enzo Ferreira Signed-off-by: Isabella Basso Cc: Brendan Higgins Cc: Daniel Latypov Cc: Geert Uytterhoeven Cc: Rodrigo Siqueira Cc: Shuah Khan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.debug | 28 +++++--- lib/Makefile | 2 +- lib/test_hash.c | 194 +++++++++++++++++------------------------------------- 3 files changed, 81 insertions(+), 143 deletions(-) (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index f27de2050ca0..a789da4a19a1 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2207,15 +2207,6 @@ config TEST_RHASHTABLE If unsure, say N. -config TEST_HASH - tristate "Perform selftest on hash functions" - help - Enable this option to test the kernel's integer (), and - string () hash functions on boot (or module load). - - This is intended to help people writing architecture-specific - optimized versions. If unsure, say N. - config TEST_SIPHASH tristate "Perform selftest on siphash functions" help @@ -2364,6 +2355,25 @@ config BITFIELD_KUNIT If unsure, say N. +config HASH_KUNIT_TEST + tristate "KUnit Test for integer hash functions" if !KUNIT_ALL_TESTS + depends on KUNIT + default KUNIT_ALL_TESTS + help + Enable this option to test the kernel's string (), and + integer () hash functions on boot. + + KUnit tests run during boot and output the results to the debug log + in TAP format (https://testanything.org/). Only useful for kernel devs + running the KUnit test harness, and not intended for inclusion into a + production build. + + For more information on KUnit and unit tests in general please refer + to the KUnit documentation in Documentation/dev-tools/kunit/. + + This is intended to help people writing architecture-specific + optimized versions. If unsure, say N. + config RESOURCE_KUNIT_TEST tristate "KUnit test for resource API" depends on KUNIT diff --git a/lib/Makefile b/lib/Makefile index f3a2a251471d..511c27827701 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -62,7 +62,7 @@ obj-$(CONFIG_TEST_BITOPS) += test_bitops.o CFLAGS_test_bitops.o += -Werror obj-$(CONFIG_TEST_SYSCTL) += test_sysctl.o obj-$(CONFIG_TEST_SIPHASH) += test_siphash.o -obj-$(CONFIG_TEST_HASH) += test_hash.o +obj-$(CONFIG_HASH_KUNIT_TEST) += test_hash.o obj-$(CONFIG_TEST_IDA) += test_ida.o obj-$(CONFIG_KASAN_KUNIT_TEST) += test_kasan.o CFLAGS_test_kasan.o += -fno-builtin diff --git a/lib/test_hash.c b/lib/test_hash.c index 032849a48da7..bb25fda34794 100644 --- a/lib/test_hash.c +++ b/lib/test_hash.c @@ -14,17 +14,15 @@ * and hash_64(). */ -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt "\n" - #include #include #include #include #include -#include +#include /* 32-bit XORSHIFT generator. Seed must not be zero. */ -static u32 __init __attribute_const__ +static u32 __attribute_const__ xorshift(u32 seed) { seed ^= seed << 13; @@ -34,7 +32,7 @@ xorshift(u32 seed) } /* Given a non-zero x, returns a non-zero byte. */ -static u8 __init __attribute_const__ +static u8 __attribute_const__ mod255(u32 x) { x = (x & 0xffff) + (x >> 16); /* 1 <= x <= 0x1fffe */ @@ -45,8 +43,7 @@ mod255(u32 x) } /* Fill the buffer with non-zero bytes. */ -static void __init -fill_buf(char *buf, size_t len, u32 seed) +static void fill_buf(char *buf, size_t len, u32 seed) { size_t i; @@ -71,40 +68,32 @@ struct test_hash_params { }; #ifdef HAVE_ARCH__HASH_32 -static bool __init -test_int__hash_32(struct test_hash_params *params) +static void +test_int__hash_32(struct kunit *test, struct test_hash_params *params) { params->hash_or[1][0] |= params->h2 = __hash_32_generic(params->h0); #if HAVE_ARCH__HASH_32 == 1 - if (params->h1 != params->h2) { - pr_err("__hash_32(%#x) = %#x != __hash_32_generic() = %#x", - params->h0, params->h1, params->h2); - return false; - } + KUNIT_EXPECT_EQ_MSG(test, params->h1, params->h2, + "__hash_32(%#x) = %#x != __hash_32_generic() = %#x", + params->h0, params->h1, params->h2); #endif - return true; } #endif #ifdef HAVE_ARCH_HASH_64 -static bool __init -test_int_hash_64(struct test_hash_params *params, u32 const *m, int *k) +static void +test_int_hash_64(struct kunit *test, struct test_hash_params *params, u32 const *m, int *k) { params->h2 = hash_64_generic(*params->h64, *k); #if HAVE_ARCH_HASH_64 == 1 - if (params->h1 != params->h2) { - pr_err("hash_64(%#llx, %d) = %#x != hash_64_generic() = %#x", - *params->h64, *k, params->h1, params->h2); - return false; - } + KUNIT_EXPECT_EQ_MSG(test, params->h1, params->h2, + "hash_64(%#llx, %d) = %#x != hash_64_generic() = %#x", + *params->h64, *k, params->h1, params->h2); #else - if (params->h2 > *m) { - pr_err("hash_64_generic(%#llx, %d) = %#x > %#x", - *params->h64, *k, params->h1, *m); - return false; - } + KUNIT_EXPECT_LE_MSG(test, params->h1, params->h2, + "hash_64_generic(%#llx, %d) = %#x > %#x", + *params->h64, *k, params->h1, *m); #endif - return true; } #endif @@ -117,8 +106,8 @@ test_int_hash_64(struct test_hash_params *params, u32 const *m, int *k) * inline, the code being tested is actually in the module, and you can * recompile and re-test the module without rebooting. */ -static bool __init -test_int_hash(unsigned long long h64, u32 hash_or[2][33]) +static void +test_int_hash(struct kunit *test, unsigned long long h64, u32 hash_or[2][33]) { int k; struct test_hash_params params = { &h64, (u32)h64, 0, 0, hash_or }; @@ -126,8 +115,7 @@ test_int_hash(unsigned long long h64, u32 hash_or[2][33]) /* Test __hash32 */ hash_or[0][0] |= params.h1 = __hash_32(params.h0); #ifdef HAVE_ARCH__HASH_32 - if (!test_int__hash_32(¶ms)) - return false; + test_int__hash_32(test, ¶ms); #endif /* Test k = 1..32 bits */ @@ -136,29 +124,24 @@ test_int_hash(unsigned long long h64, u32 hash_or[2][33]) /* Test hash_32 */ hash_or[0][k] |= params.h1 = hash_32(params.h0, k); - if (params.h1 > m) { - pr_err("hash_32(%#x, %d) = %#x > %#x", params.h0, k, params.h1, m); - return false; - } + KUNIT_EXPECT_LE_MSG(test, params.h1, m, + "hash_32(%#x, %d) = %#x > %#x", + params.h0, k, params.h1, m); /* Test hash_64 */ hash_or[1][k] |= params.h1 = hash_64(h64, k); - if (params.h1 > m) { - pr_err("hash_64(%#llx, %d) = %#x > %#x", h64, k, params.h1, m); - return false; - } + KUNIT_EXPECT_LE_MSG(test, params.h1, m, + "hash_64(%#llx, %d) = %#x > %#x", + h64, k, params.h1, m); #ifdef HAVE_ARCH_HASH_64 - if (!test_int_hash_64(¶ms, &m, &k)) - return false; + test_int_hash_64(test, ¶ms, &m, &k); #endif } - - return true; } #define SIZE 256 /* Run time is cubic in SIZE */ -static int __init test_string_or(void) +static void test_string_or(struct kunit *test) { char buf[SIZE+1]; u32 string_or = 0; @@ -178,20 +161,15 @@ static int __init test_string_or(void) } /* j */ /* The OR of all the hash values should cover all the bits */ - if (~string_or) { - pr_err("OR of all string hash results = %#x != %#x", - string_or, -1u); - return -EINVAL; - } - - return 0; + KUNIT_EXPECT_EQ_MSG(test, string_or, -1u, + "OR of all string hash results = %#x != %#x", + string_or, -1u); } -static int __init test_hash_or(void) +static void test_hash_or(struct kunit *test) { char buf[SIZE+1]; u32 hash_or[2][33] = { { 0, } }; - unsigned tests = 0; unsigned long long h64 = 0; int i, j; @@ -206,39 +184,27 @@ static int __init test_hash_or(void) u32 h0 = full_name_hash(buf+i, buf+i, j-i); /* Check that hashlen_string gets the length right */ - if (hashlen_len(hashlen) != j-i) { - pr_err("hashlen_string(%d..%d) returned length" - " %u, expected %d", - i, j, hashlen_len(hashlen), j-i); - return -EINVAL; - } + KUNIT_EXPECT_EQ_MSG(test, hashlen_len(hashlen), j-i, + "hashlen_string(%d..%d) returned length %u, expected %d", + i, j, hashlen_len(hashlen), j-i); /* Check that the hashes match */ - if (hashlen_hash(hashlen) != h0) { - pr_err("hashlen_string(%d..%d) = %08x != " - "full_name_hash() = %08x", - i, j, hashlen_hash(hashlen), h0); - return -EINVAL; - } + KUNIT_EXPECT_EQ_MSG(test, hashlen_hash(hashlen), h0, + "hashlen_string(%d..%d) = %08x != full_name_hash() = %08x", + i, j, hashlen_hash(hashlen), h0); h64 = h64 << 32 | h0; /* For use with hash_64 */ - if (!test_int_hash(h64, hash_or)) - return -EINVAL; - tests++; + test_int_hash(test, h64, hash_or); } /* i */ } /* j */ - if (~hash_or[0][0]) { - pr_err("OR of all __hash_32 results = %#x != %#x", - hash_or[0][0], -1u); - return -EINVAL; - } + KUNIT_EXPECT_EQ_MSG(test, hash_or[0][0], -1u, + "OR of all __hash_32 results = %#x != %#x", + hash_or[0][0], -1u); #ifdef HAVE_ARCH__HASH_32 #if HAVE_ARCH__HASH_32 != 1 /* Test is pointless if results match */ - if (~hash_or[1][0]) { - pr_err("OR of all __hash_32_generic results = %#x != %#x", - hash_or[1][0], -1u); - return -EINVAL; - } + KUNIT_EXPECT_EQ_MSG(test, hash_or[1][0], -1u, + "OR of all __hash_32_generic results = %#x != %#x", + hash_or[1][0], -1u); #endif #endif @@ -246,65 +212,27 @@ static int __init test_hash_or(void) for (i = 1; i <= 32; i++) { u32 const m = ((u32)2 << (i-1)) - 1; /* Low i bits set */ - if (hash_or[0][i] != m) { - pr_err("OR of all hash_32(%d) results = %#x " - "(%#x expected)", i, hash_or[0][i], m); - return -EINVAL; - } - if (hash_or[1][i] != m) { - pr_err("OR of all hash_64(%d) results = %#x " - "(%#x expected)", i, hash_or[1][i], m); - return -EINVAL; - } + KUNIT_EXPECT_EQ_MSG(test, hash_or[0][i], m, + "OR of all hash_32(%d) results = %#x (%#x expected)", + i, hash_or[0][i], m); + KUNIT_EXPECT_EQ_MSG(test, hash_or[1][i], m, + "OR of all hash_64(%d) results = %#x (%#x expected)", + i, hash_or[1][i], m); } - - pr_notice("%u tests passed.", tests); - - return 0; } -static void __init notice_skipped_tests(void) -{ - /* Issue notices about skipped tests. */ -#ifdef HAVE_ARCH__HASH_32 -#if HAVE_ARCH__HASH_32 != 1 - pr_info("__hash_32() is arch-specific; not compared to generic."); -#endif -#else - pr_info("__hash_32() has no arch implementation to test."); -#endif -#ifdef HAVE_ARCH_HASH_64 -#if HAVE_ARCH_HASH_64 != 1 - pr_info("hash_64() is arch-specific; not compared to generic."); -#endif -#else - pr_info("hash_64() has no arch implementation to test."); -#endif -} - -static int __init -test_hash_init(void) -{ - int ret; - - ret = test_string_or(); - if (ret < 0) - return ret; - - ret = test_hash_or(); - if (ret < 0) - return ret; - - notice_skipped_tests(); +static struct kunit_case hash_test_cases[] __refdata = { + KUNIT_CASE(test_string_or), + KUNIT_CASE(test_hash_or), + {} +}; - return ret; -} +static struct kunit_suite hash_test_suite = { + .name = "hash", + .test_cases = hash_test_cases, +}; -static void __exit test_hash_exit(void) -{ -} -module_init(test_hash_init); /* Does everything */ -module_exit(test_hash_exit); /* Does nothing */ +kunit_test_suite(hash_test_suite); MODULE_LICENSE("GPL"); -- cgit v1.2.3 From e073e5ef90298d2d6e5e7f04b545a0815e92110c Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Wed, 19 Jan 2022 18:09:28 -0800 Subject: lib/test_meminit: destroy cache in kmem_cache_alloc_bulk() test Make do_kmem_cache_size_bulk() destroy the cache it creates. Link: https://lkml.kernel.org/r/aced20a94bf04159a139f0846e41d38a1537debb.1640018297.git.andreyknvl@google.com Fixes: 03a9349ac0e0 ("lib/test_meminit: add a kmem_cache_alloc_bulk() test") Signed-off-by: Andrey Konovalov Reviewed-by: Marco Elver Cc: Alexander Potapenko Cc: Dmitry Vyukov Cc: Andrey Ryabinin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_meminit.c | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/test_meminit.c b/lib/test_meminit.c index e4f706a404b3..3ca717f11397 100644 --- a/lib/test_meminit.c +++ b/lib/test_meminit.c @@ -337,6 +337,7 @@ static int __init do_kmem_cache_size_bulk(int size, int *total_failures) if (num) kmem_cache_free_bulk(c, num, objects); } + kmem_cache_destroy(c); *total_failures += fail; return 1; } -- cgit v1.2.3 From bbd2e05fad3e692ff2495895975bd0fce02bdbae Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Wed, 19 Jan 2022 18:10:28 -0800 Subject: lib/Kconfig.debug: make TEST_KMOD depend on PAGE_SIZE_LESS_THAN_256KB Commit b05fbcc36be1 ("btrfs: disable build on platforms having page size 256K") disabled btrfs for configurations that used a 256kB page size. However, it did not fully solve the problem because CONFIG_TEST_KMOD selects CONFIG_BTRFS, which does not account for the dependency. This results in a Kconfig warning and the failed BUILD_BUG_ON error returning. WARNING: unmet direct dependencies detected for BTRFS_FS Depends on [n]: BLOCK [=y] && !PPC_256K_PAGES && !PAGE_SIZE_256KB [=y] Selected by [m]: - TEST_KMOD [=m] && RUNTIME_TESTING_MENU [=y] && m && MODULES [=y] && NETDEVICES [=y] && NET_CORE [=y] && INET [=y] && BLOCK [=y] To resolve this, add CONFIG_PAGE_SIZE_LESS_THAN_256KB as a dependency of CONFIG_TEST_KMOD so there is no more invalid configuration or build errors. Link: https://lkml.kernel.org/r/20211129230141.228085-4-nathan@kernel.org Fixes: b05fbcc36be1 ("btrfs: disable build on platforms having page size 256K") Signed-off-by: Nathan Chancellor Reported-by: kernel test robot Cc: Chris Mason Cc: David Sterba Cc: Josef Bacik Cc: Luis Chamberlain Cc: Nick Desaulniers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.debug | 1 + 1 file changed, 1 insertion(+) (limited to 'lib') diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index a789da4a19a1..666e070feeb6 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2505,6 +2505,7 @@ config TEST_KMOD depends on m depends on NETDEVICES && NET_CORE && INET # for TUN depends on BLOCK + depends on PAGE_SIZE_LESS_THAN_256KB # for BTRFS select TEST_LKM select XFS_FS select TUN -- cgit v1.2.3 From bece04b5b41dd7730dd06aec0d6b15c53d1fbb5a Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Wed, 19 Jan 2022 18:10:31 -0800 Subject: kcov: fix generic Kconfig dependencies if ARCH_WANTS_NO_INSTR Until recent versions of GCC and Clang, it was not possible to disable KCOV instrumentation via a function attribute. The relevant function attribute was introduced in 540540d06e9d9 ("kcov: add __no_sanitize_coverage to fix noinstr for all architectures"). x86 was the first architecture to want a working noinstr, and at the time no compiler support for the attribute existed yet. Therefore, commit 0f1441b44e823 ("objtool: Fix noinstr vs KCOV") introduced the ability to NOP __sanitizer_cov_*() calls in .noinstr.text. However, this doesn't work for other architectures like arm64 and s390 that want a working noinstr per ARCH_WANTS_NO_INSTR. At the time of 0f1441b44e823, we didn't yet have ARCH_WANTS_NO_INSTR, but now we can move the Kconfig dependency checks to the generic KCOV option. KCOV will be available if: - architecture does not care about noinstr, OR - we have objtool support (like on x86), OR - GCC is 12.0 or newer, OR - Clang is 13.0 or newer. Link: https://lkml.kernel.org/r/20211201152604.3984495-1-elver@google.com Signed-off-by: Marco Elver Reviewed-by: Nathan Chancellor Acked-by: Peter Zijlstra (Intel) Cc: Mark Rutland Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: H. Peter Anvin Cc: Nick Desaulniers Cc: Dmitry Vyukov Cc: Andrey Konovalov Cc: Catalin Marinas Cc: Will Deacon Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86/Kconfig | 2 +- lib/Kconfig.debug | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'lib') diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1275bab8be2c..f79a063d8ea3 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -78,7 +78,7 @@ config X86 select ARCH_HAS_FILTER_PGPROT select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_GCOV_PROFILE_ALL - select ARCH_HAS_KCOV if X86_64 && STACK_VALIDATION + select ARCH_HAS_KCOV if X86_64 select ARCH_HAS_MEM_ENCRYPT select ARCH_HAS_MEMBARRIER_SYNC_CORE select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 666e070feeb6..1a5d168c388b 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1979,6 +1979,8 @@ config KCOV bool "Code coverage for fuzzing" depends on ARCH_HAS_KCOV depends on CC_HAS_SANCOV_TRACE_PC || GCC_PLUGINS + depends on !ARCH_WANTS_NO_INSTR || STACK_VALIDATION || \ + GCC_VERSION >= 120000 || CLANG_VERSION >= 130000 select DEBUG_FS select GCC_PLUGIN_SANCOV if !CC_HAS_SANCOV_TRACE_PC help -- cgit v1.2.3 From 69d0db01e210e07fe915e5da91b54a867cda040f Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Wed, 19 Jan 2022 18:10:35 -0800 Subject: ubsan: remove CONFIG_UBSAN_OBJECT_SIZE The object-size sanitizer is redundant to -Warray-bounds, and inappropriately performs its checks at run-time when all information needed for the evaluation is available at compile-time, making it quite difficult to use: https://bugzilla.kernel.org/show_bug.cgi?id=214861 With -Warray-bounds almost enabled globally, it doesn't make sense to keep this around. Link: https://lkml.kernel.org/r/20211203235346.110809-1-keescook@chromium.org Signed-off-by: Kees Cook Reviewed-by: Marco Elver Cc: Masahiro Yamada Cc: Michal Marek Cc: Nick Desaulniers Cc: Nathan Chancellor Cc: Andrey Ryabinin Cc: "Peter Zijlstra (Intel)" Cc: Stephen Rothwell Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.ubsan | 13 ------------- lib/test_ubsan.c | 22 ---------------------- scripts/Makefile.ubsan | 1 - 3 files changed, 36 deletions(-) (limited to 'lib') diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan index e5372a13511d..236c5cefc4cc 100644 --- a/lib/Kconfig.ubsan +++ b/lib/Kconfig.ubsan @@ -112,19 +112,6 @@ config UBSAN_UNREACHABLE This option enables -fsanitize=unreachable which checks for control flow reaching an expected-to-be-unreachable position. -config UBSAN_OBJECT_SIZE - bool "Perform checking for accesses beyond the end of objects" - default UBSAN - # gcc hugely expands stack usage with -fsanitize=object-size - # https://lore.kernel.org/lkml/CAHk-=wjPasyJrDuwDnpHJS2TuQfExwe=px-SzLeN8GFMAQJPmQ@mail.gmail.com/ - depends on !CC_IS_GCC - depends on $(cc-option,-fsanitize=object-size) - help - This option enables -fsanitize=object-size which checks for accesses - beyond the end of objects where the optimizer can determine both the - object being operated on and its size, usually seen with bad downcasts, - or access to struct members from NULL pointers. - config UBSAN_BOOL bool "Perform checking for non-boolean values used as boolean" default UBSAN diff --git a/lib/test_ubsan.c b/lib/test_ubsan.c index 7e7bbd0f3fd2..2062be1f2e80 100644 --- a/lib/test_ubsan.c +++ b/lib/test_ubsan.c @@ -79,15 +79,6 @@ static void test_ubsan_load_invalid_value(void) eval2 = eval; } -static void test_ubsan_null_ptr_deref(void) -{ - volatile int *ptr = NULL; - int val; - - UBSAN_TEST(CONFIG_UBSAN_OBJECT_SIZE); - val = *ptr; -} - static void test_ubsan_misaligned_access(void) { volatile char arr[5] __aligned(4) = {1, 2, 3, 4, 5}; @@ -98,29 +89,16 @@ static void test_ubsan_misaligned_access(void) *ptr = val; } -static void test_ubsan_object_size_mismatch(void) -{ - /* "((aligned(8)))" helps this not into be misaligned for ptr-access. */ - volatile int val __aligned(8) = 4; - volatile long long *ptr, val2; - - UBSAN_TEST(CONFIG_UBSAN_OBJECT_SIZE); - ptr = (long long *)&val; - val2 = *ptr; -} - static const test_ubsan_fp test_ubsan_array[] = { test_ubsan_shift_out_of_bounds, test_ubsan_out_of_bounds, test_ubsan_load_invalid_value, test_ubsan_misaligned_access, - test_ubsan_object_size_mismatch, }; /* Excluded because they Oops the module. */ static const test_ubsan_fp skip_ubsan_array[] = { test_ubsan_divrem_overflow, - test_ubsan_null_ptr_deref, }; static int __init test_ubsan_init(void) diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan index 9e2092fd5206..7099c603ff0a 100644 --- a/scripts/Makefile.ubsan +++ b/scripts/Makefile.ubsan @@ -8,7 +8,6 @@ ubsan-cflags-$(CONFIG_UBSAN_LOCAL_BOUNDS) += -fsanitize=local-bounds ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift ubsan-cflags-$(CONFIG_UBSAN_DIV_ZERO) += -fsanitize=integer-divide-by-zero ubsan-cflags-$(CONFIG_UBSAN_UNREACHABLE) += -fsanitize=unreachable -ubsan-cflags-$(CONFIG_UBSAN_OBJECT_SIZE) += -fsanitize=object-size ubsan-cflags-$(CONFIG_UBSAN_BOOL) += -fsanitize=bool ubsan-cflags-$(CONFIG_UBSAN_ENUM) += -fsanitize=enum ubsan-cflags-$(CONFIG_UBSAN_TRAP) += -fsanitize-undefined-trap-on-error -- cgit v1.2.3 From b1e78ef3be2533973953a35a56739fda7325875c Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 19 Jan 2022 18:10:38 -0800 Subject: lib: remove redundant assignment to variable ret The variable ret is being assigned a value that is never read. If the for-loop is entered then ret is immediately re-assigned a new value. If the for-loop is not executed ret is never read. The assignment is redundant and can be removed. Link: https://lkml.kernel.org/r/20211230134557.83633-1-colin.i.king@gmail.com Signed-off-by: Colin Ian King Reviewed-by: Jarkko Sakkinen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/asn1_encoder.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'lib') diff --git a/lib/asn1_encoder.c b/lib/asn1_encoder.c index 27bbe891714f..0fd3c454a468 100644 --- a/lib/asn1_encoder.c +++ b/lib/asn1_encoder.c @@ -164,8 +164,6 @@ asn1_encode_oid(unsigned char *data, const unsigned char *end_data, data_len -= 3; - ret = 0; - for (i = 2; i < oid_len; i++) { ret = asn1_encode_oid_digit(&d, &data_len, oid[i]); if (ret < 0) -- cgit v1.2.3