Skip to content

Commit 378d713

Browse files
danobikernel-patches-bot
authored andcommitted
selftest/bpf: Test bpf_probe_read_user_str() strips trailing bytes after NUL
Previously, bpf_probe_read_user_str() could potentially overcopy the trailing bytes after the NUL due to how do_strncpy_from_user() does the copy in long-sized strides. The issue has been fixed in the previous commit. This commit adds a selftest that ensures we don't regress bpf_probe_read_user_str() again. Acked-by: Song Liu <[email protected]> Acked-by: Andrii Nakryiko <[email protected]> Signed-off-by: Daniel Xu <[email protected]>
1 parent a299f43 commit 378d713

File tree

2 files changed

+96
-0
lines changed

2 files changed

+96
-0
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <test_progs.h>
3+
#include "test_probe_read_user_str.skel.h"
4+
5+
static const char str1[] = "mestring";
6+
static const char str2[] = "mestringalittlebigger";
7+
static const char str3[] = "mestringblubblubblubblubblub";
8+
9+
static int test_one_str(struct test_probe_read_user_str *skel, const char *str,
10+
size_t len)
11+
{
12+
int err, duration = 0;
13+
char buf[256];
14+
15+
/* Ensure bytes after string are ones */
16+
memset(buf, 1, sizeof(buf));
17+
memcpy(buf, str, len);
18+
19+
/* Give prog our userspace pointer */
20+
skel->bss->user_ptr = buf;
21+
22+
/* Trigger tracepoint */
23+
usleep(1);
24+
25+
/* Did helper fail? */
26+
if (CHECK(skel->bss->ret < 0, "prog_ret", "prog returned: %ld\n",
27+
skel->bss->ret))
28+
return 1;
29+
30+
/* Check that string was copied correctly */
31+
err = memcmp(skel->bss->buf, str, len);
32+
if (CHECK(err, "memcmp", "prog copied wrong string"))
33+
return 1;
34+
35+
/* Now check that no extra trailing bytes were copied */
36+
memset(buf, 0, sizeof(buf));
37+
err = memcmp(skel->bss->buf + len, buf, sizeof(buf) - len);
38+
if (CHECK(err, "memcmp", "trailing bytes were not stripped"))
39+
return 1;
40+
41+
return 0;
42+
}
43+
44+
void test_probe_read_user_str(void)
45+
{
46+
struct test_probe_read_user_str *skel;
47+
int err, duration = 0;
48+
49+
skel = test_probe_read_user_str__open_and_load();
50+
if (CHECK(!skel, "test_probe_read_user_str__open_and_load",
51+
"skeleton open and load failed\n"))
52+
return;
53+
54+
/* Give pid to bpf prog so it doesn't read from anyone else */
55+
skel->bss->pid = getpid();
56+
57+
err = test_probe_read_user_str__attach(skel);
58+
if (CHECK(err, "test_probe_read_user_str__attach",
59+
"skeleton attach failed: %d\n", err))
60+
goto out;
61+
62+
if (test_one_str(skel, str1, sizeof(str1)))
63+
goto out;
64+
if (test_one_str(skel, str2, sizeof(str2)))
65+
goto out;
66+
if (test_one_str(skel, str3, sizeof(str3)))
67+
goto out;
68+
69+
out:
70+
test_probe_read_user_str__destroy(skel);
71+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
#include <linux/bpf.h>
4+
#include <bpf/bpf_helpers.h>
5+
#include <bpf/bpf_tracing.h>
6+
7+
#include <sys/types.h>
8+
9+
pid_t pid = 0;
10+
long ret = 0;
11+
void *user_ptr = 0;
12+
char buf[256] = {};
13+
14+
SEC("tracepoint/syscalls/sys_enter_nanosleep")
15+
int on_write(void *ctx)
16+
{
17+
if (pid != (bpf_get_current_pid_tgid() >> 32))
18+
return 0;
19+
20+
ret = bpf_probe_read_user_str(buf, sizeof(buf), user_ptr);
21+
22+
return 0;
23+
}
24+
25+
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)