diff options
Diffstat (limited to 'arch/x86/kernel/alternative.c')
-rw-r--r-- | arch/x86/kernel/alternative.c | 9 |
1 files changed, 8 insertions, 1 deletions
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 0c92ad4d257a..df4099dc1c68 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -515,7 +515,7 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) | |||
515 | BUG_ON(len > sizeof(long)); | 515 | BUG_ON(len > sizeof(long)); |
516 | BUG_ON((((long)addr + len - 1) & ~(sizeof(long) - 1)) | 516 | BUG_ON((((long)addr + len - 1) & ~(sizeof(long) - 1)) |
517 | - ((long)addr & ~(sizeof(long) - 1))); | 517 | - ((long)addr & ~(sizeof(long) - 1))); |
518 | { | 518 | if (kernel_text_address((unsigned long)addr)) { |
519 | struct page *pages[2] = { virt_to_page(addr), | 519 | struct page *pages[2] = { virt_to_page(addr), |
520 | virt_to_page(addr + PAGE_SIZE) }; | 520 | virt_to_page(addr + PAGE_SIZE) }; |
521 | if (!pages[1]) | 521 | if (!pages[1]) |
@@ -526,6 +526,13 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) | |||
526 | memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); | 526 | memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); |
527 | local_irq_restore(flags); | 527 | local_irq_restore(flags); |
528 | vunmap(vaddr); | 528 | vunmap(vaddr); |
529 | } else { | ||
530 | /* | ||
531 | * modules are in vmalloc'ed memory, always writable. | ||
532 | */ | ||
533 | local_irq_save(flags); | ||
534 | memcpy(addr, opcode, len); | ||
535 | local_irq_restore(flags); | ||
529 | } | 536 | } |
530 | sync_core(); | 537 | sync_core(); |
531 | /* Could also do a CLFLUSH here to speed up CPU recovery; but | 538 | /* Could also do a CLFLUSH here to speed up CPU recovery; but |