提交 54b50199 编写于 作者: K Kees Cook 提交者: Linus Torvalds

coredump: warn about unsafe suid_dumpable / core_pattern combo

When suid_dumpable=2, detect unsafe core_pattern settings and warn when
they are seen.
Signed-off-by: NKees Cook <keescook@chromium.org>
Suggested-by: NAndrew Morton <akpm@linux-foundation.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: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 9520628e
...@@ -2002,17 +2002,17 @@ static void coredump_finish(struct mm_struct *mm) ...@@ -2002,17 +2002,17 @@ static void coredump_finish(struct mm_struct *mm)
void set_dumpable(struct mm_struct *mm, int value) void set_dumpable(struct mm_struct *mm, int value)
{ {
switch (value) { switch (value) {
case 0: case SUID_DUMPABLE_DISABLED:
clear_bit(MMF_DUMPABLE, &mm->flags); clear_bit(MMF_DUMPABLE, &mm->flags);
smp_wmb(); smp_wmb();
clear_bit(MMF_DUMP_SECURELY, &mm->flags); clear_bit(MMF_DUMP_SECURELY, &mm->flags);
break; break;
case 1: case SUID_DUMPABLE_ENABLED:
set_bit(MMF_DUMPABLE, &mm->flags); set_bit(MMF_DUMPABLE, &mm->flags);
smp_wmb(); smp_wmb();
clear_bit(MMF_DUMP_SECURELY, &mm->flags); clear_bit(MMF_DUMP_SECURELY, &mm->flags);
break; break;
case 2: case SUID_DUMPABLE_SAFE:
set_bit(MMF_DUMP_SECURELY, &mm->flags); set_bit(MMF_DUMP_SECURELY, &mm->flags);
smp_wmb(); smp_wmb();
set_bit(MMF_DUMPABLE, &mm->flags); set_bit(MMF_DUMPABLE, &mm->flags);
...@@ -2025,7 +2025,7 @@ static int __get_dumpable(unsigned long mm_flags) ...@@ -2025,7 +2025,7 @@ static int __get_dumpable(unsigned long mm_flags)
int ret; int ret;
ret = mm_flags & MMF_DUMPABLE_MASK; ret = mm_flags & MMF_DUMPABLE_MASK;
return (ret >= 2) ? 2 : ret; return (ret > SUID_DUMPABLE_ENABLED) ? SUID_DUMPABLE_SAFE : ret;
} }
int get_dumpable(struct mm_struct *mm) int get_dumpable(struct mm_struct *mm)
...@@ -2142,7 +2142,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs) ...@@ -2142,7 +2142,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
* so we dump it as root in mode 2, and only into a controlled * so we dump it as root in mode 2, and only into a controlled
* environment (pipe handler or fully qualified path). * environment (pipe handler or fully qualified path).
*/ */
if (__get_dumpable(cprm.mm_flags) == 2) { if (__get_dumpable(cprm.mm_flags) == SUID_DUMPABLE_SAFE) {
/* Setuid core dump mode */ /* Setuid core dump mode */
flag = O_EXCL; /* Stop rewrite attacks */ flag = O_EXCL; /* Stop rewrite attacks */
cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */ cred->fsuid = GLOBAL_ROOT_UID; /* Dump root private */
......
...@@ -406,6 +406,11 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm) {} ...@@ -406,6 +406,11 @@ static inline void arch_pick_mmap_layout(struct mm_struct *mm) {}
extern void set_dumpable(struct mm_struct *mm, int value); extern void set_dumpable(struct mm_struct *mm, int value);
extern int get_dumpable(struct mm_struct *mm); extern int get_dumpable(struct mm_struct *mm);
/* get/set_dumpable() values */
#define SUID_DUMPABLE_DISABLED 0
#define SUID_DUMPABLE_ENABLED 1
#define SUID_DUMPABLE_SAFE 2
/* mm flags */ /* mm flags */
/* dumpable bits */ /* dumpable bits */
#define MMF_DUMPABLE 0 /* core dump is permitted */ #define MMF_DUMPABLE 0 /* core dump is permitted */
......
...@@ -174,6 +174,11 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write, ...@@ -174,6 +174,11 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos); void __user *buffer, size_t *lenp, loff_t *ppos);
#endif #endif
static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);
static int proc_dostring_coredump(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos);
#ifdef CONFIG_MAGIC_SYSRQ #ifdef CONFIG_MAGIC_SYSRQ
/* Note: sysrq code uses it's own private copy */ /* Note: sysrq code uses it's own private copy */
static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE; static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE;
...@@ -410,7 +415,7 @@ static struct ctl_table kern_table[] = { ...@@ -410,7 +415,7 @@ static struct ctl_table kern_table[] = {
.data = core_pattern, .data = core_pattern,
.maxlen = CORENAME_MAX_SIZE, .maxlen = CORENAME_MAX_SIZE,
.mode = 0644, .mode = 0644,
.proc_handler = proc_dostring, .proc_handler = proc_dostring_coredump,
}, },
{ {
.procname = "core_pipe_limit", .procname = "core_pipe_limit",
...@@ -1498,7 +1503,7 @@ static struct ctl_table fs_table[] = { ...@@ -1498,7 +1503,7 @@ static struct ctl_table fs_table[] = {
.data = &suid_dumpable, .data = &suid_dumpable,
.maxlen = sizeof(int), .maxlen = sizeof(int),
.mode = 0644, .mode = 0644,
.proc_handler = proc_dointvec_minmax, .proc_handler = proc_dointvec_minmax_coredump,
.extra1 = &zero, .extra1 = &zero,
.extra2 = &two, .extra2 = &two,
}, },
...@@ -2009,6 +2014,34 @@ int proc_dointvec_minmax(struct ctl_table *table, int write, ...@@ -2009,6 +2014,34 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
do_proc_dointvec_minmax_conv, &param); do_proc_dointvec_minmax_conv, &param);
} }
static void validate_coredump_safety(void)
{
if (suid_dumpable == SUID_DUMPABLE_SAFE &&
core_pattern[0] != '/' && core_pattern[0] != '|') {
printk(KERN_WARNING "Unsafe core_pattern used with "\
"suid_dumpable=2. Pipe handler or fully qualified "\
"core dump path required.\n");
}
}
static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
if (!error)
validate_coredump_safety();
return error;
}
static int proc_dostring_coredump(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
int error = proc_dostring(table, write, buffer, lenp, ppos);
if (!error)
validate_coredump_safety();
return error;
}
static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write, static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,
void __user *buffer, void __user *buffer,
size_t *lenp, loff_t *ppos, size_t *lenp, loff_t *ppos,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册