* [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o @ 2020-09-28 14:41 Ahmad Fatoum 2020-09-28 14:41 ` [PATCH 2/2] lib: kasan: migrate Kconfig option to Debugging menu Ahmad Fatoum 2020-09-28 14:58 ` [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o Sascha Hauer 0 siblings, 2 replies; 7+ messages in thread From: Ahmad Fatoum @ 2020-09-28 14:41 UTC (permalink / raw) To: barebox; +Cc: Ahmad Fatoum We don't have anything that test_kasan.o can be generated out of, thus drop it to fix the build. It would still be nice to have this as a command, but that should be a separate patch. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> --- lib/kasan/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/kasan/Makefile b/lib/kasan/Makefile index 31e9d890d538..11106574e0c2 100644 --- a/lib/kasan/Makefile +++ b/lib/kasan/Makefile @@ -1,5 +1,5 @@ -obj-y += generic_report.o generic.o report.o common.o test_kasan.o +obj-y += generic_report.o generic.o report.o common.o KASAN_SANITIZE_generic_report.o := n KASAN_SANITIZE_generic.o := n KASAN_SANITIZE_report.o := n -- 2.28.0 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 2/2] lib: kasan: migrate Kconfig option to Debugging menu 2020-09-28 14:41 [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o Ahmad Fatoum @ 2020-09-28 14:41 ` Ahmad Fatoum 2020-09-29 6:37 ` Sascha Hauer 2020-09-28 14:58 ` [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o Sascha Hauer 1 sibling, 1 reply; 7+ messages in thread From: Ahmad Fatoum @ 2020-09-28 14:41 UTC (permalink / raw) To: barebox; +Cc: Ahmad Fatoum UBSAN and ASAN as well as other debugging aids are all in the Debugging menu. Relocate KASAN to be there as well. Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> --- common/Kconfig | 1 + lib/Kconfig | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/common/Kconfig b/common/Kconfig index 8b8b30db0fc7..9419977276b2 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -1379,6 +1379,7 @@ config PBL_BREAK on early pbl init. This option should be used only with JTAG debugger! source "lib/Kconfig.ubsan" +source "lib/kasan/Kconfig" config ASAN bool "ASAN: runtime memory debugger" diff --git a/lib/Kconfig b/lib/Kconfig index 6d909c1ac8f0..90552f3c2762 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -154,8 +154,6 @@ source "lib/logo/Kconfig" source "lib/bootstrap/Kconfig" -source "lib/kasan/Kconfig" - config PRINTF_UUID bool -- 2.28.0 _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 2/2] lib: kasan: migrate Kconfig option to Debugging menu 2020-09-28 14:41 ` [PATCH 2/2] lib: kasan: migrate Kconfig option to Debugging menu Ahmad Fatoum @ 2020-09-29 6:37 ` Sascha Hauer 0 siblings, 0 replies; 7+ messages in thread From: Sascha Hauer @ 2020-09-29 6:37 UTC (permalink / raw) To: Ahmad Fatoum; +Cc: barebox On Mon, Sep 28, 2020 at 04:41:46PM +0200, Ahmad Fatoum wrote: > UBSAN and ASAN as well as other debugging aids are all in the > Debugging menu. Relocate KASAN to be there as well. > > Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> > --- > common/Kconfig | 1 + > lib/Kconfig | 2 -- > 2 files changed, 1 insertion(+), 2 deletions(-) Applied, thanks Sascha > > diff --git a/common/Kconfig b/common/Kconfig > index 8b8b30db0fc7..9419977276b2 100644 > --- a/common/Kconfig > +++ b/common/Kconfig > @@ -1379,6 +1379,7 @@ config PBL_BREAK > on early pbl init. This option should be used only with JTAG debugger! > > source "lib/Kconfig.ubsan" > +source "lib/kasan/Kconfig" > > config ASAN > bool "ASAN: runtime memory debugger" > diff --git a/lib/Kconfig b/lib/Kconfig > index 6d909c1ac8f0..90552f3c2762 100644 > --- a/lib/Kconfig > +++ b/lib/Kconfig > @@ -154,8 +154,6 @@ source "lib/logo/Kconfig" > > source "lib/bootstrap/Kconfig" > > -source "lib/kasan/Kconfig" > - > config PRINTF_UUID > bool > > -- > 2.28.0 > > > _______________________________________________ > barebox mailing list > barebox@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/barebox > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o 2020-09-28 14:41 [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o Ahmad Fatoum 2020-09-28 14:41 ` [PATCH 2/2] lib: kasan: migrate Kconfig option to Debugging menu Ahmad Fatoum @ 2020-09-28 14:58 ` Sascha Hauer 2020-09-28 14:59 ` Ahmad Fatoum 1 sibling, 1 reply; 7+ messages in thread From: Sascha Hauer @ 2020-09-28 14:58 UTC (permalink / raw) To: Ahmad Fatoum; +Cc: barebox On Mon, Sep 28, 2020 at 04:41:45PM +0200, Ahmad Fatoum wrote: > We don't have anything that test_kasan.o can be generated out of, > thus drop it to fix the build. > > It would still be nice to have this as a command, but that > should be a separate patch. > > Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> > --- > lib/kasan/Makefile | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) I prefer to add the code that I have forgotten to git add ;) Sascha ----------------------8<----------------- From ff5cbfcbbe21d7883e3ce661fec3751f7cb7e58c Mon Sep 17 00:00:00 2001 From: Sascha Hauer <s.hauer@pengutronix.de> Date: Mon, 28 Sep 2020 16:56:36 +0200 Subject: [PATCH] KASan: Add missing test code Add missing test code. Fixes: 6cd9d2d600 ("Add KASan support") Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> --- lib/kasan/test_kasan.c | 478 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 478 insertions(+) create mode 100644 lib/kasan/test_kasan.c diff --git a/lib/kasan/test_kasan.c b/lib/kasan/test_kasan.c new file mode 100644 index 0000000000..e472bb3499 --- /dev/null +++ b/lib/kasan/test_kasan.c @@ -0,0 +1,478 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Author: Andrey Ryabinin <a.ryabinin@samsung.com> + */ + +#define pr_fmt(fmt) "kasan test: " fmt + +#include <common.h> +#include <command.h> +#include <complete.h> + +#include "kasan.h" + +/* + * We assign some test results to these globals to make sure the tests + * are not eliminated as dead code. + */ + +int kasan_int_result; +void *kasan_ptr_result; + +/* + * Note: test functions are marked noinline so that their names appear in + * reports. + */ + +static noinline void malloc_oob_right(void) +{ + char *ptr; + size_t size = 123; + + pr_info("out-of-bounds to right\n"); + ptr = malloc(size); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + ptr[size] = 'x'; + + free(ptr); +} + +static noinline void malloc_oob_left(void) +{ + char *ptr; + size_t size = 15; + + pr_info("out-of-bounds to left\n"); + ptr = malloc(size); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + *ptr = *(ptr - 1); + free(ptr); +} + +static noinline void malloc_oob_realloc_more(void) +{ + char *ptr1, *ptr2; + size_t size1 = 17; + size_t size2 = 19; + + pr_info("out-of-bounds after krealloc more\n"); + ptr1 = malloc(size1); + ptr2 = realloc(ptr1, size2); + if (!ptr1 || !ptr2) { + pr_err("Allocation failed\n"); + free(ptr1); + free(ptr2); + return; + } + + ptr2[size2] = 'x'; + + free(ptr2); +} + +static noinline void malloc_oob_realloc_less(void) +{ + char *ptr1, *ptr2; + size_t size1 = 17; + size_t size2 = 15; + + pr_info("out-of-bounds after krealloc less\n"); + ptr1 = malloc(size1); + ptr2 = realloc(ptr1, size2); + if (!ptr1 || !ptr2) { + pr_err("Allocation failed\n"); + free(ptr1); + return; + } + + ptr2[size2] = 'x'; + + free(ptr2); +} + +static noinline void malloc_oob_16(void) +{ + struct { + u64 words[2]; + } *ptr1, *ptr2; + + pr_info("malloc out-of-bounds for 16-bytes access\n"); + ptr1 = malloc(sizeof(*ptr1) - 3); + ptr2 = malloc(sizeof(*ptr2)); + if (!ptr1 || !ptr2) { + pr_err("Allocation failed\n"); + free(ptr1); + free(ptr2); + return; + } + *ptr1 = *ptr2; + free(ptr1); + free(ptr2); +} + +static noinline void malloc_oob_memset_2(void) +{ + char *ptr; + size_t size = 8; + + pr_info("out-of-bounds in memset2\n"); + ptr = malloc(size); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + memset(ptr + 7, 0, 2); + + free(ptr); +} + +static noinline void malloc_oob_memset_4(void) +{ + char *ptr; + size_t size = 8; + + pr_info("out-of-bounds in memset4\n"); + ptr = malloc(size); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + memset(ptr + 5, 0, 4); + + free(ptr); +} + + +static noinline void malloc_oob_memset_8(void) +{ + char *ptr; + size_t size = 8; + + pr_info("out-of-bounds in memset8\n"); + ptr = malloc(size); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + memset(ptr + 1, 0, 8); + + free(ptr); +} + +static noinline void malloc_oob_memset_16(void) +{ + char *ptr; + size_t size = 16; + + pr_info("out-of-bounds in memset16\n"); + ptr = malloc(size); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + memset(ptr + 1, 0, 16); + + free(ptr); +} + +static noinline void malloc_oob_in_memset(void) +{ + char *ptr; + size_t size = 666; + + pr_info("out-of-bounds in memset\n"); + ptr = malloc(size); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + memset(ptr, 0, size + 5); + + free(ptr); +} + +static noinline void malloc_uaf(void) +{ + char *ptr; + size_t size = 10; + + pr_info("use-after-free\n"); + ptr = malloc(size); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + free(ptr); + *(ptr + 8) = 'x'; +} + +static noinline void malloc_uaf_memset(void) +{ + char *ptr; + size_t size = 33; + + pr_info("use-after-free in memset\n"); + ptr = malloc(size); + if (!ptr) { + pr_err("Allocation failed\n"); + return; + } + + free(ptr); + memset(ptr, 0, size); +} + +static noinline void malloc_uaf2(void) +{ + char *ptr1, *ptr2; + size_t size = 43; + + pr_info("use-after-free after another malloc\n"); + ptr1 = malloc(size); + if (!ptr1) { + pr_err("Allocation failed\n"); + return; + } + + free(ptr1); + ptr2 = malloc(size); + if (!ptr2) { + pr_err("Allocation failed\n"); + return; + } + + ptr1[40] = 'x'; + if (ptr1 == ptr2) + pr_err("Could not detect use-after-free: ptr1 == ptr2\n"); + free(ptr2); +} + +static char global_array[10]; + +static noinline void kasan_global_oob(void) +{ + volatile int i = 3; + char *p = &global_array[ARRAY_SIZE(global_array) + i]; + + pr_info("out-of-bounds global variable\n"); + *(volatile char *)p; +} + +static noinline void kasan_stack_oob(void) +{ + char stack_array[10]; + volatile int i = 0; + char *p = &stack_array[ARRAY_SIZE(stack_array) + i]; + + pr_info("out-of-bounds on stack\n"); + *(volatile char *)p; +} + +static noinline void kasan_alloca_oob_left(void) +{ + volatile int i = 10; + char alloca_array[i]; + char *p = alloca_array - 1; + + pr_info("out-of-bounds to left on alloca\n"); + *(volatile char *)p; +} + +static noinline void kasan_alloca_oob_right(void) +{ + volatile int i = 10; + char alloca_array[i]; + char *p = alloca_array + i; + + pr_info("out-of-bounds to right on alloca\n"); + *(volatile char *)p; +} + +static noinline void kasan_memchr(void) +{ + char *ptr; + size_t size = 24; + + pr_info("out-of-bounds in memchr\n"); + ptr = kzalloc(size, 0); + if (!ptr) + return; + + kasan_ptr_result = memchr(ptr, '1', size + 1); + free(ptr); +} + +static noinline void kasan_memcmp(void) +{ + char *ptr; + size_t size = 24; + int arr[9]; + + pr_info("out-of-bounds in memcmp\n"); + ptr = kzalloc(size, 0); + if (!ptr) + return; + + memset(arr, 0, sizeof(arr)); + kasan_int_result = memcmp(ptr, arr, size + 1); + free(ptr); +} + +static noinline void kasan_strings(void) +{ + char *ptr; + size_t size = 24; + + pr_info("use-after-free in strchr\n"); + ptr = malloc(size); + if (!ptr) + return; + + free(ptr); + + /* + * Try to cause only 1 invalid access (less spam in dmesg). + * For that we need ptr to point to zeroed byte. + * Skip metadata that could be stored in freed object so ptr + * will likely point to zeroed byte. + */ + ptr += 16; + kasan_ptr_result = strchr(ptr, '1'); + + pr_info("use-after-free in strrchr\n"); + kasan_ptr_result = strrchr(ptr, '1'); + + pr_info("use-after-free in strcmp\n"); + kasan_int_result = strcmp(ptr, "2"); + + pr_info("use-after-free in strncmp\n"); + kasan_int_result = strncmp(ptr, "2", 1); + + pr_info("use-after-free in strlen\n"); + kasan_int_result = strlen(ptr); + + pr_info("use-after-free in strnlen\n"); + kasan_int_result = strnlen(ptr, 1); +} + +static noinline void kasan_bitops(void) +{ + /* + * Allocate 1 more byte, which causes kzalloc to round up to 16-bytes; + * this way we do not actually corrupt other memory. + */ + long *bits = xzalloc(sizeof(*bits) + 1); + if (!bits) + return; + + /* + * Below calls try to access bit within allocated memory; however, the + * below accesses are still out-of-bounds, since bitops are defined to + * operate on the whole long the bit is in. + */ + pr_info("out-of-bounds in set_bit\n"); + set_bit(BITS_PER_LONG, bits); + + pr_info("out-of-bounds in __set_bit\n"); + __set_bit(BITS_PER_LONG, bits); + + pr_info("out-of-bounds in clear_bit\n"); + clear_bit(BITS_PER_LONG, bits); + + pr_info("out-of-bounds in __clear_bit\n"); + __clear_bit(BITS_PER_LONG, bits); + + pr_info("out-of-bounds in change_bit\n"); + change_bit(BITS_PER_LONG, bits); + + pr_info("out-of-bounds in __change_bit\n"); + __change_bit(BITS_PER_LONG, bits); + + /* + * Below calls try to access bit beyond allocated memory. + */ + pr_info("out-of-bounds in test_and_set_bit\n"); + test_and_set_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); + + pr_info("out-of-bounds in __test_and_set_bit\n"); + __test_and_set_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); + + pr_info("out-of-bounds in test_and_clear_bit\n"); + test_and_clear_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); + + pr_info("out-of-bounds in __test_and_clear_bit\n"); + __test_and_clear_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); + + pr_info("out-of-bounds in test_and_change_bit\n"); + test_and_change_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); + + pr_info("out-of-bounds in __test_and_change_bit\n"); + __test_and_change_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); + + pr_info("out-of-bounds in test_bit\n"); + kasan_int_result = test_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); + +#if defined(clear_bit_unlock_is_negative_byte) + pr_info("out-of-bounds in clear_bit_unlock_is_negative_byte\n"); + kasan_int_result = clear_bit_unlock_is_negative_byte(BITS_PER_LONG + + BITS_PER_BYTE, bits); +#endif + free(bits); +} + +static int do_kasan_test(int argc, char *argv[]) +{ + /* + * Temporarily enable multi-shot mode. Otherwise, we'd only get a + * report for the first case. + */ + bool multishot = kasan_save_enable_multi_shot(); + + malloc_oob_right(); + malloc_oob_left(); + malloc_oob_realloc_more(); + malloc_oob_realloc_less(); + malloc_oob_16(); + malloc_oob_in_memset(); + malloc_oob_memset_2(); + malloc_oob_memset_4(); + malloc_oob_memset_8(); + malloc_oob_memset_16(); + malloc_uaf(); + malloc_uaf_memset(); + malloc_uaf2(); + kasan_stack_oob(); + kasan_global_oob(); + kasan_alloca_oob_left(); + kasan_alloca_oob_right(); + kasan_memchr(); + kasan_memcmp(); + kasan_strings(); + kasan_bitops(); + + kasan_restore_multi_shot(multishot); + + return 0; +} + +BAREBOX_CMD_START(kasan_tests) + .cmd = do_kasan_test, + BAREBOX_CMD_DESC("Run KAsan tests") + BAREBOX_CMD_COMPLETE(empty_complete) +BAREBOX_CMD_END -- 2.28.0 -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o 2020-09-28 14:58 ` [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o Sascha Hauer @ 2020-09-28 14:59 ` Ahmad Fatoum 2020-09-28 15:32 ` Sascha Hauer 0 siblings, 1 reply; 7+ messages in thread From: Ahmad Fatoum @ 2020-09-28 14:59 UTC (permalink / raw) To: Sascha Hauer; +Cc: barebox On 9/28/20 4:58 PM, Sascha Hauer wrote: > On Mon, Sep 28, 2020 at 04:41:45PM +0200, Ahmad Fatoum wrote: >> We don't have anything that test_kasan.o can be generated out of, >> thus drop it to fix the build. >> >> It would still be nice to have this as a command, but that >> should be a separate patch. >> >> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> >> --- >> lib/kasan/Makefile | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) > > I prefer to add the code that I have forgotten to git add ;) Wouldn't locating it in commands/ be better? > > Sascha > > ----------------------8<----------------- > > > From ff5cbfcbbe21d7883e3ce661fec3751f7cb7e58c Mon Sep 17 00:00:00 2001 > From: Sascha Hauer <s.hauer@pengutronix.de> > Date: Mon, 28 Sep 2020 16:56:36 +0200 > Subject: [PATCH] KASan: Add missing test code > > Add missing test code. > > Fixes: 6cd9d2d600 ("Add KASan support") > Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> > --- > lib/kasan/test_kasan.c | 478 +++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 478 insertions(+) > create mode 100644 lib/kasan/test_kasan.c > > diff --git a/lib/kasan/test_kasan.c b/lib/kasan/test_kasan.c > new file mode 100644 > index 0000000000..e472bb3499 > --- /dev/null > +++ b/lib/kasan/test_kasan.c > @@ -0,0 +1,478 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * > + * Copyright (c) 2014 Samsung Electronics Co., Ltd. > + * Author: Andrey Ryabinin <a.ryabinin@samsung.com> > + */ > + > +#define pr_fmt(fmt) "kasan test: " fmt > + > +#include <common.h> > +#include <command.h> > +#include <complete.h> > + > +#include "kasan.h" > + > +/* > + * We assign some test results to these globals to make sure the tests > + * are not eliminated as dead code. > + */ > + > +int kasan_int_result; > +void *kasan_ptr_result; > + > +/* > + * Note: test functions are marked noinline so that their names appear in > + * reports. > + */ > + > +static noinline void malloc_oob_right(void) > +{ > + char *ptr; > + size_t size = 123; > + > + pr_info("out-of-bounds to right\n"); > + ptr = malloc(size); > + if (!ptr) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + ptr[size] = 'x'; > + > + free(ptr); > +} > + > +static noinline void malloc_oob_left(void) > +{ > + char *ptr; > + size_t size = 15; > + > + pr_info("out-of-bounds to left\n"); > + ptr = malloc(size); > + if (!ptr) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + *ptr = *(ptr - 1); > + free(ptr); > +} > + > +static noinline void malloc_oob_realloc_more(void) > +{ > + char *ptr1, *ptr2; > + size_t size1 = 17; > + size_t size2 = 19; > + > + pr_info("out-of-bounds after krealloc more\n"); > + ptr1 = malloc(size1); > + ptr2 = realloc(ptr1, size2); > + if (!ptr1 || !ptr2) { > + pr_err("Allocation failed\n"); > + free(ptr1); > + free(ptr2); > + return; > + } > + > + ptr2[size2] = 'x'; > + > + free(ptr2); > +} > + > +static noinline void malloc_oob_realloc_less(void) > +{ > + char *ptr1, *ptr2; > + size_t size1 = 17; > + size_t size2 = 15; > + > + pr_info("out-of-bounds after krealloc less\n"); > + ptr1 = malloc(size1); > + ptr2 = realloc(ptr1, size2); > + if (!ptr1 || !ptr2) { > + pr_err("Allocation failed\n"); > + free(ptr1); > + return; > + } > + > + ptr2[size2] = 'x'; > + > + free(ptr2); > +} > + > +static noinline void malloc_oob_16(void) > +{ > + struct { > + u64 words[2]; > + } *ptr1, *ptr2; > + > + pr_info("malloc out-of-bounds for 16-bytes access\n"); > + ptr1 = malloc(sizeof(*ptr1) - 3); > + ptr2 = malloc(sizeof(*ptr2)); > + if (!ptr1 || !ptr2) { > + pr_err("Allocation failed\n"); > + free(ptr1); > + free(ptr2); > + return; > + } > + *ptr1 = *ptr2; > + free(ptr1); > + free(ptr2); > +} > + > +static noinline void malloc_oob_memset_2(void) > +{ > + char *ptr; > + size_t size = 8; > + > + pr_info("out-of-bounds in memset2\n"); > + ptr = malloc(size); > + if (!ptr) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + memset(ptr + 7, 0, 2); > + > + free(ptr); > +} > + > +static noinline void malloc_oob_memset_4(void) > +{ > + char *ptr; > + size_t size = 8; > + > + pr_info("out-of-bounds in memset4\n"); > + ptr = malloc(size); > + if (!ptr) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + memset(ptr + 5, 0, 4); > + > + free(ptr); > +} > + > + > +static noinline void malloc_oob_memset_8(void) > +{ > + char *ptr; > + size_t size = 8; > + > + pr_info("out-of-bounds in memset8\n"); > + ptr = malloc(size); > + if (!ptr) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + memset(ptr + 1, 0, 8); > + > + free(ptr); > +} > + > +static noinline void malloc_oob_memset_16(void) > +{ > + char *ptr; > + size_t size = 16; > + > + pr_info("out-of-bounds in memset16\n"); > + ptr = malloc(size); > + if (!ptr) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + memset(ptr + 1, 0, 16); > + > + free(ptr); > +} > + > +static noinline void malloc_oob_in_memset(void) > +{ > + char *ptr; > + size_t size = 666; > + > + pr_info("out-of-bounds in memset\n"); > + ptr = malloc(size); > + if (!ptr) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + memset(ptr, 0, size + 5); > + > + free(ptr); > +} > + > +static noinline void malloc_uaf(void) > +{ > + char *ptr; > + size_t size = 10; > + > + pr_info("use-after-free\n"); > + ptr = malloc(size); > + if (!ptr) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + free(ptr); > + *(ptr + 8) = 'x'; > +} > + > +static noinline void malloc_uaf_memset(void) > +{ > + char *ptr; > + size_t size = 33; > + > + pr_info("use-after-free in memset\n"); > + ptr = malloc(size); > + if (!ptr) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + free(ptr); > + memset(ptr, 0, size); > +} > + > +static noinline void malloc_uaf2(void) > +{ > + char *ptr1, *ptr2; > + size_t size = 43; > + > + pr_info("use-after-free after another malloc\n"); > + ptr1 = malloc(size); > + if (!ptr1) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + free(ptr1); > + ptr2 = malloc(size); > + if (!ptr2) { > + pr_err("Allocation failed\n"); > + return; > + } > + > + ptr1[40] = 'x'; > + if (ptr1 == ptr2) > + pr_err("Could not detect use-after-free: ptr1 == ptr2\n"); > + free(ptr2); > +} > + > +static char global_array[10]; > + > +static noinline void kasan_global_oob(void) > +{ > + volatile int i = 3; > + char *p = &global_array[ARRAY_SIZE(global_array) + i]; > + > + pr_info("out-of-bounds global variable\n"); > + *(volatile char *)p; > +} > + > +static noinline void kasan_stack_oob(void) > +{ > + char stack_array[10]; > + volatile int i = 0; > + char *p = &stack_array[ARRAY_SIZE(stack_array) + i]; > + > + pr_info("out-of-bounds on stack\n"); > + *(volatile char *)p; > +} > + > +static noinline void kasan_alloca_oob_left(void) > +{ > + volatile int i = 10; > + char alloca_array[i]; > + char *p = alloca_array - 1; > + > + pr_info("out-of-bounds to left on alloca\n"); > + *(volatile char *)p; > +} > + > +static noinline void kasan_alloca_oob_right(void) > +{ > + volatile int i = 10; > + char alloca_array[i]; > + char *p = alloca_array + i; > + > + pr_info("out-of-bounds to right on alloca\n"); > + *(volatile char *)p; > +} > + > +static noinline void kasan_memchr(void) > +{ > + char *ptr; > + size_t size = 24; > + > + pr_info("out-of-bounds in memchr\n"); > + ptr = kzalloc(size, 0); > + if (!ptr) > + return; > + > + kasan_ptr_result = memchr(ptr, '1', size + 1); > + free(ptr); > +} > + > +static noinline void kasan_memcmp(void) > +{ > + char *ptr; > + size_t size = 24; > + int arr[9]; > + > + pr_info("out-of-bounds in memcmp\n"); > + ptr = kzalloc(size, 0); > + if (!ptr) > + return; > + > + memset(arr, 0, sizeof(arr)); > + kasan_int_result = memcmp(ptr, arr, size + 1); > + free(ptr); > +} > + > +static noinline void kasan_strings(void) > +{ > + char *ptr; > + size_t size = 24; > + > + pr_info("use-after-free in strchr\n"); > + ptr = malloc(size); > + if (!ptr) > + return; > + > + free(ptr); > + > + /* > + * Try to cause only 1 invalid access (less spam in dmesg). > + * For that we need ptr to point to zeroed byte. > + * Skip metadata that could be stored in freed object so ptr > + * will likely point to zeroed byte. > + */ > + ptr += 16; > + kasan_ptr_result = strchr(ptr, '1'); > + > + pr_info("use-after-free in strrchr\n"); > + kasan_ptr_result = strrchr(ptr, '1'); > + > + pr_info("use-after-free in strcmp\n"); > + kasan_int_result = strcmp(ptr, "2"); > + > + pr_info("use-after-free in strncmp\n"); > + kasan_int_result = strncmp(ptr, "2", 1); > + > + pr_info("use-after-free in strlen\n"); > + kasan_int_result = strlen(ptr); > + > + pr_info("use-after-free in strnlen\n"); > + kasan_int_result = strnlen(ptr, 1); > +} > + > +static noinline void kasan_bitops(void) > +{ > + /* > + * Allocate 1 more byte, which causes kzalloc to round up to 16-bytes; > + * this way we do not actually corrupt other memory. > + */ > + long *bits = xzalloc(sizeof(*bits) + 1); > + if (!bits) > + return; > + > + /* > + * Below calls try to access bit within allocated memory; however, the > + * below accesses are still out-of-bounds, since bitops are defined to > + * operate on the whole long the bit is in. > + */ > + pr_info("out-of-bounds in set_bit\n"); > + set_bit(BITS_PER_LONG, bits); > + > + pr_info("out-of-bounds in __set_bit\n"); > + __set_bit(BITS_PER_LONG, bits); > + > + pr_info("out-of-bounds in clear_bit\n"); > + clear_bit(BITS_PER_LONG, bits); > + > + pr_info("out-of-bounds in __clear_bit\n"); > + __clear_bit(BITS_PER_LONG, bits); > + > + pr_info("out-of-bounds in change_bit\n"); > + change_bit(BITS_PER_LONG, bits); > + > + pr_info("out-of-bounds in __change_bit\n"); > + __change_bit(BITS_PER_LONG, bits); > + > + /* > + * Below calls try to access bit beyond allocated memory. > + */ > + pr_info("out-of-bounds in test_and_set_bit\n"); > + test_and_set_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); > + > + pr_info("out-of-bounds in __test_and_set_bit\n"); > + __test_and_set_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); > + > + pr_info("out-of-bounds in test_and_clear_bit\n"); > + test_and_clear_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); > + > + pr_info("out-of-bounds in __test_and_clear_bit\n"); > + __test_and_clear_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); > + > + pr_info("out-of-bounds in test_and_change_bit\n"); > + test_and_change_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); > + > + pr_info("out-of-bounds in __test_and_change_bit\n"); > + __test_and_change_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); > + > + pr_info("out-of-bounds in test_bit\n"); > + kasan_int_result = test_bit(BITS_PER_LONG + BITS_PER_BYTE, bits); > + > +#if defined(clear_bit_unlock_is_negative_byte) > + pr_info("out-of-bounds in clear_bit_unlock_is_negative_byte\n"); > + kasan_int_result = clear_bit_unlock_is_negative_byte(BITS_PER_LONG + > + BITS_PER_BYTE, bits); > +#endif > + free(bits); > +} > + > +static int do_kasan_test(int argc, char *argv[]) > +{ > + /* > + * Temporarily enable multi-shot mode. Otherwise, we'd only get a > + * report for the first case. > + */ > + bool multishot = kasan_save_enable_multi_shot(); > + > + malloc_oob_right(); > + malloc_oob_left(); > + malloc_oob_realloc_more(); > + malloc_oob_realloc_less(); > + malloc_oob_16(); > + malloc_oob_in_memset(); > + malloc_oob_memset_2(); > + malloc_oob_memset_4(); > + malloc_oob_memset_8(); > + malloc_oob_memset_16(); > + malloc_uaf(); > + malloc_uaf_memset(); > + malloc_uaf2(); > + kasan_stack_oob(); > + kasan_global_oob(); > + kasan_alloca_oob_left(); > + kasan_alloca_oob_right(); > + kasan_memchr(); > + kasan_memcmp(); > + kasan_strings(); > + kasan_bitops(); > + > + kasan_restore_multi_shot(multishot); > + > + return 0; > +} > + > +BAREBOX_CMD_START(kasan_tests) > + .cmd = do_kasan_test, > + BAREBOX_CMD_DESC("Run KAsan tests") > + BAREBOX_CMD_COMPLETE(empty_complete) > +BAREBOX_CMD_END > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o 2020-09-28 14:59 ` Ahmad Fatoum @ 2020-09-28 15:32 ` Sascha Hauer 2020-09-28 15:37 ` Ahmad Fatoum 0 siblings, 1 reply; 7+ messages in thread From: Sascha Hauer @ 2020-09-28 15:32 UTC (permalink / raw) To: Ahmad Fatoum; +Cc: barebox On Mon, Sep 28, 2020 at 04:59:40PM +0200, Ahmad Fatoum wrote: > On 9/28/20 4:58 PM, Sascha Hauer wrote: > > On Mon, Sep 28, 2020 at 04:41:45PM +0200, Ahmad Fatoum wrote: > >> We don't have anything that test_kasan.o can be generated out of, > >> thus drop it to fix the build. > >> > >> It would still be nice to have this as a command, but that > >> should be a separate patch. > >> > >> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> > >> --- > >> lib/kasan/Makefile | 2 +- > >> 1 file changed, 1 insertion(+), 1 deletion(-) > > > > I prefer to add the code that I have forgotten to git add ;) > > Wouldn't locating it in commands/ be better? It uses internal KASan functions. Putting it into commands would mean that we have to include "../lib/kasan/kasan.h". That's possible of course, but I thought it looks better that way. Sascha -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o 2020-09-28 15:32 ` Sascha Hauer @ 2020-09-28 15:37 ` Ahmad Fatoum 0 siblings, 0 replies; 7+ messages in thread From: Ahmad Fatoum @ 2020-09-28 15:37 UTC (permalink / raw) To: Sascha Hauer; +Cc: barebox On 9/28/20 5:32 PM, Sascha Hauer wrote: > On Mon, Sep 28, 2020 at 04:59:40PM +0200, Ahmad Fatoum wrote: >> On 9/28/20 4:58 PM, Sascha Hauer wrote: >>> On Mon, Sep 28, 2020 at 04:41:45PM +0200, Ahmad Fatoum wrote: >>>> We don't have anything that test_kasan.o can be generated out of, >>>> thus drop it to fix the build. >>>> >>>> It would still be nice to have this as a command, but that >>>> should be a separate patch. >>>> >>>> Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de> >>>> --- >>>> lib/kasan/Makefile | 2 +- >>>> 1 file changed, 1 insertion(+), 1 deletion(-) >>> >>> I prefer to add the code that I have forgotten to git add ;) >> >> Wouldn't locating it in commands/ be better? > > It uses internal KASan functions. Putting it into commands would mean > that we have to include "../lib/kasan/kasan.h". That's possible of > course, but I thought it looks better that way. Ok. > > Sascha > > -- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | _______________________________________________ barebox mailing list barebox@lists.infradead.org http://lists.infradead.org/mailman/listinfo/barebox ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2020-09-29 6:37 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2020-09-28 14:41 [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o Ahmad Fatoum 2020-09-28 14:41 ` [PATCH 2/2] lib: kasan: migrate Kconfig option to Debugging menu Ahmad Fatoum 2020-09-29 6:37 ` Sascha Hauer 2020-09-28 14:58 ` [PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o Sascha Hauer 2020-09-28 14:59 ` Ahmad Fatoum 2020-09-28 15:32 ` Sascha Hauer 2020-09-28 15:37 ` Ahmad Fatoum
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox