diff -ruN linux-2.6.10_orig/arch/alpha/Kconfig linux-2.6.10/arch/alpha/Kconfig
--- linux-2.6.10_orig/arch/alpha/Kconfig	2004-12-24 22:35:59.000000000 +0100
+++ linux-2.6.10/arch/alpha/Kconfig	2005-03-02 13:15:44.000000000 +0100
@@ -594,6 +594,8 @@
 
 source "arch/alpha/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/alpha/kernel/osf_sys.c linux-2.6.10/arch/alpha/kernel/osf_sys.c
--- linux-2.6.10_orig/arch/alpha/kernel/osf_sys.c	2004-12-24 22:33:47.000000000 +0100
+++ linux-2.6.10/arch/alpha/kernel/osf_sys.c	2005-03-02 13:10:40.000000000 +0100
@@ -37,6 +37,7 @@
 #include <linux/namei.h>
 #include <linux/uio.h>
 #include <linux/vfs.h>
+#include <linux/grsecurity.h>
 
 #include <asm/fpu.h>
 #include <asm/io.h>
@@ -179,6 +180,11 @@
 	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", 
@@ -189,6 +195,13 @@
 		if (!file)
 			goto out;
 	}
+
+	if (gr_handle_mmap(file, prot)) {
+		fput(file);
+		ret = -EACCES;
+		goto out;
+	}
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	down_write(&current->mm->mmap_sem);
 	ret = do_mmap(file, addr, len, prot, flags, off);
@@ -1288,6 +1301,10 @@
 	   merely specific addresses, but regions of memory -- perhaps
 	   this feature should be incorporated into all ports?  */
 
+#ifdef CONFIG_PAX_RANDMMAP
+	if (!(current->mm->flags & MF_PAX_RANDMMAP) || !filp)
+#endif
+
 	if (addr) {
 		addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
 		if (addr != (unsigned long) -ENOMEM)
@@ -1295,8 +1312,16 @@
 	}
 
 	/* 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->mm->flags & MF_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 -ruN linux-2.6.10_orig/arch/alpha/kernel/ptrace.c linux-2.6.10/arch/alpha/kernel/ptrace.c
--- linux-2.6.10_orig/arch/alpha/kernel/ptrace.c	2004-12-24 22:35:27.000000000 +0100
+++ linux-2.6.10/arch/alpha/kernel/ptrace.c	2005-03-02 13:15:44.000000000 +0100
@@ -14,6 +14,7 @@
 #include <linux/user.h>
 #include <linux/slab.h>
 #include <linux/security.h>
+#include <linux/grsecurity.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -288,6 +289,11 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out_notsk;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out;
+
+	if (gr_handle_ptrace(child, request))
+		goto out;
 
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
diff -ruN linux-2.6.10_orig/arch/alpha/kernel/systbls.S linux-2.6.10/arch/alpha/kernel/systbls.S
--- linux-2.6.10_orig/arch/alpha/kernel/systbls.S	2004-12-24 22:35:00.000000000 +0100
+++ linux-2.6.10/arch/alpha/kernel/systbls.S	2005-03-02 13:15:44.000000000 +0100
@@ -447,7 +447,7 @@
 	.quad sys_stat64			/* 425 */
 	.quad sys_lstat64
 	.quad sys_fstat64
-	.quad sys_ni_syscall			/* sys_vserver */
+	.quad sys_vserver			/* sys_vserver */
 	.quad sys_ni_syscall			/* sys_mbind */
 	.quad sys_ni_syscall			/* sys_get_mempolicy */
 	.quad sys_ni_syscall			/* sys_set_mempolicy */
diff -ruN linux-2.6.10_orig/arch/alpha/mm/fault.c linux-2.6.10/arch/alpha/mm/fault.c
--- linux-2.6.10_orig/arch/alpha/mm/fault.c	2004-12-24 22:34:30.000000000 +0100
+++ linux-2.6.10/arch/alpha/mm/fault.c	2005-03-02 13:10:40.000000000 +0100
@@ -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 @@
 	__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->mm->flags & MF_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 @@
  good_area:
 	si_code = SEGV_ACCERR;
 	if (cause < 0) {
-		if (!(vma->vm_flags & VM_EXEC))
+		if (!(vma->vm_flags & VM_EXEC)) {
+
+#ifdef CONFIG_PAX_PAGEEXEC
+			if (!(mm->flags & MF_PAX_PAGEEXEC) || address != regs->pc)
+				goto bad_area;
+
+			up_read(&mm->mmap_sem);
+			switch(pax_handle_fetch_fault(regs)) {
+
+#ifdef CONFIG_PAX_EMUPLT
+			case 2:
+			case 3:
+				return;
+#endif
+
+#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 -ruN linux-2.6.10_orig/arch/arm/Kconfig linux-2.6.10/arch/arm/Kconfig
--- linux-2.6.10_orig/arch/arm/Kconfig	2004-12-24 22:34:57.000000000 +0100
+++ linux-2.6.10/arch/arm/Kconfig	2005-03-02 13:15:44.000000000 +0100
@@ -709,6 +709,8 @@
 
 source "arch/arm/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/arm/kernel/ptrace.c linux-2.6.10/arch/arm/kernel/ptrace.c
--- linux-2.6.10_orig/arch/arm/kernel/ptrace.c	2004-12-24 22:33:59.000000000 +0100
+++ linux-2.6.10/arch/arm/kernel/ptrace.c	2005-03-02 13:15:44.000000000 +0100
@@ -754,6 +754,8 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out_tsk;
 
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
diff -ruN linux-2.6.10_orig/arch/arm/mm/mmap.c linux-2.6.10/arch/arm/mm/mmap.c
--- linux-2.6.10_orig/arch/arm/mm/mmap.c	2004-12-24 22:34:58.000000000 +0100
+++ linux-2.6.10/arch/arm/mm/mmap.c	2005-03-02 13:10:40.000000000 +0100
@@ -62,6 +62,10 @@
 	if (len > TASK_SIZE)
 		return -ENOMEM;
 
+#ifdef CONFIG_PAX_RANDMMAP
+	if (!(mm->flags & MF_PAX_RANDMMAP) || !filp)
+#endif
+
 	if (addr) {
 		if (do_align)
 			addr = COLOUR_ALIGN(addr, pgoff);
@@ -88,8 +92,8 @@
 			 * Start a new search - just in case we missed
 			 * some holes.
 			 */
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = addr = TASK_UNMAPPED_BASE;
+			if (start_addr != mm->mmap_base) {
+				start_addr = addr = mm->mmap_base;
 				goto full_search;
 			}
 			return -ENOMEM;
diff -ruN linux-2.6.10_orig/arch/arm26/Kconfig linux-2.6.10/arch/arm26/Kconfig
--- linux-2.6.10_orig/arch/arm26/Kconfig	2004-12-24 22:34:58.000000000 +0100
+++ linux-2.6.10/arch/arm26/Kconfig	2005-03-02 13:15:44.000000000 +0100
@@ -216,6 +216,8 @@
 
 source "arch/arm26/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/arm26/kernel/ptrace.c linux-2.6.10/arch/arm26/kernel/ptrace.c
--- linux-2.6.10_orig/arch/arm26/kernel/ptrace.c	2004-12-24 22:34:57.000000000 +0100
+++ linux-2.6.10/arch/arm26/kernel/ptrace.c	2005-03-02 13:15:44.000000000 +0100
@@ -691,6 +691,8 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out_tsk;
 
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
diff -ruN linux-2.6.10_orig/arch/cris/Kconfig linux-2.6.10/arch/cris/Kconfig
--- linux-2.6.10_orig/arch/cris/Kconfig	2004-12-24 22:35:28.000000000 +0100
+++ linux-2.6.10/arch/cris/Kconfig	2005-03-02 13:15:44.000000000 +0100
@@ -169,6 +169,8 @@
 
 source "arch/cris/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/h8300/Kconfig linux-2.6.10/arch/h8300/Kconfig
--- linux-2.6.10_orig/arch/h8300/Kconfig	2004-12-24 22:35:24.000000000 +0100
+++ linux-2.6.10/arch/h8300/Kconfig	2005-03-02 13:15:44.000000000 +0100
@@ -183,6 +183,8 @@
 
 source "arch/h8300/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/h8300/kernel/ptrace.c linux-2.6.10/arch/h8300/kernel/ptrace.c
--- linux-2.6.10_orig/arch/h8300/kernel/ptrace.c	2004-12-24 22:34:30.000000000 +0100
+++ linux-2.6.10/arch/h8300/kernel/ptrace.c	2005-03-02 13:15:44.000000000 +0100
@@ -80,6 +80,8 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out_tsk;
 
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
diff -ruN linux-2.6.10_orig/arch/i386/Kconfig linux-2.6.10/arch/i386/Kconfig
--- linux-2.6.10_orig/arch/i386/Kconfig	2004-12-24 22:34:01.000000000 +0100
+++ linux-2.6.10/arch/i386/Kconfig	2005-03-02 13:15:44.000000000 +0100
@@ -405,7 +405,7 @@
 
 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
@@ -553,6 +553,14 @@
 	depends on !SMP && X86_UP_IOAPIC
 	default y
 
+config KERNEL_HZ
+	int "Timer Frequency (100-20000)"
+	range 100 20000
+	default "1000"
+	help
+	  This allows you to specify the frequency at which the
+	  kernel timer interrupt will occur.
+
 config X86_TSC
 	bool
 	depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2) && !X86_NUMAQ
@@ -720,6 +728,46 @@
 
 endchoice
 
+choice
+	prompt "Memory Split User Space"
+	default SPLIT_3GB
+	help
+	  A different Userspace/Kernel split allows you to
+	  utilize up to alsmost 3GB of RAM without the requirement
+	  for HIGHMEM. It also increases the available lowmem.
+
+config SPLIT_3GB
+	bool "3.0GB/1.0GB Kernel (Default)"
+	help
+	  This is the default split of 3GB userspace to 1GB kernel
+	  space, which will result in about 860MB of lowmem.
+
+config SPLIT_25GB
+	bool "2.5GB/1.5GB Kernel"
+	help
+	  This split provides 2.5GB userspace and 1.5GB kernel
+	  space, which will result in about 1370MB of lowmem.
+
+config SPLIT_2GB
+	bool "2.0GB/2.0GB Kernel"
+	help
+	  This split provides 2GB userspace and 2GB kernel
+	  space, which will result in about 1880MB of lowmem.
+
+config SPLIT_15GB
+	bool "1.5GB/2.5GB Kernel"
+	help
+	  This split provides 1.5GB userspace and 2.5GB kernel
+	  space, which will result in about 2390MB of lowmem.
+
+config SPLIT_1GB
+	bool "1.0GB/3.0GB Kernel"
+	help
+	  This split provides 1GB userspace and 3GB kernel
+	  space, which will result in about 2900MB of lowmem.
+
+endchoice
+
 config HIGHMEM
 	bool
 	depends on HIGHMEM64G || HIGHMEM4G
@@ -1194,6 +1242,8 @@
 
 source "arch/i386/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/i386/kernel/apic.c linux-2.6.10/arch/i386/kernel/apic.c
--- linux-2.6.10_orig/arch/i386/kernel/apic.c	2004-12-24 22:35:49.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/apic.c	2005-03-02 13:15:44.000000000 +0100
@@ -877,23 +877,18 @@
 /* next tick in 8254 can be caught by catching timer wraparound */
 static void __init wait_8254_wraparound(void)
 {
-	unsigned int curr_count, prev_count=~0;
-	int delta;
+	unsigned int curr_count, prev_count;
 
 	curr_count = get_8254_timer_count();
-
 	do {
 		prev_count = curr_count;
 		curr_count = get_8254_timer_count();
-		delta = curr_count-prev_count;
 
-	/*
-	 * This limit for delta seems arbitrary, but it isn't, it's
-	 * slightly above the level of error a buggy Mercury/Neptune
-	 * chipset timer can cause.
-	 */
+		/* workaround for broken Mercury/Neptune */
+		if (prev_count >= curr_count + 0x100)
+			curr_count = get_8254_timer_count();
 
-	} while (delta < 300);
+	} while (prev_count >= curr_count);
 }
 
 /*
diff -ruN linux-2.6.10_orig/arch/i386/kernel/apm.c linux-2.6.10/arch/i386/kernel/apm.c
--- linux-2.6.10_orig/arch/i386/kernel/apm.c	2004-12-24 22:33:50.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/apm.c	2005-03-02 13:10:40.000000000 +0100
@@ -598,19 +598,39 @@
 	int			cpu;
 	struct desc_struct	save_desc_40;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long		cr3;
+#endif
+
 	cpus = apm_save_cpus();
-	
 	cpu = get_cpu();
-	save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8];
-	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc;
 
+#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);
-	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = save_desc_40;
+#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);
 	
@@ -640,20 +660,39 @@
 	int			cpu;
 	struct desc_struct	save_desc_40;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long		cr3;
+#endif
 
 	cpus = apm_save_cpus();
-	
 	cpu = get_cpu();
-	save_desc_40 = per_cpu(cpu_gdt_table, cpu)[0x40 / 8];
-	per_cpu(cpu_gdt_table, cpu)[0x40 / 8] = bad_bios_desc;
 
+#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);
-	__get_cpu_var(cpu_gdt_table)[0x40 / 8] = save_desc_40;
+#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);
 	return error;
@@ -2294,35 +2333,35 @@
 	apm_bios_entry.segment = APM_CS;
 
 	for (i = 0; i < NR_CPUS; i++) {
-		set_base(per_cpu(cpu_gdt_table, i)[APM_CS >> 3],
+		set_base(cpu_gdt_table[i][APM_CS >> 3],
 			 __va((unsigned long)apm_info.bios.cseg << 4));
-		set_base(per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3],
+		set_base(cpu_gdt_table[i][APM_CS_16 >> 3],
 			 __va((unsigned long)apm_info.bios.cseg_16 << 4));
-		set_base(per_cpu(cpu_gdt_table, i)[APM_DS >> 3],
+		set_base(cpu_gdt_table[i][APM_DS >> 3],
 			 __va((unsigned long)apm_info.bios.dseg << 4));
 #ifndef APM_RELAX_SEGMENTS
 		if (apm_info.bios.version == 0x100) {
 #endif
 			/* For ASUS motherboard, Award BIOS rev 110 (and others?) */
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 - 1);
 			/* For some unknown machine. */
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3], 64 * 1024 - 1);
 			/* For the DEC Hinote Ultra CT475 (and others?) */
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3], 64 * 1024 - 1);
+			_set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3], 64 * 1024 - 1);
 #ifndef APM_RELAX_SEGMENTS
 		} else {
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3],
+			_set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3],
 				(apm_info.bios.cseg_len - 1) & 0xffff);
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS_16 >> 3],
+			_set_limit((char *)&cpu_gdt_table[i][APM_CS_16 >> 3],
 				(apm_info.bios.cseg_16_len - 1) & 0xffff);
