diff -urNPp --minimal linux-2.6.11/Documentation/vserver/debug.txt vs-1.9.5rc1-grsec-2.1.3/Documentation/vserver/debug.txt
--- linux-2.6.11/Documentation/vserver/debug.txt	1970-01-01 01:00:00.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/Documentation/vserver/debug.txt	2005-03-08 09:27:34.023395464 +0100
@@ -0,0 +1,171 @@
+
+debug_switch:
+
+ 0   1
+
+ 1   2
+
+ 2   4
+
+ 3   8
+
+ 4  16
+
+ 5  32
+
+ 6  64
+
+ 7 128
+
+
+debug_xid:
+
+ 0   1	"alloc_vx_info(%d) = %p\n"
+	"dealloc_vx_info(%p)"
+	"loc_vx_info(%d) = %p (not available)"
+	"loc_vx_info(%d) = %p (found)"
+	"loc_vx_info(%d) = %p (new)"
+
+ 1   2	"alloc_vx_info(%d)*"
+	"loc_vx_info(%d)*"
+	"locate_vx_info(%d)"
+
+ 2   4	"get_vx_info(%p[#%d.%d])"
+	"put_vx_info(%p[#%d.%d])"
+
+ 3   8	"set_vx_info(%p[#%d.%d.%d])"
+	"clr_vx_info(%p[#%d.%d.%d])"
+	"rcu_free_vx_info(%p): uc=%d"
+
+ 4  16	"__hash_vx_info: %p[#%d]"
+	"__unhash_vx_info: %p[#%d]"
+	"__vx_dynamic_id: [#%d]"
+
+ 5  32	"vx_migrate_task(%p,%p[#%d.%d])"
+	"task_get_vx_info(%p)"
+
+ 6  64	"vx_set_init(%p[#%d],%p[#%d,%d,%d])"
+
+ 7 128	"vx_propagate_xid(%p[#%d.%d]): %d"
+
+
+debug_nid:
+
+ 0   1	"alloc_nx_info() = %p"
+	"dealloc_nx_info(%p)"
+	"loc_nx_info(%d) = %p (not available)"
+	"loc_nx_info(%d) = %p (found)"
+	"loc_nx_info(%d) = %p (new)"
+
+ 1   2	"alloc_nx_info(%d)*"
+	"loc_nx_info(%d)*"
+
+ 2   4	"get_nx_info(%p[#%d.%d])"
+	"put_nx_info(%p[#%d.%d])"
+
+ 3   8	"set_nx_info(%p[#%d.%d.%d])"
+	"clr_nx_info(%p[#%d.%d.%d])"
+	"rcu_free_nx_info(%p): uc=%d"
+
+ 4  16	"__hash_nx_info: %p[#%d]"
+	"__unhash_nx_info: %p[#%d]"
+	"__nx_dynamic_id: [#%d]"
+
+ 5  32	"nx_migrate_task(%p,%p[#%d.%d])"
+	"task_get_nx_info(%p)"
+	"create_nx_info()"
+
+ 6  64
+
+ 7 128
+
+
+debug_dlim:
+
+ 0   1	"alloc_dl_info(%p,%d) = %p"
+	"dealloc_dl_info(%p)"
+	"locate_dl_info(%p,#%d) = %p"
+
+ 1   2	"alloc_dl_info(%p,%d)*"
+
+ 2   4	"get_dl_info(%p[#%d.%d])"
+	"put_dl_info(%p[#%d.%d])"
+
+ 3   8	"rcu_free_dl_info(%p)"
+	"__hash_dl_info: %p[#%d]"
+	"__unhash_dl_info: %p[#%d]"
+
+
+ 4  16	"ALLOC (%p,#%d)%c inode (%d)"
+	"FREE  (%p,#%d)%c inode"
+
+ 5  32	"ALLOC (%p,#%d)%c %lld bytes (%d)"
+	"FREE  (%p,#%d)%c %lld bytes"
+
+ 6  64	"ADJUST: %lld,%lld on %d,%d [mult=%d]"
+
+ 7 128	"ext3_has_free_blocks(%p): free=%u, root=%u"
+	"ext3_has_free_blocks(%p): %u<%u+1, %c, %u!=%u r=%d"
+
+
+
+debug_cvirt:
+
+
+ 0   1
+
+ 1   2
+
+ 2   4	"vx_map_tgid: %p/%llx: %d -> %d"
+	"vx_rmap_tgid: %p/%llx: %d -> %d"
+
+ 3   8
+
+ 4  16
+
+ 5  32
+
+ 6  64
+
+ 7 128
+
+
+
+debug_net:
+
+
+ 0   1
+
+ 1   2
+
+ 2   4	"nx_addr_conflict(%p,%p) %d.%d,%d.%d"
+
+ 3   8	"inet_bind(%p)* %p,%p;%lx %d.%d.%d.%d"
+	"inet_bind(%p) %d.%d.%d.%d, %d.%d.%d.%d, %d.%d.%d.%d"
+
+ 4  16	"ip_route_connect(%p) %p,%p;%lx"
+
+ 5  32	"__addr_in_socket(%p,%d.%d.%d.%d) %p:%d.%d.%d.%d %p;%lx"
+
+ 6  64	"sk: %p [#%d] (from %d)"
+	"sk,req: %p [#%d] (from %d)"
+	"sk,egf: %p [#%d] (from %d)"
+	"sk,egn: %p [#%d] (from %d)"
+	"tw: %p [#%d] (from %d)"
+
+ 7 128	"__sock_sendmsg: %p[%p,%p,%p;%d]:%d/%d"
+	"__sock_recvmsg: %p[%p,%p,%p;%d]:%d/%d"
+
+
+
+
+debug_limit:
+
+ n 2^n	"vx_acc_cres[%5d,%s,%2d]: %5d%s"
+	"vx_cres_avail[%5d,%s,%2d]: %5ld > %5d + %5d"
+
+ m 2^m	"vx_acc_page[%5d,%s,%2d]: %5d%s"
+	"vx_acc_pages[%5d,%s,%2d]: %5d += %5d"
+	"vx_pages_avail[%5d,%s,%2d]: %5ld > %5d + %5d"
+
+
diff -urNPp --minimal linux-2.6.11/Makefile vs-1.9.5rc1-grsec-2.1.3/Makefile
--- linux-2.6.11/Makefile	2005-03-02 08:38:13.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/Makefile	2005-03-08 09:27:34.024395312 +0100
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 11
-EXTRAVERSION =
+EXTRAVERSION = -grsec-vs1.9.5-rc1
 NAME=Woozy Numbat
 
 # *DOCUMENTATION*
@@ -561,7 +561,7 @@ export MODLIB
 
 
 ifeq ($(KBUILD_EXTMOD),)
-core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/
+core-y		+= kernel/ mm/ fs/ ipc/ security/ crypto/ grsecurity/
 
 vmlinux-dirs	:= $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
 		     $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
diff -urNPp --minimal linux-2.6.11/arch/alpha/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/alpha/Kconfig
--- linux-2.6.11/arch/alpha/Kconfig	2005-03-02 08:38:38.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/alpha/Kconfig	2005-03-08 09:27:34.025395160 +0100
@@ -598,6 +598,8 @@ source "arch/alpha/oprofile/Kconfig"
 
 source "arch/alpha/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/alpha/kernel/osf_sys.c vs-1.9.5rc1-grsec-2.1.3/arch/alpha/kernel/osf_sys.c
