mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-28 16:56:26 +00:00
sysctl: Add a size arg to __register_sysctl_table
We make these changes in order to prepare __register_sysctl_table and its callers for when we remove the sentinel element (empty element at the end of ctl_table arrays). We don't actually remove any sentinels in this commit, but we *do* make sure to use ARRAY_SIZE so the table_size is available when the removal occurs. We add a table_size argument to __register_sysctl_table and adjust callers, all of which pass ctl_table pointers and need an explicit call to ARRAY_SIZE. We implement a size calculation in register_net_sysctl in order to forward the size of the array pointer received from the network register calls. The new table_size argument does not yet have any effect in the init_header call which is still dependent on the sentinel's presence. table_size *does* however drive the `kzalloc` allocation in __register_sysctl_table with no adverse effects as the allocated memory is either one element greater than the calculated ctl_table array (for the calls in ipc_sysctl.c, mq_sysctl.c and ucount.c) or the exact size of the calculated ctl_table array (for the call from sysctl_net.c and register_sysctl). This approach will allows us to "just" remove the sentinel without further changes to __register_sysctl_table as table_size will represent the exact size for all the callers at that point. Signed-off-by: Joel Granados <j.granados@samsung.com> Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
This commit is contained in:
parent
b1f01e2bae
commit
bff97cf11b
@ -1312,6 +1312,7 @@ static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
|
||||
* should not be free'd after registration. So it should not be
|
||||
* used on stack. It can either be a global or dynamically allocated
|
||||
* by the caller and free'd later after sysctl unregistration.
|
||||
* @table_size : The number of elements in table
|
||||
*
|
||||
* Register a sysctl table hierarchy. @table should be a filled in ctl_table
|
||||
* array. A completely 0 filled entry terminates the table.
|
||||
@ -1354,27 +1355,20 @@ static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
|
||||
*/
|
||||
struct ctl_table_header *__register_sysctl_table(
|
||||
struct ctl_table_set *set,
|
||||
const char *path, struct ctl_table *table)
|
||||
const char *path, struct ctl_table *table, size_t table_size)
|
||||
{
|
||||
struct ctl_table_root *root = set->dir.header.root;
|
||||
struct ctl_table_header *header;
|
||||
struct ctl_table_header h_tmp;
|
||||
struct ctl_dir *dir;
|
||||
struct ctl_table *entry;
|
||||
struct ctl_node *node;
|
||||
int nr_entries = 0;
|
||||
|
||||
h_tmp.ctl_table = table;
|
||||
list_for_each_table_entry(entry, (&h_tmp))
|
||||
nr_entries++;
|
||||
|
||||
header = kzalloc(sizeof(struct ctl_table_header) +
|
||||
sizeof(struct ctl_node)*nr_entries, GFP_KERNEL_ACCOUNT);
|
||||
sizeof(struct ctl_node)*table_size, GFP_KERNEL_ACCOUNT);
|
||||
if (!header)
|
||||
return NULL;
|
||||
|
||||
node = (struct ctl_node *)(header + 1);
|
||||
init_header(header, root, set, node, table, nr_entries);
|
||||
init_header(header, root, set, node, table, table_size);
|
||||
if (sysctl_check_table(path, header))
|
||||
goto fail;
|
||||
|
||||
@ -1423,8 +1417,15 @@ struct ctl_table_header *__register_sysctl_table(
|
||||
*/
|
||||
struct ctl_table_header *register_sysctl(const char *path, struct ctl_table *table)
|
||||
{
|
||||
int count = 0;
|
||||
struct ctl_table *entry;
|
||||
struct ctl_table_header t_hdr;
|
||||
|
||||
t_hdr.ctl_table = table;
|
||||
list_for_each_table_entry(entry, (&t_hdr))
|
||||
count++;
|
||||
return __register_sysctl_table(&sysctl_table_root.default_set,
|
||||
path, table);
|
||||
path, table, count);
|
||||
}
|
||||
EXPORT_SYMBOL(register_sysctl);
|
||||
|
||||
|
@ -226,7 +226,7 @@ extern void retire_sysctl_set(struct ctl_table_set *set);
|
||||
|
||||
struct ctl_table_header *__register_sysctl_table(
|
||||
struct ctl_table_set *set,
|
||||
const char *path, struct ctl_table *table);
|
||||
const char *path, struct ctl_table *table, size_t table_size);
|
||||
struct ctl_table_header *register_sysctl(const char *path, struct ctl_table *table);
|
||||
void unregister_sysctl_table(struct ctl_table_header * table);
|
||||
|
||||
|
@ -259,7 +259,9 @@ bool setup_ipc_sysctls(struct ipc_namespace *ns)
|
||||
tbl[i].data = NULL;
|
||||
}
|
||||
|
||||
ns->ipc_sysctls = __register_sysctl_table(&ns->ipc_set, "kernel", tbl);
|
||||
ns->ipc_sysctls = __register_sysctl_table(&ns->ipc_set,
|
||||
"kernel", tbl,
|
||||
ARRAY_SIZE(ipc_sysctls));
|
||||
}
|
||||
if (!ns->ipc_sysctls) {
|
||||
kfree(tbl);
|
||||
|
@ -109,7 +109,9 @@ bool setup_mq_sysctls(struct ipc_namespace *ns)
|
||||
tbl[i].data = NULL;
|
||||
}
|
||||
|
||||
ns->mq_sysctls = __register_sysctl_table(&ns->mq_set, "fs/mqueue", tbl);
|
||||
ns->mq_sysctls = __register_sysctl_table(&ns->mq_set,
|
||||
"fs/mqueue", tbl,
|
||||
ARRAY_SIZE(mq_sysctls));
|
||||
}
|
||||
if (!ns->mq_sysctls) {
|
||||
kfree(tbl);
|
||||
|
@ -104,7 +104,8 @@ bool setup_userns_sysctls(struct user_namespace *ns)
|
||||
for (i = 0; i < UCOUNT_COUNTS; i++) {
|
||||
tbl[i].data = &ns->ucount_max[i];
|
||||
}
|
||||
ns->sysctls = __register_sysctl_table(&ns->set, "user", tbl);
|
||||
ns->sysctls = __register_sysctl_table(&ns->set, "user", tbl,
|
||||
ARRAY_SIZE(user_table));
|
||||
}
|
||||
if (!ns->sysctls) {
|
||||
kfree(tbl);
|
||||
|
@ -163,10 +163,16 @@ static void ensure_safe_net_sysctl(struct net *net, const char *path,
|
||||
struct ctl_table_header *register_net_sysctl(struct net *net,
|
||||
const char *path, struct ctl_table *table)
|
||||
{
|
||||
int count = 0;
|
||||
struct ctl_table *entry;
|
||||
|
||||
if (!net_eq(net, &init_net))
|
||||
ensure_safe_net_sysctl(net, path, table);
|
||||
|
||||
return __register_sysctl_table(&net->sysctls, path, table);
|
||||
for (entry = table; entry->procname; entry++)
|
||||
count++;
|
||||
|
||||
return __register_sysctl_table(&net->sysctls, path, table, count);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(register_net_sysctl);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user