diff -NurpX nopatch linux-2.6.7/arch/alpha/kernel/osf_sys.c linux-2.6.7-pax/arch/alpha/kernel/osf_sys.c
--- linux-2.6.7/arch/alpha/kernel/osf_sys.c	2004-06-16 07:18:37.000000000 +0200
+++ linux-2.6.7-pax/arch/alpha/kernel/osf_sys.c	2004-06-19 15:57:00.000000000 +0200
@@ -179,6 +179,11 @@ osf_mmap(unsigned long addr, unsigned lo
 	struct file *file = NULL;
 	unsigned long ret = -EBADF;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 #if 0
 	if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
 		printk("%s: unimplemented OSF mmap flags %04lx\n", 
@@ -1274,6 +1279,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->flags & PF_PAX_RANDMMAP) || !filp)
+#endif
+
 	if (addr) {
 		addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
 		if (addr != (unsigned long) -ENOMEM)
@@ -1281,8 +1290,16 @@ 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 = TASK_UNMAPPED_BASE;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (current->flags & PF_PAX_RANDMMAP)
+		addr += current->mm->delta_mmap;
+#endif
+
+	addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
+
 	if (addr != (unsigned long) -ENOMEM)
 		return addr;
 
diff -NurpX nopatch linux-2.6.7/arch/alpha/mm/fault.c linux-2.6.7-pax/arch/alpha/mm/fault.c
--- linux-2.6.7/arch/alpha/mm/fault.c	2004-06-16 07:19:03.000000000 +0200
+++ linux-2.6.7-pax/arch/alpha/mm/fault.c	2004-06-19 15:57:00.000000000 +0200
@@ -25,6 +25,7 @@
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/binfmts.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -56,6 +57,142 @@ __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
+ *         4 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#ifdef CONFIG_PAX_EMUPLT
+	int err;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (current->flags & PF_PAX_RANDEXEC) {
+		if (regs->pc >= current->mm->start_code &&
+		    regs->pc < current->mm->end_code)
+		{
+			if (regs->r26 == regs->pc)
+				return 1;
+
+			regs->pc += current->mm->delta_exec;
+			return 4;
+		}
+	}
+#endif
+
+#ifdef CONFIG_PAX_EMUPLT
+	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("<invalid address>.");
+			break;
+		}
+		printk("%08x ", c);
+	}
+	printk("\n");
+}
+#endif
 
 /*
  * This routine handles page faults.  It determines the address,
@@ -133,8 +270,34 @@ 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 (!(current->flags & PF_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
+
+#ifdef CONFIG_PAX_RANDEXEC
+			case 4:
+				return;
+#endif
+
+			}
+			pax_report_fault(regs, (void*)regs->pc, (void*)rdusp());
+			do_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 -NurpX nopatch linux-2.6.7/arch/i386/Kconfig linux-2.6.7-pax/arch/i386/Kconfig
--- linux-2.6.7/arch/i386/Kconfig	2004-06-16 07:18:59.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/Kconfig	2004-06-19 15:57:00.000000000 +0200
@@ -396,7 +396,7 @@ config X86_POPAD_OK
 
 config X86_ALIGNMENT_16
 	bool
-	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2
+	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2
 	default y
 
 config X86_GOOD_APIC
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/apm.c linux-2.6.7-pax/arch/i386/kernel/apm.c
--- linux-2.6.7/arch/i386/kernel/apm.c	2004-06-16 07:18:56.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/apm.c	2004-06-19 15:57:00.000000000 +0200
@@ -597,19 +597,40 @@ static u8 apm_bios_call(u32 func, u32 eb
 	int			cpu;
 	struct desc_struct	save_desc_40;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long		cr3;
+#endif
+
 	cpus = apm_save_cpus();
 	
 	cpu = get_cpu();
+
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_open_kernel(flags, cr3);
+#endif
+
 	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
 	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
 
+#ifndef CONFIG_PAX_KERNEXEC
 	local_save_flags(flags);
 	APM_DO_CLI;
+#endif
+
 	APM_DO_SAVE_SEGS;
 	apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi);
 	APM_DO_RESTORE_SEGS;
+
+#ifndef CONFIG_PAX_KERNEXEC
 	local_irq_restore(flags);
+#endif
+
 	cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
+
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_close_kernel(flags, cr3);
+#endif
+
 	put_cpu();
 	apm_restore_cpus(cpus);
 	
@@ -639,20 +660,40 @@ static u8 apm_bios_call_simple(u32 func,
 	int			cpu;
 	struct desc_struct	save_desc_40;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long		cr3;
+#endif
 
 	cpus = apm_save_cpus();
 	
 	cpu = get_cpu();
+
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_open_kernel(flags, cr3);
+#endif
+
 	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
 	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
 
+#ifndef CONFIG_PAX_KERNEXEC
 	local_save_flags(flags);
 	APM_DO_CLI;
+#endif
+
 	APM_DO_SAVE_SEGS;
 	error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax);
 	APM_DO_RESTORE_SEGS;
+
+#ifndef CONFIG_PAX_KERNEXEC
 	local_irq_restore(flags);
+#endif
+
 	cpu_gdt_table[smp_processor_id()][0x40 / 8] = save_desc_40;
+
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_close_kernel(flags, cr3);
+#endif
+
 	put_cpu();
 	apm_restore_cpus(cpus);
 	return error;
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/cpu/common.c linux-2.6.7-pax/arch/i386/kernel/cpu/common.c
--- linux-2.6.7/arch/i386/kernel/cpu/common.c	2004-06-16 07:18:56.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/cpu/common.c	2004-06-19 15:57:00.000000000 +0200
@@ -358,6 +358,10 @@ void __init identify_cpu(struct cpuinfo_
 	if (this_cpu->c_init)
 		this_cpu->c_init(c);
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_NOVSYSCALL)
+	clear_bit(X86_FEATURE_SEP, c->x86_capability);
+#endif
+
 	/* Disable the PN if appropriate */
 	squash_the_stupid_serial_number(c);
 
@@ -554,7 +558,7 @@ void __init cpu_init (void)
 	set_tss_desc(cpu,t);
 	cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff;
 	load_TR_desc();
-	load_LDT(&init_mm.context);
+	_load_LDT(&init_mm.context);
 
 	/* Set up doublefault TSS pointer in the GDT */
 	__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/entry.S linux-2.6.7-pax/arch/i386/kernel/entry.S
--- linux-2.6.7/arch/i386/kernel/entry.S	2004-06-16 07:19:02.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/entry.S	2004-11-06 13:31:38.000000000 +0100
@@ -266,6 +266,15 @@ sysenter_past_esp:
 	movl TI_flags(%ebp), %ecx
 	testw $_TIF_ALLWORK_MASK, %cx
 	jne syscall_exit_work
+
+#ifdef CONFIG_PAX_RANDKSTACK
+	pushl %eax
+	call pax_randomize_kstack
+	popl %eax
+#endif
+
+	xorl %ebp,%ebp	/* prevent info leak */
+
 /* if something modifies registers it must also disable sysexit */
 	movl EIP(%esp), %edx
 	movl OLDESP(%esp), %ecx
@@ -293,6 +302,11 @@ syscall_exit:
 	movl TI_flags(%ebp), %ecx
 	testw $_TIF_ALLWORK_MASK, %cx	# current->work
 	jne syscall_exit_work
+
+#ifdef CONFIG_PAX_RANDKSTACK
+	call pax_randomize_kstack
+#endif
+
 restore_all:
 	RESTORE_ALL
 
@@ -600,7 +614,7 @@ ENTRY(spurious_interrupt_bug)
 	pushl $do_spurious_interrupt_bug
 	jmp error_code
 
-.data
+.section .rodata,"a",@progbits
 ENTRY(sys_call_table)
 	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */
 	.long sys_exit
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/head.S linux-2.6.7-pax/arch/i386/kernel/head.S
--- linux-2.6.7/arch/i386/kernel/head.S	2004-06-16 07:18:57.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/head.S	2004-11-04 22:22:01.000000000 +0100
@@ -48,6 +48,12 @@
 
 
 /*
+ * Real beginning of normal "text" segment
+ */
+ENTRY(stext)
+ENTRY(_stext)
+
+/*
  * 32-bit kernel entrypoint; only used by the boot CPU.  On entry,
  * %esi points to the real-mode code as a 32-bit pointer.
  * CS and DS must be 4 GB flat segments, but we don't depend on
@@ -78,6 +84,19 @@ ENTRY(startup_32)
 	shrl $2,%ecx
 	rep ; stosl
 
+#ifdef CONFIG_PAX_KERNEXEC
+	movl $ __KERNEL_TEXT_OFFSET,%eax
+	movw %ax,(cpu_gdt_table - __PAGE_OFFSET + 0x62)
+	rorl $16,%eax
+	movb %al,(cpu_gdt_table - __PAGE_OFFSET + 0x64)
+	movb %ah,(cpu_gdt_table - __PAGE_OFFSET + 0x67)
+
+	movb %al,(boot_gdt_table - __PAGE_OFFSET + 0x14)
+	movb %ah,(boot_gdt_table - __PAGE_OFFSET + 0x17)
+	rorl $16,%eax
+	movw %ax,(boot_gdt_table - __PAGE_OFFSET + 0x12)
+#endif
+
 /*
  * Initialize page tables.  This creates a PDE and a set of page
  * tables, which are located immediately beyond _end.  The variable
@@ -91,21 +110,36 @@ ENTRY(startup_32)
 page_pde_offset = (__PAGE_OFFSET >> 20);
 
 	movl $(pg0 - __PAGE_OFFSET), %edi
+#ifdef CONFIG_X86_PAE
+	movl $(swapper_pm_dir - __PAGE_OFFSET), %edx
+#else
 	movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
-	movl $0x007, %eax			/* 0x007 = PRESENT+RW+USER */
+#endif
+	movl $0x063, %eax			/* 0x063 = DIRTY+ACCESSED+PRESENT+RW */
 10:
-	leal 0x007(%edi),%ecx			/* Create PDE entry */
+	leal 0x063(%edi),%ecx			/* Create PDE entry */
 	movl %ecx,(%edx)			/* Store identity PDE entry */
 	movl %ecx,page_pde_offset(%edx)		/* Store kernel PDE entry */
+#ifdef CONFIG_X86_PAE
+	movl $0,4(%edx)
+	movl $0,page_pde_offset+4(%edx)
+	addl $8,%edx
+	movl $512, %ecx
+#else
 	addl $4,%edx
 	movl $1024, %ecx
+#endif
 11:
 	stosl
+#ifdef CONFIG_X86_PAE
+	movl $0,(%edi)
+	addl $4,%edi
+#endif
 	addl $0x1000,%eax
 	loop 11b
 	/* End condition: we must map up to and including INIT_MAP_BEYOND_END */
-	/* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */
-	leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp
+	/* bytes beyond the end of our own page tables; the +0x063 is the attribute bits */
+	leal (INIT_MAP_BEYOND_END+0x063)(%edi),%ebp
 	cmpl %ebp,%eax
 	jb 10b
 	movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
@@ -130,6 +164,7 @@ ENTRY(startup_32_smp)
 
 	xorl %ebx,%ebx
 	incl %ebx				/* This is a secondary processor (AP) */
+#endif /* CONFIG_SMP */
 
 /*
  *	New page tables may be in 4Mbyte page mode and may
@@ -154,7 +189,6 @@ ENTRY(startup_32_smp)
 	movl %eax,%cr4
 
 3:
-#endif /* CONFIG_SMP */
 
 /*
  * Enable paging
@@ -378,32 +412,75 @@ ignore_int:
 	popl %eax
 	iret
 
-/*
- * Real beginning of normal "text" segment
- */
-ENTRY(stext)
-ENTRY(_stext)
-
-/*
- * BSS section
- */
-.section ".bss.page_aligned","w"
+.section .data.swapper_pg_dir,"a",@progbits
 ENTRY(swapper_pg_dir)
+#ifdef CONFIG_X86_PAE
+	.long swapper_pm_dir-__PAGE_OFFSET+1
+	.long 0
+	.long swapper_pm_dir+512*8-__PAGE_OFFSET+1
+	.long 0
+	.long swapper_pm_dir+512*16-__PAGE_OFFSET+1
+	.long 0
+	.long swapper_pm_dir+512*24-__PAGE_OFFSET+1
+	.long 0
+#else
+	.fill 1024,4,0
+#endif
+
+#ifdef CONFIG_PAX_KERNEXEC
+ENTRY(kernexec_pg_dir)
+#ifdef CONFIG_X86_PAE
+	.long kernexec_pm_dir-__PAGE_OFFSET+1
+	.long 0
+	.long kernexec_pm_dir+512*8-__PAGE_OFFSET+1
+	.long 0
+	.long kernexec_pm_dir+512*16-__PAGE_OFFSET+1
+	.long 0
+	.long kernexec_pm_dir+512*24-__PAGE_OFFSET+1
+	.long 0
+#else
 	.fill 1024,4,0
+#endif
+#endif
+
+#if CONFIG_X86_PAE
+.section .data.swapper_pm_dir,"a",@progbits
+ENTRY(swapper_pm_dir)
+	.fill 512,8,0
+	.fill 512,8,0
+	.fill 512,8,0
+	.fill 512,8,0
+
+#ifdef CONFIG_PAX_KERNEXEC
+ENTRY(kernexec_pm_dir)
+	.fill 512,8,0
+	.fill 512,8,0
+	.fill 512,8,0
+	.fill 512,8,0
+#endif
+#endif
+
+.section .rodata.empty_zero_page,"a",@progbits
 ENTRY(empty_zero_page)
 	.fill 4096,1,0
 
 /*
- * This starts the data section.
- */
-.data
+ * The IDT has to be page-aligned to simplify the Pentium
+ * F0 0F bug workaround.. We have a special link segment
+ * for this.
+ */
+.section .rodata.idt,"a",@progbits
+ENTRY(idt_table)
+	.fill 256,8,0
+
+.section .rodata,"a",@progbits
+ready:	.byte 0
 
 ENTRY(stack_start)
 	.long init_thread_union+THREAD_SIZE
 	.long __BOOT_DS
 
-ready:	.byte 0
-
+/* This is the default interrupt "handler" :-) */
 int_msg:
 	.asciz "Unknown interrupt or fault at EIP %p %p %p\n"
 
@@ -445,8 +522,8 @@ cpu_gdt_descr:
 	.align L1_CACHE_BYTES
 ENTRY(boot_gdt_table)
 	.fill GDT_ENTRY_BOOT_CS,8,0
-	.quad 0x00cf9a000000ffff	/* kernel 4GB code at 0x00000000 */
-	.quad 0x00cf92000000ffff	/* kernel 4GB data at 0x00000000 */
+	.quad 0x00cf9b000000ffff	/* kernel 4GB code at 0x00000000 */
+	.quad 0x00cf93000000ffff	/* kernel 4GB data at 0x00000000 */
 
 /*
  * The Global Descriptor Table contains 28 quadwords, per-CPU.
@@ -465,28 +542,27 @@ ENTRY(cpu_gdt_table)
 	.quad 0x0000000000000000	/* 0x4b reserved */
 	.quad 0x0000000000000000	/* 0x53 reserved */
 	.quad 0x0000000000000000	/* 0x5b reserved */
-
-	.quad 0x00cf9a000000ffff	/* 0x60 kernel 4GB code at 0x00000000 */
-	.quad 0x00cf92000000ffff	/* 0x68 kernel 4GB data at 0x00000000 */
-	.quad 0x00cffa000000ffff	/* 0x73 user 4GB code at 0x00000000 */
-	.quad 0x00cff2000000ffff	/* 0x7b user 4GB data at 0x00000000 */
+	.quad 0x00cf9b000000ffff	/* 0x60 kernel 4GB code at 0x00000000 */
+	.quad 0x00cf93000000ffff	/* 0x68 kernel 4GB data at 0x00000000 */
+	.quad 0x00cffb000000ffff	/* 0x73 user 4GB code at 0x00000000 */
+	.quad 0x00cff3000000ffff	/* 0x7b user 4GB data at 0x00000000 */
 
 	.quad 0x0000000000000000	/* 0x80 TSS descriptor */
 	.quad 0x0000000000000000	/* 0x88 LDT descriptor */
 
 	/* Segments used for calling PnP BIOS */
-	.quad 0x00c09a0000000000	/* 0x90 32-bit code */
-	.quad 0x00809a0000000000	/* 0x98 16-bit code */
-	.quad 0x0080920000000000	/* 0xa0 16-bit data */
-	.quad 0x0080920000000000	/* 0xa8 16-bit data */
-	.quad 0x0080920000000000	/* 0xb0 16-bit data */
+	.quad 0x00c09b0000000000	/* 0x90 32-bit code */
+	.quad 0x00809b0000000000	/* 0x98 16-bit code */
+	.quad 0x0080930000000000	/* 0xa0 16-bit data */
+	.quad 0x0080930000000000	/* 0xa8 16-bit data */
+	.quad 0x0080930000000000	/* 0xb0 16-bit data */
 	/*
 	 * The APM segments have byte granularity and their bases
 	 * and limits are set at run time.
 	 */
-	.quad 0x00409a0000000000	/* 0xb8 APM CS    code */
-	.quad 0x00009a0000000000	/* 0xc0 APM CS 16 code (16 bit) */
-	.quad 0x0040920000000000	/* 0xc8 APM DS    data */
+	.quad 0x00409b0000000000	/* 0xb8 APM CS    code */
+	.quad 0x00009b0000000000	/* 0xc0 APM CS 16 code (16 bit) */
+	.quad 0x0040930000000000	/* 0xc8 APM DS    data */
 
 	.quad 0x0000000000000000	/* 0xd0 - unused */
 	.quad 0x0000000000000000	/* 0xd8 - unused */
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/irq.c linux-2.6.7-pax/arch/i386/kernel/irq.c
--- linux-2.6.7/arch/i386/kernel/irq.c	2004-06-16 07:18:57.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/irq.c	2004-07-24 21:11:21.000000000 +0200
@@ -1117,8 +1117,8 @@ void init_irq_proc (void)
 
 
 #ifdef CONFIG_4KSTACKS
-static char softirq_stack[NR_CPUS * THREAD_SIZE]  __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
-static char hardirq_stack[NR_CPUS * THREAD_SIZE]  __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
+char softirq_stack[NR_CPUS * THREAD_SIZE]  __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
+char hardirq_stack[NR_CPUS * THREAD_SIZE]  __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
 
 /*
  * allocate per-cpu stacks for hardirq and for softirq processing
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/ldt.c linux-2.6.7-pax/arch/i386/kernel/ldt.c
--- linux-2.6.7/arch/i386/kernel/ldt.c	2004-06-16 07:19:42.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/ldt.c	2004-06-19 15:57:00.000000000 +0200
@@ -102,6 +102,19 @@ int init_new_context(struct task_struct 
 		retval = copy_ldt(&mm->context, &old_mm->context);
 		up(&old_mm->context.sem);
 	}
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+	if (!mm->context.user_cs_limit) {
+		mm->context.user_cs_base = 0UL;
+		mm->context.user_cs_limit = ~0UL;
+
+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
+		cpus_clear(mm->context.cpu_user_cs_mask);
+#endif
+
+	}
+#endif
+
 	return retval;
 }
 
@@ -154,7 +167,7 @@ static int read_default_ldt(void __user 
 {
 	int err;
 	unsigned long size;
-	void *address;
+	const void *address;
 
 	err = 0;
 	address = &default_ldt[0];
@@ -211,6 +224,13 @@ static int write_ldt(void __user * ptr, 
 		}
 	}
 
+#ifdef CONFIG_PAX_SEGMEXEC
+	if ((current->flags & PF_PAX_SEGMEXEC) && (ldt_info.contents & 2)) {
+		error = -EINVAL;
+		goto out_unlock;
+	}
+#endif
+
 	entry_1 = LDT_entry_a(&ldt_info);
 	entry_2 = LDT_entry_b(&ldt_info);
 	if (oldmode)
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/process.c linux-2.6.7-pax/arch/i386/kernel/process.c
--- linux-2.6.7/arch/i386/kernel/process.c	2004-06-16 07:18:37.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/process.c	2004-06-19 15:57:00.000000000 +0200
@@ -352,7 +352,7 @@ int copy_thread(int nr, unsigned long cl
 	struct task_struct *tsk;
 	int err;
 
-	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
+	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info - sizeof(unsigned long))) - 1;
 	struct_cpy(childregs, regs);
 	childregs->eax = 0;
 	childregs->esp = esp;
@@ -454,9 +454,8 @@ void dump_thread(struct pt_regs * regs, 
 int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
 {
 	struct pt_regs ptregs;
-	
-	ptregs = *(struct pt_regs *)
-		((unsigned long)tsk->thread_info+THREAD_SIZE - sizeof(ptregs));
+
+	ptregs = *(struct pt_regs *)(tsk->thread.esp0 - sizeof(ptregs));
 	ptregs.xcs &= 0xffff;
 	ptregs.xds &= 0xffff;
 	ptregs.xes &= 0xffff;
@@ -509,10 +508,18 @@ struct task_struct fastcall * __switch_t
 	int cpu = smp_processor_id();
 	struct tss_struct *tss = init_tss + cpu;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long flags, cr3;
+#endif
+
 	/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
 	__unlazy_fpu(prev_p);
 
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_open_kernel(flags, cr3);
+#endif
+
 	/*
 	 * Reload esp0, LDT and the page table pointer:
 	 */
@@ -523,6 +530,10 @@ struct task_struct fastcall * __switch_t
 	 */
 	load_TLS(next, cpu);
 
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_close_kernel(flags, cr3);
+#endif
+
 	/*
 	 * Save away %fs and %gs. No need to save %es and %ds, as
 	 * those are always kernel segments while inside the kernel.
@@ -688,6 +699,10 @@ asmlinkage int sys_set_thread_area(struc
 	struct desc_struct *desc;
 	int cpu, idx;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long flags, cr3;
+#endif
+
 	if (copy_from_user(&info, u_info, sizeof(info)))
 		return -EFAULT;
 	idx = info.entry_number;
@@ -721,8 +736,17 @@ asmlinkage int sys_set_thread_area(struc
 		desc->a = LDT_entry_a(&info);
 		desc->b = LDT_entry_b(&info);
 	}
+
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_open_kernel(flags, cr3);
+#endif
+
 	load_TLS(t, cpu);
 
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_close_kernel(flags, cr3);
+#endif
+
 	put_cpu();
 
 	return 0;
@@ -776,3 +800,29 @@ asmlinkage int sys_get_thread_area(struc
 	return 0;
 }
 
+#ifdef CONFIG_PAX_RANDKSTACK
+asmlinkage void pax_randomize_kstack(void)
+{
+	struct tss_struct *tss = init_tss + smp_processor_id();
+	unsigned long time;
+
+#ifdef CONFIG_PAX_SOFTMODE
+	if (!pax_aslr)
+		return;
+#endif
+
+	rdtscl(time);
+
+	/* P4 seems to return a 0 LSB, ignore it */
+#ifdef CONFIG_MPENTIUM4
+	time &= 0x3EUL;
+	time <<= 1;
+#else
+	time &= 0x1FUL;
+	time <<= 2;
+#endif
+
+	tss->esp0 ^= time;
+	current->thread.esp0 = tss->esp0;
+}
+#endif
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/reboot.c linux-2.6.7-pax/arch/i386/kernel/reboot.c
--- linux-2.6.7/arch/i386/kernel/reboot.c	2004-06-16 07:19:03.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/reboot.c	2004-06-19 15:57:00.000000000 +0200
@@ -74,18 +74,18 @@ __setup("reboot=", reboot_setup);
    doesn't work with at least one type of 486 motherboard.  It is easy
    to stop this code working; hence the copious comments. */
 
-static unsigned long long
+static const unsigned long long
 real_mode_gdt_entries [3] =
 {
 	0x0000000000000000ULL,	/* Null descriptor */
-	0x00009a000000ffffULL,	/* 16-bit real-mode 64k code at 0x00000000 */
-	0x000092000100ffffULL	/* 16-bit real-mode 64k data at 0x00000100 */
+	0x00009b000000ffffULL,	/* 16-bit real-mode 64k code at 0x00000000 */
+	0x000093000100ffffULL	/* 16-bit real-mode 64k data at 0x00000100 */
 };
 
 static struct
 {
 	unsigned short       size __attribute__ ((packed));
-	unsigned long long * base __attribute__ ((packed));
+	const unsigned long long * base __attribute__ ((packed));
 }
 real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries },
 real_mode_idt = { 0x3ff, 0 },
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/setup.c linux-2.6.7-pax/arch/i386/kernel/setup.c
--- linux-2.6.7/arch/i386/kernel/setup.c	2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/setup.c	2004-11-03 22:15:25.000000000 +0100
@@ -73,7 +73,11 @@ struct cpuinfo_x86 new_cpu_data __initda
 /* common cpu data for all cpus */
 struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 
+#ifdef CONFIG_X86_PAE
+unsigned long mmu_cr4_features = X86_CR4_PAE;
+#else
 unsigned long mmu_cr4_features;
+#endif
 EXPORT_SYMBOL_GPL(mmu_cr4_features);
 
 #ifdef	CONFIG_ACPI_INTERPRETER
@@ -1137,7 +1141,7 @@ void __init setup_arch(char **cmdline_p)
 
 	code_resource.start = virt_to_phys(_text);
 	code_resource.end = virt_to_phys(_etext)-1;
-	data_resource.start = virt_to_phys(_etext);
+	data_resource.start = virt_to_phys(_data);
 	data_resource.end = virt_to_phys(_edata)-1;
 
 	parse_cmdline_early(cmdline_p);
@@ -1197,6 +1201,15 @@ void __init setup_arch(char **cmdline_p)
 #endif
 }
 
+#ifdef CONFIG_PAX_SOFTMODE
+static int __init setup_pax_softmode(char *str)
+{
+	get_option (&str, &pax_softmode);
+	return 1;
+}
+__setup("pax_softmode=", setup_pax_softmode);
+#endif
+
 #include "setup_arch_post.h"
 /*
  * Local Variables:
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/signal.c linux-2.6.7-pax/arch/i386/kernel/signal.c
--- linux-2.6.7/arch/i386/kernel/signal.c	2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/signal.c	2004-06-19 15:57:00.000000000 +0200
@@ -367,7 +367,17 @@ static void setup_frame(int sig, struct 
 	if (err)
 		goto give_sigsegv;
 
+#ifdef CONFIG_PAX_NOVSYSCALL
+	restorer = frame->retcode;
+#else
 	restorer = &__kernel_sigreturn;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->flags & PF_PAX_SEGMEXEC)
+		restorer -= SEGMEXEC_TASK_SIZE;
+#endif
+#endif
+
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 
@@ -450,7 +460,18 @@ static void setup_rt_frame(int sig, stru
 		goto give_sigsegv;
 
 	/* Set up to return from userspace.  */
+
+#ifdef CONFIG_PAX_NOVSYSCALL
+	restorer = frame->retcode;
+#else
 	restorer = &__kernel_rt_sigreturn;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->flags & PF_PAX_SEGMEXEC)
+		restorer -= SEGMEXEC_TASK_SIZE;
+#endif
+#endif
+
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 	err |= __put_user(restorer, &frame->pretcode);
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/sys_i386.c linux-2.6.7-pax/arch/i386/kernel/sys_i386.c
--- linux-2.6.7/arch/i386/kernel/sys_i386.c	2004-06-16 07:20:04.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/sys_i386.c	2004-06-19 15:57:00.000000000 +0200
@@ -49,6 +49,11 @@ static inline long do_mmap2(
 	int error = -EBADF;
 	struct file * file = NULL;
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
@@ -106,6 +111,77 @@ out:
 	return err;
 }
 
+unsigned long
+arch_get_unmapped_area(struct file *filp, unsigned long addr,
+		unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long start_addr, start_mmap, task_unmapped_base, task_size = TASK_SIZE;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->flags & PF_PAX_SEGMEXEC)
+		task_size = SEGMEXEC_TASK_SIZE;
+#endif
+
+	if (len > task_size)
+		return -ENOMEM;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (!(current->flags & PF_PAX_RANDMMAP) || !filp)
+#endif
+
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (task_size - len >= addr &&
+		    (!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+	start_addr = addr = mm->free_area_cache;
+	start_mmap = PAGE_ALIGN(task_size/3);
+	task_unmapped_base = TASK_UNMAPPED_BASE;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (current->flags & PF_PAX_RANDMMAP) {
+		start_mmap += mm->delta_mmap;
+		task_unmapped_base += mm->delta_mmap;
+	}
+#endif
+
+	if (!(flags & MAP_EXECUTABLE) && start_addr < start_mmap)
+		start_addr = addr = start_mmap;
+	else if ((flags & MAP_EXECUTABLE) && start_addr >= start_mmap)
+		start_addr = addr = task_unmapped_base;
+
+full_search:
+	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
+		/* At this point:  (!vma || addr < vma->vm_end). */
+		if (task_size - len < addr) {
+			/*
+			 * Start a new search - just in case we missed
+			 * some holes.
+			 */
+			if (start_addr != task_unmapped_base) {
+				start_addr = addr = task_unmapped_base;
+				goto full_search;
+			}
+			return -ENOMEM;
+		}
+		if (!vma || (addr + len <= vma->vm_start && (addr + len <= mm->start_brk || start_mmap <= addr))) {
+			/*
+			 * Remember the place where we stopped the search:
+			 */
+			mm->free_area_cache = addr + len;
+			return addr;
+		}
+		if (addr < start_mmap && addr + len > mm->start_brk) {
+			addr = start_mmap;
+			goto full_search;
+		} else
+			addr = vma->vm_end;
+	}
+}
 
 struct sel_arg_struct {
 	unsigned long n;
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/sysenter.c linux-2.6.7-pax/arch/i386/kernel/sysenter.c
--- linux-2.6.7/arch/i386/kernel/sysenter.c	2004-06-16 07:20:26.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/sysenter.c	2004-06-19 15:57:00.000000000 +0200
@@ -41,6 +41,7 @@ void enable_sep_cpu(void *info)
 extern const char vsyscall_int80_start, vsyscall_int80_end;
 extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
 
+#ifndef CONFIG_PAX_NOVSYSCALL
 static int __init sysenter_setup(void)
 {
 	unsigned long page = get_zeroed_page(GFP_ATOMIC);
@@ -63,3 +64,4 @@ static int __init sysenter_setup(void)
 }
 
 __initcall(sysenter_setup);
+#endif
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/trampoline.S linux-2.6.7-pax/arch/i386/kernel/trampoline.S
--- linux-2.6.7/arch/i386/kernel/trampoline.S	2004-06-16 07:19:13.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/trampoline.S	2004-06-19 15:57:00.000000000 +0200
@@ -58,7 +58,7 @@ r_base = .
 	inc	%ax		# protected mode (PE) bit
 	lmsw	%ax		# into protected mode
 	# flush prefetch and jump to startup_32_smp in arch/i386/kernel/head.S
-	ljmpl	$__BOOT_CS, $(startup_32_smp-__PAGE_OFFSET)
+	ljmpl	$__BOOT_CS, $(startup_32_smp+__KERNEL_TEXT_OFFSET-__PAGE_OFFSET)
 
 	# These need to be in the same 64K segment as the above;
 	# hence we don't use the boot_gdt_descr defined in head.S
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/traps.c linux-2.6.7-pax/arch/i386/kernel/traps.c
--- linux-2.6.7/arch/i386/kernel/traps.c	2004-06-16 07:19:01.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/traps.c	2004-11-03 22:15:00.000000000 +0100
@@ -26,6 +26,7 @@
 #include <linux/kallsyms.h>
 #include <linux/ptrace.h>
 #include <linux/version.h>
+#include <linux/binfmts.h>
 
 #ifdef CONFIG_EISA
 #include <linux/ioport.h>
@@ -59,18 +60,13 @@ asmlinkage int system_call(void);
 asmlinkage void lcall7(void);
 asmlinkage void lcall27(void);
 
-struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
+const struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
 		{ 0, 0 }, { 0, 0 } };
 
 /* Do we ignore FPU interrupts ? */
 char ignore_fpu_irq = 0;
 
-/*
- * The IDT has to be page-aligned to simplify the Pentium
- * F0 0F bug workaround.. We have a special link segment
- * for this.
- */
-struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
+extern struct desc_struct idt_table[256];
 
 asmlinkage void divide_error(void);
 asmlinkage void debug(void);
@@ -94,10 +90,24 @@ asmlinkage void machine_check(void);
 
 static int kstack_depth_to_print = 24;
 
+#ifdef CONFIG_4KSTACKS
+extern char softirq_stack[];
+extern char hardirq_stack[];
+#endif
+
 static int valid_stack_ptr(struct task_struct *task, void *p)
 {
+
+#ifdef CONFIG_4KSTACKS
+	if ((p <= softirq_stack || p > softirq_stack + sizeof(softirq_stack)) &&
+	    (p <= hardirq_stack || p > hardirq_stack + sizeof(hardirq_stack)) &&
+	    (p <= (void *)task->thread_info))
+		return 0;
+#else
 	if (p <= (void *)task->thread_info)
 		return 0;
+#endif
+
 	if (kstack_end(p))
 		return 0;
 	return 1;
@@ -108,13 +118,15 @@ void print_context_stack(struct task_str
 			 unsigned long ebp)
 {
 	unsigned long addr;
+	int i = kstack_depth_to_print;
 
-	while (valid_stack_ptr(task, (void *)ebp)) {
+	while (i && valid_stack_ptr(task, (void *)ebp)) {
 		addr = *(unsigned long *)(ebp + 4);
 		printk(" [<%08lx>] ", addr);
 		print_symbol("%s", addr);
 		printk("\n");
 		ebp = *(unsigned long *)ebp;
+		--i;
 	}
 }
 #else
@@ -240,13 +252,13 @@ void show_registers(struct pt_regs *regs
 		show_stack(NULL, (unsigned long*)esp);
 
 		printk("Code: ");
-		if(regs->eip < PAGE_OFFSET)
+		if(regs->eip + __KERNEL_TEXT_OFFSET < PAGE_OFFSET)
 			goto bad;
 
 		for(i=0;i<20;i++)
 		{
 			unsigned char c;
-			if(__get_user(c, &((unsigned char*)regs->eip)[i])) {
+			if(__get_user(c, &((unsigned char*)regs->eip)[i+__KERNEL_TEXT_OFFSET])) {
 bad:
 				printk(" Bad EIP value.");
 				break;
@@ -268,7 +280,7 @@ static void handle_BUG(struct pt_regs *r
 	if (regs->xcs & 3)
 		goto no_bug;		/* Not in kernel */
 
-	eip = regs->eip;
+	eip = regs->eip + __KERNEL_TEXT_OFFSET;
 
 	if (eip < PAGE_OFFSET)
 		goto no_bug;
@@ -441,6 +453,22 @@ asmlinkage void do_general_protection(st
 	if (!(regs->xcs & 3))
 		goto gp_in_kernel;
 
+#ifdef CONFIG_PAX_PAGEEXEC
+	if ((current->flags & PF_PAX_PAGEEXEC)) {
+		struct mm_struct *mm = current->mm;
+		unsigned long limit;
+
+		down_write(&mm->mmap_sem);
+		limit = mm->context.user_cs_limit;
+		if (limit < TASK_SIZE) {
+			track_exec_limit(mm, limit, TASK_SIZE, PROT_EXEC);
+			up_write(&mm->mmap_sem);
+			return;
+		}
+		up_write(&mm->mmap_sem);
+	}
+#endif
+
 	current->thread.error_code = error_code;
 	current->thread.trap_no = 13;
 	force_sig(SIGSEGV, current);
@@ -452,8 +480,16 @@ gp_in_vm86:
 	return;
 
 gp_in_kernel:
-	if (!fixup_exception(regs))
+	if (!fixup_exception(regs)) {
+
+#ifdef CONFIG_PAX_KERNEXEC
+		if ((regs->xcs & 0xFFFF) == __KERNEL_CS)
+			die("PAX: suspicious general protection fault", regs, error_code);
+		else
+#endif
+
 		die("general protection fault", regs, error_code);
+	}
 }
 
 static void mem_parity_error(unsigned char reason, struct pt_regs * regs)
@@ -886,7 +922,7 @@ static void __init set_system_gate(unsig
 	_set_gate(idt_table+n,15,3,addr,__KERNEL_CS);
 }
 
-static void __init set_call_gate(void *a, void *addr)
+static void __init set_call_gate(const void *a, void *addr)
 {
 	_set_gate(a,12,3,addr,__KERNEL_CS);
 }
diff -NurpX nopatch linux-2.6.7/arch/i386/kernel/vmlinux.lds.S linux-2.6.7-pax/arch/i386/kernel/vmlinux.lds.S
--- linux-2.6.7/arch/i386/kernel/vmlinux.lds.S	2004-06-16 07:19:01.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/kernel/vmlinux.lds.S	2004-11-04 22:19:42.000000000 +0100
@@ -2,7 +2,12 @@
  * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
  */
 
+#include <linux/config.h>
+
 #include <asm-generic/vmlinux.lds.h>
+#include <asm-i386/page.h>
+#include <asm-i386/segment.h>
+
 #include <asm/thread_info.h>
 
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
@@ -11,56 +16,16 @@ ENTRY(startup_32)
 jiffies = jiffies_64;
 SECTIONS
 {
-  . = 0xC0000000 + 0x100000;
-  /* read-only */
-  _text = .;			/* Text and read-only data */
-  .text : {
-	*(.text)
-	SCHED_TEXT
-	*(.fixup)
-	*(.gnu.warning)
-	} = 0x9090
-
-  _etext = .;			/* End of text section */
-
-  . = ALIGN(16);		/* Exception table */
-  __start___ex_table = .;
-  __ex_table : { *(__ex_table) }
-  __stop___ex_table = .;
-
-  RODATA
-
-  /* writeable */
-  .data : {			/* Data */
-	*(.data)
-	CONSTRUCTORS
+  . = __PAGE_OFFSET + 0x100000;
+  .text.startup : {
+	BYTE(0xEA) /* jmp far */
+	LONG(startup_32 + __KERNEL_TEXT_OFFSET - __PAGE_OFFSET)
+	SHORT(__BOOT_CS)
 	}
 
-  . = ALIGN(4096);
-  __nosave_begin = .;
-  .data_nosave : { *(.data.nosave) }
-  . = ALIGN(4096);
-  __nosave_end = .;
-
-  . = ALIGN(4096);
-  .data.page_aligned : { *(.data.idt) }
-
-  . = ALIGN(32);
-  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
-  _edata = .;			/* End of data section */
-
-  . = ALIGN(THREAD_SIZE);	/* init_task */
-  .data.init_task : { *(.data.init_task) }
-
   /* will be freed after init */
   . = ALIGN(4096);		/* Init code and data */
   __init_begin = .;
-  .init.text : { 
-	_sinittext = .;
-	*(.init.text)
-	_einittext = .;
-  }
   .init.data : { *(.init.data) }
   . = ALIGN(16);
   __setup_start = .;
@@ -89,9 +54,13 @@ SECTIONS
   .altinstructions : { *(.altinstructions) } 
   __alt_instructions_end = .; 
  .altinstr_replacement : { *(.altinstr_replacement) } 
+
+#ifndef CONFIG_PAX_KERNEXEC
   /* .exit.text is discard at runtime, not link time, to deal with references
      from .altinstructions and .eh_frame */
   .exit.text : { *(.exit.text) }
+#endif
+
   .exit.data : { *(.exit.data) }
   . = ALIGN(4096);
   __initramfs_start = .;
@@ -101,15 +70,106 @@ SECTIONS
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
+
+  /* read-only */
+
+#ifdef CONFIG_PAX_KERNEXEC
+  __init_text_start = .;
+  .init.text (. - __KERNEL_TEXT_OFFSET) : AT (__init_text_start) {
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+	*(.exit.text)
+	. = ALIGN(4*1024*1024) - 1;
+	BYTE(0)
+  }
+  . = ALIGN(4096);
+  __init_end = . + __KERNEL_TEXT_OFFSET;
+  /* freed after init ends here */
+
+/*
+ * PaX: this must be kept in synch with the KERNEL_CS base
+ * in the GDTs in arch/i386/kernel/head.S
+ */
+  _text = .;			/* Text and read-only data */
+  .text : AT (. + __KERNEL_TEXT_OFFSET) {
+#else
+  .init.text : {
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+  }
   . = ALIGN(4096);
   __init_end = .;
   /* freed after init ends here */
-	
+
+  _text = .;			/* Text and read-only data */
+  .text : {
+#endif
+
+	*(.text)
+	SCHED_TEXT
+	*(.fixup)
+	*(.gnu.warning)
+	} = 0x9090
+
+  _etext = .;			/* End of text section */
+  . += __KERNEL_TEXT_OFFSET;
+  . = ALIGN(4096);		/* Exception table */
+  __start___ex_table = .;
+  __ex_table : { *(__ex_table) }
+  __stop___ex_table = .;
+
+  . = ALIGN(4096);
+  .rodata.page_aligned : {
+	*(.rodata.empty_zero_page)
+	*(.rodata.idt)
+	}
+
+  RODATA
+
+#ifdef CONFIG_PAX_KERNEXEC
+  . = ALIGN(4*1024*1024);
+#else
+  . = ALIGN(32);
+#endif
+
+  /* writeable */
+  _data = .;
+  .data : {			/* Data */
+	*(.data)
+	CONSTRUCTORS
+	}
+
+  . = ALIGN(4096);
+  __nosave_begin = .;
+  .data_nosave : { *(.data.nosave) }
+  . = ALIGN(4096);
+  __nosave_end = .;
+
+  . = ALIGN(32);
+  .data.cacheline_aligned : { *(.data.cacheline_aligned) }
+
+  . = ALIGN(THREAD_SIZE);	/* init_task */
+  .data.init_task : { *(.data.init_task) }
+
+  . = ALIGN(4096);
+  .data.page_aligned : {
+
+#ifdef CONFIG_X86_PAE
+	*(.data.swapper_pm_dir)
+#endif
+
+	*(.data.swapper_pg_dir)
+	}
+
+  _edata = .;			/* End of data section */
+
   __bss_start = .;		/* BSS */
   .bss : {
 	*(.bss.page_aligned)
 	*(.bss)
-  }
+	}
   . = ALIGN(4);
   __bss_stop = .; 
 
Files linux-2.6.7/arch/i386/kernel/vsyscall-int80.so and linux-2.6.7-pax/arch/i386/kernel/vsyscall-int80.so differ
Files linux-2.6.7/arch/i386/kernel/vsyscall-sysenter.so and linux-2.6.7-pax/arch/i386/kernel/vsyscall-sysenter.so differ
diff -NurpX nopatch linux-2.6.7/arch/i386/mm/fault.c linux-2.6.7-pax/arch/i386/mm/fault.c
--- linux-2.6.7/arch/i386/mm/fault.c	2004-06-16 07:18:37.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/mm/fault.c	2004-11-03 22:13:17.000000000 +0100
@@ -21,6 +21,9 @@
 #include <linux/vt_kern.h>		/* For unblank_screen() */
 #include <linux/highmem.h>
 #include <linux/module.h>
+#include <linux/unistd.h>
+#include <linux/compiler.h>
+#include <linux/binfmts.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -66,7 +69,7 @@ void bust_spinlocks(int yes)
  *
  * If CS is no longer a valid code segment, or if EIP is beyond the
  * limit, or if it is a kernel address when CS is not a kernel segment,
- * then the returned value will be greater than *eip_limit.
+ * =then the returned value will be greater than *eip_limit.
  * 
  * This is slow, but is very rarely executed.
  */
@@ -199,6 +202,27 @@ static inline int is_prefetch(struct pt_
 
 asmlinkage void do_invalid_op(struct pt_regs *, unsigned long);
 
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_EMUTRAMP) || defined(CONFIG_PAX_RANDEXEC)
+static int pax_handle_fetch_fault(struct pt_regs *regs);
+#endif
+
+#ifdef CONFIG_PAX_PAGEEXEC
+/* PaX: called with the page_table_lock spinlock held */
+static inline pte_t * pax_get_pte(struct mm_struct *mm, unsigned long address)
+{
+	pgd_t *pgd;
+	pmd_t *pmd;
+
+	pgd = pgd_offset(mm, address);
+	if (!pgd || !pgd_present(*pgd))
+		return 0;
+	pmd = pmd_offset(pgd, address);
+	if (!pmd || !pmd_present(*pmd))
+		return 0;
+	return pte_offset_map(pmd, address);
+}
+#endif
+
 /*
  * This routine handles page faults.  It determines the address,
  * and the problem, and then passes it off to one of the appropriate
@@ -219,6 +243,11 @@ asmlinkage void do_page_fault(struct pt_
 	int write;
 	siginfo_t info;
 
+#ifdef CONFIG_PAX_PAGEEXEC
+	pte_t *pte;
+	unsigned char pte_mask1, pte_mask2;
+#endif
+
 	/* get the address */
 	__asm__("movl %%cr2,%0":"=r" (address));
 
@@ -262,6 +291,93 @@ asmlinkage void do_page_fault(struct pt_
 	if (in_atomic() || !mm)
 		goto bad_area_nosemaphore;
 
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (unlikely((error_code & 5) != 5 ||
+		     (regs->eflags & X86_EFLAGS_VM) ||
+		     !(tsk->flags & PF_PAX_PAGEEXEC)))
+		goto not_pax_fault;
+
+	/* PaX: it's our fault, let's handle it if we can */
+
+	/* PaX: take a look at read faults before acquiring any locks */
+	if (unlikely(!(error_code & 2) && (regs->eip == address))) {
+		/* instruction fetch attempt from a protected page in user mode */
+		switch (pax_handle_fetch_fault(regs)) {
+
+#ifdef CONFIG_PAX_RANDEXEC
+		case 3:
+			return;
+#endif
+
+#ifdef CONFIG_PAX_EMUTRAMP
+		case 2:
+			return;
+#endif
+
+		}
+		pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
+		do_exit(SIGKILL);
+	}
+
+	spin_lock(&mm->page_table_lock);
+	pte = pax_get_pte(mm, address);
+	if (unlikely(!pte || !(pte_val(*pte) & _PAGE_PRESENT) || pte_exec(*pte))) {
+		pte_unmap(pte);
+		spin_unlock(&mm->page_table_lock);
+		goto not_pax_fault;
+	}
+
+	if (unlikely((error_code & 2) && !pte_write(*pte))) {
+		/* write attempt to a protected page in user mode */
+		pte_unmap(pte);
+		spin_unlock(&mm->page_table_lock);
+		goto not_pax_fault;
+	}
+
+	pte_mask1 = _PAGE_ACCESSED | _PAGE_USER | ((error_code & 2) << (_PAGE_BIT_DIRTY-1));
+
+#ifdef CONFIG_SMP
+	if (likely(cpu_isset(smp_processor_id(), mm->context.cpu_user_cs_mask)) && address >= get_limit(regs->xcs))
+		pte_mask2 = 0;
+	else
+		pte_mask2 = _PAGE_USER;
+#else
+	pte_mask2 = (address >= get_limit(regs->xcs)) ? 0 : _PAGE_USER;
+#endif
+
+	/*
+	 * PaX: fill DTLB with user rights and retry
+	 */
+	__asm__ __volatile__ (
+		"orb %2,%1\n"
+#if defined(CONFIG_M586) || defined(CONFIG_M586TSC)
+/*
+ * PaX: let this uncommented 'invlpg' remind us on the behaviour of Intel's
+ * (and AMD's) TLBs. namely, they do not cache PTEs that would raise *any*
+ * page fault when examined during a TLB load attempt. this is true not only
+ * for PTEs holding a non-present entry but also present entries that will
+ * raise a page fault (such as those set up by PaX, or the copy-on-write
+ * mechanism). in effect it means that we do *not* need to flush the TLBs
+ * for our target pages since their PTEs are simply not in the TLBs at all.
+
+ * the best thing in omitting it is that we gain around 15-20% speed in the
+ * fast path of the page fault handler and can get rid of tracing since we
+ * can no longer flush unintended entries.
+ */
+		"invlpg %0\n"
+#endif
+		"testb $0,%0\n"
+		"xorb %3,%1\n"
+		:
+		: "m" (*(char*)address), "m" (*(char*)pte), "q" (pte_mask1), "q" (pte_mask2)
+		: "memory", "cc");
+	pte_unmap(pte);
+	spin_unlock(&mm->page_table_lock);
+	return;
+
+not_pax_fault:
+#endif
+
 	down_read(&mm->mmap_sem);
 
 	vma = find_vma(mm, address);
@@ -349,6 +465,44 @@ bad_area:
 	up_read(&mm->mmap_sem);
 
 bad_area_nosemaphore:
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+	if ((error_code & 4) && !(regs->eflags & X86_EFLAGS_VM)) {
+
+#ifdef CONFIG_PAX_PAGEEXEC
+		if ((tsk->flags & PF_PAX_PAGEEXEC) && !(error_code & 3) && (regs->eip == address)) {
+			pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
+			do_exit(SIGKILL);
+		}
+#endif
+
+#ifdef CONFIG_PAX_SEGMEXEC
+		if ((tsk->flags & PF_PAX_SEGMEXEC) && !(error_code & 3) && (regs->eip + SEGMEXEC_TASK_SIZE == address)) {
+
+#if defined(CONFIG_PAX_EMUTRAMP) || defined(CONFIG_PAX_RANDEXEC)
+			switch (pax_handle_fetch_fault(regs)) {
+
+#ifdef CONFIG_PAX_RANDEXEC
+			case 3:
+				return;
+#endif
+
+#ifdef CONFIG_PAX_EMUTRAMP
+			case 2:
+				return;
+#endif
+
+			}
+#endif
+
+			pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
+			do_exit(SIGKILL);
+		}
+#endif
+
+	}
+#endif
+
 	/* User mode accesses just cause a SIGSEGV */
 	if (error_code & 4) {
 		/* 
@@ -408,6 +562,14 @@ no_context:
 
 	if (address < PAGE_SIZE)
 		printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+
+#ifdef CONFIG_PAX_KERNEXEC
+	else if (init_mm.start_code + __KERNEL_TEXT_OFFSET <= address &&
+		 address < init_mm.end_code + __KERNEL_TEXT_OFFSET)
+		printk(KERN_ERR "PAX: %s:%d, uid/euid: %u/%u, attempted to modify kernel code",
+				 tsk->comm, tsk->pid, tsk->uid, tsk->euid);
+#endif
+
 	else
 		printk(KERN_ALERT "Unable to handle kernel paging request");
 	printk(" at virtual address %08lx\n",address);
@@ -423,7 +585,7 @@ no_context:
 	 * it's allocated already.
 	 */
 #ifndef CONFIG_HIGHPTE
-	if (page & 1) {
+	if ((page & (_PAGE_PRESENT | _PAGE_PSE)) == _PAGE_PRESENT) {
 		page &= PAGE_MASK;
 		address &= 0x003ff000;
 		page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
@@ -509,3 +671,252 @@ vmalloc_fault:
 		return;
 	}
 }
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_EMUTRAMP) || defined(CONFIG_PAX_RANDEXEC)
+/*
+ * PaX: decide what to do with offenders (regs->eip = fault address)
+ *
+ * returns 1 when task should be killed
+ *         2 when gcc trampoline was detected
+ *         3 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#ifdef CONFIG_PAX_EMUTRAMP
+	static const unsigned char trans[8] = {6, 1, 2, 0, 13, 5, 3, 4};
+#endif
+
+#if defined(CONFIG_PAX_RANDEXEC) || defined(CONFIG_PAX_EMUTRAMP)
+	int err;
+#endif
+
+	if (regs->eflags & X86_EFLAGS_VM)
+		return 1;
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (current->flags & PF_PAX_RANDEXEC) {
+		unsigned long esp_4;
+
+		if (regs->eip >= current->mm->start_code &&
+		    regs->eip < current->mm->end_code)
+		{
+			err = get_user(esp_4, (unsigned long*)(regs->esp-4UL));
+			if (err || esp_4 == regs->eip)
+				return 1;
+
+			regs->eip += current->mm->delta_exec;
+			return 3;
+		}
+	}
+#endif
+
+#ifdef CONFIG_PAX_EMUTRAMP
+	do { /* PaX: gcc trampoline emulation #1 */
+		unsigned char mov1, mov2;
+		unsigned short jmp;
+		unsigned long addr1, addr2, ret;
+		unsigned short call;
+
+		err = get_user(mov1, (unsigned char *)regs->eip);
+		err |= get_user(addr1, (unsigned long *)(regs->eip + 1));
+		err |= get_user(mov2, (unsigned char *)(regs->eip + 5));
+		err |= get_user(addr2, (unsigned long *)(regs->eip + 6));
+		err |= get_user(jmp, (unsigned short *)(regs->eip + 10));
+		err |= get_user(ret, (unsigned long *)regs->esp);
+
+		if (err)
+			break;
+
+		err = get_user(call, (unsigned short *)(ret-2));
+		if (err)
+			break;
+
+		if ((mov1 & 0xF8) == 0xB8 &&
+		    (mov2 & 0xF8) == 0xB8 &&
+		    (mov1 & 0x07) != (mov2 & 0x07) &&
+		    (jmp & 0xF8FF) == 0xE0FF &&
+		    (mov2 & 0x07) == ((jmp>>8) & 0x07) &&
+		    (call & 0xF8FF) == 0xD0FF &&
+		    regs->eip == ((unsigned long*)regs)[trans[(call>>8) & 0x07]])
+		{
+			((unsigned long *)regs)[trans[mov1 & 0x07]] = addr1;
+			((unsigned long *)regs)[trans[mov2 & 0x07]] = addr2;
+			regs->eip = addr2;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: gcc trampoline emulation #2 */
+		unsigned char mov, jmp;
+		unsigned long addr1, addr2, ret;
+		unsigned short call;
+
+		err = get_user(mov, (unsigned char *)regs->eip);
+		err |= get_user(addr1, (unsigned long *)(regs->eip + 1));
+		err |= get_user(jmp, (unsigned char *)(regs->eip + 5));
+		err |= get_user(addr2, (unsigned long *)(regs->eip + 6));
+		err |= get_user(ret, (unsigned long *)regs->esp);
+
+		if (err)
+			break;
+
+		err = get_user(call, (unsigned short *)(ret-2));
+		if (err)
+			break;
+
+		if ((mov & 0xF8) == 0xB8 &&
+		    jmp == 0xE9 &&
+		    (call & 0xF8FF) == 0xD0FF &&
+		    regs->eip == ((unsigned long*)regs)[trans[(call>>8) & 0x07]])
+		{
+			((unsigned long *)regs)[trans[mov & 0x07]] = addr1;
+			regs->eip += addr2 + 10;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: gcc trampoline emulation #3 */
+		unsigned char mov, jmp;
+		char offset;
+		unsigned long addr1, addr2, ret;
+		unsigned short call;
+
+		err = get_user(mov, (unsigned char *)regs->eip);
+		err |= get_user(addr1, (unsigned long *)(regs->eip + 1));
+		err |= get_user(jmp, (unsigned char *)(regs->eip + 5));
+		err |= get_user(addr2, (unsigned long *)(regs->eip + 6));
+		err |= get_user(ret, (unsigned long *)regs->esp);
+
+		if (err)
+			break;
+
+		err = get_user(call, (unsigned short *)(ret-3));
+		err |= get_user(offset, (char *)(ret-1));
+		if (err)
+			break;
+
+		if ((mov & 0xF8) == 0xB8 &&
+		    jmp == 0xE9 &&
+		    call == 0x55FF)
+		{
+			unsigned long addr;
+
+			err = get_user(addr, (unsigned long*)(regs->ebp + (unsigned long)(long)offset));
+			if (err || regs->eip != addr)
+				break;
+
+			((unsigned long *)regs)[trans[mov & 0x07]] = addr1;
+			regs->eip += addr2 + 10;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: gcc trampoline emulation #4 */
+		unsigned char mov, jmp, sib;
+		char offset;
+		unsigned long addr1, addr2, ret;
+		unsigned short call;
+
+		err = get_user(mov, (unsigned char *)regs->eip);
+		err |= get_user(addr1, (unsigned long *)(regs->eip + 1));
+		err |= get_user(jmp, (unsigned char *)(regs->eip + 5));
+		err |= get_user(addr2, (unsigned long *)(regs->eip + 6));
+		err |= get_user(ret, (unsigned long *)regs->esp);
+
+		if (err)
+			break;
+
+		err = get_user(call, (unsigned short *)(ret-4));
+		err |= get_user(sib, (unsigned char *)(ret-2));
+		err |= get_user(offset, (char *)(ret-1));
+		if (err)
+			break;
+
+		if ((mov & 0xF8) == 0xB8 &&
+		    jmp == 0xE9 &&
+		    call == 0x54FF &&
+		    sib == 0x24)
+		{
+			unsigned long addr;
+
+			err = get_user(addr, (unsigned long*)(regs->esp + 4 + (unsigned long)(long)offset));
+			if (err || regs->eip != addr)
+				break;
+
+			((unsigned long *)regs)[trans[mov & 0x07]] = addr1;
+			regs->eip += addr2 + 10;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: gcc trampoline emulation #5 */
+		unsigned char mov, jmp, sib;
+		unsigned long addr1, addr2, ret, offset;
+		unsigned short call;
+
+		err = get_user(mov, (unsigned char *)regs->eip);
+		err |= get_user(addr1, (unsigned long *)(regs->eip + 1));
+		err |= get_user(jmp, (unsigned char *)(regs->eip + 5));
+		err |= get_user(addr2, (unsigned long *)(regs->eip + 6));
+		err |= get_user(ret, (unsigned long *)regs->esp);
+
+		if (err)
+			break;
+
+		err = get_user(call, (unsigned short *)(ret-7));
+		err |= get_user(sib, (unsigned char *)(ret-5));
+		err |= get_user(offset, (unsigned long *)(ret-4));
+		if (err)
+			break;
+
+		if ((mov & 0xF8) == 0xB8 &&
+		    jmp == 0xE9 &&
+		    call == 0x94FF &&
+		    sib == 0x24)
+		{
+			unsigned long addr;
+
+			err = get_user(addr, (unsigned long*)(regs->esp + 4 + offset));
+			if (err || regs->eip != addr)
+				break;
+
+			((unsigned long *)regs)[trans[mov & 0x07]] = addr1;
+			regs->eip += addr2 + 10;
+			return 2;
+		}
+	} while (0);
+#endif
+
+	return 1; /* PaX in action */
+}
+#endif
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+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("<invalid address>.");
+			break;
+		}
+		printk("%02x ", c);
+	}
+	printk("\n");
+
+	printk(KERN_ERR "PAX: bytes at SP: ");
+	for (i = 0; i < 20; i++) {
+		unsigned long c;
+		if (get_user(c, (unsigned long*)sp+i)) {
+			printk("<invalid address>.");
+			break;
+		}
+		printk("%08lx ", c);
+	}
+	printk("\n");
+}
+#endif
diff -NurpX nopatch linux-2.6.7/arch/i386/mm/init.c linux-2.6.7-pax/arch/i386/mm/init.c
--- linux-2.6.7/arch/i386/mm/init.c	2004-06-16 07:19:44.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/mm/init.c	2004-11-03 22:02:19.000000000 +0100
@@ -40,6 +40,7 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
+#include <asm/desc.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 unsigned long highstart_pfn, highend_pfn;
@@ -47,27 +48,6 @@ unsigned long highstart_pfn, highend_pfn
 static int do_test_wp_bit(void);
 
 /*
- * Creates a middle page table and puts a pointer to it in the
- * given global directory entry. This only returns the gd entry
- * in non-PAE compilation mode, since the middle layer is folded.
- */
-static pmd_t * __init one_md_table_init(pgd_t *pgd)
-{
-	pmd_t *pmd_table;
-		
-#ifdef CONFIG_X86_PAE
-	pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
-	set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
-	if (pmd_table != pmd_offset(pgd, 0)) 
-		BUG();
-#else
-	pmd_table = pmd_offset(pgd, 0);
-#endif
-
-	return pmd_table;
-}
-
-/*
  * Create a page table and place a pointer to it in a middle page
  * directory entry.
  */
@@ -109,9 +89,6 @@ static void __init page_table_range_init
 	pgd = pgd_base + pgd_idx;
 
 	for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
-		if (pgd_none(*pgd)) 
-			one_md_table_init(pgd);
-
 		pmd = pmd_offset(pgd, vaddr);
 		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
 			if (pmd_none(*pmd)) 
@@ -141,7 +118,7 @@ static void __init kernel_physical_mappi
 	pfn = 0;
 
 	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
-		pmd = one_md_table_init(pgd);
+		pmd = pmd_offset(pgd, 0);
 		if (pfn >= max_low_pfn)
 			continue;
 		for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
@@ -286,13 +263,6 @@ static void __init pagetable_init (void)
 	unsigned long vaddr;
 	pgd_t *pgd_base = swapper_pg_dir;
 
-#ifdef CONFIG_X86_PAE
-	int i;
-	/* Init entries of the first-level page table to the zero page */
-	for (i = 0; i < PTRS_PER_PGD; i++)
-		set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
-#endif
-
 	/* Enable PSE if available */
 	if (cpu_has_pse) {
 		set_in_cr4(X86_CR4_PSE);
@@ -315,17 +285,6 @@ static void __init pagetable_init (void)
 	page_table_range_init(vaddr, 0, pgd_base);
 
 	permanent_kmaps_init(pgd_base);
-
-#ifdef CONFIG_X86_PAE
-	/*
-	 * Add low memory identity-mappings - SMP needs it when
-	 * starting up on an AP from real-mode. In the non-PAE
-	 * case we already have these mappings through head.S.
-	 * All user-space mappings are explicitly cleared after
-	 * SMP startup.
-	 */
-	pgd_base[0] = pgd_base[USER_PTRS_PER_PGD];
-#endif
 }
 
 #if defined(CONFIG_PM_DISK) || defined(CONFIG_SOFTWARE_SUSPEND)
@@ -359,11 +318,7 @@ void zap_low_mappings (void)
 	 * us, because pgd_clear() is a no-op on i386.
 	 */
 	for (i = 0; i < USER_PTRS_PER_PGD; i++)
-#ifdef CONFIG_X86_PAE
-		set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
-#else
 		set_pgd(swapper_pg_dir+i, __pgd(0));
-#endif
 	flush_tlb_all();
 }
 
@@ -405,15 +360,17 @@ void __init paging_init(void)
 
 	load_cr3(swapper_pg_dir);
 
+	__flush_tlb_all();
+
+#ifdef CONFIG_PAX_KERNEXEC
+
 #ifdef CONFIG_X86_PAE
-	/*
-	 * We will bail out later - printk doesn't work right now so
-	 * the user would just see a hanging kernel.
-	 */
-	if (cpu_has_pae)
-		set_in_cr4(X86_CR4_PAE);
+	memcpy(kernexec_pm_dir, swapper_pm_dir, sizeof(kernexec_pm_dir));
+#else
+	memcpy(kernexec_pg_dir, swapper_pg_dir, sizeof(kernexec_pg_dir));
+#endif
+
 #endif
-	__flush_tlb_all();
 
 	kmap_init();
 	zone_sizes_init();
@@ -509,7 +466,7 @@ void __init mem_init(void)
 	set_highmem_pages_init(bad_ppro);
 
 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
-	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_data;
 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
 	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); 
@@ -526,10 +483,6 @@ void __init mem_init(void)
 		(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
 	       );
 
-#ifdef CONFIG_X86_PAE
-	if (!cpu_has_pae)
-		panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
-#endif
 	if (boot_cpu_data.wp_works_ok < 0)
 		test_wp_bit();
 
@@ -600,6 +553,37 @@ void free_initmem(void)
 {
 	unsigned long addr;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	/* PaX: limit KERNEL_CS to actual size */
+	{
+		unsigned long limit;
+		int cpu;
+		pgd_t *pgd;
+		pmd_t *pmd;
+
+		limit = (unsigned long)&_etext >> PAGE_SHIFT;
+		for (cpu = 0; cpu < NR_CPUS; cpu++) {
+			cpu_gdt_table[cpu][GDT_ENTRY_KERNEL_CS].a = (cpu_gdt_table[cpu][GDT_ENTRY_KERNEL_CS].a & 0xFFFF0000UL) | (limit & 0x0FFFFUL);
+			cpu_gdt_table[cpu][GDT_ENTRY_KERNEL_CS].b = (cpu_gdt_table[cpu][GDT_ENTRY_KERNEL_CS].b & 0xFFF0FFFFUL) | (limit & 0xF0000UL);
+		}
+
+	/* PaX: make KERNEL_CS read-only */
+		for (addr = __KERNEL_TEXT_OFFSET; addr < (unsigned long)&_data; addr += PMD_SIZE) {
+			pgd = pgd_offset_k(addr);
+			pmd = pmd_offset(pgd, addr);
+			set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_GLOBAL));
+		}
+		memcpy(kernexec_pg_dir, swapper_pg_dir, sizeof(kernexec_pg_dir));
+		for (addr = __KERNEL_TEXT_OFFSET; addr < (unsigned long)&_data; addr += PMD_SIZE) {
+			pgd = pgd_offset_k(addr);
+			pmd = pmd_offset(pgd, addr);
+			set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW));
+		}
+		flush_tlb_all();
+	}
+#endif
+
+	memset(__init_begin, 0, (unsigned long)&__init_end - (unsigned long)&__init_begin);
 	addr = (unsigned long)(&__init_begin);
 	for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
 		ClearPageReserved(virt_to_page(addr));
diff -NurpX nopatch linux-2.6.7/arch/i386/pci/pcbios.c linux-2.6.7-pax/arch/i386/pci/pcbios.c
--- linux-2.6.7/arch/i386/pci/pcbios.c	2004-06-16 07:18:57.000000000 +0200
+++ linux-2.6.7-pax/arch/i386/pci/pcbios.c	2004-10-31 22:13:30.000000000 +0100
@@ -6,7 +6,7 @@
 #include <linux/init.h>
 #include "pci.h"
 #include "pci-functions.h"
-
+#include <asm/desc.h>
 
 /* BIOS32 signature: "_32_" */
 #define BIOS32_SIGNATURE	(('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
diff -NurpX nopatch linux-2.6.7/arch/ia64/ia32/binfmt_elf32.c linux-2.6.7-pax/arch/ia64/ia32/binfmt_elf32.c
--- linux-2.6.7/arch/ia64/ia32/binfmt_elf32.c	2004-06-16 07:20:03.000000000 +0200
+++ linux-2.6.7-pax/arch/ia64/ia32/binfmt_elf32.c	2004-06-19 15:57:00.000000000 +0200
@@ -41,6 +41,17 @@ static void elf32_set_personality (void)
 #undef SET_PERSONALITY
 #define SET_PERSONALITY(ex, ibcs2)	elf32_set_personality()
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		IA32_PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		((tsk)->personality == PER_LINUX32 ? 16 : 43 - IA32_PAGE_SHIFT)
+#define PAX_DELTA_EXEC_LSB(tsk)		IA32_PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		((tsk)->personality == PER_LINUX32 ? 16 : 43 - IA32_PAGE_SHIFT)
+#define PAX_DELTA_STACK_LSB(tsk)	IA32_PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	((tsk)->personality == PER_LINUX32 ? 16 : 43 - IA32_PAGE_SHIFT)
+#endif
+
 /* Ugly but avoids duplication */
 #include "../../../fs/binfmt_elf.c"
 
diff -NurpX nopatch linux-2.6.7/arch/ia64/ia32/ia32priv.h linux-2.6.7-pax/arch/ia64/ia32/ia32priv.h
--- linux-2.6.7/arch/ia64/ia32/ia32priv.h	2004-06-16 07:20:19.000000000 +0200
+++ linux-2.6.7-pax/arch/ia64/ia32/ia32priv.h	2004-06-19 15:57:00.000000000 +0200
@@ -295,7 +295,14 @@ struct old_linux32_dirent {
 #define ELF_ARCH	EM_386
 
 #define IA32_PAGE_OFFSET	0xc0000000
-#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)
 
 /*
  * The system segments (GDT, TSS, LDT) have to be mapped below 4GB so the IA-32 engine can
diff -NurpX nopatch linux-2.6.7/arch/ia64/ia32/sys_ia32.c linux-2.6.7-pax/arch/ia64/ia32/sys_ia32.c
--- linux-2.6.7/arch/ia64/ia32/sys_ia32.c	2004-06-16 07:19:37.000000000 +0200
+++ linux-2.6.7-pax/arch/ia64/ia32/sys_ia32.c	2004-06-19 15:57:00.000000000 +0200
@@ -433,6 +433,11 @@ sys32_mmap (struct mmap_arg_struct *arg)
 
 	flags = a.flags;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(a.fd);
@@ -454,6 +459,11 @@ sys32_mmap2 (unsigned int addr, unsigned
 	struct file *file = NULL;
 	unsigned long retval;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
diff -NurpX nopatch linux-2.6.7/arch/ia64/kernel/sys_ia64.c linux-2.6.7-pax/arch/ia64/kernel/sys_ia64.c
--- linux-2.6.7/arch/ia64/kernel/sys_ia64.c	2004-06-16 07:19:36.000000000 +0200
+++ linux-2.6.7-pax/arch/ia64/kernel/sys_ia64.c	2004-06-19 15:57:00.000000000 +0200
@@ -27,7 +27,7 @@ arch_get_unmapped_area (struct file *fil
 			unsigned long pgoff, unsigned long flags)
 {
 	long map_shared = (flags & MAP_SHARED);
-	unsigned long start_addr, align_mask = PAGE_SIZE - 1;
+	unsigned long start_addr, align_mask = PAGE_SIZE - 1, task_unmapped_base = TASK_UNMAPPED_BASE;
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 
@@ -38,6 +38,15 @@ arch_get_unmapped_area (struct file *fil
 	if (REGION_NUMBER(addr) == REGION_HPAGE)
 		addr = 0;
 #endif
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (current->flags & PF_PAX_RANDMMAP)
+		task_unmapped_base += mm->delta_mmap;
+	if ((current->flags & PF_PAX_RANDMMAP) && addr && filp)
+		addr = mm->free_area_cache;
+	else
+#endif
+
 	if (!addr)
 		addr = mm->free_area_cache;
 
@@ -56,9 +65,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 != task_unmapped_base) {
 				/* Start a new search --- just in case we missed some holes.  */
-				addr = TASK_UNMAPPED_BASE;
+				addr = task_unmapped_base;
 				goto full_search;
 			}
 			return -ENOMEM;
@@ -185,6 +194,11 @@ do_mmap2 (unsigned long addr, unsigned l
 	unsigned long roff;
 	struct file *file = 0;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
diff -NurpX nopatch linux-2.6.7/arch/ia64/mm/fault.c linux-2.6.7-pax/arch/ia64/mm/fault.c
--- linux-2.6.7/arch/ia64/mm/fault.c	2004-06-16 07:20:04.000000000 +0200
+++ linux-2.6.7-pax/arch/ia64/mm/fault.c	2004-06-19 15:57:00.000000000 +0200
@@ -9,6 +9,7 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/binfmts.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -70,6 +71,54 @@ mapped_kernel_page_is_present (unsigned 
 	return pte_present(pte);
 }
 
+#ifdef CONFIG_PAX_PAGEEXEC
+/*
+ * PaX: decide what to do with offenders (regs->cr_iip = fault address)
+ *
+ * returns 1 when task should be killed
+ *         2 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#ifdef CONFIG_PAX_RANDEXEC
+	int err;
+
+	if (current->flags & PF_PAX_RANDEXEC) {
+		if (regs->cr_iip >= current->mm->start_code &&
+		    regs->cr_iip < current->mm->end_code)
+		{
+#if 0
+			/* PaX: this needs fixing */
+			if (regs->b0 == regs->cr_iip)
+				return 1;
+#endif
+			regs->cr_iip += current->mm->delta_exec;
+			return 2;
+		}
+	}
+#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 < 8; i++) {
+		unsigned int c;
+		if (get_user(c, (unsigned int*)pc+i)) {
+			printk("<invalid address>.");
+			break;
+		}
+		printk("%08x ", c);
+	}
+	printk("\n");
+}
+#endif
+
 void
 ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
 {
@@ -125,9 +174,31 @@ ia64_do_page_fault (unsigned long addres
 		| (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)
 		| (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_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 (!(current->flags & PF_PAX_PAGEEXEC) || address != regs->cr_iip)
+				goto bad_area;
+
+			up_read(&mm->mmap_sem);
+			switch(pax_handle_fetch_fault(regs)) {
+
+#ifdef CONFIG_PAX_RANDEXEC
+			case 2:
+				return;
+#endif
+
+			}
+			pax_report_fault(regs, (void*)regs->cr_iip, (void*)regs->r12);
+			do_exit(SIGKILL);
+		}
+#endif
+
 		goto bad_area;
 
+	}
+
   survive:
 	/*
 	 * If for any reason at all we couldn't handle the fault, make
diff -NurpX nopatch linux-2.6.7/arch/mips/kernel/binfmt_elfn32.c linux-2.6.7-pax/arch/mips/kernel/binfmt_elfn32.c
--- linux-2.6.7/arch/mips/kernel/binfmt_elfn32.c	2004-06-16 07:19:36.000000000 +0200
+++ linux-2.6.7-pax/arch/mips/kernel/binfmt_elfn32.c	2004-06-19 15:57:00.000000000 +0200
@@ -50,6 +50,17 @@ 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(tsk)	(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#endif
+
 #include <asm/processor.h>
 #include <linux/module.h>
 #include <linux/config.h>
diff -NurpX nopatch linux-2.6.7/arch/mips/kernel/binfmt_elfo32.c linux-2.6.7-pax/arch/mips/kernel/binfmt_elfo32.c
--- linux-2.6.7/arch/mips/kernel/binfmt_elfo32.c	2004-06-16 07:19:13.000000000 +0200
+++ linux-2.6.7-pax/arch/mips/kernel/binfmt_elfo32.c	2004-06-19 15:57:00.000000000 +0200
@@ -52,6 +52,17 @@ 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(tsk)	(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#endif
+
 #include <asm/processor.h>
 #include <linux/module.h>
 #include <linux/config.h>
diff -NurpX nopatch linux-2.6.7/arch/mips/kernel/syscall.c linux-2.6.7-pax/arch/mips/kernel/syscall.c
--- linux-2.6.7/arch/mips/kernel/syscall.c	2004-06-16 07:19:44.000000000 +0200
+++ linux-2.6.7-pax/arch/mips/kernel/syscall.c	2004-06-19 15:57:00.000000000 +0200
@@ -86,6 +86,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->flags & PF_PAX_RANDMMAP) || !filp)
+#endif
+
 	if (addr) {
 		if (do_color_align)
 			addr = COLOUR_ALIGN(addr, pgoff);
@@ -96,6 +101,13 @@ unsigned long arch_get_unmapped_area(str
 		    (!vmm || addr + len <= vmm->vm_start))
 			return addr;
 	}
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if ((current->flags & PF_PAX_RANDMMAP) && (!addr || filp))
+		addr = TASK_UNMAPPED_BASE + current->mm->delta_mmap;
+	else
+#endif
+
 	addr = TASK_UNMAPPED_BASE;
 	if (do_color_align)
 		addr = COLOUR_ALIGN(addr, pgoff);
diff -NurpX nopatch linux-2.6.7/arch/mips/mm/fault.c linux-2.6.7-pax/arch/mips/mm/fault.c
--- linux-2.6.7/arch/mips/mm/fault.c	2004-06-16 07:19:02.000000000 +0200
+++ linux-2.6.7-pax/arch/mips/mm/fault.c	2004-06-19 15:57:00.000000000 +0200
@@ -27,6 +27,24 @@
 #include <asm/uaccess.h>
 #include <asm/ptrace.h>
 
+#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("<invalid address>.");
+			break;
+		}
+		printk("%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 -NurpX nopatch linux-2.6.7/arch/parisc/kernel/sys_parisc.c linux-2.6.7-pax/arch/parisc/kernel/sys_parisc.c
--- linux-2.6.7/arch/parisc/kernel/sys_parisc.c	2004-06-16 07:19:52.000000000 +0200
+++ linux-2.6.7-pax/arch/parisc/kernel/sys_parisc.c	2004-06-19 15:57:00.000000000 +0200
@@ -104,6 +104,13 @@ unsigned long arch_get_unmapped_area(str
 {
 	if (len > TASK_SIZE)
 		return -ENOMEM;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if ((current->flags & PF_PAX_RANDMMAP) && (!addr || filp))
+		addr = TASK_UNMAPPED_BASE + current->mm->delta_mmap;
+	else
+#endif
+
 	if (!addr)
 		addr = TASK_UNMAPPED_BASE;
 
@@ -123,6 +130,12 @@ static unsigned long do_mmap2(unsigned l
 {
 	struct file * file = NULL;
 	unsigned long error = -EBADF;
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
 		if (!file)
diff -NurpX nopatch linux-2.6.7/arch/parisc/kernel/traps.c linux-2.6.7-pax/arch/parisc/kernel/traps.c
--- linux-2.6.7/arch/parisc/kernel/traps.c	2004-06-16 07:20:26.000000000 +0200
+++ linux-2.6.7-pax/arch/parisc/kernel/traps.c	2004-06-19 15:57:00.000000000 +0200
@@ -656,9 +656,7 @@ void handle_interruption(int code, struc
 
 			down_read(&current->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 -NurpX nopatch linux-2.6.7/arch/parisc/mm/fault.c linux-2.6.7-pax/arch/parisc/mm/fault.c
--- linux-2.6.7/arch/parisc/mm/fault.c	2004-06-16 07:19:52.000000000 +0200
+++ linux-2.6.7-pax/arch/parisc/mm/fault.c	2004-06-19 15:57:00.000000000 +0200
@@ -16,6 +16,8 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/unistd.h>
+#include <linux/binfmts.h>
 
 #include <asm/uaccess.h>
 #include <asm/traps.h>
@@ -54,7 +56,7 @@
 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) {
@@ -140,6 +142,139 @@ 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
+ *         4 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUTRAMP)
+	int err;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (current->flags & PF_PAX_RANDEXEC) {
+		if (instruction_pointer(regs) >= current->mm->start_code &&
+		    instruction_pointer(regs) < current->mm->end_code)
+		{
+#if 0
+			/* PaX: this needs fixing */
+			if ((regs->gr[2] & ~3UL) == instruction_pointer(regs))
+				return 1;
+#endif
+			regs->iaoq[0] += current->mm->delta_exec;
+			if ((regs->iaoq[1] & ~3UL) >= current->mm->start_code &&
+			    (regs->iaoq[1] & ~3UL) < current->mm->end_code)
+				regs->iaoq[1] += current->mm->delta_exec;
+			return 4;
+		}
+	}
+#endif
+
+#ifdef CONFIG_PAX_EMUPLT
+	do { /* PaX: unpatched PLT emulation */
+		unsigned int bl, depwi;
+
+		err = get_user(bl, (unsigned int*)instruction_pointer(regs));
+		err |= get_user(depwi, (unsigned int*)(instruction_pointer(regs)+4));
+
+		if (err)
+			break;
+
+		if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) {
+			unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12;
+
+			err = get_user(ldw, (unsigned int*)addr);
+			err |= get_user(bv, (unsigned int*)(addr+4));
+			err |= get_user(ldw2, (unsigned int*)(addr+8));
+
+			if (err)
+				break;
+
+			if (ldw == 0x0E801096U &&
+			    bv == 0xEAC0C000U &&
+			    ldw2 == 0x0E881095U)
+			{
+				unsigned int resolver, map;
+
+				err = get_user(resolver, (unsigned int*)(instruction_pointer(regs)+8));
+				err |= get_user(map, (unsigned int*)(instruction_pointer(regs)+12));
+				if (err)
+					break;
+
+				regs->gr[20] = instruction_pointer(regs)+8;
+				regs->gr[21] = map;
+				regs->gr[22] = resolver;
+				regs->iaoq[0] = resolver | 3UL;
+				regs->iaoq[1] = regs->iaoq[0] + 4;
+				return 3;
+			}
+		}
+	} while (0);
+#endif
+
+#ifdef CONFIG_PAX_EMUTRAMP
+
+#ifndef CONFIG_PAX_EMUSIGRT
+	if (!(current->flags & PF_PAX_EMUTRAMP))
+		return 1;
+#endif
+
+	do { /* PaX: rt_sigreturn emulation */
+		unsigned int ldi1, ldi2, bel, nop;
+
+		err = get_user(ldi1, (unsigned int *)instruction_pointer(regs));
+		err |= get_user(ldi2, (unsigned int *)(instruction_pointer(regs)+4));
+		err |= get_user(bel, (unsigned int *)(instruction_pointer(regs)+8));
+		err |= get_user(nop, (unsigned int *)(instruction_pointer(regs)+12));
+
+		if (err)
+			break;
+
+		if ((ldi1 == 0x34190000U || ldi1 == 0x34190002U) &&
+		    ldi2 == 0x3414015AU &&
+		    bel == 0xE4008200U &&
+		    nop == 0x08000240U)
+		{
+			regs->gr[25] = (ldi1 & 2) >> 1;
+			regs->gr[20] = __NR_rt_sigreturn;
+			regs->gr[31] = regs->iaoq[1] + 16;
+			regs->sr[0] = regs->iasq[1];
+			regs->iaoq[0] = 0x100UL;
+			regs->iaoq[1] = regs->iaoq[0] + 4;
+			regs->iasq[0] = regs->sr[2];
+			regs->iasq[1] = regs->sr[2];
+			return 2;
+		}
+	} 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("<invalid address>.");
+			break;
+		}
+		printk("%08x ", c);
+	}
+	printk("\n");
+}
+#endif
+
 void do_page_fault(struct pt_regs *regs, unsigned long code,
 			      unsigned long address)
 {
@@ -165,8 +300,38 @@ good_area:
 
 	acc_type = parisc_acctyp(code,regs->iir);
 
-	if ((vma->vm_flags & acc_type) != acc_type)
+	if ((vma->vm_flags & acc_type) != acc_type) {
+
+#ifdef CONFIG_PAX_PAGEEXEC
+		if ((current->flags & PF_PAX_PAGEEXEC) && (acc_type & VM_EXEC) &&
+		    (address & ~3UL) == instruction_pointer(regs))
+		{
+			up_read(&mm->mmap_sem);
+			switch(pax_handle_fetch_fault(regs)) {
+
+#ifdef CONFIG_PAX_RANDEXEC
+			case 4:
+				return;
+#endif
+
+#ifdef CONFIG_PAX_EMUPLT
+			case 3:
+				return;
+#endif
+
+#ifdef CONFIG_PAX_EMUTRAMP
+			case 2:
+				return;
+#endif
+
+			}
+			pax_report_fault(regs, (void*)instruction_pointer(regs), (void*)regs->gr[30]);
+			do_exit(SIGKILL);
+		}
+#endif
+
 		goto bad_area;
+	}
 
 	/*
 	 * If for any reason at all we couldn't handle the fault, make
diff -NurpX nopatch linux-2.6.7/arch/ppc/kernel/syscalls.c linux-2.6.7-pax/arch/ppc/kernel/syscalls.c
--- linux-2.6.7/arch/ppc/kernel/syscalls.c	2004-06-16 07:20:04.000000000 +0200
+++ linux-2.6.7-pax/arch/ppc/kernel/syscalls.c	2004-06-19 15:57:00.000000000 +0200
@@ -165,6 +165,11 @@ do_mmap2(unsigned long addr, size_t len,
 	struct file * file = NULL;
 	int ret = -EBADF;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
 		if (!(file = fget(fd)))
diff -NurpX nopatch linux-2.6.7/arch/ppc/mm/fault.c linux-2.6.7-pax/arch/ppc/mm/fault.c
--- linux-2.6.7/arch/ppc/mm/fault.c	2004-06-16 07:19:03.000000000 +0200
+++ linux-2.6.7-pax/arch/ppc/mm/fault.c	2004-06-30 19:07:35.000000000 +0200
@@ -28,6 +28,11 @@
 #include <linux/interrupt.h>
 #include <linux/highmem.h>
 #include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/compiler.h>
+#include <linux/binfmts.h>
+#include <linux/unistd.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -51,6 +56,363 @@ unsigned long pte_misses;	/* updated by 
 unsigned long pte_errors;	/* updated by do_page_fault() */
 unsigned int probingmem;
 
+#ifdef CONFIG_PAX_EMUSIGRT
+void pax_syscall_close(struct vm_area_struct * vma)
+{
+	vma->vm_mm->call_syscall = 0UL;
+}
+
+static struct page* pax_syscall_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
+{
+	struct page* page;
+	unsigned int *kaddr;
+
+	page = alloc_page(GFP_HIGHUSER);
+	if (!page)
+		return NOPAGE_OOM;
+
+	kaddr = kmap(page);
+	memset(kaddr, 0, PAGE_SIZE);
+	kaddr[0] = 0x44000002U; /* sc */
+	__flush_dcache_icache(kaddr);
+	kunmap(page);
+	if (type)
+		*type = VM_FAULT_MAJOR;
+	return page;
+}
+
+static struct vm_operations_struct pax_vm_ops = {
+	close:		pax_syscall_close,
+	nopage:		pax_syscall_nopage,
+};
+
+static void pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
+{
+	memset(vma, 0, sizeof(*vma));
+	vma->vm_mm = current->mm;
+	vma->vm_start = addr;
+	vma->vm_end = addr + PAGE_SIZE;
+	vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
+	vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
+	vma->vm_ops = &pax_vm_ops;
+	insert_vm_struct(current->mm, vma);
+	++current->mm->total_vm;
+}
+#endif
+
+#ifdef CONFIG_PAX_PAGEEXEC
+/*
+ * PaX: decide what to do with offenders (regs->nip = fault address)
+ *
+ * returns 1 when task should be killed
+ *         2 when patched GOT trampoline was detected
+ *         3 when patched PLT trampoline was detected
+ *         4 when unpatched PLT trampoline was detected
+ *         5 when legitimate ET_EXEC was detected
+ *         6 when sigreturn trampoline was detected
+ *         7 when rt_sigreturn trampoline was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT)
+	int err;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (current->flags & PF_PAX_RANDEXEC) {
+		if (regs->nip >= current->mm->start_code &&
+		    regs->nip < current->mm->end_code)
+		{
+			if (regs->link == regs->nip)
+				return 1;
+
+			regs->nip += current->mm->delta_exec;
+			return 5;
+		}
+	}
+#endif
+
+#ifdef CONFIG_PAX_EMUPLT
+	do { /* PaX: patched GOT emulation */
+		unsigned int blrl;
+
+		err = get_user(blrl, (unsigned int*)regs->nip);
+
+		if (!err && blrl == 0x4E800021U) {
+			unsigned long temp = regs->nip;
+
+			regs->nip = regs->link & 0xFFFFFFFCUL;
+			regs->link = temp + 4UL;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: patched PLT emulation #1 */
+		unsigned int b;
+
+		err = get_user(b, (unsigned int *)regs->nip);
+
+		if (!err && (b & 0xFC000003U) == 0x48000000U) {
+			regs->nip += (((b | 0xFC000000UL) ^ 0x02000000UL) + 0x02000000UL);
+			return 3;
+		}
+	} while (0);
+
+	do { /* PaX: unpatched PLT emulation #1 */
+		unsigned int li, b;
+
+		err = get_user(li, (unsigned int *)regs->nip);
+		err |= get_user(b, (unsigned int *)(regs->nip+4));
+
+		if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) {
+			unsigned int rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr;
+			unsigned long addr = b | 0xFC000000UL;
+
+			addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL);
+			err = get_user(rlwinm, (unsigned int*)addr);
+			err |= get_user(add, (unsigned int*)(addr+4));
+			err |= get_user(li2, (unsigned int*)(addr+8));
+			err |= get_user(addis2, (unsigned int*)(addr+12));
+			err |= get_user(mtctr, (unsigned int*)(addr+16));
+			err |= get_user(li3, (unsigned int*)(addr+20));
+			err |= get_user(addis3, (unsigned int*)(addr+24));
+			err |= get_user(bctr, (unsigned int*)(addr+28));
+
+			if (err)
+				break;
+
+			if (rlwinm == 0x556C083CU &&
+			    add == 0x7D6C5A14U &&
+			    (li2 & 0xFFFF0000U) == 0x39800000U &&
+			    (addis2 & 0xFFFF0000U) == 0x3D8C0000U &&
+			    mtctr == 0x7D8903A6U &&
+			    (li3 & 0xFFFF0000U) == 0x39800000U &&
+			    (addis3 & 0xFFFF0000U) == 0x3D8C0000U &&
+			    bctr == 0x4E800420U)
+			{
+				regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
+				regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
+				regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16;
+				regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
+				regs->ctr += (addis2 & 0xFFFFU) << 16;
+				regs->nip = regs->ctr;
+				return 4;
+			}
+		}
+	} while (0);
+
+#if 0
+	do { /* PaX: unpatched PLT emulation #2 */
+		unsigned int lis, lwzu, b, bctr;
+
+		err = get_user(lis, (unsigned int *)regs->nip);
+		err |= get_user(lwzu, (unsigned int *)(regs->nip+4));
+		err |= get_user(b, (unsigned int *)(regs->nip+8));
+		err |= get_user(bctr, (unsigned int *)(regs->nip+12));
+
+		if (err)
+			break;
+
+		if ((lis & 0xFFFF0000U) == 0x39600000U &&
+		    (lwzu & 0xU) == 0xU &&
+		    (b & 0xFC000003U) == 0x48000000U &&
+		    bctr == 0x4E800420U)
+		{
+			unsigned int addis, addi, rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr;
+			unsigned long addr = b | 0xFC000000UL;
+
+			addr = regs->nip + 12 + ((addr ^ 0x02000000UL) + 0x02000000UL);
+			err = get_user(addis, (unsigned int*)addr);
+			err |= get_user(addi, (unsigned int*)(addr+4));
+			err |= get_user(rlwinm, (unsigned int*)(addr+8));
+			err |= get_user(add, (unsigned int*)(addr+12));
+			err |= get_user(li2, (unsigned int*)(addr+16));
+			err |= get_user(addis2, (unsigned int*)(addr+20));
+			err |= get_user(mtctr, (unsigned int*)(addr+24));
+			err |= get_user(li3, (unsigned int*)(addr+28));
+			err |= get_user(addis3, (unsigned int*)(addr+32));
+			err |= get_user(bctr, (unsigned int*)(addr+36));
+
+			if (err)
+				break;
+
+			if ((addis & 0xFFFF0000U) == 0x3D6B0000U &&
+			    (addi & 0xFFFF0000U) == 0x396B0000U &&
+			    rlwinm == 0x556C083CU &&
+			    add == 0x7D6C5A14U &&
+			    (li2 & 0xFFFF0000U) == 0x39800000U &&
+			    (addis2 & 0xFFFF0000U) == 0x3D8C0000U &&
+			    mtctr == 0x7D8903A6U &&
+			    (li3 & 0xFFFF0000U) == 0x39800000U &&
+			    (addis3 & 0xFFFF0000U) == 0x3D8C0000U &&
+			    bctr == 0x4E800420U)
+			{
+				regs->gpr[PT_R11] = 
+				regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
+				regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
+				regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16;
+				regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
+				regs->ctr += (addis2 & 0xFFFFU) << 16;
+				regs->nip = regs->ctr;
+				return 4;
+			}
+		}
+	} while (0);
+#endif
+
+	do { /* PaX: unpatched PLT emulation #3 */
+		unsigned int li, b;
+
+		err = get_user(li, (unsigned int *)regs->nip);
+		err |= get_user(b, (unsigned int *)(regs->nip+4));
+
+		if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) {
+			unsigned int addis, lwz, mtctr, bctr;
+			unsigned long addr = b | 0xFC000000UL;
+
+			addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL);
+			err = get_user(addis, (unsigned int*)addr);
+			err |= get_user(lwz, (unsigned int*)(addr+4));
+			err |= get_user(mtctr, (unsigned int*)(addr+8));
+			err |= get_user(bctr, (unsigned int*)(addr+12));
+
+			if (err)
+				break;
+
+			if ((addis & 0xFFFF0000U) == 0x3D6B0000U &&
+			    (lwz & 0xFFFF0000U) == 0x816B0000U &&
+			    mtctr == 0x7D6903A6U &&
+			    bctr == 0x4E800420U)
+			{
+				unsigned int r11;
+
+				addr = (addis << 16) + (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
+				addr += (((lwz | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
+
+				err = get_user(r11, (unsigned int*)addr);
+				if (err)
+					break;
+
+				regs->gpr[PT_R11] = r11;
+				regs->ctr = r11;
+				regs->nip = r11;
+				return 4;
+			}
+		}
+	} while (0);
+#endif
+
+#ifdef CONFIG_PAX_EMUSIGRT
+	do { /* PaX: sigreturn emulation */
+		unsigned int li, sc;
+
+		err = get_user(li, (unsigned int *)regs->nip);
+		err |= get_user(sc, (unsigned int *)(regs->nip+4));
+
+		if (!err && li == 0x38000000U + __NR_sigreturn && sc == 0x44000002U) {
+			struct vm_area_struct *vma;
+			unsigned long call_syscall;
+
+			down_read(&current->mm->mmap_sem);
+			call_syscall = current->mm->call_syscall;
+			up_read(&current->mm->mmap_sem);
+			if (likely(call_syscall))
+				goto emulate;
+
+			vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+
+			down_write(&current->mm->mmap_sem);
+			if (current->mm->call_syscall) {
+				call_syscall = current->mm->call_syscall;
+				up_write(&current->mm->mmap_sem);
+				if (vma) kmem_cache_free(vm_area_cachep, vma);
+				goto emulate;
+			}
+
+			call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
+			if (!vma || (call_syscall & ~PAGE_MASK)) {
+				up_write(&current->mm->mmap_sem);
+				if (vma) kmem_cache_free(vm_area_cachep, vma);
+				return 1;
+			}
+
+			pax_insert_vma(vma, call_syscall);
+			current->mm->call_syscall = call_syscall;
+			up_write(&current->mm->mmap_sem);
+
+emulate:
+			regs->gpr[PT_R0] = __NR_sigreturn;
+			regs->nip = call_syscall;
+			return 6;
+		}
+	} while (0);
+
+	do { /* PaX: rt_sigreturn emulation */
+		unsigned int li, sc;
+
+		err = get_user(li, (unsigned int *)regs->nip);
+		err |= get_user(sc, (unsigned int *)(regs->nip+4));
+
+		if (!err && li == 0x38000000U + __NR_rt_sigreturn && sc == 0x44000002U) {
+			struct vm_area_struct *vma;
+			unsigned int call_syscall;
+
+			down_read(&current->mm->mmap_sem);
+			call_syscall = current->mm->call_syscall;
+			up_read(&current->mm->mmap_sem);
+			if (likely(call_syscall))
+				goto rt_emulate;
+
+			vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+
+			down_write(&current->mm->mmap_sem);
+			if (current->mm->call_syscall) {
+				call_syscall = current->mm->call_syscall;
+				up_write(&current->mm->mmap_sem);
+				if (vma) kmem_cache_free(vm_area_cachep, vma);
+				goto rt_emulate;
+			}
+
+			call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
+			if (!vma || (call_syscall & ~PAGE_MASK)) {
+				up_write(&current->mm->mmap_sem);
+				if (vma) kmem_cache_free(vm_area_cachep, vma);
+				return 1;
+			}
+
+			pax_insert_vma(vma, call_syscall);
+			current->mm->call_syscall = call_syscall;
+			up_write(&current->mm->mmap_sem);
+
+rt_emulate:
+			regs->gpr[PT_R0] = __NR_rt_sigreturn;
+			regs->nip = call_syscall;
+			return 7;
+		}
+	} 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("<invalid address>.");
+			break;
+		}
+		printk("%08x ", c);
+	}
+	printk("\n");
+}
+#endif
+
 /*
  * Check whether the instruction at regs->nip is a store using
  * an update addressing form which will update r1.
@@ -111,7 +473,7 @@ int do_page_fault(struct pt_regs *regs, 
 	 * indicate errors in DSISR but can validly be set in SRR1.
 	 */
 	if (TRAP(regs) == 0x400)
-		error_code &= 0x48200000;
+		error_code &= 0x58200000;
 	else
 		is_write = error_code & 0x02000000;
 #endif /* CONFIG_4xx */
@@ -205,15 +567,14 @@ good_area:
 	} else if (TRAP(regs) == 0x400) {
 		pte_t *ptep;
 
-#if 0
+#if 1
 		/* It would be nice to actually enforce the VM execute
 		   permission on CPUs which can do so, but far too
 		   much stuff in userspace doesn't get the permissions
 		   right, so we let any page be executed for now. */
 		if (! (vma->vm_flags & VM_EXEC))
 			goto bad_area;
-#endif
-
+#else
 		/* Since 4xx supports per-page execute permission,
 		 * we lazily flush dcache to icache. */
 		ptep = NULL;
@@ -233,6 +594,7 @@ good_area:
 		if (ptep != NULL)
 			pte_unmap(ptep);
 #endif
+#endif
 	/* a read */
 	} else {
 		/* protection fault */
@@ -278,6 +640,38 @@ bad_area:
 
 	/* User mode accesses cause a SIGSEGV */
 	if (user_mode(regs)) {
+
+#ifdef CONFIG_PAX_PAGEEXEC
+		if (current->flags & PF_PAX_PAGEEXEC) {
+			if ((TRAP(regs) == 0x400) && (regs->nip == address)) {
+				switch (pax_handle_fetch_fault(regs)) {
+
+#ifdef CONFIG_PAX_EMUPLT
+				case 2:
+				case 3:
+				case 4:
+					return 0;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+				case 5:
+					return 0;
+#endif
+
+#ifdef CONFIG_PAX_EMUSIGRT
+				case 6:
+				case 7:
+					return 0;
+#endif
+
+				}
+
+				pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]);
+				do_exit(SIGKILL);
+			}
+		}
+#endif
+
 		info.si_signo = SIGSEGV;
 		info.si_errno = 0;
 		info.si_code = code;
diff -NurpX nopatch linux-2.6.7/arch/ppc64/kernel/syscalls.c linux-2.6.7-pax/arch/ppc64/kernel/syscalls.c
--- linux-2.6.7/arch/ppc64/kernel/syscalls.c	2004-06-16 07:19:42.000000000 +0200
+++ linux-2.6.7-pax/arch/ppc64/kernel/syscalls.c	2004-06-19 15:57:00.000000000 +0200
@@ -177,6 +177,11 @@ unsigned long sys_mmap(unsigned long add
 	struct file * file = NULL;
 	unsigned long ret = -EBADF;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	if (!(flags & MAP_ANONYMOUS)) {
 		if (!(file = fget(fd)))
 			goto out;
diff -NurpX nopatch linux-2.6.7/arch/ppc64/mm/fault.c linux-2.6.7-pax/arch/ppc64/mm/fault.c
--- linux-2.6.7/arch/ppc64/mm/fault.c	2004-06-16 07:19:44.000000000 +0200
+++ linux-2.6.7-pax/arch/ppc64/mm/fault.c	2004-06-19 15:57:00.000000000 +0200
@@ -29,6 +29,7 @@
 #include <linux/interrupt.h>
 #include <linux/smp_lock.h>
 #include <linux/module.h>
+#include <linux/binfmts.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -75,6 +76,54 @@ static int store_updates_sp(struct pt_re
 	return 0;
 }
 
+#ifdef CONFIG_PAX_PAGEEXEC
+/*
+ * PaX: decide what to do with offenders (regs->nip = fault address)
+ *
+ * returns 1 when task should be killed
+ *         2 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT)
+	int err;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (current->flags & PF_PAX_RANDEXEC) {
+		if (regs->nip >= current->mm->start_code &&
+		    regs->nip < current->mm->end_code)
+		{
+			if (regs->link == regs->nip)
+				return 1;
+
+			regs->nip += current->mm->delta_exec;
+			return 2;
+		}
+	}
+#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("<invalid address>.");
+			break;
+		}
+		printk("%08x ", c);
+	}
+	printk("\n");
+}
+#endif
+
 /*
  * The error_code parameter is
  *  - DSISR for a non-SLB data access fault,
@@ -202,6 +251,25 @@ bad_area:
 
 	/* User mode accesses cause a SIGSEGV */
 	if (user_mode(regs)) {
+
+#ifdef CONFIG_PAX_PAGEEXEC
+		if (current->flags & PF_PAX_PAGEEXEC) {
+			if ((regs->trap == 0x400) && (regs->nip == address)) {
+				switch (pax_handle_fetch_fault(regs)) {
+
+#ifdef CONFIG_PAX_RANDEXEC
+				case 2:
+					return;
+#endif
+
+				}
+
+				pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]);
+				do_exit(SIGKILL);
+			}
+		}
+#endif
+
 		info.si_signo = SIGSEGV;
 		info.si_errno = 0;
 		info.si_code = code;
diff -NurpX nopatch linux-2.6.7/arch/sparc/kernel/sys_sparc.c linux-2.6.7-pax/arch/sparc/kernel/sys_sparc.c
--- linux-2.6.7/arch/sparc/kernel/sys_sparc.c	2004-06-16 07:19:13.000000000 +0200
+++ linux-2.6.7-pax/arch/sparc/kernel/sys_sparc.c	2004-06-19 15:57:00.000000000 +0200
@@ -55,6 +55,13 @@ unsigned long arch_get_unmapped_area(str
 		return -ENOMEM;
 	if (ARCH_SUN4C_SUN4 && len > 0x20000000)
 		return -ENOMEM;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if ((current->flags & PF_PAX_RANDMMAP) && (!addr || filp))
+		addr = TASK_UNMAPPED_BASE + current->mm->delta_mmap;
+	else
+#endif
+
 	if (!addr)
 		addr = TASK_UNMAPPED_BASE;
 
@@ -228,6 +235,11 @@ static unsigned long do_mmap2(unsigned l
 	struct file * file = NULL;
 	unsigned long retval = -EBADF;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
 		if (!file)
diff -NurpX nopatch linux-2.6.7/arch/sparc/kernel/sys_sunos.c linux-2.6.7-pax/arch/sparc/kernel/sys_sunos.c
--- linux-2.6.7/arch/sparc/kernel/sys_sunos.c	2004-06-16 07:19:17.000000000 +0200
+++ linux-2.6.7-pax/arch/sparc/kernel/sys_sunos.c	2004-06-19 16:03:59.000000000 +0200
@@ -71,6 +71,11 @@ asmlinkage unsigned long sunos_mmap(unsi
 	struct file * file = NULL;
 	unsigned long retval, ret_type;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	if (flags & MAP_NORESERVE) {
 		static int cnt;
 		if (cnt++ < 10)
diff -NurpX nopatch linux-2.6.7/arch/sparc/mm/fault.c linux-2.6.7-pax/arch/sparc/mm/fault.c
--- linux-2.6.7/arch/sparc/mm/fault.c	2004-06-16 07:19:11.000000000 +0200
+++ linux-2.6.7-pax/arch/sparc/mm/fault.c	2004-08-31 19:49:57.000000000 +0200
@@ -21,6 +21,10 @@
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/compiler.h>
+#include <linux/binfmts.h>
 
 #include <asm/system.h>
 #include <asm/segment.h>
@@ -220,6 +224,269 @@ static unsigned long compute_si_addr(str
 	return safe_compute_effective_address(regs, insn);
 }
 
+#ifdef CONFIG_PAX_PAGEEXEC
+void pax_emuplt_close(struct vm_area_struct * vma)
+{
+	vma->vm_mm->call_dl_resolve = 0UL;
+}
+
+static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
+{
+	struct page* page;
+	unsigned int *kaddr;
+
+	page = alloc_page(GFP_HIGHUSER);
+	if (!page)
+		return NOPAGE_OOM;
+
+	kaddr = kmap(page);
+	memset(kaddr, 0, PAGE_SIZE);
+	kaddr[0] = 0x9DE3BFA8U; /* save */
+	flush_dcache_page(page);
+	kunmap(page);
+	if (type)
+		*type = VM_FAULT_MAJOR;
+
+	return page;
+}
+
+static struct vm_operations_struct pax_vm_ops = {
+	close:		pax_emuplt_close,
+	nopage:		pax_emuplt_nopage,
+};
+
+static void pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
+{
+	memset(vma, 0, sizeof(*vma));
+	vma->vm_mm = current->mm;
+	vma->vm_start = addr;
+	vma->vm_end = addr + PAGE_SIZE;
+	vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
+	vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
+	vma->vm_ops = &pax_vm_ops;
+	insert_vm_struct(current->mm, vma);
+	++current->mm->total_vm;
+}
+
+/*
+ * 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
+ *         4 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#ifdef CONFIG_PAX_EMUPLT
+	int err;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (current->flags & PF_PAX_RANDEXEC) {
+		if (regs->pc >= current->mm->start_code &&
+		    regs->pc < current->mm->end_code)
+		{
+			if (regs->u_regs[UREG_RETPC] + 8UL == regs->pc)
+				return 1;
+
+			regs->pc += current->mm->delta_exec;
+			if (regs->npc >= current->mm->start_code &&
+			    regs->npc < current->mm->end_code)
+				regs->npc += current->mm->delta_exec;
+			return 4;
+		}
+		if (regs->pc >= current->mm->start_code + current->mm->delta_exec &&
+		    regs->pc < current->mm->end_code + current->mm->delta_exec)
+		{
+			regs->pc -= current->mm->delta_exec;
+			if (regs->npc >= current->mm->start_code + current->mm->delta_exec &&
+			    regs->npc < current->mm->end_code + current->mm->delta_exec)
+				regs->npc -= current->mm->delta_exec;
+		}
+	}
+#endif
+
+#ifdef CONFIG_PAX_EMUPLT
+	do { /* PaX: patched PLT emulation #1 */
+		unsigned int sethi1, sethi2, jmpl;
+
+		err = get_user(sethi1, (unsigned int*)regs->pc);
+		err |= get_user(sethi2, (unsigned int*)(regs->pc+4));
+		err |= get_user(jmpl, (unsigned int*)(regs->pc+8));
+
+		if (err)
+			break;
+
+		if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
+		    (sethi2 & 0xFFC00000U) == 0x03000000U &&
+		    (jmpl & 0xFFFFE000U) == 0x81C06000U)
+		{
+			unsigned int addr;
+
+			regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
+			addr = regs->u_regs[UREG_G1];
+			addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
+			regs->pc = addr;
+			regs->npc = addr+4;
+			return 2;
+		}
+	} while (0);
+
+	{ /* PaX: patched PLT emulation #2 */
+		unsigned int ba;
+
+		err = get_user(ba, (unsigned int*)regs->pc);
+
+		if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
+			unsigned int addr;
+
+			addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
+			regs->pc = addr;
+			regs->npc = addr+4;
+			return 2;
+		}
+	}
+
+	do { /* PaX: patched PLT emulation #3 */
+		unsigned int sethi, jmpl, nop;
+
+		err = get_user(sethi, (unsigned int*)regs->pc);
+		err |= get_user(jmpl, (unsigned int*)(regs->pc+4));
+		err |= get_user(nop, (unsigned int*)(regs->pc+8));
+
+		if (err)
+			break;
+
+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
+		    (jmpl & 0xFFFFE000U) == 0x81C06000U &&
+		    nop == 0x01000000U)
+		{
+			unsigned int addr;
+
+			addr = (sethi & 0x003FFFFFU) << 10;
+			regs->u_regs[UREG_G1] = addr;
+			addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
+			regs->pc = addr;
+			regs->npc = addr+4;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: unpatched PLT emulation step 1 */
+		unsigned int sethi, ba, nop;
+
+		err = get_user(sethi, (unsigned int*)regs->pc);
+		err |= get_user(ba, (unsigned int*)(regs->pc+4));
+		err |= get_user(nop, (unsigned int*)(regs->pc+8));
+
+		if (err)
+			break;
+
+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
+		    ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
+		    nop == 0x01000000U)
+		{
+			unsigned int addr, save, call;
+
+			if ((ba & 0xFFC00000U) == 0x30800000U)
+				addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
+			else
+				addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2);
+
+			err = get_user(save, (unsigned int*)addr);
+			err |= get_user(call, (unsigned int*)(addr+4));
+			err |= get_user(nop, (unsigned int*)(addr+8));
+			if (err)
+				break;
+
+			if (save == 0x9DE3BFA8U &&
+			    (call & 0xC0000000U) == 0x40000000U &&
+			    nop == 0x01000000U)
+			{
+				struct vm_area_struct *vma;
+				unsigned long call_dl_resolve;
+
+				down_read(&current->mm->mmap_sem);
+				call_dl_resolve = current->mm->call_dl_resolve;
+				up_read(&current->mm->mmap_sem);
+				if (likely(call_dl_resolve))
+					goto emulate;
+
+				vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+
+				down_write(&current->mm->mmap_sem);
+				if (current->mm->call_dl_resolve) {
+					call_dl_resolve = current->mm->call_dl_resolve;
+					up_write(&current->mm->mmap_sem);
+					if (vma) kmem_cache_free(vm_area_cachep, vma);
+					goto emulate;
+				}
+
+				call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
+				if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
+					up_write(&current->mm->mmap_sem);
+					if (vma) kmem_cache_free(vm_area_cachep, vma);
+					return 1;
+				}
+
+				pax_insert_vma(vma, call_dl_resolve);
+				current->mm->call_dl_resolve = call_dl_resolve;
+				up_write(&current->mm->mmap_sem);
+
+emulate:
+				regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
+				regs->pc = call_dl_resolve;
+				regs->npc = addr+4;
+				return 3;
+			}
+		}
+	} while (0);
+
+	do { /* PaX: unpatched PLT emulation step 2 */
+		unsigned int save, call, nop;
+
+		err = get_user(save, (unsigned int*)(regs->pc-4));
+		err |= get_user(call, (unsigned int*)regs->pc);
+		err |= get_user(nop, (unsigned int*)(regs->pc+4));
+		if (err)
+			break;
+
+		if (save == 0x9DE3BFA8U &&
+		    (call & 0xC0000000U) == 0x40000000U &&
+		    nop == 0x01000000U)
+		{
+			unsigned int dl_resolve = regs->pc + ((((call | 0xC0000000U) ^ 0x20000000U) + 0x20000000U) << 2);
+
+			regs->u_regs[UREG_RETPC] = regs->pc;
+			regs->pc = dl_resolve;
+			regs->npc = dl_resolve+4;
+			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("<invalid address>.");
+			break;
+		}
+		printk("%08x ", c);
+	}
+	printk("\n");
+}
+#endif
+
 asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
 			       unsigned long address)
 {
@@ -283,6 +550,29 @@ good_area:
 		if(!(vma->vm_flags & VM_WRITE))
 			goto bad_area;
 	} else {
+
+#ifdef CONFIG_PAX_PAGEEXEC
+		if ((current->flags & PF_PAX_PAGEEXEC) && text_fault && !(vma->vm_flags & VM_EXEC)) {
+			up_read(&mm->mmap_sem);
+			switch (pax_handle_fetch_fault(regs)) {
+
+#ifdef CONFIG_PAX_EMUPLT
+			case 2:
+			case 3:
+				return;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+			case 4:
+				return;
+#endif
+
+			}
+			pax_report_fault(regs, (void*)regs->pc, (void*)regs->u_regs[UREG_FP]);
+			do_exit(SIGKILL);
+		}
+#endif
+
 		/* Allow reads even for write-only mappings */
 		if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
 			goto bad_area;
diff -NurpX nopatch linux-2.6.7/arch/sparc/mm/init.c linux-2.6.7-pax/arch/sparc/mm/init.c
--- linux-2.6.7/arch/sparc/mm/init.c	2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7-pax/arch/sparc/mm/init.c	2004-06-19 15:57:01.000000000 +0200
@@ -337,17 +337,17 @@ void __init paging_init(void)
 
 	/* Initialize the protection map with non-constant, MMU dependent values. */
 	protection_map[0] = PAGE_NONE;
-	protection_map[1] = PAGE_READONLY;
-	protection_map[2] = PAGE_COPY;
-	protection_map[3] = PAGE_COPY;
+	protection_map[1] = PAGE_READONLY_NOEXEC;
+	protection_map[2] = PAGE_COPY_NOEXEC;
+	protection_map[3] = PAGE_COPY_NOEXEC;
 	protection_map[4] = PAGE_READONLY;
 	protection_map[5] = PAGE_READONLY;
 	protection_map[6] = PAGE_COPY;
 	protection_map[7] = PAGE_COPY;
 	protection_map[8] = PAGE_NONE;
-	protection_map[9] = PAGE_READONLY;
-	protection_map[10] = PAGE_SHARED;
-	protection_map[11] = PAGE_SHARED;
+	protection_map[9] = PAGE_READONLY_NOEXEC;
+	protection_map[10] = PAGE_SHARED_NOEXEC;
+	protection_map[11] = PAGE_SHARED_NOEXEC;
 	protection_map[12] = PAGE_READONLY;
 	protection_map[13] = PAGE_READONLY;
 	protection_map[14] = PAGE_SHARED;
diff -NurpX nopatch linux-2.6.7/arch/sparc/mm/srmmu.c linux-2.6.7-pax/arch/sparc/mm/srmmu.c
--- linux-2.6.7/arch/sparc/mm/srmmu.c	2004-06-16 07:19:36.000000000 +0200
+++ linux-2.6.7-pax/arch/sparc/mm/srmmu.c	2004-06-19 15:57:01.000000000 +0200
@@ -2149,6 +2149,13 @@ void __init ld_mmu_srmmu(void)
 	BTFIXUPSET_INT(page_shared, pgprot_val(SRMMU_PAGE_SHARED));
 	BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY));
 	BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY));
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	BTFIXUPSET_INT(page_shared_noexec, pgprot_val(SRMMU_PAGE_SHARED_NOEXEC));
+	BTFIXUPSET_INT(page_copy_noexec, pgprot_val(SRMMU_PAGE_COPY_NOEXEC));
+	BTFIXUPSET_INT(page_readonly_noexec, pgprot_val(SRMMU_PAGE_RDONLY_NOEXEC));
+#endif
+
 	BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL));
 	page_kernel = pgprot_val(SRMMU_PAGE_KERNEL);
 	pg_iobits = SRMMU_VALID | SRMMU_WRITE | SRMMU_REF;
diff -NurpX nopatch linux-2.6.7/arch/sparc64/kernel/itlb_base.S linux-2.6.7-pax/arch/sparc64/kernel/itlb_base.S
--- linux-2.6.7/arch/sparc64/kernel/itlb_base.S	2004-06-16 07:18:58.000000000 +0200
+++ linux-2.6.7-pax/arch/sparc64/kernel/itlb_base.S	2004-06-19 15:57:01.000000000 +0200
@@ -41,7 +41,9 @@
 	CREATE_VPTE_OFFSET2(%g4, %g6)			! Create VPTE offset
 	ldxa		[%g3 + %g6] ASI_P, %g5		! Load VPTE
 1:	brgez,pn	%g5, 3f				! Not valid, branch out
-	 nop						! Delay-slot
+	and		%g5, _PAGE_EXEC, %g4
+	brz,pn		%g4, 3f				! Not executable, branch out
+	nop						! Delay-slot
 2:	stxa		%g5, [%g0] ASI_ITLB_DATA_IN	! Load PTE into TLB
 	retry						! Trap return
 3:	rdpr		%pstate, %g4			! Move into alternate globals
@@ -74,8 +76,6 @@ winfix_trampoline:
 	nop
 	nop
 	nop
-	nop
-	nop
 	CREATE_VPTE_NOP
 
 #undef CREATE_VPTE_OFFSET1
diff -NurpX nopatch linux-2.6.7/arch/sparc64/kernel/sys_sparc.c linux-2.6.7-pax/arch/sparc64/kernel/sys_sparc.c
--- linux-2.6.7/arch/sparc64/kernel/sys_sparc.c	2004-06-16 07:19:36.000000000 +0200
+++ linux-2.6.7-pax/arch/sparc64/kernel/sys_sparc.c	2004-06-19 15:57:01.000000000 +0200
@@ -49,7 +49,7 @@ unsigned long arch_get_unmapped_area(str
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct * vma;
-	unsigned long task_size = TASK_SIZE;
+	unsigned long task_size = TASK_SIZE, task_unmapped_base = TASK_UNMAPPED_BASE;
 	unsigned long start_addr;
 	int do_color_align;
 
@@ -72,6 +72,12 @@ unsigned long arch_get_unmapped_area(str
 	if (filp || (flags & MAP_SHARED))
 		do_color_align = 1;
 
+#ifdef CONFIG_PAX_RANDMMAP
+	if (current->flags & PF_PAX_RANDMMAP)
+		task_unmapped_base += mm->delta_mmap;
+	if (!(current->flags & PF_PAX_RANDMMAP) || !filp)
+#endif
+
 	if (addr) {
 		if (do_color_align)
 			addr = COLOUR_ALIGN(addr, pgoff);
@@ -101,8 +107,8 @@ full_search:
 			vma = find_vma(mm, PAGE_OFFSET);
 		}
 		if (task_size < addr) {
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = addr = TASK_UNMAPPED_BASE;
+			if (start_addr != task_unmapped_base) {
+				start_addr = addr = task_unmapped_base;
 				goto full_search;
 			}
 			return -ENOMEM;
@@ -319,6 +325,11 @@ asmlinkage unsigned long sys_mmap(unsign
 	struct file * file = NULL;
 	unsigned long retval = -EBADF;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
 		if (!file)
diff -NurpX nopatch linux-2.6.7/arch/sparc64/kernel/sys_sunos32.c linux-2.6.7-pax/arch/sparc64/kernel/sys_sunos32.c
--- linux-2.6.7/arch/sparc64/kernel/sys_sunos32.c	2004-06-16 07:19:37.000000000 +0200
+++ linux-2.6.7-pax/arch/sparc64/kernel/sys_sunos32.c	2004-06-19 15:57:01.000000000 +0200
@@ -66,6 +66,11 @@ asmlinkage u32 sunos_mmap(u32 addr, u32 
 	struct file *file = NULL;
 	unsigned long retval, ret_type;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	if (flags & MAP_NORESERVE) {
 		static int cnt;
 		if (cnt++ < 10)
diff -NurpX nopatch linux-2.6.7/arch/sparc64/mm/fault.c linux-2.6.7-pax/arch/sparc64/mm/fault.c
--- linux-2.6.7/arch/sparc64/mm/fault.c	2004-06-16 07:20:04.000000000 +0200
+++ linux-2.6.7-pax/arch/sparc64/mm/fault.c	2004-08-31 19:50:42.000000000 +0200
@@ -18,6 +18,10 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/pagemap.h>
+#include <linux/compiler.h>
+#include <linux/binfmts.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -310,6 +314,386 @@ cannot_handle:
 	unhandled_fault (address, current, regs);
 }
 
+#ifdef CONFIG_PAX_PAGEEXEC
+#ifdef CONFIG_PAX_EMUPLT
+static void pax_emuplt_close(struct vm_area_struct * vma)
+{
+	vma->vm_mm->call_dl_resolve = 0UL;
+}
+
+static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
+{
+	struct page* page;
+	unsigned int *kaddr;
+
+	page = alloc_page(GFP_HIGHUSER);
+	if (!page)
+		return NOPAGE_OOM;
+
+	kaddr = kmap(page);
+	memset(kaddr, 0, PAGE_SIZE);
+	kaddr[0] = 0x9DE3BFA8U; /* save */
+	flush_dcache_page(page);
+	kunmap(page);
+	if (type)
+		*type = VM_FAULT_MAJOR;
+	return page;
+}
+
+static struct vm_operations_struct pax_vm_ops = {
+	close:		pax_emuplt_close,
+	nopage:		pax_emuplt_nopage,
+};
+
+static void pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
+{
+	memset(vma, 0, sizeof(*vma));
+	vma->vm_mm = current->mm;
+	vma->vm_start = addr;
+	vma->vm_end = addr + PAGE_SIZE;
+	vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
+	vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
+	vma->vm_ops = &pax_vm_ops;
+	insert_vm_struct(current->mm, vma);
+	++current->mm->total_vm;
+}
+#endif
+
+/*
+ * PaX: decide what to do with offenders (regs->tpc = fault address)
+ *
+ * returns 1 when task should be killed
+ *         2 when patched PLT trampoline was detected
+ *         3 when unpatched PLT trampoline was detected
+ *         4 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#ifdef CONFIG_PAX_EMUPLT
+	int err;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (current->flags & PF_PAX_RANDEXEC) {
+		if (regs->tpc >= current->mm->start_code &&
+		    regs->tpc < current->mm->end_code)
+		{
+			if (regs->u_regs[UREG_RETPC] + 8UL == regs->tpc)
+				return 1;
+
+			regs->tpc += current->mm->delta_exec;
+			if (regs->tnpc >= current->mm->start_code &&
+			    regs->tnpc < current->mm->end_code)
+				regs->tnpc += current->mm->delta_exec;
+			return 4;
+		}
+		if (regs->tpc >= current->mm->start_code + current->mm->delta_exec &&
+		    regs->tpc < current->mm->end_code + current->mm->delta_exec)
+		{
+			regs->tpc -= current->mm->delta_exec;
+			if (regs->tnpc >= current->mm->start_code + current->mm->delta_exec &&
+			    regs->tnpc < current->mm->end_code + current->mm->delta_exec)
+				regs->tnpc -= current->mm->delta_exec;
+		}
+	}
+#endif
+
+#ifdef CONFIG_PAX_EMUPLT
+	do { /* PaX: patched PLT emulation #1 */
+		unsigned int sethi1, sethi2, jmpl;
+
+		err = get_user(sethi1, (unsigned int*)regs->tpc);
+		err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
+		err |= get_user(jmpl, (unsigned int*)(regs->tpc+8));
+
+		if (err)
+			break;
+
+		if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
+		    (sethi2 & 0xFFC00000U) == 0x03000000U &&
+		    (jmpl & 0xFFFFE000U) == 0x81C06000U)
+		{
+			unsigned long addr;
+
+			regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
+			addr = regs->u_regs[UREG_G1];
+			addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
+			regs->tpc = addr;
+			regs->tnpc = addr+4;
+			return 2;
+		}
+	} while (0);
+
+	{ /* PaX: patched PLT emulation #2 */
+		unsigned int ba;
+
+		err = get_user(ba, (unsigned int*)regs->tpc);
+
+		if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
+			unsigned long addr;
+
+			addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
+			regs->tpc = addr;
+			regs->tnpc = addr+4;
+			return 2;
+		}
+	}
+
+	do { /* PaX: patched PLT emulation #3 */
+		unsigned int sethi, jmpl, nop;
+
+		err = get_user(sethi, (unsigned int*)regs->tpc);
+		err |= get_user(jmpl, (unsigned int*)(regs->tpc+4));
+		err |= get_user(nop, (unsigned int*)(regs->tpc+8));
+
+		if (err)
+			break;
+
+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
+		    (jmpl & 0xFFFFE000U) == 0x81C06000U &&
+		    nop == 0x01000000U)
+		{
+			unsigned long addr;
+
+			addr = (sethi & 0x003FFFFFU) << 10;
+			regs->u_regs[UREG_G1] = addr;
+			addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
+			regs->tpc = addr;
+			regs->tnpc = addr+4;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: patched PLT emulation #4 */
+		unsigned int mov1, call, mov2;
+
+		err = get_user(mov1, (unsigned int*)regs->tpc);
+		err |= get_user(call, (unsigned int*)(regs->tpc+4));
+		err |= get_user(mov2, (unsigned int*)(regs->tpc+8));
+
+		if (err)
+			break;
+
+		if (mov1 == 0x8210000FU &&
+		    (call & 0xC0000000U) == 0x40000000U &&
+		    mov2 == 0x9E100001U)
+		{
+			unsigned long addr;
+
+			regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC];
+			addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
+			regs->tpc = addr;
+			regs->tnpc = addr+4;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: patched PLT emulation #5 */
+		unsigned int sethi1, sethi2, or1, or2, sllx, jmpl, nop;
+
+		err = get_user(sethi1, (unsigned int*)regs->tpc);
+		err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
+		err |= get_user(or1, (unsigned int*)(regs->tpc+8));
+		err |= get_user(or2, (unsigned int*)(regs->tpc+12));
+		err |= get_user(sllx, (unsigned int*)(regs->tpc+16));
+		err |= get_user(jmpl, (unsigned int*)(regs->tpc+20));
+		err |= get_user(nop, (unsigned int*)(regs->tpc+24));
+
+		if (err)
+			break;
+
+		if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
+		    (sethi2 & 0xFFC00000U) == 0x0B000000U &&
+		    (or1 & 0xFFFFE000U) == 0x82106000U &&
+		    (or2 & 0xFFFFE000U) == 0x8A116000U &&
+		    sllx == 0x83287020 &&
+		    jmpl == 0x81C04005U &&
+		    nop == 0x01000000U)
+		{
+			unsigned long addr;
+
+			regs->u_regs[UREG_G1] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU);
+			regs->u_regs[UREG_G1] <<= 32;
+			regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU);
+			addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
+			regs->tpc = addr;
+			regs->tnpc = addr+4;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: patched PLT emulation #6 */
+		unsigned int sethi1, sethi2, sllx, or,  jmpl, nop;
+
+		err = get_user(sethi1, (unsigned int*)regs->tpc);
+		err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
+		err |= get_user(sllx, (unsigned int*)(regs->tpc+8));
+		err |= get_user(or, (unsigned int*)(regs->tpc+12));
+		err |= get_user(jmpl, (unsigned int*)(regs->tpc+16));
+		err |= get_user(nop, (unsigned int*)(regs->tpc+20));
+
+		if (err)
+			break;
+
+		if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
+		    (sethi2 & 0xFFC00000U) == 0x0B000000U &&
+		    sllx == 0x83287020 &&
+		    (or & 0xFFFFE000U) == 0x8A116000U &&
+		    jmpl == 0x81C04005U &&
+		    nop == 0x01000000U)
+		{
+			unsigned long addr;
+
+			regs->u_regs[UREG_G1] = (sethi1 & 0x003FFFFFU) << 10;
+			regs->u_regs[UREG_G1] <<= 32;
+			regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or & 0x3FFU);
+			addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
+			regs->tpc = addr;
+			regs->tnpc = addr+4;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: patched PLT emulation #7 */
+		unsigned int sethi, ba, nop;
+
+		err = get_user(sethi, (unsigned int*)regs->tpc);
+		err |= get_user(ba, (unsigned int*)(regs->tpc+4));
+		err |= get_user(nop, (unsigned int*)(regs->tpc+8));
+
+		if (err)
+			break;
+
+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
+		    (ba & 0xFFF00000U) == 0x30600000U &&
+		    nop == 0x01000000U)
+		{
+			unsigned long addr;
+
+			addr = (sethi & 0x003FFFFFU) << 10;
+			regs->u_regs[UREG_G1] = addr;
+			addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
+			regs->tpc = addr;
+			regs->tnpc = addr+4;
+			return 2;
+		}
+	} while (0);
+
+	do { /* PaX: unpatched PLT emulation step 1 */
+		unsigned int sethi, ba, nop;
+
+		err = get_user(sethi, (unsigned int*)regs->tpc);
+		err |= get_user(ba, (unsigned int*)(regs->tpc+4));
+		err |= get_user(nop, (unsigned int*)(regs->tpc+8));
+
+		if (err)
+			break;
+
+		if ((sethi & 0xFFC00000U) == 0x03000000U &&
+		    ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
+		    nop == 0x01000000U)
+		{
+			unsigned long addr;
+			unsigned int save, call;
+
+			if ((ba & 0xFFC00000U) == 0x30800000U)
+				addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
+			else
+				addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
+
+			err = get_user(save, (unsigned int*)addr);
+			err |= get_user(call, (unsigned int*)(addr+4));
+			err |= get_user(nop, (unsigned int*)(addr+8));
+			if (err)
+				break;
+
+			if (save == 0x9DE3BFA8U &&
+			    (call & 0xC0000000U) == 0x40000000U &&
+			    nop == 0x01000000U)
+			{
+				struct vm_area_struct *vma;
+				unsigned long call_dl_resolve;
+
+				down_read(&current->mm->mmap_sem);
+				call_dl_resolve = current->mm->call_dl_resolve;
+				up_read(&current->mm->mmap_sem);
+				if (likely(call_dl_resolve))
+					goto emulate;
+
+				vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+
+				down_write(&current->mm->mmap_sem);
+				if (current->mm->call_dl_resolve) {
+					call_dl_resolve = current->mm->call_dl_resolve;
+					up_write(&current->mm->mmap_sem);
+					if (vma) kmem_cache_free(vm_area_cachep, vma);
+					goto emulate;
+				}
+
+				call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
+				if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
+					up_write(&current->mm->mmap_sem);
+					if (vma) kmem_cache_free(vm_area_cachep, vma);
+					return 1;
+				}
+
+				pax_insert_vma(vma, call_dl_resolve);
+				current->mm->call_dl_resolve = call_dl_resolve;
+				up_write(&current->mm->mmap_sem);
+
+emulate:
+				regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
+				regs->tpc = call_dl_resolve;
+				regs->tnpc = addr+4;
+				return 3;
+			}
+		}
+	} while (0);
+
+	do { /* PaX: unpatched PLT emulation step 2 */
+		unsigned int save, call, nop;
+
+		err = get_user(save, (unsigned int*)(regs->tpc-4));
+		err |= get_user(call, (unsigned int*)regs->tpc);
+		err |= get_user(nop, (unsigned int*)(regs->tpc+4));
+		if (err)
+			break;
+
+		if (save == 0x9DE3BFA8U &&
+		    (call & 0xC0000000U) == 0x40000000U &&
+		    nop == 0x01000000U)
+		{
+			unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
+
+			regs->u_regs[UREG_RETPC] = regs->tpc;
+			regs->tpc = dl_resolve;
+			regs->tnpc = dl_resolve+4;
+			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("<invalid address>.");
+			break;
+		}
+		printk("%08x ", c);
+	}
+	printk("\n");
+}
+#endif
+
 asmlinkage void do_sparc64_fault(struct pt_regs *regs)
 {
 	struct mm_struct *mm = current->mm;
@@ -347,8 +731,10 @@ asmlinkage void do_sparc64_fault(struct 
 		goto intr_or_no_mm;
 
 	if (test_thread_flag(TIF_32BIT)) {
-		if (!(regs->tstate & TSTATE_PRIV))
+		if (!(regs->tstate & TSTATE_PRIV)) {
 			regs->tpc &= 0xffffffff;
+			regs->tnpc &= 0xffffffff;
+		}
 		address &= 0xffffffff;
 	}
 
@@ -357,6 +743,34 @@ asmlinkage void do_sparc64_fault(struct 
 	if (!vma)
 		goto bad_area;
 
+#ifdef CONFIG_PAX_PAGEEXEC
+	/* PaX: detect ITLB misses on non-exec pages */
+	if ((current->flags & PF_PAX_PAGEEXEC) && vma->vm_start <= address &&
+	    !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB))
+	{
+		if (address != regs->tpc)
+			goto good_area;
+
+		up_read(&mm->mmap_sem);
+		switch (pax_handle_fetch_fault(regs)) {
+
+#ifdef CONFIG_PAX_EMUPLT
+		case 2:
+		case 3:
+			goto fault_done;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+		case 4:
+			goto fault_done;
+#endif
+
+		}
+		pax_report_fault(regs, (void*)regs->tpc, (void*)(regs->u_regs[UREG_FP] + STACK_BIAS));
+		do_exit(SIGKILL);
+	}
+#endif
+
 	/* Pure DTLB misses do not tell us whether the fault causing
 	 * load/store/atomic was a write or not, it only says that there
 	 * was no match.  So in such a case we (carefully) read the
diff -NurpX nopatch linux-2.6.7/arch/sparc64/solaris/misc.c linux-2.6.7-pax/arch/sparc64/solaris/misc.c
--- linux-2.6.7/arch/sparc64/solaris/misc.c	2004-06-16 07:20:04.000000000 +0200
+++ linux-2.6.7-pax/arch/sparc64/solaris/misc.c	2004-06-19 15:57:01.000000000 +0200
@@ -56,6 +56,11 @@ static u32 do_solaris_mmap(u32 addr, u32
 	struct file *file = NULL;
 	unsigned long retval, ret_type;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	/* Do we need it here? */
 	set_personality(PER_SVR4);
 	if (flags & MAP_NORESERVE) {
diff -NurpX nopatch linux-2.6.7/arch/x86_64/ia32/ia32_binfmt.c linux-2.6.7-pax/arch/x86_64/ia32/ia32_binfmt.c
--- linux-2.6.7/arch/x86_64/ia32/ia32_binfmt.c	2004-06-16 07:18:55.000000000 +0200
+++ linux-2.6.7-pax/arch/x86_64/ia32/ia32_binfmt.c	2004-06-19 15:57:01.000000000 +0200
@@ -185,6 +185,17 @@ struct elf_prpsinfo
 //#include <asm/ia32.h>
 #include <linux/elf.h>
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	(test_thread_flag(TIF_IA32) ? 0x08048000UL : 0x400000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		(test_thread_flag(TIF_IA32) ? 16 : 24)
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		(test_thread_flag(TIF_IA32) ? 16 : 24)
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	(test_thread_flag(TIF_IA32) ? 16 : 24)
+#endif
+
 typedef struct user_i387_ia32_struct elf_fpregset_t;
 typedef struct user32_fxsr_struct elf_fpxregset_t;
 
@@ -361,7 +372,13 @@ int setup_arg_pages(struct linux_binprm 
 		else if (executable_stack == EXSTACK_DISABLE_X)
 			mpnt->vm_flags = vm_stack_flags32 & ~VM_EXEC;
 		else
+
+#ifdef CONFIG_PAX_PAGEEXEC
+			mpnt->vm_flags = VM_STACK_FLAGS;
+#else
 			mpnt->vm_flags = vm_stack_flags32;
+#endif
+
  		mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? 
  			PAGE_COPY_EXEC : PAGE_COPY;
 		insert_vm_struct(mm, mpnt);
diff -NurpX nopatch linux-2.6.7/arch/x86_64/ia32/sys_ia32.c linux-2.6.7-pax/arch/x86_64/ia32/sys_ia32.c
--- linux-2.6.7/arch/x86_64/ia32/sys_ia32.c	2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7-pax/arch/x86_64/ia32/sys_ia32.c	2004-06-19 15:57:01.000000000 +0200
@@ -212,6 +212,11 @@ sys32_mmap(struct mmap_arg_struct __user
 	if (a.offset & ~PAGE_MASK)
 		return -EINVAL; 
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (a.flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	if (!(a.flags & MAP_ANONYMOUS)) {
 		file = fget(a.fd);
 		if (!file)
@@ -1037,6 +1042,11 @@ asmlinkage long sys32_mmap2(unsigned lon
 	unsigned long error;
 	struct file * file = NULL;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
diff -NurpX nopatch linux-2.6.7/arch/x86_64/kernel/setup64.c linux-2.6.7-pax/arch/x86_64/kernel/setup64.c
--- linux-2.6.7/arch/x86_64/kernel/setup64.c	2004-06-16 07:19:03.000000000 +0200
+++ linux-2.6.7-pax/arch/x86_64/kernel/setup64.c	2004-06-19 15:57:01.000000000 +0200
@@ -43,8 +43,15 @@ char boot_cpu_stack[IRQSTACKSIZE] __attr
 
 unsigned long __supported_pte_mask = ~0UL;
 static int do_not_nx __initdata = 0;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+unsigned long vm_stack_flags = VM_GROWSDOWN | __VM_DATA_DEFAULT_FLAGS;
+unsigned long vm_stack_flags32 = VM_GROWSDOWN | __VM_DATA_DEFAULT_FLAGS;
+#else
 unsigned long vm_stack_flags = __VM_STACK_FLAGS; 
 unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; 
+#endif
+
 unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; 
 unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; 
 unsigned long vm_force_exec32 = PROT_EXEC; 
diff -NurpX nopatch linux-2.6.7/arch/x86_64/kernel/sys_x86_64.c linux-2.6.7-pax/arch/x86_64/kernel/sys_x86_64.c
--- linux-2.6.7/arch/x86_64/kernel/sys_x86_64.c	2004-06-16 07:19:37.000000000 +0200
+++ linux-2.6.7-pax/arch/x86_64/kernel/sys_x86_64.c	2004-06-19 15:57:01.000000000 +0200
@@ -48,6 +48,11 @@ long sys_mmap(unsigned long addr, unsign
 	if (off & ~PAGE_MASK)
 		goto out;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		goto out;
+#endif
+
 	error = -EBADF;
 	file = NULL;
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
@@ -102,6 +107,15 @@ arch_get_unmapped_area(struct file *filp
 	
 	find_start_end(flags, &begin, &end); 
 
+#ifdef CONFIG_PAX_RANDMMAP
+	if ((current->flags & PF_PAX_RANDMMAP) && (!addr || filp)) {
+		if (begin == 0x40000000)
+			begin += current->mm->delta_mmap & 0x0FFFFFFFU;
+		else
+			begin += current->mm->delta_mmap;
+	}
+#endif
+
 	if (len > end)
 		return -ENOMEM;
 
diff -NurpX nopatch linux-2.6.7/arch/x86_64/mm/fault.c linux-2.6.7-pax/arch/x86_64/mm/fault.c
--- linux-2.6.7/arch/x86_64/mm/fault.c	2004-06-16 07:18:52.000000000 +0200
+++ linux-2.6.7-pax/arch/x86_64/mm/fault.c	2004-06-19 15:57:01.000000000 +0200
@@ -23,6 +23,7 @@
 #include <linux/vt_kern.h>		/* For unblank_screen() */
 #include <linux/compiler.h>
 #include <linux/module.h>
+#include <linux/binfmts.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -218,6 +219,63 @@ int unhandled_signal(struct task_struct 
 		(tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL);
 }
 
+#ifdef CONFIG_PAX_PAGEEXEC
+/*
+ * PaX: decide what to do with offenders (regs->rip = fault address)
+ *
+ * returns 1 when task should be killed
+ *         2 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#ifdef CONFIG_PAX_RANDEXEC
+	int err;
+
+	if (current->flags & PF_PAX_RANDEXEC) {
+		if (regs->rip >= current->mm->start_code &&
+		    regs->rip < current->mm->end_code)
+		{
+			if (test_thread_flag(TIF_IA32)) {
+				unsigned int esp_4;
+
+				err = get_user(esp_4, (unsigned int*)(regs->rsp-4UL));
+				if (err || esp_4 == regs->rip)
+					return 1;
+			} else {
+				unsigned long esp_8;
+
+				err = get_user(esp_8, (unsigned long*)(regs->rsp-8UL));
+				if (err || esp_8 == regs->rip)
+					return 1;
+			}
+
+			regs->rip += current->mm->delta_exec;
+			return 2;
+		}
+	}
+#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 < 20; i++) {
+		unsigned int c;
+		if (get_user(c, (unsigned char*)pc+i)) {
+			printk("<invalid address>.");
+			break;
+		}
+		printk("%08x ", c);
+	}
+	printk("\n");
+}
+#endif
+
 int page_fault_trace; 
 int exception_trace = 1;
 
@@ -303,6 +361,23 @@ asmlinkage void do_page_fault(struct pt_
  * we can handle it..
  */
 good_area:
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	if ((current->flags & PF_PAX_PAGEEXEC) && (error_code & 16) && !(vma->vm_flags & VM_EXEC)) {
+		up_read(&mm->mmap_sem);
+		switch(pax_handle_fetch_fault(regs)) {
+
+#ifdef CONFIG_PAX_RANDEXEC
+		case 2:
+			return;
+#endif
+
+		}
+		pax_report_fault(regs, (void*)regs->rip, (void*)regs->rsp);
+		do_exit(SIGKILL);
+	}
+#endif
+
 	info.si_code = SEGV_ACCERR;
 	write = 0;
 	switch (error_code & 3) {
diff -NurpX nopatch linux-2.6.7/drivers/char/mem.c linux-2.6.7-pax/drivers/char/mem.c
--- linux-2.6.7/drivers/char/mem.c	2004-06-16 07:19:23.000000000 +0200
+++ linux-2.6.7-pax/drivers/char/mem.c	2004-06-20 18:36:23.000000000 +0200
@@ -424,7 +424,23 @@ static inline size_t read_zero_pagealign
 			count = size;
 
 		zap_page_range(vma, addr, count, NULL);
-        	zeromap_page_range(vma, addr, count, PAGE_COPY);
+        	zeromap_page_range(vma, addr, count, vma->vm_page_prot);
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+		if (vma->vm_flags & VM_MIRROR) {
+			unsigned long addr_m;
+			struct vm_area_struct * vma_m;
+
+			addr_m = vma->vm_start + vma->vm_mirror;
+			vma_m = find_vma(mm, addr_m);
+			if (vma_m && vma_m->vm_start == addr_m && (vma_m->vm_flags & VM_MIRROR)) {
+				addr_m = addr + vma->vm_mirror;
+				zap_page_range(vma_m, addr_m, count, NULL);
+			} else
+				printk(KERN_ERR "PAX: VMMIRROR: read_zero bug, %08lx, %08lx\n",
+				       addr, vma->vm_start);
+		}
+#endif
 
 		size -= count;
 		buf += count;
diff -NurpX nopatch linux-2.6.7/drivers/char/random.c linux-2.6.7-pax/drivers/char/random.c
--- linux-2.6.7/drivers/char/random.c	2004-06-16 07:18:57.000000000 +0200
+++ linux-2.6.7-pax/drivers/char/random.c	2004-06-19 15:57:01.000000000 +0200
@@ -2478,3 +2478,25 @@ __u32 check_tcp_syn_cookie(__u32 cookie,
 	return (cookie - tmp[17]) & COOKIEMASK;	/* Leaving the data behind */
 }
 #endif
+
+#ifdef CONFIG_PAX_ASLR
+unsigned long pax_get_random_long(void)
+{
+	static time_t   rekey_time;
+	static __u32    secret[12];
+	time_t          t;
+
+	/*
+	 * Pick a random secret every REKEY_INTERVAL seconds.
+	 */
+	t = get_seconds();
+	if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) {
+		rekey_time = t;
+		get_random_bytes(secret, sizeof(secret));
+	}
+
+	secret[1] = halfMD4Transform(secret+8, secret);
+	secret[0] = halfMD4Transform(secret+8, secret);
+	return *(unsigned long *)secret;
+}
+#endif
diff -NurpX nopatch linux-2.6.7/drivers/pnp/pnpbios/bioscalls.c linux-2.6.7-pax/drivers/pnp/pnpbios/bioscalls.c
--- linux-2.6.7/drivers/pnp/pnpbios/bioscalls.c	2004-06-16 07:19:42.000000000 +0200
+++ linux-2.6.7-pax/drivers/pnp/pnpbios/bioscalls.c	2004-06-19 15:57:01.000000000 +0200
@@ -79,7 +79,7 @@ set_base(cpu_gdt_table[cpu][(selname) >>
 set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \
 } while(0)
 
-static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
+static struct desc_struct bad_bios_desc = { 0, 0x00409300 };
 
 /*
  * At some point we want to use this stack frame pointer to unwind
@@ -107,6 +107,10 @@ static inline u16 call_pnp_bios(u16 func
 	struct desc_struct save_desc_40;
 	int cpu;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long cr3;
+#endif
+
 	/*
 	 * PnP BIOSes are generally not terribly re-entrant.
 	 * Also, don't rely on them to save everything correctly.
@@ -115,12 +119,17 @@ static inline u16 call_pnp_bios(u16 func
 		return PNP_FUNCTION_NOT_SUPPORTED;
 
 	cpu = get_cpu();
-	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
-	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
 
 	/* On some boxes IRQ's during PnP BIOS calls are deadly.  */
 	spin_lock_irqsave(&pnp_bios_lock, flags);
 
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_open_kernel_noirq(cr3);
+#endif
+
+	save_desc_40 = cpu_gdt_table[cpu][0x40 / 8];
+	cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc;
+
 	/* The lock prevents us bouncing CPU here */
 	if (ts1_size)
 		Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
@@ -156,9 +165,14 @@ static inline u16 call_pnp_bios(u16 func
 		  "i" (0)
 		: "memory"
 	);
-	spin_unlock_irqrestore(&pnp_bios_lock, flags);
 
 	cpu_gdt_table[cpu][0x40 / 8] = save_desc_40;
+
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_close_kernel_noirq(cr3);
+#endif
+
+	spin_unlock_irqrestore(&pnp_bios_lock, flags);
 	put_cpu();
 
 	/* If we get here and this is set then the PnP BIOS faulted on us. */
diff -NurpX nopatch linux-2.6.7/drivers/scsi/scsi_devinfo.c linux-2.6.7-pax/drivers/scsi/scsi_devinfo.c
--- linux-2.6.7/drivers/scsi/scsi_devinfo.c	2004-06-16 07:19:11.000000000 +0200
+++ linux-2.6.7-pax/drivers/scsi/scsi_devinfo.c	2004-06-19 15:57:01.000000000 +0200
@@ -27,7 +27,7 @@ struct scsi_dev_info_list {
 static const char spaces[] = "                "; /* 16 of them */
 static unsigned scsi_default_dev_flags;
 static LIST_HEAD(scsi_dev_info_list);
-static __init char scsi_dev_flags[256];
+static __initdata char scsi_dev_flags[256];
 
 /*
  * scsi_static_device_list: deprecated list of devices that require
diff -NurpX nopatch linux-2.6.7/drivers/video/vesafb.c linux-2.6.7-pax/drivers/video/vesafb.c
--- linux-2.6.7/drivers/video/vesafb.c	2004-06-16 07:18:57.000000000 +0200
+++ linux-2.6.7-pax/drivers/video/vesafb.c	2004-06-19 15:57:01.000000000 +0200
@@ -250,7 +250,7 @@ static int __init vesafb_probe(struct de
 	if (vesafb_fix.smem_len > 16 * 1024 * 1024)
 		vesafb_fix.smem_len = 16 * 1024 * 1024;
 
-#ifndef __i386__
+#if !defined(__i386__) || defined(CONFIG_PAX_KERNEXEC)
 	screen_info.vesapm_seg = 0;
 #endif
 
diff -NurpX nopatch linux-2.6.7/fs/binfmt_aout.c linux-2.6.7-pax/fs/binfmt_aout.c
--- linux-2.6.7/fs/binfmt_aout.c	2004-06-16 07:19:01.000000000 +0200
+++ linux-2.6.7-pax/fs/binfmt_aout.c	2004-06-19 15:57:01.000000000 +0200
@@ -309,10 +309,33 @@ static int load_aout_binary(struct linux
 		(current->mm->start_brk = N_BSSADDR(ex));
 	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
 
+#ifdef CONFIG_PAX_RANDMMAP
+	if (current->flags & PF_PAX_RANDMMAP)
+		current->mm->free_area_cache += current->mm->delta_mmap;
+#endif
+
 	current->mm->rss = 0;
 	current->mm->mmap = NULL;
 	compute_creds(bprm);
  	current->flags &= ~PF_FORKNOEXEC;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (!(N_FLAGS(ex) & F_PAX_PAGEEXEC)) {
+		current->flags |= PF_PAX_PAGEEXEC;
+
+#ifdef CONFIG_PAX_EMUTRAMP
+		if (N_FLAGS(ex) & F_PAX_EMUTRAMP)
+			current->flags |= PF_PAX_EMUTRAMP;
+#endif
+
+#ifdef CONFIG_PAX_MPROTECT
+		if (!(N_FLAGS(ex) & F_PAX_MPROTECT))
+			current->flags |= PF_PAX_MPROTECT;
+#endif
+
+	}
+#endif
+
 #ifdef __sparc__
 	if (N_MAGIC(ex) == NMAGIC) {
 		loff_t pos = fd_offset;
@@ -399,7 +422,7 @@ static int load_aout_binary(struct linux
 
 		down_write(&current->mm->mmap_sem);
  		error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
-				PROT_READ | PROT_WRITE | PROT_EXEC,
+				PROT_READ | PROT_WRITE,
 				MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 				fd_offset + ex.a_text);
 		up_write(&current->mm->mmap_sem);
diff -NurpX nopatch linux-2.6.7/fs/binfmt_elf.c linux-2.6.7-pax/fs/binfmt_elf.c
--- linux-2.6.7/fs/binfmt_elf.c	2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7-pax/fs/binfmt_elf.c	2004-10-31 00:46:37.000000000 +0200
@@ -37,11 +37,16 @@
 #include <linux/pagemap.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/pgalloc.h>
 
+#ifdef CONFIG_PAX_SEGMEXEC
+#include <asm/desc.h>
+#endif
+
 #include <linux/elf.h>
 
 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
@@ -85,14 +90,22 @@ static struct linux_binfmt elf_format = 
 
 static int set_brk(unsigned long start, unsigned long end)
 {
+	current->mm->start_brk = current->mm->brk = end;
 	start = ELF_PAGEALIGN(start);
 	end = ELF_PAGEALIGN(end);
 	if (end > start) {
 		unsigned long addr = do_brk(start, end - start);
 		if (BAD_ADDR(addr))
 			return addr;
+
+#ifdef CONFIG_PAX_RANDEXEC
+		if (current->flags & PF_PAX_RANDEXEC)
+			addr = __do_mmap_pgoff(NULL, ELF_PAGEALIGN(start + current->mm->delta_exec), 0UL, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_MIRROR, start);
+		if (BAD_ADDR(addr))
+			return addr;
+#endif
+
 	}
-	current->mm->start_brk = current->mm->brk = end;
 	return 0;
 }
 
@@ -303,6 +316,7 @@ static unsigned long load_elf_interp(str
 	unsigned long last_bss = 0, elf_bss = 0;
 	unsigned long error = ~0UL;
 	int retval, i, size;
+	unsigned long task_size = TASK_SIZE;
 
 	/* First of all, some simple consistency checks */
 	if (interp_elf_ex->e_type != ET_EXEC &&
@@ -336,6 +350,11 @@ static unsigned long load_elf_interp(str
 	if (retval < 0)
 		goto out_close;
 
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->flags & PF_PAX_SEGMEXEC)
+		task_size = SEGMEXEC_TASK_SIZE;
+#endif
+
 	eppnt = elf_phdata;
 	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
 	  if (eppnt->p_type == PT_LOAD) {
@@ -367,8 +386,8 @@ static unsigned long load_elf_interp(str
 	     * <= p_memsize so it is only necessary to check p_memsz.
 	     */
 	    k = load_addr + eppnt->p_vaddr;
-	    if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz ||
-		eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) {
+	    if (k > task_size || eppnt->p_filesz > eppnt->p_memsz ||
+		eppnt->p_memsz > task_size || task_size - eppnt->p_memsz < k) {
 	        error = -ENOMEM;
 		goto out_close;
 	    }
@@ -458,6 +477,227 @@ out:
 	return elf_entry;
 }
 
+#if (defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)) && defined(CONFIG_PAX_SOFTMODE)
+static unsigned long pax_parse_softmode(const struct elf_phdr * const elf_phdata)
+{
+	unsigned long pax_flags = 0UL;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (elf_phdata->p_flags & PF_PAGEEXEC)
+		pax_flags |= PF_PAX_PAGEEXEC;
+#endif
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (elf_phdata->p_flags & PF_SEGMEXEC)
+		pax_flags |= PF_PAX_SEGMEXEC;
+#endif
+
+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
+	if (pax_flags & PF_PAX_PAGEEXEC)
+		pax_flags &= ~PF_PAX_SEGMEXEC;
+#endif
+
+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
+	if (pax_flags & PF_PAX_SEGMEXEC)
+		pax_flags &= ~PF_PAX_PAGEEXEC;
+#endif
+
+#ifdef CONFIG_PAX_EMUTRAMP
+	if (elf_phdata->p_flags & PF_EMUTRAMP)
+		pax_flags |= PF_PAX_EMUTRAMP;
+#endif
+
+#ifdef CONFIG_PAX_MPROTECT
+	if (elf_phdata->p_flags & PF_MPROTECT)
+		pax_flags |= PF_PAX_MPROTECT;
+#endif
+
+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
+
+#ifdef CONFIG_PAX_SOFTMODE
+	if (pax_aslr)
+#endif
+
+	if (elf_phdata->p_flags & PF_RANDMMAP)
+		pax_flags |= PF_PAX_RANDMMAP;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+
+#ifdef CONFIG_PAX_SOFTMODE
+	if (pax_aslr)
+#endif
+
+	if (elf_phdata->p_flags & PF_RANDEXEC)
+		pax_flags |= PF_PAX_RANDEXEC;
+#endif
+
+	return pax_flags;
+}
+#endif
+
+#ifdef CONFIG_PAX_PT_PAX_FLAGS
+static unsigned long pax_parse_hardmode(const struct elf_phdr * const elf_phdata)
+{
+	unsigned long pax_flags = 0UL;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (!(elf_phdata->p_flags & PF_NOPAGEEXEC))
+		pax_flags |= PF_PAX_PAGEEXEC;
+#endif
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (!(elf_phdata->p_flags & PF_NOSEGMEXEC))
+		pax_flags |= PF_PAX_SEGMEXEC;
+#endif
+
+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
+	if (pax_flags & PF_PAX_PAGEEXEC)
+		pax_flags &= ~PF_PAX_SEGMEXEC;
+#endif
+
+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
+	if (pax_flags & PF_PAX_SEGMEXEC)
+		pax_flags &= ~PF_PAX_PAGEEXEC;
+#endif
+
+#ifdef CONFIG_PAX_EMUTRAMP
+	if (!(elf_phdata->p_flags & PF_NOEMUTRAMP))
+		pax_flags |= PF_PAX_EMUTRAMP;
+#endif
+
+#ifdef CONFIG_PAX_MPROTECT
+	if (!(elf_phdata->p_flags & PF_NOMPROTECT))
+		pax_flags |= PF_PAX_MPROTECT;
+#endif
+
+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
+
+#ifdef CONFIG_PAX_SOFTMODE
+	if (pax_aslr)
+#endif
+
+	if (!(elf_phdata->p_flags & PF_NORANDMMAP))
+		pax_flags |= PF_PAX_RANDMMAP;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+
+#ifdef CONFIG_PAX_SOFTMODE
+	if (pax_aslr)
+#endif
+
+	if (!(elf_phdata->p_flags & PF_NORANDEXEC))
+		pax_flags |= PF_PAX_RANDEXEC;
+#endif
+
+	return pax_flags;
+}
+#endif
+
+#ifdef CONFIG_PAX_EI_PAX
+static int pax_parse_ei_pax(const struct elfhdr * const elf_ex)
+{
+	unsigned long pax_flags = 0UL;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_PAGEEXEC))
+		pax_flags |= PF_PAX_PAGEEXEC;
+#endif
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_SEGMEXEC))
+		pax_flags |= PF_PAX_SEGMEXEC;
+#endif
+
+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
+	if (pax_flags & PF_PAX_PAGEEXEC)
+		pax_flags &= ~PF_PAX_SEGMEXEC;
+#endif
+
+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
+	if (pax_flags & PF_PAX_SEGMEXEC)
+		pax_flags &= ~PF_PAX_PAGEEXEC;
+#endif
+
+#ifdef CONFIG_PAX_EMUTRAMP
+	if ((pax_flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) && (elf_ex->e_ident[EI_PAX] & EF_PAX_EMUTRAMP))
+		pax_flags |= PF_PAX_EMUTRAMP;
+#endif
+
+#ifdef CONFIG_PAX_MPROTECT
+	if ((pax_flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) && !(elf_ex->e_ident[EI_PAX] & EF_PAX_MPROTECT))
+		pax_flags |= PF_PAX_MPROTECT;
+#endif
+
+#ifdef CONFIG_PAX_ASLR
+
+#ifdef CONFIG_PAX_SOFTMODE
+	if (pax_aslr)
+#endif
+
+	if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_RANDMMAP))
+		pax_flags |= PF_PAX_RANDMMAP;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+
+#ifdef CONFIG_PAX_SOFTMODE
+	if (pax_aslr)
+#endif
+
+	if ((elf_ex->e_ident[EI_PAX] & EF_PAX_RANDEXEC) && (elf_ex->e_type == ET_EXEC) && (pax_flags & PF_PAX_MPROTECT))
+		pax_flags |= PF_PAX_RANDEXEC;
+#endif
+
+	return pax_flags;
+}
+#endif
+
+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)
+static int pax_parse_elf_flags(const struct elfhdr * const elf_ex, const struct elf_phdr * const elf_phdata)
+{
+	unsigned long pax_flags = 0UL;
+
+#ifdef CONFIG_PAX_PT_PAX_FLAGS
+	unsigned long i;
+#endif
+
+#ifdef CONFIG_PAX_EI_PAX
+	pax_flags = pax_parse_ei_pax(elf_ex);
+#endif
+
+#ifdef CONFIG_PAX_PT_PAX_FLAGS
+	for (i = 0UL; i < elf_ex->e_phnum; i++)
+		if (elf_phdata[i].p_type == PT_PAX_FLAGS) {
+			if (((elf_phdata[i].p_flags & PF_PAGEEXEC) && (elf_phdata[i].p_flags & PF_NOPAGEEXEC)) ||
+			    ((elf_phdata[i].p_flags & PF_SEGMEXEC) && (elf_phdata[i].p_flags & PF_NOSEGMEXEC)) ||
+			    ((elf_phdata[i].p_flags & PF_EMUTRAMP) && (elf_phdata[i].p_flags & PF_NOEMUTRAMP)) ||
+			    ((elf_phdata[i].p_flags & PF_MPROTECT) && (elf_phdata[i].p_flags & PF_NOMPROTECT)) ||
+			    ((elf_phdata[i].p_flags & PF_RANDMMAP) && (elf_phdata[i].p_flags & PF_NORANDMMAP)) ||
+			    ((elf_phdata[i].p_flags & PF_RANDEXEC) && ((elf_phdata[i].p_flags & PF_NORANDEXEC) || elf_ex->e_type == ET_DYN || !(elf_phdata[i].p_flags & PF_MPROTECT))) ||
+			    (!(elf_phdata[i].p_flags & PF_NORANDEXEC) && (elf_ex->e_type == ET_DYN || (elf_phdata[i].p_flags & PF_NOMPROTECT))))
+				return -EINVAL;
+
+#ifdef CONFIG_PAX_SOFTMODE
+			if (pax_softmode)
+				pax_flags = pax_parse_softmode(&elf_phdata[i]);
+			else
+#endif
+
+				pax_flags = pax_parse_hardmode(&elf_phdata[i]);
+			break;
+		}
+#endif
+
+	if (0 > pax_check_flags(&pax_flags))
+		return -EINVAL;
+
+	current->flags |= pax_flags;
+	return 0;
+}
+#endif
+
 /*
  * These are the functions used to load ELF style executables and shared
  * libraries.  There is no binary dependent code anywhere else.
@@ -491,7 +731,13 @@ static int load_elf_binary(struct linux_
 	char passed_fileno[6];
 	struct files_struct *files;
 	int executable_stack = EXSTACK_DEFAULT;
-	
+	unsigned long task_size = TASK_SIZE;
+
+#ifdef CONFIG_PAX_RANDEXEC
+	unsigned long load_addr_random = 0UL;
+	unsigned long load_bias_random = 0UL;
+#endif
+
 	/* Get the exec-header */
 	elf_ex = *((struct elfhdr *) bprm->buf);
 
@@ -615,6 +861,7 @@ static int load_elf_binary(struct linux_
 		elf_ppnt++;
 	}
 
+#if 0
 	elf_ppnt = elf_phdata;
 	for (i = 0; i < elf_ex.e_phnum; i++, elf_ppnt++)
 		if (elf_ppnt->p_type == PT_GNU_STACK) {
@@ -623,6 +870,7 @@ static int load_elf_binary(struct linux_
 			else
 				executable_stack = EXSTACK_DISABLE_X;
 		}
+#endif
 
 	/* Some simple consistency checks for the interpreter */
 	if (elf_interpreter) {
@@ -689,8 +937,64 @@ static int load_elf_binary(struct linux_
 	current->mm->end_data = 0;
 	current->mm->end_code = 0;
 	current->mm->mmap = NULL;
+
+#ifdef CONFIG_PAX_DLRESOLVE
+	current->mm->call_dl_resolve = 0UL;
+#endif
+
+#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
+	current->mm->call_syscall = 0UL;
+#endif
+
+#ifdef CONFIG_PAX_ASLR
+	current->mm->delta_mmap = 0UL;
+	current->mm->delta_exec = 0UL;
+	current->mm->delta_stack = 0UL;
+#endif
+
 	current->flags &= ~PF_FORKNOEXEC;
 
+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)
+	if (0 > pax_parse_elf_flags(&elf_ex, elf_phdata)) {
+		send_sig(SIGKILL, current, 0);
+		goto out_free_dentry;
+	}
+#endif
+
+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
+	pax_set_flags(bprm);
+#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
+	if (pax_set_flags_func)
+		(pax_set_flags_func)(bprm);
+#endif
+
+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
+	if (current->flags & PF_PAX_PAGEEXEC)
+		current->mm->context.user_cs_limit = PAGE_SIZE;
+#endif
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->flags & PF_PAX_SEGMEXEC) {
+		int cpu = get_cpu();
+
+		current->mm->context.user_cs_base = SEGMEXEC_TASK_SIZE;
+		current->mm->context.user_cs_limit = -SEGMEXEC_TASK_SIZE;
+		set_user_cs(current->mm, cpu);
+		put_cpu();
+		task_size = SEGMEXEC_TASK_SIZE;
+	}
+#endif
+
+#ifdef CONFIG_PAX_ASLR
+	if (current->flags & PF_PAX_RANDMMAP) {
+#define pax_delta_mask(delta, lsb, len) (((delta) & ((1UL << (len)) - 1)) << (lsb))
+
+		current->mm->delta_mmap = pax_delta_mask(pax_get_random_long(), PAX_DELTA_MMAP_LSB(current), PAX_DELTA_MMAP_LEN(current));
+		current->mm->delta_exec = pax_delta_mask(pax_get_random_long(), PAX_DELTA_EXEC_LSB(current), PAX_DELTA_EXEC_LEN(current));
+		current->mm->delta_stack = pax_delta_mask(pax_get_random_long(), PAX_DELTA_STACK_LSB(current), PAX_DELTA_STACK_LEN(current));
+	}
+#endif
+
 	/* Do this immediately, since STACK_TOP as used in setup_arg_pages
 	   may depend on the personality.  */
 	SET_PERSONALITY(elf_ex, ibcs2_interpreter);
@@ -699,6 +1003,12 @@ static int load_elf_binary(struct linux_
 	   change some of these later */
 	current->mm->rss = 0;
 	current->mm->free_area_cache = TASK_UNMAPPED_BASE;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (current->flags & PF_PAX_RANDMMAP)
+		current->mm->free_area_cache += current->mm->delta_mmap;
+#endif
+
 	retval = setup_arg_pages(bprm, executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
@@ -753,12 +1063,92 @@ static int load_elf_binary(struct linux_
 			/* Try and get dynamic programs out of the way of the default mmap
 			   base, as well as whatever program they might try to exec.  This
 			   is because the brk will follow the loader, and is not movable.  */
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+			if (current->flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) {
+				load_bias = ELF_PAGESTART(PAX_ELF_ET_DYN_BASE(current) - vaddr);
+				elf_flags |= MAP_FIXED;
+			} else
+#endif
+
 			load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
+
+#ifdef CONFIG_PAX_RANDMMAP
+			/* PaX: randomize base address at the default exe base if requested */
+			if (current->flags & PF_PAX_RANDMMAP)
+				load_bias += ELF_PAGESTART(current->mm->delta_exec);
+#endif
+
 		}
 
-		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
-		if (BAD_ADDR(error))
-			continue;
+#ifdef CONFIG_PAX_RANDEXEC
+		if ((current->flags & PF_PAX_RANDEXEC) && (elf_ex.e_type == ET_EXEC)) {
+			error = -ENOMEM;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+			if (current->flags & PF_PAX_PAGEEXEC)
+				error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot & ~PROT_EXEC, elf_flags);
+#endif
+
+#ifdef CONFIG_PAX_SEGMEXEC
+			if (current->flags & PF_PAX_SEGMEXEC) {
+				unsigned long addr, len;
+
+				addr = ELF_PAGESTART(load_bias + vaddr);
+				len = elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr);
+				if (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len)
+					continue;
+				down_write(&current->mm->mmap_sem);
+				error = __do_mmap_pgoff(bprm->file, addr, len, elf_prot, elf_flags, (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr)) >> PAGE_SHIFT);
+				up_write(&current->mm->mmap_sem);
+			}
+#endif
+
+			if (BAD_ADDR(error))
+				continue;
+
+			/* PaX: mirror at a randomized base */
+			down_write(&current->mm->mmap_sem);
+
+			if (!load_addr_set) {
+				load_addr_random = get_unmapped_area(bprm->file, 0UL, elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr), (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr)) >> PAGE_SHIFT, MAP_PRIVATE);
+				if (BAD_ADDR(load_addr_random)) {
+					up_write(&current->mm->mmap_sem);
+					continue;
+				}
+				load_bias_random = load_addr_random - vaddr;
+			}
+
+#ifdef CONFIG_PAX_PAGEEXEC
+			if (current->flags & PF_PAX_PAGEEXEC)
+				load_addr_random = __do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr), 0UL, elf_prot, elf_flags | MAP_MIRROR, error);
+#endif
+
+#ifdef CONFIG_PAX_SEGMEXEC
+			if (current->flags & PF_PAX_SEGMEXEC) {
+				if (elf_prot & PROT_EXEC) {
+					load_addr_random = __do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr), elf_ppnt->p_memsz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr), PROT_NONE, MAP_PRIVATE | MAP_FIXED, 0UL);
+					if (!BAD_ADDR(load_addr_random)) {
+						load_addr_random = __do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr + SEGMEXEC_TASK_SIZE), 0UL, elf_prot, elf_flags | MAP_MIRROR, error);
+						if (!BAD_ADDR(load_addr_random))
+							load_addr_random -= SEGMEXEC_TASK_SIZE;
+					}
+				} else
+					load_addr_random = __do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr), 0UL, elf_prot, elf_flags | MAP_MIRROR, error);
+			}
+#endif
+
+			up_write(&current->mm->mmap_sem);
+			if (BAD_ADDR(load_addr_random))
+				continue;
+		} else
+#endif
+
+		{
+			error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
+			if (BAD_ADDR(error))
+				continue;
+		}
 
 		if (!load_addr_set) {
 			load_addr_set = 1;
@@ -769,6 +1159,11 @@ static int load_elf_binary(struct linux_
 				load_addr += load_bias;
 				reloc_func_desc = load_bias;
 			}
+
+#ifdef CONFIG_PAX_RANDEXEC
+			current->mm->delta_exec = load_addr_random - load_addr;
+#endif
+
 		}
 		k = elf_ppnt->p_vaddr;
 		if (k < start_code) start_code = k;
@@ -779,9 +1174,9 @@ static int load_elf_binary(struct linux_
 		 * allowed task size. Note that p_filesz must always be
 		 * <= p_memsz so it is only necessary to check p_memsz.
 		 */
-		if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
-		    elf_ppnt->p_memsz > TASK_SIZE ||
-		    TASK_SIZE - elf_ppnt->p_memsz < k) {
+		if (k > task_size || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
+		    elf_ppnt->p_memsz > task_size ||
+		    task_size - elf_ppnt->p_memsz < k) {
 			/* set_brk can never work.  Avoid overflows.  */
 			send_sig(SIGKILL, current, 0);
 			goto out_free_dentry;
@@ -808,6 +1203,16 @@ static int load_elf_binary(struct linux_
 	start_data += load_bias;
 	end_data += load_bias;
 
+#ifdef CONFIG_PAX_RANDMMAP
+
+#ifdef CONFIG_PAX_SOFTMODE
+	if (pax_aslr)
+#endif
+
+	elf_brk += PAGE_SIZE + pax_delta_mask(pax_get_random_long(), 4, PAGE_SHIFT);
+#undef pax_delta_mask
+#endif
+
 	/* Calling set_brk effectively mmaps the pages that we need
 	 * for the bss and break sections.  We must do this before
 	 * mapping in the interpreter, to make sure it doesn't wind
@@ -1043,7 +1448,7 @@ static int maydump(struct vm_area_struct
 	/* Do not dump I/O mapped devices! -DaveM */
 	if (vma->vm_flags & VM_IO)
 		return 0;
-#if 1
+#if 0
 	if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN))
 		return 1;
 	if (vma->vm_flags & (VM_READ|VM_EXEC|VM_EXECUTABLE|VM_SHARED))
diff -NurpX nopatch linux-2.6.7/fs/binfmt_flat.c linux-2.6.7-pax/fs/binfmt_flat.c
--- linux-2.6.7/fs/binfmt_flat.c	2004-06-16 07:18:37.000000000 +0200
+++ linux-2.6.7-pax/fs/binfmt_flat.c	2004-06-19 15:57:01.000000000 +0200
@@ -541,7 +541,9 @@ static int load_flat_file(struct linux_b
 				realdatastart = (unsigned long) -ENOMEM;
 			printk("Unable to allocate RAM for process data, errno %d\n",
 					(int)-datapos);
+			down_write(&current->mm->mmap_sem);
 			do_munmap(current->mm, textpos, text_len);
+			up_write(&current->mm->mmap_sem);
 			return realdatastart;
 		}
 		datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
@@ -562,8 +564,10 @@ static int load_flat_file(struct linux_b
 		}
 		if (result >= (unsigned long)-4096) {
 			printk("Unable to read data+bss, errno %d\n", (int)-result);
+			down_write(&current->mm->mmap_sem);
 			do_munmap(current->mm, textpos, text_len);
 			do_munmap(current->mm, realdatastart, data_len + extra);
+			up_write(&current->mm->mmap_sem);
 			return result;
 		}
 
@@ -625,8 +629,10 @@ static int load_flat_file(struct linux_b
 		}
 		if (result >= (unsigned long)-4096) {
 			printk("Unable to read code+data+bss, errno %d\n",(int)-result);
+			down_write(&current->mm->mmap_sem);
 			do_munmap(current->mm, textpos, text_len + data_len + extra +
 				MAX_SHARED_LIBS * sizeof(unsigned long));
+			up_write(&current->mm->mmap_sem);
 			return result;
 		}
 	}
diff -NurpX nopatch linux-2.6.7/fs/binfmt_misc.c linux-2.6.7-pax/fs/binfmt_misc.c
--- linux-2.6.7/fs/binfmt_misc.c	2004-06-16 07:19:13.000000000 +0200
+++ linux-2.6.7-pax/fs/binfmt_misc.c	2004-06-19 15:57:01.000000000 +0200
@@ -108,9 +108,11 @@ static int load_misc_binary(struct linux
 	int retval;
 
 	retval = -ENOEXEC;
-	if (!enabled)
+	if (!enabled || bprm->misc)
 		goto _ret;
 
+	bprm->misc++;
+
 	/* to keep locking time low, we copy the interpreter string */
 	read_lock(&entries_lock);
 	fmt = check_file(bprm);
diff -NurpX nopatch linux-2.6.7/fs/exec.c linux-2.6.7-pax/fs/exec.c
--- linux-2.6.7/fs/exec.c	2004-06-16 07:19:13.000000000 +0200
+++ linux-2.6.7-pax/fs/exec.c	2004-06-21 09:57:57.000000000 +0200
@@ -46,6 +46,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/rmap.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
@@ -62,6 +63,20 @@ char core_pattern[65] = "core";
 static struct linux_binfmt *formats;
 static rwlock_t binfmt_lock = RW_LOCK_UNLOCKED;
 
+#ifdef CONFIG_PAX_SOFTMODE
+
+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) || defined(CONFIG_PAX_RANDKSTACK)
+unsigned int pax_aslr=1;
+#endif
+
+unsigned int pax_softmode;
+#endif
+
+#ifdef CONFIG_PAX_HOOK_ACL_FLAGS
+void (*pax_set_flags_func)(struct linux_binprm * bprm);
+EXPORT_SYMBOL(pax_set_flags_func);
+#endif
+
 int register_binfmt(struct linux_binfmt * fmt)
 {
 	struct linux_binfmt ** tmp = &formats;
@@ -306,6 +321,10 @@ void install_arg_page(struct vm_area_str
 	if (unlikely(anon_vma_prepare(vma)))
 		goto out_sig;
 
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (page_count(page) == 1)
+#endif
+
 	flush_dcache_page(page);
 	pgd = pgd_offset(mm, address);
 
@@ -321,6 +340,11 @@ void install_arg_page(struct vm_area_str
 		goto out;
 	}
 	mm->rss++;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (page_count(page) == 1)
+#endif
+
 	lru_cache_add_active(page);
 	set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(
 					page, vma->vm_page_prot))));
@@ -345,6 +369,10 @@ int setup_arg_pages(struct linux_binprm 
 	int i;
 	long arg_size;
 
+#ifdef CONFIG_PAX_SEGMEXEC
+	struct vm_area_struct *mpnt_m = NULL;
+#endif
+
 #ifdef CONFIG_STACK_GROWSUP
 	/* Move the argument and environment strings to the bottom of the
 	 * stack space.
@@ -404,8 +432,24 @@ int setup_arg_pages(struct linux_binprm 
 	if (!mpnt)
 		return -ENOMEM;
 
+#ifdef CONFIG_PAX_SEGMEXEC
+	if ((current->flags & PF_PAX_SEGMEXEC) && (VM_STACK_FLAGS & VM_MAYEXEC)) {
+		mpnt_m = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+		if (!mpnt_m) {
+			kmem_cache_free(vm_area_cachep, mpnt);
+			return -ENOMEM;
+		}
+	}
+#endif
+
 	if (security_vm_enough_memory(arg_size >> PAGE_SHIFT)) {
 		kmem_cache_free(vm_area_cachep, mpnt);
+
+#ifdef CONFIG_PAX_SEGMEXEC
+		if (mpnt_m)
+			kmem_cache_free(vm_area_cachep, mpnt_m);
+#endif
+
 		return -ENOMEM;
 	}
 
@@ -431,9 +475,36 @@ int setup_arg_pages(struct linux_binprm 
 			mpnt->vm_flags = VM_STACK_FLAGS & ~VM_EXEC;
 		else
 			mpnt->vm_flags = VM_STACK_FLAGS;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+		if (!(current->flags & PF_PAX_PAGEEXEC))
+			mpnt->vm_page_prot = protection_map[(mpnt->vm_flags | VM_EXEC) & 0x7];
+		else
+#endif
+
 		mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
 		insert_vm_struct(mm, mpnt);
 		mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+		if (mpnt_m) {
+			*mpnt_m = *mpnt;
+			if (!(mpnt->vm_flags & VM_EXEC)) {
+				mpnt_m->vm_flags &= ~(VM_READ | VM_WRITE | VM_EXEC);
+				mpnt_m->vm_page_prot = PAGE_NONE;
+			}
+			mpnt_m->vm_start += SEGMEXEC_TASK_SIZE;
+			mpnt_m->vm_end += SEGMEXEC_TASK_SIZE;
+			mpnt_m->vm_flags |= VM_MIRROR;
+			mpnt->vm_flags |= VM_MIRROR;
+			mpnt_m->vm_mirror = mpnt->vm_start - mpnt_m->vm_start;
+			mpnt->vm_mirror = mpnt_m->vm_start - mpnt->vm_start;
+			insert_vm_struct(mm, mpnt_m);
+			mpnt_m->vm_pgoff = mpnt->vm_pgoff;
+			mm->total_vm += (mpnt_m->vm_end - mpnt_m->vm_start) >> PAGE_SHIFT;
+		}
+#endif
+
 	}
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
@@ -441,6 +512,14 @@ int setup_arg_pages(struct linux_binprm 
 		if (page) {
 			bprm->page[i] = NULL;
 			install_arg_page(mpnt, page, stack_base);
+
+#if defined(CONFIG_PAX_SEGMEXEC) && defined(CONFIG_PAX_MPROTECT)
+			if (mpnt_m) {
+				page_cache_get(page);
+				install_arg_page(mpnt_m, page, stack_base + SEGMEXEC_TASK_SIZE);
+			}
+#endif
+
 		}
 		stack_base += PAGE_SIZE;
 	}
@@ -836,6 +915,30 @@ int flush_old_exec(struct linux_binprm *
 	}
 	current->comm[i] = '\0';
 
+#ifdef CONFIG_PAX_PAGEEXEC
+	current->flags &= ~PF_PAX_PAGEEXEC;
+#endif
+
+#ifdef CONFIG_PAX_EMUTRAMP
+	current->flags &= ~PF_PAX_EMUTRAMP;
+#endif
+
+#ifdef CONFIG_PAX_MPROTECT
+	current->flags &= ~PF_PAX_MPROTECT;
+#endif
+
+#ifdef CONFIG_PAX_ASLR
+	current->flags &= ~PF_PAX_RANDMMAP;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+	current->flags &= ~PF_PAX_RANDEXEC;
+#endif
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	current->flags &= ~PF_PAX_SEGMEXEC;
+#endif
+
 	flush_thread();
 
 	if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || 
@@ -1083,12 +1186,23 @@ int do_execve(char * filename,
 	sched_balance_exec();
 
 	bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
+
+#ifdef CONFIG_PAX_RANDUSTACK
+
+#ifdef CONFIG_PAX_SOFTMODE
+	if (pax_aslr)
+#endif
+
+	bprm.p -= (pax_get_random_long() & ~(sizeof(void *)-1)) & ~PAGE_MASK;
+#endif
+
 	memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0]));
 
 	bprm.file = file;
 	bprm.filename = filename;
 	bprm.interp = filename;
 	bprm.sh_bang = 0;
+	bprm.misc = 0;
 	bprm.loader = 0;
 	bprm.exec = 0;
 	bprm.security = NULL;
@@ -1296,6 +1410,123 @@ void format_corename(char *corename, con
 	*out_ptr = 0;
 }
 
+int pax_check_flags(unsigned long * flags)
+{
+	int retval = 0;
+
+#if !defined(__i386__) || !defined(CONFIG_PAX_SEGMEXEC)
+	if (*flags & PF_PAX_SEGMEXEC)
+	{
+		*flags &= ~PF_PAX_SEGMEXEC;
+		retval = -EINVAL;
+	}
+#endif
+
+	if ((*flags & PF_PAX_PAGEEXEC)
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	    &&  (*flags & PF_PAX_SEGMEXEC)
+#endif
+
+	   )
+	{
+		*flags &= ~PF_PAX_PAGEEXEC;
+		retval = -EINVAL;
+	}
+
+	if ((*flags & PF_PAX_MPROTECT)
+
+#ifdef CONFIG_PAX_MPROTECT
+	    && !(*flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC))
+#endif
+
+	   )
+	{
+		*flags &= ~PF_PAX_MPROTECT;
+		retval = -EINVAL;
+	}
+
+	if ((*flags & PF_PAX_EMUTRAMP)
+
+#ifdef CONFIG_PAX_EMUTRAMP
+	    && !(*flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC))
+#endif
+
+	   )
+	{
+		*flags &= ~PF_PAX_EMUTRAMP;
+		retval = -EINVAL;
+	}
+
+	if ((*flags & PF_PAX_RANDEXEC)
+
+#ifdef CONFIG_PAX_RANDEXEC
+	    && !(*flags & PF_PAX_MPROTECT)
+#endif
+
+	   )
+	{
+		*flags &= ~PF_PAX_RANDEXEC;
+		retval = -EINVAL;
+	}
+
+	return retval;
+}
+
+EXPORT_SYMBOL(pax_check_flags);
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp)
+{
+	struct task_struct *tsk = current;
+	struct mm_struct *mm = current->mm;
+	char* buffer_exec = (char*)__get_free_page(GFP_ATOMIC);
+	char* buffer_fault = (char*)__get_free_page(GFP_ATOMIC);
+	char* path_exec=NULL;
+	char* path_fault=NULL;
+	unsigned long start=0UL, end=0UL, offset=0UL;
+
+	if (buffer_exec && buffer_fault) {
+		struct vm_area_struct* vma, * vma_exec=NULL, * vma_fault=NULL;
+
+		down_read(&mm->mmap_sem);
+		vma = mm->mmap;
+		while (vma && (!vma_exec || !vma_fault)) {
+			if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
+				vma_exec = vma;
+			if (vma->vm_start <= (unsigned long)pc && (unsigned long)pc < vma->vm_end)
+				vma_fault = vma;
+			vma = vma->vm_next;
+		}
+		if (vma_exec) {
+			path_exec = d_path(vma_exec->vm_file->f_dentry, vma_exec->vm_file->f_vfsmnt, buffer_exec, PAGE_SIZE);
+			if (IS_ERR(path_exec))
+				path_exec = "<path too long>";
+		}
+		if (vma_fault) {
+			start = vma_fault->vm_start;
+			end = vma_fault->vm_end;
+			offset = vma_fault->vm_pgoff << PAGE_SHIFT;
+			if (vma_fault->vm_file) {
+				path_fault = d_path(vma_fault->vm_file->f_dentry, vma_fault->vm_file->f_vfsmnt, buffer_fault, PAGE_SIZE);
+				if (IS_ERR(path_fault))
+					path_fault = "<path too long>";
+			} else
+				path_fault = "<anonymous mapping>";
+		}
+		up_read(&mm->mmap_sem);
+	}
+	printk(KERN_ERR "PAX: execution attempt in: %s, %08lx-%08lx %08lx\n", path_fault, start, end, offset);
+	printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, "
+			"PC: %p, SP: %p\n", path_exec, tsk->comm, tsk->pid,
+			tsk->uid, tsk->euid, pc, sp);
+	if (buffer_exec) free_page((unsigned long)buffer_exec);
+	if (buffer_fault) free_page((unsigned long)buffer_fault);
+	pax_report_insns(pc, sp);
+	do_coredump(SIGKILL, SIGKILL, regs);
+}
+#endif
+
 static void zap_threads (struct mm_struct *mm)
 {
 	struct task_struct *g, *p;
diff -NurpX nopatch linux-2.6.7/fs/proc/array.c linux-2.6.7-pax/fs/proc/array.c
--- linux-2.6.7/fs/proc/array.c	2004-06-16 07:19:36.000000000 +0200
+++ linux-2.6.7-pax/fs/proc/array.c	2004-06-19 15:57:01.000000000 +0200
@@ -274,6 +274,19 @@ static inline char *task_cap(struct task
 			    cap_t(p->cap_effective));
 }
 
+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
+static inline char *task_pax(struct task_struct *p, char *buffer)
+{
+	return buffer + sprintf(buffer, "PaX:\t%c%c%c%c%c%c\n",
+				p->flags & PF_PAX_PAGEEXEC ? 'P' : 'p',
+				p->flags & PF_PAX_EMUTRAMP ? 'E' : 'e',
+				p->flags & PF_PAX_MPROTECT ? 'M' : 'm',
+				p->flags & PF_PAX_RANDMMAP ? 'R' : 'r',
+				p->flags & PF_PAX_RANDEXEC ? 'X' : 'x',
+				p->flags & PF_PAX_SEGMEXEC ? 'S' : 's');
+}
+#endif
+
 extern char *task_mem(struct mm_struct *, char *);
 int proc_pid_status(struct task_struct *task, char * buffer)
 {
@@ -292,6 +305,11 @@ int proc_pid_status(struct task_struct *
 #if defined(CONFIG_ARCH_S390)
 	buffer = task_show_regs(task, buffer);
 #endif
+
+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
+	buffer = task_pax(task, buffer);
+#endif
+
 	return buffer - orig;
 }
 
diff -NurpX nopatch linux-2.6.7/fs/proc/task_mmu.c linux-2.6.7-pax/fs/proc/task_mmu.c
--- linux-2.6.7/fs/proc/task_mmu.c	2004-06-16 07:18:59.000000000 +0200
+++ linux-2.6.7-pax/fs/proc/task_mmu.c	2004-06-19 15:57:01.000000000 +0200
@@ -34,12 +34,23 @@ char *task_mem(struct mm_struct *mm, cha
 		"VmData:\t%8lu kB\n"
 		"VmStk:\t%8lu kB\n"
 		"VmExe:\t%8lu kB\n"
-		"VmLib:\t%8lu kB\n",
-		mm->total_vm << (PAGE_SHIFT-10),
+		"VmLib:\t%8lu kB\n"
+
+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
+		"CsBase:\t%8lx\nCsLim:\t%8lx\n"
+#endif
+
+		,mm->total_vm << (PAGE_SHIFT-10),
 		mm->locked_vm << (PAGE_SHIFT-10),
 		mm->rss << (PAGE_SHIFT-10),
 		data - stack, stack,
-		exec - lib, lib);
+		exec - lib, lib
+
+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
+		, mm->context.user_cs_base, mm->context.user_cs_limit
+#endif
+
+);
 	up_read(&mm->mmap_sem);
 	return buffer;
 }
@@ -94,9 +105,17 @@ static int show_map(struct seq_file *m, 
 	seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
 			map->vm_start,
 			map->vm_end,
+
+#if 1
+			flags & VM_MAYREAD ? flags & VM_READ ? 'R' : '+' : flags & VM_READ ? 'r' : '-',
+			flags & VM_MAYWRITE ? flags & VM_WRITE ? 'W' : '+' : flags & VM_WRITE ? 'w' : '-',
+			flags & VM_MAYEXEC ? flags & VM_EXEC ? 'X' : '+' : flags & VM_EXEC ? 'x' : '-',
+#else
 			flags & VM_READ ? 'r' : '-',
 			flags & VM_WRITE ? 'w' : '-',
 			flags & VM_EXEC ? 'x' : '-',
+#endif
+
 			flags & VM_MAYSHARE ? 's' : 'p',
 			map->vm_pgoff << PAGE_SHIFT,
 			MAJOR(dev), MINOR(dev), ino, &len);
diff -NurpX nopatch linux-2.6.7/fs/xfs/linux-2.6/xfs_file.c linux-2.6.7-pax/fs/xfs/linux-2.6/xfs_file.c
--- linux-2.6.7/fs/xfs/linux-2.6/xfs_file.c	2004-06-16 07:19:26.000000000 +0200
+++ linux-2.6.7-pax/fs/xfs/linux-2.6/xfs_file.c	2004-10-31 21:40:50.000000000 +0100
@@ -423,6 +423,11 @@ linvfs_file_mmap(
 			return error;
 	}
 
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (current->flags & PF_PAX_PAGEEXEC)
+		vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
+#endif
+
 	vma->vm_ops = &linvfs_file_vm_ops;
 
 	VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error);
diff -NurpX nopatch linux-2.6.7/include/asm-alpha/a.out.h linux-2.6.7-pax/include/asm-alpha/a.out.h
--- linux-2.6.7/include/asm-alpha/a.out.h	2004-06-16 07:19:43.000000000 +0200
+++ linux-2.6.7-pax/include/asm-alpha/a.out.h	2004-06-19 15:57:01.000000000 +0200
@@ -98,7 +98,7 @@ struct exec
 	set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000 \
 			   ? ADDR_LIMIT_32BIT : 0) | PER_OSF4))
 
-#define STACK_TOP \
+#define __STACK_TOP \
   (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL)
 
 #endif
diff -NurpX nopatch linux-2.6.7/include/asm-alpha/elf.h linux-2.6.7-pax/include/asm-alpha/elf.h
--- linux-2.6.7/include/asm-alpha/elf.h	2004-06-16 07:19:23.000000000 +0200
+++ linux-2.6.7-pax/include/asm-alpha/elf.h	2004-06-19 15:57:01.000000000 +0200
@@ -89,6 +89,17 @@ 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(tsk)	((tsk)->personality & ADDR_LIMIT_32BIT ? 0x10000 : 0x120000000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28)
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28)
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	((tsk)->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 -NurpX nopatch linux-2.6.7/include/asm-alpha/mman.h linux-2.6.7-pax/include/asm-alpha/mman.h
--- linux-2.6.7/include/asm-alpha/mman.h	2004-06-16 07:18:52.000000000 +0200
+++ linux-2.6.7-pax/include/asm-alpha/mman.h	2004-06-19 15:57:01.000000000 +0200
@@ -29,6 +29,10 @@
 #define MAP_POPULATE	0x20000		/* populate (prefault) pagetables */
 #define MAP_NONBLOCK	0x40000		/* do not block on IO */
 
+#ifdef CONFIG_PAX_RANDEXEC
+#define MAP_MIRROR	0x20000
+#endif
+
 #define MS_ASYNC	1		/* sync memory asynchronously */
 #define MS_SYNC		2		/* synchronous memory sync */
 #define MS_INVALIDATE	4		/* invalidate the caches */
diff -NurpX nopatch linux-2.6.7/include/asm-alpha/page.h linux-2.6.7-pax/include/asm-alpha/page.h
--- linux-2.6.7/include/asm-alpha/page.h	2004-06-16 07:19:44.000000000 +0200
+++ linux-2.6.7-pax/include/asm-alpha/page.h	2004-06-19 15:57:01.000000000 +0200
@@ -106,6 +106,15 @@ extern __inline__ int get_order(unsigned
 #define VM_DATA_DEFAULT_FLAGS		(VM_READ | VM_WRITE | VM_EXEC | \
 					 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+#ifdef CONFIG_PAX_PAGEEXEC
+#ifdef CONFIG_PAX_MPROTECT
+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
+			  ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#else
+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#endif
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _ALPHA_PAGE_H */
diff -NurpX nopatch linux-2.6.7/include/asm-alpha/pgtable.h linux-2.6.7-pax/include/asm-alpha/pgtable.h
--- linux-2.6.7/include/asm-alpha/pgtable.h	2004-06-16 07:19:03.000000000 +0200
+++ linux-2.6.7-pax/include/asm-alpha/pgtable.h	2004-06-19 15:57:01.000000000 +0200
@@ -96,6 +96,17 @@
 #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 -NurpX nopatch linux-2.6.7/include/asm-i386/a.out.h linux-2.6.7-pax/include/asm-i386/a.out.h
--- linux-2.6.7/include/asm-i386/a.out.h	2004-06-16 07:19:13.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/a.out.h	2004-06-19 15:57:01.000000000 +0200
@@ -19,7 +19,11 @@ struct exec
 
 #ifdef __KERNEL__
 
-#define STACK_TOP	TASK_SIZE
+#ifdef CONFIG_PAX_SEGMEXEC
+#define __STACK_TOP ((current->flags & PF_PAX_SEGMEXEC)?TASK_SIZE/2:TASK_SIZE)
+#else
+#define __STACK_TOP TASK_SIZE
+#endif
 
 #endif
 
diff -NurpX nopatch linux-2.6.7/include/asm-i386/desc.h linux-2.6.7-pax/include/asm-i386/desc.h
--- linux-2.6.7/include/asm-i386/desc.h	2004-06-16 07:18:37.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/desc.h	2004-06-19 15:57:01.000000000 +0200
@@ -8,11 +8,71 @@
 
 #include <linux/preempt.h>
 #include <linux/smp.h>
+#include <linux/sched.h>
 
 #include <asm/mmu.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
 
 extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES];
 
+#define pax_open_kernel(flags, cr3)		\
+do {						\
+	typecheck(unsigned long,flags);		\
+	typecheck(unsigned long,cr3);		\
+	local_irq_save(flags);			\
+	asm("movl %%cr3,%0":"=r" (cr3));	\
+	load_cr3(kernexec_pg_dir);		\
+} while(0)
+
+#define pax_close_kernel(flags, cr3)		\
+do {						\
+	typecheck(unsigned long,flags);		\
+	typecheck(unsigned long,cr3);		\
+	asm("movl %0,%%cr3": :"r" (cr3));	\
+	local_irq_restore(flags);		\
+} while(0)
+
+#define pax_open_kernel_noirq(cr3)			\
+do {						\
+	typecheck(unsigned long,cr3);		\
+	asm("movl %%cr3,%0":"=r" (cr3));	\
+	load_cr3(kernexec_pg_dir);		\
+} while(0)
+
+#define pax_close_kernel_noirq(cr3)			\
+do {						\
+	typecheck(unsigned long,cr3);		\
+	asm("movl %0,%%cr3": :"r" (cr3));	\
+} while(0)
+
+static inline void set_user_cs(struct mm_struct *mm, int cpu)
+{
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+	unsigned long base = mm->context.user_cs_base;
+	unsigned long limit = mm->context.user_cs_limit;
+
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long flags, cr3;
+
+	pax_open_kernel(flags, cr3);
+#endif
+
+	if (limit) {
+		limit -= 1UL;
+		limit >>= 12;
+	}
+
+	cpu_gdt_table[cpu][GDT_ENTRY_DEFAULT_USER_CS].a = (limit & 0xFFFFUL) | (base << 16);
+	cpu_gdt_table[cpu][GDT_ENTRY_DEFAULT_USER_CS].b = (limit & 0xF0000UL) | 0xC0FB00UL | (base & 0xFF000000UL) | ((base >> 16) & 0xFFUL);
+
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_close_kernel(flags, cr3);
+#endif
+
+#endif
+}
+
 struct Xgt_desc_struct {
 	unsigned short size;
 	unsigned long address __attribute__((packed));
@@ -28,7 +88,7 @@ extern struct Xgt_desc_struct idt_descr,
  * This is the ldt that every process will get unless we need
  * something other than this.
  */
-extern struct desc_struct default_ldt[];
+extern const struct desc_struct default_ldt[];
 extern void set_intr_gate(unsigned int irq, void * addr);
 
 #define _set_tssldt_desc(n,addr,limit,type) \
@@ -42,18 +102,35 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\
 	"rorl $16,%%eax" \
 	: "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type))
 
-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
+static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
 {
 	_set_tssldt_desc(&cpu_gdt_table[cpu][entry], (int)addr, 235, 0x89);
 }
 
 #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
 
-static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
+static inline void __set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size)
 {
 	_set_tssldt_desc(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
 }
 
+static inline void set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size)
+{
+
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long flags, cr3;
+
+	pax_open_kernel(flags, cr3);
+#endif
+
+	_set_tssldt_desc(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
+
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_close_kernel(flags, cr3);
+#endif
+
+}
+
 #define LDT_entry_a(info) \
 	((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
 
@@ -67,7 +144,7 @@ static inline void set_ldt_desc(unsigned
 	((info)->seg_32bit << 22) | \
 	((info)->limit_in_pages << 23) | \
 	((info)->useable << 20) | \
-	0x7000)
+	0x7100)
 
 #define LDT_empty(info) (\
 	(info)->base_addr	== 0	&& \
@@ -104,7 +181,7 @@ static inline void clear_LDT(void)
  */
 static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
 {
-	void *segments = pc->ldt;
+	const void *segments = pc->ldt;
 	int count = pc->size;
 
 	if (likely(!count)) {
@@ -123,6 +200,22 @@ static inline void load_LDT(mm_context_t
 	put_cpu();
 }
 
+static inline void _load_LDT(mm_context_t *pc)
+{
+	int cpu = get_cpu();
+	const void *segments = pc->ldt;
+	int count = pc->size;
+
+	if (likely(!count)) {
+		segments = &default_ldt[0];
+		count = 5;
+	}
+		
+	__set_ldt_desc(cpu, segments, count);
+	load_LDT_desc();
+	put_cpu();
+}
+
 #endif /* !__ASSEMBLY__ */
 
 #endif
diff -NurpX nopatch linux-2.6.7/include/asm-i386/elf.h linux-2.6.7-pax/include/asm-i386/elf.h
--- linux-2.6.7/include/asm-i386/elf.h	2004-06-16 07:19:42.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/elf.h	2004-06-19 15:57:01.000000000 +0200
@@ -72,6 +72,19 @@ typedef struct user_fxsr_struct elf_fpxr
 
 #define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
 
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+#define PAX_ELF_ET_DYN_BASE(tsk)	0x10000000UL
+#endif
+
+#ifdef CONFIG_PAX_ASLR
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		15
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		15
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	((tsk)->flags & PF_PAX_SEGMEXEC ? 15 : 16)
+#endif
+
 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
    now struct_user_regs, they are different) */
 
@@ -113,8 +126,11 @@ typedef struct user_fxsr_struct elf_fpxr
  * Architecture-neutral AT_ values in 0-17, leave some room
  * for more of them, start the x86-specific ones at 32.
  */
+
+#ifndef CONFIG_PAX_NOVSYSCALL
 #define AT_SYSINFO		32
 #define AT_SYSINFO_EHDR		33
+#endif
 
 #ifdef __KERNEL__
 #define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX)
@@ -129,7 +145,14 @@ extern int dump_task_extended_fpu (struc
 
 #define VSYSCALL_BASE	(__fix_to_virt(FIX_VSYSCALL))
 #define VSYSCALL_EHDR	((const struct elfhdr *) VSYSCALL_BASE)
+
+#ifndef CONFIG_PAX_NOVSYSCALL
+#ifdef CONFIG_PAX_SEGMEXEC
+#define VSYSCALL_ENTRY	((current->flags & PF_PAX_SEGMEXEC) ? (unsigned long) &__kernel_vsyscall - SEGMEXEC_TASK_SIZE : (unsigned long) &__kernel_vsyscall)
+#else
 #define VSYSCALL_ENTRY	((unsigned long) &__kernel_vsyscall)
+#endif
+
 extern void __kernel_vsyscall;
 
 #define ARCH_DLINFO						\
@@ -185,3 +208,5 @@ do {									      \
 #endif
 
 #endif
+
+#endif
diff -NurpX nopatch linux-2.6.7/include/asm-i386/mach-default/apm.h linux-2.6.7-pax/include/asm-i386/mach-default/apm.h
--- linux-2.6.7/include/asm-i386/mach-default/apm.h	2004-06-16 07:19:01.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/mach-default/apm.h	2004-06-19 15:57:01.000000000 +0200
@@ -36,7 +36,7 @@ static inline void apm_bios_call_asm(u32
 	__asm__ __volatile__(APM_DO_ZERO_SEGS
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
-		"lcall *%%cs:apm_bios_entry\n\t"
+		"lcall *%%ss:apm_bios_entry\n\t"
 		"setc %%al\n\t"
 		"popl %%ebp\n\t"
 		"popl %%edi\n\t"
@@ -60,7 +60,7 @@ static inline u8 apm_bios_call_simple_as
 	__asm__ __volatile__(APM_DO_ZERO_SEGS
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
-		"lcall *%%cs:apm_bios_entry\n\t"
+		"lcall *%%ss:apm_bios_entry\n\t"
 		"setc %%bl\n\t"
 		"popl %%ebp\n\t"
 		"popl %%edi\n\t"
diff -NurpX nopatch linux-2.6.7/include/asm-i386/mach-pc9800/apm.h linux-2.6.7-pax/include/asm-i386/mach-pc9800/apm.h
--- linux-2.6.7/include/asm-i386/mach-pc9800/apm.h	2004-06-16 07:19:17.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/mach-pc9800/apm.h	2004-06-19 15:57:01.000000000 +0200
@@ -39,7 +39,7 @@ static inline void apm_bios_call_asm(u32
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
 		"pushfl\n\t"
-		"lcall *%%cs:apm_bios_entry\n\t"
+		"lcall *%%ss:apm_bios_entry\n\t"
 		"setc %%al\n\t"
 		"popl %%ebp\n\t"
 		"popl %%edi\n\t"
@@ -64,7 +64,7 @@ static inline u8 apm_bios_call_simple_as
 		"pushl %%edi\n\t"
 		"pushl %%ebp\n\t"
 		"pushfl\n\t"
-		"lcall *%%cs:apm_bios_entry\n\t"
+		"lcall *%%ss:apm_bios_entry\n\t"
 		"setc %%bl\n\t"
 		"popl %%ebp\n\t"
 		"popl %%edi\n\t"
diff -NurpX nopatch linux-2.6.7/include/asm-i386/mman.h linux-2.6.7-pax/include/asm-i386/mman.h
--- linux-2.6.7/include/asm-i386/mman.h	2004-06-16 07:18:58.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/mman.h	2004-06-19 15:57:01.000000000 +0200
@@ -23,6 +23,10 @@
 #define MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
 #define MAP_NONBLOCK	0x10000		/* do not block on IO */
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+#define MAP_MIRROR	0x20000
+#endif
+
 #define MS_ASYNC	1		/* sync memory asynchronously */
 #define MS_INVALIDATE	2		/* invalidate the caches */
 #define MS_SYNC		4		/* synchronous memory sync */
diff -NurpX nopatch linux-2.6.7/include/asm-i386/mmu.h linux-2.6.7-pax/include/asm-i386/mmu.h
--- linux-2.6.7/include/asm-i386/mmu.h	2004-06-16 07:19:37.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/mmu.h	2004-06-19 15:57:01.000000000 +0200
@@ -12,6 +12,17 @@ typedef struct { 
 	int size;
 	struct semaphore sem;
 	void *ldt;
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+	unsigned long user_cs_base;
+	unsigned long user_cs_limit;
+
+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
+	cpumask_t cpu_user_cs_mask;
+#endif
+
+#endif
+
 } mm_context_t;
 
 #endif
diff -NurpX nopatch linux-2.6.7/include/asm-i386/mmu_context.h linux-2.6.7-pax/include/asm-i386/mmu_context.h
--- linux-2.6.7/include/asm-i386/mmu_context.h	2004-06-16 07:18:37.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/mmu_context.h	2004-06-19 15:57:01.000000000 +0200
@@ -46,6 +46,13 @@ static inline void switch_mm(struct mm_s
 		 */
 		if (unlikely(prev->context.ldt != next->context.ldt))
 			load_LDT_nolock(&next->context, cpu);
+
+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
+		cpu_clear(cpu, prev->context.cpu_user_cs_mask);
+		cpu_set(cpu, next->context.cpu_user_cs_mask);
+#endif
+
+		set_user_cs(next, cpu);
 	}
 #ifdef CONFIG_SMP
 	else {
@@ -58,6 +65,12 @@ static inline void switch_mm(struct mm_s
 			 */
 			load_cr3(next->pgd);
 			load_LDT_nolock(&next->context, cpu);
+
+#ifdef CONFIG_PAX_PAGEEXEC
+			cpu_set(cpu, next->context.cpu_user_cs_mask);
+#endif
+
+			set_user_cs(next, cpu);
 		}
 	}
 #endif
diff -NurpX nopatch linux-2.6.7/include/asm-i386/page.h linux-2.6.7-pax/include/asm-i386/page.h
--- linux-2.6.7/include/asm-i386/page.h	2004-06-16 07:18:59.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/page.h	2004-06-19 15:57:01.000000000 +0200
@@ -120,6 +120,19 @@ static __inline__ int get_order(unsigned
 #define __PAGE_OFFSET		(0xC0000000UL)
 #endif
 
+#ifdef CONFIG_PAX_KERNEXEC
+#ifdef __ASSEMBLY__
+#define __KERNEL_TEXT_OFFSET	(0xC0400000)
+#else
+#define __KERNEL_TEXT_OFFSET	(0xC0400000UL)
+#endif
+#else
+#ifdef __ASSEMBLY__
+#define __KERNEL_TEXT_OFFSET	(0)
+#else
+#define __KERNEL_TEXT_OFFSET	(0x0UL)
+#endif
+#endif
 
 #define PAGE_OFFSET		((unsigned long)__PAGE_OFFSET)
 #define VMALLOC_RESERVE		((unsigned long)__VMALLOC_RESERVE)
@@ -139,6 +152,19 @@ static __inline__ int get_order(unsigned
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+#ifdef CONFIG_PAX_MPROTECT
+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
+			  ((current->flags & (PF_PAX_PAGEEXEC|PF_PAX_SEGMEXEC))?0:VM_EXEC))
+#else
+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & (PF_PAX_PAGEEXEC|PF_PAX_SEGMEXEC))?0:VM_EXEC))
+#endif
+#endif
+
+#ifdef CONFIG_PAX_PAGEEXEC
+#define CONFIG_ARCH_TRACK_EXEC_LIMIT 1
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _I386_PAGE_H */
diff -NurpX nopatch linux-2.6.7/include/asm-i386/pgalloc.h linux-2.6.7-pax/include/asm-i386/pgalloc.h
--- linux-2.6.7/include/asm-i386/pgalloc.h	2004-06-16 07:18:57.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/pgalloc.h	2004-06-19 15:57:01.000000000 +0200
@@ -8,7 +8,7 @@
 #include <linux/mm.h>		/* for struct page */
 
 #define pmd_populate_kernel(mm, pmd, pte) \
-		set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
+		set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)))
 
 static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte)
 {
diff -NurpX nopatch linux-2.6.7/include/asm-i386/pgtable.h linux-2.6.7-pax/include/asm-i386/pgtable.h
--- linux-2.6.7/include/asm-i386/pgtable.h	2004-06-16 07:19:43.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/pgtable.h	2004-11-04 21:43:11.000000000 +0100
@@ -25,13 +25,6 @@
 #include <linux/list.h>
 #include <linux/spinlock.h>
 
-/*
- * ZERO_PAGE is a global shared page that is always zero: used
- * for zero-mapped memory areas etc..
- */
-#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
-extern unsigned long empty_zero_page[1024];
-extern pgd_t swapper_pg_dir[1024];
 extern kmem_cache_t *pgd_cache;
 extern kmem_cache_t *pmd_cache;
 extern spinlock_t pgd_lock;
@@ -43,21 +36,42 @@ void pgd_dtor(void *, kmem_cache_t *, un
 void pgtable_cache_init(void);
 void paging_init(void);
 
-#endif /* !__ASSEMBLY__ */
-
 /*
  * The Linux x86 paging architecture is 'compile-time dual-mode', it
  * implements both the traditional 2-level x86 page tables and the
  * newer 3-level PAE-mode page tables.
  */
-#ifndef __ASSEMBLY__
 #ifdef CONFIG_X86_PAE
 # include <asm/pgtable-3level.h>
 #else
 # include <asm/pgtable-2level.h>
 #endif
+
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+extern unsigned long empty_zero_page[1024];
+
+#if CONFIG_X86_PAE
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+extern pmd_t swapper_pm_dir[PTRS_PER_PGD][PTRS_PER_PMD];
+
+#ifdef CONFIG_PAX_KERNEXEC
+extern pgd_t kernexec_pg_dir[PTRS_PER_PGD];
+extern pmd_t kernexec_pm_dir[PTRS_PER_PGD][PTRS_PER_PMD];
+#endif
+#else
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+#ifdef CONFIG_PAX_KERNEXEC
+extern pgd_t kernexec_pg_dir[PTRS_PER_PGD];
+#endif
 #endif
 
+#endif /* !__ASSEMBLY__ */
+
 #define PMD_SIZE	(1UL << PMD_SHIFT)
 #define PMD_MASK	(~(PMD_SIZE-1))
 #define PGDIR_SIZE	(1UL << PGDIR_SHIFT)
@@ -136,6 +150,16 @@ void paging_init(void);
 #define PAGE_COPY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 
+#ifdef CONFIG_PAX_PAGEEXEC
+# define PAGE_SHARED_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED)
+# define PAGE_COPY_NOEXEC	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
+# define PAGE_READONLY_NOEXEC	__pgprot(_PAGE_PRESENT | _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 \
 	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
 
@@ -155,18 +179,18 @@ extern unsigned long __PAGE_KERNEL;
  * This is the closest we can get..
  */
 #define __P000	PAGE_NONE
-#define __P001	PAGE_READONLY
-#define __P010	PAGE_COPY
-#define __P011	PAGE_COPY
+#define __P001	PAGE_READONLY_NOEXEC
+#define __P010	PAGE_COPY_NOEXEC
+#define __P011	PAGE_COPY_NOEXEC
 #define __P100	PAGE_READONLY
 #define __P101	PAGE_READONLY
 #define __P110	PAGE_COPY
 #define __P111	PAGE_COPY
 
 #define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY
-#define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED
+#define __S001	PAGE_READONLY_NOEXEC
+#define __S010	PAGE_SHARED_NOEXEC
+#define __S011	PAGE_SHARED_NOEXEC
 #define __S100	PAGE_READONLY
 #define __S101	PAGE_READONLY
 #define __S110	PAGE_SHARED
@@ -343,6 +367,8 @@ static inline pte_t pte_modify(pte_t pte
 
 #endif /* !__ASSEMBLY__ */
 
+#define HAVE_ARCH_UNMAPPED_AREA
+
 #ifndef CONFIG_DISCONTIGMEM
 #define kern_addr_valid(addr)	(1)
 #endif /* !CONFIG_DISCONTIGMEM */
diff -NurpX nopatch linux-2.6.7/include/asm-i386/processor.h linux-2.6.7-pax/include/asm-i386/processor.h
--- linux-2.6.7/include/asm-i386/processor.h	2004-06-16 07:18:56.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/processor.h	2004-06-19 15:57:01.000000000 +0200
@@ -28,7 +28,7 @@ struct desc_struct {
 };
 
 #define desc_empty(desc) \
-		(!((desc)->a + (desc)->b))
+		(!((desc)->a | (desc)->b))
 
 #define desc_equal(desc1, desc2) \
 		(((desc1)->a == (desc2)->a) && ((desc1)->b == (desc2)->b))
@@ -297,10 +297,23 @@ extern unsigned int mca_pentium_flag;
  */
 #define TASK_SIZE	(PAGE_OFFSET)
 
+#ifdef CONFIG_PAX_SEGMEXEC
+#define SEGMEXEC_TASK_SIZE	((PAGE_OFFSET) / 2)
+#endif
+
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
+
+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC)
+#define TASK_UNMAPPED_BASE	(PAGE_ALIGN((current->flags & PF_PAX_PAGEEXEC)? 0x00110000UL : (current->flags & PF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3 : TASK_SIZE/3))
+#elif defined(CONFIG_PAX_PAGEEXEC)
+#define TASK_UNMAPPED_BASE	(PAGE_ALIGN((current->flags & PF_PAX_PAGEEXEC)? 0x00110000UL : TASK_SIZE/3))
+#elif defined(CONFIG_PAX_SEGMEXEC)
+#define TASK_UNMAPPED_BASE	(PAGE_ALIGN((current->flags & PF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3 : TASK_SIZE/3))
+#else
 #define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
+#endif
 
 /*
  * Size of io_bitmap, covering ports 0 to 0x3ff.
@@ -494,16 +507,12 @@ void show_trace(struct task_struct *task
 unsigned long get_wchan(struct task_struct *p);
 
 #define THREAD_SIZE_LONGS      (THREAD_SIZE/sizeof(unsigned long))
-#define KSTK_TOP(info)                                                 \
-({                                                                     \
-       unsigned long *__ptr = (unsigned long *)(info);                 \
-       (unsigned long)(&__ptr[THREAD_SIZE_LONGS]);                     \
-})
+#define KSTK_TOP(info)         ((info)->task.thread.esp0)
 
 #define task_pt_regs(task)                                             \
 ({                                                                     \
        struct pt_regs *__regs__;                                       \
-       __regs__ = (struct pt_regs *)KSTK_TOP((task)->thread_info);     \
+       __regs__ = (struct pt_regs *)((task)->thread.esp0);             \
        __regs__ - 1;                                                   \
 })
 
@@ -627,7 +636,7 @@ static inline void rep_nop(void)
 extern inline void prefetch(const void *x)
 {
 	alternative_input(ASM_NOP4,
-			  "prefetchnta (%1)",
+			  "prefetchnta (%2)",
 			  X86_FEATURE_XMM,
 			  "r" (x));
 }
@@ -641,7 +650,7 @@ extern inline void prefetch(const void *
 extern inline void prefetchw(const void *x)
 {
 	alternative_input(ASM_NOP4,
-			  "prefetchw (%1)",
+			  "prefetchw (%2)",
 			  X86_FEATURE_3DNOW,
 			  "r" (x));
 }
diff -NurpX nopatch linux-2.6.7/include/asm-i386/system.h linux-2.6.7-pax/include/asm-i386/system.h
--- linux-2.6.7/include/asm-i386/system.h	2004-06-16 07:18:38.000000000 +0200
+++ linux-2.6.7-pax/include/asm-i386/system.h	2004-06-19 15:57:01.000000000 +0200
@@ -5,6 +5,7 @@
 #include <linux/kernel.h>
 #include <asm/segment.h>
 #include <asm/cpufeature.h>
+#include <asm/page.h>
 #include <linux/bitops.h> /* for LOCK_PREFIX */
 
 #ifdef __KERNEL__
@@ -301,7 +302,7 @@ struct alt_instr { 
 	asm volatile ("661:\n\t" oldinstr "\n662:\n" 		     \
 		      ".section .altinstructions,\"a\"\n"     	     \
 		      "  .align 4\n"				       \
-		      "  .long 661b\n"            /* label */          \
+		      "  .long 661b + %c1\n"       /* label */          \
 		      "  .long 663f\n"		  /* new instruction */ 	\
 		      "  .byte %c0\n"             /* feature bit */    \
 		      "  .byte 662b-661b\n"       /* sourcelen */      \
@@ -309,7 +310,7 @@ struct alt_instr { 
 		      ".previous\n"						\
 		      ".section .altinstr_replacement,\"ax\"\n"			\
 		      "663:\n\t" newinstr "\n664:\n"   /* replacement */    \
-		      ".previous" :: "i" (feature) : "memory")  
+		      ".previous" :: "i" (feature), "i" (__KERNEL_TEXT_OFFSET) : "memory")  
 
 /*
  * Alternative inline assembly with input.
@@ -325,7 +326,7 @@ struct alt_instr { 
 	asm volatile ("661:\n\t" oldinstr "\n662:\n"				\
 		      ".section .altinstructions,\"a\"\n"			\
 		      "  .align 4\n"						\
-		      "  .long 661b\n"            /* label */			\
+		      "  .long 661b + %c1\n"      /* label */			\
 		      "  .long 663f\n"		  /* new instruction */ 	\
 		      "  .byte %c0\n"             /* feature bit */		\
 		      "  .byte 662b-661b\n"       /* sourcelen */		\
@@ -333,7 +334,7 @@ struct alt_instr { 
 		      ".previous\n"						\
 		      ".section .altinstr_replacement,\"ax\"\n"			\
 		      "663:\n\t" newinstr "\n664:\n"   /* replacement */ 	\
-		      ".previous" :: "i" (feature), input)  
+		      ".previous" :: "i" (feature), "i" (__KERNEL_TEXT_OFFSET), input)  
 
 /*
  * Force strict CPU ordering.
diff -NurpX nopatch linux-2.6.7/include/asm-ia64/elf.h linux-2.6.7-pax/include/asm-ia64/elf.h
--- linux-2.6.7/include/asm-ia64/elf.h	2004-06-16 07:19:42.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ia64/elf.h	2004-06-19 15:57:01.000000000 +0200
@@ -162,6 +162,16 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR
 typedef struct ia64_fpreg elf_fpreg_t;
 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		((tsk)->personality == PER_LINUX32 ? 16 : 43 - PAGE_SHIFT)
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		((tsk)->personality == PER_LINUX32 ? 16 : 43 - PAGE_SHIFT)
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	((tsk)->personality == PER_LINUX32 ? 16 : 43 - PAGE_SHIFT)
+#endif
 
 
 struct pt_regs;	/* forward declaration... */
diff -NurpX nopatch linux-2.6.7/include/asm-ia64/mman.h linux-2.6.7-pax/include/asm-ia64/mman.h
--- linux-2.6.7/include/asm-ia64/mman.h	2004-06-16 07:19:23.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ia64/mman.h	2004-06-19 15:57:01.000000000 +0200
@@ -31,6 +31,10 @@
 #define MAP_POPULATE	0x08000		/* populate (prefault) pagetables */
 #define MAP_NONBLOCK	0x10000		/* do not block on IO */
 
+#ifdef CONFIG_PAX_RANDEXEC
+#define MAP_MIRROR	0x40000
+#endif
+
 #define MS_ASYNC	1		/* sync memory asynchronously */
 #define MS_INVALIDATE	2		/* invalidate the caches */
 #define MS_SYNC		4		/* synchronous memory sync */
diff -NurpX nopatch linux-2.6.7/include/asm-ia64/page.h linux-2.6.7-pax/include/asm-ia64/page.h
--- linux-2.6.7/include/asm-ia64/page.h	2004-06-16 07:18:58.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ia64/page.h	2004-06-19 15:57:01.000000000 +0200
@@ -187,4 +187,13 @@ get_order (unsigned long size)
 					 (((current->thread.flags & IA64_THREAD_XSTACK) != 0)	\
 					  ? VM_EXEC : 0))
 
+#ifdef CONFIG_PAX_PAGEEXEC
+#ifdef CONFIG_PAX_MPROTECT
+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
+			  ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#else
+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#endif
+#endif
+
 #endif /* _ASM_IA64_PAGE_H */
diff -NurpX nopatch linux-2.6.7/include/asm-ia64/pgtable.h linux-2.6.7-pax/include/asm-ia64/pgtable.h
--- linux-2.6.7/include/asm-ia64/pgtable.h	2004-06-16 07:19:09.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ia64/pgtable.h	2004-06-19 15:57:01.000000000 +0200
@@ -121,6 +121,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 -NurpX nopatch linux-2.6.7/include/asm-ia64/ustack.h linux-2.6.7-pax/include/asm-ia64/ustack.h
--- linux-2.6.7/include/asm-ia64/ustack.h	2004-06-16 07:20:04.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ia64/ustack.h	2004-06-19 15:57:01.000000000 +0200
@@ -11,6 +11,6 @@
 #define MAX_USER_STACK_SIZE	(RGN_MAP_LIMIT/2)
 /* Make a default stack size of 2GB */
 #define DEFAULT_USER_STACK_SIZE	(1UL << 31)
-#define STACK_TOP		(0x6000000000000000UL + RGN_MAP_LIMIT)
+#define __STACK_TOP		(0x6000000000000000UL + RGN_MAP_LIMIT)
 
 #endif /* _ASM_IA64_USTACK_H */
diff -NurpX nopatch linux-2.6.7/include/asm-mips/a.out.h linux-2.6.7-pax/include/asm-mips/a.out.h
--- linux-2.6.7/include/asm-mips/a.out.h	2004-06-16 07:19:13.000000000 +0200
+++ linux-2.6.7-pax/include/asm-mips/a.out.h	2004-06-19 15:57:01.000000000 +0200
@@ -36,10 +36,10 @@ struct exec
 #ifdef __KERNEL__
 
 #ifdef CONFIG_MIPS32
-#define STACK_TOP	TASK_SIZE
+#define __STACK_TOP	TASK_SIZE
 #endif
 #ifdef CONFIG_MIPS64
-#define STACK_TOP	(current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
+#define __STACK_TOP	(current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
 #endif
 
 #endif
diff -NurpX nopatch linux-2.6.7/include/asm-mips/elf.h linux-2.6.7-pax/include/asm-mips/elf.h
--- linux-2.6.7/include/asm-mips/elf.h	2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7-pax/include/asm-mips/elf.h	2004-06-19 15:57:01.000000000 +0200
@@ -273,4 +273,15 @@ do {	current->thread.mflags &= ~MF_ABI_M
 #define ELF_ET_DYN_BASE         (TASK_SIZE / 3 * 2)
 #endif
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#endif
+
 #endif /* _ASM_ELF_H */
diff -NurpX nopatch linux-2.6.7/include/asm-mips/page.h linux-2.6.7-pax/include/asm-mips/page.h
--- linux-2.6.7/include/asm-mips/page.h	2004-06-16 07:19:13.000000000 +0200
+++ linux-2.6.7-pax/include/asm-mips/page.h	2004-06-19 15:57:01.000000000 +0200
@@ -124,6 +124,15 @@ static __inline__ int get_order(unsigned
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+#ifdef CONFIG_PAX_PAGEEXEC
+#ifdef CONFIG_PAX_MPROTECT
+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
+			  ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#else
+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#endif
+#endif
+
 #define UNCAC_ADDR(addr)	((addr) - PAGE_OFFSET + UNCAC_BASE)
 #define CAC_ADDR(addr)		((addr) - UNCAC_BASE + PAGE_OFFSET)
 
diff -NurpX nopatch linux-2.6.7/include/asm-parisc/a.out.h linux-2.6.7-pax/include/asm-parisc/a.out.h
--- linux-2.6.7/include/asm-parisc/a.out.h	2004-06-16 07:20:04.000000000 +0200
+++ linux-2.6.7-pax/include/asm-parisc/a.out.h	2004-06-19 15:57:01.000000000 +0200
@@ -22,7 +22,7 @@ struct exec
 /* XXX: STACK_TOP actually should be STACK_BOTTOM for parisc.
  * prumpf */
 
-#define STACK_TOP	TASK_SIZE
+#define __STACK_TOP	TASK_SIZE
 
 #endif
 
diff -NurpX nopatch linux-2.6.7/include/asm-parisc/elf.h linux-2.6.7-pax/include/asm-parisc/elf.h
--- linux-2.6.7/include/asm-parisc/elf.h	2004-06-16 07:19:43.000000000 +0200
+++ linux-2.6.7-pax/include/asm-parisc/elf.h	2004-06-19 15:57:01.000000000 +0200
@@ -337,6 +337,17 @@ struct pt_regs;	/* forward declaration..
 
 #define ELF_ET_DYN_BASE         (TASK_UNMAPPED_BASE + 0x01000000)
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	0x10000UL
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		16
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT 
+#define PAX_DELTA_EXEC_LEN(tsk)		16
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	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 -NurpX nopatch linux-2.6.7/include/asm-parisc/mman.h linux-2.6.7-pax/include/asm-parisc/mman.h
--- linux-2.6.7/include/asm-parisc/mman.h	2004-06-16 07:19:37.000000000 +0200
+++ linux-2.6.7-pax/include/asm-parisc/mman.h	2004-06-19 15:57:01.000000000 +0200
@@ -23,6 +23,10 @@
 #define MAP_POPULATE	0x10000		/* populate (prefault) pagetables */
 #define MAP_NONBLOCK	0x20000		/* do not block on IO */
 
+#ifdef CONFIG_PAX_RANDEXEC
+#define MAP_MIRROR	0x0400
+#endif
+
 #define MS_SYNC		1		/* synchronous memory sync */
 #define MS_ASYNC	2		/* sync memory asynchronously */
 #define MS_INVALIDATE	4		/* invalidate the caches */
diff -NurpX nopatch linux-2.6.7/include/asm-parisc/page.h linux-2.6.7-pax/include/asm-parisc/page.h
--- linux-2.6.7/include/asm-parisc/page.h	2004-06-16 07:19:01.000000000 +0200
+++ linux-2.6.7-pax/include/asm-parisc/page.h	2004-06-19 15:57:01.000000000 +0200
@@ -157,6 +157,15 @@ extern int npmem_ranges;
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+#ifdef CONFIG_PAX_PAGEEXEC
+#ifdef CONFIG_PAX_MPROTECT
+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
+			  ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#else
+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#endif
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _PARISC_PAGE_H */
diff -NurpX nopatch linux-2.6.7/include/asm-parisc/pgtable.h linux-2.6.7-pax/include/asm-parisc/pgtable.h
--- linux-2.6.7/include/asm-parisc/pgtable.h	2004-06-16 07:19:52.000000000 +0200
+++ linux-2.6.7-pax/include/asm-parisc/pgtable.h	2004-06-19 15:57:01.000000000 +0200
@@ -189,6 +189,17 @@ extern  void *vmalloc_start;
 #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_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_DIRTY | _PAGE_ACCESSED)
 #define PAGE_KERNEL_UNC	__pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
diff -NurpX nopatch linux-2.6.7/include/asm-ppc/a.out.h linux-2.6.7-pax/include/asm-ppc/a.out.h
--- linux-2.6.7/include/asm-ppc/a.out.h	2004-06-16 07:19:23.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ppc/a.out.h	2004-06-19 15:57:01.000000000 +0200
@@ -2,7 +2,7 @@
 #define __PPC_A_OUT_H__
 
 /* grabbed from the intel stuff  */
-#define STACK_TOP TASK_SIZE
+#define __STACK_TOP TASK_SIZE
 
 
 struct exec
diff -NurpX nopatch linux-2.6.7/include/asm-ppc/elf.h linux-2.6.7-pax/include/asm-ppc/elf.h
--- linux-2.6.7/include/asm-ppc/elf.h	2004-06-16 07:18:37.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ppc/elf.h	2004-06-19 15:57:01.000000000 +0200
@@ -89,6 +89,17 @@ struct task_struct;
 
 #define ELF_ET_DYN_BASE         (0x08000000)
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	0x10000000UL
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		15
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		15
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	15
+#endif
+
 #define USE_ELF_CORE_DUMP
 #define ELF_EXEC_PAGESIZE	4096
 
diff -NurpX nopatch linux-2.6.7/include/asm-ppc/mman.h linux-2.6.7-pax/include/asm-ppc/mman.h
--- linux-2.6.7/include/asm-ppc/mman.h	2004-06-16 07:20:26.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ppc/mman.h	2004-06-19 15:57:01.000000000 +0200
@@ -24,6 +24,10 @@
 #define MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
 #define MAP_NONBLOCK	0x10000		/* do not block on IO */
 
+#ifdef CONFIG_PAX_RANDEXEC
+#define MAP_MIRROR	0x0200
+#endif
+
 #define MS_ASYNC	1		/* sync memory asynchronously */
 #define MS_INVALIDATE	2		/* invalidate the caches */
 #define MS_SYNC		4		/* synchronous memory sync */
diff -NurpX nopatch linux-2.6.7/include/asm-ppc/page.h linux-2.6.7-pax/include/asm-ppc/page.h
--- linux-2.6.7/include/asm-ppc/page.h	2004-06-16 07:19:02.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ppc/page.h	2004-06-19 15:57:01.000000000 +0200
@@ -163,5 +163,14 @@ extern __inline__ int get_order(unsigned
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+#ifdef CONFIG_PAX_PAGEEXEC
+#ifdef CONFIG_PAX_MPROTECT
+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
+			  ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#else
+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#endif
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _PPC_PAGE_H */
diff -NurpX nopatch linux-2.6.7/include/asm-ppc/pgtable.h linux-2.6.7-pax/include/asm-ppc/pgtable.h
--- linux-2.6.7/include/asm-ppc/pgtable.h	2004-06-16 07:19:01.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ppc/pgtable.h	2004-06-19 15:57:01.000000000 +0200
@@ -349,11 +349,21 @@ extern unsigned long ioremap_bot, iorema
 
 #define PAGE_NONE	__pgprot(_PAGE_BASE)
 #define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC)
 #define PAGE_SHARED	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
-#define PAGE_SHARED_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
+#define PAGE_SHARED_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC | _PAGE_HWEXEC)
 #define PAGE_COPY	__pgprot(_PAGE_BASE | _PAGE_USER)
-#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+#define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC)
+
+#if defined(CONFIG_PAX_PAGEEXEC) && !defined(CONFIG_40x) && !defined(CONFIG_44x)
+# define PAGE_SHARED_NOEXEC	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_GUARDED)
+# define PAGE_COPY_NOEXEC	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
+# define PAGE_READONLY_NOEXEC	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
+#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_RAM)
 #define PAGE_KERNEL_NOCACHE	__pgprot(_PAGE_IO)
@@ -365,21 +375,21 @@ extern unsigned long ioremap_bot, iorema
  * This is the closest we can get..
  */
 #define __P000	PAGE_NONE
-#define __P001	PAGE_READONLY_X
-#define __P010	PAGE_COPY
-#define __P011	PAGE_COPY_X
-#define __P100	PAGE_READONLY
+#define __P001	PAGE_READONLY_NOEXEC
+#define __P010	PAGE_COPY_NOEXEC
+#define __P011	PAGE_COPY_NOEXEC
+#define __P100	PAGE_READONLY_X
 #define __P101	PAGE_READONLY_X
-#define __P110	PAGE_COPY
+#define __P110	PAGE_COPY_X
 #define __P111	PAGE_COPY_X
 
 #define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY_X
-#define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED_X
-#define __S100	PAGE_READONLY
+#define __S001	PAGE_READONLY_NOEXEC
+#define __S010	PAGE_SHARED_NOEXEC
+#define __S011	PAGE_SHARED_NOEXEC
+#define __S100	PAGE_READONLY_X
 #define __S101	PAGE_READONLY_X
-#define __S110	PAGE_SHARED
+#define __S110	PAGE_SHARED_X
 #define __S111	PAGE_SHARED_X
 
 #ifndef __ASSEMBLY__
diff -NurpX nopatch linux-2.6.7/include/asm-ppc64/a.out.h linux-2.6.7-pax/include/asm-ppc64/a.out.h
--- linux-2.6.7/include/asm-ppc64/a.out.h	2004-06-16 07:18:52.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ppc64/a.out.h	2004-06-19 15:57:01.000000000 +0200
@@ -35,7 +35,7 @@ struct exec
 /* Give 32-bit user space a full 4G address space to live in. */
 #define STACK_TOP_USER32 (TASK_SIZE_USER32)
 
-#define STACK_TOP ((test_thread_flag(TIF_32BIT) || \
+#define __STACK_TOP ((test_thread_flag(TIF_32BIT) || \
 		(ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? \
 		STACK_TOP_USER32 : STACK_TOP_USER64)
 
diff -NurpX nopatch linux-2.6.7/include/asm-ppc64/elf.h linux-2.6.7-pax/include/asm-ppc64/elf.h
--- linux-2.6.7/include/asm-ppc64/elf.h	2004-06-16 07:19:43.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ppc64/elf.h	2004-06-19 15:57:01.000000000 +0200
@@ -154,6 +154,17 @@ typedef elf_vrreg_t elf_vrregset_t32[ELF
 
 #define ELF_ET_DYN_BASE         (0x08000000)
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	(0x10000000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		((test_thread_flag(TIF_32BIT) || (ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? 16 : 24)
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		((test_thread_flag(TIF_32BIT) || (ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? 16 : 24)
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	((test_thread_flag(TIF_32BIT) || (ppcdebugset(PPCDBG_BINFMT_32ADDR))) ? 16 : 24)
+#endif
+
 #ifdef __KERNEL__
 
 /* Common routine for both 32-bit and 64-bit processes */
diff -NurpX nopatch linux-2.6.7/include/asm-ppc64/mman.h linux-2.6.7-pax/include/asm-ppc64/mman.h
--- linux-2.6.7/include/asm-ppc64/mman.h	2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ppc64/mman.h	2004-06-19 15:57:01.000000000 +0200
@@ -29,6 +29,10 @@
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
 #define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
 
+#ifdef CONFIG_PAX_RANDEXEC
+#define MAP_MIRROR	0x0200
+#endif
+
 #define MS_ASYNC	1		/* sync memory asynchronously */
 #define MS_INVALIDATE	2		/* invalidate the caches */
 #define MS_SYNC		4		/* synchronous memory sync */
diff -NurpX nopatch linux-2.6.7/include/asm-ppc64/page.h linux-2.6.7-pax/include/asm-ppc64/page.h
--- linux-2.6.7/include/asm-ppc64/page.h	2004-06-16 07:18:47.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ppc64/page.h	2004-06-19 15:57:01.000000000 +0200
@@ -245,5 +245,14 @@ extern int page_is_ram(unsigned long phy
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+#ifdef CONFIG_PAX_PAGEEXEC
+#ifdef CONFIG_PAX_MPROTECT
+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
+			 ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#else
+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#endif
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _PPC64_PAGE_H */
diff -NurpX nopatch linux-2.6.7/include/asm-ppc64/pgtable.h linux-2.6.7-pax/include/asm-ppc64/pgtable.h
--- linux-2.6.7/include/asm-ppc64/pgtable.h	2004-06-16 07:20:04.000000000 +0200
+++ linux-2.6.7-pax/include/asm-ppc64/pgtable.h	2004-06-19 15:57:01.000000000 +0200
@@ -112,6 +112,17 @@
 #define PAGE_COPY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
 #define PAGE_READONLY	__pgprot(_PAGE_BASE | _PAGE_USER)
 #define PAGE_READONLY_X	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
+
+#ifdef CONFIG_PAX_PAGEEXEC
+# define PAGE_SHARED_NOEXEC	__pgprot(_PAGE_BASE | _PAGE_RW | _PAGE_USER | _PAGE_GUARDED)
+# define PAGE_COPY_NOEXEC	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
+# define PAGE_READONLY_NOEXEC	__pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
+#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_BASE | _PAGE_WRENABLE)
 #define PAGE_KERNEL_CI	__pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | \
 			       _PAGE_WRENABLE | _PAGE_NO_CACHE | _PAGE_GUARDED)
@@ -123,21 +134,21 @@
  * This is the closest we can get..
  */
 #define __P000	PAGE_NONE
-#define __P001	PAGE_READONLY_X
-#define __P010	PAGE_COPY
-#define __P011	PAGE_COPY_X
-#define __P100	PAGE_READONLY
+#define __P001	PAGE_READONLY_NOEXEC
+#define __P010	PAGE_COPY_NOEXEC
+#define __P011	PAGE_COPY_NOEXEC
+#define __P100	PAGE_READONLY_X
 #define __P101	PAGE_READONLY_X
-#define __P110	PAGE_COPY
+#define __P110	PAGE_COPY_X
 #define __P111	PAGE_COPY_X
 
 #define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY_X
-#define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED_X
-#define __S100	PAGE_READONLY
+#define __S001	PAGE_READONLY_NOEXEC
+#define __S010	PAGE_SHARED_NOEXEC
+#define __S011	PAGE_SHARED_NOEXEC
+#define __S100	PAGE_READONLY_X
 #define __S101	PAGE_READONLY_X
-#define __S110	PAGE_SHARED
+#define __S110	PAGE_SHARED_X
 #define __S111	PAGE_SHARED_X
 
 #ifndef __ASSEMBLY__
diff -NurpX nopatch linux-2.6.7/include/asm-sparc/a.out.h linux-2.6.7-pax/include/asm-sparc/a.out.h
--- linux-2.6.7/include/asm-sparc/a.out.h	2004-06-16 07:18:57.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc/a.out.h	2004-06-19 15:57:01.000000000 +0200
@@ -91,7 +91,7 @@ struct relocation_info /* used when head
 
 #include <asm/page.h>
 
-#define STACK_TOP	(PAGE_OFFSET - PAGE_SIZE)
+#define __STACK_TOP	(PAGE_OFFSET - PAGE_SIZE)
 
 #endif /* __KERNEL__ */
 
diff -NurpX nopatch linux-2.6.7/include/asm-sparc/elf.h linux-2.6.7-pax/include/asm-sparc/elf.h
--- linux-2.6.7/include/asm-sparc/elf.h	2004-06-16 07:19:51.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc/elf.h	2004-06-19 15:57:01.000000000 +0200
@@ -145,6 +145,17 @@ typedef struct {
 
 #define ELF_ET_DYN_BASE         (0x08000000)
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	0x10000UL
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		16
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		16
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	16
+#endif
+
 /* This yields a mask that user programs can use to figure out what
    instruction set this cpu supports.  This can NOT be done in userspace
    on Sparc.  */
diff -NurpX nopatch linux-2.6.7/include/asm-sparc/mman.h linux-2.6.7-pax/include/asm-sparc/mman.h
--- linux-2.6.7/include/asm-sparc/mman.h	2004-06-16 07:20:04.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc/mman.h	2004-06-19 15:57:01.000000000 +0200
@@ -27,6 +27,10 @@
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
 #define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
 
+#ifdef CONFIG_PAX_RANDEXEC
+#define MAP_MIRROR	0x0400
+#endif
+
 #define MS_ASYNC	1		/* sync memory asynchronously */
 #define MS_INVALIDATE	2		/* invalidate the caches */
 #define MS_SYNC		4		/* synchronous memory sync */
diff -NurpX nopatch linux-2.6.7/include/asm-sparc/page.h linux-2.6.7-pax/include/asm-sparc/page.h
--- linux-2.6.7/include/asm-sparc/page.h	2004-06-16 07:19:02.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc/page.h	2004-06-19 15:57:01.000000000 +0200
@@ -176,6 +176,15 @@ extern unsigned long pfn_base;
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+#ifdef CONFIG_PAX_PAGEEXEC
+#ifdef CONFIG_PAX_MPROTECT
+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
+			 ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#else
+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#endif
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _SPARC_PAGE_H */
diff -NurpX nopatch linux-2.6.7/include/asm-sparc/pgtable.h linux-2.6.7-pax/include/asm-sparc/pgtable.h
--- linux-2.6.7/include/asm-sparc/pgtable.h	2004-06-16 07:19:36.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc/pgtable.h	2004-06-19 15:57:01.000000000 +0200
@@ -91,6 +91,13 @@ BTFIXUPDEF_INT(page_none)
 BTFIXUPDEF_INT(page_shared)
 BTFIXUPDEF_INT(page_copy)
 BTFIXUPDEF_INT(page_readonly)
+
+#ifdef CONFIG_PAX_PAGEEXEC
+BTFIXUPDEF_INT(page_shared_noexec)
+BTFIXUPDEF_INT(page_copy_noexec)
+BTFIXUPDEF_INT(page_readonly_noexec)
+#endif
+
 BTFIXUPDEF_INT(page_kernel)
 
 #define PMD_SHIFT		SUN4C_PMD_SHIFT
@@ -112,6 +119,16 @@ BTFIXUPDEF_INT(page_kernel)
 #define PAGE_COPY      __pgprot(BTFIXUP_INT(page_copy))
 #define PAGE_READONLY  __pgprot(BTFIXUP_INT(page_readonly))
 
+#ifdef CONFIG_PAX_PAGEEXEC
+# define PAGE_SHARED_NOEXEC	__pgprot(BTFIXUP_INT(page_shared_noexec))
+# define PAGE_COPY_NOEXEC	__pgprot(BTFIXUP_INT(page_copy_noexec))
+# define PAGE_READONLY_NOEXEC	__pgprot(BTFIXUP_INT(page_readonly_noexec))
+#else
+# define PAGE_SHARED_NOEXEC	PAGE_SHARED
+# define PAGE_COPY_NOEXEC	PAGE_COPY
+# define PAGE_READONLY_NOEXEC	PAGE_READONLY
+#endif
+
 extern unsigned long page_kernel;
 
 #ifdef MODULE
diff -NurpX nopatch linux-2.6.7/include/asm-sparc/pgtsrmmu.h linux-2.6.7-pax/include/asm-sparc/pgtsrmmu.h
--- linux-2.6.7/include/asm-sparc/pgtsrmmu.h	2004-06-16 07:19:10.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc/pgtsrmmu.h	2004-06-19 15:57:01.000000000 +0200
@@ -114,6 +114,16 @@
 				    SRMMU_EXEC | SRMMU_REF)
 #define SRMMU_PAGE_RDONLY  __pgprot(SRMMU_VALID | SRMMU_CACHE | \
 				    SRMMU_EXEC | SRMMU_REF)
+
+#ifdef CONFIG_PAX_PAGEEXEC
+#define SRMMU_PAGE_SHARED_NOEXEC  __pgprot(SRMMU_VALID | SRMMU_CACHE | \
+					   SRMMU_WRITE | SRMMU_REF)
+#define SRMMU_PAGE_COPY_NOEXEC    __pgprot(SRMMU_VALID | SRMMU_CACHE | \
+					   SRMMU_REF)
+#define SRMMU_PAGE_RDONLY_NOEXEC  __pgprot(SRMMU_VALID | SRMMU_CACHE | \
+					   SRMMU_REF)
+#endif
+
 #define SRMMU_PAGE_KERNEL  __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \
 				    SRMMU_DIRTY | SRMMU_REF)
 
diff -NurpX nopatch linux-2.6.7/include/asm-sparc/uaccess.h linux-2.6.7-pax/include/asm-sparc/uaccess.h
--- linux-2.6.7/include/asm-sparc/uaccess.h	2004-06-16 07:19:53.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc/uaccess.h	2004-06-19 15:57:01.000000000 +0200
@@ -41,7 +41,7 @@
  * No one can read/write anything from userland in the kernel space by setting
  * large size and address near to PAGE_OFFSET - a fault will break his intentions.
  */
-#define __user_ok(addr,size) ((addr) < STACK_TOP)
+#define __user_ok(addr,size) ((addr) < __STACK_TOP)
 #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
 #define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
 #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size))
diff -NurpX nopatch linux-2.6.7/include/asm-sparc64/a.out.h linux-2.6.7-pax/include/asm-sparc64/a.out.h
--- linux-2.6.7/include/asm-sparc64/a.out.h	2004-06-16 07:19:43.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc64/a.out.h	2004-06-19 15:57:01.000000000 +0200
@@ -95,7 +95,7 @@ struct relocation_info /* used when head
 
 #ifdef __KERNEL__
 
-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? 0xf0000000 : 0x80000000000L)
+#define __STACK_TOP (test_thread_flag(TIF_32BIT) ? 0xf0000000 : 0x80000000000L)
 
 #endif
 
diff -NurpX nopatch linux-2.6.7/include/asm-sparc64/elf.h linux-2.6.7-pax/include/asm-sparc64/elf.h
--- linux-2.6.7/include/asm-sparc64/elf.h	2004-06-16 07:19:10.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc64/elf.h	2004-06-19 15:57:01.000000000 +0200
@@ -140,6 +140,16 @@ typedef struct {
 #define ELF_ET_DYN_BASE         0x0000010000000000UL
 #endif
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	(test_thread_flag(TIF_32BIT) ? 0x10000UL : 0x100000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		(PAGE_SHIFT + 1)
+#define PAX_DELTA_MMAP_LEN(tsk)		(test_thread_flag(TIF_32BIT) ? 14 : 28 )
+#define PAX_DELTA_EXEC_LSB(tsk)		(PAGE_SHIFT + 1)
+#define PAX_DELTA_EXEC_LEN(tsk)		(test_thread_flag(TIF_32BIT) ? 14 : 28 )
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	(test_thread_flag(TIF_32BIT) ? 15 : 29 )
+#endif
 
 /* This yields a mask that user programs can use to figure out what
    instruction set this cpu supports.  */
diff -NurpX nopatch linux-2.6.7/include/asm-sparc64/mman.h linux-2.6.7-pax/include/asm-sparc64/mman.h
--- linux-2.6.7/include/asm-sparc64/mman.h	2004-06-16 07:19:23.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc64/mman.h	2004-06-19 15:57:01.000000000 +0200
@@ -27,6 +27,10 @@
 #define MAP_DENYWRITE	0x0800		/* ETXTBSY */
 #define MAP_EXECUTABLE	0x1000		/* mark it as an executable */
 
+#ifdef CONFIG_PAX_RANDEXEC
+#define MAP_MIRROR	0x0400
+#endif
+
 #define MS_ASYNC	1		/* sync memory asynchronously */
 #define MS_INVALIDATE	2		/* invalidate the caches */
 #define MS_SYNC		4		/* synchronous memory sync */
diff -NurpX nopatch linux-2.6.7/include/asm-sparc64/page.h linux-2.6.7-pax/include/asm-sparc64/page.h
--- linux-2.6.7/include/asm-sparc64/page.h	2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc64/page.h	2004-06-19 15:57:01.000000000 +0200
@@ -168,6 +168,15 @@ static __inline__ int get_order(unsigned
 #define VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
+#ifdef CONFIG_PAX_PAGEEXEC
+#ifdef CONFIG_PAX_MPROTECT
+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
+			  ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#else
+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#endif
+#endif
+
 #endif /* !(__KERNEL__) */
 
 #endif /* !(_SPARC64_PAGE_H) */
diff -NurpX nopatch linux-2.6.7/include/asm-sparc64/pgtable.h linux-2.6.7-pax/include/asm-sparc64/pgtable.h
--- linux-2.6.7/include/asm-sparc64/pgtable.h	2004-06-16 07:18:52.000000000 +0200
+++ linux-2.6.7-pax/include/asm-sparc64/pgtable.h	2004-06-20 14:42:59.000000000 +0200
@@ -128,7 +128,8 @@
 
 /* Here are the SpitFire software bits we use in the TTE's. */
 #define _PAGE_FILE	_AC(0x0000000000001000,UL)	/* Pagecache page     */
-#define _PAGE_MODIFIED	_AC(0x0000000000000800,UL)	/* Modified (dirty)   */
+#define _PAGE_MODIFIED	_AC(0x0000000000001000,UL)	/* Modified (dirty)   */
+#define _PAGE_EXEC	_AC(0x0000000000000800,UL)	/* Executable SW Bit  */
 #define _PAGE_ACCESSED	_AC(0x0000000000000400,UL)	/* Accessed (ref'd)   */
 #define _PAGE_READ	_AC(0x0000000000000200,UL)	/* Readable SW Bit    */
 #define _PAGE_WRITE	_AC(0x0000000000000100,UL)	/* Writable SW Bit    */
@@ -164,16 +165,30 @@
 
 /* Don't set the TTE _PAGE_W bit here, else the dirty bit never gets set. */
 #define PAGE_SHARED	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
-				  __ACCESS_BITS | _PAGE_WRITE)
+				  __ACCESS_BITS | _PAGE_WRITE | _PAGE_EXEC)
 
 #define PAGE_COPY	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
-				  __ACCESS_BITS)
+				  __ACCESS_BITS | _PAGE_EXEC)
 
 #define PAGE_READONLY	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
-				  __ACCESS_BITS)
+				  __ACCESS_BITS | _PAGE_EXEC)
 
 #define PAGE_KERNEL	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
-				  __PRIV_BITS | __ACCESS_BITS | __DIRTY_BITS)
+				  __PRIV_BITS | __ACCESS_BITS | __DIRTY_BITS | \
+				  _PAGE_EXEC)
+
+#ifdef CONFIG_PAX_PAGEEXEC
+# define PAGE_SHARED_NOEXEC	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
+					  __ACCESS_BITS | _PAGE_WRITE)
+# define PAGE_COPY_NOEXEC	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
+					  __ACCESS_BITS)
+# define PAGE_READONLY_NOEXEC	__pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
+					  __ACCESS_BITS)
+#else
+# define PAGE_SHARED_NOEXEC	PAGE_SHARED
+# define PAGE_COPY_NOEXEC	PAGE_COPY
+# define PAGE_READONLY_NOEXEC	PAGE_READONLY
+#endif
 
 #define _PFN_MASK	_PAGE_PADDR
 
@@ -181,18 +196,18 @@
 		   __ACCESS_BITS | _PAGE_E)
 
 #define __P000	PAGE_NONE
-#define __P001	PAGE_READONLY
-#define __P010	PAGE_COPY
-#define __P011	PAGE_COPY
+#define __P001	PAGE_READONLY_NOEXEC
+#define __P010	PAGE_COPY_NOEXEC
+#define __P011	PAGE_COPY_NOEXEC
 #define __P100	PAGE_READONLY
 #define __P101	PAGE_READONLY
 #define __P110	PAGE_COPY
 #define __P111	PAGE_COPY
 
 #define __S000	PAGE_NONE
-#define __S001	PAGE_READONLY
-#define __S010	PAGE_SHARED
-#define __S011	PAGE_SHARED
+#define __S001	PAGE_READONLY_NOEXEC
+#define __S010	PAGE_SHARED_NOEXEC
+#define __S011	PAGE_SHARED_NOEXEC
 #define __S100	PAGE_READONLY
 #define __S101	PAGE_READONLY
 #define __S110	PAGE_SHARED
diff -NurpX nopatch linux-2.6.7/include/asm-x86_64/a.out.h linux-2.6.7-pax/include/asm-x86_64/a.out.h
--- linux-2.6.7/include/asm-x86_64/a.out.h	2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7-pax/include/asm-x86_64/a.out.h	2004-06-19 15:57:01.000000000 +0200
@@ -21,7 +21,7 @@ struct exec
 
 #ifdef __KERNEL__
 #include <linux/thread_info.h>
-#define STACK_TOP (test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE)
+#define __STACK_TOP (test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE)
 #endif
 
 #endif /* __A_OUT_GNU_H__ */
diff -NurpX nopatch linux-2.6.7/include/asm-x86_64/elf.h linux-2.6.7-pax/include/asm-x86_64/elf.h
--- linux-2.6.7/include/asm-x86_64/elf.h	2004-06-16 07:19:52.000000000 +0200
+++ linux-2.6.7-pax/include/asm-x86_64/elf.h	2004-06-19 15:57:01.000000000 +0200
@@ -89,6 +89,17 @@ typedef struct user_i387_struct elf_fpre
 
 #define ELF_ET_DYN_BASE         (2 * TASK_SIZE / 3)
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	(test_thread_flag(TIF_IA32) ? 0x08048000UL : 0x400000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		(test_thread_flag(TIF_IA32) ? 16 : 24)
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		(test_thread_flag(TIF_IA32) ? 16 : 24)
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	(test_thread_flag(TIF_IA32) ? 16 : 24)
+#endif
+
 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
    now struct_user_regs, they are different). Assumes current is the process
    getting dumped. */
diff -NurpX nopatch linux-2.6.7/include/asm-x86_64/mman.h linux-2.6.7-pax/include/asm-x86_64/mman.h
--- linux-2.6.7/include/asm-x86_64/mman.h	2004-06-16 07:19:42.000000000 +0200
+++ linux-2.6.7-pax/include/asm-x86_64/mman.h	2004-06-19 15:57:01.000000000 +0200
@@ -24,6 +24,10 @@
 #define MAP_POPULATE	0x8000		/* populate (prefault) pagetables */
 #define MAP_NONBLOCK	0x10000		/* do not block on IO */
 
+#ifdef CONFIG_PAX_RANDEXEC
+#define MAP_MIRROR	0x8000
+#endif
+
 #define MS_ASYNC	1		/* sync memory asynchronously */
 #define MS_INVALIDATE	2		/* invalidate the caches */
 #define MS_SYNC		4		/* synchronous memory sync */
diff -NurpX nopatch linux-2.6.7/include/asm-x86_64/page.h linux-2.6.7-pax/include/asm-x86_64/page.h
--- linux-2.6.7/include/asm-x86_64/page.h	2004-06-16 07:18:56.000000000 +0200
+++ linux-2.6.7-pax/include/asm-x86_64/page.h	2004-06-19 15:57:01.000000000 +0200
@@ -132,6 +132,16 @@ extern __inline__ int get_order(unsigned
 
 #define __VM_DATA_DEFAULT_FLAGS	(VM_READ | VM_WRITE | VM_EXEC | \
 				 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#ifdef CONFIG_PAX_PAGEEXEC
+#define VM_DATA_DEFAULT_FLAGS __VM_DATA_DEFAULT_FLAGS
+#ifdef CONFIG_PAX_MPROTECT
+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
+			  ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#else
+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC))
+#endif
+#else
 #define __VM_STACK_FLAGS 	(VM_GROWSDOWN | VM_READ | VM_WRITE | VM_EXEC | \
                                 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
 
@@ -142,6 +152,8 @@ extern __inline__ int get_order(unsigned
 #define VM_STACK_DEFAULT_FLAGS \
 	(test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags) 
 	
+#endif
+
 #define CONFIG_ARCH_GATE_AREA 1	
 
 #ifndef __ASSEMBLY__
diff -NurpX nopatch linux-2.6.7/include/asm-x86_64/pgalloc.h linux-2.6.7-pax/include/asm-x86_64/pgalloc.h
--- linux-2.6.7/include/asm-x86_64/pgalloc.h	2004-06-16 07:19:29.000000000 +0200
+++ linux-2.6.7-pax/include/asm-x86_64/pgalloc.h	2004-06-19 15:57:01.000000000 +0200
@@ -8,7 +8,7 @@
 #include <linux/mm.h>
 
 #define pmd_populate_kernel(mm, pmd, pte) \
-		set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
+		set_pmd(pmd, __pmd(_KERNPG_TABLE | __pa(pte)))
 #define pgd_populate(mm, pgd, pmd) \
 		set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pmd)))
 
diff -NurpX nopatch linux-2.6.7/include/asm-x86_64/pgtable.h linux-2.6.7-pax/include/asm-x86_64/pgtable.h
--- linux-2.6.7/include/asm-x86_64/pgtable.h	2004-06-16 07:19:43.000000000 +0200
+++ linux-2.6.7-pax/include/asm-x86_64/pgtable.h	2004-06-19 15:57:01.000000000 +0200
@@ -170,6 +170,10 @@ static inline void set_pml4(pml4_t *dst,
 #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_READONLY	__pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
 #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+
+#define PAGE_READONLY_NOEXEC PAGE_READONLY
+#define PAGE_SHARED_NOEXEC PAGE_SHARED
+
 #define __PAGE_KERNEL \
 	(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
 #define __PAGE_KERNEL_EXECUTABLE \
diff -NurpX nopatch linux-2.6.7/include/linux/a.out.h linux-2.6.7-pax/include/linux/a.out.h
--- linux-2.6.7/include/linux/a.out.h	2004-06-16 07:19:37.000000000 +0200
+++ linux-2.6.7-pax/include/linux/a.out.h	2004-06-19 15:57:01.000000000 +0200
@@ -7,6 +7,16 @@
 
 #include <asm/a.out.h>
 
+#ifdef CONFIG_PAX_RANDUSTACK
+#define __DELTA_STACK (current->mm->delta_stack)
+#else
+#define __DELTA_STACK 0UL
+#endif
+
+#ifndef STACK_TOP
+#define STACK_TOP	(__STACK_TOP - __DELTA_STACK)
+#endif
+
 #endif /* __STRUCT_EXEC_OVERRIDE__ */
 
 /* these go in the N_MACHTYPE field */
@@ -37,6 +47,14 @@ enum machine_type {
   M_MIPS2 = 152		/* MIPS R6000/R4000 binary */
 };
 
+/* Constants for the N_FLAGS field */
+#define F_PAX_PAGEEXEC	1	/* Paging based non-executable pages */
+#define F_PAX_EMUTRAMP	2	/* Emulate trampolines */
+#define F_PAX_MPROTECT	4	/* Restrict mprotect() */
+#define F_PAX_RANDMMAP	8	/* Randomize mmap() base */
+#define F_PAX_RANDEXEC	16	/* Randomize ET_EXEC base */
+#define F_PAX_SEGMEXEC	32	/* Segmentation based non-executable pages */
+
 #if !defined (N_MAGIC)
 #define N_MAGIC(exec) ((exec).a_info & 0xffff)
 #endif
diff -NurpX nopatch linux-2.6.7/include/linux/binfmts.h linux-2.6.7-pax/include/linux/binfmts.h
--- linux-2.6.7/include/linux/binfmts.h	2004-06-16 07:19:26.000000000 +0200
+++ linux-2.6.7-pax/include/linux/binfmts.h	2004-06-19 15:57:01.000000000 +0200
@@ -36,6 +36,7 @@ struct linux_binprm{
 				   of the time same as filename, but could be
 				   different for binfmt_{misc,script} */
 	unsigned long loader, exec;
+	int misc;
 };
 
 /*
@@ -71,5 +72,8 @@ extern void compute_creds(struct linux_b
 extern int do_coredump(long signr, int exit_code, struct pt_regs * regs);
 extern int set_binfmt(struct linux_binfmt *new);
 
+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp);
+void pax_report_insns(void *pc, void *sp);
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_BINFMTS_H */
diff -NurpX nopatch linux-2.6.7/include/linux/elf.h linux-2.6.7-pax/include/linux/elf.h
--- linux-2.6.7/include/linux/elf.h	2004-06-16 07:18:59.000000000 +0200
+++ linux-2.6.7-pax/include/linux/elf.h	2004-06-20 18:04:07.000000000 +0200
@@ -37,6 +37,16 @@ typedef __s64	Elf64_Sxword;
 
 #define PT_GNU_STACK	(PT_LOOS + 0x474e551)
 
+#define PT_PAX_FLAGS	(PT_LOOS + 0x5041580)
+
+/* Constants for the e_flags field */
+#define EF_PAX_PAGEEXEC		1	/* Paging based non-executable pages */
+#define EF_PAX_EMUTRAMP		2	/* Emulate trampolines */
+#define EF_PAX_MPROTECT		4	/* Restrict mprotect() */
+#define EF_PAX_RANDMMAP		8	/* Randomize mmap() base */
+#define EF_PAX_RANDEXEC		16	/* Randomize ET_EXEC base */
+#define EF_PAX_SEGMEXEC		32	/* Segmentation based non-executable pages */
+
 /* These constants define the different elf file types */
 #define ET_NONE   0
 #define ET_REL    1
@@ -122,6 +132,8 @@ typedef __s64	Elf64_Sxword;
 #define DT_DEBUG	21
 #define DT_TEXTREL	22
 #define DT_JMPREL	23
+#define DT_FLAGS	30
+  #define DF_TEXTREL	0x00000004
 #define DT_LOPROC	0x70000000
 #define DT_HIPROC	0x7fffffff
 
@@ -272,6 +284,19 @@ typedef struct elf64_hdr {
 #define PF_W		0x2
 #define PF_X		0x1
 
+#define PF_PAGEEXEC	(1 << 4)	/* Enable  PAGEEXEC */
+#define PF_NOPAGEEXEC	(1 << 5)	/* Disable PAGEEXEC */
+#define PF_SEGMEXEC	(1 << 6)	/* Enable  SEGMEXEC */
+#define PF_NOSEGMEXEC	(1 << 7)	/* Disable SEGMEXEC */
+#define PF_MPROTECT	(1 << 8)	/* Enable  MPROTECT */
+#define PF_NOMPROTECT	(1 << 9)	/* Disable MPROTECT */
+#define PF_RANDEXEC	(1 << 10)	/* Enable  RANDEXEC */
+#define PF_NORANDEXEC	(1 << 11)	/* Disable RANDEXEC */
+#define PF_EMUTRAMP	(1 << 12)	/* Enable  EMUTRAMP */
+#define PF_NOEMUTRAMP	(1 << 13)	/* Disable EMUTRAMP */
+#define PF_RANDMMAP	(1 << 14)	/* Enable  RANDMMAP */
+#define PF_NORANDMMAP	(1 << 15)	/* Disable RANDMMAP */
+
 typedef struct elf32_phdr{
   Elf32_Word	p_type;
   Elf32_Off	p_offset;
@@ -364,6 +389,8 @@ typedef struct elf64_shdr {
 #define	EI_OSABI	7
 #define	EI_PAD		8
 
+#define	EI_PAX		14
+
 #define	ELFMAG0		0x7f		/* EI_MAG */
 #define	ELFMAG1		'E'
 #define	ELFMAG2		'L'
@@ -420,6 +447,7 @@ extern Elf32_Dyn _DYNAMIC [];
 #define elfhdr		elf32_hdr
 #define elf_phdr	elf32_phdr
 #define elf_note	elf32_note
+#define elf_dyn		Elf32_Dyn
 
 #else
 
@@ -427,6 +455,7 @@ extern Elf64_Dyn _DYNAMIC [];
 #define elfhdr		elf64_hdr
 #define elf_phdr	elf64_phdr
 #define elf_note	elf64_note
+#define elf_dyn		Elf64_Dyn
 
 #endif
 
diff -NurpX nopatch linux-2.6.7/include/linux/mm.h linux-2.6.7-pax/include/linux/mm.h
--- linux-2.6.7/include/linux/mm.h	2004-06-16 07:18:56.000000000 +0200
+++ linux-2.6.7-pax/include/linux/mm.h	2004-06-20 15:26:37.000000000 +0200
@@ -29,6 +29,7 @@ extern int page_cluster;
 #include <asm/pgtable.h>
 #include <asm/processor.h>
 #include <asm/atomic.h>
+#include <asm/mman.h>
 
 #ifndef MM_VM_SIZE
 #define MM_VM_SIZE(mm)	TASK_SIZE
@@ -100,6 +101,11 @@ struct vm_area_struct {
 #ifdef CONFIG_NUMA
 	struct mempolicy *vm_policy;	/* NUMA policy for the VMA */
 #endif
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	unsigned long vm_mirror;	/* PaX: mirror distance */
+#endif
+
 };
 
 /*
@@ -135,6 +141,18 @@ struct vm_area_struct {
 #define VM_HUGETLB	0x00400000	/* Huge TLB Page VM */
 #define VM_NONLINEAR	0x00800000	/* Is non-linear (remap_file_pages) */
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+#define VM_MIRROR	0x01000000	/* vma is mirroring another */
+#endif
+
+#ifdef CONFIG_PAX_MPROTECT
+#define VM_MAYNOTWRITE	0x02000000	/* vma cannot be granted VM_WRITE any more */
+#endif
+
+#ifdef __VM_STACK_FLAGS
+#define VM_STACK_DEFAULT_FLAGS (0x00000033 | __VM_STACK_FLAGS)
+#endif
+
 #ifndef VM_STACK_DEFAULT_FLAGS		/* arch can override this */
 #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
 #endif
@@ -636,6 +654,10 @@ extern unsigned long do_mmap_pgoff(struc
 	unsigned long len, unsigned long prot,
 	unsigned long flag, unsigned long pgoff);
 
+extern unsigned long __do_mmap_pgoff(struct file *file, unsigned long addr,
+	unsigned long len, unsigned long prot,
+	unsigned long flag, unsigned long pgoff);
+
 static inline unsigned long do_mmap(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot,
 	unsigned long flag, unsigned long offset)
@@ -725,5 +747,11 @@ extern struct vm_area_struct *get_gate_v
 int in_gate_area(struct task_struct *task, unsigned long addr);
 #endif
 
+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
+extern void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot);
+#else
+static inline void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot) {}
+#endif
+
 #endif /* __KERNEL__ */
 #endif /* _LINUX_MM_H */
diff -NurpX nopatch linux-2.6.7/include/linux/mman.h linux-2.6.7-pax/include/linux/mman.h
--- linux-2.6.7/include/linux/mman.h	2004-06-16 07:18:58.000000000 +0200
+++ linux-2.6.7-pax/include/linux/mman.h	2004-06-19 15:57:02.000000000 +0200
@@ -56,6 +56,11 @@ static inline unsigned long
 calc_vm_flag_bits(unsigned long flags)
 {
 	return _calc_vm_trans(flags, MAP_GROWSDOWN,  VM_GROWSDOWN ) |
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	       _calc_vm_trans(flags, MAP_MIRROR, VM_MIRROR) |
+#endif
+
 	       _calc_vm_trans(flags, MAP_DENYWRITE,  VM_DENYWRITE ) |
 	       _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) |
 	       _calc_vm_trans(flags, MAP_LOCKED,     VM_LOCKED    );
diff -NurpX nopatch linux-2.6.7/include/linux/random.h linux-2.6.7-pax/include/linux/random.h
--- linux-2.6.7/include/linux/random.h	2004-06-16 07:20:26.000000000 +0200
+++ linux-2.6.7-pax/include/linux/random.h	2004-06-19 15:57:02.000000000 +0200
@@ -69,6 +69,8 @@ extern __u32 secure_tcpv6_sequence_numbe
 
 extern __u32 secure_ipv6_id(__u32 *daddr);
 
+extern unsigned long pax_get_random_long(void);
+
 #ifndef MODULE
 extern struct file_operations random_fops, urandom_fops;
 #endif
diff -NurpX nopatch linux-2.6.7/include/linux/sched.h linux-2.6.7-pax/include/linux/sched.h
--- linux-2.6.7/include/linux/sched.h	2004-06-16 07:18:57.000000000 +0200
+++ linux-2.6.7-pax/include/linux/sched.h	2004-06-19 15:57:02.000000000 +0200
@@ -31,6 +31,7 @@
 #include <linux/percpu.h>
 
 struct exec_domain;
+struct linux_binprm;
 
 /*
  * cloning flags:
@@ -234,6 +235,21 @@ struct mm_struct {
 	struct kioctx		*ioctx_list;
 
 	struct kioctx		default_kioctx;
+
+#ifdef CONFIG_PAX_DLRESOLVE
+	unsigned long call_dl_resolve;
+#endif
+
+#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
+	unsigned long call_syscall;
+#endif
+
+#ifdef CONFIG_PAX_ASLR
+	unsigned long delta_mmap;		/* randomized offset */
+	unsigned long delta_exec;		/* randomized offset */
+	unsigned long delta_stack;		/* randomized offset */
+#endif
+
 };
 
 extern int mmlist_nr;
@@ -550,6 +566,29 @@ do { if (atomic_dec_and_test(&(tsk)->usa
 #define PF_LESS_THROTTLE 0x00100000	/* Throttle me less: I clean memory */
 #define PF_SYNCWRITE	0x00200000	/* I am doing a sync write */
 
+#define PF_PAX_PAGEEXEC		0x01000000	/* Paging based non-executable pages */
+#define PF_PAX_EMUTRAMP		0x02000000	/* Emulate trampolines */
+#define PF_PAX_MPROTECT		0x04000000	/* Restrict mprotect() */
+#define PF_PAX_RANDMMAP		0x08000000	/* Randomize mmap() base */
+#define PF_PAX_RANDEXEC		0x10000000	/* Randomize ET_EXEC base */
+#define PF_PAX_SEGMEXEC		0x20000000	/* Segmentation based non-executable pages */
+
+#ifdef CONFIG_PAX_SOFTMODE
+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) || defined(CONFIG_PAX_RANDKSTACK)
+extern unsigned int pax_aslr;
+#endif
+
+extern unsigned int pax_softmode;
+#endif
+
+extern int pax_check_flags(unsigned long *);
+
+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
+extern void pax_set_flags(struct linux_binprm * bprm);
+#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
+extern void (*pax_set_flags_func)(struct linux_binprm * bprm);
+#endif
+
 #ifdef CONFIG_SMP
 #define SCHED_LOAD_SCALE	128UL	/* increase resolution of load */
 
diff -NurpX nopatch linux-2.6.7/include/linux/sysctl.h linux-2.6.7-pax/include/linux/sysctl.h
--- linux-2.6.7/include/linux/sysctl.h	2004-06-16 07:19:35.000000000 +0200
+++ linux-2.6.7-pax/include/linux/sysctl.h	2004-06-19 15:57:02.000000000 +0200
@@ -133,8 +133,19 @@ enum
 	KERN_NGROUPS_MAX=63,	/* int: NGROUPS_MAX */
 	KERN_SPARC_SCONS_PWROFF=64, /* int: serial console power-off halt */
 	KERN_HZ_TIMER=65,	/* int: hz timer on or off */
+
+#ifdef CONFIG_PAX_SOFTMODE
+	KERN_PAX=69,		/* PaX control */
+#endif
+
 };
 
+#ifdef CONFIG_PAX_SOFTMODE
+enum {
+	PAX_ASLR=1,		/* PaX: disable/enable all randomization features */
+	PAX_SOFTMODE=2		/* PaX: disable/enable soft mode */
+};
+#endif
 
 /* CTL_VM names: */
 enum
diff -NurpX nopatch linux-2.6.7/kernel/fork.c linux-2.6.7-pax/kernel/fork.c
--- linux-2.6.7/kernel/fork.c	2004-06-16 07:18:57.000000000 +0200
+++ linux-2.6.7-pax/kernel/fork.c	2004-06-19 15:57:02.000000000 +0200
@@ -279,7 +279,7 @@ static inline int dup_mmap(struct mm_str
 	mm->locked_vm = 0;
 	mm->mmap = NULL;
 	mm->mmap_cache = NULL;
-	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	mm->free_area_cache = oldmm->free_area_cache;
 	mm->map_count = 0;
 	mm->rss = 0;
 	cpus_clear(mm->cpu_vm_mask);
diff -NurpX nopatch linux-2.6.7/kernel/sysctl.c linux-2.6.7-pax/kernel/sysctl.c
--- linux-2.6.7/kernel/sysctl.c	2004-06-16 07:18:58.000000000 +0200
+++ linux-2.6.7-pax/kernel/sysctl.c	2004-06-19 15:57:02.000000000 +0200
@@ -143,6 +143,31 @@ extern ctl_table random_table[];
 extern ctl_table pty_table[];
 #endif
 
+#ifdef CONFIG_PAX_SOFTMODE
+static ctl_table pax_table[] = {
+
+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) || defined(CONFIG_PAX_RANDKSTACK)
+	{
+		.ctl_name	= PAX_ASLR,
+		.procname	= "aslr",
+		.data		= &pax_aslr,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0600,
+		.proc_handler	= &proc_dointvec,
+	},
+#endif
+
+	{
+		.ctl_name	= PAX_SOFTMODE,
+		.procname	= "softmode",
+		.data		= &pax_softmode,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0600,
+		.proc_handler	= &proc_dointvec,
+	}
+};
+#endif
+
 /* /proc declarations: */
 
 #ifdef CONFIG_PROC_FS
@@ -636,6 +661,16 @@ static ctl_table kern_table[] = {
 		.mode		= 0444,
 		.proc_handler	= &proc_dointvec,
 	},
+
+#ifdef CONFIG_PAX_SOFTMODE
+	{
+		.ctl_name	= KERN_PAX,
+		.procname	= "pax",
+		.mode		= 0500,
+		.child		= pax_table,
+	},
+#endif
+
 	{ .ctl_name = 0 }
 };
 
diff -NurpX nopatch linux-2.6.7/mm/filemap.c linux-2.6.7-pax/mm/filemap.c
--- linux-2.6.7/mm/filemap.c	2004-06-16 07:19:12.000000000 +0200
+++ linux-2.6.7-pax/mm/filemap.c	2004-06-19 15:57:02.000000000 +0200
@@ -1423,6 +1423,12 @@ int generic_file_mmap(struct file * file
 
 	if (!mapping->a_ops->readpage)
 		return -ENOEXEC;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (current->flags & PF_PAX_PAGEEXEC)
+		vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
+#endif
+
 	file_accessed(file);
 	vma->vm_ops = &generic_file_vm_ops;
 	return 0;
diff -NurpX nopatch linux-2.6.7/mm/madvise.c linux-2.6.7-pax/mm/madvise.c
--- linux-2.6.7/mm/madvise.c	2004-06-16 07:19:02.000000000 +0200
+++ linux-2.6.7-pax/mm/madvise.c	2004-06-20 18:36:57.000000000 +0200
@@ -13,8 +13,42 @@
  * We can potentially split a vm area into separate
  * areas, each area with its own behavior.
  */
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+static long __madvise_behavior(struct vm_area_struct * vma, unsigned long start,
+			     unsigned long end, int behavior);
+
+static long madvise_behavior(struct vm_area_struct * vma, unsigned long start,
+			     unsigned long end, int behavior)
+{
+	if (vma->vm_flags & VM_MIRROR) {
+		struct vm_area_struct * vma_m, * prev_m;
+		unsigned long start_m, end_m;
+		int error;
+
+		start_m = vma->vm_start + vma->vm_mirror;
+		vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m);
+		if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
+			start_m = start + vma->vm_mirror;
+			end_m = end + vma->vm_mirror;
+			error = __madvise_behavior(vma_m, start_m, end_m, behavior);
+			if (error)
+				return error;
+		} else {
+			printk("PAX: VMMIRROR: madvise bug in %s, %08lx\n", current->comm, vma->vm_start);
+			return -ENOMEM;
+		}
+	}
+
+	return __madvise_behavior(vma, start, end, behavior);
+}
+
+static long __madvise_behavior(struct vm_area_struct * vma, unsigned long start,
+			     unsigned long end, int behavior)
+#else
 static long madvise_behavior(struct vm_area_struct * vma, unsigned long start,
 			     unsigned long end, int behavior)
+#endif
 {
 	struct mm_struct * mm = vma->vm_mm;
 	int error;
diff -NurpX nopatch linux-2.6.7/mm/memory.c linux-2.6.7-pax/mm/memory.c
--- linux-2.6.7/mm/memory.c	2004-06-16 07:19:22.000000000 +0200
+++ linux-2.6.7-pax/mm/memory.c	2004-07-01 22:46:00.000000000 +0200
@@ -1004,6 +1004,81 @@ static inline void break_cow(struct vm_a
 	update_mmu_cache(vma, address, entry);
 }
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+/* PaX: if vma is mirrored, synchronize the mirror's PTE
+ *
+ * mm->page_table_lock is held on entry and is not released on exit or inside
+ * to ensure atomic changes to the PTE states (swapout, mremap, munmap, etc)
+ */
+static void pax_mirror_fault(struct mm_struct *mm, struct vm_area_struct * vma,
+	unsigned long address, pte_t *pte)
+{
+	unsigned long address_m;
+	struct vm_area_struct * vma_m = NULL;
+	pte_t * pte_m, entry_m;
+	struct page * page_m;
+
+	address_m = vma->vm_start + vma->vm_mirror;
+	vma_m = find_vma(mm, address_m);
+	BUG_ON(!vma_m || vma_m->vm_start != address_m);
+
+	address_m = address + vma->vm_mirror;
+
+	{
+		pgd_t *pgd_m;
+		pmd_t *pmd_m;
+
+		pgd_m = pgd_offset(mm, address_m);
+		pmd_m = pmd_offset(pgd_m, address_m);
+		pte_m = pte_offset_map_nested(pmd_m, address_m);
+	}
+
+	if (pte_present(*pte_m)) {
+		flush_cache_page(vma_m, address_m);
+		flush_icache_page(vma_m, pte_page(*pte_m));
+	}
+	entry_m = ptep_get_and_clear(pte_m);
+	if (pte_present(entry_m))
+		flush_tlb_page(vma_m, address_m);
+
+	if (pte_none(entry_m)) {
+		++mm->rss;
+	} else if (pte_present(entry_m)) {
+		page_m = pte_page(entry_m);
+		if (PageReserved(page_m))
+			++mm->rss;
+		else
+			page_remove_rmap(page_m);
+		page_cache_release(page_m);
+	} else if (!pte_file(entry_m)) {
+		free_swap_and_cache(pte_to_swp_entry(entry_m));
+		++mm->rss;
+	} else {
+		printk(KERN_ERR "PAX: VMMIRROR: bug in mirror_fault: %08lx, %08lx, %08lx, %08lx\n",
+				address, vma->vm_start, address_m, vma_m->vm_start);
+	}
+
+	page_m = pte_page(*pte);
+	entry_m = mk_pte(page_m, vma_m->vm_page_prot);
+	if (pte_write(*pte) && (vma_m->vm_flags & VM_WRITE))
+		entry_m = pte_mkdirty(pte_mkwrite(entry_m));
+	if (!PageReserved(page_m)) {
+		page_cache_get(page_m);
+		/*
+		 * we can test PG_anon without holding page_map_lock because
+		 * we hold the page table lock and have a reference to page_m
+		 */
+		if (PageAnon(page_m))
+			page_add_anon_rmap(page_m, vma_m, address_m);
+		else
+			page_add_file_rmap(page_m);
+	}
+	ptep_establish(vma_m, address_m, pte_m, entry_m);
+	update_mmu_cache(vma_m, address_m, entry_m);
+	pte_unmap_nested(pte_m);
+}
+#endif
+
 /*
  * This routine handles present pages, when users try to write
  * to a shared page. It is done by copying the page to a new address
@@ -1090,6 +1165,12 @@ static int do_wp_page(struct mm_struct *
 
 		/* Free the old page.. */
 		new_page = old_page;
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+		if (vma->vm_flags & VM_MIRROR)
+			pax_mirror_fault(mm, vma, address, page_table);
+#endif
+
 	}
 	pte_unmap(page_table);
 	page_cache_release(new_page);
@@ -1375,6 +1456,12 @@ static int do_swap_page(struct mm_struct
 
 	/* No need to invalidate - it was non-present before */
 	update_mmu_cache(vma, address, pte);
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if (vma->vm_flags & VM_MIRROR)
+		pax_mirror_fault(mm, vma, address, page_table);
+#endif
+
 	pte_unmap(page_table);
 	spin_unlock(&mm->page_table_lock);
 out:
@@ -1429,10 +1516,16 @@ do_anonymous_page(struct mm_struct *mm, 
 	}
 
 	set_pte(page_table, entry);
-	pte_unmap(page_table);
 
 	/* No need to invalidate - it was non-present before */
 	update_mmu_cache(vma, addr, entry);
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if (vma->vm_flags & VM_MIRROR)
+		pax_mirror_fault(mm, vma, addr, page_table);
+#endif
+
+	pte_unmap(page_table);
 	spin_unlock(&mm->page_table_lock);
 out:
 	return VM_FAULT_MINOR;
@@ -1539,6 +1632,15 @@ retry:
 			page_add_anon_rmap(new_page, vma, address);
 		} else
 			page_add_file_rmap(new_page);
+
+		/* no need to invalidate: a not-present page shouldn't be cached */
+		update_mmu_cache(vma, address, entry);
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+		if (vma->vm_flags & VM_MIRROR)
+			pax_mirror_fault(mm, vma, address, page_table);
+#endif
+
 		pte_unmap(page_table);
 	} else {
 		/* One of our sibling threads was faster, back out. */
@@ -1548,8 +1650,6 @@ retry:
 		goto out;
 	}
 
-	/* no need to invalidate: a not-present page shouldn't be cached */
-	update_mmu_cache(vma, address, entry);
 	spin_unlock(&mm->page_table_lock);
 out:
 	return ret;
@@ -1658,6 +1758,11 @@ int handle_mm_fault(struct mm_struct *mm
 	pgd_t *pgd;
 	pmd_t *pmd;
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	unsigned long address_m = 0UL;
+	struct vm_area_struct * vma_m = NULL;
+#endif
+
 	__set_current_state(TASK_RUNNING);
 	pgd = pgd_offset(mm, address);
 
@@ -1671,6 +1776,45 @@ int handle_mm_fault(struct mm_struct *mm
 	 * and the SMP-safe atomic PTE updates.
 	 */
 	spin_lock(&mm->page_table_lock);
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if (vma->vm_flags & VM_MIRROR) {
+		pgd_t *pgd_m;
+		pmd_t *pmd_m;
+		pte_t *pte_m;
+
+		address_m = vma->vm_start + vma->vm_mirror;
+		vma_m = find_vma(mm, address_m);
+
+		/* PaX: sanity checks */
+		if (!vma_m) {
+			spin_unlock(&mm->page_table_lock);
+			printk(KERN_ERR "PAX: VMMIRROR: fault bug, %08lx, %p, %08lx, %p\n",
+			       address, vma, address_m, vma_m);
+			return VM_FAULT_SIGBUS;
+		} else if (!(vma_m->vm_flags & VM_MIRROR) ||
+			   vma_m->vm_start != address_m ||
+			   vma->vm_end - vma->vm_start != vma_m->vm_end - vma_m->vm_start)
+		{
+			spin_unlock(&mm->page_table_lock);
+			printk(KERN_ERR "PAX: VMMIRROR: fault bug2, %08lx, %08lx, %08lx, %08lx, %08lx\n",
+			       address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
+			return VM_FAULT_SIGBUS;
+		}
+
+		address_m = address + vma->vm_mirror;
+		pgd_m = pgd_offset(mm, address_m);
+		pmd_m = pmd_alloc(mm, pgd_m, address_m);
+		if (pmd_m)
+			pte_m = pte_alloc_map(mm, pmd_m, address_m);
+		if (!pmd_m || !pte_m) {
+			spin_unlock(&mm->page_table_lock);
+			return VM_FAULT_OOM;
+		}
+		pte_unmap(pte_m);
+	}
+#endif
+
 	pmd = pmd_alloc(mm, pgd, address);
 
 	if (pmd) {
diff -NurpX nopatch linux-2.6.7/mm/mlock.c linux-2.6.7-pax/mm/mlock.c
--- linux-2.6.7/mm/mlock.c	2004-06-16 07:18:57.000000000 +0200
+++ linux-2.6.7-pax/mm/mlock.c	2004-06-20 18:37:24.000000000 +0200
@@ -9,8 +9,40 @@
 #include <linux/mm.h>
 
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+static int __mlock_fixup(struct vm_area_struct * vma, 
+	unsigned long start, unsigned long end, unsigned int newflags);
+
+static int mlock_fixup(struct vm_area_struct * vma, 
+	unsigned long start, unsigned long end, unsigned int newflags)
+{
+	if (vma->vm_flags & VM_MIRROR) {
+		struct vm_area_struct * vma_m;
+		unsigned long start_m, end_m;
+		int error;
+
+		start_m = vma->vm_start + vma->vm_mirror;
+		vma_m = find_vma(vma->vm_mm, start_m);
+		if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
+			start_m = start + vma->vm_mirror;
+			end_m = end + vma->vm_mirror;
+			error = __mlock_fixup(vma_m, start_m, end_m, newflags);
+			if (error)
+				return error;
+		} else {
+			printk("PAX: VMMIRROR: mlock bug in %s, %08lx\n", current->comm, vma->vm_start);
+			return -ENOMEM;
+		}
+	}
+	return __mlock_fixup(vma, start, end, newflags);
+}
+
+static int __mlock_fixup(struct vm_area_struct * vma, 
+	unsigned long start, unsigned long end, unsigned int newflags)
+#else
 static int mlock_fixup(struct vm_area_struct * vma, 
 	unsigned long start, unsigned long end, unsigned int newflags)
+#endif
 {
 	struct mm_struct * mm = vma->vm_mm;
 	int pages;
@@ -68,6 +100,17 @@ static int do_mlock(unsigned long start,
 		return -EINVAL;
 	if (end == start)
 		return 0;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->flags & PF_PAX_SEGMEXEC) {
+		if (end > SEGMEXEC_TASK_SIZE)
+			return -EINVAL;
+	} else
+#endif
+
+	if (end > TASK_SIZE)
+		return -EINVAL;
+
 	vma = find_vma(current->mm, start);
 	if (!vma || vma->vm_start > start)
 		return -ENOMEM;
@@ -154,6 +197,16 @@ static int do_mlockall(int flags)
 	for (vma = current->mm->mmap; vma ; vma = vma->vm_next) {
 		unsigned int newflags;
 
+#ifdef CONFIG_PAX_SEGMEXEC
+		if (current->flags & PF_PAX_SEGMEXEC) {
+			if (vma->vm_end > SEGMEXEC_TASK_SIZE)
+				break;
+		} else
+#endif
+
+		if (vma->vm_end > TASK_SIZE)
+			break;
+
 		newflags = vma->vm_flags | VM_LOCKED;
 		if (!(flags & MCL_CURRENT))
 			newflags &= ~VM_LOCKED;
diff -NurpX nopatch linux-2.6.7/mm/mmap.c linux-2.6.7-pax/mm/mmap.c
--- linux-2.6.7/mm/mmap.c	2004-06-16 07:19:37.000000000 +0200
+++ linux-2.6.7-pax/mm/mmap.c	2004-06-21 12:20:56.000000000 +0200
@@ -495,7 +495,11 @@ again:			remove_next = 1 + (end > next->
  * If the vma has a ->close operation then the driver probably needs to release
  * per-vma resources, so we don't attempt to merge those.
  */
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+#define VM_SPECIAL (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_MIRROR)
+#else
 #define VM_SPECIAL (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED)
+#endif
 
 static inline int is_mergeable_vma(struct vm_area_struct *vma,
 			struct file *file, unsigned long vm_flags)
@@ -729,6 +733,42 @@ unsigned long do_mmap_pgoff(struct file 
 			unsigned long len, unsigned long prot,
 			unsigned long flags, unsigned long pgoff)
 {
+	unsigned long ret = -EINVAL;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if ((current->flags & PF_PAX_SEGMEXEC) &&
+	    (len > SEGMEXEC_TASK_SIZE || (addr && addr > SEGMEXEC_TASK_SIZE-len)))
+		return ret;
+#endif
+
+	ret = __do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if ((current->flags & PF_PAX_SEGMEXEC) && ret < TASK_SIZE && ((flags & MAP_TYPE) == MAP_PRIVATE)
+
+#ifdef CONFIG_PAX_MPROTECT
+	    && (!(current->flags & PF_PAX_MPROTECT) || ((prot & PROT_EXEC) && file && !(prot & PROT_WRITE)))
+#endif
+
+	   )
+	{
+		unsigned long ret_m;
+		prot = prot & PROT_EXEC ? prot : PROT_NONE;
+		ret_m = __do_mmap_pgoff(NULL, ret + SEGMEXEC_TASK_SIZE, 0UL, prot, flags | MAP_MIRROR | MAP_FIXED, ret);
+		if (ret_m >= TASK_SIZE) {
+			do_munmap(current->mm, ret, len);
+			ret = ret_m;
+		}
+	}
+#endif
+
+	return ret;
+}
+
+unsigned long __do_mmap_pgoff(struct file * file, unsigned long addr,
+			unsigned long len, unsigned long prot,
+			unsigned long flags, unsigned long pgoff)
+{
 	struct mm_struct * mm = current->mm;
 	struct vm_area_struct * vma, * prev;
 	struct inode *inode;
@@ -739,6 +779,28 @@ unsigned long do_mmap_pgoff(struct file 
 	int accountable = 1;
 	unsigned long charged = 0;
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	struct vm_area_struct * vma_m = NULL;
+
+	if (flags & MAP_MIRROR) {
+		/* PaX: sanity checks, to be removed when proved to be stable */
+		if (file || len || ((flags & MAP_TYPE) != MAP_PRIVATE))
+			return -EINVAL;
+
+		vma_m = find_vma(mm, pgoff);
+
+		if (!vma_m || is_vm_hugetlb_page(vma_m) ||
+		    vma_m->vm_start != pgoff ||
+		    (vma_m->vm_flags & VM_MIRROR) ||
+		    (!(vma_m->vm_flags & VM_WRITE) && (prot & PROT_WRITE)))
+			return -EINVAL;
+
+		file = vma_m->vm_file;
+		pgoff = vma_m->vm_pgoff;
+		len = vma_m->vm_end - vma_m->vm_start;
+	}
+#endif
+
 	if (file) {
 		if (is_file_hugepages(file))
 			accountable = 0;
@@ -770,7 +832,7 @@ unsigned long do_mmap_pgoff(struct file 
 	/* Obtain the address to map to. we verify (or select) it and ensure
 	 * that it represents a valid section of the address space.
 	 */
-	addr = get_unmapped_area(file, addr, len, pgoff, flags);
+	addr = get_unmapped_area(file, addr, len, pgoff, flags | ((prot & PROT_EXEC) ? MAP_EXECUTABLE : 0));
 	if (addr & ~PAGE_MASK)
 		return addr;
 
@@ -781,6 +843,30 @@ unsigned long do_mmap_pgoff(struct file 
 	vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) |
 			mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
 
+	if (file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
+		vm_flags &= ~VM_MAYEXEC;
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+	if (current->flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) {
+
+#ifdef CONFIG_PAX_MPROTECT
+		if (current->flags & PF_PAX_MPROTECT) {
+			if (!file || (prot & PROT_WRITE))
+				vm_flags &= ~(VM_EXEC | VM_MAYEXEC);
+			else
+				vm_flags &= ~VM_MAYWRITE;
+
+#ifdef CONFIG_PAX_RANDEXEC
+			if (file && (flags & MAP_MIRROR) && (vm_flags & VM_EXEC))
+				vma_m->vm_flags &= ~VM_MAYWRITE;
+#endif
+
+		}
+#endif
+
+	}
+#endif
+
 	if (flags & MAP_LOCKED) {
 		if (!capable(CAP_IPC_LOCK))
 			return -EPERM;
@@ -837,6 +923,11 @@ unsigned long do_mmap_pgoff(struct file 
 			/*
 			 * Set pgoff according to addr for anon_vma.
 			 */
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+			if (!(flags & MAP_MIRROR))
+#endif
+
 			pgoff = addr >> PAGE_SHIFT;
 			break;
 		default:
@@ -905,6 +996,13 @@ munmap_back:
 	vma->vm_start = addr;
 	vma->vm_end = addr + len;
 	vma->vm_flags = vm_flags;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	if ((file || !(current->flags & PF_PAX_PAGEEXEC)) && (vm_flags & (VM_READ|VM_WRITE)))
+		vma->vm_page_prot = protection_map[(vm_flags | VM_EXEC) & 0x0f];
+	else
+#endif
+
 	vma->vm_page_prot = protection_map[vm_flags & 0x0f];
 	vma->vm_pgoff = pgoff;
 
@@ -929,6 +1027,14 @@ munmap_back:
 			goto free_vma;
 	}
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if (flags & MAP_MIRROR) {
+		vma_m->vm_flags |= VM_MIRROR;
+		vma_m->vm_mirror = vma->vm_start - vma_m->vm_start;
+		vma->vm_mirror = vma_m->vm_start - vma->vm_start;
+	}
+#endif
+
 	/* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform
 	 * shmem_zero_setup (perhaps called through /dev/zero's ->mmap)
 	 * that memory reservation must be checked; but that reservation
@@ -970,6 +1076,7 @@ out:	
 					pgoff, flags & MAP_NONBLOCK);
 		down_write(&mm->mmap_sem);
 	}
+	track_exec_limit(mm, addr, addr + len, vm_flags);
 	return addr;
 
 unmap_and_free_vma:
@@ -989,6 +1096,7 @@ unacct_error:
 }
 
 EXPORT_SYMBOL(do_mmap_pgoff);
+EXPORT_SYMBOL(__do_mmap_pgoff);
 
 /* Get an address range which is currently unmapped.
  * For shmat() with addr=0.
@@ -1008,11 +1116,17 @@ arch_get_unmapped_area(struct file *filp
 {
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
-	unsigned long start_addr;
+	unsigned long start_addr, task_unmapped_base = TASK_UNMAPPED_BASE;
 
 	if (len > TASK_SIZE)
 		return -ENOMEM;
 
+#ifdef CONFIG_PAX_RANDMMAP
+	if (current->flags & PF_PAX_RANDMMAP)
+		task_unmapped_base += mm->delta_mmap;
+	if (!(current->flags & PF_PAX_RANDMMAP) || !filp)
+#endif
+
 	if (addr) {
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma(mm, addr);
@@ -1030,8 +1144,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 != task_unmapped_base) {
+				start_addr = addr = task_unmapped_base;
 				goto full_search;
 			}
 			return -ENOMEM;
@@ -1172,6 +1286,11 @@ int expand_stack(struct vm_area_struct *
 {
 	unsigned long grow;
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	struct vm_area_struct * vma_m = NULL;
+	unsigned long address_m = 0UL;
+#endif
+
 	if (!(vma->vm_flags & VM_GROWSUP))
 		return -EFAULT;
 
@@ -1197,10 +1316,42 @@ int expand_stack(struct vm_area_struct *
 		anon_vma_unlock(vma);
 		return -ENOMEM;
 	}
-	
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if (vma->vm_flags & VM_MIRROR) {
+		address_m = vma->vm_start + vma->vm_mirror;
+		vma_m = find_vma(vma->vm_mm, address_m);
+		if (!vma_m || vma_m->vm_start != address_m ||
+				!(vma_m->vm_flags & VM_MIRROR) ||
+				vma->vm_end - vma->vm_start !=
+				vma_m->vm_end - vma_m->vm_start) {
+			anon_vma_unlock(vma);
+			vm_unacct_memory(grow);
+			printk(KERN_ERR "PAX: VMMIRROR: expand bug, %08lx, %08lx, %08lx, %08lx, %08lx\n",
+			       address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
+			return -ENOMEM;
+		}
+
+		address_m = address + vma->vm_mirror;
+		if (address_m - vma_m->vm_start > current->rlim[RLIMIT_STACK].rlim_cur ||
+				((vma_m->vm_mm->total_vm + 2*grow) << PAGE_SHIFT) >
+				current->rlim[RLIMIT_AS].rlim_cur ||
+				((vma_m->vm_flags & VM_LOCKED) &&
+				((vma_m->vm_mm->locked_vm + 2*grow) << PAGE_SHIFT) >
+				current->rlim[RLIMIT_MEMLOCK].rlim_cur)) {
+			anon_vma_unlock(vma);
+			vm_unacct_memory(grow);
+			return -ENOMEM;
+		}
+	} else
+#endif
+
 	if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur ||
 			((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
-			current->rlim[RLIMIT_AS].rlim_cur) {
+			current->rlim[RLIMIT_AS].rlim_cur ||
+			((vma->vm_flags & VM_LOCKED) &&
+			((vma->vm_mm->locked_vm + grow) << PAGE_SHIFT) >
+			current->rlim[RLIMIT_MEMLOCK].rlim_cur)) {
 		anon_vma_unlock(vma);
 		vm_unacct_memory(grow);
 		return -ENOMEM;
@@ -1209,6 +1360,18 @@ int expand_stack(struct vm_area_struct *
 	vma->vm_mm->total_vm += grow;
 	if (vma->vm_flags & VM_LOCKED)
 		vma->vm_mm->locked_vm += grow;
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if (vma->vm_flags & VM_MIRROR) {
+		vma_m->vm_end = address_m;
+		vma_m->vm_mm->total_vm += grow;
+		if (vma_m->vm_flags & VM_LOCKED)
+			vma_m->vm_mm->locked_vm += grow;
+		track_exec_limit(vma_m->vm_mm, vma_m->vm_start, vma_m->vm_end, vma_m->vm_flags);
+	}
+#endif
+
+	track_exec_limit(vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_flags);
 	anon_vma_unlock(vma);
 	return 0;
 }
@@ -1237,6 +1400,11 @@ int expand_stack(struct vm_area_struct *
 {
 	unsigned long grow;
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	struct vm_area_struct * vma_m = NULL;
+	unsigned long address_m = 0UL;
+#endif
+
 	/*
 	 * We must make sure the anon_vma is allocated
 	 * so that the anon_vma locking is not a noop.
@@ -1258,10 +1426,43 @@ int expand_stack(struct vm_area_struct *
 		anon_vma_unlock(vma);
 		return -ENOMEM;
 	}
-	
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if (vma->vm_flags & VM_MIRROR) {
+		address_m = vma->vm_start + vma->vm_mirror;
+		vma_m = find_vma(vma->vm_mm, address_m);
+		if (!vma_m || vma_m->vm_start != address_m ||
+				!(vma_m->vm_flags & VM_MIRROR) ||
+				vma->vm_end - vma->vm_start !=
+				vma_m->vm_end - vma_m->vm_start ||
+				vma->anon_vma != vma_m->anon_vma) {
+			anon_vma_unlock(vma);
+			vm_unacct_memory(grow);
+			printk(KERN_ERR "PAX: VMMIRROR: expand bug, %08lx, %08lx, %08lx, %08lx, %08lx\n",
+			       address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
+			return -ENOMEM;
+		}
+
+		address_m = address + vma->vm_mirror;
+		if (vma_m->vm_end - address_m > current->rlim[RLIMIT_STACK].rlim_cur ||
+				((vma_m->vm_mm->total_vm + 2*grow) << PAGE_SHIFT) >
+				current->rlim[RLIMIT_AS].rlim_cur ||
+				((vma_m->vm_flags & VM_LOCKED) &&
+				((vma_m->vm_mm->locked_vm + 2*grow) << PAGE_SHIFT) >
+				current->rlim[RLIMIT_MEMLOCK].rlim_cur)) {
+			anon_vma_unlock(vma);
+			vm_unacct_memory(grow);
+			return -ENOMEM;
+		}
+	} else
+#endif
+
 	if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur ||
 			((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
-			current->rlim[RLIMIT_AS].rlim_cur) {
+			current->rlim[RLIMIT_AS].rlim_cur ||
+			((vma->vm_flags & VM_LOCKED) &&
+			((vma->vm_mm->locked_vm + grow) << PAGE_SHIFT) >
+			current->rlim[RLIMIT_MEMLOCK].rlim_cur)) {
 		anon_vma_unlock(vma);
 		vm_unacct_memory(grow);
 		return -ENOMEM;
@@ -1271,6 +1472,19 @@ int expand_stack(struct vm_area_struct *
 	vma->vm_mm->total_vm += grow;
 	if (vma->vm_flags & VM_LOCKED)
 		vma->vm_mm->locked_vm += grow;
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if (vma->vm_flags & VM_MIRROR) {
+		vma_m->vm_start = address_m;
+		vma_m->vm_pgoff -= grow;
+		vma_m->vm_mm->total_vm += grow;
+		if (vma_m->vm_flags & VM_LOCKED)
+			vma_m->vm_mm->locked_vm += grow;
+		track_exec_limit(vma_m->vm_mm, vma_m->vm_start, vma_m->vm_end, vma_m->vm_flags);
+	}
+#endif
+
+	track_exec_limit(vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_flags);
 	anon_vma_unlock(vma);
 	return 0;
 }
@@ -1373,15 +1587,15 @@ static void unmap_vma(struct mm_struct *
 {
 	size_t len = area->vm_end - area->vm_start;
 
-	area->vm_mm->total_vm -= len >> PAGE_SHIFT;
+	mm->total_vm -= len >> PAGE_SHIFT;
 	if (area->vm_flags & VM_LOCKED)
-		area->vm_mm->locked_vm -= len >> PAGE_SHIFT;
+		mm->locked_vm -= len >> PAGE_SHIFT;
 	/*
 	 * Is this a new hole at the lowest possible address?
 	 */
 	if (area->vm_start >= TASK_UNMAPPED_BASE &&
-				area->vm_start < area->vm_mm->free_area_cache)
-	      area->vm_mm->free_area_cache = area->vm_start;
+				area->vm_start < mm->free_area_cache)
+	      mm->free_area_cache = area->vm_start;
 
 	remove_vm_struct(area);
 }
@@ -1435,21 +1649,73 @@ static void unmap_region(struct mm_struc
  */
 static void
 detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma,
-	struct vm_area_struct *prev, unsigned long end)
+	struct vm_area_struct *prev, unsigned long *start, unsigned long *end)
 {
 	struct vm_area_struct **insertion_point;
 	struct vm_area_struct *tail_vma = NULL;
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	unsigned long start_m;
+	struct vm_area_struct *vma_m, *head_vma = vma, *mirrors = NULL, *head_vma_m = NULL;
+#endif
+
 	insertion_point = (prev ? &prev->vm_next : &mm->mmap);
 	do {
 		rb_erase(&vma->vm_rb, &mm->mm_rb);
 		mm->map_count--;
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+		if ((vma->vm_flags & VM_MIRROR) &&
+		    vma->vm_start + vma->vm_mirror >= *start &&
+		    vma->vm_start + vma->vm_mirror < *end)
+		{
+			mm->mmap_cache = NULL;		/* Kill the cache. */
+			start_m = vma->vm_start + vma->vm_mirror;
+			vma_m = find_vma(mm, start_m);
+			if (vma_m && (vma_m->vm_flags & VM_MIRROR) && vma_m->vm_start == start_m) {
+				vma->vm_flags &= ~VM_MIRROR;
+				vma_m->vm_flags &= ~VM_MIRROR;
+			} else
+				printk("PAX: VMMIRROR: munmap bug in %s, %08lx\n", current->comm, vma->vm_start);
+		}
+#endif
+
 		tail_vma = vma;
 		vma = vma->vm_next;
-	} while (vma && vma->vm_start < end);
+	} while (vma && vma->vm_start < *end);
 	*insertion_point = vma;
 	tail_vma->vm_next = NULL;
 	mm->mmap_cache = NULL;		/* Kill the cache. */
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	for (; head_vma; head_vma = head_vma->vm_next) {
+		struct vm_area_struct *prev_m;
+
+		if (!(head_vma->vm_flags & VM_MIRROR))
+			continue;
+
+		start_m = head_vma->vm_start + head_vma->vm_mirror;
+		vma_m = find_vma_prev(mm, start_m, &prev_m);
+		rb_erase(&vma_m->vm_rb, &mm->mm_rb);
+		mm->map_count--;
+		insertion_point = prev_m ? &prev_m->vm_next : &mm->mmap;
+		*insertion_point = vma_m->vm_next;
+		if (head_vma_m) {
+			mirrors->vm_next = vma_m;
+			mirrors = vma_m;
+		} else
+			head_vma_m = mirrors = vma_m;
+		mirrors->vm_next = NULL;
+		if (vma_m->vm_start < *start)
+			*start = vma_m->vm_start;
+		if (vma_m->vm_end > *end)
+			*end = vma_m->vm_end;
+		mm->mmap_cache = NULL;		/* Kill the cache. */
+	}
+	if (head_vma_m)
+		tail_vma->vm_next = head_vma_m;
+#endif
+
 }
 
 /*
@@ -1512,6 +1778,10 @@ int do_munmap(struct mm_struct *mm, unsi
 	unsigned long end;
 	struct vm_area_struct *mpnt, *prev, *last;
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	struct vm_area_struct *mpnt_m = NULL, *last_m;
+#endif
+
 	if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE-start)
 		return -EINVAL;
 
@@ -1548,6 +1818,20 @@ int do_munmap(struct mm_struct *mm, unsi
 	 * places tmp vma above, and higher split_vma places tmp vma below.
 	 */
 	if (start > mpnt->vm_start) {
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+		if (mpnt->vm_flags & VM_MIRROR) {
+			unsigned long start_m = mpnt->vm_start + mpnt->vm_mirror;
+
+			mpnt_m = find_vma(mm, start_m);
+			if (!mpnt_m || (!mpnt_m->vm_flags & VM_MIRROR) || mpnt_m->vm_start != start_m)
+				return -EINVAL;
+			start_m = start + mpnt->vm_mirror;
+			if (split_vma(mm, mpnt_m, start_m, 0))
+				return -ENOMEM;
+		}
+#endif
+
 		if (split_vma(mm, mpnt, start, 0))
 			return -ENOMEM;
 		prev = mpnt;
@@ -1556,6 +1840,20 @@ int do_munmap(struct mm_struct *mm, unsi
 	/* Does it split the last one? */
 	last = find_vma(mm, end);
 	if (last && end > last->vm_start) {
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+		if (last->vm_flags & VM_MIRROR) {
+			unsigned long end_m = last->vm_start + last->vm_mirror;
+
+			last_m = find_vma(mm, end_m);
+			if (!last_m || (!last_m->vm_flags & VM_MIRROR) || last_m->vm_start != end_m)
+				return -EINVAL;
+			end_m = end + last->vm_mirror;
+			if (split_vma(mm, last_m, end_m, 1))
+				return -ENOMEM;
+		}
+#endif
+
 		if (split_vma(mm, last, end, 1))
 			return -ENOMEM;
 	}
@@ -1564,7 +1862,7 @@ int do_munmap(struct mm_struct *mm, unsi
 	/*
 	 * Remove the vma's, and unmap the actual pages
 	 */
-	detach_vmas_to_be_unmapped(mm, mpnt, prev, end);
+	detach_vmas_to_be_unmapped(mm, mpnt, prev, &start, &end);
 	spin_lock(&mm->page_table_lock);
 	unmap_region(mm, mpnt, prev, start, end);
 	spin_unlock(&mm->page_table_lock);
@@ -1572,6 +1870,8 @@ int do_munmap(struct mm_struct *mm, unsi
 	/* Fix up all other VM information */
 	unmap_vma_list(mm, mpnt);
 
+	track_exec_limit(mm, start, end, 0UL);
+
 	return 0;
 }
 
@@ -1582,6 +1882,12 @@ asmlinkage long sys_munmap(unsigned long
 	int ret;
 	struct mm_struct *mm = current->mm;
 
+#ifdef CONFIG_PAX_SEGMEXEC
+	if ((current->flags & PF_PAX_SEGMEXEC) &&
+	    (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len))
+		return -EINVAL;
+#endif
+
 	down_write(&mm->mmap_sem);
 	ret = do_munmap(mm, addr, len);
 	up_write(&mm->mmap_sem);
@@ -1593,7 +1899,31 @@ asmlinkage long sys_munmap(unsigned long
  *  anonymous maps.  eventually we may be able to do some
  *  brk-specific accounting here.
  */
+#if defined(CONFIG_PAX_SEGMEXEC) && defined(CONFIG_PAX_MPROTECT)
+unsigned long __do_brk(unsigned long addr, unsigned long len);
+
+unsigned long do_brk(unsigned long addr, unsigned long len)
+{
+	unsigned long ret;
+
+	ret = __do_brk(addr, len);
+	if (ret == addr && (current->flags & (PF_PAX_SEGMEXEC | PF_PAX_MPROTECT)) == PF_PAX_SEGMEXEC) {
+		unsigned long ret_m;
+
+		ret_m = __do_mmap_pgoff(NULL, addr + SEGMEXEC_TASK_SIZE, 0UL, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_MIRROR, addr);
+		if (ret_m > TASK_SIZE) {
+			do_munmap(current->mm, addr, len);
+			ret = ret_m;
+		}
+	}
+
+	return ret;
+}
+
+unsigned long __do_brk(unsigned long addr, unsigned long len)
+#else
 unsigned long do_brk(unsigned long addr, unsigned long len)
+#endif
 {
 	struct mm_struct * mm = current->mm;
 	struct vm_area_struct * vma, * prev;
@@ -1605,6 +1935,13 @@ unsigned long do_brk(unsigned long addr,
 	if (!len)
 		return addr;
 
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->flags & PF_PAX_SEGMEXEC) {
+		if ((addr + len) > SEGMEXEC_TASK_SIZE || (addr + len) < addr)
+			return -EINVAL;
+	} else
+#endif
+
 	if ((addr + len) > TASK_SIZE || (addr + len) < addr)
 		return -EINVAL;
 
@@ -1642,6 +1979,18 @@ unsigned long do_brk(unsigned long addr,
 
 	flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
 
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+	if (current->flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) {
+		flags &= ~VM_EXEC;
+
+#ifdef CONFIG_PAX_MPROTECT
+		if (current->flags & PF_PAX_MPROTECT)
+			flags &= ~VM_MAYEXEC;
+#endif
+
+	}
+#endif
+
 	/* Can we just expand an old private anonymous mapping? */
 	if (vma_merge(mm, prev, addr, addr + len, flags,
 					NULL, NULL, pgoff, NULL))
@@ -1662,6 +2011,13 @@ unsigned long do_brk(unsigned long addr,
 	vma->vm_end = addr + len;
 	vma->vm_pgoff = pgoff;
 	vma->vm_flags = flags;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (!(current->flags & PF_PAX_PAGEEXEC) && (flags & (VM_READ|VM_WRITE)))
+		vma->vm_page_prot = protection_map[(flags | VM_EXEC) & 0x0f];
+	else
+#endif
+
 	vma->vm_page_prot = protection_map[flags & 0x0f];
 	vma_link(mm, vma, prev, rb_link, rb_parent);
 out:
@@ -1670,6 +2026,7 @@ out:
 		mm->locked_vm += len >> PAGE_SHIFT;
 		make_pages_present(addr, addr + len);
 	}
+	track_exec_limit(mm, addr, addr + len, flags);
 	return addr;
 }
 
diff -NurpX nopatch linux-2.6.7/mm/mprotect.c linux-2.6.7-pax/mm/mprotect.c
--- linux-2.6.7/mm/mprotect.c	2004-06-16 07:20:27.000000000 +0200
+++ linux-2.6.7-pax/mm/mprotect.c	2004-10-31 22:32:23.000000000 +0100
@@ -18,11 +18,17 @@
 #include <linux/security.h>
 #include <linux/mempolicy.h>
 
+#ifdef CONFIG_PAX_MPROTECT
+#include <linux/elf.h>
+#include <linux/fs.h>
+#endif
+
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
+#include <asm/mmu_context.h>
 
 static inline void
 change_pte_range(pmd_t *pmd, unsigned long address,
@@ -108,6 +114,94 @@ change_protection(struct vm_area_struct 
 	return;
 }
 
+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
+/* called while holding the mmap semaphor for writing */
+static inline void establish_user_cs_limit(struct mm_struct *mm, unsigned long start, unsigned long end)
+{
+	struct vm_area_struct *vma = find_vma(mm, start);
+
+	for (; vma && vma->vm_start < end; vma = vma->vm_next)
+		change_protection(vma, vma->vm_start, vma->vm_end, vma->vm_page_prot);
+
+}
+
+void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot)
+{
+	if (current->flags & PF_PAX_PAGEEXEC) {
+		unsigned long oldlimit, newlimit = 0UL;
+
+		spin_lock(&mm->page_table_lock);
+		oldlimit = mm->context.user_cs_limit;
+		if ((prot & VM_EXEC) && oldlimit < end)
+			/* USER_CS limit moved up */
+			newlimit = end;
+		else if (!(prot & VM_EXEC) && start < oldlimit && oldlimit <= end)
+			/* USER_CS limit moved down */
+			newlimit = start;
+
+		if (newlimit) {
+			mm->context.user_cs_limit = newlimit;
+
+#ifdef CONFIG_SMP
+			wmb();
+			cpus_clear(mm->context.cpu_user_cs_mask);
+			cpu_set(smp_processor_id(), mm->context.cpu_user_cs_mask);
+#endif
+
+			set_user_cs(mm, smp_processor_id());
+		}
+		spin_unlock(&mm->page_table_lock);
+		if (newlimit == end)
+			establish_user_cs_limit(mm, oldlimit, end);
+	}
+}
+#endif
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
+	unsigned long start, unsigned long end, unsigned int newflags);
+
+static int mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
+	unsigned long start, unsigned long end, unsigned int newflags)
+{
+	if (vma->vm_flags & VM_MIRROR) {
+		struct vm_area_struct * vma_m, * prev_m;
+		unsigned long start_m, end_m;
+		int error;
+
+		start_m = vma->vm_start + vma->vm_mirror;
+		vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m);
+		if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
+			start_m = start + vma->vm_mirror;
+			end_m = end + vma->vm_mirror;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+			if ((current->flags & PF_PAX_SEGMEXEC) && (vma_m->vm_start >= SEGMEXEC_TASK_SIZE) && !(newflags & VM_EXEC))
+				error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, vma_m->vm_flags & ~(PROT_READ | PROT_WRITE | PROT_EXEC));
+			else
+#endif
+
+				error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, newflags);
+			if (error)
+				return error;
+		} else {
+			printk("PAX: VMMIRROR: mprotect bug in %s, %08lx\n", current->comm, vma->vm_start);
+			return -ENOMEM;
+		}
+	}
+
+	return __mprotect_fixup(vma, pprev, start, end, newflags);
+}
+
+static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
+	unsigned long start, unsigned long end, unsigned int newflags)
+{
+	struct mm_struct * mm = vma->vm_mm;
+	unsigned long charged = 0;
+	pgprot_t newprot;
+	pgoff_t pgoff;
+	int error;
+#else
 static int
 mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
 	unsigned long start, unsigned long end, unsigned int newflags)
@@ -122,6 +216,7 @@ mprotect_fixup(struct vm_area_struct *vm
 		*pprev = vma;
 		return 0;
 	}
+#endif
 
 	/*
 	 * If we make a private mapping writable we increase our commit;
@@ -140,6 +235,12 @@ mprotect_fixup(struct vm_area_struct *vm
 		}
 	}
 
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (!(current->flags & PF_PAX_PAGEEXEC) && (newflags & (VM_READ|VM_WRITE)))
+		newprot = protection_map[(newflags | VM_EXEC) & 0xf];
+	else
+#endif
+
 	newprot = protection_map[newflags & 0xf];
 
 	/*
@@ -185,6 +286,68 @@ fail:
 	return error;
 }
 
+#ifdef CONFIG_PAX_MPROTECT
+/* PaX: non-PIC ELF libraries need relocations on their executable segments
+ * therefore we'll grant them VM_MAYWRITE once during their life.
+ *
+ * The checks favour ld-linux.so behaviour which operates on a per ELF segment
+ * basis because we want to allow the common case and not the special ones.
+ */
+static inline void pax_handle_maywrite(struct vm_area_struct * vma, unsigned long start)
+{
+	struct elfhdr elf_h;
+	struct elf_phdr elf_p, p_dyn;
+	elf_dyn dyn;
+	unsigned long i, j = 65536UL / sizeof(struct elf_phdr);
+
+#ifndef CONFIG_PAX_NOELFRELOCS
+	if ((vma->vm_start != start) ||
+	    !vma->vm_file ||
+	    !(vma->vm_flags & VM_MAYEXEC) ||
+	    (vma->vm_flags & VM_MAYNOTWRITE))
+#endif
+
+		return;
+
+	if (0 > kernel_read(vma->vm_file, 0UL, (char*)&elf_h, sizeof(elf_h)) ||
+	    memcmp(elf_h.e_ident, ELFMAG, SELFMAG) ||
+
+#ifdef CONFIG_PAX_ETEXECRELOCS
+	    (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC) ||
+#else
+	    elf_h.e_type != ET_DYN ||
+#endif
+
+	    !elf_check_arch(&elf_h) ||
+	    elf_h.e_phentsize != sizeof(struct elf_phdr) ||
+	    elf_h.e_phnum > j)
+		return;
+
+	for (i = 0UL; i < elf_h.e_phnum; i++) {
+		if (0 > kernel_read(vma->vm_file, elf_h.e_phoff + i*sizeof(elf_p), (char*)&elf_p, sizeof(elf_p)))
+			return;
+		if (elf_p.p_type == PT_DYNAMIC) {
+			p_dyn = elf_p;
+			j = i;
+		}
+	}
+	if (elf_h.e_phnum <= j)
+		return;
+
+	i = 0UL;
+	do {
+		if (0 > kernel_read(vma->vm_file, p_dyn.p_offset + i*sizeof(dyn), (char*)&dyn, sizeof(dyn)))
+			return;
+		if (dyn.d_tag == DT_TEXTREL || (dyn.d_tag == DT_FLAGS && (dyn.d_un.d_val & DF_TEXTREL))) {
+			vma->vm_flags |= VM_MAYWRITE | VM_MAYNOTWRITE;
+			return;
+		}
+		i++;
+	} while (dyn.d_tag != DT_NULL);
+	return;
+}
+#endif
+
 asmlinkage long
 sys_mprotect(unsigned long start, size_t len, unsigned long prot)
 {
@@ -202,6 +365,17 @@ sys_mprotect(unsigned long start, size_t
 	end = start + len;
 	if (end < start)
 		return -ENOMEM;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->flags & PF_PAX_SEGMEXEC) {
+		if (end > SEGMEXEC_TASK_SIZE)
+			return -EINVAL;
+	} else
+#endif
+
+	if (end > TASK_SIZE)
+		return -EINVAL;
+
 	if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM))
 		return -EINVAL;
 	if (end == start)
@@ -236,6 +410,11 @@ sys_mprotect(unsigned long start, size_t
 	if (start > vma->vm_start)
 		prev = vma;
 
+#ifdef CONFIG_PAX_MPROTECT
+	if ((current->flags & PF_PAX_MPROTECT) && (prot & PROT_WRITE))
+		pax_handle_maywrite(vma, start);
+#endif
+
 	for (nstart = start ; ; ) {
 		unsigned int newflags;
 
@@ -253,6 +432,12 @@ sys_mprotect(unsigned long start, size_t
 			goto out;
 		}
 
+#ifdef CONFIG_PAX_MPROTECT
+		/* PaX: disallow write access after relocs are done, hopefully noone else needs it... */
+		if ((current->flags & PF_PAX_MPROTECT) && (prot & PROT_WRITE) && (vma->vm_flags & VM_MAYNOTWRITE))
+			newflags &= ~VM_MAYWRITE;
+#endif
+
 		error = security_file_mprotect(vma, prot);
 		if (error)
 			goto out;
@@ -276,6 +461,9 @@ sys_mprotect(unsigned long start, size_t
 			goto out;
 		}
 	}
+
+	track_exec_limit(current->mm, start, end, vm_flags);
+
 out:
 	up_write(&current->mm->mmap_sem);
 	return error;
diff -NurpX nopatch linux-2.6.7/mm/mremap.c linux-2.6.7-pax/mm/mremap.c
--- linux-2.6.7/mm/mremap.c	2004-06-16 07:19:35.000000000 +0200
+++ linux-2.6.7-pax/mm/mremap.c	2004-07-01 22:32:43.000000000 +0200
@@ -129,6 +129,12 @@ move_one_page(struct vm_area_struct *vma
 			if (dst) {
 				pte_t pte;
 				pte = ptep_clear_flush(vma, old_addr, src);
+
+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
+				if ((current->flags & PF_PAX_PAGEEXEC) && !(vma->vm_flags & VM_EXEC))
+					pte_exprotect(pte);
+#endif
+
 				set_pte(dst, pte);
 			} else
 				error = -ENOMEM;
@@ -267,6 +273,18 @@ unsigned long do_mremap(unsigned long ad
 	if (!new_len)
 		goto out;
 
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->flags & PF_PAX_SEGMEXEC) {
+		if (new_len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-new_len ||
+		    old_len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-old_len)
+			goto out;
+	} else
+#endif
+
+	if (new_len > TASK_SIZE || addr > TASK_SIZE-new_len ||
+	    old_len > TASK_SIZE || addr > TASK_SIZE-old_len)
+		goto out;
+
 	/* new_addr is only valid if MREMAP_FIXED is specified */
 	if (flags & MREMAP_FIXED) {
 		if (new_addr & ~PAGE_MASK)
@@ -274,6 +292,13 @@ unsigned long do_mremap(unsigned long ad
 		if (!(flags & MREMAP_MAYMOVE))
 			goto out;
 
+#ifdef CONFIG_PAX_SEGMEXEC
+		if (current->flags & PF_PAX_SEGMEXEC) {
+			if (new_len > SEGMEXEC_TASK_SIZE || new_addr > SEGMEXEC_TASK_SIZE-new_len)
+				goto out;
+		} else
+#endif
+
 		if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
 			goto out;
 
@@ -317,6 +342,16 @@ unsigned long do_mremap(unsigned long ad
 		ret = -EINVAL;
 		goto out;
 	}
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if ((current->flags & (PF_PAX_SEGMEXEC | PF_PAX_RANDEXEC)) &&
+	    (vma->vm_flags & VM_MIRROR))
+	{
+		ret = -EINVAL;
+		goto out;
+	}
+#endif
+
 	/* We can't remap across vm area boundaries */
 	if (old_len > vma->vm_end - addr)
 		goto out;
@@ -365,6 +400,7 @@ unsigned long do_mremap(unsigned long ad
 						   addr + new_len);
 			}
 			ret = addr;
+			track_exec_limit(vma->vm_mm, vma->vm_start, addr + new_len, vma->vm_flags);
 			goto out;
 		}
 	}
@@ -375,8 +411,8 @@ unsigned long do_mremap(unsigned long ad
 	 */
 	ret = -ENOMEM;
 	if (flags & MREMAP_MAYMOVE) {
+		unsigned long map_flags = 0;
 		if (!(flags & MREMAP_FIXED)) {
-			unsigned long map_flags = 0;
 			if (vma->vm_flags & VM_MAYSHARE)
 				map_flags |= MAP_SHARED;
 
@@ -386,7 +422,12 @@ unsigned long do_mremap(unsigned long ad
 			if (new_addr & ~PAGE_MASK)
 				goto out;
 		}
+		map_flags = vma->vm_flags;
 		ret = move_vma(vma, addr, old_len, new_len, new_addr);
+		if (!(ret & ~PAGE_MASK)) {
+			track_exec_limit(current->mm, addr, addr + old_len, 0UL);
+			track_exec_limit(current->mm, new_addr, new_addr + new_len, map_flags);
+		}
 	}
 out:
 	if (ret & ~PAGE_MASK)
diff -NurpX nopatch linux-2.6.7/mm/rmap.c linux-2.6.7-pax/mm/rmap.c
--- linux-2.6.7/mm/rmap.c	2004-06-16 07:20:03.000000000 +0200
+++ linux-2.6.7-pax/mm/rmap.c	2004-06-21 13:22:19.000000000 +0200
@@ -83,6 +83,19 @@ int anon_vma_prepare(struct vm_area_stru
 			list_add(&vma->anon_vma_node, &anon_vma->head);
 			allocated = NULL;
 		}
+
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+		if (vma->vm_flags & VM_MIRROR) {
+			struct vm_area_struct *vma_m;
+
+			vma_m = find_vma(vma->vm_mm, vma->vm_start + vma->vm_mirror);
+			BUG_ON(!vma_m || vma_m->vm_start != vma->vm_start + vma->vm_mirror);
+			BUG_ON(vma_m->anon_vma || vma->vm_pgoff != vma_m->vm_pgoff);
+			vma_m->anon_vma = anon_vma;
+			__anon_vma_link(vma_m);
+		}
+#endif
+
 		spin_unlock(&mm->page_table_lock);
 		if (unlikely(allocated))
 			anon_vma_free(allocated);
diff -NurpX nopatch linux-2.6.7/security/Kconfig linux-2.6.7-pax/security/Kconfig
--- linux-2.6.7/security/Kconfig	2004-06-16 07:19:42.000000000 +0200
+++ linux-2.6.7-pax/security/Kconfig	2004-10-31 22:12:07.000000000 +0100
@@ -4,6 +4,423 @@
 
 menu "Security options"
 
+menu "PaX"
+
+config PAX
+	bool "Enable various PaX features"
+	depends on ALPHA || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || PPC64 || SPARC32 || SPARC64 || X86 || X86_64
+	help
+	  This allows you to enable various PaX features.  PaX adds
+	  intrusion prevention mechanisms to the kernel that reduce
+	  the risks posed by exploitable memory corruption bugs.
+
+menu "PaX Control"
+	depends on PAX
+
+config PAX_SOFTMODE
+	bool 'Support soft mode'
+	help
+	  Enabling this option will allow you to run PaX in soft mode, that
+	  is, PaX features will not be enforced by default, only on executables
+	  marked explicitly.  You must also enable PT_PAX_FLAGS support as it
+	  is the only way to mark executables for soft mode use.
+
+	  Soft mode can be activated by using the "pax_softmode=1" kernel command
+	  line option on boot.  Furthermore you can control various PaX features
+	  at runtime via the entries in /proc/sys/kernel/pax.
+
+config PAX_EI_PAX
+	bool 'Use legacy ELF header marking'
+	help
+	  Enabling this option will allow you to control PaX features on
+	  a per executable basis via the 'chpax' utility available at
+	  http://pax.grsecurity.net/.  The control flags will be read from
+	  an otherwise reserved part of the ELF header.  This marking has
+	  numerous drawbacks (no support for soft-mode, toolchain does not
+	  know about the non-standard use of the ELF header) therefore it
+	  has been deprecated in favour of PT_PAX_FLAGS support.
+
+	  If you have applications not marked by the PT_PAX_FLAGS ELF
+	  program header then you MUST enable this option otherwise they
+	  will not get any protection.
+
+	  Note that if you enable PT_PAX_FLAGS marking support as well,
+	  the PT_PAX_FLAG marks will override the legacy EI_PAX marks.
+
+config PAX_PT_PAX_FLAGS
+	bool 'Use ELF program header marking'
+	help
+	  Enabling this option will allow you to control PaX features on
+	  a per executable basis via the 'paxctl' utility available at
+	  http://pax.grsecurity.net/.  The control flags will be read from
+	  a PaX specific ELF program header (PT_PAX_FLAGS).  This marking
+	  has the benefits of supporting both soft mode and being fully
+	  integrated into the toolchain (the binutils patch is available
+	  from http://pax.grsecurity.net).
+
+	  If you have applications not marked by the PT_PAX_FLAGS ELF
+	  program header then you MUST enable the EI_PAX marking support
+	  otherwise they will not get any protection.
+
+	  Note that if you enable the legacy EI_PAX marking support as well,
+	  the EI_PAX marks will be overridden by the PT_PAX_FLAGS marks.
+
+choice
+	prompt 'MAC system integration'
+	default PAX_NO_ACL_FLAGS
+	help
+	  Mandatory Access Control systems have the option of controlling
+	  PaX flags on a per executable basis, choose the method supported
+	  by your particular system.
+
+	  - "none": if your MAC system does not interact with PaX,
+	  - "direct": if your MAC system defines pax_set_flags() itself,
+	  - "hook": if your MAC system uses the pax_set_flags_func callback.
+
+	  NOTE: this option is for developers/integrators only.
+
+config PAX_NO_ACL_FLAGS
+	bool 'none'
+
+config PAX_HAVE_ACL_FLAGS
+	bool 'direct'
+
+config PAX_HOOK_ACL_FLAGS
+	bool 'hook'
+endchoice
+
+endmenu
+
+menu "Non-executable pages"
+	depends on PAX
+
+config PAX_NOEXEC
+	bool "Enforce non-executable pages"
+	depends on (PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS) && (ALPHA || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || PPC64 || SPARC32 || SPARC64 || X86 || X86_64)
+	help
+	  By design some architectures do not allow for protecting memory
+	  pages against execution or even if they do, Linux does not make
+	  use of this feature.  In practice this means that if a page is
+	  readable (such as the stack or heap) it is also executable.
+
+	  There is a well known exploit technique that makes use of this
+	  fact and a common programming mistake where an attacker can
+	  introduce code of his choice somewhere in the attacked program's
+	  memory (typically the stack or the heap) and then execute it.
+
+	  If the attacked program was running with different (typically
+	  higher) privileges than that of the attacker, then he can elevate
+	  his own privilege level (e.g. get a root shell, write to files for
+	  which he does not have write access to, etc).
+
+	  Enabling this option will let you choose from various features
+	  that prevent the injection and execution of 'foreign' code in
+	  a program.
+
+	  This will also break programs that rely on the old behaviour and
+	  expect that dynamically allocated memory via the malloc() family
+	  of functions is executable (which it is not).  Notable examples
+	  are the XFree86 4.x server, the java runtime and wine.
+
+config PAX_PAGEEXEC
+	bool "Paging based non-executable pages"
+	depends on PAX_NOEXEC && !HIGHPTE && (!X86 || X86_64 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUM4 || MK7 || MK8)
+	select PAX_NOVSYSCALL if X86 && !X86_64
+	help
+	  This implementation is based on the paging feature of the CPU.
+	  On i386 and ppc there is a variable but usually low performance
+	  impact on applications.  On alpha, ia64, parisc, sparc, sparc64
+	  and x86_64 there is no performance impact.
+
+config PAX_SEGMEXEC
+	bool "Segmentation based non-executable pages"
+	depends on PAX_NOEXEC && X86 && !X86_64
+	help
+	  This implementation is based on the segmentation feature of the
+	  CPU and has little performance impact, however applications will
+	  be limited to a 1.5 GB address space instead of the normal 3 GB.
+
+choice
+	prompt "Default non-executable page method"
+	depends on PAX_PAGEEXEC && PAX_SEGMEXEC
+	default PAX_DEFAULT_SEGMEXEC
+	help
+	  Select the default non-executable page method applied to applications
+	  that do not select one themselves.
+
+config	PAX_DEFAULT_PAGEEXEC
+	bool "PAGEEXEC"
+
+config	PAX_DEFAULT_SEGMEXEC
+	bool "SEGMEXEC"
+endchoice
+
+config PAX_EMUTRAMP
+	bool "Emulate trampolines" if (PAX_PAGEEXEC || PAX_SEGMEXEC) && (PARISC || PPC32 || X86) && !X86_64
+	default y if PARISC || PPC32
+	help
+	  There are some programs and libraries that for one reason or
+	  another attempt to execute special small code snippets from
+	  non-executable memory pages.  Most notable examples are the
+	  signal handler return code generated by the kernel itself and
+	  the GCC trampolines.
+
+	  If you enabled CONFIG_PAX_PAGEEXEC or CONFIG_PAX_SEGMEXEC then
+	  such programs will no longer work under your kernel.
+
+	  As a remedy you can say Y here and use the 'chpax' or 'paxctl'
+	  utilities to enable trampoline emulation for the affected programs
+	  yet still have the protection provided by the non-executable pages.
+
+	  On parisc and ppc you MUST enable this option and EMUSIGRT as
+	  well, otherwise your system will not even boot.
+
+	  Alternatively you can say N here and use the 'chpax' or 'paxctl'
+	  utilities to disable CONFIG_PAX_PAGEEXEC and CONFIG_PAX_SEGMEXEC
+	  for the affected files.
+
+	  NOTE: enabling this feature *may* open up a loophole in the
+	  protection provided by non-executable pages that an attacker
+	  could abuse.  Therefore the best solution is to not have any
+	  files on your system that would require this option.  This can
+	  be achieved by not using libc5 (which relies on the kernel
+	  signal handler return code) and not using or rewriting programs
+	  that make use of the nested function implementation of GCC.
+	  Skilled users can just fix GCC itself so that it implements
+	  nested function calls in a way that does not interfere with PaX.
+
+config PAX_EMUSIGRT
+	bool "Automatically emulate sigreturn trampolines"
+	depends on PAX_EMUTRAMP && (PARISC || PPC32)
+	default y
+	help
+	  Enabling this option will have the kernel automatically detect
+	  and emulate signal return trampolines executing on the stack
+	  that would otherwise lead to task termination.
+
+	  This solution is intended as a temporary one for users with
+	  legacy versions of libc (libc5, glibc 2.0, uClibc before 0.9.17,
+	  Modula-3 runtime, etc) or executables linked to such, basically
+	  everything that does not specify its own SA_RESTORER function in
+	  normal executable memory like glibc 2.1+ does.
+
+	  On parisc and ppc you MUST enable this option, otherwise your
+	  system will not even boot.
+
+	  NOTE: this feature cannot be disabled on a per executable basis
+	  and since it *does* open up a loophole in the protection provided
+	  by non-executable pages, the best solution is to not have any
+	  files on your system that would require this option.
+
+config PAX_MPROTECT
+	bool "Restrict mprotect()"
+	depends on (PAX_PAGEEXEC || PAX_SEGMEXEC) && !PPC64
+	help
+	  Enabling this option will prevent programs from
+	   - changing the executable status of memory pages that were
+	     not originally created as executable,
+	   - making read-only executable pages writable again,
+	   - creating executable pages from anonymous memory.
+
+	  You should say Y here to complete the protection provided by
+	  the enforcement of non-executable pages.
+
+	  NOTE: you can use the 'chpax' or 'paxctl' utilities to control
+	  this feature on a per file basis.
+
+config PAX_NOELFRELOCS
+	bool "Disallow ELF text relocations"
+	depends on PAX_MPROTECT && (IA64 || X86 || X86_64)
+	help
+	  Non-executable pages and mprotect() restrictions are effective
+	  in preventing the introduction of new executable code into an
+	  attacked task's address space.  There remain only two venues
+	  for this kind of attack: if the attacker can execute already
+	  existing code in the attacked task then he can either have it
+	  create and mmap() a file containing his code or have it mmap()
+	  an already existing ELF library that does not have position
+	  independent code in it and use mprotect() on it to make it
+	  writable and copy his code there.  While protecting against
+	  the former approach is beyond PaX, the latter can be prevented
+	  by having only PIC ELF libraries on one's system (which do not
+	  need to relocate their code).  If you are sure this is your case,
+	  then enable this option otherwise be careful as you may not even
+	  be able to boot or log on your system (for example, some PAM
+	  modules are erroneously compiled as non-PIC by default).
+
+	  NOTE: if you are using dynamic ELF executables (as suggested
+	  when using ASLR) then you must have made sure that you linked
+	  your files using the PIC version of crt1 (the et_dyn.tar.gz package
+	  referenced there has already been updated to support this).
+
+config PAX_ETEXECRELOCS
+	bool "Allow ELF ET_EXEC text relocations"
+	depends on PAX_MPROTECT && (ALPHA || IA64 || PARISC)
+	default y
+	help
+	  On some architectures there are incorrectly created applications
+	  that require text relocations and would not work without enabling
+	  this option.  If you are an alpha, ia64 or parisc user, you should
+	  enable this option and disable it once you have made sure that
+	  none of your applications need it.
+
+config PAX_EMUPLT
+	bool "Automatically emulate ELF PLT"
+	depends on PAX_MPROTECT && (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64)
+	default y
+	help
+	  Enabling this option will have the kernel automatically detect
+	  and emulate the Procedure Linkage Table entries in ELF files.
+	  On some architectures such entries are in writable memory, and
+	  become non-executable leading to task termination.  Therefore
+	  it is mandatory that you enable this option on alpha, parisc, ppc,
+	  sparc and sparc64, otherwise your system would not even boot.
+
+	  NOTE: this feature *does* open up a loophole in the protection
+	  provided by the non-executable pages, therefore the proper
+	  solution is to modify the toolchain to produce a PLT that does
+	  not need to be writable.
+
+config PAX_DLRESOLVE
+	bool
+	depends on PAX_EMUPLT && (SPARC32 || SPARC64)
+	default y
+
+config PAX_SYSCALL
+	bool
+	depends on PAX_PAGEEXEC && PPC32
+	default y
+
+config PAX_KERNEXEC
+	bool "Enforce non-executable kernel pages"
+	depends on PAX_NOEXEC && X86 && !X86_64 && !MODULES && !HOTPLUG_PCI_COMPAQ_NVRAM && !CONFIG_PCI_BIOS
+	help
+	  This is the kernel land equivalent of PAGEEXEC and MPROTECT,
+	  that is, enabling this option will make it harder to inject
+	  and execute 'foreign' code in kernel memory itself.
+
+endmenu
+
+menu "Address Space Layout Randomization"
+	depends on PAX
+
+config PAX_ASLR
+	bool "Address Space Layout Randomization"
+	depends on PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS
+	help
+	  Many if not most exploit techniques rely on the knowledge of
+	  certain addresses in the attacked program.  The following options
+	  will allow the kernel to apply a certain amount of randomization
+	  to specific parts of the program thereby forcing an attacker to
+	  guess them in most cases.  Any failed guess will most likely crash
+	  the attacked program which allows the kernel to detect such attempts
+	  and react on them.  PaX itself provides no reaction mechanisms,
+	  instead it is strongly encouraged that you make use of Nergal's
+	  segvguard (ftp://ftp.pl.openwall.com/misc/segvguard/) or grsecurity's
+	  (http://www.grsecurity.net/) built-in crash detection features or
+	  develop one yourself.
+
+	  By saying Y here you can choose to randomize the following areas:
+	   - top of the task's kernel stack
+	   - top of the task's userland stack
+	   - base address for mmap() requests that do not specify one
+	     (this includes all libraries)
+	   - base address of the main executable
+
+	  It is strongly recommended to say Y here as address space layout
+	  randomization has negligible impact on performance yet it provides
+	  a very effective protection.
+
+	  NOTE: you can use the 'chpax' or 'paxctl' utilities to control
+	  this feature on a per file basis.
+
+config PAX_RANDKSTACK
+	bool "Randomize kernel stack base"
+	depends on PAX_ASLR && X86_TSC && !X86_64
+	help
+	  By saying Y here the kernel will randomize every task's kernel
+	  stack on every system call.  This will not only force an attacker
+	  to guess it but also prevent him from making use of possible
+	  leaked information about it.
+
+	  Since the kernel stack is a rather scarce resource, randomization
+	  may cause unexpected stack overflows, therefore you should very
+	  carefully test your system.  Note that once enabled in the kernel
+	  configuration, this feature cannot be disabled on a per file basis.
+
+config PAX_RANDUSTACK
+	bool "Randomize user stack base"
+	depends on PAX_ASLR
+	help
+	  By saying Y here the kernel will randomize every task's userland
+	  stack.  The randomization is done in two steps where the second
+	  one may apply a big amount of shift to the top of the stack and
+	  cause problems for programs that want to use lots of memory (more
+	  than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is).
+	  For this reason the second step can be controlled by 'chpax' or
+	  'paxctl' on a per file basis.
+
+config PAX_RANDMMAP
+	bool "Randomize mmap() base"
+	depends on PAX_ASLR
+	help
+	  By saying Y here the kernel will use a randomized base address for
+	  mmap() requests that do not specify one themselves.  As a result
+	  all dynamically loaded libraries will appear at random addresses
+	  and therefore be harder to exploit by a technique where an attacker
+	  attempts to execute library code for his purposes (e.g. spawn a
+	  shell from an exploited program that is running at an elevated
+	  privilege level).
+
+	  Furthermore, if a program is relinked as a dynamic ELF file, its
+	  base address will be randomized as well, completing the full
+	  randomization of the address space layout.  Attacking such programs
+	  becomes a guess game.  You can find an example of doing this at
+	  http://pax.grsecurity.net/et_dyn.tar.gz and practical samples at
+	  http://www.grsecurity.net/grsec-gcc-specs.tar.gz .
+
+	  NOTE: you can use the 'chpax' or 'paxctl' utilities to control this
+	  feature on a per file basis.
+
+config PAX_RANDEXEC
+	bool "Randomize ET_EXEC base"
+	depends on PAX_MPROTECT && PAX_RANDMMAP
+	help
+	  By saying Y here the kernel will randomize the base address of normal
+	  ET_EXEC ELF executables as well.  This is accomplished by mapping the
+	  executable in memory in a special way which also allows for detecting
+	  attackers who attempt to execute its code for their purposes.  Since
+	  this special mapping causes performance degradation and the attack
+	  detection may create false alarms as well, you should carefully test
+	  your executables when this feature is enabled.
+
+	  This solution is intended only as a temporary one until you relink
+	  your programs as a dynamic ELF file.
+
+	  NOTE: you can use the 'chpax' or 'paxctl' utilities to control this
+	  feature on a per file basis.
+
+config PAX_NOVSYSCALL
+	bool "Disable the vsyscall page"
+	depends on PAX_ASLR && X86 && !X86_64
+	help
+	  The Linux 2.6 kernel introduced a new feature that speeds up or
+	  simplifies certain operations, such as system calls or returns
+	  from signal handlers.
+
+	  Unfortunately the implementation also gives a powerful instrument
+	  into the hands of exploit writers: the so-called vsyscall page exists
+	  in every task at the same fixed address and it contains machine code
+	  that is very useful in performing the return-to-libc style attack.
+
+	  Since this exploit technique cannot in general be protected against
+	  via kernel solutions, this option will allow you to disable the use
+	  of the vsyscall page and revert back to the old behaviour.
+
+endmenu
+
+endmenu
+
 config SECURITY
 	bool "Enable different security models"
 	help