-			_set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_DS >> 3],
+			_set_limit((char *)&cpu_gdt_table[i][APM_DS >> 3],
 				(apm_info.bios.dseg_len - 1) & 0xffff);
 		      /* workaround for broken BIOSes */
 	                if (apm_info.bios.cseg_len <= apm_info.bios.offset)
-        	                _set_limit((char *)&per_cpu(cpu_gdt_table, i)[APM_CS >> 3], 64 * 1024 -1);
+        	                _set_limit((char *)&cpu_gdt_table[i][APM_CS >> 3], 64 * 1024 -1);
                        if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */
                         	/* for the BIOS that assumes granularity = 1 */
-                        	per_cpu(cpu_gdt_table, i)[APM_DS >> 3].b |= 0x800000;
+                        	cpu_gdt_table[i][APM_DS >> 3].b |= 0x800000;
                         	printk(KERN_NOTICE "apm: we set the granularity of dseg.\n");
         	        }
 		}
diff -ruN linux-2.6.10_orig/arch/i386/kernel/cpu/common.c linux-2.6.10/arch/i386/kernel/cpu/common.c
--- linux-2.6.10_orig/arch/i386/kernel/cpu/common.c	2004-12-24 22:33:50.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/cpu/common.c	2005-03-02 13:10:40.000000000 +0100
@@ -3,7 +3,6 @@
 #include <linux/delay.h>
 #include <linux/smp.h>
 #include <linux/module.h>
-#include <linux/percpu.h>
 #include <asm/semaphore.h>
 #include <asm/processor.h>
 #include <asm/i387.h>
@@ -13,8 +12,7 @@
 
 #include "cpu.h"
 
-DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]);
-EXPORT_PER_CPU_SYMBOL(cpu_gdt_table);
+EXPORT_SYMBOL_GPL(cpu_gdt_table);
 
 static int cachesize_override __initdata = -1;
 static int disable_x86_fxsr __initdata = 0;
@@ -334,21 +332,19 @@
 
 	generic_identify(c);
 
-	printk(KERN_DEBUG "CPU: After generic identify, caps: %08lx %08lx %08lx %08lx\n",
-		c->x86_capability[0],
-		c->x86_capability[1],
-		c->x86_capability[2],
-		c->x86_capability[3]);
+	printk(KERN_DEBUG "CPU: After generic identify, caps:");
+	for (i = 0; i < NCAPINTS; i++)
+		printk(" %08lx", c->x86_capability[i]);
+	printk("\n");
 
 	if (this_cpu->c_identify) {
 		this_cpu->c_identify(c);
 
-	printk(KERN_DEBUG "CPU: After vendor identify, caps:  %08lx %08lx %08lx %08lx\n",
-		c->x86_capability[0],
-		c->x86_capability[1],
-		c->x86_capability[2],
-		c->x86_capability[3]);
-}
+		printk(KERN_DEBUG "CPU: After vendor identify, caps:");
+		for (i = 0; i < NCAPINTS; i++)
+			printk(" %08lx", c->x86_capability[i]);
+		printk("\n");
+	}
 
 	/*
 	 * Vendor-specific initialization.  In this section we
@@ -363,6 +359,10 @@
 	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);
 
@@ -398,11 +398,10 @@
 
 	/* Now the feature flags better reflect actual CPU features! */
 
-	printk(KERN_DEBUG "CPU: After all inits, caps:        %08lx %08lx %08lx %08lx\n",
-	       c->x86_capability[0],
-	       c->x86_capability[1],
-	       c->x86_capability[2],
-	       c->x86_capability[3]);
+	printk(KERN_DEBUG "CPU: After all inits, caps:");
+	for (i = 0; i < NCAPINTS; i++)
+		printk(" %08lx", c->x86_capability[i]);
+	printk("\n");
 
 	/*
 	 * On SMP, boot_cpu_data holds the common feature set between
@@ -506,7 +505,7 @@
 void __init cpu_init (void)
 {
 	int cpu = smp_processor_id();
-	struct tss_struct * t = &per_cpu(init_tss, cpu);
+	struct tss_struct * t = init_tss + cpu;
 	struct thread_struct *thread = &current->thread;
 
 	if (test_and_set_bit(cpu, &cpu_initialized)) {
@@ -528,17 +527,16 @@
 	 * Initialize the per-CPU GDT with the boot GDT,
 	 * and set up the GDT descriptor:
 	 */
-	memcpy(&per_cpu(cpu_gdt_table, cpu), cpu_gdt_table,
-	       GDT_SIZE);
-	cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
-	cpu_gdt_descr[cpu].address =
-	    (unsigned long)&per_cpu(cpu_gdt_table, cpu);
+	if (cpu) {
+		memcpy(cpu_gdt_table[cpu], cpu_gdt_table[0], GDT_SIZE);
+		cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
+		cpu_gdt_descr[cpu].address = (unsigned long)cpu_gdt_table[cpu];
+	}
 
 	/*
 	 * Set up the per-thread TLS descriptor cache:
 	 */
-	memcpy(thread->tls_array, &per_cpu(cpu_gdt_table, cpu),
-		GDT_ENTRY_TLS_ENTRIES * 8);
+	memcpy(thread->tls_array, cpu_gdt_table[cpu], GDT_ENTRY_TLS_ENTRIES * 8);
 
 	__asm__ __volatile__("lgdt %0" : : "m" (cpu_gdt_descr[cpu]));
 	__asm__ __volatile__("lidt %0" : : "m" (idt_descr));
@@ -560,7 +558,7 @@
 	load_esp0(t, thread);
 	set_tss_desc(cpu,t);
 	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 -ruN linux-2.6.10_orig/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c linux-2.6.10/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c
--- linux-2.6.10_orig/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	2004-12-24 22:35:50.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c	2005-03-02 13:10:27.000000000 +0100
@@ -209,7 +209,7 @@
 	if ((gx_params->pci_suscfg & SUSMOD) == 0) 
 		return stock_freq;
 
-	return (stock_freq * gx_params->on_duration) 
+	return (stock_freq * gx_params->off_duration) 
 		/ (gx_params->on_duration + gx_params->off_duration);
 }
 
diff -ruN linux-2.6.10_orig/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c linux-2.6.10/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c
--- linux-2.6.10_orig/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2004-12-24 22:35:28.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c	2005-03-02 13:10:27.000000000 +0100
@@ -171,7 +171,7 @@
 		return speedstep_get_processor_frequency(SPEEDSTEP_PROCESSOR_PM);
 	}
 
-	if ((c->x86 == 0x06) && (c->x86_model == 0x13)) {
+	if ((c->x86 == 0x06) && (c->x86_model == 0x0D)) {
 		/* Pentium M (Dothan) */
 		printk(KERN_WARNING PFX "Warning: Pentium M detected. "
 		       "The speedstep_centrino module offers voltage scaling"
diff -ruN linux-2.6.10_orig/arch/i386/kernel/cpu/proc.c linux-2.6.10/arch/i386/kernel/cpu/proc.c
--- linux-2.6.10_orig/arch/i386/kernel/cpu/proc.c	2004-12-24 22:35:27.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/cpu/proc.c	2005-03-02 13:15:44.000000000 +0100
@@ -121,8 +121,8 @@
 			seq_printf(m, " %s", x86_cap_flags[i]);
 
 	seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n",
-		     c->loops_per_jiffy/(500000/HZ),
-		     (c->loops_per_jiffy/(5000/HZ)) % 100);
+		     HZ*(c->loops_per_jiffy >> 3)/62500,
+		     (HZ*(c->loops_per_jiffy >> 3)/625) % 100);
 	return 0;
 }
 
diff -ruN linux-2.6.10_orig/arch/i386/kernel/entry.S linux-2.6.10/arch/i386/kernel/entry.S
--- linux-2.6.10_orig/arch/i386/kernel/entry.S	2004-12-24 22:34:27.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/entry.S	2005-03-02 13:15:45.000000000 +0100
@@ -232,6 +232,15 @@
 	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
@@ -260,6 +269,11 @@
 	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
 
@@ -574,7 +588,7 @@
 	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
@@ -849,7 +863,7 @@
 	.long sys_tgkill	/* 270 */
 	.long sys_utimes
  	.long sys_fadvise64_64
-	.long sys_ni_syscall	/* sys_vserver */
+	.long sys_vserver
 	.long sys_mbind
 	.long sys_get_mempolicy
 	.long sys_set_mempolicy
