Re: [PATCH RFC v2 03/13] sysctl, mod_devicetable: add macro MODULE_SYSCTL_TABLE

Mauricio Faria de Oliveira <[email protected]>
Newsgroups dev.linux.lists.mptcp,dev.linux.lists.sashiko-reviews,org.kernel.vger.bpf,org.kernel.vger.linux-s390
Message-ID <[email protected]>
On 2026-08-18 23:40, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
> - [High] The file2alias.c handler for sysctl device tables is entirely missing from the patch, resulting in no module aliases being generated.

This is handled in a later patch.

> - [High] `__UNIQUE_ID` is used without arguments, preventing its expansion and causing redefinition compiler errors.

Fixed.

> - [High] Pointers in device table structs cannot be dereferenced by modpost without relocation resolution.
> - [High] modpost cannot parse `struct ctl_table` due to randomized layout and nested pointers.
> - [High] Macro generates a single struct, but modpost expects a NULL-terminated array.

These are handled in later patches.

> - [Medium] The MODULE_SYSCTL_TABLE macro silently accepts pointers instead of arrays, resulting in an invalid table_size.

Fixed.

Note: this case has been checked during design, and it fails due to
pointers not being constant but used as static initializers (must be
constant); however, there's indeed a exposure with constant pointers
(e.g., 'static const struct ctl_table *const ptr' -- not seen in
practice, but theoretically possible).


