mirror of
https://github.com/torvalds/linux.git
synced 2026-09-11 20:13:02 +02:00
selftests/bpf: Check rbtree callback restrictions in subprogs
Add a verifier failure case where an rbtree comparator enters two nested static subprograms and the innermost subprogram unlocks and relocks the tree. Restoring the lock keeps the surrounding callback state balanced, so the test specifically exercises whether the callback restriction follows the nested calls. Also add a load-only positive control whose comparator calls a harmless static subprogram. This preserves the intended support for verified static subprogram calls while holding the tree lock. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Link: https://lore.kernel.org/r/20260903214758.2727663-3-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
369f4ce734
commit
22ab49afe1
|
|
@ -272,6 +272,47 @@ static bool less__bad_res_spin_unlock(struct bpf_rb_node *a, const struct bpf_rb
|
|||
return false;
|
||||
}
|
||||
|
||||
static __noinline void rbtree_cb_unlock_relock(void)
|
||||
{
|
||||
bpf_spin_unlock(&glock);
|
||||
bpf_spin_lock(&glock);
|
||||
}
|
||||
|
||||
static __noinline void rbtree_cb_nested_unlock(void)
|
||||
{
|
||||
rbtree_cb_unlock_relock();
|
||||
asm volatile ("");
|
||||
}
|
||||
|
||||
static bool less__bad_subprog_unlock(struct bpf_rb_node *a, const struct bpf_rb_node *b)
|
||||
{
|
||||
struct node_data *node_a;
|
||||
struct node_data *node_b;
|
||||
|
||||
node_a = container_of(a, struct node_data, node);
|
||||
node_b = container_of(b, struct node_data, node);
|
||||
rbtree_cb_nested_unlock();
|
||||
|
||||
return node_a->key < node_b->key;
|
||||
}
|
||||
|
||||
static __noinline void rbtree_cb_noop(void)
|
||||
{
|
||||
asm volatile ("");
|
||||
}
|
||||
|
||||
static bool less__subprog_allowed(struct bpf_rb_node *a, const struct bpf_rb_node *b)
|
||||
{
|
||||
struct node_data *node_a;
|
||||
struct node_data *node_b;
|
||||
|
||||
node_a = container_of(a, struct node_data, node);
|
||||
node_b = container_of(b, struct node_data, node);
|
||||
rbtree_cb_noop();
|
||||
|
||||
return node_a->key < node_b->key;
|
||||
}
|
||||
|
||||
static __always_inline
|
||||
long add_with_cb(bool (cb)(struct bpf_rb_node *a, const struct bpf_rb_node *b))
|
||||
{
|
||||
|
|
@ -330,4 +371,18 @@ long rbtree_api_add_bad_cb_res_spin_unlock(void *ctx)
|
|||
return 0;
|
||||
}
|
||||
|
||||
SEC("?tc")
|
||||
__failure __msg("can't spin_{lock,unlock} in rbtree cb")
|
||||
long rbtree_api_add_bad_cb_subprog_unlock(void *ctx)
|
||||
{
|
||||
return add_with_cb(less__bad_subprog_unlock);
|
||||
}
|
||||
|
||||
SEC("?tc")
|
||||
__success
|
||||
long rbtree_api_add_cb_subprog_allowed(void *ctx)
|
||||
{
|
||||
return add_with_cb(less__subprog_allowed);
|
||||
}
|
||||
|
||||
char _license[] SEC("license") = "GPL";
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user