aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c103
1 files changed, 85 insertions, 18 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 74f5b580fe34..db19e3e2aa4b 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -173,6 +173,13 @@ extern int no_unaligned_warning;
173#endif 173#endif
174 174
175#ifdef CONFIG_PROC_SYSCTL 175#ifdef CONFIG_PROC_SYSCTL
176
177#define SYSCTL_WRITES_LEGACY -1
178#define SYSCTL_WRITES_WARN 0
179#define SYSCTL_WRITES_STRICT 1
180
181static int sysctl_writes_strict = SYSCTL_WRITES_WARN;
182
176static int proc_do_cad_pid(struct ctl_table *table, int write, 183static int proc_do_cad_pid(struct ctl_table *table, int write,
177 void __user *buffer, size_t *lenp, loff_t *ppos); 184 void __user *buffer, size_t *lenp, loff_t *ppos);
178static int proc_taint(struct ctl_table *table, int write, 185static int proc_taint(struct ctl_table *table, int write,
@@ -195,7 +202,7 @@ static int proc_dostring_coredump(struct ctl_table *table, int write,
195/* Note: sysrq code uses it's own private copy */ 202/* Note: sysrq code uses it's own private copy */
196static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE; 203static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE;
197 204
198static int sysrq_sysctl_handler(ctl_table *table, int write, 205static int sysrq_sysctl_handler(struct ctl_table *table, int write,
199 void __user *buffer, size_t *lenp, 206 void __user *buffer, size_t *lenp,
200 loff_t *ppos) 207 loff_t *ppos)
201{ 208{
@@ -495,6 +502,15 @@ static struct ctl_table kern_table[] = {
495 .mode = 0644, 502 .mode = 0644,
496 .proc_handler = proc_taint, 503 .proc_handler = proc_taint,
497 }, 504 },
505 {
506 .procname = "sysctl_writes_strict",
507 .data = &sysctl_writes_strict,
508 .maxlen = sizeof(int),
509 .mode = 0644,
510 .proc_handler = proc_dointvec_minmax,
511 .extra1 = &neg_one,
512 .extra2 = &one,
513 },
498#endif 514#endif
499#ifdef CONFIG_LATENCYTOP 515#ifdef CONFIG_LATENCYTOP
500 { 516 {
@@ -643,7 +659,7 @@ static struct ctl_table kern_table[] = {
643 .extra2 = &one, 659 .extra2 = &one,
644 }, 660 },
645#endif 661#endif
646 662#ifdef CONFIG_UEVENT_HELPER
647 { 663 {
648 .procname = "hotplug", 664 .procname = "hotplug",
649 .data = &uevent_helper, 665 .data = &uevent_helper,
@@ -651,7 +667,7 @@ static struct ctl_table kern_table[] = {
651 .mode = 0644, 667 .mode = 0644,
652 .proc_handler = proc_dostring, 668 .proc_handler = proc_dostring,
653 }, 669 },
654 670#endif
655#ifdef CONFIG_CHR_DEV_SG 671#ifdef CONFIG_CHR_DEV_SG
656 { 672 {
657 .procname = "sg-big-buff", 673 .procname = "sg-big-buff",
@@ -1418,8 +1434,13 @@ static struct ctl_table vm_table[] = {
1418 (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL)) 1434 (defined(CONFIG_SUPERH) && defined(CONFIG_VSYSCALL))
1419 { 1435 {
1420 .procname = "vdso_enabled", 1436 .procname = "vdso_enabled",
1437#ifdef CONFIG_X86_32
1438 .data = &vdso32_enabled,
1439 .maxlen = sizeof(vdso32_enabled),
1440#else
1421 .data = &vdso_enabled, 1441 .data = &vdso_enabled,
1422 .maxlen = sizeof(vdso_enabled), 1442 .maxlen = sizeof(vdso_enabled),
1443#endif
1423 .mode = 0644, 1444 .mode = 0644,
1424 .proc_handler = proc_dointvec, 1445 .proc_handler = proc_dointvec,
1425 .extra1 = &zero, 1446 .extra1 = &zero,
@@ -1698,8 +1719,8 @@ int __init sysctl_init(void)
1698 1719
1699#ifdef CONFIG_PROC_SYSCTL 1720#ifdef CONFIG_PROC_SYSCTL
1700 1721
1701static int _proc_do_string(void* data, int maxlen, int write, 1722static int _proc_do_string(char *data, int maxlen, int write,
1702 void __user *buffer, 1723 char __user *buffer,
1703 size_t *lenp, loff_t *ppos) 1724 size_t *lenp, loff_t *ppos)
1704{ 1725{
1705 size_t len; 1726 size_t len;
@@ -1712,21 +1733,30 @@ static int _proc_do_string(void* data, int maxlen, int write,
1712 } 1733 }
1713 1734
1714 if (write) { 1735 if (write) {
1715 len = 0; 1736 if (sysctl_writes_strict == SYSCTL_WRITES_STRICT) {
1737 /* Only continue writes not past the end of buffer. */
1738 len = strlen(data);
1739 if (len > maxlen - 1)
1740 len = maxlen - 1;
1741
1742 if (*ppos > len)
1743 return 0;
1744 len = *ppos;
1745 } else {
1746 /* Start writing from beginning of buffer. */
1747 len = 0;
1748 }
1749
1750 *ppos += *lenp;
1716 p = buffer; 1751 p = buffer;
1717 while (len < *lenp) { 1752 while ((p - buffer) < *lenp && len < maxlen - 1) {
1718 if (get_user(c, p++)) 1753 if (get_user(c, p++))
1719 return -EFAULT; 1754 return -EFAULT;
1720 if (c == 0 || c == '\n') 1755 if (c == 0 || c == '\n')
1721 break; 1756 break;
1722 len++; 1757 data[len++] = c;
1723 } 1758 }
1724 if (len >= maxlen) 1759 data[len] = 0;
1725 len = maxlen-1;
1726 if(copy_from_user(data, buffer, len))
1727 return -EFAULT;
1728 ((char *) data)[len] = 0;
1729 *ppos += *lenp;
1730 } else { 1760 } else {
1731 len = strlen(data); 1761 len = strlen(data);
1732 if (len > maxlen) 1762 if (len > maxlen)
@@ -1743,10 +1773,10 @@ static int _proc_do_string(void* data, int maxlen, int write,
1743 if (len > *lenp) 1773 if (len > *lenp)
1744 len = *lenp; 1774 len = *lenp;
1745 if (len) 1775 if (len)
1746 if(copy_to_user(buffer, data, len)) 1776 if (copy_to_user(buffer, data, len))
1747 return -EFAULT; 1777 return -EFAULT;
1748 if (len < *lenp) { 1778 if (len < *lenp) {
1749 if(put_user('\n', ((char __user *) buffer) + len)) 1779 if (put_user('\n', buffer + len))
1750 return -EFAULT; 1780 return -EFAULT;
1751 len++; 1781 len++;
1752 } 1782 }
@@ -1756,6 +1786,14 @@ static int _proc_do_string(void* data, int maxlen, int write,
1756 return 0; 1786 return 0;
1757} 1787}
1758 1788
1789static void warn_sysctl_write(struct ctl_table *table)
1790{
1791 pr_warn_once("%s wrote to %s when file position was not 0!\n"
1792 "This will not be supported in the future. To silence this\n"
1793 "warning, set kernel.sysctl_writes_strict = -1\n",
1794 current->comm, table->procname);
1795}
1796
1759/** 1797/**
1760 * proc_dostring - read a string sysctl 1798 * proc_dostring - read a string sysctl
1761 * @table: the sysctl table 1799 * @table: the sysctl table
@@ -1776,8 +1814,11 @@ static int _proc_do_string(void* data, int maxlen, int write,
1776int proc_dostring(struct ctl_table *table, int write, 1814int proc_dostring(struct ctl_table *table, int write,
1777 void __user *buffer, size_t *lenp, loff_t *ppos) 1815 void __user *buffer, size_t *lenp, loff_t *ppos)
1778{ 1816{
1779 return _proc_do_string(table->data, table->maxlen, write, 1817 if (write && *ppos && sysctl_writes_strict == SYSCTL_WRITES_WARN)
1780 buffer, lenp, ppos); 1818 warn_sysctl_write(table);
1819
1820 return _proc_do_string((char *)(table->data), table->maxlen, write,
1821 (char __user *)buffer, lenp, ppos);
1781} 1822}
1782 1823
1783static size_t proc_skip_spaces(char **buf) 1824static size_t proc_skip_spaces(char **buf)
@@ -1951,6 +1992,18 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table,
1951 conv = do_proc_dointvec_conv; 1992 conv = do_proc_dointvec_conv;
1952 1993
1953 if (write) { 1994 if (write) {
1995 if (*ppos) {
1996 switch (sysctl_writes_strict) {
1997 case SYSCTL_WRITES_STRICT:
1998 goto out;
1999 case SYSCTL_WRITES_WARN:
2000 warn_sysctl_write(table);
2001 break;
2002 default:
2003 break;
2004 }
2005 }
2006
1954 if (left > PAGE_SIZE - 1) 2007 if (left > PAGE_SIZE - 1)
1955 left = PAGE_SIZE - 1; 2008 left = PAGE_SIZE - 1;
1956 page = __get_free_page(GFP_TEMPORARY); 2009 page = __get_free_page(GFP_TEMPORARY);
@@ -2008,6 +2061,7 @@ free:
2008 return err ? : -EINVAL; 2061 return err ? : -EINVAL;
2009 } 2062 }
2010 *lenp -= left; 2063 *lenp -= left;
2064out:
2011 *ppos += *lenp; 2065 *ppos += *lenp;
2012 return err; 2066 return err;
2013} 2067}
@@ -2200,6 +2254,18 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int
2200 left = *lenp; 2254 left = *lenp;
2201 2255
2202 if (write) { 2256 if (write) {
2257 if (*ppos) {
2258 switch (sysctl_writes_strict) {
2259 case SYSCTL_WRITES_STRICT:
2260 goto out;
2261 case SYSCTL_WRITES_WARN:
2262 warn_sysctl_write(table);
2263 break;
2264 default:
2265 break;
2266 }
2267 }
2268
2203 if (left > PAGE_SIZE - 1) 2269 if (left > PAGE_SIZE - 1)
2204 left = PAGE_SIZE - 1; 2270 left = PAGE_SIZE - 1;
2205 page = __get_free_page(GFP_TEMPORARY); 2271 page = __get_free_page(GFP_TEMPORARY);
@@ -2255,6 +2321,7 @@ free:
2255 return err ? : -EINVAL; 2321 return err ? : -EINVAL;
2256 } 2322 }
2257 *lenp -= left; 2323 *lenp -= left;
2324out:
2258 *ppos += *lenp; 2325 *ppos += *lenp;
2259 return err; 2326 return err;
2260} 2327}