diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2007-11-30 07:54:00 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:55:17 -0500 |
commit | e51b6ba077791f2f8c876022b37419be7a2ceec3 (patch) | |
tree | 9d8ca18f3239eff84cad5b79b715c332970fa89d /kernel/sysctl.c | |
parent | 23eb06de7d2d333a0f7ebba2da663e00c9c9483e (diff) |
sysctl: Infrastructure for per namespace sysctls
This patch implements the basic infrastructure for per namespace sysctls.
A list of lists of sysctl headers is added, allowing each namespace to have
it's own list of sysctl headers.
Each list of sysctl headers has a lookup function to find the first
sysctl header in the list, allowing the lists to have a per namespace
instance.
register_sysct_root is added to tell sysctl.c about additional
lists of sysctl_headers. As all of the users are expected to be in
kernel no unregister function is provided.
sysctl_head_next is updated to walk through the list of lists.
__register_sysctl_paths is added to add a new sysctl table on
a non-default sysctl list.
The only intrusive part of this patch is propagating the information
to decided which list of sysctls to use for sysctl_check_table.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
Cc: Serge Hallyn <serue@us.ibm.com>
Cc: Daniel Lezcano <dlezcano@fr.ibm.com>
Cc: Cedric Le Goater <clg@fr.ibm.com>
Cc: Pavel Emelyanov <xemul@openvz.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'kernel/sysctl.c')
-rw-r--r-- | kernel/sysctl.c | 93 |
1 files changed, 82 insertions, 11 deletions
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 89b7d95ecf51..45e76f209dcb 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -157,8 +157,16 @@ static int proc_dointvec_taint(struct ctl_table *table, int write, struct file * | |||
157 | #endif | 157 | #endif |
158 | 158 | ||
159 | static struct ctl_table root_table[]; | 159 | static struct ctl_table root_table[]; |
160 | static struct ctl_table_header root_table_header = | 160 | static struct ctl_table_root sysctl_table_root; |
161 | { root_table, LIST_HEAD_INIT(root_table_header.ctl_entry) }; | 161 | static struct ctl_table_header root_table_header = { |
162 | .ctl_table = root_table, | ||
163 | .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.header_list), | ||
164 | .root = &sysctl_table_root, | ||
165 | }; | ||
166 | static struct ctl_table_root sysctl_table_root = { | ||
167 | .root_list = LIST_HEAD_INIT(sysctl_table_root.root_list), | ||
168 | .header_list = LIST_HEAD_INIT(root_table_header.ctl_entry), | ||
169 | }; | ||
162 | 170 | ||
163 | static struct ctl_table kern_table[]; | 171 | static struct ctl_table kern_table[]; |
164 | static struct ctl_table vm_table[]; | 172 | static struct ctl_table vm_table[]; |
@@ -1371,12 +1379,27 @@ void sysctl_head_finish(struct ctl_table_header *head) | |||
1371 | spin_unlock(&sysctl_lock); | 1379 | spin_unlock(&sysctl_lock); |
1372 | } | 1380 | } |
1373 | 1381 | ||
1374 | struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev) | 1382 | static struct list_head * |
1383 | lookup_header_list(struct ctl_table_root *root, struct nsproxy *namespaces) | ||
1375 | { | 1384 | { |
1385 | struct list_head *header_list; | ||
1386 | header_list = &root->header_list; | ||
1387 | if (root->lookup) | ||
1388 | header_list = root->lookup(root, namespaces); | ||
1389 | return header_list; | ||
1390 | } | ||
1391 | |||
1392 | struct ctl_table_header *__sysctl_head_next(struct nsproxy *namespaces, | ||
1393 | struct ctl_table_header *prev) | ||
1394 | { | ||
1395 | struct ctl_table_root *root; | ||
1396 | struct list_head *header_list; | ||
1376 | struct ctl_table_header *head; | 1397 | struct ctl_table_header *head; |
1377 | struct list_head *tmp; | 1398 | struct list_head *tmp; |
1399 | |||
1378 | spin_lock(&sysctl_lock); | 1400 | spin_lock(&sysctl_lock); |
1379 | if (prev) { | 1401 | if (prev) { |
1402 | head = prev; | ||
1380 | tmp = &prev->ctl_entry; | 1403 | tmp = &prev->ctl_entry; |
1381 | unuse_table(prev); | 1404 | unuse_table(prev); |
1382 | goto next; | 1405 | goto next; |
@@ -1390,14 +1413,38 @@ struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev) | |||
1390 | spin_unlock(&sysctl_lock); | 1413 | spin_unlock(&sysctl_lock); |
1391 | return head; | 1414 | return head; |
1392 | next: | 1415 | next: |
1416 | root = head->root; | ||
1393 | tmp = tmp->next; | 1417 | tmp = tmp->next; |
1394 | if (tmp == &root_table_header.ctl_entry) | 1418 | header_list = lookup_header_list(root, namespaces); |
1395 | break; | 1419 | if (tmp != header_list) |
1420 | continue; | ||
1421 | |||
1422 | do { | ||
1423 | root = list_entry(root->root_list.next, | ||
1424 | struct ctl_table_root, root_list); | ||
1425 | if (root == &sysctl_table_root) | ||
1426 | goto out; | ||
1427 | header_list = lookup_header_list(root, namespaces); | ||
1428 | } while (list_empty(header_list)); | ||
1429 | tmp = header_list->next; | ||
1396 | } | 1430 | } |
1431 | out: | ||
1397 | spin_unlock(&sysctl_lock); | 1432 | spin_unlock(&sysctl_lock); |
1398 | return NULL; | 1433 | return NULL; |
1399 | } | 1434 | } |
1400 | 1435 | ||
1436 | struct ctl_table_header *sysctl_head_next(struct ctl_table_header *prev) | ||
1437 | { | ||
1438 | return __sysctl_head_next(current->nsproxy, prev); | ||
1439 | } | ||
1440 | |||
1441 | void register_sysctl_root(struct ctl_table_root *root) | ||
1442 | { | ||
1443 | spin_lock(&sysctl_lock); | ||
1444 | list_add_tail(&root->root_list, &sysctl_table_root.root_list); | ||
1445 | spin_unlock(&sysctl_lock); | ||
1446 | } | ||
1447 | |||
1401 | #ifdef CONFIG_SYSCTL_SYSCALL | 1448 | #ifdef CONFIG_SYSCTL_SYSCALL |
1402 | int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, | 1449 | int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *oldlenp, |
1403 | void __user *newval, size_t newlen) | 1450 | void __user *newval, size_t newlen) |
@@ -1554,14 +1601,16 @@ static __init int sysctl_init(void) | |||
1554 | { | 1601 | { |
1555 | int err; | 1602 | int err; |
1556 | sysctl_set_parent(NULL, root_table); | 1603 | sysctl_set_parent(NULL, root_table); |
1557 | err = sysctl_check_table(root_table); | 1604 | err = sysctl_check_table(current->nsproxy, root_table); |
1558 | return 0; | 1605 | return 0; |
1559 | } | 1606 | } |
1560 | 1607 | ||
1561 | core_initcall(sysctl_init); | 1608 | core_initcall(sysctl_init); |
1562 | 1609 | ||
1563 | /** | 1610 | /** |
1564 | * register_sysctl_paths - register a sysctl hierarchy | 1611 | * __register_sysctl_paths - register a sysctl hierarchy |
1612 | * @root: List of sysctl headers to register on | ||
1613 | * @namespaces: Data to compute which lists of sysctl entries are visible | ||
1565 | * @path: The path to the directory the sysctl table is in. | 1614 | * @path: The path to the directory the sysctl table is in. |
1566 | * @table: the top-level table structure | 1615 | * @table: the top-level table structure |
1567 | * | 1616 | * |
@@ -1629,9 +1678,12 @@ core_initcall(sysctl_init); | |||
1629 | * This routine returns %NULL on a failure to register, and a pointer | 1678 | * This routine returns %NULL on a failure to register, and a pointer |
1630 | * to the table header on success. | 1679 | * to the table header on success. |
1631 | */ | 1680 | */ |
1632 | struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, | 1681 | struct ctl_table_header *__register_sysctl_paths( |
1633 | struct ctl_table *table) | 1682 | struct ctl_table_root *root, |
1683 | struct nsproxy *namespaces, | ||
1684 | const struct ctl_path *path, struct ctl_table *table) | ||
1634 | { | 1685 | { |
1686 | struct list_head *header_list; | ||
1635 | struct ctl_table_header *header; | 1687 | struct ctl_table_header *header; |
1636 | struct ctl_table *new, **prevp; | 1688 | struct ctl_table *new, **prevp; |
1637 | unsigned int n, npath; | 1689 | unsigned int n, npath; |
@@ -1674,19 +1726,38 @@ struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, | |||
1674 | INIT_LIST_HEAD(&header->ctl_entry); | 1726 | INIT_LIST_HEAD(&header->ctl_entry); |
1675 | header->used = 0; | 1727 | header->used = 0; |
1676 | header->unregistering = NULL; | 1728 | header->unregistering = NULL; |
1729 | header->root = root; | ||
1677 | sysctl_set_parent(NULL, header->ctl_table); | 1730 | sysctl_set_parent(NULL, header->ctl_table); |
1678 | if (sysctl_check_table(header->ctl_table)) { | 1731 | if (sysctl_check_table(namespaces, header->ctl_table)) { |
1679 | kfree(header); | 1732 | kfree(header); |
1680 | return NULL; | 1733 | return NULL; |
1681 | } | 1734 | } |
1682 | spin_lock(&sysctl_lock); | 1735 | spin_lock(&sysctl_lock); |
1683 | list_add_tail(&header->ctl_entry, &root_table_header.ctl_entry); | 1736 | header_list = lookup_header_list(root, namespaces); |
1737 | list_add_tail(&header->ctl_entry, header_list); | ||
1684 | spin_unlock(&sysctl_lock); | 1738 | spin_unlock(&sysctl_lock); |
1685 | 1739 | ||
1686 | return header; | 1740 | return header; |
1687 | } | 1741 | } |
1688 | 1742 | ||
1689 | /** | 1743 | /** |
1744 | * register_sysctl_table_path - register a sysctl table hierarchy | ||
1745 | * @path: The path to the directory the sysctl table is in. | ||
1746 | * @table: the top-level table structure | ||
1747 | * | ||
1748 | * Register a sysctl table hierarchy. @table should be a filled in ctl_table | ||
1749 | * array. A completely 0 filled entry terminates the table. | ||
1750 | * | ||
1751 | * See __register_sysctl_paths for more details. | ||
1752 | */ | ||
1753 | struct ctl_table_header *register_sysctl_paths(const struct ctl_path *path, | ||
1754 | struct ctl_table *table) | ||
1755 | { | ||
1756 | return __register_sysctl_paths(&sysctl_table_root, current->nsproxy, | ||
1757 | path, table); | ||
1758 | } | ||
1759 | |||
1760 | /** | ||
1690 | * register_sysctl_table - register a sysctl table hierarchy | 1761 | * register_sysctl_table - register a sysctl table hierarchy |
1691 | * @table: the top-level table structure | 1762 | * @table: the top-level table structure |
1692 | * | 1763 | * |