[stable] [Stable-review] [0/3] 2.6.27.52 stable review

[stable] [Stable-review] [0/3] 2.6.27.52 stable review

Post by Greg K » Mon, 16 Aug 2010 03:50:02


Content-Type: text/plain; charset=iso-8859-1
Content-Disposition: inline
Content-Transfer-Encoding: 8bit

On Sat, Aug 14, 2010 at 07:43:35AM +0200, Willy Tarreau wrote:

Wonderful. I've released a 2.6.27.52-rc2 with this fix in it. I'm
building it and will test it on my box now. The full patch is below if
anyone wants to try it out.

Odds are it will need whatever patch Linus is currently working on for
mainline, so I'll hold off on releasing a real release until that is all
worked out.

thanks,

greg k-h


Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="patch-2.6.27.52-rc2"

diff --git a/Makefile b/Makefile
index 5382c55..096cde6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 27
-EXTRAVERSION = .51
+EXTRAVERSION = .52-rc2
NAME = Trembling Tortoise

# *DOCUMENTATION*
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 3384255..9d3c576 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -589,6 +589,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
unsigned long address;
int write, si_code;
int fault;
+ int should_exit_no_context = 0;
#ifdef CONFIG_X86_64
unsigned long flags;
#endif
@@ -876,6 +877,9 @@ no_context:
oops_end(flags, regs, SIGKILL);
#endif

+ if (should_exit_no_context)
+ return;
+
/*
* We ran out of memory, or some other thing happened to us that made
* us unable to handle the page fault gracefully.
@@ -901,8 +905,11 @@ do_sigbus:
up_read(&mm->mmap_sem);

/* Kernel mode? Handle exceptions or die */
- if (!(error_code & PF_USER))
+ if (!(error_code & PF_USER)) {
+ should_exit_no_context = 1;
goto no_context;
+ }
+
#ifdef CONFIG_X86_32
/* User space => ok to do another page fault */
if (is_prefetch(regs, address, error_code))
diff --git a/mm/memory.c b/mm/memory.c
index 1300b70..7e308fc 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2396,6 +2396,26 @@ out_nomap:
}

/*
+ * This is like a special single-page "expand_downwards()",
+ * except we must first make sure that 'address-PAGE_SIZE'
+ * doesn't hit another vma.
+ *
+ * The "find_vma()" will do the right thing even if we wrap
+ */
+static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address)
+{
+ address &= PAGE_MASK;
+ if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) {
+ address -= PAGE_SIZE;
+ if (find_vma(vma->vm_mm, address) != vma)
+ return -ENOMEM;
+
+ expand_stack(vma, address);
+ }
+ return 0;
+}
+
+/*
* We enter with non-exclusive mmap_sem (to exclude vma changes,
* but allow concurrent faults), and pte mapped but not yet locked.
* We return with mmap_sem still held, but pte unmapped and unlocked.
@@ -2408,6 +2428,11 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
spinlock_t *ptl;
pte_t entry;

+ if (check_stack_guard_page(vma, address) < 0) {
+ pte_unmap(page_table);
+ return VM_FAULT_SIGBUS;
+ }
+
/* Allocate our own private page. */
pte_unmap(page_table);

diff --git a/mm/mmap.c b/mm/mmap.c
index f3e5bfe..08a32cf 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1573,7 +1573,7 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
* Overcommit.. This must be the final test, as it will
* update security statistics.
*/