task.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Landlock LSM - Ptrace hooks
  4. *
  5. * Copyright © 2017-2020 Mickaël Salaün <mic@digikod.net>
  6. * Copyright © 2019-2020 ANSSI
  7. */
  8. #include <asm/current.h>
  9. #include <linux/cred.h>
  10. #include <linux/errno.h>
  11. #include <linux/kernel.h>
  12. #include <linux/lsm_hooks.h>
  13. #include <linux/rcupdate.h>
  14. #include <linux/sched.h>
  15. #include <linux/sched/signal.h>
  16. #include <net/af_unix.h>
  17. #include <net/sock.h>
  18. #include "common.h"
  19. #include "cred.h"
  20. #include "fs.h"
  21. #include "ruleset.h"
  22. #include "setup.h"
  23. #include "task.h"
  24. /**
  25. * domain_scope_le - Checks domain ordering for scoped ptrace
  26. *
  27. * @parent: Parent domain.
  28. * @child: Potential child of @parent.
  29. *
  30. * Checks if the @parent domain is less or equal to (i.e. an ancestor, which
  31. * means a subset of) the @child domain.
  32. */
  33. static bool domain_scope_le(const struct landlock_ruleset *const parent,
  34. const struct landlock_ruleset *const child)
  35. {
  36. const struct landlock_hierarchy *walker;
  37. if (!parent)
  38. return true;
  39. if (!child)
  40. return false;
  41. for (walker = child->hierarchy; walker; walker = walker->parent) {
  42. if (walker == parent->hierarchy)
  43. /* @parent is in the scoped hierarchy of @child. */
  44. return true;
  45. }
  46. /* There is no relationship between @parent and @child. */
  47. return false;
  48. }
  49. static bool task_is_scoped(const struct task_struct *const parent,
  50. const struct task_struct *const child)
  51. {
  52. bool is_scoped;
  53. const struct landlock_ruleset *dom_parent, *dom_child;
  54. rcu_read_lock();
  55. dom_parent = landlock_get_task_domain(parent);
  56. dom_child = landlock_get_task_domain(child);
  57. is_scoped = domain_scope_le(dom_parent, dom_child);
  58. rcu_read_unlock();
  59. return is_scoped;
  60. }
  61. static int task_ptrace(const struct task_struct *const parent,
  62. const struct task_struct *const child)
  63. {
  64. /* Quick return for non-landlocked tasks. */
  65. if (!landlocked(parent))
  66. return 0;
  67. if (task_is_scoped(parent, child))
  68. return 0;
  69. return -EPERM;
  70. }
  71. /**
  72. * hook_ptrace_access_check - Determines whether the current process may access
  73. * another
  74. *
  75. * @child: Process to be accessed.
  76. * @mode: Mode of attachment.
  77. *
  78. * If the current task has Landlock rules, then the child must have at least
  79. * the same rules. Else denied.
  80. *
  81. * Determines whether a process may access another, returning 0 if permission
  82. * granted, -errno if denied.
  83. */
  84. static int hook_ptrace_access_check(struct task_struct *const child,
  85. const unsigned int mode)
  86. {
  87. return task_ptrace(current, child);
  88. }
  89. /**
  90. * hook_ptrace_traceme - Determines whether another process may trace the
  91. * current one
  92. *
  93. * @parent: Task proposed to be the tracer.
  94. *
  95. * If the parent has Landlock rules, then the current task must have the same
  96. * or more rules. Else denied.
  97. *
  98. * Determines whether the nominated task is permitted to trace the current
  99. * process, returning 0 if permission is granted, -errno if denied.
  100. */
  101. static int hook_ptrace_traceme(struct task_struct *const parent)
  102. {
  103. return task_ptrace(parent, current);
  104. }
  105. /**
  106. * domain_is_scoped - Checks if the client domain is scoped in the same
  107. * domain as the server.
  108. *
  109. * @client: IPC sender domain.
  110. * @server: IPC receiver domain.
  111. * @scope: The scope restriction criteria.
  112. *
  113. * Returns: True if the @client domain is scoped to access the @server,
  114. * unless the @server is also scoped in the same domain as @client.
  115. */
  116. static bool domain_is_scoped(const struct landlock_ruleset *const client,
  117. const struct landlock_ruleset *const server,
  118. access_mask_t scope)
  119. {
  120. int client_layer, server_layer;
  121. struct landlock_hierarchy *client_walker, *server_walker;
  122. /* Quick return if client has no domain */
  123. if (WARN_ON_ONCE(!client))
  124. return false;
  125. client_layer = client->num_layers - 1;
  126. client_walker = client->hierarchy;
  127. /*
  128. * client_layer must be a signed integer with greater capacity
  129. * than client->num_layers to ensure the following loop stops.
  130. */
  131. BUILD_BUG_ON(sizeof(client_layer) > sizeof(client->num_layers));
  132. server_layer = server ? (server->num_layers - 1) : -1;
  133. server_walker = server ? server->hierarchy : NULL;
  134. /*
  135. * Walks client's parent domains down to the same hierarchy level
  136. * as the server's domain, and checks that none of these client's
  137. * parent domains are scoped.
  138. */
  139. for (; client_layer > server_layer; client_layer--) {
  140. if (landlock_get_scope_mask(client, client_layer) & scope)
  141. return true;
  142. client_walker = client_walker->parent;
  143. }
  144. /*
  145. * Walks server's parent domains down to the same hierarchy level as
  146. * the client's domain.
  147. */
  148. for (; server_layer > client_layer; server_layer--)
  149. server_walker = server_walker->parent;
  150. for (; client_layer >= 0; client_layer--) {
  151. if (landlock_get_scope_mask(client, client_layer) & scope) {
  152. /*
  153. * Client and server are at the same level in the
  154. * hierarchy. If the client is scoped, the request is
  155. * only allowed if this domain is also a server's
  156. * ancestor.
  157. */
  158. return server_walker != client_walker;
  159. }
  160. client_walker = client_walker->parent;
  161. server_walker = server_walker->parent;
  162. }
  163. return false;
  164. }
  165. static bool sock_is_scoped(struct sock *const other,
  166. const struct landlock_ruleset *const domain)
  167. {
  168. const struct landlock_ruleset *dom_other;
  169. /* The credentials will not change. */
  170. lockdep_assert_held(&unix_sk(other)->lock);
  171. dom_other = landlock_cred(other->sk_socket->file->f_cred)->domain;
  172. return domain_is_scoped(domain, dom_other,
  173. LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET);
  174. }
  175. static bool is_abstract_socket(struct sock *const sock)
  176. {
  177. struct unix_address *addr = unix_sk(sock)->addr;
  178. if (!addr)
  179. return false;
  180. if (addr->len >= offsetof(struct sockaddr_un, sun_path) + 1 &&
  181. addr->name->sun_path[0] == '\0')
  182. return true;
  183. return false;
  184. }
  185. static const struct access_masks unix_scope = {
  186. .scope = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET,
  187. };
  188. static int hook_unix_stream_connect(struct sock *const sock,
  189. struct sock *const other,
  190. struct sock *const newsk)
  191. {
  192. const struct landlock_ruleset *const dom =
  193. landlock_get_applicable_domain(landlock_get_current_domain(),
  194. unix_scope);
  195. /* Quick return for non-landlocked tasks. */
  196. if (!dom)
  197. return 0;
  198. if (is_abstract_socket(other) && sock_is_scoped(other, dom))
  199. return -EPERM;
  200. return 0;
  201. }
  202. static int hook_unix_may_send(struct socket *const sock,
  203. struct socket *const other)
  204. {
  205. const struct landlock_ruleset *const dom =
  206. landlock_get_applicable_domain(landlock_get_current_domain(),
  207. unix_scope);
  208. if (!dom)
  209. return 0;
  210. /*
  211. * Checks if this datagram socket was already allowed to be connected
  212. * to other.
  213. */
  214. if (unix_peer(sock->sk) == other->sk)
  215. return 0;
  216. if (is_abstract_socket(other->sk) && sock_is_scoped(other->sk, dom))
  217. return -EPERM;
  218. return 0;
  219. }
  220. static const struct access_masks signal_scope = {
  221. .scope = LANDLOCK_SCOPE_SIGNAL,
  222. };
  223. static int hook_task_kill(struct task_struct *const p,
  224. struct kernel_siginfo *const info, const int sig,
  225. const struct cred *const cred)
  226. {
  227. bool is_scoped;
  228. const struct landlock_ruleset *dom;
  229. if (cred) {
  230. /* Dealing with USB IO. */
  231. dom = landlock_cred(cred)->domain;
  232. } else {
  233. /*
  234. * Always allow sending signals between threads of the same process.
  235. * This is required for process credential changes by the Native POSIX
  236. * Threads Library and implemented by the set*id(2) wrappers and
  237. * libcap(3) with tgkill(2). See nptl(7) and libpsx(3).
  238. *
  239. * This exception is similar to the __ptrace_may_access() one.
  240. */
  241. if (same_thread_group(p, current))
  242. return 0;
  243. dom = landlock_get_current_domain();
  244. }
  245. dom = landlock_get_applicable_domain(dom, signal_scope);
  246. /* Quick return for non-landlocked tasks. */
  247. if (!dom)
  248. return 0;
  249. rcu_read_lock();
  250. is_scoped = domain_is_scoped(dom, landlock_get_task_domain(p),
  251. LANDLOCK_SCOPE_SIGNAL);
  252. rcu_read_unlock();
  253. if (is_scoped)
  254. return -EPERM;
  255. return 0;
  256. }
  257. static int hook_file_send_sigiotask(struct task_struct *tsk,
  258. struct fown_struct *fown, int signum)
  259. {
  260. const struct landlock_ruleset *dom;
  261. bool is_scoped = false;
  262. /* Lock already held by send_sigio() and send_sigurg(). */
  263. lockdep_assert_held(&fown->lock);
  264. dom = landlock_get_applicable_domain(
  265. landlock_file(fown->file)->fown_domain, signal_scope);
  266. /* Quick return for unowned socket. */
  267. if (!dom)
  268. return 0;
  269. rcu_read_lock();
  270. is_scoped = domain_is_scoped(dom, landlock_get_task_domain(tsk),
  271. LANDLOCK_SCOPE_SIGNAL);
  272. rcu_read_unlock();
  273. if (is_scoped)
  274. return -EPERM;
  275. return 0;
  276. }
  277. static struct security_hook_list landlock_hooks[] __ro_after_init = {
  278. LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check),
  279. LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme),
  280. LSM_HOOK_INIT(unix_stream_connect, hook_unix_stream_connect),
  281. LSM_HOOK_INIT(unix_may_send, hook_unix_may_send),
  282. LSM_HOOK_INIT(task_kill, hook_task_kill),
  283. LSM_HOOK_INIT(file_send_sigiotask, hook_file_send_sigiotask),
  284. };
  285. __init void landlock_add_task_hooks(void)
  286. {
  287. security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
  288. &landlock_lsmid);
  289. }