x86, cpa: Fix kernel text RO checks in static_protection()
authorSuresh Siddha <suresh.b.siddha@intel.com>
Thu, 29 Oct 2009 02:46:56 +0000 (18:46 -0800)
committerIngo Molnar <mingo@elte.hu>
Mon, 2 Nov 2009 16:16:35 +0000 (17:16 +0100)
Steven Rostedt reported that we are unconditionally making the
kernel text mapping as read-only. i.e., if someone does cpa() to
the kernel text area for setting/clearing any page table
attribute, we unconditionally clear the read-write attribute for
the kernel text mapping that is set at compile time.

We should delay (to forbid the write attribute) and enforce only
after the kernel has mapped the text as read-only.

Reported-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Acked-by: Steven Rostedt <rostedt@goodmis.org>
Tested-by: Steven Rostedt <rostedt@goodmis.org>
LKML-Reference: <20091029024820.996634347@sbs-t61.sc.intel.com>
[ marked kernel_set_to_readonly as __read_mostly ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/include/asm/cacheflush.h
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/pageattr.c

index b54f6afe7ec4e2fb8406c8ac16fd48b6bb82ff6d..eebb2cd2b9bf972117d41d4d164b69a1c5883e37 100644 (file)
@@ -176,6 +176,7 @@ void clflush_cache_range(void *addr, unsigned int size);
 #ifdef CONFIG_DEBUG_RODATA
 void mark_rodata_ro(void);
 extern const int rodata_test_data;
+extern int kernel_set_to_readonly;
 void set_kernel_text_rw(void);
 void set_kernel_text_ro(void);
 #else
index f64d0d5e0f89a42585d45bd354a934ab543e0bf4..c973f8e2a6cf1db740c6f22ec5bc50bfb65bcc67 100644 (file)
@@ -997,7 +997,7 @@ static noinline int do_test_wp_bit(void)
 const int rodata_test_data = 0xC3;
 EXPORT_SYMBOL_GPL(rodata_test_data);
 
-static int kernel_set_to_readonly;
+int kernel_set_to_readonly __read_mostly;
 
 void set_kernel_text_rw(void)
 {
index 0ed09fad6aa1558024194cd75afaba4f03516549..4b507c089402bfb2531c1f715968a871a206d889 100644 (file)
@@ -695,7 +695,7 @@ void __init mem_init(void)
 const int rodata_test_data = 0xC3;
 EXPORT_SYMBOL_GPL(rodata_test_data);
 
-static int kernel_set_to_readonly;
+int kernel_set_to_readonly;
 
 void set_kernel_text_rw(void)
 {
index 78d3168b3c6438e663ff78bedcfb37ab726ddd73..8d1e8d95ea45d99b189c13e32b2229a89be2bce0 100644 (file)
@@ -282,14 +282,16 @@ static inline pgprot_t static_protections(pgprot_t prot, unsigned long address,
 #if defined(CONFIG_X86_64) && defined(CONFIG_DEBUG_RODATA) && \
        !defined(CONFIG_DYNAMIC_FTRACE)
        /*
-        * Kernel text mappings for the large page aligned .rodata section
-        * will be read-only. For the kernel identity mappings covering
-        * the holes caused by this alignment can be anything.
+        * Once the kernel maps the text as RO (kernel_set_to_readonly is set),
+        * kernel text mappings for the large page aligned text, rodata sections
+        * will be always read-only. For the kernel identity mappings covering
+        * the holes caused by this alignment can be anything that user asks.
         *
         * This will preserve the large page mappings for kernel text/data
         * at no extra cost.
         */
-       if (within(address, (unsigned long)_text,
+       if (kernel_set_to_readonly &&
+           within(address, (unsigned long)_text,
                   (unsigned long)__end_rodata_hpage_align))
                pgprot_val(forbidden) |= _PAGE_RW;
 #endif