diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c
index db6b9ed..e2b77bf 100644
--- a/arch/x86/kernel/sys_i386_32.c
+++ b/arch/x86/kernel/sys_i386_32.c
@@ -46,6 +46,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 	unsigned long start_addr, pax_task_size = TASK_SIZE;
+	unsigned long offset = (!filp && (flags & MAP_STACK)) ? ((random32() & 0xFF) << PAGE_SHIFT) : 0;
 
 #ifdef CONFIG_PAX_SEGMEXEC
 	if (mm->pax_flags & MF_PAX_SEGMEXEC)
@@ -68,7 +69,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 		addr = PAGE_ALIGN(addr);
 		if (pax_task_size - len >= addr) {
 			vma = find_vma(mm, addr);
-			if (check_heap_stack_gap(vma, addr, len))
+			if (check_heap_stack_gap(vma, addr, len, offset))
 				return addr;
 		}
 	}
@@ -110,7 +111,7 @@ full_search:
 			}
 			return -ENOMEM;
 		}
-		if (check_heap_stack_gap(vma, addr, len))
+		if (check_heap_stack_gap(vma, addr, len, offset))
 			break;
 		if (addr + mm->cached_hole_size < vma->vm_start)
 			mm->cached_hole_size = vma->vm_start - addr;
@@ -137,6 +138,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
 	unsigned long base = mm->mmap_base, addr = addr0, pax_task_size = TASK_SIZE;
+	unsigned long offset = (!filp && (flags & MAP_STACK)) ? ((random32() & 0xFF) << PAGE_SHIFT) : 0;
 
 #ifdef CONFIG_PAX_SEGMEXEC
 	if (mm->pax_flags & MF_PAX_SEGMEXEC)
@@ -166,7 +168,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 		addr = PAGE_ALIGN(addr);
 		if (pax_task_size - len >= addr) {
 			vma = find_vma(mm, addr);
-			if (check_heap_stack_gap(vma, addr, len))
+			if (check_heap_stack_gap(vma, addr, len, offset))
 				return addr;
 		}
 	}
@@ -183,7 +185,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	/* make sure it can fit in the remaining address space */
 	if (addr > len) {
 		vma = find_vma(mm, addr-len);
-		if (check_heap_stack_gap(vma, addr - len, len))
+		if (check_heap_stack_gap(vma, addr - len, len, offset))
 			/* remember the address as a hint for next time */
 			return (mm->free_area_cache = addr-len);
 	}
@@ -200,7 +202,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 		 * return with success:
 		 */
 		vma = find_vma(mm, addr);
-		if (check_heap_stack_gap(vma, addr, len))
+		if (check_heap_stack_gap(vma, addr, len, offset))
 			/* remember the address as a hint for next time */
 			return (mm->free_area_cache = addr);
 
@@ -209,7 +211,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 			mm->cached_hole_size = vma->vm_start - addr;
 
 		/* try just below the current vma->vm_start */
-		addr = skip_heap_stack_gap(vma, len);
+		addr = skip_heap_stack_gap(vma, len, offset);
 	} while (!IS_ERR_VALUE(addr));
 
 bottomup:
diff --git a/arch/x86/kernel/sys_x86_64.c b/arch/x86/kernel/sys_x86_64.c
index 82bb73b..a6b05dd 100644
--- a/arch/x86/kernel/sys_x86_64.c
+++ b/arch/x86/kernel/sys_x86_64.c
@@ -128,6 +128,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	struct vm_area_struct *vma;
 	unsigned long start_addr;
 	unsigned long begin, end;
+	unsigned long offset = (!filp && (flags & MAP_STACK)) ? ((random32() & 0xFF) << PAGE_SHIFT) : 0;
 
 	if (flags & MAP_FIXED)
 		return addr;
@@ -144,7 +145,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr,
 	if (addr) {
 		addr = PAGE_ALIGN(addr);
 		vma = find_vma(mm, addr);
-		if (end - len >= addr && check_heap_stack_gap(vma, addr, len))
+		if (end - len >= addr && check_heap_stack_gap(vma, addr, len, offset))
 			return addr;
 	}
 	if (((flags & MAP_32BIT) || test_thread_flag(TIF_ADDR32))
@@ -175,7 +176,7 @@ full_search:
 			}
 			return -ENOMEM;
 		}
