Commit bf06189e4d14641c0148bea16e9dd24943862215
Committed by
James Morris
1 parent
3ab1aff894
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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>
Showing 3 changed files with 13 additions and 3 deletions Side-by-side Diff
Documentation/security/Yama.txt
... | ... | @@ -41,7 +41,12 @@ |
41 | 41 | against it. Only one such declared debugging process can exists for |
42 | 42 | each inferior at a time. For example, this is used by KDE, Chromium, and |
43 | 43 | Firefox's crash handlers, and by Wine for allowing only Wine processes |
44 | -to ptrace each other. | |
44 | +to ptrace each other. If a process wishes to entirely disable these ptrace | |
45 | +restrictions, it can call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...) | |
46 | +so that any otherwise allowed process (even those in external pid namespaces) | |
47 | +may attach. | |
48 | + | |
49 | +The sysctl settings are: | |
45 | 50 | |
46 | 51 | 0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other |
47 | 52 | process running under the same uid, as long as it is dumpable (i.e. |
include/linux/prctl.h
security/yama/yama_lsm.c
... | ... | @@ -84,7 +84,7 @@ |
84 | 84 | spin_lock_bh(&ptracer_relations_lock); |
85 | 85 | list_for_each_entry_safe(relation, safe, &ptracer_relations, node) |
86 | 86 | if (relation->tracee == tracee || |
87 | - relation->tracer == tracer) { | |
87 | + (tracer && relation->tracer == tracer)) { | |
88 | 88 | list_del(&relation->node); |
89 | 89 | kfree(relation); |
90 | 90 | } |
... | ... | @@ -138,6 +138,8 @@ |
138 | 138 | if (arg2 == 0) { |
139 | 139 | yama_ptracer_del(NULL, myself); |
140 | 140 | rc = 0; |
141 | + } else if (arg2 == PR_SET_PTRACER_ANY) { | |
142 | + rc = yama_ptracer_add(NULL, myself); | |
141 | 143 | } else { |
142 | 144 | struct task_struct *tracer; |
143 | 145 | |
... | ... | @@ -208,6 +210,7 @@ |
208 | 210 | int rc = 0; |
209 | 211 | struct ptrace_relation *relation; |
210 | 212 | struct task_struct *parent = NULL; |
213 | + bool found = false; | |
211 | 214 | |
212 | 215 | spin_lock_bh(&ptracer_relations_lock); |
213 | 216 | rcu_read_lock(); |
214 | 217 | |
... | ... | @@ -216,10 +219,11 @@ |
216 | 219 | list_for_each_entry(relation, &ptracer_relations, node) |
217 | 220 | if (relation->tracee == tracee) { |
218 | 221 | parent = relation->tracer; |
222 | + found = true; | |
219 | 223 | break; |
220 | 224 | } |
221 | 225 | |
222 | - if (task_is_descendant(parent, tracer)) | |
226 | + if (found && (parent == NULL || task_is_descendant(parent, tracer))) | |
223 | 227 | rc = 1; |
224 | 228 | rcu_read_unlock(); |
225 | 229 | spin_unlock_bh(&ptracer_relations_lock); |