2021-03-30 12:06:34

by Oliver Glitta

[permalink] [raw]
Subject: [PATCH v2 1/2] kunit: add a KUnit test for SLUB debugging functionality

From: Oliver Glitta <[email protected]>

SLUB has resiliency_test() function which is hidden behind #ifdef
SLUB_RESILIENCY_TEST that is not part of Kconfig, so nobody
runs it. KUnit should be a proper replacement for it.

Try changing byte in redzone after allocation and changing
pointer to next free node, first byte, 50th byte and redzone
byte. Check if validation finds errors.

There are several differences from the original resiliency test:
Tests create own caches with known state instead of corrupting
shared kmalloc caches.

The corruption of freepointer uses correct offset, the original
resiliency test got broken with freepointer changes.

Scratch changing random byte test, because it does not have
meaning in this form where we need deterministic results.

Add new option CONFIG_SLUB_KUNIT_TEST in Kconfig.

Add a counter field "errors" to struct kmem_cache to count number
of errors detected in cache.

Silence bug report in SLUB test. Add SLAB_SILENT_ERRORS debug flag.
Add SLAB_SILENT_ERRORS flag to SLAB_NEVER_MERGE, SLAB_DEBUG_FLAGS,
SLAB_FLAGS_PERMITTED macros.

Signed-off-by: Oliver Glitta <[email protected]>
---
Changes since v1

Conversion from kselftest to KUnit test suggested by Marco Elver.
Error silencing.
Error counting improvements.

include/linux/slab.h | 2 +
include/linux/slub_def.h | 2 +
lib/Kconfig.debug | 5 ++
lib/Makefile | 1 +
lib/test_slub.c | 124 +++++++++++++++++++++++++++++++++++++++
mm/slab.h | 7 ++-
mm/slab_common.c | 2 +-
mm/slub.c | 64 +++++++++++++-------
8 files changed, 184 insertions(+), 23 deletions(-)
create mode 100644 lib/test_slub.c

diff --git a/include/linux/slab.h b/include/linux/slab.h
index 7ae604076767..ed1a5a64d028 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -25,6 +25,8 @@
*/
/* DEBUG: Perform (expensive) checks on alloc/free */
#define SLAB_CONSISTENCY_CHECKS ((slab_flags_t __force)0x00000100U)
+/* DEBUG: Silent bug reports */
+#define SLAB_SILENT_ERRORS ((slab_flags_t __force)0x00000200U)
/* DEBUG: Red zone objs in a cache */
#define SLAB_RED_ZONE ((slab_flags_t __force)0x00000400U)
/* DEBUG: Poison objects */
diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h
index dcde82a4434c..e4b51bb5bb83 100644
--- a/include/linux/slub_def.h
+++ b/include/linux/slub_def.h
@@ -133,6 +133,8 @@ struct kmem_cache {
unsigned int usersize; /* Usercopy region size */

struct kmem_cache_node *node[MAX_NUMNODES];
+
+ int errors; /* Number of errors in cache */
};

#ifdef CONFIG_SLUB_CPU_PARTIAL
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 2779c29d9981..e0dec830c269 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2371,6 +2371,11 @@ config BITS_TEST

If unsure, say N.

+config SLUB_KUNIT_TEST
+ tristate "KUnit Test for SLUB cache error detection" if !KUNIT_ALL_TESTS
+ depends on SLUB_DEBUG && KUNIT
+ default KUNIT_ALL_TESTS
+
config TEST_UDELAY
tristate "udelay test driver"
help
diff --git a/lib/Makefile b/lib/Makefile
index b5307d3eec1a..e1eb986c0e87 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -352,5 +352,6 @@ obj-$(CONFIG_LIST_KUNIT_TEST) += list-test.o
obj-$(CONFIG_LINEAR_RANGES_TEST) += test_linear_ranges.o
obj-$(CONFIG_BITS_TEST) += test_bits.o
obj-$(CONFIG_CMDLINE_KUNIT_TEST) += cmdline_kunit.o
+obj-$(CONFIG_SLUB_KUNIT_TEST) += test_slub.o

