1 // SPDX-License-Identifier: GPL-2.0 2 3 #include "vmlinux.h" 4 #include "bpf_tracing_net.h" 5 #include <bpf/bpf_helpers.h> 6 #include <bpf/bpf_tracing.h> 7 8 char _license[] SEC("license") = "GPL"; 9 10 extern bool CONFIG_SECURITY_SELINUX __kconfig __weak; 11 extern bool CONFIG_SECURITY_SMACK __kconfig __weak; 12 extern bool CONFIG_SECURITY_APPARMOR __kconfig __weak; 13 14 #ifndef AF_PACKET 15 #define AF_PACKET 17 16 #endif 17 18 #ifndef AF_UNIX 19 #define AF_UNIX 1 20 #endif 21 22 #ifndef EPERM 23 #define EPERM 1 24 #endif 25 26 struct { 27 __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE); 28 __type(key, __u64); 29 __type(value, __u64); 30 } cgroup_storage SEC(".maps"); 31 32 int called_socket_post_create; 33 int called_socket_post_create2; 34 int called_socket_bind; 35 int called_socket_bind2; 36 int called_socket_alloc; 37 int called_socket_clone; 38 39 static __always_inline int test_local_storage(void) 40 { 41 __u64 *val; 42 43 val = bpf_get_local_storage(&cgroup_storage, 0); 44 if (!val) 45 return 0; 46 *val += 1; 47 48 return 1; 49 } 50 51 static __always_inline int real_create(struct socket *sock, int family, 52 int protocol) 53 { 54 struct sock *sk; 55 int prio = 123; 56 57 /* Reject non-tx-only AF_PACKET. */ 58 if (family == AF_PACKET && protocol != 0) 59 return 0; /* EPERM */ 60 61 sk = sock->sk; 62 if (!sk) 63 return 1; 64 65 /* The rest of the sockets get default policy. */ 66 if (bpf_setsockopt(sk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) 67 return 0; /* EPERM */ 68 69 /* Make sure bpf_getsockopt is allowed and works. */ 70 prio = 0; 71 if (bpf_getsockopt(sk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) 72 return 0; /* EPERM */ 73 if (prio != 123) 74 return 0; /* EPERM */ 75 76 /* Can access cgroup local storage. */ 77 if (!test_local_storage()) 78 return 0; /* EPERM */ 79 80 return 1; 81 } 82 83 /* __cgroup_bpf_run_lsm_socket */ 84 SEC("lsm_cgroup/socket_post_create") 85 int BPF_PROG(socket_post_create, struct socket *sock, int family, 86 int type, int protocol, int kern) 87 { 88 called_socket_post_create++; 89 return real_create(sock, family, protocol); 90 } 91 92 /* __cgroup_bpf_run_lsm_socket */ 93 SEC("lsm_cgroup/socket_post_create") 94 int BPF_PROG(socket_post_create2, struct socket *sock, int family, 95 int type, int protocol, int kern) 96 { 97 called_socket_post_create2++; 98 return real_create(sock, family, protocol); 99 } 100 101 static __always_inline int real_bind(struct socket *sock, 102 struct sockaddr *address, 103 int addrlen) 104 { 105 struct sockaddr_ll sa = {}; 106 107 if (sock->sk->__sk_common.skc_family != AF_PACKET) 108 return 1; 109 110 if (sock->sk->sk_kern_sock) 111 return 1; 112 113 bpf_probe_read_kernel(&sa, sizeof(sa), address); 114 if (sa.sll_protocol) 115 return 0; /* EPERM */ 116 117 /* Can access cgroup local storage. */ 118 if (!test_local_storage()) 119 return 0; /* EPERM */ 120 121 return 1; 122 } 123 124 /* __cgroup_bpf_run_lsm_socket */ 125 SEC("lsm_cgroup/socket_bind") 126 int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, 127 int addrlen) 128 { 129 called_socket_bind++; 130 return real_bind(sock, address, addrlen); 131 } 132 133 /* __cgroup_bpf_run_lsm_socket */ 134 SEC("lsm_cgroup/socket_bind") 135 int BPF_PROG(socket_bind2, struct socket *sock, struct sockaddr *address, 136 int addrlen) 137 { 138 called_socket_bind2++; 139 return real_bind(sock, address, addrlen); 140 } 141 142 /* __cgroup_bpf_run_lsm_current (via bpf_lsm_current_hooks) */ 143 SEC("lsm_cgroup/sk_alloc_security") 144 int BPF_PROG(socket_alloc, struct sock *sk, int family, gfp_t priority) 145 { 146 called_socket_alloc++; 147 /* if already have non-bpf lsms installed, EPERM will cause memory leak of non-bpf lsms */ 148 if (CONFIG_SECURITY_SELINUX || CONFIG_SECURITY_SMACK || CONFIG_SECURITY_APPARMOR) 149 return 1; 150 151 if (family == AF_UNIX) 152 return 0; /* EPERM */ 153 154 /* Can access cgroup local storage. */ 155 if (!test_local_storage()) 156 return 0; /* EPERM */ 157 158 return 1; 159 } 160 161 /* __cgroup_bpf_run_lsm_sock */ 162 SEC("lsm_cgroup/inet_csk_clone") 163 int BPF_PROG(socket_clone, struct sock *newsk, const struct request_sock *req) 164 { 165 int prio = 234; 166 167 if (!newsk) 168 return 1; 169 170 /* Accepted request sockets get a different priority. */ 171 if (bpf_setsockopt(newsk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) 172 return 1; 173 174 /* Make sure bpf_getsockopt is allowed and works. */ 175 prio = 0; 176 if (bpf_getsockopt(newsk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) 177 return 1; 178 if (prio != 234) 179 return 1; 180 181 /* Can access cgroup local storage. */ 182 if (!test_local_storage()) 183 return 1; 184 185 called_socket_clone++; 186 187 return 1; 188 } 189