From a6f99ce6a95f3e60391b257a90ef390aa8115b3f Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Tue, 14 Feb 2012 16:48:09 -0800 Subject: [PATCH] --- yaml --- r: 292283 b: refs/heads/master c: bf06189e4d14641c0148bea16e9dd24943862215 h: refs/heads/master i: 292281: cfdf9dc19ecae4e36cec2f54669208191d0715c1 292279: 5541e28c363fd7ae7c0584fd03bfe721a222d114 v: v3 --- [refs] | 2 +- trunk/Documentation/security/Yama.txt | 7 ++++++- trunk/include/linux/prctl.h | 1 + trunk/security/yama/yama_lsm.c | 8 ++++++-- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index c697eb047126..8eb9b266e9c9 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 3ab1aff89477dafb1aaeafe8c8669114a02b7226 +refs/heads/master: bf06189e4d14641c0148bea16e9dd24943862215 diff --git a/trunk/Documentation/security/Yama.txt b/trunk/Documentation/security/Yama.txt index 4f0b7896a21d..a9511f179069 100644 --- a/trunk/Documentation/security/Yama.txt +++ b/trunk/Documentation/security/Yama.txt @@ -41,7 +41,12 @@ other process (and its descendents) are allowed to call PTRACE_ATTACH against it. Only one such declared debugging process can exists for each inferior at a time. For example, this is used by KDE, Chromium, and Firefox's crash handlers, and by Wine for allowing only Wine processes -to ptrace each other. +to ptrace each other. If a process wishes to entirely disable these ptrace +restrictions, it can call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...) +so that any otherwise allowed process (even those in external pid namespaces) +may attach. + +The sysctl settings are: 0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other process running under the same uid, as long as it is dumpable (i.e. diff --git a/trunk/include/linux/prctl.h b/trunk/include/linux/prctl.h index 4d0e5bc5458c..a0413ac3abe8 100644 --- a/trunk/include/linux/prctl.h +++ b/trunk/include/linux/prctl.h @@ -119,5 +119,6 @@ * A value of 0 mean "no process". */ #define PR_SET_PTRACER 0x59616d61 +# define PR_SET_PTRACER_ANY ((unsigned long)-1) #endif /* _LINUX_PRCTL_H */ diff --git a/trunk/security/yama/yama_lsm.c b/trunk/security/yama/yama_lsm.c index dd4d36067c50..573723843a04 100644 --- a/trunk/security/yama/yama_lsm.c +++ b/trunk/security/yama/yama_lsm.c @@ -84,7 +84,7 @@ static void yama_ptracer_del(struct task_struct *tracer, spin_lock_bh(&ptracer_relations_lock); list_for_each_entry_safe(relation, safe, &ptracer_relations, node) if (relation->tracee == tracee || - relation->tracer == tracer) { + (tracer && relation->tracer == tracer)) { list_del(&relation->node); kfree(relation); } @@ -138,6 +138,8 @@ static int yama_task_prctl(int option, unsigned long arg2, unsigned long arg3, if (arg2 == 0) { yama_ptracer_del(NULL, myself); rc = 0; + } else if (arg2 == PR_SET_PTRACER_ANY) { + rc = yama_ptracer_add(NULL, myself); } else { struct task_struct *tracer; @@ -208,6 +210,7 @@ static int ptracer_exception_found(struct task_struct *tracer, int rc = 0; struct ptrace_relation *relation; struct task_struct *parent = NULL; + bool found = false; spin_lock_bh(&ptracer_relations_lock); rcu_read_lock(); @@ -216,10 +219,11 @@ static int ptracer_exception_found(struct task_struct *tracer, list_for_each_entry(relation, &ptracer_relations, node) if (relation->tracee == tracee) { parent = relation->tracer; + found = true; break; } - if (task_is_descendant(parent, tracer)) + if (found && (parent == NULL || task_is_descendant(parent, tracer))) rc = 1; rcu_read_unlock(); spin_unlock_bh(&ptracer_relations_lock);