yama_lsm.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Yama Linux Security Module
  3. *
  4. * Author: Kees Cook <keescook@chromium.org>
  5. *
  6. * Copyright (C) 2010 Canonical, Ltd.
  7. * Copyright (C) 2011 The Chromium OS Authors.
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2, as
  11. * published by the Free Software Foundation.
  12. *
  13. */
  14. #include <linux/security.h>
  15. #include <linux/sysctl.h>
  16. #include <linux/ptrace.h>
  17. #include <linux/prctl.h>
  18. #include <linux/ratelimit.h>
  19. static int ptrace_scope = 1;
  20. /* describe a ptrace relationship for potential exception */
  21. struct ptrace_relation {
  22. struct task_struct *tracer;
  23. struct task_struct *tracee;
  24. struct list_head node;
  25. };
  26. static LIST_HEAD(ptracer_relations);
  27. static DEFINE_SPINLOCK(ptracer_relations_lock);
  28. /**
  29. * yama_ptracer_add - add/replace an exception for this tracer/tracee pair
  30. * @tracer: the task_struct of the process doing the ptrace
  31. * @tracee: the task_struct of the process to be ptraced
  32. *
  33. * Each tracee can have, at most, one tracer registered. Each time this
  34. * is called, the prior registered tracer will be replaced for the tracee.
  35. *
  36. * Returns 0 if relationship was added, -ve on error.
  37. */
  38. static int yama_ptracer_add(struct task_struct *tracer,
  39. struct task_struct *tracee)
  40. {
  41. int rc = 0;
  42. struct ptrace_relation *added;
  43. struct ptrace_relation *entry, *relation = NULL;
  44. added = kmalloc(sizeof(*added), GFP_KERNEL);
  45. if (!added)
  46. return -ENOMEM;
  47. spin_lock_bh(&ptracer_relations_lock);
  48. list_for_each_entry(entry, &ptracer_relations, node)
  49. if (entry->tracee == tracee) {
  50. relation = entry;
  51. break;
  52. }
  53. if (!relation) {
  54. relation = added;
  55. relation->tracee = tracee;
  56. list_add(&relation->node, &ptracer_relations);
  57. }
  58. relation->tracer = tracer;
  59. spin_unlock_bh(&ptracer_relations_lock);
  60. if (added != relation)
  61. kfree(added);
  62. return rc;
  63. }
  64. /**
  65. * yama_ptracer_del - remove exceptions related to the given tasks
  66. * @tracer: remove any relation where tracer task matches
  67. * @tracee: remove any relation where tracee task matches
  68. */
  69. static void yama_ptracer_del(struct task_struct *tracer,
  70. struct task_struct *tracee)
  71. {
  72. struct ptrace_relation *relation, *safe;
  73. spin_lock_bh(&ptracer_relations_lock);
  74. list_for_each_entry_safe(relation, safe, &ptracer_relations, node)
  75. if (relation->tracee == tracee ||
  76. (tracer && relation->tracer == tracer)) {
  77. list_del(&relation->node);
  78. kfree(relation);
  79. }
  80. spin_unlock_bh(&ptracer_relations_lock);
  81. }
  82. /**
  83. * yama_task_free - check for task_pid to remove from exception list
  84. * @task: task being removed
  85. */
  86. static void yama_task_free(struct task_struct *task)
  87. {
  88. yama_ptracer_del(task, task);
  89. }
  90. /**
  91. * yama_task_prctl - check for Yama-specific prctl operations
  92. * @option: operation
  93. * @arg2: argument
  94. * @arg3: argument
  95. * @arg4: argument
  96. * @arg5: argument
  97. *
  98. * Return 0 on success, -ve on error. -ENOSYS is returned when Yama
  99. * does not handle the given option.
  100. */
  101. static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
  102. unsigned long arg4, unsigned long arg5)
  103. {
  104. int rc;
  105. struct task_struct *myself = current;
  106. rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
  107. if (rc != -ENOSYS)
  108. return rc;
  109. switch (option) {
  110. case PR_SET_PTRACER:
  111. /* Since a thread can call prctl(), find the group leader
  112. * before calling _add() or _del() on it, since we want
  113. * process-level granularity of control. The tracer group
  114. * leader checking is handled later when walking the ancestry
  115. * at the time of PTRACE_ATTACH check.
  116. */
  117. rcu_read_lock();
  118. if (!thread_group_leader(myself))
  119. myself = rcu_dereference(myself->group_leader);
  120. get_task_struct(myself);
  121. rcu_read_unlock();
  122. if (arg2 == 0) {
  123. yama_ptracer_del(NULL, myself);
  124. rc = 0;
  125. } else if (arg2 == PR_SET_PTRACER_ANY || (int)arg2 == -1) {
  126. rc = yama_ptracer_add(NULL, myself);
  127. } else {
  128. struct task_struct *tracer;
  129. rcu_read_lock();
  130. tracer = find_task_by_vpid(arg2);
  131. if (tracer)
  132. get_task_struct(tracer);
  133. else
  134. rc = -EINVAL;
  135. rcu_read_unlock();
  136. if (tracer) {
  137. rc = yama_ptracer_add(tracer, myself);
  138. put_task_struct(tracer);
  139. }
  140. }
  141. put_task_struct(myself);
  142. break;
  143. }
  144. return rc;
  145. }
  146. /**
  147. * task_is_descendant - walk up a process family tree looking for a match
  148. * @parent: the process to compare against while walking up from child
  149. * @child: the process to start from while looking upwards for parent
  150. *
  151. * Returns 1 if child is a descendant of parent, 0 if not.
  152. */
  153. static int task_is_descendant(struct task_struct *parent,
  154. struct task_struct *child)
  155. {
  156. int rc = 0;
  157. struct task_struct *walker = child;
  158. if (!parent || !child)
  159. return 0;
  160. rcu_read_lock();
  161. if (!thread_group_leader(parent))
  162. parent = rcu_dereference(parent->group_leader);
  163. while (walker->pid > 0) {
  164. if (!thread_group_leader(walker))
  165. walker = rcu_dereference(walker->group_leader);
  166. if (walker == parent) {
  167. rc = 1;
  168. break;
  169. }
  170. walker = rcu_dereference(walker->real_parent);
  171. }
  172. rcu_read_unlock();
  173. return rc;
  174. }
  175. /**
  176. * ptracer_exception_found - tracer registered as exception for this tracee
  177. * @tracer: the task_struct of the process attempting ptrace
  178. * @tracee: the task_struct of the process to be ptraced
  179. *
  180. * Returns 1 if tracer has is ptracer exception ancestor for tracee.
  181. */
  182. static int ptracer_exception_found(struct task_struct *tracer,
  183. struct task_struct *tracee)
  184. {
  185. int rc = 0;
  186. struct ptrace_relation *relation;
  187. struct task_struct *parent = NULL;
  188. bool found = false;
  189. spin_lock_bh(&ptracer_relations_lock);
  190. rcu_read_lock();
  191. if (!thread_group_leader(tracee))
  192. tracee = rcu_dereference(tracee->group_leader);
  193. list_for_each_entry(relation, &ptracer_relations, node)
  194. if (relation->tracee == tracee) {
  195. parent = relation->tracer;
  196. found = true;
  197. break;
  198. }
  199. if (found && (parent == NULL || task_is_descendant(parent, tracer)))
  200. rc = 1;
  201. rcu_read_unlock();
  202. spin_unlock_bh(&ptracer_relations_lock);
  203. return rc;
  204. }
  205. /**
  206. * yama_ptrace_access_check - validate PTRACE_ATTACH calls
  207. * @child: task that current task is attempting to ptrace
  208. * @mode: ptrace attach mode
  209. *
  210. * Returns 0 if following the ptrace is allowed, -ve on error.
  211. */
  212. static int yama_ptrace_access_check(struct task_struct *child,
  213. unsigned int mode)
  214. {
  215. int rc;
  216. /* If standard caps disallows it, so does Yama. We should
  217. * only tighten restrictions further.
  218. */
  219. rc = cap_ptrace_access_check(child, mode);
  220. if (rc)
  221. return rc;
  222. /* require ptrace target be a child of ptracer on attach */
  223. if (mode == PTRACE_MODE_ATTACH &&
  224. ptrace_scope &&
  225. !task_is_descendant(current, child) &&
  226. !ptracer_exception_found(current, child) &&
  227. !capable(CAP_SYS_PTRACE))
  228. rc = -EPERM;
  229. if (rc) {
  230. char name[sizeof(current->comm)];
  231. printk_ratelimited(KERN_NOTICE "ptrace of non-child"
  232. " pid %d was attempted by: %s (pid %d)\n",
  233. child->pid,
  234. get_task_comm(name, current),
  235. current->pid);
  236. }
  237. return rc;
  238. }
  239. static struct security_operations yama_ops = {
  240. .name = "yama",
  241. .ptrace_access_check = yama_ptrace_access_check,
  242. .task_prctl = yama_task_prctl,
  243. .task_free = yama_task_free,
  244. };
  245. #ifdef CONFIG_SYSCTL
  246. static int zero;
  247. static int one = 1;
  248. struct ctl_path yama_sysctl_path[] = {
  249. { .procname = "kernel", },
  250. { .procname = "yama", },
  251. { }
  252. };
  253. static struct ctl_table yama_sysctl_table[] = {
  254. {
  255. .procname = "ptrace_scope",
  256. .data = &ptrace_scope,
  257. .maxlen = sizeof(int),
  258. .mode = 0644,
  259. .proc_handler = proc_dointvec_minmax,
  260. .extra1 = &zero,
  261. .extra2 = &one,
  262. },
  263. { }
  264. };
  265. #endif /* CONFIG_SYSCTL */
  266. static __init int yama_init(void)
  267. {
  268. if (!security_module_enable(&yama_ops))
  269. return 0;
  270. printk(KERN_INFO "Yama: becoming mindful.\n");
  271. if (register_security(&yama_ops))
  272. panic("Yama: kernel registration failed.\n");
  273. #ifdef CONFIG_SYSCTL
  274. if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
  275. panic("Yama: sysctl registration failed.\n");
  276. #endif
  277. return 0;
  278. }
  279. security_initcall(yama_init);