module: Rework layout alignment to avoid BUG_ON()s
authorChristophe Leroy <christophe.leroy@csgroup.eu>
Wed, 23 Feb 2022 09:01:00 +0000 (10:01 +0100)
committerLuis Chamberlain <mcgrof@kernel.org>
Tue, 5 Apr 2022 15:43:04 +0000 (08:43 -0700)
Perform layout alignment verification up front and WARN_ON()
and fail module loading instead of crashing the machine.

Signed-off-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Luis Chamberlain <mcgrof@kernel.org>
kernel/module/internal.h
kernel/module/main.c
kernel/module/strict_rwx.c

index c59473b..e94defb 100644 (file)
@@ -180,6 +180,7 @@ void module_enable_nx(const struct module *mod);
 void module_enable_x(const struct module *mod);
 int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
                                char *secstrings, struct module *mod);
+bool module_check_misalignment(const struct module *mod);
 
 #ifdef CONFIG_MODULE_SIG
 int module_sig_check(struct load_info *info, int flags);
index 7175b44..55e710b 100644 (file)
@@ -2550,6 +2550,9 @@ static int complete_formation(struct module *mod, struct load_info *info)
        /* This relies on module_mutex for list integrity. */
        module_bug_finalize(info->hdr, info->sechdrs, mod);
 
+       if (module_check_misalignment(mod))
+               goto out_misaligned;
+
        module_enable_ro(mod, false);
        module_enable_nx(mod);
        module_enable_x(mod);
@@ -2563,6 +2566,8 @@ static int complete_formation(struct module *mod, struct load_info *info)
 
        return 0;
 
+out_misaligned:
+       err = -EINVAL;
 out:
        mutex_unlock(&module_mutex);
        return err;
index 43332b4..f36ea54 100644 (file)
@@ -42,9 +42,6 @@ static void frob_text(const struct module_layout *layout,
 static void frob_rodata(const struct module_layout *layout,
                 int (*set_memory)(unsigned long start, int num_pages))
 {
-       BUG_ON(!PAGE_ALIGNED(layout->base));
-       BUG_ON(!PAGE_ALIGNED(layout->text_size));
-       BUG_ON(!PAGE_ALIGNED(layout->ro_size));
        set_memory((unsigned long)layout->base + layout->text_size,
                   (layout->ro_size - layout->text_size) >> PAGE_SHIFT);
 }
@@ -52,9 +49,6 @@ static void frob_rodata(const struct module_layout *layout,
 static void frob_ro_after_init(const struct module_layout *layout,
                        int (*set_memory)(unsigned long start, int num_pages))
 {
-       BUG_ON(!PAGE_ALIGNED(layout->base));
-       BUG_ON(!PAGE_ALIGNED(layout->ro_size));
-       BUG_ON(!PAGE_ALIGNED(layout->ro_after_init_size));
        set_memory((unsigned long)layout->base + layout->ro_size,
                   (layout->ro_after_init_size - layout->ro_size) >> PAGE_SHIFT);
 }
@@ -62,13 +56,28 @@ static void frob_ro_after_init(const struct module_layout *layout,
 static void frob_writable_data(const struct module_layout *layout,
                        int (*set_memory)(unsigned long start, int num_pages))
 {
-       BUG_ON(!PAGE_ALIGNED(layout->base));
-       BUG_ON(!PAGE_ALIGNED(layout->ro_after_init_size));
-       BUG_ON(!PAGE_ALIGNED(layout->size));
        set_memory((unsigned long)layout->base + layout->ro_after_init_size,
                   (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT);
 }
 
+static bool layout_check_misalignment(const struct module_layout *layout)
+{
+       return WARN_ON(!PAGE_ALIGNED(layout->base)) ||
+              WARN_ON(!PAGE_ALIGNED(layout->text_size)) ||
+              WARN_ON(!PAGE_ALIGNED(layout->ro_size)) ||
+              WARN_ON(!PAGE_ALIGNED(layout->ro_after_init_size)) ||
+              WARN_ON(!PAGE_ALIGNED(layout->size));
+}
+
+bool module_check_misalignment(const struct module *mod)
+{
+       if (!IS_ENABLED(CONFIG_STRICT_MODULE_RWX))
+               return false;
+
+       return layout_check_misalignment(&mod->core_layout) ||
+              layout_check_misalignment(&mod->init_layout);
+}
+
 void module_enable_x(const struct module *mod)
 {
        if (!PAGE_ALIGNED(mod->core_layout.base) ||