root/tools/testing/selftests/bpf/prog_tests/sockopt_multi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. prog_attach
  2. prog_detach
  3. run_getsockopt_test
  4. run_setsockopt_test
  5. test_sockopt_multi

   1 // SPDX-License-Identifier: GPL-2.0
   2 #include <test_progs.h>
   3 #include "cgroup_helpers.h"
   4 
   5 static int prog_attach(struct bpf_object *obj, int cgroup_fd, const char *title)
   6 {
   7         enum bpf_attach_type attach_type;
   8         enum bpf_prog_type prog_type;
   9         struct bpf_program *prog;
  10         int err;
  11 
  12         err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
  13         if (err) {
  14                 log_err("Failed to deduct types for %s BPF program", title);
  15                 return -1;
  16         }
  17 
  18         prog = bpf_object__find_program_by_title(obj, title);
  19         if (!prog) {
  20                 log_err("Failed to find %s BPF program", title);
  21                 return -1;
  22         }
  23 
  24         err = bpf_prog_attach(bpf_program__fd(prog), cgroup_fd,
  25                               attach_type, BPF_F_ALLOW_MULTI);
  26         if (err) {
  27                 log_err("Failed to attach %s BPF program", title);
  28                 return -1;
  29         }
  30 
  31         return 0;
  32 }
  33 
  34 static int prog_detach(struct bpf_object *obj, int cgroup_fd, const char *title)
  35 {
  36         enum bpf_attach_type attach_type;
  37         enum bpf_prog_type prog_type;
  38         struct bpf_program *prog;
  39         int err;
  40 
  41         err = libbpf_prog_type_by_name(title, &prog_type, &attach_type);
  42         if (err)
  43                 return -1;
  44 
  45         prog = bpf_object__find_program_by_title(obj, title);
  46         if (!prog)
  47                 return -1;
  48 
  49         err = bpf_prog_detach2(bpf_program__fd(prog), cgroup_fd,
  50                                attach_type);
  51         if (err)
  52                 return -1;
  53 
  54         return 0;
  55 }
  56 
  57 static int run_getsockopt_test(struct bpf_object *obj, int cg_parent,
  58                                int cg_child, int sock_fd)
  59 {
  60         socklen_t optlen;
  61         __u8 buf;
  62         int err;
  63 
  64         /* Set IP_TOS to the expected value (0x80). */
  65 
  66         buf = 0x80;
  67         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
  68         if (err < 0) {
  69                 log_err("Failed to call setsockopt(IP_TOS)");
  70                 goto detach;
  71         }
  72 
  73         buf = 0x00;
  74         optlen = 1;
  75         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
  76         if (err) {
  77                 log_err("Failed to call getsockopt(IP_TOS)");
  78                 goto detach;
  79         }
  80 
  81         if (buf != 0x80) {
  82                 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
  83                 err = -1;
  84                 goto detach;
  85         }
  86 
  87         /* Attach child program and make sure it returns new value:
  88          * - kernel:      -> 0x80
  89          * - child:  0x80 -> 0x90
  90          */
  91 
  92         err = prog_attach(obj, cg_child, "cgroup/getsockopt/child");
  93         if (err)
  94                 goto detach;
  95 
  96         buf = 0x00;
  97         optlen = 1;
  98         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
  99         if (err) {
 100                 log_err("Failed to call getsockopt(IP_TOS)");
 101                 goto detach;
 102         }
 103 
 104         if (buf != 0x90) {
 105                 log_err("Unexpected getsockopt 0x%x != 0x90", buf);
 106                 err = -1;
 107                 goto detach;
 108         }
 109 
 110         /* Attach parent program and make sure it returns new value:
 111          * - kernel:      -> 0x80
 112          * - child:  0x80 -> 0x90
 113          * - parent: 0x90 -> 0xA0
 114          */
 115 
 116         err = prog_attach(obj, cg_parent, "cgroup/getsockopt/parent");
 117         if (err)
 118                 goto detach;
 119 
 120         buf = 0x00;
 121         optlen = 1;
 122         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
 123         if (err) {
 124                 log_err("Failed to call getsockopt(IP_TOS)");
 125                 goto detach;
 126         }
 127 
 128         if (buf != 0xA0) {
 129                 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
 130                 err = -1;
 131                 goto detach;
 132         }
 133 
 134         /* Setting unexpected initial sockopt should return EPERM:
 135          * - kernel: -> 0x40
 136          * - child:  unexpected 0x40, EPERM
 137          * - parent: unexpected 0x40, EPERM
 138          */
 139 
 140         buf = 0x40;
 141         if (setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1) < 0) {
 142                 log_err("Failed to call setsockopt(IP_TOS)");
 143                 goto detach;
 144         }
 145 
 146         buf = 0x00;
 147         optlen = 1;
 148         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
 149         if (!err) {
 150                 log_err("Unexpected success from getsockopt(IP_TOS)");
 151                 goto detach;
 152         }
 153 
 154         /* Detach child program and make sure we still get EPERM:
 155          * - kernel: -> 0x40
 156          * - parent: unexpected 0x40, EPERM
 157          */
 158 
 159         err = prog_detach(obj, cg_child, "cgroup/getsockopt/child");
 160         if (err) {
 161                 log_err("Failed to detach child program");
 162                 goto detach;
 163         }
 164 
 165         buf = 0x00;
 166         optlen = 1;
 167         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
 168         if (!err) {
 169                 log_err("Unexpected success from getsockopt(IP_TOS)");
 170                 goto detach;
 171         }
 172 
 173         /* Set initial value to the one the parent program expects:
 174          * - kernel:      -> 0x90
 175          * - parent: 0x90 -> 0xA0
 176          */
 177 
 178         buf = 0x90;
 179         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
 180         if (err < 0) {
 181                 log_err("Failed to call setsockopt(IP_TOS)");
 182                 goto detach;
 183         }
 184 
 185         buf = 0x00;
 186         optlen = 1;
 187         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
 188         if (err) {
 189                 log_err("Failed to call getsockopt(IP_TOS)");
 190                 goto detach;
 191         }
 192 
 193         if (buf != 0xA0) {
 194                 log_err("Unexpected getsockopt 0x%x != 0xA0", buf);
 195                 err = -1;
 196                 goto detach;
 197         }
 198 
 199 detach:
 200         prog_detach(obj, cg_child, "cgroup/getsockopt/child");
 201         prog_detach(obj, cg_parent, "cgroup/getsockopt/parent");
 202 
 203         return err;
 204 }
 205 
 206 static int run_setsockopt_test(struct bpf_object *obj, int cg_parent,
 207                                int cg_child, int sock_fd)
 208 {
 209         socklen_t optlen;
 210         __u8 buf;
 211         int err;
 212 
 213         /* Set IP_TOS to the expected value (0x80). */
 214 
 215         buf = 0x80;
 216         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
 217         if (err < 0) {
 218                 log_err("Failed to call setsockopt(IP_TOS)");
 219                 goto detach;
 220         }
 221 
 222         buf = 0x00;
 223         optlen = 1;
 224         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
 225         if (err) {
 226                 log_err("Failed to call getsockopt(IP_TOS)");
 227                 goto detach;
 228         }
 229 
 230         if (buf != 0x80) {
 231                 log_err("Unexpected getsockopt 0x%x != 0x80 without BPF", buf);
 232                 err = -1;
 233                 goto detach;
 234         }
 235 
 236         /* Attach child program and make sure it adds 0x10. */
 237 
 238         err = prog_attach(obj, cg_child, "cgroup/setsockopt");
 239         if (err)
 240                 goto detach;
 241 
 242         buf = 0x80;
 243         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
 244         if (err < 0) {
 245                 log_err("Failed to call setsockopt(IP_TOS)");
 246                 goto detach;
 247         }
 248 
 249         buf = 0x00;
 250         optlen = 1;
 251         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
 252         if (err) {
 253                 log_err("Failed to call getsockopt(IP_TOS)");
 254                 goto detach;
 255         }
 256 
 257         if (buf != 0x80 + 0x10) {
 258                 log_err("Unexpected getsockopt 0x%x != 0x80 + 0x10", buf);
 259                 err = -1;
 260                 goto detach;
 261         }
 262 
 263         /* Attach parent program and make sure it adds another 0x10. */
 264 
 265         err = prog_attach(obj, cg_parent, "cgroup/setsockopt");
 266         if (err)
 267                 goto detach;
 268 
 269         buf = 0x80;
 270         err = setsockopt(sock_fd, SOL_IP, IP_TOS, &buf, 1);
 271         if (err < 0) {
 272                 log_err("Failed to call setsockopt(IP_TOS)");
 273                 goto detach;
 274         }
 275 
 276         buf = 0x00;
 277         optlen = 1;
 278         err = getsockopt(sock_fd, SOL_IP, IP_TOS, &buf, &optlen);
 279         if (err) {
 280                 log_err("Failed to call getsockopt(IP_TOS)");
 281                 goto detach;
 282         }
 283 
 284         if (buf != 0x80 + 2 * 0x10) {
 285                 log_err("Unexpected getsockopt 0x%x != 0x80 + 2 * 0x10", buf);
 286                 err = -1;
 287                 goto detach;
 288         }
 289 
 290 detach:
 291         prog_detach(obj, cg_child, "cgroup/setsockopt");
 292         prog_detach(obj, cg_parent, "cgroup/setsockopt");
 293 
 294         return err;
 295 }
 296 
 297 void test_sockopt_multi(void)
 298 {
 299         struct bpf_prog_load_attr attr = {
 300                 .file = "./sockopt_multi.o",
 301         };
 302         int cg_parent = -1, cg_child = -1;
 303         struct bpf_object *obj = NULL;
 304         int sock_fd = -1;
 305         int err = -1;
 306         int ignored;
 307 
 308         cg_parent = test__join_cgroup("/parent");
 309         if (CHECK_FAIL(cg_parent < 0))
 310                 goto out;
 311 
 312         cg_child = test__join_cgroup("/parent/child");
 313         if (CHECK_FAIL(cg_child < 0))
 314                 goto out;
 315 
 316         err = bpf_prog_load_xattr(&attr, &obj, &ignored);
 317         if (CHECK_FAIL(err))
 318                 goto out;
 319 
 320         sock_fd = socket(AF_INET, SOCK_STREAM, 0);
 321         if (CHECK_FAIL(sock_fd < 0))
 322                 goto out;
 323 
 324         CHECK_FAIL(run_getsockopt_test(obj, cg_parent, cg_child, sock_fd));
 325         CHECK_FAIL(run_setsockopt_test(obj, cg_parent, cg_child, sock_fd));
 326 
 327 out:
 328         close(sock_fd);
 329         bpf_object__close(obj);
 330         close(cg_child);
 331         close(cg_parent);
 332 }

/* [<][>][^][v][top][bottom][index][help] */