1 // SPDX-License-Identifier: GPL-2.0
4 #include "bpf_tracing_net.h"
5 #include <bpf/bpf_helpers.h>
6 #include <bpf/bpf_tracing.h>
8 char _license[] SEC("license") = "GPL";
10 extern bool CONFIG_SECURITY_SELINUX __kconfig __weak;
11 extern bool CONFIG_SECURITY_SMACK __kconfig __weak;
12 extern bool CONFIG_SECURITY_APPARMOR __kconfig __weak;
27 __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
30 } cgroup_storage SEC(".maps");
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;
39 static __always_inline int test_local_storage(void)
43 val = bpf_get_local_storage(&cgroup_storage, 0);
51 static __always_inline int real_create(struct socket *sock, int family,
57 /* Reject non-tx-only AF_PACKET. */
58 if (family == AF_PACKET && protocol != 0)
65 /* The rest of the sockets get default policy. */
66 if (bpf_setsockopt(sk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)))
69 /* Make sure bpf_getsockopt is allowed and works. */
71 if (bpf_getsockopt(sk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)))
76 /* Can access cgroup local storage. */
77 if (!test_local_storage())
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)
88 called_socket_post_create++;
89 return real_create(sock, family, protocol);
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)
97 called_socket_post_create2++;
98 return real_create(sock, family, protocol);
101 static __always_inline int real_bind(struct socket *sock,
102 struct sockaddr *address,
105 struct sockaddr_ll sa = {};
107 if (sock->sk->__sk_common.skc_family != AF_PACKET)
110 if (sock->sk->sk_kern_sock)
113 bpf_probe_read_kernel(&sa, sizeof(sa), address);
115 return 0; /* EPERM */
117 /* Can access cgroup local storage. */
118 if (!test_local_storage())
119 return 0; /* EPERM */
124 /* __cgroup_bpf_run_lsm_socket */
125 SEC("lsm_cgroup/socket_bind")
126 int BPF_PROG(socket_bind, struct socket *sock, struct sockaddr *address,
129 called_socket_bind++;
130 return real_bind(sock, address, addrlen);
133 /* __cgroup_bpf_run_lsm_socket */
134 SEC("lsm_cgroup/socket_bind")
135 int BPF_PROG(socket_bind2, struct socket *sock, struct sockaddr *address,
138 called_socket_bind2++;
139 return real_bind(sock, address, addrlen);
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)
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)
151 if (family == AF_UNIX)
152 return 0; /* EPERM */
154 /* Can access cgroup local storage. */
155 if (!test_local_storage())
156 return 0; /* EPERM */
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)
170 /* Accepted request sockets get a different priority. */
171 if (bpf_setsockopt(newsk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)))
174 /* Make sure bpf_getsockopt is allowed and works. */
176 if (bpf_getsockopt(newsk, SOL_SOCKET, SO_PRIORITY, &prio, sizeof(prio)))
181 /* Can access cgroup local storage. */
182 if (!test_local_storage())
185 called_socket_clone++;