aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/sysctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r--kernel/sysctl.c144
1 files changed, 68 insertions, 76 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 1cdfe942d160..874e813e40c8 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -145,12 +145,6 @@ extern int no_unaligned_warning;
145extern int max_lock_depth; 145extern int max_lock_depth;
146#endif 146#endif
147 147
148#ifdef CONFIG_SYSCTL_SYSCALL
149static int parse_table(int __user *, int, void __user *, size_t __user *,
150 void __user *, size_t, struct ctl_table *);
151#endif
152
153
154#ifdef CONFIG_PROC_SYSCTL 148#ifdef CONFIG_PROC_SYSCTL
155static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp, 149static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp,
156 void __user *buffer, size_t *lenp, loff_t *ppos); 150 void __user *buffer, size_t *lenp, loff_t *ppos);
@@ -1439,6 +1433,74 @@ void register_sysctl_root(struct ctl_table_root *root)
1439} 1433}
1440 1434
1441#ifdef CONFIG_SYSCTL_SYSCALL 1435#ifdef CONFIG_SYSCTL_SYSCALL
1436/* Perform the actual read/write of a sysctl table entry. */
1437static int do_sysctl_strategy(struct ctl_table *table,
1438 int __user *name, int nlen,
1439 void __user *oldval, size_t __user *oldlenp,
1440 void __user *newval, size_t newlen)
1441{
1442 int op = 0, rc;
1443
1444 if (oldval)
1445 op |= 004;
1446 if (newval)
1447 op |= 002;
1448 if (sysctl_perm(table, op))
1449 return -EPERM;
1450
1451 if (table->strategy) {
1452 rc = table->strategy(table, name, nlen, oldval, oldlenp,
1453 newval, newlen);
1454 if (rc < 0)
1455 return rc;
1456 if (rc > 0)
1457 return 0;
1458 }
1459
1460 /* If there is no strategy routine, or if the strategy returns
1461 * zero, proceed with automatic r/w */
1462 if (table->data && table->maxlen) {
1463 rc = sysctl_data(table, name, nlen, oldval, oldlenp,
1464 newval, newlen);
1465 if (rc < 0)
1466 return rc;
1467 }
1468 return 0;
1469}
1470
1471static int parse_table(int __user *name, int nlen,
1472 void __user *oldval, size_t __user *oldlenp,
1473 void __user *newval, size_t newlen,
1474 struct ctl_table *table)
1475{
1476 int n;
1477repeat:
1478 if (!nlen)
1479 return -ENOTDIR;
1480 if (get_user(n, name))
1481 return -EFAULT;
1482 for ( ; table->ctl_name || table->procname; table++) {
1483 if (!table->ctl_name)
1484 continue;
1485 if (n == table->ctl_name) {
1486 int error;
1487 if (table->child) {
1488 if (sysctl_perm(table, 001))
1489 return -EPERM;
1490 name++;
1491 nlen--;
1492 table = table->child;
1493 goto repeat;
1494 }
1495 error = do_sysctl_strategy(table, name, nlen,
1496 oldval, oldlenp,
1497 newval, newlen);
1498 return error;
1499 }
1500 }
1501 return -ENOTDIR;
1502}
1503
1442int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, 1504int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp,
1443 void __user *newval, size_t newlen) 1505 void __user *newval, size_t newlen)
1444{ 1506{
@@ -1511,76 +1573,6 @@ int sysctl_perm(struct ctl_table *table, int op)
1511 return test_perm(table->mode, op); 1573 return test_perm(table->mode, op);
1512} 1574}
1513 1575
1514#ifdef CONFIG_SYSCTL_SYSCALL
1515static int parse_table(int __user *name, int nlen,
1516 void __user *oldval, size_t __user *oldlenp,
1517 void __user *newval, size_t newlen,
1518 struct ctl_table *table)
1519{
1520 int n;
1521repeat:
1522 if (!nlen)
1523 return -ENOTDIR;
1524 if (get_user(n, name))
1525 return -EFAULT;
1526 for ( ; table->ctl_name || table->procname; table++) {
1527 if (!table->ctl_name)
1528 continue;
1529 if (n == table->ctl_name) {
1530 int error;
1531 if (table->child) {
1532 if (sysctl_perm(table, 001))
1533 return -EPERM;
1534 name++;
1535 nlen--;
1536 table = table->child;
1537 goto repeat;
1538 }
1539 error = do_sysctl_strategy(table, name, nlen,
1540 oldval, oldlenp,
1541 newval, newlen);
1542 return error;
1543 }
1544 }
1545 return -ENOTDIR;
1546}
1547
1548/* Perform the actual read/write of a sysctl table entry. */
1549int do_sysctl_strategy (struct ctl_table *table,
1550 int __user *name, int nlen,
1551 void __user *oldval, size_t __user *oldlenp,
1552 void __user *newval, size_t newlen)
1553{
1554 int op = 0, rc;
1555
1556 if (oldval)
1557 op |= 004;
1558 if (newval)
1559 op |= 002;
1560 if (sysctl_perm(table, op))
1561 return -EPERM;
1562
1563 if (table->strategy) {
1564 rc = table->strategy(table, name, nlen, oldval, oldlenp,
1565 newval, newlen);
1566 if (rc < 0)
1567 return rc;
1568 if (rc > 0)
1569 return 0;
1570 }
1571
1572 /* If there is no strategy routine, or if the strategy returns
1573 * zero, proceed with automatic r/w */
1574 if (table->data && table->maxlen) {
1575 rc = sysctl_data(table, name, nlen, oldval, oldlenp,
1576 newval, newlen);
1577 if (rc < 0)
1578 return rc;
1579 }
1580 return 0;
1581}
1582#endif /* CONFIG_SYSCTL_SYSCALL */
1583
1584static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table) 1576static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table)
1585{ 1577{
1586 for (; table->ctl_name || table->procname; table++) { 1578 for (; table->ctl_name || table->procname; table++) {