diff --git a/arch/arm64/configs/openeuler_defconfig b/arch/arm64/configs/openeuler_defconfig index f055d8e93bc49240da646fff336def76a6b694ff..0f0c027d0d7e8300def1cf666cea5b708dce8e08 100644 --- a/arch/arm64/configs/openeuler_defconfig +++ b/arch/arm64/configs/openeuler_defconfig @@ -7334,3 +7334,4 @@ CONFIG_ARCH_HAS_KCOV=y # CONFIG_MEMTEST is not set # end of Kernel Testing and Coverage # end of Kernel hacking +CONFIG_CORE_PATTERN_ISOLATION=y diff --git a/arch/x86/configs/openeuler_defconfig b/arch/x86/configs/openeuler_defconfig index 9adedd9d615a10af912d64649b5f41d5ac5a52a3..15765da384c36f05d56c80ebe6d88b90843b8221 100644 --- a/arch/x86/configs/openeuler_defconfig +++ b/arch/x86/configs/openeuler_defconfig @@ -8433,3 +8433,4 @@ CONFIG_ARCH_HAS_KCOV=y # CONFIG_HYPERV_TESTING is not set # end of Kernel Testing and Coverage # end of Kernel hacking +CONFIG_CORE_PATTERN_ISOLATION=y diff --git a/fs/Kconfig b/fs/Kconfig index 385602ba0d9951f3bb90d403a95b024ebf017c13..f9985671c6a31fc678a79c862559b3951b18da82 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -395,3 +395,11 @@ config RESCTRL help Memory Partitioning and Monitoring. More exactly Memory system performance resource Partitioning and Monitoring + +config CORE_PATTERN_ISOLATION + bool "Core pattern isolation per mount namespace" + depends on COREDUMP + default n + help + Userspace coredump file is generated according to the per mount + namespace core_pattern string instead of the global one. diff --git a/fs/coredump.c b/fs/coredump.c index 6c0d0a42fda940628d527c7080c2d2eef3477fc4..c641c28b2e2372d48083098ad2c6fac5d291cae4 100644 --- a/fs/coredump.c +++ b/fs/coredump.c @@ -52,13 +52,18 @@ #include "internal.h" #include +#ifdef CONFIG_CORE_PATTERN_ISOLATION +#include "mount.h" +#endif static bool dump_vma_snapshot(struct coredump_params *cprm); static void free_vma_snapshot(struct coredump_params *cprm); int core_uses_pid; unsigned int core_pipe_limit; +#ifndef CONFIG_CORE_PATTERN_ISOLATION char core_pattern[CORENAME_MAX_SIZE] = "core"; +#endif static int core_name_size = CORENAME_MAX_SIZE; struct core_name { @@ -201,7 +206,12 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm, size_t **argv, int *argc) { const struct cred *cred = current_cred(); +#ifdef CONFIG_CORE_PATTERN_ISOLATION + const char *pat_ptr = current->nsproxy->mnt_ns->core_pattern; +#else const char *pat_ptr = core_pattern; +#endif + int ispipe = (*pat_ptr == '|'); bool was_space = false; int pid_in_pattern = 0; @@ -214,7 +224,7 @@ static int format_corename(struct core_name *cn, struct coredump_params *cprm, cn->corename[0] = '\0'; if (ispipe) { - int argvs = sizeof(core_pattern) / 2; + int argvs = CORENAME_MAX_SIZE / 2; (*argv) = kmalloc_array(argvs, sizeof(**argv), GFP_KERNEL); if (!(*argv)) return -ENOMEM; diff --git a/fs/mount.h b/fs/mount.h index c7abb7b394d8eed9ca2833e656d345fc44e3a402..1d7052257567341b9121f7ab80bc68de452faa3d 100644 --- a/fs/mount.h +++ b/fs/mount.h @@ -4,6 +4,11 @@ #include #include #include +#ifdef CONFIG_CORE_PATTERN_ISOLATION +#ifndef __GENKSYMS__ +#include +#endif +#endif struct mnt_namespace { atomic_t count; @@ -23,6 +28,9 @@ struct mnt_namespace { u64 event; unsigned int mounts; /* # of mounts in the namespace */ unsigned int pending_mounts; +#ifdef CONFIG_CORE_PATTERN_ISOLATION + KABI_EXTEND(char core_pattern[CORENAME_MAX_SIZE]) +#endif } __randomize_layout; struct mnt_pcp { diff --git a/fs/namespace.c b/fs/namespace.c index 6e76f2a72cfca0a691f125e2ffafaa569a585fd4..739cf0c2fc7bd8b8c4764fbd90fcf15748454397 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -3305,6 +3305,9 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns, bool a spin_lock_init(&new_ns->ns_lock); new_ns->user_ns = get_user_ns(user_ns); new_ns->ucounts = ucounts; +#ifdef CONFIG_CORE_PATTERN_ISOLATION + strncpy(new_ns->core_pattern, "core", CORENAME_MAX_SIZE); +#endif return new_ns; } @@ -3333,6 +3336,9 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, return new_ns; namespace_lock(); +#ifdef CONFIG_CORE_PATTERN_ISOLATION + strncpy(new_ns->core_pattern, ns->core_pattern, CORENAME_MAX_SIZE); +#endif /* First pass: copy the tree topology */ copy_flags = CL_COPY_UNBINDABLE | CL_EXPIRE; if (user_ns != ns->user_ns) diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 078bbe07becde964461a028c8c01a48f7ba1b523..c8e2f16fbacf9a5a6fdf945fb212db84328763f4 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -71,6 +71,9 @@ #include #include #include +#ifdef CONFIG_CORE_PATTERN_ISOLATION +#include "../fs/mount.h" +#endif #include "../lib/kstrtox.h" @@ -1096,14 +1099,24 @@ static int proc_dopipe_max_size(struct ctl_table *table, int write, static void validate_coredump_safety(void) { #ifdef CONFIG_COREDUMP +#ifdef CONFIG_CORE_PATTERN_ISOLATION + char *core_pattern = current->nsproxy->mnt_ns->core_pattern; +#endif if (suid_dumpable == SUID_DUMP_ROOT && core_pattern[0] != '/' && core_pattern[0] != '|') { - printk(KERN_WARNING -"Unsafe core_pattern used with fs.suid_dumpable=2.\n" -"Pipe handler or fully qualified core dump path required.\n" -"Set kernel.core_pattern before fs.suid_dumpable.\n" + pr_warn("Unsafe core_pattern used with fs.suid_dumpable=2.\n" + "Pipe handler or fully qualified core dump path required.\n" + "Set kernel.core_pattern before fs.suid_dumpable.\n" ); } + +#ifdef CONFIG_CORE_PATTERN_ISOLATION + if (current->nsproxy->mnt_ns != init_task.nsproxy->mnt_ns + && core_pattern[0] == '|') { + pr_warn("core_pattern with pipe is setted in container environment.\n" + "Pipe handler will be lookup in init mnt ns.\n"); + } +#endif #endif } @@ -1120,9 +1133,21 @@ static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write, static int proc_dostring_coredump(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { - int error = proc_dostring(table, write, buffer, lenp, ppos); + int error; +#ifdef CONFIG_CORE_PATTERN_ISOLATION + struct mnt_namespace *mnt = current->nsproxy->mnt_ns; + + if (write) + proc_first_pos_non_zero_ignore(ppos, table); + + error = _proc_do_string((char *)(mnt->core_pattern), + table->maxlen, write, (char __user *)buffer, lenp, ppos); +#else + error = proc_dostring(table, write, buffer, lenp, ppos); +#endif if (!error) validate_coredump_safety(); + return error; } #endif @@ -1925,7 +1950,11 @@ static struct ctl_table kern_table[] = { }, { .procname = "core_pattern", +#ifdef CONFIG_CORE_PATTERN_ISOLATION + .data = NULL, +#else .data = core_pattern, +#endif .maxlen = CORENAME_MAX_SIZE, .mode = 0644, .proc_handler = proc_dostring_coredump,