aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c208
1 files changed, 103 insertions, 105 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index b2a2d6889bab..f6d2e57b99a0 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -38,6 +38,7 @@
38#include <linux/writeback.h> 38#include <linux/writeback.h>
39#include <linux/hugetlb.h> 39#include <linux/hugetlb.h>
40#include <linux/initrd.h> 40#include <linux/initrd.h>
41#include <linux/key.h>
41#include <linux/times.h> 42#include <linux/times.h>
42#include <linux/limits.h> 43#include <linux/limits.h>
43#include <linux/dcache.h> 44#include <linux/dcache.h>
@@ -80,6 +81,7 @@ extern int compat_log;
80extern int maps_protect; 81extern int maps_protect;
81extern int sysctl_stat_interval; 82extern int sysctl_stat_interval;
82extern int latencytop_enabled; 83extern int latencytop_enabled;
84extern int sysctl_nr_open_min, sysctl_nr_open_max;
83 85
84/* Constants used for minimum and maximum */ 86/* Constants used for minimum and maximum */
85#if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM) 87#if defined(CONFIG_DETECT_SOFTLOCKUP) || defined(CONFIG_HIGHMEM)
@@ -130,8 +132,6 @@ extern int sysctl_userprocess_debug;
130extern int spin_retry; 132extern int spin_retry;
131#endif 133#endif
132 134
133extern int sysctl_hz_timer;
134
135#ifdef CONFIG_BSD_PROCESS_ACCT 135#ifdef CONFIG_BSD_PROCESS_ACCT
136extern int acct_parm[]; 136extern int acct_parm[];
137#endif 137#endif
@@ -144,12 +144,6 @@ extern int no_unaligned_warning;
144extern int max_lock_depth; 144extern int max_lock_depth;
145#endif 145#endif
146 146
147#ifdef CONFIG_SYSCTL_SYSCALL
148static int parse_table(int __user *, int, void __user *, size_t __user *,
149 void __user *, size_t, struct ctl_table *);
150#endif
151
152
153#ifdef CONFIG_PROC_SYSCTL 147#ifdef CONFIG_PROC_SYSCTL
154static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp, 148static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
155 void __user *buffer, size_t *lenp, loff_t *ppos); 149 void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -270,17 +264,6 @@ static struct ctl_table kern_table[] = {
270 }, 264 },
271 { 265 {
272 .ctl_name = CTL_UNNUMBERED, 266 .ctl_name = CTL_UNNUMBERED,
273 .procname = "sched_batch_wakeup_granularity_ns",
274 .data = &sysctl_sched_batch_wakeup_granularity,
275 .maxlen = sizeof(unsigned int),
276 .mode = 0644,
277 .proc_handler = &proc_dointvec_minmax,
278 .strategy = &sysctl_intvec,
279 .extra1 = &min_wakeup_granularity_ns,
280 .extra2 = &max_wakeup_granularity_ns,
281 },
282 {
283 .ctl_name = CTL_UNNUMBERED,
284 .procname = "sched_child_runs_first", 267 .procname = "sched_child_runs_first",
285 .data = &sysctl_sched_child_runs_first, 268 .data = &sysctl_sched_child_runs_first,
286 .maxlen = sizeof(unsigned int), 269 .maxlen = sizeof(unsigned int),
@@ -318,7 +301,7 @@ static struct ctl_table kern_table[] = {
318 .data = &sysctl_sched_rt_period, 301 .data = &sysctl_sched_rt_period,
319 .maxlen = sizeof(unsigned int), 302 .maxlen = sizeof(unsigned int),
320 .mode = 0644, 303 .mode = 0644,
321 .proc_handler = &proc_dointvec, 304 .proc_handler = &sched_rt_handler,
322 }, 305 },
323 { 306 {
324 .ctl_name = CTL_UNNUMBERED, 307 .ctl_name = CTL_UNNUMBERED,
@@ -326,7 +309,7 @@ static struct ctl_table kern_table[] = {
326 .data = &sysctl_sched_rt_runtime, 309 .data = &sysctl_sched_rt_runtime,
327 .maxlen = sizeof(int), 310 .maxlen = sizeof(int),
328 .mode = 0644, 311 .mode = 0644,
329 .proc_handler = &proc_dointvec, 312 .proc_handler = &sched_rt_handler,
330 }, 313 },
331 { 314 {
332 .ctl_name = CTL_UNNUMBERED, 315 .ctl_name = CTL_UNNUMBERED,
@@ -578,16 +561,6 @@ static struct ctl_table kern_table[] = {
578 .proc_handler = &proc_dointvec, 561 .proc_handler = &proc_dointvec,
579 }, 562 },
580#endif 563#endif
581#ifdef CONFIG_NO_IDLE_HZ
582 {
583 .ctl_name = KERN_HZ_TIMER,
584 .procname = "hz_timer",
585 .data = &sysctl_hz_timer,
586 .maxlen = sizeof(int),
587 .mode = 0644,
588 .proc_handler = &proc_dointvec,
589 },
590#endif
591 { 564 {
592 .ctl_name = KERN_S390_USER_DEBUG_LOGGING, 565 .ctl_name = KERN_S390_USER_DEBUG_LOGGING,
593 .procname = "userprocess_debug", 566 .procname = "userprocess_debug",
@@ -820,6 +793,14 @@ static struct ctl_table kern_table[] = {
820 .proc_handler = &proc_dostring, 793 .proc_handler = &proc_dostring,
821 .strategy = &sysctl_string, 794 .strategy = &sysctl_string,
822 }, 795 },
796#ifdef CONFIG_KEYS
797 {
798 .ctl_name = CTL_UNNUMBERED,
799 .procname = "keys",
800 .mode = 0555,
801 .child = key_sysctls,
802 },
803#endif
823/* 804/*
824 * NOTE: do not add new entries to this table unless you have read 805 * NOTE: do not add new entries to this table unless you have read
825 * Documentation/sysctl/ctl_unnumbered.txt 806 * Documentation/sysctl/ctl_unnumbered.txt
@@ -1198,7 +1179,9 @@ static struct ctl_table fs_table[] = {
1198 .data = &sysctl_nr_open, 1179 .data = &sysctl_nr_open,
1199 .maxlen = sizeof(int), 1180 .maxlen = sizeof(int),
1200 .mode = 0644, 1181 .mode = 0644,
1201 .proc_handler = &proc_dointvec, 1182 .proc_handler = &proc_dointvec_minmax,
1183 .extra1 = &sysctl_nr_open_min,
1184 .extra2 = &sysctl_nr_open_max,
1202 }, 1185 },
1203 { 1186 {
1204 .ctl_name = FS_DENTRY, 1187 .ctl_name = FS_DENTRY,
@@ -1441,6 +1424,76 @@ void register_sysctl_root(struct ctl_table_root *root)
1441} 1424}
1442 1425
1443#ifdef CONFIG_SYSCTL_SYSCALL 1426#ifdef CONFIG_SYSCTL_SYSCALL
1427/* Perform the actual read/write of a sysctl table entry. */
1428static int do_sysctl_strategy(struct ctl_table_root *root,
1429 struct ctl_table *table,
1430 int __user *name, int nlen,
1431 void __user *oldval, size_t __user *oldlenp,
1432 void __user *newval, size_t newlen)
1433{
1434 int op = 0, rc;
1435
1436 if (oldval)
1437 op |= 004;
1438 if (newval)
1439 op |= 002;
1440 if (sysctl_perm(root, table, op))
1441 return -EPERM;
1442
1443 if (table->strategy) {
1444 rc = table->strategy(table, name, nlen, oldval, oldlenp,
1445 newval, newlen);
1446 if (rc < 0)
1447 return rc;
1448 if (rc > 0)
1449 return 0;
1450 }
1451
1452 /* If there is no strategy routine, or if the strategy returns
1453 * zero, proceed with automatic r/w */
1454 if (table->data && table->maxlen) {
1455 rc = sysctl_data(table, name, nlen, oldval, oldlenp,
1456 newval, newlen);
1457 if (rc < 0)
1458 return rc;
1459 }
1460 return 0;
1461}
1462
1463static int parse_table(int __user *name, int nlen,
1464 void __user *oldval, size_t __user *oldlenp,
1465 void __user *newval, size_t newlen,
1466 struct ctl_table_root *root,
1467 struct ctl_table *table)
1468{
1469 int n;
1470repeat:
1471 if (!nlen)
1472 return -ENOTDIR;
1473 if (get_user(n, name))
1474 return -EFAULT;
1475 for ( ; table->ctl_name || table->procname; table++) {
1476 if (!table->ctl_name)
1477 continue;
1478 if (n == table->ctl_name) {
1479 int error;
1480 if (table->child) {
1481 if (sysctl_perm(root, table, 001))
1482 return -EPERM;
1483 name++;
1484 nlen--;
1485 table = table->child;
1486 goto repeat;
1487 }
1488 error = do_sysctl_strategy(root, table, name, nlen,
1489 oldval, oldlenp,
1490 newval, newlen);
1491 return error;
1492 }
1493 }
1494 return -ENOTDIR;
1495}
1496
1444int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, 1497int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
1445 void __user *newval, size_t newlen) 1498 void __user *newval, size_t newlen)
1446{ 1499{
@@ -1458,7 +1511,8 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol
1458 for (head = sysctl_head_next(NULL); head; 1511 for (head = sysctl_head_next(NULL); head;
1459 head = sysctl_head_next(head)) { 1512 head = sysctl_head_next(head)) {
1460 error = parse_table(name, nlen, oldval, oldlenp, 1513 error = parse_table(name, nlen, oldval, oldlenp,
1461 newval, newlen, head->ctl_table); 1514 newval, newlen,
1515 head->root, head->ctl_table);
1462 if (error != -ENOTDIR) { 1516 if (error != -ENOTDIR) {
1463 sysctl_head_finish(head); 1517 sysctl_head_finish(head);
1464 break; 1518 break;
@@ -1504,84 +1558,22 @@ static int test_perm(int mode, int op)
1504 return -EACCES; 1558 return -EACCES;
1505} 1559}
1506 1560
1507int sysctl_perm(struct ctl_table *table, int op) 1561int sysctl_perm(struct ctl_table_root *root, struct ctl_table *table, int op)
1508{ 1562{
1509 int error; 1563 int error;
1564 int mode;
1565
1510 error = security_sysctl(table, op); 1566 error = security_sysctl(table, op);
1511 if (error) 1567 if (error)
1512 return error; 1568 return error;
1513 return test_perm(table->mode, op);
1514}
1515
1516#ifdef CONFIG_SYSCTL_SYSCALL
1517static int parse_table(int __user *name, int nlen,
1518 void __user *oldval, size_t __user *oldlenp,
1519 void __user *newval, size_t newlen,
1520 struct ctl_table *table)
1521{
1522 int n;
1523repeat:
1524 if (!nlen)
1525 return -ENOTDIR;
1526 if (get_user(n, name))
1527 return -EFAULT;
1528 for ( ; table->ctl_name || table->procname; table++) {
1529 if (!table->ctl_name)
1530 continue;
1531 if (n == table->ctl_name) {
1532 int error;
1533 if (table->child) {
1534 if (sysctl_perm(table, 001))
1535 return -EPERM;
1536 name++;
1537 nlen--;
1538 table = table->child;
1539 goto repeat;
1540 }
1541 error = do_sysctl_strategy(table, name, nlen,
1542 oldval, oldlenp,
1543 newval, newlen);
1544 return error;
1545 }
1546 }
1547 return -ENOTDIR;
1548}
1549
1550/* Perform the actual read/write of a sysctl table entry. */
1551int do_sysctl_strategy (struct ctl_table *table,
1552 int __user *name, int nlen,
1553 void __user *oldval, size_t __user *oldlenp,
1554 void __user *newval, size_t newlen)
1555{
1556 int op = 0, rc;
1557
1558 if (oldval)
1559 op |= 004;
1560 if (newval)
1561 op |= 002;
1562 if (sysctl_perm(table, op))
1563 return -EPERM;
1564 1569
1565 if (table->strategy) { 1570 if (root->permissions)
1566 rc = table->strategy(table, name, nlen, oldval, oldlenp, 1571 mode = root->permissions(root, current->nsproxy, table);
1567 newval, newlen); 1572 else
1568 if (rc < 0) 1573 mode = table->mode;
1569 return rc;
1570 if (rc > 0)
1571 return 0;
1572 }
1573 1574
1574 /* If there is no strategy routine, or if the strategy returns 1575 return test_perm(mode, op);
1575 * zero, proceed with automatic r/w */
1576 if (table->data && table->maxlen) {
1577 rc = sysctl_data(table, name, nlen, oldval, oldlenp,
1578 newval, newlen);
1579 if (rc < 0)
1580 return rc;
1581 }
1582 return 0;
1583} 1576}
1584#endif /* CONFIG_SYSCTL_SYSCALL */
1585 1577
1586static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table) 1578static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
1587{ 1579{
@@ -1594,9 +1586,13 @@ static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
1594 1586
1595static __init int sysctl_init(void) 1587static __init int sysctl_init(void)
1596{ 1588{
1597 int err;
1598 sysctl_set_parent(NULL, root_table); 1589 sysctl_set_parent(NULL, root_table);
1599 err = sysctl_check_table(current->nsproxy, root_table); 1590#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
1591 {
1592 int err;
1593 err = sysctl_check_table(current->nsproxy, root_table);
1594 }
1595#endif
1600 return 0; 1596 return 0;
1601} 1597}
1602 1598
@@ -1723,10 +1719,12 @@ struct ctl_table_header *__register_sysctl_paths(
1723 header->unregistering = NULL; 1719 header->unregistering = NULL;
1724 header->root = root; 1720 header->root = root;
1725 sysctl_set_parent(NULL, header->ctl_table); 1721 sysctl_set_parent(NULL, header->ctl_table);
1722#ifdef CONFIG_SYSCTL_SYSCALL_CHECK
1726 if (sysctl_check_table(namespaces, header->ctl_table)) { 1723 if (sysctl_check_table(namespaces, header->ctl_table)) {
1727 kfree(header); 1724 kfree(header);
1728 return NULL; 1725 return NULL;
1729 } 1726 }
1727#endif
1730 spin_lock(&sysctl_lock); 1728 spin_lock(&sysctl_lock);
1731 header_list = lookup_header_list(root, namespaces); 1729 header_list = lookup_header_list(root, namespaces);
1732 list_add_tail(&header->ctl_entry, header_list); 1730 list_add_tail(&header->ctl_entry, header_list);