Skip to content

Commit 0fd7562

Browse files
andreimateiAlexei Starovoitov
authored and
Alexei Starovoitov
committed
selftest/bpf: Add test for var-offset stack access
Add a higher-level test (C BPF program) for the new functionality - variable access stack reads and writes. Signed-off-by: Andrei Matei <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent 7a22930 commit 0fd7562

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <test_progs.h>
3+
#include "test_stack_var_off.skel.h"
4+
5+
/* Test read and writes to the stack performed with offsets that are not
6+
* statically known.
7+
*/
8+
void test_stack_var_off(void)
9+
{
10+
int duration = 0;
11+
struct test_stack_var_off *skel;
12+
13+
skel = test_stack_var_off__open_and_load();
14+
if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
15+
return;
16+
17+
/* Give pid to bpf prog so it doesn't trigger for anyone else. */
18+
skel->bss->test_pid = getpid();
19+
/* Initialize the probe's input. */
20+
skel->bss->input[0] = 2;
21+
skel->bss->input[1] = 42; /* This will be returned in probe_res. */
22+
23+
if (!ASSERT_OK(test_stack_var_off__attach(skel), "skel_attach"))
24+
goto cleanup;
25+
26+
/* Trigger probe. */
27+
usleep(1);
28+
29+
if (CHECK(skel->bss->probe_res != 42, "check_probe_res",
30+
"wrong probe res: %d\n", skel->bss->probe_res))
31+
goto cleanup;
32+
33+
cleanup:
34+
test_stack_var_off__destroy(skel);
35+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/bpf.h>
4+
#include <bpf/bpf_helpers.h>
5+
6+
int probe_res;
7+
8+
char input[4] = {};
9+
int test_pid;
10+
11+
SEC("tracepoint/syscalls/sys_enter_nanosleep")
12+
int probe(void *ctx)
13+
{
14+
/* This BPF program performs variable-offset reads and writes on a
15+
* stack-allocated buffer.
16+
*/
17+
char stack_buf[16];
18+
unsigned long len;
19+
unsigned long last;
20+
21+
if ((bpf_get_current_pid_tgid() >> 32) != test_pid)
22+
return 0;
23+
24+
/* Copy the input to the stack. */
25+
__builtin_memcpy(stack_buf, input, 4);
26+
27+
/* The first byte in the buffer indicates the length. */
28+
len = stack_buf[0] & 0xf;
29+
last = (len - 1) & 0xf;
30+
31+
/* Append something to the buffer. The offset where we write is not
32+
* statically known; this is a variable-offset stack write.
33+
*/
34+
stack_buf[len] = 42;
35+
36+
/* Index into the buffer at an unknown offset. This is a
37+
* variable-offset stack read.
38+
*
39+
* Note that if it wasn't for the preceding variable-offset write, this
40+
* read would be rejected because the stack slot cannot be verified as
41+
* being initialized. With the preceding variable-offset write, the
42+
* stack slot still cannot be verified, but the write inhibits the
43+
* respective check on the reasoning that, if there was a
44+
* variable-offset to a higher-or-equal spot, we're probably reading
45+
* what we just wrote.
46+
*/
47+
probe_res = stack_buf[last];
48+
return 0;
49+
}
50+
51+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)