From 7523e4dc5057e157212b4741abd6256e03404cf1 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 26 Nov 2015 09:44:08 +1030 Subject: module: use a structure to encapsulate layout. Makes it easier to handle init vs core cleanly, though the change is fairly invasive across random architectures. It simplifies the rbtree code immediately, however, while keeping the core data together in the same cachline (now iff the rbtree code is enabled). Acked-by: Peter Zijlstra Reviewed-by: Josh Poimboeuf Signed-off-by: Rusty Russell Signed-off-by: Jiri Kosina --- arch/x86/kernel/livepatch.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/kernel/livepatch.c b/arch/x86/kernel/livepatch.c index d1d35ccffed3..bcc06e82a593 100644 --- a/arch/x86/kernel/livepatch.c +++ b/arch/x86/kernel/livepatch.c @@ -41,8 +41,8 @@ int klp_write_module_reloc(struct module *mod, unsigned long type, int ret, numpages, size = 4; bool readonly; unsigned long val; - unsigned long core = (unsigned long)mod->module_core; - unsigned long core_size = mod->core_size; + unsigned long core = (unsigned long)mod->core_layout.base; + unsigned long core_size = mod->core_layout.size; switch (type) { case R_X86_64_NONE: @@ -72,7 +72,7 @@ int klp_write_module_reloc(struct module *mod, unsigned long type, readonly = false; #ifdef CONFIG_DEBUG_SET_MODULE_RONX - if (loc < core + mod->core_ro_size) + if (loc < core + mod->core_layout.ro_size) readonly = true; #endif -- cgit v1.2.3 From b56b36ee6751abe7fb3890681e86fc8de2122953 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Thu, 3 Dec 2015 16:33:26 -0600 Subject: livepatch: Cleanup module page permission changes Calling set_memory_rw() and set_memory_ro() for every iteration of the loop in klp_write_object_relocations() is messy, inefficient, and error-prone. Change all the read-only pages to read-write before the loop and convert them back to read-only again afterwards. Suggested-by: Miroslav Benes Signed-off-by: Josh Poimboeuf Reviewed-by: Petr Mladek Signed-off-by: Jiri Kosina --- arch/x86/kernel/livepatch.c | 25 ++----------------------- kernel/livepatch/core.c | 16 +++++++++++----- 2 files changed, 13 insertions(+), 28 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/kernel/livepatch.c b/arch/x86/kernel/livepatch.c index bcc06e82a593..92fc1a51f994 100644 --- a/arch/x86/kernel/livepatch.c +++ b/arch/x86/kernel/livepatch.c @@ -20,8 +20,6 @@ #include #include -#include -#include #include #include @@ -38,8 +36,7 @@ int klp_write_module_reloc(struct module *mod, unsigned long type, unsigned long loc, unsigned long value) { - int ret, numpages, size = 4; - bool readonly; + size_t size = 4; unsigned long val; unsigned long core = (unsigned long)mod->core_layout.base; unsigned long core_size = mod->core_layout.size; @@ -69,23 +66,5 @@ int klp_write_module_reloc(struct module *mod, unsigned long type, /* loc does not point to any symbol inside the module */ return -EINVAL; - readonly = false; - -#ifdef CONFIG_DEBUG_SET_MODULE_RONX - if (loc < core + mod->core_layout.ro_size) - readonly = true; -#endif - - /* determine if the relocation spans a page boundary */ - numpages = ((loc & PAGE_MASK) == ((loc + size) & PAGE_MASK)) ? 1 : 2; - - if (readonly) - set_memory_rw(loc & PAGE_MASK, numpages); - - ret = probe_kernel_write((void *)loc, &val, size); - - if (readonly) - set_memory_ro(loc & PAGE_MASK, numpages); - - return ret; + return probe_kernel_write((void *)loc, &val, size); } diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c index 94893e844e44..bc2c85c064c1 100644 --- a/kernel/livepatch/core.c +++ b/kernel/livepatch/core.c @@ -28,6 +28,7 @@ #include #include #include +#include /** * struct klp_ops - structure for tracking registered ftrace ops structs @@ -232,7 +233,7 @@ static int klp_find_external_symbol(struct module *pmod, const char *name, static int klp_write_object_relocations(struct module *pmod, struct klp_object *obj) { - int ret; + int ret = 0; unsigned long val; struct klp_reloc *reloc; @@ -242,13 +243,16 @@ static int klp_write_object_relocations(struct module *pmod, if (WARN_ON(!obj->relocs)) return -EINVAL; + module_disable_ro(pmod); + for (reloc = obj->relocs; reloc->name; reloc++) { /* discover the address of the referenced symbol */ if (reloc->external) { if (reloc->sympos > 0) { pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n", reloc->name); - return -EINVAL; + ret = -EINVAL; + goto out; } ret = klp_find_external_symbol(pmod, reloc->name, &val); } else @@ -257,18 +261,20 @@ static int klp_write_object_relocations(struct module *pmod, reloc->sympos, &val); if (ret) - return ret; + goto out; ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc, val + reloc->addend); if (ret) { pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n", reloc->name, val, ret); - return ret; + goto out; } } - return 0; +out: + module_enable_ro(pmod); + return ret; } static void notrace klp_ftrace_handler(unsigned long ip, -- cgit v1.2.3