diff mbox series

[v2,3/3] module: Make .static_call_sites read-only after init

Message ID 20250306131430.7016-4-petr.pavlu@suse.com (mailing list archive)
State New
Headers show
Series module: Make .static_call_sites read-only after init | expand

Checks

Context Check Description
mcgrof/vmtest-modules-next-VM_Test-0 success Logs for Run CI tests
mcgrof/vmtest-modules-next-VM_Test-2 fail Logs for cleanup / Archive results and cleanup
mcgrof/vmtest-modules-next-VM_Test-1 success Logs for Run CI tests
mcgrof/vmtest-modules-next-VM_Test-5 fail Logs for setup / Setup kdevops environment
mcgrof/vmtest-modules-next-VM_Test-3 fail Logs for cleanup / Archive results and cleanup
mcgrof/vmtest-modules-next-VM_Test-4 fail Logs for setup / Setup kdevops environment
mcgrof/vmtest-modules-next-PR fail PR summary

Commit Message

Petr Pavlu March 6, 2025, 1:13 p.m. UTC
Section .static_call_sites holds data structures that need to be sorted and
processed only at module load time. This initial processing happens in
static_call_add_module(), which is invoked as a callback to the
MODULE_STATE_COMING notification from prepare_coming_module().

The section is never modified afterwards. Make it therefore read-only after
module initialization to avoid any (non-)accidental modifications.

Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
---
 kernel/module/strict_rwx.c | 9 +++++++++
 1 file changed, 9 insertions(+)

Comments

Christophe Leroy March 6, 2025, 5:28 p.m. UTC | #1
Le 06/03/2025 à 14:13, Petr Pavlu a écrit :
> Section .static_call_sites holds data structures that need to be sorted and
> processed only at module load time. This initial processing happens in
> static_call_add_module(), which is invoked as a callback to the
> MODULE_STATE_COMING notification from prepare_coming_module().
> 
> The section is never modified afterwards. Make it therefore read-only after
> module initialization to avoid any (non-)accidental modifications.

Maybe this suggestion is stupid, I didn't investigate the feasability 
but: why don't we group everything that is ro_after_init in a single 
section just like we do in vmlinux ? That would avoid having to add 
every new possible section in the C code.

Like we have in asm-generic/vmlinux.lds.h:

#define RO_AFTER_INIT_DATA						\
	. = ALIGN(8);							\
	__start_ro_after_init = .;					\
	*(.data..ro_after_init)						\
	JUMP_TABLE_DATA							\
	STATIC_CALL_DATA						\
	__end_ro_after_init = .;


