selftests/bpf: Fix erroneous bitmask operation
[platform/kernel/linux-rpi.git] / tools / testing / selftests / bpf / progs / lsm_cgroup.c
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 extern bool CONFIG_SECURITY_SELINUX __kconfig __weak;
11 extern bool CONFIG_SECURITY_SMACK __kconfig __weak;
12 extern 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
26 struct {
27         __uint(type, BPF_MAP_TYPE_CGROUP_STORAGE);
28         __type(key, __u64);
29         __type(value, __u64);
30 } cgroup_storage SEC(".maps");
31
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;
38
39 static __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
51 static __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 */
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)
87 {
88         called_socket_post_create++;
89         return real_create(sock, family, protocol);
90 }
91
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)
96 {
97         called_socket_post_create2++;
98         return real_create(sock, family, protocol);
99 }
100
101 static __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 */
125 SEC("lsm_cgroup/socket_bind")
126 int 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 */
134 SEC("lsm_cgroup/socket_bind")
135 int 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) */
143 SEC("lsm_cgroup/sk_alloc_security")
144 int 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 */
162 SEC("lsm_cgroup/inet_csk_clone")
163 int 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 }