[PATCH 1/2] lib: kasan: remove reference of non-existent test_kasan.o

Ahmad Fatoum a.fatoum at pengutronix.de
Mon Sep 28 10:59:40 EDT 2020


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 at 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 at 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 at 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 at 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 |



More information about the barebox mailing list