286 lines · c
1// SPDX-License-Identifier: GPL-2.02#include <test_progs.h>3#include "cgroup_helpers.h"4 5#include "sockopt_multi.skel.h"6 7static int run_getsockopt_test(struct sockopt_multi *obj, int cg_parent,8 int cg_child, int sock_fd)9{10 struct bpf_link *link_parent = NULL;11 struct bpf_link *link_child = NULL;12 socklen_t optlen;13 __u8 buf;14 int err;15 16 /* Set IP_TOS to the expected value (0x80). */17 18 buf = 0x80;19 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);20 if (err < 0) {21 log_err("Failed to call setsockopt(IP_TOS)");22 goto detach;23 }24 25 buf = 0x00;26 optlen = 1;27 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);28 if (err) {29 log_err("Failed to call getsockopt(IP_TOS)");30 goto detach;31 }32 33 if (buf != 0x80) {34 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);35 err = -1;36 goto detach;37 }38 39 /* Attach child program and make sure it returns new value:40 * - kernel: -> 0x8041 * - child: 0x80 -> 0x9042 */43 44 link_child = bpf_program__attach_cgroup(obj->progs._getsockopt_child,45 cg_child);46 if (!ASSERT_OK_PTR(link_child, "cg-attach-getsockopt_child"))47 goto detach;48 49 buf = 0x00;50 optlen = 1;51 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);52 if (err) {53 log_err("Failed to call getsockopt(IP_TOS)");54 goto detach;55 }56 57 if (buf != 0x90) {58 log_err("Unexpected getsockopt 0x%x != 0x90", buf);59 err = -1;60 goto detach;61 }62 63 /* Attach parent program and make sure it returns new value:64 * - kernel: -> 0x8065 * - child: 0x80 -> 0x9066 * - parent: 0x90 -> 0xA067 */68 69 link_parent = bpf_program__attach_cgroup(obj->progs._getsockopt_parent,70 cg_parent);71 if (!ASSERT_OK_PTR(link_parent, "cg-attach-getsockopt_parent"))72 goto detach;73 74 buf = 0x00;75 optlen = 1;76 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);77 if (err) {78 log_err("Failed to call getsockopt(IP_TOS)");79 goto detach;80 }81 82 if (buf != 0xA0) {83 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);84 err = -1;85 goto detach;86 }87 88 /* Setting unexpected initial sockopt should return EPERM:89 * - kernel: -> 0x4090 * - child: unexpected 0x40, EPERM91 * - parent: unexpected 0x40, EPERM92 */93 94 buf = 0x40;95 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);96 if (err < 0) {97 log_err("Failed to call setsockopt(IP_TOS)");98 goto detach;99 }100 101 buf = 0x00;102 optlen = 1;103 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);104 if (!err) {105 log_err("Unexpected success from getsockopt(IP_TOS)");106 goto detach;107 }108 109 /* Detach child program and make sure we still get EPERM:110 * - kernel: -> 0x40111 * - parent: unexpected 0x40, EPERM112 */113 114 bpf_link__destroy(link_child);115 link_child = NULL;116 117 buf = 0x00;118 optlen = 1;119 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);120 if (!err) {121 log_err("Unexpected success from getsockopt(IP_TOS)");122 goto detach;123 }124 125 /* Set initial value to the one the parent program expects:126 * - kernel: -> 0x90127 * - parent: 0x90 -> 0xA0128 */129 130 buf = 0x90;131 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);132 if (err < 0) {133 log_err("Failed to call setsockopt(IP_TOS)");134 goto detach;135 }136 137 buf = 0x00;138 optlen = 1;139 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);140 if (err) {141 log_err("Failed to call getsockopt(IP_TOS)");142 goto detach;143 }144 145 if (buf != 0xA0) {146 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);147 err = -1;148 goto detach;149 }150 151detach:152 bpf_link__destroy(link_child);153 bpf_link__destroy(link_parent);154 155 return err;156}157 158static int run_setsockopt_test(struct sockopt_multi *obj, int cg_parent,159 int cg_child, int sock_fd)160{161 struct bpf_link *link_parent = NULL;162 struct bpf_link *link_child = NULL;163 socklen_t optlen;164 __u8 buf;165 int err;166 167 /* Set IP_TOS to the expected value (0x80). */168 169 buf = 0x80;170 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);171 if (err < 0) {172 log_err("Failed to call setsockopt(IP_TOS)");173 goto detach;174 }175 176 buf = 0x00;177 optlen = 1;178 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);179 if (err) {180 log_err("Failed to call getsockopt(IP_TOS)");181 goto detach;182 }183 184 if (buf != 0x80) {185 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);186 err = -1;187 goto detach;188 }189 190 /* Attach child program and make sure it adds 0x10. */191 192 link_child = bpf_program__attach_cgroup(obj->progs._setsockopt,193 cg_child);194 if (!ASSERT_OK_PTR(link_child, "cg-attach-setsockopt_child"))195 goto detach;196 197 buf = 0x80;198 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);199 if (err < 0) {200 log_err("Failed to call setsockopt(IP_TOS)");201 goto detach;202 }203 204 buf = 0x00;205 optlen = 1;206 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);207 if (err) {208 log_err("Failed to call getsockopt(IP_TOS)");209 goto detach;210 }211 212 if (buf != 0x80 + 0x10) {213 log_err("Unexpected getsockopt 0x%x != 0x80 + 0x10", buf);214 err = -1;215 goto detach;216 }217 218 /* Attach parent program and make sure it adds another 0x10. */219 220 link_parent = bpf_program__attach_cgroup(obj->progs._setsockopt,221 cg_parent);222 if (!ASSERT_OK_PTR(link_parent, "cg-attach-setsockopt_parent"))223 goto detach;224 225 buf = 0x80;226 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);227 if (err < 0) {228 log_err("Failed to call setsockopt(IP_TOS)");229 goto detach;230 }231 232 buf = 0x00;233 optlen = 1;234 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);235 if (err) {236 log_err("Failed to call getsockopt(IP_TOS)");237 goto detach;238 }239 240 if (buf != 0x80 + 2 * 0x10) {241 log_err("Unexpected getsockopt 0x%x != 0x80 + 2 * 0x10", buf);242 err = -1;243 goto detach;244 }245 246detach:247 bpf_link__destroy(link_child);248 bpf_link__destroy(link_parent);249 250 return err;251}252 253void test_sockopt_multi(void)254{255 int cg_parent = -1, cg_child = -1;256 struct sockopt_multi *obj = NULL;257 int sock_fd = -1;258 259 cg_parent = test__join_cgroup("/parent");260 if (!ASSERT_GE(cg_parent, 0, "join_cgroup /parent"))261 goto out;262 263 cg_child = test__join_cgroup("/parent/child");264 if (!ASSERT_GE(cg_child, 0, "join_cgroup /parent/child"))265 goto out;266 267 obj = sockopt_multi__open_and_load();268 if (!ASSERT_OK_PTR(obj, "skel-load"))269 goto out;270 271 obj->bss->page_size = sysconf(_SC_PAGESIZE);272 273 sock_fd = socket(AF_INET, SOCK_STREAM, 0);274 if (!ASSERT_GE(sock_fd, 0, "socket"))275 goto out;276 277 ASSERT_OK(run_getsockopt_test(obj, cg_parent, cg_child, sock_fd), "getsockopt_test");278 ASSERT_OK(run_setsockopt_test(obj, cg_parent, cg_child, sock_fd), "setsockopt_test");279 280out:281 close(sock_fd);282 sockopt_multi__destroy(obj);283 close(cg_child);284 close(cg_parent);285}286