From f7984942630b0508c44276ceaa3a3a47d8fd3d2c Mon Sep 17 00:00:00 2001 From: Petr Pavlu Date: Thu, 6 Mar 2025 14:13:53 +0100 Subject: [PATCH] module: Add a separate function to mark sections as read-only after init Move the logic to mark special sections as read-only after module initialization into a separate function, along other related code in strict_rwx.c. Use a table with names of such sections to make it easier to add more. Reviewed-by: Sami Tolvanen Reviewed-by: Luis Chamberlain Link: https://lore.kernel.org/r/20250306131430.7016-3-petr.pavlu@suse.com Signed-off-by: Petr Pavlu --- kernel/module/internal.h | 2 ++ kernel/module/main.c | 18 +++--------------- kernel/module/strict_rwx.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 15 deletions(-) diff --git a/kernel/module/internal.h b/kernel/module/internal.h index e7ab2a2e7a322..8d74b0a21c82b 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -325,6 +325,8 @@ int module_enable_text_rox(const struct module *mod); int module_enforce_rwx_sections(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, const char *secstrings, const struct module *mod); +void module_mark_ro_after_init(const Elf_Ehdr *hdr, Elf_Shdr *sechdrs, + const char *secstrings); #ifdef CONFIG_MODULE_SIG int module_sig_check(struct load_info *info, int flags); diff --git a/kernel/module/main.c b/kernel/module/main.c index a2859dc3eea66..15781c2fb008a 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -2768,7 +2768,6 @@ core_param(module_blacklist, module_blacklist, charp, 0400); static struct module *layout_and_allocate(struct load_info *info, int flags) { struct module *mod; - unsigned int ndx; int err; /* Allow arches to frob section contents and sizes. */ @@ -2786,22 +2785,11 @@ static struct module *layout_and_allocate(struct load_info *info, int flags) info->sechdrs[info->index.pcpu].sh_flags &= ~(unsigned long)SHF_ALLOC; /* - * Mark ro_after_init section with SHF_RO_AFTER_INIT so that - * layout_sections() can put it in the right place. + * Mark relevant sections as SHF_RO_AFTER_INIT so layout_sections() can + * put them in the right place. * Note: ro_after_init sections also have SHF_{WRITE,ALLOC} set. */ - ndx = find_sec(info, ".data..ro_after_init"); - if (ndx) - info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT; - /* - * Mark the __jump_table section as ro_after_init as well: these data - * structures are never modified, with the exception of entries that - * refer to code in the __init section, which are annotated as such - * at module load time. - */ - ndx = find_sec(info, "__jump_table"); - if (ndx) - info->sechdrs[ndx].sh_flags |= SHF_RO_AFTER_INIT; + module_mark_ro_after_init(info->hdr, info->sechdrs, info->secstrings); /* * Determine total sizes, and put offsets in sh_entsize. For now diff --git a/kernel/module/strict_rwx.c b/kernel/module/strict_rwx.c index 9c20a2f3eaa42..7aab6a524eccc 100644 --- a/kernel/module/strict_rwx.c +++ b/kernel/module/strict_rwx.c @@ -107,3 +107,36 @@ int module_enforce_rwx_sections(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, return 0; } + +static const char *const ro_after_init[] = { + /* + * Section .data..ro_after_init holds data explicitly annotated by + * __ro_after_init. + */ + ".data..ro_after_init", + + /* + * Section __jump_table holds data structures that are never modified, + * with the exception of entries that refer to code in the __init + * section, which are marked as such at module load time. + */ + "__jump_table", +}; + +void module_mark_ro_after_init(const Elf_Ehdr *hdr, Elf_Shdr *sechdrs, + const char *secstrings) +{ + int i, j; + + for (i = 1; i < hdr->e_shnum; i++) { + Elf_Shdr *shdr = &sechdrs[i]; + + for (j = 0; j < ARRAY_SIZE(ro_after_init); j++) { + if (strcmp(secstrings + shdr->sh_name, + ro_after_init[j]) == 0) { + shdr->sh_flags |= SHF_RO_AFTER_INIT; + break; + } + } + } +} -- 2.39.5