Skip to content

Commit

Permalink
selftests/bpf: Add test for static subprog call in lock cs
Browse files Browse the repository at this point in the history
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: Yonghong Song <yonghong.song@linux.dev>
Acked-by: David Vernet <void@manifault.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Link: https://lore.kernel.org/r/20240204222349.938118-3-memxor@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
  • Loading branch information
Kumar Kartikeya Dwivedi authored and Alexei Starovoitov committed Feb 6, 2024
1 parent a44b133 commit e8699c4
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 0 deletions.
2 changes: 2 additions & 0 deletions tools/testing/selftests/bpf/prog_tests/spin_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
65 changes: 65 additions & 0 deletions tools/testing/selftests/bpf/progs/test_spin_lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";
44 changes: 44 additions & 0 deletions tools/testing/selftests/bpf/progs/test_spin_lock_fail.c
Original file line number Diff line number Diff line change
Expand Up @@ -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";

0 comments on commit e8699c4

Please sign in to comment.