diff options
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r-- | kernel/sysctl.c | 144 |
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; | |||
145 | extern int max_lock_depth; | 145 | extern int max_lock_depth; |
146 | #endif | 146 | #endif |
147 | 147 | ||
148 | #ifdef CONFIG_SYSCTL_SYSCALL | ||
149 | static 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 |
155 | static int proc_do_cad_pid(struct ctl_table *table, int write, struct file *filp, | 149 | static 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. */ | ||
1437 | static 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 | |||
1471 | static 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; | ||
1477 | repeat: | ||
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 | |||
1442 | int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, | 1504 | int 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 | ||
1515 | static 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; | ||
1521 | repeat: | ||
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. */ | ||
1549 | int 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 | |||
1584 | static void sysctl_set_parent(struct ctl_table *parent, struct ctl_table *table) | 1576 | static 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++) { |