Skip to content

Commit bff97cf

Browse files
Joelgranadosmcgrof
authored andcommitted
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 <[email protected]> Signed-off-by: Luis Chamberlain <[email protected]>
1 parent b1f01e2 commit bff97cf

File tree

6 files changed

+28
-16
lines changed

6 files changed

+28
-16
lines changed

fs/proc/proc_sysctl.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,7 @@ static struct ctl_dir *sysctl_mkdir_p(struct ctl_dir *dir, const char *path)
13121312
* should not be free'd after registration. So it should not be
13131313
* used on stack. It can either be a global or dynamically allocated
13141314
* by the caller and free'd later after sysctl unregistration.
1315+
* @table_size : The number of elements in table
13151316
*
13161317
* Register a sysctl table hierarchy. @table should be a filled in ctl_table
13171318
* 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)
13541355
*/
13551356
struct ctl_table_header *__register_sysctl_table(
13561357
struct ctl_table_set *set,
1357-
const char *path, struct ctl_table *table)
1358+
const char *path, struct ctl_table *table, size_t table_size)
13581359
{
13591360
struct ctl_table_root *root = set->dir.header.root;
13601361
struct ctl_table_header *header;
1361-
struct ctl_table_header h_tmp;
13621362
struct ctl_dir *dir;
1363-
struct ctl_table *entry;
13641363
struct ctl_node *node;
1365-
int nr_entries = 0;
1366-
1367-
h_tmp.ctl_table = table;
1368-
list_for_each_table_entry(entry, (&h_tmp))
1369-
nr_entries++;
13701364

13711365
header = kzalloc(sizeof(struct ctl_table_header) +
1372-
sizeof(struct ctl_node)*nr_entries, GFP_KERNEL_ACCOUNT);
1366+
sizeof(struct ctl_node)*table_size, GFP_KERNEL_ACCOUNT);
13731367
if (!header)
13741368
return NULL;
13751369

13761370
node = (struct ctl_node *)(header + 1);
1377-
init_header(header, root, set, node, table, nr_entries);
1371+
init_header(header, root, set, node, table, table_size);
13781372
if (sysctl_check_table(path, header))
13791373
goto fail;
13801374

@@ -1423,8 +1417,15 @@ struct ctl_table_header *__register_sysctl_table(
14231417
*/
14241418
struct ctl_table_header *register_sysctl(const char *path, struct ctl_table *table)
14251419
{
1420+
int count = 0;
1421+
struct ctl_table *entry;
1422+
struct ctl_table_header t_hdr;
1423+
1424+
t_hdr.ctl_table = table;
1425+
list_for_each_table_entry(entry, (&t_hdr))
1426+
count++;
14261427
return __register_sysctl_table(&sysctl_table_root.default_set,
1427-
path, table);
1428+
path, table, count);
14281429
}
14291430
EXPORT_SYMBOL(register_sysctl);
14301431

include/linux/sysctl.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ extern void retire_sysctl_set(struct ctl_table_set *set);
226226

227227
struct ctl_table_header *__register_sysctl_table(
228228
struct ctl_table_set *set,
229-
const char *path, struct ctl_table *table);
229+
const char *path, struct ctl_table *table, size_t table_size);
230230
struct ctl_table_header *register_sysctl(const char *path, struct ctl_table *table);
231231
void unregister_sysctl_table(struct ctl_table_header * table);
232232

ipc/ipc_sysctl.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,9 @@ bool setup_ipc_sysctls(struct ipc_namespace *ns)
259259
tbl[i].data = NULL;
260260
}
261261

262-
ns->ipc_sysctls = __register_sysctl_table(&ns->ipc_set, "kernel", tbl);
262+
ns->ipc_sysctls = __register_sysctl_table(&ns->ipc_set,
263+
"kernel", tbl,
264+
ARRAY_SIZE(ipc_sysctls));
263265
}
264266
if (!ns->ipc_sysctls) {
265267
kfree(tbl);

ipc/mq_sysctl.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,9 @@ bool setup_mq_sysctls(struct ipc_namespace *ns)
109109
tbl[i].data = NULL;
110110
}
111111

112-
ns->mq_sysctls = __register_sysctl_table(&ns->mq_set, "fs/mqueue", tbl);
112+
ns->mq_sysctls = __register_sysctl_table(&ns->mq_set,
113+
"fs/mqueue", tbl,
114+
ARRAY_SIZE(mq_sysctls));
113115
}
114116
if (!ns->mq_sysctls) {
115117
kfree(tbl);

kernel/ucount.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,8 @@ bool setup_userns_sysctls(struct user_namespace *ns)
104104
for (i = 0; i < UCOUNT_COUNTS; i++) {
105105
tbl[i].data = &ns->ucount_max[i];
106106
}
107-
ns->sysctls = __register_sysctl_table(&ns->set, "user", tbl);
107+
ns->sysctls = __register_sysctl_table(&ns->set, "user", tbl,
108+
ARRAY_SIZE(user_table));
108109
}
109110
if (!ns->sysctls) {
110111
kfree(tbl);

net/sysctl_net.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,10 +163,16 @@ static void ensure_safe_net_sysctl(struct net *net, const char *path,
163163
struct ctl_table_header *register_net_sysctl(struct net *net,
164164
const char *path, struct ctl_table *table)
165165
{
166+
int count = 0;
167+
struct ctl_table *entry;
168+
166169
if (!net_eq(net, &init_net))
167170
ensure_safe_net_sysctl(net, path, table);
168171

169-
return __register_sysctl_table(&net->sysctls, path, table);
172+
for (entry = table; entry->procname; entry++)
173+
count++;
174+
175+
return __register_sysctl_table(&net->sysctls, path, table, count);
170176
}
171177
EXPORT_SYMBOL_GPL(register_net_sysctl);
172178

0 commit comments

Comments
 (0)