Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.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}