Revert "binfmt_elf, coredump: Log the reason of the failed core dumps"
This reverts commit fb97d2eb54
.
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: Vegard Nossum <vegard.nossum@oracle.com>
Link: https://lore.kernel.org/all/d122ece6-3606-49de-ae4d-8da88846bef2@oracle.com/
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
62a0e2fa40
commit
a78282e2c9
@ -2032,10 +2032,8 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
* Collect all the non-memory information about the process for the
|
||||
* notes. This also sets up the file header.
|
||||
*/
|
||||
if (!fill_note_info(&elf, e_phnum, &info, cprm)) {
|
||||
coredump_report_failure("Error collecting note info");
|
||||
if (!fill_note_info(&elf, e_phnum, &info, cprm))
|
||||
goto end_coredump;
|
||||
}
|
||||
|
||||
has_dumped = 1;
|
||||
|
||||
@ -2050,10 +2048,8 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
sz += elf_coredump_extra_notes_size();
|
||||
|
||||
phdr4note = kmalloc(sizeof(*phdr4note), GFP_KERNEL);
|
||||
if (!phdr4note) {
|
||||
coredump_report_failure("Error allocating program headers note entry");
|
||||
if (!phdr4note)
|
||||
goto end_coredump;
|
||||
}
|
||||
|
||||
fill_elf_note_phdr(phdr4note, sz, offset);
|
||||
offset += sz;
|
||||
@ -2067,24 +2063,18 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
|
||||
if (e_phnum == PN_XNUM) {
|
||||
shdr4extnum = kmalloc(sizeof(*shdr4extnum), GFP_KERNEL);
|
||||
if (!shdr4extnum) {
|
||||
coredump_report_failure("Error allocating extra program headers");
|
||||
if (!shdr4extnum)
|
||||
goto end_coredump;
|
||||
}
|
||||
fill_extnum_info(&elf, shdr4extnum, e_shoff, segs);
|
||||
}
|
||||
|
||||
offset = dataoff;
|
||||
|
||||
if (!dump_emit(cprm, &elf, sizeof(elf))) {
|
||||
coredump_report_failure("Error emitting the ELF headers");
|
||||
if (!dump_emit(cprm, &elf, sizeof(elf)))
|
||||
goto end_coredump;
|
||||
}
|
||||
|
||||
if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note))) {
|
||||
coredump_report_failure("Error emitting the program header for notes");
|
||||
if (!dump_emit(cprm, phdr4note, sizeof(*phdr4note)))
|
||||
goto end_coredump;
|
||||
}
|
||||
|
||||
/* Write program headers for segments dump */
|
||||
for (i = 0; i < cprm->vma_count; i++) {
|
||||
@ -2107,28 +2097,20 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
phdr.p_flags |= PF_X;
|
||||
phdr.p_align = ELF_EXEC_PAGESIZE;
|
||||
|
||||
if (!dump_emit(cprm, &phdr, sizeof(phdr))) {
|
||||
coredump_report_failure("Error emitting program headers");
|
||||
if (!dump_emit(cprm, &phdr, sizeof(phdr)))
|
||||
goto end_coredump;
|
||||
}
|
||||
}
|
||||
|
||||
if (!elf_core_write_extra_phdrs(cprm, offset)) {
|
||||
coredump_report_failure("Error writing out extra program headers");
|
||||
if (!elf_core_write_extra_phdrs(cprm, offset))
|
||||
goto end_coredump;
|
||||
}
|
||||
|
||||
/* write out the notes section */
|
||||
if (!write_note_info(&info, cprm)) {
|
||||
coredump_report_failure("Error writing out notes");
|
||||
if (!write_note_info(&info, cprm))
|
||||
goto end_coredump;
|
||||
}
|
||||
|
||||
/* For cell spufs and x86 xstate */
|
||||
if (elf_coredump_extra_notes_write(cprm)) {
|
||||
coredump_report_failure("Error writing out extra notes");
|
||||
if (elf_coredump_extra_notes_write(cprm))
|
||||
goto end_coredump;
|
||||
}
|
||||
|
||||
/* Align to page */
|
||||
dump_skip_to(cprm, dataoff);
|
||||
@ -2136,22 +2118,16 @@ static int elf_core_dump(struct coredump_params *cprm)
|
||||
for (i = 0; i < cprm->vma_count; i++) {
|
||||
struct core_vma_metadata *meta = cprm->vma_meta + i;
|
||||
|
||||
if (!dump_user_range(cprm, meta->start, meta->dump_size)) {
|
||||
coredump_report_failure("Error writing out the process memory");
|
||||
if (!dump_user_range(cprm, meta->start, meta->dump_size))
|
||||
goto end_coredump;
|
||||
}
|
||||
}
|
||||
|
||||
if (!elf_core_write_extra_data(cprm)) {
|
||||
coredump_report_failure("Error writing out extra data");
|
||||
if (!elf_core_write_extra_data(cprm))
|
||||
goto end_coredump;
|
||||
}
|
||||
|
||||
if (e_phnum == PN_XNUM) {
|
||||
if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum))) {
|
||||
coredump_report_failure("Error emitting extra program headers");
|
||||
if (!dump_emit(cprm, shdr4extnum, sizeof(*shdr4extnum)))
|
||||
goto end_coredump;
|
||||
}
|
||||
}
|
||||
|
||||
end_coredump:
|
||||
|
107
fs/coredump.c
107
fs/coredump.c
@ -465,17 +465,7 @@ static bool dump_interrupted(void)
|
||||
* but then we need to teach dump_write() to restart and clear
|
||||
* TIF_SIGPENDING.
|
||||
*/
|
||||
if (fatal_signal_pending(current)) {
|
||||
coredump_report_failure("interrupted: fatal signal pending");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (freezing(current)) {
|
||||
coredump_report_failure("interrupted: freezing");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return fatal_signal_pending(current) || freezing(current);
|
||||
}
|
||||
|
||||
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)
|
||||
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_name cn;
|
||||
@ -538,7 +528,7 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
struct linux_binfmt * binfmt;
|
||||
const struct cred *old_cred;
|
||||
struct cred *cred;
|
||||
int retval;
|
||||
int retval = 0;
|
||||
int ispipe;
|
||||
size_t *argv = NULL;
|
||||
int argc = 0;
|
||||
@ -562,20 +552,14 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
audit_core_dumps(siginfo->si_signo);
|
||||
|
||||
binfmt = mm->binfmt;
|
||||
if (!binfmt || !binfmt->core_dump) {
|
||||
retval = -ENOEXEC;
|
||||
if (!binfmt || !binfmt->core_dump)
|
||||
goto fail;
|
||||
}
|
||||
if (!__get_dumpable(cprm.mm_flags)) {
|
||||
retval = -EACCES;
|
||||
if (!__get_dumpable(cprm.mm_flags))
|
||||
goto fail;
|
||||
}
|
||||
|
||||
cred = prepare_creds();
|
||||
if (!cred) {
|
||||
retval = -EPERM;
|
||||
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
|
||||
@ -604,7 +588,6 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
|
||||
if (ispipe < 0) {
|
||||
coredump_report_failure("format_corename failed, aborting core");
|
||||
retval = ispipe;
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
@ -625,7 +608,6 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
* core_pattern process dies.
|
||||
*/
|
||||
coredump_report_failure("RLIMIT_CORE is set to 1, aborting core");
|
||||
retval = -EPERM;
|
||||
goto fail_unlock;
|
||||
}
|
||||
cprm.limit = RLIM_INFINITY;
|
||||
@ -633,7 +615,6 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
dump_count = atomic_inc_return(&core_dump_count);
|
||||
if (core_pipe_limit && (core_pipe_limit < dump_count)) {
|
||||
coredump_report_failure("over core_pipe_limit, skipping core dump");
|
||||
retval = -E2BIG;
|
||||
goto fail_dropcount;
|
||||
}
|
||||
|
||||
@ -641,7 +622,6 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
GFP_KERNEL);
|
||||
if (!helper_argv) {
|
||||
coredump_report_failure("%s failed to allocate memory", __func__);
|
||||
retval = -ENOMEM;
|
||||
goto fail_dropcount;
|
||||
}
|
||||
for (argi = 0; argi < argc; argi++)
|
||||
@ -667,16 +647,12 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
int open_flags = O_CREAT | O_WRONLY | O_NOFOLLOW |
|
||||
O_LARGEFILE | O_EXCL;
|
||||
|
||||
if (cprm.limit < binfmt->min_coredump) {
|
||||
coredump_report_failure("over coredump resource limit, skipping core dump");
|
||||
retval = -E2BIG;
|
||||
if (cprm.limit < binfmt->min_coredump)
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
if (need_suid_safe && cn.corename[0] != '/') {
|
||||
coredump_report_failure(
|
||||
"this process can only dump core to a fully qualified path, skipping core dump");
|
||||
retval = -EPERM;
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
@ -722,28 +698,20 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
} else {
|
||||
cprm.file = filp_open(cn.corename, open_flags, 0600);
|
||||
}
|
||||
if (IS_ERR(cprm.file)) {
|
||||
retval = PTR_ERR(cprm.file);
|
||||
if (IS_ERR(cprm.file))
|
||||
goto fail_unlock;
|
||||
}
|
||||
|
||||
inode = file_inode(cprm.file);
|
||||
if (inode->i_nlink > 1) {
|
||||
retval = -EMLINK;
|
||||
if (inode->i_nlink > 1)
|
||||
goto close_fail;
|
||||
}
|
||||
if (d_unhashed(cprm.file->f_path.dentry)) {
|
||||
retval = -EEXIST;
|
||||
if (d_unhashed(cprm.file->f_path.dentry))
|
||||
goto close_fail;
|
||||
}
|
||||
/*
|
||||
* AK: actually i see no reason to not allow this for named
|
||||
* pipes etc, but keep the previous behaviour for now.
|
||||
*/
|
||||
if (!S_ISREG(inode->i_mode)) {
|
||||
retval = -EISDIR;
|
||||
if (!S_ISREG(inode->i_mode))
|
||||
goto close_fail;
|
||||
}
|
||||
/*
|
||||
* Don't dump core if the filesystem changed owner or mode
|
||||
* of the file during file creation. This is an issue when
|
||||
@ -755,22 +723,17 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
current_fsuid())) {
|
||||
coredump_report_failure("Core dump to %s aborted: "
|
||||
"cannot preserve file owner", cn.corename);
|
||||
retval = -EPERM;
|
||||
goto close_fail;
|
||||
}
|
||||
if ((inode->i_mode & 0677) != 0600) {
|
||||
coredump_report_failure("Core dump to %s aborted: "
|
||||
"cannot preserve file permissions", cn.corename);
|
||||
retval = -EPERM;
|
||||
goto close_fail;
|
||||
}
|
||||
if (!(cprm.file->f_mode & FMODE_CAN_WRITE)) {
|
||||
retval = -EACCES;
|
||||
if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
|
||||
goto close_fail;
|
||||
}
|
||||
retval = do_truncate(idmap, cprm.file->f_path.dentry,
|
||||
0, 0, cprm.file);
|
||||
if (retval)
|
||||
if (do_truncate(idmap, cprm.file->f_path.dentry,
|
||||
0, 0, cprm.file))
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
@ -786,15 +749,10 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
*/
|
||||
if (!cprm.file) {
|
||||
coredump_report_failure("Core dump to |%s disabled", cn.corename);
|
||||
retval = -EPERM;
|
||||
goto close_fail;
|
||||
}
|
||||
if (!dump_vma_snapshot(&cprm)) {
|
||||
coredump_report_failure("Can't get VMA snapshot for core dump |%s",
|
||||
cn.corename);
|
||||
retval = -EACCES;
|
||||
if (!dump_vma_snapshot(&cprm))
|
||||
goto close_fail;
|
||||
}
|
||||
|
||||
file_start_write(cprm.file);
|
||||
core_dumped = binfmt->core_dump(&cprm);
|
||||
@ -810,21 +768,9 @@ int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
}
|
||||
file_end_write(cprm.file);
|
||||
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)
|
||||
wait_for_dump_helpers(cprm.file);
|
||||
|
||||
retval = 0;
|
||||
|
||||
close_fail:
|
||||
if (cprm.file)
|
||||
filp_close(cprm.file, NULL);
|
||||
@ -839,7 +785,7 @@ fail_unlock:
|
||||
fail_creds:
|
||||
put_cred(cred);
|
||||
fail:
|
||||
return retval;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -859,16 +805,8 @@ static int __dump_emit(struct coredump_params *cprm, const void *addr, int nr)
|
||||
if (dump_interrupted())
|
||||
return 0;
|
||||
n = __kernel_write(file, addr, nr, &pos);
|
||||
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);
|
||||
|
||||
if (n != nr)
|
||||
return 0;
|
||||
}
|
||||
file->f_pos = pos;
|
||||
cprm->written += n;
|
||||
cprm->pos += n;
|
||||
@ -881,16 +819,9 @@ static int __dump_skip(struct coredump_params *cprm, size_t nr)
|
||||
static char zeroes[PAGE_SIZE];
|
||||
struct file *file = cprm->file;
|
||||
if (file->f_mode & FMODE_LSEEK) {
|
||||
int ret;
|
||||
|
||||
if (dump_interrupted())
|
||||
if (dump_interrupted() ||
|
||||
vfs_llseek(file, nr, SEEK_CUR) < 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;
|
||||
return 1;
|
||||
} else {
|
||||
|
@ -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);
|
||||
int dump_user_range(struct coredump_params *cprm, unsigned long start,
|
||||
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.
|
||||
@ -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__)
|
||||
|
||||
#else
|
||||
static inline int do_coredump(const kernel_siginfo_t *siginfo)
|
||||
{
|
||||
/* Coredump support is not available, can't fail. */
|
||||
return 0;
|
||||
}
|
||||
static inline void do_coredump(const kernel_siginfo_t *siginfo) {}
|
||||
|
||||
#define coredump_report(...)
|
||||
#define coredump_report_failure(...)
|
||||
|
@ -2888,8 +2888,6 @@ relock:
|
||||
current->flags |= PF_SIGNALED;
|
||||
|
||||
if (sig_kernel_coredump(signr)) {
|
||||
int ret;
|
||||
|
||||
if (print_fatal_signals)
|
||||
print_fatal_signal(signr);
|
||||
proc_coredump_connector(current);
|
||||
@ -2901,24 +2899,7 @@ relock:
|
||||
* first and our do_group_exit call below will use
|
||||
* that value and ignore the one we pass it.
|
||||
*/
|
||||
ret = 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");
|
||||
}
|
||||
do_coredump(&ksig->info);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user