linux/tools/testing/selftests/bpf/prog_tests/bind_perm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <test_progs.h>
   3#include "bind_perm.skel.h"
   4
   5#include <sys/types.h>
   6#include <sys/socket.h>
   7#include <sys/capability.h>
   8
   9static int duration;
  10
  11void try_bind(int family, int port, int expected_errno)
  12{
  13        struct sockaddr_storage addr = {};
  14        struct sockaddr_in6 *sin6;
  15        struct sockaddr_in *sin;
  16        int fd = -1;
  17
  18        fd = socket(family, SOCK_STREAM, 0);
  19        if (CHECK(fd < 0, "fd", "errno %d", errno))
  20                goto close_socket;
  21
  22        if (family == AF_INET) {
  23                sin = (struct sockaddr_in *)&addr;
  24                sin->sin_family = family;
  25                sin->sin_port = htons(port);
  26        } else {
  27                sin6 = (struct sockaddr_in6 *)&addr;
  28                sin6->sin6_family = family;
  29                sin6->sin6_port = htons(port);
  30        }
  31
  32        errno = 0;
  33        bind(fd, (struct sockaddr *)&addr, sizeof(addr));
  34        ASSERT_EQ(errno, expected_errno, "bind");
  35
  36close_socket:
  37        if (fd >= 0)
  38                close(fd);
  39}
  40
  41bool cap_net_bind_service(cap_flag_value_t flag)
  42{
  43        const cap_value_t cap_net_bind_service = CAP_NET_BIND_SERVICE;
  44        cap_flag_value_t original_value;
  45        bool was_effective = false;
  46        cap_t caps;
  47
  48        caps = cap_get_proc();
  49        if (CHECK(!caps, "cap_get_proc", "errno %d", errno))
  50                goto free_caps;
  51
  52        if (CHECK(cap_get_flag(caps, CAP_NET_BIND_SERVICE, CAP_EFFECTIVE,
  53                               &original_value),
  54                  "cap_get_flag", "errno %d", errno))
  55                goto free_caps;
  56
  57        was_effective = (original_value == CAP_SET);
  58
  59        if (CHECK(cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap_net_bind_service,
  60                               flag),
  61                  "cap_set_flag", "errno %d", errno))
  62                goto free_caps;
  63
  64        if (CHECK(cap_set_proc(caps), "cap_set_proc", "errno %d", errno))
  65                goto free_caps;
  66
  67free_caps:
  68        CHECK(cap_free(caps), "cap_free", "errno %d", errno);
  69        return was_effective;
  70}
  71
  72void test_bind_perm(void)
  73{
  74        bool cap_was_effective;
  75        struct bind_perm *skel;
  76        int cgroup_fd;
  77
  78        cgroup_fd = test__join_cgroup("/bind_perm");
  79        if (CHECK(cgroup_fd < 0, "cg-join", "errno %d", errno))
  80                return;
  81
  82        skel = bind_perm__open_and_load();
  83        if (!ASSERT_OK_PTR(skel, "skel"))
  84                goto close_cgroup_fd;
  85
  86        skel->links.bind_v4_prog = bpf_program__attach_cgroup(skel->progs.bind_v4_prog, cgroup_fd);
  87        if (!ASSERT_OK_PTR(skel, "bind_v4_prog"))
  88                goto close_skeleton;
  89
  90        skel->links.bind_v6_prog = bpf_program__attach_cgroup(skel->progs.bind_v6_prog, cgroup_fd);
  91        if (!ASSERT_OK_PTR(skel, "bind_v6_prog"))
  92                goto close_skeleton;
  93
  94        cap_was_effective = cap_net_bind_service(CAP_CLEAR);
  95
  96        try_bind(AF_INET, 110, EACCES);
  97        try_bind(AF_INET6, 110, EACCES);
  98
  99        try_bind(AF_INET, 111, 0);
 100        try_bind(AF_INET6, 111, 0);
 101
 102        if (cap_was_effective)
 103                cap_net_bind_service(CAP_SET);
 104
 105close_skeleton:
 106        bind_perm__destroy(skel);
 107close_cgroup_fd:
 108        close(cgroup_fd);
 109}
 110