Commit e8699c4f authored by Kumar Kartikeya Dwivedi's avatar Kumar Kartikeya Dwivedi Committed by Alexei Starovoitov

selftests/bpf: Add test for static subprog call in lock cs

Add selftests for static subprog calls within bpf_spin_lock critical
section, and ensure we still reject global subprog calls. Also test the
case where a subprog call will unlock the caller's held lock, or the
caller will unlock a lock taken by a subprog call, ensuring correct
transfer of lock state across frames on exit.
Acked-by: default avatarYonghong Song <yonghong.song@linux.dev>
Acked-by: default avatarDavid Vernet <void@manifault.com>
Signed-off-by: default avatarKumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20240204222349.938118-3-memxor@gmail.comSigned-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent a44b1334
......@@ -48,6 +48,8 @@ static struct {
{ "lock_id_mismatch_innermapval_kptr", "bpf_spin_unlock of different lock" },
{ "lock_id_mismatch_innermapval_global", "bpf_spin_unlock of different lock" },
{ "lock_id_mismatch_innermapval_mapval", "bpf_spin_unlock of different lock" },
{ "lock_global_subprog_call1", "global function calls are not allowed while holding a lock" },
{ "lock_global_subprog_call2", "global function calls are not allowed while holding a lock" },
};
static int match_regex(const char *pattern, const char *string)
......
......@@ -101,4 +101,69 @@ int bpf_spin_lock_test(struct __sk_buff *skb)
err:
return err;
}
struct bpf_spin_lock lockA __hidden SEC(".data.A");
__noinline
static int static_subprog(struct __sk_buff *ctx)
{
volatile int ret = 0;
if (ctx->protocol)
return ret;
return ret + ctx->len;
}
__noinline
static int static_subprog_lock(struct __sk_buff *ctx)
{
volatile int ret = 0;
ret = static_subprog(ctx);
bpf_spin_lock(&lockA);
return ret + ctx->len;
}
__noinline
static int static_subprog_unlock(struct __sk_buff *ctx)
{
volatile int ret = 0;
ret = static_subprog(ctx);
bpf_spin_unlock(&lockA);
return ret + ctx->len;
}
SEC("tc")
int lock_static_subprog_call(struct __sk_buff *ctx)
{
int ret = 0;
bpf_spin_lock(&lockA);
if (ctx->mark == 42)
ret = static_subprog(ctx);
bpf_spin_unlock(&lockA);
return ret;
}
SEC("tc")
int lock_static_subprog_lock(struct __sk_buff *ctx)
{
int ret = 0;
ret = static_subprog_lock(ctx);
bpf_spin_unlock(&lockA);
return ret;
}
SEC("tc")
int lock_static_subprog_unlock(struct __sk_buff *ctx)
{
int ret = 0;
bpf_spin_lock(&lockA);
ret = static_subprog_unlock(ctx);
return ret;
}
char _license[] SEC("license") = "GPL";
......@@ -201,4 +201,48 @@ CHECK(innermapval_mapval, &iv->lock, &v->lock);
#undef CHECK
__noinline
int global_subprog(struct __sk_buff *ctx)
{
volatile int ret = 0;
if (ctx->protocol)
ret += ctx->protocol;
return ret + ctx->mark;
}
__noinline
static int static_subprog_call_global(struct __sk_buff *ctx)
{
volatile int ret = 0;
if (ctx->protocol)
return ret;
return ret + ctx->len + global_subprog(ctx);
}
SEC("?tc")
int lock_global_subprog_call1(struct __sk_buff *ctx)
{
int ret = 0;
bpf_spin_lock(&lockA);
if (ctx->mark == 42)
ret = global_subprog(ctx);
bpf_spin_unlock(&lockA);
return ret;
}
SEC("?tc")
int lock_global_subprog_call2(struct __sk_buff *ctx)
{
int ret = 0;
bpf_spin_lock(&lockA);
if (ctx->mark == 42)
ret = static_subprog_call_global(ctx);
bpf_spin_unlock(&lockA);
return ret;
}
char _license[] SEC("license") = "GPL";
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment