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.
* A value of 0 mean "no process".
*/
#define PR_SET_PTRACER 0x59616d61
+# define PR_SET_PTRACER_ANY ((unsigned long)-1)
#endif /* _LINUX_PRCTL_H */
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);
}
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;
int rc = 0;
struct ptrace_relation *relation;
struct task_struct *parent = NULL;
+ bool found = false;
spin_lock_bh(&ptracer_relations_lock);
rcu_read_lock();
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);