diff options
| author | Josh Poimboeuf <jpoimboe@redhat.com> | 2015-12-03 17:33:26 -0500 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2015-12-04 16:51:07 -0500 |
| commit | b56b36ee6751abe7fb3890681e86fc8de2122953 (patch) | |
| tree | b95a1d26730cf2389214e303199c25bc160134c9 /kernel/livepatch | |
| parent | fc284d631894d8673d229fad92762b66c9875cab (diff) | |
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 <mbenes@suse.cz>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Diffstat (limited to 'kernel/livepatch')
| -rw-r--r-- | kernel/livepatch/core.c | 16 |
1 files changed, 11 insertions, 5 deletions
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 @@ | |||
| 28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
| 29 | #include <linux/kallsyms.h> | 29 | #include <linux/kallsyms.h> |
| 30 | #include <linux/livepatch.h> | 30 | #include <linux/livepatch.h> |
| 31 | #include <asm/cacheflush.h> | ||
| 31 | 32 | ||
| 32 | /** | 33 | /** |
| 33 | * struct klp_ops - structure for tracking registered ftrace ops structs | 34 | * 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, | |||
| 232 | static int klp_write_object_relocations(struct module *pmod, | 233 | static int klp_write_object_relocations(struct module *pmod, |
| 233 | struct klp_object *obj) | 234 | struct klp_object *obj) |
| 234 | { | 235 | { |
| 235 | int ret; | 236 | int ret = 0; |
| 236 | unsigned long val; | 237 | unsigned long val; |
| 237 | struct klp_reloc *reloc; | 238 | struct klp_reloc *reloc; |
| 238 | 239 | ||
| @@ -242,13 +243,16 @@ static int klp_write_object_relocations(struct module *pmod, | |||
| 242 | if (WARN_ON(!obj->relocs)) | 243 | if (WARN_ON(!obj->relocs)) |
| 243 | return -EINVAL; | 244 | return -EINVAL; |
| 244 | 245 | ||
| 246 | module_disable_ro(pmod); | ||
| 247 | |||
| 245 | for (reloc = obj->relocs; reloc->name; reloc++) { | 248 | for (reloc = obj->relocs; reloc->name; reloc++) { |
| 246 | /* discover the address of the referenced symbol */ | 249 | /* discover the address of the referenced symbol */ |
| 247 | if (reloc->external) { | 250 | if (reloc->external) { |
| 248 | if (reloc->sympos > 0) { | 251 | if (reloc->sympos > 0) { |
| 249 | pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n", | 252 | pr_err("non-zero sympos for external reloc symbol '%s' is not supported\n", |
| 250 | reloc->name); | 253 | reloc->name); |
| 251 | return -EINVAL; | 254 | ret = -EINVAL; |
| 255 | goto out; | ||
| 252 | } | 256 | } |
| 253 | ret = klp_find_external_symbol(pmod, reloc->name, &val); | 257 | ret = klp_find_external_symbol(pmod, reloc->name, &val); |
| 254 | } else | 258 | } else |
| @@ -257,18 +261,20 @@ static int klp_write_object_relocations(struct module *pmod, | |||
| 257 | reloc->sympos, | 261 | reloc->sympos, |
| 258 | &val); | 262 | &val); |
| 259 | if (ret) | 263 | if (ret) |
| 260 | return ret; | 264 | goto out; |
| 261 | 265 | ||
| 262 | ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc, | 266 | ret = klp_write_module_reloc(pmod, reloc->type, reloc->loc, |
| 263 | val + reloc->addend); | 267 | val + reloc->addend); |
| 264 | if (ret) { | 268 | if (ret) { |
| 265 | pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n", | 269 | pr_err("relocation failed for symbol '%s' at 0x%016lx (%d)\n", |
| 266 | reloc->name, val, ret); | 270 | reloc->name, val, ret); |
| 267 | return ret; | 271 | goto out; |
| 268 | } | 272 | } |
| 269 | } | 273 | } |
| 270 | 274 | ||
| 271 | return 0; | 275 | out: |
| 276 | module_enable_ro(pmod); | ||
| 277 | return ret; | ||
| 272 | } | 278 | } |
| 273 | 279 | ||
| 274 | static void notrace klp_ftrace_handler(unsigned long ip, | 280 | static void notrace klp_ftrace_handler(unsigned long ip, |