diff -ruN linux-2.6.10_orig/arch/i386/kernel/head.S linux-2.6.10/arch/i386/kernel/head.S
--- linux-2.6.10_orig/arch/i386/kernel/head.S	2004-12-24 22:33:52.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/head.S	2005-03-02 13:10:40.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 @@
 	shrl $2,%ecx
 	rep ; stosl
 
+#ifdef CONFIG_PAX_KERNEXEC
+	movl $ __KERNEL_TEXT_OFFSET,%eax
+	movw %ax,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 2)
+	rorl $16,%eax
+	movb %al,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 4)
+	movb %ah,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 7)
+
+	movb %al,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 4)
+	movb %ah,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 7)
+	rorl $16,%eax
+	movw %ax,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 2)
+#endif
+
 /*
  * Initialize page tables.  This creates a PDE and a set of page
  * tables, which are located immediately beyond _end.  The variable
@@ -88,24 +107,39 @@
  * Warning: don't use %esi or the stack in this code.  However, %esp
  * can be used as a GPR if you really need it...
  */
-page_pde_offset = (__PAGE_OFFSET >> 20);
+page_pde_offset = ((__PAGE_OFFSET >> PMD_SHIFT) * (4096 / PTRS_PER_PTE));
 
 	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 @@
 
 	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
@@ -146,26 +181,27 @@
  *	not yet offset PAGE_OFFSET..
  */
 #define cr4_bits mmu_cr4_features-__PAGE_OFFSET
+3:
 	movl cr4_bits,%edx
 	andl %edx,%edx
-	jz 3f
+	jz 5f
 	movl %cr4,%eax		# Turn on paging options (PSE,PAE,..)
 	orl %edx,%eax
 	movl %eax,%cr4
 
-	btl $5, %eax		# check if PAE is enabled
-	jnc 6f
+#ifdef CONFIG_X86_PAE
+	movl %ebx,%edi
 
 	/* Check if extended functions are implemented */
 	movl $0x80000000, %eax
 	cpuid
 	cmpl $0x80000000, %eax
-	jbe 6f
+	jbe 4f
 	mov $0x80000001, %eax
 	cpuid
 	/* Execute Disable bit supported? */
 	btl $20, %edx
-	jnc 6f
+	jnc 4f
 
 	/* Setup EFER (Extended Feature Enable Register) */
 	movl $0xc0000080, %ecx
@@ -175,12 +211,10 @@
 	/* Make changes effective */
 	wrmsr
 
-6:
-	/* cpuid clobbered ebx, set it up again: */
-	xorl %ebx,%ebx
-	incl %ebx
-3:
-#endif /* CONFIG_SMP */
+4:
+	movl %edi,%ebx
+#endif
+5:
 
 /*
  * Enable paging
@@ -205,9 +239,7 @@
 
 #ifdef CONFIG_SMP
 	andl %ebx,%ebx
-	jz  1f				/* Initial CPU cleans BSS */
-	jmp checkCPUtype
-1:
+	jnz  checkCPUtype	/* Initial CPU cleans BSS */
 #endif /* CONFIG_SMP */
 
 /*
@@ -404,32 +436,75 @@
 	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
+
+#ifdef 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"
 
@@ -471,8 +546,8 @@
 	.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.
@@ -491,28 +566,27 @@
 	.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 */
@@ -521,3 +595,6 @@
 	.quad 0x0000000000000000	/* 0xf0 - unused */
 	.quad 0x0000000000000000	/* 0xf8 - GDT entry 31: double-fault TSS */
 
+#ifdef CONFIG_SMP
+	.fill (NR_CPUS-1)*GDT_ENTRIES,8,0 /* other CPU's GDT */
+#endif
diff -ruN linux-2.6.10_orig/arch/i386/kernel/init_task.c linux-2.6.10/arch/i386/kernel/init_task.c
--- linux-2.6.10_orig/arch/i386/kernel/init_task.c	2004-12-24 22:35:39.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/init_task.c	2005-03-02 13:10:40.000000000 +0100
@@ -42,5 +42,4 @@
  * per-CPU TSS segments. Threads are completely 'soft' on Linux,
  * no more per-task TSS's.
  */ 
-DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_maxaligned_in_smp = INIT_TSS;
-
+struct tss_struct init_tss[NR_CPUS] ____cacheline_maxaligned_in_smp = { [0 ... NR_CPUS-1] = INIT_TSS };
diff -ruN linux-2.6.10_orig/arch/i386/kernel/io_apic.c linux-2.6.10/arch/i386/kernel/io_apic.c
--- linux-2.6.10_orig/arch/i386/kernel/io_apic.c	2004-12-24 22:34:30.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/io_apic.c	2005-03-02 13:15:45.000000000 +0100
@@ -1764,7 +1764,7 @@
 
 	local_irq_enable();
 	/* Let ten ticks pass... */
-	mdelay((10 * 1000) / HZ);
+	mdelay((10 * 1000) / HZ + 1);
 
 	/*
 	 * Expect a few ticks at least, to be sure some possible
diff -ruN linux-2.6.10_orig/arch/i386/kernel/ioport.c linux-2.6.10/arch/i386/kernel/ioport.c
--- linux-2.6.10_orig/arch/i386/kernel/ioport.c	2004-12-24 22:34:44.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/ioport.c	2005-03-02 13:10:40.000000000 +0100
@@ -15,6 +15,7 @@
 #include <linux/stddef.h>
 #include <linux/slab.h>
 #include <linux/thread_info.h>
+#include <linux/grsecurity.h>
 
 /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
 static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
@@ -63,9 +64,16 @@
 
 	if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
 		return -EINVAL;
+#ifdef CONFIG_GRKERNSEC_IO
+	if (turn_on) {
+		gr_handle_ioperm();
+#else
 	if (turn_on && !capable(CAP_SYS_RAWIO))
+#endif
 		return -EPERM;
-
+#ifdef CONFIG_GRKERNSEC_IO
+	}
+#endif
 	/*
 	 * If it's the first ioperm() call in this thread's lifetime, set the
 	 * IO bitmap up. ioperm() is much less timing critical than clone(),
@@ -87,7 +95,7 @@
 	 * because the ->io_bitmap_max value must match the bitmap
 	 * contents:
 	 */
-	tss = &per_cpu(init_tss, get_cpu());
+	tss = init_tss + get_cpu();
 
 	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
 
@@ -137,8 +145,13 @@
 		return -EINVAL;
 	/* Trying to gain more privileges? */
 	if (level > old) {
+#ifdef CONFIG_GRKERNSEC_IO
+		gr_handle_iopl();
+		return -EPERM;
+#else
 		if (!capable(CAP_SYS_RAWIO))
 			return -EPERM;
+#endif
 	}
 	regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12);
 	/* Make sure we return the long way (not sysenter) */
diff -ruN linux-2.6.10_orig/arch/i386/kernel/irq.c linux-2.6.10/arch/i386/kernel/irq.c
--- linux-2.6.10_orig/arch/i386/kernel/irq.c	2004-12-24 22:33:51.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/irq.c	2005-03-02 13:10:40.000000000 +0100
@@ -113,10 +113,10 @@
  * gcc's 3.0 and earlier don't handle that correctly.
  */
 static char softirq_stack[NR_CPUS * THREAD_SIZE]
-		__attribute__((__aligned__(THREAD_SIZE)));
+		__attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
 
 static char hardirq_stack[NR_CPUS * THREAD_SIZE]
-		__attribute__((__aligned__(THREAD_SIZE)));
+		__attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
 
 /*
  * allocate per-cpu stacks for hardirq and for softirq processing
diff -ruN linux-2.6.10_orig/arch/i386/kernel/ldt.c linux-2.6.10/arch/i386/kernel/ldt.c
--- linux-2.6.10_orig/arch/i386/kernel/ldt.c	2004-12-24 22:35:23.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/ldt.c	2005-03-02 13:10:40.000000000 +0100
@@ -102,6 +102,19 @@
 		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;
 }
 
@@ -159,7 +172,7 @@
 {
 	int err;
 	unsigned long size;
-	void *address;
+	const void *address;
 
 	err = 0;
 	address = &default_ldt[0];
@@ -216,6 +229,13 @@
 		}
 	}
 
+#ifdef CONFIG_PAX_SEGMEXEC
+	if ((mm->flags & MF_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 -ruN linux-2.6.10_orig/arch/i386/kernel/process.c linux-2.6.10/arch/i386/kernel/process.c
--- linux-2.6.10_orig/arch/i386/kernel/process.c	2004-12-24 22:33:47.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/process.c	2005-03-02 13:10:40.000000000 +0100
@@ -309,7 +309,7 @@
 	/* The process may have allocated an io port bitmap... nuke it. */
 	if (unlikely(NULL != t->io_bitmap_ptr)) {
 		int cpu = get_cpu();
-		struct tss_struct *tss = &per_cpu(init_tss, cpu);
+		struct tss_struct *tss = init_tss + cpu;
 
 		kfree(t->io_bitmap_ptr);
 		t->io_bitmap_ptr = NULL;
@@ -329,6 +329,9 @@
 {
 	struct task_struct *tsk = current;
 
+	__asm__("movl %0,%%fs\n"
+		"movl %0,%%gs\n"
+		: : "r" (0) : "memory");
 	memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
 	memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));	
 	/*
@@ -371,7 +374,7 @@
 	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;
 	*childregs = *regs;
 	childregs->eax = 0;
 	childregs->esp = esp;
@@ -476,9 +479,8 @@
 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;
@@ -560,12 +562,20 @@
 	struct thread_struct *prev = &prev_p->thread,
 				 *next = &next_p->thread;
 	int cpu = smp_processor_id();
-	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+	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:
 	 */
@@ -576,6 +586,10 @@
 	 */
 	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.
@@ -724,6 +738,10 @@
 	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;
@@ -757,8 +775,17 @@
 		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;
@@ -812,3 +839,29 @@
 	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 -ruN linux-2.6.10_orig/arch/i386/kernel/ptrace.c linux-2.6.10/arch/i386/kernel/ptrace.c
--- linux-2.6.10_orig/arch/i386/kernel/ptrace.c	2004-12-24 22:34:29.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/ptrace.c	2005-03-02 13:15:45.000000000 +0100
@@ -15,6 +15,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
+#include <linux/grsecurity.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -278,11 +279,16 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out_tsk;
 
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
 		goto out_tsk;
 
+	if (gr_handle_ptrace(child, request))
+		goto out_tsk;
+
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
 		goto out_tsk;
@@ -361,6 +367,17 @@
 			  if(addr == (long) &dummy->u_debugreg[5]) break;
 			  if(addr < (long) &dummy->u_debugreg[4] &&
 			     ((unsigned long) data) >= TASK_SIZE-3) break;
