Skip to content

Commit 437ffcb

Browse files
committed
Merge branch 'current_pid_tgid-for-all-prog-types'
Yonghong Song says: ==================== current_pid_tgid() for all prog types Currently bpf_get_current_pid_tgid() is allowed in tracing, cgroup and sk_msg progs while bpf_get_ns_current_pid_tgid() is only allowed in tracing progs. We have an internal use case where for an application running in a container (with pid namespace), user wants to get the pid associated with the pid namespace in a cgroup bpf program. Besides cgroup, the only prog type, supporting bpf_get_current_pid_tgid() but not bpf_get_ns_current_pid_tgid(), is sk_msg. But actually both bpf_get_current_pid_tgid() and bpf_get_ns_current_pid_tgid() helpers do not reveal kernel internal data and there is no reason that they cannot be used in other program types. This patch just did this and enabled these two helpers for all program types. Patch 1 added the kernel support and patches 2-5 added the test for cgroup and sk_msg. Change logs: v1 -> v2: - allow bpf_get_[ns_]current_pid_tgid() for all prog types. - for network related selftests, using netns. ==================== Link: https://lore.kernel.org/r/20240315184849.2974556-1-yonghong.song@linux.dev Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
2 parents 1a4a0cb + 4c195ee commit 437ffcb

File tree

6 files changed

+215
-42
lines changed

6 files changed

+215
-42
lines changed

kernel/bpf/cgroup.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,8 +2575,6 @@ cgroup_current_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
25752575
switch (func_id) {
25762576
case BPF_FUNC_get_current_uid_gid:
25772577
return &bpf_get_current_uid_gid_proto;
2578-
case BPF_FUNC_get_current_pid_tgid:
2579-
return &bpf_get_current_pid_tgid_proto;
25802578
case BPF_FUNC_get_current_comm:
25812579
return &bpf_get_current_comm_proto;
25822580
#ifdef CONFIG_CGROUP_NET_CLASSID

kernel/bpf/helpers.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,6 +1730,10 @@ bpf_base_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
17301730
return &bpf_strtol_proto;
17311731
case BPF_FUNC_strtoul:
17321732
return &bpf_strtoul_proto;
1733+
case BPF_FUNC_get_current_pid_tgid:
1734+
return &bpf_get_current_pid_tgid_proto;
1735+
case BPF_FUNC_get_ns_current_pid_tgid:
1736+
return &bpf_get_ns_current_pid_tgid_proto;
17331737
default:
17341738
break;
17351739
}

kernel/trace/bpf_trace.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,8 +1525,6 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
15251525
return &bpf_ktime_get_boot_ns_proto;
15261526
case BPF_FUNC_tail_call:
15271527
return &bpf_tail_call_proto;
1528-
case BPF_FUNC_get_current_pid_tgid:
1529-
return &bpf_get_current_pid_tgid_proto;
15301528
case BPF_FUNC_get_current_task:
15311529
return &bpf_get_current_task_proto;
15321530
case BPF_FUNC_get_current_task_btf:
@@ -1582,8 +1580,6 @@ bpf_tracing_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
15821580
return &bpf_send_signal_thread_proto;
15831581
case BPF_FUNC_perf_event_read_value:
15841582
return &bpf_perf_event_read_value_proto;
1585-
case BPF_FUNC_get_ns_current_pid_tgid:
1586-
return &bpf_get_ns_current_pid_tgid_proto;
15871583
case BPF_FUNC_ringbuf_output:
15881584
return &bpf_ringbuf_output_proto;
15891585
case BPF_FUNC_ringbuf_reserve:

net/core/filter.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8342,8 +8342,6 @@ sk_msg_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
83428342
return &bpf_event_output_data_proto;
83438343
case BPF_FUNC_get_current_uid_gid:
83448344
return &bpf_get_current_uid_gid_proto;
8345-
case BPF_FUNC_get_current_pid_tgid:
8346-
return &bpf_get_current_pid_tgid_proto;
83478345
case BPF_FUNC_sk_storage_get:
83488346
return &bpf_sk_storage_get_proto;
83498347
case BPF_FUNC_sk_storage_delete:

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

Lines changed: 183 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,77 +12,229 @@
1212
#include <sys/wait.h>
1313
#include <sys/mount.h>
1414
#include <sys/fcntl.h>
15+
#include "network_helpers.h"
1516

