Commit c114e994 authored by Roman Kisel's avatar Roman Kisel Committed by Kees Cook

coredump: Standartize and fix logging

The coredump code does not log the process ID and the comm
consistently, logs unescaped comm when it does log it, and
does not always use the ratelimited logging. That makes it
harder to analyze logs and puts the system at the risk of
spamming the system log incase something crashes many times
over and over again.

Fix that by logging TGID and comm (escaped) consistently and
using the ratelimited logging always.
Signed-off-by: default avatarRoman Kisel <romank@linux.microsoft.com>
Tested-by: default avatarAllen Pais <apais@linux.microsoft.com>
Link: https://lore.kernel.org/r/20240718182743.1959160-2-romank@linux.microsoft.comSigned-off-by: default avatarKees Cook <kees@kernel.org>
parent de9c2c66
...@@ -586,8 +586,7 @@ void do_coredump(const kernel_siginfo_t *siginfo) ...@@ -586,8 +586,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
struct subprocess_info *sub_info; struct subprocess_info *sub_info;
if (ispipe < 0) { if (ispipe < 0) {
printk(KERN_WARNING "format_corename failed\n"); coredump_report_failure("format_corename failed, aborting core");
printk(KERN_WARNING "Aborting core\n");
goto fail_unlock; goto fail_unlock;
} }
...@@ -607,27 +606,21 @@ void do_coredump(const kernel_siginfo_t *siginfo) ...@@ -607,27 +606,21 @@ void do_coredump(const kernel_siginfo_t *siginfo)
* right pid if a thread in a multi-threaded * right pid if a thread in a multi-threaded
* core_pattern process dies. * core_pattern process dies.
*/ */
printk(KERN_WARNING coredump_report_failure("RLIMIT_CORE is set to 1, aborting core");
"Process %d(%s) has RLIMIT_CORE set to 1\n",
task_tgid_vnr(current), current->comm);
printk(KERN_WARNING "Aborting core\n");
goto fail_unlock; goto fail_unlock;
} }
cprm.limit = RLIM_INFINITY; cprm.limit = RLIM_INFINITY;
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)) {
printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n", coredump_report_failure("over core_pipe_limit, skipping core dump");
task_tgid_vnr(current), current->comm);
printk(KERN_WARNING "Skipping core dump\n");
goto fail_dropcount; goto fail_dropcount;
} }
helper_argv = kmalloc_array(argc + 1, sizeof(*helper_argv), helper_argv = kmalloc_array(argc + 1, sizeof(*helper_argv),
GFP_KERNEL); GFP_KERNEL);
if (!helper_argv) { if (!helper_argv) {
printk(KERN_WARNING "%s failed to allocate memory\n", coredump_report_failure("%s failed to allocate memory", __func__);
__func__);
goto fail_dropcount; goto fail_dropcount;
} }
for (argi = 0; argi < argc; argi++) for (argi = 0; argi < argc; argi++)
...@@ -644,8 +637,7 @@ void do_coredump(const kernel_siginfo_t *siginfo) ...@@ -644,8 +637,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
kfree(helper_argv); kfree(helper_argv);
if (retval) { if (retval) {
printk(KERN_INFO "Core dump to |%s pipe failed\n", coredump_report_failure("|%s pipe failed", cn.corename);
cn.corename);
goto close_fail; goto close_fail;
} }
} else { } else {
...@@ -658,10 +650,8 @@ void do_coredump(const kernel_siginfo_t *siginfo) ...@@ -658,10 +650,8 @@ void do_coredump(const kernel_siginfo_t *siginfo)
goto fail_unlock; goto fail_unlock;
if (need_suid_safe && cn.corename[0] != '/') { if (need_suid_safe && cn.corename[0] != '/') {
printk(KERN_WARNING "Pid %d(%s) can only dump core "\ coredump_report_failure(
"to fully qualified path!\n", "this process can only dump core to a fully qualified path, skipping core dump");
task_tgid_vnr(current), current->comm);
printk(KERN_WARNING "Skipping core dump\n");
goto fail_unlock; goto fail_unlock;
} }
...@@ -730,13 +720,13 @@ void do_coredump(const kernel_siginfo_t *siginfo) ...@@ -730,13 +720,13 @@ void do_coredump(const kernel_siginfo_t *siginfo)
idmap = file_mnt_idmap(cprm.file); idmap = file_mnt_idmap(cprm.file);
if (!vfsuid_eq_kuid(i_uid_into_vfsuid(idmap, inode), if (!vfsuid_eq_kuid(i_uid_into_vfsuid(idmap, inode),
current_fsuid())) { current_fsuid())) {
pr_info_ratelimited("Core dump to %s aborted: cannot preserve file owner\n", coredump_report_failure("Core dump to %s aborted: "
cn.corename); "cannot preserve file owner", cn.corename);
goto close_fail; goto close_fail;
} }
if ((inode->i_mode & 0677) != 0600) { if ((inode->i_mode & 0677) != 0600) {
pr_info_ratelimited("Core dump to %s aborted: cannot preserve file permissions\n", coredump_report_failure("Core dump to %s aborted: "
cn.corename); "cannot preserve file permissions", cn.corename);
goto close_fail; goto close_fail;
} }
if (!(cprm.file->f_mode & FMODE_CAN_WRITE)) if (!(cprm.file->f_mode & FMODE_CAN_WRITE))
...@@ -757,7 +747,7 @@ void do_coredump(const kernel_siginfo_t *siginfo) ...@@ -757,7 +747,7 @@ void do_coredump(const kernel_siginfo_t *siginfo)
* have this set to NULL. * have this set to NULL.
*/ */
if (!cprm.file) { if (!cprm.file) {
pr_info("Core dump to |%s disabled\n", cn.corename); coredump_report_failure("Core dump to |%s disabled", cn.corename);
goto close_fail; goto close_fail;
} }
if (!dump_vma_snapshot(&cprm)) if (!dump_vma_snapshot(&cprm))
...@@ -983,11 +973,10 @@ void validate_coredump_safety(void) ...@@ -983,11 +973,10 @@ void validate_coredump_safety(void)
{ {
if (suid_dumpable == SUID_DUMP_ROOT && if (suid_dumpable == SUID_DUMP_ROOT &&
core_pattern[0] != '/' && core_pattern[0] != '|') { core_pattern[0] != '/' && core_pattern[0] != '|') {
pr_warn(
"Unsafe core_pattern used with fs.suid_dumpable=2.\n" coredump_report_failure("Unsafe core_pattern used with fs.suid_dumpable=2: "
"Pipe handler or fully qualified core dump path required.\n" "pipe handler or fully qualified core dump path required. "
"Set kernel.core_pattern before fs.suid_dumpable.\n" "Set kernel.core_pattern before fs.suid_dumpable.");
);
} }
} }
......
...@@ -43,8 +43,30 @@ extern int dump_align(struct coredump_params *cprm, int align); ...@@ -43,8 +43,30 @@ 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 void do_coredump(const kernel_siginfo_t *siginfo); extern void do_coredump(const kernel_siginfo_t *siginfo);
/*
* Logging for the coredump code, ratelimited.
* The TGID and comm fields are added to the message.
*/
#define __COREDUMP_PRINTK(Level, Format, ...) \
do { \
char comm[TASK_COMM_LEN]; \
\
get_task_comm(comm, current); \
printk_ratelimited(Level "coredump: %d(%*pE): " Format "\n", \
task_tgid_vnr(current), (int)strlen(comm), comm, ##__VA_ARGS__); \
} while (0) \
#define coredump_report(fmt, ...) __COREDUMP_PRINTK(KERN_INFO, fmt, ##__VA_ARGS__)
#define coredump_report_failure(fmt, ...) __COREDUMP_PRINTK(KERN_WARNING, fmt, ##__VA_ARGS__)
#else #else
static inline void do_coredump(const kernel_siginfo_t *siginfo) {} static inline void do_coredump(const kernel_siginfo_t *siginfo) {}
#define coredump_report(...)
#define coredump_report_failure(...)
#endif #endif
#if defined(CONFIG_COREDUMP) && defined(CONFIG_SYSCTL) #if defined(CONFIG_COREDUMP) && defined(CONFIG_SYSCTL)
......
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