diff options
Diffstat (limited to 'kernel/sysctl.c')
| -rw-r--r-- | kernel/sysctl.c | 207 | 
1 files changed, 151 insertions, 56 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index b2f06f3c6a3..75b22e22a72 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -62,6 +62,7 @@  #include <linux/capability.h>  #include <linux/binfmts.h>  #include <linux/sched/sysctl.h> +#include <linux/kexec.h>  #include <asm/uaccess.h>  #include <asm/processor.h> @@ -95,8 +96,6 @@  #if defined(CONFIG_SYSCTL)  /* External variables not in a header file. */ -extern int sysctl_overcommit_memory; -extern int sysctl_overcommit_ratio;  extern int max_threads;  extern int suid_dumpable;  #ifdef CONFIG_COREDUMP @@ -113,19 +112,18 @@ extern int sysctl_nr_open_min, sysctl_nr_open_max;  #ifndef CONFIG_MMU  extern int sysctl_nr_trim_pages;  #endif -#ifdef CONFIG_BLOCK -extern int blk_iopoll_enabled; -#endif  /* Constants used for minimum and  maximum */  #ifdef CONFIG_LOCKUP_DETECTOR  static int sixty = 60;  #endif +static int __maybe_unused neg_one = -1; +  static int zero;  static int __maybe_unused one = 1;  static int __maybe_unused two = 2; -static int __maybe_unused three = 3; +static int __maybe_unused four = 4;  static unsigned long one_ul = 1;  static int one_hundred = 100;  #ifdef CONFIG_PRINTK @@ -138,21 +136,21 @@ static unsigned long dirty_bytes_min = 2 * PAGE_SIZE;  /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */  static int maxolduid = 65535;  static int minolduid; -static int min_percpu_pagelist_fract = 8;  static int ngroups_max = NGROUPS_MAX;  static const int cap_last_cap = CAP_LAST_CAP; +/*this is needed for proc_doulongvec_minmax of sysctl_hung_task_timeout_secs */ +#ifdef CONFIG_DETECT_HUNG_TASK +static unsigned long hung_task_timeout_max = (LONG_MAX/HZ); +#endif +  #ifdef CONFIG_INOTIFY_USER  #include <linux/inotify.h>  #endif  #ifdef CONFIG_SPARC  #endif -#ifdef CONFIG_SPARC64 -extern int sysctl_tsb_ratio; -#endif -  #ifdef __hppa__  extern int pwrsw_enabled;  #endif @@ -170,6 +168,13 @@ extern int no_unaligned_warning;  #endif  #ifdef CONFIG_PROC_SYSCTL + +#define SYSCTL_WRITES_LEGACY	-1 +#define SYSCTL_WRITES_WARN	 0 +#define SYSCTL_WRITES_STRICT	 1 + +static int sysctl_writes_strict = SYSCTL_WRITES_WARN; +  static int proc_do_cad_pid(struct ctl_table *table, int write,  		  void __user *buffer, size_t *lenp, loff_t *ppos);  static int proc_taint(struct ctl_table *table, int write, @@ -190,9 +195,9 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,  #ifdef CONFIG_MAGIC_SYSRQ  /* Note: sysrq code uses it's own private copy */ -static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE; +static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE; -static int sysrq_sysctl_handler(ctl_table *table, int write, +static int sysrq_sysctl_handler(struct ctl_table *table, int write,  				void __user *buffer, size_t *lenp,  				loff_t *ppos)  { @@ -371,13 +376,6 @@ static struct ctl_table kern_table[] = {  		.proc_handler	= proc_dointvec,  	},  	{ -		.procname	= "numa_balancing_scan_period_reset", -		.data		= &sysctl_numa_balancing_scan_period_reset, -		.maxlen		= sizeof(unsigned int), -		.mode		= 0644, -		.proc_handler	= proc_dointvec, -	}, -	{  		.procname	= "numa_balancing_scan_period_max_ms",  		.data		= &sysctl_numa_balancing_scan_period_max,  		.maxlen		= sizeof(unsigned int), @@ -391,6 +389,15 @@ static struct ctl_table kern_table[] = {  		.mode		= 0644,  		.proc_handler	= proc_dointvec,  	}, +	{ +		.procname	= "numa_balancing", +		.data		= NULL, /* filled in by handler */ +		.maxlen		= sizeof(unsigned int), +		.mode		= 0644, +		.proc_handler	= sysctl_numa_balancing, +		.extra1		= &zero, +		.extra2		= &one, +	},  #endif /* CONFIG_NUMA_BALANCING */  #endif /* CONFIG_SCHED_DEBUG */  	{ @@ -490,6 +497,15 @@ static struct ctl_table kern_table[] = {  		.mode		= 0644,  		.proc_handler	= proc_taint,  	}, +	{ +		.procname	= "sysctl_writes_strict", +		.data		= &sysctl_writes_strict, +		.maxlen		= sizeof(int), +		.mode		= 0644, +		.proc_handler	= proc_dointvec_minmax, +		.extra1		= &neg_one, +		.extra2		= &one, +	},  #endif  #ifdef CONFIG_LATENCYTOP  	{ @@ -607,6 +623,18 @@ static struct ctl_table kern_table[] = {  		.proc_handler	= proc_dointvec,  	},  #endif +#ifdef CONFIG_KEXEC +	{ +		.procname	= "kexec_load_disabled", +		.data		= &kexec_load_disabled, +		.maxlen		= sizeof(int), +		.mode		= 0644, +		/* only handle a transition from default "0" to "1" */ +		.proc_handler	= proc_dointvec_minmax, +		.extra1		= &one, +		.extra2		= &one, +	}, +#endif  #ifdef CONFIG_MODULES  	{  		.procname	= "modprobe", @@ -626,7 +654,7 @@ static struct ctl_table kern_table[] = {  		.extra2		= &one,  	},  #endif - +#ifdef CONFIG_UEVENT_HELPER  	{  		.procname	= "hotplug",  		.data		= &uevent_helper, @@ -634,7 +662,7 @@ static struct ctl_table kern_table[] = {  		.mode		= 0644,  		.proc_handler	= proc_dostring,  	}, - +#endif  #ifdef CONFIG_CHR_DEV_SG  	{  		.procname	= "sg-big-buff", @@ -832,6 +860,17 @@ static struct ctl_table kern_table[] = {  		.extra1		= &zero,  		.extra2		= &one,  	}, +#ifdef CONFIG_SMP +	{ +		.procname	= "softlockup_all_cpu_backtrace", +		.data		= &sysctl_softlockup_all_cpu_backtrace, +		.maxlen		= sizeof(int), +		.mode		= 0644, +		.proc_handler	= proc_dointvec_minmax, +		.extra1		= &zero, +		.extra2		= &one, +	}, +#endif /* CONFIG_SMP */  	{  		.procname       = "nmi_watchdog",  		.data           = &watchdog_user_enabled, @@ -962,9 +1001,10 @@ static struct ctl_table kern_table[] = {  	{  		.procname	= "hung_task_check_count",  		.data		= &sysctl_hung_task_check_count, -		.maxlen		= sizeof(unsigned long), +		.maxlen		= sizeof(int),  		.mode		= 0644, -		.proc_handler	= proc_doulongvec_minmax, +		.proc_handler	= proc_dointvec_minmax, +		.extra1		= &zero,  	},  	{  		.procname	= "hung_task_timeout_secs", @@ -972,13 +1012,15 @@ static struct ctl_table kern_table[] = {  		.maxlen		= sizeof(unsigned long),  		.mode		= 0644,  		.proc_handler	= proc_dohung_task_timeout_secs, +		.extra2		= &hung_task_timeout_max,  	},  	{  		.procname	= "hung_task_warnings",  		.data		= &sysctl_hung_task_warnings, -		.maxlen		= sizeof(unsigned long), +		.maxlen		= sizeof(int),  		.mode		= 0644, -		.proc_handler	= proc_doulongvec_minmax, +		.proc_handler	= proc_dointvec_minmax, +		.extra1		= &neg_one,  	},  #endif  #ifdef CONFIG_COMPAT @@ -1049,6 +1091,7 @@ static struct ctl_table kern_table[] = {  		.maxlen		= sizeof(sysctl_perf_event_sample_rate),  		.mode		= 0644,  		.proc_handler	= perf_proc_update_handler, +		.extra1		= &one,  	},  	{  		.procname	= "perf_cpu_time_max_percent", @@ -1069,15 +1112,6 @@ static struct ctl_table kern_table[] = {  		.proc_handler	= proc_dointvec,  	},  #endif -#ifdef CONFIG_BLOCK -	{ -		.procname	= "blk_iopoll", -		.data		= &blk_iopoll_enabled, -		.maxlen		= sizeof(int), -		.mode		= 0644, -		.proc_handler	= proc_dointvec, -	}, -#endif  	{ }  }; @@ -1119,7 +1153,14 @@ static struct ctl_table vm_table[] = {  		.data		= &sysctl_overcommit_ratio,  		.maxlen		= sizeof(sysctl_overcommit_ratio),  		.mode		= 0644, -		.proc_handler	= proc_dointvec, +		.proc_handler	= overcommit_ratio_handler, +	}, +	{ +		.procname	= "overcommit_kbytes", +		.data		= &sysctl_overcommit_kbytes, +		.maxlen		= sizeof(sysctl_overcommit_kbytes), +		.mode		= 0644, +		.proc_handler	= overcommit_kbytes_handler,  	},  	{  		.procname	= "page-cluster",  @@ -1251,7 +1292,7 @@ static struct ctl_table vm_table[] = {  		.mode		= 0644,  		.proc_handler	= drop_caches_sysctl_handler,  		.extra1		= &one, -		.extra2		= &three, +		.extra2		= &four,  	},  #ifdef CONFIG_COMPACTION  	{ @@ -1286,7 +1327,7 @@ static struct ctl_table vm_table[] = {  		.maxlen		= sizeof(percpu_pagelist_fraction),  		.mode		= 0644,  		.proc_handler	= percpu_pagelist_fraction_sysctl_handler, -		.extra1		= &min_percpu_pagelist_fract, +		.extra1		= &zero,  	},  #ifdef CONFIG_MMU  	{ @@ -1399,8 +1440,13 @@ static struct ctl_table vm_table[] = {     (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))  	{  		.procname	= "vdso_enabled", +#ifdef CONFIG_X86_32 +		.data		= &vdso32_enabled, +		.maxlen		= sizeof(vdso32_enabled), +#else  		.data		= &vdso_enabled,  		.maxlen		= sizeof(vdso_enabled), +#endif  		.mode		= 0644,  		.proc_handler	= proc_dointvec,  		.extra1		= &zero, @@ -1679,8 +1725,8 @@ int __init sysctl_init(void)  #ifdef CONFIG_PROC_SYSCTL -static int _proc_do_string(void* data, int maxlen, int write, -			   void __user *buffer, +static int _proc_do_string(char *data, int maxlen, int write, +			   char __user *buffer,  			   size_t *lenp, loff_t *ppos)  {  	size_t len; @@ -1693,21 +1739,30 @@ static int _proc_do_string(void* data, int maxlen, int write,  	}  	if (write) { -		len = 0; +		if (sysctl_writes_strict == SYSCTL_WRITES_STRICT) { +			/* Only continue writes not past the end of buffer. */ +			len = strlen(data); +			if (len > maxlen - 1) +				len = maxlen - 1; + +			if (*ppos > len) +				return 0; +			len = *ppos; +		} else { +			/* Start writing from beginning of buffer. */ +			len = 0; +		} + +		*ppos += *lenp;  		p = buffer; -		while (len < *lenp) { +		while ((p - buffer) < *lenp && len < maxlen - 1) {  			if (get_user(c, p++))  				return -EFAULT;  			if (c == 0 || c == '\n')  				break; -			len++; +			data[len++] = c;  		} -		if (len >= maxlen) -			len = maxlen-1; -		if(copy_from_user(data, buffer, len)) -			return -EFAULT; -		((char *) data)[len] = 0; -		*ppos += *lenp; +		data[len] = 0;  	} else {  		len = strlen(data);  		if (len > maxlen) @@ -1724,10 +1779,10 @@ static int _proc_do_string(void* data, int maxlen, int write,  		if (len > *lenp)  			len = *lenp;  		if (len) -			if(copy_to_user(buffer, data, len)) +			if (copy_to_user(buffer, data, len))  				return -EFAULT;  		if (len < *lenp) { -			if(put_user('\n', ((char __user *) buffer) + len)) +			if (put_user('\n', buffer + len))  				return -EFAULT;  			len++;  		} @@ -1737,6 +1792,14 @@ static int _proc_do_string(void* data, int maxlen, int write,  	return 0;  } +static void warn_sysctl_write(struct ctl_table *table) +{ +	pr_warn_once("%s wrote to %s when file position was not 0!\n" +		"This will not be supported in the future. To silence this\n" +		"warning, set kernel.sysctl_writes_strict = -1\n", +		current->comm, table->procname); +} +  /**   * proc_dostring - read a string sysctl   * @table: the sysctl table @@ -1757,8 +1820,11 @@ static int _proc_do_string(void* data, int maxlen, int write,  int proc_dostring(struct ctl_table *table, int write,  		  void __user *buffer, size_t *lenp, loff_t *ppos)  { -	return _proc_do_string(table->data, table->maxlen, write, -			       buffer, lenp, ppos); +	if (write && *ppos && sysctl_writes_strict == SYSCTL_WRITES_WARN) +		warn_sysctl_write(table); + +	return _proc_do_string((char *)(table->data), table->maxlen, write, +			       (char __user *)buffer, lenp, ppos);  }  static size_t proc_skip_spaces(char **buf) @@ -1932,6 +1998,18 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,  		conv = do_proc_dointvec_conv;  	if (write) { +		if (*ppos) { +			switch (sysctl_writes_strict) { +			case SYSCTL_WRITES_STRICT: +				goto out; +			case SYSCTL_WRITES_WARN: +				warn_sysctl_write(table); +				break; +			default: +				break; +			} +		} +  		if (left > PAGE_SIZE - 1)  			left = PAGE_SIZE - 1;  		page = __get_free_page(GFP_TEMPORARY); @@ -1989,6 +2067,7 @@ free:  			return err ? : -EINVAL;  	}  	*lenp -= left; +out:  	*ppos += *lenp;  	return err;  } @@ -2181,6 +2260,18 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int  	left = *lenp;  	if (write) { +		if (*ppos) { +			switch (sysctl_writes_strict) { +			case SYSCTL_WRITES_STRICT: +				goto out; +			case SYSCTL_WRITES_WARN: +				warn_sysctl_write(table); +				break; +			default: +				break; +			} +		} +  		if (left > PAGE_SIZE - 1)  			left = PAGE_SIZE - 1;  		page = __get_free_page(GFP_TEMPORARY); @@ -2214,8 +2305,11 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int  			*i = val;  		} else {  			val = convdiv * (*i) / convmul; -			if (!first) +			if (!first) {  				err = proc_put_char(&buffer, &left, '\t'); +				if (err) +					break; +			}  			err = proc_put_long(&buffer, &left, val, false);  			if (err)  				break; @@ -2233,6 +2327,7 @@ free:  			return err ? : -EINVAL;  	}  	*lenp -= left; +out:  	*ppos += *lenp;  	return err;  } @@ -2479,11 +2574,11 @@ int proc_do_large_bitmap(struct ctl_table *table, int write,  	bool first = 1;  	size_t left = *lenp;  	unsigned long bitmap_len = table->maxlen; -	unsigned long *bitmap = (unsigned long *) table->data; +	unsigned long *bitmap = *(unsigned long **) table->data;  	unsigned long *tmp_bitmap = NULL;  	char tr_a[] = { '-', ',', '\n' }, tr_b[] = { ',', '\n', 0 }, c; -	if (!bitmap_len || !left || (*ppos && !write)) { +	if (!bitmap || !bitmap_len || !left || (*ppos && !write)) {  		*lenp = 0;  		return 0;  	}  | 
