task.c 11 KB

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