13886bd7cSStanislav Fomichev // SPDX-License-Identifier: GPL-2.0
23886bd7cSStanislav Fomichev #include <test_progs.h>
33886bd7cSStanislav Fomichev #include "cgroup_helpers.h"
43886bd7cSStanislav Fomichev
5*e01b4a72SStanislav Fomichev #include "sockopt_multi.skel.h"
63886bd7cSStanislav Fomichev
run_getsockopt_test(struct sockopt_multi * obj,int cg_parent,int cg_child,int sock_fd)7*e01b4a72SStanislav Fomichev static int run_getsockopt_test(struct sockopt_multi *obj, int cg_parent,
83886bd7cSStanislav Fomichev int cg_child, int sock_fd)
93886bd7cSStanislav Fomichev {
10*e01b4a72SStanislav Fomichev struct bpf_link *link_parent = NULL;
11*e01b4a72SStanislav Fomichev struct bpf_link *link_child = NULL;
123886bd7cSStanislav Fomichev socklen_t optlen;
133886bd7cSStanislav Fomichev __u8 buf;
143886bd7cSStanislav Fomichev int err;
153886bd7cSStanislav Fomichev
163886bd7cSStanislav Fomichev /* Set IP_TOS to the expected value (0x80). */
173886bd7cSStanislav Fomichev
183886bd7cSStanislav Fomichev buf = 0x80;
193886bd7cSStanislav Fomichev err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
203886bd7cSStanislav Fomichev if (err < 0) {
213886bd7cSStanislav Fomichev log_err("Failed to call setsockopt(IP_TOS)");
223886bd7cSStanislav Fomichev goto detach;
233886bd7cSStanislav Fomichev }
243886bd7cSStanislav Fomichev
253886bd7cSStanislav Fomichev buf = 0x00;
263886bd7cSStanislav Fomichev optlen = 1;
273886bd7cSStanislav Fomichev err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
283886bd7cSStanislav Fomichev if (err) {
293886bd7cSStanislav Fomichev log_err("Failed to call getsockopt(IP_TOS)");
303886bd7cSStanislav Fomichev goto detach;
313886bd7cSStanislav Fomichev }
323886bd7cSStanislav Fomichev
333886bd7cSStanislav Fomichev if (buf != 0x80) {
343886bd7cSStanislav Fomichev log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
353886bd7cSStanislav Fomichev err = -1;
363886bd7cSStanislav Fomichev goto detach;
373886bd7cSStanislav Fomichev }
383886bd7cSStanislav Fomichev
393886bd7cSStanislav Fomichev /* Attach child program and make sure it returns new value:
403886bd7cSStanislav Fomichev * - kernel: -> 0x80
413886bd7cSStanislav Fomichev * - child: 0x80 -> 0x90
423886bd7cSStanislav Fomichev */
433886bd7cSStanislav Fomichev
44*e01b4a72SStanislav Fomichev link_child = bpf_program__attach_cgroup(obj->progs._getsockopt_child,
45*e01b4a72SStanislav Fomichev cg_child);
46*e01b4a72SStanislav Fomichev if (!ASSERT_OK_PTR(link_child, "cg-attach-getsockopt_child"))
473886bd7cSStanislav Fomichev goto detach;
483886bd7cSStanislav Fomichev
493886bd7cSStanislav Fomichev buf = 0x00;
503886bd7cSStanislav Fomichev optlen = 1;
513886bd7cSStanislav Fomichev err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
523886bd7cSStanislav Fomichev if (err) {
533886bd7cSStanislav Fomichev log_err("Failed to call getsockopt(IP_TOS)");
543886bd7cSStanislav Fomichev goto detach;
553886bd7cSStanislav Fomichev }
563886bd7cSStanislav Fomichev
573886bd7cSStanislav Fomichev if (buf != 0x90) {
583886bd7cSStanislav Fomichev log_err("Unexpected getsockopt 0x%x != 0x90", buf);
593886bd7cSStanislav Fomichev err = -1;
603886bd7cSStanislav Fomichev goto detach;
613886bd7cSStanislav Fomichev }
623886bd7cSStanislav Fomichev
633886bd7cSStanislav Fomichev /* Attach parent program and make sure it returns new value:
643886bd7cSStanislav Fomichev * - kernel: -> 0x80
653886bd7cSStanislav Fomichev * - child: 0x80 -> 0x90
663886bd7cSStanislav Fomichev * - parent: 0x90 -> 0xA0
673886bd7cSStanislav Fomichev */
683886bd7cSStanislav Fomichev
69*e01b4a72SStanislav Fomichev link_parent = bpf_program__attach_cgroup(obj->progs._getsockopt_parent,
70*e01b4a72SStanislav Fomichev cg_parent);
71*e01b4a72SStanislav Fomichev if (!ASSERT_OK_PTR(link_parent, "cg-attach-getsockopt_parent"))
723886bd7cSStanislav Fomichev goto detach;
733886bd7cSStanislav Fomichev
743886bd7cSStanislav Fomichev buf = 0x00;
753886bd7cSStanislav Fomichev optlen = 1;
763886bd7cSStanislav Fomichev err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
773886bd7cSStanislav Fomichev if (err) {
783886bd7cSStanislav Fomichev log_err("Failed to call getsockopt(IP_TOS)");
793886bd7cSStanislav Fomichev goto detach;
803886bd7cSStanislav Fomichev }
813886bd7cSStanislav Fomichev
823886bd7cSStanislav Fomichev if (buf != 0xA0) {
833886bd7cSStanislav Fomichev log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
843886bd7cSStanislav Fomichev err = -1;
853886bd7cSStanislav Fomichev goto detach;
863886bd7cSStanislav Fomichev }
873886bd7cSStanislav Fomichev
883886bd7cSStanislav Fomichev /* Setting unexpected initial sockopt should return EPERM:
893886bd7cSStanislav Fomichev * - kernel: -> 0x40
903886bd7cSStanislav Fomichev * - child: unexpected 0x40, EPERM
913886bd7cSStanislav Fomichev * - parent: unexpected 0x40, EPERM
923886bd7cSStanislav Fomichev */
933886bd7cSStanislav Fomichev
943886bd7cSStanislav Fomichev buf = 0x40;
952acc3c1bSWang Hai err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
962acc3c1bSWang Hai if (err < 0) {
973886bd7cSStanislav Fomichev log_err("Failed to call setsockopt(IP_TOS)");
983886bd7cSStanislav Fomichev goto detach;
993886bd7cSStanislav Fomichev }
1003886bd7cSStanislav Fomichev
1013886bd7cSStanislav Fomichev buf = 0x00;
1023886bd7cSStanislav Fomichev optlen = 1;
1033886bd7cSStanislav Fomichev err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
1043886bd7cSStanislav Fomichev if (!err) {
1053886bd7cSStanislav Fomichev log_err("Unexpected success from getsockopt(IP_TOS)");
1063886bd7cSStanislav Fomichev goto detach;
1073886bd7cSStanislav Fomichev }
1083886bd7cSStanislav Fomichev
1093886bd7cSStanislav Fomichev /* Detach child program and make sure we still get EPERM:
1103886bd7cSStanislav Fomichev * - kernel: -> 0x40
1113886bd7cSStanislav Fomichev * - parent: unexpected 0x40, EPERM
1123886bd7cSStanislav Fomichev */
1133886bd7cSStanislav Fomichev
114*e01b4a72SStanislav Fomichev bpf_link__destroy(link_child);
115*e01b4a72SStanislav Fomichev link_child = NULL;
1163886bd7cSStanislav Fomichev
1173886bd7cSStanislav Fomichev buf = 0x00;
1183886bd7cSStanislav Fomichev optlen = 1;
1193886bd7cSStanislav Fomichev err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
1203886bd7cSStanislav Fomichev if (!err) {
1213886bd7cSStanislav Fomichev log_err("Unexpected success from getsockopt(IP_TOS)");
1223886bd7cSStanislav Fomichev goto detach;
1233886bd7cSStanislav Fomichev }
1243886bd7cSStanislav Fomichev
1253886bd7cSStanislav Fomichev /* Set initial value to the one the parent program expects:
1263886bd7cSStanislav Fomichev * - kernel: -> 0x90
1273886bd7cSStanislav Fomichev * - parent: 0x90 -> 0xA0
1283886bd7cSStanislav Fomichev */
1293886bd7cSStanislav Fomichev
1303886bd7cSStanislav Fomichev buf = 0x90;
1313886bd7cSStanislav Fomichev err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
1323886bd7cSStanislav Fomichev if (err < 0) {
1333886bd7cSStanislav Fomichev log_err("Failed to call setsockopt(IP_TOS)");
1343886bd7cSStanislav Fomichev goto detach;
1353886bd7cSStanislav Fomichev }
1363886bd7cSStanislav Fomichev
1373886bd7cSStanislav Fomichev buf = 0x00;
1383886bd7cSStanislav Fomichev optlen = 1;
1393886bd7cSStanislav Fomichev err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
1403886bd7cSStanislav Fomichev if (err) {
1413886bd7cSStanislav Fomichev log_err("Failed to call getsockopt(IP_TOS)");
1423886bd7cSStanislav Fomichev goto detach;
1433886bd7cSStanislav Fomichev }
1443886bd7cSStanislav Fomichev
1453886bd7cSStanislav Fomichev if (buf != 0xA0) {
1463886bd7cSStanislav Fomichev log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
1473886bd7cSStanislav Fomichev err = -1;
1483886bd7cSStanislav Fomichev goto detach;
1493886bd7cSStanislav Fomichev }
1503886bd7cSStanislav Fomichev
1513886bd7cSStanislav Fomichev detach:
152*e01b4a72SStanislav Fomichev bpf_link__destroy(link_child);
153*e01b4a72SStanislav Fomichev bpf_link__destroy(link_parent);
1543886bd7cSStanislav Fomichev
1553886bd7cSStanislav Fomichev return err;
1563886bd7cSStanislav Fomichev }
1573886bd7cSStanislav Fomichev
run_setsockopt_test(struct sockopt_multi * obj,int cg_parent,int cg_child,int sock_fd)158*e01b4a72SStanislav Fomichev static int run_setsockopt_test(struct sockopt_multi *obj, int cg_parent,
1593886bd7cSStanislav Fomichev int cg_child, int sock_fd)
1603886bd7cSStanislav Fomichev {
161*e01b4a72SStanislav Fomichev struct bpf_link *link_parent = NULL;
162*e01b4a72SStanislav Fomichev struct bpf_link *link_child = NULL;
1633886bd7cSStanislav Fomichev socklen_t optlen;
1643886bd7cSStanislav Fomichev __u8 buf;
1653886bd7cSStanislav Fomichev int err;
1663886bd7cSStanislav Fomichev
1673886bd7cSStanislav Fomichev /* Set IP_TOS to the expected value (0x80). */
1683886bd7cSStanislav Fomichev
1693886bd7cSStanislav Fomichev buf = 0x80;
1703886bd7cSStanislav Fomichev err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
1713886bd7cSStanislav Fomichev if (err < 0) {
1723886bd7cSStanislav Fomichev log_err("Failed to call setsockopt(IP_TOS)");
1733886bd7cSStanislav Fomichev goto detach;
1743886bd7cSStanislav Fomichev }
1753886bd7cSStanislav Fomichev
1763886bd7cSStanislav Fomichev buf = 0x00;
1773886bd7cSStanislav Fomichev optlen = 1;
1783886bd7cSStanislav Fomichev err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
1793886bd7cSStanislav Fomichev if (err) {
1803886bd7cSStanislav Fomichev log_err("Failed to call getsockopt(IP_TOS)");
1813886bd7cSStanislav Fomichev goto detach;
1823886bd7cSStanislav Fomichev }
1833886bd7cSStanislav Fomichev
1843886bd7cSStanislav Fomichev if (buf != 0x80) {
1853886bd7cSStanislav Fomichev log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
1863886bd7cSStanislav Fomichev err = -1;
1873886bd7cSStanislav Fomichev goto detach;
1883886bd7cSStanislav Fomichev }
1893886bd7cSStanislav Fomichev
1903886bd7cSStanislav Fomichev /* Attach child program and make sure it adds 0x10. */
1913886bd7cSStanislav Fomichev
192*e01b4a72SStanislav Fomichev link_child = bpf_program__attach_cgroup(obj->progs._setsockopt,
193*e01b4a72SStanislav Fomichev cg_child);
194*e01b4a72SStanislav Fomichev if (!ASSERT_OK_PTR(link_child, "cg-attach-setsockopt_child"))
1953886bd7cSStanislav Fomichev goto detach;
1963886bd7cSStanislav Fomichev
1973886bd7cSStanislav Fomichev buf = 0x80;
1983886bd7cSStanislav Fomichev err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
1993886bd7cSStanislav Fomichev if (err < 0) {
2003886bd7cSStanislav Fomichev log_err("Failed to call setsockopt(IP_TOS)");
2013886bd7cSStanislav Fomichev goto detach;
2023886bd7cSStanislav Fomichev }
2033886bd7cSStanislav Fomichev
2043886bd7cSStanislav Fomichev buf = 0x00;
2053886bd7cSStanislav Fomichev optlen = 1;
2063886bd7cSStanislav Fomichev err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
2073886bd7cSStanislav Fomichev if (err) {
2083886bd7cSStanislav Fomichev log_err("Failed to call getsockopt(IP_TOS)");
2093886bd7cSStanislav Fomichev goto detach;
2103886bd7cSStanislav Fomichev }
2113886bd7cSStanislav Fomichev
2123886bd7cSStanislav Fomichev if (buf != 0x80 + 0x10) {
2133886bd7cSStanislav Fomichev log_err("Unexpected getsockopt 0x%x != 0x80 + 0x10", buf);
2143886bd7cSStanislav Fomichev err = -1;
2153886bd7cSStanislav Fomichev goto detach;
2163886bd7cSStanislav Fomichev }
2173886bd7cSStanislav Fomichev
2183886bd7cSStanislav Fomichev /* Attach parent program and make sure it adds another 0x10. */
2193886bd7cSStanislav Fomichev
220*e01b4a72SStanislav Fomichev link_parent = bpf_program__attach_cgroup(obj->progs._setsockopt,
221*e01b4a72SStanislav Fomichev cg_parent);
222*e01b4a72SStanislav Fomichev if (!ASSERT_OK_PTR(link_parent, "cg-attach-setsockopt_parent"))
2233886bd7cSStanislav Fomichev goto detach;
2243886bd7cSStanislav Fomichev
2253886bd7cSStanislav Fomichev buf = 0x80;
2263886bd7cSStanislav Fomichev err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
2273886bd7cSStanislav Fomichev if (err < 0) {
2283886bd7cSStanislav Fomichev log_err("Failed to call setsockopt(IP_TOS)");
2293886bd7cSStanislav Fomichev goto detach;
2303886bd7cSStanislav Fomichev }
2313886bd7cSStanislav Fomichev
2323886bd7cSStanislav Fomichev buf = 0x00;
2333886bd7cSStanislav Fomichev optlen = 1;
2343886bd7cSStanislav Fomichev err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
2353886bd7cSStanislav Fomichev if (err) {
2363886bd7cSStanislav Fomichev log_err("Failed to call getsockopt(IP_TOS)");
2373886bd7cSStanislav Fomichev goto detach;
2383886bd7cSStanislav Fomichev }
2393886bd7cSStanislav Fomichev
2403886bd7cSStanislav Fomichev if (buf != 0x80 + 2 * 0x10) {
2413886bd7cSStanislav Fomichev log_err("Unexpected getsockopt 0x%x != 0x80 + 2 * 0x10", buf);
2423886bd7cSStanislav Fomichev err = -1;
2433886bd7cSStanislav Fomichev goto detach;
2443886bd7cSStanislav Fomichev }
2453886bd7cSStanislav Fomichev
2463886bd7cSStanislav Fomichev detach:
247*e01b4a72SStanislav Fomichev bpf_link__destroy(link_child);
248*e01b4a72SStanislav Fomichev bpf_link__destroy(link_parent);
2493886bd7cSStanislav Fomichev
2503886bd7cSStanislav Fomichev return err;
2513886bd7cSStanislav Fomichev }
2523886bd7cSStanislav Fomichev
test_sockopt_multi(void)2533886bd7cSStanislav Fomichev void test_sockopt_multi(void)
2543886bd7cSStanislav Fomichev {
2553886bd7cSStanislav Fomichev int cg_parent = -1, cg_child = -1;
256*e01b4a72SStanislav Fomichev struct sockopt_multi *obj = NULL;
2573886bd7cSStanislav Fomichev int sock_fd = -1;
2583886bd7cSStanislav Fomichev
2593886bd7cSStanislav Fomichev cg_parent = test__join_cgroup("/parent");
260a605a6bbSWang Yufen if (!ASSERT_GE(cg_parent, 0, "join_cgroup /parent"))
2613886bd7cSStanislav Fomichev goto out;
2623886bd7cSStanislav Fomichev
2633886bd7cSStanislav Fomichev cg_child = test__join_cgroup("/parent/child");
264a605a6bbSWang Yufen if (!ASSERT_GE(cg_child, 0, "join_cgroup /parent/child"))
2653886bd7cSStanislav Fomichev goto out;
2663886bd7cSStanislav Fomichev
267*e01b4a72SStanislav Fomichev obj = sockopt_multi__open_and_load();
268*e01b4a72SStanislav Fomichev if (!ASSERT_OK_PTR(obj, "skel-load"))
269186d1a86SAndrii Nakryiko goto out;
270186d1a86SAndrii Nakryiko
271*e01b4a72SStanislav Fomichev obj->bss->page_size = sysconf(_SC_PAGESIZE);
2723886bd7cSStanislav Fomichev
2733886bd7cSStanislav Fomichev sock_fd = socket(AF_INET, SOCK_STREAM, 0);
274a605a6bbSWang Yufen if (!ASSERT_GE(sock_fd, 0, "socket"))
2753886bd7cSStanislav Fomichev goto out;
2763886bd7cSStanislav Fomichev
277a605a6bbSWang Yufen ASSERT_OK(run_getsockopt_test(obj, cg_parent, cg_child, sock_fd), "getsockopt_test");
278a605a6bbSWang Yufen ASSERT_OK(run_setsockopt_test(obj, cg_parent, cg_child, sock_fd), "setsockopt_test");
2793886bd7cSStanislav Fomichev
2803886bd7cSStanislav Fomichev out:
2813886bd7cSStanislav Fomichev close(sock_fd);
282*e01b4a72SStanislav Fomichev sockopt_multi__destroy(obj);
2833886bd7cSStanislav Fomichev close(cg_child);
2843886bd7cSStanislav Fomichev close(cg_parent);
2853886bd7cSStanislav Fomichev }
286