aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig.debug8
-rw-r--r--lib/Makefile1
-rw-r--r--lib/ioremap.c11
-rw-r--r--lib/mpi/longlong.h16
-rw-r--r--lib/rbtree.c40
-rw-r--r--lib/string.c11
-rw-r--r--lib/string_helpers.c77
-rw-r--r--lib/test_meminit.c364
-rw-r--r--lib/test_overflow.c11
-rw-r--r--lib/test_string.c83
10 files changed, 531 insertions, 91 deletions
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index a858b55e8ac7..bc6673ab3a08 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2076,6 +2076,14 @@ config TEST_STACKINIT
2076 2076
2077 If unsure, say N. 2077 If unsure, say N.
2078 2078
2079config TEST_MEMINIT
2080 tristate "Test heap/page initialization"
2081 help
2082 Test if the kernel is zero-initializing heap and page allocations.
2083 This can be useful to test init_on_alloc and init_on_free features.
2084
2085 If unsure, say N.
2086
2079endif # RUNTIME_TESTING_MENU 2087endif # RUNTIME_TESTING_MENU
2080 2088
2081config MEMTEST 2089config MEMTEST
diff --git a/lib/Makefile b/lib/Makefile
index fdd56bc219b8..59067f51f3ab 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -92,6 +92,7 @@ obj-$(CONFIG_TEST_MEMCAT_P) += test_memcat_p.o
92obj-$(CONFIG_TEST_OBJAGG) += test_objagg.o 92obj-$(CONFIG_TEST_OBJAGG) += test_objagg.o
93obj-$(CONFIG_TEST_STACKINIT) += test_stackinit.o 93obj-$(CONFIG_TEST_STACKINIT) += test_stackinit.o
94obj-$(CONFIG_TEST_BLACKHOLE_DEV) += test_blackhole_dev.o 94obj-$(CONFIG_TEST_BLACKHOLE_DEV) += test_blackhole_dev.o
95obj-$(CONFIG_TEST_MEMINIT) += test_meminit.o
95 96
96obj-$(CONFIG_TEST_LIVEPATCH) += livepatch/ 97obj-$(CONFIG_TEST_LIVEPATCH) += livepatch/
97 98
diff --git a/lib/ioremap.c b/lib/ioremap.c
index 063213685563..0a2ffadc6d71 100644
--- a/lib/ioremap.c
+++ b/lib/ioremap.c
@@ -30,6 +30,8 @@ early_param("nohugeiomap", set_nohugeiomap);
30void __init ioremap_huge_init(void) 30void __init ioremap_huge_init(void)
31{ 31{
32 if (!ioremap_huge_disabled) { 32 if (!ioremap_huge_disabled) {
33 if (arch_ioremap_p4d_supported())
34 ioremap_p4d_capable = 1;
33 if (arch_ioremap_pud_supported()) 35 if (arch_ioremap_pud_supported())
34 ioremap_pud_capable = 1; 36 ioremap_pud_capable = 1;
35 if (arch_ioremap_pmd_supported()) 37 if (arch_ioremap_pmd_supported())
@@ -86,6 +88,9 @@ static int ioremap_try_huge_pmd(pmd_t *pmd, unsigned long addr,
86 if ((end - addr) != PMD_SIZE) 88 if ((end - addr) != PMD_SIZE)
87 return 0; 89 return 0;
88 90
91 if (!IS_ALIGNED(addr, PMD_SIZE))
92 return 0;
93
89 if (!IS_ALIGNED(phys_addr, PMD_SIZE)) 94 if (!IS_ALIGNED(phys_addr, PMD_SIZE))
90 return 0; 95 return 0;
91 96
@@ -126,6 +131,9 @@ static int ioremap_try_huge_pud(pud_t *pud, unsigned long addr,
126 if ((end - addr) != PUD_SIZE) 131 if ((end - addr) != PUD_SIZE)
127 return 0; 132 return 0;
128 133
134 if (!IS_ALIGNED(addr, PUD_SIZE))
135 return 0;
136
129 if (!IS_ALIGNED(phys_addr, PUD_SIZE)) 137 if (!IS_ALIGNED(phys_addr, PUD_SIZE))
130 return 0; 138 return 0;
131 139
@@ -166,6 +174,9 @@ static int ioremap_try_huge_p4d(p4d_t *p4d, unsigned long addr,
166 if ((end - addr) != P4D_SIZE) 174 if ((end - addr) != P4D_SIZE)
167 return 0; 175 return 0;
168 176
177 if (!IS_ALIGNED(addr, P4D_SIZE))
178 return 0;
179
169 if (!IS_ALIGNED(phys_addr, P4D_SIZE)) 180 if (!IS_ALIGNED(phys_addr, P4D_SIZE))
170 return 0; 181 return 0;
171 182
diff --git a/lib/mpi/longlong.h b/lib/mpi/longlong.h
index 08c60d10747f..3bb6260d8f42 100644
--- a/lib/mpi/longlong.h
+++ b/lib/mpi/longlong.h
@@ -397,8 +397,8 @@ do { \
397#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ 397#define add_ssaaaa(sh, sl, ah, al, bh, bl) \
398 __asm__ ("addl %5,%1\n" \ 398 __asm__ ("addl %5,%1\n" \
399 "adcl %3,%0" \ 399 "adcl %3,%0" \
400 : "=r" ((USItype)(sh)), \ 400 : "=r" (sh), \
401 "=&r" ((USItype)(sl)) \ 401 "=&r" (sl) \
402 : "%0" ((USItype)(ah)), \ 402 : "%0" ((USItype)(ah)), \
403 "g" ((USItype)(bh)), \ 403 "g" ((USItype)(bh)), \
404 "%1" ((USItype)(al)), \ 404 "%1" ((USItype)(al)), \
@@ -406,22 +406,22 @@ do { \
406#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ 406#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
407 __asm__ ("subl %5,%1\n" \ 407 __asm__ ("subl %5,%1\n" \
408 "sbbl %3,%0" \ 408 "sbbl %3,%0" \
409 : "=r" ((USItype)(sh)), \ 409 : "=r" (sh), \
410 "=&r" ((USItype)(sl)) \ 410 "=&r" (sl) \
411 : "0" ((USItype)(ah)), \ 411 : "0" ((USItype)(ah)), \
412 "g" ((USItype)(bh)), \ 412 "g" ((USItype)(bh)), \
413 "1" ((USItype)(al)), \ 413 "1" ((USItype)(al)), \
414 "g" ((USItype)(bl))) 414 "g" ((USItype)(bl)))
415#define umul_ppmm(w1, w0, u, v) \ 415#define umul_ppmm(w1, w0, u, v) \
416 __asm__ ("mull %3" \ 416 __asm__ ("mull %3" \
417 : "=a" ((USItype)(w0)), \ 417 : "=a" (w0), \
418 "=d" ((USItype)(w1)) \ 418 "=d" (w1) \
419 : "%0" ((USItype)(u)), \ 419 : "%0" ((USItype)(u)), \
420 "rm" ((USItype)(v))) 420 "rm" ((USItype)(v)))
421#define udiv_qrnnd(q, r, n1, n0, d) \ 421#define udiv_qrnnd(q, r, n1, n0, d) \
422 __asm__ ("divl %4" \ 422 __asm__ ("divl %4" \
423 : "=a" ((USItype)(q)), \ 423 : "=a" (q), \
424 "=d" ((USItype)(r)) \ 424 "=d" (r) \
425 : "0" ((USItype)(n0)), \ 425 : "0" ((USItype)(n0)), \
426 "1" ((USItype)(n1)), \ 426 "1" ((USItype)(n1)), \
427 "rm" ((USItype)(d))) 427 "rm" ((USItype)(d)))
diff --git a/lib/rbtree.c b/lib/rbtree.c
index 1ef6e25d031c..abc86c6a3177 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -83,14 +83,10 @@ __rb_rotate_set_parents(struct rb_node *old, struct rb_node *new,
83 83
84static __always_inline void 84static __always_inline void
85__rb_insert(struct rb_node *node, struct rb_root *root, 85__rb_insert(struct rb_node *node, struct rb_root *root,
86 bool newleft, struct rb_node **leftmost,
87 void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 86 void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
88{ 87{
89 struct rb_node *parent = rb_red_parent(node), *gparent, *tmp; 88 struct rb_node *parent = rb_red_parent(node), *gparent, *tmp;
90 89
91 if (newleft)
92 *leftmost = node;
93
94 while (true) { 90 while (true) {
95 /* 91 /*
96 * Loop invariant: node is red. 92 * Loop invariant: node is red.
@@ -437,38 +433,19 @@ static const struct rb_augment_callbacks dummy_callbacks = {
437 433
438void rb_insert_color(struct rb_node *node, struct rb_root *root) 434void rb_insert_color(struct rb_node *node, struct rb_root *root)
439{ 435{
440 __rb_insert(node, root, false, NULL, dummy_rotate); 436 __rb_insert(node, root, dummy_rotate);
441} 437}
442EXPORT_SYMBOL(rb_insert_color); 438EXPORT_SYMBOL(rb_insert_color);
443 439
444void rb_erase(struct rb_node *node, struct rb_root *root) 440void rb_erase(struct rb_node *node, struct rb_root *root)
445{ 441{
446 struct rb_node *rebalance; 442 struct rb_node *rebalance;
447 rebalance = __rb_erase_augmented(node, root, 443 rebalance = __rb_erase_augmented(node, root, &dummy_callbacks);
448 NULL, &dummy_callbacks);
449 if (rebalance) 444 if (rebalance)
450 ____rb_erase_color(rebalance, root, dummy_rotate); 445 ____rb_erase_color(rebalance, root, dummy_rotate);
451} 446}
452EXPORT_SYMBOL(rb_erase); 447EXPORT_SYMBOL(rb_erase);
453 448
454void rb_insert_color_cached(struct rb_node *node,
455 struct rb_root_cached *root, bool leftmost)
456{
457 __rb_insert(node, &root->rb_root, leftmost,
458 &root->rb_leftmost, dummy_rotate);
459}
460EXPORT_SYMBOL(rb_insert_color_cached);
461
462void rb_erase_cached(struct rb_node *node, struct rb_root_cached *root)
463{
464 struct rb_node *rebalance;
465 rebalance = __rb_erase_augmented(node, &root->rb_root,
466 &root->rb_leftmost, &dummy_callbacks);
467 if (rebalance)
468 ____rb_erase_color(rebalance, &root->rb_root, dummy_rotate);
469}
470EXPORT_SYMBOL(rb_erase_cached);
471
472/* 449/*
473 * Augmented rbtree manipulation functions. 450 * Augmented rbtree manipulation functions.
474 * 451 *
@@ -477,10 +454,9 @@ EXPORT_SYMBOL(rb_erase_cached);
477 */ 454 */
478 455
479void __rb_insert_augmented(struct rb_node *node, struct rb_root *root, 456void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
480 bool newleft, struct rb_node **leftmost,
481 void (*augment_rotate)(struct rb_node *old, struct rb_node *new)) 457 void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
482{ 458{
483 __rb_insert(node, root, newleft, leftmost, augment_rotate); 459 __rb_insert(node, root, augment_rotate);
484} 460}
485EXPORT_SYMBOL(__rb_insert_augmented); 461EXPORT_SYMBOL(__rb_insert_augmented);
486 462
@@ -591,16 +567,6 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new,
591} 567}
592EXPORT_SYMBOL(rb_replace_node); 568EXPORT_SYMBOL(rb_replace_node);
593 569
594void rb_replace_node_cached(struct rb_node *victim, struct rb_node *new,
595 struct rb_root_cached *root)
596{
597 rb_replace_node(victim, new, &root->rb_root);
598
599 if (root->rb_leftmost == victim)
600 root->rb_leftmost = new;
601}
602EXPORT_SYMBOL(rb_replace_node_cached);
603
604void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new, 570void rb_replace_node_rcu(struct rb_node *victim, struct rb_node *new,
605 struct rb_root *root) 571 struct rb_root *root)
606{ 572{
diff --git a/lib/string.c b/lib/string.c
index 6016eb3ac73d..461fb620f85f 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -400,6 +400,9 @@ EXPORT_SYMBOL(strncmp);
400 * strchr - Find the first occurrence of a character in a string 400 * strchr - Find the first occurrence of a character in a string
401 * @s: The string to be searched 401 * @s: The string to be searched
402 * @c: The character to search for 402 * @c: The character to search for
403 *
404 * Note that the %NUL-terminator is considered part of the string, and can
405 * be searched for.
403 */ 406 */
404char *strchr(const char *s, int c) 407char *strchr(const char *s, int c)
405{ 408{
@@ -453,12 +456,18 @@ EXPORT_SYMBOL(strrchr);
453 * @s: The string to be searched 456 * @s: The string to be searched
454 * @count: The number of characters to be searched 457 * @count: The number of characters to be searched
455 * @c: The character to search for 458 * @c: The character to search for
459 *
460 * Note that the %NUL-terminator is considered part of the string, and can
461 * be searched for.
456 */ 462 */
457char *strnchr(const char *s, size_t count, int c) 463char *strnchr(const char *s, size_t count, int c)
458{ 464{
459 for (; count-- && *s != '\0'; ++s) 465 while (count--) {
460 if (*s == (char)c) 466 if (*s == (char)c)
461 return (char *)s; 467 return (char *)s;
468 if (*s++ == '\0')
469 break;
470 }
462 return NULL; 471 return NULL;
463} 472}
464EXPORT_SYMBOL(strnchr); 473EXPORT_SYMBOL(strnchr);
diff --git a/lib/string_helpers.c b/lib/string_helpers.c
index 3a90a9e2b94a..963050c0283e 100644
--- a/lib/string_helpers.c
+++ b/lib/string_helpers.c
@@ -231,35 +231,36 @@ static bool unescape_special(char **src, char **dst)
231 * @src: source buffer (escaped) 231 * @src: source buffer (escaped)
232 * @dst: destination buffer (unescaped) 232 * @dst: destination buffer (unescaped)
233 * @size: size of the destination buffer (0 to unlimit) 233 * @size: size of the destination buffer (0 to unlimit)
234 * @flags: combination of the flags (bitwise OR): 234 * @flags: combination of the flags.
235 * %UNESCAPE_SPACE: 235 *
236 * Description:
237 * The function unquotes characters in the given string.
238 *
239 * Because the size of the output will be the same as or less than the size of
240 * the input, the transformation may be performed in place.
241 *
242 * Caller must provide valid source and destination pointers. Be aware that
243 * destination buffer will always be NULL-terminated. Source string must be
244 * NULL-terminated as well. The supported flags are::
245 *
246 * UNESCAPE_SPACE:
236 * '\f' - form feed 247 * '\f' - form feed
237 * '\n' - new line 248 * '\n' - new line
238 * '\r' - carriage return 249 * '\r' - carriage return
239 * '\t' - horizontal tab 250 * '\t' - horizontal tab
240 * '\v' - vertical tab 251 * '\v' - vertical tab
241 * %UNESCAPE_OCTAL: 252 * UNESCAPE_OCTAL:
242 * '\NNN' - byte with octal value NNN (1 to 3 digits) 253 * '\NNN' - byte with octal value NNN (1 to 3 digits)
243 * %UNESCAPE_HEX: 254 * UNESCAPE_HEX:
244 * '\xHH' - byte with hexadecimal value HH (1 to 2 digits) 255 * '\xHH' - byte with hexadecimal value HH (1 to 2 digits)
245 * %UNESCAPE_SPECIAL: 256 * UNESCAPE_SPECIAL:
246 * '\"' - double quote 257 * '\"' - double quote
247 * '\\' - backslash 258 * '\\' - backslash
248 * '\a' - alert (BEL) 259 * '\a' - alert (BEL)
249 * '\e' - escape 260 * '\e' - escape
250 * %UNESCAPE_ANY: 261 * UNESCAPE_ANY:
251 * all previous together 262 * all previous together
252 * 263 *
253 * Description:
254 * The function unquotes characters in the given string.
255 *
256 * Because the size of the output will be the same as or less than the size of
257 * the input, the transformation may be performed in place.
258 *
259 * Caller must provide valid source and destination pointers. Be aware that
260 * destination buffer will always be NULL-terminated. Source string must be
261 * NULL-terminated as well.
262 *
263 * Return: 264 * Return:
264 * The amount of the characters processed to the destination buffer excluding 265 * The amount of the characters processed to the destination buffer excluding
265 * trailing '\0' is returned. 266 * trailing '\0' is returned.
@@ -441,7 +442,29 @@ static bool escape_hex(unsigned char c, char **dst, char *end)
441 * @isz: source buffer size 442 * @isz: source buffer size
442 * @dst: destination buffer (escaped) 443 * @dst: destination buffer (escaped)
443 * @osz: destination buffer size 444 * @osz: destination buffer size
444 * @flags: combination of the flags (bitwise OR): 445 * @flags: combination of the flags
446 * @only: NULL-terminated string containing characters used to limit
447 * the selected escape class. If characters are included in @only
448 * that would not normally be escaped by the classes selected
449 * in @flags, they will be copied to @dst unescaped.
450 *
451 * Description:
452 * The process of escaping byte buffer includes several parts. They are applied
453 * in the following sequence.
454 *
455 * 1. The character is matched to the printable class, if asked, and in
456 * case of match it passes through to the output.
457 * 2. The character is not matched to the one from @only string and thus
458 * must go as-is to the output.
459 * 3. The character is checked if it falls into the class given by @flags.
460 * %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any
461 * character. Note that they actually can't go together, otherwise
462 * %ESCAPE_HEX will be ignored.
463 *
464 * Caller must provide valid source and destination pointers. Be aware that
465 * destination buffer will not be NULL-terminated, thus caller have to append
466 * it if needs. The supported flags are::
467 *
445 * %ESCAPE_SPACE: (special white space, not space itself) 468 * %ESCAPE_SPACE: (special white space, not space itself)
446 * '\f' - form feed 469 * '\f' - form feed
447 * '\n' - new line 470 * '\n' - new line
@@ -464,26 +487,6 @@ static bool escape_hex(unsigned char c, char **dst, char *end)
464 * all previous together 487 * all previous together
465 * %ESCAPE_HEX: 488 * %ESCAPE_HEX:
466 * '\xHH' - byte with hexadecimal value HH (2 digits) 489 * '\xHH' - byte with hexadecimal value HH (2 digits)
467 * @only: NULL-terminated string containing characters used to limit
468 * the selected escape class. If characters are included in @only
469 * that would not normally be escaped by the classes selected
470 * in @flags, they will be copied to @dst unescaped.
471 *
472 * Description:
473 * The process of escaping byte buffer includes several parts. They are applied
474 * in the following sequence.
475 * 1. The character is matched to the printable class, if asked, and in
476 * case of match it passes through to the output.
477 * 2. The character is not matched to the one from @only string and thus
478 * must go as-is to the output.
479 * 3. The character is checked if it falls into the class given by @flags.
480 * %ESCAPE_OCTAL and %ESCAPE_HEX are going last since they cover any
481 * character. Note that they actually can't go together, otherwise
482 * %ESCAPE_HEX will be ignored.
483 *
484 * Caller must provide valid source and destination pointers. Be aware that
485 * destination buffer will not be NULL-terminated, thus caller have to append
486 * it if needs.
487 * 490 *
488 * Return: 491 * Return:
489 * The total size of the escaped output that would be generated for 492 * The total size of the escaped output that would be generated for
diff --git a/lib/test_meminit.c b/lib/test_meminit.c
new file mode 100644
index 000000000000..62d19f270cad
--- /dev/null
+++ b/lib/test_meminit.c
@@ -0,0 +1,364 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Test cases for SL[AOU]B/page initialization at alloc/free time.
4 */
5#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
6
7#include <linux/init.h>
8#include <linux/kernel.h>
9#include <linux/mm.h>
10#include <linux/module.h>
11#include <linux/slab.h>
12#include <linux/string.h>
13#include <linux/vmalloc.h>
14
15#define GARBAGE_INT (0x09A7BA9E)
16#define GARBAGE_BYTE (0x9E)
17
18#define REPORT_FAILURES_IN_FN() \
19 do { \
20 if (failures) \
21 pr_info("%s failed %d out of %d times\n", \
22 __func__, failures, num_tests); \
23 else \
24 pr_info("all %d tests in %s passed\n", \
25 num_tests, __func__); \
26 } while (0)
27
28/* Calculate the number of uninitialized bytes in the buffer. */
29static int __init count_nonzero_bytes(void *ptr, size_t size)
30{
31 int i, ret = 0;
32 unsigned char *p = (unsigned char *)ptr;
33
34 for (i = 0; i < size; i++)
35 if (p[i])
36 ret++;
37 return ret;
38}
39
40/* Fill a buffer with garbage, skipping |skip| first bytes. */
41static void __init fill_with_garbage_skip(void *ptr, int size, size_t skip)
42{
43 unsigned int *p = (unsigned int *)((char *)ptr + skip);
44 int i = 0;
45
46 WARN_ON(skip > size);
47 size -= skip;
48
49 while (size >= sizeof(*p)) {
50 p[i] = GARBAGE_INT;
51 i++;
52 size -= sizeof(*p);
53 }
54 if (size)
55 memset(&p[i], GARBAGE_BYTE, size);
56}
57
58static void __init fill_with_garbage(void *ptr, size_t size)
59{
60 fill_with_garbage_skip(ptr, size, 0);
61}
62
63static int __init do_alloc_pages_order(int order, int *total_failures)
64{
65 struct page *page;
66 void *buf;
67 size_t size = PAGE_SIZE << order;
68
69 page = alloc_pages(GFP_KERNEL, order);
70 buf = page_address(page);
71 fill_with_garbage(buf, size);
72 __free_pages(page, order);
73
74 page = alloc_pages(GFP_KERNEL, order);
75 buf = page_address(page);
76 if (count_nonzero_bytes(buf, size))
77 (*total_failures)++;
78 fill_with_garbage(buf, size);
79 __free_pages(page, order);
80 return 1;
81}
82
83/* Test the page allocator by calling alloc_pages with different orders. */
84static int __init test_pages(int *total_failures)
85{
86 int failures = 0, num_tests = 0;
87 int i;
88
89 for (i = 0; i < 10; i++)
90 num_tests += do_alloc_pages_order(i, &failures);
91
92 REPORT_FAILURES_IN_FN();
93 *total_failures += failures;
94 return num_tests;
95}
96
97/* Test kmalloc() with given parameters. */
98static int __init do_kmalloc_size(size_t size, int *total_failures)
99{
100 void *buf;
101
102 buf = kmalloc(size, GFP_KERNEL);
103 fill_with_garbage(buf, size);
104 kfree(buf);
105
106 buf = kmalloc(size, GFP_KERNEL);
107 if (count_nonzero_bytes(buf, size))
108 (*total_failures)++;
109 fill_with_garbage(buf, size);
110 kfree(buf);
111 return 1;
112}
113
114/* Test vmalloc() with given parameters. */
115static int __init do_vmalloc_size(size_t size, int *total_failures)
116{
117 void *buf;
118
119 buf = vmalloc(size);
120 fill_with_garbage(buf, size);
121 vfree(buf);
122
123 buf = vmalloc(size);
124 if (count_nonzero_bytes(buf, size))
125 (*total_failures)++;
126 fill_with_garbage(buf, size);
127 vfree(buf);
128 return 1;
129}
130
131/* Test kmalloc()/vmalloc() by allocating objects of different sizes. */
132static int __init test_kvmalloc(int *total_failures)
133{
134 int failures = 0, num_tests = 0;
135 int i, size;
136
137 for (i = 0; i < 20; i++) {
138 size = 1 << i;
139 num_tests += do_kmalloc_size(size, &failures);
140 num_tests += do_vmalloc_size(size, &failures);
141 }
142
143 REPORT_FAILURES_IN_FN();
144 *total_failures += failures;
145 return num_tests;
146}
147
148#define CTOR_BYTES (sizeof(unsigned int))
149#define CTOR_PATTERN (0x41414141)
150/* Initialize the first 4 bytes of the object. */
151static void test_ctor(void *obj)
152{
153 *(unsigned int *)obj = CTOR_PATTERN;
154}
155
156/*
157 * Check the invariants for the buffer allocated from a slab cache.
158 * If the cache has a test constructor, the first 4 bytes of the object must
159 * always remain equal to CTOR_PATTERN.
160 * If the cache isn't an RCU-typesafe one, or if the allocation is done with
161 * __GFP_ZERO, then the object contents must be zeroed after allocation.
162 * If the cache is an RCU-typesafe one, the object contents must never be
163 * zeroed after the first use. This is checked by memcmp() in
164 * do_kmem_cache_size().
165 */
166static bool __init check_buf(void *buf, int size, bool want_ctor,
167 bool want_rcu, bool want_zero)
168{
169 int bytes;
170 bool fail = false;
171
172 bytes = count_nonzero_bytes(buf, size);
173 WARN_ON(want_ctor && want_zero);
174 if (want_zero)
175 return bytes;
176 if (want_ctor) {
177 if (*(unsigned int *)buf != CTOR_PATTERN)
178 fail = 1;
179 } else {
180 if (bytes)
181 fail = !want_rcu;
182 }
183 return fail;
184}
185
186/*
187 * Test kmem_cache with given parameters:
188 * want_ctor - use a constructor;
189 * want_rcu - use SLAB_TYPESAFE_BY_RCU;
190 * want_zero - use __GFP_ZERO.
191 */
192static int __init do_kmem_cache_size(size_t size, bool want_ctor,
193 bool want_rcu, bool want_zero,
194 int *total_failures)
195{
196 struct kmem_cache *c;
197 int iter;
198 bool fail = false;
199 gfp_t alloc_mask = GFP_KERNEL | (want_zero ? __GFP_ZERO : 0);
200 void *buf, *buf_copy;
201
202 c = kmem_cache_create("test_cache", size, 1,
203 want_rcu ? SLAB_TYPESAFE_BY_RCU : 0,
204 want_ctor ? test_ctor : NULL);
205 for (iter = 0; iter < 10; iter++) {
206 buf = kmem_cache_alloc(c, alloc_mask);
207 /* Check that buf is zeroed, if it must be. */
208 fail = check_buf(buf, size, want_ctor, want_rcu, want_zero);
209 fill_with_garbage_skip(buf, size, want_ctor ? CTOR_BYTES : 0);
210
211 if (!want_rcu) {
212 kmem_cache_free(c, buf);
213 continue;
214 }
215
216 /*
217 * If this is an RCU cache, use a critical section to ensure we
218 * can touch objects after they're freed.
219 */
220 rcu_read_lock();
221 /*
222 * Copy the buffer to check that it's not wiped on
223 * free().
224 */
225 buf_copy = kmalloc(size, GFP_KERNEL);
226 if (buf_copy)
227 memcpy(buf_copy, buf, size);
228
229 kmem_cache_free(c, buf);
230 /*
231 * Check that |buf| is intact after kmem_cache_free().
232 * |want_zero| is false, because we wrote garbage to
233 * the buffer already.
234 */
235 fail |= check_buf(buf, size, want_ctor, want_rcu,
236 false);
237 if (buf_copy) {
238 fail |= (bool)memcmp(buf, buf_copy, size);
239 kfree(buf_copy);
240 }
241 rcu_read_unlock();
242 }
243 kmem_cache_destroy(c);
244
245 *total_failures += fail;
246 return 1;
247}
248
249/*
250 * Check that the data written to an RCU-allocated object survives
251 * reallocation.
252 */
253static int __init do_kmem_cache_rcu_persistent(int size, int *total_failures)
254{
255 struct kmem_cache *c;
256 void *buf, *buf_contents, *saved_ptr;
257 void **used_objects;
258 int i, iter, maxiter = 1024;
259 bool fail = false;
260
261 c = kmem_cache_create("test_cache", size, size, SLAB_TYPESAFE_BY_RCU,
262 NULL);
263 buf = kmem_cache_alloc(c, GFP_KERNEL);
264 saved_ptr = buf;
265 fill_with_garbage(buf, size);
266 buf_contents = kmalloc(size, GFP_KERNEL);
267 if (!buf_contents)
268 goto out;
269 used_objects = kmalloc_array(maxiter, sizeof(void *), GFP_KERNEL);
270 if (!used_objects) {
271 kfree(buf_contents);
272 goto out;
273 }
274 memcpy(buf_contents, buf, size);
275 kmem_cache_free(c, buf);
276 /*
277 * Run for a fixed number of iterations. If we never hit saved_ptr,
278 * assume the test passes.
279 */
280 for (iter = 0; iter < maxiter; iter++) {
281 buf = kmem_cache_alloc(c, GFP_KERNEL);
282 used_objects[iter] = buf;
283 if (buf == saved_ptr) {
284 fail = memcmp(buf_contents, buf, size);
285 for (i = 0; i <= iter; i++)
286 kmem_cache_free(c, used_objects[i]);
287 goto free_out;
288 }
289 }
290
291free_out:
292 kmem_cache_destroy(c);
293 kfree(buf_contents);
294 kfree(used_objects);
295out:
296 *total_failures += fail;
297 return 1;
298}
299
300/*
301 * Test kmem_cache allocation by creating caches of different sizes, with and
302 * without constructors, with and without SLAB_TYPESAFE_BY_RCU.
303 */
304static int __init test_kmemcache(int *total_failures)
305{
306 int failures = 0, num_tests = 0;
307 int i, flags, size;
308 bool ctor, rcu, zero;
309
310 for (i = 0; i < 10; i++) {
311 size = 8 << i;
312 for (flags = 0; flags < 8; flags++) {
313 ctor = flags & 1;
314 rcu = flags & 2;
315 zero = flags & 4;
316 if (ctor & zero)
317 continue;
318 num_tests += do_kmem_cache_size(size, ctor, rcu, zero,
319 &failures);
320 }
321 }
322 REPORT_FAILURES_IN_FN();
323 *total_failures += failures;
324 return num_tests;
325}
326
327/* Test the behavior of SLAB_TYPESAFE_BY_RCU caches of different sizes. */
328static int __init test_rcu_persistent(int *total_failures)
329{
330 int failures = 0, num_tests = 0;
331 int i, size;
332
333 for (i = 0; i < 10; i++) {
334 size = 8 << i;
335 num_tests += do_kmem_cache_rcu_persistent(size, &failures);
336 }
337 REPORT_FAILURES_IN_FN();
338 *total_failures += failures;
339 return num_tests;
340}
341
342/*
343 * Run the tests. Each test function returns the number of executed tests and
344 * updates |failures| with the number of failed tests.
345 */
346static int __init test_meminit_init(void)
347{
348 int failures = 0, num_tests = 0;
349
350 num_tests += test_pages(&failures);
351 num_tests += test_kvmalloc(&failures);
352 num_tests += test_kmemcache(&failures);
353 num_tests += test_rcu_persistent(&failures);
354
355 if (failures == 0)
356 pr_info("all %d tests passed!\n", num_tests);
357 else
358 pr_info("failures: %d out of %d\n", failures, num_tests);
359
360 return failures ? -EINVAL : 0;
361}
362module_init(test_meminit_init);
363
364MODULE_LICENSE("GPL");
diff --git a/lib/test_overflow.c b/lib/test_overflow.c
index fc680562d8b6..7a4b6f6c5473 100644
--- a/lib/test_overflow.c
+++ b/lib/test_overflow.c
@@ -486,16 +486,17 @@ static int __init test_overflow_shift(void)
486 * Deal with the various forms of allocator arguments. See comments above 486 * Deal with the various forms of allocator arguments. See comments above
487 * the DEFINE_TEST_ALLOC() instances for mapping of the "bits". 487 * the DEFINE_TEST_ALLOC() instances for mapping of the "bits".
488 */ 488 */
489#define alloc010(alloc, arg, sz) alloc(sz, GFP_KERNEL) 489#define alloc_GFP (GFP_KERNEL | __GFP_NOWARN)
490#define alloc011(alloc, arg, sz) alloc(sz, GFP_KERNEL, NUMA_NO_NODE) 490#define alloc010(alloc, arg, sz) alloc(sz, alloc_GFP)
491#define alloc011(alloc, arg, sz) alloc(sz, alloc_GFP, NUMA_NO_NODE)
491#define alloc000(alloc, arg, sz) alloc(sz) 492#define alloc000(alloc, arg, sz) alloc(sz)
492#define alloc001(alloc, arg, sz) alloc(sz, NUMA_NO_NODE) 493#define alloc001(alloc, arg, sz) alloc(sz, NUMA_NO_NODE)
493#define alloc110(alloc, arg, sz) alloc(arg, sz, GFP_KERNEL) 494#define alloc110(alloc, arg, sz) alloc(arg, sz, alloc_GFP)
494#define free0(free, arg, ptr) free(ptr) 495#define free0(free, arg, ptr) free(ptr)
495#define free1(free, arg, ptr) free(arg, ptr) 496#define free1(free, arg, ptr) free(arg, ptr)
496 497
497/* Wrap around to 8K */ 498/* Wrap around to 16K */
498#define TEST_SIZE (9 << PAGE_SHIFT) 499#define TEST_SIZE (5 * 4096)
499 500
500#define DEFINE_TEST_ALLOC(func, free_func, want_arg, want_gfp, want_node)\ 501#define DEFINE_TEST_ALLOC(func, free_func, want_arg, want_gfp, want_node)\
501static int __init test_ ## func (void *arg) \ 502static int __init test_ ## func (void *arg) \
diff --git a/lib/test_string.c b/lib/test_string.c
index bf8def01ed20..7b31f4a505bf 100644
--- a/lib/test_string.c
+++ b/lib/test_string.c
@@ -36,7 +36,7 @@ static __init int memset16_selftest(void)
36fail: 36fail:
37 kfree(p); 37 kfree(p);
38 if (i < 256) 38 if (i < 256)
39 return (i << 24) | (j << 16) | k; 39 return (i << 24) | (j << 16) | k | 0x8000;
40 return 0; 40 return 0;
41} 41}
42 42
@@ -72,7 +72,7 @@ static __init int memset32_selftest(void)
72fail: 72fail:
73 kfree(p); 73 kfree(p);
74 if (i < 256) 74 if (i < 256)
75 return (i << 24) | (j << 16) | k; 75 return (i << 24) | (j << 16) | k | 0x8000;
76 return 0; 76 return 0;
77} 77}
78 78
@@ -108,7 +108,74 @@ static __init int memset64_selftest(void)
108fail: 108fail:
109 kfree(p); 109 kfree(p);
110 if (i < 256) 110 if (i < 256)
111 return (i << 24) | (j << 16) | k; 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
112 return 0; 179 return 0;
113} 180}
114 181
@@ -131,6 +198,16 @@ static __init int string_selftest_init(void)
131 if (subtest) 198 if (subtest)
132 goto fail; 199 goto fail;
133 200
201 test = 4;
202 subtest = strchr_selftest();
203 if (subtest)
204 goto fail;
205
206 test = 5;
207 subtest = strnchr_selftest();
208 if (subtest)
209 goto fail;
210
134 pr_info("String selftests succeeded\n"); 211 pr_info("String selftests succeeded\n");
135 return 0; 212 return 0;
136fail: 213fail: