Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add uptr failure verifier tests

Add verifier tests to ensure invalid uptr usages are rejected.

Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20241023234759.860539-12-martin.lau@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Martin KaFai Lau and committed by
Alexei Starovoitov
898cbca4 cbf9f849

+107
+2
tools/testing/selftests/bpf/prog_tests/task_local_storage.c
··· 18 18 #include "uptr_test_common.h" 19 19 #include "task_ls_uptr.skel.h" 20 20 #include "uptr_update_failure.skel.h" 21 + #include "uptr_failure.skel.h" 21 22 22 23 static void test_sys_enter_exit(void) 23 24 { ··· 468 467 test_uptr_across_pages(); 469 468 if (test__start_subtest("uptr_update_failure")) 470 469 test_uptr_update_failure(); 470 + RUN_TESTS(uptr_failure); 471 471 }
+105
tools/testing/selftests/bpf/progs/uptr_failure.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */ 3 + 4 + #include <vmlinux.h> 5 + #include <bpf/bpf_helpers.h> 6 + #include "bpf_experimental.h" 7 + #include "bpf_misc.h" 8 + #include "uptr_test_common.h" 9 + 10 + struct { 11 + __uint(type, BPF_MAP_TYPE_TASK_STORAGE); 12 + __uint(map_flags, BPF_F_NO_PREALLOC); 13 + __type(key, int); 14 + __type(value, struct value_type); 15 + } datamap SEC(".maps"); 16 + 17 + SEC("?syscall") 18 + __failure __msg("store to uptr disallowed") 19 + int uptr_write(const void *ctx) 20 + { 21 + struct task_struct *task; 22 + struct value_type *v; 23 + 24 + task = bpf_get_current_task_btf(); 25 + v = bpf_task_storage_get(&datamap, task, 0, 26 + BPF_LOCAL_STORAGE_GET_F_CREATE); 27 + if (!v) 28 + return 0; 29 + 30 + v->udata = NULL; 31 + return 0; 32 + } 33 + 34 + SEC("?syscall") 35 + __failure __msg("store to uptr disallowed") 36 + int uptr_write_nested(const void *ctx) 37 + { 38 + struct task_struct *task; 39 + struct value_type *v; 40 + 41 + task = bpf_get_current_task_btf(); 42 + v = bpf_task_storage_get(&datamap, task, 0, 43 + BPF_LOCAL_STORAGE_GET_F_CREATE); 44 + if (!v) 45 + return 0; 46 + 47 + v->nested.udata = NULL; 48 + return 0; 49 + } 50 + 51 + SEC("?syscall") 52 + __failure __msg("R1 invalid mem access 'mem_or_null'") 53 + int uptr_no_null_check(const void *ctx) 54 + { 55 + struct task_struct *task; 56 + struct value_type *v; 57 + 58 + task = bpf_get_current_task_btf(); 59 + v = bpf_task_storage_get(&datamap, task, 0, 60 + BPF_LOCAL_STORAGE_GET_F_CREATE); 61 + if (!v) 62 + return 0; 63 + 64 + v->udata->result = 0; 65 + 66 + return 0; 67 + } 68 + 69 + SEC("?syscall") 70 + __failure __msg("doesn't point to kptr") 71 + int uptr_kptr_xchg(const void *ctx) 72 + { 73 + struct task_struct *task; 74 + struct value_type *v; 75 + 76 + task = bpf_get_current_task_btf(); 77 + v = bpf_task_storage_get(&datamap, task, 0, 78 + BPF_LOCAL_STORAGE_GET_F_CREATE); 79 + if (!v) 80 + return 0; 81 + 82 + bpf_kptr_xchg(&v->udata, NULL); 83 + 84 + return 0; 85 + } 86 + 87 + SEC("?syscall") 88 + __failure __msg("invalid mem access 'scalar'") 89 + int uptr_obj_new(const void *ctx) 90 + { 91 + struct value_type *v; 92 + 93 + v = bpf_obj_new(typeof(*v)); 94 + if (!v) 95 + return 0; 96 + 97 + if (v->udata) 98 + v->udata->result = 0; 99 + 100 + bpf_obj_drop(v); 101 + 102 + return 0; 103 + } 104 + 105 + char _license[] SEC("license") = "GPL";