oss-sec mailing list archives

Linux kernel: fs: fix get_dumpable() incorrect tests (CVE-2013-2929)


From: Solar Designer <solar () openwall com>
Date: Fri, 31 Jan 2014 04:51:55 +0400

I'm afraid the issue below was never brought to oss-security (as it must
have been).  The fix was committed on November 13:

http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=d049f74f2dbe71354d43d393ac3a188947811348

including detailed description and the CVE-2013-2929 reference.  So it
was clearly disclosed as a security issue, yet bringing it to
oss-security specifically seems to have falled through the cracks. :-(

Kees' posting to linux-distros:

----- Forwarded message from Kees Cook <kees () outflux net> -----

From: Kees Cook <kees () outflux net>
Subject: [PATCH] fs: fix get_dumpable() incorrect tests
Date: Tue, 22 Oct 2013 16:25:30 -0700

The get_dumpable() return value is not boolean. Most users of the
function actually want to be testing for SUID_DUMP_USER rather than
non-zero.

Without this patch, if the system had set the sysctl fs/suid_dumpable=2,
a user was able to ptrace attach to processes that had dropped privileges
to that user. (This may have been partially mitigated if Yama was enabled.)

CVE-2013-2929

Reported-by: Vasily Kulikov <segoon () openwall com>
Signed-off-by: Kees Cook <keescook () chromium org>
Cc: stable () vger kernel org
---
I plan to send this to security () kernel org on Monday, unless anyone
would like to push that a bit. Also note, I do not have ia64 cross
compilers available, so I used the "1" literal instead of adding
binfmts.h to the ia64 code.
---
 arch/ia64/include/asm/processor.h |    2 +-
 fs/exec.c                         |    6 ++++++
 kernel/ptrace.c                   |    4 +++-
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h
index e0a899a..d036a33 100644
--- a/arch/ia64/include/asm/processor.h
+++ b/arch/ia64/include/asm/processor.h
@@ -319,7 +319,7 @@ struct thread_struct {
        regs->loadrs = 0;                                                                       \
        regs->r8 = get_dumpable(current->mm);   /* set "don't zap registers" flag */            \
        regs->r12 = new_sp - 16;        /* allocate 16 byte scratch area */                     \
-       if (unlikely(!get_dumpable(current->mm))) {                                                     \
+       if (unlikely(get_dumpable(current->mm) != 1)) { \
                /*                                                                              \
                 * Zap scratch regs to avoid leaking bits between processes with different      \
                 * uid/privileges.                                                              \
diff --git a/fs/exec.c b/fs/exec.c
index 8875dd1..bb8afc1 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -1668,6 +1668,12 @@ int __get_dumpable(unsigned long mm_flags)
        return (ret > SUID_DUMP_USER) ? SUID_DUMP_ROOT : ret;
 }
 
+/*
+ * This returns the actual value of the suid_dumpable flag. For things
+ * that are using this for checking for privilege transitions, it must
+ * test against SUID_DUMP_USER rather than treating it as a boolean
+ * value.
+ */
 int get_dumpable(struct mm_struct *mm)
 {
        return __get_dumpable(mm->flags);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index dd562e9..a75ad41 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -26,6 +26,7 @@
 #include <linux/hw_breakpoint.h>
 #include <linux/cn_proc.h>
 #include <linux/compat.h>
+#include <linux/binfmts.h>
 
 
 static int ptrace_trapping_sleep_fn(void *flags)
@@ -257,7 +258,8 @@ ok:
        if (task->mm)
                dumpable = get_dumpable(task->mm);
        rcu_read_lock();
-       if (!dumpable && !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
+       if (dumpable != SUID_DUMP_USER &&
+           !ptrace_has_cap(__task_cred(task)->user_ns, mode)) {
                rcu_read_unlock();
                return -EPERM;
        }
-- 
1.7.9.5


-- 
Kees Cook                                            @outflux.net

----- End forwarded message -----


Current thread: