My favorites | Sign in
Project Home Downloads Wiki Issues Source
Checkout   Browse   Changes    
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/*
* CVE-2010-2240
* Adapted for 2.6.23 by Ole Andre Rodlie for Draco GNU/Linux i386
* Based on the 2.6.27.52-rc3 patches by Greg KH
*/
--- arch/i386/mm/fault.c.orig 2010-08-19 17:13:10.548005345 +0200
+++ arch/i386/mm/fault.c 2010-08-19 18:19:11.020035942 +0200
@@ -307,6 +307,7 @@
unsigned long address;
int write, si_code;
int fault;
+ int should_exit_no_context = 0;

/* get the address */
address = read_cr2();
@@ -585,6 +586,9 @@
bust_spinlocks(0);
do_exit(SIGKILL);

+ 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.
@@ -605,8 +609,10 @@
up_read(&mm->mmap_sem);

/* Kernel mode? Handle exceptions or die */
- if (!(error_code & 4))
+ if (!(error_code & 4)) {
+ should_exit_no_context = 1;
goto no_context;
+ }

/* User space => ok to do another page fault */
if (is_prefetch(regs, address, error_code))
--- mm/memory.c.orig 2010-08-19 17:36:03.423011821 +0200
+++ mm/memory.c 2010-08-19 17:49:55.638017348 +0200
@@ -2240,6 +2240,26 @@
}

/*
+ * 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.
@@ -2253,9 +2273,14 @@
pte_t entry;

if (write_access) {
- /* Allocate our own private page. */
+
pte_unmap(page_table);

+ /* Check if we need to add a guard page to the stack */
+ if (check_stack_guard_page(vma, address) < 0)
+ return VM_FAULT_SIGBUS;
+
+ /* Allocate our own private page. */
if (unlikely(anon_vma_prepare(vma)))
goto oom;
page = alloc_zeroed_user_highpage_movable(vma, address);
--- mm/mmap.c.orig 2010-08-19 17:51:05.805011948 +0200
+++ mm/mmap.c 2010-08-19 17:53:15.843027757 +0200
@@ -1541,7 +1541,7 @@
* Overcommit.. This must be the final test, as it will
* update security statistics.
*/
- if (security_vm_enough_memory(grow))
+ if (security_vm_enough_memory_mm(mm, grow))
return -ENOMEM;

/* Ok, everything looks good - let it rip */
--- fs/proc/task_mmu.c.orig 2010-08-19 17:54:20.077158267 +0200
+++ fs/proc/task_mmu.c 2010-08-19 17:57:01.492017980 +0200
@@ -140,6 +140,7 @@
struct file *file = vma->vm_file;
int flags = vma->vm_flags;
unsigned long ino = 0;
+ unsigned long start;
dev_t dev = 0;
int len;

@@ -152,8 +153,13 @@
ino = inode->i_ino;
}

+ /* We don't show the stack guard page in /proc/maps */
+ start = vma->vm_start;
+ if (vma->vm_flags & VM_GROWSDOWN)
+ start += PAGE_SIZE;
+
seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
- vma->vm_start,
+ start,
vma->vm_end,
flags & VM_READ ? 'r' : '-',
flags & VM_WRITE ? 'w' : '-',

Change log

r785 by ole.andre.rodlie on Aug 19, 2010   Diff
initial fix for CVE-2010-2240, needs
testing.
Go to: 

Older revisions

All revisions of this file

File info

Size: 3335 bytes, 118 lines
Powered by Google Project Hosting