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 struct sock *sk = sock->sk; 107 108 if (!sk) 109 return 1; 110 111 if (sk->__sk_common.skc_family != AF_PACKET) 112 return 1; 113 114 if (sk->sk_kern_sock) 115 return 1; 116 117 bpf_probe_read_kernel(&sa, sizeof(sa), address); 118 if (sa.sll_protocol) 119 return 0; /* EPERM */ 120 121 /* Can access cgroup local storage. */ 122 if (!test_local_storage()) 123 return 0; /* EPERM */ 124 125 return 1; 126 } 127 128 /* __cgroup_bpf_run_lsm_socket */ 129 SEC("lsm_cgroup/socket_bind") 130 int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address, 131 int addrlen) 132 { 133 called_socket_bind++; 134 return real_bind(sock, address, addrlen); 135 } 136 137 /* __cgroup_bpf_run_lsm_socket */ 138 SEC("lsm_cgroup/socket_bind") 139 int BPF_PROG(socket_bind2, struct socket *sock, struct sockaddr *address, 140 int addrlen) 141 { 142 called_socket_bind2++; 143 return real_bind(sock, address, addrlen); 144 } 145 146 /* __cgroup_bpf_run_lsm_current (via bpf_lsm_current_hooks) */ 147 SEC("lsm_cgroup/sk_alloc_security") 148 int BPF_PROG(socket_alloc, struct sock *sk, int family, gfp_t priority) 149 { 150 called_socket_alloc++; 151 /* if already have non-bpf lsms installed, EPERM will cause memory leak of non-bpf lsms */ 152 if (CONFIG_SECURITY_SELINUX || CONFIG_SECURITY_SMACK || CONFIG_SECURITY_APPARMOR) 153 return 1; 154 155 if (family == AF_UNIX) 156 return 0; /* EPERM */ 157 158 /* Can access cgroup local storage. */ 159 if (!test_local_storage()) 160 return 0; /* EPERM */ 161 162 return 1; 163 } 164 165 /* __cgroup_bpf_run_lsm_sock */ 166 SEC("lsm_cgroup/inet_csk_clone") 167 int BPF_PROG(socket_clone, struct sock *newsk, const struct request_sock *req) 168 { 169 int prio = 234; 170 171 if (!newsk) 172 return 1; 173 174 /* Accepted request sockets get a different priority. */ 175 if (bpf_setsockopt(newsk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) 176 return 1; 177 178 /* Make sure bpf_getsockopt is allowed and works. */ 179 prio = 0; 180 if (bpf_getsockopt(newsk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio))) 181 return 1; 182 if (prio != 234) 183 return 1; 184 185 /* Can access cgroup local storage. */ 186 if (!test_local_storage()) 187 return 1; 188 189 called_socket_clone++; 190 191 return 1; 192 } 193