1 // SPDX-License-Identifier: GPL-2.0 2 #define _GNU_SOURCE 3 #include <sched.h> 4 #include <stdlib.h> 5 #include <sys/types.h> 6 #include <sys/socket.h> 7 8 #include "test_progs.h" 9 #include "cap_helpers.h" 10 #include "bind_perm.skel.h" 11 12 static int create_netns(void) 13 { 14 if (!ASSERT_OK(unshare(CLONE_NEWNET), "create netns")) 15 return -1; 16 17 return 0; 18 } 19 20 void try_bind(int family, int port, int expected_errno) 21 { 22 struct sockaddr_storage addr = {}; 23 struct sockaddr_in6 *sin6; 24 struct sockaddr_in *sin; 25 int fd = -1; 26 27 fd = socket(family, SOCK_STREAM, 0); 28 if (!ASSERT_GE(fd, 0, "socket")) 29 goto close_socket; 30 31 if (family == AF_INET) { 32 sin = (struct sockaddr_in *)&addr; 33 sin->sin_family = family; 34 sin->sin_port = htons(port); 35 } else { 36 sin6 = (struct sockaddr_in6 *)&addr; 37 sin6->sin6_family = family; 38 sin6->sin6_port = htons(port); 39 } 40 41 errno = 0; 42 bind(fd, (struct sockaddr *)&addr, sizeof(addr)); 43 ASSERT_EQ(errno, expected_errno, "bind"); 44 45 close_socket: 46 if (fd >= 0) 47 close(fd); 48 } 49 50 void test_bind_perm(void) 51 { 52 const __u64 net_bind_svc_cap = 1ULL << CAP_NET_BIND_SERVICE; 53 struct bind_perm *skel; 54 __u64 old_caps = 0; 55 int cgroup_fd; 56 57 if (create_netns()) 58 return; 59 60 cgroup_fd = test__join_cgroup("/bind_perm"); 61 if (!ASSERT_GE(cgroup_fd, 0, "test__join_cgroup")) 62 return; 63 64 skel = bind_perm__open_and_load(); 65 if (!ASSERT_OK_PTR(skel, "skel")) 66 goto close_cgroup_fd; 67 68 skel->links.bind_v4_prog = bpf_program__attach_cgroup(skel->progs.bind_v4_prog, cgroup_fd); 69 if (!ASSERT_OK_PTR(skel, "bind_v4_prog")) 70 goto close_skeleton; 71 72 skel->links.bind_v6_prog = bpf_program__attach_cgroup(skel->progs.bind_v6_prog, cgroup_fd); 73 if (!ASSERT_OK_PTR(skel, "bind_v6_prog")) 74 goto close_skeleton; 75 76 ASSERT_OK(cap_disable_effective(net_bind_svc_cap, &old_caps), 77 "cap_disable_effective"); 78 79 try_bind(AF_INET, 110, EACCES); 80 try_bind(AF_INET6, 110, EACCES); 81 82 try_bind(AF_INET, 111, 0); 83 try_bind(AF_INET6, 111, 0); 84 85 if (old_caps & net_bind_svc_cap) 86 ASSERT_OK(cap_enable_effective(net_bind_svc_cap, NULL), 87 "cap_enable_effective"); 88 89 close_skeleton: 90 bind_perm__destroy(skel); 91 close_cgroup_fd: 92 close(cgroup_fd); 93 } 94