Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
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     /* Set IP_TOS to the expected value (0x80). */
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     /* Attach child program and make sure it returns new value:
0088      * - kernel:      -> 0x80
0089      * - child:  0x80 -> 0x90
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     /* Attach parent program and make sure it returns new value:
0111      * - kernel:      -> 0x80
0112      * - child:  0x80 -> 0x90
0113      * - parent: 0x90 -> 0xA0
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     /* Setting unexpected initial sockopt should return EPERM:
0135      * - kernel: -> 0x40
0136      * - child:  unexpected 0x40, EPERM
0137      * - parent: unexpected 0x40, EPERM
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     /* Detach child program and make sure we still get EPERM:
0156      * - kernel: -> 0x40
0157      * - parent: unexpected 0x40, EPERM
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     /* Set initial value to the one the parent program expects:
0175      * - kernel:      -> 0x90
0176      * - parent: 0x90 -> 0xA0
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     /* Set IP_TOS to the expected value (0x80). */
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     /* Attach child program and make sure it adds 0x10. */
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     /* Attach parent program and make sure it adds another 0x10. */
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 }