1617
#define STACK_SIZE (1024 * 1024)
1718
static char child_stack[STACK_SIZE];
1819

19-
static int test_current_pid_tgid(void *args)
20+
static int get_pid_tgid(pid_t *pid, pid_t *tgid,
21+
struct test_ns_current_pid_tgid__bss *bss)
2022
{
21-
struct test_ns_current_pid_tgid__bss *bss;
22-
struct test_ns_current_pid_tgid *skel;
23-
int err = -1, duration = 0;
24-
pid_t tgid, pid;
2523
struct stat st;
24+
int err;
2625

27-
skel = test_ns_current_pid_tgid__open_and_load();
28-
if (CHECK(!skel, "skel_open_load", "failed to load skeleton\n"))
29-
goto cleanup;
30-
31-
pid = syscall(SYS_gettid);
32-
tgid = getpid();
26+
*pid = syscall(SYS_gettid);
27+
*tgid = getpid();
3328

3429
err = stat("/proc/self/ns/pid", &st);
35-
if (CHECK(err, "stat", "failed /proc/self/ns/pid: %d\n", err))
36-
goto cleanup;
30+
if (!ASSERT_OK(err, "stat /proc/self/ns/pid"))
31+
return err;
3732

38-
bss = skel->bss;
3933
bss->dev = st.st_dev;
4034
bss->ino = st.st_ino;
4135
bss->user_pid = 0;
4236
bss->user_tgid = 0;
37+
return 0;
38+
}
39+
40+
static int test_current_pid_tgid_tp(void *args)
41+
{
42+
struct test_ns_current_pid_tgid__bss *bss;
43+
struct test_ns_current_pid_tgid *skel;
44+
int ret = -1, err;
45+
pid_t tgid, pid;
46+
47+
skel = test_ns_current_pid_tgid__open();
48+
if (!ASSERT_OK_PTR(skel, "test_ns_current_pid_tgid__open"))
49+
return ret;
50+
51+
bpf_program__set_autoload(skel->progs.tp_handler, true);
52+
53+
err = test_ns_current_pid_tgid__load(skel);
54+
if (!ASSERT_OK(err, "test_ns_current_pid_tgid__load"))
55+
goto cleanup;
56+
57+
bss = skel->bss;
58+
if (get_pid_tgid(&pid, &tgid, bss))
59+
goto cleanup;
4360

4461
err = test_ns_current_pid_tgid__attach(skel);
45-
if (CHECK(err, "skel_attach", "skeleton attach failed: %d\n", err))
62+
if (!ASSERT_OK(err, "test_ns_current_pid_tgid__attach"))
4663
goto cleanup;
4764

4865
/* trigger tracepoint */
4966
usleep(1);
50-
ASSERT_EQ(bss->user_pid, pid, "pid");
51-
ASSERT_EQ(bss->user_tgid, tgid, "tgid");
52-
err = 0;
67+
if (!ASSERT_EQ(bss->user_pid, pid, "pid"))
68+
goto cleanup;
69+
if (!ASSERT_EQ(bss->user_tgid, tgid, "tgid"))
70+
goto cleanup;
71+
ret = 0;
72+
73+
cleanup:
74+
test_ns_current_pid_tgid__destroy(skel);
75+
return ret;
76+
}
77+
78+
static int test_current_pid_tgid_cgrp(void *args)
79+
{
80+
struct test_ns_current_pid_tgid__bss *bss;
81+
struct test_ns_current_pid_tgid *skel;
82+
int server_fd = -1, ret = -1, err;
83+
int cgroup_fd = *(int *)args;
84+
pid_t tgid, pid;
85+
86+
skel = test_ns_current_pid_tgid__open();
87+
if (!ASSERT_OK_PTR(skel, "test_ns_current_pid_tgid__open"))
88+
return ret;
89+
90+
bpf_program__set_autoload(skel->progs.cgroup_bind4, true);
91+
92+
err = test_ns_current_pid_tgid__load(skel);
93+
if (!ASSERT_OK(err, "test_ns_current_pid_tgid__load"))
94+
goto cleanup;
95+
96+
bss = skel->bss;
97+
if (get_pid_tgid(&pid, &tgid, bss))
98+
goto cleanup;
99+
100+
skel->links.cgroup_bind4 = bpf_program__attach_cgroup(
101+
skel->progs.cgroup_bind4, cgroup_fd);
102+
if (!ASSERT_OK_PTR(skel->links.cgroup_bind4, "bpf_program__attach_cgroup"))
103+
goto cleanup;
104+
105+
server_fd = start_server(AF_INET, SOCK_STREAM, NULL, 0, 0);
106+
if (!ASSERT_GE(server_fd, 0, "start_server"))
107+
goto cleanup;
108+
109+
if (!ASSERT_EQ(bss->user_pid, pid, "pid"))
110+
goto cleanup;
111+
if (!ASSERT_EQ(bss->user_tgid, tgid, "tgid"))
112+
goto cleanup;
113+
ret = 0;
53114

54115
cleanup:
55-
test_ns_current_pid_tgid__destroy(skel);
116+
if (server_fd >= 0)
117+
close(server_fd);
118+
test_ns_current_pid_tgid__destroy(skel);
119+
return ret;
120+
}
121+
122+
static int test_current_pid_tgid_sk_msg(void *args)
123+
{
124+
int verdict, map, server_fd = -1, client_fd = -1;
125+
struct test_ns_current_pid_tgid__bss *bss;
126+
static const char send_msg[] = "message";
127+
struct test_ns_current_pid_tgid *skel;
128+
int ret = -1, err, key = 0;
129+
pid_t tgid, pid;
130+
131+
skel = test_ns_current_pid_tgid__open();
132+
if (!ASSERT_OK_PTR(skel, "test_ns_current_pid_tgid__open"))
133+
return ret;
134+
135+
bpf_program__set_autoload(skel->progs.sk_msg, true);
136+
137+
err = test_ns_current_pid_tgid__load(skel);
138+
if (!ASSERT_OK(err, "test_ns_current_pid_tgid__load"))
139+
goto cleanup;
140+
141+
bss = skel->bss;
142+
if (get_pid_tgid(&pid, &tgid, skel->bss))
143+
goto cleanup;
144+
145+
verdict = bpf_program__fd(skel->progs.sk_msg);
146+
map = bpf_map__fd(skel->maps.sock_map);
147+
err = bpf_prog_attach(verdict, map, BPF_SK_MSG_VERDICT, 0);
148+
if (!ASSERT_OK(err, "prog_attach"))
149+
goto cleanup;
150+
151+
server_fd = start_server(AF_INET6, SOCK_STREAM, "::1", 0, 0);
152+
if (!ASSERT_GE(server_fd, 0, "start_server"))
153+
goto cleanup;
56154

57-
return err;
155+
client_fd = connect_to_fd(server_fd, 0);
156+
if (!ASSERT_GE(client_fd, 0, "connect_to_fd"))
157+
goto cleanup;
158+
159+
err = bpf_map_update_elem(map, &key, &client_fd, BPF_ANY);
160+
if (!ASSERT_OK(err, "bpf_map_update_elem"))
161+
goto cleanup;
162+
163+
err = send(client_fd, send_msg, sizeof(send_msg), 0);
164+
if (!ASSERT_EQ(err, sizeof(send_msg), "send(msg)"))
165+
goto cleanup;
166+
167+
if (!ASSERT_EQ(bss->user_pid, pid, "pid"))
168+
goto cleanup;
169+
if (!ASSERT_EQ(bss->user_tgid, tgid, "tgid"))
170+
goto cleanup;
171+
ret = 0;
172+
173+
cleanup:
174+
if (server_fd >= 0)
175+
close(server_fd);
176+
if (client_fd >= 0)
177+
close(client_fd);
178+
test_ns_current_pid_tgid__destroy(skel);
179+
return ret;
58180
}
59181

