cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

map_kptr.c (5568B)


      1// SPDX-License-Identifier: GPL-2.0
      2#include <test_progs.h>
      3#include <network_helpers.h>
      4
      5#include "map_kptr.skel.h"
      6#include "map_kptr_fail.skel.h"
      7
      8static char log_buf[1024 * 1024];
      9
     10struct {
     11	const char *prog_name;
     12	const char *err_msg;
     13} map_kptr_fail_tests[] = {
     14	{ "size_not_bpf_dw", "kptr access size must be BPF_DW" },
     15	{ "non_const_var_off", "kptr access cannot have variable offset" },
     16	{ "non_const_var_off_kptr_xchg", "R1 doesn't have constant offset. kptr has to be" },
     17	{ "misaligned_access_write", "kptr access misaligned expected=8 off=7" },
     18	{ "misaligned_access_read", "kptr access misaligned expected=8 off=1" },
     19	{ "reject_var_off_store", "variable untrusted_ptr_ access var_off=(0x0; 0x1e0)" },
     20	{ "reject_bad_type_match", "invalid kptr access, R1 type=untrusted_ptr_prog_test_ref_kfunc" },
     21	{ "marked_as_untrusted_or_null", "R1 type=untrusted_ptr_or_null_ expected=percpu_ptr_" },
     22	{ "correct_btf_id_check_size", "access beyond struct prog_test_ref_kfunc at off 32 size 4" },
     23	{ "inherit_untrusted_on_walk", "R1 type=untrusted_ptr_ expected=percpu_ptr_" },
     24	{ "reject_kptr_xchg_on_unref", "off=8 kptr isn't referenced kptr" },
     25	{ "reject_kptr_get_no_map_val", "arg#0 expected pointer to map value" },
     26	{ "reject_kptr_get_no_null_map_val", "arg#0 expected pointer to map value" },
     27	{ "reject_kptr_get_no_kptr", "arg#0 no referenced kptr at map value offset=0" },
     28	{ "reject_kptr_get_on_unref", "arg#0 no referenced kptr at map value offset=8" },
     29	{ "reject_kptr_get_bad_type_match", "kernel function bpf_kfunc_call_test_kptr_get args#0" },
     30	{ "mark_ref_as_untrusted_or_null", "R1 type=untrusted_ptr_or_null_ expected=percpu_ptr_" },
     31	{ "reject_untrusted_store_to_ref", "store to referenced kptr disallowed" },
     32	{ "reject_bad_type_xchg", "invalid kptr access, R2 type=ptr_prog_test_ref_kfunc expected=ptr_prog_test_member" },
     33	{ "reject_untrusted_xchg", "R2 type=untrusted_ptr_ expected=ptr_" },
     34	{ "reject_member_of_ref_xchg", "invalid kptr access, R2 type=ptr_prog_test_ref_kfunc" },
     35	{ "reject_indirect_helper_access", "kptr cannot be accessed indirectly by helper" },
     36	{ "reject_indirect_global_func_access", "kptr cannot be accessed indirectly by helper" },
     37	{ "kptr_xchg_ref_state", "Unreleased reference id=5 alloc_insn=" },
     38	{ "kptr_get_ref_state", "Unreleased reference id=3 alloc_insn=" },
     39};
     40
     41static void test_map_kptr_fail_prog(const char *prog_name, const char *err_msg)
     42{
     43	LIBBPF_OPTS(bpf_object_open_opts, opts, .kernel_log_buf = log_buf,
     44						.kernel_log_size = sizeof(log_buf),
     45						.kernel_log_level = 1);
     46	struct map_kptr_fail *skel;
     47	struct bpf_program *prog;
     48	int ret;
     49
     50	skel = map_kptr_fail__open_opts(&opts);
     51	if (!ASSERT_OK_PTR(skel, "map_kptr_fail__open_opts"))
     52		return;
     53
     54	prog = bpf_object__find_program_by_name(skel->obj, prog_name);
     55	if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
     56		goto end;
     57
     58	bpf_program__set_autoload(prog, true);
     59
     60	ret = map_kptr_fail__load(skel);
     61	if (!ASSERT_ERR(ret, "map_kptr__load must fail"))
     62		goto end;
     63
     64	if (!ASSERT_OK_PTR(strstr(log_buf, err_msg), "expected error message")) {
     65		fprintf(stderr, "Expected: %s\n", err_msg);
     66		fprintf(stderr, "Verifier: %s\n", log_buf);
     67	}
     68
     69end:
     70	map_kptr_fail__destroy(skel);
     71}
     72
     73static void test_map_kptr_fail(void)
     74{
     75	int i;
     76
     77	for (i = 0; i < ARRAY_SIZE(map_kptr_fail_tests); i++) {
     78		if (!test__start_subtest(map_kptr_fail_tests[i].prog_name))
     79			continue;
     80		test_map_kptr_fail_prog(map_kptr_fail_tests[i].prog_name,
     81					map_kptr_fail_tests[i].err_msg);
     82	}
     83}
     84
     85static void test_map_kptr_success(bool test_run)
     86{
     87	LIBBPF_OPTS(bpf_test_run_opts, opts,
     88		.data_in = &pkt_v4,
     89		.data_size_in = sizeof(pkt_v4),
     90		.repeat = 1,
     91	);
     92	struct map_kptr *skel;
     93	int key = 0, ret;
     94	char buf[16];
     95
     96	skel = map_kptr__open_and_load();
     97	if (!ASSERT_OK_PTR(skel, "map_kptr__open_and_load"))
     98		return;
     99
    100	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.test_map_kptr_ref), &opts);
    101	ASSERT_OK(ret, "test_map_kptr_ref refcount");
    102	ASSERT_OK(opts.retval, "test_map_kptr_ref retval");
    103	ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.test_map_kptr_ref2), &opts);
    104	ASSERT_OK(ret, "test_map_kptr_ref2 refcount");
    105	ASSERT_OK(opts.retval, "test_map_kptr_ref2 retval");
    106
    107	if (test_run)
    108		return;
    109
    110	ret = bpf_map__update_elem(skel->maps.array_map,
    111				   &key, sizeof(key), buf, sizeof(buf), 0);
    112	ASSERT_OK(ret, "array_map update");
    113	ret = bpf_map__update_elem(skel->maps.array_map,
    114				   &key, sizeof(key), buf, sizeof(buf), 0);
    115	ASSERT_OK(ret, "array_map update2");
    116
    117	ret = bpf_map__update_elem(skel->maps.hash_map,
    118				   &key, sizeof(key), buf, sizeof(buf), 0);
    119	ASSERT_OK(ret, "hash_map update");
    120	ret = bpf_map__delete_elem(skel->maps.hash_map, &key, sizeof(key), 0);
    121	ASSERT_OK(ret, "hash_map delete");
    122
    123	ret = bpf_map__update_elem(skel->maps.hash_malloc_map,
    124				   &key, sizeof(key), buf, sizeof(buf), 0);
    125	ASSERT_OK(ret, "hash_malloc_map update");
    126	ret = bpf_map__delete_elem(skel->maps.hash_malloc_map, &key, sizeof(key), 0);
    127	ASSERT_OK(ret, "hash_malloc_map delete");
    128
    129	ret = bpf_map__update_elem(skel->maps.lru_hash_map,
    130				   &key, sizeof(key), buf, sizeof(buf), 0);
    131	ASSERT_OK(ret, "lru_hash_map update");
    132	ret = bpf_map__delete_elem(skel->maps.lru_hash_map, &key, sizeof(key), 0);
    133	ASSERT_OK(ret, "lru_hash_map delete");
    134
    135	map_kptr__destroy(skel);
    136}
    137
    138void test_map_kptr(void)
    139{
    140	if (test__start_subtest("success")) {
    141		test_map_kptr_success(false);
    142		/* Do test_run twice, so that we see refcount going back to 1
    143		 * after we leave it in map from first iteration.
    144		 */
    145		test_map_kptr_success(true);
    146	}
    147	test_map_kptr_fail();
    148}