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

selftests/bpf: Add selftests for bpf_task_from_pid()

Add some selftest testcases that validate the expected behavior of the
bpf_task_from_pid() kfunc that was added in the prior patch.

Signed-off-by: David Vernet <void@manifault.com>
Link: https://lore.kernel.org/r/20221122145300.251210-3-void@manifault.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

David Vernet and committed by
Alexei Starovoitov
f471748b 3f0e6f2b

+91
+4
tools/testing/selftests/bpf/prog_tests/task_kfunc.c
··· 78 78 "test_task_xchg_release", 79 79 "test_task_get_release", 80 80 "test_task_current_acquire_release", 81 + "test_task_from_pid_arg", 82 + "test_task_from_pid_current", 83 + "test_task_from_pid_invalid", 81 84 }; 82 85 83 86 static struct { ··· 102 99 {"task_kfunc_release_fp", "arg#0 pointer type STRUCT task_struct must point"}, 103 100 {"task_kfunc_release_null", "arg#0 is ptr_or_null_ expected ptr_ or socket"}, 104 101 {"task_kfunc_release_unacquired", "release kernel function bpf_task_release expects"}, 102 + {"task_kfunc_from_pid_no_null_check", "arg#0 is ptr_or_null_ expected ptr_ or socket"}, 105 103 }; 106 104 107 105 static void verify_fail(const char *prog_name, const char *expected_err_msg)
+1
tools/testing/selftests/bpf/progs/task_kfunc_common.h
··· 23 23 struct task_struct *bpf_task_acquire(struct task_struct *p) __ksym; 24 24 struct task_struct *bpf_task_kptr_get(struct task_struct **pp) __ksym; 25 25 void bpf_task_release(struct task_struct *p) __ksym; 26 + struct task_struct *bpf_task_from_pid(s32 pid) __ksym; 26 27 27 28 static inline struct __tasks_kfunc_map_value *tasks_kfunc_map_value_lookup(struct task_struct *p) 28 29 {
+13
tools/testing/selftests/bpf/progs/task_kfunc_failure.c
··· 258 258 259 259 return 0; 260 260 } 261 + 262 + SEC("tp_btf/task_newtask") 263 + int BPF_PROG(task_kfunc_from_pid_no_null_check, struct task_struct *task, u64 clone_flags) 264 + { 265 + struct task_struct *acquired; 266 + 267 + acquired = bpf_task_from_pid(task->pid); 268 + 269 + /* Releasing bpf_task_from_pid() lookup without a NULL check. */ 270 + bpf_task_release(acquired); 271 + 272 + return 0; 273 + }
+73
tools/testing/selftests/bpf/progs/task_kfunc_success.c
··· 147 147 148 148 return 0; 149 149 } 150 + 151 + static void lookup_compare_pid(const struct task_struct *p) 152 + { 153 + struct task_struct *acquired; 154 + 155 + acquired = bpf_task_from_pid(p->pid); 156 + if (!acquired) { 157 + err = 1; 158 + return; 159 + } 160 + 161 + if (acquired->pid != p->pid) 162 + err = 2; 163 + bpf_task_release(acquired); 164 + } 165 + 166 + SEC("tp_btf/task_newtask") 167 + int BPF_PROG(test_task_from_pid_arg, struct task_struct *task, u64 clone_flags) 168 + { 169 + struct task_struct *acquired; 170 + 171 + if (!is_test_kfunc_task()) 172 + return 0; 173 + 174 + lookup_compare_pid(task); 175 + return 0; 176 + } 177 + 178 + SEC("tp_btf/task_newtask") 179 + int BPF_PROG(test_task_from_pid_current, struct task_struct *task, u64 clone_flags) 180 + { 181 + struct task_struct *current, *acquired; 182 + 183 + if (!is_test_kfunc_task()) 184 + return 0; 185 + 186 + lookup_compare_pid(bpf_get_current_task_btf()); 187 + return 0; 188 + } 189 + 190 + static int is_pid_lookup_valid(s32 pid) 191 + { 192 + struct task_struct *acquired; 193 + 194 + acquired = bpf_task_from_pid(pid); 195 + if (acquired) { 196 + bpf_task_release(acquired); 197 + return 1; 198 + } 199 + 200 + return 0; 201 + } 202 + 203 + SEC("tp_btf/task_newtask") 204 + int BPF_PROG(test_task_from_pid_invalid, struct task_struct *task, u64 clone_flags) 205 + { 206 + struct task_struct *acquired; 207 + 208 + if (!is_test_kfunc_task()) 209 + return 0; 210 + 211 + if (is_pid_lookup_valid(-1)) { 212 + err = 1; 213 + return 0; 214 + } 215 + 216 + if (is_pid_lookup_valid(0xcafef00d)) { 217 + err = 2; 218 + return 0; 219 + } 220 + 221 + return 0; 222 + }