]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
module: Add a separate function to mark sections as read-only after init
authorPetr Pavlu <petr.pavlu@suse.com>
Thu, 6 Mar 2025 13:13:53 +0000 (14:13 +0100)
committerPetr Pavlu <petr.pavlu@suse.com>
Sun, 18 May 2025 11:56:21 +0000 (13:56 +0200)
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 <samitolvanen@google.com>
Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Link: https://lore.kernel.org/r/20250306131430.7016-3-petr.pavlu@suse.com
Signed-off-by: Petr Pavlu <petr.pavlu@suse.com>
kernel/module/internal.h
kernel/module/main.c
kernel/module/strict_rwx.c

index e7ab2a2e7a322249dcaf90e20da48beaf3902069..8d74b0a21c82b5360977a29736eca78ee6b6be3e 100644 (file)
@@ -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);
index a2859dc3eea66ec19991e7e4afb5bbcae2c2d167..15781c2fb008aa4776f66d7426f26aa5bf172953 100644 (file)
@@ -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
index 9c20a2f3eaa427ade96ace5aeb60097d10785bed..7aab6a524eccc67ecc4dd12c687c9847c9f6d9b4 100644 (file)
@@ -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;
+                       }
+               }
+       }
+}