obj-$(CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED) += devmem_is_allowed.o
diff --git a/lib/test_slub.c b/lib/test_slub.c
new file mode 100644
index 000000000000..4f8ea3c7d867
--- /dev/null
+++ b/lib/test_slub.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <kunit/test.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include "../mm/slab.h"
+
+
+static void test_clobber_zone(struct kunit *test)
+{
+ struct kmem_cache *s = kmem_cache_create("TestSlub_RZ_alloc", 64, 0,
+ SLAB_RED_ZONE | SLAB_SILENT_ERRORS, NULL);
+ u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
+
+ p[64] = 0x12;
+
+ validate_slab_cache(s);
+ KUNIT_EXPECT_EQ(test, 1, s->errors);
+
+ kmem_cache_free(s, p);
+ kmem_cache_destroy(s);
+}
+
+static void test_next_pointer(struct kunit *test)
+{
+ struct kmem_cache *s = kmem_cache_create("TestSlub_next_ptr_free", 64, 0,
+ SLAB_POISON | SLAB_SILENT_ERRORS, NULL);
+ u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
+ unsigned long tmp;
+ unsigned long *ptr_addr;
+
+ kmem_cache_free(s, p);
+
+ ptr_addr = (unsigned long *)(p + s->offset);
+ tmp = *ptr_addr;
+ p[s->offset] = 0x12;
+
+ /*
+ * Expecting two errors.
+ * One for the corrupted freechain and the other one for the wrong
+ * count of objects in use.
+ */
+ validate_slab_cache(s);
+ KUNIT_EXPECT_EQ(test, 2, s->errors);
+
+ /*
+ * Try to repair corrupted freepointer.
+ * Still expecting one error for the wrong count of objects in use.
+ */
+ *ptr_addr = tmp;
+
+ validate_slab_cache(s);
+ KUNIT_EXPECT_EQ(test, 1, s->errors);
+
+ /*
+ * Previous validation repaired the count of objects in use.
+ * Now expecting no error.
+ */
+ validate_slab_cache(s);
+ KUNIT_EXPECT_EQ(test, 0, s->errors);
+
+ kmem_cache_destroy(s);
+}
+
+static void test_first_word(struct kunit *test)
+{
+ struct kmem_cache *s = kmem_cache_create("TestSlub_1th_word_free", 64, 0,
+ SLAB_POISON | SLAB_SILENT_ERRORS, NULL);
+ u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
+
+ kmem_cache_free(s, p);
+ *p = 0x78;
+
+ validate_slab_cache(s);
+ KUNIT_EXPECT_EQ(test, 1, s->errors);
+
+ kmem_cache_destroy(s);
+}
+
+static void test_clobber_50th_byte(struct kunit *test)
+{
+ struct kmem_cache *s = kmem_cache_create("TestSlub_50th_word_free", 64, 0,
+ SLAB_POISON | SLAB_SILENT_ERRORS, NULL);
+ u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
+
+ kmem_cache_free(s, p);
+ p[50] = 0x9a;
+
+ validate_slab_cache(s);
+ KUNIT_EXPECT_EQ(test, 1, s->errors);
+ kmem_cache_destroy(s);
+}
+
+static void test_clobber_redzone_free(struct kunit *test)
+{
+ struct kmem_cache *s = kmem_cache_create("TestSlub_RZ_free", 64, 0,
+ SLAB_RED_ZONE | SLAB_SILENT_ERRORS, NULL);
+ u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
+
+ kmem_cache_free(s, p);
+ p[64] = 0xab;
+
+ validate_slab_cache(s);
+ KUNIT_EXPECT_EQ(test, 1, s->errors);
+ kmem_cache_destroy(s);
+}
+
+static struct kunit_case test_cases[] = {
+ KUNIT_CASE(test_clobber_zone),
+ KUNIT_CASE(test_next_pointer),
+ KUNIT_CASE(test_first_word),
+ KUNIT_CASE(test_clobber_50th_byte),
+ KUNIT_CASE(test_clobber_redzone_free),
+ {}
+};
+
+static struct kunit_suite test_suite = {
+ .name = "slub_test",
+ .test_cases = test_cases,
+};
+kunit_test_suite(test_suite);
+
+MODULE_LICENSE("GPL");
diff --git a/mm/slab.h b/mm/slab.h
index 076582f58f68..382507b6cab9 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -134,7 +134,8 @@ static inline slab_flags_t kmem_cache_flags(unsigned int object_size,
#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER)
#elif defined(CONFIG_SLUB_DEBUG)
#define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
- SLAB_TRACE | SLAB_CONSISTENCY_CHECKS)
+ SLAB_TRACE | SLAB_CONSISTENCY_CHECKS | \
+ SLAB_SILENT_ERRORS)
#else
#define SLAB_DEBUG_FLAGS (0)
#endif
@@ -164,7 +165,8 @@ static inline slab_flags_t kmem_cache_flags(unsigned int object_size,
SLAB_NOLEAKTRACE | \
SLAB_RECLAIM_ACCOUNT | \
SLAB_TEMPORARY | \
- SLAB_ACCOUNT)
+ SLAB_ACCOUNT | \
+ SLAB_SILENT_ERRORS)