--- linux-2.6.11/arch/alpha/kernel/osf_sys.c	2005-03-02 08:37:30.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/alpha/kernel/osf_sys.c	2005-03-08 09:17:21.301543344 +0100
@@ -179,6 +179,11 @@ osf_mmap(unsigned long addr, unsigned lo
 	struct file *file = NULL;
 	unsigned long ret = -EBADF;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 #if 0
 	if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED))
 		printk("%s: unimplemented OSF mmap flags %04lx\n", 
@@ -1288,6 +1293,10 @@ arch_get_unmapped_area(struct file *filp
 	   merely specific addresses, but regions of memory -- perhaps
 	   this feature should be incorporated into all ports?  */
 
+#ifdef CONFIG_PAX_RANDMMAP
+	if (!(current->mm->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 +1304,16 @@ arch_get_unmapped_area(struct file *filp
 	}
 
 	/* Next, try allocating at TASK_UNMAPPED_BASE.  */
-	addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE),
-					 len, limit);
+
+	addr = TASK_UNMAPPED_BASE;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (current->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 -urNPp --minimal linux-2.6.11/arch/alpha/kernel/ptrace.c vs-1.9.5rc1-grsec-2.1.3/arch/alpha/kernel/ptrace.c
--- linux-2.6.11/arch/alpha/kernel/ptrace.c	2005-03-02 08:38:25.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/alpha/kernel/ptrace.c	2005-03-08 09:27:34.026395008 +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 @@ do_sys_ptrace(long request, long pid, lo
 	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 -urNPp --minimal linux-2.6.11/arch/alpha/kernel/systbls.S vs-1.9.5rc1-grsec-2.1.3/arch/alpha/kernel/systbls.S
--- linux-2.6.11/arch/alpha/kernel/systbls.S	2005-03-02 08:38:12.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/alpha/kernel/systbls.S	2005-03-08 09:27:34.027394856 +0100
@@ -447,7 +447,7 @@ sys_call_table:
 	.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 -urNPp --minimal linux-2.6.11/arch/alpha/mm/fault.c vs-1.9.5rc1-grsec-2.1.3/arch/alpha/mm/fault.c
--- linux-2.6.11/arch/alpha/mm/fault.c	2005-03-02 08:37:52.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/alpha/mm/fault.c	2005-03-08 09:17:21.302543192 +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 @@ __load_new_mm_context(struct mm_struct *
 	__reload_thread(pcb);
 }
 
+#ifdef CONFIG_PAX_PAGEEXEC
+/*
+ * PaX: decide what to do with offenders (regs->pc = fault address)
+ *
+ * returns 1 when task should be killed
+ *         2 when patched PLT trampoline was detected
+ *         3 when unpatched PLT trampoline was detected
+ *         4 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#ifdef CONFIG_PAX_EMUPLT
+	int err;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (current->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,
@@ -125,7 +262,7 @@ do_page_fault(unsigned long address, uns
 		goto good_area;
 	if (!(vma->vm_flags & VM_GROWSDOWN))
 		goto bad_area;
-	if (expand_stack(vma, address))
+	if (expand_stack(current, vma, address))
 		goto bad_area;
 
 	/* Ok, we have a good vm_area for this memory access, so
@@ -133,8 +270,34 @@ do_page_fault(unsigned long address, uns
  good_area:
 	si_code = SEGV_ACCERR;
 	if (cause < 0) {
-		if (!(vma->vm_flags & VM_EXEC))
+		if (!(vma->vm_flags & VM_EXEC)) {
+
+#ifdef CONFIG_PAX_PAGEEXEC
+			if (!(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 -urNPp --minimal linux-2.6.11/arch/arm/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/arm/Kconfig
--- linux-2.6.11/arch/arm/Kconfig	2005-03-02 08:38:10.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/arm/Kconfig	2005-03-08 09:27:34.027394856 +0100
@@ -731,6 +731,8 @@ source "drivers/mmc/Kconfig"
 
 source "arch/arm/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/arm/kernel/ptrace.c vs-1.9.5rc1-grsec-2.1.3/arch/arm/kernel/ptrace.c
--- linux-2.6.11/arch/arm/kernel/ptrace.c	2005-03-02 08:37:48.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/arm/kernel/ptrace.c	2005-03-08 09:27:34.029394552 +0100
@@ -759,6 +759,8 @@ asmlinkage int sys_ptrace(long request, 
 	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 -urNPp --minimal linux-2.6.11/arch/arm/mm/fault.c vs-1.9.5rc1-grsec-2.1.3/arch/arm/mm/fault.c
--- linux-2.6.11/arch/arm/mm/fault.c	2005-03-02 08:38:38.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/arm/mm/fault.c	2005-03-08 09:17:21.303543040 +0100
@@ -208,7 +208,7 @@ survive:
 	goto survive;
 
 check_stack:
-	if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
+	if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(tsk, vma, addr))
 		goto good_area;
 out:
 	return fault;
diff -urNPp --minimal linux-2.6.11/arch/arm/mm/mmap.c vs-1.9.5rc1-grsec-2.1.3/arch/arm/mm/mmap.c
--- linux-2.6.11/arch/arm/mm/mmap.c	2005-03-02 08:38:10.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/arm/mm/mmap.c	2005-03-08 09:17:21.303543040 +0100
@@ -62,6 +62,10 @@ arch_get_unmapped_area(struct file *filp
 	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 @@ full_search:
 			 * Start a new search - just in case we missed
 			 * some holes.
 			 */
-			if (start_addr != TASK_UNMAPPED_BASE) {
-				start_addr = addr = TASK_UNMAPPED_BASE;
+			if (start_addr != mm->mmap_base) {
+				start_addr = addr = mm->mmap_base;
 				goto full_search;
 			}
 			return -ENOMEM;
diff -urNPp --minimal linux-2.6.11/arch/arm26/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/arm26/Kconfig
--- linux-2.6.11/arch/arm26/Kconfig	2005-03-02 08:38:10.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/arm26/Kconfig	2005-03-08 09:27:34.030394400 +0100
@@ -220,6 +220,8 @@ source "drivers/usb/Kconfig"
 
 source "arch/arm26/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/arm26/kernel/ptrace.c vs-1.9.5rc1-grsec-2.1.3/arch/arm26/kernel/ptrace.c
--- linux-2.6.11/arch/arm26/kernel/ptrace.c	2005-03-02 08:38:09.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/arm26/kernel/ptrace.c	2005-03-08 09:27:34.031394248 +0100
@@ -691,6 +691,8 @@ asmlinkage int sys_ptrace(long request, 
 	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 -urNPp --minimal linux-2.6.11/arch/arm26/mm/fault.c vs-1.9.5rc1-grsec-2.1.3/arch/arm26/mm/fault.c
--- linux-2.6.11/arch/arm26/mm/fault.c	2005-03-02 08:37:52.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/arm26/mm/fault.c	2005-03-08 09:17:21.303543040 +0100
@@ -197,7 +197,7 @@ survive:
 	goto survive;
 
 check_stack:
-	if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
+	if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(tsk, vma, addr))
 		goto good_area;
 out:
 	return fault;
diff -urNPp --minimal linux-2.6.11/arch/cris/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/cris/Kconfig
--- linux-2.6.11/arch/cris/Kconfig	2005-03-02 08:38:26.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/cris/Kconfig	2005-03-08 09:27:34.031394248 +0100
@@ -173,6 +173,8 @@ source "drivers/usb/Kconfig"
 
 source "arch/cris/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/cris/mm/fault.c vs-1.9.5rc1-grsec-2.1.3/arch/cris/mm/fault.c
--- linux-2.6.11/arch/cris/mm/fault.c	2005-03-02 08:38:25.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/cris/mm/fault.c	2005-03-08 09:17:21.304542888 +0100
@@ -207,7 +207,7 @@ do_page_fault(unsigned long address, str
 		if (address + PAGE_SIZE < rdusp())
 			goto bad_area;
 	}
-	if (expand_stack(vma, address))
+	if (expand_stack(tsk, vma, address))
 		goto bad_area;
 
 	/*
diff -urNPp --minimal linux-2.6.11/arch/h8300/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/h8300/Kconfig
--- linux-2.6.11/arch/h8300/Kconfig	2005-03-02 08:38:17.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/h8300/Kconfig	2005-03-08 09:27:34.032394096 +0100
@@ -187,6 +187,8 @@ source "fs/Kconfig"
 
 source "arch/h8300/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/h8300/kernel/ptrace.c vs-1.9.5rc1-grsec-2.1.3/arch/h8300/kernel/ptrace.c
--- linux-2.6.11/arch/h8300/kernel/ptrace.c	2005-03-02 08:37:53.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/h8300/kernel/ptrace.c	2005-03-08 09:27:34.032394096 +0100
@@ -80,6 +80,8 @@ asmlinkage int sys_ptrace(long request, 
 	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 -urNPp --minimal linux-2.6.11/arch/i386/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/i386/Kconfig
--- linux-2.6.11/arch/i386/Kconfig	2005-03-02 08:37:49.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/Kconfig	2005-03-08 09:27:34.034393792 +0100
@@ -409,7 +409,7 @@ config X86_POPAD_OK
 
 config X86_ALIGNMENT_16
 	bool
-	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2
+	depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2
 	default y
 
 config X86_GOOD_APIC
@@ -568,6 +568,14 @@ config X86_IO_APIC
 	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
@@ -735,6 +743,46 @@ config HIGHMEM64G
 
 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
@@ -1210,6 +1258,8 @@ source "arch/i386/oprofile/Kconfig"
 
 source "arch/i386/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/i386/kernel/apm.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/apm.c
--- linux-2.6.11/arch/i386/kernel/apm.c	2005-03-02 08:37:47.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/apm.c	2005-03-08 09:17:21.307542432 +0100
@@ -598,19 +598,39 @@ static u8 apm_bios_call(u32 func, u32 eb
 	int			cpu;
 	struct desc_struct	save_desc_40;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long		cr3;
+#endif
+
 	cpus = apm_save_cpus();
-	
 	cpu = get_cpu();
-	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 @@ static u8 apm_bios_call_simple(u32 func,
 	int			cpu;
 	struct desc_struct	save_desc_40;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long		cr3;
+#endif
 
 	cpus = apm_save_cpus();
-	
 	cpu = get_cpu();
-	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 @@ static int __init apm_init(void)
 	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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/cpu/common.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/cpu/common.c
--- linux-2.6.11/arch/i386/kernel/cpu/common.c	2005-03-02 08:37:47.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/cpu/common.c	2005-03-08 09:17:21.307542432 +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>
@@ -18,8 +17,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;
@@ -369,6 +367,10 @@ void __init identify_cpu(struct cpuinfo_
 	if (this_cpu->c_init)
 		this_cpu->c_init(c);
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_NOVSYSCALL)
+	clear_bit(X86_FEATURE_SEP, c->x86_capability);
+#endif
+
 	/* Disable the PN if appropriate */
 	squash_the_stupid_serial_number(c);
 
@@ -555,7 +557,7 @@ void __init early_cpu_init(void)
 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 (cpu_test_and_set(cpu, cpu_initialized)) {
@@ -577,17 +579,16 @@ void __init cpu_init (void)
 	 * 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));
@@ -609,7 +610,7 @@ void __init cpu_init (void)
 	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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/cpu/proc.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/cpu/proc.c
--- linux-2.6.11/arch/i386/kernel/cpu/proc.c	2005-03-02 08:38:25.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/cpu/proc.c	2005-03-08 09:27:34.034393792 +0100
@@ -124,8 +124,8 @@ static int show_cpuinfo(struct seq_file 
 			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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/entry.S vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/entry.S
--- linux-2.6.11/arch/i386/kernel/entry.S	2005-03-02 08:37:51.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/entry.S	2005-03-08 09:27:34.035393640 +0100
@@ -229,6 +229,15 @@ sysenter_past_esp:
 	movl TI_flags(%ebp), %ecx
 	testw $_TIF_ALLWORK_MASK, %cx
 	jne syscall_exit_work
+
+#ifdef CONFIG_PAX_RANDKSTACK
+	pushl %eax
+	call pax_randomize_kstack
+	popl %eax
+#endif
+
+	xorl %ebp,%ebp	/* prevent info leak */
+
 /* if something modifies registers it must also disable sysexit */
 	movl EIP(%esp), %edx
 	movl OLDESP(%esp), %ecx
@@ -257,6 +266,11 @@ syscall_exit:
 	movl TI_flags(%ebp), %ecx
 	testw $_TIF_ALLWORK_MASK, %cx	# current->work
 	jne syscall_exit_work
+
+#ifdef CONFIG_PAX_RANDKSTACK
+	call pax_randomize_kstack
+#endif
+
 restore_all:
 	RESTORE_ALL
 
@@ -571,7 +585,7 @@ ENTRY(spurious_interrupt_bug)
 	pushl $do_spurious_interrupt_bug
 	jmp error_code
 
-.data
+.section .rodata,"a",@progbits
 ENTRY(sys_call_table)
 	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */
 	.long sys_exit
@@ -846,7 +860,7 @@ ENTRY(sys_call_table)
 	.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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/head.S vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/head.S
--- linux-2.6.11/arch/i386/kernel/head.S	2005-03-02 08:37:48.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/head.S	2005-03-08 09:17:21.309542128 +0100
@@ -48,6 +48,12 @@
 
 
 /*
+ * Real beginning of normal "text" segment
+ */
+ENTRY(stext)
+ENTRY(_stext)
+
+/*
  * 32-bit kernel entrypoint; only used by the boot CPU.  On entry,
  * %esi points to the real-mode code as a 32-bit pointer.
  * CS and DS must be 4 GB flat segments, but we don't depend on
@@ -78,6 +84,19 @@ ENTRY(startup_32)
 	shrl $2,%ecx
 	rep ; stosl
 
+#ifdef CONFIG_PAX_KERNEXEC
+	movl $ __KERNEL_TEXT_OFFSET,%eax
+	movw %ax,(cpu_gdt_table - __PAGE_OFFSET + __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,42 @@ ENTRY(startup_32)
  * 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);
-
+#ifdef CONFIG_X86_PAE
+page_pde_offset = ((__PAGE_OFFSET >> 21) * (4096 / PTRS_PER_PTE));
+#else
+page_pde_offset = ((__PAGE_OFFSET >> 22) * (4096 / PTRS_PER_PTE));
+#endif
 	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)
@@ -128,6 +165,11 @@ ENTRY(startup_32_smp)
 	movl %eax,%fs
 	movl %eax,%gs
 
+	/* This is a secondary processor (AP) */
+	xorl %ebx,%ebx
+	incl %ebx
+#endif /* CONFIG_SMP */
+
 /*
  *	New page tables may be in 4Mbyte page mode and may
  *	be using the global pages. 
@@ -143,26 +185,27 @@ ENTRY(startup_32_smp)
  *	not yet offset PAGE_OFFSET..
  */
 #define cr4_bits mmu_cr4_features-__PAGE_OFFSET
+3:
 	movl cr4_bits,%edx
 	andl %edx,%edx
-	jz 6f
+	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
@@ -172,13 +215,10 @@ ENTRY(startup_32_smp)
 	/* Make changes effective */
 	wrmsr
 
-6:
-	/* This is a secondary processor (AP) */
-	xorl %ebx,%ebx
-	incl %ebx
-
-3:
-#endif /* CONFIG_SMP */
+4:
+	movl %edi,%ebx
+#endif
+5:
 
 /*
  * Enable paging
@@ -203,9 +243,7 @@ ENTRY(startup_32_smp)
 
 #ifdef CONFIG_SMP
 	andl %ebx,%ebx
-	jz  1f				/* Initial CPU cleans BSS */
-	jmp checkCPUtype
-1:
+	jnz  checkCPUtype	/* Initial CPU cleans BSS */
 #endif /* CONFIG_SMP */
 
 /*
@@ -402,32 +440,74 @@ ignore_int:
 	popl %eax
 	iret
 
-/*
- * Real beginning of normal "text" segment
- */
-ENTRY(stext)
-ENTRY(_stext)
-
-/*
- * BSS section
- */
-.section ".bss.page_aligned","w"
+.section .data.swapper_pg_dir,"a",@progbits
 ENTRY(swapper_pg_dir)
+#ifdef CONFIG_X86_PAE
+	.long swapper_pm_dir-__PAGE_OFFSET+1
+	.long 0
+	.long swapper_pm_dir+512*8-__PAGE_OFFSET+1
+	.long 0
+	.long swapper_pm_dir+512*16-__PAGE_OFFSET+1
+	.long 0
+	.long swapper_pm_dir+512*24-__PAGE_OFFSET+1
+	.long 0
+#else
+	.fill 1024,4,0
+#endif
+
+#ifdef CONFIG_PAX_KERNEXEC
+ENTRY(kernexec_pg_dir)
+#ifdef CONFIG_X86_PAE
+	.long kernexec_pm_dir-__PAGE_OFFSET+1
+	.long 0
+	.long kernexec_pm_dir+512*8-__PAGE_OFFSET+1
+	.long 0
+	.long kernexec_pm_dir+512*16-__PAGE_OFFSET+1
+	.long 0
+	.long kernexec_pm_dir+512*24-__PAGE_OFFSET+1
+	.long 0
+#else
 	.fill 1024,4,0
+#endif
+#endif
+
+#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.
+ * The IDT has to be page-aligned to simplify the Pentium
+ * F0 0F bug workaround.. We have a special link segment
+ * for this.
  */
-.data
+.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
-
 int_msg:
 	.asciz "Unknown interrupt or fault at EIP %p %p %p\n"
 
@@ -469,8 +549,8 @@ cpu_gdt_descr:
 	.align L1_CACHE_BYTES
 ENTRY(boot_gdt_table)
 	.fill GDT_ENTRY_BOOT_CS,8,0
-	.quad 0x00cf9a000000ffff	/* kernel 4GB code at 0x00000000 */
-	.quad 0x00cf92000000ffff	/* kernel 4GB data at 0x00000000 */
+	.quad 0x00cf9b000000ffff	/* kernel 4GB code at 0x00000000 */
+	.quad 0x00cf93000000ffff	/* kernel 4GB data at 0x00000000 */
 
 /*
  * The Global Descriptor Table contains 28 quadwords, per-CPU.
@@ -489,28 +569,27 @@ ENTRY(cpu_gdt_table)
 	.quad 0x0000000000000000	/* 0x4b reserved */
 	.quad 0x0000000000000000	/* 0x53 reserved */
 	.quad 0x0000000000000000	/* 0x5b reserved */
-
-	.quad 0x00cf9a000000ffff	/* 0x60 kernel 4GB code at 0x00000000 */
-	.quad 0x00cf92000000ffff	/* 0x68 kernel 4GB data at 0x00000000 */
-	.quad 0x00cffa000000ffff	/* 0x73 user 4GB code at 0x00000000 */
-	.quad 0x00cff2000000ffff	/* 0x7b user 4GB data at 0x00000000 */
+	.quad 0x00cf9b000000ffff	/* 0x60 kernel 4GB code at 0x00000000 */
+	.quad 0x00cf93000000ffff	/* 0x68 kernel 4GB data at 0x00000000 */
+	.quad 0x00cffb000000ffff	/* 0x73 user 4GB code at 0x00000000 */
+	.quad 0x00cff3000000ffff	/* 0x7b user 4GB data at 0x00000000 */
 
 	.quad 0x0000000000000000	/* 0x80 TSS descriptor */
 	.quad 0x0000000000000000	/* 0x88 LDT descriptor */
 
 	/* Segments used for calling PnP BIOS */
-	.quad 0x00c09a0000000000	/* 0x90 32-bit code */
-	.quad 0x00809a0000000000	/* 0x98 16-bit code */
-	.quad 0x0080920000000000	/* 0xa0 16-bit data */
-	.quad 0x0080920000000000	/* 0xa8 16-bit data */
-	.quad 0x0080920000000000	/* 0xb0 16-bit data */
+	.quad 0x00c09b0000000000	/* 0x90 32-bit code */
+	.quad 0x00809b0000000000	/* 0x98 16-bit code */
+	.quad 0x0080930000000000	/* 0xa0 16-bit data */
+	.quad 0x0080930000000000	/* 0xa8 16-bit data */
+	.quad 0x0080930000000000	/* 0xb0 16-bit data */
 	/*
 	 * The APM segments have byte granularity and their bases
 	 * and limits are set at run time.
 	 */
-	.quad 0x00409a0000000000	/* 0xb8 APM CS    code */
-	.quad 0x00009a0000000000	/* 0xc0 APM CS 16 code (16 bit) */
-	.quad 0x0040920000000000	/* 0xc8 APM DS    data */
+	.quad 0x00409b0000000000	/* 0xb8 APM CS    code */
+	.quad 0x00009b0000000000	/* 0xc0 APM CS 16 code (16 bit) */
+	.quad 0x0040930000000000	/* 0xc8 APM DS    data */
 
 	.quad 0x0000000000000000	/* 0xd0 - unused */
 	.quad 0x0000000000000000	/* 0xd8 - unused */
@@ -519,3 +598,6 @@ ENTRY(cpu_gdt_table)
 	.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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/init_task.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/init_task.c
--- linux-2.6.11/arch/i386/kernel/init_task.c	2005-03-02 08:38:32.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/init_task.c	2005-03-08 09:17:21.309542128 +0100
@@ -42,5 +42,4 @@ EXPORT_SYMBOL(init_task);
  * 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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/io_apic.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/io_apic.c
--- linux-2.6.11/arch/i386/kernel/io_apic.c	2005-03-02 08:37:54.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/io_apic.c	2005-03-08 09:27:34.037393336 +0100
@@ -1765,7 +1765,7 @@ static int __init timer_irq_works(void)
 
 	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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/ioport.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/ioport.c
--- linux-2.6.11/arch/i386/kernel/ioport.c	2005-03-02 08:38:08.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/ioport.c	2005-03-08 09:17:21.310541976 +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 @@ asmlinkage long sys_ioperm(unsigned long
 
 	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 @@ asmlinkage long sys_ioperm(unsigned long
 	 * 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 @@ asmlinkage long sys_iopl(unsigned long u
 		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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/irq.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/irq.c
--- linux-2.6.11/arch/i386/kernel/irq.c	2005-03-02 08:37:48.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/irq.c	2005-03-08 09:17:21.310541976 +0100
@@ -113,10 +113,10 @@ fastcall unsigned int do_IRQ(struct pt_r
  * 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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/ldt.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/ldt.c
--- linux-2.6.11/arch/i386/kernel/ldt.c	2005-03-02 08:38:13.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/ldt.c	2005-03-08 09:17:21.311541824 +0100
@@ -102,6 +102,19 @@ int init_new_context(struct task_struct 
 		retval = copy_ldt(&mm->context, &old_mm->context);
 		up(&old_mm->context.sem);
 	}
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
+	if (!mm->context.user_cs_limit) {
+		mm->context.user_cs_base = 0UL;
+		mm->context.user_cs_limit = ~0UL;
+
+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
+		cpus_clear(mm->context.cpu_user_cs_mask);
+#endif
+
+	}
+#endif
+
 	return retval;
 }
 
@@ -159,7 +172,7 @@ static int read_default_ldt(void __user 
 {
 	int err;
 	unsigned long size;
-	void *address;
+	const void *address;
 
 	err = 0;
 	address = &default_ldt[0];
@@ -216,6 +229,13 @@ static int write_ldt(void __user * ptr, 
 		}
 	}
 
+#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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/process.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/process.c
--- linux-2.6.11/arch/i386/kernel/process.c	2005-03-02 08:37:30.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/process.c	2005-03-08 09:17:21.311541824 +0100
@@ -325,7 +325,7 @@ void exit_thread(void)
 	/* 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;
@@ -345,6 +345,9 @@ void flush_thread(void)
 {
 	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));	
 	/*
@@ -387,7 +390,7 @@ int copy_thread(int nr, unsigned long cl
 	struct task_struct *tsk;
 	int err;
 
-	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1;
+	childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info - sizeof(unsigned long))) - 1;
 	*childregs = *regs;
 	childregs->eax = 0;
 	childregs->esp = esp;
@@ -492,9 +495,8 @@ void dump_thread(struct pt_regs * regs, 
 int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs)
 {
 	struct pt_regs ptregs;
-	
-	ptregs = *(struct pt_regs *)
-		((unsigned long)tsk->thread_info+THREAD_SIZE - sizeof(ptregs));
+
+	ptregs = *(struct pt_regs *)(tsk->thread.esp0 - sizeof(ptregs));
 	ptregs.xcs &= 0xffff;
 	ptregs.xds &= 0xffff;
 	ptregs.xes &= 0xffff;
@@ -576,12 +578,20 @@ struct task_struct fastcall * __switch_t
 	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:
 	 */
@@ -592,6 +602,10 @@ struct task_struct fastcall * __switch_t
 	 */
 	load_TLS(next, cpu);
 
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_close_kernel(flags, cr3);
+#endif
+
 	/*
 	 * Save away %fs and %gs. No need to save %es and %ds, as
 	 * those are always kernel segments while inside the kernel.
@@ -740,6 +754,10 @@ asmlinkage int sys_set_thread_area(struc
 	struct desc_struct *desc;
 	int cpu, idx;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	unsigned long flags, cr3;
+#endif
+
 	if (copy_from_user(&info, u_info, sizeof(info)))
 		return -EFAULT;
 	idx = info.entry_number;
@@ -773,8 +791,17 @@ asmlinkage int sys_set_thread_area(struc
 		desc->a = LDT_entry_a(&info);
 		desc->b = LDT_entry_b(&info);
 	}
+
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_open_kernel(flags, cr3);
+#endif
+
 	load_TLS(t, cpu);
 
+#ifdef CONFIG_PAX_KERNEXEC
+	pax_close_kernel(flags, cr3);
+#endif
+
 	put_cpu();
 
 	return 0;
@@ -828,3 +855,29 @@ asmlinkage int sys_get_thread_area(struc
 	return 0;
 }
 
+#ifdef CONFIG_PAX_RANDKSTACK
+asmlinkage void pax_randomize_kstack(void)
+{
+	struct tss_struct *tss = init_tss + smp_processor_id();
+	unsigned long time;
+
+#ifdef CONFIG_PAX_SOFTMODE
+	if (!pax_aslr)
+		return;
+#endif
+
+	rdtscl(time);
+
+	/* P4 seems to return a 0 LSB, ignore it */
+#ifdef CONFIG_MPENTIUM4
+	time &= 0x3EUL;
+	time <<= 1;
+#else
+	time &= 0x1FUL;
+	time <<= 2;
+#endif
+
+	tss->esp0 ^= time;
+	current->thread.esp0 = tss->esp0;
+}
+#endif
diff -urNPp --minimal linux-2.6.11/arch/i386/kernel/ptrace.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/ptrace.c
--- linux-2.6.11/arch/i386/kernel/ptrace.c	2005-03-02 08:37:51.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/ptrace.c	2005-03-08 09:27:34.038393184 +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>
@@ -379,11 +380,16 @@ asmlinkage int sys_ptrace(long request, 
 	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;
@@ -462,6 +468,17 @@ asmlinkage int sys_ptrace(long request, 
 			  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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/reboot.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/reboot.c
--- linux-2.6.11/arch/i386/kernel/reboot.c	2005-03-02 08:37:52.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/reboot.c	2005-03-08 09:17:21.313541520 +0100
@@ -152,18 +152,18 @@ core_initcall(reboot_init);
    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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/setup.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/setup.c
--- linux-2.6.11/arch/i386/kernel/setup.c	2005-03-02 08:38:08.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/setup.c	2005-03-08 09:17:21.314541368 +0100
@@ -73,7 +73,11 @@ struct cpuinfo_x86 new_cpu_data __initda
 /* common cpu data for all cpus */
 struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
 
+#ifdef CONFIG_X86_PAE
+unsigned long mmu_cr4_features = X86_CR4_PAE;
+#else
 unsigned long mmu_cr4_features;
+#endif
 EXPORT_SYMBOL_GPL(mmu_cr4_features);
 
 #ifdef	CONFIG_ACPI_INTERPRETER
@@ -1411,7 +1415,7 @@ void __init setup_arch(char **cmdline_p)
 
 	code_resource.start = virt_to_phys(_text);
 	code_resource.end = virt_to_phys(_etext)-1;
-	data_resource.start = virt_to_phys(_etext);
+	data_resource.start = virt_to_phys(_data);
 	data_resource.end = virt_to_phys(_edata)-1;
 
 	parse_cmdline_early(cmdline_p);
@@ -1481,6 +1485,15 @@ void __init setup_arch(char **cmdline_p)
 #endif
 }
 
+#ifdef CONFIG_PAX_SOFTMODE
+static int __init setup_pax_softmode(char *str)
+{
+	get_option (&str, &pax_softmode);
+	return 1;
+}
+__setup("pax_softmode=", setup_pax_softmode);
+#endif
+
 #include "setup_arch_post.h"
 /*
  * Local Variables:
diff -urNPp --minimal linux-2.6.11/arch/i386/kernel/signal.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/signal.c
--- linux-2.6.11/arch/i386/kernel/signal.c	2005-03-02 08:38:08.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/signal.c	2005-03-08 09:17:21.314541368 +0100
@@ -380,7 +380,17 @@ static void setup_frame(int sig, struct 
 			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;
 
@@ -475,7 +485,18 @@ static void setup_rt_frame(int sig, stru
 		goto give_sigsegv;
 
 	/* Set up to return from userspace.  */
+
+#ifdef CONFIG_PAX_NOVSYSCALL
+	restorer = frame->retcode;
+#else
 	restorer = &__kernel_rt_sigreturn;
+
+#ifdef CONFIG_PAX_SEGMEXEC
+	if (current->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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/smpboot.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/smpboot.c
--- linux-2.6.11/arch/i386/kernel/smpboot.c	2005-03-02 08:38:09.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/smpboot.c	2005-03-08 09:27:34.039393032 +0100
@@ -1025,8 +1025,8 @@ static void __init smp_boot_cpus(unsigne
 	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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/sys_i386.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/sys_i386.c
--- linux-2.6.11/arch/i386/kernel/sys_i386.c	2005-03-02 08:38:32.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/sys_i386.c	2005-03-08 09:27:34.040392880 +0100
@@ -19,6 +19,7 @@
 #include <linux/mman.h>
 #include <linux/file.h>
 #include <linux/utsname.h>
+#include <linux/vs_cvirt.h>
 
 #include <asm/uaccess.h>
 #include <asm/ipc.h>
@@ -49,6 +50,11 @@ static inline long do_mmap2(
 	int error = -EBADF;
 	struct file * file = NULL;
 
+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC)
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
@@ -106,6 +112,182 @@ out:
 	return err;
 }
 
+unsigned long
+arch_get_unmapped_area(struct file *filp, unsigned long addr,
+		unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long start_addr, start_mmap, task_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;
+	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(mm, addr)))
+			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 +399,7 @@ asmlinkage int sys_uname(struct old_utsn
 	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 +407,7 @@ asmlinkage int sys_uname(struct old_utsn
 asmlinkage int sys_olduname(struct oldold_utsname __user * name)
 {
 	int error;
+	struct new_utsname *ptr;
 
 	if (!name)
 		return -EFAULT;
@@ -233,15 +416,16 @@ asmlinkage int sys_olduname(struct oldol
   
   	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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/sysenter.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/sysenter.c
--- linux-2.6.11/arch/i386/kernel/sysenter.c	2005-03-02 08:38:33.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/sysenter.c	2005-03-08 09:17:21.315541216 +0100
@@ -24,7 +24,7 @@ extern asmlinkage void sysenter_entry(vo
 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 @@ void enable_sep_cpu(void *info)
 extern const char vsyscall_int80_start, vsyscall_int80_end;
 extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
 
+#ifndef CONFIG_PAX_NOVSYSCALL
 static int __init sysenter_setup(void)
 {
 	void *page = (void *)get_zeroed_page(GFP_ATOMIC);
@@ -63,3 +64,4 @@ static int __init sysenter_setup(void)
 }
 
 __initcall(sysenter_setup);
+#endif
diff -urNPp --minimal linux-2.6.11/arch/i386/kernel/traps.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/traps.c
--- linux-2.6.11/arch/i386/kernel/traps.c	2005-03-02 08:37:49.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/traps.c	2005-03-08 09:27:34.042392576 +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 @@ static inline unsigned long print_contex
 				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 @@ static inline unsigned long print_contex
 		print_symbol("%s", addr);
 		printk("\n");
 		ebp = *(unsigned long *)ebp;
+		--i;
 	}
 #else
 	while (valid_stack_ptr(tinfo, stack)) {
@@ -131,6 +130,7 @@ static inline unsigned long print_contex
 			printk(" [<%08lx>]", addr);
 			print_symbol(" %s", addr);
 			printk("\n");
+			--i;
 		}
 	}
 #endif
@@ -240,7 +240,7 @@ void show_registers(struct pt_regs *regs
 
 		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 @@ static void handle_BUG(struct pt_regs *r
 	if (regs->xcs & 3)
 		goto no_bug;		/* Not in kernel */
 
-	eip = regs->eip;
+	eip = regs->eip + __KERNEL_TEXT_OFFSET;
 
 	if (eip < PAGE_OFFSET)
 		goto no_bug;
@@ -306,6 +306,7 @@ void die(const char * str, struct pt_reg
 	};
 	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 @@ void die(const char * str, struct pt_reg
 	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 @@ DO_ERROR_INFO(17, SIGBUS, "alignment che
 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 @@ fastcall void do_general_protection(stru
 	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 @@ gp_in_kernel:
 		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);
 	}
 }
@@ -932,6 +959,8 @@ asmlinkage void math_emulate(long arg)
 #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);
 
 	/*
@@ -940,6 +969,8 @@ void __init trap_init_f00f_bug(void)
 	 */
 	idt_descr.address = fix_to_virt(FIX_F00F_IDT);
 	__asm__ __volatile__("lidt %0" : : "m" (idt_descr));
+#endif
+
 }
 #endif
 
diff -urNPp --minimal linux-2.6.11/arch/i386/kernel/vm86.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/vm86.c
--- linux-2.6.11/arch/i386/kernel/vm86.c	2005-03-02 08:37:48.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/vm86.c	2005-03-08 09:17:21.598498200 +0100
@@ -121,7 +121,7 @@ struct pt_regs * fastcall save_v86_state
 		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);
@@ -312,7 +312,7 @@ static void do_sys_vm86(struct kernel_vm
 	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 -urNPp --minimal linux-2.6.11/arch/i386/kernel/vmlinux.lds.S vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/vmlinux.lds.S
--- linux-2.6.11/arch/i386/kernel/vmlinux.lds.S	2005-03-02 08:38:37.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/kernel/vmlinux.lds.S	2005-03-08 09:17:21.598498200 +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 @@ jiffies = jiffies_64;
 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 @@ SECTIONS
   .altinstructions : { *(.altinstructions) } 
   __alt_instructions_end = .; 
  .altinstr_replacement : { *(.altinstr_replacement) } 
+
+#ifndef CONFIG_PAX_KERNEXEC
   /* .exit.text is discard at runtime, not link time, to deal with references
      from .altinstructions and .eh_frame */
   .exit.text : { *(.exit.text) }
+#endif
+
   .exit.data : { *(.exit.data) }
   . = ALIGN(4096);
   __initramfs_start = .;
@@ -100,15 +66,107 @@ SECTIONS
   __per_cpu_start = .;
   .data.percpu  : { *(.data.percpu) }
   __per_cpu_end = .;
+
+  /* read-only */
+
+#ifdef CONFIG_PAX_KERNEXEC
+  __init_text_start = .;
+  .init.text (. - __KERNEL_TEXT_OFFSET) : AT (__init_text_start) {
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+	*(.exit.text)
+	. = ALIGN(4*1024*1024) - 1;
+	BYTE(0)
+  }
+  . = ALIGN(4096);
+  __init_end = . + __KERNEL_TEXT_OFFSET;
+  /* freed after init ends here */
+
+/*
+ * PaX: this must be kept in synch with the KERNEL_CS base
+ * in the GDTs in arch/i386/kernel/head.S
+ */
+  _text = .;			/* Text and read-only data */
+  .text : AT (. + __KERNEL_TEXT_OFFSET) {
+#else
+  .init.text : {
+	_sinittext = .;
+	*(.init.text)
+	_einittext = .;
+  }
   . = ALIGN(4096);
   __init_end = .;
   /* freed after init ends here */
-	
+
+  _text = .;			/* Text and read-only data */
+  .text : {
+#endif
+
+	*(.text)
+	SCHED_TEXT
+	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 -urNPp --minimal linux-2.6.11/arch/i386/mm/fault.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/mm/fault.c
--- linux-2.6.11/arch/i386/mm/fault.c	2005-03-02 08:37:30.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/mm/fault.c	2005-03-08 09:17:21.600497896 +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>
@@ -81,7 +84,7 @@ static inline unsigned long get_segment_
 
 	/* Unlikely, but must come before segment checks. */
 	if (unlikely((regs->eflags & VM_MASK) != 0))
-		return eip + (seg << 4);
+		return (eip & 0xFFFF) + (seg << 4);
 	
 	/* By far the most common cases. */
 	if (likely(seg == __USER_CS || seg == __KERNEL_CS))
@@ -107,7 +110,7 @@ static inline unsigned long get_segment_
 		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);
 	}
 
@@ -201,6 +204,31 @@ static inline int is_prefetch(struct pt_
 
 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;
+	pud_t *pud;
+	pmd_t *pmd;
+
+	pgd = pgd_offset(mm, address);
+	if (!pgd || !pgd_present(*pgd))
+		return 0;
+	pud = pud_offset(pgd, address);
+	if (!pud || !pud_present(*pud))
+		return 0;
+	pmd = pmd_offset(pud, 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
@@ -217,10 +245,14 @@ fastcall void do_page_fault(struct pt_re
 	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));
 
@@ -232,6 +264,7 @@ fastcall void do_page_fault(struct pt_re
 		local_irq_enable();
 
 	tsk = current;
+	mm = tsk->mm;
 
 	info.si_code = SEGV_MAPERR;
 
@@ -258,14 +291,99 @@ fastcall void do_page_fault(struct pt_re
 		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
@@ -285,7 +403,7 @@ fastcall void do_page_fault(struct pt_re
 	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);
 	}
 
@@ -306,7 +424,7 @@ fastcall void do_page_fault(struct pt_re
 		if (address + 32 < regs->esp)
 			goto bad_area;
 	}
-	if (expand_stack(vma, address))
+	if (expand_stack(tsk, vma, address))
 		goto bad_area;
 /*
  * Ok, we have a good vm_area for this memory access, so
@@ -374,6 +492,45 @@ bad_area:
 	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) {
 		/* 
@@ -441,28 +598,52 @@ no_context:
 #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;
+		pud_t *pud;
+		pmd_t *pmd;
+		pte_t *pte;
+
+		asm("movl %%cr3,%0":"=r" (pgd_paddr));
+		pgd = index + (pgd_t *)__va(pgd_paddr);
+		printk(KERN_ALERT "*pgd = %*llx\n", sizeof(*pgd), (unsigned long long)pgd_val(*pgd));
+		if (pgd_present(*pgd)) {
+			pud = pud_offset(pgd, address);
+			pmd = pmd_offset(pud, address);
+			printk(KERN_ALERT "*pmd = %*llx\n", sizeof(*pmd), (unsigned long long)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 = %*llx\n", sizeof(*pte), (unsigned long long)pte_val(*pte));
+			}
 #endif
+		}
+	}
 	die("Oops", regs, error_code);
 	bust_spinlocks(0);
 	do_exit(SIGKILL);
@@ -513,7 +694,7 @@ vmalloc_fault:
 		 * 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;
 		pud_t *pud, *pud_k;
@@ -550,3 +731,255 @@ vmalloc_fault:
 		return;
 	}
 }
+
+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_EMUTRAMP) || defined(CONFIG_PAX_RANDEXEC)
+/*
+ * PaX: decide what to do with offenders (regs->eip = fault address)
+ *
+ * returns 1 when task should be killed
+ *         2 when gcc trampoline was detected
+ *         3 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#ifdef CONFIG_PAX_EMUTRAMP
+	static const unsigned char trans[8] = {6, 1, 2, 0, 13, 5, 3, 4};
+#endif
+
+#if defined(CONFIG_PAX_RANDEXEC) || defined(CONFIG_PAX_EMUTRAMP)
+	int err;
+#endif
+
+	if (regs->eflags & X86_EFLAGS_VM)
+		return 1;
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (current->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
+
+	if (!(current->mm->flags & MF_PAX_EMUTRAMP))
+		return 1;
+
+#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 -urNPp --minimal linux-2.6.11/arch/i386/mm/hugetlbpage.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/mm/hugetlbpage.c
--- linux-2.6.11/arch/i386/mm/hugetlbpage.c	2005-03-02 08:38:26.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/mm/hugetlbpage.c	2005-03-08 09:27:34.042392576 +0100
@@ -46,7 +46,8 @@ static void set_huge_pte(struct mm_struc
 {
 	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)));
@@ -86,7 +87,8 @@ int copy_hugetlb_page_range(struct mm_st
 		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;
@@ -222,7 +224,8 @@ void unmap_hugepage_range(struct vm_area
 		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 -urNPp --minimal linux-2.6.11/arch/i386/mm/init.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/mm/init.c
--- linux-2.6.11/arch/i386/mm/init.c	2005-03-02 08:38:17.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/mm/init.c	2005-03-08 09:17:21.610496376 +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,30 +49,6 @@ unsigned long highstart_pfn, highend_pfn
 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)
-{
-	pud_t *pud;
-	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));
-	pud = pud_offset(pgd, 0);
-	if (pmd_table != pmd_offset(pud, 0)) 
-		BUG();
-#else
-	pud = pud_offset(pgd, 0);
-	pmd_table = pmd_offset(pud, 0);
-#endif
-
-	return pmd_table;
-}
-
-/*
  * Create a page table and place a pointer to it in a middle page
  * directory entry.
  */
@@ -114,8 +91,6 @@ static void __init page_table_range_init
 	pgd = pgd_base + pgd_idx;
 
 	for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
-		if (pgd_none(*pgd)) 
-			one_md_table_init(pgd);
 		pud = pud_offset(pgd, vaddr);
 		pmd = pmd_offset(pud, vaddr);
 		for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
@@ -144,6 +119,7 @@ static void __init kernel_physical_mappi
 {
 	unsigned long pfn;
 	pgd_t *pgd;
+	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 	int pgd_idx, pmd_idx, pte_ofs;
@@ -153,7 +129,8 @@ static void __init kernel_physical_mappi
 	pfn = 0;
 
 	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
-		pmd = one_md_table_init(pgd);
+		pud = pud_offset(pgd, 0);
+		pmd = pmd_offset(pud, 0);
 		if (pfn >= max_low_pfn)
 			continue;
 		for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
@@ -312,13 +289,6 @@ static void __init pagetable_init (void)
 	unsigned long vaddr;
 	pgd_t *pgd_base = swapper_pg_dir;
 
-#ifdef CONFIG_X86_PAE
-	int i;
-	/* Init entries of the first-level page table to the zero page */
-	for (i = 0; i < PTRS_PER_PGD; i++)
-		set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
-#endif
-
 	/* Enable PSE if available */
 	if (cpu_has_pse) {
 		set_in_cr4(X86_CR4_PSE);
@@ -342,17 +312,6 @@ static void __init pagetable_init (void)
 	page_table_range_init(vaddr, 0, pgd_base);
 
 	permanent_kmaps_init(pgd_base);
-
-#ifdef CONFIG_X86_PAE
-	/*
-	 * Add low memory identity-mappings - SMP needs it when
-	 * starting up on an AP from real-mode. In the non-PAE
-	 * case we already have these mappings through head.S.
-	 * All user-space mappings are explicitly cleared after
-	 * SMP startup.
-	 */
-	pgd_base[0] = pgd_base[USER_PTRS_PER_PGD];
-#endif
 }
 
 #if defined(CONFIG_PM_DISK) || defined(CONFIG_SOFTWARE_SUSPEND)
@@ -386,11 +345,7 @@ void zap_low_mappings (void)
 	 * us, because pgd_clear() is a no-op on i386.
 	 */
 	for (i = 0; i < USER_PTRS_PER_PGD; i++)
-#ifdef CONFIG_X86_PAE
-		set_pgd(swapper_pg_dir+i, __pgd(1 + __pa(empty_zero_page)));
-#else
 		set_pgd(swapper_pg_dir+i, __pgd(0));
-#endif
 	flush_tlb_all();
 }
 
@@ -508,15 +463,17 @@ void __init paging_init(void)
 
 	load_cr3(swapper_pg_dir);
 
+	__flush_tlb_all();
+
+#ifdef CONFIG_PAX_KERNEXEC
+
 #ifdef CONFIG_X86_PAE
-	/*
-	 * We will bail out later - printk doesn't work right now so
-	 * the user would just see a hanging kernel.
-	 */
-	if (cpu_has_pae)
-		set_in_cr4(X86_CR4_PAE);
+	memcpy(kernexec_pm_dir, swapper_pm_dir, sizeof(kernexec_pm_dir));
+#else
+	memcpy(kernexec_pg_dir, swapper_pg_dir, sizeof(kernexec_pg_dir));
+#endif
+
 #endif
-	__flush_tlb_all();
 
 	kmap_init();
 	zone_sizes_init();
@@ -611,7 +568,7 @@ void __init mem_init(void)
 	set_highmem_pages_init(bad_ppro);
 
 	codesize =  (unsigned long) &_etext - (unsigned long) &_text;
-	datasize =  (unsigned long) &_edata - (unsigned long) &_etext;
+	datasize =  (unsigned long) &_edata - (unsigned long) &_data;
 	initsize =  (unsigned long) &__init_end - (unsigned long) &__init_begin;
 
 	kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); 
@@ -628,10 +585,6 @@ void __init mem_init(void)
 		(unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
 	       );
 
-#ifdef CONFIG_X86_PAE
-	if (!cpu_has_pae)
-		panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
-#endif
 	if (boot_cpu_data.wp_works_ok < 0)
 		test_wp_bit();
 
@@ -702,6 +655,46 @@ void free_initmem(void)
 {
 	unsigned long addr;
 
+#ifdef CONFIG_PAX_KERNEXEC
+	/* PaX: limit KERNEL_CS to actual size */
+	{
+		unsigned long limit;
+		int cpu;
+		pgd_t *pgd;
+		pud_t *pud;
+		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);
+			pud = pud_offset(pgd, addr);
+			pmd = pmd_offset(pud, 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);
+			pud = pud_offset(pgd, addr);
+			pmd = pmd_offset(pud, 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 -urNPp --minimal linux-2.6.11/arch/i386/mm/mmap.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/mm/mmap.c
--- linux-2.6.11/arch/i386/mm/mmap.c	2005-03-02 08:38:08.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/mm/mmap.c	2005-03-08 09:17:21.611496224 +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 @@ void arch_pick_mmap_layout(struct mm_str
 			(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 -urNPp --minimal linux-2.6.11/arch/i386/pci/pcbios.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/pci/pcbios.c
--- linux-2.6.11/arch/i386/pci/pcbios.c	2005-03-02 08:38:34.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/pci/pcbios.c	2005-03-08 09:17:21.611496224 +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 -urNPp --minimal linux-2.6.11/arch/i386/power/cpu.c vs-1.9.5rc1-grsec-2.1.3/arch/i386/power/cpu.c
--- linux-2.6.11/arch/i386/power/cpu.c	2005-03-02 08:38:18.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/i386/power/cpu.c	2005-03-08 09:17:21.612496072 +0100
@@ -83,10 +83,9 @@ do_fpu_end(void)
 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 -urNPp --minimal linux-2.6.11/arch/ia64/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/ia64/Kconfig
--- linux-2.6.11/arch/ia64/Kconfig	2005-03-02 08:38:26.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/ia64/Kconfig	2005-03-08 09:27:34.043392424 +0100
@@ -414,6 +414,8 @@ source "arch/ia64/oprofile/Kconfig"
 
 source "arch/ia64/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/ia64/ia32/binfmt_elf32.c vs-1.9.5rc1-grsec-2.1.3/arch/ia64/ia32/binfmt_elf32.c
--- linux-2.6.11/arch/ia64/ia32/binfmt_elf32.c	2005-03-02 08:38:38.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/ia64/ia32/binfmt_elf32.c	2005-03-08 09:27:34.044392272 +0100
@@ -43,6 +43,17 @@ static void elf32_set_personality (void)
 
 #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 @@ ia64_elf32_init (struct pt_regs *regs)
 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 @@ ia32_setup_arg_pages (struct linux_binpr
 	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 @@ ia32_setup_arg_pages (struct linux_binpr
 			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 -urNPp --minimal linux-2.6.11/arch/ia64/ia32/ia32priv.h vs-1.9.5rc1-grsec-2.1.3/arch/ia64/ia32/ia32priv.h
--- linux-2.6.11/arch/ia64/ia32/ia32priv.h	2005-03-02 08:38:32.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/ia64/ia32/ia32priv.h	2005-03-08 09:17:21.613495920 +0100
@@ -326,10 +326,17 @@ struct old_linux32_dirent {
 #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 -urNPp --minimal linux-2.6.11/arch/ia64/ia32/sys_ia32.c vs-1.9.5rc1-grsec-2.1.3/arch/ia64/ia32/sys_ia32.c
--- linux-2.6.11/arch/ia64/ia32/sys_ia32.c	2005-03-02 08:38:12.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/ia64/ia32/sys_ia32.c	2005-03-08 09:17:21.615495616 +0100
@@ -939,6 +939,11 @@ sys32_mmap (struct mmap_arg_struct __use
 
 	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 @@ sys32_mmap2 (unsigned int addr, unsigned
 	struct file *file = NULL;
 	unsigned long retval;
 
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
diff -urNPp --minimal linux-2.6.11/arch/ia64/kernel/entry.S vs-1.9.5rc1-grsec-2.1.3/arch/ia64/kernel/entry.S
--- linux-2.6.11/arch/ia64/kernel/entry.S	2005-03-02 08:37:50.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/ia64/kernel/entry.S	2005-03-08 09:27:34.045392120 +0100
@@ -1572,7 +1572,7 @@ sys_call_table:
 	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 -urNPp --minimal linux-2.6.11/arch/ia64/kernel/perfmon.c vs-1.9.5rc1-grsec-2.1.3/arch/ia64/kernel/perfmon.c
--- linux-2.6.11/arch/ia64/kernel/perfmon.c	2005-03-02 08:38:26.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/ia64/kernel/perfmon.c	2005-03-08 09:27:34.049391512 +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>
@@ -2339,7 +2341,8 @@ pfm_smpl_buffer_alloc(struct task_struct
 	 */
 	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 -urNPp --minimal linux-2.6.11/arch/ia64/kernel/ptrace.c vs-1.9.5rc1-grsec-2.1.3/arch/ia64/kernel/ptrace.c
--- linux-2.6.11/arch/ia64/kernel/ptrace.c	2005-03-02 08:38:33.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/ia64/kernel/ptrace.c	2005-03-08 09:27:34.051391208 +0100
@@ -17,6 +17,7 @@
 #include <linux/user.h>
 #include <linux/security.h>
 #include <linux/audit.h>
+#include <linux/grsecurity.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -1420,10 +1421,16 @@ sys_ptrace (long request, pid_t pid, uns
 	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 -urNPp --minimal linux-2.6.11/arch/ia64/kernel/sys_ia64.c vs-1.9.5rc1-grsec-2.1.3/arch/ia64/kernel/sys_ia64.c
--- linux-2.6.11/arch/ia64/kernel/sys_ia64.c	2005-03-02 08:38:10.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/ia64/kernel/sys_ia64.c	2005-03-08 09:17:21.616495464 +0100
@@ -27,7 +27,7 @@ arch_get_unmapped_area (struct file *fil
 			unsigned long pgoff, unsigned long flags)
 {
 	long map_shared = (flags & MAP_SHARED);
-	unsigned long start_addr, align_mask = PAGE_SIZE - 1;
+	unsigned long start_addr, align_mask = PAGE_SIZE - 1, task_unmapped_base = TASK_UNMAPPED_BASE;
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 
@@ -38,6 +38,15 @@ arch_get_unmapped_area (struct file *fil
 	if (REGION_NUMBER(addr) == REGION_HPAGE)
 		addr = 0;
 #endif
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (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 +65,9 @@ arch_get_unmapped_area (struct file *fil
 	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
 		/* At this point:  (!vma || addr < vma->vm_end). */
 		if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) {
-			if (start_addr != TASK_UNMAPPED_BASE) {
+			if (start_addr != task_unmapped_base) {
 				/* Start a new search --- just in case we missed some holes.  */
-				addr = TASK_UNMAPPED_BASE;
+				addr = task_unmapped_base;
 				goto full_search;
 			}
 			return -ENOMEM;
@@ -184,6 +193,11 @@ do_mmap2 (unsigned long addr, unsigned l
 	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);
diff -urNPp --minimal linux-2.6.11/arch/ia64/mm/fault.c vs-1.9.5rc1-grsec-2.1.3/arch/ia64/mm/fault.c
--- linux-2.6.11/arch/ia64/mm/fault.c	2005-03-02 08:38:32.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/ia64/mm/fault.c	2005-03-08 09:27:34.052391056 +0100
@@ -9,6 +9,8 @@
 #include <linux/mm.h>
 #include <linux/smp_lock.h>
 #include <linux/interrupt.h>
+#include <linux/binfmts.h>
+#include <linux/vs_memory.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -33,12 +35,23 @@ expand_backing_store (struct vm_area_str
 
 	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;
+	if ((vma->vm_flags & VM_LOCKED) &&
+	    ((vma->vm_mm->locked_vm + grow) << PAGE_SHIFT) > current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur &&
+	    !capable(CAP_IPC_LOCK))
 		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;
 }
@@ -75,6 +88,54 @@ mapped_kernel_page_is_present (unsigned 
 	return pte_present(pte);
 }
 
+#ifdef CONFIG_PAX_PAGEEXEC
+/*
+ * PaX: decide what to do with offenders (regs->cr_iip = fault address)
+ *
+ * returns 1 when task should be killed
+ *         2 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#ifdef CONFIG_PAX_RANDEXEC
+	int err;
+
+	if (current->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)
 {
@@ -130,9 +191,31 @@ ia64_do_page_fault (unsigned long addres
 		| (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)
 		| (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_BIT));
 
-	if ((vma->vm_flags & mask) != mask)
+	if ((vma->vm_flags & mask) != mask) {
+
+#ifdef CONFIG_PAX_PAGEEXEC
+		if (!(vma->vm_flags & VM_EXEC) && (mask & VM_EXEC)) {
+			if (!(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
@@ -169,7 +252,7 @@ ia64_do_page_fault (unsigned long addres
 		if (REGION_NUMBER(address) != REGION_NUMBER(vma->vm_start)
 		    || REGION_OFFSET(address) >= RGN_MAP_LIMIT)
 			goto bad_area;
-		if (expand_stack(vma, address))
+		if (expand_stack(current, vma, address))
 			goto bad_area;
 	} else {
 		vma = prev_vma;
diff -urNPp --minimal linux-2.6.11/arch/ia64/mm/hugetlbpage.c vs-1.9.5rc1-grsec-2.1.3/arch/ia64/mm/hugetlbpage.c
--- linux-2.6.11/arch/ia64/mm/hugetlbpage.c	2005-03-02 08:38:09.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/ia64/mm/hugetlbpage.c	2005-03-08 09:27:34.052391056 +0100
@@ -73,7 +73,8 @@ set_huge_pte (struct mm_struct *mm, stru
 {
 	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)));
@@ -116,7 +117,8 @@ int copy_hugetlb_page_range(struct mm_st
 		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;
@@ -246,7 +248,8 @@ void unmap_hugepage_range(struct vm_area
 		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 -urNPp --minimal linux-2.6.11/arch/m32r/mm/fault.c vs-1.9.5rc1-grsec-2.1.3/arch/m32r/mm/fault.c
--- linux-2.6.11/arch/m32r/mm/fault.c	2005-03-02 08:37:52.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/m32r/mm/fault.c	2005-03-08 09:17:21.627493792 +0100
@@ -186,7 +186,7 @@ asmlinkage void do_page_fault(struct pt_
 			goto bad_area;
 	}
 #endif
-	if (expand_stack(vma, address))
+	if (expand_stack(tsk, vma, address))
 		goto bad_area;
 /*
  * Ok, we have a good vm_area for this memory access, so
diff -urNPp --minimal linux-2.6.11/arch/m68k/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/m68k/Kconfig
--- linux-2.6.11/arch/m68k/Kconfig	2005-03-02 08:38:10.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/m68k/Kconfig	2005-03-08 09:27:34.053390904 +0100
@@ -663,6 +663,8 @@ source "fs/Kconfig"
 
 source "arch/m68k/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/m68k/atari/stram.c vs-1.9.5rc1-grsec-2.1.3/arch/m68k/atari/stram.c
--- linux-2.6.11/arch/m68k/atari/stram.c	2005-03-02 08:38:17.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/m68k/atari/stram.c	2005-03-08 09:27:34.054390752 +0100
@@ -635,7 +635,8 @@ static inline void unswap_pte(struct vm_
 	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 -urNPp --minimal linux-2.6.11/arch/m68k/kernel/ptrace.c vs-1.9.5rc1-grsec-2.1.3/arch/m68k/kernel/ptrace.c
--- linux-2.6.11/arch/m68k/kernel/ptrace.c	2005-03-02 08:37:52.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/m68k/kernel/ptrace.c	2005-03-08 09:27:34.055390600 +0100
@@ -140,6 +140,8 @@ asmlinkage int sys_ptrace(long request, 
 	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 -urNPp --minimal linux-2.6.11/arch/m68k/mm/fault.c vs-1.9.5rc1-grsec-2.1.3/arch/m68k/mm/fault.c
--- linux-2.6.11/arch/m68k/mm/fault.c	2005-03-02 08:38:08.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/m68k/mm/fault.c	2005-03-08 09:17:21.628493640 +0100
@@ -121,7 +121,7 @@ int do_page_fault(struct pt_regs *regs, 
 		if (address + 256 < rdusp())
 			goto map_err;
 	}
-	if (expand_stack(vma, address))
+	if (expand_stack(current, vma, address))
 		goto map_err;
 
 /*
diff -urNPp --minimal linux-2.6.11/arch/m68knommu/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/m68knommu/Kconfig
--- linux-2.6.11/arch/m68knommu/Kconfig	2005-03-02 08:38:13.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/m68knommu/Kconfig	2005-03-08 09:27:34.055390600 +0100
@@ -574,6 +574,8 @@ source "fs/Kconfig"
 
 source "arch/m68knommu/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/m68knommu/kernel/ptrace.c vs-1.9.5rc1-grsec-2.1.3/arch/m68knommu/kernel/ptrace.c
--- linux-2.6.11/arch/m68knommu/kernel/ptrace.c	2005-03-02 08:38:10.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/m68knommu/kernel/ptrace.c	2005-03-08 09:27:34.056390448 +0100
@@ -124,6 +124,8 @@ asmlinkage int sys_ptrace(long request, 
 	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 -urNPp --minimal linux-2.6.11/arch/mips/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/mips/Kconfig
--- linux-2.6.11/arch/mips/Kconfig	2005-03-02 08:38:09.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/mips/Kconfig	2005-03-08 09:27:34.057390296 +0100
@@ -1644,6 +1644,8 @@ source "fs/Kconfig"
 
 source "arch/mips/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/mips/kernel/binfmt_elfn32.c vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/binfmt_elfn32.c
--- linux-2.6.11/arch/mips/kernel/binfmt_elfn32.c	2005-03-02 08:38:10.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/binfmt_elfn32.c	2005-03-08 09:17:21.628493640 +0100
@@ -50,6 +50,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
 #undef ELF_ET_DYN_BASE
 #define ELF_ET_DYN_BASE         (TASK32_SIZE / 3 * 2)
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#endif
+
 #include <asm/processor.h>
 #include <linux/module.h>
 #include <linux/config.h>
diff -urNPp --minimal linux-2.6.11/arch/mips/kernel/binfmt_elfo32.c vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/binfmt_elfo32.c
--- linux-2.6.11/arch/mips/kernel/binfmt_elfo32.c	2005-03-02 08:37:55.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/binfmt_elfo32.c	2005-03-08 09:17:21.629493488 +0100
@@ -52,6 +52,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
 #undef ELF_ET_DYN_BASE
 #define ELF_ET_DYN_BASE         (TASK32_SIZE / 3 * 2)
 
+#ifdef CONFIG_PAX_ASLR
+#define PAX_ELF_ET_DYN_BASE(tsk)	(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
+
+#define PAX_DELTA_MMAP_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_MMAP_LEN(tsk)		(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#define PAX_DELTA_EXEC_LSB(tsk)		PAGE_SHIFT
+#define PAX_DELTA_EXEC_LEN(tsk)		(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#define PAX_DELTA_STACK_LSB(tsk)	PAGE_SHIFT
+#define PAX_DELTA_STACK_LEN(tsk)	(((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
+#endif
+
 #include <asm/processor.h>
 #include <linux/module.h>
 #include <linux/config.h>
diff -urNPp --minimal linux-2.6.11/arch/mips/kernel/irixelf.c vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/irixelf.c
--- linux-2.6.11/arch/mips/kernel/irixelf.c	2005-03-02 08:38:34.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/irixelf.c	2005-03-08 09:27:34.058390144 +0100
@@ -692,7 +692,8 @@ static int load_irix_binary(struct linux
 	/* 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, STACK_TOP, EXSTACK_DEFAULT);
 	current->mm->start_stack = bprm->p;
 
diff -urNPp --minimal linux-2.6.11/arch/mips/kernel/linux32.c vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/linux32.c
--- linux-2.6.11/arch/mips/kernel/linux32.c	2005-03-02 08:38:12.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/linux32.c	2005-03-08 09:27:34.059389992 +0100
@@ -1199,7 +1199,7 @@ asmlinkage long sys32_newuname(struct ne
 	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 -urNPp --minimal linux-2.6.11/arch/mips/kernel/ptrace.c vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/ptrace.c
--- linux-2.6.11/arch/mips/kernel/ptrace.c	2005-03-02 08:38:33.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/ptrace.c	2005-03-08 09:27:34.060389840 +0100
@@ -76,6 +76,8 @@ asmlinkage int sys_ptrace(long request, 
 	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 -urNPp --minimal linux-2.6.11/arch/mips/kernel/syscall.c vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/syscall.c
--- linux-2.6.11/arch/mips/kernel/syscall.c	2005-03-02 08:38:18.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/syscall.c	2005-03-08 09:27:34.061389688 +0100
@@ -26,6 +26,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>
@@ -84,6 +85,11 @@ unsigned long arch_get_unmapped_area(str
 	do_color_align = 0;
 	if (filp || (flags & MAP_SHARED))
 		do_color_align = 1;
+
+#ifdef CONFIG_PAX_RANDMMAP
+	if (!(current->mm->flags & MF_PAX_RANDMMAP) || !filp)
+#endif
+
 	if (addr) {
 		if (do_color_align)
 			addr = COLOUR_ALIGN(addr, pgoff);
@@ -94,6 +100,13 @@ unsigned long arch_get_unmapped_area(str
 		    (!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);
@@ -210,7 +223,7 @@ out:
  */
 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;
 }
@@ -221,21 +234,23 @@ asmlinkage int sys_uname(struct old_utsn
 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;
 
@@ -261,10 +276,10 @@ asmlinkage int _sys_sysmips(int cmd, lon
 			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 -urNPp --minimal linux-2.6.11/arch/mips/kernel/sysirix.c vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/sysirix.c
--- linux-2.6.11/arch/mips/kernel/sysirix.c	2005-03-02 08:38:26.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/mips/kernel/sysirix.c	2005-03-08 09:27:34.063389384 +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 @@ asmlinkage int irix_brk(unsigned long br
 	/*
 	 * 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 -urNPp --minimal linux-2.6.11/arch/mips/mm/fault.c vs-1.9.5rc1-grsec-2.1.3/arch/mips/mm/fault.c
--- linux-2.6.11/arch/mips/mm/fault.c	2005-03-02 08:37:51.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/mips/mm/fault.c	2005-03-08 09:17:21.630493336 +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
@@ -75,7 +93,7 @@ asmlinkage void do_page_fault(struct pt_
 		goto good_area;
 	if (!(vma->vm_flags & VM_GROWSDOWN))
 		goto bad_area;
-	if (expand_stack(vma, address))
+	if (expand_stack(tsk, vma, address))
 		goto bad_area;
 /*
  * Ok, we have a good vm_area for this memory access, so
diff -urNPp --minimal linux-2.6.11/arch/parisc/Kconfig vs-1.9.5rc1-grsec-2.1.3/arch/parisc/Kconfig
--- linux-2.6.11/arch/parisc/Kconfig	2005-03-02 08:38:10.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/parisc/Kconfig	2005-03-08 09:27:34.063389384 +0100
@@ -200,6 +200,8 @@ source "arch/parisc/oprofile/Kconfig"
 
 source "arch/parisc/Kconfig.debug"
 
+source "kernel/vserver/Kconfig"
+
 source "security/Kconfig"
 
 source "crypto/Kconfig"
diff -urNPp --minimal linux-2.6.11/arch/parisc/kernel/ptrace.c vs-1.9.5rc1-grsec-2.1.3/arch/parisc/kernel/ptrace.c
--- linux-2.6.11/arch/parisc/kernel/ptrace.c	2005-03-02 08:37:48.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/parisc/kernel/ptrace.c	2005-03-08 09:27:34.078387104 +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 @@ long sys_ptrace(long request, pid_t pid,
 	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 -urNPp --minimal linux-2.6.11/arch/parisc/kernel/sys_parisc.c vs-1.9.5rc1-grsec-2.1.3/arch/parisc/kernel/sys_parisc.c
--- linux-2.6.11/arch/parisc/kernel/sys_parisc.c	2005-03-02 08:38:25.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/parisc/kernel/sys_parisc.c	2005-03-08 09:17:21.631493184 +0100
@@ -104,6 +104,13 @@ unsigned long arch_get_unmapped_area(str
 {
 	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,6 +130,12 @@ static unsigned long do_mmap2(unsigned l
 {
 	struct file * file = NULL;
 	unsigned long error = -EBADF;
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (flags & MAP_MIRROR)
+		return -EINVAL;
+#endif
+
 	if (!(flags & MAP_ANONYMOUS)) {
 		file = fget(fd);
 		if (!file)
diff -urNPp --minimal linux-2.6.11/arch/parisc/kernel/sys_parisc32.c vs-1.9.5rc1-grsec-2.1.3/arch/parisc/kernel/sys_parisc32.c
--- linux-2.6.11/arch/parisc/kernel/sys_parisc32.c	2005-03-02 08:37:55.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/parisc/kernel/sys_parisc32.c	2005-03-08 09:27:34.080386800 +0100
@@ -659,6 +659,7 @@ asmlinkage int sys32_sysinfo(struct sysi
 
 	do {
 		seq = read_seqbegin(&xtime_lock);
+		/* requires vx virtualization */
 		val.uptime = jiffies / HZ;
 
 		val.loads[0] = avenrun[0] << (SI_LOAD_SHIFT - FSHIFT);
diff -urNPp --minimal linux-2.6.11/arch/parisc/kernel/traps.c vs-1.9.5rc1-grsec-2.1.3/arch/parisc/kernel/traps.c
--- linux-2.6.11/arch/parisc/kernel/traps.c	2005-03-02 08:38:33.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/parisc/kernel/traps.c	2005-03-08 09:17:21.632493032 +0100
@@ -680,9 +680,7 @@ void handle_interruption(int code, struc
 
 			down_read(&current->mm->mmap_sem);
 			vma = find_vma(current->mm,regs->iaoq[0]);
-			if (vma && (regs->iaoq[0] >= vma->vm_start)
-				&& (vma->vm_flags & VM_EXEC)) {
-
+			if (vma && (regs->iaoq[0] >= vma->vm_start)) {
 				fault_address = regs->iaoq[0];
 				fault_space = regs->iasq[0];
 
diff -urNPp --minimal linux-2.6.11/arch/parisc/mm/fault.c vs-1.9.5rc1-grsec-2.1.3/arch/parisc/mm/fault.c
--- linux-2.6.11/arch/parisc/mm/fault.c	2005-03-02 08:38:25.000000000 +0100
+++ vs-1.9.5rc1-grsec-2.1.3/arch/parisc/mm/fault.c	2005-03-08 09:17:21.633492880 +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 @@ DEFINE_PER_CPU(struct exception_data, ex
 static unsigned long
 parisc_acctyp(unsigned long code, unsigned int inst)
 {
-	if (code == 6 || code == 16)
+	if (code == 6 || code == 7 || code == 16)
 	    return VM_EXEC;
 
 	switch (inst & 0xf0000000) {
@@ -143,6 +145,139 @@ parisc_acctyp(unsigned long code, unsign
 			}
 #endif
 
+#ifdef CONFIG_PAX_PAGEEXEC
+/*
+ * PaX: decide what to do with offenders (instruction_pointer(regs) = fault address)
+ *
+ * returns 1 when task should be killed
+ *         2 when rt_sigreturn trampoline was detected
+ *         3 when unpatched PLT trampoline was detected
+ *         4 when legitimate ET_EXEC was detected
+ */
+static int pax_handle_fetch_fault(struct pt_regs *regs)
+{
+
+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUTRAMP)
+	int err;
+#endif
+
+#ifdef CONFIG_PAX_RANDEXEC
+	if (current->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-