summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2012-02-14 19:48:09 -0500
committerJames Morris <jmorris@namei.org>2012-02-15 18:25:18 -0500
commitbf06189e4d14641c0148bea16e9dd24943862215 (patch)
tree5c62eb24339041baf65b8e42daac42c7a01efc0e
parent3ab1aff89477dafb1aaeafe8c8669114a02b7226 (diff)
Yama: add PR_SET_PTRACER_ANY
For a process to entirely disable Yama ptrace restrictions, it can use the special PR_SET_PTRACER_ANY pid to indicate that any otherwise allowed process may ptrace it. This is stronger than calling PR_SET_PTRACER with pid "1" because it includes processes in external pid namespaces. This is currently needed by the Chrome renderer, since its crash handler (Breakpad) runs external to the renderer's pid namespace. Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--Documentation/security/Yama.txt7
-rw-r--r--include/linux/prctl.h1
-rw-r--r--security/yama/yama_lsm.c8
3 files changed, 13 insertions, 3 deletions
diff --git a/Documentation/security/Yama.txt b/Documentation/security/Yama.txt
index 4f0b7896a21d..a9511f179069 100644
--- a/Documentation/security/Yama.txt
+++ b/Documentation/security/Yama.txt
@@ -41,7 +41,12 @@ other process (and its descendents) are allowed to call PTRACE_ATTACH
41against it. Only one such declared debugging process can exists for 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 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 43Firefox's crash handlers, and by Wine for allowing only Wine processes
44to ptrace each other. 44to ptrace each other. If a process wishes to entirely disable these ptrace
45restrictions, it can call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...)
46so that any otherwise allowed process (even those in external pid namespaces)
47may attach.
48
49The sysctl settings are:
45 50
460 - classic ptrace permissions: a process can PTRACE_ATTACH to any other 510 - 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. 52 process running under the same uid, as long as it is dumpable (i.e.
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index 4d0e5bc5458c..a0413ac3abe8 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -119,5 +119,6 @@
119 * A value of 0 mean "no process". 119 * A value of 0 mean "no process".
120 */ 120 */
121#define PR_SET_PTRACER 0x59616d61 121#define PR_SET_PTRACER 0x59616d61
122# define PR_SET_PTRACER_ANY ((unsigned long)-1)
122 123
123#endif /* _LINUX_PRCTL_H */ 124#endif /* _LINUX_PRCTL_H */
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c
index dd4d36067c50..573723843a04 100644
--- a/security/yama/yama_lsm.c
+++ b/security/yama/yama_lsm.c
@@ -84,7 +84,7 @@ static void yama_ptracer_del(struct task_struct *tracer,
84 spin_lock_bh(&ptracer_relations_lock); 84 spin_lock_bh(&ptracer_relations_lock);
85 list_for_each_entry_safe(relation, safe, &ptracer_relations, node) 85 list_for_each_entry_safe(relation, safe, &ptracer_relations, node)
86 if (relation->tracee == tracee || 86 if (relation->tracee == tracee ||
87 relation->tracer == tracer) { 87 (tracer && relation->tracer == tracer)) {
88 list_del(&relation->node); 88 list_del(&relation->node);
89 kfree(relation); 89 kfree(relation);
90 } 90 }
@@ -138,6 +138,8 @@ static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3,
138 if (arg2 == 0) { 138 if (arg2 == 0) {
139 yama_ptracer_del(NULL, myself); 139 yama_ptracer_del(NULL, myself);
140 rc = 0; 140 rc = 0;
141 } else if (arg2 == PR_SET_PTRACER_ANY) {
142 rc = yama_ptracer_add(NULL, myself);
141 } else { 143 } else {
142 struct task_struct *tracer; 144 struct task_struct *tracer;
143 145
@@ -208,6 +210,7 @@ static int ptracer_exception_found(struct task_struct *tracer,
208 int rc = 0; 210 int rc = 0;
209 struct ptrace_relation *relation; 211 struct ptrace_relation *relation;
210 struct task_struct *parent = NULL; 212 struct task_struct *parent = NULL;
213 bool found = false;
211 214
212 spin_lock_bh(&ptracer_relations_lock); 215 spin_lock_bh(&ptracer_relations_lock);
213 rcu_read_lock(); 216 rcu_read_lock();
@@ -216,10 +219,11 @@ static int ptracer_exception_found(struct task_struct *tracer,
216 list_for_each_entry(relation, &ptracer_relations, node) 219 list_for_each_entry(relation, &ptracer_relations, node)
217 if (relation->tracee == tracee) { 220 if (relation->tracee == tracee) {
218 parent = relation->tracer; 221 parent = relation->tracer;
222 found = true;
219 break; 223 break;
220 } 224 }
221 225
222 if (task_is_descendant(parent, tracer)) 226 if (found && (parent == NULL || task_is_descendant(parent, tracer)))
223 rc = 1; 227 rc = 1;
224 rcu_read_unlock(); 228 rcu_read_unlock();
225 spin_unlock_bh(&ptracer_relations_lock); 229 spin_unlock_bh(&ptracer_relations_lock);