0001
0002 #include <test_progs.h>
0003 #include "cgroup_helpers.h"
0004
0005 static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title, const char *name)
0006 {
0007 enum bpf_attach_type attach_type;
0008 enum bpf_prog_type prog_type;
0009 struct bpf_program *prog;
0010 int err;
0011
0012 err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
0013 if (err) {
0014 log_err("Failed to deduct types for %s BPF program", title);
0015 return -1;
0016 }
0017
0018 prog = bpf_object__find_program_by_name(obj, name);
0019 if (!prog) {
0020 log_err("Failed to find %s BPF program", name);
0021 return -1;
0022 }
0023
0024 err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
0025 attach_type, BPF_F_ALLOW_MULTI);
0026 if (err) {
0027 log_err("Failed to attach %s BPF program", name);
0028 return -1;
0029 }
0030
0031 return 0;
0032 }
0033
0034 static int prog_detach(struct bpf_object *obj, int cgroup_fd, const char *title, const char *name)
0035 {
0036 enum bpf_attach_type attach_type;
0037 enum bpf_prog_type prog_type;
0038 struct bpf_program *prog;
0039 int err;
0040
0041 err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
0042 if (err)
0043 return -1;
0044
0045 prog = bpf_object__find_program_by_name(obj, name);
0046 if (!prog)
0047 return -1;
0048
0049 err = bpf_prog_detach2(bpf_program__fd(prog), cgroup_fd,
0050 attach_type);
0051 if (err)
0052 return -1;
0053
0054 return 0;
0055 }
0056
0057 static int run_getsockopt_test(struct bpf_object *obj, int cg_parent,
0058 int cg_child, int sock_fd)
0059 {
0060 socklen_t optlen;
0061 __u8 buf;
0062 int err;
0063
0064
0065
0066 buf = 0x80;
0067 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
0068 if (err < 0) {
0069 log_err("Failed to call setsockopt(IP_TOS)");
0070 goto detach;
0071 }
0072
0073 buf = 0x00;
0074 optlen = 1;
0075 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
0076 if (err) {
0077 log_err("Failed to call getsockopt(IP_TOS)");
0078 goto detach;
0079 }
0080
0081 if (buf != 0x80) {
0082 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
0083 err = -1;
0084 goto detach;
0085 }
0086
0087
0088
0089
0090
0091
0092 err = prog_attach(obj, cg_child, "cgroup/getsockopt", "_getsockopt_child");
0093 if (err)
0094 goto detach;
0095
0096 buf = 0x00;
0097 optlen = 1;
0098 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
0099 if (err) {
0100 log_err("Failed to call getsockopt(IP_TOS)");
0101 goto detach;
0102 }
0103
0104 if (buf != 0x90) {
0105 log_err("Unexpected getsockopt 0x%x != 0x90", buf);
0106 err = -1;
0107 goto detach;
0108 }
0109
0110
0111
0112
0113
0114
0115
0116 err = prog_attach(obj, cg_parent, "cgroup/getsockopt", "_getsockopt_parent");
0117 if (err)
0118 goto detach;
0119
0120 buf = 0x00;
0121 optlen = 1;
0122 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
0123 if (err) {
0124 log_err("Failed to call getsockopt(IP_TOS)");
0125 goto detach;
0126 }
0127
0128 if (buf != 0xA0) {
0129 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
0130 err = -1;
0131 goto detach;
0132 }
0133
0134
0135
0136
0137
0138
0139
0140 buf = 0x40;
0141 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
0142 if (err < 0) {
0143 log_err("Failed to call setsockopt(IP_TOS)");
0144 goto detach;
0145 }
0146
0147 buf = 0x00;
0148 optlen = 1;
0149 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
0150 if (!err) {
0151 log_err("Unexpected success from getsockopt(IP_TOS)");
0152 goto detach;
0153 }
0154
0155
0156
0157
0158
0159
0160 err = prog_detach(obj, cg_child, "cgroup/getsockopt", "_getsockopt_child");
0161 if (err) {
0162 log_err("Failed to detach child program");
0163 goto detach;
0164 }
0165
0166 buf = 0x00;
0167 optlen = 1;
0168 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
0169 if (!err) {
0170 log_err("Unexpected success from getsockopt(IP_TOS)");
0171 goto detach;
0172 }
0173
0174
0175
0176
0177
0178
0179 buf = 0x90;
0180 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
0181 if (err < 0) {
0182 log_err("Failed to call setsockopt(IP_TOS)");
0183 goto detach;
0184 }
0185
0186 buf = 0x00;
0187 optlen = 1;
0188 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
0189 if (err) {
0190 log_err("Failed to call getsockopt(IP_TOS)");
0191 goto detach;
0192 }
0193
0194 if (buf != 0xA0) {
0195 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
0196 err = -1;
0197 goto detach;
0198 }
0199
0200 detach:
0201 prog_detach(obj, cg_child, "cgroup/getsockopt", "_getsockopt_child");
0202 prog_detach(obj, cg_parent, "cgroup/getsockopt", "_getsockopt_parent");
0203
0204 return err;
0205 }
0206
0207 static int run_setsockopt_test(struct bpf_object *obj, int cg_parent,
0208 int cg_child, int sock_fd)
0209 {
0210 socklen_t optlen;
0211 __u8 buf;
0212 int err;
0213
0214
0215
0216 buf = 0x80;
0217 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
0218 if (err < 0) {
0219 log_err("Failed to call setsockopt(IP_TOS)");
0220 goto detach;
0221 }
0222
0223 buf = 0x00;
0224 optlen = 1;
0225 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
0226 if (err) {
0227 log_err("Failed to call getsockopt(IP_TOS)");
0228 goto detach;
0229 }
0230
0231 if (buf != 0x80) {
0232 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
0233 err = -1;
0234 goto detach;
0235 }
0236
0237
0238
0239 err = prog_attach(obj, cg_child, "cgroup/setsockopt", "_setsockopt");
0240 if (err)
0241 goto detach;
0242
0243 buf = 0x80;
0244 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
0245 if (err < 0) {
0246 log_err("Failed to call setsockopt(IP_TOS)");
0247 goto detach;
0248 }
0249
0250 buf = 0x00;
0251 optlen = 1;
0252 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
0253 if (err) {
0254 log_err("Failed to call getsockopt(IP_TOS)");
0255 goto detach;
0256 }
0257
0258 if (buf != 0x80 + 0x10) {
0259 log_err("Unexpected getsockopt 0x%x != 0x80 + 0x10", buf);
0260 err = -1;
0261 goto detach;
0262 }
0263
0264
0265
0266 err = prog_attach(obj, cg_parent, "cgroup/setsockopt", "_setsockopt");
0267 if (err)
0268 goto detach;
0269
0270 buf = 0x80;
0271 err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
0272 if (err < 0) {
0273 log_err("Failed to call setsockopt(IP_TOS)");
0274 goto detach;
0275 }
0276
0277 buf = 0x00;
0278 optlen = 1;
0279 err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
0280 if (err) {
0281 log_err("Failed to call getsockopt(IP_TOS)");
0282 goto detach;
0283 }
0284
0285 if (buf != 0x80 + 2 * 0x10) {
0286 log_err("Unexpected getsockopt 0x%x != 0x80 + 2 * 0x10", buf);
0287 err = -1;
0288 goto detach;
0289 }
0290
0291 detach:
0292 prog_detach(obj, cg_child, "cgroup/setsockopt", "_setsockopt");
0293 prog_detach(obj, cg_parent, "cgroup/setsockopt", "_setsockopt");
0294
0295 return err;
0296 }
0297
0298 void test_sockopt_multi(void)
0299 {
0300 int cg_parent = -1, cg_child = -1;
0301 struct bpf_object *obj = NULL;
0302 int sock_fd = -1;
0303 int err = -1;
0304
0305 cg_parent = test__join_cgroup("/parent");
0306 if (CHECK_FAIL(cg_parent < 0))
0307 goto out;
0308
0309 cg_child = test__join_cgroup("/parent/child");
0310 if (CHECK_FAIL(cg_child < 0))
0311 goto out;
0312
0313 obj = bpf_object__open_file("sockopt_multi.o", NULL);
0314 if (!ASSERT_OK_PTR(obj, "obj_load"))
0315 goto out;
0316
0317 err = bpf_object__load(obj);
0318 if (!ASSERT_OK(err, "obj_load"))
0319 goto out;
0320
0321 sock_fd = socket(AF_INET, SOCK_STREAM, 0);
0322 if (CHECK_FAIL(sock_fd < 0))
0323 goto out;
0324
0325 CHECK_FAIL(run_getsockopt_test(obj, cg_parent, cg_child, sock_fd));
0326 CHECK_FAIL(run_setsockopt_test(obj, cg_parent, cg_child, sock_fd));
0327
0328 out:
0329 close(sock_fd);
0330 bpf_object__close(obj);
0331 close(cg_child);
0332 close(cg_parent);
0333 }