Linux Audio

Check our new training course

Loading...
v5.4
  1// SPDX-License-Identifier: GPL-2.0
  2#include <test_progs.h>
  3#include "cgroup_helpers.h"
  4
 
 
 
 
 
 
 
  5#define SOL_CUSTOM			0xdeadbeef
  6
  7static int getsetsockopt(void)
  8{
  9	int fd, err;
 10	union {
 11		char u8[4];
 12		__u32 u32;
 13		char cc[16]; /* TCP_CA_NAME_MAX */
 
 14	} buf = {};
 15	socklen_t optlen;
 
 16
 17	fd = socket(AF_INET, SOCK_STREAM, 0);
 18	if (fd < 0) {
 19		log_err("Failed to create socket");
 20		return -1;
 21	}
 22
 23	/* IP_TOS - BPF bypass */
 24
 25	buf.u8[0] = 0x08;
 26	err = setsockopt(fd, SOL_IP, IP_TOS, &buf, 1);
 
 
 
 
 
 
 
 27	if (err) {
 28		log_err("Failed to call setsockopt(IP_TOS)");
 29		goto err;
 30	}
 31
 32	buf.u8[0] = 0x00;
 33	optlen = 1;
 34	err = getsockopt(fd, SOL_IP, IP_TOS, &buf, &optlen);
 35	if (err) {
 36		log_err("Failed to call getsockopt(IP_TOS)");
 37		goto err;
 38	}
 39
 40	if (buf.u8[0] != 0x08) {
 41		log_err("Unexpected getsockopt(IP_TOS) buf[0] 0x%02x != 0x08",
 42			buf.u8[0]);
 43		goto err;
 44	}
 45
 46	/* IP_TTL - EPERM */
 47
 48	buf.u8[0] = 1;
 49	err = setsockopt(fd, SOL_IP, IP_TTL, &buf, 1);
 50	if (!err || errno != EPERM) {
 51		log_err("Unexpected success from setsockopt(IP_TTL)");
 52		goto err;
 53	}
 54
 55	/* SOL_CUSTOM - handled by BPF */
 56
 57	buf.u8[0] = 0x01;
 58	err = setsockopt(fd, SOL_CUSTOM, 0, &buf, 1);
 59	if (err) {
 60		log_err("Failed to call setsockopt");
 61		goto err;
 62	}
 63
 64	buf.u32 = 0x00;
 65	optlen = 4;
 66	err = getsockopt(fd, SOL_CUSTOM, 0, &buf, &optlen);
 67	if (err) {
 68		log_err("Failed to call getsockopt");
 69		goto err;
 70	}
 71
 72	if (optlen != 1) {
 73		log_err("Unexpected optlen %d != 1", optlen);
 74		goto err;
 75	}
 76	if (buf.u8[0] != 0x01) {
 77		log_err("Unexpected buf[0] 0x%02x != 0x01", buf.u8[0]);
 78		goto err;
 79	}
 80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 81	/* SO_SNDBUF is overwritten */
 82
 83	buf.u32 = 0x01010101;
 84	err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, 4);
 85	if (err) {
 86		log_err("Failed to call setsockopt(SO_SNDBUF)");
 87		goto err;
 88	}
 89
 90	buf.u32 = 0x00;
 91	optlen = 4;
 92	err = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, &optlen);
 93	if (err) {
 94		log_err("Failed to call getsockopt(SO_SNDBUF)");
 95		goto err;
 96	}
 97
 98	if (buf.u32 != 0x55AA*2) {
 99		log_err("Unexpected getsockopt(SO_SNDBUF) 0x%x != 0x55AA*2",
100			buf.u32);
101		goto err;
102	}
103
104	/* TCP_CONGESTION can extend the string */
105
106	strcpy(buf.cc, "nv");
107	err = setsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, strlen("nv"));
108	if (err) {
109		log_err("Failed to call setsockopt(TCP_CONGESTION)");
110		goto err;
111	}
112
113
114	optlen = sizeof(buf.cc);
115	err = getsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, &optlen);
116	if (err) {
117		log_err("Failed to call getsockopt(TCP_CONGESTION)");
118		goto err;
119	}
120
121	if (strcmp(buf.cc, "cubic") != 0) {
122		log_err("Unexpected getsockopt(TCP_CONGESTION) %s != %s",
123			buf.cc, "cubic");
124		goto err;
125	}
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127	close(fd);
128	return 0;
129err:
 