60-
static void test_ns_current_pid_tgid_new_ns(void)
182+
static void test_ns_current_pid_tgid_new_ns(int (*fn)(void *), void *arg)
61183
{
62-
int wstatus, duration = 0;
184+
int wstatus;
63185
pid_t cpid;
64186

65187
/* Create a process in a new namespace, this process
66188
* will be the init process of this new namespace hence will be pid 1.
67189
*/
68-
cpid = clone(test_current_pid_tgid, child_stack + STACK_SIZE,
69-
CLONE_NEWPID | SIGCHLD, NULL);
190+
cpid = clone(fn, child_stack + STACK_SIZE,
191+
CLONE_NEWPID | SIGCHLD, arg);
70192

71-
if (CHECK(cpid == -1, "clone", "%s\n", strerror(errno)))
193+
if (!ASSERT_NEQ(cpid, -1, "clone"))
72194
return;
73195

74-
if (CHECK(waitpid(cpid, &wstatus, 0) == -1, "waitpid", "%s\n", strerror(errno)))
196+
if (!ASSERT_NEQ(waitpid(cpid, &wstatus, 0), -1, "waitpid"))
75197
return;
76198

77-
if (CHECK(WEXITSTATUS(wstatus) != 0, "newns_pidtgid", "failed"))
199+
if (!ASSERT_OK(WEXITSTATUS(wstatus), "newns_pidtgid"))
78200
return;
79201
}
80202

