From 2a143fbbca925da44c11c317a108db4ff32b59d9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 26 Nov 2013 09:28:39 -0800 Subject: [PATCH] 3.4-stable patches added patches: exec-ptrace-fix-get_dumpable-incorrect-tests.patch --- ...ace-fix-get_dumpable-incorrect-tests.patch | 116 ++++++++++++++++++ queue-3.4/series | 1 + 2 files changed, 117 insertions(+) create mode 100644 queue-3.4/exec-ptrace-fix-get_dumpable-incorrect-tests.patch diff --git a/queue-3.4/exec-ptrace-fix-get_dumpable-incorrect-tests.patch b/queue-3.4/exec-ptrace-fix-get_dumpable-incorrect-tests.patch new file mode 100644 index 00000000000..d5433bd9367 --- /dev/null +++ b/queue-3.4/exec-ptrace-fix-get_dumpable-incorrect-tests.patch @@ -0,0 +1,116 @@ +From d049f74f2dbe71354d43d393ac3a188947811348 Mon Sep 17 00:00:00 2001 +From: Kees Cook +Date: Tue, 12 Nov 2013 15:11:17 -0800 +Subject: exec/ptrace: fix get_dumpable() incorrect tests + +From: Kees Cook + +commit d049f74f2dbe71354d43d393ac3a188947811348 upstream. + +The get_dumpable() return value is not boolean. Most users of the +function actually want to be testing for non-SUID_DUMP_USER(1) rather than +SUID_DUMP_DISABLE(0). The SUID_DUMP_ROOT(2) is also considered a +protected state. Almost all places did this correctly, excepting the two +places fixed in this patch. + +Wrong logic: + if (dumpable == SUID_DUMP_DISABLE) { /* be protective */ } + or + if (dumpable == 0) { /* be protective */ } + or + if (!dumpable) { /* be protective */ } + +Correct logic: + if (dumpable != SUID_DUMP_USER) { /* be protective */ } + or + if (dumpable != 1) { /* be protective */ } + +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.) + +The macros have been moved into the file that declares get/set_dumpable(), +which means things like the ia64 code can see them too. + +CVE-2013-2929 + +Reported-by: Vasily Kulikov +Signed-off-by: Kees Cook +Cc: "Luck, Tony" +Cc: Oleg Nesterov +Cc: "Eric W. Biederman" +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + arch/ia64/include/asm/processor.h | 2 +- + fs/exec.c | 6 ++++++ + include/linux/binfmts.h | 3 --- + include/linux/sched.h | 4 ++++ + kernel/ptrace.c | 3 ++- + 5 files changed, 13 insertions(+), 5 deletions(-) + +--- a/arch/ia64/include/asm/processor.h ++++ b/arch/ia64/include/asm/processor.h +@@ -322,7 +322,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) != SUID_DUMP_USER)) { \ + /* \ + * Zap scratch regs to avoid leaking bits between processes with different \ + * uid/privileges. \ +--- a/fs/exec.c ++++ b/fs/exec.c +@@ -2027,6 +2027,12 @@ static int __get_dumpable(unsigned long + return (ret >= 2) ? 2 : 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); +--- a/include/linux/binfmts.h ++++ b/include/linux/binfmts.h +@@ -113,9 +113,6 @@ extern void setup_new_exec(struct linux_ + extern void would_dump(struct linux_binprm *, struct file *); + + extern int suid_dumpable; +-#define SUID_DUMP_DISABLE 0 /* No setuid dumping */ +-#define SUID_DUMP_USER 1 /* Dump as user of process */ +-#define SUID_DUMP_ROOT 2 /* Dump as root */ + + /* Stack area protections */ + #define EXSTACK_DEFAULT 0 /* Whatever the arch defaults to */ +--- a/include/linux/sched.h ++++ b/include/linux/sched.h +@@ -404,6 +404,10 @@ static inline void arch_pick_mmap_layout + extern void set_dumpable(struct mm_struct *mm, int value); + extern int get_dumpable(struct mm_struct *mm); + ++#define SUID_DUMP_DISABLE 0 /* No setuid dumping */ ++#define SUID_DUMP_USER 1 /* Dump as user of process */ ++#define SUID_DUMP_ROOT 2 /* Dump as root */ ++ + /* mm flags */ + /* dumpable bits */ + #define MMF_DUMPABLE 0 /* core dump is permitted */ +--- a/kernel/ptrace.c ++++ b/kernel/ptrace.c +@@ -254,7 +254,8 @@ ok: + smp_rmb(); + if (task->mm) + dumpable = get_dumpable(task->mm); +- if (!dumpable && !ptrace_has_cap(task_user_ns(task), mode)) ++ if (dumpable != SUID_DUMP_USER && ++ !ptrace_has_cap(task_user_ns(task), mode)) + return -EPERM; + + return security_ptrace_access_check(task, mode); diff --git a/queue-3.4/series b/queue-3.4/series index 7a3d2c8a25f..4f77e727089 100644 --- a/queue-3.4/series +++ b/queue-3.4/series @@ -19,3 +19,4 @@ include-linux-fs.h-disable-preempt-when-acquire-i_size_seqcount-write-lock.patch perf-ftrace-fix-paranoid-level-for-enabling-function-tracer.patch rt2x00-check-if-device-is-still-available-on-rt2x00mac_flush.patch revert-ima-policy-for-ramfs.patch +exec-ptrace-fix-get_dumpable-incorrect-tests.patch -- 2.47.3