b6bd3b9e044ed2159d94eb98496125430471d1d2
[linux-2.6.git] / 52.patch
1 diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
2 index cd535c7..1b53da9 100644
3 --- a/arch/x86/mm/fault.c
4 +++ b/arch/x86/mm/fault.c
5 @@ -599,6 +599,7 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
6         unsigned long address;
7         int write, si_code;
8         int fault;
9 +       int should_exit_no_context = 0;
10  #ifdef CONFIG_X86_64
11         unsigned long flags;
12  #endif
13 @@ -886,6 +887,9 @@ no_context:
14         oops_end(flags, regs, SIGKILL);
15  #endif
16  
17 +       if (should_exit_no_context)
18 +               return;
19 +
20  /*
21   * We ran out of memory, or some other thing happened to us that made
22   * us unable to handle the page fault gracefully.
23 @@ -911,8 +915,11 @@ do_sigbus:
24         up_read(&mm->mmap_sem);
25  
26         /* Kernel mode? Handle exceptions or die */
27 -       if (!(error_code & PF_USER))
28 +       if (!(error_code & PF_USER)) {
29 +               should_exit_no_context = 1;
30                 goto no_context;
31 +       }
32 +
33  #ifdef CONFIG_X86_32
34         /* User space => ok to do another page fault */
35         if (is_prefetch(regs, address, error_code))
36 diff --git a/mm/memory.c b/mm/memory.c
37 index 1c1a375..9739ae4 100644
38 --- a/mm/memory.c
39 +++ b/mm/memory.c
40 @@ -2405,6 +2405,26 @@ out_nomap:
41  }
42  
43  /*
44 + * This is like a special single-page "expand_downwards()",
45 + * except we must first make sure that 'address-PAGE_SIZE'
46 + * doesn't hit another vma.
47 + *
48 + * The "find_vma()" will do the right thing even if we wrap
49 + */
50 +static inline int check_stack_guard_page(struct vm_area_struct *vma, unsigned long address)
51 +{
52 +       address &= PAGE_MASK;
53 +       if ((vma->vm_flags & VM_GROWSDOWN) && address == vma->vm_start) {
54 +               address -= PAGE_SIZE;
55 +               if (find_vma(vma->vm_mm, address) != vma)
56 +                       return -ENOMEM;
57 +
58 +               expand_stack(vma, address);
59 +       }
60 +       return 0;
61 +}
62 +
63 +/*
64   * We enter with non-exclusive mmap_sem (to exclude vma changes,
65   * but allow concurrent faults), and pte mapped but not yet locked.
66   * We return with mmap_sem still held, but pte unmapped and unlocked.
67 @@ -2417,6 +2437,11 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
68         spinlock_t *ptl;
69         pte_t entry;
70  
71 +       if (check_stack_guard_page(vma, address) < 0) {
72 +               pte_unmap(page_table);
73 +               return VM_FAULT_SIGBUS;
74 +       }
75 +
76         /* Allocate our own private page. */
77         pte_unmap(page_table);
78  
79 diff --git a/mm/mmap.c b/mm/mmap.c
80 index 7201372..bef13a1 100644
81 --- a/mm/mmap.c
82 +++ b/mm/mmap.c
83 @@ -1573,7 +1573,7 @@ static int acct_stack_growth(struct vm_area_struct * vma, unsigned long size, un
84          * Overcommit..  This must be the final test, as it will
85          * update security statistics.
86          */
87 -       if (security_vm_enough_memory(grow))
88 +       if (security_vm_enough_memory_mm(mm, grow))
89                 return -ENOMEM;
90  
91         /* Ok, everything looks good - let it rip */