+
+#ifdef CONFIG_GRKERNSEC
+			  if(addr >= (long) &dummy->u_debugreg[0] &&
+			     addr <= (long) &dummy->u_debugreg[3]){
+				long reg   = (addr - (long) &dummy->u_debugreg[0]) >> 2;
+				long type  = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 4*reg)) & 3;
+				long align = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 2 + 4*reg)) & 3;
+				if((type & 1) && (data & align))
+					break;
+			  }
+#endif
 			  
 			  /* Sanity-check data. Take one half-byte at once with
 			   * check = (val >> (16 + 4*i)) & 0xf. It contains the
diff -ruN linux-2.6.10_orig/arch/i386/kernel/reboot.c linux-2.6.10/arch/i386/kernel/reboot.c
--- linux-2.6.10_orig/arch/i386/kernel/reboot.c	2004-12-24 22:34:29.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/reboot.c	2005-03-02 13:10:40.000000000 +0100
@@ -152,18 +152,18 @@
    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, NULL },
diff -ruN linux-2.6.10_orig/arch/i386/kernel/setup.c linux-2.6.10/arch/i386/kernel/setup.c
--- linux-2.6.10_orig/arch/i386/kernel/setup.c	2004-12-24 22:34:45.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/setup.c	2005-03-02 13:10:40.000000000 +0100
@@ -72,7 +72,11 @@
 /* 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
@@ -1354,7 +1358,7 @@
 
 	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);
@@ -1423,6 +1427,15 @@
 #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 -ruN linux-2.6.10_orig/arch/i386/kernel/signal.c linux-2.6.10/arch/i386/kernel/signal.c
--- linux-2.6.10_orig/arch/i386/kernel/signal.c	2004-12-24 22:34:44.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/signal.c	2005-03-02 13:10:40.000000000 +0100
@@ -384,7 +384,17 @@
 	if (err)
 		goto give_sigsegv;
 
+#ifdef CONFIG_PAX_NOVSYSCALL
+	restorer = frame->retcode;
+#else
 	restorer = &__kernel_sigreturn;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->mm->flags & MF_PAX_SEGMEXEC)
+		restorer -= SEGMEXEC_TASK_SIZE;
+#endif
+#endif
+
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 
@@ -481,7 +491,18 @@
 		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->mm->flags & MF_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 -ruN linux-2.6.10_orig/arch/i386/kernel/smpboot.c linux-2.6.10/arch/i386/kernel/smpboot.c
--- linux-2.6.10_orig/arch/i386/kernel/smpboot.c	2004-12-24 22:34:45.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/smpboot.c	2005-03-02 13:15:45.000000000 +0100
@@ -1024,8 +1024,8 @@
 	printk(KERN_INFO
 		"Total of %d processors activated (%lu.%02lu BogoMIPS).\n",
 		cpucount+1,
-		bogosum/(500000/HZ),
-		(bogosum/(5000/HZ))%100);
+		HZ*(bogosum >> 3)/62500,
+		(HZ*(bogosum >> 3)/625) % 100);
 	
 	Dprintk("Before bogocount - setting activated=1.\n");
 
diff -ruN linux-2.6.10_orig/arch/i386/kernel/sysenter.c linux-2.6.10/arch/i386/kernel/sysenter.c
--- linux-2.6.10_orig/arch/i386/kernel/sysenter.c	2004-12-24 22:35:40.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/sysenter.c	2005-03-02 13:10:40.000000000 +0100
@@ -24,7 +24,7 @@
 void enable_sep_cpu(void *info)
 {
 	int cpu = get_cpu();
-	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+	struct tss_struct *tss = init_tss + cpu;
 
 	tss->ss1 = __KERNEL_CS;
 	tss->esp1 = sizeof(struct tss_struct) + (unsigned long) tss;
@@ -41,6 +41,7 @@
 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)
 {
 	void *page = (void *)get_zeroed_page(GFP_ATOMIC);
@@ -63,3 +64,4 @@
 }
 
 __initcall(sysenter_setup);
+#endif
diff -ruN linux-2.6.10_orig/arch/i386/kernel/sys_i386.c linux-2.6.10/arch/i386/kernel/sys_i386.c
--- linux-2.6.10_orig/arch/i386/kernel/sys_i386.c	2004-12-24 22:35:39.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/sys_i386.c	2005-03-02 13:17:44.000000000 +0100
@@ -19,6 +19,8 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
+#include <linux/grsecurity.h>
+#include <linux/vs_cvirt.h>
 
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
@@ -49,6 +51,11 @@
 	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);
@@ -56,6 +63,12 @@
 			goto out;
 	}
 
+	if (gr_handle_mmap(file, prot)) {
+		fput(file);
+		error = -EACCES;
+		goto out;
+	}
+
 	down_write(&current->mm->mmap_sem);
 	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
@@ -106,6 +119,182 @@
 	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_size = TASK_SIZE;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (mm->flags & MF_PAX_SEGMEXEC)
+		task_size = SEGMEXEC_TASK_SIZE;
+#endif
+
+	if (len > task_size)
+		return -ENOMEM;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (!(mm->flags & MF_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);
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (mm->flags & MF_PAX_RANDMMAP)
+		start_mmap += 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 = mm->mmap_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 != mm->mmap_base) {
+				start_addr = addr = mm->mmap_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;
+	}
+}
+
+unsigned long
+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
+			  const unsigned long len, const unsigned long pgoff,
+			  const unsigned long flags)
+{
+	struct vm_area_struct *vma, *prev_vma;
+	struct mm_struct *mm = current->mm;
+	unsigned long base = mm->mmap_base, addr = addr0, task_size = TASK_SIZE;
+	int first_time = 1;
+
+	if (flags & MAP_EXECUTABLE) {
+		mm->mmap_base = TASK_UNMAPPED_BASE;
+
+#ifdef CONFIG_PAX_RANDMMAP
+		if (mm->flags & MF_PAX_RANDMMAP)
+			mm->mmap_base += mm->delta_mmap;
+#endif
+
+		mm->free_area_cache = mm->mmap_base;
+		addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+		mm->free_area_cache = base;
+		mm->mmap_base = base;
+		return addr;
+	}
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (mm->flags & MF_PAX_SEGMEXEC)
+		task_size = SEGMEXEC_TASK_SIZE;
+#endif
+
+	/* requested length too big for entire address space */
+	if (len > task_size)
+		return -ENOMEM;
+
+	/* dont allow allocations above current base */
+	if (mm->free_area_cache > base)
+		mm->free_area_cache = base;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (!(mm->flags & MF_PAX_RANDMMAP) || !filp)
+#endif
+
+	/* requesting a specific address */
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (task_size - len >= addr &&
+				(!vma || addr + len <= vma->vm_start))
+			return addr;
+	}
+
+try_again:
+	/* make sure it can fit in the remaining address space */
+	if (mm->free_area_cache < len)
+		goto fail;
+
+	/* either no address requested or cant fit in requested address hole */
+	addr = (mm->free_area_cache - len) & PAGE_MASK;
+	do {
+		/*
+		 * Lookup failure means no vma is above this address,
+		 * i.e. return with success:
+		 */
+		if (!(vma = find_vma_prev(mm, addr, &prev_vma)))
+			return addr;
+
+		/*
+		 * new region fits between prev_vma->vm_end and
+		 * vma->vm_start, use it:
+		 */
+		if (addr+len <= vma->vm_start)
+			/* remember the address as a hint for next time */
+			return (mm->free_area_cache = addr);
+		else
+			/* pull free_area_cache down to the first hole */
+			if (mm->free_area_cache == vma->vm_end)
+				mm->free_area_cache = vma->vm_start;
+
+		/* try just below the current vma->vm_start */
+		addr = vma->vm_start-len;
+	} while (len <= vma->vm_start);
+
+fail:
+	/*
+	* if hint left us with no space for the requested
+	* mapping then try again:
+	*/
+	if (first_time) {
+		mm->free_area_cache = base;
+		first_time = 0;
+		goto try_again;
+	}
+	/*
+	 * A failed mmap() very likely causes application failure,
+	 * so fall back to the bottom-up function here. This scenario
+	 * can happen with large stack limits and large mmap()
+	 * allocations.
+	 */
+	mm->free_area_cache = TASK_UNMAPPED_BASE;
+	addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
+	/*
+	 * Restore the topdown base:
+	 */
+	mm->free_area_cache = base;
+
+	return addr;
+}
 
 struct sel_arg_struct {
 	unsigned long n;
@@ -217,7 +406,7 @@
 	if (!name)
 		return -EFAULT;
 	down_read(&uts_sem);
-	err=copy_to_user(name, &system_utsname, sizeof (*name));
+	err=copy_to_user(name, vx_new_utsname(), sizeof (*name));
 	up_read(&uts_sem);
 	return err?-EFAULT:0;
 }
@@ -225,6 +414,7 @@
 asmlinkage int sys_olduname(struct oldold_utsname __user * name)
 {
 	int error;
+	struct new_utsname *ptr;
 
 	if (!name)
 		return -EFAULT;
@@ -233,15 +423,16 @@
   
   	down_read(&uts_sem);
 	
-	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+	ptr = vx_new_utsname();
+	error = __copy_to_user(&name->sysname,ptr->sysname,__OLD_UTS_LEN);
 	error |= __put_user(0,name->sysname+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->nodename,ptr->nodename,__OLD_UTS_LEN);
 	error |= __put_user(0,name->nodename+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->release,ptr->release,__OLD_UTS_LEN);
 	error |= __put_user(0,name->release+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->version,ptr->version,__OLD_UTS_LEN);
 	error |= __put_user(0,name->version+__OLD_UTS_LEN);
-	error |= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+	error |= __copy_to_user(&name->machine,ptr->machine,__OLD_UTS_LEN);
 	error |= __put_user(0,name->machine+__OLD_UTS_LEN);
 	
 	up_read(&uts_sem);
diff -ruN linux-2.6.10_orig/arch/i386/kernel/traps.c linux-2.6.10/arch/i386/kernel/traps.c
--- linux-2.6.10_orig/arch/i386/kernel/traps.c	2004-12-24 22:34:01.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/traps.c	2005-03-02 13:15:45.000000000 +0100
@@ -27,6 +27,7 @@
 #include <linux/ptrace.h>
 #include <linux/utsname.h>
 #include <linux/kprobes.h>
+#include <linux/binfmts.h>
 
 #ifdef CONFIG_EISA
 #include <linux/ioport.h>
@@ -53,23 +54,19 @@
 
 #include <linux/irq.h>
 #include <linux/module.h>
+#include <linux/vserver/debug.h>
 
 #include "mach_traps.h"
 
 asmlinkage int system_call(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);
@@ -115,6 +112,7 @@
 				unsigned long *stack, unsigned long ebp)
 {
 	unsigned long addr;
+	int i = kstack_depth_to_print;
 
 #ifdef	CONFIG_FRAME_POINTER
 	while (valid_stack_ptr(tinfo, (void *)ebp)) {
@@ -123,6 +121,7 @@
 		print_symbol("%s", addr);
 		printk("\n");
 		ebp = *(unsigned long *)ebp;
+		--i;
 	}
 #else
 	while (valid_stack_ptr(tinfo, stack)) {
@@ -131,6 +130,7 @@
 			printk(" [<%08lx>]", addr);
 			print_symbol(" %s", addr);
 			printk("\n");
+			--i;
 		}
 	}
 #endif
@@ -240,7 +240,7 @@
 
 		printk("Code: ");
 
-		eip = (u8 *)regs->eip - 43;
+		eip = (u8 *)regs->eip - 43 + __KERNEL_TEXT_OFFSET;
 		for (i = 0; i < 64; i++, eip++) {
 			unsigned char c;
 
@@ -268,7 +268,7 @@
 	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;
@@ -306,6 +306,7 @@
 	};
 	static int die_counter;
 