> --
> 
> --- Patch [3]: [PATCH RFC v2 03/13] sysctl, mod_devicetable: add macro MODULE_SYSCTL_TABLE ---
> commit 4b00a2bf658ca058127bbaaa61c3c168a3a4574c
> Author: Mauricio Faria de Oliveira <[email protected]>
> 
> sysctl, mod_devicetable: add macro MODULE_SYSCTL_TABLE
> 
> This commit adds the MODULE_SYSCTL_TABLE macro to emit a struct
> module_sysctl_table variable containing pointers to a sysctl table's path
> and entries. It also adds the necessary struct definitions and field
> offsets for modpost integration.
> 
>> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
>> index a397213bedace..818a4a53448db 100644
>> --- a/include/linux/mod_devicetable.h
>> +++ b/include/linux/mod_devicetable.h
> 
> [ ... ]
> 
>> @@ -78,4 +78,11 @@ struct cpu_feature {
>>  	__u16	feature;
>>  };
>> 
>> +struct module_sysctl_table {
>> +	kernel_ulong_t path;
>> +	kernel_ulong_t table;
> 
> [Severity: High]
> Does modpost know how to read these external pointers?
> 
> Modpost's file2alias.c extracts raw bytes from the struct and typically
> does not resolve relocations to dereference .rodata or .data pointers. Will
> this prevent modpost from actually reading the path or table strings/data
> from unlinked ELF object files (.o)?
> 
>> +	__u16 table_size;
>> +	__u16 entry_size;
>> +};
>> +
>>  #endif /* LINUX_MOD_DEVICETABLE_H */
>> diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
>> index e5d7226ab6f5a..6960fe22c50bf 100644
>> --- a/include/linux/sysctl.h
>> +++ b/include/linux/sysctl.h
> 
> [ ... ]
> 
>> @@ -293,6 +293,48 @@ struct ctl_table_root {
>>  	int (*permissions)(struct ctl_table_header *head, const struct ctl_table *table);
>>  };
>> 
>> +/*
>> + * Creates a symbol so file2alias.c can find the sysctl table.
>> + *
>> + * MODULE_SYSCTL_TABLE() is the sysctl equivalent of MODULE_DEVICE_TABLE(),
>> + * with pointers to a sysctl table's path and entries, and table/entry sizes.
>> + *
>> + * The parameters 'path' and 'table' must be static (e.g., string literal or
>> + * static char[]; static struct ctl_table[]) as both are used as initializer
>> + * elements for a static struct variable.
>> + *
>> + * The generated symbol name contains 'table' by default. However, if 'table'
>> + * is a struct field (contains '.' or '->'), in order to avoid syntax errors,
>> + * define the macro SYSCTL_MODULE_ALIASES_UNIQUE_ID.
>> + *
>> + * Define the macro SYSCTL_MODULE_ALIASES_DISABLE to disable this.
>> + */
>> +#if defined(CONFIG_SYSCTL_MODULE_ALIASES) && defined(MODULE) &&			\
>> +    !defined(SYSCTL_MODULE_ALIASES_DISABLE)
>> +
>> +#include <linux/module.h>
>> +#include <linux/mod_devicetable.h>
>> +
>> +#if defined(SYSCTL_MODULE_ALIASES_UNIQUE_ID)
>> +#define __MODULE_SYSCTL_TABLE_NAME(table)					\
>> +	__mod_device_table(sysctl, __UNIQUE_ID)
> 
> [Severity: High]
> Does this use of __UNIQUE_ID work correctly without an argument?
> 
> Since __UNIQUE_ID is a function-like macro, using it without parentheses
> prevents its expansion. This could result in the preprocessor treating it
> as a literal token, generating a variable name like ...__sysctl____UNIQUE_ID
> and causing redefinition errors if invoked multiple times in the same file.
> 
>> +#else
>> +#define __MODULE_SYSCTL_TABLE_NAME(table)					\
>> +	__mod_device_table(sysctl, table)
>> +#endif
>> +
>> +#define MODULE_SYSCTL_TABLE(path, table)					\
>> +	static struct module_sysctl_table __used				\
>> +		__MODULE_SYSCTL_TABLE_NAME(table) = {				\
> 
> [Severity: High]
> Will this work with modpost's do_table() logic?
> 
> This macro generates a single struct instance, but modpost expects all
> __mod_device_table symbols to point to an array terminated by an all-zero
> element. Scanning this single struct could cause a build-time
> "not terminated with a NULL entry" error when it sees non-zero bytes.
> 
>> +			(kernel_ulong_t) path,					\
>> +			(kernel_ulong_t) table,					\
> 
> [Severity: High]
> If modpost attempts to parse struct ctl_table through this pointer, how does
> it handle a randomized struct layout?
> 
> Since struct ctl_table can be marked with __randomize_layout when
> CONFIG_RANDSTRUCT is enabled, a host tool like modpost cannot reliably extract
> information from these entries without having the field offsets explicitly
> exported in devicetable-offsets.c.
> 
>> +			(u16) sizeof(table),					\
> 
> [Severity: Medium]
> Can this silently evaluate to a pointer size instead of the array size?
> 
> If a pointer to a ctl_table is passed instead of a static array, sizeof(table)
> evaluates to the pointer size, leading to an incorrect table size being
> emitted. Could this be protected using __must_be_array(table)?
> 
>> +			(u16) sizeof(const struct ctl_table)			\
>> +		}
>> +#else
>> +#define MODULE_SYSCTL_TABLE(path, table)
>> +#endif
>> +
>>  #define register_sysctl(path, table)	\
>>  	register_sysctl_sz(path, table, ARRAY_SIZE(table))
>> 
>> diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
>> index b4178c42d08f5..e3b8855e6ebcf 100644
>> --- a/scripts/mod/devicetable-offsets.c
>> +++ b/scripts/mod/devicetable-offsets.c
> 
> [ ... ]
> 
>> @@ -284,5 +284,11 @@ int main(void)
>>  	DEVID(coreboot_device_id);
>>  	DEVID_FIELD(coreboot_device_id, tag);
>> 
>> +	DEVID(module_sysctl_table);
> 
> [Severity: High]
> Where is the file2alias.c handler for sysctl device tables?
> 
> The commit message mentions this symbol will be handled by file2alias.c,
> but the patch does not appear to add the corresponding entry in the
> devtable[] array to actually parse the new struct. Will this result in
> no module aliases being generated at all?
> 
>> +	DEVID_FIELD(module_sysctl_table, path);
>> +	DEVID_FIELD(module_sysctl_table, table);
>> +	DEVID_FIELD(module_sysctl_table, table_size);
>> +	DEVID_FIELD(module_sysctl_table, entry_size);
>> +
>>  	return 0;
>>  }

-- 
Mauricio
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.