Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=ed724be65fa18833244d81b484e425fc838837fa
Commit:     ed724be65fa18833244d81b484e425fc838837fa
Parent:     f316fe687521fad5ad2fd8389397c38aa97439d2
Author:     Arjan van de Ven <[EMAIL PROTECTED]>
AuthorDate: Wed Jan 30 13:34:04 2008 +0100
Committer:  Ingo Molnar <[EMAIL PROTECTED]>
CommitDate: Wed Jan 30 13:34:04 2008 +0100

    x86: turn the check_exec function into function that
    
    What the check_exec() function really is trying to do is enforce certain
    bits in the pgprot that are required by the x86 architecture, but that
    callers might not be aware of (such as NX bit exclusion of the BIOS
    area for BIOS based PCI access; it's not uncommon to ioremap the BIOS
    region for various purposes and normally ioremap() memory has the NX bit
    set).
    
    This patch turns the check_exec() function into static_protections()
    which also is now used to make sure the kernel text area remains non-NX
    and that the .rodata section remains read-only. If the architecture
    ends up requiring more such mandatory prot settings for specific areas,
    this is now a reasonable place to add these.
    
    Signed-off-by: Arjan van de Ven <[EMAIL PROTECTED]>
    Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>
    Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
---
 arch/x86/mm/pageattr.c |   47 +++++++++++++++++++++++++++++++++++++----------
 1 files changed, 37 insertions(+), 10 deletions(-)

diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c
index cbe8e92..00f6f34 100644
--- a/arch/x86/mm/pageattr.c
+++ b/arch/x86/mm/pageattr.c
@@ -24,22 +24,49 @@ void clflush_cache_range(void *addr, int size)
 #include <asm/pgalloc.h>
 
 /*
- * We allow the BIOS range to be executable:
+ * We must allow the BIOS range to be executable:
  */
 #define BIOS_BEGIN             0x000a0000
 #define BIOS_END               0x00100000
 
-static inline pgprot_t check_exec(pgprot_t prot, unsigned long address)
+static inline int
+within(unsigned long addr, unsigned long start, unsigned long end)
 {
-       if (__pa(address) >= BIOS_BEGIN && __pa(address) < BIOS_END)
-               pgprot_val(prot) &= ~_PAGE_NX;
+       return addr >= start && addr < end;
+}
+
+/*
+ * Certain areas of memory on x86 require very specific protection flags,
+ * for example the BIOS area or kernel text. Callers don't always get this
+ * right (again, ioremap() on BIOS memory is not uncommon) so this function
+ * checks and fixes these known static required protection bits.
+ */
+static inline pgprot_t static_protections(pgprot_t prot, unsigned long address)
+{
+       pgprot_t forbidden = __pgprot(0);
+
        /*
-        * Better fail early if someone sets the kernel text to NX.
-        * Does not cover __inittext
+        * The BIOS area between 640k and 1Mb needs to be executable for
+        * PCI BIOS based config access (CONFIG_PCI_GOBIOS) support.
         */
-       BUG_ON(address >= (unsigned long)&_text &&
-               address < (unsigned long)&_etext &&
-              (pgprot_val(prot) & _PAGE_NX));
+       if (within(__pa(address), BIOS_BEGIN, BIOS_END))
+               pgprot_val(forbidden) |= _PAGE_NX;
+
+       /*
+        * The kernel text needs to be executable for obvious reasons
+        * Does not cover __inittext since that is gone later on
+        */
+       if (within(address, (unsigned long)_text, (unsigned long)_etext))
+               pgprot_val(forbidden) |= _PAGE_NX;
+
+#ifdef CONFIG_DEBUG_RODATA
+       /* The .rodata section needs to be read-only */
+       if (within(address, (unsigned long)__start_rodata,
+                               (unsigned long)__end_rodata))
+               pgprot_val(forbidden) |= _PAGE_RW;
+#endif
+
+       prot = __pgprot(pgprot_val(prot) & ~pgprot_val(forbidden));
 
        return prot;
 }
@@ -169,7 +196,7 @@ repeat:
        BUG_ON(PageLRU(kpte_page));
        BUG_ON(PageCompound(kpte_page));
 
-       prot = check_exec(prot, address);
+       prot = static_protections(prot, address);
 
        if (level == PG_LEVEL_4K) {
                set_pte_atomic(kpte, pfn_pte(pfn, canon_pgprot(prot)));
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to