+	vxh_throw_oops();
 	if (die.lock_owner != smp_processor_id()) {
 		console_verbose();
 		spin_lock_irq(&die.lock);
@@ -340,6 +341,7 @@
 	bust_spinlocks(0);
 	die.lock_owner = -1;
 	spin_unlock_irq(&die.lock);
+	vxh_dump_history();
 	if (in_interrupt())
 		panic("Fatal exception in interrupt");
 
@@ -456,7 +458,7 @@
 fastcall void do_general_protection(struct pt_regs * regs, long error_code)
 {
 	int cpu = get_cpu();
-	struct tss_struct *tss = &per_cpu(init_tss, cpu);
+	struct tss_struct *tss = &init_tss[cpu];
 	struct thread_struct *thread = &current->thread;
 
 	/*
@@ -491,6 +493,24 @@
 	if (!(regs->xcs & 3))
 		goto gp_in_kernel;
 
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (current->mm) {
+		struct mm_struct *mm = current->mm;
+		unsigned long limit;
+
+		if (mm->flags & MF_PAX_PAGEEXEC) {
+			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);
@@ -506,6 +526,13 @@
 		if (notify_die(DIE_GPF, "general protection fault", regs,
 				error_code, 13, SIGSEGV) == NOTIFY_STOP)
 			return;
+
+#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);
 	}
 }
@@ -941,6 +968,8 @@
 #ifdef CONFIG_X86_F00F_BUG
 void __init trap_init_f00f_bug(void)
 {
+
+#ifndef CONFIG_PAX_KERNEXEC
 	__set_fixmap(FIX_F00F_IDT, __pa(&idt_table), PAGE_KERNEL_RO);
 
 	/*
@@ -949,6 +978,8 @@
 	 */
 	idt_descr.address = fix_to_virt(FIX_F00F_IDT);
 	__asm__ __volatile__("lidt %0" : : "m" (idt_descr));
+#endif
+
 }
 #endif
 
diff -ruN linux-2.6.10_orig/arch/i386/kernel/vm86.c linux-2.6.10/arch/i386/kernel/vm86.c
--- linux-2.6.10_orig/arch/i386/kernel/vm86.c	2004-12-24 22:33:59.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/vm86.c	2005-03-02 13:10:40.000000000 +0100
@@ -121,7 +121,7 @@
 		do_exit(SIGSEGV);
 	}
 
-	tss = &per_cpu(init_tss, get_cpu());
+	tss = init_tss + get_cpu();
 	current->thread.esp0 = current->thread.saved_esp0;
 	current->thread.sysenter_cs = __KERNEL_CS;
 	load_esp0(tss, &current->thread);
@@ -303,7 +303,7 @@
 	asm volatile("movl %%fs,%0":"=m" (tsk->thread.saved_fs));
 	asm volatile("movl %%gs,%0":"=m" (tsk->thread.saved_gs));
 
-	tss = &per_cpu(init_tss, get_cpu());
+	tss = init_tss + get_cpu();
 	tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
 	if (cpu_has_sep)
 		tsk->thread.sysenter_cs = 0;
diff -ruN linux-2.6.10_orig/arch/i386/kernel/vmlinux.lds.S linux-2.6.10/arch/i386/kernel/vmlinux.lds.S
--- linux-2.6.10_orig/arch/i386/kernel/vmlinux.lds.S	2004-12-24 22:35:50.000000000 +0100
+++ linux-2.6.10/arch/i386/kernel/vmlinux.lds.S	2005-03-02 13:10:40.000000000 +0100
@@ -2,9 +2,12 @@
  * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
  */
 
+#include <linux/config.h>
+
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
 #include <asm/page.h>
+#include <asm/segment.h>
 
 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
 OUTPUT_ARCH(i386)
@@ -13,56 +16,15 @@
 SECTIONS
 {
   . = __PAGE_OFFSET + 0x100000;
-  /* read-only */
-  _text = .;			/* Text and read-only data */
-  .text : {
-	*(.text)
-	SCHED_TEXT
-	LOCK_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
+  .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 = .;
@@ -88,9 +50,13 @@
   .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 = .;
@@ -100,15 +66,107 @@
   __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
+	LOCK_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 = .; 
 
diff -ruN linux-2.6.10_orig/arch/i386/mm/fault.c linux-2.6.10/arch/i386/mm/fault.c
--- linux-2.6.10_orig/arch/i386/mm/fault.c	2004-12-24 22:33:48.000000000 +0100
+++ linux-2.6.10/arch/i386/mm/fault.c	2005-03-02 13:10:40.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>
@@ -107,7 +110,7 @@
 		desc = (void *)desc + (seg & ~7);
 	} else {
 		/* Must disable preemption while reading the GDT. */
-		desc = (u32 *)&per_cpu(cpu_gdt_table, get_cpu());
+		desc = (u32 *)&cpu_gdt_table[get_cpu()];
 		desc = (void *)desc + (seg & ~7);
 	}
 
@@ -203,6 +206,27 @@
 
 fastcall 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,10 +243,14 @@
 	struct mm_struct *mm;
 	struct vm_area_struct * vma;
 	unsigned long address;
-	unsigned long page;
 	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));
 
@@ -234,6 +262,7 @@
 		local_irq_enable();
 
 	tsk = current;
+	mm = tsk->mm;
 
 	info.si_code = SEGV_MAPERR;
 
@@ -260,14 +289,99 @@
 		goto bad_area_nosemaphore;
 	} 
 
-	mm = tsk->mm;
-
 	/*
 	 * If we're in an interrupt, have no user context or are running in an
 	 * atomic region then we must not take the fault..
 	 */
 	if (in_atomic() || !mm)
-		goto bad_area_nosemaphore;
+		goto bad_area_nopax;
+
+#ifdef CONFIG_PAX_PAGEEXEC
+	if (unlikely((error_code & 5) != 5 ||
+		     (regs->eflags & X86_EFLAGS_VM) ||
+		     !(mm->flags & MF_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
 
 	/* When running in the kernel we expect faults to occur only to
 	 * addresses in user space.  All other faults represent errors in the
@@ -287,7 +401,7 @@
 	if (!down_read_trylock(&mm->mmap_sem)) {
 		if ((error_code & 4) == 0 &&
 		    !search_exception_tables(regs->eip))
-			goto bad_area_nosemaphore;
+			goto bad_area_nopax;
 		down_read(&mm->mmap_sem);
 	}
 
@@ -376,6 +490,45 @@
 	up_read(&mm->mmap_sem);
 
 bad_area_nosemaphore:
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+	if (mm && (error_code & 4) && !(regs->eflags & X86_EFLAGS_VM)) {
+
+#ifdef CONFIG_PAX_PAGEEXEC
+		if ((mm->flags & MF_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 ((mm->flags & MF_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
+
+bad_area_nopax:
 	/* User mode accesses just cause a SIGSEGV */
 	if (error_code & 4) {
 		/* 
@@ -443,28 +596,51 @@
 #endif
 	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) {
+		if (tsk->curr_ip)
+			printk(KERN_ERR "PAX: From %u.%u.%u.%u: %s:%d, uid/euid: %u/%u, attempted to modify kernel code",
+					 NIPQUAD(tsk->curr_ip), tsk->comm, tsk->pid, tsk->uid, tsk->euid);
+		else
+			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);
 	printk(KERN_ALERT " printing eip:\n");
 	printk("%08lx\n", regs->eip);
-	asm("movl %%cr3,%0":"=r" (page));
-	page = ((unsigned long *) __va(page))[address >> 22];
-	printk(KERN_ALERT "*pde = %08lx\n", page);
-	/*
-	 * We must not directly access the pte in the highpte
-	 * case, the page table might be allocated in highmem.
-	 * And lets rather not kmap-atomic the pte, just in case
-	 * it's allocated already.
-	 */
+	{
+		unsigned long index = pgd_index(address);
+		unsigned long pgd_paddr;
+		pgd_t *pgd;
+		pmd_t *pmd;
+		pte_t *pte;
+
+		asm("movl %%cr3,%0":"=r" (pgd_paddr));
+		pgd = index + (pgd_t *)__va(pgd_paddr);
+		printk(KERN_ALERT "*pgd = %016llx\n", (u64)pgd_val(*pgd));
+		if (pgd_present(*pgd)) {
+			pmd = pmd_offset(pgd, address);
+			printk(KERN_ALERT "*pmd = %016llx\n", (u64)pmd_val(*pmd));
+			/*
+			 * We must not directly access the pte in the highpte
+			 * case, the page table might be allocated in highmem.
+			 * And lets rather not kmap-atomic the pte, just in case
+			 * it's allocated already.
+			 */
 #ifndef CONFIG_HIGHPTE
-	if (page & 1) {
-		page &= PAGE_MASK;
-		address &= 0x003ff000;
-		page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
-		printk(KERN_ALERT "*pte = %08lx\n", page);
-	}
+			if (pmd_present(*pmd) && !pmd_large(*pmd)) {
+				pte = pte_offset_kernel(pmd, address);
+				printk(KERN_ALERT "*pte = %016llx\n", (u64)pte_val(*pte));
+			}
 #endif
+		}
+	}
 	die("Oops", regs, error_code);
 	bust_spinlocks(0);
 	do_exit(SIGKILL);
@@ -515,7 +691,7 @@
 		 * Do _not_ use "tsk" here. We might be inside
 		 * an interrupt in the middle of a task switch..
 		 */
-		int index = pgd_index(address);
+		unsigned long index = pgd_index(address);
 		unsigned long pgd_paddr;
 		pgd_t *pgd, *pgd_k;
 		pmd_t *pmd, *pmd_k;
@@ -545,3 +721,252 @@
 		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->mm->flags & MF_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 -ruN linux-2.6.10_orig/arch/i386/mm/hugetlbpage.c linux-2.6.10/arch/i386/mm/hugetlbpage.c
--- linux-2.6.10_orig/arch/i386/mm/hugetlbpage.c	2004-12-24 22:35:28.000000000 +0100
+++ linux-2.6.10/arch/i386/mm/hugetlbpage.c	2005-03-02 13:15:45.000000000 +0100
@@ -42,7 +42,8 @@
 {
 	pte_t entry;
 
-	mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+	// mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+	vx_rsspages_add(mm, HPAGE_SIZE / PAGE_SIZE);
 	if (write_access) {
 		entry =
 		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
@@ -82,7 +83,8 @@
 		ptepage = pte_page(entry);
 		get_page(ptepage);
 		set_pte(dst_pte, entry);
-		dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+		// dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+		vx_rsspages_add(dst, HPAGE_SIZE / PAGE_SIZE);
 		addr += HPAGE_SIZE;
 	}
 	return 0;
@@ -218,7 +220,8 @@
 		page = pte_page(pte);
 		put_page(page);
 	}
-	mm->rss -= (end - start) >> PAGE_SHIFT;
+	// mm->rss -= (end - start) >> PAGE_SHIFT;
+	vx_rsspages_sub(mm, (end - start) >> PAGE_SHIFT);
 	flush_tlb_range(vma, start, end);
 }
 
diff -ruN linux-2.6.10_orig/arch/i386/mm/init.c linux-2.6.10/arch/i386/mm/init.c
--- linux-2.6.10_orig/arch/i386/mm/init.c	2004-12-24 22:35:23.000000000 +0100
+++ linux-2.6.10/arch/i386/mm/init.c	2005-03-02 13:10:40.000000000 +0100
@@ -39,6 +39,7 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
+#include <asm/desc.h>
 
 unsigned int __VMALLOC_RESERVE = 128 << 20;
 
@@ -48,27 +49,6 @@
 static int noinline 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.
  */
@@ -110,9 +90,6 @@
 	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)) 
@@ -149,7 +126,7 @@
 	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++) {
@@ -306,13 +283,6 @@
 	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);
@@ -336,17 +306,6 @@
 	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)
@@ -380,11 +339,7 @@
 	 * 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();
 }
 
@@ -505,15 +460,17 @@
 
 	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();
@@ -609,7 +566,7 @@
 	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); 
@@ -626,10 +583,6 @@
 		(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();
 
@@ -700,6 +653,43 @@
 {
 	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));
