linux/tools/testing/selftests/bpf/prog_tests/cgroup_attach_autodetach.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2
   3#include <test_progs.h>
   4
   5#include "cgroup_helpers.h"
   6
   7#define PING_CMD        "ping -q -c1 -w1 127.0.0.1 > /dev/null"
   8
   9static char bpf_log_buf[BPF_LOG_BUF_SIZE];
  10
  11static int prog_load(void)
  12{
  13        struct bpf_insn prog[] = {
  14                BPF_MOV64_IMM(BPF_REG_0, 1), /* r0 = 1 */
  15                BPF_EXIT_INSN(),
  16        };
  17        size_t insns_cnt = sizeof(prog) / sizeof(struct bpf_insn);
  18
  19        return bpf_load_program(BPF_PROG_TYPE_CGROUP_SKB,
  20                               prog, insns_cnt, "GPL", 0,
  21                               bpf_log_buf, BPF_LOG_BUF_SIZE);
  22}
  23
  24void test_cgroup_attach_autodetach(void)
  25{
  26        __u32 duration = 0, prog_cnt = 4, attach_flags;
  27        int allow_prog[2] = {-1};
  28        __u32 prog_ids[2] = {0};
  29        void *ptr = NULL;
  30        int cg = 0, i;
  31        int attempts;
  32
  33        for (i = 0; i < ARRAY_SIZE(allow_prog); i++) {
  34                allow_prog[i] = prog_load();
  35                if (CHECK(allow_prog[i] < 0, "prog_load",
  36                          "verifier output:\n%s\n-------\n", bpf_log_buf))
  37                        goto err;
  38        }
  39
  40        if (CHECK_FAIL(setup_cgroup_environment()))
  41                goto err;
  42
  43        /* create a cgroup, attach two programs and remember their ids */
  44        cg = create_and_get_cgroup("/cg_autodetach");
  45        if (CHECK_FAIL(cg < 0))
  46                goto err;
  47
  48        if (CHECK_FAIL(join_cgroup("/cg_autodetach")))
  49                goto err;
  50
  51        for (i = 0; i < ARRAY_SIZE(allow_prog); i++)
  52                if (CHECK(bpf_prog_attach(allow_prog[i], cg,
  53                                          BPF_CGROUP_INET_EGRESS,
  54                                          BPF_F_ALLOW_MULTI),
  55                          "prog_attach", "prog[%d], errno=%d\n", i, errno))
  56                        goto err;
  57
  58        /* make sure that programs are attached and run some traffic */
  59        if (CHECK(bpf_prog_query(cg, BPF_CGROUP_INET_EGRESS, 0, &attach_flags,
  60                                 prog_ids, &prog_cnt),
  61                  "prog_query", "errno=%d\n", errno))
  62                goto err;
  63        if (CHECK_FAIL(system(PING_CMD)))
  64                goto err;
  65
  66        /* allocate some memory (4Mb) to pin the original cgroup */
  67        ptr = malloc(4 * (1 << 20));
  68        if (CHECK_FAIL(!ptr))
  69                goto err;
  70
  71        /* close programs and cgroup fd */
  72        for (i = 0; i < ARRAY_SIZE(allow_prog); i++) {
  73                close(allow_prog[i]);
  74                allow_prog[i] = -1;
  75        }
  76
  77        close(cg);
  78        cg = 0;
  79
  80        /* leave the cgroup and remove it. don't detach programs */
  81        cleanup_cgroup_environment();
  82
  83        /* wait for the asynchronous auto-detachment.
  84         * wait for no more than 5 sec and give up.
  85         */
  86        for (i = 0; i < ARRAY_SIZE(prog_ids); i++) {
  87                for (attempts = 5; attempts >= 0; attempts--) {
  88                        int fd = bpf_prog_get_fd_by_id(prog_ids[i]);
  89
  90                        if (fd < 0)
  91                                break;
  92
  93                        /* don't leave the fd open */
  94                        close(fd);
  95
  96                        if (CHECK_FAIL(!attempts))
  97                                goto err;
  98
  99                        sleep(1);
 100                }
 101        }
 102
 103err:
 104        for (i = 0; i < ARRAY_SIZE(allow_prog); i++)
 105                if (allow_prog[i] >= 0)
 106                        close(allow_prog[i]);
 107        if (cg)
 108                close(cg);
 109        free(ptr);
 110        cleanup_cgroup_environment();
 111}
 112