Merge tag 'modules-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 13 Mar 2024 19:40:58 +0000 (12:40 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 13 Mar 2024 19:40:58 +0000 (12:40 -0700)
Pull modules updates from Luis Chamberlain:
 "Christophe Leroy did most of the work on this release, first with a
  few cleanups on CONFIG_STRICT_KERNEL_RWX and ending with error
  handling for when set_memory_XX() can fail.

  This is part of a larger effort to clean up all these callers which
  can fail, modules is just part of it"

* tag 'modules-6.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/mcgrof/linux:
  module: Don't ignore errors from set_memory_XX()
  lib/test_kmod: fix kernel-doc warnings
  powerpc: Simplify strict_kernel_rwx_enabled()
  modules: Remove #ifdef CONFIG_STRICT_MODULE_RWX around rodata_enabled
  init: Declare rodata_enabled and mark_rodata_ro() at all time
  module: Change module_enable_{nx/x/ro}() to more explicit names
  module: Use set_memory_rox()

arch/powerpc/include/asm/mmu.h
include/linux/init.h
init/main.c
kernel/module/internal.h
kernel/module/main.c
kernel/module/strict_rwx.c
lib/test_kmod.c

index d8b7e246a32f5925bc09132bc56db598920fffb5..24241995f7406e7f30b3b0b2b8537fb3f59e85f1 100644 (file)
@@ -330,17 +330,10 @@ static __always_inline bool early_radix_enabled(void)
        return early_mmu_has_feature(MMU_FTR_TYPE_RADIX);
 }
 
-#ifdef CONFIG_STRICT_KERNEL_RWX
 static inline bool strict_kernel_rwx_enabled(void)
 {
-       return rodata_enabled;
+       return IS_ENABLED(CONFIG_STRICT_KERNEL_RWX) && rodata_enabled;
 }
