From: Arjan van de Ven <arjan@infradead.org>

In addition to randomisation of the stack pointer within the stack, the stack
itself should be randomized too.  We need both approaches, we can only
randomize the stack itself in pagesize increments.  However randomizing large
ranges with the stackpointer runs into the situation where a huge chunk of the
stack rlimit is used by the randomisation; this is undesirable so we need to
do both.

Signed-off-by: Arjan van de Ven <arjan@infradead.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 /dev/null               |    0 
 25-akpm/fs/binfmt_elf.c |   17 ++++++++++++++++-
 25-akpm/fs/exec.c       |    2 +-
 3 files changed, 17 insertions(+), 2 deletions(-)

diff -puN fs/binfmt_elf.c~randomisation-top-of-stack-randomization fs/binfmt_elf.c
--- 25/fs/binfmt_elf.c~randomisation-top-of-stack-randomization	2005-02-02 15:22:21.115704688 -0800
+++ 25-akpm/fs/binfmt_elf.c	2005-02-02 15:22:21.123703472 -0800
@@ -37,6 +37,7 @@
 #include <linux/pagemap.h>
 #include <linux/security.h>
 #include <linux/syscalls.h>
+#include <linux/random.h>
 
 #include <asm/uaccess.h>
 #include <asm/param.h>
@@ -494,6 +495,19 @@ out:
 #define INTERPRETER_ELF 2
 
 
+static unsigned long randomize_stack_top(unsigned long stack_top)
+{
+	unsigned int random_variable = 0;
+
+	if (current->flags & PF_RANDOMIZE)
+		random_variable = get_random_int() % (8*1024*1024);
+#ifdef CONFIG_STACK_GROWSUP
+	return PAGE_ALIGN(stack_top + random_variable);
+#else
+	return PAGE_ALIGN(stack_top - random_variable);
+#endif
+}
+
 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
 {
 	struct file *interpreter = NULL; /* to shut gcc up */
@@ -761,7 +775,8 @@ static int load_elf_binary(struct linux_
 	   change some of these later */
 	current->mm->rss = 0;
 	current->mm->free_area_cache = current->mm->mmap_base;
-	retval = setup_arg_pages(bprm, STACK_TOP, executable_stack);
+	retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP),
+				 executable_stack);
 	if (retval < 0) {
 		send_sig(SIGKILL, current, 0);
 		goto out_free_dentry;
diff -L fs/binfmt_elf.c.org -puN /dev/null /dev/null
diff -puN fs/exec.c~randomisation-top-of-stack-randomization fs/exec.c
--- 25/fs/exec.c~randomisation-top-of-stack-randomization	2005-02-02 15:22:21.117704384 -0800
+++ 25-akpm/fs/exec.c	2005-02-02 15:22:21.121703776 -0800
@@ -400,7 +400,7 @@ int setup_arg_pages(struct linux_binprm 
 	while (i < MAX_ARG_PAGES)
 		bprm->page[i++] = NULL;
 #else
-	stack_base = arch_align_stack(STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE);
+	stack_base = arch_align_stack(stack_top - MAX_ARG_PAGES*PAGE_SIZE);
 	stack_base = PAGE_ALIGN(stack_base);
 	bprm->p += stack_base;
 	mm->arg_start = bprm->p;
diff -L fs/exec.c.org -puN /dev/null /dev/null
_