diff -urNp linux-2.6.31/arch/alpha/include/asm/atomic.h linux-2.6.31/arch/alpha/include/asm/atomic.h --- linux-2.6.31/arch/alpha/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/alpha/include/asm/atomic.h 2009-09-11 22:49:04.785615322 -0400 @@ -18,9 +18,11 @@ #define ATOMIC64_INIT(i) ( (atomic64_t) { (i) } ) #define atomic_read(v) ((v)->counter + 0) +#define atomic_read_unchecked(v) ((v)->counter + 0) #define atomic64_read(v) ((v)->counter + 0) #define atomic_set(v,i) ((v)->counter = (i)) +#define atomic_set_unchecked(v,i) ((v)->counter = (i)) #define atomic64_set(v,i) ((v)->counter = (i)) /* @@ -44,6 +46,11 @@ static __inline__ void atomic_add(int i, :"Ir" (i), "m" (v->counter)); } +static __inline__ void atomic_add_unchecked(int i, atomic_unchecked_t * v) +{ + atomic_add(i, (atomic_t *)v); +} + static __inline__ void atomic64_add(long i, atomic64_t * v) { unsigned long temp; @@ -74,6 +81,11 @@ static __inline__ void atomic_sub(int i, :"Ir" (i), "m" (v->counter)); } +static __inline__ void atomic_sub_unchecked(int i, atomic_unchecked_t * v) +{ + atomic_sub(i, (atomic_t *)v); +} + static __inline__ void atomic64_sub(long i, atomic64_t * v) { unsigned long temp; @@ -246,6 +258,7 @@ static __inline__ int atomic64_add_unles #define atomic64_dec_and_test(v) (atomic64_sub_return(1, (v)) == 0) #define atomic_inc(v) atomic_add(1,(v)) +#define atomic_inc_unchecked(v) atomic_add_unchecked(1,(v)) #define atomic64_inc(v) atomic64_add(1,(v)) #define atomic_dec(v) atomic_sub(1,(v)) diff -urNp linux-2.6.31/arch/alpha/include/asm/elf.h linux-2.6.31/arch/alpha/include/asm/elf.h --- linux-2.6.31/arch/alpha/include/asm/elf.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/alpha/include/asm/elf.h 2009-09-06 15:29:11.105049911 -0400 @@ -91,6 +91,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE (current->personality & ADDR_LIMIT_32BIT ? 0x10000 : 0x120000000UL) + +#define PAX_DELTA_MMAP_LEN (current->personality & ADDR_LIMIT_32BIT ? 14 : 28) +#define PAX_DELTA_STACK_LEN (current->personality & ADDR_LIMIT_32BIT ? 14 : 19) +#endif + /* $0 is set by ld.so to a pointer to a function which might be registered using atexit. This provides a mean for the dynamic linker to call DT_FINI functions for shared libraries that have diff -urNp linux-2.6.31/arch/alpha/include/asm/pgtable.h linux-2.6.31/arch/alpha/include/asm/pgtable.h --- linux-2.6.31/arch/alpha/include/asm/pgtable.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/alpha/include/asm/pgtable.h 2009-09-06 15:29:11.105049911 -0400 @@ -101,6 +101,17 @@ struct vm_area_struct; #define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS) #define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) #define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) + +#ifdef CONFIG_PAX_PAGEEXEC +# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOE) +# define PAGE_COPY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE) +# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE) +#else +# define PAGE_SHARED_NOEXEC PAGE_SHARED +# define PAGE_COPY_NOEXEC PAGE_COPY +# define PAGE_READONLY_NOEXEC PAGE_READONLY +#endif + #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE) #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x)) diff -urNp linux-2.6.31/arch/alpha/kernel/module.c linux-2.6.31/arch/alpha/kernel/module.c --- linux-2.6.31/arch/alpha/kernel/module.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/alpha/kernel/module.c 2009-09-06 15:29:11.105049911 -0400 @@ -182,7 +182,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs, /* The small sections were sorted to the end of the segment. The following should definitely cover them. */ - gp = (u64)me->module_core + me->core_size - 0x8000; + gp = (u64)me->module_core_rw + me->core_size_rw - 0x8000; got = sechdrs[me->arch.gotsecindex].sh_addr; for (i = 0; i < n; i++) { diff -urNp linux-2.6.31/arch/alpha/kernel/osf_sys.c linux-2.6.31/arch/alpha/kernel/osf_sys.c --- linux-2.6.31/arch/alpha/kernel/osf_sys.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/alpha/kernel/osf_sys.c 2009-09-06 15:29:11.106230045 -0400 @@ -1212,6 +1212,10 @@ arch_get_unmapped_area(struct file *filp merely specific addresses, but regions of memory -- perhaps this feature should be incorporated into all ports? */ +#ifdef CONFIG_PAX_RANDMMAP + if (!(current->mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (addr) { addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit); if (addr != (unsigned long) -ENOMEM) @@ -1219,8 +1223,8 @@ arch_get_unmapped_area(struct file *filp } /* Next, try allocating at TASK_UNMAPPED_BASE. */ - addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE), - len, limit); + addr = arch_get_unmapped_area_1 (PAGE_ALIGN(current->mm->mmap_base), len, limit); + if (addr != (unsigned long) -ENOMEM) return addr; diff -urNp linux-2.6.31/arch/alpha/mm/fault.c linux-2.6.31/arch/alpha/mm/fault.c --- linux-2.6.31/arch/alpha/mm/fault.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/alpha/mm/fault.c 2009-09-06 15:29:11.106230045 -0400 @@ -54,6 +54,124 @@ __load_new_mm_context(struct mm_struct * __reload_thread(pcb); } +#ifdef CONFIG_PAX_PAGEEXEC +/* + * PaX: decide what to do with offenders (regs->pc = fault address) + * + * returns 1 when task should be killed + * 2 when patched PLT trampoline was detected + * 3 when unpatched PLT trampoline was detected + */ +static int pax_handle_fetch_fault(struct pt_regs *regs) +{ + +#ifdef CONFIG_PAX_EMUPLT + int err; + + do { /* PaX: patched PLT emulation #1 */ + unsigned int ldah, ldq, jmp; + + err = get_user(ldah, (unsigned int *)regs->pc); + err |= get_user(ldq, (unsigned int *)(regs->pc+4)); + err |= get_user(jmp, (unsigned int *)(regs->pc+8)); + + if (err) + break; + + if ((ldah & 0xFFFF0000U) == 0x277B0000U && + (ldq & 0xFFFF0000U) == 0xA77B0000U && + jmp == 0x6BFB0000U) + { + unsigned long r27, addr; + unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16; + unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL; + + addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL); + err = get_user(r27, (unsigned long *)addr); + if (err) + break; + + regs->r27 = r27; + regs->pc = r27; + return 2; + } + } while (0); + + do { /* PaX: patched PLT emulation #2 */ + unsigned int ldah, lda, br; + + err = get_user(ldah, (unsigned int *)regs->pc); + err |= get_user(lda, (unsigned int *)(regs->pc+4)); + err |= get_user(br, (unsigned int *)(regs->pc+8)); + + if (err) + break; + + if ((ldah & 0xFFFF0000U) == 0x277B0000U && + (lda & 0xFFFF0000U) == 0xA77B0000U && + (br & 0xFFE00000U) == 0xC3E00000U) + { + unsigned long addr = br | 0xFFFFFFFFFFE00000UL; + unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16; + unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL; + + regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL); + regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2); + return 2; + } + } while (0); + + do { /* PaX: unpatched PLT emulation */ + unsigned int br; + + err = get_user(br, (unsigned int *)regs->pc); + + if (!err && (br & 0xFFE00000U) == 0xC3800000U) { + unsigned int br2, ldq, nop, jmp; + unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver; + + addr = regs->pc + 4 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2); + err = get_user(br2, (unsigned int *)addr); + err |= get_user(ldq, (unsigned int *)(addr+4)); + err |= get_user(nop, (unsigned int *)(addr+8)); + err |= get_user(jmp, (unsigned int *)(addr+12)); + err |= get_user(resolver, (unsigned long *)(addr+16)); + + if (err) + break; + + if (br2 == 0xC3600000U && + ldq == 0xA77B000CU && + nop == 0x47FF041FU && + jmp == 0x6B7B0000U) + { + regs->r28 = regs->pc+4; + regs->r27 = addr+16; + regs->pc = resolver; + return 3; + } + } + } while (0); +#endif + + return 1; +} + +void pax_report_insns(void *pc, void *sp) +{ + unsigned long i; + + printk(KERN_ERR "PAX: bytes at PC: "); + for (i = 0; i < 5; i++) { + unsigned int c; + if (get_user(c, (unsigned int *)pc+i)) + printk(KERN_CONT "???????? "); + else + printk(KERN_CONT "%08x ", c); + } + printk("\n"); +} +#endif /* * This routine handles page faults. It determines the address, @@ -131,8 +249,29 @@ do_page_fault(unsigned long address, uns good_area: si_code = SEGV_ACCERR; if (cause < 0) { - if (!(vma->vm_flags & VM_EXEC)) + if (!(vma->vm_flags & VM_EXEC)) { + +#ifdef CONFIG_PAX_PAGEEXEC + if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->pc) + goto bad_area; + + up_read(&mm->mmap_sem); + switch (pax_handle_fetch_fault(regs)) { + +#ifdef CONFIG_PAX_EMUPLT + case 2: + case 3: + return; +#endif + + } + pax_report_fault(regs, (void *)regs->pc, (void *)rdusp()); + do_group_exit(SIGKILL); +#else goto bad_area; +#endif + + } } else if (!cause) { /* Allow reads even for write-only mappings */ if (!(vma->vm_flags & (VM_READ | VM_WRITE))) diff -urNp linux-2.6.31/arch/arm/include/asm/atomic.h linux-2.6.31/arch/arm/include/asm/atomic.h --- linux-2.6.31/arch/arm/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/arm/include/asm/atomic.h 2009-09-11 22:51:00.173407719 -0400 @@ -20,6 +20,7 @@ #ifdef __KERNEL__ #define atomic_read(v) ((v)->counter) +#define atomic_read_unchecked(v) ((v)->counter) #if __LINUX_ARM_ARCH__ >= 6 @@ -44,6 +45,11 @@ static inline void atomic_set(atomic_t * : "cc"); } +static inline void atomic_set_unchecked(atomic_unchecked_t *v, int i) +{ + atomic_set((atomic_t *)v, i); +} + static inline void atomic_add(int i, atomic_t *v) { unsigned long tmp; @@ -60,6 +66,11 @@ static inline void atomic_add(int i, ato : "cc"); } +static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_add(i, (atomic_t *)v); +} + static inline int atomic_add_return(int i, atomic_t *v) { unsigned long tmp; @@ -98,6 +109,11 @@ static inline void atomic_sub(int i, ato : "cc"); } +static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_sub(i, (atomic_t *)v); +} + static inline int atomic_sub_return(int i, atomic_t *v) { unsigned long tmp; @@ -164,6 +180,7 @@ static inline void atomic_clear_mask(uns #endif #define atomic_set(v,i) (((v)->counter) = (i)) +#define atomic_set_unchecked(v,i) (((v)->counter) = (i)) static inline int atomic_add_return(int i, atomic_t *v) { @@ -232,6 +249,7 @@ static inline int atomic_add_unless(atom #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) #define atomic_inc(v) atomic_add(1, v) +#define atomic_inc_unchecked(v) atomic_add_unchecked(1, v) #define atomic_dec(v) atomic_sub(1, v) #define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0) diff -urNp linux-2.6.31/arch/arm/include/asm/elf.h linux-2.6.31/arch/arm/include/asm/elf.h --- linux-2.6.31/arch/arm/include/asm/elf.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/arm/include/asm/elf.h 2009-09-06 15:29:11.107211663 -0400 @@ -103,7 +103,14 @@ extern int arm_elf_read_implies_exec(con the loader. We need to make sure that it is out of the way of the program that it will "exec", and that there is sufficient room for the brk. */ -#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) +#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) + +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE 0x00008000UL + +#define PAX_DELTA_MMAP_LEN ((current->personality == PER_LINUX_32BIT) ? 16 : 10) +#define PAX_DELTA_STACK_LEN ((current->personality == PER_LINUX_32BIT) ? 16 : 10) +#endif /* When the program starts, a1 contains a pointer to a function to be registered with atexit, as per the SVR4 ABI. A value of 0 means we diff -urNp linux-2.6.31/arch/arm/include/asm/kmap_types.h linux-2.6.31/arch/arm/include/asm/kmap_types.h --- linux-2.6.31/arch/arm/include/asm/kmap_types.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/arm/include/asm/kmap_types.h 2009-09-06 15:29:11.107211663 -0400 @@ -19,6 +19,7 @@ enum km_type { KM_SOFTIRQ0, KM_SOFTIRQ1, KM_L2_CACHE, + KM_CLEARPAGE, KM_TYPE_NR }; diff -urNp linux-2.6.31/arch/arm/include/asm/uaccess.h linux-2.6.31/arch/arm/include/asm/uaccess.h --- linux-2.6.31/arch/arm/include/asm/uaccess.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/arm/include/asm/uaccess.h 2009-09-06 15:29:11.108180388 -0400 @@ -400,6 +400,9 @@ extern unsigned long __must_check __strn static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) { + if ((long)n < 0) + return n; + if (access_ok(VERIFY_READ, from, n)) n = __copy_from_user(to, from, n); else /* security hole - plug it */ @@ -409,6 +412,9 @@ static inline unsigned long __must_check static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) { + if ((long)n < 0) + return n; + if (access_ok(VERIFY_WRITE, to, n)) n = __copy_to_user(to, from, n); return n; diff -urNp linux-2.6.31/arch/arm/mach-ns9xxx/clock.c linux-2.6.31/arch/arm/mach-ns9xxx/clock.c --- linux-2.6.31/arch/arm/mach-ns9xxx/clock.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/arm/mach-ns9xxx/clock.c 2009-09-06 15:29:11.108180388 -0400 @@ -195,7 +195,7 @@ static int clk_debugfs_open(struct inode return single_open(file, clk_debugfs_show, NULL); } -static struct file_operations clk_debugfs_operations = { +static const struct file_operations clk_debugfs_operations = { .open = clk_debugfs_open, .read = seq_read, .llseek = seq_lseek, diff -urNp linux-2.6.31/arch/arm/mm/mmap.c linux-2.6.31/arch/arm/mm/mmap.c --- linux-2.6.31/arch/arm/mm/mmap.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/arm/mm/mmap.c 2009-09-06 15:29:11.108180388 -0400 @@ -62,6 +62,10 @@ arch_get_unmapped_area(struct file *filp if (len > TASK_SIZE) return -ENOMEM; +#ifdef CONFIG_PAX_RANDMMAP + if (!(mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (addr) { if (do_align) addr = COLOUR_ALIGN(addr, pgoff); @@ -74,10 +78,10 @@ arch_get_unmapped_area(struct file *filp return addr; } if (len > mm->cached_hole_size) { - start_addr = addr = mm->free_area_cache; + start_addr = addr = mm->free_area_cache; } else { - start_addr = addr = TASK_UNMAPPED_BASE; - mm->cached_hole_size = 0; + start_addr = addr = mm->mmap_base; + mm->cached_hole_size = 0; } full_search: @@ -93,8 +97,8 @@ full_search: * Start a new search - just in case we missed * some holes. */ - if (start_addr != TASK_UNMAPPED_BASE) { - start_addr = addr = TASK_UNMAPPED_BASE; + if (start_addr != mm->mmap_base) { + start_addr = addr = mm->mmap_base; mm->cached_hole_size = 0; goto full_search; } diff -urNp linux-2.6.31/arch/avr32/include/asm/atomic.h linux-2.6.31/arch/avr32/include/asm/atomic.h --- linux-2.6.31/arch/avr32/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/avr32/include/asm/atomic.h 2009-09-11 22:52:43.047793693 -0400 @@ -20,7 +20,9 @@ #define ATOMIC_INIT(i) { (i) } #define atomic_read(v) ((v)->counter) +#define atomic_read_unchecked(v) ((v)->counter) #define atomic_set(v, i) (((v)->counter) = i) +#define atomic_set_unchecked(v, i) (((v)->counter) = i) /* * atomic_sub_return - subtract the atomic variable @@ -48,6 +50,18 @@ static inline int atomic_sub_return(int } /* + * atomic_sub_return_unchecked - subtract the atomic variable + * @i: integer value to subtract + * @v: pointer of type atomic_unchecked_t + * + * Atomically subtracts @i from @v. Returns the resulting value. + */ +static inline int atomic_sub_return_unchecked(int i, atomic_unchecked_t *v) +{ + return atomic_sub_return(i, (atomic_t *)v); +} + +/* * atomic_add_return - add integer to atomic variable * @i: integer value to add * @v: pointer of type atomic_t @@ -76,6 +90,18 @@ static inline int atomic_add_return(int } /* + * atomic_add_return_unchecked - add integer to atomic variable + * @i: integer value to add + * @v: pointer of type atomic_unchecked_t + * + * Atomically adds @i to @v. Returns the resulting value. + */ +static inline int atomic_add_return_unchecked(int i, atomic_unchecked_t *v) +{ + return atomic_add_return(i, (atomic_t *)v); +} + +/* * atomic_sub_unless - sub unless the number is a given value * @v: pointer of type atomic_t * @a: the amount to add to v... @@ -176,9 +202,12 @@ static inline int atomic_sub_if_positive #define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) #define atomic_sub(i, v) (void)atomic_sub_return(i, v) +#define atomic_sub_unchecked(i, v) (void)atomic_sub_return_unchecked(i, v) #define atomic_add(i, v) (void)atomic_add_return(i, v) +#define atomic_add_unchecked(i, v) (void)atomic_add_return_unchecked(i, v) #define atomic_dec(v) atomic_sub(1, (v)) #define atomic_inc(v) atomic_add(1, (v)) +#define atomic_inc_unchecked(v) (void)atomic_add_return_unchecked(1, (v)) #define atomic_dec_return(v) atomic_sub_return(1, v) #define atomic_inc_return(v) atomic_add_return(1, v) diff -urNp linux-2.6.31/arch/avr32/include/asm/elf.h linux-2.6.31/arch/avr32/include/asm/elf.h --- linux-2.6.31/arch/avr32/include/asm/elf.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/avr32/include/asm/elf.h 2009-09-06 15:29:11.109255148 -0400 @@ -85,8 +85,14 @@ typedef struct user_fpu_struct elf_fpreg the loader. We need to make sure that it is out of the way of the program that it will "exec", and that there is sufficient room for the brk. */ -#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) +#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE 0x00001000UL + +#define PAX_DELTA_MMAP_LEN 15 +#define PAX_DELTA_STACK_LEN 15 +#endif /* This yields a mask that user programs can use to figure out what instruction set this CPU supports. This could be done in user space, diff -urNp linux-2.6.31/arch/avr32/include/asm/kmap_types.h linux-2.6.31/arch/avr32/include/asm/kmap_types.h --- linux-2.6.31/arch/avr32/include/asm/kmap_types.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/avr32/include/asm/kmap_types.h 2009-09-06 15:29:11.109255148 -0400 @@ -22,7 +22,8 @@ D(10) KM_IRQ0, D(11) KM_IRQ1, D(12) KM_SOFTIRQ0, D(13) KM_SOFTIRQ1, -D(14) KM_TYPE_NR +D(14) KM_CLEARPAGE, +D(15) KM_TYPE_NR }; #undef D diff -urNp linux-2.6.31/arch/avr32/mm/fault.c linux-2.6.31/arch/avr32/mm/fault.c --- linux-2.6.31/arch/avr32/mm/fault.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/avr32/mm/fault.c 2009-09-06 15:29:11.110254440 -0400 @@ -41,6 +41,23 @@ static inline int notify_page_fault(stru int exception_trace = 1; +#ifdef CONFIG_PAX_PAGEEXEC +void pax_report_insns(void *pc, void *sp) +{ + unsigned long i; + + printk(KERN_ERR "PAX: bytes at PC: "); + for (i = 0; i < 20; i++) { + unsigned char c; + if (get_user(c, (unsigned char *)pc+i)) + printk(KERN_CONT "???????? "); + else + printk(KERN_CONT "%02x ", c); + } + printk("\n"); +} +#endif + /* * This routine handles page faults. It determines the address and the * problem, and then passes it off to one of the appropriate routines. @@ -157,6 +174,16 @@ bad_area: up_read(&mm->mmap_sem); if (user_mode(regs)) { + +#ifdef CONFIG_PAX_PAGEEXEC + if (mm->pax_flags & MF_PAX_PAGEEXEC) { + if (ecr == ECR_PROTECTION_X || ecr == ECR_TLB_MISS_X) { + pax_report_fault(regs, (void *)regs->pc, (void *)regs->sp); + do_group_exit(SIGKILL); + } + } +#endif + if (exception_trace && printk_ratelimit()) printk("%s%s[%d]: segfault at %08lx pc %08lx " "sp %08lx ecr %lu\n", diff -urNp linux-2.6.31/arch/blackfin/include/asm/atomic.h linux-2.6.31/arch/blackfin/include/asm/atomic.h --- linux-2.6.31/arch/blackfin/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/blackfin/include/asm/atomic.h 2009-09-11 22:53:53.058593048 -0400 @@ -15,8 +15,10 @@ #define ATOMIC_INIT(i) { (i) } #define atomic_set(v, i) (((v)->counter) = i) +#define atomic_set_unchecked(v, i) (((v)->counter) = i) #define atomic_read(v) __raw_uncached_fetch_asm(&(v)->counter) +#define atomic_read_unchecked(v) __raw_uncached_fetch_asm(&(v)->counter) asmlinkage int __raw_uncached_fetch_asm(const volatile int *ptr); @@ -35,11 +37,21 @@ static inline void atomic_add(int i, ato __raw_atomic_update_asm(&v->counter, i); } +static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_add(i, (atomic_t *)v); +} + static inline void atomic_sub(int i, atomic_t *v) { __raw_atomic_update_asm(&v->counter, -i); } +static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_sub(i, (atomic_t *)v); +} + static inline int atomic_add_return(int i, atomic_t *v) { return __raw_atomic_update_asm(&v->counter, i); @@ -55,6 +67,11 @@ static inline void atomic_inc(volatile a __raw_atomic_update_asm(&v->counter, 1); } +static inline void atomic_inc_unchecked(volatile atomic_unchecked_t *v) +{ + atomic_inc((atomic_t *)v); +} + static inline void atomic_dec(volatile atomic_t *v) { __raw_atomic_update_asm(&v->counter, -1); diff -urNp linux-2.6.31/arch/blackfin/mach-bf561/coreb.c linux-2.6.31/arch/blackfin/mach-bf561/coreb.c --- linux-2.6.31/arch/blackfin/mach-bf561/coreb.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/blackfin/mach-bf561/coreb.c 2009-09-06 15:29:11.110254440 -0400 @@ -48,7 +48,7 @@ coreb_ioctl(struct inode *inode, struct return ret; } -static struct file_operations coreb_fops = { +static const struct file_operations coreb_fops = { .owner = THIS_MODULE, .ioctl = coreb_ioctl, }; diff -urNp linux-2.6.31/arch/cris/arch-v10/drivers/sync_serial.c linux-2.6.31/arch/cris/arch-v10/drivers/sync_serial.c --- linux-2.6.31/arch/cris/arch-v10/drivers/sync_serial.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/cris/arch-v10/drivers/sync_serial.c 2009-09-06 15:29:11.111389293 -0400 @@ -244,7 +244,7 @@ static unsigned sync_serial_prescale_sha #define NUMBER_OF_PORTS 2 -static struct file_operations sync_serial_fops = { +static const struct file_operations sync_serial_fops = { .owner = THIS_MODULE, .write = sync_serial_write, .read = sync_serial_read, diff -urNp linux-2.6.31/arch/cris/arch-v32/drivers/mach-fs/gpio.c linux-2.6.31/arch/cris/arch-v32/drivers/mach-fs/gpio.c --- linux-2.6.31/arch/cris/arch-v32/drivers/mach-fs/gpio.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/cris/arch-v32/drivers/mach-fs/gpio.c 2009-09-06 15:29:11.112155258 -0400 @@ -855,7 +855,7 @@ gpio_leds_ioctl(unsigned int cmd, unsign return 0; } -struct file_operations gpio_fops = { +struct struct file_operations gpio_fops = { .owner = THIS_MODULE, .poll = gpio_poll, .ioctl = gpio_ioctl, diff -urNp linux-2.6.31/arch/cris/include/asm/atomic.h linux-2.6.31/arch/cris/include/asm/atomic.h --- linux-2.6.31/arch/cris/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/cris/include/asm/atomic.h 2009-09-11 22:55:08.915710428 -0400 @@ -16,7 +16,9 @@ #define ATOMIC_INIT(i) { (i) } #define atomic_read(v) ((v)->counter) +#define atomic_read_unchecked(v) ((v)->counter) #define atomic_set(v,i) (((v)->counter) = (i)) +#define atomic_set_unchecked(v,i) (((v)->counter) = (i)) /* These should be written in asm but we do it in C for now. */ @@ -28,6 +30,11 @@ static inline void atomic_add(int i, vol cris_atomic_restore(v, flags); } +static inline void atomic_add_unchecked(int i, volatile atomic_unchecked_t *v) +{ + atomic_add(i, (volatile atomic_t *)v); +} + static inline void atomic_sub(int i, volatile atomic_t *v) { unsigned long flags; @@ -36,6 +43,11 @@ static inline void atomic_sub(int i, vol cris_atomic_restore(v, flags); } +static inline void atomic_sub_unchecked(int i, volatile atomic_unchecked_t *v) +{ + atomic_sub(i, (volatile atomic_t *)v); +} + static inline int atomic_add_return(int i, volatile atomic_t *v) { unsigned long flags; @@ -76,6 +88,11 @@ static inline void atomic_inc(volatile a cris_atomic_restore(v, flags); } +static inline void atomic_inc_unchecked(volatile atomic_unchecked_t *v) +{ + atomic_inc((volatile atomic_t *)v); +} + static inline void atomic_dec(volatile atomic_t *v) { unsigned long flags; diff -urNp linux-2.6.31/arch/frv/include/asm/atomic.h linux-2.6.31/arch/frv/include/asm/atomic.h --- linux-2.6.31/arch/frv/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/frv/include/asm/atomic.h 2009-09-11 21:49:34.085801883 -0400 @@ -37,7 +37,9 @@ #define ATOMIC_INIT(i) { (i) } #define atomic_read(v) ((v)->counter) +#define atomic_read_unchecked(v) ((v)->counter) #define atomic_set(v, i) (((v)->counter) = (i)) +#define atomic_set_unchecked(v, i) (((v)->counter) = (i)) #ifndef CONFIG_FRV_OUTOFLINE_ATOMIC_OPS static inline int atomic_add_return(int i, atomic_t *v) @@ -99,16 +101,31 @@ static inline void atomic_add(int i, ato atomic_add_return(i, v); } +static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_add_return(i, (atomic_t *)v); +} + static inline void atomic_sub(int i, atomic_t *v) { atomic_sub_return(i, v); } +static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_sub_return(i, (atomic_t *)v); +} + static inline void atomic_inc(atomic_t *v) { atomic_add_return(1, v); } +static inline void atomic_inc_unchecked(atomic_unchecked_t *v) +{ + atomic_add_return(1, (atomic_t *)v); +} + static inline void atomic_dec(atomic_t *v) { atomic_sub_return(1, v); diff -urNp linux-2.6.31/arch/frv/include/asm/kmap_types.h linux-2.6.31/arch/frv/include/asm/kmap_types.h --- linux-2.6.31/arch/frv/include/asm/kmap_types.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/frv/include/asm/kmap_types.h 2009-09-06 15:29:11.113186643 -0400 @@ -23,6 +23,7 @@ enum km_type { KM_IRQ1, KM_SOFTIRQ0, KM_SOFTIRQ1, + KM_CLEARPAGE, KM_TYPE_NR }; diff -urNp linux-2.6.31/arch/h8300/include/asm/atomic.h linux-2.6.31/arch/h8300/include/asm/atomic.h --- linux-2.6.31/arch/h8300/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/h8300/include/asm/atomic.h 2009-09-11 22:59:01.477552220 -0400 @@ -11,7 +11,9 @@ #define ATOMIC_INIT(i) { (i) } #define atomic_read(v) ((v)->counter) +#define atomic_read_unchecked(v) ((v)->counter) #define atomic_set(v, i) (((v)->counter) = i) +#define atomic_set_unchecked(v, i) (((v)->counter) = i) #include #include @@ -25,7 +27,13 @@ static __inline__ int atomic_add_return( return ret; } +static __inline__ int atomic_add_return_unchecked(int i, atomic_unchecked_t *v) +{ + return atomic_add_return(i, (atomic_t *)v); +} + #define atomic_add(i, v) atomic_add_return(i, v) +#define atomic_add_unchecked(i, v) atomic_add_return_unchecked(i, v) #define atomic_add_negative(a, v) (atomic_add_return((a), (v)) < 0) static __inline__ int atomic_sub_return(int i, atomic_t *v) @@ -37,7 +45,13 @@ static __inline__ int atomic_sub_return( return ret; } +static __inline__ int atomic_sub_return_unchecked(int i, atomic_unchecked_t *v) +{ + return atomic_sub_return(i, (atomic_t *)v); +} + #define atomic_sub(i, v) atomic_sub_return(i, v) +#define atomic_sub_unchecked(i, v) atomic_sub_return_unchecked(i, v) #define atomic_sub_and_test(i,v) (atomic_sub_return(i, v) == 0) static __inline__ int atomic_inc_return(atomic_t *v) @@ -50,7 +64,13 @@ static __inline__ int atomic_inc_return( return ret; } +static __inline__ int atomic_inc_return_unchecked(atomic_unchecked_t *v) +{ + return atomic_inc_return((atomic_t *)v); +} + #define atomic_inc(v) atomic_inc_return(v) +#define atomic_inc_unchecked(v) atomic_inc_return_unchecked(v) /* * atomic_inc_and_test - increment and test diff -urNp linux-2.6.31/arch/ia64/ia32/binfmt_elf32.c linux-2.6.31/arch/ia64/ia32/binfmt_elf32.c --- linux-2.6.31/arch/ia64/ia32/binfmt_elf32.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/ia64/ia32/binfmt_elf32.c 2009-09-06 15:29:11.113186643 -0400 @@ -45,6 +45,13 @@ randomize_stack_top(unsigned long stack_ #define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack)) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE (current->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL) + +#define PAX_DELTA_MMAP_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) +#define PAX_DELTA_STACK_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) +#endif + /* Ugly but avoids duplication */ #include "../../../fs/binfmt_elf.c" @@ -69,11 +76,11 @@ ia32_install_gate_page (struct vm_area_s } -static struct vm_operations_struct ia32_shared_page_vm_ops = { +static const struct vm_operations_struct ia32_shared_page_vm_ops = { .fault = ia32_install_shared_page }; -static struct vm_operations_struct ia32_gate_page_vm_ops = { +static const struct vm_operations_struct ia32_gate_page_vm_ops = { .fault = ia32_install_gate_page }; diff -urNp linux-2.6.31/arch/ia64/ia32/ia32priv.h linux-2.6.31/arch/ia64/ia32/ia32priv.h --- linux-2.6.31/arch/ia64/ia32/ia32priv.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/ia64/ia32/ia32priv.h 2009-09-06 15:29:11.114322463 -0400 @@ -296,7 +296,14 @@ typedef struct compat_siginfo { #define ELF_DATA ELFDATA2LSB #define ELF_ARCH EM_386 -#define IA32_STACK_TOP IA32_PAGE_OFFSET +#ifdef CONFIG_PAX_RANDUSTACK +#define __IA32_DELTA_STACK (current->mm->delta_stack) +#else +#define __IA32_DELTA_STACK 0UL +#endif + +#define IA32_STACK_TOP (IA32_PAGE_OFFSET - __IA32_DELTA_STACK) + #define IA32_GATE_OFFSET IA32_PAGE_OFFSET #define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE diff -urNp linux-2.6.31/arch/ia64/include/asm/atomic.h linux-2.6.31/arch/ia64/include/asm/atomic.h --- linux-2.6.31/arch/ia64/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/ia64/include/asm/atomic.h 2009-09-11 22:02:02.446796802 -0400 @@ -22,9 +22,11 @@ #define ATOMIC64_INIT(i) ((atomic64_t) { (i) }) #define atomic_read(v) ((v)->counter) +#define atomic_read_unchecked(v) ((v)->counter) #define atomic64_read(v) ((v)->counter) #define atomic_set(v,i) (((v)->counter) = (i)) +#define atomic_set_unchecked(v,i) (((v)->counter) = (i)) #define atomic64_set(v,i) (((v)->counter) = (i)) static __inline__ int @@ -201,8 +203,11 @@ atomic64_add_negative (__s64 i, atomic64 #define atomic64_inc_and_test(v) (atomic64_add_return(1, (v)) == 0) #define atomic_add(i,v) atomic_add_return((i), (v)) +#define atomic_add_unchecked(i,v) atomic_add((i), (atomic_t *)(v)) #define atomic_sub(i,v) atomic_sub_return((i), (v)) +#define atomic_sub_unchecked(i,v) atomic_sub((i), (atomic_t *)(v)) #define atomic_inc(v) atomic_add(1, (v)) +#define atomic_inc_unchecked(v) atomic_inc((atomic_t *)(v)) #define atomic_dec(v) atomic_sub(1, (v)) #define atomic64_add(i,v) atomic64_add_return((i), (v)) diff -urNp linux-2.6.31/arch/ia64/include/asm/elf.h linux-2.6.31/arch/ia64/include/asm/elf.h --- linux-2.6.31/arch/ia64/include/asm/elf.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/ia64/include/asm/elf.h 2009-09-06 15:29:11.114322463 -0400 @@ -43,6 +43,13 @@ */ #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x800000000UL) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE (current->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL) + +#define PAX_DELTA_MMAP_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) +#define PAX_DELTA_STACK_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) +#endif + #define PT_IA_64_UNWIND 0x70000001 /* IA-64 relocations: */ diff -urNp linux-2.6.31/arch/ia64/include/asm/pgtable.h linux-2.6.31/arch/ia64/include/asm/pgtable.h --- linux-2.6.31/arch/ia64/include/asm/pgtable.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/ia64/include/asm/pgtable.h 2009-09-06 15:29:11.115307704 -0400 @@ -143,6 +143,17 @@ #define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) #define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) #define PAGE_COPY_EXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX) + +#ifdef CONFIG_PAX_PAGEEXEC +# define PAGE_SHARED_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW) +# define PAGE_READONLY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) +# define PAGE_COPY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) +#else +# define PAGE_SHARED_NOEXEC PAGE_SHARED +# define PAGE_READONLY_NOEXEC PAGE_READONLY +# define PAGE_COPY_NOEXEC PAGE_COPY +#endif + #define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX) #define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX) #define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX) diff -urNp linux-2.6.31/arch/ia64/include/asm/uaccess.h linux-2.6.31/arch/ia64/include/asm/uaccess.h --- linux-2.6.31/arch/ia64/include/asm/uaccess.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/ia64/include/asm/uaccess.h 2009-09-06 15:29:11.115307704 -0400 @@ -257,7 +257,7 @@ __copy_from_user (void *to, const void _ const void *__cu_from = (from); \ long __cu_len = (n); \ \ - if (__access_ok(__cu_to, __cu_len, get_fs())) \ + if (__cu_len > 0 && __cu_len <= INT_MAX && __access_ok(__cu_to, __cu_len, get_fs())) \ __cu_len = __copy_user(__cu_to, (__force void __user *) __cu_from, __cu_len); \ __cu_len; \ }) @@ -269,7 +269,7 @@ __copy_from_user (void *to, const void _ long __cu_len = (n); \ \ __chk_user_ptr(__cu_from); \ - if (__access_ok(__cu_from, __cu_len, get_fs())) \ + if (__cu_len > 0 && __cu_len <= INT_MAX && __access_ok(__cu_from, __cu_len, get_fs())) \ __cu_len = __copy_user((__force void __user *) __cu_to, __cu_from, __cu_len); \ __cu_len; \ }) diff -urNp linux-2.6.31/arch/ia64/kernel/module.c linux-2.6.31/arch/ia64/kernel/module.c --- linux-2.6.31/arch/ia64/kernel/module.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/ia64/kernel/module.c 2009-09-06 15:29:11.116247536 -0400 @@ -315,8 +315,7 @@ module_alloc (unsigned long size) void module_free (struct module *mod, void *module_region) { - if (mod && mod->arch.init_unw_table && - module_region == mod->module_init) { + if (mod && mod->arch.init_unw_table && module_region == mod->module_init_rx) { unw_remove_unwind_table(mod->arch.init_unw_table); mod->arch.init_unw_table = NULL; } @@ -502,15 +501,39 @@ module_frob_arch_sections (Elf_Ehdr *ehd } static inline int +in_init_rx (const struct module *mod, uint64_t addr) +{ + return addr - (uint64_t) mod->module_init_rx < mod->init_size_rx; +} + +static inline int +in_init_rw (const struct module *mod, uint64_t addr) +{ + return addr - (uint64_t) mod->module_init_rw < mod->init_size_rw; +} + +static inline int in_init (const struct module *mod, uint64_t addr) { - return addr - (uint64_t) mod->module_init < mod->init_size; + return in_init_rx(mod, addr) || in_init_rw(mod, addr); +} + +static inline int +in_core_rx (const struct module *mod, uint64_t addr) +{ + return addr - (uint64_t) mod->module_core_rx < mod->core_size_rx; +} + +static inline int +in_core_rw (const struct module *mod, uint64_t addr) +{ + return addr - (uint64_t) mod->module_core_rw < mod->core_size_rw; } static inline int in_core (const struct module *mod, uint64_t addr) { - return addr - (uint64_t) mod->module_core < mod->core_size; + return in_core_rx(mod, addr) || in_core_rw(mod, addr); } static inline int @@ -693,7 +716,14 @@ do_reloc (struct module *mod, uint8_t r_ break; case RV_BDREL: - val -= (uint64_t) (in_init(mod, val) ? mod->module_init : mod->module_core); + if (in_init_rx(mod, val)) + val -= (uint64_t) mod->module_init_rx; + else if (in_init_rw(mod, val)) + val -= (uint64_t) mod->module_init_rw; + else if (in_core_rx(mod, val)) + val -= (uint64_t) mod->module_core_rx; + else if (in_core_rw(mod, val)) + val -= (uint64_t) mod->module_core_rw; break; case RV_LTV: @@ -828,15 +858,15 @@ apply_relocate_add (Elf64_Shdr *sechdrs, * addresses have been selected... */ uint64_t gp; - if (mod->core_size > MAX_LTOFF) + if (mod->core_size_rx + mod->core_size_rw > MAX_LTOFF) /* * This takes advantage of fact that SHF_ARCH_SMALL gets allocated * at the end of the module. */ - gp = mod->core_size - MAX_LTOFF / 2; + gp = mod->core_size_rx + mod->core_size_rw - MAX_LTOFF / 2; else - gp = mod->core_size / 2; - gp = (uint64_t) mod->module_core + ((gp + 7) & -8); + gp = (mod->core_size_rx + mod->core_size_rw) / 2; + gp = (uint64_t) mod->module_core_rx + ((gp + 7) & -8); mod->arch.gp = gp; DEBUGP("%s: placing gp at 0x%lx\n", __func__, gp); } diff -urNp linux-2.6.31/arch/ia64/kernel/sys_ia64.c linux-2.6.31/arch/ia64/kernel/sys_ia64.c --- linux-2.6.31/arch/ia64/kernel/sys_ia64.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/ia64/kernel/sys_ia64.c 2009-09-06 15:29:11.116247536 -0400 @@ -43,6 +43,13 @@ arch_get_unmapped_area (struct file *fil if (REGION_NUMBER(addr) == RGN_HPAGE) addr = 0; #endif + +#ifdef CONFIG_PAX_RANDMMAP + if (mm->pax_flags & MF_PAX_RANDMMAP) + addr = mm->free_area_cache; + else +#endif + if (!addr) addr = mm->free_area_cache; @@ -61,9 +68,9 @@ arch_get_unmapped_area (struct file *fil for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { /* At this point: (!vma || addr < vma->vm_end). */ if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) { - if (start_addr != TASK_UNMAPPED_BASE) { + if (start_addr != mm->mmap_base) { /* Start a new search --- just in case we missed some holes. */ - addr = TASK_UNMAPPED_BASE; + addr = mm->mmap_base; goto full_search; } return -ENOMEM; diff -urNp linux-2.6.31/arch/ia64/mm/fault.c linux-2.6.31/arch/ia64/mm/fault.c --- linux-2.6.31/arch/ia64/mm/fault.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/ia64/mm/fault.c 2009-09-06 15:29:11.117202694 -0400 @@ -72,6 +72,23 @@ mapped_kernel_page_is_present (unsigned return pte_present(pte); } +#ifdef CONFIG_PAX_PAGEEXEC +void pax_report_insns(void *pc, void *sp) +{ + unsigned long i; + + printk(KERN_ERR "PAX: bytes at PC: "); + for (i = 0; i < 8; i++) { + unsigned int c; + if (get_user(c, (unsigned int *)pc+i)) + printk(KERN_CONT "???????? "); + else + printk(KERN_CONT "%08x ", c); + } + printk("\n"); +} +#endif + void __kprobes ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) { @@ -145,9 +162,23 @@ ia64_do_page_fault (unsigned long addres mask = ( (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT) | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)); - if ((vma->vm_flags & mask) != mask) + if ((vma->vm_flags & mask) != mask) { + +#ifdef CONFIG_PAX_PAGEEXEC + if (!(vma->vm_flags & VM_EXEC) && (mask & VM_EXEC)) { + if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->cr_iip) + goto bad_area; + + up_read(&mm->mmap_sem); + pax_report_fault(regs, (void *)regs->cr_iip, (void *)regs->r12); + do_group_exit(SIGKILL); + } +#endif + goto bad_area; + } + survive: /* * If for any reason at all we couldn't handle the fault, make diff -urNp linux-2.6.31/arch/ia64/mm/init.c linux-2.6.31/arch/ia64/mm/init.c --- linux-2.6.31/arch/ia64/mm/init.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/ia64/mm/init.c 2009-09-06 15:29:11.117202694 -0400 @@ -122,6 +122,19 @@ ia64_init_addr_space (void) vma->vm_start = current->thread.rbs_bot & PAGE_MASK; vma->vm_end = vma->vm_start + PAGE_SIZE; vma->vm_flags = VM_DATA_DEFAULT_FLAGS|VM_GROWSUP|VM_ACCOUNT; + +#ifdef CONFIG_PAX_PAGEEXEC + if (current->mm->pax_flags & MF_PAX_PAGEEXEC) { + vma->vm_flags &= ~VM_EXEC; + +#ifdef CONFIG_PAX_MPROTECT + if (current->mm->pax_flags & MF_PAX_MPROTECT) + vma->vm_flags &= ~VM_MAYEXEC; +#endif + + } +#endif + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); down_write(¤t->mm->mmap_sem); if (insert_vm_struct(current->mm, vma)) { diff -urNp linux-2.6.31/arch/m32r/include/asm/atomic.h linux-2.6.31/arch/m32r/include/asm/atomic.h --- linux-2.6.31/arch/m32r/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/m32r/include/asm/atomic.h 2009-09-11 22:04:17.637685200 -0400 @@ -29,6 +29,14 @@ #define atomic_read(v) ((v)->counter) /** + * atomic_read_unchecked - read atomic variable + * @v: pointer of type atomic_unchecked_t + * + * Atomically reads the value of @v. + */ +#define atomic_read_unchecked(v) ((v)->counter) + +/** * atomic_set - set atomic variable * @v: pointer of type atomic_t * @i: required value @@ -38,6 +46,15 @@ #define atomic_set(v,i) (((v)->counter) = (i)) /** + * atomic_set_unchecked - set atomic variable + * @v: pointer of type atomic_unchecked_t + * @i: required value + * + * Atomically sets the value of @v to @i. + */ +#define atomic_set_unchecked(v,i) (((v)->counter) = (i)) + +/** * atomic_add_return - add integer to atomic variable and return it * @i: integer value to add * @v: pointer of type atomic_t @@ -308,6 +325,10 @@ static __inline__ void atomic_set_mask(u local_irq_restore(flags); } +#define atomic_inc_unchecked(v) atomic_inc((atomic_t *)(v)) +#define atomic_add_unchecked(i,v) atomic_add((i),(atomic_t *)(v)) +#define atomic_sub_unchecked(i,v) atomic_sub((i),(atomic_t *)(v)) + /* Atomic operations are already serializing on m32r */ #define smp_mb__before_atomic_dec() barrier() #define smp_mb__after_atomic_dec() barrier() diff -urNp linux-2.6.31/arch/m32r/lib/usercopy.c linux-2.6.31/arch/m32r/lib/usercopy.c --- linux-2.6.31/arch/m32r/lib/usercopy.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/m32r/lib/usercopy.c 2009-09-06 15:29:11.118236580 -0400 @@ -14,6 +14,9 @@ unsigned long __generic_copy_to_user(void __user *to, const void *from, unsigned long n) { + if ((long)n < 0) + return n; + prefetch(from); if (access_ok(VERIFY_WRITE, to, n)) __copy_user(to,from,n); @@ -23,6 +26,9 @@ __generic_copy_to_user(void __user *to, unsigned long __generic_copy_from_user(void *to, const void __user *from, unsigned long n) { + if ((long)n < 0) + return n; + prefetchw(to); if (access_ok(VERIFY_READ, from, n)) __copy_user_zeroing(to,from,n); diff -urNp linux-2.6.31/arch/m68k/include/asm/atomic_mm.h linux-2.6.31/arch/m68k/include/asm/atomic_mm.h --- linux-2.6.31/arch/m68k/include/asm/atomic_mm.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/m68k/include/asm/atomic_mm.h 2009-09-12 09:48:47.937349132 -0400 @@ -16,23 +16,40 @@ #define ATOMIC_INIT(i) { (i) } #define atomic_read(v) ((v)->counter) +#define atomic_read_unchecked(v) ((v)->counter) #define atomic_set(v, i) (((v)->counter) = i) +#define atomic_set_unchecked(v, i) (((v)->counter) = i) static inline void atomic_add(int i, atomic_t *v) { __asm__ __volatile__("addl %1,%0" : "+m" (*v) : "id" (i)); } +static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_add(i, (atomic_t *)v); +} + static inline void atomic_sub(int i, atomic_t *v) { __asm__ __volatile__("subl %1,%0" : "+m" (*v) : "id" (i)); } +static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_sub(i, (atomic_t *)v); +} + static inline void atomic_inc(atomic_t *v) { __asm__ __volatile__("addql #1,%0" : "+m" (*v)); } +static inline void atomic_inc_unchecked(atomic_unchecked_t *v) +{ + atomic_inc((atomic_t *)v); +} + static inline void atomic_dec(atomic_t *v) { __asm__ __volatile__("subql #1,%0" : "+m" (*v)); diff -urNp linux-2.6.31/arch/m68k/include/asm/atomic_no.h linux-2.6.31/arch/m68k/include/asm/atomic_no.h --- linux-2.6.31/arch/m68k/include/asm/atomic_no.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/m68k/include/asm/atomic_no.h 2009-09-12 09:50:27.179985977 -0400 @@ -16,7 +16,9 @@ #define ATOMIC_INIT(i) { (i) } #define atomic_read(v) ((v)->counter) +#define atomic_read_unchecked(v) ((v)->counter) #define atomic_set(v, i) (((v)->counter) = i) +#define atomic_set_unchecked(v, i) (((v)->counter) = i) static __inline__ void atomic_add(int i, atomic_t *v) { @@ -27,6 +29,11 @@ static __inline__ void atomic_add(int i, #endif } +static __inline__ void atomic_add_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_add(i, (atomic_t *)v); +} + static __inline__ void atomic_sub(int i, atomic_t *v) { #ifdef CONFIG_COLDFIRE @@ -36,6 +43,11 @@ static __inline__ void atomic_sub(int i, #endif } +static __inline__ void atomic_sub_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_sub(i, (atomic_t *)v); +} + static __inline__ int atomic_sub_and_test(int i, atomic_t * v) { char c; @@ -56,6 +68,11 @@ static __inline__ void atomic_inc(volati __asm__ __volatile__("addql #1,%0" : "+m" (*v)); } +static __inline__ void atomic_inc_unchecked(volatile atomic_unchecked_t *v) +{ + atomic_inc((volatile atomic_t *)v); +} + /* * atomic_inc_and_test - increment and test * @v: pointer of type atomic_t diff -urNp linux-2.6.31/arch/mips/include/asm/atomic.h linux-2.6.31/arch/mips/include/asm/atomic.h --- linux-2.6.31/arch/mips/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mips/include/asm/atomic.h 2009-09-11 22:19:56.216381287 -0400 @@ -32,6 +32,14 @@ #define atomic_read(v) ((v)->counter) /* + * atomic_read_unchecked - read atomic variable + * @v: pointer of type atomic_unchecked_t + * + * Atomically reads the value of @v. + */ +#define atomic_read_unchecked(v) ((v)->counter) + +/* * atomic_set - set atomic variable * @v: pointer of type atomic_t * @i: required value @@ -41,6 +49,15 @@ #define atomic_set(v, i) ((v)->counter = (i)) /* + * atomic_set_unchecked - set atomic variable + * @v: pointer of type atomic_unchecked_t + * @i: required value + * + * Atomically sets the value of @v to @i. + */ +#define atomic_set_unchecked(v, i) ((v)->counter = (i)) + +/* * atomic_add - add integer to atomic variable * @i: integer value to add * @v: pointer of type atomic_t @@ -381,6 +398,9 @@ static __inline__ int atomic_add_unless( * Atomically increments @v by 1. */ #define atomic_inc(v) atomic_add(1, (v)) +#define atomic_inc_unchecked(v) atomic_inc((atomic_t *)(v)) +#define atomic_add_unchecked(i, v) atomic_add((i), (atomic_t *)(v)) +#define atomic_sub_unchecked(i, v) atomic_sub((i), (atomic_t *)(v)) /* * atomic_dec - decrement and test diff -urNp linux-2.6.31/arch/mips/include/asm/elf.h linux-2.6.31/arch/mips/include/asm/elf.h --- linux-2.6.31/arch/mips/include/asm/elf.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mips/include/asm/elf.h 2009-09-06 15:29:11.120185424 -0400 @@ -368,4 +368,11 @@ extern int dump_task_fpu(struct task_str #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) #endif +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) + +#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) +#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) +#endif + #endif /* _ASM_ELF_H */ diff -urNp linux-2.6.31/arch/mips/include/asm/page.h linux-2.6.31/arch/mips/include/asm/page.h --- linux-2.6.31/arch/mips/include/asm/page.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mips/include/asm/page.h 2009-09-06 15:29:11.120185424 -0400 @@ -92,7 +92,7 @@ extern void copy_user_highpage(struct pa #ifdef CONFIG_CPU_MIPS32 typedef struct { unsigned long pte_low, pte_high; } pte_t; #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32)) - #define __pte(x) ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; }) + #define __pte(x) ({ pte_t __pte = {(x), (x) >> 32}; __pte; }) #else typedef struct { unsigned long long pte; } pte_t; #define pte_val(x) ((x).pte) diff -urNp linux-2.6.31/arch/mips/include/asm/system.h linux-2.6.31/arch/mips/include/asm/system.h --- linux-2.6.31/arch/mips/include/asm/system.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mips/include/asm/system.h 2009-09-06 15:29:11.121159580 -0400 @@ -217,6 +217,6 @@ extern void per_cpu_trap_init(void); */ #define __ARCH_WANT_UNLOCKED_CTXSW -extern unsigned long arch_align_stack(unsigned long sp); +#define arch_align_stack(x) ((x) & ALMASK) #endif /* _ASM_SYSTEM_H */ diff -urNp linux-2.6.31/arch/mips/kernel/binfmt_elfn32.c linux-2.6.31/arch/mips/kernel/binfmt_elfn32.c --- linux-2.6.31/arch/mips/kernel/binfmt_elfn32.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mips/kernel/binfmt_elfn32.c 2009-09-06 15:29:11.121159580 -0400 @@ -50,6 +50,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N #undef ELF_ET_DYN_BASE #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) + +#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) +#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) +#endif + #include #include #include diff -urNp linux-2.6.31/arch/mips/kernel/binfmt_elfo32.c linux-2.6.31/arch/mips/kernel/binfmt_elfo32.c --- linux-2.6.31/arch/mips/kernel/binfmt_elfo32.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mips/kernel/binfmt_elfo32.c 2009-09-06 15:29:11.121159580 -0400 @@ -52,6 +52,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N #undef ELF_ET_DYN_BASE #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) + +#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) +#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) +#endif + #include /* diff -urNp linux-2.6.31/arch/mips/kernel/process.c linux-2.6.31/arch/mips/kernel/process.c --- linux-2.6.31/arch/mips/kernel/process.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mips/kernel/process.c 2009-09-06 15:29:11.121159580 -0400 @@ -470,15 +470,3 @@ unsigned long get_wchan(struct task_stru out: return pc; } - -/* - * Don't forget that the stack pointer must be aligned on a 8 bytes - * boundary for 32-bits ABI and 16 bytes for 64-bits ABI. - */ -unsigned long arch_align_stack(unsigned long sp) -{ - if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) - sp -= get_random_int() & ~PAGE_MASK; - - return sp & ALMASK; -} diff -urNp linux-2.6.31/arch/mips/kernel/syscall.c linux-2.6.31/arch/mips/kernel/syscall.c --- linux-2.6.31/arch/mips/kernel/syscall.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mips/kernel/syscall.c 2009-09-06 15:29:11.122248738 -0400 @@ -99,6 +99,11 @@ unsigned long arch_get_unmapped_area(str do_color_align = 0; if (filp || (flags & MAP_SHARED)) do_color_align = 1; + +#ifdef CONFIG_PAX_RANDMMAP + if (!(current->mm->pax_flags & MF_PAX_RANDMMAP)) +#endif + if (addr) { if (do_color_align) addr = COLOUR_ALIGN(addr, pgoff); @@ -109,7 +114,7 @@ unsigned long arch_get_unmapped_area(str (!vmm || addr + len <= vmm->vm_start)) return addr; } - addr = TASK_UNMAPPED_BASE; + addr = current->mm->mmap_base; if (do_color_align) addr = COLOUR_ALIGN(addr, pgoff); else diff -urNp linux-2.6.31/arch/mips/mm/fault.c linux-2.6.31/arch/mips/mm/fault.c --- linux-2.6.31/arch/mips/mm/fault.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mips/mm/fault.c 2009-09-06 15:29:11.122248738 -0400 @@ -26,6 +26,23 @@ #include #include /* For VMALLOC_END */ +#ifdef CONFIG_PAX_PAGEEXEC +void pax_report_insns(void *pc) +{ + unsigned long i; + + printk(KERN_ERR "PAX: bytes at PC: "); + for (i = 0; i < 5; i++) { + unsigned int c; + if (get_user(c, (unsigned int *)pc+i)) + printk(KERN_CONT "???????? "); + else + printk(KERN_CONT "%08x ", c); + } + printk("\n"); +} +#endif + /* * This routine handles page faults. It determines the address, * and the problem, and then passes it off to one of the appropriate diff -urNp linux-2.6.31/arch/mn10300/include/asm/atomic.h linux-2.6.31/arch/mn10300/include/asm/atomic.h --- linux-2.6.31/arch/mn10300/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mn10300/include/asm/atomic.h 2009-09-11 22:24:04.850517005 -0400 @@ -34,6 +34,15 @@ #define atomic_read(v) ((v)->counter) /** + * atomic_read_unchecked - read atomic variable + * @v: pointer of type atomic_unchecked_t + * + * Atomically reads the value of @v. Note that the guaranteed + * useful range of an atomic_unchecked_t is only 24 bits. + */ +#define atomic_read_unchecked(v) ((v)->counter) + +/** * atomic_set - set atomic variable * @v: pointer of type atomic_t * @i: required value @@ -43,6 +52,16 @@ */ #define atomic_set(v, i) (((v)->counter) = (i)) +/** + * atomic_set_unchecked - set atomic variable + * @v: pointer of type atomic_unchecked_t + * @i: required value + * + * Atomically sets the value of @v to @i. Note that the guaranteed + * useful range of an atomic_unchecked_t is only 24 bits. + */ +#define atomic_set_unchecked(v, i) (((v)->counter) = (i)) + #include /** @@ -99,16 +118,31 @@ static inline void atomic_add(int i, ato atomic_add_return(i, v); } +static inline void atomic_add_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_add_return(i, (atomic_t *)v); +} + static inline void atomic_sub(int i, atomic_t *v) { atomic_sub_return(i, v); } +static inline void atomic_sub_unchecked(int i, atomic_unchecked_t *v) +{ + atomic_sub_return(i, (atomic_t *)v); +} + static inline void atomic_inc(atomic_t *v) { atomic_add_return(1, v); } +static inline void atomic_inc_unchecked(atomic_unchecked_t *v) +{ + atomic_add_return(1, (atomic_t *)v); +} + static inline void atomic_dec(atomic_t *v) { atomic_sub_return(1, v); diff -urNp linux-2.6.31/arch/mn10300/kernel/setup.c linux-2.6.31/arch/mn10300/kernel/setup.c --- linux-2.6.31/arch/mn10300/kernel/setup.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/mn10300/kernel/setup.c 2009-09-06 15:29:11.123326294 -0400 @@ -285,7 +285,7 @@ static void c_stop(struct seq_file *m, v { } -struct seq_operations cpuinfo_op = { +const struct seq_operations cpuinfo_op = { .start = c_start, .next = c_next, .stop = c_stop, diff -urNp linux-2.6.31/arch/parisc/include/asm/atomic.h linux-2.6.31/arch/parisc/include/asm/atomic.h --- linux-2.6.31/arch/parisc/include/asm/atomic.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/parisc/include/asm/atomic.h 2009-09-11 22:30:04.233759484 -0400 @@ -177,6 +177,18 @@ static __inline__ int __atomic_add_retur return ret; } +static __inline__ int __atomic_add_return_unchecked(int i, atomic_unchecked_t *v) +{ + int ret; + unsigned long flags; + _atomic_spin_lock_irqsave(v, flags); + + ret = (v->counter += i); + + _atomic_spin_unlock_irqrestore(v, flags); + return ret; +} + static __inline__ void atomic_set(atomic_t *v, int i) { unsigned long flags; @@ -187,11 +199,26 @@ static __inline__ void atomic_set(atomic _atomic_spin_unlock_irqrestore(v, flags); } +static __inline__ void atomic_set_unchecked(atomic_unchecked_t *v, int i) +{ + unsigned long flags; + _atomic_spin_lock_irqsave(v, flags); + + v->counter = i; + + _atomic_spin_unlock_irqrestore(v, flags); +} + static __inline__ int atomic_read(const atomic_t *v) { return v->counter; } +static __inline__ int atomic_read_unchecked(const atomic_unchecked_t *v) +{ + return v->counter; +} + /* exported interface */ #define atomic_cmpxchg(v, o, n) (cmpxchg(&((v)->counter), (o), (n))) #define atomic_xchg(v, new) (xchg(&((v)->counter), new)) @@ -223,8 +250,11 @@ static __inline__ int atomic_add_unless( #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) #define atomic_add(i,v) ((void)(__atomic_add_return( (i),(v)))) +#define atomic_add_unchecked(i,v) ((void)(__atomic_add_return_unchecked( ((i),(v)))) #define atomic_sub(i,v) ((void)(__atomic_add_return(-(i),(v)))) +#define atomic_sub_unchecked(i,v) ((void)(__atomic_add_return_unchecked(-(i),(v)))) #define atomic_inc(v) ((void)(__atomic_add_return( 1,(v)))) +#define atomic_inc_unchecked(v) ((void)(__atomic_add_return_unchecked( 1,(v)))) #define atomic_dec(v) ((void)(__atomic_add_return( -1,(v)))) #define atomic_add_return(i,v) (__atomic_add_return( (i),(v))) diff -urNp linux-2.6.31/arch/parisc/include/asm/elf.h linux-2.6.31/arch/parisc/include/asm/elf.h --- linux-2.6.31/arch/parisc/include/asm/elf.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/parisc/include/asm/elf.h 2009-09-06 15:29:11.124187237 -0400 @@ -343,6 +343,13 @@ struct pt_regs; /* forward declaration.. #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000) +#ifdef CONFIG_PAX_ASLR +#define PAX_ELF_ET_DYN_BASE 0x10000UL + +#define PAX_DELTA_MMAP_LEN 16 +#define PAX_DELTA_STACK_LEN 16 +#endif + /* This yields a mask that user programs can use to figure out what instruction set this CPU supports. This could be done in user space, but it's not easy, and we've already done it here. */ diff -urNp linux-2.6.31/arch/parisc/include/asm/pgtable.h linux-2.6.31/arch/parisc/include/asm/pgtable.h --- linux-2.6.31/arch/parisc/include/asm/pgtable.h 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/parisc/include/asm/pgtable.h 2009-09-06 15:29:11.124187237 -0400 @@ -207,6 +207,17 @@ #define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED) #define PAGE_COPY PAGE_EXECREAD #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED) + +#ifdef CONFIG_PAX_PAGEEXEC +# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_ACCESSED) +# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED) +# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED) +#else +# define PAGE_SHARED_NOEXEC PAGE_SHARED +# define PAGE_COPY_NOEXEC PAGE_COPY +# define PAGE_READONLY_NOEXEC PAGE_READONLY +#endif + #define PAGE_KERNEL __pgprot(_PAGE_KERNEL) #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE) #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) diff -urNp linux-2.6.31/arch/parisc/kernel/module.c linux-2.6.31/arch/parisc/kernel/module.c --- linux-2.6.31/arch/parisc/kernel/module.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/parisc/kernel/module.c 2009-09-06 15:29:11.125330310 -0400 @@ -95,16 +95,38 @@ /* three functions to determine where in the module core * or init pieces the location is */ +static inline int in_init_rx(struct module *me, void *loc) +{ + return (loc >= me->module_init_rx && + loc < (me->module_init_rx + me->init_size_rx)); +} + +static inline int in_init_rw(struct module *me, void *loc) +{ + return (loc >= me->module_init_rw && + loc < (me->module_init_rw + me->init_size_rw)); +} + static inline int in_init(struct module *me, void *loc) { - return (loc >= me->module_init && - loc <= (me->module_init + me->init_size)); + return in_init_rx(me, loc) || in_init_rw(me, loc); +} + +static inline int in_core_rx(struct module *me, void *loc) +{ + return (loc >= me->module_core_rx && + loc < (me->module_core_rx + me->core_size_rx)); +} + +static inline int in_core_rw(struct module *me, void *loc) +{ + return (loc >= me->module_core_rw && + loc < (me->module_core_rw + me->core_size_rw)); } static inline int in_core(struct module *me, void *loc) { - return (loc >= me->module_core && - loc <= (me->module_core + me->core_size)); + return in_core_rx(me, loc) || in_core_rw(me, loc); } static inline int in_local(struct module *me, void *loc) @@ -364,13 +386,13 @@ int module_frob_arch_sections(CONST Elf_ } /* align things a bit */ - me->core_size = ALIGN(me->core_size, 16); - me->arch.got_offset = me->core_size; - me->core_size += gots * sizeof(struct got_entry); - - me->core_size = ALIGN(me->core_size, 16); - me->arch.fdesc_offset = me->core_size; - me->core_size += fdescs * sizeof(Elf_Fdesc); + me->core_size_rw = ALIGN(me->core_size_rw, 16); + me->arch.got_offset = me->core_size_rw; + me->core_size_rw += gots * sizeof(struct got_entry); + + me->core_size_rw = ALIGN(me->core_size_rw, 16); + me->arch.fdesc_offset = me->core_size_rw; + me->core_size_rw += fdescs * sizeof(Elf_Fdesc); me->arch.got_max = gots; me->arch.fdesc_max = fdescs; @@ -388,7 +410,7 @@ static Elf64_Word get_got(struct module BUG_ON(value == 0); - got = me->module_core + me->arch.got_offset; + got = me->module_core_rw + me->arch.got_offset; for (i = 0; got[i].addr; i++) if (got[i].addr == value) goto out; @@ -406,7 +428,7 @@ static Elf64_Word get_got(struct module #ifdef CONFIG_64BIT static Elf_Addr get_fdesc(struct module *me, unsigned long value) { - Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset; + Elf_Fdesc *fdesc = me->module_core_rw + me->arch.fdesc_offset; if (!value) { printk(KERN_ERR "%s: zero OPD requested!\n", me->name); @@ -424,7 +446,7 @@ static Elf_Addr get_fdesc(struct module /* Create new one */ fdesc->addr = value; - fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset; + fdesc->gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset; return (Elf_Addr)fdesc; } #endif /* CONFIG_64BIT */ @@ -848,7 +870,7 @@ register_unwind_table(struct module *me, table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr; end = table + sechdrs[me->arch.unwind_section].sh_size; - gp = (Elf_Addr)me->module_core + me->arch.got_offset; + gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset; DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n", me->arch.unwind_section, table, end, gp); diff -urNp linux-2.6.31/arch/parisc/kernel/sys_parisc.c linux-2.6.31/arch/parisc/kernel/sys_parisc.c --- linux-2.6.31/arch/parisc/kernel/sys_parisc.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/parisc/kernel/sys_parisc.c 2009-09-06 15:29:11.125330310 -0400 @@ -98,7 +98,7 @@ unsigned long arch_get_unmapped_area(str if (flags & MAP_FIXED) return addr; if (!addr) - addr = TASK_UNMAPPED_BASE; + addr = current->mm->mmap_base; if (filp) { addr = get_shared_area(filp->f_mapping, addr, len, pgoff); diff -urNp linux-2.6.31/arch/parisc/kernel/traps.c linux-2.6.31/arch/parisc/kernel/traps.c --- linux-2.6.31/arch/parisc/kernel/traps.c 2009-09-06 19:00:55.650249496 -0400 +++ linux-2.6.31/arch/parisc/kernel/traps.c 2009-09-06 19:01:14.292191773 -0400 @@ -733,9 +733,7 @@ void notrace handle_interruption(int cod down_read(¤t->mm->mmap_sem); vma = find_vma(current->mm,regs->iaoq[0]); - if (vma && (regs->iaoq[0] >= vma->vm_start) - && (vma->vm_flags & VM_EXEC)) { - + if (vma && (regs->iaoq[0] >= vma->vm_start)) { fault_address = regs->iaoq[0]; fault_space = regs->iasq[0]; diff -urNp linux-2.6.31/arch/parisc/mm/fault.c linux-2.6.31/arch/parisc/mm/fault.c --- linux-2.6.31/arch/parisc/mm/fault.c 2009-08-27 20:59:04.000000000 -0400 +++ linux-2.6.31/arch/parisc/mm/fault.c 2009-09-06 15:29:11.126169242 -0400 @@ -15,6 +15,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,7 @@ DEFINE_PER_CPU(struct exception_data, ex static unsigned long parisc_acctyp(unsigned long code, unsigned int inst) { - if (code == 6 || code == 16) + if (code == 6 || code == 7 || code == 16) return VM_EXEC; switch (inst & 0xf0000000) { @@ -138,6 +139,116 @@ parisc_acctyp(unsigned long code, unsign } #endif +#ifdef CONFIG_PAX_PAGEEXEC +/* + * PaX: decide what to do with offenders (instruction_pointer(regs) = fault address) + * + * returns 1 when task should be killed + * 2 when rt_sigreturn trampoline was detected + * 3 when unpatched PLT trampoline was detected + */ +static int pax_handle_fetch_fault(struct pt_regs *regs) +{ + +#ifdef CONFIG_PAX_EMUPLT + int err; + + do { /* PaX: unpatched PLT emulation */ + unsigned int bl, depwi; + + err = get_user(bl, (unsigned int *)instruction_pointer(regs)); + err |= get_user(depwi, (unsigned int *)(i