[PATCH bpf-next v2 8/8] selftests/bpf: add tests to validate KASAN on JIT programs

Yonghong Song yonghong.song at linux.dev
Fri Jun 5 08:47:19 PDT 2026



On 6/4/26 1:22 PM, Alexis Lothoré (eBPF Foundation) wrote:
> Add a basic KASAN test runner that loads and test-run programs that can
> trigger memory management bugs. The test captures kernel logs and ensure
> that the expected KASAN splat is emitted by searching for the
> corresponding first lines in the report, hence validated that the needed
> instrumentation has been inserted by the JIT compiler before the
> relevant memory accesses.
>
> The runner covers different cases and settings: in the nominal case, it
> validates kasan reports on basic instructions (on all supported accesses
> sizes) but also when report _should not_ be emitted (eg: for accesses on
> program stack). The runner also comes with a few specialized tests that
> are then not executed for all sizes/locations. A few of those tests
> depends on cpuv4 (load_acquire and store_release).
>
>    # ./test_progs -a kasan
>    #164/1   kasan/st_1_not_on_stack:OK
>    #164/2   kasan/st_1_on_stack:OK
>    #164/3   kasan/st_2_not_on_stack:OK
>    #164/4   kasan/st_2_on_stack:OK
>    #164/5   kasan/st_4_not_on_stack:OK
>    #164/6   kasan/st_4_on_stack:OK
>    #164/7   kasan/st_8_not_on_stack:OK
>    #164/8   kasan/st_8_on_stack:OK
>    #164/9   kasan/stx_1_not_on_stack:OK
>    #164/10  kasan/stx_1_on_stack:OK
>    #164/11  kasan/stx_2_not_on_stack:OK
>    #164/12  kasan/stx_2_on_stack:OK
>    #164/13  kasan/stx_4_not_on_stack:OK
>    #164/14  kasan/stx_4_on_stack:OK
>    #164/15  kasan/stx_8_not_on_stack:OK
>    #164/16  kasan/stx_8_on_stack:OK
>    #164/17  kasan/ldx_1_not_on_stack:OK
>    #164/18  kasan/ldx_1_on_stack:OK
>    #164/19  kasan/ldx_2_not_on_stack:OK
>    #164/20  kasan/ldx_2_on_stack:OK
>    #164/21  kasan/ldx_4_not_on_stack:OK
>    #164/22  kasan/ldx_4_on_stack:OK
>    #164/23  kasan/ldx_8_not_on_stack:OK
>    #164/24  kasan/ldx_8_on_stack:OK
>    #164/25  kasan/simple_atomic_4_not_on_stack:OK
>    #164/26  kasan/simple_atomic_4_on_stack:OK
>    #164/27  kasan/simple_atomic_8_not_on_stack:OK
>    #164/28  kasan/simple_atomic_8_on_stack:OK
>    #164/29  kasan/load_acquire_1_not_on_stack:SKIP
>    #164/30  kasan/load_acquire_1_on_stack:SKIP
>    #164/31  kasan/load_acquire_2_not_on_stack:SKIP
>    #164/32  kasan/load_acquire_2_on_stack:SKIP
>    #164/33  kasan/load_acquire_4_not_on_stack:SKIP
>    #164/34  kasan/load_acquire_4_on_stack:SKIP
>    #164/35  kasan/load_acquire_8_not_on_stack:SKIP
>    #164/36  kasan/load_acquire_8_on_stack:SKIP
>    #164/37  kasan/store_release_1_not_on_stack:SKIP
>    #164/38  kasan/store_release_1_on_stack:SKIP
>    #164/39  kasan/store_release_2_not_on_stack:SKIP
>    #164/40  kasan/store_release_2_on_stack:SKIP
>    #164/41  kasan/store_release_4_not_on_stack:SKIP
>    #164/42  kasan/store_release_4_on_stack:SKIP
>    #164/43  kasan/store_release_8_not_on_stack:SKIP
>    #164/44  kasan/store_release_8_on_stack:SKIP
>    #164/45  kasan/ldx_patched:OK
>    #164/46  kasan/stack_and_non_stack:OK
>    #164     kasan:OK (SKIP: 16/46)
>    Summary: 1/30 PASSED, 16 SKIPPED, 0 FAILED

On my qemu run, I got a bunch of failures like below:

