Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Mar 24-27, 2025, special US time zones
Register
Loading...
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2020 Carlos Neira cneirabustos@gmail.com */
  3
  4#define _GNU_SOURCE
  5#include <test_progs.h>
  6#include "test_ns_current_pid_tgid.skel.h"
  7#include <sys/stat.h>
  8#include <sys/types.h>
  9#include <unistd.h>
 10#include <sys/syscall.h>
 11#include <sched.h>
 12#include <sys/wait.h>
 13#include <sys/mount.h>
 14#include <fcntl.h>
 15#include "network_helpers.h"
 16
 17#define STACK_SIZE (1024 * 1024)
 18static char child_stack[STACK_SIZE];
 19
 20static int get_pid_tgid(pid_t *pid, pid_t *tgid,
 21			struct test_ns_current_pid_tgid__bss *bss)
 22{
 23	struct stat st;
 24	int err;
 25
 26	*pid = sys_gettid();
 27	*tgid = getpid();
 28
 29	err = stat("/proc/self/ns/pid", &st);
 30	if (!ASSERT_OK(err, "stat /proc/self/ns/pid"))
 31		return err;
 32
 33	bss->dev = st.st_dev;
 34	bss->ino = st.st_ino;
 35	bss->user_pid = 0;
 36	bss->user_tgid = 0;
 37	return 0;
 38}
 39
 40static 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;
 60
 61	err = test_ns_current_pid_tgid__attach(skel);
 62	if (!ASSERT_OK(err, "test_ns_current_pid_tgid__attach"))
 63		goto cleanup;
 64
 65	/* trigger tracepoint */
 66	usleep(1);
 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
 73cleanup:
 74	test_ns_current_pid_tgid__destroy(skel);
 75	return ret;
 76}
 77
 78static 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;
114
115cleanup:
116	if (server_fd >= 0)
117		close(server_fd);
118	test_ns_current_pid_tgid__destroy(skel);
119	return ret;
120}
121
122static 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;
154
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
173cleanup:
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;
180}
181
182static void test_ns_current_pid_tgid_new_ns(int (*fn)(void *), void *arg)
183{
184	int wstatus;
185	pid_t cpid;
186
187	/* Create a process in a new namespace, this process
188	 * will be the init process of this new namespace hence will be pid 1.
189	 */
190	cpid = clone(fn, child_stack + STACK_SIZE,
191		     CLONE_NEWPID | SIGCHLD, arg);
192
193	if (!ASSERT_NEQ(cpid, -1, "clone"))
194		return;
195
196	if (!ASSERT_NEQ(waitpid(cpid, &wstatus, 0), -1, "waitpid"))
197		return;
198
199	if (!ASSERT_OK(WEXITSTATUS(wstatus), "newns_pidtgid"))
200		return;
201}
202
203static 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
216cleanup:
217	if (nstoken)
218		close_netns(nstoken);
219	SYS_NOFAIL("ip netns del ns_current_pid_tgid");
220}
221
222/* TODO: use a different tracepoint */
223void serial_test_ns_current_pid_tgid(void)
224{
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);
240}