> 
> Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
> ---
>   kernel/module/strict_rwx.c | 9 +++++++++
>   1 file changed, 9 insertions(+)
> 
> diff --git a/kernel/module/strict_rwx.c b/kernel/module/strict_rwx.c
> index fa701dad4ed1..a3fc8d603750 100644
> --- a/kernel/module/strict_rwx.c
> +++ b/kernel/module/strict_rwx.c
> @@ -120,6 +120,15 @@ static const char *const ro_after_init[] = {
>   	 * section, which are marked as such at module load time.
>   	 */
>   	"__jump_table",
> +
> +#ifdef CONFIG_HAVE_STATIC_CALL_INLINE
> +	/*
> +	 * Section .static_call_sites holds data structures that need to be
> +	 * sorted and processed at module load time but are never modified
> +	 * afterwards.
> +	 */
> +	".static_call_sites",
> +#endif
>   };
>   
>   void module_mark_ro_after_init(const Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
Sami Tolvanen March 7, 2025, 12:12 a.m. UTC | #2
On Thu, Mar 06, 2025 at 06:28:58PM +0100, Christophe Leroy wrote:
> 
> 
> Le 06/03/2025 à 14:13, Petr Pavlu a écrit :
> > Section .static_call_sites holds data structures that need to be sorted and
> > processed only at module load time. This initial processing happens in
> > static_call_add_module(), which is invoked as a callback to the
> > MODULE_STATE_COMING notification from prepare_coming_module().
> > 
> > The section is never modified afterwards. Make it therefore read-only after
> > module initialization to avoid any (non-)accidental modifications.
> 
> Maybe this suggestion is stupid, I didn't investigate the feasability but:
> why don't we group everything that is ro_after_init in a single section just
> like we do in vmlinux ? That would avoid having to add every new possible
> section in the C code.
> 
> Like we have in asm-generic/vmlinux.lds.h:
> 
> #define RO_AFTER_INIT_DATA						\
> 	. = ALIGN(8);							\
> 	__start_ro_after_init = .;					\
> 	*(.data..ro_after_init)						\
> 	JUMP_TABLE_DATA							\
> 	STATIC_CALL_DATA						\
> 	__end_ro_after_init = .;

I like this idea. Grouping the sections in the module linker script
feels cleaner than having an array of section names in the code. To be
fair, I think this code predates v5.10, where scripts/module.lds.S was
first added.

Sami
Petr Pavlu March 12, 2025, 12:05 p.m. UTC | #3
On 3/7/25 01:12, Sami Tolvanen wrote:
> On Thu, Mar 06, 2025 at 06:28:58PM +0100, Christophe Leroy wrote:
>> Le 06/03/2025 à 14:13, Petr Pavlu a écrit :
>>> Section .static_call_sites holds data structures that need to be sorted and
>>> processed only at module load time. This initial processing happens in
>>> static_call_add_module(), which is invoked as a callback to the
>>> MODULE_STATE_COMING notification from prepare_coming_module().
>>>
>>> The section is never modified afterwards. Make it therefore read-only after
>>> module initialization to avoid any (non-)accidental modifications.
>>
>> Maybe this suggestion is stupid, I didn't investigate the feasability but:
>> why don't we group everything that is ro_after_init in a single section just
>> like we do in vmlinux ? That would avoid having to add every new possible
>> section in the C code.
>>
>> Like we have in asm-generic/vmlinux.lds.h:
>>
>> #define RO_AFTER_INIT_DATA						\
>> 	. = ALIGN(8);							\
>> 	__start_ro_after_init = .;					\
>> 	*(.data..ro_after_init)						\
>> 	JUMP_TABLE_DATA							\
>> 	STATIC_CALL_DATA						\
>> 	__end_ro_after_init = .;
> 
> I like this idea. Grouping the sections in the module linker script
> feels cleaner than having an array of section names in the code. To be
> fair, I think this code predates v5.10, where scripts/module.lds.S was
> first added.

I agree in principle. I like that the information about ro_after_init
sections for vmlinux and modules would be in the same source form, in
linker scripts. This could eventually allow us to share the definition
of ro_after_init sections between vmlinux and modules.

The problem is however how to find the location of the __jump_table and
static_call_sites data. In vmlinux, as a final binary, they are
annotated with start and end symbols. In modules, as relocatable files,
the approach is to rely on them being separate sections, see function
find_module_sections().

I could add start+end symbols for __jump_table and static_call_sites
data in scripts/module.lds.S and use them by the module loader, but this
would create an inconsistency in how various data is looked up. Another
problem is that I can't find a way to tell the linker to add these
symbols only if the specific data is actually present.
diff mbox series

Patch

diff --git a/kernel/module/strict_rwx.c b/kernel/module/strict_rwx.c
index fa701dad4ed1..a3fc8d603750 100644
--- a/kernel/module/strict_rwx.c
+++ b/kernel/module/strict_rwx.c
@@ -120,6 +120,15 @@  static const char *const ro_after_init[] = {
 	 * section, which are marked as such at module load time.
 	 */
 	"__jump_table",
+
+#ifdef CONFIG_HAVE_STATIC_CALL_INLINE
+	/*
+	 * Section .static_call_sites holds data structures that need to be
+	 * sorted and processed at module load time but are never modified
+	 * afterwards.
+	 */
+	".static_call_sites",
+#endif
 };
 
 void module_mark_ro_after_init(const Elf_Ehdr *hdr, Elf_Shdr *sechdrs,