[root at arch-fb-vm1 bpf]# ./test_progs -n 164
test_kasan:PASS:alloc test ctx 0 nsec
gzopen /boot/config-7.1.0-rc5-gec86c8156bd6: No such file or directory
test_kasan:PASS:open prog 0 nsec
test_kasan:PASS:find rnd_hi32 prog 0 nsec
...
All error logs:
test_kasan:PASS:alloc test ctx 0 nsec
gzopen /boot/config-7.1.0-rc5-gec86c8156bd6: No such file or directory
test_kasan:PASS:open prog 0 nsec
test_kasan:PASS:find rnd_hi32 prog 0 nsec
test_kasan:PASS:load prog 0 nsec
test_kasan:PASS:open kernel logs 0 nsec
test_kasan:PASS:get map 0 nsec
test_kasan:PASS:set map 0 nsec
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/1   kasan/st_1_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/3   kasan/st_2_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/5   kasan/st_4_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/7   kasan/st_8_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/9   kasan/stx_1_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/11  kasan/stx_2_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/13  kasan/stx_4_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/15  kasan/stx_8_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/17  kasan/ldx_1_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/19  kasan/ldx_2_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/21  kasan/ldx_4_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/23  kasan/ldx_8_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/25  kasan/simple_atomic_4_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/27  kasan/simple_atomic_8_not_on_stack:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/45  kasan/ldx_patched:FAIL
run_subtest_with_size_and_location:PASS:find test prog 0 nsec
run_subtest_with_size_and_location:PASS:fetch loaded program info 0 nsec
run_subtest_with_size_and_location:PASS:run prog 0 nsec
run_subtest_with_size_and_location:PASS:read kernel logs 0 nsec
run_subtest_with_size_and_location:FAIL:report should be generated unexpected error: 1 (errno 11)
#164/46  kasan/stack_and_non_stack:FAIL
#164     kasan:FAIL

I checked the subtest 164/1,

For

         ret = check_kasan_report_in_kernel_logs(klog_buffer, ctx,
                                                 test->is_write, access_size);
         if (on_stack || test->expect_no_report)
                 ASSERT_NEQ(ret, 0, "no report should be generated");
         else
                 ASSERT_OK(ret, "report should be generated");

the ret is equal to 1 as klog_buffer is empty. This caused the failure.

>
> Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore at bootlin.com>
> ---
> Changes in v2:
> - simplify tests by just manually poisoning test areas with a dedicated
>    kfunc
> - introduce one prog per covered instruction family
> - make sure that tests do not consume kernel logs (use /dev/kmgs rather
>    than klogctl)
> - add tests for stack accesses:
>    - marking correctly set when there are diverging verifier states
>      leading to different memory types
>    - marking kept in sync with prog when it is patched
> ---
>   tools/testing/selftests/bpf/prog_tests/kasan.c     | 356 +++++++++++++++++++
>   tools/testing/selftests/bpf/progs/kasan.c          | 382 +++++++++++++++++++++
>   .../testing/selftests/bpf/test_kmods/bpf_testmod.c |  22 ++
>   3 files changed, 760 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/kasan.c b/tools/testing/selftests/bpf/prog_tests/kasan.c
> new file mode 100644
> index 000000000000..adf61e230ec9
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/kasan.c
> @@ -0,0 +1,356 @@
> +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
> +#include <bpf/bpf.h>
> +#include <errno.h>
> +#include <fcntl.h>
> +#include <linux/if_ether.h>
> +#include <unistd.h>
> +#include <test_progs.h>
> +#include <unpriv_helpers.h>
> +#include "kasan.skel.h"
> +
> +#define SUBTEST_NAME_MAX_LEN	128
> +#define PROG_NAME_MAX_LEN	128
> +
> +#define MAX_LOG_SIZE		(8 * 1024)
> +#define READ_CHUNK_SIZE		256
> +
> +#define KASAN_PATTERN_SLAB_UAF "BUG: KASAN: slab-use-after-free " \
> +	"in bpf_prog_%02x%02x%02x%02x%02x%02x%02x%02x_%s"
> +#define KASAN_PATTERN_REPORT "%s of size %d at addr"
> +
> +static char klog_buffer[MAX_LOG_SIZE];
> +
> +struct test_spec {
> +	char *prog_type;
> +	bool is_write;
> +	bool only_32_or_64;
> +	bool needs_load_acq_store_rel;
> +	bool skip_multi_size_testing;
> +	bool skip_on_stack_testing;
> +	int run_size;
> +	bool expect_no_report;

expect_no_report is not set in the code. The only usage is in

         if (on_stack || test->expect_no_report)
                 ASSERT_NEQ(ret, 0, "no report should be generated");
         else
                 ASSERT_OK(ret, "report should be generated");

> +	bool rnd_hi32;
> +};
> +
> +struct kasan_write_val {
> +	__u8 data_1;
> +	__u16 data_2;
> +	__u32 data_4;
> +	__u64 data_8;
> +};
> +
>
[...]




More information about the linux-arm-kernel mailing list