bool __kmem_cache_empty(struct kmem_cache *);
int __kmem_cache_shutdown(struct kmem_cache *);
@@ -215,6 +217,7 @@ DECLARE_STATIC_KEY_TRUE(slub_debug_enabled);
DECLARE_STATIC_KEY_FALSE(slub_debug_enabled);
#endif
extern void print_tracking(struct kmem_cache *s, void *object);
+long validate_slab_cache(struct kmem_cache *s);
#else
static inline void print_tracking(struct kmem_cache *s, void *object)
{
diff --git a/mm/slab_common.c b/mm/slab_common.c
index 88e833986332..239c9095e7ea 100644
--- a/mm/slab_common.c
+++ b/mm/slab_common.c
@@ -55,7 +55,7 @@ static DECLARE_WORK(slab_caches_to_rcu_destroy_work,
*/
#define SLAB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
SLAB_TRACE | SLAB_TYPESAFE_BY_RCU | SLAB_NOLEAKTRACE | \
- SLAB_FAILSLAB | kasan_never_merge())
+ SLAB_FAILSLAB | SLAB_SILENT_ERRORS | kasan_never_merge())

#define SLAB_MERGE_SAME (SLAB_RECLAIM_ACCOUNT | SLAB_CACHE_DMA | \
SLAB_CACHE_DMA32 | SLAB_ACCOUNT)
diff --git a/mm/slub.c b/mm/slub.c
index 3021ce9bf1b3..06916e11a2bf 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -673,14 +673,16 @@ static void slab_bug(struct kmem_cache *s, char *fmt, ...)

static void slab_fix(struct kmem_cache *s, char *fmt, ...)
{
- struct va_format vaf;
- va_list args;
-
- va_start(args, fmt);
- vaf.fmt = fmt;
- vaf.va = &args;
- pr_err("FIX %s: %pV\n", s->name, &vaf);
- va_end(args);
+ if (!(s->flags & SLAB_SILENT_ERRORS)) {
+ struct va_format vaf;
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.fmt = fmt;
+ vaf.va = &args;
+ pr_err("FIX %s: %pV\n", s->name, &vaf);
+ va_end(args);
+ }
}

