fs: make dumpable=2 require fully qualified path
When the suid_dumpable sysctl is set to "2", and there is no core dump pipe defined in the core_pattern sysctl, a local user can cause core files to be written to root-writable directories, potentially with user-controlled content. This means an admin can unknowningly reintroduce a variation of CVE-2006-2451, allowing local users to gain root privileges. $ cat /proc/sys/fs/suid_dumpable 2 $ cat /proc/sys/kernel/core_pattern core $ ulimit -c unlimited $ cd / $ ls -l core ls: cannot access core: No such file or directory $ touch core touch: cannot touch `core': Permission denied $ OHAI="evil-string-here" ping localhost >/dev/null 2>&1 & $ pid=$! $ sleep 1 $ kill -SEGV $pid $ ls -l core -rw------- 1 root kees 458752 Jun 21 11:35 core $ sudo strings core | grep evil OHAI=evil-string-here While cron has been fixed to abort reading a file when there is any parse error, there are still other sensitive directories that will read any file present and skip unparsable lines. Instead of introducing a suid_dumpable=3 mode and breaking all users of mode 2, this only disables the unsafe portion of mode 2 (writing to disk via relative path). Most users of mode 2 (e.g. Chrome OS) already use a core dump pipe handler, so this change will not break them. For the situations where a pipe handler is not defined but mode 2 is still active, crash dumps will only be written to fully qualified paths. If a relative path is defined (e.g. the default "core" pattern), dump attempts will trigger a printk yelling about the lack of a fully qualified path. Signed-off-by: Kees Cook <keescook@chromium.org> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Alan Cox <alan@linux.intel.com> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Cc: Doug Ledford <dledford@redhat.com> Cc: Serge Hallyn <serge.hallyn@canonical.com> Cc: James Morris <james.l.morris@oracle.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:

committed by
Linus Torvalds

parent
779302e678
commit
9520628e8c
17
fs/exec.c
17
fs/exec.c
@@ -2111,6 +2111,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
|
||||
int retval = 0;
|
||||
int flag = 0;
|
||||
int ispipe;
|
||||
bool need_nonrelative = false;
|
||||
static atomic_t core_dump_count = ATOMIC_INIT(0);
|
||||
struct coredump_params cprm = {
|
||||
.signr = signr,
|
||||
@@ -2136,14 +2137,16 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
|
||||
if (!cred)
|
||||
goto fail;
|
||||
/*
|
||||
* We cannot trust fsuid as being the "true" uid of the
|
||||
* process nor do we know its entire history. We only know it
|
||||
* was tainted so we dump it as root in mode 2.
|
||||
* We cannot trust fsuid as being the "true" uid of the process
|
||||
* nor do we know its entire history. We only know it was tainted
|
||||
* so we dump it as root in mode 2, and only into a controlled
|
||||
* environment (pipe handler or fully qualified path).
|
||||
*/
|
||||
if (__get_dumpable(cprm.mm_flags) == 2) {
|
||||
/* Setuid core dump mode */
|
||||
flag = O_EXCL; /* Stop rewrite attacks */
|
||||
cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */
|
||||
need_nonrelative = true;
|
||||
}
|
||||
|
||||
retval = coredump_wait(exit_code, &core_state);
|
||||
@@ -2223,6 +2226,14 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
|
||||
if (cprm.limit < binfmt->min_coredump)
|
||||
goto fail_unlock;
|
||||
|
||||
if (need_nonrelative && cn.corename[0] != '/') {
|
||||
printk(KERN_WARNING "Pid %d(%s) can only dump core "\
|
||||
"to fully qualified path!\n",
|
||||
task_tgid_vnr(current), current->comm);
|
||||
printk(KERN_WARNING "Skipping core dump\n");
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
cprm.file = filp_open(cn.corename,
|
||||
O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
|
||||
0600);
|
||||
|
Reference in New Issue
Block a user