Commit a78282e2 authored by Linus Torvalds's avatar Linus Torvalds

Revert "binfmt_elf, coredump: Log the reason of the failed core dumps"

This reverts commit fb97d2eb.

The logging was questionable to begin with, but it seems to actively
deadlock on the task lock.

 "On second thought, let's not log core dump failures. 'Tis a silly place"

because if you can't tell your core dump is truncated, maybe you should
just fix your debugger instead of adding bugs to the kernel.
Reported-by: default avatarVegard Nossum <vegard.nossum@oracle.com>
Link: https://lore.kernel.org/all/d122ece6-3606-49de-ae4d-8da88846bef2@oracle.com/Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 62a0e2fa
...@@ -2032,10 +2032,8 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2032,10 +2032,8 @@ static int elf_core_dump(struct coredump_params *cprm)
* Collect all the non-memory information about the process for the * Collect all the non-memory information about the process for the
* notes. This also sets up the file header. * notes. This also sets up the file header.
*/ */
if (!fill_note_info(&elf, e_phnum, &info, cprm)) { if (!fill_note_info(&elf, e_phnum, &info, cprm))
coredump_report_failure("Error collecting note info");
goto end_coredump; goto end_coredump;
}
has_dumped = 1; has_dumped = 1;
...@@ -2050,10 +2048,8 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2050,10 +2048,8 @@ static int elf_core_dump(struct coredump_params *cprm)
sz += elf_coredump_extra_notes_size(); sz += elf_coredump_extra_notes_size();
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL); phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
if (!phdr4note) { if (!phdr4note)
coredump_report_failure("Error allocating program headers note entry");
goto end_coredump; goto end_coredump;
}
fill_elf_note_phdr(phdr4note, sz, offset); fill_elf_note_phdr(phdr4note, sz, offset);
offset += sz; offset += sz;
...@@ -2067,24 +2063,18 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2067,24 +2063,18 @@ static int elf_core_dump(struct coredump_params *cprm)
if (e_phnum == PN_XNUM) { if (e_phnum == PN_XNUM) {
shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL); shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
if (!shdr4extnum) { if (!shdr4extnum)
coredump_report_failure("Error allocating extra program headers");
goto end_coredump; goto end_coredump;
}
fill_extnum_info(&elf, shdr4extnum, e_shoff, segs); fill_extnum_info(&elf, shdr4extnum, e_shoff, segs);
} }
offset = dataoff; offset = dataoff;
if (!dump_emit(cprm, &elf, sizeof(elf))) { if (!dump_emit(cprm, &elf, sizeof(elf)))
coredump_report_failure("Error emitting the ELF headers");
goto end_coredump; goto end_coredump;
}
if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note))) { if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note)))
coredump_report_failure("Error emitting the program header for notes");
goto end_coredump; goto end_coredump;
}
/* Write program headers for segments dump */ /* Write program headers for segments dump */
for (i = 0; i < cprm->vma_count; i++) { for (i = 0; i < cprm->vma_count; i++) {
...@@ -2107,28 +2097,20 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2107,28 +2097,20 @@ static int elf_core_dump(struct coredump_params *cprm)
phdr.p_flags |= PF_X; phdr.p_flags |= PF_X;
phdr.p_align = ELF_EXEC_PAGESIZE; phdr.p_align = ELF_EXEC_PAGESIZE;
if (!dump_emit(cprm, &phdr, sizeof(phdr))) { if (!dump_emit(cprm, &phdr, sizeof(phdr)))
coredump_report_failure("Error emitting program headers");
goto end_coredump; goto end_coredump;
}
} }
if (!elf_core_write_extra_phdrs(cprm, offset)) { if (!elf_core_write_extra_phdrs(cprm, offset))
coredump_report_failure("Error writing out extra program headers");
goto end_coredump; goto end_coredump;
}
/* write out the notes section */ /* write out the notes section */
if (!write_note_info(&info, cprm)) { if (!write_note_info(&info, cprm))
coredump_report_failure("Error writing out notes");
goto end_coredump; goto end_coredump;
}
/* For cell spufs and x86 xstate */ /* For cell spufs and x86 xstate */
if (elf_coredump_extra_notes_write(cprm)) { if (elf_coredump_extra_notes_write(cprm))
coredump_report_failure("Error writing out extra notes");
goto end_coredump; goto end_coredump;
}
/* Align to page */ /* Align to page */
dump_skip_to(cprm, dataoff); dump_skip_to(cprm, dataoff);
...@@ -2136,22 +2118,16 @@ static int elf_core_dump(struct coredump_params *cprm) ...@@ -2136,22 +2118,16 @@ static int elf_core_dump(struct coredump_params *cprm)
for (i = 0; i < cprm->vma_count; i++) { for (i = 0; i < cprm->vma_count; i++) {
struct core_vma_metadata *meta = cprm->vma_meta + i; struct core_vma_metadata *meta = cprm->vma_meta + i;
if (!dump_user_range(cprm, meta->start, meta->dump_size)) { if (!dump_user_range(cprm, meta->start, meta->dump_size))
coredump_report_failure("Error writing out the process memory");
goto end_coredump; goto end_coredump;
}
} }
if (!elf_core_write_extra_data(cprm)) { if (!elf_core_write_extra_data(cprm))
coredump_report_failure("Error writing out extra data");
goto end_coredump; goto end_coredump;
}
if (e_phnum == PN_XNUM) { if (e_phnum == PN_XNUM) {
if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum))) { if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum)))
coredump_report_failure("Error emitting extra program headers");
goto end_coredump; goto end_coredump;
}
} }
end_coredump: end_coredump:
......
...@@ -465,17 +465,7 @@ static bool dump_interrupted(void) ...@@ -465,17 +465,7 @@ static bool dump_interrupted(void)
* but then we need to teach dump_write() to restart and clear * but then we need to teach dump_write() to restart and clear
* TIF_SIGPENDING. * TIF_SIGPENDING.
*/ */
if (fatal_signal_pending(current)) { return fatal_signal_pending(current) || freezing(current);
coredump_report_failure("interrupted: fatal signal pending");
return true;
}
if (freezing(current)) {
coredump_report_failure("interrupted: freezing");
return true;
}
return false;
} }
static void wait_for_dump_helpers(struct file *file) static void wait_for_dump_helpers(struct file *file)
...@@ -530,7 +520,7 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new) ...@@ -530,7 +520,7 @@ static int umh_pipe_setup(struct subprocess_info *info, struct cred *new)
return err; return err;
} }
int do_coredump(const kernel_siginfo_t *siginfo) void do_coredump(const kernel_siginfo_t *siginfo)
{ {
struct core_state core_state; struct core_state core_state;
struct core_name cn; struct core_name cn;
...@@ -538,7 +528,7 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -538,7 +528,7 @@ int do_coredump(const kernel_siginfo_t *siginfo)
struct linux_binfmt * binfmt; struct linux_binfmt * binfmt;
const struct cred *old_cred; const struct cred *old_cred;
struct cred *cred; struct cred *cred;
int retval; int retval = 0;
int ispipe; int ispipe;
size_t *argv = NULL; size_t *argv = NULL;
int argc = 0; int argc = 0;
...@@ -562,20 +552,14 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -562,20 +552,14 @@ int do_coredump(const kernel_siginfo_t *siginfo)
audit_core_dumps(siginfo->si_signo); audit_core_dumps(siginfo->si_signo);
binfmt = mm->binfmt; binfmt = mm->binfmt;
if (!binfmt || !binfmt->core_dump) { if (!binfmt || !binfmt->core_dump)
retval = -ENOEXEC;
goto fail; goto fail;
} if (!__get_dumpable(cprm.mm_flags))
if (!__get_dumpable(cprm.mm_flags)) {
retval = -EACCES;
goto fail; goto fail;
}
cred = prepare_creds(); cred = prepare_creds();
if (!cred) { if (!cred)
retval = -EPERM;
goto fail; goto fail;
}
/* /*
* We cannot trust fsuid as being the "true" uid of the process * 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 * nor do we know its entire history. We only know it was tainted
...@@ -604,7 +588,6 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -604,7 +588,6 @@ int do_coredump(const kernel_siginfo_t *siginfo)
if (ispipe < 0) { if (ispipe < 0) {
coredump_report_failure("format_corename failed, aborting core"); coredump_report_failure("format_corename failed, aborting core");
retval = ispipe;
goto fail_unlock; goto fail_unlock;
} }
...@@ -625,7 +608,6 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -625,7 +608,6 @@ int do_coredump(const kernel_siginfo_t *siginfo)
* core_pattern process dies. * core_pattern process dies.
*/ */
coredump_report_failure("RLIMIT_CORE is set to 1, aborting core"); coredump_report_failure("RLIMIT_CORE is set to 1, aborting core");
retval = -EPERM;
goto fail_unlock; goto fail_unlock;
} }
cprm.limit = RLIM_INFINITY; cprm.limit = RLIM_INFINITY;
...@@ -633,7 +615,6 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -633,7 +615,6 @@ int do_coredump(const kernel_siginfo_t *siginfo)
dump_count = atomic_inc_return(&core_dump_count); dump_count = atomic_inc_return(&core_dump_count);
if (core_pipe_limit && (core_pipe_limit < dump_count)) { if (core_pipe_limit && (core_pipe_limit < dump_count)) {
coredump_report_failure("over core_pipe_limit, skipping core dump"); coredump_report_failure("over core_pipe_limit, skipping core dump");
retval = -E2BIG;
goto fail_dropcount; goto fail_dropcount;
} }
...@@ -641,7 +622,6 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -641,7 +622,6 @@ int do_coredump(const kernel_siginfo_t *siginfo)
GFP_KERNEL); GFP_KERNEL);
if (!helper_argv) { if (!helper_argv) {
coredump_report_failure("%s failed to allocate memory", __func__); coredump_report_failure("%s failed to allocate memory", __func__);
retval = -ENOMEM;
goto fail_dropcount; goto fail_dropcount;
} }
for (argi = 0; argi < argc; argi++) for (argi = 0; argi < argc; argi++)
...@@ -667,16 +647,12 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -667,16 +647,12 @@ int do_coredump(const kernel_siginfo_t *siginfo)
int open_flags = O_CREAT | O_WRONLY | O_NOFOLLOW | int open_flags = O_CREAT | O_WRONLY | O_NOFOLLOW |
O_LARGEFILE | O_EXCL; O_LARGEFILE | O_EXCL;
if (cprm.limit < binfmt->min_coredump) { if (cprm.limit < binfmt->min_coredump)
coredump_report_failure("over coredump resource limit, skipping core dump");
retval = -E2BIG;
goto fail_unlock; goto fail_unlock;
}
if (need_suid_safe && cn.corename[0] != '/') { if (need_suid_safe && cn.corename[0] != '/') {
coredump_report_failure( coredump_report_failure(
"this process can only dump core to a fully qualified path, skipping core dump"); "this process can only dump core to a fully qualified path, skipping core dump");
retval = -EPERM;
goto fail_unlock; goto fail_unlock;
} }
...@@ -722,28 +698,20 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -722,28 +698,20 @@ int do_coredump(const kernel_siginfo_t *siginfo)
} else { } else {
cprm.file = filp_open(cn.corename, open_flags, 0600); cprm.file = filp_open(cn.corename, open_flags, 0600);
} }
if (IS_ERR(cprm.file)) { if (IS_ERR(cprm.file))
retval = PTR_ERR(cprm.file);
goto fail_unlock; goto fail_unlock;
}
inode = file_inode(cprm.file); inode = file_inode(cprm.file);
if (inode->i_nlink > 1) { if (inode->i_nlink > 1)
retval = -EMLINK;
goto close_fail; goto close_fail;
} if (d_unhashed(cprm.file->f_path.dentry))
if (d_unhashed(cprm.file->f_path.dentry)) {
retval = -EEXIST;
goto close_fail; goto close_fail;
}
/* /*
* AK: actually i see no reason to not allow this for named * AK: actually i see no reason to not allow this for named
* pipes etc, but keep the previous behaviour for now. * pipes etc, but keep the previous behaviour for now.
*/ */
if (!S_ISREG(inode->i_mode)) { if (!S_ISREG(inode->i_mode))
retval = -EISDIR;
goto close_fail; goto close_fail;
}
/* /*
* Don't dump core if the filesystem changed owner or mode * Don't dump core if the filesystem changed owner or mode
* of the file during file creation. This is an issue when * of the file during file creation. This is an issue when
...@@ -755,22 +723,17 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -755,22 +723,17 @@ int do_coredump(const kernel_siginfo_t *siginfo)
current_fsuid())) { current_fsuid())) {
coredump_report_failure("Core dump to %s aborted: " coredump_report_failure("Core dump to %s aborted: "
"cannot preserve file owner", cn.corename); "cannot preserve file owner", cn.corename);
retval = -EPERM;
goto close_fail; goto close_fail;
} }
if ((inode->i_mode & 0677) != 0600) { if ((inode->i_mode & 0677) != 0600) {
coredump_report_failure("Core dump to %s aborted: " coredump_report_failure("Core dump to %s aborted: "
"cannot preserve file permissions", cn.corename); "cannot preserve file permissions", cn.corename);
retval = -EPERM;
goto close_fail; goto close_fail;
} }
if (!(cprm.file->f_mode & FMODE_CAN_WRITE)) { if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
retval = -EACCES;
goto close_fail; goto close_fail;
} if (do_truncate(idmap, cprm.file->f_path.dentry,
retval = do_truncate(idmap, cprm.file->f_path.dentry, 0, 0, cprm.file))
0, 0, cprm.file);
if (retval)
goto close_fail; goto close_fail;
} }
...@@ -786,15 +749,10 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -786,15 +749,10 @@ int do_coredump(const kernel_siginfo_t *siginfo)
*/ */
if (!cprm.file) { if (!cprm.file) {
coredump_report_failure("Core dump to |%s disabled", cn.corename); coredump_report_failure("Core dump to |%s disabled", cn.corename);
retval = -EPERM;
goto close_fail; goto close_fail;
} }
if (!dump_vma_snapshot(&cprm)) { if (!dump_vma_snapshot(&cprm))
coredump_report_failure("Can't get VMA snapshot for core dump |%s",
cn.corename);
retval = -EACCES;
goto close_fail; goto close_fail;
}
file_start_write(cprm.file); file_start_write(cprm.file);
core_dumped = binfmt->core_dump(&cprm); core_dumped = binfmt->core_dump(&cprm);
...@@ -810,21 +768,9 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -810,21 +768,9 @@ int do_coredump(const kernel_siginfo_t *siginfo)
} }
file_end_write(cprm.file); file_end_write(cprm.file);
free_vma_snapshot(&cprm); free_vma_snapshot(&cprm);
} else {
coredump_report_failure("Core dump to %s%s has been interrupted",
ispipe ? "|" : "", cn.corename);
retval = -EAGAIN;
goto fail;
} }
coredump_report(
"written to %s%s: VMAs: %d, size %zu; core: %lld bytes, pos %lld",
ispipe ? "|" : "", cn.corename,
cprm.vma_count, cprm.vma_data_size, cprm.written, cprm.pos);
if (ispipe && core_pipe_limit) if (ispipe && core_pipe_limit)
wait_for_dump_helpers(cprm.file); wait_for_dump_helpers(cprm.file);
retval = 0;
close_fail: close_fail:
if (cprm.file) if (cprm.file)
filp_close(cprm.file, NULL); filp_close(cprm.file, NULL);
...@@ -839,7 +785,7 @@ int do_coredump(const kernel_siginfo_t *siginfo) ...@@ -839,7 +785,7 @@ int do_coredump(const kernel_siginfo_t *siginfo)
fail_creds: fail_creds:
put_cred(cred); put_cred(cred);
fail: fail:
return retval; return;
} }
/* /*
...@@ -859,16 +805,8 @@ static int __dump_emit(struct coredump_params *cprm, const void *addr, int nr) ...@@ -859,16 +805,8 @@ static int __dump_emit(struct coredump_params *cprm, const void *addr, int nr)
if (dump_interrupted()) if (dump_interrupted())
return 0; return 0;
n = __kernel_write(file, addr, nr, &pos); n = __kernel_write(file, addr, nr, &pos);
if (n != nr) { if (n != nr)
if (n < 0)
coredump_report_failure("failed when writing out, error %zd", n);
else
coredump_report_failure(
"partially written out, only %zd(of %d) bytes written",
n, nr);
return 0; return 0;
}
file->f_pos = pos; file->f_pos = pos;
cprm->written += n; cprm->written += n;
cprm->pos += n; cprm->pos += n;
...@@ -881,16 +819,9 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr) ...@@ -881,16 +819,9 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr)
static char zeroes[PAGE_SIZE]; static char zeroes[PAGE_SIZE];
struct file *file = cprm->file; struct file *file = cprm->file;
if (file->f_mode & FMODE_LSEEK) { if (file->f_mode & FMODE_LSEEK) {
int ret; if (dump_interrupted() ||
vfs_llseek(file, nr, SEEK_CUR) < 0)
if (dump_interrupted())
return 0; return 0;
ret = vfs_llseek(file, nr, SEEK_CUR);
if (ret < 0) {
coredump_report_failure("failed when seeking, error %d", ret);
return 0;
}
cprm->pos += nr; cprm->pos += nr;
return 1; return 1;
} else { } else {
......
...@@ -42,7 +42,7 @@ extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); ...@@ -42,7 +42,7 @@ extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr);
extern int dump_align(struct coredump_params *cprm, int align); extern int dump_align(struct coredump_params *cprm, int align);
int dump_user_range(struct coredump_params *cprm, unsigned long start, int dump_user_range(struct coredump_params *cprm, unsigned long start,
unsigned long len); unsigned long len);
extern int do_coredump(const kernel_siginfo_t *siginfo); extern void do_coredump(const kernel_siginfo_t *siginfo);
/* /*
* Logging for the coredump code, ratelimited. * Logging for the coredump code, ratelimited.
...@@ -62,11 +62,7 @@ extern int do_coredump(const kernel_siginfo_t *siginfo); ...@@ -62,11 +62,7 @@ extern int do_coredump(const kernel_siginfo_t *siginfo);
#define coredump_report_failure(fmt, ...) __COREDUMP_PRINTK(KERN_WARNING, fmt, ##__VA_ARGS__) #define coredump_report_failure(fmt, ...) __COREDUMP_PRINTK(KERN_WARNING, fmt, ##__VA_ARGS__)
#else #else
static inline int do_coredump(const kernel_siginfo_t *siginfo) static inline void do_coredump(const kernel_siginfo_t *siginfo) {}
{
/* Coredump support is not available, can't fail. */
return 0;
}
#define coredump_report(...) #define coredump_report(...)
#define coredump_report_failure(...) #define coredump_report_failure(...)
......
...@@ -2888,8 +2888,6 @@ bool get_signal(struct ksignal *ksig) ...@@ -2888,8 +2888,6 @@ bool get_signal(struct ksignal *ksig)
current->flags |= PF_SIGNALED; current->flags |= PF_SIGNALED;
if (sig_kernel_coredump(signr)) { if (sig_kernel_coredump(signr)) {
int ret;
if (print_fatal_signals) if (print_fatal_signals)
print_fatal_signal(signr); print_fatal_signal(signr);
proc_coredump_connector(current); proc_coredump_connector(current);
...@@ -2901,24 +2899,7 @@ bool get_signal(struct ksignal *ksig) ...@@ -2901,24 +2899,7 @@ bool get_signal(struct ksignal *ksig)
* first and our do_group_exit call below will use * first and our do_group_exit call below will use
* that value and ignore the one we pass it. * that value and ignore the one we pass it.
*/ */
ret = do_coredump(&ksig->info); do_coredump(&ksig->info);
if (ret)
coredump_report_failure("coredump has not been created, error %d",
ret);
else if (!IS_ENABLED(CONFIG_COREDUMP)) {
/*
* Coredumps are not available, can't fail collecting
* the coredump.
*
* Leave a note though that the coredump is going to be
* not created. This is not an error or a warning as disabling
* support in the kernel for coredumps isn't commonplace, and
* the user must've built the kernel with the custom config so
* let them know all works as desired.
*/
coredump_report("no coredump collected as "
"that is disabled in the kernel configuration");
}
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment