1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3 * Landlock - Network management and hooks
4 *
5 * Copyright © 2022-2023 Huawei Tech. Co., Ltd.
6 * Copyright © 2022-2025 Microsoft Corporation
7 */
8
9 #include <linux/in.h>
10 #include <linux/lsm_audit.h>
11 #include <linux/net.h>
12 #include <linux/socket.h>
13 #include <net/ipv6.h>
14
15 #include "audit.h"
16 #include "common.h"
17 #include "cred.h"
18 #include "limits.h"
19 #include "net.h"
20 #include "ruleset.h"
21
landlock_append_net_rule(struct landlock_ruleset * const ruleset,const u16 port,access_mask_t access_rights,const u32 flags)22 int landlock_append_net_rule(struct landlock_ruleset *const ruleset,
23 const u16 port, access_mask_t access_rights,
24 const u32 flags)
25 {
26 int err;
27 const struct landlock_id id = {
28 .key.data = (__force uintptr_t)htons(port),
29 .type = LANDLOCK_KEY_NET_PORT,
30 };
31
32 BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data));
33
34 /* Transforms relative access rights to absolute ones. */
35 access_rights |= LANDLOCK_MASK_ACCESS_NET &
36 ~landlock_get_net_access_mask(ruleset, 0);
37
38 mutex_lock(&ruleset->lock);
39 err = landlock_insert_rule(ruleset, id, access_rights, flags);
40 mutex_unlock(&ruleset->lock);
41
42 return err;
43 }
44
current_check_access_socket(struct socket * const sock,struct sockaddr * const address,const int addrlen,access_mask_t access_request,bool connecting)45 static int current_check_access_socket(struct socket *const sock,
46 struct sockaddr *const address,
47 const int addrlen,
48 access_mask_t access_request,
49 bool connecting)
50 {
51 unsigned short sock_family;
52 __be16 port;
53 struct layer_masks layer_masks = {};
54 const struct landlock_rule *rule;
55 struct landlock_id id = {
56 .type = LANDLOCK_KEY_NET_PORT,
57 };
58 const struct access_masks masks = {
59 .net = access_request,
60 };
61 const struct landlock_cred_security *const subject =
62 landlock_get_applicable_subject(current_cred(), masks, NULL);
63 struct lsm_network_audit audit_net = {};
64
65 if (!subject)
66 return 0;
67
68 /* Checks for minimal header length to safely read sa_family. */
69 if (addrlen < offsetofend(typeof(*address), sa_family))
70 return -EINVAL;
71
72 /*
73 * The socket is not locked, so sk_family can change concurrently due to
74 * e.g. setsockopt(IPV6_ADDRFORM).
75 */
76 sock_family = READ_ONCE(sock->sk->sk_family);
77
78 switch (address->sa_family) {
79 case AF_UNSPEC:
80 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP ||
81 (access_request == LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP &&
82 connecting)) {
83 /*
84 * Connecting to an address with AF_UNSPEC dissolves the
85 * remote association while retaining the socket object
86 * (i.e., the file descriptor). For TCP, it has the same
87 * effect as closing the connection. For UDP, it removes
88 * any preset remote address. As for dropping
89 * privileges, these actions are always allowed. Let
90 * the network stack handle potential inconsistencies
91 * and return -EINVAL if needed.
92 */
93 return 0;
94 } else if (access_request ==
95 LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP) {
96 if (sock_family == AF_INET6) {
97 /*
98 * We cannot allow sending UDP datagrams to an
99 * explicit AF_UNSPEC address on IPv6 sockets,
100 * even if AF_UNSPEC is treated as "no address"
101 * on such sockets (so it should always be
102 * allowed). That's because the socket's family
103 * can change under our feet (if another thread
104 * calls setsockopt(IPV6_ADDRFORM)) to IPv4,
105 * which would then treat AF_UNSPEC as AF_INET.
106 */
107 audit_net.family = AF_UNSPEC;
108 audit_net.sk = sock->sk;
109 landlock_init_layer_masks(
110 subject->domain, access_request,
111 &layer_masks, LANDLOCK_KEY_NET_PORT);
112 landlock_log_denial(
113 subject,
114 &(struct landlock_request){
115 .type = LANDLOCK_REQUEST_NET_ACCESS,
116 .audit.type =
117 LSM_AUDIT_DATA_NET,
118 .audit.u.net = &audit_net,
119 .access = access_request,
120 .layer_masks = &layer_masks,
121 });
122 return -EACCES;
123 }
124 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP ||
125 access_request == LANDLOCK_ACCESS_NET_BIND_UDP) {
126 /*
127 * Binding to an AF_UNSPEC address is treated
128 * differently by IPv4 and IPv6 sockets. The socket's
129 * family may change under our feet due to
130 * setsockopt(IPV6_ADDRFORM), but that's ok: we either
131 * reject entirely for IPv6 or require
132 * %LANDLOCK_ACCESS_NET_BIND_TCP or
133 * %LANDLOCK_ACCESS_NET_BIND_UDP for IPv4, so it cannot
134 * be used to bypass the policy.
135 *
136 * IPv4 sockets map AF_UNSPEC to AF_INET for
137 * retrocompatibility for bind accesses, only if the
138 * address is INADDR_ANY (cf. __inet_bind). IPv6
139 * sockets always reject it.
140 *
141 * Checking the address is required to not wrongfully
142 * return -EACCES instead of -EAFNOSUPPORT or -EINVAL.
143 * We could return 0 and let the network stack handle
144 * these checks, but it is safer to return a proper
145 * error and test consistency thanks to kselftest.
146 */
147 if (sock_family == AF_INET) {
148 const struct sockaddr_in *const sockaddr =
149 (struct sockaddr_in *)address;
150
151 if (addrlen < sizeof(struct sockaddr_in))
152 return -EINVAL;
153
154 if (sockaddr->sin_addr.s_addr !=
155 htonl(INADDR_ANY))
156 return -EAFNOSUPPORT;
157 } else {
158 if (addrlen < SIN6_LEN_RFC2133)
159 return -EINVAL;
160 else
161 return -EAFNOSUPPORT;
162 }
163 } else {
164 WARN_ON_ONCE(1);
165 }
166 /*
167 * AF_UNSPEC is treated as AF_INET only in
168 * bind(AF_UNSPEC+INADDR_ANY) on IPv4 sockets and when sending
169 * to AF_UNSPEC addresses on IPv4 sockets.
170 */
171 fallthrough;
172 case AF_INET: {
173 const struct sockaddr_in *addr4;
174
175 if (addrlen < sizeof(struct sockaddr_in))
176 return -EINVAL;
177
178 addr4 = (struct sockaddr_in *)address;
179 port = addr4->sin_port;
180
181 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP ||
182 access_request == LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP) {
183 audit_net.dport = port;
184 audit_net.v4info.daddr = addr4->sin_addr.s_addr;
185 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP ||
186 access_request == LANDLOCK_ACCESS_NET_BIND_UDP) {
187 audit_net.sport = port;
188 audit_net.v4info.saddr = addr4->sin_addr.s_addr;
189 } else {
190 WARN_ON_ONCE(1);
191 }
192 break;
193 }
194
195 #if IS_ENABLED(CONFIG_IPV6)
196 case AF_INET6: {
197 const struct sockaddr_in6 *addr6;
198
199 if (addrlen < SIN6_LEN_RFC2133)
200 return -EINVAL;
201
202 addr6 = (struct sockaddr_in6 *)address;
203 port = addr6->sin6_port;
204
205 if (access_request == LANDLOCK_ACCESS_NET_CONNECT_TCP ||
206 access_request == LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP) {
207 audit_net.dport = port;
208 audit_net.v6info.daddr = addr6->sin6_addr;
209 } else if (access_request == LANDLOCK_ACCESS_NET_BIND_TCP ||
210 access_request == LANDLOCK_ACCESS_NET_BIND_UDP) {
211 audit_net.sport = port;
212 audit_net.v6info.saddr = addr6->sin6_addr;
213 } else {
214 WARN_ON_ONCE(1);
215 }
216 break;
217 }
218 #endif /* IS_ENABLED(CONFIG_IPV6) */
219
220 default:
221 return 0;
222 }
223
224 /*
225 * Checks sa_family consistency to not wrongfully return
226 * -EACCES instead of -EINVAL. Valid sa_family changes are
227 * only (from AF_INET or AF_INET6) to AF_UNSPEC.
228 *
229 * We could return 0 and let the network stack handle this
230 * check, but it is safer to return a proper error and test
231 * consistency thanks to kselftest.
232 */
233 if (address->sa_family != sock_family &&
234 address->sa_family != AF_UNSPEC)
235 return -EINVAL;
236
237 id.key.data = (__force uintptr_t)port;
238 BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data));
239
240 rule = landlock_find_rule(subject->domain, id);
241 access_request = landlock_init_layer_masks(subject->domain,
242 access_request, &layer_masks,
243 LANDLOCK_KEY_NET_PORT);
244 if (!access_request)
245 return 0;
246
247 if (landlock_unmask_layers(rule, &layer_masks))
248 return 0;
249
250 audit_net.family = address->sa_family;
251 audit_net.sk = sock->sk;
252 landlock_log_denial(subject,
253 &(struct landlock_request){
254 .type = LANDLOCK_REQUEST_NET_ACCESS,
255 .audit.type = LSM_AUDIT_DATA_NET,
256 .audit.u.net = &audit_net,
257 .access = access_request,
258 .layer_masks = &layer_masks,
259 });
260 return -EACCES;
261 }
262
current_check_autobind_udp_socket(struct socket * const sock)263 static int current_check_autobind_udp_socket(struct socket *const sock)
264 {
265 const struct access_masks bind_udp = {
266 .net = LANDLOCK_ACCESS_NET_BIND_UDP,
267 };
268 struct sockaddr_storage port0 = {};
269 unsigned short num;
270 bool slow;
271
272 /* Quick return for non-Landlocked tasks. */
273 if (!landlock_get_applicable_subject(current_cred(), bind_udp, NULL))
274 return 0;
275
276 /*
277 * On UDP sockets, if a local port has not already been bound, calling
278 * connect() or sending a first datagram has the side effect of
279 * autobinding an ephemeral port: we also have to check that the process
280 * would have had the right to bind(0) explicitly. Hold the socket lock
281 * around the inet_num read to exclude udp_lib_get_port()'s transient
282 * inet_num = snum write that is reverted to 0 on a failing reuseport
283 * bind.
284 */
285 slow = lock_sock_fast(sock->sk);
286 num = inet_sk(sock->sk)->inet_num;
287 unlock_sock_fast(sock->sk, slow);
288 if (num != 0)
289 return 0;
290
291 /*
292 * Construct a struct sockaddr* with port 0 to pretend the process tried
293 * to bind() on that address.
294 */
295 port0.ss_family = READ_ONCE(sock->sk->sk_family);
296
297 return current_check_access_socket(sock, (struct sockaddr *)&port0,
298 sizeof(port0), bind_udp.net, false);
299 }
300
hook_socket_bind(struct socket * const sock,struct sockaddr * const address,const int addrlen)301 static int hook_socket_bind(struct socket *const sock,
302 struct sockaddr *const address, const int addrlen)
303 {
304 access_mask_t access_request;
305
306 if (sk_is_tcp(sock->sk))
307 access_request = LANDLOCK_ACCESS_NET_BIND_TCP;
308 else if (sk_is_udp(sock->sk))
309 access_request = LANDLOCK_ACCESS_NET_BIND_UDP;
310 else
311 return 0;
312
313 return current_check_access_socket(sock, address, addrlen,
314 access_request, false);
315 }
316
hook_socket_connect(struct socket * const sock,struct sockaddr * const address,const int addrlen)317 static int hook_socket_connect(struct socket *const sock,
318 struct sockaddr *const address,
319 const int addrlen)
320 {
321 access_mask_t access_request;
322 int ret = 0;
323
324 if (sk_is_tcp(sock->sk))
325 access_request = LANDLOCK_ACCESS_NET_CONNECT_TCP;
326 else if (sk_is_udp(sock->sk))
327 access_request = LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP;
328 else
329 return 0;
330
331 ret = current_check_access_socket(sock, address, addrlen,
332 access_request, true);
333
334 /*
335 * connect()ing to an AF_UNSPEC address does not trigger an autobind and
336 * should never be restricted.
337 */
338 if (ret == 0 && sk_is_udp(sock->sk) &&
339 addrlen >= offsetofend(typeof(*address), sa_family) &&
340 address->sa_family != AF_UNSPEC)
341 ret = current_check_autobind_udp_socket(sock);
342
343 return ret;
344 }
345
hook_socket_sendmsg(struct socket * const sock,struct msghdr * const msg,const int size)346 static int hook_socket_sendmsg(struct socket *const sock,
347 struct msghdr *const msg, const int size)
348 {
349 struct sockaddr *const address = msg->msg_name;
350 const int addrlen = msg->msg_namelen;
351 access_mask_t access_request;
352 int ret = 0;
353
354 if ((msg->msg_flags & MSG_FASTOPEN) && address && sk_is_tcp(sock->sk)) {
355 ret = current_check_access_socket(
356 sock, address, addrlen, LANDLOCK_ACCESS_NET_CONNECT_TCP,
357 true);
358 if (ret != 0)
359 return ret;
360 }
361
362 if (sk_is_udp(sock->sk))
363 access_request = LANDLOCK_ACCESS_NET_CONNECT_SEND_UDP;
364 else
365 return 0;
366
367 if (address != NULL)
368 ret = current_check_access_socket(sock, address, addrlen,
369 access_request, false);
370
371 if (ret == 0)
372 ret = current_check_autobind_udp_socket(sock);
373
374 return ret;
375 }
376
377 static struct security_hook_list landlock_hooks[] __ro_after_init = {
378 LSM_HOOK_INIT(socket_bind, hook_socket_bind),
379 LSM_HOOK_INIT(socket_connect, hook_socket_connect),
380 LSM_HOOK_INIT(socket_sendmsg, hook_socket_sendmsg),
381 };
382
landlock_add_net_hooks(void)383 __init void landlock_add_net_hooks(void)
384 {
385 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
386 &landlock_lsmid);
387 }
388