-		if (check_heap_stack_gap(vma, addr, len)) {
+		if (check_heap_stack_gap(vma, addr, len, offset)) {
 			/*
 			 * Remember the place where we stopped the search:
 			 */
@@ -199,6 +200,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 	struct vm_area_struct *vma;
 	struct mm_struct *mm = current->mm;
 	unsigned long base = mm->mmap_base, addr = addr0, start_addr;
+	unsigned long offset = (!filp && (flags & MAP_STACK)) ? ((random32() & 0xFF) << PAGE_SHIFT) : 0;
 
 	/* requested length too big for entire address space */
 	if (len > TASK_SIZE)
@@ -220,7 +222,7 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
 		addr = PAGE_ALIGN(addr);
 		if (TASK_SIZE - len >= addr) {
 			vma = find_vma(mm, addr);
-			if (check_heap_stack_gap(vma, addr, len))
+			if (check_heap_stack_gap(vma, addr, len, offset))
 				return addr;
 		}
 	}
@@ -248,7 +250,7 @@ try_again:
 		 * return with success:
 		 */
 		vma = find_vma(mm, addr);
-		if (check_heap_stack_gap(vma, addr, len))
+		if (check_heap_stack_gap(vma, addr, len, offset))
 			/* remember the address as a hint for next time */
 			return mm->free_area_cache = addr;
 
@@ -257,7 +259,7 @@ try_again:
 			mm->cached_hole_size = vma->vm_start - addr;
 
 		/* try just below the current vma->vm_start */
-		addr = skip_heap_stack_gap(vma, len);
+		addr = skip_heap_stack_gap(vma, len, offset);
 	} while (!IS_ERR_VALUE(addr));
 
 fail:
diff --git a/include/linux/sched.h b/include/linux/sched.h
index cc9bffb..1e60824 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -350,8 +350,8 @@ extern unsigned long sysctl_heap_stack_gap;
 #include <linux/aio.h>
 
 #ifdef CONFIG_MMU
-extern bool check_heap_stack_gap(const struct vm_area_struct *vma, unsigned long addr, unsigned long len);
-extern unsigned long skip_heap_stack_gap(const struct vm_area_struct *vma, unsigned long len);
+extern bool check_heap_stack_gap(const struct vm_area_struct *vma, unsigned long addr, unsigned long len, unsigned long offset);
+extern unsigned long skip_heap_stack_gap(const struct vm_area_struct *vma, unsigned long len, unsigned long offset);
 extern void arch_pick_mmap_layout(struct mm_struct *mm);
 extern unsigned long
 arch_get_unmapped_area(struct file *, unsigned long, unsigned long,
diff --git a/mm/mmap.c b/mm/mmap.c
index 4fba820..aafc719 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1549,7 +1549,7 @@ unacct_error:
 	return error;
 }
 
-bool check_heap_stack_gap(const struct vm_area_struct *vma, unsigned long addr, unsigned long len)
+bool check_heap_stack_gap(const struct vm_area_struct *vma, unsigned long addr, unsigned long len, unsigned long offset)
 {
 	if (!vma) {
 #ifdef CONFIG_STACK_GROWSUP
@@ -1572,16 +1572,26 @@ bool check_heap_stack_gap(const struct vm_area_struct *vma, unsigned long addr,
 	else if (vma->vm_prev && (vma->vm_prev->vm_flags & VM_GROWSUP))
 		return addr - vma->vm_prev->vm_end <= sysctl_heap_stack_gap;
 #endif
+	else if (offset)
+		return offset <= vma->vm_start - addr - len;
 
 	return true;
 }
 
-unsigned long skip_heap_stack_gap(const struct vm_area_struct *vma, unsigned long len)
+unsigned long skip_heap_stack_gap(const struct vm_area_struct *vma, unsigned long len, unsigned long offset)
 {
 	if (vma->vm_start < len)
 		return -ENOMEM;
-	if (!(vma->vm_flags & VM_GROWSDOWN))
-		return vma->vm_start - len;
+
+	if (!(vma->vm_flags & VM_GROWSDOWN)) {
+		if (offset) {
+			if (offset <= vma->vm_start - len)
+				return vma->vm_start - len - offset;
+			return -ENOMEM;
+		} else
+			return vma->vm_start - len;
+	}
+
 	if (sysctl_heap_stack_gap <= vma->vm_start - len)
 		return vma->vm_start - len - sysctl_heap_stack_gap;
 	return -ENOMEM;
