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