diff options
Diffstat (limited to 'kernel/sysctl.c')
| -rw-r--r-- | kernel/sysctl.c | 103 |
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 | |||
| 181 | static int sysctl_writes_strict = SYSCTL_WRITES_WARN; | ||
| 182 | |||
| 176 | static int proc_do_cad_pid(struct ctl_table *table, int write, | 183 | static 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); |
| 178 | static int proc_taint(struct ctl_table *table, int write, | 185 | static 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 */ |
| 196 | static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE; | 203 | static int __sysrq_enabled = CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE; |
| 197 | 204 | ||
| 198 | static int sysrq_sysctl_handler(ctl_table *table, int write, | 205 | static 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 | ||
| 1701 | static int _proc_do_string(void* data, int maxlen, int write, | 1722 | static 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 | ||
| 1789 | static 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, | |||
| 1776 | int proc_dostring(struct ctl_table *table, int write, | 1814 | int 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 | ||
| 1783 | static size_t proc_skip_spaces(char **buf) | 1824 | static 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; |
| 2064 | out: | ||
| 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; |
| 2324 | out: | ||
| 2258 | *ppos += *lenp; | 2325 | *ppos += *lenp; |
| 2259 | return err; | 2326 | return err; |
| 2260 | } | 2327 | } |
