Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include <test_progs.h>
0003 #include <network_helpers.h>
0004 
0005 #include "map_kptr.skel.h"
0006 #include "map_kptr_fail.skel.h"
0007 
0008 static char log_buf[1024 * 1024];
0009 
0010 struct {
0011     const char *prog_name;
0012     const char *err_msg;
0013 } map_kptr_fail_tests[] = {
0014     { "size_not_bpf_dw", "kptr access size must be BPF_DW" },
0015     { "non_const_var_off", "kptr access cannot have variable offset" },
0016     { "non_const_var_off_kptr_xchg", "R1 doesn't have constant offset. kptr has to be" },
0017     { "misaligned_access_write", "kptr access misaligned expected=8 off=7" },
0018     { "misaligned_access_read", "kptr access misaligned expected=8 off=1" },
0019     { "reject_var_off_store", "variable untrusted_ptr_ access var_off=(0x0; 0x1e0)" },
0020     { "reject_bad_type_match", "invalid kptr access, R1 type=untrusted_ptr_prog_test_ref_kfunc" },
0021     { "marked_as_untrusted_or_null", "R1 type=untrusted_ptr_or_null_ expected=percpu_ptr_" },
0022     { "correct_btf_id_check_size", "access beyond struct prog_test_ref_kfunc at off 32 size 4" },
0023     { "inherit_untrusted_on_walk", "R1 type=untrusted_ptr_ expected=percpu_ptr_" },
0024     { "reject_kptr_xchg_on_unref", "off=8 kptr isn't referenced kptr" },
0025     { "reject_kptr_get_no_map_val", "arg#0 expected pointer to map value" },
0026     { "reject_kptr_get_no_null_map_val", "arg#0 expected pointer to map value" },
0027     { "reject_kptr_get_no_kptr", "arg#0 no referenced kptr at map value offset=0" },
0028     { "reject_kptr_get_on_unref", "arg#0 no referenced kptr at map value offset=8" },
0029     { "reject_kptr_get_bad_type_match", "kernel function bpf_kfunc_call_test_kptr_get args#0" },
0030     { "mark_ref_as_untrusted_or_null", "R1 type=untrusted_ptr_or_null_ expected=percpu_ptr_" },
0031     { "reject_untrusted_store_to_ref", "store to referenced kptr disallowed" },
0032     { "reject_bad_type_xchg", "invalid kptr access, R2 type=ptr_prog_test_ref_kfunc expected=ptr_prog_test_member" },
0033     { "reject_untrusted_xchg", "R2 type=untrusted_ptr_ expected=ptr_" },
0034     { "reject_member_of_ref_xchg", "invalid kptr access, R2 type=ptr_prog_test_ref_kfunc" },
0035     { "reject_indirect_helper_access", "kptr cannot be accessed indirectly by helper" },
0036     { "reject_indirect_global_func_access", "kptr cannot be accessed indirectly by helper" },
0037     { "kptr_xchg_ref_state", "Unreleased reference id=5 alloc_insn=" },
0038     { "kptr_get_ref_state", "Unreleased reference id=3 alloc_insn=" },
0039 };
0040 
0041 static void test_map_kptr_fail_prog(const char *prog_name, const char *err_msg)
0042 {
0043     LIBBPF_OPTS(bpf_object_open_opts, opts, .kernel_log_buf = log_buf,
0044                         .kernel_log_size = sizeof(log_buf),
0045                         .kernel_log_level = 1);
0046     struct map_kptr_fail *skel;
0047     struct bpf_program *prog;
0048     int ret;
0049 
0050     skel = map_kptr_fail__open_opts(&opts);
0051     if (!ASSERT_OK_PTR(skel, "map_kptr_fail__open_opts"))
0052         return;
0053 
0054     prog = bpf_object__find_program_by_name(skel->obj, prog_name);
0055     if (!ASSERT_OK_PTR(prog, "bpf_object__find_program_by_name"))
0056         goto end;
0057 
0058     bpf_program__set_autoload(prog, true);
0059 
0060     ret = map_kptr_fail__load(skel);
0061     if (!ASSERT_ERR(ret, "map_kptr__load must fail"))
0062         goto end;
0063 
0064     if (!ASSERT_OK_PTR(strstr(log_buf, err_msg), "expected error message")) {
0065         fprintf(stderr, "Expected: %s\n", err_msg);
0066         fprintf(stderr, "Verifier: %s\n", log_buf);
0067     }
0068 
0069 end:
0070     map_kptr_fail__destroy(skel);
0071 }
0072 
0073 static void test_map_kptr_fail(void)
0074 {
0075     int i;
0076 
0077     for (i = 0; i < ARRAY_SIZE(map_kptr_fail_tests); i++) {
0078         if (!test__start_subtest(map_kptr_fail_tests[i].prog_name))
0079             continue;
0080         test_map_kptr_fail_prog(map_kptr_fail_tests[i].prog_name,
0081                     map_kptr_fail_tests[i].err_msg);
0082     }
0083 }
0084 
0085 static void test_map_kptr_success(bool test_run)
0086 {
0087     LIBBPF_OPTS(bpf_test_run_opts, opts,
0088         .data_in = &pkt_v4,
0089         .data_size_in = sizeof(pkt_v4),
0090         .repeat = 1,
0091     );
0092     struct map_kptr *skel;
0093     int key = 0, ret;
0094     char buf[16];
0095 
0096     skel = map_kptr__open_and_load();
0097     if (!ASSERT_OK_PTR(skel, "map_kptr__open_and_load"))
0098         return;
0099 
0100     ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.test_map_kptr_ref), &opts);
0101     ASSERT_OK(ret, "test_map_kptr_ref refcount");
0102     ASSERT_OK(opts.retval, "test_map_kptr_ref retval");
0103     ret = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.test_map_kptr_ref2), &opts);
0104     ASSERT_OK(ret, "test_map_kptr_ref2 refcount");
0105     ASSERT_OK(opts.retval, "test_map_kptr_ref2 retval");
0106 
0107     if (test_run)
0108         return;
0109 
0110     ret = bpf_map__update_elem(skel->maps.array_map,
0111                    &key, sizeof(key), buf, sizeof(buf), 0);
0112     ASSERT_OK(ret, "array_map update");
0113     ret = bpf_map__update_elem(skel->maps.array_map,
0114                    &key, sizeof(key), buf, sizeof(buf), 0);
0115     ASSERT_OK(ret, "array_map update2");
0116 
0117     ret = bpf_map__update_elem(skel->maps.hash_map,
0118                    &key, sizeof(key), buf, sizeof(buf), 0);
0119     ASSERT_OK(ret, "hash_map update");
0120     ret = bpf_map__delete_elem(skel->maps.hash_map, &key, sizeof(key), 0);
0121     ASSERT_OK(ret, "hash_map delete");
0122 
0123     ret = bpf_map__update_elem(skel->maps.hash_malloc_map,
0124                    &key, sizeof(key), buf, sizeof(buf), 0);
0125     ASSERT_OK(ret, "hash_malloc_map update");
0126     ret = bpf_map__delete_elem(skel->maps.hash_malloc_map, &key, sizeof(key), 0);
0127     ASSERT_OK(ret, "hash_malloc_map delete");
0128 
0129     ret = bpf_map__update_elem(skel->maps.lru_hash_map,
0130                    &key, sizeof(key), buf, sizeof(buf), 0);
0131     ASSERT_OK(ret, "lru_hash_map update");
0132     ret = bpf_map__delete_elem(skel->maps.lru_hash_map, &key, sizeof(key), 0);
0133     ASSERT_OK(ret, "lru_hash_map delete");
0134 
0135     map_kptr__destroy(skel);
0136 }
0137 
0138 void test_map_kptr(void)
0139 {
0140     if (test__start_subtest("success")) {
0141         test_map_kptr_success(false);
0142         /* Do test_run twice, so that we see refcount going back to 1
0143          * after we leave it in map from first iteration.
0144          */
0145         test_map_kptr_success(true);
0146     }
0147     test_map_kptr_fail();
0148 }