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 "common.h" 24 #include "cred.h" 25 #include "domain.h" 26 #include "fs.h" 27 #include "log.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_domain *const parent, 45 const struct landlock_domain *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_domain *const parent, 67 const struct landlock_domain *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 u64 tracee_domain_id = 0; 92 int err; 93 94 /* Quick return for non-landlocked tasks. */ 95 parent_subject = landlock_cred(current_cred()); 96 if (!parent_subject) 97 return 0; 98 99 scoped_guard(rcu) { 100 const struct landlock_domain *const child_dom = 101 landlock_get_task_domain(child); 102 err = domain_ptrace(parent_subject->domain, child_dom); 103 #ifdef CONFIG_SECURITY_LANDLOCK_LOG 104 if (child_dom) 105 tracee_domain_id = child_dom->hierarchy->id; 106 #endif /* CONFIG_SECURITY_LANDLOCK_LOG */ 107 } 108 109 if (!err) 110 return 0; 111 112 /* 113 * For the ptrace_access_check case, we log the current/parent domain 114 * and the child task. 115 */ 116 if (!(mode & PTRACE_MODE_NOAUDIT)) 117 landlock_log_denial(parent_subject, &(struct landlock_request) { 118 .type = LANDLOCK_REQUEST_PTRACE, 119 .audit = { 120 .type = LSM_AUDIT_DATA_TASK, 121 .u.tsk = child, 122 }, 123 .layer_plus_one = parent_subject->domain->num_layers, 124 .other_domain_id = tracee_domain_id, 125 }); 126 127 return err; 128 } 129 130 /** 131 * hook_ptrace_traceme - Determines whether another process may trace the 132 * current one 133 * 134 * @parent: Task proposed to be the tracer. 135 * 136 * If the parent has Landlock rules, then the current task must have the same 137 * or more rules. Else denied. 138 * 139 * Return: 0 if permission is granted, -errno if denied. 140 */ 141 static int hook_ptrace_traceme(struct task_struct *const parent) 142 { 143 const struct landlock_cred_security *parent_subject; 144 const struct landlock_domain *child_dom; 145 u64 tracee_domain_id = 0; 146 int err; 147 148 child_dom = landlock_get_current_domain(); 149 150 guard(rcu)(); 151 parent_subject = landlock_cred(__task_cred(parent)); 152 err = domain_ptrace(parent_subject->domain, child_dom); 153 154 if (!err) 155 return 0; 156 157 #ifdef CONFIG_SECURITY_LANDLOCK_LOG 158 /* The tracee is the current task; its domain is stable here. */ 159 if (child_dom) 160 tracee_domain_id = child_dom->hierarchy->id; 161 #endif /* CONFIG_SECURITY_LANDLOCK_LOG */ 162 163 /* 164 * For the ptrace_traceme case, we log the domain which is the cause of 165 * the denial, which means the parent domain instead of the current 166 * domain. This may look unusual because the ptrace_traceme action is a 167 * request to be traced, but the semantic is consistent with 168 * hook_ptrace_access_check(). 169 */ 170 landlock_log_denial(parent_subject, &(struct landlock_request) { 171 .type = LANDLOCK_REQUEST_PTRACE, 172 .audit = { 173 .type = LSM_AUDIT_DATA_TASK, 174 .u.tsk = current, 175 }, 176 .layer_plus_one = parent_subject->domain->num_layers, 177 .other_domain_id = tracee_domain_id, 178 }); 179 return err; 180 } 181 182 /** 183 * domain_is_scoped - Check if an interaction from a client/sender to a 184 * server/receiver should be restricted based on scope controls. 185 * 186 * @client: IPC sender domain. 187 * @server: IPC receiver domain. 188 * @scope: The scope restriction criteria. 189 * 190 * Return: True if @server is in a different domain from @client and @client 191 * is scoped to access @server (i.e. access should be denied), false otherwise. 192 */ 193 static bool domain_is_scoped(const struct landlock_domain *const client, 194 const struct landlock_domain *const server, 195 access_mask_t scope) 196 { 197 int client_layer, server_layer; 198 const struct landlock_hierarchy *client_walker, *server_walker; 199 200 /* Quick return if client has no domain */ 201 if (WARN_ON_ONCE(!client)) 202 return false; 203 204 client_layer = client->num_layers - 1; 205 client_walker = client->hierarchy; 206 /* 207 * client_layer must be able to represent all numbers from 208 * LANDLOCK_MAX_NUM_LAYERS - 1 to -1 for the loop below to terminate. 209 * (It must be large enough, and it must be signed.) 210 */ 211 BUILD_BUG_ON(!is_signed_type(typeof(client_layer))); 212 BUILD_BUG_ON(LANDLOCK_MAX_NUM_LAYERS - 1 > 213 type_max(typeof(client_layer))); 214 215 server_layer = server ? (server->num_layers - 1) : -1; 216 server_walker = server ? server->hierarchy : NULL; 217 218 /* 219 * Walks client's parent domains down to the same hierarchy level 220 * as the server's domain, and checks that none of these client's 221 * parent domains are scoped. 222 */ 223 for (; client_layer > server_layer; client_layer--) { 224 if (landlock_get_scope_mask(client, client_layer) & scope) 225 return true; 226 227 client_walker = client_walker->parent; 228 } 229 /* 230 * Walks server's parent domains down to the same hierarchy level as 231 * the client's domain. 232 */ 233 for (; server_layer > client_layer; server_layer--) 234 server_walker = server_walker->parent; 235 236 for (; client_layer >= 0; client_layer--) { 237 if (landlock_get_scope_mask(client, client_layer) & scope) { 238 /* 239 * Client and server are at the same level in the 240 * hierarchy. If the client is scoped, the request is 241 * only allowed if this domain is also a server's 242 * ancestor. 243 */ 244 return server_walker != client_walker; 245 } 246 client_walker = client_walker->parent; 247 server_walker = server_walker->parent; 248 } 249 return false; 250 } 251 252 static bool sock_is_scoped(struct sock *const other, 253 const struct landlock_domain *const domain, 254 u64 *const peer_domain_id) 255 { 256 const struct landlock_domain *dom_other; 257 258 /* The credentials will not change. */ 259 lockdep_assert_held(&unix_sk(other)->lock); 260 261 /* 262 * A live kernel socket (e.g. from sock_create_kern()) has no backing 263 * file, hence no Landlock domain, so treat it as unscoped. The 264 * sk_socket check only guards that dereference; sk_socket is NULL 265 * solely for a dead peer, which the caller already excludes under the 266 * held lock, so no separate SOCK_DEAD check is needed. 267 */ 268 if (unlikely(!other->sk_socket || !other->sk_socket->file)) 269 return false; 270 271 dom_other = landlock_cred(other->sk_socket->file->f_cred)->domain; 272 #ifdef CONFIG_SECURITY_LANDLOCK_LOG 273 *peer_domain_id = dom_other ? dom_other->hierarchy->id : 0; 274 #endif /* CONFIG_SECURITY_LANDLOCK_LOG */ 275 return domain_is_scoped(domain, dom_other, 276 LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET); 277 } 278 279 static bool is_abstract_socket(struct sock *const sock) 280 { 281 struct unix_address *addr = unix_sk(sock)->addr; 282 283 if (!addr) 284 return false; 285 286 if (addr->len >= offsetof(struct sockaddr_un, sun_path) + 1 && 287 addr->name->sun_path[0] == '\0') 288 return true; 289 290 return false; 291 } 292 293 static const struct access_masks unix_scope = { 294 .scope = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET, 295 }; 296 297 static int hook_unix_stream_connect(struct sock *const sock, 298 struct sock *const other, 299 struct sock *const newsk) 300 { 301 size_t handle_layer; 302 u64 peer_domain_id = 0; 303 const struct landlock_cred_security *const subject = 304 landlock_get_applicable_subject(current_cred(), unix_scope, 305 &handle_layer); 306 307 /* Quick return for non-landlocked tasks. */ 308 if (!subject) 309 return 0; 310 311 if (!is_abstract_socket(other)) 312 return 0; 313 314 if (!sock_is_scoped(other, subject->domain, &peer_domain_id)) 315 return 0; 316 317 landlock_log_denial(subject, &(struct landlock_request) { 318 .type = LANDLOCK_REQUEST_SCOPE_ABSTRACT_UNIX_SOCKET, 319 .audit = { 320 .type = LSM_AUDIT_DATA_NET, 321 .u.net = &(struct lsm_network_audit) { 322 .sk = other, 323 }, 324 }, 325 .layer_plus_one = handle_layer + 1, 326 .other_domain_id = peer_domain_id, 327 }); 328 return -EPERM; 329 } 330 331 static int hook_unix_may_send(struct socket *const sock, 332 struct socket *const other) 333 { 334 size_t handle_layer; 335 u64 peer_domain_id = 0; 336 const struct landlock_cred_security *const subject = 337 landlock_get_applicable_subject(current_cred(), unix_scope, 338 &handle_layer); 339 340 if (!subject) 341 return 0; 342 343 /* 344 * Checks if this datagram socket was already allowed to be connected 345 * to other. 346 */ 347 if (unix_peer(sock->sk) == other->sk) 348 return 0; 349 350 if (!is_abstract_socket(other->sk)) 351 return 0; 352 353 if (!sock_is_scoped(other->sk, subject->domain, &peer_domain_id)) 354 return 0; 355 356 landlock_log_denial(subject, &(struct landlock_request) { 357 .type = LANDLOCK_REQUEST_SCOPE_ABSTRACT_UNIX_SOCKET, 358 .audit = { 359 .type = LSM_AUDIT_DATA_NET, 360 .u.net = &(struct lsm_network_audit) { 361 .sk = other->sk, 362 }, 363 }, 364 .layer_plus_one = handle_layer + 1, 365 .other_domain_id = peer_domain_id, 366 }); 367 return -EPERM; 368 } 369 370 static const struct access_masks signal_scope = { 371 .scope = LANDLOCK_SCOPE_SIGNAL, 372 }; 373 374 static int hook_task_kill(struct task_struct *const p, 375 struct kernel_siginfo *const info, const int sig, 376 const struct cred *cred) 377 { 378 bool is_scoped; 379 size_t handle_layer; 380 u64 target_domain_id = 0; 381 const struct landlock_cred_security *subject; 382 383 if (!cred) { 384 /* 385 * Always allow sending signals between threads of the same process. 386 * This is required for process credential changes by the Native POSIX 387 * Threads Library and implemented by the set*id(2) wrappers and 388 * libcap(3) with tgkill(2). See nptl(7) and libpsx(3). 389 * 390 * This exception is similar to the __ptrace_may_access() one. 391 */ 392 if (same_thread_group(p, current)) 393 return 0; 394 395 /* Not dealing with USB IO. */ 396 cred = current_cred(); 397 } 398 399 subject = landlock_get_applicable_subject(cred, signal_scope, 400 &handle_layer); 401 402 /* Quick return for non-landlocked tasks. */ 403 if (!subject) 404 return 0; 405 406 scoped_guard(rcu) { 407 const struct landlock_domain *const other = 408 landlock_get_task_domain(p); 409 410 is_scoped = domain_is_scoped(subject->domain, other, 411 signal_scope.scope); 412 #ifdef CONFIG_SECURITY_LANDLOCK_LOG 413 if (other) 414 target_domain_id = other->hierarchy->id; 415 #endif /* CONFIG_SECURITY_LANDLOCK_LOG */ 416 } 417 418 if (!is_scoped) 419 return 0; 420 421 landlock_log_denial(subject, &(struct landlock_request) { 422 .type = LANDLOCK_REQUEST_SCOPE_SIGNAL, 423 .audit = { 424 .type = LSM_AUDIT_DATA_TASK, 425 .u.tsk = p, 426 }, 427 .layer_plus_one = handle_layer + 1, 428 .other_domain_id = target_domain_id, 429 }); 430 return -EPERM; 431 } 432 433 static int hook_file_send_sigiotask(struct task_struct *tsk, 434 struct fown_struct *fown, int signum) 435 { 436 const struct landlock_cred_security *subject; 437 bool is_scoped = false; 438 u64 target_domain_id = 0; 439 440 /* Lock already held by send_sigio() and send_sigurg(). */ 441 lockdep_assert_held(&fown->lock); 442 subject = &landlock_file(fown->file)->fown_subject; 443 444 /* 445 * Quick return for unowned socket. 446 * 447 * subject->domain has already been filtered when saved by 448 * hook_file_set_fowner(), so there is no need to call 449 * landlock_get_applicable_subject() here. 450 */ 451 if (!subject->domain) 452 return 0; 453 454 /* 455 * Always allow delivery to the file owner's own process, including a 456 * thread-group leader reached through a process-group owner. This 457 * mirrors hook_task_kill()'s same-process exemption and preserves the 458 * guarantee of commit 18eb75f3af40 ("landlock: Always allow signals 459 * between threads of the same process"), which the registration-time 460 * check cannot honor for a process-group target. 461 */ 462 if (task_tgid(tsk) == landlock_file(fown->file)->fown_tg) 463 return 0; 464 465 scoped_guard(rcu) { 466 const struct landlock_domain *const other = 467 landlock_get_task_domain(tsk); 468 469 is_scoped = domain_is_scoped(subject->domain, other, 470 signal_scope.scope); 471 #ifdef CONFIG_SECURITY_LANDLOCK_LOG 472 if (other) 473 target_domain_id = other->hierarchy->id; 474 #endif /* CONFIG_SECURITY_LANDLOCK_LOG */ 475 } 476 477 if (!is_scoped) 478 return 0; 479 480 landlock_log_denial(subject, &(struct landlock_request) { 481 .type = LANDLOCK_REQUEST_SCOPE_SIGNAL, 482 .audit = { 483 .type = LSM_AUDIT_DATA_TASK, 484 .u.tsk = tsk, 485 }, 486 #ifdef CONFIG_SECURITY_LANDLOCK_LOG 487 .layer_plus_one = landlock_file(fown->file)->fown_layer + 1, 488 #endif /* CONFIG_SECURITY_LANDLOCK_LOG */ 489 .other_domain_id = target_domain_id, 490 }); 491 return -EPERM; 492 } 493 494 static struct security_hook_list landlock_hooks[] __ro_after_init = { 495 LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check), 496 LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme), 497 498 LSM_HOOK_INIT(unix_stream_connect, hook_unix_stream_connect), 499 LSM_HOOK_INIT(unix_may_send, hook_unix_may_send), 500 501 LSM_HOOK_INIT(task_kill, hook_task_kill), 502 LSM_HOOK_INIT(file_send_sigiotask, hook_file_send_sigiotask), 503 }; 504 505 __init void landlock_add_task_hooks(void) 506 { 507 security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks), 508 &landlock_lsmid); 509 } 510