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
test_local_storage(void)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
real_create(struct socket * sock,int family,int protocol)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")
BPF_PROG(socket_post_create,struct socket * sock,int family,int type,int protocol,int kern)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")
BPF_PROG(socket_post_create2,struct socket * sock,int family,int type,int protocol,int kern)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
real_bind(struct socket * sock,struct sockaddr * address,int addrlen)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")
BPF_PROG(socket_bind,struct socket * sock,struct sockaddr * address,int addrlen)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")
BPF_PROG(socket_bind2,struct socket * sock,struct sockaddr * address,int addrlen)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")
BPF_PROG(socket_alloc,struct sock * sk,int family,gfp_t priority)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")
BPF_PROG(socket_clone,struct sock * newsk,const struct request_sock * req)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