From: Kaitao Cheng <[email protected]>

KF_ARG_PTR_TO_LIST_NODE normally requires an owning reference
(PTR_TO_BTF_ID | MEM_ALLOC and ref_obj_id). For bpf_list_add_impl's
third argument (prev), allow a non-owning reference with ref_obj_id==0
so that the result of bpf_list_front() or bpf_list_back() can be passed
as the insertion point. When prev is such a non-owning ref, skip the
MEM_ALLOC/ref_obj_id checks and jump to the shared list-node processing.
Owning refs (e.g. from pop + refcount_acquire) still pass the existing
checks and reach the same label.

Signed-off-by: Kaitao Cheng <[email protected]>
---
 kernel/bpf/verifier.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 98ddb370feb5..0a6f2e6a5d28 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -13737,6 +13737,14 @@ static int check_kfunc_args(struct bpf_verifier_env 
*env, struct bpf_kfunc_call_
                                return ret;
                        break;
                case KF_ARG_PTR_TO_LIST_NODE:
+                       if (meta->func_id == 
special_kfunc_list[KF_bpf_list_add_impl]
+                           && i == 2 && type_is_non_owning_ref(reg->type)
+                           && !reg->ref_obj_id) {
+                               /* Allow bpf_list_front/back return value as
+                                * list_add_impl's third arg (R3).
+                                */
+                               goto check_ok;
+                       }
                        if (reg->type != (PTR_TO_BTF_ID | MEM_ALLOC)) {
                                verbose(env, "arg#%d expected pointer to 
allocated object\n", i);
                                return -EINVAL;
@@ -13745,6 +13753,7 @@ static int check_kfunc_args(struct bpf_verifier_env 
*env, struct bpf_kfunc_call_
                                verbose(env, "allocated object must be 
referenced\n");
                                return -EINVAL;
                        }
+check_ok:
                        ret = process_kf_arg_ptr_to_list_node(env, reg, regno, 
meta);
                        if (ret < 0)
                                return ret;
-- 
2.50.1 (Apple Git-155)


Reply via email to