+		}
+
+#ifdef CONFIG_X86_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
+
+		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 -ruN linux-2.6.10_orig/arch/i386/mm/mmap.c linux-2.6.10/arch/i386/mm/mmap.c
--- linux-2.6.10_orig/arch/i386/mm/mmap.c	2004-12-24 22:34:33.000000000 +0100
+++ linux-2.6.10/arch/i386/mm/mmap.c	2005-03-02 13:10:40.000000000 +0100
@@ -38,13 +38,19 @@
 static inline unsigned long mmap_base(struct mm_struct *mm)
 {
 	unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
+	unsigned long task_size = TASK_SIZE;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (mm->flags & MF_PAX_SEGMEXEC)
+		task_size = SEGMEXEC_TASK_SIZE;
+#endif
 
 	if (gap < MIN_GAP)
 		gap = MIN_GAP;
 	else if (gap > MAX_GAP)
 		gap = MAX_GAP;
 
-	return TASK_SIZE - (gap & PAGE_MASK);
+	return task_size - (gap & PAGE_MASK);
 }
 
 /*
@@ -61,10 +67,22 @@
 			(current->personality & ADDR_COMPAT_LAYOUT) ||
 			current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
 		mm->mmap_base = TASK_UNMAPPED_BASE;
+
+#ifdef CONFIG_PAX_RANDMMAP
+		if (mm->flags & MF_PAX_RANDMMAP)
+			mm->mmap_base += mm->delta_mmap;
+#endif
+
 		mm->get_unmapped_area = arch_get_unmapped_area;
 		mm->unmap_area = arch_unmap_area;
 	} else {
 		mm->mmap_base = mmap_base(mm);
+
+#ifdef CONFIG_PAX_RANDMMAP
+		if (mm->flags & MF_PAX_RANDMMAP)
+			mm->mmap_base -= mm->delta_mmap;
+#endif
+
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
 		mm->unmap_area = arch_unmap_area_topdown;
 	}
diff -ruN linux-2.6.10_orig/arch/i386/pci/pcbios.c linux-2.6.10/arch/i386/pci/pcbios.c
--- linux-2.6.10_orig/arch/i386/pci/pcbios.c	2004-12-24 22:33:51.000000000 +0100
+++ linux-2.6.10/arch/i386/pci/pcbios.c	2005-03-02 13:10:40.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 -ruN linux-2.6.10_orig/arch/i386/power/cpu.c linux-2.6.10/arch/i386/power/cpu.c
--- linux-2.6.10_orig/arch/i386/power/cpu.c	2004-12-24 22:35:24.000000000 +0100
+++ linux-2.6.10/arch/i386/power/cpu.c	2005-03-02 13:10:40.000000000 +0100
@@ -83,10 +83,9 @@
 static void fix_processor_context(void)
 {
 	int cpu = smp_processor_id();
-	struct tss_struct * t = &per_cpu(init_tss, cpu);
+	struct tss_struct * t = init_tss + cpu;
 
 	set_tss_desc(cpu,t);	/* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
-        per_cpu(cpu_gdt_table, cpu)[GDT_ENTRY_TSS].b &= 0xfffffdff;
 
 	load_TR_desc();				/* This does ltr */
 	load_LDT(&current->active_mm->context);	/* This does lldt */
diff -ruN linux-2.6.10_orig/arch/ia64/ia32/binfmt_elf32.c linux-2.6.10/arch/ia64/ia32/binfmt_elf32.c
--- linux-2.6.10_orig/arch/ia64/ia32/binfmt_elf32.c	2004-12-24 22:35:28.000000000 +0100
+++ linux-2.6.10/arch/ia64/ia32/binfmt_elf32.c	2005-03-02 13:15:45.000000000 +0100
@@ -43,6 +43,17 @@
 
 #define elf_read_implies_exec(ex, have_pt_gnu_stack)	(!(have_pt_gnu_stack))
 
+#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"
 
@@ -199,7 +210,7 @@
 int
 ia32_setup_arg_pages (struct linux_binprm *bprm, int executable_stack)
 {
-	unsigned long stack_base;
+	unsigned long stack_base, grow;
 	struct vm_area_struct *mpnt;
 	struct mm_struct *mm = current->mm;
 	int i, ret;
@@ -216,8 +227,10 @@
 	if (!mpnt)
 		return -ENOMEM;
 
-	if (security_vm_enough_memory((IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))
-				      >> PAGE_SHIFT)) {
+	grow = (IA32_STACK_TOP - (PAGE_MASK & (unsigned long) bprm->p))
+		>> PAGE_SHIFT;
+	if (security_vm_enough_memory(grow) ||
+		!vx_vmpages_avail(mm, grow)) {
 		kmem_cache_free(vm_area_cachep, mpnt);
 		return -ENOMEM;
 	}
@@ -242,7 +255,9 @@
 			kmem_cache_free(vm_area_cachep, mpnt);
 			return ret;
 		}
-		current->mm->stack_vm = current->mm->total_vm = vma_pages(mpnt);
+		// current->mm->stack_vm = current->mm->total_vm = vma_pages(mpnt);
+		vx_vmpages_sub(current->mm, current->mm->total_vm - vma_pages(mpnt));
+		current->mm->stack_vm = current->mm->total_vm;
 	}
 
 	for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
diff -ruN linux-2.6.10_orig/arch/ia64/ia32/ia32priv.h linux-2.6.10/arch/ia64/ia32/ia32priv.h
--- linux-2.6.10_orig/arch/ia64/ia32/ia32priv.h	2004-12-24 22:35:39.000000000 +0100
+++ linux-2.6.10/arch/ia64/ia32/ia32priv.h	2005-03-02 13:10:40.000000000 +0100
@@ -326,10 +326,17 @@
 #define ELF_ARCH	EM_386
 
 #define IA32_PAGE_OFFSET	0xc0000000
-#define IA32_STACK_TOP		IA32_PAGE_OFFSET
 #define IA32_GATE_OFFSET	IA32_PAGE_OFFSET
 #define IA32_GATE_END		IA32_PAGE_OFFSET + PAGE_SIZE
 
+#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
  * access them.
diff -ruN linux-2.6.10_orig/arch/ia64/ia32/sys_ia32.c linux-2.6.10/arch/ia64/ia32/sys_ia32.c
--- linux-2.6.10_orig/arch/ia64/ia32/sys_ia32.c	2004-12-24 22:35:00.000000000 +0100
+++ linux-2.6.10/arch/ia64/ia32/sys_ia32.c	2005-03-02 13:10:40.000000000 +0100
@@ -939,6 +939,11 @@
 
 	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);
@@ -960,6 +965,11 @@
 	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 -ruN linux-2.6.10_orig/arch/ia64/Kconfig linux-2.6.10/arch/ia64/Kconfig
--- linux-2.6.10_orig/arch/ia64/Kconfig	2004-12-24 22:35:29.000000000 +0100
+++ linux-2.6.10/arch/ia64/Kconfig	2005-03-02 13:15:45.000000000 +0100
@@ -387,6 +387,8 @@
 
 source "arch/ia64/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/ia64/kernel/entry.S linux-2.6.10/arch/ia64/kernel/entry.S
--- linux-2.6.10_orig/arch/ia64/kernel/entry.S	2004-12-24 22:34:27.000000000 +0100
+++ linux-2.6.10/arch/ia64/kernel/entry.S	2005-03-02 13:15:45.000000000 +0100
@@ -1526,7 +1526,7 @@
 	data8 sys_mq_notify
 	data8 sys_mq_getsetattr
 	data8 sys_ni_syscall			// reserved for kexec_load
-	data8 sys_ni_syscall			// reserved for vserver
+	data8 sys_vserver
 	data8 sys_waitid			// 1270
 	data8 sys_add_key
 	data8 sys_request_key
diff -ruN linux-2.6.10_orig/arch/ia64/kernel/perfmon.c linux-2.6.10/arch/ia64/kernel/perfmon.c
--- linux-2.6.10_orig/arch/ia64/kernel/perfmon.c	2004-12-24 22:35:28.000000000 +0100
+++ linux-2.6.10/arch/ia64/kernel/perfmon.c	2005-03-02 13:15:45.000000000 +0100
@@ -39,6 +39,8 @@
 #include <linux/mount.h>
 #include <linux/version.h>
 #include <linux/bitops.h>
+#include <linux/vs_memory.h>
+#include <linux/vs_cvirt.h>
 
 #include <asm/errno.h>
 #include <asm/intrinsics.h>
@@ -2341,7 +2343,8 @@
 	 */
 	insert_vm_struct(mm, vma);
 
-	mm->total_vm  += size >> PAGE_SHIFT;
+	// mm->total_vm  += size >> PAGE_SHIFT;
+	vx_vmpages_add(mm, size >> PAGE_SHIFT);
 	vm_stat_account(vma);
 	up_write(&task->mm->mmap_sem);
 
diff -ruN linux-2.6.10_orig/arch/ia64/kernel/ptrace.c linux-2.6.10/arch/ia64/kernel/ptrace.c
--- linux-2.6.10_orig/arch/ia64/kernel/ptrace.c	2004-12-24 22:35:40.000000000 +0100
+++ linux-2.6.10/arch/ia64/kernel/ptrace.c	2005-03-02 13:15:45.000000000 +0100
@@ -17,6 +17,7 @@
 #include <linux/smp_lock.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/grsecurity.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -1326,10 +1327,16 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out_tsk;
+
 	ret = -EPERM;
 	if (pid == 1)		/* no messing around with init! */
 		goto out_tsk;
 
+	if (gr_handle_ptrace(child, request))
+		goto out_tsk;
+
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
 		goto out_tsk;
diff -ruN linux-2.6.10_orig/arch/ia64/kernel/sys_ia64.c linux-2.6.10/arch/ia64/kernel/sys_ia64.c
--- linux-2.6.10_orig/arch/ia64/kernel/sys_ia64.c	2004-12-24 22:34:58.000000000 +0100
+++ linux-2.6.10/arch/ia64/kernel/sys_ia64.c	2005-03-02 13:10:40.000000000 +0100
@@ -18,6 +18,7 @@
 #include <linux/syscalls.h>
 #include <linux/highuid.h>
 #include <linux/hugetlb.h>
+#include <linux/grsecurity.h>
 
 #include <asm/shmparam.h>
 #include <asm/uaccess.h>
@@ -27,7 +28,7 @@
 			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 +39,15 @@
 	if (REGION_NUMBER(addr) == REGION_HPAGE)
 		addr = 0;
 #endif
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (mm->flags & MF_PAX_RANDMMAP)
+		task_unmapped_base += mm->delta_mmap;
+	if ((mm->flags & MF_PAX_RANDMMAP) && addr && filp)
+		addr = mm->free_area_cache;
+	else
+#endif
+
 	if (!addr)
 		addr = mm->free_area_cache;
 
@@ -56,9 +66,9 @@
 	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 +195,11 @@
 	unsigned long roff;
 	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);
@@ -222,6 +237,11 @@
 		goto out;
 	}
 
+	if (gr_handle_mmap(file, prot)) {
+		addr = -EACCES;
+		goto out;
+	}
+
 	down_write(&current->mm->mmap_sem);
 	addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
diff -ruN linux-2.6.10_orig/arch/ia64/mm/fault.c linux-2.6.10/arch/ia64/mm/fault.c
--- linux-2.6.10_orig/arch/ia64/mm/fault.c	2004-12-24 22:35:39.000000000 +0100
+++ linux-2.6.10/arch/ia64/mm/fault.c	2005-03-02 13:18:03.000000000 +0100
@@ -9,11 +9,13 @@
 #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>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <linux/vs_memory.h>
 
 extern void die (char *, struct pt_regs *, long);
 
