Skip to content

Commit bd0b483

Browse files
Amery HungAlexei Starovoitov
authored andcommitted
selftests/bpf: Make sure stashed kptr in local kptr is freed recursively
When dropping a local kptr, any kptr stashed into it is supposed to be freed through bpf_obj_free_fields->__bpf_obj_drop_impl recursively. Add a test to make sure it happens. The test first stashes a referenced kptr to "struct task" into a local kptr and gets the reference count of the task. Then, it drops the local kptr and reads the reference count of the task again. Since bpf_obj_free_fields and __bpf_obj_drop_impl will go through the local kptr recursively during bpf_obj_drop, the dtor of the stashed task kptr should eventually be called. The second reference count should be one less than the first one. Signed-off-by: Amery Hung <[email protected]> Acked-by: Martin KaFai Lau <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent c634d6f commit bd0b483

File tree

1 file changed

+29
-1
lines changed

1 file changed

+29
-1
lines changed

tools/testing/selftests/bpf/progs/task_kfunc_success.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,9 @@ int BPF_PROG(test_task_acquire_leave_in_map, struct task_struct *task, u64 clone
143143
SEC("tp_btf/task_newtask")
144144
int BPF_PROG(test_task_xchg_release, struct task_struct *task, u64 clone_flags)
145145
{
146-
struct task_struct *kptr;
146+
struct task_struct *kptr, *acquired;
147147
struct __tasks_kfunc_map_value *v, *local;
148+
int refcnt, refcnt_after_drop;
148149
long status;
149150

150151
if (!is_test_kfunc_task())
@@ -190,7 +191,34 @@ int BPF_PROG(test_task_xchg_release, struct task_struct *task, u64 clone_flags)
190191
return 0;
191192
}
192193

194+
/* Stash a copy into local kptr and check if it is released recursively */
195+
acquired = bpf_task_acquire(kptr);
196+
if (!acquired) {
197+
err = 7;
198+
bpf_obj_drop(local);
199+
bpf_task_release(kptr);
200+
return 0;
201+
}
202+
bpf_probe_read_kernel(&refcnt, sizeof(refcnt), &acquired->rcu_users);
203+
204+
acquired = bpf_kptr_xchg(&local->task, acquired);
205+
if (acquired) {
206+
err = 8;
207+
bpf_obj_drop(local);
208+
bpf_task_release(kptr);
209+
bpf_task_release(acquired);
210+
return 0;
211+
}
212+
193213
bpf_obj_drop(local);
214+
215+
bpf_probe_read_kernel(&refcnt_after_drop, sizeof(refcnt_after_drop), &kptr->rcu_users);
216+
if (refcnt != refcnt_after_drop + 1) {
217+
err = 9;
218+
bpf_task_release(kptr);
219+
return 0;
220+
}
221+
194222
bpf_task_release(kptr);
195223

196224
return 0;

0 commit comments

Comments
 (0)