diff --git a/include/linux/module.h b/include/linux/module.h index 7937f33945144417a7b76381c96b8f8b85bf65ab..d7c6792d705b04b1fe6a0670526fc92305cebe3b 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -887,6 +887,14 @@ extern int module_sysfs_initialized; #define __MODULE_STRING(x) __stringify(x) +#ifdef CONFIG_STRICT_MODULE_RWX +extern void module_enable_ro(const struct module *mod, bool after_init); +extern void module_disable_ro(const struct module *mod); +#else +static inline void module_enable_ro(const struct module *mod, bool after_init) { } +static inline void module_disable_ro(const struct module *mod) { } +#endif + #ifdef CONFIG_GENERIC_BUG void module_bug_finalize(const Elf_Ehdr *, const Elf_Shdr *, struct module *); diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index b1b80b1c6d3e6f230891c8c51d0b2650260bab1b..ccfb0f4e5569540f7a1529a669d1461b17b18918 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -968,6 +968,7 @@ static int klp_init_object_loaded(struct klp_patch *patch, struct klp_func *func; int ret; + module_disable_ro(patch->mod); if (klp_is_module(obj)) { /* * Only write module-specific relocations here @@ -976,9 +977,12 @@ static int klp_init_object_loaded(struct klp_patch *patch, * itself. */ ret = klp_apply_object_relocs(patch, obj); - if (ret) + if (ret) { + module_enable_ro(patch->mod, true); return ret; + } } + module_enable_ro(patch->mod, true); klp_for_each_func(obj, func) { ret = klp_find_object_symbol(obj->name, func->old_name, @@ -1147,10 +1151,14 @@ static int klp_init_patch(struct klp_patch *patch) } set_mod_klp_rel_state(patch->mod, MODULE_KLP_REL_DONE); + module_disable_ro(patch->mod); jump_label_apply_nops(patch->mod); ret = jump_label_register(patch->mod); - if (ret) + if (ret) { + module_enable_ro(patch->mod, true); goto out; + } + module_enable_ro(patch->mod, true); #ifdef CONFIG_LIVEPATCH_STOP_MACHINE_CONSISTENCY klp_for_each_object(patch, obj) diff --git a/kernel/module.c b/kernel/module.c index b87b333b7bde769512159619e630d77c7006067b..a54dda703feb7ef438e7b593c49dfe29524c6d89 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2063,7 +2063,20 @@ static void frob_writable_data(const struct module_layout *layout, (layout->size - layout->ro_after_init_size) >> PAGE_SHIFT); } -static void module_enable_ro(const struct module *mod, bool after_init) +/* livepatching wants to disable read-only so it can frob module. */ +void module_disable_ro(const struct module *mod) +{ + if (!rodata_enabled) + return; + + frob_text(&mod->core_layout, set_memory_rw); + frob_rodata(&mod->core_layout, set_memory_rw); + frob_ro_after_init(&mod->core_layout, set_memory_rw); + frob_text(&mod->init_layout, set_memory_rw); + frob_rodata(&mod->init_layout, set_memory_rw); +} + +void module_enable_ro(const struct module *mod, bool after_init) { if (!rodata_enabled) return; @@ -2108,7 +2121,6 @@ static int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, #else /* !CONFIG_STRICT_MODULE_RWX */ static void module_enable_nx(const struct module *mod) { } -static void module_enable_ro(const struct module *mod, bool after_init) {} static int module_enforce_rwx_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, char *secstrings, struct module *mod) {