@@ -33,12 +35,19 @@
 
 	grow = PAGE_SIZE >> PAGE_SHIFT;
 	if (address - vma->vm_start > current->signal->rlim[RLIMIT_STACK].rlim_cur
-	    || (((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > current->signal->rlim[RLIMIT_AS].rlim_cur))
+	    || (((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) >
+		current->signal->rlim[RLIMIT_AS].rlim_cur))
+		return -ENOMEM;
+	if (!vx_vmpages_avail(vma->vm_mm, grow) ||
+		((vma->vm_flags & VM_LOCKED) &&
+		!vx_vmlocked_avail(vma->vm_mm, grow)))
 		return -ENOMEM;
 	vma->vm_end += PAGE_SIZE;
-	vma->vm_mm->total_vm += grow;
+	// vma->vm_mm->total_vm += grow;
+	vx_vmpages_add(vma->vm_mm, grow);
 	if (vma->vm_flags & VM_LOCKED)
-		vma->vm_mm->locked_vm += grow;
+		// vma->vm_mm->locked_vm += grow;
+		vx_vmlocked_add(vma->vm_mm, grow);
 	__vm_stat_account(vma->vm_mm, vma->vm_flags, vma->vm_file, grow);
 	return 0;
 }
@@ -70,6 +79,54 @@
 	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->mm->flags & MF_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 +182,31 @@
 		| (((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 (!(mm->flags & MF_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 -ruN linux-2.6.10_orig/arch/ia64/mm/hugetlbpage.c linux-2.6.10/arch/ia64/mm/hugetlbpage.c
--- linux-2.6.10_orig/arch/ia64/mm/hugetlbpage.c	2004-12-24 22:34:49.000000000 +0100
+++ linux-2.6.10/arch/ia64/mm/hugetlbpage.c	2005-03-02 13:15:45.000000000 +0100
@@ -65,7 +65,8 @@
 {
 	pte_t entry;
 
-	mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+	// mm->rss += (HPAGE_SIZE / PAGE_SIZE);
+	vx_rsspages_add(mm, HPAGE_SIZE / PAGE_SIZE);
 	if (write_access) {
 		entry =
 		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
@@ -108,7 +109,8 @@
 		ptepage = pte_page(entry);
 		get_page(ptepage);
 		set_pte(dst_pte, entry);
-		dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+		// dst->rss += (HPAGE_SIZE / PAGE_SIZE);
+		vx_rsspages_add(dst, HPAGE_SIZE / PAGE_SIZE);
 		addr += HPAGE_SIZE;
 	}
 	return 0;
@@ -249,7 +251,8 @@
 		put_page(page);
 		pte_clear(pte);
 	}
-	mm->rss -= (end - start) >> PAGE_SHIFT;
+	// mm->rss -= (end - start) >> PAGE_SHIFT;
+	vx_rsspages_sub(mm, (end - start) >> PAGE_SHIFT);
 	flush_tlb_range(vma, start, end);
 }
 
diff -ruN linux-2.6.10_orig/arch/m68k/atari/stram.c linux-2.6.10/arch/m68k/atari/stram.c
--- linux-2.6.10_orig/arch/m68k/atari/stram.c	2004-12-24 22:35:23.000000000 +0100
+++ linux-2.6.10/arch/m68k/atari/stram.c	2005-03-02 13:15:45.000000000 +0100
@@ -635,7 +635,8 @@
 	set_pte(dir, pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
 	swap_free(entry);
 	get_page(page);
-	++vma->vm_mm->rss;
+	// ++vma->vm_mm->rss;
+	vx_rsspages_inc(vma->vm_mm);
 }
 
 static inline void unswap_pmd(struct vm_area_struct * vma, pmd_t *dir,
diff -ruN linux-2.6.10_orig/arch/m68k/Kconfig linux-2.6.10/arch/m68k/Kconfig
--- linux-2.6.10_orig/arch/m68k/Kconfig	2004-12-24 22:34:58.000000000 +0100
+++ linux-2.6.10/arch/m68k/Kconfig	2005-03-02 13:15:45.000000000 +0100
@@ -659,6 +659,8 @@
 
 source "arch/m68k/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/m68k/kernel/ptrace.c linux-2.6.10/arch/m68k/kernel/ptrace.c
--- linux-2.6.10_orig/arch/m68k/kernel/ptrace.c	2004-12-24 22:34:29.000000000 +0100
+++ linux-2.6.10/arch/m68k/kernel/ptrace.c	2005-03-02 13:15:45.000000000 +0100
@@ -140,6 +140,8 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out_tsk;
 
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
diff -ruN linux-2.6.10_orig/arch/m68knommu/Kconfig linux-2.6.10/arch/m68knommu/Kconfig
--- linux-2.6.10_orig/arch/m68knommu/Kconfig	2004-12-24 22:35:23.000000000 +0100
+++ linux-2.6.10/arch/m68knommu/Kconfig	2005-03-02 13:15:45.000000000 +0100
@@ -581,6 +581,8 @@
 
 source "arch/m68knommu/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/m68knommu/kernel/ptrace.c linux-2.6.10/arch/m68knommu/kernel/ptrace.c
--- linux-2.6.10_orig/arch/m68knommu/kernel/ptrace.c	2004-12-24 22:34:58.000000000 +0100
+++ linux-2.6.10/arch/m68knommu/kernel/ptrace.c	2005-03-02 13:15:45.000000000 +0100
@@ -124,6 +124,8 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out_tsk;
 
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
diff -ruN linux-2.6.10_orig/arch/mips/Kconfig linux-2.6.10/arch/mips/Kconfig
--- linux-2.6.10_orig/arch/mips/Kconfig	2004-12-24 22:34:45.000000000 +0100
+++ linux-2.6.10/arch/mips/Kconfig	2005-03-02 13:15:45.000000000 +0100
@@ -1581,6 +1581,8 @@
 
 source "arch/mips/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/mips/kernel/binfmt_elfn32.c linux-2.6.10/arch/mips/kernel/binfmt_elfn32.c
--- linux-2.6.10_orig/arch/mips/kernel/binfmt_elfn32.c	2004-12-24 22:34:58.000000000 +0100
+++ linux-2.6.10/arch/mips/kernel/binfmt_elfn32.c	2005-03-02 13:10:40.000000000 +0100
@@ -50,6 +50,17 @@
 #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 -ruN linux-2.6.10_orig/arch/mips/kernel/binfmt_elfo32.c linux-2.6.10/arch/mips/kernel/binfmt_elfo32.c
--- linux-2.6.10_orig/arch/mips/kernel/binfmt_elfo32.c	2004-12-24 22:34:30.000000000 +0100
+++ linux-2.6.10/arch/mips/kernel/binfmt_elfo32.c	2005-03-02 13:10:40.000000000 +0100
@@ -52,6 +52,17 @@
 #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 -ruN linux-2.6.10_orig/arch/mips/kernel/irixelf.c linux-2.6.10/arch/mips/kernel/irixelf.c
--- linux-2.6.10_orig/arch/mips/kernel/irixelf.c	2004-12-24 22:35:50.000000000 +0100
+++ linux-2.6.10/arch/mips/kernel/irixelf.c	2005-03-02 13:15:45.000000000 +0100
@@ -127,7 +127,9 @@
 	end = PAGE_ALIGN(end);
 	if (end <= start)
 		return;
+	down_write(&current->mm->mmap_sem);
 	do_brk(start, end - start);
+	up_write(&current->mm->mmap_sem);
 }
 
 
@@ -375,7 +377,9 @@
 
 	/* Map the last of the bss segment */
 	if (last_bss > len) {
+		down_write(&current->mm->mmap_sem);
 		do_brk(len, (last_bss - len));
+		up_write(&current->mm->mmap_sem);
 	}
 	kfree(elf_phdata);
 
@@ -562,7 +566,9 @@
 	unsigned long v;
 	struct prda *pp;
 
+	down_write(&current->mm->mmap_sem);
 	v =  do_brk (PRDA_ADDRESS, PAGE_SIZE);
+	up_write(&current->mm->mmap_sem);
 
 	if (v < 0)
 		return;
@@ -684,7 +690,8 @@
 	/* Do this so that we can load the interpreter, if need be.  We will
 	 * change some of these later.
 	 */
-	current->mm->rss = 0;
+	// current->mm->rss = 0;
+	vx_rsspages_sub(current->mm, current->mm->rss);
 	setup_arg_pages(bprm, EXSTACK_DEFAULT);
 	current->mm->start_stack = bprm->p;
 
@@ -852,8 +859,11 @@
 
 	len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
 	bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
-	if (bss > len)
+	if (bss > len) {
+	  down_write(&current->mm->mmap_sem);
 	  do_brk(len, bss-len);
+	  up_write(&current->mm->mmap_sem);
+	}
 	kfree(elf_phdata);
 	return 0;
 }
diff -ruN linux-2.6.10_orig/arch/mips/kernel/linux32.c linux-2.6.10/arch/mips/kernel/linux32.c
--- linux-2.6.10_orig/arch/mips/kernel/linux32.c	2004-12-24 22:35:00.000000000 +0100
+++ linux-2.6.10/arch/mips/kernel/linux32.c	2005-03-02 13:15:45.000000000 +0100
@@ -1208,7 +1208,7 @@
 	int ret = 0;
 
 	down_read(&uts_sem);
-	if (copy_to_user(name,&system_utsname,sizeof *name))
+	if (copy_to_user(name, vx_new_utsname(), sizeof *name))
 		ret = -EFAULT;
 	up_read(&uts_sem);
 
diff -ruN linux-2.6.10_orig/arch/mips/kernel/ptrace.c linux-2.6.10/arch/mips/kernel/ptrace.c
--- linux-2.6.10_orig/arch/mips/kernel/ptrace.c	2004-12-24 22:35:49.000000000 +0100
+++ linux-2.6.10/arch/mips/kernel/ptrace.c	2005-03-02 13:15:45.000000000 +0100
@@ -76,6 +76,8 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out_tsk;
 
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
diff -ruN linux-2.6.10_orig/arch/mips/kernel/syscall.c linux-2.6.10/arch/mips/kernel/syscall.c
--- linux-2.6.10_orig/arch/mips/kernel/syscall.c	2004-12-24 22:35:24.000000000 +0100
+++ linux-2.6.10/arch/mips/kernel/syscall.c	2005-03-02 13:15:45.000000000 +0100
@@ -25,6 +25,7 @@
 #include <linux/msg.h>
 #include <linux/shm.h>
 #include <linux/compiler.h>
+#include <linux/vs_cvirt.h>
 
 #include <asm/branch.h>
 #include <asm/cachectl.h>
@@ -87,6 +88,11 @@
 	do_color_align = 0;
 	if (filp || (flags & MAP_SHARED))
 		do_color_align = 1;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (!(current->mm->flags & MF_PAX_RANDMMAP) || !filp)
+#endif
+
 	if (addr) {
 		if (do_color_align)
 			addr = COLOUR_ALIGN(addr, pgoff);
@@ -97,6 +103,13 @@
 		    (!vmm || addr + len <= vmm->vm_start))
 			return addr;
 	}
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if ((current->mm->flags & MF_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);
@@ -212,7 +225,7 @@
  */
 asmlinkage int sys_uname(struct old_utsname * name)
 {
-	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
+	if (name && !copy_to_user(name, vx_new_utsname(), sizeof (*name)))
 		return 0;
 	return -EFAULT;
 }
@@ -223,21 +236,23 @@
 asmlinkage int sys_olduname(struct oldold_utsname * name)
 {
 	int error;
+	struct new_utsname *ptr;
 
 	if (!name)
 		return -EFAULT;
 	if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname)))
 		return -EFAULT;
 
-	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+	ptr = vx_new_utsname();
+	error = __copy_to_user(&name->sysname,ptr->sysname,__OLD_UTS_LEN);
 	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->nodename,ptr->nodename,__OLD_UTS_LEN);
 	error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->release,ptr->release,__OLD_UTS_LEN);
 	error -= __put_user(0,name->release+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->version,ptr->version,__OLD_UTS_LEN);
 	error -= __put_user(0,name->version+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->machine,ptr->machine,__OLD_UTS_LEN);
 	error = __put_user(0,name->machine+__OLD_UTS_LEN);
 	error = error ? -EFAULT : 0;
 
@@ -263,10 +278,10 @@
 			return -EFAULT;
 
 		down_write(&uts_sem);
-		strncpy(system_utsname.nodename, nodename, len);
+		strncpy(vx_new_uts(nodename), nodename, len);
 		nodename[__NEW_UTS_LEN] = '\0';
