Re: [PATCH] sysctl: avoid spurious permanent empty tables

From: Nathan Chancellor
Date: Fri Sep 13 2024 - 19:41:00 EST


Hi Thomas,

Sorry for the delay in my response.

On Tue, Aug 27, 2024 at 11:54:43AM +0200, Thomas Weißschuh wrote:
> The test if a table is a permanently empty one, inspects the address of
> the registered ctl_table argument.
> However as sysctl_mount_point is an empty array and does not occupy and
> space it can end up sharing an address with another object in memory.
> If that other object itself is a "struct ctl_table" then registering
> that table will fail as it's incorrectly recognized as permanently empty.
>
> Avoid this issue by adding a dummy element to the array so that the
> array is not empty anymore and the potential address sharing is avoided.
> Explicitly register the table with zero elements as otherwise the dummy
> element would be recognized as a sentinel element which would lead to a
> runtime warning from the sysctl core.
>
> While the issue seems unlikely to be encountered at this time, this
> seems mostly be due to luck.
> Also a future change, constifying sysctl_mount_point and root_table, can
> reliably trigger this issue on clang 18.
>
> Given that empty arrays are non-standard in the first place,
> avoid them if possible.
>
> Reported-by: kernel test robot <oliver.sang@xxxxxxxxx>
> Closes: https://lore.kernel.org/oe-lkp/202408051453.f638857e-lkp@xxxxxxxxx
> Fixes: 4a7b29f65094 ("sysctl: move sysctl type to ctl_table_header")
> Fixes: a35dd3a786f5 ("sysctl: drop now unnecessary out-of-bounds check")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Thomas Weißschuh <linux@xxxxxxxxxxxxxx>
> ---
> This was originally part of a feature series [0], but is resubmitted on
> its own to make it into v6.11To.

It might be too late for 6.11 final since nobody seems to have picked it
up at this point but maybe it could make 6.12-rc1 and be backported in
one of the first couple of stable releases?

Regardless, thanks for sending the patch.

Acked-by: Nathan Chancellor <nathan@xxxxxxxxxx>

> [0] https://lore.kernel.org/lkml/20240805-sysctl-const-api-v2-0-52c85f02ee5e@xxxxxxxxxxxxxx/
> ---
> fs/proc/proc_sysctl.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c
> index 9553e77c9d31..d11ebc055ce0 100644
> --- a/fs/proc/proc_sysctl.c
> +++ b/fs/proc/proc_sysctl.c
> @@ -29,8 +29,13 @@ static const struct inode_operations proc_sys_inode_operations;
> static const struct file_operations proc_sys_dir_file_operations;
> static const struct inode_operations proc_sys_dir_operations;
>
> -/* Support for permanently empty directories */
> -static struct ctl_table sysctl_mount_point[] = { };
> +/*
> + * Support for permanently empty directories.
> + * Must be non-empty to avoid sharing an address with other tables.
> + */
> +static struct ctl_table sysctl_mount_point[] = {
> + { }
> +};
>
> /**
> * register_sysctl_mount_point() - registers a sysctl mount point
> @@ -42,7 +47,7 @@ static struct ctl_table sysctl_mount_point[] = { };
> */
> struct ctl_table_header *register_sysctl_mount_point(const char *path)
> {
> - return register_sysctl(path, sysctl_mount_point);
> + return register_sysctl_sz(path, sysctl_mount_point, 0);
> }
> EXPORT_SYMBOL(register_sysctl_mount_point);
>
>
> ---
> base-commit: 3e9bff3bbe1355805de919f688bef4baefbfd436
> change-id: 20240827-sysctl-const-shared-identity-9ab816e5fdfb
>
> Best regards,
> --
> Thomas Weißschuh <linux@xxxxxxxxxxxxxx>
>