rpms/kernel/devel linux-2.6-execshield-xen.patch, NONE, 1.1 linux-2.6-execshield.patch, NONE, 1.1 linux-2.6-xen-vdso-note.patch, NONE, 1.1 kernel-2.6.spec, 1.1606, 1.1607 linux-2.6.10-x86_64-read-implies-exec32.patch, 1.1, NONE linux-2.6.11-execshield.patch, 1.19, NONE linux-2.6.12rc3-xen-vdso-note.patch, 1.4, NONE linux-2.6.8-execshield-xen.patch, 1.14, NONE

fedora-cvs-commits at redhat.com fedora-cvs-commits at redhat.com
Sat Oct 15 01:02:19 UTC 2005


Author: davej

Update of /cvs/dist/rpms/kernel/devel
In directory cvs.devel.redhat.com:/tmp/cvs-serv5353

Modified Files:
	kernel-2.6.spec 
Added Files:
	linux-2.6-execshield-xen.patch linux-2.6-execshield.patch 
	linux-2.6-xen-vdso-note.patch 
Removed Files:
	linux-2.6.10-x86_64-read-implies-exec32.patch 
	linux-2.6.11-execshield.patch 
	linux-2.6.12rc3-xen-vdso-note.patch 
	linux-2.6.8-execshield-xen.patch 
Log Message:
rename execshield diffs.


linux-2.6-execshield-xen.patch:
 arch/xen/i386/kernel/cpu/common.c    |    6 ++
 arch/xen/i386/kernel/entry.S         |    7 ++
 arch/xen/i386/kernel/process.c       |   53 +++++++++++++++++++++
 arch/xen/i386/kernel/signal.c        |    4 -
 arch/xen/i386/kernel/smp.c           |    3 +
 arch/xen/i386/kernel/traps.c         |   87 ++++++++++++++++++++++++++++++++++-
 arch/xen/i386/mm/init.c              |    3 +
 fs/binfmt_elf.c                      |    1 
 include/asm-xen/asm-i386/desc.h      |   10 ++++
 include/asm-xen/asm-i386/mmu.h       |    6 ++
 include/asm-xen/asm-i386/pgalloc.h   |    5 ++
 include/asm-xen/asm-i386/processor.h |    6 ++
 12 files changed, 187 insertions(+), 4 deletions(-)

