From 3fac5cf03c3a5b6592d84ee5eeea6e3f212596e6 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Sun, 27 Dec 2015 06:19:08 +0000 Subject: [PATCH] ptrace: being capable wrt a process requires mapped uids/gids --- debian/changelog | 1 + ...-a-process-requires-mapped-uids-gids.patch | 104 ++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 106 insertions(+) create mode 100644 debian/patches/bugfix/all/ptrace-being-capable-wrt-a-process-requires-mapped-uids-gids.patch diff --git a/debian/changelog b/debian/changelog index 71d10e239..cc7f499af 100644 --- a/debian/changelog +++ b/debian/changelog @@ -8,6 +8,7 @@ linux (4.3.3-3) UNRELEASED; urgency=medium * [xen] Fix race conditions in back-end drivers (CVE-2015-8550, XSA-155) * [xen] pciback: Fix state validation in MSI control operations (CVE-2015-8551, CVE-2015-8852, XSA-157) + * ptrace: being capable wrt a process requires mapped uids/gids [ Salvatore Bonaccorso ] * ovl: fix permission checking for setattr (CVE-2015-8660) diff --git a/debian/patches/bugfix/all/ptrace-being-capable-wrt-a-process-requires-mapped-uids-gids.patch b/debian/patches/bugfix/all/ptrace-being-capable-wrt-a-process-requires-mapped-uids-gids.patch new file mode 100644 index 000000000..1463047ed --- /dev/null +++ b/debian/patches/bugfix/all/ptrace-being-capable-wrt-a-process-requires-mapped-uids-gids.patch @@ -0,0 +1,104 @@ +From: Jann Horn +Subject: ptrace: being capable wrt a process requires mapped uids/gids +Date: Sat, 26 Dec 2015 03:52:31 +0100 +Origin: https://lkml.org/lkml/2015/12/25/71 + +ptrace_has_cap() checks whether the current process should be +treated as having a certain capability for ptrace checks +against another process. Until now, this was equivalent to +has_ns_capability(current, target_ns, CAP_SYS_PTRACE). + +However, if a root-owned process wants to enter a user +namespace for some reason without knowing who owns it and +therefore can't change to the namespace owner's uid and gid +before entering, as soon as it has entered the namespace, +the namespace owner can attach to it via ptrace and thereby +gain access to its uid and gid. + +While it is possible for the entering process to switch to +the uid of a claimed namespace owner before entering, +causing the attempt to enter to fail if the claimed uid is +wrong, this doesn't solve the problem of determining an +appropriate gid. + +With this change, the entering process can first enter the +namespace and then safely inspect the namespace's +properties, e.g. through /proc/self/{uid_map,gid_map}, +assuming that the namespace owner doesn't have access to +uid 0. +Changed in v2: The caller needs to be capable in the +namespace into which tcred's uids/gids can be mapped. + +Signed-off-by: Jann Horn +--- + kernel/ptrace.c | 33 ++++++++++++++++++++++++++++----- + 1 file changed, 28 insertions(+), 5 deletions(-) + +diff --git a/kernel/ptrace.c b/kernel/ptrace.c +index b760bae..260a08d 100644 +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -207,12 +208,34 @@ static int ptrace_check_attach(struct task_struct *child, bool ignore_state) + return ret; + } + +-static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode) ++static bool ptrace_has_cap(const struct cred *tcred, unsigned int mode) + { ++ struct user_namespace *tns = tcred->user_ns; ++ ++ /* When a root-owned process enters a user namespace created by a ++ * malicious user, the user shouldn't be able to execute code under ++ * uid 0 by attaching to the root-owned process via ptrace. ++ * Therefore, similar to the capable_wrt_inode_uidgid() check, ++ * verify that all the uids and gids of the target process are ++ * mapped into a namespace below the current one in which the caller ++ * is capable. ++ * No fsuid/fsgid check because __ptrace_may_access doesn't do it ++ * either. ++ */ ++ while ( ++ !kuid_has_mapping(tns, tcred->euid) || ++ !kuid_has_mapping(tns, tcred->suid) || ++ !kuid_has_mapping(tns, tcred->uid) || ++ !kgid_has_mapping(tns, tcred->egid) || ++ !kgid_has_mapping(tns, tcred->sgid) || ++ !kgid_has_mapping(tns, tcred->gid)) { ++ tns = tns->parent; ++ } ++ + if (mode & PTRACE_MODE_NOAUDIT) +- return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE); ++ return has_ns_capability_noaudit(current, tns, CAP_SYS_PTRACE); + else +- return has_ns_capability(current, ns, CAP_SYS_PTRACE); ++ return has_ns_capability(current, tns, CAP_SYS_PTRACE); + } + + /* Returns 0 on success, -errno on denial. */ +@@ -241,7 +264,7 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode) + gid_eq(cred->gid, tcred->sgid) && + gid_eq(cred->gid, tcred->gid)) + goto ok; +- if (ptrace_has_cap(tcred->user_ns, mode)) ++ if (ptrace_has_cap(tcred, mode)) + goto ok; + rcu_read_unlock(); + return -EPERM; +@@ -252,7 +275,7 @@ ok: + dumpable = get_dumpable(task->mm); + rcu_read_lock(); + if (dumpable != SUID_DUMP_USER && +- !ptrace_has_cap(__task_cred(task)->user_ns, mode)) { ++ !ptrace_has_cap(__task_cred(task), mode)) { + rcu_read_unlock(); + return -EPERM; + } diff --git a/debian/patches/series b/debian/patches/series index a9d5c6112..02ee659cd 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -121,3 +121,4 @@ bugfix/all/xen-pciback-return-error-on-xen_pci_op_enable_msix-w.patch bugfix/all/xen-pciback-do-not-install-an-irq-handler-for-msi-in.patch bugfix/all/xen-pciback-for-xen_pci_op_disable_msi-x-only-disabl.patch bugfix/all/xen-pciback-don-t-allow-msi-x-ops-if-pci_command_mem.patch +bugfix/all/ptrace-being-capable-wrt-a-process-requires-mapped-uids-gids.patch