]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Introduce the bpf_list_del kfunc.
authorKaitao Cheng <chengkaitao@kylinos.cn>
Thu, 21 May 2026 03:23:02 +0000 (11:23 +0800)
committerAlexei Starovoitov <ast@kernel.org>
Thu, 21 May 2026 09:47:45 +0000 (02:47 -0700)
Allow users to remove any node from a linked list.

We have added an additional parameter bpf_list_head *head to
bpf_list_del, as the verifier requires the head parameter to
check whether the lock is being held.

Signed-off-by: Kaitao Cheng <chengkaitao@kylinos.cn>
Reviewed-by: Eduard Zingerman <eddyz87@gmail.com>
Link: https://lore.kernel.org/r/20260521032306.97118-5-kaitao.cheng@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/helpers.c
kernel/bpf/verifier.c

index 59855b434f0b2ed0fdd06ff5a3ff748ceb76495e..804c201c28f318928c76bab4357108f0e8401762 100644 (file)
@@ -2601,6 +2601,15 @@ __bpf_kfunc struct bpf_list_node *bpf_list_pop_back(struct bpf_list_head *head)
        return __bpf_list_del(head, h->prev);
 }
 
+__bpf_kfunc struct bpf_list_node *bpf_list_del(struct bpf_list_head *head,
+                                              struct bpf_list_node *node__nonown_allowed)
+{
+       struct bpf_list_node_kern *kn = (void *)node__nonown_allowed;
+
+       /* verifier guarantees node is a list node rather than list head */
+       return __bpf_list_del(head, &kn->list_head);
+}
+
 __bpf_kfunc struct bpf_list_node *bpf_list_front(struct bpf_list_head *head)
 {
        struct list_head *h = (struct list_head *)head;
@@ -4733,6 +4742,7 @@ BTF_ID_FLAGS(func, bpf_list_push_back, KF_IMPLICIT_ARGS)
 BTF_ID_FLAGS(func, bpf_list_push_back_impl)
 BTF_ID_FLAGS(func, bpf_list_pop_front, KF_ACQUIRE | KF_RET_NULL)
 BTF_ID_FLAGS(func, bpf_list_pop_back, KF_ACQUIRE | KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_list_del, KF_ACQUIRE | KF_RET_NULL)
 BTF_ID_FLAGS(func, bpf_list_front, KF_RET_NULL)
 BTF_ID_FLAGS(func, bpf_list_back, KF_RET_NULL)
 BTF_ID_FLAGS(func, bpf_task_acquire, KF_ACQUIRE | KF_RCU | KF_RET_NULL)
index f3cf8d85bea09bf8f68d6468e887da34dfdb03dc..35eebb5e77694a1b57112f374f04d4d99e00c287 100644 (file)
@@ -10961,6 +10961,7 @@ enum special_kfunc_type {
        KF_bpf_list_push_back,
        KF_bpf_list_pop_front,
        KF_bpf_list_pop_back,
+       KF_bpf_list_del,
        KF_bpf_list_front,
        KF_bpf_list_back,
        KF_bpf_cast_to_kern_ctx,
@@ -11029,6 +11030,7 @@ BTF_ID(func, bpf_list_push_back_impl)
 BTF_ID(func, bpf_list_push_back)
 BTF_ID(func, bpf_list_pop_front)
 BTF_ID(func, bpf_list_pop_back)
+BTF_ID(func, bpf_list_del)
 BTF_ID(func, bpf_list_front)
 BTF_ID(func, bpf_list_back)
 BTF_ID(func, bpf_cast_to_kern_ctx)
@@ -11549,6 +11551,7 @@ static bool is_bpf_list_api_kfunc(u32 btf_id)
        return is_bpf_list_push_kfunc(btf_id) ||
               btf_id == special_kfunc_list[KF_bpf_list_pop_front] ||
               btf_id == special_kfunc_list[KF_bpf_list_pop_back] ||
+              btf_id == special_kfunc_list[KF_bpf_list_del] ||
               btf_id == special_kfunc_list[KF_bpf_list_front] ||
               btf_id == special_kfunc_list[KF_bpf_list_back];
 }
@@ -11671,7 +11674,8 @@ static bool check_kfunc_is_graph_node_api(struct bpf_verifier_env *env,
 
        switch (node_field_type) {
        case BPF_LIST_NODE:
-               ret = is_bpf_list_push_kfunc(kfunc_btf_id);
+               ret = is_bpf_list_push_kfunc(kfunc_btf_id) ||
+                     kfunc_btf_id == special_kfunc_list[KF_bpf_list_del];
                break;
        case BPF_RB_NODE:
                ret = (is_bpf_rbtree_add_kfunc(kfunc_btf_id) ||