Skip to content

Commit 4bbf9c3

Browse files
allenpaiskees
authored andcommitted
fs/coredump: Enable dynamic configuration of max file note size
Introduce the capability to dynamically configure the maximum file note size for ELF core dumps via sysctl. Why is this being done? We have observed that during a crash when there are more than 65k mmaps in memory, the existing fixed limit on the size of the ELF notes section becomes a bottleneck. The notes section quickly reaches its capacity, leading to incomplete memory segment information in the resulting coredump. This truncation compromises the utility of the coredumps, as crucial information about the memory state at the time of the crash might be omitted. This enhancement removes the previous static limit of 4MB, allowing system administrators to adjust the size based on system-specific requirements or constraints. Eg: $ sysctl -a | grep core_file_note_size_limit kernel.core_file_note_size_limit = 4194304 $ sysctl -n kernel.core_file_note_size_limit 4194304 $echo 519304 > /proc/sys/kernel/core_file_note_size_limit $sysctl -n kernel.core_file_note_size_limit 519304 Attempting to write beyond the ceiling value of 16MB $echo 17194304 > /proc/sys/kernel/core_file_note_size_limit bash: echo: write error: Invalid argument Signed-off-by: Vijay Nag <[email protected]> Signed-off-by: Allen Pais <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Kees Cook <[email protected]>
1 parent 10e2925 commit 4bbf9c3

File tree

3 files changed

+24
-2
lines changed

3 files changed

+24
-2
lines changed

fs/binfmt_elf.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1567,7 +1567,6 @@ static void fill_siginfo_note(struct memelfnote *note, user_siginfo_t *csigdata,
15671567
fill_note(note, "CORE", NT_SIGINFO, sizeof(*csigdata), csigdata);
15681568
}
15691569

1570-
#define MAX_FILE_NOTE_SIZE (4*1024*1024)
15711570
/*
15721571
* Format of NT_FILE note:
15731572
*
@@ -1595,8 +1594,12 @@ static int fill_files_note(struct memelfnote *note, struct coredump_params *cprm
15951594

15961595
names_ofs = (2 + 3 * count) * sizeof(data[0]);
15971596
alloc:
1598-
if (size >= MAX_FILE_NOTE_SIZE) /* paranoia check */
1597+
/* paranoia check */
1598+
if (size >= core_file_note_size_limit) {
1599+
pr_warn_once("coredump Note size too large: %u (does kernel.core_file_note_size_limit sysctl need adjustment?\n",
1600+
size);
15991601
return -EINVAL;
1602+
}
16001603
size = round_up(size, PAGE_SIZE);
16011604
/*
16021605
* "size" can be 0 here legitimately.

fs/coredump.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,15 @@
5656
static bool dump_vma_snapshot(struct coredump_params *cprm);
5757
static void free_vma_snapshot(struct coredump_params *cprm);
5858

59+
#define CORE_FILE_NOTE_SIZE_DEFAULT (4*1024*1024)
60+
/* Define a reasonable max cap */
61+
#define CORE_FILE_NOTE_SIZE_MAX (16*1024*1024)
62+
5963
static int core_uses_pid;
6064
static unsigned int core_pipe_limit;
6165
static char core_pattern[CORENAME_MAX_SIZE] = "core";
6266
static int core_name_size = CORENAME_MAX_SIZE;
67+
unsigned int core_file_note_size_limit = CORE_FILE_NOTE_SIZE_DEFAULT;
6368

6469
struct core_name {
6570
char *corename;
@@ -998,6 +1003,9 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,
9981003
return error;
9991004
}
10001005

1006+
static const unsigned int core_file_note_size_min = CORE_FILE_NOTE_SIZE_DEFAULT;
1007+
static const unsigned int core_file_note_size_max = CORE_FILE_NOTE_SIZE_MAX;
1008+
10011009
static struct ctl_table coredump_sysctls[] = {
10021010
{
10031011
.procname = "core_uses_pid",
@@ -1020,6 +1028,15 @@ static struct ctl_table coredump_sysctls[] = {
10201028
.mode = 0644,
10211029
.proc_handler = proc_dointvec,
10221030
},
1031+
{
1032+
.procname = "core_file_note_size_limit",
1033+
.data = &core_file_note_size_limit,
1034+
.maxlen = sizeof(unsigned int),
1035+
.mode = 0644,
1036+
.proc_handler = proc_douintvec_minmax,
1037+
.extra1 = (unsigned int *)&core_file_note_size_min,
1038+
.extra2 = (unsigned int *)&core_file_note_size_max,
1039+
},
10231040
};
10241041

10251042
static int __init init_fs_coredump_sysctls(void)

include/linux/coredump.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ struct coredump_params {
3030
struct core_vma_metadata *vma_meta;
3131
};
3232

33+
extern unsigned int core_file_note_size_limit;
34+
3335
/*
3436
* These are the only things you should do on a core-file: use only these
3537
* functions to write out all the necessary info.

0 commit comments

Comments
 (0)