xref: /linux/security/landlock/task.c (revision 5c458073553f0ef74f5c8db1bd459c87c722a299)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Landlock - Ptrace and scope hooks
4  *
5  * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
6  * Copyright © 2019-2020 ANSSI
7  * Copyright © 2024-2025 Microsoft Corporation
8  */
9 
10 #include <asm/current.h>
11 #include <linux/cleanup.h>
12 #include <linux/cred.h>
13 #include <linux/errno.h>
14 #include <linux/kernel.h>
15 #include <linux/lsm_audit.h>
16 #include <linux/lsm_hooks.h>
17 #include <linux/rcupdate.h>
18 #include <linux/sched.h>
19 #include <linux/sched/signal.h>
20 #include <net/af_unix.h>
21 #include <net/sock.h>
22 
23 #include "audit.h"
24 #include "common.h"
25 #include "cred.h"
26 #include "domain.h"
27 #include "fs.h"
28 #include "ruleset.h"
29 #include "setup.h"
30 #include "task.h"
31 
32 /**
33  * domain_scope_le - Checks domain ordering for scoped ptrace
34  *
35  * @parent: Parent domain.
36  * @child: Potential child of @parent.
37  *
38  * Checks if the @parent domain is less or equal to (i.e. an ancestor, which
39  * means a subset of) the @child domain.
40  *
41  * Return: True if @parent is an ancestor of or equal to @child, false
42  * otherwise.
43  */
44 static bool domain_scope_le(const struct landlock_ruleset *const parent,
45 			    const struct landlock_ruleset *const child)
46 {
47 	const struct landlock_hierarchy *walker;
48 
49 	/* Quick return for non-landlocked tasks. */
50 	if (!parent)
51 		return true;
52 
53 	if (!child)
54 		return false;
55 
56 	for (walker = child->hierarchy; walker; walker = walker->parent) {
57 		if (walker == parent->hierarchy)
58 			/* @parent is in the scoped hierarchy of @child. */
59 			return true;
60 	}
61 
62 	/* There is no relationship between @parent and @child. */
63 	return false;
64 }
65 
66 static int domain_ptrace(const struct landlock_ruleset *const parent,
67 			 const struct landlock_ruleset *const child)
68 {
69 	if (domain_scope_le(parent, child))
70 		return 0;
71 
72 	return -EPERM;
73 }
74 
75 /**
76  * hook_ptrace_access_check - Determines whether the current process may access
77  *			      another
78  *
79  * @child: Process to be accessed.
80  * @mode: Mode of attachment.
81  *
82  * If the current task has Landlock rules, then the child must have at least
83  * the same rules.  Else denied.
84  *
85  * Return: 0 if permission is granted, -errno if denied.
86  */
87 static int hook_ptrace_access_check(struct task_struct *const child,
88 				    const unsigned int mode)
89 {
90 	const struct landlock_cred_security *parent_subject;
91 	int err;
92 
93 	/* Quick return for non-landlocked tasks. */
94 	parent_subject = landlock_cred(current_cred());
95 	if (!parent_subject)
96 		return 0;
97 
98 	scoped_guard(rcu) {
99 		const struct landlock_ruleset *const child_dom =
100 			landlock_get_task_domain(child);
101 		err = domain_ptrace(parent_subject->domain, child_dom);
102 	}
103 
104 	if (!err)
105 		return 0;
106 
107 	/*
108 	 * For the ptrace_access_check case, we log the current/parent domain
109 	 * and the child task.
110 	 */
111 	if (!(mode & PTRACE_MODE_NOAUDIT))
112 		landlock_log_denial(parent_subject, &(struct landlock_request) {
113 			.type = LANDLOCK_REQUEST_PTRACE,
114 			.audit = {
115 				.type = LSM_AUDIT_DATA_TASK,
116 				.u.tsk = child,
117 			},
118 			.layer_plus_one = parent_subject->domain->num_layers,
119 		});
120 
121 	return err;
122 }
123 
124 /**
125  * hook_ptrace_traceme - Determines whether another process may trace the
126  *			 current one
127  *
128  * @parent: Task proposed to be the tracer.
129  *
130  * If the parent has Landlock rules, then the current task must have the same
131  * or more rules.  Else denied.
132  *
133  * Return: 0 if permission is granted, -errno if denied.
134  */
135 static int hook_ptrace_traceme(struct task_struct *const parent)
136 {
137 	const struct landlock_cred_security *parent_subject;
138 	const struct landlock_ruleset *child_dom;
139 	int err;
140 
141 	child_dom = landlock_get_current_domain();
142 
143 	guard(rcu)();
144 	parent_subject = landlock_cred(__task_cred(parent));
145 	err = domain_ptrace(parent_subject->domain, child_dom);
146 
147 	if (!err)
148 		return 0;
149 
150 	/*
151 	 * For the ptrace_traceme case, we log the domain which is the cause of
152 	 * the denial, which means the parent domain instead of the current
153 	 * domain.  This may look unusual because the ptrace_traceme action is a
154 	 * request to be traced, but the semantic is consistent with
155 	 * hook_ptrace_access_check().
156 	 */
157 	landlock_log_denial(parent_subject, &(struct landlock_request) {
158 		.type = LANDLOCK_REQUEST_PTRACE,
159 		.audit = {
160 			.type = LSM_AUDIT_DATA_TASK,
161 			.u.tsk = current,
162 		},
163 		.layer_plus_one = parent_subject->domain->num_layers,
164 	});
165 	return err;
166 }
167 
168 /**
169  * domain_is_scoped - Check if an interaction from a client/sender to a
170  *		      server/receiver should be restricted based on scope controls.
171  *
172  * @client: IPC sender domain.
173  * @server: IPC receiver domain.
174  * @scope: The scope restriction criteria.
175  *
176  * Return: True if @server is in a different domain from @client and @client
177  * is scoped to access @server (i.e. access should be denied), false otherwise.
178  */
179 static bool domain_is_scoped(const struct landlock_ruleset *const client,
180 			     const struct landlock_ruleset *const server,
181 			     access_mask_t scope)
182 {
183 	int client_layer, server_layer;
184 	const struct landlock_hierarchy *client_walker, *server_walker;
185 
186 	/* Quick return if client has no domain */
187 	if (WARN_ON_ONCE(!client))
188 		return false;
189 
190 	client_layer = client->num_layers - 1;
191 	client_walker = client->hierarchy;
192 	/*
193 	 * client_layer must be able to represent all numbers from
194 	 * LANDLOCK_MAX_NUM_LAYERS - 1 to -1 for the loop below to terminate.
195 	 * (It must be large enough, and it must be signed.)
196 	 */
197 	BUILD_BUG_ON(!is_signed_type(typeof(client_layer)));
198 	BUILD_BUG_ON(LANDLOCK_MAX_NUM_LAYERS - 1 >
199 		     type_max(typeof(client_layer)));
200 
201 	server_layer = server ? (server->num_layers - 1) : -1;
202 	server_walker = server ? server->hierarchy : NULL;
203 
204 	/*
205 	 * Walks client's parent domains down to the same hierarchy level
206 	 * as the server's domain, and checks that none of these client's
207 	 * parent domains are scoped.
208 	 */
209 	for (; client_layer > server_layer; client_layer--) {
210 		if (landlock_get_scope_mask(client, client_layer) & scope)
211 			return true;
212 
213 		client_walker = client_walker->parent;
214 	}
215 	/*
216 	 * Walks server's parent domains down to the same hierarchy level as
217 	 * the client's domain.
218 	 */
219 	for (; server_layer > client_layer; server_layer--)
220 		server_walker = server_walker->parent;
221 
222 	for (; client_layer >= 0; client_layer--) {
223 		if (landlock_get_scope_mask(client, client_layer) & scope) {
224 			/*
225 			 * Client and server are at the same level in the
226 			 * hierarchy. If the client is scoped, the request is
227 			 * only allowed if this domain is also a server's
228 			 * ancestor.
229 			 */
230 			return server_walker != client_walker;
231 		}
232 		client_walker = client_walker->parent;
233 		server_walker = server_walker->parent;
234 	}
235 	return false;
236 }
237 
238 static bool sock_is_scoped(struct sock *const other,
239 			   const struct landlock_ruleset *const domain)
240 {
241 	const struct landlock_ruleset *dom_other;
242 
243 	/* The credentials will not change. */
244 	lockdep_assert_held(&unix_sk(other)->lock);
245 	dom_other = landlock_cred(other->sk_socket->file->f_cred)->domain;
246 	return domain_is_scoped(domain, dom_other,
247 				LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
248 }
249 
250 static bool is_abstract_socket(struct sock *const sock)
251 {
252 	struct unix_address *addr = unix_sk(sock)->addr;
253 
254 	if (!addr)
255 		return false;
256 
257 	if (addr->len >= offsetof(struct sockaddr_un, sun_path) + 1 &&
258 	    addr->name->sun_path[0] == '\0')
259 		return true;
260 
261 	return false;
262 }
263 
264 static const struct access_masks unix_scope = {
265 	.scope = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET,
266 };
267 
268 static int hook_unix_stream_connect(struct sock *const sock,
269 				    struct sock *const other,
270 				    struct sock *const newsk)
271 {
272 	size_t handle_layer;
273 	const struct landlock_cred_security *const subject =
274 		landlock_get_applicable_subject(current_cred(), unix_scope,
275 						&handle_layer);
276 
277 	/* Quick return for non-landlocked tasks. */
278 	if (!subject)
279 		return 0;
280 
281 	if (!is_abstract_socket(other))
282 		return 0;
283 
284 	if (!sock_is_scoped(other, subject->domain))
285 		return 0;
286 
287 	landlock_log_denial(subject, &(struct landlock_request) {
288 		.type = LANDLOCK_REQUEST_SCOPE_ABSTRACT_UNIX_SOCKET,
289 		.audit = {
290 			.type = LSM_AUDIT_DATA_NET,
291 			.u.net = &(struct lsm_network_audit) {
292 				.sk = other,
293 			},
294 		},
295 		.layer_plus_one = handle_layer + 1,
296 	});
297 	return -EPERM;
298 }
299 
300 static int hook_unix_may_send(struct socket *const sock,
301 			      struct socket *const other)
302 {
303 	size_t handle_layer;
304 	const struct landlock_cred_security *const subject =
305 		landlock_get_applicable_subject(current_cred(), unix_scope,
306 						&handle_layer);
307 
308 	if (!subject)
309 		return 0;
310 
311 	/*
312 	 * Checks if this datagram socket was already allowed to be connected
313 	 * to other.
314 	 */
315 	if (unix_peer(sock->sk) == other->sk)
316 		return 0;
317 
318 	if (!is_abstract_socket(other->sk))
319 		return 0;
320 
321 	if (!sock_is_scoped(other->sk, subject->domain))
322 		return 0;
323 
324 	landlock_log_denial(subject, &(struct landlock_request) {
325 		.type = LANDLOCK_REQUEST_SCOPE_ABSTRACT_UNIX_SOCKET,
326 		.audit = {
327 			.type = LSM_AUDIT_DATA_NET,
328 			.u.net = &(struct lsm_network_audit) {
329 				.sk = other->sk,
330 			},
331 		},
332 		.layer_plus_one = handle_layer + 1,
333 	});
334 	return -EPERM;
335 }
336 
337 static const struct access_masks signal_scope = {
338 	.scope = LANDLOCK_SCOPE_SIGNAL,
339 };
340 
341 static int hook_task_kill(struct task_struct *const p,
342 			  struct kernel_siginfo *const info, const int sig,
343 			  const struct cred *cred)
344 {
345 	bool is_scoped;
346 	size_t handle_layer;
347 	const struct landlock_cred_security *subject;
348 
349 	if (!cred) {
350 		/*
351 		 * Always allow sending signals between threads of the same process.
352 		 * This is required for process credential changes by the Native POSIX
353 		 * Threads Library and implemented by the set*id(2) wrappers and
354 		 * libcap(3) with tgkill(2).  See nptl(7) and libpsx(3).
355 		 *
356 		 * This exception is similar to the __ptrace_may_access() one.
357 		 */
358 		if (same_thread_group(p, current))
359 			return 0;
360 
361 		/* Not dealing with USB IO. */
362 		cred = current_cred();
363 	}
364 
365 	subject = landlock_get_applicable_subject(cred, signal_scope,
366 						  &handle_layer);
367 
368 	/* Quick return for non-landlocked tasks. */
369 	if (!subject)
370 		return 0;
371 
372 	scoped_guard(rcu) {
373 		is_scoped = domain_is_scoped(subject->domain,
374 					     landlock_get_task_domain(p),
375 					     signal_scope.scope);
376 	}
377 
378 	if (!is_scoped)
379 		return 0;
380 
381 	landlock_log_denial(subject, &(struct landlock_request) {
382 		.type = LANDLOCK_REQUEST_SCOPE_SIGNAL,
383 		.audit = {
384 			.type = LSM_AUDIT_DATA_TASK,
385 			.u.tsk = p,
386 		},
387 		.layer_plus_one = handle_layer + 1,
388 	});
389 	return -EPERM;
390 }
391 
392 static int hook_file_send_sigiotask(struct task_struct *tsk,
393 				    struct fown_struct *fown, int signum)
394 {
395 	const struct landlock_cred_security *subject;
396 	bool is_scoped = false;
397 
398 	/* Lock already held by send_sigio() and send_sigurg(). */
399 	lockdep_assert_held(&fown->lock);
400 	subject = &landlock_file(fown->file)->fown_subject;
401 
402 	/*
403 	 * Quick return for unowned socket.
404 	 *
405 	 * subject->domain has already been filtered when saved by
406 	 * hook_file_set_fowner(), so there is no need to call
407 	 * landlock_get_applicable_subject() here.
408 	 */
409 	if (!subject->domain)
410 		return 0;
411 
412 	/*
413 	 * Always allow delivery to the file owner's own process, including a
414 	 * thread-group leader reached through a process-group owner.  This
415 	 * mirrors hook_task_kill()'s same-process exemption and preserves the
416 	 * guarantee of commit 18eb75f3af40 ("landlock: Always allow signals
417 	 * between threads of the same process"), which the registration-time
418 	 * check cannot honor for a process-group target.
419 	 */
420 	if (task_tgid(tsk) == landlock_file(fown->file)->fown_tg)
421 		return 0;
422 
423 	scoped_guard(rcu) {
424 		is_scoped = domain_is_scoped(subject->domain,
425 					     landlock_get_task_domain(tsk),
426 					     signal_scope.scope);
427 	}
428 
429 	if (!is_scoped)
430 		return 0;
431 
432 	landlock_log_denial(subject, &(struct landlock_request) {
433 		.type = LANDLOCK_REQUEST_SCOPE_SIGNAL,
434 		.audit = {
435 			.type = LSM_AUDIT_DATA_TASK,
436 			.u.tsk = tsk,
437 		},
438 #ifdef CONFIG_AUDIT
439 		.layer_plus_one = landlock_file(fown->file)->fown_layer + 1,
440 #endif /* CONFIG_AUDIT */
441 	});
442 	return -EPERM;
443 }
444 
445 static struct security_hook_list landlock_hooks[] __ro_after_init = {
446 	LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check),
447 	LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme),
448 
449 	LSM_HOOK_INIT(unix_stream_connect, hook_unix_stream_connect),
450 	LSM_HOOK_INIT(unix_may_send, hook_unix_may_send),
451 
452 	LSM_HOOK_INIT(task_kill, hook_task_kill),
453 	LSM_HOOK_INIT(file_send_sigiotask, hook_file_send_sigiotask),
454 };
455 
456 __init void landlock_add_task_hooks(void)
457 {
458 	security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
459 			   &landlock_lsmid);
460 }
461