static bool freelist_corrupted(struct kmem_cache *s, struct page *page,
@@ -739,8 +741,10 @@ static void print_trailer(struct kmem_cache *s, struct page *page, u8 *p)
void object_err(struct kmem_cache *s, struct page *page,
u8 *object, char *reason)
{
- slab_bug(s, "%s", reason);
- print_trailer(s, page, object);
+ if (!(s->flags && SLAB_SILENT_ERRORS)) {
+ slab_bug(s, "%s", reason);
+ print_trailer(s, page, object);
+ }
}

static __printf(3, 4) void slab_err(struct kmem_cache *s, struct page *page,
@@ -752,9 +756,11 @@ static __printf(3, 4) void slab_err(struct kmem_cache *s, struct page *page,
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
- slab_bug(s, "%s", buf);
- print_page_info(page);
- dump_stack();
+ if (!(s->flags && SLAB_SILENT_ERRORS)) {
+ slab_bug(s, "%s", buf);
+ print_page_info(page);
+ dump_stack();
+ }
}

static void init_object(struct kmem_cache *s, void *object, u8 val)
@@ -798,11 +804,13 @@ static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
while (end > fault && end[-1] == value)
end--;

- slab_bug(s, "%s overwritten", what);
- pr_err("INFO: 0x%p-0x%p @offset=%tu. First byte 0x%x instead of 0x%x\n",
+ if (!(s->flags && SLAB_SILENT_ERRORS)) {
+ slab_bug(s, "%s overwritten", what);
+ pr_err("INFO: 0x%p-0x%p @offset=%tu. First byte 0x%x instead of 0x%x\n",
fault, end - 1, fault - addr,
fault[0], value);
- print_trailer(s, page, object);
+ print_trailer(s, page, object);
+ }

restore_bytes(s, what, value, fault, end);
return 0;
@@ -964,6 +972,7 @@ static int check_slab(struct kmem_cache *s, struct page *page)

if (!PageSlab(page)) {
slab_err(s, page, "Not a valid slab page");
+ s->errors += 1;
return 0;
}

@@ -971,11 +980,13 @@ static int check_slab(struct kmem_cache *s, struct page *page)
if (page->objects > maxobj) {
slab_err(s, page, "objects %u > max %u",
page->objects, maxobj);
+ s->errors += 1;
return 0;
}
if (page->inuse > page->objects) {
slab_err(s, page, "inuse %u > max %u",
page->inuse, page->objects);
+ s->errors += 1;
return 0;
}
/* Slab_pad_check fixes things up after itself */
@@ -1008,8 +1019,10 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
page->freelist = NULL;
page->inuse = page->objects;
slab_fix(s, "Freelist cleared");
+ s->errors += 1;
return 0;
}
+ s->errors += 1;
break;
}
object = fp;
@@ -1026,12 +1039,14 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search)
page->objects, max_objects);
page->objects = max_objects;
slab_fix(s, "Number of objects adjusted.");
+ s->errors += 1;
}
if (page->inuse != page->objects - nr) {
slab_err(s, page, "Wrong object count. Counter is %d but counted were %d",
page->inuse, page->objects - nr);
page->inuse = page->objects - nr;
slab_fix(s, "Object count adjusted.");
+ s->errors += 1;
}
return search == NULL;
}
@@ -4629,8 +4644,10 @@ static void validate_slab(struct kmem_cache *s, struct page *page)
u8 val = test_bit(__obj_to_index(s, addr, p), map) ?
SLUB_RED_INACTIVE : SLUB_RED_ACTIVE;

- if (!check_object(s, page, p, val))
+ if (!check_object(s, page, p, val)) {
+ s->errors += 1;
break;
+ }
}
put_map(map);
unlock:
@@ -4650,9 +4667,11 @@ static int validate_slab_node(struct kmem_cache *s,
validate_slab(s, page);
count++;
}
- if (count != n->nr_partial)
+ if (count != n->nr_partial) {
pr_err("SLUB %s: %ld partial slabs counted but counter=%ld\n",
s->name, count, n->nr_partial);
+ s->errors += 1;
+ }

if (!(s->flags & SLAB_STORE_USER))
goto out;
@@ -4661,20 +4680,23 @@ static int validate_slab_node(struct kmem_cache *s,
validate_slab(s, page);
count++;
}
- if (count != atomic_long_read(&n->nr_slabs))
+ if (count != atomic_long_read(&n->nr_slabs)) {
pr_err("SLUB: %s %ld slabs counted but counter=%ld\n",
s->name, count, atomic_long_read(&n->nr_slabs));
+ s->errors += 1;
+ }

out:
spin_unlock_irqrestore(&n->list_lock, flags);
return count;
}

