return (struct bpf_rb_node *)rb_first_cached(r);
 }
 
+__bpf_kfunc struct bpf_rb_node *bpf_rbtree_root(struct bpf_rb_root *root)
+{
+       struct rb_root_cached *r = (struct rb_root_cached *)root;
+
+       return (struct bpf_rb_node *)r->rb_root.rb_node;
+}
+
+__bpf_kfunc struct bpf_rb_node *bpf_rbtree_left(struct bpf_rb_root *root, struct bpf_rb_node *node)
+{
+       struct bpf_rb_node_kern *node_internal = (struct bpf_rb_node_kern *)node;
+
+       if (READ_ONCE(node_internal->owner) != root)
+               return NULL;
+
+       return (struct bpf_rb_node *)node_internal->rb_node.rb_left;
+}
+
+__bpf_kfunc struct bpf_rb_node *bpf_rbtree_right(struct bpf_rb_root *root, struct bpf_rb_node *node)
+{
+       struct bpf_rb_node_kern *node_internal = (struct bpf_rb_node_kern *)node;
+
+       if (READ_ONCE(node_internal->owner) != root)
+               return NULL;
+
+       return (struct bpf_rb_node *)node_internal->rb_node.rb_right;
+}
+
 /**
  * bpf_task_acquire - Acquire a reference to a task. A task acquired by this
  * kfunc which is not stored in a map as a kptr, must be released by calling
 BTF_ID_FLAGS(func, bpf_rbtree_remove, KF_ACQUIRE | KF_RET_NULL)
 BTF_ID_FLAGS(func, bpf_rbtree_add_impl)
 BTF_ID_FLAGS(func, bpf_rbtree_first, KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_rbtree_root, KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_rbtree_left, KF_RET_NULL)
+BTF_ID_FLAGS(func, bpf_rbtree_right, KF_RET_NULL)
 
 #ifdef CONFIG_CGROUPS
 BTF_ID_FLAGS(func, bpf_cgroup_acquire, KF_ACQUIRE | KF_RCU | KF_RET_NULL)
 
        KF_bpf_rbtree_remove,
        KF_bpf_rbtree_add_impl,
        KF_bpf_rbtree_first,
+       KF_bpf_rbtree_root,
+       KF_bpf_rbtree_left,
+       KF_bpf_rbtree_right,
        KF_bpf_dynptr_from_skb,
        KF_bpf_dynptr_from_xdp,
        KF_bpf_dynptr_slice,
 BTF_ID(func, bpf_rbtree_remove)
 BTF_ID(func, bpf_rbtree_add_impl)
 BTF_ID(func, bpf_rbtree_first)
+BTF_ID(func, bpf_rbtree_root)
+BTF_ID(func, bpf_rbtree_left)
+BTF_ID(func, bpf_rbtree_right)
 #ifdef CONFIG_NET
 BTF_ID(func, bpf_dynptr_from_skb)
 BTF_ID(func, bpf_dynptr_from_xdp)
 BTF_ID(func, bpf_rbtree_remove)
 BTF_ID(func, bpf_rbtree_add_impl)
 BTF_ID(func, bpf_rbtree_first)
+BTF_ID(func, bpf_rbtree_root)
+BTF_ID(func, bpf_rbtree_left)
+BTF_ID(func, bpf_rbtree_right)
 #ifdef CONFIG_NET
 BTF_ID(func, bpf_dynptr_from_skb)
 BTF_ID(func, bpf_dynptr_from_xdp)
 {
        return btf_id == special_kfunc_list[KF_bpf_rbtree_add_impl] ||
               btf_id == special_kfunc_list[KF_bpf_rbtree_remove] ||
-              btf_id == special_kfunc_list[KF_bpf_rbtree_first];
+              btf_id == special_kfunc_list[KF_bpf_rbtree_first] ||
+              btf_id == special_kfunc_list[KF_bpf_rbtree_root] ||
+              btf_id == special_kfunc_list[KF_bpf_rbtree_left] ||
+              btf_id == special_kfunc_list[KF_bpf_rbtree_right];
 }
 
 static bool is_bpf_iter_num_api_kfunc(u32 btf_id)
                break;
        case BPF_RB_NODE:
                ret = (kfunc_btf_id == special_kfunc_list[KF_bpf_rbtree_remove] ||
-                      kfunc_btf_id == special_kfunc_list[KF_bpf_rbtree_add_impl]);
+                      kfunc_btf_id == special_kfunc_list[KF_bpf_rbtree_add_impl] ||
+                      kfunc_btf_id == special_kfunc_list[KF_bpf_rbtree_left] ||
+                      kfunc_btf_id == special_kfunc_list[KF_bpf_rbtree_right]);
                break;
        default:
                verbose(env, "verifier internal error: unexpected graph node argument type %s\n",
                                }
                        } else {
                                if (!type_is_non_owning_ref(reg->type) || reg->ref_obj_id) {
-                                       verbose(env, "rbtree_remove node input must be non-owning ref\n");
+                                       verbose(env, "%s node input must be non-owning ref\n", func_name);
                                        return -EINVAL;
                                }
                                if (in_rbtree_lock_required_cb(env)) {
-                                       verbose(env, "rbtree_remove not allowed in rbtree cb\n");
+                                       verbose(env, "%s not allowed in rbtree cb\n", func_name);
                                        return -EINVAL;
                                }
                        }