203+
static void test_in_netns(int (*fn)(void *), void *arg)
204+
{
205+
struct nstoken *nstoken = NULL;
206+
207+
SYS(cleanup, "ip netns add ns_current_pid_tgid");
208+
SYS(cleanup, "ip -net ns_current_pid_tgid link set dev lo up");
209+
210+
nstoken = open_netns("ns_current_pid_tgid");
211+
if (!ASSERT_OK_PTR(nstoken, "open_netns"))
212+
goto cleanup;
213+
214+
test_ns_current_pid_tgid_new_ns(fn, arg);
215+
216+
cleanup:
217+
if (nstoken)
218+
close_netns(nstoken);
219+
SYS_NOFAIL("ip netns del ns_current_pid_tgid");
220+
}
221+
81222
/* TODO: use a different tracepoint */
82223
void serial_test_ns_current_pid_tgid(void)
83224
{
84-
if (test__start_subtest("ns_current_pid_tgid_root_ns"))
85-
test_current_pid_tgid(NULL);
86-
if (test__start_subtest("ns_current_pid_tgid_new_ns"))
87-
test_ns_current_pid_tgid_new_ns();
225+
if (test__start_subtest("root_ns_tp"))
226+
test_current_pid_tgid_tp(NULL);
227+
if (test__start_subtest("new_ns_tp"))
228+
test_ns_current_pid_tgid_new_ns(test_current_pid_tgid_tp, NULL);
229+
if (test__start_subtest("new_ns_cgrp")) {
230+
int cgroup_fd = -1;
231+
232+
cgroup_fd = test__join_cgroup("/sock_addr");
233+
if (ASSERT_GE(cgroup_fd, 0, "join_cgroup")) {
234+
test_in_netns(test_current_pid_tgid_cgrp, &cgroup_fd);
235+
close(cgroup_fd);
236+
}
237+
}
238+
if (test__start_subtest("new_ns_sk_msg"))
239+
test_in_netns(test_current_pid_tgid_sk_msg, NULL);
88240
}

tools/testing/selftests/bpf/progs/test_ns_current_pid_tgid.c

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,48 @@
55
#include <stdint.h>
66
#include <bpf/bpf_helpers.h>
77

8+
struct {
9+
__uint(type, BPF_MAP_TYPE_SOCKMAP);
10+
__uint(max_entries, 2);
11+
__type(key, __u32);
12+
__type(value, __u32);
13+
} sock_map SEC(".maps");
14+
815
__u64 user_pid = 0;
916
__u64 user_tgid = 0;
1017
__u64 dev = 0;
1118
__u64 ino = 0;
1219

13-
SEC("tracepoint/syscalls/sys_enter_nanosleep")
14-
int handler(const void *ctx)
20+
static void get_pid_tgid(void)
1521
{
1622
struct bpf_pidns_info nsdata;
1723

1824
if (bpf_get_ns_current_pid_tgid(dev, ino, &nsdata, sizeof(struct bpf_pidns_info)))
19-
return 0;
25+
return;
2026

2127
user_pid = nsdata.pid;
2228
user_tgid = nsdata.tgid;
29+
}
2330

31+
SEC("?tracepoint/syscalls/sys_enter_nanosleep")
32+
int tp_handler(const void *ctx)
33+
{
34+
get_pid_tgid();
2435
return 0;
2536
}
2637

38+
SEC("?cgroup/bind4")
39+
int cgroup_bind4(struct bpf_sock_addr *ctx)
40+
{
41+
get_pid_tgid();
42+
return 1;
43+
}
44+
45+
SEC("?sk_msg")
46+
int sk_msg(struct sk_msg_md *msg)
47+
{
48+
get_pid_tgid();
49+
return SK_PASS;
50+
}
51+
2752
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)