aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/security/00-INDEX2
-rw-r--r--Documentation/security/Yama.txt60
-rw-r--r--include/linux/prctl.h6
-rw-r--r--security/Kconfig6
-rw-r--r--security/Makefile2
-rw-r--r--security/yama/Kconfig13
-rw-r--r--security/yama/Makefile3
-rw-r--r--security/yama/yama_lsm.c319
8 files changed, 411 insertions, 0 deletions
diff --git a/Documentation/security/00-INDEX b/Documentation/security/00-INDEX
index 99b85d39751..eeed1de546d 100644
--- a/Documentation/security/00-INDEX
+++ b/Documentation/security/00-INDEX
@@ -6,6 +6,8 @@ SELinux.txt
6 - how to get started with the SELinux security enhancement. 6 - how to get started with the SELinux security enhancement.
7Smack.txt 7Smack.txt
8 - documentation on the Smack Linux Security Module. 8 - documentation on the Smack Linux Security Module.
9Yama.txt
10 - documentation on the Yama Linux Security Module.
9apparmor.txt 11apparmor.txt
10 - documentation on the AppArmor security extension. 12 - documentation on the AppArmor security extension.
11credentials.txt 13credentials.txt
diff --git a/Documentation/security/Yama.txt b/Documentation/security/Yama.txt
new file mode 100644
index 00000000000..4f0b7896a21
--- /dev/null
+++ b/Documentation/security/Yama.txt
@@ -0,0 +1,60 @@
1Yama is a Linux Security Module that collects a number of system-wide DAC
2security protections that are not handled by the core kernel itself. To
3select it at boot time, specify "security=yama" (though this will disable
4any other LSM).
5
6Yama is controlled through sysctl in /proc/sys/kernel/yama:
7
8- ptrace_scope
9
10==============================================================
11
12ptrace_scope:
13
14As Linux grows in popularity, it will become a larger target for
15malware. One particularly troubling weakness of the Linux process
16interfaces is that a single user is able to examine the memory and
17running state of any of their processes. For example, if one application
18(e.g. Pidgin) was compromised, it would be possible for an attacker to
19attach to other running processes (e.g. Firefox, SSH sessions, GPG agent,
20etc) to extract additional credentials and continue to expand the scope
21of their attack without resorting to user-assisted phishing.
22
23This is not a theoretical problem. SSH session hijacking
24(http://www.storm.net.nz/projects/7) and arbitrary code injection
25(http://c-skills.blogspot.com/2007/05/injectso.html) attacks already
26exist and remain possible if ptrace is allowed to operate as before.
27Since ptrace is not commonly used by non-developers and non-admins, system
28builders should be allowed the option to disable this debugging system.
29
30For a solution, some applications use prctl(PR_SET_DUMPABLE, ...) to
31specifically disallow such ptrace attachment (e.g. ssh-agent), but many
32do not. A more general solution is to only allow ptrace directly from a
33parent to a child process (i.e. direct "gdb EXE" and "strace EXE" still
34work), or with CAP_SYS_PTRACE (i.e. "gdb --pid=PID", and "strace -p PID"
35still work as root).
36
37For software that has defined application-specific relationships
38between a debugging process and its inferior (crash handlers, etc),
39prctl(PR_SET_PTRACER, pid, ...) can be used. An inferior can declare which
40other process (and its descendents) are allowed to call PTRACE_ATTACH
41against it. Only one such declared debugging process can exists for
42each inferior at a time. For example, this is used by KDE, Chromium, and
43Firefox's crash handlers, and by Wine for allowing only Wine processes
44to ptrace each other.
45
460 - classic ptrace permissions: a process can PTRACE_ATTACH to any other
47 process running under the same uid, as long as it is dumpable (i.e.
48 did not transition uids, start privileged, or have called
49 prctl(PR_SET_DUMPABLE...) already).
50
511 - restricted ptrace: a process must have a predefined relationship
52 with the inferior it wants to call PTRACE_ATTACH on. By default,
53 this relationship is that of only its descendants when the above
54 classic criteria is also met. To change the relationship, an
55 inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare
56 an allowed debugger PID to call PTRACE_ATTACH on the inferior.
57
58The original children-only logic was based on the restrictions in grsecurity.
59
60==============================================================
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index 7ddc7f1b480..4d0e5bc5458 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -114,4 +114,10 @@
114# define PR_SET_MM_START_BRK 6 114# define PR_SET_MM_START_BRK 6
115# define PR_SET_MM_BRK 7 115# define PR_SET_MM_BRK 7
116 116
117/*
118 * Set specific pid that is allowed to ptrace the current task.
119 * A value of 0 mean "no process".
120 */
121#define PR_SET_PTRACER 0x59616d61
122
117#endif /* _LINUX_PRCTL_H */ 123#endif /* _LINUX_PRCTL_H */
diff --git a/security/Kconfig b/security/Kconfig
index 51bd5a0b69a..ccc61f8006b 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -187,6 +187,7 @@ source security/selinux/Kconfig
187source security/smack/Kconfig 187source security/smack/Kconfig
188source security/tomoyo/Kconfig 188source security/tomoyo/Kconfig
189source security/apparmor/Kconfig 189source security/apparmor/Kconfig
190source security/yama/Kconfig
190 191
191source security/integrity/Kconfig 192source security/integrity/Kconfig
192 193
@@ -196,6 +197,7 @@ choice
196 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK 197 default DEFAULT_SECURITY_SMACK if SECURITY_SMACK
197 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO 198 default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
198 default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR 199 default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
200 default DEFAULT_SECURITY_YAMA if SECURITY_YAMA
199 default DEFAULT_SECURITY_DAC 201 default DEFAULT_SECURITY_DAC
200 202
201 help 203 help
@@ -214,6 +216,9 @@ choice
214 config DEFAULT_SECURITY_APPARMOR 216 config DEFAULT_SECURITY_APPARMOR
215 bool "AppArmor" if SECURITY_APPARMOR=y 217 bool "AppArmor" if SECURITY_APPARMOR=y
216 218
219 config DEFAULT_SECURITY_YAMA
220 bool "Yama" if SECURITY_YAMA=y
221
217 config DEFAULT_SECURITY_DAC 222 config DEFAULT_SECURITY_DAC
218 bool "Unix Discretionary Access Controls" 223 bool "Unix Discretionary Access Controls"
219 224
@@ -225,6 +230,7 @@ config DEFAULT_SECURITY
225 default "smack" if DEFAULT_SECURITY_SMACK 230 default "smack" if DEFAULT_SECURITY_SMACK
226 default "tomoyo" if DEFAULT_SECURITY_TOMOYO 231 default "tomoyo" if DEFAULT_SECURITY_TOMOYO
227 default "apparmor" if DEFAULT_SECURITY_APPARMOR 232 default "apparmor" if DEFAULT_SECURITY_APPARMOR
233 default "yama" if DEFAULT_SECURITY_YAMA
228 default "" if DEFAULT_SECURITY_DAC 234 default "" if DEFAULT_SECURITY_DAC
229 235
230endmenu 236endmenu
diff --git a/security/Makefile b/security/Makefile
index a5e502f8a05..c26c81e9257 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -7,6 +7,7 @@ subdir-$(CONFIG_SECURITY_SELINUX) += selinux
7subdir-$(CONFIG_SECURITY_SMACK) += smack 7subdir-$(CONFIG_SECURITY_SMACK) += smack
8subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo 8subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo
9subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor 9subdir-$(CONFIG_SECURITY_APPARMOR) += apparmor
10subdir-$(CONFIG_SECURITY_YAMA) += yama
10 11
11# always enable default capabilities 12# always enable default capabilities
12obj-y += commoncap.o 13obj-y += commoncap.o
@@ -21,6 +22,7 @@ obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
21obj-$(CONFIG_AUDIT) += lsm_audit.o 22obj-$(CONFIG_AUDIT) += lsm_audit.o
22obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o 23obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o
23obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o 24obj-$(CONFIG_SECURITY_APPARMOR) += apparmor/built-in.o
25obj-$(CONFIG_SECURITY_YAMA) += yama/built-in.o
24obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o 26obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
25 27
26# Object integrity file lists 28# Object integrity file lists
diff --git a/security/yama/Kconfig b/security/yama/Kconfig
new file mode 100644
index 00000000000..51d6709d8bb
--- /dev/null
+++ b/security/yama/Kconfig
@@ -0,0 +1,13 @@
1config SECURITY_YAMA
2 bool "Yama support"
3 depends on SECURITY
4 select SECURITYFS
5 select SECURITY_PATH
6 default n
7 help
8 This selects Yama, which extends DAC support with additional
9 system-wide security settings beyond regular Linux discretionary
10 access controls. Currently available is ptrace scope restriction.
11 Further information can be found in Documentation/security/Yama.txt.
12
13 If you are unsure how to answer this question, answer N.
diff --git a/security/yama/Makefile b/security/yama/Makefile
new file mode 100644
index 00000000000..8b5e0658845
--- /dev/null
+++ b/security/yama/Makefile
@@ -0,0 +1,3 @@
1obj-$(CONFIG_SECURITY_YAMA) := yama.o
2
3yama-y := yama_lsm.o
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
new file mode 100644
index 00000000000..dd4d36067c5
--- /dev/null
+++ b/security/yama/yama_lsm.c
@@ -0,0 +1,319 @@
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
15#include <linux/security.h>
16#include <linux/sysctl.h>
17#include <linux/ptrace.h>
18#include <linux/prctl.h>
19#include <linux/ratelimit.h>
20
21static int ptrace_scope = 1;
22
23/* describe a ptrace relationship for potential exception */
24struct ptrace_relation {
25 struct task_struct *tracer;
26 struct task_struct *tracee;
27 struct list_head node;
28};
29
30static LIST_HEAD(ptracer_relations);
31static DEFINE_SPINLOCK(ptracer_relations_lock);
32
33/**
34 * yama_ptracer_add - add/replace an exception for this tracer/tracee pair
35 * @tracer: the task_struct of the process doing the ptrace
36 * @tracee: the task_struct of the process to be ptraced
37 *
38 * Each tracee can have, at most, one tracer registered. Each time this
39 * is called, the prior registered tracer will be replaced for the tracee.
40 *
41 * Returns 0 if relationship was added, -ve on error.
42 */
43static int yama_ptracer_add(struct task_struct *tracer,
44 struct task_struct *tracee)
45{
46 int rc = 0;
47 struct ptrace_relation *added;
48 struct ptrace_relation *entry, *relation = NULL;
49
50 added = kmalloc(sizeof(*added), GFP_KERNEL);
51 if (!added)
52 return -ENOMEM;
53
54 spin_lock_bh(&ptracer_relations_lock);
55 list_for_each_entry(entry, &ptracer_relations, node)
56 if (entry->tracee == tracee) {
57 relation = entry;
58 break;
59 }
60 if (!relation) {
61 relation = added;
62 relation->tracee = tracee;
63 list_add(&relation->node, &ptracer_relations);
64 }
65 relation->tracer = tracer;
66
67 spin_unlock_bh(&ptracer_relations_lock);
68 if (added != relation)
69 kfree(added);
70
71 return rc;
72}
73
74/**
75 * yama_ptracer_del - remove exceptions related to the given tasks
76 * @tracer: remove any relation where tracer task matches
77 * @tracee: remove any relation where tracee task matches
78 */
79static void yama_ptracer_del(struct task_struct *tracer,
80 struct task_struct *tracee)
81{
82 struct ptrace_relation *relation, *safe;
83
84 spin_lock_bh(&ptracer_relations_lock);
85 list_for_each_entry_safe(relation, safe, &ptracer_relations, node)
86 if (relation->tracee == tracee ||
87 relation->tracer == tracer) {
88 list_del(&relation->node);
89 kfree(relation);
90 }
91 spin_unlock_bh(&ptracer_relations_lock);
92}
93
94/**
95 * yama_task_free - check for task_pid to remove from exception list
96 * @task: task being removed
97 */
98static void yama_task_free(struct task_struct *task)
99{
100 yama_ptracer_del(task, task);
101}
102
103/**
104 * yama_task_prctl - check for Yama-specific prctl operations
105 * @option: operation
106 * @arg2: argument
107 * @arg3: argument
108 * @arg4: argument
109 * @arg5: argument
110 *
111 * Return 0 on success, -ve on error. -ENOSYS is returned when Yama
112 * does not handle the given option.
113 */
114static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
115 unsigned long arg4, unsigned long arg5)
116{
117 int rc;
118 struct task_struct *myself = current;
119
120 rc = cap_task_prctl(option, arg2, arg3, arg4, arg5);
121 if (rc != -ENOSYS)
122 return rc;
123
124 switch (option) {
125 case PR_SET_PTRACER:
126 /* Since a thread can call prctl(), find the group leader
127 * before calling _add() or _del() on it, since we want
128 * process-level granularity of control. The tracer group
129 * leader checking is handled later when walking the ancestry
130 * at the time of PTRACE_ATTACH check.
131 */
132 rcu_read_lock();
133 if (!thread_group_leader(myself))
134 myself = rcu_dereference(myself->group_leader);
135 get_task_struct(myself);
136 rcu_read_unlock();
137
138 if (arg2 == 0) {
139 yama_ptracer_del(NULL, myself);
140 rc = 0;
141 } else {
142 struct task_struct *tracer;
143
144 rcu_read_lock();
145 tracer = find_task_by_vpid(arg2);
146 if (tracer)
147 get_task_struct(tracer);
148 else
149 rc = -EINVAL;
150 rcu_read_unlock();
151
152 if (tracer) {
153 rc = yama_ptracer_add(tracer, myself);
154 put_task_struct(tracer);
155 }
156 }
157
158 put_task_struct(myself);
159 break;
160 }
161
162 return rc;
163}
164
165/**
166 * task_is_descendant - walk up a process family tree looking for a match
167 * @parent: the process to compare against while walking up from child
168 * @child: the process to start from while looking upwards for parent
169 *
170 * Returns 1 if child is a descendant of parent, 0 if not.
171 */
172static int task_is_descendant(struct task_struct *parent,
173 struct task_struct *child)
174{
175 int rc = 0;
176 struct task_struct *walker = child;
177
178 if (!parent || !child)
179 return 0;
180
181 rcu_read_lock();
182 if (!thread_group_leader(parent))
183 parent = rcu_dereference(parent->group_leader);
184 while (walker->pid > 0) {
185 if (!thread_group_leader(walker))
186 walker = rcu_dereference(walker->group_leader);
187 if (walker == parent) {
188 rc = 1;
189 break;
190 }
191 walker = rcu_dereference(walker->real_parent);
192 }
193 rcu_read_unlock();
194
195 return rc;
196}
197
198/**
199 * ptracer_exception_found - tracer registered as exception for this tracee
200 * @tracer: the task_struct of the process attempting ptrace
201 * @tracee: the task_struct of the process to be ptraced
202 *
203 * Returns 1 if tracer has is ptracer exception ancestor for tracee.
204 */
205static int ptracer_exception_found(struct task_struct *tracer,
206 struct task_struct *tracee)
207{
208 int rc = 0;
209 struct ptrace_relation *relation;
210 struct task_struct *parent = NULL;
211
212 spin_lock_bh(&ptracer_relations_lock);
213 rcu_read_lock();
214 if (!thread_group_leader(tracee))
215 tracee = rcu_dereference(tracee->group_leader);
216 list_for_each_entry(relation, &ptracer_relations, node)
217 if (relation->tracee == tracee) {
218 parent = relation->tracer;
219 break;
220 }
221
222 if (task_is_descendant(parent, tracer))
223 rc = 1;
224 rcu_read_unlock();
225 spin_unlock_bh(&ptracer_relations_lock);
226
227 return rc;
228}
229
230/**
231 * yama_ptrace_access_check - validate PTRACE_ATTACH calls
232 * @child: task that current task is attempting to ptrace
233 * @mode: ptrace attach mode
234 *
235 * Returns 0 if following the ptrace is allowed, -ve on error.
236 */
237static int yama_ptrace_access_check(struct task_struct *child,
238 unsigned int mode)
239{
240 int rc;
241
242 /* If standard caps disallows it, so does Yama. We should
243 * only tighten restrictions further.
244 */
245 rc = cap_ptrace_access_check(child, mode);
246 if (rc)
247 return rc;
248
249 /* require ptrace target be a child of ptracer on attach */
250 if (mode == PTRACE_MODE_ATTACH &&
251 ptrace_scope &&
252 !task_is_descendant(current, child) &&
253 !ptracer_exception_found(current, child) &&
254 !capable(CAP_SYS_PTRACE))
255 rc = -EPERM;
256
257 if (rc) {
258 char name[sizeof(current->comm)];
259 printk_ratelimited(KERN_NOTICE "ptrace of non-child"
260 " pid %d was attempted by: %s (pid %d)\n",
261 child->pid,
262 get_task_comm(name, current),
263 current->pid);
264 }
265
266 return rc;
267}
268
269static struct security_operations yama_ops = {
270 .name = "yama",
271
272 .ptrace_access_check = yama_ptrace_access_check,
273 .task_prctl = yama_task_prctl,
274 .task_free = yama_task_free,
275};
276
277#ifdef CONFIG_SYSCTL
278static int zero;
279static int one = 1;
280
281struct ctl_path yama_sysctl_path[] = {
282 { .procname = "kernel", },
283 { .procname = "yama", },
284 { }
285};
286
287static struct ctl_table yama_sysctl_table[] = {
288 {
289 .procname = "ptrace_scope",
290 .data = &ptrace_scope,
291 .maxlen = sizeof(int),
292 .mode = 0644,
293 .proc_handler = proc_dointvec_minmax,
294 .extra1 = &zero,
295 .extra2 = &one,
296 },
297 { }
298};
299#endif /* CONFIG_SYSCTL */
300
301static __init int yama_init(void)
302{
303 if (!security_module_enable(&yama_ops))
304 return 0;
305
306 printk(KERN_INFO "Yama: becoming mindful.\n");
307
308 if (register_security(&yama_ops))
309 panic("Yama: kernel registration failed.\n");
310
311#ifdef CONFIG_SYSCTL
312 if (!register_sysctl_paths(yama_sysctl_path, yama_sysctl_table))
313 panic("Yama: sysctl registration failed.\n");
314#endif
315
316 return 0;
317}
318
319security_initcall(yama_init);