Loading...
Note: File does not exist in v5.4.
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}