-#else
-static inline bool strict_kernel_rwx_enabled(void)
-{
-       return false;
-}
-#endif
 
 static inline bool strict_module_rwx_enabled(void)
 {
index 3fa3f6241350b2a81226a58fc77e2e4d0135e78d..58cef4c2e59a625fdb59530ad46937ad2d968668 100644 (file)
@@ -168,12 +168,8 @@ extern initcall_entry_t __initcall_end[];
 
 extern struct file_system_type rootfs_fs_type;
 
-#if defined(CONFIG_STRICT_KERNEL_RWX) || defined(CONFIG_STRICT_MODULE_RWX)
 extern bool rodata_enabled;
-#endif
-#ifdef CONFIG_STRICT_KERNEL_RWX
 void mark_rodata_ro(void);
-#endif
 
 extern void (*late_time_init)(void);
 
index 7dce08198b13352357a1262138c71460da1cb584..d002f30f7f24c99e124149cea43f613c15818fbe 100644 (file)
@@ -1401,10 +1401,9 @@ static int __init set_debug_rodata(char *str)
 early_param("rodata", set_debug_rodata);
 #endif
 
-#ifdef CONFIG_STRICT_KERNEL_RWX
 static void mark_readonly(void)
 {
-       if (rodata_enabled) {
+       if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX) && rodata_enabled) {
                /*
                 * load_module() results in W+X mappings, which are cleaned
                 * up with call_rcu().  Let's make sure that queued work is
@@ -1414,20 +1413,14 @@ static void mark_readonly(void)
                rcu_barrier();
                mark_rodata_ro();
                rodata_test();
-       } else
+       } else if (IS_ENABLED(CONFIG_STRICT_KERNEL_RWX)) {
                pr_info("Kernel memory protection disabled.\n");
+       } else if (IS_ENABLED(CONFIG_ARCH_HAS_STRICT_KERNEL_RWX)) {
+               pr_warn("Kernel memory protection not selected by kernel config.\n");
+       } else {
+               pr_warn("This architecture does not have kernel memory protection.\n");
+       }
 }
-#elif defined(CONFIG_ARCH_HAS_STRICT_KERNEL_RWX)
-static inline void mark_readonly(void)
-{
-       pr_warn("Kernel memory protection not selected by kernel config.\n");
-}
-#else
-static inline void mark_readonly(void)
-{
-       pr_warn("This architecture does not have kernel memory protection.\n");
-}
-#endif
 
 void __weak free_initmem(void)
 {
index c8b7b4dcf7820dcfea57c5ea5003ac2094285855..2ebece8a789f52b9b544da0e13a4f7d919929309 100644 (file)
@@ -322,9 +322,9 @@ static inline struct module *mod_find(unsigned long addr, struct mod_tree_root *
 }
 #endif /* CONFIG_MODULES_TREE_LOOKUP */
 
-void module_enable_ro(const struct module *mod, bool after_init);
-void module_enable_nx(const struct module *mod);
-void module_enable_x(const struct module *mod);
+int module_enable_rodata_ro(const struct module *mod, bool after_init);
+int module_enable_data_nx(const struct module *mod);
+int module_enable_text_rox(const struct module *mod);
 int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
                                char *secstrings, struct module *mod);
 
index 36681911c05acd779c42d016ae7275a503c2ab9a..689def7676c4c957b38db9104a9976a4f22b15cc 100644 (file)
@@ -2571,7 +2571,9 @@ static noinline int do_init_module(struct module *mod)
        /* Switch to core kallsyms now init is done: kallsyms may be walking! */
        rcu_assign_pointer(mod->kallsyms, &mod->core_kallsyms);
 #endif
-       module_enable_ro(mod, true);
+       ret = module_enable_rodata_ro(mod, true);
+       if (ret)
+               goto fail_mutex_unlock;
        mod_tree_remove_init(mod);
        module_arch_freeing_init(mod);
        for_class_mod_mem_type(type, init) {
@@ -2609,6 +2611,8 @@ static noinline int do_init_module(struct module *mod)
 
        return 0;
 
+fail_mutex_unlock:
+       mutex_unlock(&module_mutex);
 fail_free_freeinit:
        kfree(freeinit);
 fail:
@@ -2736,9 +2740,15 @@ static int complete_formation(struct module *mod, struct load_info *info)
        module_bug_finalize(info->hdr, info->sechdrs, mod);
        module_cfi_finalize(info->hdr, info->sechdrs, mod);
 
-       module_enable_ro(mod, false);
-       module_enable_nx(mod);
-       module_enable_x(mod);
+       err = module_enable_rodata_ro(mod, false);
+       if (err)
+               goto out_strict_rwx;
+       err = module_enable_data_nx(mod);
+       if (err)
+               goto out_strict_rwx;
+       err = module_enable_text_rox(mod);
+       if (err)
+               goto out_strict_rwx;
 
        /*
         * Mark state as coming so strong_try_module_get() ignores us,
@@ -2749,6 +2759,8 @@ static int complete_formation(struct module *mod, struct load_info *info)
 
        return 0;
 
+out_strict_rwx:
+       module_bug_cleanup(mod);
 out:
        mutex_unlock(&module_mutex);
        return err;
index a2b656b4e3d2bec27c7cf5541b8a126904f36fc1..c45caa4690e536c8ccea525def8f8f01881c4a74 100644 (file)
 #include <linux/set_memory.h>
 #include "internal.h"
 
-static void module_set_memory(const struct module *mod, enum mod_mem_type type,
-                             int (*set_memory)(unsigned long start, int num_pages))
+static int module_set_memory(const struct module *mod, enum mod_mem_type type,
+                            int (*set_memory)(unsigned long start, int num_pages))
 {
        const struct module_memory *mod_mem = &mod->mem[type];
 
+       if (!mod_mem->base)
+               return 0;
+
        set_vm_flush_reset_perms(mod_mem->base);
-       set_memory((unsigned long)mod_mem->base, mod_mem->size >> PAGE_SHIFT);
+       return set_memory((unsigned long)mod_mem->base, mod_mem->size >> PAGE_SHIFT);
 }
 
 /*
@@ -26,37 +29,53 @@ static void module_set_memory(const struct module *mod, enum mod_mem_type type,
  * CONFIG_STRICT_MODULE_RWX because they are needed regardless of whether we
  * are strict.
  */
-void module_enable_x(const struct module *mod)
+int module_enable_text_rox(const struct module *mod)
 {
-       for_class_mod_mem_type(type, text)
-               module_set_memory(mod, type, set_memory_x);
+       for_class_mod_mem_type(type, text) {
+               int ret;
+
+               if (IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
+                       ret = module_set_memory(mod, type, set_memory_rox);
+               else
+                       ret = module_set_memory(mod, type, set_memory_x);
+               if (ret)
+                       return ret;
+       }
+       return 0;
 }
 
-void module_enable_ro(const struct module *mod, bool after_init)
+int module_enable_rodata_ro(const struct module *mod, bool after_init)
 {
-       if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
-               return;
-#ifdef CONFIG_STRICT_MODULE_RWX
-       if (!rodata_enabled)
-               return;
-#endif
+       int ret;
+
+       if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX) || !rodata_enabled)
+               return 0;
 
-       module_set_memory(mod, MOD_TEXT, set_memory_ro);
-       module_set_memory(mod, MOD_INIT_TEXT, set_memory_ro);
-       module_set_memory(mod, MOD_RODATA, set_memory_ro);
-       module_set_memory(mod, MOD_INIT_RODATA, set_memory_ro);
+       ret = module_set_memory(mod, MOD_RODATA, set_memory_ro);
+       if (ret)
+               return ret;
+       ret = module_set_memory(mod, MOD_INIT_RODATA, set_memory_ro);
+       if (ret)
+               return ret;
 
        if (after_init)
-               module_set_memory(mod, MOD_RO_AFTER_INIT, set_memory_ro);
+               return module_set_memory(mod, MOD_RO_AFTER_INIT, set_memory_ro);
+
+       return 0;
 }
 
-void module_enable_nx(const struct module *mod)
+int module_enable_data_nx(const struct module *mod)
 {
        if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
-               return;
+               return 0;
 
-       for_class_mod_mem_type(type, data)
-               module_set_memory(mod, type, set_memory_nx);
+       for_class_mod_mem_type(type, data) {
+               int ret = module_set_memory(mod, type, set_memory_nx);
+
+               if (ret)
+                       return ret;
+       }
+       return 0;
 }
 
 int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
index 43d9dfd57ab7d59c7a5c177e5906b7b28aeca7ee..1eec3b7ac67c29e532cd87a15895d9b7447088a3 100644 (file)
@@ -58,11 +58,14 @@ static int num_test_devs;
  * @need_mod_put for your tests case.
  */
 enum kmod_test_case {
+       /* private: */
        __TEST_KMOD_INVALID = 0,
+       /* public: */
 
        TEST_KMOD_DRIVER,
        TEST_KMOD_FS_TYPE,
 
+       /* private: */
        __TEST_KMOD_MAX,
 };
 
@@ -82,6 +85,7 @@ struct kmod_test_device;
  * @ret_sync: return value if request_module() is used, sync request for
  *     @TEST_KMOD_DRIVER
  * @fs_sync: return value of get_fs_type() for @TEST_KMOD_FS_TYPE
+ * @task_sync: kthread's task_struct or %NULL if not running
  * @thread_idx: thread ID
  * @test_dev: test device test is being performed under
  * @need_mod_put: Some tests (get_fs_type() is one) requires putting the module
@@ -108,7 +112,7 @@ struct kmod_test_device_info {
  * @dev: pointer to misc_dev's own struct device
  * @config_mutex: protects configuration of test
  * @trigger_mutex: the test trigger can only be fired once at a time
- * @thread_lock: protects @done count, and the @info per each thread
+ * @thread_mutex: protects @done count, and the @info per each thread
  * @done: number of threads which have completed or failed
  * @test_is_oom: when we run out of memory, use this to halt moving forward
  * @kthreads_done: completion used to signal when all work is done