瀏覽代碼

Yama: higher restrictions should block PTRACE_TRACEME

The higher ptrace restriction levels should be blocking even
PTRACE_TRACEME requests. The comments in the LSM documentation are
misleading about when the checks happen (the parent does not go through
security_ptrace_access_check() on a PTRACE_TRACEME call).

Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: stable@vger.kernel.org # 3.5.x and later
Signed-off-by: James Morris <james.l.morris@oracle.com>
Kees Cook 13 年之前
父節點
當前提交
9d8dad742a
共有 3 個文件被更改,包括 48 次插入9 次删除
  1. 7 7
      Documentation/security/Yama.txt
  2. 0 2
      include/linux/security.h
  3. 41 0
      security/yama/yama_lsm.c

+ 7 - 7
Documentation/security/Yama.txt

@@ -46,14 +46,13 @@ restrictions, it can call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, ...)
 so that any otherwise allowed process (even those in external pid namespaces)
 so that any otherwise allowed process (even those in external pid namespaces)
 may attach.
 may attach.
 
 
-These restrictions do not change how ptrace via PTRACE_TRACEME operates.
-
-The sysctl settings are:
+The sysctl settings (writable only with CAP_SYS_PTRACE) are:
 
 
 0 - classic ptrace permissions: a process can PTRACE_ATTACH to any other
 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.
     process running under the same uid, as long as it is dumpable (i.e.
     did not transition uids, start privileged, or have called
     did not transition uids, start privileged, or have called
-    prctl(PR_SET_DUMPABLE...) already).
+    prctl(PR_SET_DUMPABLE...) already). Similarly, PTRACE_TRACEME is
+    unchanged.
 
 
 1 - restricted ptrace: a process must have a predefined relationship
 1 - restricted ptrace: a process must have a predefined relationship
     with the inferior it wants to call PTRACE_ATTACH on. By default,
     with the inferior it wants to call PTRACE_ATTACH on. By default,
@@ -61,12 +60,13 @@ The sysctl settings are:
     classic criteria is also met. To change the relationship, an
     classic criteria is also met. To change the relationship, an
     inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare
     inferior can call prctl(PR_SET_PTRACER, debugger, ...) to declare
     an allowed debugger PID to call PTRACE_ATTACH on the inferior.
     an allowed debugger PID to call PTRACE_ATTACH on the inferior.
+    Using PTRACE_TRACEME is unchanged.
 
 
 2 - admin-only attach: only processes with CAP_SYS_PTRACE may use ptrace
 2 - admin-only attach: only processes with CAP_SYS_PTRACE may use ptrace
-    with PTRACE_ATTACH.
+    with PTRACE_ATTACH, or through children calling PTRACE_TRACEME.
 
 
-3 - no attach: no processes may use ptrace with PTRACE_ATTACH. Once set,
-    this sysctl cannot be changed to a lower value.
+3 - no attach: no processes may use ptrace with PTRACE_ATTACH nor via
+    PTRACE_TRACEME. Once set, this sysctl value cannot be changed.
 
 
 The original children-only logic was based on the restrictions in grsecurity.
 The original children-only logic was based on the restrictions in grsecurity.
 
 

+ 0 - 2
include/linux/security.h

@@ -1242,8 +1242,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
  *	Check that the @parent process has sufficient permission to trace the
  *	Check that the @parent process has sufficient permission to trace the
  *	current process before allowing the current process to present itself
  *	current process before allowing the current process to present itself
  *	to the @parent process for tracing.
  *	to the @parent process for tracing.
- *	The parent process will still have to undergo the ptrace_access_check
- *	checks before it is allowed to trace this one.
  *	@parent contains the task_struct structure for debugger process.
  *	@parent contains the task_struct structure for debugger process.
  *	Return 0 if permission is granted.
  *	Return 0 if permission is granted.
  * @capget:
  * @capget:

+ 41 - 0
security/yama/yama_lsm.c

@@ -290,10 +290,51 @@ static int yama_ptrace_access_check(struct task_struct *child,
 	return rc;
 	return rc;
 }
 }
 
 
+/**
+ * yama_ptrace_traceme - validate PTRACE_TRACEME calls
+ * @parent: task that will become the ptracer of the current task
+ *
+ * Returns 0 if following the ptrace is allowed, -ve on error.
+ */
+static int yama_ptrace_traceme(struct task_struct *parent)
+{
+	int rc;
+
+	/* If standard caps disallows it, so does Yama.  We should
+	 * only tighten restrictions further.
+	 */
+	rc = cap_ptrace_traceme(parent);
+	if (rc)
+		return rc;
+
+	/* Only disallow PTRACE_TRACEME on more aggressive settings. */
+	switch (ptrace_scope) {
+	case YAMA_SCOPE_CAPABILITY:
+		if (!ns_capable(task_user_ns(parent), CAP_SYS_PTRACE))
+			rc = -EPERM;
+		break;
+	case YAMA_SCOPE_NO_ATTACH:
+		rc = -EPERM;
+		break;
+	}
+
+	if (rc) {
+		char name[sizeof(current->comm)];
+		printk_ratelimited(KERN_NOTICE
+			"ptraceme of pid %d was attempted by: %s (pid %d)\n",
+			current->pid,
+			get_task_comm(name, parent),
+			parent->pid);
+	}
+
+	return rc;
+}
+
 static struct security_operations yama_ops = {
 static struct security_operations yama_ops = {
 	.name =			"yama",
 	.name =			"yama",
 
 
 	.ptrace_access_check =	yama_ptrace_access_check,
 	.ptrace_access_check =	yama_ptrace_access_check,
+	.ptrace_traceme =	yama_ptrace_traceme,
 	.task_prctl =		yama_task_prctl,
 	.task_prctl =		yama_task_prctl,
 	.task_free =		yama_task_free,
 	.task_free =		yama_task_free,
 };
 };