Re: [PATCH 1/2] selftests: add a kselftest for SLUB debugging functionality

2021-03-19 Thread Marco Elver
On Fri, 19 Mar 2021 at 11:46, Vlastimil Babka  wrote:
> On 3/18/21 12:47 PM, Marco Elver wrote:
> > On Tue, Mar 16, 2021 at 01:41PM +0100, glit...@gmail.com wrote:
> >> From: Oliver Glitta 
> >>
> >> SLUB has resiliency_test() function which is hidden behind #ifdef
> >> SLUB_RESILIENCY_TEST that is not part of Kconfig, so nobody
> >> runs it. Kselftest should 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_TEST_SLUB in Kconfig.
> >>
> >> Add parameter to function validate_slab_cache() to return
> >> number of errors in cache.
> >>
> >> Signed-off-by: Oliver Glitta 
> >
> > No objection per-se, but have you considered a KUnit-based test instead?
>
> To be honest, we didn't realize about that option.
>
> > There is no user space portion required to run this test, and a pure
> > in-kernel KUnit test would be cleaner. Various boiler-plate below,
> > including pr_err()s, the kselftest script etc. would simply not be
> > necessary.
> >
> > This is only a suggestion, but just want to make sure you've considered
> > the option and weighed its pros/cons.
>
> Thanks for the suggestion. But I hope we would expand the tests later to e.g.
> check the contents of various SLUB related sysfs files or even write to them,
> and for that goal kselftest seems to be a better starting place?

Not sure, but I would probably go about it this way:

A. Anything that is purely in-kernel and doesn't require a user space
component should be a KUnit test.

B. For any test that requires a user space component, it'd be a kselftest.

And I think the best design here would also clearly separate those 2
types of tests, and I wouldn't lump tests of type A into modules that
are also used for B. That way, running tests of type A also is a bit
easier, and if somebody wants to just quickly run those it's e.g. very
quick to do so with kunit-tool.

Thanks,
-- Marco


Re: [PATCH 1/2] selftests: add a kselftest for SLUB debugging functionality

2021-03-19 Thread Vlastimil Babka
On 3/18/21 12:47 PM, Marco Elver wrote:
> On Tue, Mar 16, 2021 at 01:41PM +0100, glit...@gmail.com wrote:
>> From: Oliver Glitta 
>> 
>> SLUB has resiliency_test() function which is hidden behind #ifdef
>> SLUB_RESILIENCY_TEST that is not part of Kconfig, so nobody
>> runs it. Kselftest should 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_TEST_SLUB in Kconfig.
>> 
>> Add parameter to function validate_slab_cache() to return
>> number of errors in cache.
>> 
>> Signed-off-by: Oliver Glitta 
> 
> No objection per-se, but have you considered a KUnit-based test instead?

To be honest, we didn't realize about that option.

> There is no user space portion required to run this test, and a pure
> in-kernel KUnit test would be cleaner. Various boiler-plate below,
> including pr_err()s, the kselftest script etc. would simply not be
> necessary.
> 
> This is only a suggestion, but just want to make sure you've considered
> the option and weighed its pros/cons.

Thanks for the suggestion. But I hope we would expand the tests later to e.g.
check the contents of various SLUB related sysfs files or even write to them,
and for that goal kselftest seems to be a better starting place?

Vlastimil


Re: [PATCH 1/2] selftests: add a kselftest for SLUB debugging functionality

2021-03-18 Thread Marco Elver
On Tue, Mar 16, 2021 at 01:41PM +0100, glit...@gmail.com wrote:
> From: Oliver Glitta 
> 
> SLUB has resiliency_test() function which is hidden behind #ifdef
> SLUB_RESILIENCY_TEST that is not part of Kconfig, so nobody
> runs it. Kselftest should 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_TEST_SLUB in Kconfig.
> 
> Add parameter to function validate_slab_cache() to return
> number of errors in cache.
> 
> Signed-off-by: Oliver Glitta 

No objection per-se, but have you considered a KUnit-based test instead?

There is no user space portion required to run this test, and a pure
in-kernel KUnit test would be cleaner. Various boiler-plate below,
including pr_err()s, the kselftest script etc. would simply not be
necessary.

This is only a suggestion, but just want to make sure you've considered
the option and weighed its pros/cons.

Thanks,
-- Marco

