diff options
author | Christophe Leroy <christophe.leroy@csgroup.eu> | 2022-02-23 10:01:00 +0100 |
---|---|---|
committer | Luis Chamberlain <mcgrof@kernel.org> | 2022-04-05 17:43:04 +0200 |
commit | ef505058dc5524488a84423b4d5e8a7598a23a2e (patch) | |
tree | 335a6a86daae4db2d7bf305df6439fa4bf53dbb6 /kernel | |
parent | module: Move module_enable_x() and frob_text() in strict_rwx.c (diff) | |
download | linux-ef505058dc5524488a84423b4d5e8a7598a23a2e.tar.xz linux-ef505058dc5524488a84423b4d5e8a7598a23a2e.zip |
module: Rework layout alignment to avoid BUG_ON()s
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>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/module/internal.h | 1 | ||||
-rw-r--r-- | kernel/module/main.c | 5 | ||||
-rw-r--r-- | kernel/module/strict_rwx.c | 27 |
3 files changed, 24 insertions, 9 deletions
diff --git a/kernel/module/internal.h b/kernel/module/internal.h index c59473b232df..e94defbeda00 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -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); diff --git a/kernel/module/main.c b/kernel/module/main.c index 7175b44ba88a..55e710bc7f46 100644 --- a/kernel/module/main.c +++ b/kernel/module/main.c @@ -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; diff --git a/kernel/module/strict_rwx.c b/kernel/module/strict_rwx.c index 43332b4416b0..f36ea54c1dac 100644 --- a/kernel/module/strict_rwx.c +++ b/kernel/module/strict_rwx.c @@ -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) || |