lkml.org 
[lkml]   [2007]   [Jul]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 3/8] Text Edit Lock - i386
    Interface to use for code patching : makes sure the page is writable
    between calls to kernel_text_mark_rw() and kernel_text_unmark().

    Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
    ---
    arch/i386/mm/init.c | 60 ++++++++++++++++++++++++++++++++----------
    include/asm-i386/cacheflush.h | 9 ++++++
    2 files changed, 56 insertions(+), 13 deletions(-)

    Index: linux-2.6-lttng/arch/i386/mm/init.c
    ===================================================================
    --- linux-2.6-lttng.orig/arch/i386/mm/init.c 2007-07-13 17:01:24.000000000 -0400
    +++ linux-2.6-lttng/arch/i386/mm/init.c 2007-07-13 17:02:31.000000000 -0400
    @@ -31,6 +31,7 @@
    #include <linux/memory_hotplug.h>
    #include <linux/initrd.h>
    #include <linux/cpumask.h>
    +#include <linux/kprobes.h>

    #include <asm/processor.h>
    #include <asm/system.h>
    @@ -53,6 +54,10 @@

    static int noinline do_test_wp_bit(void);

    +#ifdef CONFIG_DEBUG_RODATA
    +static int rodata_marked;
    +#endif
    +
    /*
    * Creates a middle page table and puts a pointer to it in the
    * given global directory entry. This only returns the gd entry
    @@ -796,24 +801,16 @@
    }

    #ifdef CONFIG_DEBUG_RODATA
    -
    void mark_rodata_ro(void)
    {
    unsigned long start = PFN_ALIGN(_text);
    unsigned long size = PFN_ALIGN(_etext) - start;

    -#ifndef CONFIG_KPROBES
    -#ifdef CONFIG_HOTPLUG_CPU
    - /* It must still be possible to apply SMP alternatives. */
    - if (num_possible_cpus() <= 1)
    -#endif
    - {
    - change_page_attr(virt_to_page(start),
    - size >> PAGE_SHIFT, PAGE_KERNEL_RX);
    - printk("Write protecting the kernel text: %luk\n", size >> 10);
    - kernel_text_is_ro = 1;
    - }
    -#endif
    + change_page_attr(virt_to_page(start),
    + size >> PAGE_SHIFT, PAGE_KERNEL_RX);
    + printk("Write protecting the kernel text: %luk\n", size >> 10);
    + kernel_text_is_ro = 1;
    +
    start += size;
    size = (unsigned long)__end_rodata - start;
    change_page_attr(virt_to_page(start),
    @@ -828,9 +825,46 @@
    * of who is the culprit.
    */
    global_flush_tlb();
    + rodata_marked = 1;
    +}
    +
    +/*
    + * Lock the kernel text for mutual write exclusion.
    + * Make sure the pages are writable.
    + */
    +void __kprobes kernel_text_mark_rw(unsigned long address, size_t len)
    +{
    + if (rodata_marked && address >= PFN_ALIGN(_text)
    + && (address + len) <= PFN_ALIGN(_etext)) {
    + unsigned long nr_pages;
    + nr_pages = ((address + len) >> PAGE_SHIFT)
    + - (address >> PAGE_SHIFT) + 1;
    + change_page_attr(virt_to_page(address), nr_pages,
    + PAGE_KERNEL_EXEC);
    + mb();
    + global_flush_tlb();
    + mb();
    + }
    }
    +EXPORT_SYMBOL_GPL(kernel_text_mark_rw);
    #endif

    +void __kprobes kernel_text_unmark(unsigned long address, size_t len)
    +{
    + if (rodata_marked && address >= PFN_ALIGN(_text)
    + && (address + len) <= PFN_ALIGN(_etext)) {
    + unsigned long nr_pages;
    + nr_pages = ((address + len) >> PAGE_SHIFT)
    + - (address >> PAGE_SHIFT) + 1;
    + change_page_attr(virt_to_page(address), nr_pages,
    + PAGE_KERNEL_RX);
    + mb();
    + global_flush_tlb();
    + mb();
    + }
    +}
    +EXPORT_SYMBOL_GPL(kernel_text_unmark);
    +
    void free_init_pages(char *what, unsigned long begin, unsigned long end)
    {
    unsigned long addr;
    Index: linux-2.6-lttng/include/asm-i386/cacheflush.h
    ===================================================================
    --- linux-2.6-lttng.orig/include/asm-i386/cacheflush.h 2007-07-13 17:01:24.000000000 -0400
    +++ linux-2.6-lttng/include/asm-i386/cacheflush.h 2007-07-13 17:01:26.000000000 -0400
    @@ -36,4 +36,13 @@
    void mark_rodata_ro(void);
    #endif

    +#if defined(CONFIG_DEBUG_RODATA)
    +/* mark kernel text pages writable */
    +extern void kernel_text_mark_rw(unsigned long address, size_t len);
    +extern void kernel_text_unmark(unsigned long address, size_t len);
    +#else
    +void kernel_text_mark_rw(unsigned long address, size_t len) { }
    +void kernel_text_unmark(unsigned long address, size_t len) { }
    +#endif
    +
    #endif /* _I386_CACHEFLUSH_H */
    --
    Mathieu Desnoyers
    Computer Engineering Ph.D. Student, Ecole Polytechnique de Montreal
    OpenPGP key fingerprint: 8CD5 52C3 8E3C 4140 715F BA06 3F25 A8FE 3BAE 9A68
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-07-14 03:27    [W:4.129 / U:0.620 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site