--- NEW FILE linux-2.6-execshield-xen.patch ---
diff -urNp --exclude-from=/home/davej/.exclude linux-811/arch/xen/i386/kernel/cpu/common.c linux-812/arch/xen/i386/kernel/cpu/common.c
--- linux-811/arch/xen/i386/kernel/cpu/common.c
+++ linux-812/arch/xen/i386/kernel/cpu/common.c
@@ -400,6 +400,12 @@ void __init identify_cpu(struct cpuinfo_
 	if (disable_pse)
 		clear_bit(X86_FEATURE_PSE, c->x86_capability);
 
+	/* hack: disable SEP for non-NX cpus; SEP breaks Execshield. */
+	#ifdef CONFIG_HIGHMEM64G
+	if (!test_bit(X86_FEATURE_NX, c->x86_capability))
+	#endif
+		clear_bit(X86_FEATURE_SEP, c->x86_capability);
+
 	/* If the model name is still unset, do table lookup. */
 	if ( !c->x86_model_id[0] ) {
 		char *p;
diff -urNp --exclude-from=/home/davej/.exclude linux-811/arch/xen/i386/kernel/entry.S linux-812/arch/xen/i386/kernel/entry.S
--- linux-811/arch/xen/i386/kernel/entry.S
+++ linux-812/arch/xen/i386/kernel/entry.S
@@ -234,7 +234,12 @@ sysenter_past_esp:
 	pushl %ebp
 	pushfl
 	pushl $(__USER_CS)
-	pushl $SYSENTER_RETURN
+	/*
+	 * Push current_thread_info()->sysenter_return to the stack.
+	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
+	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
+	 */
+	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
 
 /*
  * Load the potential sixth argument from user stack.
diff -urNp --exclude-from=/home/davej/.exclude linux-811/arch/xen/i386/kernel/process.c linux-812/arch/xen/i386/kernel/process.c
--- linux-811/arch/xen/i386/kernel/process.c
+++ linux-812/arch/xen/i386/kernel/process.c
@@ -55,6 +55,7 @@
 
 #include <linux/irq.h>
 #include <linux/err.h>
+#include <linux/random.h>
 
 #include <asm/tlbflush.h>
 #include <asm/cpu.h>
@@ -94,6 +95,52 @@ void enable_hlt(void)
 
 EXPORT_SYMBOL(enable_hlt);
 
+void randomize_brk(unsigned long old_brk)
+{
+	unsigned long new_brk, range_start, range_end;
+
+	range_start = 0x08000000;
+	if (current->mm->brk >= range_start)
+		range_start = current->mm->brk;
+	range_end = range_start + 0x02000000;
+	new_brk = randomize_range(range_start, range_end, 0);
+	if (new_brk)
+		current->mm->brk = new_brk;
+}
+
+void arch_add_exec_range(struct mm_struct *mm, unsigned long limit)
+{
+	if (limit > mm->context.exec_limit) {
+		mm->context.exec_limit = limit;
+		set_user_cs(&mm->context.user_cs, limit);
+		if (mm == current->mm)
+			load_user_cs_desc(smp_processor_id(), mm);
+	}
+}
+
+void arch_remove_exec_range(struct mm_struct *mm, unsigned long old_end)
+{
+	struct vm_area_struct *vma;
+	unsigned long limit = 0;
+
+	if (old_end == mm->context.exec_limit) {
+		for (vma = mm->mmap; vma; vma = vma->vm_next)
+			if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit))
+				limit = vma->vm_end;
+
+		mm->context.exec_limit = limit;
+		set_user_cs(&mm->context.user_cs, limit);
+		if (mm == current->mm)
+			load_user_cs_desc(smp_processor_id(), mm);
+	}
+}
+
+void arch_flush_exec_range(struct mm_struct *mm)
+{
+	mm->context.exec_limit = 0;
+	set_user_cs(&mm->context.user_cs, 0);
+}
+
 /* XXX XEN doesn't use default_idle(), poll_idle(). Use xen_idle() instead. */
 extern void stop_hz_timer(void);
 extern void start_hz_timer(void);
@@ -566,6 +613,12 @@ struct task_struct fastcall * __switch_t
 	}
 
 	/*
+	 * Exec-shield CS adjustment.
+	 */
+	if (next_p->mm)
+		load_user_cs_desc(cpu, next_p->mm);
+
+	/*
 	 * Now maybe reload the debug registers
 	 */
 	if (unlikely(next->debugreg[7])) {
diff -urNp --exclude-from=/home/davej/.exclude linux-811/arch/xen/i386/kernel/signal.c linux-812/arch/xen/i386/kernel/signal.c
--- linux-811/arch/xen/i386/kernel/signal.c
+++ linux-812/arch/xen/i386/kernel/signal.c
@@ -380,7 +380,7 @@ static void setup_frame(int sig, struct 
 			goto give_sigsegv;
 	}
 
-	restorer = &__kernel_sigreturn;
+	restorer = current->mm->context.vdso + (long)&__kernel_sigreturn;
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 
@@ -475,7 +475,7 @@ static void setup_rt_frame(int sig, stru
 		goto give_sigsegv;
 
 	/* Set up to return from userspace.  */
-	restorer = &__kernel_rt_sigreturn;
+	restorer = current->mm->context.vdso + (long)&__kernel_rt_sigreturn;
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 	err |= __put_user(restorer, &frame->pretcode);
diff -urNp --exclude-from=/home/davej/.exclude linux-811/arch/xen/i386/kernel/smp.c linux-812/arch/xen/i386/kernel/smp.c
--- linux-811/arch/xen/i386/kernel/smp.c
+++ linux-812/arch/xen/i386/kernel/smp.c
@@ -23,6 +23,7 @@
 
 #include <asm/mtrr.h>
 #include <asm/tlbflush.h>
+#include <asm/desc.h>
 #if 0
 #include <mach_apic.h>
 #endif
@@ -289,6 +290,8 @@ irqreturn_t smp_invalidate_interrupt(int
 	unsigned long cpu;
 
 	cpu = get_cpu();
+	if (current->active_mm)
+		load_user_cs_desc(cpu, current->active_mm);
 
 	if (!cpu_isset(cpu, flush_cpumask))
 		goto out;
diff -urNp --exclude-from=/home/davej/.exclude linux-811/arch/xen/i386/kernel/traps.c linux-812/arch/xen/i386/kernel/traps.c
--- linux-811/arch/xen/i386/kernel/traps.c
+++ linux-812/arch/xen/i386/kernel/traps.c
@@ -449,13 +449,91 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", inv
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
 #ifdef CONFIG_X86_MCE
 DO_ERROR(18, SIGBUS, "machine check", machine_check)
 #endif
 
+/*
+ * lazy-check for CS validity on exec-shield binaries:
+ *
+ * the original non-exec stack patch was written by
+ * Solar Designer <solar at openwall.com>. Thanks!
+ */
+static int
+check_lazy_exec_limit(int cpu, struct pt_regs * regs, long error_code)
+{
+	struct desc_struct *desc1, *desc2;
+	struct vm_area_struct *vma;
+	unsigned long limit;
+
+	if (current->mm == NULL)
+		return 0;
+
+	limit = -1UL;
+	if (current->mm->context.exec_limit != -1UL) {
+		limit = PAGE_SIZE;
+		spin_lock(&current->mm->page_table_lock);
+		for (vma = current->mm->mmap; vma; vma = vma->vm_next)
+			if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit))
+				limit = vma->vm_end;
+		spin_unlock(&current->mm->page_table_lock);
+		if (limit >= TASK_SIZE)
+			limit = -1UL;
+		current->mm->context.exec_limit = limit;
+	}
+	set_user_cs(&current->mm->context.user_cs, limit);
+
+	desc1 = &current->mm->context.user_cs;
+	desc2 = &get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS];
+
+	if (desc1->a != desc2->a || desc1->b != desc2->b) {
+		/*
+		 * The CS was not in sync - reload it and retry the
+		 * instruction. If the instruction still faults then
+		 * we won't hit this branch next time around.
+		 */
+		if (print_fatal_signals >= 2) {
+			printk("#GPF fixup (%ld[seg:%lx]) at %08lx, CPU#%d.\n", error_code, error_code/8, regs->eip, smp_processor_id());
+			printk(" exec_limit: %08lx, user_cs: %08lx/%08lx, CPU_cs: %08lx/%08lx.\n", current->mm->context.exec_limit, desc1->a, desc1->b, desc2->a, desc2->b);
+		}
+		load_user_cs_desc(cpu, current->mm);
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * The fixup code for errors in iret jumps to here (iret_exc).  It loses
+ * the original trap number and error code.  The bogus trap 32 and error
+ * code 0 are what the vanilla kernel delivers via:
+ * DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
+ *
+ * In case of a general protection fault in the iret instruction, we
+ * need to check for a lazy CS update for exec-shield.
+ */
+fastcall void do_iret_error(struct pt_regs *regs, long error_code)
+{
+	int ok;
+	ok = check_lazy_exec_limit(get_cpu(), regs, error_code);
+	put_cpu();
+	if (!ok && notify_die(DIE_TRAP, "iret exception", regs,
+				error_code, 32, SIGSEGV) != NOTIFY_STOP) {
+		siginfo_t info;
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		info.si_code = ILL_BADSTK;
+		info.si_addr = 0;
+		do_trap(32, SIGSEGV, "iret exception", 0, regs, error_code,
+				&info);
+	}
+}
+
 fastcall void do_general_protection(struct pt_regs * regs, long error_code)
 {
+	int cpu = get_cpu();
+	int ok;
+
 	/*
 	 * If we trapped on an LDT access then ensure that the default_ldt is
 	 * loaded, if nothing else. We load default_ldt lazily because LDT
@@ -465,11 +543,18 @@ fastcall void do_general_protection(stru
 		unsigned long ldt;
 		__asm__ __volatile__ ("sldt %0" : "=r" (ldt));
 		if (ldt == 0) {
+			put_cpu();
 			xen_set_ldt((unsigned long)&default_ldt[0], 5);
 			return;
 		}
 	}
 
+	ok = check_lazy_exec_limit(cpu, regs, error_code);
+	put_cpu();
+
+	if (ok)
+		return;
+
 	if (regs->eflags & VM_MASK)
 		goto gp_in_vm86;
 
diff -urNp --exclude-from=/home/davej/.exclude linux-811/arch/xen/i386/mm/init.c linux-812/arch/xen/i386/mm/init.c
--- linux-811/arch/xen/i386/mm/init.c
+++ linux-812/arch/xen/i386/mm/init.c
@@ -504,7 +504,10 @@ void __init paging_init(void)
 	set_nx();
 	if (nx_enabled)
 		printk("NX (Execute Disable) protection: active\n");
+	else
 #endif
+	if (exec_shield)
+		printk("Using x86 segment limits to approximate NX protection\n");
 
 	pagetable_init();
 
diff -urNp --exclude-from=/home/davej/.exclude linux-811/fs/binfmt_elf.c linux-812/fs/binfmt_elf.c
--- linux-811/fs/binfmt_elf.c
+++ linux-812/fs/binfmt_elf.c
@@ -42,6 +42,7 @@
 #include <asm/uaccess.h>
 #include <asm/param.h>
 #include <asm/page.h>
+#include <asm/pgalloc.h>
 
 #include <linux/elf.h>
 
diff -urNp --exclude-from=/home/davej/.exclude linux-811/include/asm-xen/asm-i386/desc.h linux-812/include/asm-xen/asm-i386/desc.h
--- linux-811/include/asm-xen/asm-i386/desc.h
+++ linux-812/include/asm-xen/asm-i386/desc.h
@@ -141,6 +141,16 @@ static inline unsigned long get_desc_bas
 	return base;
 }
 
+static inline void set_user_cs(struct desc_struct *desc, unsigned long limit)
+{
+	limit = (limit - 1) / PAGE_SIZE;
+	desc->a = limit & 0xffff;
+	desc->b = (limit & 0xf0000) | 0x00c0fb00;
+}
+
+#define load_user_cs_desc(cpu, mm) \
+	HYPERVISOR_update_descriptor(virt_to_machine(&get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS]), (u64)(mm)->context.user_cs.a | ((u64)(mm)->context.user_cs.b) << 32); 
+
 #endif /* !__ASSEMBLY__ */
 
 #endif
diff -urNp --exclude-from=/home/davej/.exclude linux-811/include/asm-xen/asm-i386/mmu.h linux-812/include/asm-xen/asm-i386/mmu.h
--- linux-811/include/asm-xen/asm-i386/mmu.h
+++ linux-812/include/asm-xen/asm-i386/mmu.h
@@ -7,6 +7,9 @@
  * we put the segment information here.
  *
  * cpu_vm_mask is used to optimize ldt flushing.
+ *
+ * exec_limit is used to track the range PROT_EXEC
+ * mappings span.
  */
 typedef struct { 
 	int size;
@@ -14,6 +17,9 @@ typedef struct { 
 	void *ldt;
 	unsigned pinned:1;
 	struct list_head unpinned;
+	struct desc_struct user_cs;
+	unsigned long exec_limit;
+	void *vdso;
 } mm_context_t;
 
 extern struct list_head mm_unpinned;
diff -urNp --exclude-from=/home/davej/.exclude linux-811/include/asm-xen/asm-i386/pgalloc.h linux-812/include/asm-xen/asm-i386/pgalloc.h
--- linux-811/include/asm-xen/asm-i386/pgalloc.h
+++ linux-812/include/asm-xen/asm-i386/pgalloc.h
@@ -58,4 +58,9 @@ extern void pte_free(struct page *pte);
 
 #define check_pgt_cache()	do { } while (0)
 
+/* Exec-Shield dummy macros */
+extern void arch_add_exec_range(struct mm_struct *mm, unsigned long limit);
+extern void arch_remove_exec_range(struct mm_struct *mm, unsigned long limit);
+extern void arch_flush_exec_range(struct mm_struct *mm);
+
 #endif /* _I386_PGALLOC_H */
diff -urNp --exclude-from=/home/davej/.exclude linux-811/include/asm-xen/asm-i386/processor.h linux-812/include/asm-xen/asm-i386/processor.h
--- linux-811/include/asm-xen/asm-i386/processor.h
+++ linux-812/include/asm-xen/asm-i386/processor.h
@@ -511,6 +511,9 @@ static inline void load_esp0(struct tss_
 	regs->xcs = __USER_CS;					\
 	regs->eip = new_eip;					\
 	regs->esp = new_esp;					\
+	preempt_disable();					\
+	load_user_cs_desc(smp_processor_id(), current->mm);	\
+	preempt_enable();					\
 } while (0)
 
 /*
@@ -700,4 +703,7 @@ extern void select_idle_routine(const st
 
 extern unsigned long boot_option_idle_override;
 
+#define __HAVE_ARCH_ALIGN_STACK
+extern unsigned long arch_align_stack(unsigned long sp);
+
 #endif /* __ASM_I386_PROCESSOR_H */

linux-2.6-execshield.patch:
 linux-2.6.13-a/arch/x86_64/ia32/ia32_binfmt.c  |    4 
 linux-2.6.13-a/arch/x86_64/kernel/process.c    |    6 -
 linux-2.6.13-a/arch/x86_64/kernel/setup64.c    |   25 -----
 linux-2.6.13-a/include/asm-x86_64/pgtable.h    |    2 
 linux-2.6.13/mm/fremap.c                       |   16 +--
 linux-810/arch/i386/kernel/asm-offsets.c       |    1 
 linux-810/arch/i386/kernel/entry.S             |    8 +
 linux-810/arch/i386/kernel/process.c           |   59 ++++++++++++
 linux-810/arch/i386/kernel/signal.c            |    4 
 linux-810/arch/i386/kernel/smp.c               |    3 
 linux-810/arch/i386/kernel/sysenter.c          |   55 +++++++++++
 linux-810/arch/i386/kernel/traps.c             |   93 ++++++++++++++++++-
 linux-810/arch/i386/kernel/vsyscall-sysenter.S |    6 -
 linux-810/arch/i386/kernel/vsyscall.lds.S      |    4 
 linux-810/arch/i386/mm/init.c                  |    6 +
 linux-810/arch/i386/mm/mmap.c                  |    6 -
 linux-810/arch/ia64/ia32/binfmt_elf32.c        |    2 
 linux-810/arch/x86_64/ia32/ia32_binfmt.c       |    2 
 linux-810/arch/x86_64/kernel/process.c         |    7 -
 linux-810/arch/x86_64/mm/Makefile              |    2 
 linux-810/arch/x86_64/mm/fault.c               |    2 
 linux-810/arch/x86_64/mm/mmap.c                |   95 +++++++++++++++++++
 linux-810/drivers/char/random.c                |    7 +
 linux-810/fs/binfmt_elf.c                      |  120 ++++++++++++++++++++-----
 linux-810/fs/proc/array.c                      |    8 +
 linux-810/fs/proc/base.c                       |    4 
 linux-810/fs/proc/task_mmu.c                   |   25 ++++-
 linux-810/include/asm-i386/desc.h              |   14 ++
 linux-810/include/asm-i386/elf.h               |   42 +++++---
 linux-810/include/asm-i386/mmu.h               |    6 +
 linux-810/include/asm-i386/pgalloc.h           |    1 
 linux-810/include/asm-i386/processor.h         |    8 +
 linux-810/include/asm-i386/thread_info.h       |    1 
 linux-810/include/asm-ia64/pgalloc.h           |    4 
 linux-810/include/asm-ppc/pgalloc.h            |    5 +
 linux-810/include/asm-ppc64/pgalloc.h          |    5 +
 linux-810/include/asm-s390/pgalloc.h           |    4 
 linux-810/include/asm-sparc/pgalloc.h          |    4 
 linux-810/include/asm-sparc64/pgalloc.h        |    4 
 linux-810/include/asm-x86_64/pgalloc.h         |    7 +
 linux-810/include/asm-x86_64/processor.h       |    5 +
 linux-810/include/linux/mm.h                   |    9 +
 linux-810/include/linux/resource.h             |    5 -
 linux-810/include/linux/sched.h                |    9 +
 linux-810/include/linux/sysctl.h               |    3 
 linux-810/kernel/signal.c                      |   38 +++++++
 linux-810/kernel/sysctl.c                      |   39 ++++++++
 linux-810/mm/mmap.c                            |  105 ++++++++++++++++++++-
 linux-810/mm/mprotect.c                        |    5 -
 linux-810/mm/mremap.c                          |    4 
 linux-813/arch/i386/kernel/cpu/common.c        |    7 +
 51 files changed, 780 insertions(+), 126 deletions(-)

--- NEW FILE linux-2.6-execshield.patch ---
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/kernel/asm-offsets.c linux-810/arch/i386/kernel/asm-offsets.c
--- linux-804/arch/i386/kernel/asm-offsets.c
+++ linux-810/arch/i386/kernel/asm-offsets.c
@@ -53,6 +53,7 @@ void foo(void)
 	OFFSET(TI_preempt_count, thread_info, preempt_count);
 	OFFSET(TI_addr_limit, thread_info, addr_limit);
 	OFFSET(TI_restart_block, thread_info, restart_block);
+	OFFSET(TI_sysenter_return, thread_info, sysenter_return);
 	BLANK();
 
 	OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/kernel/entry.S linux-810/arch/i386/kernel/entry.S
--- linux-804/arch/i386/kernel/entry.S
+++ linux-810/arch/i386/kernel/entry.S
@@ -184,8 +184,12 @@ sysenter_past_esp:
 	pushl %ebp
 	pushfl
 	pushl $(__USER_CS)
-	pushl $SYSENTER_RETURN
-
+	/*
+	 * Push current_thread_info()->sysenter_return to the stack.
+	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
+	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
+	 */
+	pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp)
 /*
  * Load the potential sixth argument from user stack.
  * Careful about security.
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/kernel/process.c linux-810/arch/i386/kernel/process.c
--- linux-804/arch/i386/kernel/process.c
+++ linux-810/arch/i386/kernel/process.c
@@ -676,6 +676,8 @@ struct task_struct fastcall * __switch_t
 	/* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
 
 	__unlazy_fpu(prev_p);
+	if (next_p->mm)
+		load_user_cs_desc(cpu, next_p->mm);
 
 	/*
 	 * Reload esp0.
@@ -949,3 +951,60 @@ unsigned long arch_align_stack(unsigned 
 		sp -= get_random_int() % 8192;
 	return sp & ~0xf;
 }
+
+void arch_add_exec_range(struct mm_struct *mm, unsigned long limit)
+{
+	if (limit > mm->context.exec_limit) {
+		mm->context.exec_limit = limit;
+		set_user_cs(&mm->context.user_cs, limit);
+		if (mm == current->mm) {
+			preempt_disable();
+			load_user_cs_desc(smp_processor_id(), mm);
+			preempt_enable();
+		}
+	}
+}
+
+void arch_remove_exec_range(struct mm_struct *mm, unsigned long old_end)
+{
+	struct vm_area_struct *vma;
+	unsigned long limit = PAGE_SIZE;
+
+	if (old_end == mm->context.exec_limit) {
+		for (vma = mm->mmap; vma; vma = vma->vm_next)
+			if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit))
+				limit = vma->vm_end;
+
+		mm->context.exec_limit = limit;
+		set_user_cs(&mm->context.user_cs, limit);
+		if (mm == current->mm) {
+			preempt_disable();
+			load_user_cs_desc(smp_processor_id(), mm);
+			preempt_enable();
+		}
+	}
+}
+
+void arch_flush_exec_range(struct mm_struct *mm)
+{
+	mm->context.exec_limit = 0;
+	set_user_cs(&mm->context.user_cs, 0);
+}
+
+/*
+ * Generate random brk address between 128MB and 196MB. (if the layout
+ * allows it.)
+ */
+void randomize_brk(unsigned long old_brk)
+{
+	unsigned long new_brk, range_start, range_end;
+
+	range_start = 0x08000000;
+	if (current->mm->brk >= range_start)
+		range_start = current->mm->brk;
+	range_end = range_start + 0x02000000;
+	new_brk = randomize_range(range_start, range_end, 0);
+	if (new_brk)
+		current->mm->brk = new_brk;
+}
+
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/kernel/signal.c linux-810/arch/i386/kernel/signal.c
--- linux-804/arch/i386/kernel/signal.c
+++ linux-810/arch/i386/kernel/signal.c
@@ -380,7 +380,7 @@ static int setup_frame(int sig, struct k
 			goto give_sigsegv;
 	}
 
-	restorer = &__kernel_sigreturn;
+	restorer = current->mm->context.vdso + (long)&__kernel_sigreturn;
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 
@@ -476,7 +476,7 @@ static int setup_rt_frame(int sig, struc
 		goto give_sigsegv;
 
 	/* Set up to return from userspace.  */
-	restorer = &__kernel_rt_sigreturn;
+	restorer = current->mm->context.vdso + (long)&__kernel_rt_sigreturn;
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 	err |= __put_user(restorer, &frame->pretcode);
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/kernel/smp.c linux-810/arch/i386/kernel/smp.c
--- linux-804/arch/i386/kernel/smp.c
+++ linux-810/arch/i386/kernel/smp.c
@@ -24,6 +24,7 @@
 
 #include <asm/mtrr.h>
 #include <asm/tlbflush.h>
+#include <asm/desc.h>
 #include <mach_apic.h>
 
 /*
@@ -315,6 +316,8 @@ fastcall void smp_invalidate_interrupt(s
 	unsigned long cpu;
 
 	cpu = get_cpu();
+	if (current->active_mm)
+		load_user_cs_desc(cpu, current->active_mm);
 
 	if (!cpu_isset(cpu, flush_cpumask))
 		goto out;
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/kernel/sysenter.c linux-810/arch/i386/kernel/sysenter.c
--- linux-804/arch/i386/kernel/sysenter.c
+++ linux-810/arch/i386/kernel/sysenter.c
@@ -13,6 +13,7 @@
 #include <linux/gfp.h>
 #include <linux/string.h>
 #include <linux/elf.h>
+#include <linux/mman.h>
 
 #include <asm/cpufeature.h>
 #include <asm/msr.h>
@@ -46,11 +47,20 @@ void enable_sep_cpu(void)
 extern const char vsyscall_int80_start, vsyscall_int80_end;
 extern const char vsyscall_sysenter_start, vsyscall_sysenter_end;
 
+struct page *sysenter_page;
+
 int __init sysenter_setup(void)
 {
 	void *page = (void *)get_zeroed_page(GFP_ATOMIC);
 
-	__set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
+	/*
+	 * We keep this page mapped readonly, even though the executable
+	 * portion is randomized into a userspace vma - so that we dont
+	 * have to fix up the data within the VDSO page every time we
+	 * exec().
+	 */
+	__set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_KERNEL_RO);
+	sysenter_page = virt_to_page(page);
 
 	if (!boot_cpu_has(X86_FEATURE_SEP)) {
 		memcpy(page,
@@ -65,3 +75,46 @@ int __init sysenter_setup(void)
 
 	return 0;
 }
+
+extern void SYSENTER_RETURN_OFFSET;
+
+unsigned int vdso_enabled = 0;
+
+void map_vsyscall(void)
+{
+	struct thread_info *ti = current_thread_info();
+	struct vm_area_struct *vma;
+	unsigned long addr;
+
+	if (unlikely(!vdso_enabled)) {
+		current->mm->context.vdso = NULL;
+		return;
+	}
+
+	/*
+	 * Map the vDSO (it will be randomized):
+	 */
+	down_write(&current->mm->mmap_sem);
+	addr = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, 0);
+	current->mm->context.vdso = (void *)addr;
+	ti->sysenter_return = (void *)addr + (long)&SYSENTER_RETURN_OFFSET;
+	if (addr != -1) {
+		vma = find_vma(current->mm, addr);
+		if (vma) {
+			pgprot_val(vma->vm_page_prot) &= ~_PAGE_RW;
+			get_page(sysenter_page);
+			install_page(current->mm, vma, addr,
+					sysenter_page, vma->vm_page_prot);
+			
+		}
+	}
+	up_write(&current->mm->mmap_sem);
+}
+
+static int __init vdso_setup(char *str)
+{
+        vdso_enabled = simple_strtoul(str, NULL, 0);
+        return 1;
+}
+__setup("vdso=", vdso_setup);
+
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/kernel/traps.c linux-810/arch/i386/kernel/traps.c
--- linux-804/arch/i386/kernel/traps.c
+++ linux-810/arch/i386/kernel/traps.c
@@ -458,13 +458,89 @@ DO_ERROR(10, SIGSEGV, "invalid TSS", inv
 DO_ERROR(11, SIGBUS,  "segment not present", segment_not_present)
 DO_ERROR(12, SIGBUS,  "stack segment", stack_segment)
 DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
-DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
+
+
+/*
+ * lazy-check for CS validity on exec-shield binaries:
+ *
+ * the original non-exec stack patch was written by
+ * Solar Designer <solar at openwall.com>. Thanks!
+ */
+static int
+check_lazy_exec_limit(int cpu, struct pt_regs *regs, long error_code)
+{
+	struct desc_struct *desc1, *desc2;
+	struct vm_area_struct *vma;
+	unsigned long limit;
+
+	if (current->mm == NULL)
+		return 0;
+
+	limit = -1UL;
+	if (current->mm->context.exec_limit != -1UL) {
+		limit = PAGE_SIZE;
+		spin_lock(&current->mm->page_table_lock);
+		for (vma = current->mm->mmap; vma; vma = vma->vm_next)
+			if ((vma->vm_flags & VM_EXEC) && (vma->vm_end > limit))
+				limit = vma->vm_end;
+		spin_unlock(&current->mm->page_table_lock);
+		if (limit >= TASK_SIZE)
+			limit = -1UL;
+		current->mm->context.exec_limit = limit;
+	}
+	set_user_cs(&current->mm->context.user_cs, limit);
+
+	desc1 = &current->mm->context.user_cs;
+	desc2 = per_cpu(cpu_gdt_table, cpu) + GDT_ENTRY_DEFAULT_USER_CS;
+
+	if (desc1->a != desc2->a || desc1->b != desc2->b) {
+		/*
+		 * The CS was not in sync - reload it and retry the
+		 * instruction. If the instruction still faults then
+		 * we won't hit this branch next time around.
+		 */
+		if (print_fatal_signals >= 2) {
+			printk("#GPF fixup (%ld[seg:%lx]) at %08lx, CPU#%d.\n", error_code, error_code/8, regs->eip, smp_processor_id());
+			printk(" exec_limit: %08lx, user_cs: %08lx/%08lx, CPU_cs: %08lx/%08lx.\n", current->mm->context.exec_limit, desc1->a, desc1->b, desc2->a, desc2->b);
+		}
+		load_user_cs_desc(cpu, current->mm);
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * The fixup code for errors in iret jumps to here (iret_exc).  It loses
+ * the original trap number and error code.  The bogus trap 32 and error
+ * code 0 are what the vanilla kernel delivers via:
+ * DO_ERROR_INFO(32, SIGSEGV, "iret exception", iret_error, ILL_BADSTK, 0)
+ *
+ * In case of a general protection fault in the iret instruction, we
+ * need to check for a lazy CS update for exec-shield.
+ */
+fastcall void do_iret_error(struct pt_regs *regs, long error_code)
+{
+	int ok = check_lazy_exec_limit(get_cpu(), regs, error_code);
+	put_cpu();
+	if (!ok && notify_die(DIE_TRAP, "iret exception", regs,
+			      error_code, 32, SIGSEGV) != NOTIFY_STOP) {
+		siginfo_t info;
+		info.si_signo = SIGSEGV;
+		info.si_errno = 0;
+		info.si_code = ILL_BADSTK;
+		info.si_addr = 0;
+		do_trap(32, SIGSEGV, "iret exception", 0, regs, error_code,
+			&info);
+	}
+}
 
 fastcall void __kprobes do_general_protection(struct pt_regs * regs,
 					      long error_code)
 {
 	int cpu = get_cpu();
 	struct tss_struct *tss = &per_cpu(init_tss, cpu);
 	struct thread_struct *thread = &current->thread;
+	int ok;
 
 	/*
@@ -490,7 +566,6 @@ fastcall void do_general_protection(stru
 		put_cpu();
 		return;
 	}
-	put_cpu();
 
 	current->thread.error_code = error_code;
 	current->thread.trap_no = 13;
@@ -501,17 +576,31 @@ fastcall void do_general_protection(stru
 	if (!user_mode(regs))
 		goto gp_in_kernel;
 
+	ok = check_lazy_exec_limit(cpu, regs, error_code);
+
+	put_cpu();
+
+	if (ok)
+		return;
+
+	if (print_fatal_signals) {
+		printk("#GPF(%ld[seg:%lx]) at %08lx, CPU#%d.\n", error_code, error_code/8, regs->eip, smp_processor_id());
+		printk(" exec_limit: %08lx, user_cs: %08lx/%08lx.\n", current->mm->context.exec_limit, current->mm->context.user_cs.a, current->mm->context.user_cs.b);
+	}
+
 	current->thread.error_code = error_code;
 	current->thread.trap_no = 13;
 	force_sig(SIGSEGV, current);
 	return;
 
 gp_in_vm86:
+	put_cpu();
 	local_irq_enable();
 	handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
 	return;
 
 gp_in_kernel:
+	put_cpu();
 	if (!fixup_exception(regs)) {
 		if (notify_die(DIE_GPF, "general protection fault", regs,
 				error_code, 13, SIGSEGV) == NOTIFY_STOP)
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/kernel/vsyscall.lds.S linux-810/arch/i386/kernel/vsyscall.lds.S
--- linux-804/arch/i386/kernel/vsyscall.lds.S
+++ linux-810/arch/i386/kernel/vsyscall.lds.S
@@ -7,7 +7,7 @@
 
 SECTIONS
 {
-  . = VSYSCALL_BASE + SIZEOF_HEADERS;
+  . = SIZEOF_HEADERS;
 
   .hash           : { *(.hash) }		:text
   .dynsym         : { *(.dynsym) }
@@ -20,7 +20,7 @@ SECTIONS
      For the layouts to match, we need to skip more than enough
      space for the dynamic symbol table et al.  If this amount
      is insufficient, ld -shared will barf.  Just increase it here.  */
-  . = VSYSCALL_BASE + 0x400;
+  . = 0x400;
 
   .text           : { *(.text) }		:text =0x90909090
   .note		  : { *(.note.*) }		:text :note
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/kernel/vsyscall-sysenter.S linux-810/arch/i386/kernel/vsyscall-sysenter.S
--- linux-804/arch/i386/kernel/vsyscall-sysenter.S
+++ linux-810/arch/i386/kernel/vsyscall-sysenter.S
@@ -24,11 +24,11 @@ __kernel_vsyscall:
 	/* 7: align return point with nop's to make disassembly easier */
 	.space 7,0x90
 
-	/* 14: System call restart point is here! (SYSENTER_RETURN - 2) */
+	/* 14: System call restart point is here! (SYSENTER_RETURN_OFFSET-2) */
 	jmp .Lenter_kernel
 	/* 16: System call normal return point is here! */
-	.globl SYSENTER_RETURN	/* Symbol used by entry.S.  */
-SYSENTER_RETURN:
+	.globl SYSENTER_RETURN_OFFSET	/* Symbol used by sysenter.c  */
+SYSENTER_RETURN_OFFSET:
 	pop %ebp
 .Lpop_ebp:
 	pop %edx
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/mm/init.c linux-810/arch/i386/mm/init.c
--- linux-804/arch/i386/mm/init.c
+++ linux-810/arch/i386/mm/init.c
@@ -401,7 +401,7 @@ u64 __supported_pte_mask = ~_PAGE_NX;
  * Control non executable mappings.
  *
  * on      Enable
- * off     Disable
+ * off     Disable (disables exec-shield too)
  */
 void __init noexec_setup(const char *str)
 {
@@ -411,6 +411,7 @@ void __init noexec_setup(const char *str
 	} else if (!strncmp(str,"off",3)) {
 		disable_nx = 1;
 		__supported_pte_mask &= ~_PAGE_NX;
+		exec_shield = 0;
 	}
 }
 
@@ -475,7 +476,10 @@ void __init paging_init(void)
 	set_nx();
 	if (nx_enabled)
 		printk("NX (Execute Disable) protection: active\n");
+	else
 #endif
+	if (exec_shield)
+		printk("Using x86 segment limits to approximate NX protection\n");
 
 	pagetable_init();
 
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/i386/mm/mmap.c linux-810/arch/i386/mm/mmap.c
--- linux-804/arch/i386/mm/mmap.c
+++ linux-810/arch/i386/mm/mmap.c
@@ -62,15 +62,17 @@ void arch_pick_mmap_layout(struct mm_str
 	 * Fall back to the standard layout if the personality
 	 * bit is set, or if the expected stack growth is unlimited:
 	 */
-	if (sysctl_legacy_va_layout ||
+	if ((exec_shield != 2) && (sysctl_legacy_va_layout ||
 			(current->personality & ADDR_COMPAT_LAYOUT) ||
-			current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
+			current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)) {
 		mm->mmap_base = TASK_UNMAPPED_BASE;
 		mm->get_unmapped_area = arch_get_unmapped_area;
 		mm->unmap_area = arch_unmap_area;
 	} else {
 		mm->mmap_base = mmap_base(mm);
 		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+		if (!(current->personality & READ_IMPLIES_EXEC))
+			mm->get_unmapped_exec_area = arch_get_unmapped_exec_area;
 		mm->unmap_area = arch_unmap_area_topdown;
 	}
 }
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/ia64/ia32/binfmt_elf32.c linux-810/arch/ia64/ia32/binfmt_elf32.c
--- linux-804/arch/ia64/ia32/binfmt_elf32.c
+++ linux-810/arch/ia64/ia32/binfmt_elf32.c
@@ -272,7 +272,7 @@ elf32_set_personality (void)
 }
 
 static unsigned long
-elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
 {
 	unsigned long pgoff = (eppnt->p_vaddr) & ~IA32_PAGE_MASK;
 
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/x86_64/ia32/ia32_binfmt.c linux-810/arch/x86_64/ia32/ia32_binfmt.c
--- linux-804/arch/x86_64/ia32/ia32_binfmt.c
+++ linux-810/arch/x86_64/ia32/ia32_binfmt.c
@@ -396,7 +396,7 @@ int setup_arg_pages(struct linux_binprm 
 }
 
 static unsigned long
-elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type)
+elf32_map (struct file *filep, unsigned long addr, struct elf_phdr *eppnt, int prot, int type, unsigned long unused)
 {
 	unsigned long map_addr;
 	struct task_struct *me = current; 
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/x86_64/kernel/process.c linux-810/arch/x86_64/kernel/process.c
--- linux-804/arch/x86_64/kernel/process.c
+++ linux-810/arch/x86_64/kernel/process.c
@@ -833,10 +833,3 @@ int dump_task_regs(struct task_struct *t
  
 	return 1;
 }
-
-unsigned long arch_align_stack(unsigned long sp)
-{
-	if (randomize_va_space)
-		sp -= get_random_int() % 8192;
-	return sp & ~0xf;
-}
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/x86_64/mm/fault.c linux-810/arch/x86_64/mm/fault.c
--- linux-804/arch/x86_64/mm/fault.c
+++ linux-810/arch/x86_64/mm/fault.c
@@ -73,7 +73,7 @@ static noinline int is_prefetch(struct p
 	instr = (unsigned char *)convert_rip_to_linear(current, regs);
 	max_instr = instr + 15;
 
-	if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE)
+	if (user_mode(regs) && instr >= (unsigned char *)TASK_SIZE64)
 		return 0;
 
 	while (scan_more && instr < max_instr) { 
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/x86_64/mm/Makefile linux-810/arch/x86_64/mm/Makefile
--- linux-804/arch/x86_64/mm/Makefile
+++ linux-810/arch/x86_64/mm/Makefile
@@ -2,7 +2,7 @@
 # Makefile for the linux x86_64-specific parts of the memory manager.
 #
 
-obj-y	 := init.o fault.o ioremap.o extable.o pageattr.o
+obj-y	 := init.o fault.o ioremap.o extable.o pageattr.o mmap.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
 obj-$(CONFIG_NUMA) += numa.o
 obj-$(CONFIG_K8_NUMA) += k8topology.o
diff -urNp --exclude-from=/home/davej/.exclude linux-804/arch/x86_64/mm/mmap.c linux-810/arch/x86_64/mm/mmap.c
--- linux-804/arch/x86_64/mm/mmap.c
+++ linux-810/arch/x86_64/mm/mmap.c
@@ -0,0 +1,95 @@
+/*
+ *  linux/arch/x86-64/mm/mmap.c
+ *
+ *  flexible mmap layout support
+ *
+ * Copyright 2003-2004 Red Hat Inc., Durham, North Carolina.
+ * All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *
+ * Started by Ingo Molnar <mingo at elte.hu>
+ */
+
+#include <linux/personality.h>
+#include <linux/mm.h>
+#include <linux/random.h>
+
+/*
+ * Top of mmap area (just below the process stack).
+ *
+ * Leave an at least ~128 MB hole.
+ */
+#define MIN_GAP (128*1024*1024)
+#define MAX_GAP (TASK_SIZE/6*5)
+
+static inline unsigned long mmap_base(void)
+{
+	unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
+
+	if (gap < MIN_GAP)
+		gap = MIN_GAP;
+	else if (gap > MAX_GAP)
+		gap = MAX_GAP;
+
+	return TASK_SIZE - (gap & PAGE_MASK);
+}
+
+static inline int mmap_is_legacy(void)
+{
+	/*
+	 * Force standard allocation for 64 bit programs.
+	 */
+	if (!test_thread_flag(TIF_IA32))
+		return 1;
+		
+	if (current->personality & ADDR_COMPAT_LAYOUT) 
+		return 1;
+	
+	if (current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY)
+		return 1;
+		
+	return sysctl_legacy_va_layout;
+}
+
+/*
+ * This function, called very early during the creation of a new
+ * process VM image, sets up which VM layout function to use:
+ */
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+	/*
+	 * Fall back to the standard layout if the personality
+	 * bit is set, or if the expected stack growth is unlimited:
+	 */
+	if (mmap_is_legacy()) {
+		mm->mmap_base = TASK_UNMAPPED_BASE;
+		mm->get_unmapped_area = arch_get_unmapped_area;
+		mm->unmap_area = arch_unmap_area;
+	} else {
+		mm->mmap_base = mmap_base();
+		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
+		mm->unmap_area = arch_unmap_area_topdown;
+	}
+}
+
+unsigned long arch_align_stack(unsigned long sp)
+{
+	if (current->flags & PF_RANDOMIZE)
+		sp -= get_random_int() % 8192;
+	return sp & ~0xf;
+}
+
diff -urNp --exclude-from=/home/davej/.exclude linux-804/drivers/char/random.c linux-810/drivers/char/random.c
--- linux-804/drivers/char/random.c
+++ linux-810/drivers/char/random.c
@@ -1634,13 +1634,18 @@ EXPORT_SYMBOL(secure_dccp_sequence_numbe
  */
 unsigned int get_random_int(void)
 {
+	unsigned int val = 0;
+
+#ifdef CONFIG_X86_HAS_TSC
+	rdtscl(val);
+#endif
 	/*
 	 * Use IP's RNG. It suits our purpose perfectly: it re-keys itself
 	 * every second, from the entropy pool (and thus creates a limited
 	 * drain on it), and uses halfMD4Transform within the second. We
 	 * also mix it with jiffies and the PID:
 	 */
-	return secure_ip_id(current->pid + jiffies);
+	return secure_ip_id(current->pid + jiffies + (int)val);
 }
 
 /*
diff -urNp --exclude-from=/home/davej/.exclude linux-804/fs/binfmt_elf.c linux-810/fs/binfmt_elf.c
--- linux-804/fs/binfmt_elf.c
+++ linux-810/fs/binfmt_elf.c
@@ -47,7 +47,7 @@
 
 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
 static int load_elf_library(struct file*);
-static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int);
+static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int, unsigned long);
 extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
 
 #ifndef elf_addr_t
@@ -285,20 +285,59 @@ create_elf_tables(struct linux_binprm *b
 #ifndef elf_map
 
 static unsigned long elf_map(struct file *filep, unsigned long addr,
-			struct elf_phdr *eppnt, int prot, int type)
+			     struct elf_phdr *eppnt, int prot, int type,
+			     unsigned long total_size)
 {
 	unsigned long map_addr;
+	unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr);
+	unsigned long off = eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr);
+
+	addr = ELF_PAGESTART(addr);
+	size = ELF_PAGEALIGN(size);
 
 	down_write(&current->mm->mmap_sem);
-	map_addr = do_mmap(filep, ELF_PAGESTART(addr),
-			   eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, type,
-			   eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));
+
+	/*
+	 * total_size is the size of the ELF (interpreter) image.
+	 * The _first_ mmap needs to know the full size, otherwise
+	 * randomization might put this image into an overlapping
+	 * position with the ELF binary image. (since size < total_size)
+	 * So we first map the 'big' image - and unmap the remainder at
+	 * the end. (which unmap is needed for ELF images with holes.)
+	 */
+	if (total_size) {
+		total_size = ELF_PAGEALIGN(total_size);
+		map_addr = do_mmap(filep, addr, total_size, prot, type, off);
+		if (!BAD_ADDR(map_addr))
+			do_munmap(current->mm, map_addr+size, total_size-size);
+	} else
+		map_addr = do_mmap(filep, addr, size, prot, type, off);
+		
 	up_write(&current->mm->mmap_sem);
-	return(map_addr);
+
+	return map_addr;
 }
 
 #endif /* !elf_map */
 
+static inline unsigned long total_mapping_size(struct elf_phdr *cmds, int nr)
+{
+	int i, first_idx = -1, last_idx = -1;
+
+	for (i = 0; i < nr; i++)
+		if (cmds[i].p_type == PT_LOAD) {
+			last_idx = i;
+			if (first_idx == -1)
+				first_idx = i;
+		}
+
+	if (first_idx == -1)
+		return 0;
+
+	return cmds[last_idx].p_vaddr + cmds[last_idx].p_memsz -
+				ELF_PAGESTART(cmds[first_idx].p_vaddr);
+}
+
 /* This is much more generalized than the library routine read function,
    so we keep this separate.  Technically the library read function
    is only provided so that we can read a.out libraries that have
@@ -306,7 +345,8 @@ static unsigned long elf_map(struct file
 
 static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
 				     struct file * interpreter,
-				     unsigned long *interp_load_addr)
+				     unsigned long *interp_load_addr,
+				     unsigned long no_base)
 {
 	struct elf_phdr *elf_phdata;
 	struct elf_phdr *eppnt;
@@ -314,6 +354,7 @@ static unsigned long load_elf_interp(str
 	int load_addr_set = 0;
 	unsigned long last_bss = 0, elf_bss = 0;
 	unsigned long error = ~0UL;
+	unsigned long total_size;
 	int retval, i, size;
 
 	/* First of all, some simple consistency checks */
@@ -352,6 +393,10 @@ static unsigned long load_elf_interp(str
 		goto out_close;
 	}
 
+	total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum);
+	if (!total_size)
+		goto out_close;
+
 	eppnt = elf_phdata;
 	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
 	  if (eppnt->p_type == PT_LOAD) {
@@ -366,8 +411,11 @@ static unsigned long load_elf_interp(str
 	    vaddr = eppnt->p_vaddr;
 	    if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
 	    	elf_type |= MAP_FIXED;
+	    else if (no_base && interp_elf_ex->e_type == ET_DYN)
+		load_addr = -vaddr;
 
-	    map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
+	    map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type, total_size);
+	    total_size = 0;
 	    error = map_addr;
 	    if (BAD_ADDR(map_addr))
 	    	goto out_close;
@@ -527,7 +575,7 @@ static int load_elf_binary(struct linux_
 	unsigned long reloc_func_desc = 0;
 	char passed_fileno[6];
 	struct files_struct *files;
-	int have_pt_gnu_stack, executable_stack = EXSTACK_DEFAULT;
+	int have_pt_gnu_stack, executable_stack;
 	unsigned long def_flags = 0;
 	struct {
 		struct elfhdr elf_ex;
@@ -683,6 +731,8 @@ static int load_elf_binary(struct linux_
 	}
 
 	elf_ppnt = elf_phdata;
+	executable_stack = EXSTACK_DEFAULT;
+
 	for (i = 0; i < loc->elf_ex.e_phnum; i++, elf_ppnt++)
 		if (elf_ppnt->p_type == PT_GNU_STACK) {
 			if (elf_ppnt->p_flags & PF_X)
@@ -693,6 +743,11 @@ static int load_elf_binary(struct linux_
 		}
 	have_pt_gnu_stack = (i < loc->elf_ex.e_phnum);
 
+	if (current->personality == PER_LINUX && exec_shield == 2) {
+		executable_stack = EXSTACK_DISABLE_X;
+		current->flags |= PF_RANDOMIZE;
+	}
+
 	/* Some simple consistency checks for the interpreter */
 	if (elf_interpreter) {
 		interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
@@ -746,6 +801,15 @@ static int load_elf_binary(struct linux_
 	if (retval)
 		goto out_free_dentry;
 
+#ifdef __i386__
+	/*
+	 * Turn off the CS limit completely if exec-shield disabled or
+	 * NX active:
+	 */
+	if (!exec_shield || executable_stack != EXSTACK_DISABLE_X || nx_enabled)
+		arch_add_exec_range(current->mm, -1);
+#endif
+
 	/* Discard our unneeded old files struct */
 	if (files) {
 		steal_locks(files);
@@ -764,7 +828,8 @@ static int load_elf_binary(struct linux_
 	/* Do this immediately, since STACK_TOP as used in setup_arg_pages
 	   may depend on the personality.  */
 	SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
-	if (elf_read_implies_exec(loc->elf_ex, executable_stack))
+	if (exec_shield != 2 &&
+			elf_read_implies_exec(loc->elf_ex, executable_stack))
 		current->personality |= READ_IMPLIES_EXEC;
 
 	if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
@@ -785,10 +850,10 @@ static int load_elf_binary(struct linux_
 	
 	current->mm->start_stack = bprm->p;
 
+
 	/* Now we do a little grungy work by mmaping the ELF image into
-	   the correct location in memory.  At this point, we assume that
-	   the image should be loaded at fixed address, not at a variable
-	   address. */
+	   the correct location in memory.
+	 */
 
 	for(i = 0, elf_ppnt = elf_phdata; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) {
 		int elf_prot = 0, elf_flags;
@@ -832,16 +897,16 @@ static int load_elf_binary(struct linux_
 		elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
 
 		vaddr = elf_ppnt->p_vaddr;
-		if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) {
+		if (loc->elf_ex.e_type == ET_EXEC || load_addr_set)
 			elf_flags |= MAP_FIXED;
-		} else if (loc->elf_ex.e_type == ET_DYN) {
-			/* Try and get dynamic programs out of the way of the default mmap
-			   base, as well as whatever program they might try to exec.  This
-			   is because the brk will follow the loader, and is not movable.  */
+		else if (loc->elf_ex.e_type == ET_DYN)
+#ifdef __i386__
+			load_bias = 0;
+#else
 			load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
-		}
+#endif
 
-		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
+		error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags, 0);
 		if (BAD_ADDR(error)) {
 			send_sig(SIGKILL, current, 0);
 			goto out_free_dentry;
@@ -918,7 +983,8 @@ static int load_elf_binary(struct linux_
 		else
 			elf_entry = load_elf_interp(&loc->interp_elf_ex,
 						    interpreter,
-						    &interp_load_addr);
+						    &interp_load_addr,
+						    load_bias);
 		if (BAD_ADDR(elf_entry)) {
 			printk(KERN_ERR "Unable to load interpreter %.128s\n",
 				elf_interpreter);
@@ -950,6 +1016,14 @@ static int load_elf_binary(struct linux_
 	}
 #endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */
 
+	/*
+	 * Map the vsyscall trampoline. This address is then passed via
+	 * AT_SYSINFO.
+	 */
+#ifdef __HAVE_ARCH_VSYSCALL
+	map_vsyscall();
+#endif
+
 	compute_creds(bprm);
 	current->flags &= ~PF_FORKNOEXEC;
 	create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT),
@@ -963,6 +1037,10 @@ static int load_elf_binary(struct linux_
 	current->mm->end_data = end_data;
 	current->mm->start_stack = bprm->p;
 
+#ifdef __HAVE_ARCH_RANDOMIZE_BRK
+	if (current->flags & PF_RANDOMIZE)
+		randomize_brk(elf_brk);
+#endif
 	if (current->personality & MMAP_PAGE_ZERO) {
 		/* Why this, you ask???  Well SVr4 maps page 0 as read-only,
 		   and some applications "depend" upon this behavior.
diff -urNp --exclude-from=/home/davej/.exclude linux-804/fs/proc/array.c linux-810/fs/proc/array.c
--- linux-804/fs/proc/array.c
+++ linux-810/fs/proc/array.c
@@ -385,8 +385,12 @@ static int do_task_stat(struct task_stru
 	ppid = pid_alive(task) ? task->group_leader->real_parent->tgid : 0;
 	read_unlock(&tasklist_lock);
 
-	if (!whole || num_threads<2)
-		wchan = get_wchan(task);
+	if (!whole || num_threads<2) {
+		wchan = 0;
+		if (current->uid == task->uid || current->euid == task->uid ||
+				capable(CAP_SYS_NICE))
+			wchan = get_wchan(task);
+	}
 	if (!whole) {
 		min_flt = task->min_flt;
 		maj_flt = task->maj_flt;
diff -urNp --exclude-from=/home/davej/.exclude linux-804/fs/proc/base.c linux-810/fs/proc/base.c
--- linux-804/fs/proc/base.c
+++ linux-810/fs/proc/base.c
@@ -181,7 +181,7 @@ static struct pid_entry tgid_base_stuff[
 	E(PROC_TGID_CMDLINE,   "cmdline", S_IFREG|S_IRUGO),
 	E(PROC_TGID_STAT,      "stat",    S_IFREG|S_IRUGO),
 	E(PROC_TGID_STATM,     "statm",   S_IFREG|S_IRUGO),
-	E(PROC_TGID_MAPS,      "maps",    S_IFREG|S_IRUGO),
+	E(PROC_TGID_MAPS,      "maps",    S_IFREG|S_IRUSR),
 #ifdef CONFIG_NUMA
 	E(PROC_TGID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
 #endif
@@ -221,7 +221,7 @@ static struct pid_entry tid_base_stuff[]
 	E(PROC_TID_CMDLINE,    "cmdline", S_IFREG|S_IRUGO),
 	E(PROC_TID_STAT,       "stat",    S_IFREG|S_IRUGO),
 	E(PROC_TID_STATM,      "statm",   S_IFREG|S_IRUGO),
-	E(PROC_TID_MAPS,       "maps",    S_IFREG|S_IRUGO),
+	E(PROC_TID_MAPS,       "maps",    S_IFREG|S_IRUSR),
 #ifdef CONFIG_NUMA
 	E(PROC_TID_NUMA_MAPS,  "numa_maps",    S_IFREG|S_IRUGO),
 #endif
diff -urNp --exclude-from=/home/davej/.exclude linux-804/fs/proc/task_mmu.c linux-810/fs/proc/task_mmu.c
--- linux-804/fs/proc/task_mmu.c
+++ linux-810/fs/proc/task_mmu.c
@@ -26,13 +26,23 @@ char *task_mem(struct mm_struct *mm, cha
 		"VmStk:\t%8lu kB\n"
 		"VmExe:\t%8lu kB\n"
 		"VmLib:\t%8lu kB\n"
-		"VmPTE:\t%8lu kB\n",
+		"VmPTE:\t%8lu kB\n"
+		"StaBrk:\t%08lx kB\n"
+		"Brk:\t%08lx kB\n"
+		"StaStk:\t%08lx kB\n"
+		,
 		(mm->total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
 		mm->locked_vm << (PAGE_SHIFT-10),
 		get_mm_counter(mm, rss) << (PAGE_SHIFT-10),
 		data << (PAGE_SHIFT-10),
 		mm->stack_vm << (PAGE_SHIFT-10), text, lib,
-		(PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
+		(PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10,
+		mm->start_brk, mm->brk, mm->start_stack);
+#ifdef __i386__
+	if (!nx_enabled)
+		buffer += sprintf(buffer,
+				"ExecLim:\t%08lx\n", mm->context.exec_limit);
+#endif
 	return buffer;
 }
 
@@ -123,7 +133,13 @@ static int show_map_internal(struct seq_
 			vma->vm_end,
 			flags & VM_READ ? 'r' : '-',
 			flags & VM_WRITE ? 'w' : '-',
-			flags & VM_EXEC ? 'x' : '-',
+			(flags & VM_EXEC
+#ifdef __i386__
+				|| (!nx_enabled &&
+				(vma->vm_start < task->mm->context.exec_limit))
+#endif
+			)
+				? 'x' : '-',
 			flags & VM_MAYSHARE ? 's' : 'p',
 			vma->vm_pgoff << PAGE_SHIFT,
 			MAJOR(dev), MINOR(dev), ino, &len);
@@ -137,8 +153,7 @@ static int show_map_internal(struct seq_
 		seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
 	} else {
 		if (mm) {
-			if (vma->vm_start <= mm->start_brk &&
-						vma->vm_end >= mm->brk) {
+			if (vma->vm_end == mm->brk) {
 				pad_len_spaces(m, len);
 				seq_puts(m, "[heap]");
 			} else {
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-i386/desc.h linux-810/include/asm-i386/desc.h
--- linux-804/include/asm-i386/desc.h
+++ linux-810/include/asm-i386/desc.h
@@ -156,6 +156,20 @@ static inline unsigned long get_desc_bas
 	return base;
 }
 
+static inline void set_user_cs(struct desc_struct *desc, unsigned long limit)
+{
+	limit = (limit - 1) / PAGE_SIZE;
+	desc->a = limit & 0xffff;
+	desc->b = (limit & 0xf0000) | 0x00c0fb00;
+}
+
+#define load_user_cs_desc(cpu, mm) \
+    	per_cpu(cpu_gdt_table, (cpu))[GDT_ENTRY_DEFAULT_USER_CS] = (mm)->context.user_cs
+
+extern void arch_add_exec_range(struct mm_struct *mm, unsigned long limit);
+extern void arch_remove_exec_range(struct mm_struct *mm, unsigned long limit);
+extern void arch_flush_exec_range(struct mm_struct *mm);
+
 #endif /* !__ASSEMBLY__ */
 
 #endif
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-i386/elf.h linux-810/include/asm-i386/elf.h
--- linux-804/include/asm-i386/elf.h
+++ linux-810/include/asm-i386/elf.h
@@ -9,6 +9,7 @@
 #include <asm/user.h>
 #include <asm/processor.h>
 #include <asm/system.h>		/* for savesegment */
 #include <asm/auxvec.h>
+#include <asm/desc.h>
 
 #include <linux/utsname.h>
@@ -133,15 +134,22 @@ extern int dump_task_extended_fpu (struc
 #define ELF_CORE_COPY_FPREGS(tsk, elf_fpregs) dump_task_fpu(tsk, elf_fpregs)
 #define ELF_CORE_COPY_XFPREGS(tsk, elf_xfpregs) dump_task_extended_fpu(tsk, elf_xfpregs)
 
-#define VSYSCALL_BASE	(__fix_to_virt(FIX_VSYSCALL))
-#define VSYSCALL_EHDR	((const struct elfhdr *) VSYSCALL_BASE)
-#define VSYSCALL_ENTRY	((unsigned long) &__kernel_vsyscall)
 extern void __kernel_vsyscall;
+#define VSYSCALL_BASE	((unsigned long)current->mm->context.vdso)
+#define VSYSCALL_EHDR	((const struct elfhdr *) VSYSCALL_BASE)
+#define VSYSCALL_OFFSET	((unsigned long) &__kernel_vsyscall)
+#define VSYSCALL_ENTRY	(VSYSCALL_BASE + VSYSCALL_OFFSET)
 
-#define ARCH_DLINFO						\
-do {								\
-		NEW_AUX_ENT(AT_SYSINFO,	VSYSCALL_ENTRY);	\
-		NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE);	\
+/* kernel-internal fixmap address: */
+#define __VSYSCALL_BASE	(__fix_to_virt(FIX_VSYSCALL))
+#define __VSYSCALL_EHDR	((const struct elfhdr *) __VSYSCALL_BASE)
+
+#define ARCH_DLINFO							\
+do {									\
+	if (VSYSCALL_BASE) {						\
+		NEW_AUX_ENT(AT_SYSINFO,	VSYSCALL_ENTRY);		\
+		NEW_AUX_ENT(AT_SYSINFO_EHDR, VSYSCALL_BASE);		\
+	}								\
 } while (0)
 
 /*
@@ -152,15 +160,15 @@ do {								\
  * Dumping its extra ELF program headers includes all the other information
  * a debugger needs to easily find how the vsyscall DSO was being used.
  */
-#define ELF_CORE_EXTRA_PHDRS		(VSYSCALL_EHDR->e_phnum)
+#define ELF_CORE_EXTRA_PHDRS		(__VSYSCALL_EHDR->e_phnum)
 #define ELF_CORE_WRITE_EXTRA_PHDRS					      \
 do {									      \
 	const struct elf_phdr *const vsyscall_phdrs =			      \
-		(const struct elf_phdr *) (VSYSCALL_BASE		      \
-					   + VSYSCALL_EHDR->e_phoff);	      \
+		(const struct elf_phdr *) (__VSYSCALL_BASE		      \
+					   + __VSYSCALL_EHDR->e_phoff);	      \
 	int i;								      \
 	Elf32_Off ofs = 0;						      \
-	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+	for (i = 0; i < __VSYSCALL_EHDR->e_phnum; ++i) {		      \
 		struct elf_phdr phdr = vsyscall_phdrs[i];		      \
 		if (phdr.p_type == PT_LOAD) {				      \
 			BUG_ON(ofs != 0);				      \
@@ -178,10 +186,10 @@ do {									      \
 #define ELF_CORE_WRITE_EXTRA_DATA					      \
 do {									      \
 	const struct elf_phdr *const vsyscall_phdrs =			      \
-		(const struct elf_phdr *) (VSYSCALL_BASE		      \
-					   + VSYSCALL_EHDR->e_phoff);	      \
+		(const struct elf_phdr *) (__VSYSCALL_BASE		      \
+					   + __VSYSCALL_EHDR->e_phoff);	      \
 	int i;								      \
-	for (i = 0; i < VSYSCALL_EHDR->e_phnum; ++i) {			      \
+	for (i = 0; i < __VSYSCALL_EHDR->e_phnum; ++i) {		      \
 		if (vsyscall_phdrs[i].p_type == PT_LOAD)		      \
 			DUMP_WRITE((void *) vsyscall_phdrs[i].p_vaddr,	      \
 				   PAGE_ALIGN(vsyscall_phdrs[i].p_memsz));    \
@@ -190,4 +198,10 @@ do {									      \
 
 #endif
 
+#define __HAVE_ARCH_RANDOMIZE_BRK
+extern void randomize_brk(unsigned long old_brk);
+
+#define __HAVE_ARCH_VSYSCALL
+extern void map_vsyscall(void);
+
 #endif
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-i386/mmu.h linux-810/include/asm-i386/mmu.h
--- linux-804/include/asm-i386/mmu.h
+++ linux-810/include/asm-i386/mmu.h
@@ -7,11 +7,17 @@
  * we put the segment information here.
  *
  * cpu_vm_mask is used to optimize ldt flushing.
+ *
+ * exec_limit is used to track the range PROT_EXEC
+ * mappings span.
  */
 typedef struct { 
 	int size;
 	struct semaphore sem;
 	void *ldt;
+	struct desc_struct user_cs;
+	unsigned long exec_limit;
+	void *vdso;
 } mm_context_t;
 
 #endif
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-i386/pgalloc.h linux-810/include/asm-i386/pgalloc.h
--- linux-804/include/asm-i386/pgalloc.h
+++ linux-810/include/asm-i386/pgalloc.h
@@ -3,6 +3,7 @@
 
 #include <linux/config.h>
 #include <asm/fixmap.h>
+#include <asm/desc.h>
 #include <linux/threads.h>
 #include <linux/mm.h>		/* for struct page */
 
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-i386/processor.h linux-810/include/asm-i386/processor.h
--- linux-804/include/asm-i386/processor.h
+++ linux-810/include/asm-i386/processor.h
@@ -317,7 +317,10 @@ extern int bootloader_type;
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))
+#define TASK_UNMAPPED_BASE	PAGE_ALIGN(TASK_SIZE/3)
+
+#define __HAVE_ARCH_ALIGN_STACK
+extern unsigned long arch_align_stack(unsigned long sp);
 
 #define HAVE_ARCH_PICK_MMAP_LAYOUT
 
@@ -499,6 +502,9 @@ static inline void load_esp0(struct tss_
 	regs->xcs = __USER_CS;					\
 	regs->eip = new_eip;					\
 	regs->esp = new_esp;					\
+	preempt_disable();					\
+	load_user_cs_desc(smp_processor_id(), current->mm);	\
+	preempt_enable();					\
 } while (0)
 
 /*
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-i386/thread_info.h linux-810/include/asm-i386/thread_info.h
--- linux-804/include/asm-i386/thread_info.h
+++ linux-810/include/asm-i386/thread_info.h
@@ -38,6 +38,7 @@ struct thread_info {
 					 	   0-0xBFFFFFFF for user-thead
 						   0-0xFFFFFFFF for kernel-thread
 						*/
+	void			*sysenter_return;
 	struct restart_block    restart_block;
 
 	unsigned long           previous_esp;   /* ESP of the previous stack in case
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-ia64/pgalloc.h linux-810/include/asm-ia64/pgalloc.h
--- linux-804/include/asm-ia64/pgalloc.h
+++ linux-810/include/asm-ia64/pgalloc.h
@@ -1,6 +1,10 @@
 #ifndef _ASM_IA64_PGALLOC_H
 #define _ASM_IA64_PGALLOC_H
 
+#define arch_add_exec_range(mm, limit)		do { ; } while (0)
+#define arch_flush_exec_range(mm)		do { ; } while (0)
+#define arch_remove_exec_range(mm, limit)	do { ; } while (0)
+
 /*
  * This file contains the functions and defines necessary to allocate
  * page tables.
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-ppc/pgalloc.h linux-810/include/asm-ppc/pgalloc.h
--- linux-804/include/asm-ppc/pgalloc.h
+++ linux-810/include/asm-ppc/pgalloc.h
@@ -40,5 +40,10 @@ extern void pte_free(struct page *pte);
 
 #define check_pgt_cache()	do { } while (0)
 
+#define arch_add_exec_range(mm, limit)         do { ; } while (0)
+#define arch_flush_exec_range(mm)              do { ; } while (0)
+#define arch_remove_exec_range(mm, limit)      do { ; } while (0)
+
+
 #endif /* _PPC_PGALLOC_H */
 #endif /* __KERNEL__ */
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-ppc64/pgalloc.h linux-810/include/asm-ppc64/pgalloc.h
--- linux-804/include/asm-ppc64/pgalloc.h
+++ linux-810/include/asm-ppc64/pgalloc.h
@@ -13,6 +13,11 @@ extern kmem_cache_t *pgtable_cache[];
 #define PUD_CACHE_NUM	1
 #define PGD_CACHE_NUM	0
 
+/* Dummy functions since we don't support execshield on ppc */
+#define arch_add_exec_range(mm, limit) do { ; } while (0)
+#define arch_flush_exec_range(mm)      do { ; } while (0)
+#define arch_remove_exec_range(mm, limit) do { ; } while (0)
+
 /*
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-s390/pgalloc.h linux-810/include/asm-s390/pgalloc.h
--- linux-804/include/asm-s390/pgalloc.h
+++ linux-810/include/asm-s390/pgalloc.h
@@ -18,6 +18,10 @@
 #include <linux/gfp.h>
 #include <linux/mm.h>
 
+#define arch_add_exec_range(mm, limit) do { ; } while (0)
+#define arch_flush_exec_range(mm)      do { ; } while (0)
+#define arch_remove_exec_range(mm, limit) do { ; } while (0)
+
 #define check_pgt_cache()	do {} while (0)
 
 extern void diag10(unsigned long addr);
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-sparc/pgalloc.h linux-810/include/asm-sparc/pgalloc.h
--- linux-804/include/asm-sparc/pgalloc.h
+++ linux-810/include/asm-sparc/pgalloc.h
@@ -66,4 +66,8 @@ BTFIXUPDEF_CALL(void, pte_free, struct p
 #define pte_free(pte)		BTFIXUP_CALL(pte_free)(pte)
 #define __pte_free_tlb(tlb, pte)	pte_free(pte)
 
+#define arch_add_exec_range(mm, limit)		do { ; } while (0)
+#define arch_flush_exec_range(mm)		do { ; } while (0)
+#define arch_remove_exec_range(mm, limit)	do { ; } while (0)
+
 #endif /* _SPARC_PGALLOC_H */
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-sparc64/pgalloc.h linux-810/include/asm-sparc64/pgalloc.h
--- linux-804/include/asm-sparc64/pgalloc.h
+++ linux-810/include/asm-sparc64/pgalloc.h
@@ -180,4 +180,8 @@ static inline void pte_free(struct page 
 #define pgd_free(pgd)		free_pgd_fast(pgd)
 #define pgd_alloc(mm)		get_pgd_fast()
 
+#define arch_add_exec_range(mm, limit)		do { ; } while (0)
+#define arch_flush_exec_range(mm)		do { ; } while (0)
+#define arch_remove_exec_range(mm, limit)	do { ; } while (0)
+
 #endif /* _SPARC64_PGALLOC_H */
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-x86_64/pgalloc.h linux-810/include/asm-x86_64/pgalloc.h
--- linux-804/include/asm-x86_64/pgalloc.h
+++ linux-810/include/asm-x86_64/pgalloc.h
@@ -6,6 +6,13 @@
 #include <linux/threads.h>
 #include <linux/mm.h>
 
+#define arch_add_exec_range(mm, limit) \
+		do { (void)(mm), (void)(limit); } while (0)
+#define arch_flush_exec_range(mm) \
+		do { (void)(mm); } while (0)
+#define arch_remove_exec_range(mm, limit) \
+		do { (void)(mm), (void)(limit); } while (0)
+
 #define pmd_populate_kernel(mm, pmd, pte) \
 		set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
 #define pud_populate(mm, pud, pmd) \
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/asm-x86_64/processor.h linux-810/include/asm-x86_64/processor.h
--- linux-804/include/asm-x86_64/processor.h
+++ linux-810/include/asm-x86_64/processor.h
@@ -162,6 +162,11 @@ static inline void clear_in_cr4 (unsigne
  */
 #define TASK_SIZE64	(0x800000000000UL - 4096)
 
+#define __HAVE_ARCH_ALIGN_STACK
+extern unsigned long arch_align_stack(unsigned long sp);
+
+#define HAVE_ARCH_PICK_MMAP_LAYOUT
+
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/linux/mm.h linux-810/include/linux/mm.h
--- linux-804/include/linux/mm.h
+++ linux-810/include/linux/mm.h
@@ -840,7 +840,14 @@ extern struct vm_area_struct *copy_vma(s
 extern void exit_mmap(struct mm_struct *);
 extern int may_expand_vm(struct mm_struct *mm, unsigned long npages);
 
-extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
+extern unsigned long get_unmapped_area_prot(struct file *, unsigned long, unsigned long, unsigned long, unsigned long, int);
+
+
+static inline unsigned long get_unmapped_area(struct file * file, unsigned long addr, 
+		unsigned long len, unsigned long pgoff, unsigned long flags)
+{
+	return get_unmapped_area_prot(file, addr, len, pgoff, flags, 0);	
+}
 
 extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
 	unsigned long len, unsigned long prot,
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/linux/resource.h linux-810/include/linux/resource.h
--- linux-804/include/linux/resource.h
+++ linux-810/include/linux/resource.h
@@ -52,8 +52,11 @@ struct rlimit {
 /*
  * Limit the stack by to some sane default: root can always
  * increase this limit if needed..  8MB seems reasonable.
+ *
+ * (2MB more to cover randomization effects.)
  */
-#define _STK_LIM	(8*1024*1024)
+#define _STK_LIM	(10*1024*1024)
+#define EXEC_STACK_BIAS	(2*1024*1024)
 
 /*
  * GPG wants 32kB of mlocked memory, to make sure pass phrases
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/linux/sched.h linux-810/include/linux/sched.h
--- linux-804/include/linux/sched.h
+++ linux-810/include/linux/sched.h
@@ -36,6 +36,8 @@
 #include <linux/seccomp.h>
 
 struct exec_domain;
+extern int exec_shield;
+extern int print_fatal_signals;
 
 /*
  * cloning flags:
@@ -197,6 +199,10 @@ extern int sysctl_max_map_count;
 extern unsigned long
 arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
 		       unsigned long, unsigned long);
+
+extern unsigned long
+arch_get_unmapped_exec_area(struct file *, unsigned long, unsigned long,
+		       unsigned long, unsigned long);
 extern unsigned long
 arch_get_unmapped_area_topdown(struct file *filp, unsigned long addr,
 			  unsigned long len, unsigned long pgoff,
@@ -218,6 +224,9 @@ struct mm_struct {
 	unsigned long (*get_unmapped_area) (struct file *filp,
 				unsigned long addr, unsigned long len,
 				unsigned long pgoff, unsigned long flags);
+	unsigned long (*get_unmapped_exec_area) (struct file *filp,
+				unsigned long addr, unsigned long len,
+				unsigned long pgoff, unsigned long flags);
 	void (*unmap_area) (struct mm_struct *mm, unsigned long addr);
         unsigned long mmap_base;		/* base of mmap area */
         unsigned long cached_hole_size;         /* if non-zero, the largest hole below free_area_cache */
diff -urNp --exclude-from=/home/davej/.exclude linux-804/include/linux/sysctl.h linux-810/include/linux/sysctl.h
--- linux-804/include/linux/sysctl.h
+++ linux-810/include/linux/sysctl.h
@@ -92,6 +92,9 @@ enum
 
 	KERN_CAP_BSET=14,	/* int: capability bounding set */
 	KERN_PANIC=15,		/* int: panic timeout */
+	KERN_EXEC_SHIELD=1000,	/* int: exec-shield enabled (0/1/2) */
+	KERN_PRINT_FATAL=1001,	/* int: print fatal signals (0/1/2) */
+	KERN_VDSO=1002,		/* int: VDSO enabled (0/1) */
 	KERN_REALROOTDEV=16,	/* real root device to mount after initrd */
 
 	KERN_SPARC_REBOOT=21,	/* reboot command on Sparc */
diff -urNp --exclude-from=/home/davej/.exclude linux-804/kernel/signal.c linux-810/kernel/signal.c
--- linux-804/kernel/signal.c
+++ linux-810/kernel/signal.c
@@ -1209,6 +1209,37 @@ kill_proc_info(int sig, struct siginfo *
 	return error;
 }
 
+int print_fatal_signals = 0;
+
+static void print_fatal_signal(struct pt_regs *regs, int signr)
+{
+	printk("%s/%d: potentially unexpected fatal signal %d.\n",
+		current->comm, current->pid, signr);
+		
+#ifdef __i386__
+	printk("code at %08lx: ", regs->eip);
+	{
+		int i;
+		for (i = 0; i < 16; i++) {
+			unsigned char insn;
+
+			__get_user(insn, (unsigned char *)(regs->eip + i));
+			printk("%02x ", insn);
+		}
+	}
+#endif	
+	printk("\n");
+	show_regs(regs);
+}
+
+static int __init setup_print_fatal_signals(char *str)
+{
+	get_option (&str, &print_fatal_signals);
+
+	return 1;
+}
+
+__setup("print-fatal-signals=", setup_print_fatal_signals);
 
 /*
  * kill_something_info() interprets pid in interesting ways just like kill(2).
@@ -1859,6 +1890,11 @@ relock:
 		if (!signr)
 			break; /* will return 0 */
 
+		if ((signr == SIGSEGV) && print_fatal_signals) {
+			spin_unlock_irq(&current->sighand->siglock);
+			print_fatal_signal(regs, signr);
+			spin_lock_irq(&current->sighand->siglock);
+		}
 		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
 			ptrace_signal_deliver(regs, cookie);
 
@@ -1954,6 +1990,8 @@ relock:
 		 * Anything else is fatal, maybe with a core dump.
 		 */
 		current->flags |= PF_SIGNALED;
+		if (print_fatal_signals)
+			print_fatal_signal(regs, signr);
 		if (sig_kernel_coredump(signr)) {
 			/*
 			 * If it was able to dump core, this kills all
diff -urNp --exclude-from=/home/davej/.exclude linux-804/kernel/sysctl.c linux-810/kernel/sysctl.c
--- linux-804/kernel/sysctl.c
+++ linux-810/kernel/sysctl.c
@@ -74,6 +74,19 @@ extern int proc_unknown_nmi_panic(ctl_ta
 				  void __user *, size_t *, loff_t *);
 #endif
 
+extern unsigned int vdso_enabled;
+
+int exec_shield = 1;
+
+static int __init setup_exec_shield(char *str)
+{
+        get_option (&str, &exec_shield);
+
+        return 1;
+}
+
+__setup("exec-shield=", setup_exec_shield);
+
 /* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
 static int maxolduid = 65535;
 static int minolduid;
@@ -279,6 +292,32 @@ static ctl_table kern_table[] = {
 		.proc_handler	= &proc_dointvec,
 	},
 	{
+		.ctl_name	= KERN_EXEC_SHIELD,
+		.procname	= "exec-shield",
+		.data		= &exec_shield,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+	{
+		.ctl_name	= KERN_PRINT_FATAL,
+		.procname	= "print-fatal-signals",
+		.data		= &print_fatal_signals,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+#ifdef __i386__
+	{
+		.ctl_name	= KERN_VDSO,
+		.procname	= "vdso",
+		.data		= &vdso_enabled,
+		.maxlen		= sizeof(int),
+		.mode		= 0644,
+		.proc_handler	= &proc_dointvec,
+	},
+#endif
+	{
 		.ctl_name	= KERN_CORE_USES_PID,
 		.procname	= "core_uses_pid",
 		.data		= &core_uses_pid,
--- linux-2.6.13/mm/fremap.c~	2005-10-13 17:34:08.000000000 -0400
+++ linux-2.6.13/mm/fremap.c	2005-10-13 17:34:58.000000000 -0400
@@ -85,13 +85,15 @@ int install_page(struct mm_struct *mm, s
 	 * caller about it.
 	 */
 	err = -EINVAL;
-	inode = vma->vm_file->f_mapping->host;
-	size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
-	if (!page->mapping || page->index >= size)
-		goto err_unlock;
-	err = -ENOMEM;
-	if (page_mapcount(page) > INT_MAX/2)
-		goto err_unlock;
+	if (vma->vm_file) {
+		inode = vma->vm_file->f_mapping->host;
+		size = (i_size_read(inode) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+		if (!page->mapping || page->index >= size)
+			goto err_unlock;
+		err = -ENOMEM;
+		if (page_mapcount(page) > INT_MAX/2)
+			goto err_unlock;
+	}
 
 	zap_pte(mm, vma, addr, pte);
 
diff -urNp --exclude-from=/home/davej/.exclude linux-804/mm/mmap.c linux-810/mm/mmap.c
--- linux-804/mm/mmap.c
+++ linux-810/mm/mmap.c
@@ -24,6 +24,7 @@
 #include <linux/mount.h>
 #include <linux/mempolicy.h>
 #include <linux/rmap.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/cacheflush.h>
@@ -342,6 +343,8 @@ static inline void
 __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma,
 		struct vm_area_struct *prev, struct rb_node *rb_parent)
 {
+	if (vma->vm_flags & VM_EXEC)
+		arch_add_exec_range(mm, vma->vm_end);
 	if (prev) {
 		vma->vm_next = prev->vm_next;
 		prev->vm_next = vma;
@@ -446,6 +449,8 @@ __vma_unlink(struct mm_struct *mm, struc
 	rb_erase(&vma->vm_rb, &mm->mm_rb);
 	if (mm->mmap_cache == vma)
 		mm->mmap_cache = prev;
+	if (vma->vm_flags & VM_EXEC)
+		arch_remove_exec_range(mm, vma->vm_end);
 }
 
 /*
@@ -751,6 +756,8 @@ struct vm_area_struct *vma_merge(struct 
 		} else					/* cases 2, 5, 7 */
 			vma_adjust(prev, prev->vm_start,
 				end, prev->vm_pgoff, NULL);
+		if (prev->vm_flags & VM_EXEC)
+			arch_add_exec_range(mm, prev->vm_end);
 		return prev;
 	}
 
@@ -922,7 +929,7 @@ unsigned long do_mmap_pgoff(struct file 
 	/* Obtain the address to map to. we verify (or select) it and ensure
 	 * that it represents a valid section of the address space.
 	 */
-	addr = get_unmapped_area(file, addr, len, pgoff, flags);
+	addr = get_unmapped_area_prot(file, addr, len, pgoff, flags, prot & PROT_EXEC);
 	if (addr & ~PAGE_MASK)
 		return addr;
 
@@ -1328,16 +1335,21 @@ void arch_unmap_area_topdown(struct mm_s
 		mm->free_area_cache = mm->mmap_base;
 }
 
+
 unsigned long
-get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
-		unsigned long pgoff, unsigned long flags)
+get_unmapped_area_prot(struct file *file, unsigned long addr, unsigned long len,
+		unsigned long pgoff, unsigned long flags, int exec)
 {
 	unsigned long ret;
 
 	if (!(flags & MAP_FIXED)) {
 		unsigned long (*get_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
 
-		get_area = current->mm->get_unmapped_area;
+		if (exec && current->mm->get_unmapped_exec_area)
+			get_area = current->mm->get_unmapped_exec_area;
+		else
+			get_area = current->mm->get_unmapped_area;
+
 		if (file && file->f_op && file->f_op->get_unmapped_area)
 			get_area = file->f_op->get_unmapped_area;
 		addr = get_area(file, addr, len, pgoff, flags);
@@ -1368,7 +1380,71 @@ get_unmapped_area(struct file *file, uns
 	return addr;
 }
 
-EXPORT_SYMBOL(get_unmapped_area);
+EXPORT_SYMBOL(get_unmapped_area_prot);
+
+#define SHLIB_BASE             0x00111000
+
+unsigned long arch_get_unmapped_exec_area(struct file *filp, unsigned long addr0,
+		unsigned long len0, unsigned long pgoff, unsigned long flags)
+{
+	unsigned long addr = addr0, len = len0;
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long tmp;
+
+	if (len > TASK_SIZE)
+		return -ENOMEM;
+
+	if (!addr && !(flags & MAP_FIXED))
+		addr = randomize_range(SHLIB_BASE, 0x01000000, len);
+
+	if (addr) {
+		addr = PAGE_ALIGN(addr);
+		vma = find_vma(mm, addr);
+		if (TASK_SIZE - len >= addr &&
+		    (!vma || addr + len <= vma->vm_start)) {
+			return addr;
+		}
+	}
+
+	addr = SHLIB_BASE;
+	for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
+		/* At this point:  (!vma || addr < vma->vm_end). */
+		if (TASK_SIZE - len < addr)
+			return -ENOMEM;
+
+		if (!vma || addr + len <= vma->vm_start) {
+			/*
+			 * Must not let a PROT_EXEC mapping get into the
+			 * brk area:
+			 */
+			if (addr + len > mm->brk)
+				goto failed;
+
+			/*
+			 * Up until the brk area we randomize addresses
+			 * as much as possible:
+			 */
+			if (addr >= 0x01000000) {
+				tmp = randomize_range(0x01000000, PAGE_ALIGN(max(mm->start_brk, 0x08000000)), len);
+				vma = find_vma(mm, tmp);
+				if (TASK_SIZE - len >= tmp &&
+				    (!vma || tmp + len <= vma->vm_start))
+					return tmp;
+			}
+			/*
+			 * Ok, randomization didnt work out - return
+			 * the result of the linear search:
+			 */
+			return addr;
+		}
+		addr = vma->vm_end;
+	}
+
+failed:
+	return current->mm->get_unmapped_area(filp, addr0, len0, pgoff, flags);
+}
+
 
 /* Look up the first VMA which satisfies  addr < vm_end,  NULL if none. */
 struct vm_area_struct * find_vma(struct mm_struct * mm, unsigned long addr)
@@ -1443,6 +1519,14 @@ out:
 	return prev ? prev->vm_next : vma;
 }
 
+static int over_stack_limit(unsigned long sz)
+{
+	if (sz < EXEC_STACK_BIAS)
+		return 0;
+	return (sz - EXEC_STACK_BIAS) >
+			current->signal->rlim[RLIMIT_STACK].rlim_cur;
+}
+
 /*
  * Verify that the stack growth is acceptable and
  * update accounting. This is shared with both the
@@ -1458,7 +1542,7 @@ static int acct_stack_growth(struct vm_a
 		return -ENOMEM;
 
 	/* Stack limit test */
-	if (size > rlim[RLIMIT_STACK].rlim_cur)
+	if (over_stack_limit(size))
 		return -ENOMEM;
 
 	/* mlock limit tests */
@@ -1740,10 +1824,14 @@ int split_vma(struct mm_struct * mm, str
 	if (new->vm_ops && new->vm_ops->open)
 		new->vm_ops->open(new);
 
-	if (new_below)
+	if (new_below) {
+		unsigned long old_end = vma->vm_end;
+
 		vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff +
 			((addr - new->vm_start) >> PAGE_SHIFT), new);
-	else
+		if (vma->vm_flags & VM_EXEC)
+			arch_remove_exec_range(mm, old_end);
+	} else
 		vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new);
 
 	return 0;
@@ -1960,6 +2048,7 @@ void exit_mmap(struct mm_struct *mm)
 	set_mm_counter(mm, rss, 0);
 	mm->total_vm = 0;
 	mm->locked_vm = 0;
+	arch_flush_exec_range(mm);
 
 	spin_unlock(&mm->page_table_lock);
 
diff -urNp --exclude-from=/home/davej/.exclude linux-804/mm/mprotect.c linux-810/mm/mprotect.c
--- linux-804/mm/mprotect.c
+++ linux-810/mm/mprotect.c
@@ -22,6 +22,7 @@
 
 #include <asm/uaccess.h>
 #include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
 
@@ -106,7 +107,7 @@ mprotect_fixup(struct vm_area_struct *vm
 	struct mm_struct *mm = vma->vm_mm;
 	unsigned long oldflags = vma->vm_flags;
 	long nrpages = (end - start) >> PAGE_SHIFT;
-	unsigned long charged = 0;
+	unsigned long charged = 0, old_end = vma->vm_end;
 	pgprot_t newprot;
 	pgoff_t pgoff;
 	int error;
@@ -167,6 +168,8 @@ success:
 	 */
 	vma->vm_flags = newflags;
 	vma->vm_page_prot = newprot;
+	if (oldflags & VM_EXEC)
+		arch_remove_exec_range(current->mm, old_end);
 	change_protection(vma, start, end, newprot);
 	__vm_stat_account(mm, oldflags, vma->vm_file, -nrpages);
 	__vm_stat_account(mm, newflags, vma->vm_file, nrpages);
diff -urNp --exclude-from=/home/davej/.exclude linux-804/mm/mremap.c linux-810/mm/mremap.c
--- linux-804/mm/mremap.c
+++ linux-810/mm/mremap.c
@@ -407,8 +407,8 @@ unsigned long do_mremap(unsigned long ad
 			if (vma->vm_flags & VM_MAYSHARE)
 				map_flags |= MAP_SHARED;
 
-			new_addr = get_unmapped_area(vma->vm_file, 0, new_len,
-						vma->vm_pgoff, map_flags);
+			new_addr = get_unmapped_area_prot(vma->vm_file, 0, new_len, 
+				vma->vm_pgoff, map_flags, vma->vm_flags & VM_EXEC);
 			ret = new_addr;
 			if (new_addr & ~PAGE_MASK)
 				goto out;
diff -urNp --exclude-from=/home/davej/.exclude linux-812/arch/i386/kernel/cpu/common.c linux-813/arch/i386/kernel/cpu/common.c
--- linux-812/arch/i386/kernel/cpu/common.c
+++ linux-813/arch/i386/kernel/cpu/common.c
@@ -397,6 +397,13 @@ void __devinit identify_cpu(struct cpuin
 	if (disable_pse)
 		clear_bit(X86_FEATURE_PSE, c->x86_capability);
 
+	if (exec_shield != 0) {
+#ifdef CONFIG_HIGHMEM64G   /* NX implies PAE */
+		if (!test_bit(X86_FEATURE_NX, c->x86_capability))
+#endif
+		clear_bit(X86_FEATURE_SEP, c->x86_capability);
+	}
+
 	/* If the model name is still unset, do table lookup. */
 	if ( !c->x86_model_id[0] ) {
 		char *p;
diff -urpN --exclude-from=/home/devel/davej/.exclude linux-2.6.13/arch/x86_64/ia32/ia32_binfmt.c linux-2.6.13-a/arch/x86_64/ia32/ia32_binfmt.c
--- linux-2.6.13/arch/x86_64/ia32/ia32_binfmt.c	2005-10-14 20:55:36.000000000 -0400
+++ linux-2.6.13-a/arch/x86_64/ia32/ia32_binfmt.c	2005-10-14 20:56:15.000000000 -0400
@@ -249,8 +249,6 @@ elf_core_copy_task_xfpregs(struct task_s
 #define elf_check_arch(x) \
 	((x)->e_machine == EM_386)
 
-extern int force_personality32;
-
 #define ELF_EXEC_PAGESIZE PAGE_SIZE
 #define ELF_HWCAP (boot_cpu_data.x86_capability[0])
 #define ELF_PLATFORM  ("i686")
@@ -264,8 +262,6 @@ do {							\
 		set_thread_flag(TIF_ABI_PENDING);		\
 	else							\
 		clear_thread_flag(TIF_ABI_PENDING);		\
-	/* XXX This overwrites the user set personality */	\
-	current->personality |= force_personality32;		\
 } while (0)
 
 /* Override some function names */
diff -urpN --exclude-from=/home/devel/davej/.exclude linux-2.6.13/arch/x86_64/kernel/process.c linux-2.6.13-a/arch/x86_64/kernel/process.c
--- linux-2.6.13/arch/x86_64/kernel/process.c	2005-10-14 20:55:36.000000000 -0400
+++ linux-2.6.13-a/arch/x86_64/kernel/process.c	2005-10-14 20:56:15.000000000 -0400
@@ -638,12 +638,6 @@ void set_personality_64bit(void)
 
 	/* Make sure to be in 64bit mode */
 	clear_thread_flag(TIF_IA32); 
-
-	/* TBD: overwrites user setup. Should have two bits.
-	   But 64bit processes have always behaved this way,
-	   so it's not too bad. The main problem is just that
-   	   32bit childs are affected again. */
-	current->personality &= ~READ_IMPLIES_EXEC;
 }
 
 asmlinkage long sys_fork(struct pt_regs *regs)
diff -urpN --exclude-from=/home/devel/davej/.exclude linux-2.6.13/arch/x86_64/kernel/setup64.c linux-2.6.13-a/arch/x86_64/kernel/setup64.c
--- linux-2.6.13/arch/x86_64/kernel/setup64.c	2005-10-14 20:55:36.000000000 -0400
+++ linux-2.6.13-a/arch/x86_64/kernel/setup64.c	2005-10-14 20:56:15.000000000 -0400
@@ -45,7 +45,7 @@ Control non executable mappings for 64bi
 on	Enable(default)
 off	Disable
 */ 
-int __init nonx_setup(char *str)
+void __init nonx_setup(const char *str)
 {
 	if (!strncmp(str, "on", 2)) {
                 __supported_pte_mask |= _PAGE_NX; 
@@ -53,29 +53,8 @@ int __init nonx_setup(char *str)
 	} else if (!strncmp(str, "off", 3)) {
 		do_not_nx = 1;
 		__supported_pte_mask &= ~_PAGE_NX;
-        }
-	return 0;
+        } 
 } 
-__setup("noexec=", nonx_setup);	/* parsed early actually */
-
-int force_personality32 = READ_IMPLIES_EXEC;
-
-/* noexec32=on|off
-Control non executable heap for 32bit processes.
-To control the stack too use noexec=off
-
-on	PROT_READ does not imply PROT_EXEC for 32bit processes
-off	PROT_READ implies PROT_EXEC (default)
-*/
-static int __init nonx32_setup(char *str)
-{
-	if (!strcmp(str, "on"))
-		force_personality32 &= ~READ_IMPLIES_EXEC;
-	else if (!strcmp(str, "off"))
-		force_personality32 |= READ_IMPLIES_EXEC;
-	return 0;
-}
-__setup("noexec32=", nonx32_setup);
 
 /*
  * Great future plan:
diff -urpN --exclude-from=/home/devel/davej/.exclude linux-2.6.13/include/asm-x86_64/pgtable.h linux-2.6.13-a/include/asm-x86_64/pgtable.h
--- linux-2.6.13/include/asm-x86_64/pgtable.h	2005-10-14 20:55:36.000000000 -0400
+++ linux-2.6.13-a/include/asm-x86_64/pgtable.h	2005-10-14 20:56:15.000000000 -0400
@@ -20,7 +20,7 @@ extern unsigned long __supported_pte_mas
 
 #define swapper_pg_dir init_level4_pgt
 
-extern int nonx_setup(char *str);
+extern void nonx_setup(const char *str);
 extern void paging_init(void);
 extern void clear_kernel_mapping(unsigned long addr, unsigned long size);
 

linux-2.6-xen-vdso-note.patch:
 linux-2.6.11/include/asm-xen/asm-i386/page.h   |    2 +
 linux-2.6.12/arch/xen/i386/kernel/Makefile     |    6 ++--
 linux-2.6.12/arch/xen/i386/kernel/ldt.c        |    3 +-
 linux-2.6/arch/xen/i386/kernel/vsyscall-note.S |   32 +++++++++++++++++++++++++
 4 files changed, 39 insertions(+), 4 deletions(-)

--- NEW FILE linux-2.6-xen-vdso-note.patch ---
--- linux-2.6/arch/xen/i386/kernel/vsyscall-note.S
+++ linux-2.6/arch/xen/i386/kernel/vsyscall-note.S
@@ -0,0 +1,32 @@
+/*
+ * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text.
+ * Here we can supply some information useful to userland.
+ * First we get the vanilla i386 note that supplies the kernel version info.
+ */
+
+#include "../../../i386/kernel/vsyscall-note.S"
+
+/*
+ * Now we add a special note telling glibc's dynamic linker a fake hardware
+ * flavor that it will use to choose the search path for libraries in the
+ * same way it uses real hardware capabilities like "mmx".
+ * We supply "nosegneg" as the fake capability, to indicate that we
+ * do not like negative offsets in instructions using segment overrides,
+ * since we implement those inefficiently.  This makes it possible to
+ * install libraries optimized to avoid those access patterns in someplace
+ * like /lib/i686/tls/nosegneg.  Note that an /etc/ld.so.conf.d/file
+ * corresponding to the bits here is needed to make ldconfig work right.
+ * It should contain:
+ *	hwcap 0 nosegneg
+ * to match the mapping of bit to name that we give here.
+ */
+#define NOTE_KERNELCAP_BEGIN(ncaps, mask) \
+	ASM_ELF_NOTE_BEGIN(".note.kernelcap", "a", "GNU", 2) \
+	.long ncaps, mask
+#define NOTE_KERNELCAP(bit, name) \
+	.byte bit; .asciz name
+#define NOTE_KERNELCAP_END ASM_ELF_NOTE_END
+
+NOTE_KERNELCAP_BEGIN(1, 1)
+NOTE_KERNELCAP(0, "nosegneg")
+NOTE_KERNELCAP_END
--- linux-2.6.11/include/asm-xen/asm-i386/page.h.vdso	2005-04-27 10:33:03.000000000 -0400
+++ linux-2.6.11/include/asm-xen/asm-i386/page.h	2005-04-27 10:33:19.000000000 -0400
@@ -200,6 +200,8 @@ extern int sysctl_legacy_va_layout;
 
 #define devmem_is_allowed(x) 1
 
+#define __HAVE_ARCH_GATE_AREA 1
+
 #endif /* __KERNEL__ */
 
 #endif /* _I386_PAGE_H */
--- linux-2.6.12/arch/xen/i386/kernel/ldt.c.vdso	2005-08-19 10:50:02.000000000 -0400
+++ linux-2.6.12/arch/xen/i386/kernel/ldt.c	2005-08-21 11:01:21.000000000 -0400
@@ -101,8 +101,9 @@
 	struct mm_struct * old_mm;
 	int retval = 0;
 
-	memset(&mm->context, 0, sizeof(mm->context));
 	init_MUTEX(&mm->context.sem);
+	mm->context.size = 0;
+	mm->context.pinned = 0;
 	old_mm = current->mm;
 	if (old_mm && old_mm->context.size > 0) {
 		down(&old_mm->context.sem);
--- linux-2.6.12/arch/xen/i386/kernel/Makefile.vdso	2005-08-22 13:38:36.000000000 -0400
+++ linux-2.6.12/arch/xen/i386/kernel/Makefile	2005-08-22 13:42:00.000000000 -0400
@@ -69,7 +69,7 @@
 
 $(obj)/vsyscall-int80.so $(obj)/vsyscall-sysenter.so: \
 $(obj)/vsyscall-%.so: $(src)/vsyscall.lds \
-		      $(obj)/vsyscall-%.o FORCE
+		      $(obj)/vsyscall-%.o $(obj)/vsyscall-note.o FORCE
 	$(call if_changed,syscall)
 
 # We also create a special relocatable object that should mirror the symbol
@@ -81,11 +81,11 @@
 
 SYSCFLAGS_vsyscall-syms.o = -r
 $(obj)/vsyscall-syms.o: $(src)/vsyscall.lds \
-			$(obj)/vsyscall-sysenter.o FORCE
+			$(obj)/vsyscall-sysenter.o $(obj)/vsyscall-note.o FORCE
 	$(call if_changed,syscall)
 
 c-link	:=
-s-link	:= vsyscall-int80.o vsyscall-sysenter.o vsyscall-sigreturn.o vsyscall.lds.o syscall_table.o
+s-link	:= vsyscall-int80.o vsyscall-sysenter.o vsyscall-sigreturn.o vsyscall.lds.o vsyscall-note.o syscall_table.o
 
 $(patsubst %.o,$(obj)/%.c,$(c-obj-y) $(c-obj-m) $(c-link)) $(patsubst %.o,$(obj)/%.S,$(s-obj-y) $(s-link)):
 	@ln -fsn $(srctree)/arch/i386/kernel/$(notdir $@) $@


Index: kernel-2.6.spec
===================================================================
RCS file: /cvs/dist/rpms/kernel/devel/kernel-2.6.spec,v
retrieving revision 1.1606
retrieving revision 1.1607
diff -u -r1.1606 -r1.1607
--- kernel-2.6.spec	15 Oct 2005 00:49:29 -0000	1.1606
+++ kernel-2.6.spec	15 Oct 2005 01:02:03 -0000	1.1607
@@ -232,11 +232,10 @@
 Patch802: linux-2.6-build-qconfig-qt-lib64.patch
 Patch803: linux-2.6-build-reference-discarded-opd.patch
 
-Patch810: linux-2.6.11-execshield.patch
-Patch811: linux-2.6.10-x86_64-read-implies-exec32.patch
-Patch812: linux-2.6.8-execshield-xen.patch
-Patch813: linux-2.6-execshield-vdso.patch
-Patch814: linux-2.6.12rc3-xen-vdso-note.patch
+Patch810: linux-2.6-execshield.patch
+Patch811: linux-2.6-execshield-xen.patch
+Patch812: linux-2.6-execshield-vdso.patch
+Patch813: linux-2.6-xen-vdso-note.patch
 
 # Module signing infrastructure.
 Patch900: linux-2.6.7-modsign-core.patch
@@ -604,20 +603,17 @@
 # Exec shield 
 %patch810 -p1
 
-# Revert x86-64 read-implies-exec on 32 bit processes.
-%patch811 -p1 -R
-
 # Xen exec-shield bits
 %if %{includexen}
-%patch812 -p1
+%patch811 -p1
 %endif
 
 # Fix up the vdso.
-%patch813 -p1
+%patch812 -p1
 
 # Xen vDSO hack
 %if %{includexen}
-%patch814 -p1
+%patch813 -p1
 %endif
 
 #


--- linux-2.6.10-x86_64-read-implies-exec32.patch DELETED ---


--- linux-2.6.11-execshield.patch DELETED ---


--- linux-2.6.12rc3-xen-vdso-note.patch DELETED ---


--- linux-2.6.8-execshield-xen.patch DELETED ---




More information about the fedora-cvs-commits mailing list