> ---
>  lib/Kconfig.debug|   4 +
>  lib/Makefile |   1 +
>  lib/test_slub.c  | 125 +++
>  mm/slab.h|   1 +
>  mm/slub.c|  34 +---
>  tools/testing/selftests/lib/Makefile |   2 +-
>  tools/testing/selftests/lib/config   |   1 +
>  tools/testing/selftests/lib/slub.sh  |   3 +
>  8 files changed, 159 insertions(+), 12 deletions(-)
>  create mode 100644 lib/test_slub.c
>  create mode 100755 tools/testing/selftests/lib/slub.sh
> 
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index 2779c29d9981..2d56092abbc4 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -2123,6 +2123,10 @@ config TEST_KSTRTOX
>  config TEST_PRINTF
>   tristate "Test printf() family of functions at runtime"
>  
> +config TEST_SLUB
> + tristate "Test SLUB cache errors at runtime"
> + depends on SLUB_DEBUG
> +
>  config TEST_BITMAP
>   tristate "Test bitmap_*() family of functions at runtime"
>   help
> diff --git a/lib/Makefile b/lib/Makefile
> index b5307d3eec1a..b6603803b1c4 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -83,6 +83,7 @@ obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
>  obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
>  obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
>  obj-$(CONFIG_TEST_PRINTF) += test_printf.o
> +obj-$(CONFIG_TEST_SLUB) += test_slub.o
>  obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
>  obj-$(CONFIG_TEST_STRSCPY) += test_strscpy.o
>  obj-$(CONFIG_TEST_UUID) += test_uuid.o
> diff --git a/lib/test_slub.c b/lib/test_slub.c
> new file mode 100644
> index ..0075d9b44251
> --- /dev/null
> +++ b/lib/test_slub.c
> @@ -0,0 +1,125 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Test cases for slub facility.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include "../mm/slab.h"
> +
> +#include "../tools/testing/selftests/kselftest_module.h"
> +
> +
> +KSTM_MODULE_GLOBALS();
> +
> +
> +static void __init validate_result(struct kmem_cache *s, int expected_errors)
> +{
> + int errors = 0;
> +
> + validate_slab_cache(s, );
> + KSTM_CHECK_ZERO(errors - expected_errors);
> +}
> +
> +static void __init test_clobber_zone(void)
> +{
> + struct kmem_cache *s = kmem_cache_create("TestSlub_RZ_alloc", 64, 0,
> + SLAB_RED_ZONE, NULL);
> + u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
> +
> + p[64] = 0x12;
> + pr_err("1. kmem_cache: Clobber Redzone 0x12->0x%p\n", p + 64);
> +
> + validate_result(s, 1);
> + kmem_cache_free(s, p);
> + kmem_cache_destroy(s);
> +}
> +
> +static void __init test_next_pointer(void)
> +{
> + struct kmem_cache *s = kmem_cache_create("TestSlub_next_ptr_free", 64, 
> 0,
> + SLAB_RED_ZONE, NULL);
> + u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
> +
> + kmem_cache_free(s, p);
> + p[s->offset] = 0x12;
> + pr_err("1. kmem_cache: Clobber next pointer 0x34 -> -0x%p\n", p);
> +
> + validate_result(s, 1);
> + kmem_cache_destroy(s);
> +}
> +
> +static void __init test_first_word(void)
> +{
> + struct kmem_cache *s = kmem_cache_create("TestSlub_1th_word_free", 64, 
> 0,
> + SLAB_POISON, NULL);
> + u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
> +
> + kmem_cache_free(s, p);
> + *p = 0x78;
> + pr_err("2. kmem_cache: Clobber first word 

Re: [PATCH 1/2] selftests: add a kselftest for SLUB debugging functionality

2021-03-17 Thread David Rientjes
On Tue, 16 Mar 2021, glit...@gmail.com wrote:

> From: Oliver Glitta 
> 
> SLUB has resiliency_test() function which is hidden behind #ifdef
> SLUB_RESILIENCY_TEST that is not part of Kconfig, so nobody
> runs it. Kselftest should 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_TEST_SLUB in Kconfig.
> 
> Add parameter to function validate_slab_cache() to return
> number of errors in cache.
> 
> Signed-off-by: Oliver Glitta 

Acked-by: David Rientjes 


Re: [PATCH 1/2] selftests: add a kselftest for SLUB debugging functionality

2021-03-17 Thread Vlastimil Babka
On 3/16/21 1:41 PM, glit...@gmail.com wrote:
> From: Oliver Glitta 
> 
> SLUB has resiliency_test() function which is hidden behind #ifdef
> SLUB_RESILIENCY_TEST that is not part of Kconfig, so nobody
> runs it. Kselftest should 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_TEST_SLUB in Kconfig.
> 
> Add parameter to function validate_slab_cache() to return
> number of errors in cache.
> 
> Signed-off-by: Oliver Glitta 

Acked-by: Vlastimil Babka 

Disclaimer: this is done as part of Oliver's university project that I'm 
advising.


[PATCH 1/2] selftests: add a kselftest for SLUB debugging functionality

2021-03-16 Thread glittao
From: Oliver Glitta 

SLUB has resiliency_test() function which is hidden behind #ifdef
SLUB_RESILIENCY_TEST that is not part of Kconfig, so nobody
runs it. Kselftest should 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_TEST_SLUB in Kconfig.

Add parameter to function validate_slab_cache() to return
number of errors in cache.

Signed-off-by: Oliver Glitta 
---
 lib/Kconfig.debug|   4 +
 lib/Makefile |   1 +
 lib/test_slub.c  | 125 +++
 mm/slab.h|   1 +
 mm/slub.c|  34 +---
 tools/testing/selftests/lib/Makefile |   2 +-
 tools/testing/selftests/lib/config   |   1 +
 tools/testing/selftests/lib/slub.sh  |   3 +
 8 files changed, 159 insertions(+), 12 deletions(-)
 create mode 100644 lib/test_slub.c
 create mode 100755 tools/testing/selftests/lib/slub.sh

diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 2779c29d9981..2d56092abbc4 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -2123,6 +2123,10 @@ config TEST_KSTRTOX
 config TEST_PRINTF
tristate "Test printf() family of functions at runtime"
 
+config TEST_SLUB
+   tristate "Test SLUB cache errors at runtime"
+   depends on SLUB_DEBUG
+
 config TEST_BITMAP
tristate "Test bitmap_*() family of functions at runtime"
help
diff --git a/lib/Makefile b/lib/Makefile
index b5307d3eec1a..b6603803b1c4 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -83,6 +83,7 @@ obj-$(CONFIG_TEST_USER_COPY) += test_user_copy.o
 obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_keys.o
 obj-$(CONFIG_TEST_STATIC_KEYS) += test_static_key_base.o
 obj-$(CONFIG_TEST_PRINTF) += test_printf.o
+obj-$(CONFIG_TEST_SLUB) += test_slub.o
 obj-$(CONFIG_TEST_BITMAP) += test_bitmap.o
 obj-$(CONFIG_TEST_STRSCPY) += test_strscpy.o
 obj-$(CONFIG_TEST_UUID) += test_uuid.o
diff --git a/lib/test_slub.c b/lib/test_slub.c
new file mode 100644
index ..0075d9b44251
--- /dev/null
+++ b/lib/test_slub.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Test cases for slub facility.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include "../mm/slab.h"
+
+#include "../tools/testing/selftests/kselftest_module.h"
+
+
+KSTM_MODULE_GLOBALS();
+
+
+static void __init validate_result(struct kmem_cache *s, int expected_errors)
+{
+   int errors = 0;
+
+   validate_slab_cache(s, );
+   KSTM_CHECK_ZERO(errors - expected_errors);
+}
+
+static void __init test_clobber_zone(void)
+{
+   struct kmem_cache *s = kmem_cache_create("TestSlub_RZ_alloc", 64, 0,
+   SLAB_RED_ZONE, NULL);
+   u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
+
+   p[64] = 0x12;
+   pr_err("1. kmem_cache: Clobber Redzone 0x12->0x%p\n", p + 64);
+
+   validate_result(s, 1);
+   kmem_cache_free(s, p);
+   kmem_cache_destroy(s);
+}
+
+static void __init test_next_pointer(void)
+{
+   struct kmem_cache *s = kmem_cache_create("TestSlub_next_ptr_free", 64, 
0,
+   SLAB_RED_ZONE, NULL);
+   u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
+
+   kmem_cache_free(s, p);
+   p[s->offset] = 0x12;
+   pr_err("1. kmem_cache: Clobber next pointer 0x34 -> -0x%p\n", p);
+
+   validate_result(s, 1);
+   kmem_cache_destroy(s);
+}
+
+static void __init test_first_word(void)
+{
+   struct kmem_cache *s = kmem_cache_create("TestSlub_1th_word_free", 64, 
0,
+   SLAB_POISON, NULL);
+   u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
+
+   kmem_cache_free(s, p);
+   *p = 0x78;
+   pr_err("2. kmem_cache: Clobber first word 0x78->0x%p\n", p);
+
+   validate_result(s, 1);
+   kmem_cache_destroy(s);
+}
+
+static void __init test_clobber_50th_byte(void)
+{
+   struct kmem_cache *s = kmem_cache_create("TestSlub_50th_word_free", 64, 
0,
+   SLAB_POISON, NULL);
+   u8 *p = kmem_cache_alloc(s, GFP_KERNEL);
+
+   kmem_cache_free(s, p);
+   p[50] = 0x9a;
+   pr_err("3. kmem_cache: Clobber 50th byte 0x9a->0x%p\n", p);
+
+   validate_result(s, 1);
+   kmem_cache_destroy(s);
+}
+
+static void __init test_clobber_redzone_free(void)
+{
+   struct kmem_cache *s = kmem_cache_create("TestSlub_RZ_free", 64, 0,
+   SLAB_RED_ZONE, NULL);
+   u8