bpf: Use bpf_mem_free_rcu when bpf_obj_dropping refcounted nodes
authorDave Marchevsky <davemarchevsky@fb.com>
Mon, 21 Aug 2023 19:33:07 +0000 (12:33 -0700)
committerAlexei Starovoitov <ast@kernel.org>
Fri, 25 Aug 2023 16:23:16 +0000 (09:23 -0700)
This is the final fix for the use-after-free scenario described in
commit 7793fc3babe9 ("bpf: Make bpf_refcount_acquire fallible for
non-owning refs"). That commit, by virtue of changing
bpf_refcount_acquire's refcount_inc to a refcount_inc_not_zero, fixed
the "refcount incr on 0" splat. The not_zero check in
refcount_inc_not_zero, though, still occurs on memory that could have
been free'd and reused, so the commit didn't properly fix the root
cause.

This patch actually fixes the issue by free'ing using the recently-added
bpf_mem_free_rcu, which ensures that the memory is not reused until
RCU grace period has elapsed. If that has happened then
there are no non-owning references alive that point to the
recently-free'd memory, so it can be safely reused.

Signed-off-by: Dave Marchevsky <davemarchevsky@fb.com>
Acked-by: Yonghong Song <yonghong.song@linux.dev>
Link: https://lore.kernel.org/r/20230821193311.3290257-4-davemarchevsky@fb.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/helpers.c

index eb91cae..945a85e 100644 (file)
@@ -1913,7 +1913,11 @@ void __bpf_obj_drop_impl(void *p, const struct btf_record *rec)
 
        if (rec)
                bpf_obj_free_fields(rec, p);
 
        if (rec)
                bpf_obj_free_fields(rec, p);
-       bpf_mem_free(&bpf_global_ma, p);
+
+       if (rec && rec->refcount_off >= 0)
+               bpf_mem_free_rcu(&bpf_global_ma, p);
+       else
+               bpf_mem_free(&bpf_global_ma, p);
 }
 
 __bpf_kfunc void bpf_obj_drop_impl(void *p__alloc, void *meta__ign)
 }
 
 __bpf_kfunc void bpf_obj_drop_impl(void *p__alloc, void *meta__ign)