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 8char _license[] SEC("license") = "GPL"; 9 10extern bool CONFIG_SECURITY_SELINUX __kconfig __weak; 11extern bool CONFIG_SECURITY_SMACK __kconfig __weak; 12extern 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 26struct { 27 __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE); 28 __type(key, __u64); 29 __type(value, __u64); 30} cgroup_storage SEC(".maps"); 31 32int called_socket_post_create; 33int called_socket_post_create2; 34int called_socket_bind; 35int called_socket_bind2; 36int called_socket_alloc; 37int called_socket_clone; 38 39static __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 51static __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 */ 84SEC("lsm_cgroup/socket_post_create") 85int 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 */ 93SEC("lsm_cgroup/socket_post_create") 94int 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 101static __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 */ 125SEC("lsm_cgroup/socket_bind") 126int 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 */ 134SEC("lsm_cgroup/socket_bind") 135int 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) */ 143SEC("lsm_cgroup/sk_alloc_security") 144int 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 */ 162SEC("lsm_cgroup/inet_csk_clone") 163int 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