Skip to content

Commit 65405bf

Browse files
keeswtarreau
authored andcommitted
exec/ptrace: fix get_dumpable() incorrect tests
commit d049f74 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 <[email protected]> Signed-off-by: Kees Cook <[email protected]> Cc: Tony Luck <[email protected]> Cc: Oleg Nesterov <[email protected]> Cc: "Eric W. Biederman" <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]> [dannf: backported to Debian's 2.6.32] Signed-off-by: Willy Tarreau <[email protected]>
1 parent a14cc8a commit 65405bf

File tree

5 files changed

+12
-5
lines changed

5 files changed

+12
-5
lines changed

arch/ia64/include/asm/processor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ struct thread_struct {
361361
regs->loadrs = 0; \
362362
regs->r8 = get_dumpable(current->mm); /* set "don't zap registers" flag */ \
363363
regs->r12 = new_sp - 16; /* allocate 16 byte scratch area */ \
364-
if (unlikely(!get_dumpable(current->mm))) { \
364+
if (unlikely(get_dumpable(current->mm) != SUID_DUMP_USER)) { \
365365
/* \
366366
* Zap scratch regs to avoid leaking bits between processes with different \
367367
* uid/privileges. \

fs/exec.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1793,6 +1793,12 @@ void set_dumpable(struct mm_struct *mm, int value)
17931793
}
17941794
}
17951795

1796+
/*
1797+
* This returns the actual value of the suid_dumpable flag. For things
1798+
* that are using this for checking for privilege transitions, it must
1799+
* test against SUID_DUMP_USER rather than treating it as a boolean
1800+
* value.
1801+
*/
17961802
int get_dumpable(struct mm_struct *mm)
17971803
{
17981804
int ret;

include/linux/binfmts.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,6 @@ extern int flush_old_exec(struct linux_binprm * bprm);
107107
extern void setup_new_exec(struct linux_binprm * bprm);
108108

109109
extern int suid_dumpable;
110-
#define SUID_DUMP_DISABLE 0 /* No setuid dumping */
111-
#define SUID_DUMP_USER 1 /* Dump as user of process */
112-
#define SUID_DUMP_ROOT 2 /* Dump as root */
113110

114111
/* Stack area protections */
115112
#define EXSTACK_DEFAULT 0 /* Whatever the arch defaults to */

include/linux/sched.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,10 @@ static inline unsigned long get_mm_hiwater_vm(struct mm_struct *mm)
442442
extern void set_dumpable(struct mm_struct *mm, int value);
443443
extern int get_dumpable(struct mm_struct *mm);
444444

445+
#define SUID_DUMP_DISABLE 0 /* No setuid dumping */
446+
#define SUID_DUMP_USER 1 /* Dump as user of process */
447+
#define SUID_DUMP_ROOT 2 /* Dump as root */
448+
445449
/* mm flags */
446450
/* dumpable bits */
447451
#define MMF_DUMPABLE 0 /* core dump is permitted */

kernel/ptrace.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
187187
smp_rmb();
188188
if (task->mm)
189189
dumpable = get_dumpable(task->mm);
190-
if (!dumpable && !capable(CAP_SYS_PTRACE))
190+
if (dumpable != SUID_DUMP_USER && !capable(CAP_SYS_PTRACE))
191191
return -EPERM;
192192

193193
return security_ptrace_access_check(task, mode);

0 commit comments

Comments
 (0)