130	close(fd);
131	return -1;
132}
133
134static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title)
135{
136	enum bpf_attach_type attach_type;
137	enum bpf_prog_type prog_type;
138	struct bpf_program *prog;
139	int err;
140
141	err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
142	if (err) {
143		log_err("Failed to deduct types for %s BPF program", title);
144		return -1;
145	}
146
147	prog = bpf_object__find_program_by_title(obj, title);
148	if (!prog) {
149		log_err("Failed to find %s BPF program", title);
150		return -1;
151	}
152
153	err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
154			      attach_type, 0);
155	if (err) {
156		log_err("Failed to attach %s BPF program", title);
157		return -1;
158	}
159
160	return 0;
161}
 
 
162
163static void run_test(int cgroup_fd)
164{
165	struct bpf_prog_load_attr attr = {
166		.file = "./sockopt_sk.o",
167	};
168	struct bpf_object *obj;
169	int ignored;
170	int err;
171
172	err = bpf_prog_load_xattr(&attr, &obj, &ignored);
173	if (CHECK_FAIL(err))
174		return;
175
176	err = prog_attach(obj, cgroup_fd, "cgroup/getsockopt");
177	if (CHECK_FAIL(err))
178		goto close_bpf_object;
179
180	err = prog_attach(obj, cgroup_fd, "cgroup/setsockopt");
181	if (CHECK_FAIL(err))
182		goto close_bpf_object;
183
184	CHECK_FAIL(getsetsockopt());
185
186close_bpf_object:
187	bpf_object__close(obj);
188}
189
190void test_sockopt_sk(void)
191{
192	int cgroup_fd;
193
194	cgroup_fd = test__join_cgroup("/sockopt_sk");
195	if (CHECK_FAIL(cgroup_fd < 0))
196		return;
197
198	run_test(cgroup_fd);
199	close(cgroup_fd);
200}
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0
  2#include <test_progs.h>
  3#include "cgroup_helpers.h"
  4
  5#include <linux/tcp.h>
  6#include "sockopt_sk.skel.h"
  7
  8#ifndef SOL_TCP
  9#define SOL_TCP IPPROTO_TCP
 10#endif
 11
 12#define SOL_CUSTOM			0xdeadbeef
 13
 14static int getsetsockopt(void)
 15{
 16	int fd, err;
 17	union {
 18		char u8[4];
 19		__u32 u32;
 20		char cc[16]; /* TCP_CA_NAME_MAX */
 21		struct tcp_zerocopy_receive zc;
 22	} buf = {};
 23	socklen_t optlen;
 24	char *big_buf = NULL;
 25
 26	fd = socket(AF_INET, SOCK_STREAM, 0);
 27	if (fd < 0) {
 28		log_err("Failed to create socket");
 29		return -1;
 30	}
 31
 32	/* IP_TOS - BPF bypass */
 33
 34	optlen = getpagesize() * 2;
 35	big_buf = calloc(1, optlen);
 36	if (!big_buf) {
 37		log_err("Couldn't allocate two pages");
 38		goto err;
 39	}
 40
 41	*(int *)big_buf = 0x08;
 42	err = setsockopt(fd, SOL_IP, IP_TOS, big_buf, optlen);
 43	if (err) {
 44		log_err("Failed to call setsockopt(IP_TOS)");
 45		goto err;
 46	}
 47
 48	memset(big_buf, 0, optlen);
 49	optlen = 1;
 50	err = getsockopt(fd, SOL_IP, IP_TOS, big_buf, &optlen);
 51	if (err) {
 52		log_err("Failed to call getsockopt(IP_TOS)");
 53		goto err;
 54	}
 55
 56	if (*big_buf != 0x08) {
 57		log_err("Unexpected getsockopt(IP_TOS) optval 0x%x != 0x08",
 58			(int)*big_buf);
 59		goto err;
 60	}
 61
 62	/* IP_TTL - EPERM */
 63
 64	buf.u8[0] = 1;
 65	err = setsockopt(fd, SOL_IP, IP_TTL, &buf, 1);
 66	if (!err || errno != EPERM) {
 67		log_err("Unexpected success from setsockopt(IP_TTL)");
 68		goto err;
 69	}
 70
 71	/* SOL_CUSTOM - handled by BPF */
 72
 73	buf.u8[0] = 0x01;
 74	err = setsockopt(fd, SOL_CUSTOM, 0, &buf, 1);
 75	if (err) {
 76		log_err("Failed to call setsockopt");
 77		goto err;
 78	}
 79
 80	buf.u32 = 0x00;
 81	optlen = 4;
 82	err = getsockopt(fd, SOL_CUSTOM, 0, &buf, &optlen);
 83	if (err) {
 84		log_err("Failed to call getsockopt");
 85		goto err;
 86	}
 87
 88	if (optlen != 1) {
 89		log_err("Unexpected optlen %d != 1", optlen);
 90		goto err;
 91	}
 92	if (buf.u8[0] != 0x01) {
 93		log_err("Unexpected buf[0] 0x%02x != 0x01", buf.u8[0]);
 94		goto err;
 95	}
 96
 97	/* IP_FREEBIND - BPF can't access optval past PAGE_SIZE */
 98
 99	optlen = getpagesize() * 2;
100	memset(big_buf, 0, optlen);
101
102	err = setsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, optlen);
103	if (err != 0) {
104		log_err("Failed to call setsockopt, ret=%d", err);
105		goto err;
106	}
107
108	err = getsockopt(fd, SOL_IP, IP_FREEBIND, big_buf, &optlen);
109	if (err != 0) {
110		log_err("Failed to call getsockopt, ret=%d", err);
111		goto err;
112	}
113
114	if (optlen != 1 || *(__u8 *)big_buf != 0x55) {
115		log_err("Unexpected IP_FREEBIND getsockopt, optlen=%d, optval=0x%x",
116			optlen, *(__u8 *)big_buf);
117	}
118
119	/* SO_SNDBUF is overwritten */
120
121	buf.u32 = 0x01010101;
122	err = setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, 4);
123	if (err) {
124		log_err("Failed to call setsockopt(SO_SNDBUF)");
125		goto err;
126	}
127
128	buf.u32 = 0x00;
129	optlen = 4;
130	err = getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &buf, &optlen);
131	if (err) {
132		log_err("Failed to call getsockopt(SO_SNDBUF)");
133		goto err;
134	}
135
136	if (buf.u32 != 0x55AA*2) {
137		log_err("Unexpected getsockopt(SO_SNDBUF) 0x%x != 0x55AA*2",
138			buf.u32);
139		goto err;
140	}
141
142	/* TCP_CONGESTION can extend the string */
143
144	strcpy(buf.cc, "nv");
145	err = setsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, strlen("nv"));
146	if (err) {
147		log_err("Failed to call setsockopt(TCP_CONGESTION)");
148		goto err;
149	}
150
151
152	optlen = sizeof(buf.cc);
153	err = getsockopt(fd, SOL_TCP, TCP_CONGESTION, &buf, &optlen);
154	if (err) {
155		log_err("Failed to call getsockopt(TCP_CONGESTION)");
156		goto err;
157	}
158
159	if (strcmp(buf.cc, "cubic") != 0) {
160		log_err("Unexpected getsockopt(TCP_CONGESTION) %s != %s",
161			buf.cc, "cubic");
162		goto err;
163	}
164
165	/* TCP_ZEROCOPY_RECEIVE triggers */
166	memset(&buf, 0, sizeof(buf));
167	optlen = sizeof(buf.zc);
168	err = getsockopt(fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &buf, &optlen);
169	if (err) {
170		log_err("Unexpected getsockopt(TCP_ZEROCOPY_RECEIVE) err=%d errno=%d",
171			err, errno);
172		goto err;
173	}
174
175	memset(&buf, 0, sizeof(buf));
176	buf.zc.address = 12345; /* rejected by BPF */
177	optlen = sizeof(buf.zc);
178	errno = 0;
179	err = getsockopt(fd, SOL_TCP, TCP_ZEROCOPY_RECEIVE, &buf, &optlen);
180	if (errno != EPERM) {
181		log_err("Unexpected getsockopt(TCP_ZEROCOPY_RECEIVE) err=%d errno=%d",
182			err, errno);
183		goto err;
184	}
185
186	free(big_buf);
187	close(fd);
188	return 0;
189err:
190	free(big_buf);
191	close(fd);
192	return -1;
193}
194
195static void run_test(int cgroup_fd)
196{
197	struct sockopt_sk *skel;
 
 
 
 
 
 
 
 
 
198
199	skel = sockopt_sk__open_and_load();
200	if (!ASSERT_OK_PTR(skel, "skel_load"))
201		goto cleanup;
 
 
202
203	skel->bss->page_size = getpagesize();
 
 
 
 
 
204
205	skel->links._setsockopt =
206		bpf_program__attach_cgroup(skel->progs._setsockopt, cgroup_fd);
207	if (!ASSERT_OK_PTR(skel->links._setsockopt, "setsockopt_link"))
208		goto cleanup;
209
210	skel->links._getsockopt =
211		bpf_program__attach_cgroup(skel->progs._getsockopt, cgroup_fd);
212	if (!ASSERT_OK_PTR(skel->links._getsockopt, "getsockopt_link"))
213		goto cleanup;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
214
215	ASSERT_OK(getsetsockopt(), "getsetsockopt");
216
217cleanup:
218	sockopt_sk__destroy(skel);
219}
220
221void test_sockopt_sk(void)
222{
223	int cgroup_fd;
224
225	cgroup_fd = test__join_cgroup("/sockopt_sk");
226	if (CHECK_FAIL(cgroup_fd < 0))
227		return;
228
229	run_test(cgroup_fd);
230	close(cgroup_fd);
231}