aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/alternative.c
diff options
context:
space:
mode:
authorMathieu Desnoyers <mathieu.desnoyers@polymtl.ca>2008-03-12 11:54:16 -0400
committerIngo Molnar <mingo@elte.hu>2008-04-17 11:41:29 -0400
commit15a601eb9cdc2a9cc69d5fc745317805a85c064c (patch)
treeda93247e169e57a31917b934c8b200aab713658b /arch/x86/kernel/alternative.c
parente5699a8231593d0e11e65ccf248549935304dab1 (diff)
x86: fix test_poke for vmalloced pages
* Ingo Molnar (mingo@elte.hu) wrote: > > * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> wrote: > > > The shadow vmap for DEBUG_RODATA kernel text modification uses > > virt_to_page to get the pages from the pointer address. > > > > However, I think vmalloc_to_page would be required in case the page is > > used for modules. > > > > Since only the core kernel text is marked read-only, use > > kernel_text_address() to make sure we only shadow map the core kernel > > text, not modules. > > actually, i think we should mark module text readonly too. > Yes, but in the meantime, the x86 tree would need this patch to make kprobes work correctly on modules. I suspect that without this fix, with the enhanced hotplug and kprobes patch, kprobes will use text_poke to insert breakpoints in modules (vmalloced pages used), which will map the wrong pages and corrupt random kernel locations instead of updating the correct page. Work that would write protect the module pages should clearly be done, but it can come in a later time. We have to make sure we interact correctly with the page allocation debugging, as an example. Here is the patch against x86.git 2.6.25-rc5 : The shadow vmap for DEBUG_RODATA kernel text modification uses virt_to_page to get the pages from the pointer address. However, I think vmalloc_to_page would be required in case the page is used for modules. Since only the core kernel text is marked read-only, use kernel_text_address() to make sure we only shadow map the core kernel text, not modules. Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> CC: akpm@linux-foundation.org Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/alternative.c')
-rw-r--r--arch/x86/kernel/alternative.c9
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