diff -urNp linux-2.6.32.18/arch/sparc/kernel/module.c linux-2.6.32.18-new/arch/sparc/kernel/module.c --- linux-2.6.32.18/arch/sparc/kernel/module.c 2010-08-10 13:45:57.000000000 -0400 +++ linux-2.6.32.18-new/arch/sparc/kernel/module.c 2010-08-12 00:02:38.000000000 -0400 @@ -18,7 +18,7 @@ #include #ifdef CONFIG_SPARC64 -static void *module_map(unsigned long size) +static void *__module_alloc(unsigned long size, pgprot_t prot) { struct vm_struct *area; @@ -30,7 +30,7 @@ static void *module_map(unsigned long si if (!area) return NULL; - return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL); + return __vmalloc_area(area, GFP_KERNEL | __GFP_ZERO, prot); } static char *dot2underscore(char *name) @@ -55,21 +55,32 @@ static char *dot2underscore(char *name) #endif /* CONFIG_SPARC64 */ void *module_alloc(unsigned long size) -{ - void *ret; + +void *module_alloc(unsigned long size) +{ /* We handle the zero case fine, unlike vmalloc */ if (size == 0) return NULL; - ret = module_map(size); - if (!ret) - ret = ERR_PTR(-ENOMEM); - else - memset(ret, 0, size); +#ifdef CONFIG_PAX_KERNEXEC + return __module_alloc(size, PAGE_KERNEL); +#else + return __module_alloc(size, PAGE_KERNEL_EXEC); +#endif +} + + +#ifdef CONFIG_PAX_KERNEXEC +void *module_alloc(unsigned long size) +{ + /* We handle the zero case fine, unlike vmalloc */ + if (size == 0) + return NULL; - return ret; + return __module_alloc(size, PAGE_KERNEL_EXEC); } +#endif /* Free memory returned from module_core_alloc/module_init_alloc */ void module_free(struct module *mod, void *module_region) diff -urNp linux-2.6.32.18/arch/sparc/mm/init_64.c linux-2.6.32.18-new/arch/sparc/mm/init_64.c --- linux-2.6.32.18/arch/sparc/mm/init_64.c 2010-08-10 13:45:57.000000000 -0400 +++ linux-2.6.32.18-new/arch/sparc/mm/init_64.c 2010-08-11 23:47:44.000000000 -0400 @@ -2062,6 +2062,9 @@ void free_initrd_mem(unsigned long start pgprot_t PAGE_KERNEL __read_mostly; EXPORT_SYMBOL(PAGE_KERNEL); +pgprot_t PAGE_KERNEL_EXEC __read_mostly; +EXPORT_SYMBOL(PAGE_KERNEL_EXEC); + pgprot_t PAGE_KERNEL_LOCKED __read_mostly; pgprot_t PAGE_COPY __read_mostly; @@ -2127,6 +2130,8 @@ static void prot_init_common(unsigned lo unsigned long page_shared, unsigned long page_copy, unsigned long page_readonly, + unsigned long page_read_bit, + unsigned long page_write_bit, unsigned long page_exec_bit) { PAGE_COPY = __pgprot(page_copy); @@ -2134,31 +2139,36 @@ static void prot_init_common(unsigned lo protection_map[0x0] = __pgprot(page_none); protection_map[0x1] = __pgprot(page_readonly & ~page_exec_bit); - protection_map[0x2] = __pgprot(page_copy & ~page_exec_bit); + protection_map[0x2] = __pgprot(page_copy & ~page_exec_bit & ~page_read_bit); protection_map[0x3] = __pgprot(page_copy & ~page_exec_bit); - protection_map[0x4] = __pgprot(page_readonly); + protection_map[0x4] = __pgprot(page_readonly & ~page_read_bit); protection_map[0x5] = __pgprot(page_readonly); - protection_map[0x6] = __pgprot(page_copy); + protection_map[0x6] = __pgprot(page_copy & ~page_read_bit); protection_map[0x7] = __pgprot(page_copy); protection_map[0x8] = __pgprot(page_none); protection_map[0x9] = __pgprot(page_readonly & ~page_exec_bit); - protection_map[0xa] = __pgprot(page_shared & ~page_exec_bit); + protection_map[0xa] = __pgprot(page_shared & ~page_exec_bit & ~page_read_bit); protection_map[0xb] = __pgprot(page_shared & ~page_exec_bit); - protection_map[0xc] = __pgprot(page_readonly); + protection_map[0xc] = __pgprot(page_readonly & ~page_read_bit); protection_map[0xd] = __pgprot(page_readonly); - protection_map[0xe] = __pgprot(page_shared); + protection_map[0xe] = __pgprot(page_shared & ~page_read_bit); protection_map[0xf] = __pgprot(page_shared); } static void __init sun4u_pgprot_init(void) { unsigned long page_none, page_shared, page_copy, page_readonly; - unsigned long page_exec_bit; + unsigned long page_read_bit, page_write_bit, page_exec_bit; PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4U | _PAGE_VALID | _PAGE_CACHE_4U | _PAGE_P_4U | + __ACCESS_BITS_4U | __DIRTY_BITS_4U); + + PAGE_KERNEL_EXEC = __pgprot (_PAGE_PRESENT_4U | _PAGE_VALID | + _PAGE_CACHE_4U | _PAGE_P_4U | __ACCESS_BITS_4U | __DIRTY_BITS_4U | _PAGE_EXEC_4U); + PAGE_KERNEL_LOCKED = __pgprot (_PAGE_PRESENT_4U | _PAGE_VALID | _PAGE_CACHE_4U | _PAGE_P_4U | __ACCESS_BITS_4U | __DIRTY_BITS_4U | @@ -2198,21 +2208,28 @@ static void __init sun4u_pgprot_init(voi page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4U | _PAGE_CACHE_4U | __ACCESS_BITS_4U | _PAGE_EXEC_4U); + page_read_bit = _PAGE_READ_4U; + page_write_bit = _PAGE_WRITE_4U; page_exec_bit = _PAGE_EXEC_4U; prot_init_common(page_none, page_shared, page_copy, page_readonly, - page_exec_bit); + page_read_bit, page_write_bit, page_exec_bit); } static void __init sun4v_pgprot_init(void) { unsigned long page_none, page_shared, page_copy, page_readonly; - unsigned long page_exec_bit; + unsigned long page_read_bit, page_write_bit, page_exec_bit; PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID | _PAGE_CACHE_4V | _PAGE_P_4V | + __ACCESS_BITS_4V | __DIRTY_BITS_4V); + + PAGE_KERNEL_EXEC = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID | + _PAGE_CACHE_4V | _PAGE_P_4V | __ACCESS_BITS_4V | __DIRTY_BITS_4V | _PAGE_EXEC_4V); + PAGE_KERNEL_LOCKED = PAGE_KERNEL; _PAGE_IE = _PAGE_IE_4V; @@ -2256,10 +2273,12 @@ static void __init sun4v_pgprot_init(voi page_readonly = (_PAGE_VALID | _PAGE_PRESENT_4V | _PAGE_CACHE_4V | __ACCESS_BITS_4V | _PAGE_EXEC_4V); + page_read_bit = _PAGE_READ_4V; + page_write_bit = _PAGE_WRITE_4V; page_exec_bit = _PAGE_EXEC_4V; prot_init_common(page_none, page_shared, page_copy, page_readonly, - page_exec_bit); + page_read_bit, page_write_bit, page_exec_bit); } unsigned long pte_sz_bits(unsigned long sz) diff -urNp linux-2.6.32.18/security/Kconfig linux-2.6.32.18-new/security/Kconfig --- linux-2.6.32.18/security/Kconfig 2010-08-12 00:21:46.000000000 -0400 +++ linux-2.6.32.18-new/security/Kconfig 2010-08-11 23:02:51.000000000 -0400 @@ -300,7 +300,7 @@ config PAX_DLRESOLVE config PAX_KERNEXEC bool "Enforce non-executable kernel pages" - depends on PAX_NOEXEC && (PPC || X86) && (!X86_32 || X86_WP_WORKS_OK) && !XEN + depends on PAX_NOEXEC && (PPC || X86 || SPARC64) && (!X86_32 || X86_WP_WORKS_OK) && !XEN select PAX_PER_CPU_PGD if X86_64 || (X86_32 && X86_PAE) help This is the kernel land equivalent of PAGEEXEC and MPROTECT,