-static long validate_slab_cache(struct kmem_cache *s)
+long validate_slab_cache(struct kmem_cache *s)
{
int node;
unsigned long count = 0;
struct kmem_cache_node *n;
+ s->errors = 0;

flush_all(s);
for_each_kmem_cache_node(s, node, n)
@@ -4682,6 +4704,8 @@ static long validate_slab_cache(struct kmem_cache *s)

return count;
}
+EXPORT_SYMBOL(validate_slab_cache);
+
/*
* Generate lists of code addresses where slabcache objects are allocated
* and freed.
--
2.17.1


2021-03-30 16:25:16

by kernel test robot

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] kunit: add a KUnit test for SLUB debugging functionality

Hi,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on linus/master]
[also build test WARNING on v5.12-rc5]
[cannot apply to hnaz-linux-mm/master next-20210330]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url: https://github.com/0day-ci/linux/commits/glittao-gmail-com/kunit-add-a-KUnit-test-for-SLUB-debugging-functionality/20210330-200635
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 1e43c377a79f9189fea8f2711b399d4e8b4e609b
config: x86_64-randconfig-r022-20210330 (attached as .config)
compiler: clang version 13.0.0 (https://github.com/llvm/llvm-project 482283042f795ecc27838a3b2f76b5494991401c)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install x86_64 cross compiling tool for clang build
# apt-get install binutils-x86-64-linux-gnu
# https://github.com/0day-ci/linux/commit/98f544695d3d3b4676d7ff7bd7c964c9d39172d2
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review glittao-gmail-com/kunit-add-a-KUnit-test-for-SLUB-debugging-functionality/20210330-200635
git checkout 98f544695d3d3b4676d7ff7bd7c964c9d39172d2
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=x86_64

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>

All warnings (new ones prefixed by >>):

>> mm/slub.c:744:17: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
if (!(s->flags && SLAB_SILENT_ERRORS)) {
^ ~~~~~~~~~~~~~~~~~~
mm/slub.c:744:17: note: use '&' for a bitwise operation
if (!(s->flags && SLAB_SILENT_ERRORS)) {
^~
&
mm/slub.c:744:17: note: remove constant to silence this warning
if (!(s->flags && SLAB_SILENT_ERRORS)) {
~^~~~~~~~~~~~~~~~~~~~~
mm/slub.c:759:17: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
if (!(s->flags && SLAB_SILENT_ERRORS)) {
^ ~~~~~~~~~~~~~~~~~~
mm/slub.c:759:17: note: use '&' for a bitwise operation
if (!(s->flags && SLAB_SILENT_ERRORS)) {
^~
&
mm/slub.c:759:17: note: remove constant to silence this warning
if (!(s->flags && SLAB_SILENT_ERRORS)) {
~^~~~~~~~~~~~~~~~~~~~~
mm/slub.c:807:17: warning: use of logical '&&' with constant operand [-Wconstant-logical-operand]
if (!(s->flags && SLAB_SILENT_ERRORS)) {
^ ~~~~~~~~~~~~~~~~~~
mm/slub.c:807:17: note: use '&' for a bitwise operation
if (!(s->flags && SLAB_SILENT_ERRORS)) {
^~
&
mm/slub.c:807:17: note: remove constant to silence this warning
if (!(s->flags && SLAB_SILENT_ERRORS)) {
~^~~~~~~~~~~~~~~~~~~~~
mm/slub.c:1536:21: warning: unused function 'kmalloc_large_node_hook' [-Wunused-function]
static inline void *kmalloc_large_node_hook(void *ptr, size_t size, gfp_t flags)
^
4 warnings generated.


vim +744 mm/slub.c

740
741 void object_err(struct kmem_cache *s, struct page *page,
742 u8 *object, char *reason)
743 {
> 744 if (!(s->flags && SLAB_SILENT_ERRORS)) {
745 slab_bug(s, "%s", reason);
746 print_trailer(s, page, object);
747 }
748 }
749

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (3.97 kB)
.config.gz (31.03 kB)
Download all attachments

2021-03-31 04:40:16

by Dan Carpenter

[permalink] [raw]
Subject: Re: [PATCH v2 1/2] kunit: add a KUnit test for SLUB debugging functionality

Hi,

url: https://github.com/0day-ci/linux/commits/glittao-gmail-com/kunit-add-a-KUnit-test-for-SLUB-debugging-functionality/20210330-200635
base: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 1e43c377a79f9189fea8f2711b399d4e8b4e609b
config: i386-randconfig-m021-20210330 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <[email protected]>
Reported-by: Dan Carpenter <[email protected]>

smatch warnings:
mm/slub.c:744 object_err() warn: should this be a bitwise op?
mm/slub.c:759 slab_err() warn: should this be a bitwise op?
mm/slub.c:807 check_bytes_and_report() warn: should this be a bitwise op?

vim +744 mm/slub.c

75c66def8d8152 Andrey Ryabinin 2015-02-13 741 void object_err(struct kmem_cache *s, struct page *page,
81819f0fc8285a Christoph Lameter 2007-05-06 742 u8 *object, char *reason)
81819f0fc8285a Christoph Lameter 2007-05-06 743 {
98f544695d3d3b Oliver Glitta 2021-03-30 @744 if (!(s->flags && SLAB_SILENT_ERRORS)) {
^^
& was intended instead of &&

3dc5063786b273 Christoph Lameter 2008-04-23 745 slab_bug(s, "%s", reason);
2492268472e7d3 Christoph Lameter 2007-07-17 746 print_trailer(s, page, object);
81819f0fc8285a Christoph Lameter 2007-05-06 747 }
98f544695d3d3b Oliver Glitta 2021-03-30 748 }
81819f0fc8285a Christoph Lameter 2007-05-06 749
a38965bf941b7c Mathieu Malaterre 2018-06-07 750 static __printf(3, 4) void slab_err(struct kmem_cache *s, struct page *page,
d0e0ac9772f8ec Chen Gang 2013-07-15 751 const char *fmt, ...)
81819f0fc8285a Christoph Lameter 2007-05-06 752 {
81819f0fc8285a Christoph Lameter 2007-05-06 753 va_list args;
81819f0fc8285a Christoph Lameter 2007-05-06 754 char buf[100];
81819f0fc8285a Christoph Lameter 2007-05-06 755
2492268472e7d3 Christoph Lameter 2007-07-17 756 va_start(args, fmt);
2492268472e7d3 Christoph Lameter 2007-07-17 757 vsnprintf(buf, sizeof(buf), fmt, args);
81819f0fc8285a Christoph Lameter 2007-05-06 758 va_end(args);
98f544695d3d3b Oliver Glitta 2021-03-30 @759 if (!(s->flags && SLAB_SILENT_ERRORS)) {
^^^^^^^^^^^^^^^^^^^^^

3dc5063786b273 Christoph Lameter 2008-04-23 760 slab_bug(s, "%s", buf);
2492268472e7d3 Christoph Lameter 2007-07-17 761 print_page_info(page);
81819f0fc8285a Christoph Lameter 2007-05-06 762 dump_stack();
81819f0fc8285a Christoph Lameter 2007-05-06 763 }
98f544695d3d3b Oliver Glitta 2021-03-30 764 }
81819f0fc8285a Christoph Lameter 2007-05-06 765
f7cb1933621bce Christoph Lameter 2010-09-29 766 static void init_object(struct kmem_cache *s, void *object, u8 val)
81819f0fc8285a Christoph Lameter 2007-05-06 767 {
aa1ef4d7b3f67f Andrey Konovalov 2020-12-22 768 u8 *p = kasan_reset_tag(object);
81819f0fc8285a Christoph Lameter 2007-05-06 769
d86bd1bece6fc4 Joonsoo Kim 2016-03-15 770 if (s->flags & SLAB_RED_ZONE)
d86bd1bece6fc4 Joonsoo Kim 2016-03-15 771 memset(p - s->red_left_pad, val, s->red_left_pad);
d86bd1bece6fc4 Joonsoo Kim 2016-03-15 772
81819f0fc8285a Christoph Lameter 2007-05-06 773 if (s->flags & __OBJECT_POISON) {
3b0efdfa1e7193 Christoph Lameter 2012-06-13 774 memset(p, POISON_FREE, s->object_size - 1);
3b0efdfa1e7193 Christoph Lameter 2012-06-13 775 p[s->object_size - 1] = POISON_END;
81819f0fc8285a Christoph Lameter 2007-05-06 776 }
81819f0fc8285a Christoph Lameter 2007-05-06 777
81819f0fc8285a Christoph Lameter 2007-05-06 778 if (s->flags & SLAB_RED_ZONE)
3b0efdfa1e7193 Christoph Lameter 2012-06-13 779 memset(p + s->object_size, val, s->inuse - s->object_size);
81819f0fc8285a Christoph Lameter 2007-05-06 780 }
81819f0fc8285a Christoph Lameter 2007-05-06 781
2492268472e7d3 Christoph Lameter 2007-07-17 782 static void restore_bytes(struct kmem_cache *s, char *message, u8 data,
2492268472e7d3 Christoph Lameter 2007-07-17 783 void *from, void *to)
2492268472e7d3 Christoph Lameter 2007-07-17 784 {
2492268472e7d3 Christoph Lameter 2007-07-17 785 slab_fix(s, "Restoring 0x%p-0x%p=0x%x\n", from, to - 1, data);
2492268472e7d3 Christoph Lameter 2007-07-17 786 memset(from, data, to - from);
2492268472e7d3 Christoph Lameter 2007-07-17 787 }
2492268472e7d3 Christoph Lameter 2007-07-17 788
2492268472e7d3 Christoph Lameter 2007-07-17 789 static int check_bytes_and_report(struct kmem_cache *s, struct page *page,
2492268472e7d3 Christoph Lameter 2007-07-17 790 u8 *object, char *what,
2492268472e7d3 Christoph Lameter 2007-07-17 791 u8 *start, unsigned int value, unsigned int bytes)
2492268472e7d3 Christoph Lameter 2007-07-17 792 {
2492268472e7d3 Christoph Lameter 2007-07-17 793 u8 *fault;
2492268472e7d3 Christoph Lameter 2007-07-17 794 u8 *end;
e1b70dd1e6429f Miles Chen 2019-11-30 795 u8 *addr = page_address(page);
2492268472e7d3 Christoph Lameter 2007-07-17 796
a79316c6178ca4 Andrey Ryabinin 2015-02-13 797 metadata_access_enable();
aa1ef4d7b3f67f Andrey Konovalov 2020-12-22 798 fault = memchr_inv(kasan_reset_tag(start), value, bytes);
a79316c6178ca4 Andrey Ryabinin 2015-02-13 799 metadata_access_disable();
2492268472e7d3 Christoph Lameter 2007-07-17 800 if (!fault)
81819f0fc8285a Christoph Lameter 2007-05-06 801 return 1;
2492268472e7d3 Christoph Lameter 2007-07-17 802
2492268472e7d3 Christoph Lameter 2007-07-17 803 end = start + bytes;
2492268472e7d3 Christoph Lameter 2007-07-17 804 while (end > fault && end[-1] == value)
2492268472e7d3 Christoph Lameter 2007-07-17 805 end--;
2492268472e7d3 Christoph Lameter 2007-07-17 806
98f544695d3d3b Oliver Glitta 2021-03-30 @807 if (!(s->flags && SLAB_SILENT_ERRORS)) {
^^^^^^^^^^^^^^^^^^^^^

2492268472e7d3 Christoph Lameter 2007-07-17 808 slab_bug(s, "%s overwritten", what);
e1b70dd1e6429f Miles Chen 2019-11-30 809 pr_err("INFO: 0x%p-0x%p @offset=%tu. First byte 0x%x instead of 0x%x\n",
e1b70dd1e6429f Miles Chen 2019-11-30 810 fault, end - 1, fault - addr,
e1b70dd1e6429f Miles Chen 2019-11-30 811 fault[0], value);
2492268472e7d3 Christoph Lameter 2007-07-17 812 print_trailer(s, page, object);
98f544695d3d3b Oliver Glitta 2021-03-30 813 }
2492268472e7d3 Christoph Lameter 2007-07-17 814
2492268472e7d3 Christoph Lameter 2007-07-17 815 restore_bytes(s, what, value, fault, end);
2492268472e7d3 Christoph Lameter 2007-07-17 816 return 0;
81819f0fc8285a Christoph Lameter 2007-05-06 817 }

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/[email protected]


Attachments:
(No filename) (6.83 kB)
.config.gz (31.72 kB)
Download all attachments