diff options
Diffstat (limited to 'kernel/sysctl.c')
| -rw-r--r-- | kernel/sysctl.c | 51 | 
1 files changed, 43 insertions, 8 deletions
| diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 5d9a1d2b27b4..87174ef59161 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -30,6 +30,7 @@  #include <linux/security.h>  #include <linux/ctype.h>  #include <linux/kmemcheck.h> +#include <linux/kmemleak.h>  #include <linux/fs.h>  #include <linux/init.h>  #include <linux/kernel.h> @@ -174,6 +175,11 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write,  				void __user *buffer, size_t *lenp, loff_t *ppos);  #endif +static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write, +		void __user *buffer, size_t *lenp, loff_t *ppos); +static int proc_dostring_coredump(struct ctl_table *table, int write, +		void __user *buffer, size_t *lenp, loff_t *ppos); +  #ifdef CONFIG_MAGIC_SYSRQ  /* Note: sysrq code uses it's own private copy */  static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE; @@ -410,7 +416,7 @@ static struct ctl_table kern_table[] = {  		.data		= core_pattern,  		.maxlen		= CORENAME_MAX_SIZE,  		.mode		= 0644, -		.proc_handler	= proc_dostring, +		.proc_handler	= proc_dostring_coredump,  	},  	{  		.procname	= "core_pipe_limit", @@ -1095,11 +1101,9 @@ static struct ctl_table vm_table[] = {  		.extra1		= &zero,  	},  	{ -		.procname	= "nr_pdflush_threads", -		.data		= &nr_pdflush_threads, -		.maxlen		= sizeof nr_pdflush_threads, -		.mode		= 0444 /* read-only*/, -		.proc_handler	= proc_dointvec, +		.procname       = "nr_pdflush_threads", +		.mode           = 0444 /* read-only */, +		.proc_handler   = pdflush_proc_obsolete,  	},  	{  		.procname	= "swappiness", @@ -1516,7 +1520,7 @@ static struct ctl_table fs_table[] = {  		.data		= &suid_dumpable,  		.maxlen		= sizeof(int),  		.mode		= 0644, -		.proc_handler	= proc_dointvec_minmax, +		.proc_handler	= proc_dointvec_minmax_coredump,  		.extra1		= &zero,  		.extra2		= &two,  	}, @@ -1569,7 +1573,10 @@ static struct ctl_table dev_table[] = {  int __init sysctl_init(void)  { -	register_sysctl_table(sysctl_base_table); +	struct ctl_table_header *hdr; + +	hdr = register_sysctl_table(sysctl_base_table); +	kmemleak_not_leak(hdr);  	return 0;  } @@ -2027,6 +2034,34 @@ int proc_dointvec_minmax(struct ctl_table *table, int write,  				do_proc_dointvec_minmax_conv, ¶m);  } +static void validate_coredump_safety(void) +{ +	if (suid_dumpable == SUID_DUMPABLE_SAFE && +	    core_pattern[0] != '/' && core_pattern[0] != '|') { +		printk(KERN_WARNING "Unsafe core_pattern used with "\ +			"suid_dumpable=2. Pipe handler or fully qualified "\ +			"core dump path required.\n"); +	} +} + +static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write, +		void __user *buffer, size_t *lenp, loff_t *ppos) +{ +	int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos); +	if (!error) +		validate_coredump_safety(); +	return error; +} + +static int proc_dostring_coredump(struct ctl_table *table, int write, +		  void __user *buffer, size_t *lenp, loff_t *ppos) +{ +	int error = proc_dostring(table, write, buffer, lenp, ppos); +	if (!error) +		validate_coredump_safety(); +	return error; +} +  static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write,  				     void __user *buffer,  				     size_t *lenp, loff_t *ppos, |