aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/fs/proc/proc_sysctl.c
diff options
context:
space:
mode:
authorJoel Granados <joel.granados@gmail.com>2023-08-09 12:49:57 +0200
committerLuis Chamberlain <mcgrof@kernel.org>2023-08-15 15:26:17 -0700
commitbff97cf11b261972cae90299432238cc9a9a6a51 (patch)
tree8ddd834cc0cd9d81af48189754485d9bc547920c /fs/proc/proc_sysctl.c
parentsysctl: Add size argument to init_header (diff)
downloadwireguard-linux-bff97cf11b261972cae90299432238cc9a9a6a51.tar.xz
wireguard-linux-bff97cf11b261972cae90299432238cc9a9a6a51.zip
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>
Diffstat (limited to 'fs/proc/proc_sysctl.c')
-rw-r--r--fs/proc/proc_sysctl.c23
1 files changed, 12 insertions, 11 deletions
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
index fa1438f1a355..b8dd78e344ff 100644
--- a/fs/proc/proc_sysctl.c
+++ b/fs/proc/proc_sysctl.c
@@ -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 @@ fail:
*/
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);