Skip to content

Commit 2e8eabe

Browse files
ameryhungKernel Patches Daemon
authored andcommitted
selftests/bpf: Test using cgroup storage in a tail call callee program
Check that a BPF program that uses cgroup storage cannot be added to a program array map. Signed-off-by: Amery Hung <[email protected]>
1 parent 4568af1 commit 2e8eabe

File tree

3 files changed

+122
-0
lines changed

3 files changed

+122
-0
lines changed

tools/testing/selftests/bpf/prog_tests/tailcalls.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "tailcall_freplace.skel.h"
99
#include "tc_bpf2bpf.skel.h"
1010
#include "tailcall_fail.skel.h"
11+
#include "tailcall_cgrp_storage_owner.skel.h"
12+
#include "tailcall_cgrp_storage.skel.h"
1113

1214
/* test_tailcall_1 checks basic functionality by patching multiple locations
1315
* in a single program for a single tail call slot with nop->jmp, jmp->nop
@@ -1648,6 +1650,52 @@ static void test_tailcall_bpf2bpf_freplace(void)
16481650
tc_bpf2bpf__destroy(tc_skel);
16491651
}
16501652

1653+
/*
1654+
* test_tail_call_cgrp_storage makes sure that callee programs cannot
1655+
* use cgroup storage
1656+
*/
1657+
static void test_tailcall_cgrp_storage(void)
1658+
{
1659+
int err, prog_fd, prog_array_fd, storage_map_fd, key = 0;
1660+
struct tailcall_cgrp_storage_owner *owner_skel;
1661+
struct tailcall_cgrp_storage *skel;
1662+
1663+
/*
1664+
* The first program loaded tailcalling into prog_array map becomes the
1665+
* owner. This is needed to allow prog map compatibility check to pass
1666+
* later during map_update.
1667+
*/
1668+
owner_skel = tailcall_cgrp_storage_owner__open_and_load();
1669+
if (!ASSERT_OK_PTR(owner_skel, "tailcall_cgrp_storage_owner__open"))
1670+
return;
1671+
1672+
prog_array_fd = bpf_map__fd(owner_skel->maps.prog_array);
1673+
storage_map_fd = bpf_map__fd(owner_skel->maps.storage_map);
1674+
1675+
skel = tailcall_cgrp_storage__open();
1676+
if (!ASSERT_OK_PTR(skel, "tailcall_cgrp_storage__open")) {
1677+
tailcall_cgrp_storage_owner__destroy(owner_skel);
1678+
return;
1679+
}
1680+
1681+
err = bpf_map__reuse_fd(skel->maps.prog_array, prog_array_fd);
1682+
ASSERT_OK(err, "bpf_map__reuse_fd(prog_array)");
1683+
1684+
err = bpf_map__reuse_fd(skel->maps.storage_map, storage_map_fd);
1685+
ASSERT_OK(err, "bpf_map__reuse_fd(storage_map)");
1686+
1687+
err = bpf_object__load(skel->obj);
1688+
ASSERT_OK(err, "bpf_object__load");
1689+
1690+
prog_fd = bpf_program__fd(skel->progs.callee_prog);
1691+
prog_array_fd = bpf_map__fd(skel->maps.prog_array);
1692+
1693+
err = bpf_map_update_elem(prog_array_fd, &key, &prog_fd, BPF_ANY);
1694+
ASSERT_ERR(err, "bpf_map_update_elem");
1695+
1696+
tailcall_cgrp_storage__destroy(skel);
1697+
}
1698+
16511699
static void test_tailcall_failure()
16521700
{
16531701
RUN_TESTS(tailcall_fail);
@@ -1705,6 +1753,8 @@ void test_tailcalls(void)
17051753
test_tailcall_freplace();
17061754
if (test__start_subtest("tailcall_bpf2bpf_freplace"))
17071755
test_tailcall_bpf2bpf_freplace();
1756+
if (test__start_subtest("tailcall_cgrp_storage"))
1757+
test_tailcall_cgrp_storage();
17081758
if (test__start_subtest("tailcall_failure"))
17091759
test_tailcall_failure();
17101760
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <vmlinux.h>
4+
#include <bpf/bpf_helpers.h>
5+
6+
struct {
7+
__uint(type, BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE);
8+
__type(key, struct bpf_cgroup_storage_key);
9+
__type(value, __u64);
10+
} storage_map SEC(".maps");
11+
12+
struct {
13+
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
14+
__uint(max_entries, 1);
15+
__uint(key_size, sizeof(__u32));
16+
__uint(value_size, sizeof(__u32));
17+
} prog_array SEC(".maps");
18+
19+
SEC("cgroup_skb/egress")
20+
int caller_prog(struct __sk_buff *skb)
21+
{
22+
bpf_tail_call(skb, &prog_array, 0);
23+
24+
return 1;
25+
}
26+
27+
SEC("cgroup_skb/egress")
28+
int callee_prog(struct __sk_buff *skb)
29+
{
30+
__u64 *storage;
31+
32+
storage = bpf_get_local_storage(&storage_map, 0);
33+
if (storage)
34+
*storage = 1;
35+
36+
return 1;
37+
}
38+
39+
char _license[] SEC("license") = "GPL";
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/bpf.h>
4+
#include <bpf/bpf_helpers.h>
5+
6+
struct {
7+
__uint(type, BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE);
8+
__type(key, struct bpf_cgroup_storage_key);
9+
__type(value, __u64);
10+
} storage_map SEC(".maps");
11+
12+
struct {
13+
__uint(type, BPF_MAP_TYPE_PROG_ARRAY);
14+
__uint(max_entries, 1);
15+
__uint(key_size, sizeof(__u32));
16+
__uint(value_size, sizeof(__u32));
17+
} prog_array SEC(".maps");
18+
19+
SEC("cgroup_skb/egress")
20+
int prog_array_owner(struct __sk_buff *skb)
21+
{
22+
__u64 *storage;
23+
24+
storage = bpf_get_local_storage(&storage_map, 0);
25+
if (storage)
26+
*storage = 1;
27+
28+
bpf_tail_call(skb, &prog_array, 0);
29+
30+
return 1;
31+
}
32+
33+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)