Linux Audio

Check our new training course

Loading...
  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	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 */
129SEC("lsm_cgroup/socket_bind")
130int 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 */
138SEC("lsm_cgroup/socket_bind")
139int 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) */
147SEC("lsm_cgroup/sk_alloc_security")
148int 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 */
166SEC("lsm_cgroup/inet_csk_clone")
167int 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}