[Devel] [PATCH v2 RH7 2/2] ve/coredump: virtualize kernel.core_pattern sysctl

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Tue Feb 2 06:26:35 PST 2016


1) put core_pattern on ve_struct and add virtualized proc_handler
using macro sysctl_virtual()

2) use in-container khelper kthread for collecting cores

We need support of pipe'ing coredump in CT. If process crashes
in CT and kernel.core_pattern begins with "|" we get error:

CT:
  CT-101-bash-4.2# sysctl kernel.core_pattern
   kernel.core_pattern = |/root/core_test %p UID=%u GID=%g sig=%s
  CT-101-bash-4.2# sleep 100 &
   [1] 445
  CT-101-bash-4.2# kill -11 445
  CT-101-bash-4.2#
   [1]+  Segmentation fault      sleep 100
  CT-101-bash-4.2# ll /root
   total 8
   rwxr-xr-x 1 root root 7424 Jan 27 17:28 core_test
Host:
  [root at s143 ~]# less /var/log/messages
   Jan 28 10:40:42 s143 kernel: [87698.969582] Core dump to
   |/root/core_test 445 UID=0 GID=0 sig=11 pipe failed

Also docker is going to use pipe'ing in coredumps functionality:
https://github.com/docker/docker/issues/19289

https://jira.sw.ru/browse/PSBM-43596

v2: split sysctl_virtual in separate patch
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
 fs/coredump.c      | 14 +++++---------
 include/linux/ve.h |  4 ++++
 kernel/sysctl.c    | 14 +++++++++-----
 kernel/ve/ve.c     |  4 ++++
 4 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/fs/coredump.c b/fs/coredump.c
index 8118760..e3fdee2 100644
--- a/fs/coredump.c
+++ b/fs/coredump.c
@@ -32,6 +32,7 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/oom.h>
 #include <linux/compat.h>
+#include <linux/ve.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -45,7 +46,6 @@
 #include <trace/events/sched.h>
 
 int core_uses_pid;
-char core_pattern[CORENAME_MAX_SIZE] = "core";
 unsigned int core_pipe_limit;
 
 struct core_name {
@@ -152,7 +152,7 @@ static int cn_print_exe_file(struct core_name *cn)
 static int format_corename(struct core_name *cn, struct coredump_params *cprm)
 {
 	const struct cred *cred = current_cred();
-	const char *pat_ptr = core_pattern;
+	const char *pat_ptr = get_exec_env()->core_pattern;
 	int ispipe = (*pat_ptr == '|');
 	int pid_in_pattern = 0;
 	int err = 0;
@@ -560,7 +560,6 @@ void do_coredump(siginfo_t *siginfo)
 	if (ispipe) {
 		int dump_count;
 		char **helper_argv;
-		struct subprocess_info *sub_info;
 
 		if (ispipe < 0) {
 			printk(KERN_WARNING "format_corename failed\n");
@@ -608,12 +607,9 @@ void do_coredump(siginfo_t *siginfo)
 		}
 
 		retval = -ENOMEM;
-		sub_info = call_usermodehelper_setup(helper_argv[0],
-						helper_argv, NULL, GFP_KERNEL,
-						umh_pipe_setup, NULL, &cprm);
-		if (sub_info)
-			retval = call_usermodehelper_exec(sub_info,
-							  UMH_WAIT_EXEC);
+		retval = call_usermodehelper_fns_ve(get_exec_env(), helper_argv[0],
+		                                    helper_argv, NULL, UMH_WAIT_EXEC,
+						    umh_pipe_setup, NULL, &cprm);
 
 		argv_free(helper_argv);
 		if (retval) {
diff --git a/include/linux/ve.h b/include/linux/ve.h
index d81fa36..5d3b5aa 100644
--- a/include/linux/ve.h
+++ b/include/linux/ve.h
@@ -25,6 +25,7 @@
 #include <net/inet_frag.h>
 #include <linux/cgroup.h>
 #include <linux/kmapset.h>
+#include <linux/binfmts.h>
 
 struct tty_driver;
 struct file_system_type;
@@ -126,6 +127,9 @@ struct ve_struct {
 	 * and the VE unmounts it. This is acceptable.
 	 */
 	int			mnt_nr;
+#ifdef CONFIG_COREDUMP
+	char 			core_pattern[CORENAME_MAX_SIZE];
+#endif
 };
 
 struct ve_devmnt {
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index c2dbbf7..867eb5a 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -102,7 +102,6 @@ extern int max_threads;
 extern int suid_dumpable;
 #ifdef CONFIG_COREDUMP
 extern int core_uses_pid;
-extern char core_pattern[];
 extern unsigned int core_pipe_limit;
 #endif
 extern int pid_max_min, pid_max_max;
@@ -296,6 +295,10 @@ static int proc_dointvec_pidmax(struct ctl_table *table, int write,
 	return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
 }
 
+#ifdef CONFIG_COREDUMP
+sysctl_virtual(proc_dostring_coredump);
+#endif
+
 static struct ctl_table kern_table[] = {
 	{
 		.procname	= "sched_child_runs_first",
@@ -524,10 +527,10 @@ static struct ctl_table kern_table[] = {
 	},
 	{
 		.procname	= "core_pattern",
-		.data		= core_pattern,
+		.data		= ve0.core_pattern,
 		.maxlen		= CORENAME_MAX_SIZE,
-		.mode		= 0644,
-		.proc_handler	= proc_dostring_coredump,
+		.mode		= 0644 | S_ISVTX,
+		.proc_handler	= proc_dostring_coredump_virtual,
 	},
 	{
 		.procname	= "core_pipe_limit",
@@ -2265,9 +2268,10 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,
 
 static void validate_coredump_safety(void)
 {
+	struct ve_struct *ve = get_exec_env();
 #ifdef CONFIG_COREDUMP
 	if (suid_dumpable == SUID_DUMP_ROOT &&
-	    core_pattern[0] != '/' && core_pattern[0] != '|') {
+	    ve->core_pattern[0] != '/' && ve->core_pattern[0] != '|') {
 		printk(KERN_WARNING "Unsafe core_pattern used with "\
 			"suid_dumpable=2. Pipe handler or fully qualified "\
 			"core dump path required.\n");
diff --git a/kernel/ve/ve.c b/kernel/ve/ve.c
index 4d2b3a8..2408c3e 100644
--- a/kernel/ve/ve.c
+++ b/kernel/ve/ve.c
@@ -653,6 +653,10 @@ static struct cgroup_subsys_state *ve_create(struct cgroup *cg)
 #endif
 	ve->mnt_nr = 0;
 
+#ifdef CONFIG_COREDUMP
+	strcpy(ve->core_pattern, "core");
+#endif
+
 	return &ve->css;
 
 err_log:
-- 
1.9.3



More information about the Devel mailing list