-		strlcpy(system_utsname.nodename, nodename,
-		        sizeof(system_utsname.nodename));
+		strlcpy(vx_new_uts(nodename), nodename,
+			sizeof(vx_new_uts(nodename)));
 		up_write(&uts_sem);
 		return 0;
 	}
diff -ruN linux-2.6.10_orig/arch/mips/kernel/sysirix.c linux-2.6.10/arch/mips/kernel/sysirix.c
--- linux-2.6.10_orig/arch/mips/kernel/sysirix.c	2004-12-24 22:35:28.000000000 +0100
+++ linux-2.6.10/arch/mips/kernel/sysirix.c	2005-03-02 13:15:45.000000000 +0100
@@ -30,6 +30,7 @@
 #include <linux/socket.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/vs_cvirt.h>
 
 #include <asm/ptrace.h>
 #include <asm/page.h>
@@ -582,7 +583,8 @@
 	/*
 	 * Check if we have enough memory..
 	 */
-	if (security_vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT)) {
+	if (security_vm_enough_memory((newbrk-oldbrk) >> PAGE_SHIFT) ||
+		!vx_vmpages_avail(mm, (newbrk-oldbrk) >> PAGE_SHIFT)) {
 		ret = -ENOMEM;
 		goto out;
 	}
diff -ruN linux-2.6.10_orig/arch/mips/mm/fault.c linux-2.6.10/arch/mips/mm/fault.c
--- linux-2.6.10_orig/arch/mips/mm/fault.c	2004-12-24 22:34:29.000000000 +0100
+++ linux-2.6.10/arch/mips/mm/fault.c	2005-03-02 13:10:40.000000000 +0100
@@ -26,6 +26,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 -ruN linux-2.6.10_orig/arch/parisc/Kconfig linux-2.6.10/arch/parisc/Kconfig
--- linux-2.6.10_orig/arch/parisc/Kconfig	2004-12-24 22:35:00.000000000 +0100
+++ linux-2.6.10/arch/parisc/Kconfig	2005-03-02 13:15:45.000000000 +0100
@@ -190,6 +190,8 @@
 
 source "arch/parisc/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/parisc/kernel/ptrace.c linux-2.6.10/arch/parisc/kernel/ptrace.c
--- linux-2.6.10_orig/arch/parisc/kernel/ptrace.c	2004-12-24 22:34:00.000000000 +0100
+++ linux-2.6.10/arch/parisc/kernel/ptrace.c	2005-03-02 13:15:45.000000000 +0100
@@ -17,6 +17,7 @@
 #include <linux/personality.h>
 #include <linux/security.h>
 #include <linux/compat.h>
+#include <linux/grsecurity.h>
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
@@ -110,10 +111,16 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out_tsk;
+
 	ret = -EPERM;
 	if (pid == 1)		/* no messing around with init! */
 		goto out_tsk;
 
+	if (gr_handle_ptrace(child, request))
+		goto out_tsk;
+
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
 		goto out_tsk;
diff -ruN linux-2.6.10_orig/arch/parisc/kernel/sys_parisc32.c linux-2.6.10/arch/parisc/kernel/sys_parisc32.c
--- linux-2.6.10_orig/arch/parisc/kernel/sys_parisc32.c	2004-12-24 22:34:30.000000000 +0100
+++ linux-2.6.10/arch/parisc/kernel/sys_parisc32.c	2005-03-02 13:15:45.000000000 +0100
@@ -680,6 +680,7 @@
 
 	do {
 		seq = read_seqbegin(&xtime_lock);
+		/* requires vx virtualization */
 		val.uptime = jiffies / HZ;
 
 		val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
diff -ruN linux-2.6.10_orig/arch/parisc/kernel/sys_parisc.c linux-2.6.10/arch/parisc/kernel/sys_parisc.c
--- linux-2.6.10_orig/arch/parisc/kernel/sys_parisc.c	2004-12-24 22:35:25.000000000 +0100
+++ linux-2.6.10/arch/parisc/kernel/sys_parisc.c	2005-03-02 13:10:40.000000000 +0100
@@ -31,6 +31,7 @@
 #include <linux/shm.h>
 #include <linux/smp_lock.h>
 #include <linux/syscalls.h>
+#include <linux/grsecurity.h>
 
 int sys_pipe(int *fildes)
 {
@@ -104,6 +105,13 @@
 {
 	if (len > TASK_SIZE)
 		return -ENOMEM;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if ((current->mm->flags & MF_PAX_RANDMMAP) && (!addr || filp))
+		addr = TASK_UNMAPPED_BASE + current->mm->delta_mmap;
+	else
+#endif
+
 	if (!addr)
 		addr = TASK_UNMAPPED_BASE;
 
@@ -123,12 +131,23 @@
 {
 	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)
 			goto out;
 	}
 
+	if (gr_handle_mmap(file, prot)) {
+		fput(file);
+		return -EACCES;
+	}
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 
 	down_write(&current->mm->mmap_sem);
diff -ruN linux-2.6.10_orig/arch/parisc/kernel/traps.c linux-2.6.10/arch/parisc/kernel/traps.c
--- linux-2.6.10_orig/arch/parisc/kernel/traps.c	2004-12-24 22:35:50.000000000 +0100
+++ linux-2.6.10/arch/parisc/kernel/traps.c	2005-03-02 13:10:40.000000000 +0100
@@ -680,9 +680,7 @@
 
 			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 -ruN linux-2.6.10_orig/arch/parisc/mm/fault.c linux-2.6.10/arch/parisc/mm/fault.c
--- linux-2.6.10_orig/arch/parisc/mm/fault.c	2004-12-24 22:35:25.000000000 +0100
+++ linux-2.6.10/arch/parisc/mm/fault.c	2005-03-02 13:10:40.000000000 +0100
@@ -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>
@@ -57,7 +59,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) {
@@ -143,6 +145,139 @@
 			}
 #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->mm->flags & MF_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->mm->flags & MF_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)
 {
@@ -168,8 +303,38 @@
 
 	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 ((mm->flags & MF_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 -ruN linux-2.6.10_orig/arch/ppc/Kconfig linux-2.6.10/arch/ppc/Kconfig
--- linux-2.6.10_orig/arch/ppc/Kconfig	2004-12-24 22:35:40.000000000 +0100
+++ linux-2.6.10/arch/ppc/Kconfig	2005-03-02 13:15:45.000000000 +0100
@@ -1211,6 +1211,8 @@
 
 source "arch/ppc/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -ruN linux-2.6.10_orig/arch/ppc/kernel/misc.S linux-2.6.10/arch/ppc/kernel/misc.S
--- linux-2.6.10_orig/arch/ppc/kernel/misc.S	2004-12-24 22:35:28.000000000 +0100
+++ linux-2.6.10/arch/ppc/kernel/misc.S	2005-03-02 13:15:45.000000000 +0100
@@ -1435,7 +1435,7 @@
 	.long ppc_fadvise64_64
 	.long sys_ni_syscall		/* 255 - rtas (used on ppc64) */
 	.long sys_ni_syscall		/* 256 reserved for sys_debug_setcontext */
-	.long sys_ni_syscall		/* 257 reserved for vserver */
+	.long sys_vserver
 	.long sys_ni_syscall		/* 258 reserved for new sys_remap_file_pages */
 	.long sys_ni_syscall		/* 259 reserved for new sys_mbind */
 	.long sys_ni_syscall		/* 260 reserved for new sys_get_mempolicy */
diff -ruN linux-2.6.10_orig/arch/ppc/kernel/ptrace.c linux-2.6.10/arch/ppc/kernel/ptrace.c
--- linux-2.6.10_orig/arch/ppc/kernel/ptrace.c	2004-12-24 22:34:27.000000000 +0100
+++ linux-2.6.10/arch/ppc/kernel/ptrace.c	2005-03-02 13:15:45.000000000 +0100
@@ -26,6 +26,7 @@
 #include <linux/ptrace.h>
 #include <linux/user.h>
 #include <linux/security.h>
+#include <linux/grsecurity.h>
 
 #include <asm/uaccess.h>
 #include <asm/page.h>
@@ -262,11 +263,16 @@
 	read_unlock(&tasklist_lock);
 	if (!child)
 		goto out;
+	if (!vx_check(vx_task_xid(child), VX_WATCH|VX_IDENT))
+		goto out_tsk;
 
 	ret = -EPERM;
 	if (pid == 1)		/* you may not mess with init */
 		goto out_tsk;
 
+	if (gr_handle_ptrace(child, request))
+		goto out_tsk;
+
 	if (request == PTRACE_ATTACH) {
 		ret = ptrace_attach(child);
 		goto out_tsk;
diff -ruN linux-2.6.10_orig/arch/ppc/kernel/syscalls.c linux-2.6.10/arch/ppc/kernel/syscalls.c
--- linux-2.6.10_orig/arch/ppc/kernel/syscalls.c	2004-12-24 22:35:29.000000000 +0100
+++ linux-2.6.10/arch/ppc/kernel/syscalls.c	2005-03-02 13:18:23.000000000 +0100
@@ -36,6 +36,8 @@
 #include <linux/utsname.h>
 #include <linux/file.h>
 #include <linux/unistd.h>
+#include <linux/grsecurity.h>
+#include <linux/vs_cvirt.h>
 
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
@@ -165,12 +167,23 @@
 	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)))
 			goto out;
 	}
 
+	if (gr_handle_mmap(file, prot)) {
+		fput(file);
+		ret = -EACCES;
+		goto out;
+	}
+
 	down_write(&current->mm->mmap_sem);
 	ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
 	up_write(&current->mm->mmap_sem);
@@ -229,7 +242,7 @@
 	int err = -EFAULT;
 
 	down_read(&uts_sem);
-	if (name && !copy_to_user(name, &system_utsname, sizeof (*name)))
+	if (name && !copy_to_user(name, vx_new_utsname(), sizeof (*name)))
 		err = 0;
 	up_read(&uts_sem);
 	return err;
@@ -238,6 +251,7 @@
 int sys_olduname(struct oldold_utsname __user * name)
 {
 	int error;
+	struct new_utsname *ptr;
 
 	if (!name)
 		return -EFAULT;
@@ -245,15 +259,16 @@
 		return -EFAULT;
 
 	down_read(&uts_sem);
-	error = __copy_to_user(&name->sysname,&system_utsname.sysname,__OLD_UTS_LEN);
+	ptr = vx_new_utsname();
+	error = __copy_to_user(&name->sysname,ptr->sysname,__OLD_UTS_LEN);
 	error -= __put_user(0,name->sysname+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->nodename,&system_utsname.nodename,__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->nodename,ptr->nodename,__OLD_UTS_LEN);
 	error -= __put_user(0,name->nodename+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->release,&system_utsname.release,__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->release,ptr->release,__OLD_UTS_LEN);
 	error -= __put_user(0,name->release+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->version,&system_utsname.version,__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->version,ptr->version,__OLD_UTS_LEN);
 	error -= __put_user(0,name->version+__OLD_UTS_LEN);
-	error -= __copy_to_user(&name->machine,&system_utsname.machine,__OLD_UTS_LEN);
+	error -= __copy_to_user(&name->machine,ptr->machine,__OLD_UTS_LEN);
 	error = __put_user(0,name->machine+__OLD_UTS_LEN);
 	up_read(&uts_sem);
 
diff -ruN linux-2.6.10_orig/arch/ppc/mm/fault.c linux-2.6.10/arch/ppc/mm/fault.c
--- linux-2.6.10_orig/arch/ppc/mm/fault.c	2004-12-24 22:34:29.000000000 +0100
+++ linux-2.6.10/arch/ppc/mm/fault.c	2005-03-02 13:10:40.000000000 +0100
@@ -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_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->mm->flags & MF_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_