1 |
Author: gengor |
2 |
Date: 2009-03-21 10:58:14 +0000 (Sat, 21 Mar 2009) |
3 |
New Revision: 1529 |
4 |
|
5 |
Added: |
6 |
hardened/2.6/tags/2.6.28-7/ |
7 |
hardened/2.6/tags/2.6.28-7/0000_README |
8 |
hardened/2.6/tags/2.6.28-7/4420_grsec-2.1.13-2.6.28.8-200903191958.patch |
9 |
hardened/2.6/tags/2.6.28-7/4421_grsec-remove-localversion-grsec.patch |
10 |
hardened/2.6/tags/2.6.28-7/4422_grsec-mute-warnings.patch |
11 |
hardened/2.6/tags/2.6.28-7/4425_grsec-pax-without-grsec.patch |
12 |
hardened/2.6/tags/2.6.28-7/4430_grsec-kconfig-default-gids.patch |
13 |
hardened/2.6/tags/2.6.28-7/4435_grsec-kconfig-gentoo.patch |
14 |
hardened/2.6/tags/2.6.28-7/4440_selinux-avc_audit-log-curr_ip.patch |
15 |
hardened/2.6/tags/2.6.28-7/4445_disable-compat_vdso.patch |
16 |
hardened/2.6/tags/2.6.28-7/4450_grsec-grkernsec_io-select-rtc-cmos.patch |
17 |
Log: |
18 |
Tag hardened-extras 2.6.28-7 patchset |
19 |
|
20 |
Added: hardened/2.6/tags/2.6.28-7/0000_README |
21 |
=================================================================== |
22 |
--- hardened/2.6/tags/2.6.28-7/0000_README (rev 0) |
23 |
+++ hardened/2.6/tags/2.6.28-7/0000_README 2009-03-21 10:58:14 UTC (rev 1529) |
24 |
@@ -0,0 +1,46 @@ |
25 |
+README |
26 |
+----------------------------------------------------------------------------- |
27 |
+ |
28 |
+Individual Patch Descriptions: |
29 |
+----------------------------------------------------------------------------- |
30 |
+Patch: 4420_grsec-2.1.13-2.6.28.8-200903191958.patch |
31 |
+From: http://www.grsecurity.net |
32 |
+Desc: hardened-sources base patch from upstream grsecurity |
33 |
+ |
34 |
+Patch: 4421_grsec-remove-localversion-grsec.patch |
35 |
+From: Kerin Millar <kerframil@×××××.com> |
36 |
+Desc: Removes grsecurity's localversion-grsec file |
37 |
+ |
38 |
+Patch: 4422_grsec-mute-warnings.patch |
39 |
+From: Alexander Gabert <gaberta@××××××××.de> |
40 |
+ Gordon Malm <gengor@g.o> |
41 |
+Desc: Removes verbose compile warning settings from grsecurity, restores |
42 |
+ mainline Linux kernel behavior |
43 |
+ |
44 |
+Patch: 4425_grsec-pax-without-grsec.patch |
45 |
+From: Gordon Malm <gengor@g.o> |
46 |
+Desc: Allows PaX features to be selected without enabling GRKERNSEC |
47 |
+ |
48 |
+Patch: 4430_grsec-kconfig-default-gids.patch |
49 |
+From: Kerin Millar <kerframil@×××××.com> |
50 |
+Desc: Sets sane(r) default GIDs on various grsecurity group-dependent |
51 |
+ features |
52 |
+ |
53 |
+Patch: 4435_grsec-kconfig-gentoo.patch |
54 |
+From: Gordon Malm <gengor@g.o> |
55 |
+ Kerin Millar <kerframil@×××××.com> |
56 |
+Desc: Adds Hardened Gentoo [server/workstation] security levels, sets |
57 |
+ Hardened Gentoo [workstation] as default |
58 |
+ |
59 |
+Patch: 4440_selinux-avc_audit-log-curr_ip.patch |
60 |
+From: Gordon Malm <gengor@g.o> |
61 |
+Desc: Configurable option to add src IP address to SELinux log messages |
62 |
+ |
63 |
+Patch: 4445_disable-compat_vdso.patch |
64 |
+From: Gordon Malm <gengor@g.o> |
65 |
+ Kerin Millar <kerframil@×××××.com> |
66 |
+Desc: Disables VDSO_COMPAT operation completely |
67 |
+ |
68 |
+Patch: 4450_grsec-grkernsec_io-select-rtc-cmos.patch |
69 |
+From: Gordon Malm <gengor@g.o> |
70 |
+Desc: Build rtc-cmos driver into the kernel when GRKERNSEC_IO is enabled |
71 |
|
72 |
Added: hardened/2.6/tags/2.6.28-7/4420_grsec-2.1.13-2.6.28.8-200903191958.patch |
73 |
=================================================================== |
74 |
--- hardened/2.6/tags/2.6.28-7/4420_grsec-2.1.13-2.6.28.8-200903191958.patch (rev 0) |
75 |
+++ hardened/2.6/tags/2.6.28-7/4420_grsec-2.1.13-2.6.28.8-200903191958.patch 2009-03-21 10:58:14 UTC (rev 1529) |
76 |
@@ -0,0 +1,37186 @@ |
77 |
+diff -urNp linux-2.6.28.8/arch/alpha/include/asm/elf.h linux-2.6.28.8/arch/alpha/include/asm/elf.h |
78 |
+--- linux-2.6.28.8/arch/alpha/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500 |
79 |
++++ linux-2.6.28.8/arch/alpha/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500 |
80 |
+@@ -91,6 +91,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N |
81 |
+ |
82 |
+ #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) |
83 |
+ |
84 |
++#ifdef CONFIG_PAX_ASLR |
85 |
++#define PAX_ELF_ET_DYN_BASE (current->personality & ADDR_LIMIT_32BIT ? 0x10000 : 0x120000000UL) |
86 |
++ |
87 |
++#define PAX_DELTA_MMAP_LEN (current->personality & ADDR_LIMIT_32BIT ? 14 : 28) |
88 |
++#define PAX_DELTA_STACK_LEN (current->personality & ADDR_LIMIT_32BIT ? 14 : 19) |
89 |
++#endif |
90 |
++ |
91 |
+ /* $0 is set by ld.so to a pointer to a function which might be |
92 |
+ registered using atexit. This provides a mean for the dynamic |
93 |
+ linker to call DT_FINI functions for shared libraries that have |
94 |
+diff -urNp linux-2.6.28.8/arch/alpha/include/asm/kmap_types.h linux-2.6.28.8/arch/alpha/include/asm/kmap_types.h |
95 |
+--- linux-2.6.28.8/arch/alpha/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
96 |
++++ linux-2.6.28.8/arch/alpha/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
97 |
+@@ -24,7 +24,8 @@ D(9) KM_IRQ0, |
98 |
+ D(10) KM_IRQ1, |
99 |
+ D(11) KM_SOFTIRQ0, |
100 |
+ D(12) KM_SOFTIRQ1, |
101 |
+-D(13) KM_TYPE_NR |
102 |
++D(13) KM_CLEARPAGE, |
103 |
++D(14) KM_TYPE_NR |
104 |
+ }; |
105 |
+ |
106 |
+ #undef D |
107 |
+diff -urNp linux-2.6.28.8/arch/alpha/include/asm/pgtable.h linux-2.6.28.8/arch/alpha/include/asm/pgtable.h |
108 |
+--- linux-2.6.28.8/arch/alpha/include/asm/pgtable.h 2009-02-06 16:47:45.000000000 -0500 |
109 |
++++ linux-2.6.28.8/arch/alpha/include/asm/pgtable.h 2009-02-21 09:37:48.000000000 -0500 |
110 |
+@@ -101,6 +101,17 @@ struct vm_area_struct; |
111 |
+ #define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS) |
112 |
+ #define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) |
113 |
+ #define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) |
114 |
++ |
115 |
++#ifdef CONFIG_PAX_PAGEEXEC |
116 |
++# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOE) |
117 |
++# define PAGE_COPY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE) |
118 |
++# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE) |
119 |
++#else |
120 |
++# define PAGE_SHARED_NOEXEC PAGE_SHARED |
121 |
++# define PAGE_COPY_NOEXEC PAGE_COPY |
122 |
++# define PAGE_READONLY_NOEXEC PAGE_READONLY |
123 |
++#endif |
124 |
++ |
125 |
+ #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE) |
126 |
+ |
127 |
+ #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x)) |
128 |
+diff -urNp linux-2.6.28.8/arch/alpha/kernel/module.c linux-2.6.28.8/arch/alpha/kernel/module.c |
129 |
+--- linux-2.6.28.8/arch/alpha/kernel/module.c 2009-02-06 16:47:45.000000000 -0500 |
130 |
++++ linux-2.6.28.8/arch/alpha/kernel/module.c 2009-02-21 09:37:48.000000000 -0500 |
131 |
+@@ -182,7 +182,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs, |
132 |
+ |
133 |
+ /* The small sections were sorted to the end of the segment. |
134 |
+ The following should definitely cover them. */ |
135 |
+- gp = (u64)me->module_core + me->core_size - 0x8000; |
136 |
++ gp = (u64)me->module_core_rw + me->core_size_rw - 0x8000; |
137 |
+ got = sechdrs[me->arch.gotsecindex].sh_addr; |
138 |
+ |
139 |
+ for (i = 0; i < n; i++) { |
140 |
+diff -urNp linux-2.6.28.8/arch/alpha/kernel/osf_sys.c linux-2.6.28.8/arch/alpha/kernel/osf_sys.c |
141 |
+--- linux-2.6.28.8/arch/alpha/kernel/osf_sys.c 2009-02-06 16:47:45.000000000 -0500 |
142 |
++++ linux-2.6.28.8/arch/alpha/kernel/osf_sys.c 2009-02-21 09:37:48.000000000 -0500 |
143 |
+@@ -1230,6 +1230,10 @@ arch_get_unmapped_area(struct file *filp |
144 |
+ merely specific addresses, but regions of memory -- perhaps |
145 |
+ this feature should be incorporated into all ports? */ |
146 |
+ |
147 |
++#ifdef CONFIG_PAX_RANDMMAP |
148 |
++ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP)) |
149 |
++#endif |
150 |
++ |
151 |
+ if (addr) { |
152 |
+ addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit); |
153 |
+ if (addr != (unsigned long) -ENOMEM) |
154 |
+@@ -1237,8 +1241,8 @@ arch_get_unmapped_area(struct file *filp |
155 |
+ } |
156 |
+ |
157 |
+ /* Next, try allocating at TASK_UNMAPPED_BASE. */ |
158 |
+- addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE), |
159 |
+- len, limit); |
160 |
++ addr = arch_get_unmapped_area_1 (PAGE_ALIGN(current->mm->mmap_base), len, limit); |
161 |
++ |
162 |
+ if (addr != (unsigned long) -ENOMEM) |
163 |
+ return addr; |
164 |
+ |
165 |
+diff -urNp linux-2.6.28.8/arch/alpha/kernel/ptrace.c linux-2.6.28.8/arch/alpha/kernel/ptrace.c |
166 |
+--- linux-2.6.28.8/arch/alpha/kernel/ptrace.c 2009-02-06 16:47:45.000000000 -0500 |
167 |
++++ linux-2.6.28.8/arch/alpha/kernel/ptrace.c 2009-02-21 09:37:48.000000000 -0500 |
168 |
+@@ -266,6 +266,9 @@ long arch_ptrace(struct task_struct *chi |
169 |
+ size_t copied; |
170 |
+ long ret; |
171 |
+ |
172 |
++ if (gr_handle_ptrace(child, request)) |
173 |
++ return -EPERM; |
174 |
++ |
175 |
+ switch (request) { |
176 |
+ /* When I and D space are separate, these will need to be fixed. */ |
177 |
+ case PTRACE_PEEKTEXT: /* read word at location addr. */ |
178 |
+diff -urNp linux-2.6.28.8/arch/alpha/mm/fault.c linux-2.6.28.8/arch/alpha/mm/fault.c |
179 |
+--- linux-2.6.28.8/arch/alpha/mm/fault.c 2009-02-06 16:47:45.000000000 -0500 |
180 |
++++ linux-2.6.28.8/arch/alpha/mm/fault.c 2009-02-21 09:37:48.000000000 -0500 |
181 |
+@@ -54,6 +54,124 @@ __load_new_mm_context(struct mm_struct * |
182 |
+ __reload_thread(pcb); |
183 |
+ } |
184 |
+ |
185 |
++#ifdef CONFIG_PAX_PAGEEXEC |
186 |
++/* |
187 |
++ * PaX: decide what to do with offenders (regs->pc = fault address) |
188 |
++ * |
189 |
++ * returns 1 when task should be killed |
190 |
++ * 2 when patched PLT trampoline was detected |
191 |
++ * 3 when unpatched PLT trampoline was detected |
192 |
++ */ |
193 |
++static int pax_handle_fetch_fault(struct pt_regs *regs) |
194 |
++{ |
195 |
++ |
196 |
++#ifdef CONFIG_PAX_EMUPLT |
197 |
++ int err; |
198 |
++ |
199 |
++ do { /* PaX: patched PLT emulation #1 */ |
200 |
++ unsigned int ldah, ldq, jmp; |
201 |
++ |
202 |
++ err = get_user(ldah, (unsigned int *)regs->pc); |
203 |
++ err |= get_user(ldq, (unsigned int *)(regs->pc+4)); |
204 |
++ err |= get_user(jmp, (unsigned int *)(regs->pc+8)); |
205 |
++ |
206 |
++ if (err) |
207 |
++ break; |
208 |
++ |
209 |
++ if ((ldah & 0xFFFF0000U) == 0x277B0000U && |
210 |
++ (ldq & 0xFFFF0000U) == 0xA77B0000U && |
211 |
++ jmp == 0x6BFB0000U) |
212 |
++ { |
213 |
++ unsigned long r27, addr; |
214 |
++ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16; |
215 |
++ unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL; |
216 |
++ |
217 |
++ addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL); |
218 |
++ err = get_user(r27, (unsigned long *)addr); |
219 |
++ if (err) |
220 |
++ break; |
221 |
++ |
222 |
++ regs->r27 = r27; |
223 |
++ regs->pc = r27; |
224 |
++ return 2; |
225 |
++ } |
226 |
++ } while (0); |
227 |
++ |
228 |
++ do { /* PaX: patched PLT emulation #2 */ |
229 |
++ unsigned int ldah, lda, br; |
230 |
++ |
231 |
++ err = get_user(ldah, (unsigned int *)regs->pc); |
232 |
++ err |= get_user(lda, (unsigned int *)(regs->pc+4)); |
233 |
++ err |= get_user(br, (unsigned int *)(regs->pc+8)); |
234 |
++ |
235 |
++ if (err) |
236 |
++ break; |
237 |
++ |
238 |
++ if ((ldah & 0xFFFF0000U) == 0x277B0000U && |
239 |
++ (lda & 0xFFFF0000U) == 0xA77B0000U && |
240 |
++ (br & 0xFFE00000U) == 0xC3E00000U) |
241 |
++ { |
242 |
++ unsigned long addr = br | 0xFFFFFFFFFFE00000UL; |
243 |
++ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16; |
244 |
++ unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL; |
245 |
++ |
246 |
++ regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL); |
247 |
++ regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2); |
248 |
++ return 2; |
249 |
++ } |
250 |
++ } while (0); |
251 |
++ |
252 |
++ do { /* PaX: unpatched PLT emulation */ |
253 |
++ unsigned int br; |
254 |
++ |
255 |
++ err = get_user(br, (unsigned int *)regs->pc); |
256 |
++ |
257 |
++ if (!err && (br & 0xFFE00000U) == 0xC3800000U) { |
258 |
++ unsigned int br2, ldq, nop, jmp; |
259 |
++ unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver; |
260 |
++ |
261 |
++ addr = regs->pc + 4 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2); |
262 |
++ err = get_user(br2, (unsigned int *)addr); |
263 |
++ err |= get_user(ldq, (unsigned int *)(addr+4)); |
264 |
++ err |= get_user(nop, (unsigned int *)(addr+8)); |
265 |
++ err |= get_user(jmp, (unsigned int *)(addr+12)); |
266 |
++ err |= get_user(resolver, (unsigned long *)(addr+16)); |
267 |
++ |
268 |
++ if (err) |
269 |
++ break; |
270 |
++ |
271 |
++ if (br2 == 0xC3600000U && |
272 |
++ ldq == 0xA77B000CU && |
273 |
++ nop == 0x47FF041FU && |
274 |
++ jmp == 0x6B7B0000U) |
275 |
++ { |
276 |
++ regs->r28 = regs->pc+4; |
277 |
++ regs->r27 = addr+16; |
278 |
++ regs->pc = resolver; |
279 |
++ return 3; |
280 |
++ } |
281 |
++ } |
282 |
++ } while (0); |
283 |
++#endif |
284 |
++ |
285 |
++ return 1; |
286 |
++} |
287 |
++ |
288 |
++void pax_report_insns(void *pc, void *sp) |
289 |
++{ |
290 |
++ unsigned long i; |
291 |
++ |
292 |
++ printk(KERN_ERR "PAX: bytes at PC: "); |
293 |
++ for (i = 0; i < 5; i++) { |
294 |
++ unsigned int c; |
295 |
++ if (get_user(c, (unsigned int *)pc+i)) |
296 |
++ printk(KERN_CONT "???????? "); |
297 |
++ else |
298 |
++ printk(KERN_CONT "%08x ", c); |
299 |
++ } |
300 |
++ printk("\n"); |
301 |
++} |
302 |
++#endif |
303 |
+ |
304 |
+ /* |
305 |
+ * This routine handles page faults. It determines the address, |
306 |
+@@ -131,8 +249,29 @@ do_page_fault(unsigned long address, uns |
307 |
+ good_area: |
308 |
+ si_code = SEGV_ACCERR; |
309 |
+ if (cause < 0) { |
310 |
+- if (!(vma->vm_flags & VM_EXEC)) |
311 |
++ if (!(vma->vm_flags & VM_EXEC)) { |
312 |
++ |
313 |
++#ifdef CONFIG_PAX_PAGEEXEC |
314 |
++ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->pc) |
315 |
++ goto bad_area; |
316 |
++ |
317 |
++ up_read(&mm->mmap_sem); |
318 |
++ switch (pax_handle_fetch_fault(regs)) { |
319 |
++ |
320 |
++#ifdef CONFIG_PAX_EMUPLT |
321 |
++ case 2: |
322 |
++ case 3: |
323 |
++ return; |
324 |
++#endif |
325 |
++ |
326 |
++ } |
327 |
++ pax_report_fault(regs, (void *)regs->pc, (void *)rdusp()); |
328 |
++ do_group_exit(SIGKILL); |
329 |
++#else |
330 |
+ goto bad_area; |
331 |
++#endif |
332 |
++ |
333 |
++ } |
334 |
+ } else if (!cause) { |
335 |
+ /* Allow reads even for write-only mappings */ |
336 |
+ if (!(vma->vm_flags & (VM_READ | VM_WRITE))) |
337 |
+diff -urNp linux-2.6.28.8/arch/arm/include/asm/elf.h linux-2.6.28.8/arch/arm/include/asm/elf.h |
338 |
+--- linux-2.6.28.8/arch/arm/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500 |
339 |
++++ linux-2.6.28.8/arch/arm/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500 |
340 |
+@@ -99,7 +99,14 @@ extern int arm_elf_read_implies_exec(con |
341 |
+ the loader. We need to make sure that it is out of the way of the program |
342 |
+ that it will "exec", and that there is sufficient room for the brk. */ |
343 |
+ |
344 |
+-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) |
345 |
++#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) |
346 |
++ |
347 |
++#ifdef CONFIG_PAX_ASLR |
348 |
++#define PAX_ELF_ET_DYN_BASE 0x00008000UL |
349 |
++ |
350 |
++#define PAX_DELTA_MMAP_LEN ((current->personality == PER_LINUX_32BIT) ? 16 : 10) |
351 |
++#define PAX_DELTA_STACK_LEN ((current->personality == PER_LINUX_32BIT) ? 16 : 10) |
352 |
++#endif |
353 |
+ |
354 |
+ /* When the program starts, a1 contains a pointer to a function to be |
355 |
+ registered with atexit, as per the SVR4 ABI. A value of 0 means we |
356 |
+diff -urNp linux-2.6.28.8/arch/arm/include/asm/kmap_types.h linux-2.6.28.8/arch/arm/include/asm/kmap_types.h |
357 |
+--- linux-2.6.28.8/arch/arm/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
358 |
++++ linux-2.6.28.8/arch/arm/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
359 |
+@@ -18,6 +18,7 @@ enum km_type { |
360 |
+ KM_IRQ1, |
361 |
+ KM_SOFTIRQ0, |
362 |
+ KM_SOFTIRQ1, |
363 |
++ KM_CLEARPAGE, |
364 |
+ KM_TYPE_NR |
365 |
+ }; |
366 |
+ |
367 |
+diff -urNp linux-2.6.28.8/arch/arm/mm/mmap.c linux-2.6.28.8/arch/arm/mm/mmap.c |
368 |
+--- linux-2.6.28.8/arch/arm/mm/mmap.c 2009-02-06 16:47:45.000000000 -0500 |
369 |
++++ linux-2.6.28.8/arch/arm/mm/mmap.c 2009-02-21 09:37:48.000000000 -0500 |
370 |
+@@ -62,6 +62,10 @@ arch_get_unmapped_area(struct file *filp |
371 |
+ if (len > TASK_SIZE) |
372 |
+ return -ENOMEM; |
373 |
+ |
374 |
++#ifdef CONFIG_PAX_RANDMMAP |
375 |
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) |
376 |
++#endif |
377 |
++ |
378 |
+ if (addr) { |
379 |
+ if (do_align) |
380 |
+ addr = COLOUR_ALIGN(addr, pgoff); |
381 |
+@@ -74,10 +78,10 @@ arch_get_unmapped_area(struct file *filp |
382 |
+ return addr; |
383 |
+ } |
384 |
+ if (len > mm->cached_hole_size) { |
385 |
+- start_addr = addr = mm->free_area_cache; |
386 |
++ start_addr = addr = mm->free_area_cache; |
387 |
+ } else { |
388 |
+- start_addr = addr = TASK_UNMAPPED_BASE; |
389 |
+- mm->cached_hole_size = 0; |
390 |
++ start_addr = addr = mm->mmap_base; |
391 |
++ mm->cached_hole_size = 0; |
392 |
+ } |
393 |
+ |
394 |
+ full_search: |
395 |
+@@ -93,8 +97,8 @@ full_search: |
396 |
+ * Start a new search - just in case we missed |
397 |
+ * some holes. |
398 |
+ */ |
399 |
+- if (start_addr != TASK_UNMAPPED_BASE) { |
400 |
+- start_addr = addr = TASK_UNMAPPED_BASE; |
401 |
++ if (start_addr != mm->mmap_base) { |
402 |
++ start_addr = addr = mm->mmap_base; |
403 |
+ mm->cached_hole_size = 0; |
404 |
+ goto full_search; |
405 |
+ } |
406 |
+diff -urNp linux-2.6.28.8/arch/avr32/include/asm/elf.h linux-2.6.28.8/arch/avr32/include/asm/elf.h |
407 |
+--- linux-2.6.28.8/arch/avr32/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500 |
408 |
++++ linux-2.6.28.8/arch/avr32/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500 |
409 |
+@@ -85,8 +85,14 @@ typedef struct user_fpu_struct elf_fpreg |
410 |
+ the loader. We need to make sure that it is out of the way of the program |
411 |
+ that it will "exec", and that there is sufficient room for the brk. */ |
412 |
+ |
413 |
+-#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) |
414 |
++#define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) |
415 |
+ |
416 |
++#ifdef CONFIG_PAX_ASLR |
417 |
++#define PAX_ELF_ET_DYN_BASE 0x00001000UL |
418 |
++ |
419 |
++#define PAX_DELTA_MMAP_LEN 15 |
420 |
++#define PAX_DELTA_STACK_LEN 15 |
421 |
++#endif |
422 |
+ |
423 |
+ /* This yields a mask that user programs can use to figure out what |
424 |
+ instruction set this CPU supports. This could be done in user space, |
425 |
+diff -urNp linux-2.6.28.8/arch/avr32/include/asm/kmap_types.h linux-2.6.28.8/arch/avr32/include/asm/kmap_types.h |
426 |
+--- linux-2.6.28.8/arch/avr32/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
427 |
++++ linux-2.6.28.8/arch/avr32/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
428 |
+@@ -22,7 +22,8 @@ D(10) KM_IRQ0, |
429 |
+ D(11) KM_IRQ1, |
430 |
+ D(12) KM_SOFTIRQ0, |
431 |
+ D(13) KM_SOFTIRQ1, |
432 |
+-D(14) KM_TYPE_NR |
433 |
++D(14) KM_CLEARPAGE, |
434 |
++D(15) KM_TYPE_NR |
435 |
+ }; |
436 |
+ |
437 |
+ #undef D |
438 |
+diff -urNp linux-2.6.28.8/arch/avr32/mm/fault.c linux-2.6.28.8/arch/avr32/mm/fault.c |
439 |
+--- linux-2.6.28.8/arch/avr32/mm/fault.c 2009-02-06 16:47:45.000000000 -0500 |
440 |
++++ linux-2.6.28.8/arch/avr32/mm/fault.c 2009-02-21 09:37:48.000000000 -0500 |
441 |
+@@ -41,6 +41,23 @@ static inline int notify_page_fault(stru |
442 |
+ |
443 |
+ int exception_trace = 1; |
444 |
+ |
445 |
++#ifdef CONFIG_PAX_PAGEEXEC |
446 |
++void pax_report_insns(void *pc, void *sp) |
447 |
++{ |
448 |
++ unsigned long i; |
449 |
++ |
450 |
++ printk(KERN_ERR "PAX: bytes at PC: "); |
451 |
++ for (i = 0; i < 20; i++) { |
452 |
++ unsigned char c; |
453 |
++ if (get_user(c, (unsigned char *)pc+i)) |
454 |
++ printk(KERN_CONT "???????? "); |
455 |
++ else |
456 |
++ printk(KERN_CONT "%02x ", c); |
457 |
++ } |
458 |
++ printk("\n"); |
459 |
++} |
460 |
++#endif |
461 |
++ |
462 |
+ /* |
463 |
+ * This routine handles page faults. It determines the address and the |
464 |
+ * problem, and then passes it off to one of the appropriate routines. |
465 |
+@@ -157,6 +174,16 @@ bad_area: |
466 |
+ up_read(&mm->mmap_sem); |
467 |
+ |
468 |
+ if (user_mode(regs)) { |
469 |
++ |
470 |
++#ifdef CONFIG_PAX_PAGEEXEC |
471 |
++ if (mm->pax_flags & MF_PAX_PAGEEXEC) { |
472 |
++ if (ecr == ECR_PROTECTION_X || ecr == ECR_TLB_MISS_X) { |
473 |
++ pax_report_fault(regs, (void *)regs->pc, (void *)regs->sp); |
474 |
++ do_group_exit(SIGKILL); |
475 |
++ } |
476 |
++ } |
477 |
++#endif |
478 |
++ |
479 |
+ if (exception_trace && printk_ratelimit()) |
480 |
+ printk("%s%s[%d]: segfault at %08lx pc %08lx " |
481 |
+ "sp %08lx ecr %lu\n", |
482 |
+diff -urNp linux-2.6.28.8/arch/blackfin/include/asm/kmap_types.h linux-2.6.28.8/arch/blackfin/include/asm/kmap_types.h |
483 |
+--- linux-2.6.28.8/arch/blackfin/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
484 |
++++ linux-2.6.28.8/arch/blackfin/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
485 |
+@@ -15,6 +15,7 @@ enum km_type { |
486 |
+ KM_IRQ1, |
487 |
+ KM_SOFTIRQ0, |
488 |
+ KM_SOFTIRQ1, |
489 |
++ KM_CLEARPAGE, |
490 |
+ KM_TYPE_NR |
491 |
+ }; |
492 |
+ |
493 |
+diff -urNp linux-2.6.28.8/arch/cris/include/asm/kmap_types.h linux-2.6.28.8/arch/cris/include/asm/kmap_types.h |
494 |
+--- linux-2.6.28.8/arch/cris/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
495 |
++++ linux-2.6.28.8/arch/cris/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
496 |
+@@ -19,6 +19,7 @@ enum km_type { |
497 |
+ KM_IRQ1, |
498 |
+ KM_SOFTIRQ0, |
499 |
+ KM_SOFTIRQ1, |
500 |
++ KM_CLEARPAGE, |
501 |
+ KM_TYPE_NR |
502 |
+ }; |
503 |
+ |
504 |
+diff -urNp linux-2.6.28.8/arch/h8300/include/asm/kmap_types.h linux-2.6.28.8/arch/h8300/include/asm/kmap_types.h |
505 |
+--- linux-2.6.28.8/arch/h8300/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
506 |
++++ linux-2.6.28.8/arch/h8300/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
507 |
+@@ -15,6 +15,7 @@ enum km_type { |
508 |
+ KM_IRQ1, |
509 |
+ KM_SOFTIRQ0, |
510 |
+ KM_SOFTIRQ1, |
511 |
++ KM_CLEARPAGE, |
512 |
+ KM_TYPE_NR |
513 |
+ }; |
514 |
+ |
515 |
+diff -urNp linux-2.6.28.8/arch/ia64/ia32/binfmt_elf32.c linux-2.6.28.8/arch/ia64/ia32/binfmt_elf32.c |
516 |
+--- linux-2.6.28.8/arch/ia64/ia32/binfmt_elf32.c 2009-02-06 16:47:45.000000000 -0500 |
517 |
++++ linux-2.6.28.8/arch/ia64/ia32/binfmt_elf32.c 2009-02-21 09:37:48.000000000 -0500 |
518 |
+@@ -45,6 +45,13 @@ randomize_stack_top(unsigned long stack_ |
519 |
+ |
520 |
+ #define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack)) |
521 |
+ |
522 |
++#ifdef CONFIG_PAX_ASLR |
523 |
++#define PAX_ELF_ET_DYN_BASE (current->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL) |
524 |
++ |
525 |
++#define PAX_DELTA_MMAP_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) |
526 |
++#define PAX_DELTA_STACK_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) |
527 |
++#endif |
528 |
++ |
529 |
+ /* Ugly but avoids duplication */ |
530 |
+ #include "../../../fs/binfmt_elf.c" |
531 |
+ |
532 |
+diff -urNp linux-2.6.28.8/arch/ia64/ia32/ia32priv.h linux-2.6.28.8/arch/ia64/ia32/ia32priv.h |
533 |
+--- linux-2.6.28.8/arch/ia64/ia32/ia32priv.h 2009-02-06 16:47:45.000000000 -0500 |
534 |
++++ linux-2.6.28.8/arch/ia64/ia32/ia32priv.h 2009-02-21 09:37:48.000000000 -0500 |
535 |
+@@ -296,7 +296,14 @@ typedef struct compat_siginfo { |
536 |
+ #define ELF_DATA ELFDATA2LSB |
537 |
+ #define ELF_ARCH EM_386 |
538 |
+ |
539 |
+-#define IA32_STACK_TOP IA32_PAGE_OFFSET |
540 |
++#ifdef CONFIG_PAX_RANDUSTACK |
541 |
++#define __IA32_DELTA_STACK (current->mm->delta_stack) |
542 |
++#else |
543 |
++#define __IA32_DELTA_STACK 0UL |
544 |
++#endif |
545 |
++ |
546 |
++#define IA32_STACK_TOP (IA32_PAGE_OFFSET - __IA32_DELTA_STACK) |
547 |
++ |
548 |
+ #define IA32_GATE_OFFSET IA32_PAGE_OFFSET |
549 |
+ #define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE |
550 |
+ |
551 |
+diff -urNp linux-2.6.28.8/arch/ia64/include/asm/elf.h linux-2.6.28.8/arch/ia64/include/asm/elf.h |
552 |
+--- linux-2.6.28.8/arch/ia64/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500 |
553 |
++++ linux-2.6.28.8/arch/ia64/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500 |
554 |
+@@ -43,6 +43,13 @@ |
555 |
+ */ |
556 |
+ #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x800000000UL) |
557 |
+ |
558 |
++#ifdef CONFIG_PAX_ASLR |
559 |
++#define PAX_ELF_ET_DYN_BASE (current->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL) |
560 |
++ |
561 |
++#define PAX_DELTA_MMAP_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) |
562 |
++#define PAX_DELTA_STACK_LEN (current->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13) |
563 |
++#endif |
564 |
++ |
565 |
+ #define PT_IA_64_UNWIND 0x70000001 |
566 |
+ |
567 |
+ /* IA-64 relocations: */ |
568 |
+diff -urNp linux-2.6.28.8/arch/ia64/include/asm/kmap_types.h linux-2.6.28.8/arch/ia64/include/asm/kmap_types.h |
569 |
+--- linux-2.6.28.8/arch/ia64/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
570 |
++++ linux-2.6.28.8/arch/ia64/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
571 |
+@@ -22,7 +22,8 @@ D(9) KM_IRQ0, |
572 |
+ D(10) KM_IRQ1, |
573 |
+ D(11) KM_SOFTIRQ0, |
574 |
+ D(12) KM_SOFTIRQ1, |
575 |
+-D(13) KM_TYPE_NR |
576 |
++D(13) KM_CLEARPAGE, |
577 |
++D(14) KM_TYPE_NR |
578 |
+ }; |
579 |
+ |
580 |
+ #undef D |
581 |
+diff -urNp linux-2.6.28.8/arch/ia64/include/asm/pgtable.h linux-2.6.28.8/arch/ia64/include/asm/pgtable.h |
582 |
+--- linux-2.6.28.8/arch/ia64/include/asm/pgtable.h 2009-02-06 16:47:45.000000000 -0500 |
583 |
++++ linux-2.6.28.8/arch/ia64/include/asm/pgtable.h 2009-02-21 09:37:48.000000000 -0500 |
584 |
+@@ -143,6 +143,17 @@ |
585 |
+ #define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) |
586 |
+ #define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) |
587 |
+ #define PAGE_COPY_EXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX) |
588 |
++ |
589 |
++#ifdef CONFIG_PAX_PAGEEXEC |
590 |
++# define PAGE_SHARED_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW) |
591 |
++# define PAGE_READONLY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) |
592 |
++# define PAGE_COPY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) |
593 |
++#else |
594 |
++# define PAGE_SHARED_NOEXEC PAGE_SHARED |
595 |
++# define PAGE_READONLY_NOEXEC PAGE_READONLY |
596 |
++# define PAGE_COPY_NOEXEC PAGE_COPY |
597 |
++#endif |
598 |
++ |
599 |
+ #define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX) |
600 |
+ #define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX) |
601 |
+ #define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX) |
602 |
+diff -urNp linux-2.6.28.8/arch/ia64/kernel/module.c linux-2.6.28.8/arch/ia64/kernel/module.c |
603 |
+--- linux-2.6.28.8/arch/ia64/kernel/module.c 2009-02-06 16:47:45.000000000 -0500 |
604 |
++++ linux-2.6.28.8/arch/ia64/kernel/module.c 2009-02-21 09:37:48.000000000 -0500 |
605 |
+@@ -312,8 +312,7 @@ module_alloc (unsigned long size) |
606 |
+ void |
607 |
+ module_free (struct module *mod, void *module_region) |
608 |
+ { |
609 |
+- if (mod && mod->arch.init_unw_table && |
610 |
+- module_region == mod->module_init) { |
611 |
++ if (mod && mod->arch.init_unw_table && module_region == mod->module_init_rx) { |
612 |
+ unw_remove_unwind_table(mod->arch.init_unw_table); |
613 |
+ mod->arch.init_unw_table = NULL; |
614 |
+ } |
615 |
+@@ -491,15 +490,39 @@ module_frob_arch_sections (Elf_Ehdr *ehd |
616 |
+ } |
617 |
+ |
618 |
+ static inline int |
619 |
++in_init_rx (const struct module *mod, uint64_t addr) |
620 |
++{ |
621 |
++ return addr - (uint64_t) mod->module_init_rx < mod->init_size_rx; |
622 |
++} |
623 |
++ |
624 |
++static inline int |
625 |
++in_init_rw (const struct module *mod, uint64_t addr) |
626 |
++{ |
627 |
++ return addr - (uint64_t) mod->module_init_rw < mod->init_size_rw; |
628 |
++} |
629 |
++ |
630 |
++static inline int |
631 |
+ in_init (const struct module *mod, uint64_t addr) |
632 |
+ { |
633 |
+- return addr - (uint64_t) mod->module_init < mod->init_size; |
634 |
++ return in_init_rx(mod, addr) || in_init_rw(mod, addr); |
635 |
++} |
636 |
++ |
637 |
++static inline int |
638 |
++in_core_rx (const struct module *mod, uint64_t addr) |
639 |
++{ |
640 |
++ return addr - (uint64_t) mod->module_core_rx < mod->core_size_rx; |
641 |
++} |
642 |
++ |
643 |
++static inline int |
644 |
++in_core_rw (const struct module *mod, uint64_t addr) |
645 |
++{ |
646 |
++ return addr - (uint64_t) mod->module_core_rw < mod->core_size_rw; |
647 |
+ } |
648 |
+ |
649 |
+ static inline int |
650 |
+ in_core (const struct module *mod, uint64_t addr) |
651 |
+ { |
652 |
+- return addr - (uint64_t) mod->module_core < mod->core_size; |
653 |
++ return in_core_rx(mod, addr) || in_core_rw(mod, addr); |
654 |
+ } |
655 |
+ |
656 |
+ static inline int |
657 |
+@@ -683,7 +706,14 @@ do_reloc (struct module *mod, uint8_t r_ |
658 |
+ break; |
659 |
+ |
660 |
+ case RV_BDREL: |
661 |
+- val -= (uint64_t) (in_init(mod, val) ? mod->module_init : mod->module_core); |
662 |
++ if (in_init_rx(mod, val)) |
663 |
++ val -= (uint64_t) mod->module_init_rx; |
664 |
++ else if (in_init_rw(mod, val)) |
665 |
++ val -= (uint64_t) mod->module_init_rw; |
666 |
++ else if (in_core_rx(mod, val)) |
667 |
++ val -= (uint64_t) mod->module_core_rx; |
668 |
++ else if (in_core_rw(mod, val)) |
669 |
++ val -= (uint64_t) mod->module_core_rw; |
670 |
+ break; |
671 |
+ |
672 |
+ case RV_LTV: |
673 |
+@@ -817,15 +847,15 @@ apply_relocate_add (Elf64_Shdr *sechdrs, |
674 |
+ * addresses have been selected... |
675 |
+ */ |
676 |
+ uint64_t gp; |
677 |
+- if (mod->core_size > MAX_LTOFF) |
678 |
++ if (mod->core_size_rx + mod->core_size_rw > MAX_LTOFF) |
679 |
+ /* |
680 |
+ * This takes advantage of fact that SHF_ARCH_SMALL gets allocated |
681 |
+ * at the end of the module. |
682 |
+ */ |
683 |
+- gp = mod->core_size - MAX_LTOFF / 2; |
684 |
++ gp = mod->core_size_rx + mod->core_size_rw - MAX_LTOFF / 2; |
685 |
+ else |
686 |
+- gp = mod->core_size / 2; |
687 |
+- gp = (uint64_t) mod->module_core + ((gp + 7) & -8); |
688 |
++ gp = (mod->core_size_rx + mod->core_size_rw) / 2; |
689 |
++ gp = (uint64_t) mod->module_core_rx + ((gp + 7) & -8); |
690 |
+ mod->arch.gp = gp; |
691 |
+ DEBUGP("%s: placing gp at 0x%lx\n", __func__, gp); |
692 |
+ } |
693 |
+diff -urNp linux-2.6.28.8/arch/ia64/kernel/sys_ia64.c linux-2.6.28.8/arch/ia64/kernel/sys_ia64.c |
694 |
+--- linux-2.6.28.8/arch/ia64/kernel/sys_ia64.c 2009-02-06 16:47:45.000000000 -0500 |
695 |
++++ linux-2.6.28.8/arch/ia64/kernel/sys_ia64.c 2009-02-21 09:37:48.000000000 -0500 |
696 |
+@@ -43,6 +43,13 @@ arch_get_unmapped_area (struct file *fil |
697 |
+ if (REGION_NUMBER(addr) == RGN_HPAGE) |
698 |
+ addr = 0; |
699 |
+ #endif |
700 |
++ |
701 |
++#ifdef CONFIG_PAX_RANDMMAP |
702 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
703 |
++ addr = mm->free_area_cache; |
704 |
++ else |
705 |
++#endif |
706 |
++ |
707 |
+ if (!addr) |
708 |
+ addr = mm->free_area_cache; |
709 |
+ |
710 |
+@@ -61,9 +68,9 @@ arch_get_unmapped_area (struct file *fil |
711 |
+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { |
712 |
+ /* At this point: (!vma || addr < vma->vm_end). */ |
713 |
+ if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) { |
714 |
+- if (start_addr != TASK_UNMAPPED_BASE) { |
715 |
++ if (start_addr != mm->mmap_base) { |
716 |
+ /* Start a new search --- just in case we missed some holes. */ |
717 |
+- addr = TASK_UNMAPPED_BASE; |
718 |
++ addr = mm->mmap_base; |
719 |
+ goto full_search; |
720 |
+ } |
721 |
+ return -ENOMEM; |
722 |
+diff -urNp linux-2.6.28.8/arch/ia64/mm/fault.c linux-2.6.28.8/arch/ia64/mm/fault.c |
723 |
+--- linux-2.6.28.8/arch/ia64/mm/fault.c 2009-02-06 16:47:45.000000000 -0500 |
724 |
++++ linux-2.6.28.8/arch/ia64/mm/fault.c 2009-02-21 09:37:48.000000000 -0500 |
725 |
+@@ -72,6 +72,23 @@ mapped_kernel_page_is_present (unsigned |
726 |
+ return pte_present(pte); |
727 |
+ } |
728 |
+ |
729 |
++#ifdef CONFIG_PAX_PAGEEXEC |
730 |
++void pax_report_insns(void *pc, void *sp) |
731 |
++{ |
732 |
++ unsigned long i; |
733 |
++ |
734 |
++ printk(KERN_ERR "PAX: bytes at PC: "); |
735 |
++ for (i = 0; i < 8; i++) { |
736 |
++ unsigned int c; |
737 |
++ if (get_user(c, (unsigned int *)pc+i)) |
738 |
++ printk(KERN_CONT "???????? "); |
739 |
++ else |
740 |
++ printk(KERN_CONT "%08x ", c); |
741 |
++ } |
742 |
++ printk("\n"); |
743 |
++} |
744 |
++#endif |
745 |
++ |
746 |
+ void __kprobes |
747 |
+ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) |
748 |
+ { |
749 |
+@@ -145,9 +162,23 @@ ia64_do_page_fault (unsigned long addres |
750 |
+ mask = ( (((isr >> IA64_ISR_X_BIT) & 1UL) << VM_EXEC_BIT) |
751 |
+ | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)); |
752 |
+ |
753 |
+- if ((vma->vm_flags & mask) != mask) |
754 |
++ if ((vma->vm_flags & mask) != mask) { |
755 |
++ |
756 |
++#ifdef CONFIG_PAX_PAGEEXEC |
757 |
++ if (!(vma->vm_flags & VM_EXEC) && (mask & VM_EXEC)) { |
758 |
++ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->cr_iip) |
759 |
++ goto bad_area; |
760 |
++ |
761 |
++ up_read(&mm->mmap_sem); |
762 |
++ pax_report_fault(regs, (void *)regs->cr_iip, (void *)regs->r12); |
763 |
++ do_group_exit(SIGKILL); |
764 |
++ } |
765 |
++#endif |
766 |
++ |
767 |
+ goto bad_area; |
768 |
+ |
769 |
++ } |
770 |
++ |
771 |
+ survive: |
772 |
+ /* |
773 |
+ * If for any reason at all we couldn't handle the fault, make |
774 |
+diff -urNp linux-2.6.28.8/arch/ia64/mm/init.c linux-2.6.28.8/arch/ia64/mm/init.c |
775 |
+--- linux-2.6.28.8/arch/ia64/mm/init.c 2009-02-06 16:47:45.000000000 -0500 |
776 |
++++ linux-2.6.28.8/arch/ia64/mm/init.c 2009-02-21 09:37:48.000000000 -0500 |
777 |
+@@ -121,6 +121,19 @@ ia64_init_addr_space (void) |
778 |
+ vma->vm_start = current->thread.rbs_bot & PAGE_MASK; |
779 |
+ vma->vm_end = vma->vm_start + PAGE_SIZE; |
780 |
+ vma->vm_flags = VM_DATA_DEFAULT_FLAGS|VM_GROWSUP|VM_ACCOUNT; |
781 |
++ |
782 |
++#ifdef CONFIG_PAX_PAGEEXEC |
783 |
++ if (current->mm->pax_flags & MF_PAX_PAGEEXEC) { |
784 |
++ vma->vm_flags &= ~VM_EXEC; |
785 |
++ |
786 |
++#ifdef CONFIG_PAX_MPROTECT |
787 |
++ if (current->mm->pax_flags & MF_PAX_MPROTECT) |
788 |
++ vma->vm_flags &= ~VM_MAYEXEC; |
789 |
++#endif |
790 |
++ |
791 |
++ } |
792 |
++#endif |
793 |
++ |
794 |
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
795 |
+ down_write(¤t->mm->mmap_sem); |
796 |
+ if (insert_vm_struct(current->mm, vma)) { |
797 |
+diff -urNp linux-2.6.28.8/arch/m68knommu/include/asm/kmap_types.h linux-2.6.28.8/arch/m68knommu/include/asm/kmap_types.h |
798 |
+--- linux-2.6.28.8/arch/m68knommu/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
799 |
++++ linux-2.6.28.8/arch/m68knommu/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
800 |
+@@ -15,6 +15,7 @@ enum km_type { |
801 |
+ KM_IRQ1, |
802 |
+ KM_SOFTIRQ0, |
803 |
+ KM_SOFTIRQ1, |
804 |
++ KM_CLEARPAGE, |
805 |
+ KM_TYPE_NR |
806 |
+ }; |
807 |
+ |
808 |
+diff -urNp linux-2.6.28.8/arch/mips/include/asm/elf.h linux-2.6.28.8/arch/mips/include/asm/elf.h |
809 |
+--- linux-2.6.28.8/arch/mips/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500 |
810 |
++++ linux-2.6.28.8/arch/mips/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500 |
811 |
+@@ -364,4 +364,11 @@ extern int dump_task_fpu(struct task_str |
812 |
+ #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) |
813 |
+ #endif |
814 |
+ |
815 |
++#ifdef CONFIG_PAX_ASLR |
816 |
++#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) |
817 |
++ |
818 |
++#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) |
819 |
++#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) |
820 |
++#endif |
821 |
++ |
822 |
+ #endif /* _ASM_ELF_H */ |
823 |
+diff -urNp linux-2.6.28.8/arch/mips/include/asm/kmap_types.h linux-2.6.28.8/arch/mips/include/asm/kmap_types.h |
824 |
+--- linux-2.6.28.8/arch/mips/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
825 |
++++ linux-2.6.28.8/arch/mips/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
826 |
+@@ -22,7 +22,8 @@ D(9) KM_IRQ0, |
827 |
+ D(10) KM_IRQ1, |
828 |
+ D(11) KM_SOFTIRQ0, |
829 |
+ D(12) KM_SOFTIRQ1, |
830 |
+-D(13) KM_TYPE_NR |
831 |
++D(13) KM_CLEARPAGE, |
832 |
++D(14) KM_TYPE_NR |
833 |
+ }; |
834 |
+ |
835 |
+ #undef D |
836 |
+diff -urNp linux-2.6.28.8/arch/mips/include/asm/page.h linux-2.6.28.8/arch/mips/include/asm/page.h |
837 |
+--- linux-2.6.28.8/arch/mips/include/asm/page.h 2009-02-06 16:47:45.000000000 -0500 |
838 |
++++ linux-2.6.28.8/arch/mips/include/asm/page.h 2009-02-21 09:37:48.000000000 -0500 |
839 |
+@@ -82,7 +82,7 @@ extern void copy_user_highpage(struct pa |
840 |
+ #ifdef CONFIG_CPU_MIPS32 |
841 |
+ typedef struct { unsigned long pte_low, pte_high; } pte_t; |
842 |
+ #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32)) |
843 |
+- #define __pte(x) ({ pte_t __pte = {(x), ((unsigned long long)(x)) >> 32}; __pte; }) |
844 |
++ #define __pte(x) ({ pte_t __pte = {(x), (x) >> 32}; __pte; }) |
845 |
+ #else |
846 |
+ typedef struct { unsigned long long pte; } pte_t; |
847 |
+ #define pte_val(x) ((x).pte) |
848 |
+diff -urNp linux-2.6.28.8/arch/mips/include/asm/system.h linux-2.6.28.8/arch/mips/include/asm/system.h |
849 |
+--- linux-2.6.28.8/arch/mips/include/asm/system.h 2009-02-06 16:47:45.000000000 -0500 |
850 |
++++ linux-2.6.28.8/arch/mips/include/asm/system.h 2009-02-21 09:37:48.000000000 -0500 |
851 |
+@@ -217,6 +217,6 @@ extern void per_cpu_trap_init(void); |
852 |
+ */ |
853 |
+ #define __ARCH_WANT_UNLOCKED_CTXSW |
854 |
+ |
855 |
+-extern unsigned long arch_align_stack(unsigned long sp); |
856 |
++#define arch_align_stack(x) ((x) & ALMASK) |
857 |
+ |
858 |
+ #endif /* _ASM_SYSTEM_H */ |
859 |
+diff -urNp linux-2.6.28.8/arch/mips/kernel/binfmt_elfn32.c linux-2.6.28.8/arch/mips/kernel/binfmt_elfn32.c |
860 |
+--- linux-2.6.28.8/arch/mips/kernel/binfmt_elfn32.c 2009-02-06 16:47:45.000000000 -0500 |
861 |
++++ linux-2.6.28.8/arch/mips/kernel/binfmt_elfn32.c 2009-02-21 09:37:48.000000000 -0500 |
862 |
+@@ -50,6 +50,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N |
863 |
+ #undef ELF_ET_DYN_BASE |
864 |
+ #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) |
865 |
+ |
866 |
++#ifdef CONFIG_PAX_ASLR |
867 |
++#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) |
868 |
++ |
869 |
++#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) |
870 |
++#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) |
871 |
++#endif |
872 |
++ |
873 |
+ #include <asm/processor.h> |
874 |
+ #include <linux/module.h> |
875 |
+ #include <linux/elfcore.h> |
876 |
+diff -urNp linux-2.6.28.8/arch/mips/kernel/binfmt_elfo32.c linux-2.6.28.8/arch/mips/kernel/binfmt_elfo32.c |
877 |
+--- linux-2.6.28.8/arch/mips/kernel/binfmt_elfo32.c 2009-02-06 16:47:45.000000000 -0500 |
878 |
++++ linux-2.6.28.8/arch/mips/kernel/binfmt_elfo32.c 2009-02-21 09:37:48.000000000 -0500 |
879 |
+@@ -52,6 +52,13 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N |
880 |
+ #undef ELF_ET_DYN_BASE |
881 |
+ #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) |
882 |
+ |
883 |
++#ifdef CONFIG_PAX_ASLR |
884 |
++#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) |
885 |
++ |
886 |
++#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) |
887 |
++#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) |
888 |
++#endif |
889 |
++ |
890 |
+ #include <asm/processor.h> |
891 |
+ #include <linux/module.h> |
892 |
+ #include <linux/elfcore.h> |
893 |
+diff -urNp linux-2.6.28.8/arch/mips/kernel/process.c linux-2.6.28.8/arch/mips/kernel/process.c |
894 |
+--- linux-2.6.28.8/arch/mips/kernel/process.c 2009-02-06 16:47:45.000000000 -0500 |
895 |
++++ linux-2.6.28.8/arch/mips/kernel/process.c 2009-02-21 09:37:48.000000000 -0500 |
896 |
+@@ -457,15 +457,3 @@ unsigned long get_wchan(struct task_stru |
897 |
+ out: |
898 |
+ return pc; |
899 |
+ } |
900 |
+- |
901 |
+-/* |
902 |
+- * Don't forget that the stack pointer must be aligned on a 8 bytes |
903 |
+- * boundary for 32-bits ABI and 16 bytes for 64-bits ABI. |
904 |
+- */ |
905 |
+-unsigned long arch_align_stack(unsigned long sp) |
906 |
+-{ |
907 |
+- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) |
908 |
+- sp -= get_random_int() & ~PAGE_MASK; |
909 |
+- |
910 |
+- return sp & ALMASK; |
911 |
+-} |
912 |
+diff -urNp linux-2.6.28.8/arch/mips/kernel/syscall.c linux-2.6.28.8/arch/mips/kernel/syscall.c |
913 |
+--- linux-2.6.28.8/arch/mips/kernel/syscall.c 2009-02-06 16:47:45.000000000 -0500 |
914 |
++++ linux-2.6.28.8/arch/mips/kernel/syscall.c 2009-02-21 09:37:48.000000000 -0500 |
915 |
+@@ -99,6 +99,11 @@ unsigned long arch_get_unmapped_area(str |
916 |
+ do_color_align = 0; |
917 |
+ if (filp || (flags & MAP_SHARED)) |
918 |
+ do_color_align = 1; |
919 |
++ |
920 |
++#ifdef CONFIG_PAX_RANDMMAP |
921 |
++ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP)) |
922 |
++#endif |
923 |
++ |
924 |
+ if (addr) { |
925 |
+ if (do_color_align) |
926 |
+ addr = COLOUR_ALIGN(addr, pgoff); |
927 |
+@@ -109,7 +114,7 @@ unsigned long arch_get_unmapped_area(str |
928 |
+ (!vmm || addr + len <= vmm->vm_start)) |
929 |
+ return addr; |
930 |
+ } |
931 |
+- addr = TASK_UNMAPPED_BASE; |
932 |
++ addr = current->mm->mmap_base; |
933 |
+ if (do_color_align) |
934 |
+ addr = COLOUR_ALIGN(addr, pgoff); |
935 |
+ else |
936 |
+diff -urNp linux-2.6.28.8/arch/mips/mm/fault.c linux-2.6.28.8/arch/mips/mm/fault.c |
937 |
+--- linux-2.6.28.8/arch/mips/mm/fault.c 2009-02-06 16:47:45.000000000 -0500 |
938 |
++++ linux-2.6.28.8/arch/mips/mm/fault.c 2009-02-21 09:37:48.000000000 -0500 |
939 |
+@@ -26,6 +26,23 @@ |
940 |
+ #include <asm/ptrace.h> |
941 |
+ #include <asm/highmem.h> /* For VMALLOC_END */ |
942 |
+ |
943 |
++#ifdef CONFIG_PAX_PAGEEXEC |
944 |
++void pax_report_insns(void *pc) |
945 |
++{ |
946 |
++ unsigned long i; |
947 |
++ |
948 |
++ printk(KERN_ERR "PAX: bytes at PC: "); |
949 |
++ for (i = 0; i < 5; i++) { |
950 |
++ unsigned int c; |
951 |
++ if (get_user(c, (unsigned int *)pc+i)) |
952 |
++ printk(KERN_CONT "???????? "); |
953 |
++ else |
954 |
++ printk(KERN_CONT "%08x ", c); |
955 |
++ } |
956 |
++ printk("\n"); |
957 |
++} |
958 |
++#endif |
959 |
++ |
960 |
+ /* |
961 |
+ * This routine handles page faults. It determines the address, |
962 |
+ * and the problem, and then passes it off to one of the appropriate |
963 |
+diff -urNp linux-2.6.28.8/arch/parisc/include/asm/elf.h linux-2.6.28.8/arch/parisc/include/asm/elf.h |
964 |
+--- linux-2.6.28.8/arch/parisc/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500 |
965 |
++++ linux-2.6.28.8/arch/parisc/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500 |
966 |
+@@ -333,6 +333,13 @@ struct pt_regs; /* forward declaration.. |
967 |
+ |
968 |
+ #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000) |
969 |
+ |
970 |
++#ifdef CONFIG_PAX_ASLR |
971 |
++#define PAX_ELF_ET_DYN_BASE 0x10000UL |
972 |
++ |
973 |
++#define PAX_DELTA_MMAP_LEN 16 |
974 |
++#define PAX_DELTA_STACK_LEN 16 |
975 |
++#endif |
976 |
++ |
977 |
+ /* This yields a mask that user programs can use to figure out what |
978 |
+ instruction set this CPU supports. This could be done in user space, |
979 |
+ but it's not easy, and we've already done it here. */ |
980 |
+diff -urNp linux-2.6.28.8/arch/parisc/include/asm/kmap_types.h linux-2.6.28.8/arch/parisc/include/asm/kmap_types.h |
981 |
+--- linux-2.6.28.8/arch/parisc/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
982 |
++++ linux-2.6.28.8/arch/parisc/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
983 |
+@@ -22,7 +22,8 @@ D(9) KM_IRQ0, |
984 |
+ D(10) KM_IRQ1, |
985 |
+ D(11) KM_SOFTIRQ0, |
986 |
+ D(12) KM_SOFTIRQ1, |
987 |
+-D(13) KM_TYPE_NR |
988 |
++D(13) KM_CLEARPAGE, |
989 |
++D(14) KM_TYPE_NR |
990 |
+ }; |
991 |
+ |
992 |
+ #undef D |
993 |
+diff -urNp linux-2.6.28.8/arch/parisc/include/asm/pgtable.h linux-2.6.28.8/arch/parisc/include/asm/pgtable.h |
994 |
+--- linux-2.6.28.8/arch/parisc/include/asm/pgtable.h 2009-02-06 16:47:45.000000000 -0500 |
995 |
++++ linux-2.6.28.8/arch/parisc/include/asm/pgtable.h 2009-02-21 09:37:48.000000000 -0500 |
996 |
+@@ -202,6 +202,17 @@ |
997 |
+ #define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED) |
998 |
+ #define PAGE_COPY PAGE_EXECREAD |
999 |
+ #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED) |
1000 |
++ |
1001 |
++#ifdef CONFIG_PAX_PAGEEXEC |
1002 |
++# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_ACCESSED) |
1003 |
++# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED) |
1004 |
++# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED) |
1005 |
++#else |
1006 |
++# define PAGE_SHARED_NOEXEC PAGE_SHARED |
1007 |
++# define PAGE_COPY_NOEXEC PAGE_COPY |
1008 |
++# define PAGE_READONLY_NOEXEC PAGE_READONLY |
1009 |
++#endif |
1010 |
++ |
1011 |
+ #define PAGE_KERNEL __pgprot(_PAGE_KERNEL) |
1012 |
+ #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE) |
1013 |
+ #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) |
1014 |
+diff -urNp linux-2.6.28.8/arch/parisc/kernel/module.c linux-2.6.28.8/arch/parisc/kernel/module.c |
1015 |
+--- linux-2.6.28.8/arch/parisc/kernel/module.c 2009-02-06 16:47:45.000000000 -0500 |
1016 |
++++ linux-2.6.28.8/arch/parisc/kernel/module.c 2009-02-21 09:37:48.000000000 -0500 |
1017 |
+@@ -75,16 +75,38 @@ |
1018 |
+ |
1019 |
+ /* three functions to determine where in the module core |
1020 |
+ * or init pieces the location is */ |
1021 |
++static inline int in_init_rx(struct module *me, void *loc) |
1022 |
++{ |
1023 |
++ return (loc >= me->module_init_rx && |
1024 |
++ loc < (me->module_init_rx + me->init_size_rx)); |
1025 |
++} |
1026 |
++ |
1027 |
++static inline int in_init_rw(struct module *me, void *loc) |
1028 |
++{ |
1029 |
++ return (loc >= me->module_init_rw && |
1030 |
++ loc < (me->module_init_rw + me->init_size_rw)); |
1031 |
++} |
1032 |
++ |
1033 |
+ static inline int in_init(struct module *me, void *loc) |
1034 |
+ { |
1035 |
+- return (loc >= me->module_init && |
1036 |
+- loc <= (me->module_init + me->init_size)); |
1037 |
++ return in_init_rx(me, loc) || in_init_rw(me, loc); |
1038 |
++} |
1039 |
++ |
1040 |
++static inline int in_core_rx(struct module *me, void *loc) |
1041 |
++{ |
1042 |
++ return (loc >= me->module_core_rx && |
1043 |
++ loc < (me->module_core_rx + me->core_size_rx)); |
1044 |
++} |
1045 |
++ |
1046 |
++static inline int in_core_rw(struct module *me, void *loc) |
1047 |
++{ |
1048 |
++ return (loc >= me->module_core_rw && |
1049 |
++ loc < (me->module_core_rw + me->core_size_rw)); |
1050 |
+ } |
1051 |
+ |
1052 |
+ static inline int in_core(struct module *me, void *loc) |
1053 |
+ { |
1054 |
+- return (loc >= me->module_core && |
1055 |
+- loc <= (me->module_core + me->core_size)); |
1056 |
++ return in_core_rx(me, loc) || in_core_rw(me, loc); |
1057 |
+ } |
1058 |
+ |
1059 |
+ static inline int in_local(struct module *me, void *loc) |
1060 |
+@@ -298,21 +320,21 @@ int module_frob_arch_sections(CONST Elf_ |
1061 |
+ } |
1062 |
+ |
1063 |
+ /* align things a bit */ |
1064 |
+- me->core_size = ALIGN(me->core_size, 16); |
1065 |
+- me->arch.got_offset = me->core_size; |
1066 |
+- me->core_size += gots * sizeof(struct got_entry); |
1067 |
+- |
1068 |
+- me->core_size = ALIGN(me->core_size, 16); |
1069 |
+- me->arch.fdesc_offset = me->core_size; |
1070 |
+- me->core_size += fdescs * sizeof(Elf_Fdesc); |
1071 |
+- |
1072 |
+- me->core_size = ALIGN(me->core_size, 16); |
1073 |
+- me->arch.stub_offset = me->core_size; |
1074 |
+- me->core_size += stubs * sizeof(struct stub_entry); |
1075 |
+- |
1076 |
+- me->init_size = ALIGN(me->init_size, 16); |
1077 |
+- me->arch.init_stub_offset = me->init_size; |
1078 |
+- me->init_size += init_stubs * sizeof(struct stub_entry); |
1079 |
++ me->core_size_rw = ALIGN(me->core_size_rw, 16); |
1080 |
++ me->arch.got_offset = me->core_size_rw; |
1081 |
++ me->core_size_rw += gots * sizeof(struct got_entry); |
1082 |
++ |
1083 |
++ me->core_size_rw = ALIGN(me->core_size_rw, 16); |
1084 |
++ me->arch.fdesc_offset = me->core_size_rw; |
1085 |
++ me->core_size_rw += fdescs * sizeof(Elf_Fdesc); |
1086 |
++ |
1087 |
++ me->core_size_rx = ALIGN(me->core_size_rx, 16); |
1088 |
++ me->arch.stub_offset = me->core_size_rx; |
1089 |
++ me->core_size_rx += stubs * sizeof(struct stub_entry); |
1090 |
++ |
1091 |
++ me->init_size_rx = ALIGN(me->init_size_rx, 16); |
1092 |
++ me->arch.init_stub_offset = me->init_size_rx; |
1093 |
++ me->init_size_rx += init_stubs * sizeof(struct stub_entry); |
1094 |
+ |
1095 |
+ me->arch.got_max = gots; |
1096 |
+ me->arch.fdesc_max = fdescs; |
1097 |
+@@ -332,7 +354,7 @@ static Elf64_Word get_got(struct module |
1098 |
+ |
1099 |
+ BUG_ON(value == 0); |
1100 |
+ |
1101 |
+- got = me->module_core + me->arch.got_offset; |
1102 |
++ got = me->module_core_rw + me->arch.got_offset; |
1103 |
+ for (i = 0; got[i].addr; i++) |
1104 |
+ if (got[i].addr == value) |
1105 |
+ goto out; |
1106 |
+@@ -350,7 +372,7 @@ static Elf64_Word get_got(struct module |
1107 |
+ #ifdef CONFIG_64BIT |
1108 |
+ static Elf_Addr get_fdesc(struct module *me, unsigned long value) |
1109 |
+ { |
1110 |
+- Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset; |
1111 |
++ Elf_Fdesc *fdesc = me->module_core_rw + me->arch.fdesc_offset; |
1112 |
+ |
1113 |
+ if (!value) { |
1114 |
+ printk(KERN_ERR "%s: zero OPD requested!\n", me->name); |
1115 |
+@@ -368,7 +390,7 @@ static Elf_Addr get_fdesc(struct module |
1116 |
+ |
1117 |
+ /* Create new one */ |
1118 |
+ fdesc->addr = value; |
1119 |
+- fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset; |
1120 |
++ fdesc->gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset; |
1121 |
+ return (Elf_Addr)fdesc; |
1122 |
+ } |
1123 |
+ #endif /* CONFIG_64BIT */ |
1124 |
+@@ -388,12 +410,12 @@ static Elf_Addr get_stub(struct module * |
1125 |
+ if(init_section) { |
1126 |
+ i = me->arch.init_stub_count++; |
1127 |
+ BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max); |
1128 |
+- stub = me->module_init + me->arch.init_stub_offset + |
1129 |
++ stub = me->module_init_rx + me->arch.init_stub_offset + |
1130 |
+ i * sizeof(struct stub_entry); |
1131 |
+ } else { |
1132 |
+ i = me->arch.stub_count++; |
1133 |
+ BUG_ON(me->arch.stub_count > me->arch.stub_max); |
1134 |
+- stub = me->module_core + me->arch.stub_offset + |
1135 |
++ stub = me->module_core_rx + me->arch.stub_offset + |
1136 |
+ i * sizeof(struct stub_entry); |
1137 |
+ } |
1138 |
+ |
1139 |
+@@ -761,7 +783,7 @@ register_unwind_table(struct module *me, |
1140 |
+ |
1141 |
+ table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr; |
1142 |
+ end = table + sechdrs[me->arch.unwind_section].sh_size; |
1143 |
+- gp = (Elf_Addr)me->module_core + me->arch.got_offset; |
1144 |
++ gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset; |
1145 |
+ |
1146 |
+ DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n", |
1147 |
+ me->arch.unwind_section, table, end, gp); |
1148 |
+diff -urNp linux-2.6.28.8/arch/parisc/kernel/sys_parisc.c linux-2.6.28.8/arch/parisc/kernel/sys_parisc.c |
1149 |
+--- linux-2.6.28.8/arch/parisc/kernel/sys_parisc.c 2009-02-06 16:47:45.000000000 -0500 |
1150 |
++++ linux-2.6.28.8/arch/parisc/kernel/sys_parisc.c 2009-02-21 09:37:48.000000000 -0500 |
1151 |
+@@ -98,7 +98,7 @@ unsigned long arch_get_unmapped_area(str |
1152 |
+ if (flags & MAP_FIXED) |
1153 |
+ return addr; |
1154 |
+ if (!addr) |
1155 |
+- addr = TASK_UNMAPPED_BASE; |
1156 |
++ addr = current->mm->mmap_base; |
1157 |
+ |
1158 |
+ if (filp) { |
1159 |
+ addr = get_shared_area(filp->f_mapping, addr, len, pgoff); |
1160 |
+diff -urNp linux-2.6.28.8/arch/parisc/kernel/traps.c linux-2.6.28.8/arch/parisc/kernel/traps.c |
1161 |
+--- linux-2.6.28.8/arch/parisc/kernel/traps.c 2009-02-06 16:47:45.000000000 -0500 |
1162 |
++++ linux-2.6.28.8/arch/parisc/kernel/traps.c 2009-02-21 09:37:48.000000000 -0500 |
1163 |
+@@ -731,9 +731,7 @@ void handle_interruption(int code, struc |
1164 |
+ |
1165 |
+ down_read(¤t->mm->mmap_sem); |
1166 |
+ vma = find_vma(current->mm,regs->iaoq[0]); |
1167 |
+- if (vma && (regs->iaoq[0] >= vma->vm_start) |
1168 |
+- && (vma->vm_flags & VM_EXEC)) { |
1169 |
+- |
1170 |
++ if (vma && (regs->iaoq[0] >= vma->vm_start)) { |
1171 |
+ fault_address = regs->iaoq[0]; |
1172 |
+ fault_space = regs->iasq[0]; |
1173 |
+ |
1174 |
+diff -urNp linux-2.6.28.8/arch/parisc/mm/fault.c linux-2.6.28.8/arch/parisc/mm/fault.c |
1175 |
+--- linux-2.6.28.8/arch/parisc/mm/fault.c 2009-02-06 16:47:45.000000000 -0500 |
1176 |
++++ linux-2.6.28.8/arch/parisc/mm/fault.c 2009-02-21 09:37:48.000000000 -0500 |
1177 |
+@@ -16,6 +16,7 @@ |
1178 |
+ #include <linux/sched.h> |
1179 |
+ #include <linux/interrupt.h> |
1180 |
+ #include <linux/module.h> |
1181 |
++#include <linux/unistd.h> |
1182 |
+ |
1183 |
+ #include <asm/uaccess.h> |
1184 |
+ #include <asm/traps.h> |
1185 |
+@@ -53,7 +54,7 @@ DEFINE_PER_CPU(struct exception_data, ex |
1186 |
+ static unsigned long |
1187 |
+ parisc_acctyp(unsigned long code, unsigned int inst) |
1188 |
+ { |
1189 |
+- if (code == 6 || code == 16) |
1190 |
++ if (code == 6 || code == 7 || code == 16) |
1191 |
+ return VM_EXEC; |
1192 |
+ |
1193 |
+ switch (inst & 0xf0000000) { |
1194 |
+@@ -139,6 +140,116 @@ parisc_acctyp(unsigned long code, unsign |
1195 |
+ } |
1196 |
+ #endif |
1197 |
+ |
1198 |
++#ifdef CONFIG_PAX_PAGEEXEC |
1199 |
++/* |
1200 |
++ * PaX: decide what to do with offenders (instruction_pointer(regs) = fault address) |
1201 |
++ * |
1202 |
++ * returns 1 when task should be killed |
1203 |
++ * 2 when rt_sigreturn trampoline was detected |
1204 |
++ * 3 when unpatched PLT trampoline was detected |
1205 |
++ */ |
1206 |
++static int pax_handle_fetch_fault(struct pt_regs *regs) |
1207 |
++{ |
1208 |
++ |
1209 |
++#ifdef CONFIG_PAX_EMUPLT |
1210 |
++ int err; |
1211 |
++ |
1212 |
++ do { /* PaX: unpatched PLT emulation */ |
1213 |
++ unsigned int bl, depwi; |
1214 |
++ |
1215 |
++ err = get_user(bl, (unsigned int *)instruction_pointer(regs)); |
1216 |
++ err |= get_user(depwi, (unsigned int *)(instruction_pointer(regs)+4)); |
1217 |
++ |
1218 |
++ if (err) |
1219 |
++ break; |
1220 |
++ |
1221 |
++ if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) { |
1222 |
++ unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12; |
1223 |
++ |
1224 |
++ err = get_user(ldw, (unsigned int *)addr); |
1225 |
++ err |= get_user(bv, (unsigned int *)(addr+4)); |
1226 |
++ err |= get_user(ldw2, (unsigned int *)(addr+8)); |
1227 |
++ |
1228 |
++ if (err) |
1229 |
++ break; |
1230 |
++ |
1231 |
++ if (ldw == 0x0E801096U && |
1232 |
++ bv == 0xEAC0C000U && |
1233 |
++ ldw2 == 0x0E881095U) |
1234 |
++ { |
1235 |
++ unsigned int resolver, map; |
1236 |
++ |
1237 |
++ err = get_user(resolver, (unsigned int *)(instruction_pointer(regs)+8)); |
1238 |
++ err |= get_user(map, (unsigned int *)(instruction_pointer(regs)+12)); |
1239 |
++ if (err) |
1240 |
++ break; |
1241 |
++ |
1242 |
++ regs->gr[20] = instruction_pointer(regs)+8; |
1243 |
++ regs->gr[21] = map; |
1244 |
++ regs->gr[22] = resolver; |
1245 |
++ regs->iaoq[0] = resolver | 3UL; |
1246 |
++ regs->iaoq[1] = regs->iaoq[0] + 4; |
1247 |
++ return 3; |
1248 |
++ } |
1249 |
++ } |
1250 |
++ } while (0); |
1251 |
++#endif |
1252 |
++ |
1253 |
++#ifdef CONFIG_PAX_EMUTRAMP |
1254 |
++ |
1255 |
++#ifndef CONFIG_PAX_EMUSIGRT |
1256 |
++ if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP)) |
1257 |
++ return 1; |
1258 |
++#endif |
1259 |
++ |
1260 |
++ do { /* PaX: rt_sigreturn emulation */ |
1261 |
++ unsigned int ldi1, ldi2, bel, nop; |
1262 |
++ |
1263 |
++ err = get_user(ldi1, (unsigned int *)instruction_pointer(regs)); |
1264 |
++ err |= get_user(ldi2, (unsigned int *)(instruction_pointer(regs)+4)); |
1265 |
++ err |= get_user(bel, (unsigned int *)(instruction_pointer(regs)+8)); |
1266 |
++ err |= get_user(nop, (unsigned int *)(instruction_pointer(regs)+12)); |
1267 |
++ |
1268 |
++ if (err) |
1269 |
++ break; |
1270 |
++ |
1271 |
++ if ((ldi1 == 0x34190000U || ldi1 == 0x34190002U) && |
1272 |
++ ldi2 == 0x3414015AU && |
1273 |
++ bel == 0xE4008200U && |
1274 |
++ nop == 0x08000240U) |
1275 |
++ { |
1276 |
++ regs->gr[25] = (ldi1 & 2) >> 1; |
1277 |
++ regs->gr[20] = __NR_rt_sigreturn; |
1278 |
++ regs->gr[31] = regs->iaoq[1] + 16; |
1279 |
++ regs->sr[0] = regs->iasq[1]; |
1280 |
++ regs->iaoq[0] = 0x100UL; |
1281 |
++ regs->iaoq[1] = regs->iaoq[0] + 4; |
1282 |
++ regs->iasq[0] = regs->sr[2]; |
1283 |
++ regs->iasq[1] = regs->sr[2]; |
1284 |
++ return 2; |
1285 |
++ } |
1286 |
++ } while (0); |
1287 |
++#endif |
1288 |
++ |
1289 |
++ return 1; |
1290 |
++} |
1291 |
++ |
1292 |
++void pax_report_insns(void *pc, void *sp) |
1293 |
++{ |
1294 |
++ unsigned long i; |
1295 |
++ |
1296 |
++ printk(KERN_ERR "PAX: bytes at PC: "); |
1297 |
++ for (i = 0; i < 5; i++) { |
1298 |
++ unsigned int c; |
1299 |
++ if (get_user(c, (unsigned int *)pc+i)) |
1300 |
++ printk(KERN_CONT "???????? "); |
1301 |
++ else |
1302 |
++ printk(KERN_CONT "%08x ", c); |
1303 |
++ } |
1304 |
++ printk("\n"); |
1305 |
++} |
1306 |
++#endif |
1307 |
++ |
1308 |
+ void do_page_fault(struct pt_regs *regs, unsigned long code, |
1309 |
+ unsigned long address) |
1310 |
+ { |
1311 |
+@@ -165,8 +276,33 @@ good_area: |
1312 |
+ |
1313 |
+ acc_type = parisc_acctyp(code,regs->iir); |
1314 |
+ |
1315 |
+- if ((vma->vm_flags & acc_type) != acc_type) |
1316 |
++ if ((vma->vm_flags & acc_type) != acc_type) { |
1317 |
++ |
1318 |
++#ifdef CONFIG_PAX_PAGEEXEC |
1319 |
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (acc_type & VM_EXEC) && |
1320 |
++ (address & ~3UL) == instruction_pointer(regs)) |
1321 |
++ { |
1322 |
++ up_read(&mm->mmap_sem); |
1323 |
++ switch (pax_handle_fetch_fault(regs)) { |
1324 |
++ |
1325 |
++#ifdef CONFIG_PAX_EMUPLT |
1326 |
++ case 3: |
1327 |
++ return; |
1328 |
++#endif |
1329 |
++ |
1330 |
++#ifdef CONFIG_PAX_EMUTRAMP |
1331 |
++ case 2: |
1332 |
++ return; |
1333 |
++#endif |
1334 |
++ |
1335 |
++ } |
1336 |
++ pax_report_fault(regs, (void *)instruction_pointer(regs), (void *)regs->gr[30]); |
1337 |
++ do_group_exit(SIGKILL); |
1338 |
++ } |
1339 |
++#endif |
1340 |
++ |
1341 |
+ goto bad_area; |
1342 |
++ } |
1343 |
+ |
1344 |
+ /* |
1345 |
+ * If for any reason at all we couldn't handle the fault, make |
1346 |
+diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/elf.h linux-2.6.28.8/arch/powerpc/include/asm/elf.h |
1347 |
+--- linux-2.6.28.8/arch/powerpc/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500 |
1348 |
++++ linux-2.6.28.8/arch/powerpc/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500 |
1349 |
+@@ -180,6 +180,18 @@ typedef elf_fpreg_t elf_vsrreghalf_t32[E |
1350 |
+ |
1351 |
+ #define ELF_ET_DYN_BASE (0x20000000) |
1352 |
+ |
1353 |
++#ifdef CONFIG_PAX_ASLR |
1354 |
++#define PAX_ELF_ET_DYN_BASE (0x10000000UL) |
1355 |
++ |
1356 |
++#ifdef __powerpc64__ |
1357 |
++#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_32BIT) ? 16 : 28) |
1358 |
++#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_32BIT) ? 16 : 28) |
1359 |
++#else |
1360 |
++#define PAX_DELTA_MMAP_LEN 15 |
1361 |
++#define PAX_DELTA_STACK_LEN 15 |
1362 |
++#endif |
1363 |
++#endif |
1364 |
++ |
1365 |
+ /* |
1366 |
+ * Our registers are always unsigned longs, whether we're a 32 bit |
1367 |
+ * process or 64 bit, on either a 64 bit or 32 bit kernel. |
1368 |
+diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/kmap_types.h linux-2.6.28.8/arch/powerpc/include/asm/kmap_types.h |
1369 |
+--- linux-2.6.28.8/arch/powerpc/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
1370 |
++++ linux-2.6.28.8/arch/powerpc/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
1371 |
+@@ -26,6 +26,7 @@ enum km_type { |
1372 |
+ KM_SOFTIRQ1, |
1373 |
+ KM_PPC_SYNC_PAGE, |
1374 |
+ KM_PPC_SYNC_ICACHE, |
1375 |
++ KM_CLEARPAGE, |
1376 |
+ KM_TYPE_NR |
1377 |
+ }; |
1378 |
+ |
1379 |
+diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/page_64.h linux-2.6.28.8/arch/powerpc/include/asm/page_64.h |
1380 |
+--- linux-2.6.28.8/arch/powerpc/include/asm/page_64.h 2009-02-06 16:47:45.000000000 -0500 |
1381 |
++++ linux-2.6.28.8/arch/powerpc/include/asm/page_64.h 2009-02-21 09:37:48.000000000 -0500 |
1382 |
+@@ -170,15 +170,18 @@ do { \ |
1383 |
+ * stack by default, so in the absense of a PT_GNU_STACK program header |
1384 |
+ * we turn execute permission off. |
1385 |
+ */ |
1386 |
+-#define VM_STACK_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ |
1387 |
+- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
1388 |
++#define VM_STACK_DEFAULT_FLAGS32 \ |
1389 |
++ (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \ |
1390 |
++ VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
1391 |
+ |
1392 |
+ #define VM_STACK_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ |
1393 |
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
1394 |
+ |
1395 |
++#ifndef CONFIG_PAX_PAGEEXEC |
1396 |
+ #define VM_STACK_DEFAULT_FLAGS \ |
1397 |
+ (test_thread_flag(TIF_32BIT) ? \ |
1398 |
+ VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64) |
1399 |
++#endif |
1400 |
+ |
1401 |
+ #include <asm-generic/page.h> |
1402 |
+ |
1403 |
+diff -urNp linux-2.6.28.8/arch/powerpc/include/asm/page.h linux-2.6.28.8/arch/powerpc/include/asm/page.h |
1404 |
+--- linux-2.6.28.8/arch/powerpc/include/asm/page.h 2009-02-06 16:47:45.000000000 -0500 |
1405 |
++++ linux-2.6.28.8/arch/powerpc/include/asm/page.h 2009-02-21 09:37:48.000000000 -0500 |
1406 |
+@@ -111,8 +111,9 @@ extern phys_addr_t kernstart_addr; |
1407 |
+ * and needs to be executable. This means the whole heap ends |
1408 |
+ * up being executable. |
1409 |
+ */ |
1410 |
+-#define VM_DATA_DEFAULT_FLAGS32 (VM_READ | VM_WRITE | VM_EXEC | \ |
1411 |
+- VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
1412 |
++#define VM_DATA_DEFAULT_FLAGS32 \ |
1413 |
++ (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0) | \ |
1414 |
++ VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
1415 |
+ |
1416 |
+ #define VM_DATA_DEFAULT_FLAGS64 (VM_READ | VM_WRITE | \ |
1417 |
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
1418 |
+diff -urNp linux-2.6.28.8/arch/powerpc/kernel/module_32.c linux-2.6.28.8/arch/powerpc/kernel/module_32.c |
1419 |
+--- linux-2.6.28.8/arch/powerpc/kernel/module_32.c 2009-02-06 16:47:45.000000000 -0500 |
1420 |
++++ linux-2.6.28.8/arch/powerpc/kernel/module_32.c 2009-02-21 09:37:48.000000000 -0500 |
1421 |
+@@ -158,7 +158,7 @@ int module_frob_arch_sections(Elf32_Ehdr |
1422 |
+ me->arch.core_plt_section = i; |
1423 |
+ } |
1424 |
+ if (!me->arch.core_plt_section || !me->arch.init_plt_section) { |
1425 |
+- printk("Module doesn't contain .plt or .init.plt sections.\n"); |
1426 |
++ printk("Module %s doesn't contain .plt or .init.plt sections.\n", me->name); |
1427 |
+ return -ENOEXEC; |
1428 |
+ } |
1429 |
+ |
1430 |
+@@ -199,11 +199,16 @@ static uint32_t do_plt_call(void *locati |
1431 |
+ |
1432 |
+ DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location); |
1433 |
+ /* Init, or core PLT? */ |
1434 |
+- if (location >= mod->module_core |
1435 |
+- && location < mod->module_core + mod->core_size) |
1436 |
++ if ((location >= mod->module_core_rx && location < mod->module_core_rx + mod->core_size_rx) || |
1437 |
++ (location >= mod->module_core_rw && location < mod->module_core_rw + mod->core_size_rw)) |
1438 |
+ entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; |
1439 |
+- else |
1440 |
++ else if ((location >= mod->module_init_rx && location < mod->module_init_rx + mod->init_size_rx) || |
1441 |
++ (location >= mod->module_init_rw && location < mod->module_init_rw + mod->init_size_rw)) |
1442 |
+ entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; |
1443 |
++ else { |
1444 |
++ printk(KERN_ERR "%s: invalid R_PPC_REL24 entry found\n", mod->name); |
1445 |
++ return ~0UL; |
1446 |
++ } |
1447 |
+ |
1448 |
+ /* Find this entry, or if that fails, the next avail. entry */ |
1449 |
+ while (entry->jump[0]) { |
1450 |
+diff -urNp linux-2.6.28.8/arch/powerpc/kernel/signal_32.c linux-2.6.28.8/arch/powerpc/kernel/signal_32.c |
1451 |
+--- linux-2.6.28.8/arch/powerpc/kernel/signal_32.c 2009-02-06 16:47:45.000000000 -0500 |
1452 |
++++ linux-2.6.28.8/arch/powerpc/kernel/signal_32.c 2009-02-21 09:37:48.000000000 -0500 |
1453 |
+@@ -857,7 +857,7 @@ int handle_rt_signal32(unsigned long sig |
1454 |
+ /* Save user registers on the stack */ |
1455 |
+ frame = &rt_sf->uc.uc_mcontext; |
1456 |
+ addr = frame; |
1457 |
+- if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { |
1458 |
++ if (vdso32_rt_sigtramp && current->mm->context.vdso_base != ~0UL) { |
1459 |
+ if (save_user_regs(regs, frame, 0, 1)) |
1460 |
+ goto badframe; |
1461 |
+ regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp; |
1462 |
+diff -urNp linux-2.6.28.8/arch/powerpc/kernel/signal_64.c linux-2.6.28.8/arch/powerpc/kernel/signal_64.c |
1463 |
+--- linux-2.6.28.8/arch/powerpc/kernel/signal_64.c 2009-02-06 16:47:45.000000000 -0500 |
1464 |
++++ linux-2.6.28.8/arch/powerpc/kernel/signal_64.c 2009-02-21 09:37:48.000000000 -0500 |
1465 |
+@@ -429,7 +429,7 @@ int handle_rt_signal64(int signr, struct |
1466 |
+ current->thread.fpscr.val = 0; |
1467 |
+ |
1468 |
+ /* Set up to return from userspace. */ |
1469 |
+- if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { |
1470 |
++ if (vdso64_rt_sigtramp && current->mm->context.vdso_base != ~0UL) { |
1471 |
+ regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; |
1472 |
+ } else { |
1473 |
+ err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); |
1474 |
+diff -urNp linux-2.6.28.8/arch/powerpc/kernel/vdso.c linux-2.6.28.8/arch/powerpc/kernel/vdso.c |
1475 |
+--- linux-2.6.28.8/arch/powerpc/kernel/vdso.c 2009-02-06 16:47:45.000000000 -0500 |
1476 |
++++ linux-2.6.28.8/arch/powerpc/kernel/vdso.c 2009-02-21 09:37:48.000000000 -0500 |
1477 |
+@@ -212,7 +212,7 @@ int arch_setup_additional_pages(struct l |
1478 |
+ vdso_base = VDSO32_MBASE; |
1479 |
+ #endif |
1480 |
+ |
1481 |
+- current->mm->context.vdso_base = 0; |
1482 |
++ current->mm->context.vdso_base = ~0UL; |
1483 |
+ |
1484 |
+ /* vDSO has a problem and was disabled, just don't "enable" it for the |
1485 |
+ * process |
1486 |
+@@ -229,7 +229,7 @@ int arch_setup_additional_pages(struct l |
1487 |
+ */ |
1488 |
+ down_write(&mm->mmap_sem); |
1489 |
+ vdso_base = get_unmapped_area(NULL, vdso_base, |
1490 |
+- vdso_pages << PAGE_SHIFT, 0, 0); |
1491 |
++ vdso_pages << PAGE_SHIFT, 0, MAP_PRIVATE | MAP_EXECUTABLE); |
1492 |
+ if (IS_ERR_VALUE(vdso_base)) { |
1493 |
+ rc = vdso_base; |
1494 |
+ goto fail_mmapsem; |
1495 |
+diff -urNp linux-2.6.28.8/arch/powerpc/mm/fault.c linux-2.6.28.8/arch/powerpc/mm/fault.c |
1496 |
+--- linux-2.6.28.8/arch/powerpc/mm/fault.c 2009-02-06 16:47:45.000000000 -0500 |
1497 |
++++ linux-2.6.28.8/arch/powerpc/mm/fault.c 2009-02-21 09:37:48.000000000 -0500 |
1498 |
+@@ -29,6 +29,10 @@ |
1499 |
+ #include <linux/module.h> |
1500 |
+ #include <linux/kprobes.h> |
1501 |
+ #include <linux/kdebug.h> |
1502 |
++#include <linux/slab.h> |
1503 |
++#include <linux/pagemap.h> |
1504 |
++#include <linux/compiler.h> |
1505 |
++#include <linux/unistd.h> |
1506 |
+ |
1507 |
+ #include <asm/page.h> |
1508 |
+ #include <asm/pgtable.h> |
1509 |
+@@ -62,6 +66,363 @@ static inline int notify_page_fault(stru |
1510 |
+ } |
1511 |
+ #endif |
1512 |
+ |
1513 |
++#ifdef CONFIG_PAX_EMUSIGRT |
1514 |
++void pax_syscall_close(struct vm_area_struct *vma) |
1515 |
++{ |
1516 |
++ vma->vm_mm->call_syscall = 0UL; |
1517 |
++} |
1518 |
++ |
1519 |
++static int pax_syscall_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
1520 |
++{ |
1521 |
++ unsigned int *kaddr; |
1522 |
++ |
1523 |
++ vmf->page = alloc_page(GFP_HIGHUSER); |
1524 |
++ if (!vmf->page) |
1525 |
++ return VM_FAULT_OOM; |
1526 |
++ |
1527 |
++ kaddr = kmap(vmf->page); |
1528 |
++ memset(kaddr, 0, PAGE_SIZE); |
1529 |
++ kaddr[0] = 0x44000002U; /* sc */ |
1530 |
++ __flush_dcache_icache(kaddr); |
1531 |
++ kunmap(vmf->page); |
1532 |
++ return VM_FAULT_MAJOR; |
1533 |
++} |
1534 |
++ |
1535 |
++static struct vm_operations_struct pax_vm_ops = { |
1536 |
++ .close = pax_syscall_close, |
1537 |
++ .fault = pax_syscall_fault |
1538 |
++}; |
1539 |
++ |
1540 |
++static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) |
1541 |
++{ |
1542 |
++ int ret; |
1543 |
++ |
1544 |
++ vma->vm_mm = current->mm; |
1545 |
++ vma->vm_start = addr; |
1546 |
++ vma->vm_end = addr + PAGE_SIZE; |
1547 |
++ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC; |
1548 |
++ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
1549 |
++ vma->vm_ops = &pax_vm_ops; |
1550 |
++ |
1551 |
++ ret = insert_vm_struct(current->mm, vma); |
1552 |
++ if (ret) |
1553 |
++ return ret; |
1554 |
++ |
1555 |
++ ++current->mm->total_vm; |
1556 |
++ return 0; |
1557 |
++} |
1558 |
++#endif |
1559 |
++ |
1560 |
++#ifdef CONFIG_PAX_PAGEEXEC |
1561 |
++/* |
1562 |
++ * PaX: decide what to do with offenders (regs->nip = fault address) |
1563 |
++ * |
1564 |
++ * returns 1 when task should be killed |
1565 |
++ * 2 when patched GOT trampoline was detected |
1566 |
++ * 3 when patched PLT trampoline was detected |
1567 |
++ * 4 when unpatched PLT trampoline was detected |
1568 |
++ * 5 when sigreturn trampoline was detected |
1569 |
++ * 6 when rt_sigreturn trampoline was detected |
1570 |
++ */ |
1571 |
++static int pax_handle_fetch_fault(struct pt_regs *regs) |
1572 |
++{ |
1573 |
++ |
1574 |
++#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT) |
1575 |
++ int err; |
1576 |
++#endif |
1577 |
++ |
1578 |
++#ifdef CONFIG_PAX_EMUPLT |
1579 |
++ do { /* PaX: patched GOT emulation */ |
1580 |
++ unsigned int blrl; |
1581 |
++ |
1582 |
++ err = get_user(blrl, (unsigned int *)regs->nip); |
1583 |
++ |
1584 |
++ if (!err && blrl == 0x4E800021U) { |
1585 |
++ unsigned long temp = regs->nip; |
1586 |
++ |
1587 |
++ regs->nip = regs->link & 0xFFFFFFFCUL; |
1588 |
++ regs->link = temp + 4UL; |
1589 |
++ return 2; |
1590 |
++ } |
1591 |
++ } while (0); |
1592 |
++ |
1593 |
++ do { /* PaX: patched PLT emulation #1 */ |
1594 |
++ unsigned int b; |
1595 |
++ |
1596 |
++ err = get_user(b, (unsigned int *)regs->nip); |
1597 |
++ |
1598 |
++ if (!err && (b & 0xFC000003U) == 0x48000000U) { |
1599 |
++ regs->nip += (((b | 0xFC000000UL) ^ 0x02000000UL) + 0x02000000UL); |
1600 |
++ return 3; |
1601 |
++ } |
1602 |
++ } while (0); |
1603 |
++ |
1604 |
++ do { /* PaX: unpatched PLT emulation #1 */ |
1605 |
++ unsigned int li, b; |
1606 |
++ |
1607 |
++ err = get_user(li, (unsigned int *)regs->nip); |
1608 |
++ err |= get_user(b, (unsigned int *)(regs->nip+4)); |
1609 |
++ |
1610 |
++ if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) { |
1611 |
++ unsigned int rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr; |
1612 |
++ unsigned long addr = b | 0xFC000000UL; |
1613 |
++ |
1614 |
++ addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL); |
1615 |
++ err = get_user(rlwinm, (unsigned int *)addr); |
1616 |
++ err |= get_user(add, (unsigned int *)(addr+4)); |
1617 |
++ err |= get_user(li2, (unsigned int *)(addr+8)); |
1618 |
++ err |= get_user(addis2, (unsigned int *)(addr+12)); |
1619 |
++ err |= get_user(mtctr, (unsigned int *)(addr+16)); |
1620 |
++ err |= get_user(li3, (unsigned int *)(addr+20)); |
1621 |
++ err |= get_user(addis3, (unsigned int *)(addr+24)); |
1622 |
++ err |= get_user(bctr, (unsigned int *)(addr+28)); |
1623 |
++ |
1624 |
++ if (err) |
1625 |
++ break; |
1626 |
++ |
1627 |
++ if (rlwinm == 0x556C083CU && |
1628 |
++ add == 0x7D6C5A14U && |
1629 |
++ (li2 & 0xFFFF0000U) == 0x39800000U && |
1630 |
++ (addis2 & 0xFFFF0000U) == 0x3D8C0000U && |
1631 |
++ mtctr == 0x7D8903A6U && |
1632 |
++ (li3 & 0xFFFF0000U) == 0x39800000U && |
1633 |
++ (addis3 & 0xFFFF0000U) == 0x3D8C0000U && |
1634 |
++ bctr == 0x4E800420U) |
1635 |
++ { |
1636 |
++ regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); |
1637 |
++ regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); |
1638 |
++ regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16; |
1639 |
++ regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); |
1640 |
++ regs->ctr += (addis2 & 0xFFFFU) << 16; |
1641 |
++ regs->nip = regs->ctr; |
1642 |
++ return 4; |
1643 |
++ } |
1644 |
++ } |
1645 |
++ } while (0); |
1646 |
++ |
1647 |
++#if 0 |
1648 |
++ do { /* PaX: unpatched PLT emulation #2 */ |
1649 |
++ unsigned int lis, lwzu, b, bctr; |
1650 |
++ |
1651 |
++ err = get_user(lis, (unsigned int *)regs->nip); |
1652 |
++ err |= get_user(lwzu, (unsigned int *)(regs->nip+4)); |
1653 |
++ err |= get_user(b, (unsigned int *)(regs->nip+8)); |
1654 |
++ err |= get_user(bctr, (unsigned int *)(regs->nip+12)); |
1655 |
++ |
1656 |
++ if (err) |
1657 |
++ break; |
1658 |
++ |
1659 |
++ if ((lis & 0xFFFF0000U) == 0x39600000U && |
1660 |
++ (lwzu & 0xU) == 0xU && |
1661 |
++ (b & 0xFC000003U) == 0x48000000U && |
1662 |
++ bctr == 0x4E800420U) |
1663 |
++ { |
1664 |
++ unsigned int addis, addi, rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr; |
1665 |
++ unsigned long addr = b | 0xFC000000UL; |
1666 |
++ |
1667 |
++ addr = regs->nip + 12 + ((addr ^ 0x02000000UL) + 0x02000000UL); |
1668 |
++ err = get_user(addis, (unsigned int *)addr); |
1669 |
++ err |= get_user(addi, (unsigned int *)(addr+4)); |
1670 |
++ err |= get_user(rlwinm, (unsigned int *)(addr+8)); |
1671 |
++ err |= get_user(add, (unsigned int *)(addr+12)); |
1672 |
++ err |= get_user(li2, (unsigned int *)(addr+16)); |
1673 |
++ err |= get_user(addis2, (unsigned int *)(addr+20)); |
1674 |
++ err |= get_user(mtctr, (unsigned int *)(addr+24)); |
1675 |
++ err |= get_user(li3, (unsigned int *)(addr+28)); |
1676 |
++ err |= get_user(addis3, (unsigned int *)(addr+32)); |
1677 |
++ err |= get_user(bctr, (unsigned int *)(addr+36)); |
1678 |
++ |
1679 |
++ if (err) |
1680 |
++ break; |
1681 |
++ |
1682 |
++ if ((addis & 0xFFFF0000U) == 0x3D6B0000U && |
1683 |
++ (addi & 0xFFFF0000U) == 0x396B0000U && |
1684 |
++ rlwinm == 0x556C083CU && |
1685 |
++ add == 0x7D6C5A14U && |
1686 |
++ (li2 & 0xFFFF0000U) == 0x39800000U && |
1687 |
++ (addis2 & 0xFFFF0000U) == 0x3D8C0000U && |
1688 |
++ mtctr == 0x7D8903A6U && |
1689 |
++ (li3 & 0xFFFF0000U) == 0x39800000U && |
1690 |
++ (addis3 & 0xFFFF0000U) == 0x3D8C0000U && |
1691 |
++ bctr == 0x4E800420U) |
1692 |
++ { |
1693 |
++ regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); |
1694 |
++ regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); |
1695 |
++ regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16; |
1696 |
++ regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); |
1697 |
++ regs->ctr += (addis2 & 0xFFFFU) << 16; |
1698 |
++ regs->nip = regs->ctr; |
1699 |
++ return 4; |
1700 |
++ } |
1701 |
++ } |
1702 |
++ } while (0); |
1703 |
++#endif |
1704 |
++ |
1705 |
++ do { /* PaX: unpatched PLT emulation #3 */ |
1706 |
++ unsigned int li, b; |
1707 |
++ |
1708 |
++ err = get_user(li, (unsigned int *)regs->nip); |
1709 |
++ err |= get_user(b, (unsigned int *)(regs->nip+4)); |
1710 |
++ |
1711 |
++ if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) { |
1712 |
++ unsigned int addis, lwz, mtctr, bctr; |
1713 |
++ unsigned long addr = b | 0xFC000000UL; |
1714 |
++ |
1715 |
++ addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL); |
1716 |
++ err = get_user(addis, (unsigned int *)addr); |
1717 |
++ err |= get_user(lwz, (unsigned int *)(addr+4)); |
1718 |
++ err |= get_user(mtctr, (unsigned int *)(addr+8)); |
1719 |
++ err |= get_user(bctr, (unsigned int *)(addr+12)); |
1720 |
++ |
1721 |
++ if (err) |
1722 |
++ break; |
1723 |
++ |
1724 |
++ if ((addis & 0xFFFF0000U) == 0x3D6B0000U && |
1725 |
++ (lwz & 0xFFFF0000U) == 0x816B0000U && |
1726 |
++ mtctr == 0x7D6903A6U && |
1727 |
++ bctr == 0x4E800420U) |
1728 |
++ { |
1729 |
++ unsigned int r11; |
1730 |
++ |
1731 |
++ addr = (addis << 16) + (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); |
1732 |
++ addr += (((lwz | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); |
1733 |
++ |
1734 |
++ err = get_user(r11, (unsigned int *)addr); |
1735 |
++ if (err) |
1736 |
++ break; |
1737 |
++ |
1738 |
++ regs->gpr[PT_R11] = r11; |
1739 |
++ regs->ctr = r11; |
1740 |
++ regs->nip = r11; |
1741 |
++ return 4; |
1742 |
++ } |
1743 |
++ } |
1744 |
++ } while (0); |
1745 |
++#endif |
1746 |
++ |
1747 |
++#ifdef CONFIG_PAX_EMUSIGRT |
1748 |
++ do { /* PaX: sigreturn emulation */ |
1749 |
++ unsigned int li, sc; |
1750 |
++ |
1751 |
++ err = get_user(li, (unsigned int *)regs->nip); |
1752 |
++ err |= get_user(sc, (unsigned int *)(regs->nip+4)); |
1753 |
++ |
1754 |
++ if (!err && li == 0x38000000U + __NR_sigreturn && sc == 0x44000002U) { |
1755 |
++ struct vm_area_struct *vma; |
1756 |
++ unsigned long call_syscall; |
1757 |
++ |
1758 |
++ down_read(¤t->mm->mmap_sem); |
1759 |
++ call_syscall = current->mm->call_syscall; |
1760 |
++ up_read(¤t->mm->mmap_sem); |
1761 |
++ if (likely(call_syscall)) |
1762 |
++ goto emulate; |
1763 |
++ |
1764 |
++ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
1765 |
++ |
1766 |
++ down_write(¤t->mm->mmap_sem); |
1767 |
++ if (current->mm->call_syscall) { |
1768 |
++ call_syscall = current->mm->call_syscall; |
1769 |
++ up_write(¤t->mm->mmap_sem); |
1770 |
++ if (vma) |
1771 |
++ kmem_cache_free(vm_area_cachep, vma); |
1772 |
++ goto emulate; |
1773 |
++ } |
1774 |
++ |
1775 |
++ call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE); |
1776 |
++ if (!vma || (call_syscall & ~PAGE_MASK)) { |
1777 |
++ up_write(¤t->mm->mmap_sem); |
1778 |
++ if (vma) |
1779 |
++ kmem_cache_free(vm_area_cachep, vma); |
1780 |
++ return 1; |
1781 |
++ } |
1782 |
++ |
1783 |
++ if (pax_insert_vma(vma, call_syscall)) { |
1784 |
++ up_write(¤t->mm->mmap_sem); |
1785 |
++ kmem_cache_free(vm_area_cachep, vma); |
1786 |
++ return 1; |
1787 |
++ } |
1788 |
++ |
1789 |
++ current->mm->call_syscall = call_syscall; |
1790 |
++ up_write(¤t->mm->mmap_sem); |
1791 |
++ |
1792 |
++emulate: |
1793 |
++ regs->gpr[PT_R0] = __NR_sigreturn; |
1794 |
++ regs->nip = call_syscall; |
1795 |
++ return 5; |
1796 |
++ } |
1797 |
++ } while (0); |
1798 |
++ |
1799 |
++ do { /* PaX: rt_sigreturn emulation */ |
1800 |
++ unsigned int li, sc; |
1801 |
++ |
1802 |
++ err = get_user(li, (unsigned int *)regs->nip); |
1803 |
++ err |= get_user(sc, (unsigned int *)(regs->nip+4)); |
1804 |
++ |
1805 |
++ if (!err && li == 0x38000000U + __NR_rt_sigreturn && sc == 0x44000002U) { |
1806 |
++ struct vm_area_struct *vma; |
1807 |
++ unsigned int call_syscall; |
1808 |
++ |
1809 |
++ down_read(¤t->mm->mmap_sem); |
1810 |
++ call_syscall = current->mm->call_syscall; |
1811 |
++ up_read(¤t->mm->mmap_sem); |
1812 |
++ if (likely(call_syscall)) |
1813 |
++ goto rt_emulate; |
1814 |
++ |
1815 |
++ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
1816 |
++ |
1817 |
++ down_write(¤t->mm->mmap_sem); |
1818 |
++ if (current->mm->call_syscall) { |
1819 |
++ call_syscall = current->mm->call_syscall; |
1820 |
++ up_write(¤t->mm->mmap_sem); |
1821 |
++ if (vma) |
1822 |
++ kmem_cache_free(vm_area_cachep, vma); |
1823 |
++ goto rt_emulate; |
1824 |
++ } |
1825 |
++ |
1826 |
++ call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE); |
1827 |
++ if (!vma || (call_syscall & ~PAGE_MASK)) { |
1828 |
++ up_write(¤t->mm->mmap_sem); |
1829 |
++ if (vma) |
1830 |
++ kmem_cache_free(vm_area_cachep, vma); |
1831 |
++ return 1; |
1832 |
++ } |
1833 |
++ |
1834 |
++ if (pax_insert_vma(vma, call_syscall)) { |
1835 |
++ up_write(¤t->mm->mmap_sem); |
1836 |
++ kmem_cache_free(vm_area_cachep, vma); |
1837 |
++ return 1; |
1838 |
++ } |
1839 |
++ |
1840 |
++ current->mm->call_syscall = call_syscall; |
1841 |
++ up_write(¤t->mm->mmap_sem); |
1842 |
++ |
1843 |
++rt_emulate: |
1844 |
++ regs->gpr[PT_R0] = __NR_rt_sigreturn; |
1845 |
++ regs->nip = call_syscall; |
1846 |
++ return 6; |
1847 |
++ } |
1848 |
++ } while (0); |
1849 |
++#endif |
1850 |
++ |
1851 |
++ return 1; |
1852 |
++} |
1853 |
++ |
1854 |
++void pax_report_insns(void *pc, void *sp) |
1855 |
++{ |
1856 |
++ unsigned long i; |
1857 |
++ |
1858 |
++ printk(KERN_ERR "PAX: bytes at PC: "); |
1859 |
++ for (i = 0; i < 5; i++) { |
1860 |
++ unsigned int c; |
1861 |
++ if (get_user(c, (unsigned int *)pc+i)) |
1862 |
++ printk(KERN_CONT "???????? "); |
1863 |
++ else |
1864 |
++ printk(KERN_CONT "%08x ", c); |
1865 |
++ } |
1866 |
++ printk("\n"); |
1867 |
++} |
1868 |
++#endif |
1869 |
++ |
1870 |
+ /* |
1871 |
+ * Check whether the instruction at regs->nip is a store using |
1872 |
+ * an update addressing form which will update r1. |
1873 |
+@@ -132,7 +493,7 @@ int __kprobes do_page_fault(struct pt_re |
1874 |
+ * indicate errors in DSISR but can validly be set in SRR1. |
1875 |
+ */ |
1876 |
+ if (trap == 0x400) |
1877 |
+- error_code &= 0x48200000; |
1878 |
++ error_code &= 0x58200000; |
1879 |
+ else |
1880 |
+ is_write = error_code & DSISR_ISSTORE; |
1881 |
+ #else |
1882 |
+@@ -331,6 +692,37 @@ bad_area: |
1883 |
+ bad_area_nosemaphore: |
1884 |
+ /* User mode accesses cause a SIGSEGV */ |
1885 |
+ if (user_mode(regs)) { |
1886 |
++ |
1887 |
++#ifdef CONFIG_PAX_PAGEEXEC |
1888 |
++ if (mm->pax_flags & MF_PAX_PAGEEXEC) { |
1889 |
++#ifdef CONFIG_PPC64 |
1890 |
++ if (is_exec && (error_code & DSISR_PROTFAULT)) { |
1891 |
++#else |
1892 |
++ if (is_exec && regs->nip == address) { |
1893 |
++#endif |
1894 |
++ switch (pax_handle_fetch_fault(regs)) { |
1895 |
++ |
1896 |
++#ifdef CONFIG_PAX_EMUPLT |
1897 |
++ case 2: |
1898 |
++ case 3: |
1899 |
++ case 4: |
1900 |
++ return 0; |
1901 |
++#endif |
1902 |
++ |
1903 |
++#ifdef CONFIG_PAX_EMUSIGRT |
1904 |
++ case 5: |
1905 |
++ case 6: |
1906 |
++ return 0; |
1907 |
++#endif |
1908 |
++ |
1909 |
++ } |
1910 |
++ |
1911 |
++ pax_report_fault(regs, (void *)regs->nip, (void *)regs->gpr[PT_R1]); |
1912 |
++ do_group_exit(SIGKILL); |
1913 |
++ } |
1914 |
++ } |
1915 |
++#endif |
1916 |
++ |
1917 |
+ _exception(SIGSEGV, regs, code, address); |
1918 |
+ return 0; |
1919 |
+ } |
1920 |
+diff -urNp linux-2.6.28.8/arch/powerpc/mm/mmap.c linux-2.6.28.8/arch/powerpc/mm/mmap.c |
1921 |
+--- linux-2.6.28.8/arch/powerpc/mm/mmap.c 2009-02-06 16:47:45.000000000 -0500 |
1922 |
++++ linux-2.6.28.8/arch/powerpc/mm/mmap.c 2009-02-21 09:37:48.000000000 -0500 |
1923 |
+@@ -75,10 +75,22 @@ void arch_pick_mmap_layout(struct mm_str |
1924 |
+ */ |
1925 |
+ if (mmap_is_legacy()) { |
1926 |
+ mm->mmap_base = TASK_UNMAPPED_BASE; |
1927 |
++ |
1928 |
++#ifdef CONFIG_PAX_RANDMMAP |
1929 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
1930 |
++ mm->mmap_base += mm->delta_mmap; |
1931 |
++#endif |
1932 |
++ |
1933 |
+ mm->get_unmapped_area = arch_get_unmapped_area; |
1934 |
+ mm->unmap_area = arch_unmap_area; |
1935 |
+ } else { |
1936 |
+ mm->mmap_base = mmap_base(); |
1937 |
++ |
1938 |
++#ifdef CONFIG_PAX_RANDMMAP |
1939 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
1940 |
++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack; |
1941 |
++#endif |
1942 |
++ |
1943 |
+ mm->get_unmapped_area = arch_get_unmapped_area_topdown; |
1944 |
+ mm->unmap_area = arch_unmap_area_topdown; |
1945 |
+ } |
1946 |
+diff -urNp linux-2.6.28.8/arch/s390/include/asm/kmap_types.h linux-2.6.28.8/arch/s390/include/asm/kmap_types.h |
1947 |
+--- linux-2.6.28.8/arch/s390/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
1948 |
++++ linux-2.6.28.8/arch/s390/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
1949 |
+@@ -16,6 +16,7 @@ enum km_type { |
1950 |
+ KM_IRQ1, |
1951 |
+ KM_SOFTIRQ0, |
1952 |
+ KM_SOFTIRQ1, |
1953 |
++ KM_CLEARPAGE, |
1954 |
+ KM_TYPE_NR |
1955 |
+ }; |
1956 |
+ |
1957 |
+diff -urNp linux-2.6.28.8/arch/s390/kernel/module.c linux-2.6.28.8/arch/s390/kernel/module.c |
1958 |
+--- linux-2.6.28.8/arch/s390/kernel/module.c 2009-02-06 16:47:45.000000000 -0500 |
1959 |
++++ linux-2.6.28.8/arch/s390/kernel/module.c 2009-02-21 09:37:48.000000000 -0500 |
1960 |
+@@ -166,11 +166,11 @@ module_frob_arch_sections(Elf_Ehdr *hdr, |
1961 |
+ |
1962 |
+ /* Increase core size by size of got & plt and set start |
1963 |
+ offsets for got and plt. */ |
1964 |
+- me->core_size = ALIGN(me->core_size, 4); |
1965 |
+- me->arch.got_offset = me->core_size; |
1966 |
+- me->core_size += me->arch.got_size; |
1967 |
+- me->arch.plt_offset = me->core_size; |
1968 |
+- me->core_size += me->arch.plt_size; |
1969 |
++ me->core_size_rw = ALIGN(me->core_size_rw, 4); |
1970 |
++ me->arch.got_offset = me->core_size_rw; |
1971 |
++ me->core_size_rw += me->arch.got_size; |
1972 |
++ me->arch.plt_offset = me->core_size_rx; |
1973 |
++ me->core_size_rx += me->arch.plt_size; |
1974 |
+ return 0; |
1975 |
+ } |
1976 |
+ |
1977 |
+@@ -256,7 +256,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base |
1978 |
+ if (info->got_initialized == 0) { |
1979 |
+ Elf_Addr *gotent; |
1980 |
+ |
1981 |
+- gotent = me->module_core + me->arch.got_offset + |
1982 |
++ gotent = me->module_core_rw + me->arch.got_offset + |
1983 |
+ info->got_offset; |
1984 |
+ *gotent = val; |
1985 |
+ info->got_initialized = 1; |
1986 |
+@@ -280,7 +280,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base |
1987 |
+ else if (r_type == R_390_GOTENT || |
1988 |
+ r_type == R_390_GOTPLTENT) |
1989 |
+ *(unsigned int *) loc = |
1990 |
+- (val + (Elf_Addr) me->module_core - loc) >> 1; |
1991 |
++ (val + (Elf_Addr) me->module_core_rw - loc) >> 1; |
1992 |
+ else if (r_type == R_390_GOT64 || |
1993 |
+ r_type == R_390_GOTPLT64) |
1994 |
+ *(unsigned long *) loc = val; |
1995 |
+@@ -294,7 +294,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base |
1996 |
+ case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */ |
1997 |
+ if (info->plt_initialized == 0) { |
1998 |
+ unsigned int *ip; |
1999 |
+- ip = me->module_core + me->arch.plt_offset + |
2000 |
++ ip = me->module_core_rx + me->arch.plt_offset + |
2001 |
+ info->plt_offset; |
2002 |
+ #ifndef CONFIG_64BIT |
2003 |
+ ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */ |
2004 |
+@@ -316,7 +316,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base |
2005 |
+ val = me->arch.plt_offset - me->arch.got_offset + |
2006 |
+ info->plt_offset + rela->r_addend; |
2007 |
+ else |
2008 |
+- val = (Elf_Addr) me->module_core + |
2009 |
++ val = (Elf_Addr) me->module_core_rx + |
2010 |
+ me->arch.plt_offset + info->plt_offset + |
2011 |
+ rela->r_addend - loc; |
2012 |
+ if (r_type == R_390_PLT16DBL) |
2013 |
+@@ -336,7 +336,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base |
2014 |
+ case R_390_GOTOFF32: /* 32 bit offset to GOT. */ |
2015 |
+ case R_390_GOTOFF64: /* 64 bit offset to GOT. */ |
2016 |
+ val = val + rela->r_addend - |
2017 |
+- ((Elf_Addr) me->module_core + me->arch.got_offset); |
2018 |
++ ((Elf_Addr) me->module_core_rw + me->arch.got_offset); |
2019 |
+ if (r_type == R_390_GOTOFF16) |
2020 |
+ *(unsigned short *) loc = val; |
2021 |
+ else if (r_type == R_390_GOTOFF32) |
2022 |
+@@ -346,7 +346,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base |
2023 |
+ break; |
2024 |
+ case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */ |
2025 |
+ case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */ |
2026 |
+- val = (Elf_Addr) me->module_core + me->arch.got_offset + |
2027 |
++ val = (Elf_Addr) me->module_core_rw + me->arch.got_offset + |
2028 |
+ rela->r_addend - loc; |
2029 |
+ if (r_type == R_390_GOTPC) |
2030 |
+ *(unsigned int *) loc = val; |
2031 |
+diff -urNp linux-2.6.28.8/arch/sh/include/asm/kmap_types.h linux-2.6.28.8/arch/sh/include/asm/kmap_types.h |
2032 |
+--- linux-2.6.28.8/arch/sh/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
2033 |
++++ linux-2.6.28.8/arch/sh/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
2034 |
+@@ -24,7 +24,8 @@ D(9) KM_IRQ0, |
2035 |
+ D(10) KM_IRQ1, |
2036 |
+ D(11) KM_SOFTIRQ0, |
2037 |
+ D(12) KM_SOFTIRQ1, |
2038 |
+-D(13) KM_TYPE_NR |
2039 |
++D(13) KM_CLEARPAGE, |
2040 |
++D(14) KM_TYPE_NR |
2041 |
+ }; |
2042 |
+ |
2043 |
+ #undef D |
2044 |
+diff -urNp linux-2.6.28.8/arch/sparc/include/asm/elf_32.h linux-2.6.28.8/arch/sparc/include/asm/elf_32.h |
2045 |
+--- linux-2.6.28.8/arch/sparc/include/asm/elf_32.h 2009-02-06 16:47:45.000000000 -0500 |
2046 |
++++ linux-2.6.28.8/arch/sparc/include/asm/elf_32.h 2009-02-21 09:37:48.000000000 -0500 |
2047 |
+@@ -116,6 +116,13 @@ typedef struct { |
2048 |
+ |
2049 |
+ #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE) |
2050 |
+ |
2051 |
++#ifdef CONFIG_PAX_ASLR |
2052 |
++#define PAX_ELF_ET_DYN_BASE 0x10000UL |
2053 |
++ |
2054 |
++#define PAX_DELTA_MMAP_LEN 16 |
2055 |
++#define PAX_DELTA_STACK_LEN 16 |
2056 |
++#endif |
2057 |
++ |
2058 |
+ /* This yields a mask that user programs can use to figure out what |
2059 |
+ instruction set this cpu supports. This can NOT be done in userspace |
2060 |
+ on Sparc. */ |
2061 |
+diff -urNp linux-2.6.28.8/arch/sparc/include/asm/elf_64.h linux-2.6.28.8/arch/sparc/include/asm/elf_64.h |
2062 |
+--- linux-2.6.28.8/arch/sparc/include/asm/elf_64.h 2009-02-06 16:47:45.000000000 -0500 |
2063 |
++++ linux-2.6.28.8/arch/sparc/include/asm/elf_64.h 2009-02-21 09:37:48.000000000 -0500 |
2064 |
+@@ -163,6 +163,12 @@ typedef struct { |
2065 |
+ #define ELF_ET_DYN_BASE 0x0000010000000000UL |
2066 |
+ #define COMPAT_ELF_ET_DYN_BASE 0x0000000070000000UL |
2067 |
+ |
2068 |
++#ifdef CONFIG_PAX_ASLR |
2069 |
++#define PAX_ELF_ET_DYN_BASE (test_thread_flag(TIF_32BIT) ? 0x10000UL : 0x100000UL) |
2070 |
++ |
2071 |
++#define PAX_DELTA_MMAP_LEN (test_thread_flag(TIF_32BIT) ? 14 : 28 ) |
2072 |
++#define PAX_DELTA_STACK_LEN (test_thread_flag(TIF_32BIT) ? 15 : 29 ) |
2073 |
++#endif |
2074 |
+ |
2075 |
+ /* This yields a mask that user programs can use to figure out what |
2076 |
+ instruction set this cpu supports. */ |
2077 |
+diff -urNp linux-2.6.28.8/arch/sparc/include/asm/kmap_types.h linux-2.6.28.8/arch/sparc/include/asm/kmap_types.h |
2078 |
+--- linux-2.6.28.8/arch/sparc/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
2079 |
++++ linux-2.6.28.8/arch/sparc/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
2080 |
+@@ -19,6 +19,7 @@ enum km_type { |
2081 |
+ KM_IRQ1, |
2082 |
+ KM_SOFTIRQ0, |
2083 |
+ KM_SOFTIRQ1, |
2084 |
++ KM_CLEARPAGE, |
2085 |
+ KM_TYPE_NR |
2086 |
+ }; |
2087 |
+ |
2088 |
+diff -urNp linux-2.6.28.8/arch/sparc/include/asm/pgtable_32.h linux-2.6.28.8/arch/sparc/include/asm/pgtable_32.h |
2089 |
+--- linux-2.6.28.8/arch/sparc/include/asm/pgtable_32.h 2009-02-06 16:47:45.000000000 -0500 |
2090 |
++++ linux-2.6.28.8/arch/sparc/include/asm/pgtable_32.h 2009-02-21 09:37:48.000000000 -0500 |
2091 |
+@@ -43,6 +43,13 @@ BTFIXUPDEF_SIMM13(user_ptrs_per_pgd) |
2092 |
+ BTFIXUPDEF_INT(page_none) |
2093 |
+ BTFIXUPDEF_INT(page_copy) |
2094 |
+ BTFIXUPDEF_INT(page_readonly) |
2095 |
++ |
2096 |
++#ifdef CONFIG_PAX_PAGEEXEC |
2097 |
++BTFIXUPDEF_INT(page_shared_noexec) |
2098 |
++BTFIXUPDEF_INT(page_copy_noexec) |
2099 |
++BTFIXUPDEF_INT(page_readonly_noexec) |
2100 |
++#endif |
2101 |
++ |
2102 |
+ BTFIXUPDEF_INT(page_kernel) |
2103 |
+ |
2104 |
+ #define PMD_SHIFT SUN4C_PMD_SHIFT |
2105 |
+@@ -64,6 +71,16 @@ extern pgprot_t PAGE_SHARED; |
2106 |
+ #define PAGE_COPY __pgprot(BTFIXUP_INT(page_copy)) |
2107 |
+ #define PAGE_READONLY __pgprot(BTFIXUP_INT(page_readonly)) |
2108 |
+ |
2109 |
++#ifdef CONFIG_PAX_PAGEEXEC |
2110 |
++extern pgprot_t PAGE_SHARED_NOEXEC; |
2111 |
++# define PAGE_COPY_NOEXEC __pgprot(BTFIXUP_INT(page_copy_noexec)) |
2112 |
++# define PAGE_READONLY_NOEXEC __pgprot(BTFIXUP_INT(page_readonly_noexec)) |
2113 |
++#else |
2114 |
++# define PAGE_SHARED_NOEXEC PAGE_SHARED |
2115 |
++# define PAGE_COPY_NOEXEC PAGE_COPY |
2116 |
++# define PAGE_READONLY_NOEXEC PAGE_READONLY |
2117 |
++#endif |
2118 |
++ |
2119 |
+ extern unsigned long page_kernel; |
2120 |
+ |
2121 |
+ #ifdef MODULE |
2122 |
+diff -urNp linux-2.6.28.8/arch/sparc/include/asm/pgtsrmmu.h linux-2.6.28.8/arch/sparc/include/asm/pgtsrmmu.h |
2123 |
+--- linux-2.6.28.8/arch/sparc/include/asm/pgtsrmmu.h 2009-02-06 16:47:45.000000000 -0500 |
2124 |
++++ linux-2.6.28.8/arch/sparc/include/asm/pgtsrmmu.h 2009-02-21 09:37:48.000000000 -0500 |
2125 |
+@@ -115,6 +115,13 @@ |
2126 |
+ SRMMU_EXEC | SRMMU_REF) |
2127 |
+ #define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \ |
2128 |
+ SRMMU_EXEC | SRMMU_REF) |
2129 |
++ |
2130 |
++#ifdef CONFIG_PAX_PAGEEXEC |
2131 |
++#define SRMMU_PAGE_SHARED_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_WRITE | SRMMU_REF) |
2132 |
++#define SRMMU_PAGE_COPY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_REF) |
2133 |
++#define SRMMU_PAGE_RDONLY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_REF) |
2134 |
++#endif |
2135 |
++ |
2136 |
+ #define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \ |
2137 |
+ SRMMU_DIRTY | SRMMU_REF) |
2138 |
+ |
2139 |
+diff -urNp linux-2.6.28.8/arch/sparc/kernel/sys_sparc.c linux-2.6.28.8/arch/sparc/kernel/sys_sparc.c |
2140 |
+--- linux-2.6.28.8/arch/sparc/kernel/sys_sparc.c 2009-02-06 16:47:45.000000000 -0500 |
2141 |
++++ linux-2.6.28.8/arch/sparc/kernel/sys_sparc.c 2009-02-21 09:37:48.000000000 -0500 |
2142 |
+@@ -56,7 +56,7 @@ unsigned long arch_get_unmapped_area(str |
2143 |
+ if (ARCH_SUN4C && len > 0x20000000) |
2144 |
+ return -ENOMEM; |
2145 |
+ if (!addr) |
2146 |
+- addr = TASK_UNMAPPED_BASE; |
2147 |
++ addr = current->mm->mmap_base; |
2148 |
+ |
2149 |
+ if (flags & MAP_SHARED) |
2150 |
+ addr = COLOUR_ALIGN(addr); |
2151 |
+diff -urNp linux-2.6.28.8/arch/sparc/Makefile linux-2.6.28.8/arch/sparc/Makefile |
2152 |
+--- linux-2.6.28.8/arch/sparc/Makefile 2009-02-06 16:47:45.000000000 -0500 |
2153 |
++++ linux-2.6.28.8/arch/sparc/Makefile 2009-02-21 09:37:48.000000000 -0500 |
2154 |
+@@ -37,7 +37,7 @@ drivers-$(CONFIG_OPROFILE) += arch/sparc |
2155 |
+ # Renaming is done to avoid confusing pattern matching rules in 2.5.45 (multy-) |
2156 |
+ INIT_Y := $(patsubst %/, %/built-in.o, $(init-y)) |
2157 |
+ CORE_Y := $(core-y) |
2158 |
+-CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ |
2159 |
++CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/ |
2160 |
+ CORE_Y := $(patsubst %/, %/built-in.o, $(CORE_Y)) |
2161 |
+ DRIVERS_Y := $(patsubst %/, %/built-in.o, $(drivers-y)) |
2162 |
+ NET_Y := $(patsubst %/, %/built-in.o, $(net-y)) |
2163 |
+diff -urNp linux-2.6.28.8/arch/sparc/mm/fault.c linux-2.6.28.8/arch/sparc/mm/fault.c |
2164 |
+--- linux-2.6.28.8/arch/sparc/mm/fault.c 2009-02-06 16:47:45.000000000 -0500 |
2165 |
++++ linux-2.6.28.8/arch/sparc/mm/fault.c 2009-02-21 09:37:48.000000000 -0500 |
2166 |
+@@ -21,6 +21,9 @@ |
2167 |
+ #include <linux/interrupt.h> |
2168 |
+ #include <linux/module.h> |
2169 |
+ #include <linux/kdebug.h> |
2170 |
++#include <linux/slab.h> |
2171 |
++#include <linux/pagemap.h> |
2172 |
++#include <linux/compiler.h> |
2173 |
+ |
2174 |
+ #include <asm/system.h> |
2175 |
+ #include <asm/page.h> |
2176 |
+@@ -167,6 +170,249 @@ static unsigned long compute_si_addr(str |
2177 |
+ return safe_compute_effective_address(regs, insn); |
2178 |
+ } |
2179 |
+ |
2180 |
++#ifdef CONFIG_PAX_PAGEEXEC |
2181 |
++void pax_emuplt_close(struct vm_area_struct *vma) |
2182 |
++{ |
2183 |
++ vma->vm_mm->call_dl_resolve = 0UL; |
2184 |
++} |
2185 |
++ |
2186 |
++static int pax_emuplt_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
2187 |
++{ |
2188 |
++ unsigned int *kaddr; |
2189 |
++ |
2190 |
++ vmf->page = alloc_page(GFP_HIGHUSER); |
2191 |
++ if (!vmf->page) |
2192 |
++ return VM_FAULT_OOM; |
2193 |
++ |
2194 |
++ kaddr = kmap(vmf->page); |
2195 |
++ memset(kaddr, 0, PAGE_SIZE); |
2196 |
++ kaddr[0] = 0x9DE3BFA8U; /* save */ |
2197 |
++ flush_dcache_page(vmf->page); |
2198 |
++ kunmap(vmf->page); |
2199 |
++ return VM_FAULT_MAJOR; |
2200 |
++} |
2201 |
++ |
2202 |
++static struct vm_operations_struct pax_vm_ops = { |
2203 |
++ .close = pax_emuplt_close, |
2204 |
++ .fault = pax_emuplt_fault |
2205 |
++}; |
2206 |
++ |
2207 |
++static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) |
2208 |
++{ |
2209 |
++ int ret; |
2210 |
++ |
2211 |
++ vma->vm_mm = current->mm; |
2212 |
++ vma->vm_start = addr; |
2213 |
++ vma->vm_end = addr + PAGE_SIZE; |
2214 |
++ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC; |
2215 |
++ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
2216 |
++ vma->vm_ops = &pax_vm_ops; |
2217 |
++ |
2218 |
++ ret = insert_vm_struct(current->mm, vma); |
2219 |
++ if (ret) |
2220 |
++ return ret; |
2221 |
++ |
2222 |
++ ++current->mm->total_vm; |
2223 |
++ return 0; |
2224 |
++} |
2225 |
++ |
2226 |
++/* |
2227 |
++ * PaX: decide what to do with offenders (regs->pc = fault address) |
2228 |
++ * |
2229 |
++ * returns 1 when task should be killed |
2230 |
++ * 2 when patched PLT trampoline was detected |
2231 |
++ * 3 when unpatched PLT trampoline was detected |
2232 |
++ */ |
2233 |
++static int pax_handle_fetch_fault(struct pt_regs *regs) |
2234 |
++{ |
2235 |
++ |
2236 |
++#ifdef CONFIG_PAX_EMUPLT |
2237 |
++ int err; |
2238 |
++ |
2239 |
++ do { /* PaX: patched PLT emulation #1 */ |
2240 |
++ unsigned int sethi1, sethi2, jmpl; |
2241 |
++ |
2242 |
++ err = get_user(sethi1, (unsigned int *)regs->pc); |
2243 |
++ err |= get_user(sethi2, (unsigned int *)(regs->pc+4)); |
2244 |
++ err |= get_user(jmpl, (unsigned int *)(regs->pc+8)); |
2245 |
++ |
2246 |
++ if (err) |
2247 |
++ break; |
2248 |
++ |
2249 |
++ if ((sethi1 & 0xFFC00000U) == 0x03000000U && |
2250 |
++ (sethi2 & 0xFFC00000U) == 0x03000000U && |
2251 |
++ (jmpl & 0xFFFFE000U) == 0x81C06000U) |
2252 |
++ { |
2253 |
++ unsigned int addr; |
2254 |
++ |
2255 |
++ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10; |
2256 |
++ addr = regs->u_regs[UREG_G1]; |
2257 |
++ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); |
2258 |
++ regs->pc = addr; |
2259 |
++ regs->npc = addr+4; |
2260 |
++ return 2; |
2261 |
++ } |
2262 |
++ } while (0); |
2263 |
++ |
2264 |
++ { /* PaX: patched PLT emulation #2 */ |
2265 |
++ unsigned int ba; |
2266 |
++ |
2267 |
++ err = get_user(ba, (unsigned int *)regs->pc); |
2268 |
++ |
2269 |
++ if (!err && (ba & 0xFFC00000U) == 0x30800000U) { |
2270 |
++ unsigned int addr; |
2271 |
++ |
2272 |
++ addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2); |
2273 |
++ regs->pc = addr; |
2274 |
++ regs->npc = addr+4; |
2275 |
++ return 2; |
2276 |
++ } |
2277 |
++ } |
2278 |
++ |
2279 |
++ do { /* PaX: patched PLT emulation #3 */ |
2280 |
++ unsigned int sethi, jmpl, nop; |
2281 |
++ |
2282 |
++ err = get_user(sethi, (unsigned int *)regs->pc); |
2283 |
++ err |= get_user(jmpl, (unsigned int *)(regs->pc+4)); |
2284 |
++ err |= get_user(nop, (unsigned int *)(regs->pc+8)); |
2285 |
++ |
2286 |
++ if (err) |
2287 |
++ break; |
2288 |
++ |
2289 |
++ if ((sethi & 0xFFC00000U) == 0x03000000U && |
2290 |
++ (jmpl & 0xFFFFE000U) == 0x81C06000U && |
2291 |
++ nop == 0x01000000U) |
2292 |
++ { |
2293 |
++ unsigned int addr; |
2294 |
++ |
2295 |
++ addr = (sethi & 0x003FFFFFU) << 10; |
2296 |
++ regs->u_regs[UREG_G1] = addr; |
2297 |
++ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); |
2298 |
++ regs->pc = addr; |
2299 |
++ regs->npc = addr+4; |
2300 |
++ return 2; |
2301 |
++ } |
2302 |
++ } while (0); |
2303 |
++ |
2304 |
++ do { /* PaX: unpatched PLT emulation step 1 */ |
2305 |
++ unsigned int sethi, ba, nop; |
2306 |
++ |
2307 |
++ err = get_user(sethi, (unsigned int *)regs->pc); |
2308 |
++ err |= get_user(ba, (unsigned int *)(regs->pc+4)); |
2309 |
++ err |= get_user(nop, (unsigned int *)(regs->pc+8)); |
2310 |
++ |
2311 |
++ if (err) |
2312 |
++ break; |
2313 |
++ |
2314 |
++ if ((sethi & 0xFFC00000U) == 0x03000000U && |
2315 |
++ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) && |
2316 |
++ nop == 0x01000000U) |
2317 |
++ { |
2318 |
++ unsigned int addr, save, call; |
2319 |
++ |
2320 |
++ if ((ba & 0xFFC00000U) == 0x30800000U) |
2321 |
++ addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2); |
2322 |
++ else |
2323 |
++ addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2); |
2324 |
++ |
2325 |
++ err = get_user(save, (unsigned int *)addr); |
2326 |
++ err |= get_user(call, (unsigned int *)(addr+4)); |
2327 |
++ err |= get_user(nop, (unsigned int *)(addr+8)); |
2328 |
++ if (err) |
2329 |
++ break; |
2330 |
++ |
2331 |
++ if (save == 0x9DE3BFA8U && |
2332 |
++ (call & 0xC0000000U) == 0x40000000U && |
2333 |
++ nop == 0x01000000U) |
2334 |
++ { |
2335 |
++ struct vm_area_struct *vma; |
2336 |
++ unsigned long call_dl_resolve; |
2337 |
++ |
2338 |
++ down_read(¤t->mm->mmap_sem); |
2339 |
++ call_dl_resolve = current->mm->call_dl_resolve; |
2340 |
++ up_read(¤t->mm->mmap_sem); |
2341 |
++ if (likely(call_dl_resolve)) |
2342 |
++ goto emulate; |
2343 |
++ |
2344 |
++ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
2345 |
++ |
2346 |
++ down_write(¤t->mm->mmap_sem); |
2347 |
++ if (current->mm->call_dl_resolve) { |
2348 |
++ call_dl_resolve = current->mm->call_dl_resolve; |
2349 |
++ up_write(¤t->mm->mmap_sem); |
2350 |
++ if (vma) |
2351 |
++ kmem_cache_free(vm_area_cachep, vma); |
2352 |
++ goto emulate; |
2353 |
++ } |
2354 |
++ |
2355 |
++ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE); |
2356 |
++ if (!vma || (call_dl_resolve & ~PAGE_MASK)) { |
2357 |
++ up_write(¤t->mm->mmap_sem); |
2358 |
++ if (vma) |
2359 |
++ kmem_cache_free(vm_area_cachep, vma); |
2360 |
++ return 1; |
2361 |
++ } |
2362 |
++ |
2363 |
++ if (pax_insert_vma(vma, call_dl_resolve)) { |
2364 |
++ up_write(¤t->mm->mmap_sem); |
2365 |
++ kmem_cache_free(vm_area_cachep, vma); |
2366 |
++ return 1; |
2367 |
++ } |
2368 |
++ |
2369 |
++ current->mm->call_dl_resolve = call_dl_resolve; |
2370 |
++ up_write(¤t->mm->mmap_sem); |
2371 |
++ |
2372 |
++emulate: |
2373 |
++ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10; |
2374 |
++ regs->pc = call_dl_resolve; |
2375 |
++ regs->npc = addr+4; |
2376 |
++ return 3; |
2377 |
++ } |
2378 |
++ } |
2379 |
++ } while (0); |
2380 |
++ |
2381 |
++ do { /* PaX: unpatched PLT emulation step 2 */ |
2382 |
++ unsigned int save, call, nop; |
2383 |
++ |
2384 |
++ err = get_user(save, (unsigned int *)(regs->pc-4)); |
2385 |
++ err |= get_user(call, (unsigned int *)regs->pc); |
2386 |
++ err |= get_user(nop, (unsigned int *)(regs->pc+4)); |
2387 |
++ if (err) |
2388 |
++ break; |
2389 |
++ |
2390 |
++ if (save == 0x9DE3BFA8U && |
2391 |
++ (call & 0xC0000000U) == 0x40000000U && |
2392 |
++ nop == 0x01000000U) |
2393 |
++ { |
2394 |
++ unsigned int dl_resolve = regs->pc + ((((call | 0xC0000000U) ^ 0x20000000U) + 0x20000000U) << 2); |
2395 |
++ |
2396 |
++ regs->u_regs[UREG_RETPC] = regs->pc; |
2397 |
++ regs->pc = dl_resolve; |
2398 |
++ regs->npc = dl_resolve+4; |
2399 |
++ return 3; |
2400 |
++ } |
2401 |
++ } while (0); |
2402 |
++#endif |
2403 |
++ |
2404 |
++ return 1; |
2405 |
++} |
2406 |
++ |
2407 |
++void pax_report_insns(void *pc, void *sp) |
2408 |
++{ |
2409 |
++ unsigned long i; |
2410 |
++ |
2411 |
++ printk(KERN_ERR "PAX: bytes at PC: "); |
2412 |
++ for (i = 0; i < 5; i++) { |
2413 |
++ unsigned int c; |
2414 |
++ if (get_user(c, (unsigned int *)pc+i)) |
2415 |
++ printk(KERN_CONT "???????? "); |
2416 |
++ else |
2417 |
++ printk(KERN_CONT "%08x ", c); |
2418 |
++ } |
2419 |
++ printk("\n"); |
2420 |
++} |
2421 |
++#endif |
2422 |
++ |
2423 |
+ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, |
2424 |
+ unsigned long address) |
2425 |
+ { |
2426 |
+@@ -231,6 +477,24 @@ good_area: |
2427 |
+ if(!(vma->vm_flags & VM_WRITE)) |
2428 |
+ goto bad_area; |
2429 |
+ } else { |
2430 |
++ |
2431 |
++#ifdef CONFIG_PAX_PAGEEXEC |
2432 |
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && text_fault && !(vma->vm_flags & VM_EXEC)) { |
2433 |
++ up_read(&mm->mmap_sem); |
2434 |
++ switch (pax_handle_fetch_fault(regs)) { |
2435 |
++ |
2436 |
++#ifdef CONFIG_PAX_EMUPLT |
2437 |
++ case 2: |
2438 |
++ case 3: |
2439 |
++ return; |
2440 |
++#endif |
2441 |
++ |
2442 |
++ } |
2443 |
++ pax_report_fault(regs, (void *)regs->pc, (void *)regs->u_regs[UREG_FP]); |
2444 |
++ do_group_exit(SIGKILL); |
2445 |
++ } |
2446 |
++#endif |
2447 |
++ |
2448 |
+ /* Allow reads even for write-only mappings */ |
2449 |
+ if(!(vma->vm_flags & (VM_READ | VM_EXEC))) |
2450 |
+ goto bad_area; |
2451 |
+diff -urNp linux-2.6.28.8/arch/sparc/mm/init.c linux-2.6.28.8/arch/sparc/mm/init.c |
2452 |
+--- linux-2.6.28.8/arch/sparc/mm/init.c 2009-02-06 16:47:45.000000000 -0500 |
2453 |
++++ linux-2.6.28.8/arch/sparc/mm/init.c 2009-02-21 09:37:48.000000000 -0500 |
2454 |
+@@ -313,6 +313,9 @@ extern void device_scan(void); |
2455 |
+ pgprot_t PAGE_SHARED __read_mostly; |
2456 |
+ EXPORT_SYMBOL(PAGE_SHARED); |
2457 |
+ |
2458 |
++pgprot_t PAGE_SHARED_NOEXEC __read_mostly; |
2459 |
++EXPORT_SYMBOL(PAGE_SHARED_NOEXEC); |
2460 |
++ |
2461 |
+ void __init paging_init(void) |
2462 |
+ { |
2463 |
+ switch(sparc_cpu_model) { |
2464 |
+@@ -338,17 +341,17 @@ void __init paging_init(void) |
2465 |
+ |
2466 |
+ /* Initialize the protection map with non-constant, MMU dependent values. */ |
2467 |
+ protection_map[0] = PAGE_NONE; |
2468 |
+- protection_map[1] = PAGE_READONLY; |
2469 |
+- protection_map[2] = PAGE_COPY; |
2470 |
+- protection_map[3] = PAGE_COPY; |
2471 |
++ protection_map[1] = PAGE_READONLY_NOEXEC; |
2472 |
++ protection_map[2] = PAGE_COPY_NOEXEC; |
2473 |
++ protection_map[3] = PAGE_COPY_NOEXEC; |
2474 |
+ protection_map[4] = PAGE_READONLY; |
2475 |
+ protection_map[5] = PAGE_READONLY; |
2476 |
+ protection_map[6] = PAGE_COPY; |
2477 |
+ protection_map[7] = PAGE_COPY; |
2478 |
+ protection_map[8] = PAGE_NONE; |
2479 |
+- protection_map[9] = PAGE_READONLY; |
2480 |
+- protection_map[10] = PAGE_SHARED; |
2481 |
+- protection_map[11] = PAGE_SHARED; |
2482 |
++ protection_map[9] = PAGE_READONLY_NOEXEC; |
2483 |
++ protection_map[10] = PAGE_SHARED_NOEXEC; |
2484 |
++ protection_map[11] = PAGE_SHARED_NOEXEC; |
2485 |
+ protection_map[12] = PAGE_READONLY; |
2486 |
+ protection_map[13] = PAGE_READONLY; |
2487 |
+ protection_map[14] = PAGE_SHARED; |
2488 |
+diff -urNp linux-2.6.28.8/arch/sparc/mm/srmmu.c linux-2.6.28.8/arch/sparc/mm/srmmu.c |
2489 |
+--- linux-2.6.28.8/arch/sparc/mm/srmmu.c 2009-02-06 16:47:45.000000000 -0500 |
2490 |
++++ linux-2.6.28.8/arch/sparc/mm/srmmu.c 2009-02-21 09:37:48.000000000 -0500 |
2491 |
+@@ -2162,6 +2162,13 @@ void __init ld_mmu_srmmu(void) |
2492 |
+ PAGE_SHARED = pgprot_val(SRMMU_PAGE_SHARED); |
2493 |
+ BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY)); |
2494 |
+ BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY)); |
2495 |
++ |
2496 |
++#ifdef CONFIG_PAX_PAGEEXEC |
2497 |
++ PAGE_SHARED_NOEXEC = pgprot_val(SRMMU_PAGE_SHARED_NOEXEC); |
2498 |
++ BTFIXUPSET_INT(page_copy_noexec, pgprot_val(SRMMU_PAGE_COPY_NOEXEC)); |
2499 |
++ BTFIXUPSET_INT(page_readonly_noexec, pgprot_val(SRMMU_PAGE_RDONLY_NOEXEC)); |
2500 |
++#endif |
2501 |
++ |
2502 |
+ BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL)); |
2503 |
+ page_kernel = pgprot_val(SRMMU_PAGE_KERNEL); |
2504 |
+ |
2505 |
+diff -urNp linux-2.6.28.8/arch/sparc64/kernel/Makefile linux-2.6.28.8/arch/sparc64/kernel/Makefile |
2506 |
+--- linux-2.6.28.8/arch/sparc64/kernel/Makefile 2009-02-06 16:47:45.000000000 -0500 |
2507 |
++++ linux-2.6.28.8/arch/sparc64/kernel/Makefile 2009-02-21 09:37:48.000000000 -0500 |
2508 |
+@@ -3,7 +3,7 @@ |
2509 |
+ # |
2510 |
+ |
2511 |
+ EXTRA_AFLAGS := -ansi |
2512 |
+-EXTRA_CFLAGS := -Werror |
2513 |
++#EXTRA_CFLAGS := -Werror |
2514 |
+ |
2515 |
+ CFLAGS_REMOVE_ftrace.o = -pg |
2516 |
+ |
2517 |
+diff -urNp linux-2.6.28.8/arch/sparc64/kernel/sys_sparc.c linux-2.6.28.8/arch/sparc64/kernel/sys_sparc.c |
2518 |
+--- linux-2.6.28.8/arch/sparc64/kernel/sys_sparc.c 2009-02-08 00:54:27.000000000 -0500 |
2519 |
++++ linux-2.6.28.8/arch/sparc64/kernel/sys_sparc.c 2009-02-21 09:37:48.000000000 -0500 |
2520 |
+@@ -124,7 +124,7 @@ unsigned long arch_get_unmapped_area(str |
2521 |
+ /* We do not accept a shared mapping if it would violate |
2522 |
+ * cache aliasing constraints. |
2523 |
+ */ |
2524 |
+- if ((flags & MAP_SHARED) && |
2525 |
++ if ((filp || (flags & MAP_SHARED)) && |
2526 |
+ ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) |
2527 |
+ return -EINVAL; |
2528 |
+ return addr; |
2529 |
+@@ -139,6 +139,10 @@ unsigned long arch_get_unmapped_area(str |
2530 |
+ if (filp || (flags & MAP_SHARED)) |
2531 |
+ do_color_align = 1; |
2532 |
+ |
2533 |
++#ifdef CONFIG_PAX_RANDMMAP |
2534 |
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) |
2535 |
++#endif |
2536 |
++ |
2537 |
+ if (addr) { |
2538 |
+ if (do_color_align) |
2539 |
+ addr = COLOUR_ALIGN(addr, pgoff); |
2540 |
+@@ -152,9 +156,9 @@ unsigned long arch_get_unmapped_area(str |
2541 |
+ } |
2542 |
+ |
2543 |
+ if (len > mm->cached_hole_size) { |
2544 |
+- start_addr = addr = mm->free_area_cache; |
2545 |
++ start_addr = addr = mm->free_area_cache; |
2546 |
+ } else { |
2547 |
+- start_addr = addr = TASK_UNMAPPED_BASE; |
2548 |
++ start_addr = addr = mm->mmap_base; |
2549 |
+ mm->cached_hole_size = 0; |
2550 |
+ } |
2551 |
+ |
2552 |
+@@ -174,8 +178,8 @@ full_search: |
2553 |
+ vma = find_vma(mm, VA_EXCLUDE_END); |
2554 |
+ } |
2555 |
+ if (unlikely(task_size < addr)) { |
2556 |
+- if (start_addr != TASK_UNMAPPED_BASE) { |
2557 |
+- start_addr = addr = TASK_UNMAPPED_BASE; |
2558 |
++ if (start_addr != mm->mmap_base) { |
2559 |
++ start_addr = addr = mm->mmap_base; |
2560 |
+ mm->cached_hole_size = 0; |
2561 |
+ goto full_search; |
2562 |
+ } |
2563 |
+@@ -215,7 +219,7 @@ arch_get_unmapped_area_topdown(struct fi |
2564 |
+ /* We do not accept a shared mapping if it would violate |
2565 |
+ * cache aliasing constraints. |
2566 |
+ */ |
2567 |
+- if ((flags & MAP_SHARED) && |
2568 |
++ if ((filp || (flags & MAP_SHARED)) && |
2569 |
+ ((addr - (pgoff << PAGE_SHIFT)) & (SHMLBA - 1))) |
2570 |
+ return -EINVAL; |
2571 |
+ return addr; |
2572 |
+@@ -378,6 +382,12 @@ void arch_pick_mmap_layout(struct mm_str |
2573 |
+ current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY || |
2574 |
+ sysctl_legacy_va_layout) { |
2575 |
+ mm->mmap_base = TASK_UNMAPPED_BASE + random_factor; |
2576 |
++ |
2577 |
++#ifdef CONFIG_PAX_RANDMMAP |
2578 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
2579 |
++ mm->mmap_base += mm->delta_mmap; |
2580 |
++#endif |
2581 |
++ |
2582 |
+ mm->get_unmapped_area = arch_get_unmapped_area; |
2583 |
+ mm->unmap_area = arch_unmap_area; |
2584 |
+ } else { |
2585 |
+@@ -392,6 +402,12 @@ void arch_pick_mmap_layout(struct mm_str |
2586 |
+ gap = (task_size / 6 * 5); |
2587 |
+ |
2588 |
+ mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor); |
2589 |
++ |
2590 |
++#ifdef CONFIG_PAX_RANDMMAP |
2591 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
2592 |
++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack; |
2593 |
++#endif |
2594 |
++ |
2595 |
+ mm->get_unmapped_area = arch_get_unmapped_area_topdown; |
2596 |
+ mm->unmap_area = arch_unmap_area_topdown; |
2597 |
+ } |
2598 |
+diff -urNp linux-2.6.28.8/arch/sparc64/mm/fault.c linux-2.6.28.8/arch/sparc64/mm/fault.c |
2599 |
+--- linux-2.6.28.8/arch/sparc64/mm/fault.c 2009-02-06 16:47:45.000000000 -0500 |
2600 |
++++ linux-2.6.28.8/arch/sparc64/mm/fault.c 2009-02-21 09:37:48.000000000 -0500 |
2601 |
+@@ -19,6 +19,9 @@ |
2602 |
+ #include <linux/interrupt.h> |
2603 |
+ #include <linux/kprobes.h> |
2604 |
+ #include <linux/kdebug.h> |
2605 |
++#include <linux/slab.h> |
2606 |
++#include <linux/pagemap.h> |
2607 |
++#include <linux/compiler.h> |
2608 |
+ |
2609 |
+ #include <asm/page.h> |
2610 |
+ #include <asm/pgtable.h> |
2611 |
+@@ -224,6 +227,367 @@ cannot_handle: |
2612 |
+ unhandled_fault (address, current, regs); |
2613 |
+ } |
2614 |
+ |
2615 |
++#ifdef CONFIG_PAX_PAGEEXEC |
2616 |
++#ifdef CONFIG_PAX_EMUPLT |
2617 |
++static void pax_emuplt_close(struct vm_area_struct *vma) |
2618 |
++{ |
2619 |
++ vma->vm_mm->call_dl_resolve = 0UL; |
2620 |
++} |
2621 |
++ |
2622 |
++static int pax_emuplt_fault(struct vm_area_struct *vma, struct vm_fault *vmf) |
2623 |
++{ |
2624 |
++ unsigned int *kaddr; |
2625 |
++ |
2626 |
++ vmf->page = alloc_page(GFP_HIGHUSER); |
2627 |
++ if (!vmf->page) |
2628 |
++ return VM_FAULT_OOM; |
2629 |
++ |
2630 |
++ kaddr = kmap(vmf->page); |
2631 |
++ memset(kaddr, 0, PAGE_SIZE); |
2632 |
++ kaddr[0] = 0x9DE3BFA8U; /* save */ |
2633 |
++ flush_dcache_page(vmf->page); |
2634 |
++ kunmap(vmf->page); |
2635 |
++ return VM_FAULT_MAJOR; |
2636 |
++} |
2637 |
++ |
2638 |
++static struct vm_operations_struct pax_vm_ops = { |
2639 |
++ .close = pax_emuplt_close, |
2640 |
++ .fault = pax_emuplt_fault |
2641 |
++}; |
2642 |
++ |
2643 |
++static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) |
2644 |
++{ |
2645 |
++ int ret; |
2646 |
++ |
2647 |
++ vma->vm_mm = current->mm; |
2648 |
++ vma->vm_start = addr; |
2649 |
++ vma->vm_end = addr + PAGE_SIZE; |
2650 |
++ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC; |
2651 |
++ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
2652 |
++ vma->vm_ops = &pax_vm_ops; |
2653 |
++ |
2654 |
++ ret = insert_vm_struct(current->mm, vma); |
2655 |
++ if (ret) |
2656 |
++ return ret; |
2657 |
++ |
2658 |
++ ++current->mm->total_vm; |
2659 |
++ return 0; |
2660 |
++} |
2661 |
++#endif |
2662 |
++ |
2663 |
++/* |
2664 |
++ * PaX: decide what to do with offenders (regs->tpc = fault address) |
2665 |
++ * |
2666 |
++ * returns 1 when task should be killed |
2667 |
++ * 2 when patched PLT trampoline was detected |
2668 |
++ * 3 when unpatched PLT trampoline was detected |
2669 |
++ */ |
2670 |
++static int pax_handle_fetch_fault(struct pt_regs *regs) |
2671 |
++{ |
2672 |
++ |
2673 |
++#ifdef CONFIG_PAX_EMUPLT |
2674 |
++ int err; |
2675 |
++ |
2676 |
++ do { /* PaX: patched PLT emulation #1 */ |
2677 |
++ unsigned int sethi1, sethi2, jmpl; |
2678 |
++ |
2679 |
++ err = get_user(sethi1, (unsigned int *)regs->tpc); |
2680 |
++ err |= get_user(sethi2, (unsigned int *)(regs->tpc+4)); |
2681 |
++ err |= get_user(jmpl, (unsigned int *)(regs->tpc+8)); |
2682 |
++ |
2683 |
++ if (err) |
2684 |
++ break; |
2685 |
++ |
2686 |
++ if ((sethi1 & 0xFFC00000U) == 0x03000000U && |
2687 |
++ (sethi2 & 0xFFC00000U) == 0x03000000U && |
2688 |
++ (jmpl & 0xFFFFE000U) == 0x81C06000U) |
2689 |
++ { |
2690 |
++ unsigned long addr; |
2691 |
++ |
2692 |
++ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10; |
2693 |
++ addr = regs->u_regs[UREG_G1]; |
2694 |
++ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); |
2695 |
++ regs->tpc = addr; |
2696 |
++ regs->tnpc = addr+4; |
2697 |
++ return 2; |
2698 |
++ } |
2699 |
++ } while (0); |
2700 |
++ |
2701 |
++ { /* PaX: patched PLT emulation #2 */ |
2702 |
++ unsigned int ba; |
2703 |
++ |
2704 |
++ err = get_user(ba, (unsigned int *)regs->tpc); |
2705 |
++ |
2706 |
++ if (!err && (ba & 0xFFC00000U) == 0x30800000U) { |
2707 |
++ unsigned long addr; |
2708 |
++ |
2709 |
++ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); |
2710 |
++ regs->tpc = addr; |
2711 |
++ regs->tnpc = addr+4; |
2712 |
++ return 2; |
2713 |
++ } |
2714 |
++ } |
2715 |
++ |
2716 |
++ do { /* PaX: patched PLT emulation #3 */ |
2717 |
++ unsigned int sethi, jmpl, nop; |
2718 |
++ |
2719 |
++ err = get_user(sethi, (unsigned int *)regs->tpc); |
2720 |
++ err |= get_user(jmpl, (unsigned int *)(regs->tpc+4)); |
2721 |
++ err |= get_user(nop, (unsigned int *)(regs->tpc+8)); |
2722 |
++ |
2723 |
++ if (err) |
2724 |
++ break; |
2725 |
++ |
2726 |
++ if ((sethi & 0xFFC00000U) == 0x03000000U && |
2727 |
++ (jmpl & 0xFFFFE000U) == 0x81C06000U && |
2728 |
++ nop == 0x01000000U) |
2729 |
++ { |
2730 |
++ unsigned long addr; |
2731 |
++ |
2732 |
++ addr = (sethi & 0x003FFFFFU) << 10; |
2733 |
++ regs->u_regs[UREG_G1] = addr; |
2734 |
++ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); |
2735 |
++ regs->tpc = addr; |
2736 |
++ regs->tnpc = addr+4; |
2737 |
++ return 2; |
2738 |
++ } |
2739 |
++ } while (0); |
2740 |
++ |
2741 |
++ do { /* PaX: patched PLT emulation #4 */ |
2742 |
++ unsigned int mov1, call, mov2; |
2743 |
++ |
2744 |
++ err = get_user(mov1, (unsigned int *)regs->tpc); |
2745 |
++ err |= get_user(call, (unsigned int *)(regs->tpc+4)); |
2746 |
++ err |= get_user(mov2, (unsigned int *)(regs->tpc+8)); |
2747 |
++ |
2748 |
++ if (err) |
2749 |
++ break; |
2750 |
++ |
2751 |
++ if (mov1 == 0x8210000FU && |
2752 |
++ (call & 0xC0000000U) == 0x40000000U && |
2753 |
++ mov2 == 0x9E100001U) |
2754 |
++ { |
2755 |
++ unsigned long addr; |
2756 |
++ |
2757 |
++ regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC]; |
2758 |
++ addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2); |
2759 |
++ regs->tpc = addr; |
2760 |
++ regs->tnpc = addr+4; |
2761 |
++ return 2; |
2762 |
++ } |
2763 |
++ } while (0); |
2764 |
++ |
2765 |
++ do { /* PaX: patched PLT emulation #5 */ |
2766 |
++ unsigned int sethi1, sethi2, or1, or2, sllx, jmpl, nop; |
2767 |
++ |
2768 |
++ err = get_user(sethi1, (unsigned int *)regs->tpc); |
2769 |
++ err |= get_user(sethi2, (unsigned int *)(regs->tpc+4)); |
2770 |
++ err |= get_user(or1, (unsigned int *)(regs->tpc+8)); |
2771 |
++ err |= get_user(or2, (unsigned int *)(regs->tpc+12)); |
2772 |
++ err |= get_user(sllx, (unsigned int *)(regs->tpc+16)); |
2773 |
++ err |= get_user(jmpl, (unsigned int *)(regs->tpc+20)); |
2774 |
++ err |= get_user(nop, (unsigned int *)(regs->tpc+24)); |
2775 |
++ |
2776 |
++ if (err) |
2777 |
++ break; |
2778 |
++ |
2779 |
++ if ((sethi1 & 0xFFC00000U) == 0x03000000U && |
2780 |
++ (sethi2 & 0xFFC00000U) == 0x0B000000U && |
2781 |
++ (or1 & 0xFFFFE000U) == 0x82106000U && |
2782 |
++ (or2 & 0xFFFFE000U) == 0x8A116000U && |
2783 |
++ sllx == 0x83287020 && |
2784 |
++ jmpl == 0x81C04005U && |
2785 |
++ nop == 0x01000000U) |
2786 |
++ { |
2787 |
++ unsigned long addr; |
2788 |
++ |
2789 |
++ regs->u_regs[UREG_G1] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU); |
2790 |
++ regs->u_regs[UREG_G1] <<= 32; |
2791 |
++ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU); |
2792 |
++ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5]; |
2793 |
++ regs->tpc = addr; |
2794 |
++ regs->tnpc = addr+4; |
2795 |
++ return 2; |
2796 |
++ } |
2797 |
++ } while (0); |
2798 |
++ |
2799 |
++ do { /* PaX: patched PLT emulation #6 */ |
2800 |
++ unsigned int sethi1, sethi2, sllx, or, jmpl, nop; |
2801 |
++ |
2802 |
++ err = get_user(sethi1, (unsigned int *)regs->tpc); |
2803 |
++ err |= get_user(sethi2, (unsigned int *)(regs->tpc+4)); |
2804 |
++ err |= get_user(sllx, (unsigned int *)(regs->tpc+8)); |
2805 |
++ err |= get_user(or, (unsigned int *)(regs->tpc+12)); |
2806 |
++ err |= get_user(jmpl, (unsigned int *)(regs->tpc+16)); |
2807 |
++ err |= get_user(nop, (unsigned int *)(regs->tpc+20)); |
2808 |
++ |
2809 |
++ if (err) |
2810 |
++ break; |
2811 |
++ |
2812 |
++ if ((sethi1 & 0xFFC00000U) == 0x03000000U && |
2813 |
++ (sethi2 & 0xFFC00000U) == 0x0B000000U && |
2814 |
++ sllx == 0x83287020 && |
2815 |
++ (or & 0xFFFFE000U) == 0x8A116000U && |
2816 |
++ jmpl == 0x81C04005U && |
2817 |
++ nop == 0x01000000U) |
2818 |
++ { |
2819 |
++ unsigned long addr; |
2820 |
++ |
2821 |
++ regs->u_regs[UREG_G1] = (sethi1 & 0x003FFFFFU) << 10; |
2822 |
++ regs->u_regs[UREG_G1] <<= 32; |
2823 |
++ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or & 0x3FFU); |
2824 |
++ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5]; |
2825 |
++ regs->tpc = addr; |
2826 |
++ regs->tnpc = addr+4; |
2827 |
++ return 2; |
2828 |
++ } |
2829 |
++ } while (0); |
2830 |
++ |
2831 |
++ do { /* PaX: patched PLT emulation #7 */ |
2832 |
++ unsigned int sethi, ba, nop; |
2833 |
++ |
2834 |
++ err = get_user(sethi, (unsigned int *)regs->tpc); |
2835 |
++ err |= get_user(ba, (unsigned int *)(regs->tpc+4)); |
2836 |
++ err |= get_user(nop, (unsigned int *)(regs->tpc+8)); |
2837 |
++ |
2838 |
++ if (err) |
2839 |
++ break; |
2840 |
++ |
2841 |
++ if ((sethi & 0xFFC00000U) == 0x03000000U && |
2842 |
++ (ba & 0xFFF00000U) == 0x30600000U && |
2843 |
++ nop == 0x01000000U) |
2844 |
++ { |
2845 |
++ unsigned long addr; |
2846 |
++ |
2847 |
++ addr = (sethi & 0x003FFFFFU) << 10; |
2848 |
++ regs->u_regs[UREG_G1] = addr; |
2849 |
++ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); |
2850 |
++ regs->tpc = addr; |
2851 |
++ regs->tnpc = addr+4; |
2852 |
++ return 2; |
2853 |
++ } |
2854 |
++ } while (0); |
2855 |
++ |
2856 |
++ do { /* PaX: unpatched PLT emulation step 1 */ |
2857 |
++ unsigned int sethi, ba, nop; |
2858 |
++ |
2859 |
++ err = get_user(sethi, (unsigned int *)regs->tpc); |
2860 |
++ err |= get_user(ba, (unsigned int *)(regs->tpc+4)); |
2861 |
++ err |= get_user(nop, (unsigned int *)(regs->tpc+8)); |
2862 |
++ |
2863 |
++ if (err) |
2864 |
++ break; |
2865 |
++ |
2866 |
++ if ((sethi & 0xFFC00000U) == 0x03000000U && |
2867 |
++ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) && |
2868 |
++ nop == 0x01000000U) |
2869 |
++ { |
2870 |
++ unsigned long addr; |
2871 |
++ unsigned int save, call; |
2872 |
++ |
2873 |
++ if ((ba & 0xFFC00000U) == 0x30800000U) |
2874 |
++ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); |
2875 |
++ else |
2876 |
++ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); |
2877 |
++ |
2878 |
++ err = get_user(save, (unsigned int *)addr); |
2879 |
++ err |= get_user(call, (unsigned int *)(addr+4)); |
2880 |
++ err |= get_user(nop, (unsigned int *)(addr+8)); |
2881 |
++ if (err) |
2882 |
++ break; |
2883 |
++ |
2884 |
++ if (save == 0x9DE3BFA8U && |
2885 |
++ (call & 0xC0000000U) == 0x40000000U && |
2886 |
++ nop == 0x01000000U) |
2887 |
++ { |
2888 |
++ struct vm_area_struct *vma; |
2889 |
++ unsigned long call_dl_resolve; |
2890 |
++ |
2891 |
++ down_read(¤t->mm->mmap_sem); |
2892 |
++ call_dl_resolve = current->mm->call_dl_resolve; |
2893 |
++ up_read(¤t->mm->mmap_sem); |
2894 |
++ if (likely(call_dl_resolve)) |
2895 |
++ goto emulate; |
2896 |
++ |
2897 |
++ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
2898 |
++ |
2899 |
++ down_write(¤t->mm->mmap_sem); |
2900 |
++ if (current->mm->call_dl_resolve) { |
2901 |
++ call_dl_resolve = current->mm->call_dl_resolve; |
2902 |
++ up_write(¤t->mm->mmap_sem); |
2903 |
++ if (vma) |
2904 |
++ kmem_cache_free(vm_area_cachep, vma); |
2905 |
++ goto emulate; |
2906 |
++ } |
2907 |
++ |
2908 |
++ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE); |
2909 |
++ if (!vma || (call_dl_resolve & ~PAGE_MASK)) { |
2910 |
++ up_write(¤t->mm->mmap_sem); |
2911 |
++ if (vma) |
2912 |
++ kmem_cache_free(vm_area_cachep, vma); |
2913 |
++ return 1; |
2914 |
++ } |
2915 |
++ |
2916 |
++ if (pax_insert_vma(vma, call_dl_resolve)) { |
2917 |
++ up_write(¤t->mm->mmap_sem); |
2918 |
++ kmem_cache_free(vm_area_cachep, vma); |
2919 |
++ return 1; |
2920 |
++ } |
2921 |
++ |
2922 |
++ current->mm->call_dl_resolve = call_dl_resolve; |
2923 |
++ up_write(¤t->mm->mmap_sem); |
2924 |
++ |
2925 |
++emulate: |
2926 |
++ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10; |
2927 |
++ regs->tpc = call_dl_resolve; |
2928 |
++ regs->tnpc = addr+4; |
2929 |
++ return 3; |
2930 |
++ } |
2931 |
++ } |
2932 |
++ } while (0); |
2933 |
++ |
2934 |
++ do { /* PaX: unpatched PLT emulation step 2 */ |
2935 |
++ unsigned int save, call, nop; |
2936 |
++ |
2937 |
++ err = get_user(save, (unsigned int *)(regs->tpc-4)); |
2938 |
++ err |= get_user(call, (unsigned int *)regs->tpc); |
2939 |
++ err |= get_user(nop, (unsigned int *)(regs->tpc+4)); |
2940 |
++ if (err) |
2941 |
++ break; |
2942 |
++ |
2943 |
++ if (save == 0x9DE3BFA8U && |
2944 |
++ (call & 0xC0000000U) == 0x40000000U && |
2945 |
++ nop == 0x01000000U) |
2946 |
++ { |
2947 |
++ unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2); |
2948 |
++ |
2949 |
++ regs->u_regs[UREG_RETPC] = regs->tpc; |
2950 |
++ regs->tpc = dl_resolve; |
2951 |
++ regs->tnpc = dl_resolve+4; |
2952 |
++ return 3; |
2953 |
++ } |
2954 |
++ } while (0); |
2955 |
++#endif |
2956 |
++ |
2957 |
++ return 1; |
2958 |
++} |
2959 |
++ |
2960 |
++void pax_report_insns(void *pc, void *sp) |
2961 |
++{ |
2962 |
++ unsigned long i; |
2963 |
++ |
2964 |
++ printk(KERN_ERR "PAX: bytes at PC: "); |
2965 |
++ for (i = 0; i < 5; i++) { |
2966 |
++ unsigned int c; |
2967 |
++ if (get_user(c, (unsigned int *)pc+i)) |
2968 |
++ printk(KERN_CONT "???????? "); |
2969 |
++ else |
2970 |
++ printk(KERN_CONT "%08x ", c); |
2971 |
++ } |
2972 |
++ printk("\n"); |
2973 |
++} |
2974 |
++#endif |
2975 |
++ |
2976 |
+ asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs) |
2977 |
+ { |
2978 |
+ struct mm_struct *mm = current->mm; |
2979 |
+@@ -265,8 +629,10 @@ asmlinkage void __kprobes do_sparc64_fau |
2980 |
+ goto intr_or_no_mm; |
2981 |
+ |
2982 |
+ if (test_thread_flag(TIF_32BIT)) { |
2983 |
+- if (!(regs->tstate & TSTATE_PRIV)) |
2984 |
++ if (!(regs->tstate & TSTATE_PRIV)) { |
2985 |
+ regs->tpc &= 0xffffffff; |
2986 |
++ regs->tnpc &= 0xffffffff; |
2987 |
++ } |
2988 |
+ address &= 0xffffffff; |
2989 |
+ } |
2990 |
+ |
2991 |
+@@ -283,6 +649,29 @@ asmlinkage void __kprobes do_sparc64_fau |
2992 |
+ if (!vma) |
2993 |
+ goto bad_area; |
2994 |
+ |
2995 |
++#ifdef CONFIG_PAX_PAGEEXEC |
2996 |
++ /* PaX: detect ITLB misses on non-exec pages */ |
2997 |
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && vma->vm_start <= address && |
2998 |
++ !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB)) |
2999 |
++ { |
3000 |
++ if (address != regs->tpc) |
3001 |
++ goto good_area; |
3002 |
++ |
3003 |
++ up_read(&mm->mmap_sem); |
3004 |
++ switch (pax_handle_fetch_fault(regs)) { |
3005 |
++ |
3006 |
++#ifdef CONFIG_PAX_EMUPLT |
3007 |
++ case 2: |
3008 |
++ case 3: |
3009 |
++ return; |
3010 |
++#endif |
3011 |
++ |
3012 |
++ } |
3013 |
++ pax_report_fault(regs, (void *)regs->tpc, (void *)(regs->u_regs[UREG_FP] + STACK_BIAS)); |
3014 |
++ do_group_exit(SIGKILL); |
3015 |
++ } |
3016 |
++#endif |
3017 |
++ |
3018 |
+ /* Pure DTLB misses do not tell us whether the fault causing |
3019 |
+ * load/store/atomic was a write or not, it only says that there |
3020 |
+ * was no match. So in such a case we (carefully) read the |
3021 |
+diff -urNp linux-2.6.28.8/arch/sparc64/mm/Makefile linux-2.6.28.8/arch/sparc64/mm/Makefile |
3022 |
+--- linux-2.6.28.8/arch/sparc64/mm/Makefile 2009-02-06 16:47:45.000000000 -0500 |
3023 |
++++ linux-2.6.28.8/arch/sparc64/mm/Makefile 2009-02-21 09:37:48.000000000 -0500 |
3024 |
+@@ -2,7 +2,7 @@ |
3025 |
+ # |
3026 |
+ |
3027 |
+ EXTRA_AFLAGS := -ansi |
3028 |
+-EXTRA_CFLAGS := -Werror |
3029 |
++#EXTRA_CFLAGS := -Werror |
3030 |
+ |
3031 |
+ obj-y := ultra.o tlb.o tsb.o fault.o init.o generic.o |
3032 |
+ |
3033 |
+diff -urNp linux-2.6.28.8/arch/um/include/asm/kmap_types.h linux-2.6.28.8/arch/um/include/asm/kmap_types.h |
3034 |
+--- linux-2.6.28.8/arch/um/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
3035 |
++++ linux-2.6.28.8/arch/um/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
3036 |
+@@ -23,6 +23,7 @@ enum km_type { |
3037 |
+ KM_IRQ1, |
3038 |
+ KM_SOFTIRQ0, |
3039 |
+ KM_SOFTIRQ1, |
3040 |
++ KM_CLEARPAGE, |
3041 |
+ KM_TYPE_NR |
3042 |
+ }; |
3043 |
+ |
3044 |
+diff -urNp linux-2.6.28.8/arch/um/include/asm/page.h linux-2.6.28.8/arch/um/include/asm/page.h |
3045 |
+--- linux-2.6.28.8/arch/um/include/asm/page.h 2009-02-06 16:47:45.000000000 -0500 |
3046 |
++++ linux-2.6.28.8/arch/um/include/asm/page.h 2009-02-21 09:37:48.000000000 -0500 |
3047 |
+@@ -14,6 +14,9 @@ |
3048 |
+ #define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) |
3049 |
+ #define PAGE_MASK (~(PAGE_SIZE-1)) |
3050 |
+ |
3051 |
++#define ktla_ktva(addr) (addr) |
3052 |
++#define ktva_ktla(addr) (addr) |
3053 |
++ |
3054 |
+ #ifndef __ASSEMBLY__ |
3055 |
+ |
3056 |
+ struct page; |
3057 |
+diff -urNp linux-2.6.28.8/arch/um/sys-i386/syscalls.c linux-2.6.28.8/arch/um/sys-i386/syscalls.c |
3058 |
+--- linux-2.6.28.8/arch/um/sys-i386/syscalls.c 2009-02-06 16:47:45.000000000 -0500 |
3059 |
++++ linux-2.6.28.8/arch/um/sys-i386/syscalls.c 2009-02-21 09:37:48.000000000 -0500 |
3060 |
+@@ -11,6 +11,21 @@ |
3061 |
+ #include "asm/uaccess.h" |
3062 |
+ #include "asm/unistd.h" |
3063 |
+ |
3064 |
++int i386_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) |
3065 |
++{ |
3066 |
++ unsigned long pax_task_size = TASK_SIZE; |
3067 |
++ |
3068 |
++#ifdef CONFIG_PAX_SEGMEXEC |
3069 |
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) |
3070 |
++ pax_task_size = SEGMEXEC_TASK_SIZE; |
3071 |
++#endif |
3072 |
++ |
3073 |
++ if (len > pax_task_size || addr > pax_task_size - len) |
3074 |
++ return -EINVAL; |
3075 |
++ |
3076 |
++ return 0; |
3077 |
++} |
3078 |
++ |
3079 |
+ /* |
3080 |
+ * Perform the select(nd, in, out, ex, tv) and mmap() system |
3081 |
+ * calls. Linux/i386 didn't use to be able to handle more than |
3082 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/bitops.h linux-2.6.28.8/arch/x86/boot/bitops.h |
3083 |
+--- linux-2.6.28.8/arch/x86/boot/bitops.h 2009-02-06 16:47:45.000000000 -0500 |
3084 |
++++ linux-2.6.28.8/arch/x86/boot/bitops.h 2009-02-21 09:37:48.000000000 -0500 |
3085 |
+@@ -26,7 +26,7 @@ static inline int variable_test_bit(int |
3086 |
+ u8 v; |
3087 |
+ const u32 *p = (const u32 *)addr; |
3088 |
+ |
3089 |
+- asm("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr)); |
3090 |
++ asm volatile("btl %2,%1; setc %0" : "=qm" (v) : "m" (*p), "Ir" (nr)); |
3091 |
+ return v; |
3092 |
+ } |
3093 |
+ |
3094 |
+@@ -37,7 +37,7 @@ static inline int variable_test_bit(int |
3095 |
+ |
3096 |
+ static inline void set_bit(int nr, void *addr) |
3097 |
+ { |
3098 |
+- asm("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr)); |
3099 |
++ asm volatile("btsl %1,%0" : "+m" (*(u32 *)addr) : "Ir" (nr)); |
3100 |
+ } |
3101 |
+ |
3102 |
+ #endif /* BOOT_BITOPS_H */ |
3103 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/boot.h linux-2.6.28.8/arch/x86/boot/boot.h |
3104 |
+--- linux-2.6.28.8/arch/x86/boot/boot.h 2009-02-06 16:47:45.000000000 -0500 |
3105 |
++++ linux-2.6.28.8/arch/x86/boot/boot.h 2009-02-21 09:37:48.000000000 -0500 |
3106 |
+@@ -80,7 +80,7 @@ static inline void io_delay(void) |
3107 |
+ static inline u16 ds(void) |
3108 |
+ { |
3109 |
+ u16 seg; |
3110 |
+- asm("movw %%ds,%0" : "=rm" (seg)); |
3111 |
++ asm volatile("movw %%ds,%0" : "=rm" (seg)); |
3112 |
+ return seg; |
3113 |
+ } |
3114 |
+ |
3115 |
+@@ -176,7 +176,7 @@ static inline void wrgs32(u32 v, addr_t |
3116 |
+ static inline int memcmp(const void *s1, const void *s2, size_t len) |
3117 |
+ { |
3118 |
+ u8 diff; |
3119 |
+- asm("repe; cmpsb; setnz %0" |
3120 |
++ asm volatile("repe; cmpsb; setnz %0" |
3121 |
+ : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); |
3122 |
+ return diff; |
3123 |
+ } |
3124 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/compressed/head_32.S linux-2.6.28.8/arch/x86/boot/compressed/head_32.S |
3125 |
+--- linux-2.6.28.8/arch/x86/boot/compressed/head_32.S 2009-02-06 16:47:45.000000000 -0500 |
3126 |
++++ linux-2.6.28.8/arch/x86/boot/compressed/head_32.S 2009-03-07 10:28:24.000000000 -0500 |
3127 |
+@@ -70,7 +70,7 @@ startup_32: |
3128 |
+ addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebx |
3129 |
+ andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebx |
3130 |
+ #else |
3131 |
+- movl $LOAD_PHYSICAL_ADDR, %ebx |
3132 |
++ movl $____LOAD_PHYSICAL_ADDR, %ebx |
3133 |
+ #endif |
3134 |
+ |
3135 |
+ /* Replace the compressed data size with the uncompressed size */ |
3136 |
+@@ -80,8 +80,8 @@ startup_32: |
3137 |
+ /* Add 8 bytes for every 32K input block */ |
3138 |
+ shrl $12, %eax |
3139 |
+ addl %eax, %ebx |
3140 |
+- /* Add 32K + 18 bytes of extra slack */ |
3141 |
+- addl $(32768 + 18), %ebx |
3142 |
++ /* Add 64K of extra slack */ |
3143 |
++ addl $65536, %ebx |
3144 |
+ /* Align on a 4K boundary */ |
3145 |
+ addl $4095, %ebx |
3146 |
+ andl $~4095, %ebx |
3147 |
+@@ -105,7 +105,7 @@ startup_32: |
3148 |
+ addl $(CONFIG_PHYSICAL_ALIGN - 1), %ebp |
3149 |
+ andl $(~(CONFIG_PHYSICAL_ALIGN - 1)), %ebp |
3150 |
+ #else |
3151 |
+- movl $LOAD_PHYSICAL_ADDR, %ebp |
3152 |
++ movl $____LOAD_PHYSICAL_ADDR, %ebp |
3153 |
+ #endif |
3154 |
+ |
3155 |
+ /* |
3156 |
+@@ -160,16 +160,15 @@ relocated: |
3157 |
+ * and where it was actually loaded. |
3158 |
+ */ |
3159 |
+ movl %ebp, %ebx |
3160 |
+- subl $LOAD_PHYSICAL_ADDR, %ebx |
3161 |
++ subl $____LOAD_PHYSICAL_ADDR, %ebx |
3162 |
+ jz 2f /* Nothing to be done if loaded at compiled addr. */ |
3163 |
+ /* |
3164 |
+ * Process relocations. |
3165 |
+ */ |
3166 |
+ |
3167 |
+ 1: subl $4, %edi |
3168 |
+- movl 0(%edi), %ecx |
3169 |
+- testl %ecx, %ecx |
3170 |
+- jz 2f |
3171 |
++ movl (%edi), %ecx |
3172 |
++ jecxz 2f |
3173 |
+ addl %ebx, -__PAGE_OFFSET(%ebx, %ecx) |
3174 |
+ jmp 1b |
3175 |
+ 2: |
3176 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/compressed/misc.c linux-2.6.28.8/arch/x86/boot/compressed/misc.c |
3177 |
+--- linux-2.6.28.8/arch/x86/boot/compressed/misc.c 2009-02-06 16:47:45.000000000 -0500 |
3178 |
++++ linux-2.6.28.8/arch/x86/boot/compressed/misc.c 2009-02-21 09:37:48.000000000 -0500 |
3179 |
+@@ -373,7 +373,7 @@ static void parse_elf(void *output) |
3180 |
+ case PT_LOAD: |
3181 |
+ #ifdef CONFIG_RELOCATABLE |
3182 |
+ dest = output; |
3183 |
+- dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR); |
3184 |
++ dest += (phdr->p_paddr - ____LOAD_PHYSICAL_ADDR); |
3185 |
+ #else |
3186 |
+ dest = (void *)(phdr->p_paddr); |
3187 |
+ #endif |
3188 |
+@@ -425,7 +425,7 @@ asmlinkage void decompress_kernel(void * |
3189 |
+ if (heap > ((-__PAGE_OFFSET-(512<<20)-1) & 0x7fffffff)) |
3190 |
+ error("Destination address too large"); |
3191 |
+ #ifndef CONFIG_RELOCATABLE |
3192 |
+- if ((u32)output != LOAD_PHYSICAL_ADDR) |
3193 |
++ if ((u32)output != ____LOAD_PHYSICAL_ADDR) |
3194 |
+ error("Wrong destination address"); |
3195 |
+ #endif |
3196 |
+ #endif |
3197 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/compressed/relocs.c linux-2.6.28.8/arch/x86/boot/compressed/relocs.c |
3198 |
+--- linux-2.6.28.8/arch/x86/boot/compressed/relocs.c 2009-02-06 16:47:45.000000000 -0500 |
3199 |
++++ linux-2.6.28.8/arch/x86/boot/compressed/relocs.c 2009-02-21 09:37:48.000000000 -0500 |
3200 |
+@@ -10,8 +10,11 @@ |
3201 |
+ #define USE_BSD |
3202 |
+ #include <endian.h> |
3203 |
+ |
3204 |
++#include "../../../../include/linux/autoconf.h" |
3205 |
++ |
3206 |
+ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) |
3207 |
+ static Elf32_Ehdr ehdr; |
3208 |
++static Elf32_Phdr *phdr; |
3209 |
+ static unsigned long reloc_count, reloc_idx; |
3210 |
+ static unsigned long *relocs; |
3211 |
+ |
3212 |
+@@ -245,6 +248,36 @@ static void read_ehdr(FILE *fp) |
3213 |
+ } |
3214 |
+ } |
3215 |
+ |
3216 |
++static void read_phdrs(FILE *fp) |
3217 |
++{ |
3218 |
++ int i; |
3219 |
++ |
3220 |
++ phdr = calloc(ehdr.e_phnum, sizeof(Elf32_Phdr)); |
3221 |
++ if (!phdr) { |
3222 |
++ die("Unable to allocate %d program headers\n", |
3223 |
++ ehdr.e_phnum); |
3224 |
++ } |
3225 |
++ if (fseek(fp, ehdr.e_phoff, SEEK_SET) < 0) { |
3226 |
++ die("Seek to %d failed: %s\n", |
3227 |
++ ehdr.e_phoff, strerror(errno)); |
3228 |
++ } |
3229 |
++ if (fread(phdr, sizeof(*phdr), ehdr.e_phnum, fp) != ehdr.e_phnum) { |
3230 |
++ die("Cannot read ELF program headers: %s\n", |
3231 |
++ strerror(errno)); |
3232 |
++ } |
3233 |
++ for(i = 0; i < ehdr.e_phnum; i++) { |
3234 |
++ phdr[i].p_type = elf32_to_cpu(phdr[i].p_type); |
3235 |
++ phdr[i].p_offset = elf32_to_cpu(phdr[i].p_offset); |
3236 |
++ phdr[i].p_vaddr = elf32_to_cpu(phdr[i].p_vaddr); |
3237 |
++ phdr[i].p_paddr = elf32_to_cpu(phdr[i].p_paddr); |
3238 |
++ phdr[i].p_filesz = elf32_to_cpu(phdr[i].p_filesz); |
3239 |
++ phdr[i].p_memsz = elf32_to_cpu(phdr[i].p_memsz); |
3240 |
++ phdr[i].p_flags = elf32_to_cpu(phdr[i].p_flags); |
3241 |
++ phdr[i].p_align = elf32_to_cpu(phdr[i].p_align); |
3242 |
++ } |
3243 |
++ |
3244 |
++} |
3245 |
++ |
3246 |
+ static void read_shdrs(FILE *fp) |
3247 |
+ { |
3248 |
+ int i; |
3249 |
+@@ -341,6 +374,8 @@ static void read_symtabs(FILE *fp) |
3250 |
+ static void read_relocs(FILE *fp) |
3251 |
+ { |
3252 |
+ int i,j; |
3253 |
++ uint32_t base; |
3254 |
++ |
3255 |
+ for (i = 0; i < ehdr.e_shnum; i++) { |
3256 |
+ struct section *sec = &secs[i]; |
3257 |
+ if (sec->shdr.sh_type != SHT_REL) { |
3258 |
+@@ -360,9 +395,18 @@ static void read_relocs(FILE *fp) |
3259 |
+ die("Cannot read symbol table: %s\n", |
3260 |
+ strerror(errno)); |
3261 |
+ } |
3262 |
++ base = 0; |
3263 |
++ for (j = 0; j < ehdr.e_phnum; j++) { |
3264 |
++ if (phdr[j].p_type != PT_LOAD ) |
3265 |
++ continue; |
3266 |
++ if (secs[sec->shdr.sh_info].shdr.sh_offset < phdr[j].p_offset || secs[sec->shdr.sh_info].shdr.sh_offset >= phdr[j].p_offset + phdr[j].p_filesz) |
3267 |
++ continue; |
3268 |
++ base = CONFIG_PAGE_OFFSET + phdr[j].p_paddr - phdr[j].p_vaddr; |
3269 |
++ break; |
3270 |
++ } |
3271 |
+ for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) { |
3272 |
+ Elf32_Rel *rel = &sec->reltab[j]; |
3273 |
+- rel->r_offset = elf32_to_cpu(rel->r_offset); |
3274 |
++ rel->r_offset = elf32_to_cpu(rel->r_offset) + base; |
3275 |
+ rel->r_info = elf32_to_cpu(rel->r_info); |
3276 |
+ } |
3277 |
+ } |
3278 |
+@@ -504,6 +548,23 @@ static void walk_relocs(void (*visit)(El |
3279 |
+ if (sym->st_shndx == SHN_ABS) { |
3280 |
+ continue; |
3281 |
+ } |
3282 |
++ /* Don't relocate actual per-cpu variables, they are absolute indices, not addresses */ |
3283 |
++ if (!strcmp(sec_name(sym->st_shndx), ".data.percpu") && strncmp(sym_name(sym_strtab, sym), "__per_cpu_", 10)) |
3284 |
++ continue; |
3285 |
++#if defined(CONFIG_PAX_KERNEXEC) && defined(CONFIG_X86_32) |
3286 |
++ /* Don't relocate actual code, they are relocated implicitly by the base address of KERNEL_CS */ |
3287 |
++ if (!strcmp(sec_name(sym->st_shndx), ".init.text")) |
3288 |
++ continue; |
3289 |
++ if (!strcmp(sec_name(sym->st_shndx), ".exit.text")) |
3290 |
++ continue; |
3291 |
++ if (!strcmp(sec_name(sym->st_shndx), ".text.head")) { |
3292 |
++ if (strcmp(sym_name(sym_strtab, sym), "__init_end") && |
3293 |
++ strcmp(sym_name(sym_strtab, sym), "KERNEL_TEXT_OFFSET")) |
3294 |
++ continue; |
3295 |
++ } |
3296 |
++ if (!strcmp(sec_name(sym->st_shndx), ".text")) |
3297 |
++ continue; |
3298 |
++#endif |
3299 |
+ if (r_type == R_386_PC32) { |
3300 |
+ /* PC relative relocations don't need to be adjusted */ |
3301 |
+ } |
3302 |
+@@ -631,6 +692,7 @@ int main(int argc, char **argv) |
3303 |
+ fname, strerror(errno)); |
3304 |
+ } |
3305 |
+ read_ehdr(fp); |
3306 |
++ read_phdrs(fp); |
3307 |
+ read_shdrs(fp); |
3308 |
+ read_strtabs(fp); |
3309 |
+ read_symtabs(fp); |
3310 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/cpucheck.c linux-2.6.28.8/arch/x86/boot/cpucheck.c |
3311 |
+--- linux-2.6.28.8/arch/x86/boot/cpucheck.c 2009-02-06 16:47:45.000000000 -0500 |
3312 |
++++ linux-2.6.28.8/arch/x86/boot/cpucheck.c 2009-02-21 09:37:48.000000000 -0500 |
3313 |
+@@ -74,7 +74,7 @@ static int has_fpu(void) |
3314 |
+ u16 fcw = -1, fsw = -1; |
3315 |
+ u32 cr0; |
3316 |
+ |
3317 |
+- asm("movl %%cr0,%0" : "=r" (cr0)); |
3318 |
++ asm volatile("movl %%cr0,%0" : "=r" (cr0)); |
3319 |
+ if (cr0 & (X86_CR0_EM|X86_CR0_TS)) { |
3320 |
+ cr0 &= ~(X86_CR0_EM|X86_CR0_TS); |
3321 |
+ asm volatile("movl %0,%%cr0" : : "r" (cr0)); |
3322 |
+@@ -90,7 +90,7 @@ static int has_eflag(u32 mask) |
3323 |
+ { |
3324 |
+ u32 f0, f1; |
3325 |
+ |
3326 |
+- asm("pushfl ; " |
3327 |
++ asm volatile("pushfl ; " |
3328 |
+ "pushfl ; " |
3329 |
+ "popl %0 ; " |
3330 |
+ "movl %0,%1 ; " |
3331 |
+@@ -115,7 +115,7 @@ static void get_flags(void) |
3332 |
+ set_bit(X86_FEATURE_FPU, cpu.flags); |
3333 |
+ |
3334 |
+ if (has_eflag(X86_EFLAGS_ID)) { |
3335 |
+- asm("cpuid" |
3336 |
++ asm volatile("cpuid" |
3337 |
+ : "=a" (max_intel_level), |
3338 |
+ "=b" (cpu_vendor[0]), |
3339 |
+ "=d" (cpu_vendor[1]), |
3340 |
+@@ -124,7 +124,7 @@ static void get_flags(void) |
3341 |
+ |
3342 |
+ if (max_intel_level >= 0x00000001 && |
3343 |
+ max_intel_level <= 0x0000ffff) { |
3344 |
+- asm("cpuid" |
3345 |
++ asm volatile("cpuid" |
3346 |
+ : "=a" (tfms), |
3347 |
+ "=c" (cpu.flags[4]), |
3348 |
+ "=d" (cpu.flags[0]) |
3349 |
+@@ -136,7 +136,7 @@ static void get_flags(void) |
3350 |
+ cpu.model += ((tfms >> 16) & 0xf) << 4; |
3351 |
+ } |
3352 |
+ |
3353 |
+- asm("cpuid" |
3354 |
++ asm volatile("cpuid" |
3355 |
+ : "=a" (max_amd_level) |
3356 |
+ : "a" (0x80000000) |
3357 |
+ : "ebx", "ecx", "edx"); |
3358 |
+@@ -144,7 +144,7 @@ static void get_flags(void) |
3359 |
+ if (max_amd_level >= 0x80000001 && |
3360 |
+ max_amd_level <= 0x8000ffff) { |
3361 |
+ u32 eax = 0x80000001; |
3362 |
+- asm("cpuid" |
3363 |
++ asm volatile("cpuid" |
3364 |
+ : "+a" (eax), |
3365 |
+ "=c" (cpu.flags[6]), |
3366 |
+ "=d" (cpu.flags[1]) |
3367 |
+@@ -203,9 +203,9 @@ int check_cpu(int *cpu_level_ptr, int *r |
3368 |
+ u32 ecx = MSR_K7_HWCR; |
3369 |
+ u32 eax, edx; |
3370 |
+ |
3371 |
+- asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); |
3372 |
++ asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); |
3373 |
+ eax &= ~(1 << 15); |
3374 |
+- asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); |
3375 |
++ asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); |
3376 |
+ |
3377 |
+ get_flags(); /* Make sure it really did something */ |
3378 |
+ err = check_flags(); |
3379 |
+@@ -218,9 +218,9 @@ int check_cpu(int *cpu_level_ptr, int *r |
3380 |
+ u32 ecx = MSR_VIA_FCR; |
3381 |
+ u32 eax, edx; |
3382 |
+ |
3383 |
+- asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); |
3384 |
++ asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); |
3385 |
+ eax |= (1<<1)|(1<<7); |
3386 |
+- asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); |
3387 |
++ asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); |
3388 |
+ |
3389 |
+ set_bit(X86_FEATURE_CX8, cpu.flags); |
3390 |
+ err = check_flags(); |
3391 |
+@@ -231,12 +231,12 @@ int check_cpu(int *cpu_level_ptr, int *r |
3392 |
+ u32 eax, edx; |
3393 |
+ u32 level = 1; |
3394 |
+ |
3395 |
+- asm("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); |
3396 |
+- asm("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx)); |
3397 |
+- asm("cpuid" |
3398 |
++ asm volatile("rdmsr" : "=a" (eax), "=d" (edx) : "c" (ecx)); |
3399 |
++ asm volatile("wrmsr" : : "a" (~0), "d" (edx), "c" (ecx)); |
3400 |
++ asm volatile("cpuid" |
3401 |
+ : "+a" (level), "=d" (cpu.flags[0]) |
3402 |
+ : : "ecx", "ebx"); |
3403 |
+- asm("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); |
3404 |
++ asm volatile("wrmsr" : : "a" (eax), "d" (edx), "c" (ecx)); |
3405 |
+ |
3406 |
+ err = check_flags(); |
3407 |
+ } |
3408 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/edd.c linux-2.6.28.8/arch/x86/boot/edd.c |
3409 |
+--- linux-2.6.28.8/arch/x86/boot/edd.c 2009-02-06 16:47:45.000000000 -0500 |
3410 |
++++ linux-2.6.28.8/arch/x86/boot/edd.c 2009-02-21 09:37:48.000000000 -0500 |
3411 |
+@@ -81,7 +81,7 @@ static int get_edd_info(u8 devno, struct |
3412 |
+ ax = 0x4100; |
3413 |
+ bx = EDDMAGIC1; |
3414 |
+ dx = devno; |
3415 |
+- asm("pushfl; stc; int $0x13; setc %%al; popfl" |
3416 |
++ asm volatile("pushfl; stc; int $0x13; setc %%al; popfl" |
3417 |
+ : "+a" (ax), "+b" (bx), "=c" (cx), "+d" (dx) |
3418 |
+ : : "esi", "edi"); |
3419 |
+ |
3420 |
+@@ -100,7 +100,7 @@ static int get_edd_info(u8 devno, struct |
3421 |
+ ei->params.length = sizeof(ei->params); |
3422 |
+ ax = 0x4800; |
3423 |
+ dx = devno; |
3424 |
+- asm("pushfl; int $0x13; popfl" |
3425 |
++ asm volatile("pushfl; int $0x13; popfl" |
3426 |
+ : "+a" (ax), "+d" (dx), "=m" (ei->params) |
3427 |
+ : "S" (&ei->params) |
3428 |
+ : "ebx", "ecx", "edi"); |
3429 |
+@@ -111,7 +111,7 @@ static int get_edd_info(u8 devno, struct |
3430 |
+ ax = 0x0800; |
3431 |
+ dx = devno; |
3432 |
+ di = 0; |
3433 |
+- asm("pushw %%es; " |
3434 |
++ asm volatile("pushw %%es; " |
3435 |
+ "movw %%di,%%es; " |
3436 |
+ "pushfl; stc; int $0x13; setc %%al; popfl; " |
3437 |
+ "popw %%es" |
3438 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/main.c linux-2.6.28.8/arch/x86/boot/main.c |
3439 |
+--- linux-2.6.28.8/arch/x86/boot/main.c 2009-02-06 16:47:45.000000000 -0500 |
3440 |
++++ linux-2.6.28.8/arch/x86/boot/main.c 2009-02-21 09:37:48.000000000 -0500 |
3441 |
+@@ -78,7 +78,7 @@ static void query_ist(void) |
3442 |
+ if (cpu.level < 6) |
3443 |
+ return; |
3444 |
+ |
3445 |
+- asm("int $0x15" |
3446 |
++ asm volatile("int $0x15" |
3447 |
+ : "=a" (boot_params.ist_info.signature), |
3448 |
+ "=b" (boot_params.ist_info.command), |
3449 |
+ "=c" (boot_params.ist_info.event), |
3450 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/mca.c linux-2.6.28.8/arch/x86/boot/mca.c |
3451 |
+--- linux-2.6.28.8/arch/x86/boot/mca.c 2009-02-06 16:47:45.000000000 -0500 |
3452 |
++++ linux-2.6.28.8/arch/x86/boot/mca.c 2009-02-21 09:37:48.000000000 -0500 |
3453 |
+@@ -19,7 +19,7 @@ int query_mca(void) |
3454 |
+ u8 err; |
3455 |
+ u16 es, bx, len; |
3456 |
+ |
3457 |
+- asm("pushw %%es ; " |
3458 |
++ asm volatile("pushw %%es ; " |
3459 |
+ "int $0x15 ; " |
3460 |
+ "setc %0 ; " |
3461 |
+ "movw %%es, %1 ; " |
3462 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/memory.c linux-2.6.28.8/arch/x86/boot/memory.c |
3463 |
+--- linux-2.6.28.8/arch/x86/boot/memory.c 2009-02-06 16:47:45.000000000 -0500 |
3464 |
++++ linux-2.6.28.8/arch/x86/boot/memory.c 2009-02-21 09:37:48.000000000 -0500 |
3465 |
+@@ -30,7 +30,7 @@ static int detect_memory_e820(void) |
3466 |
+ /* Important: %edx is clobbered by some BIOSes, |
3467 |
+ so it must be either used for the error output |
3468 |
+ or explicitly marked clobbered. */ |
3469 |
+- asm("int $0x15; setc %0" |
3470 |
++ asm volatile("int $0x15; setc %0" |
3471 |
+ : "=d" (err), "+b" (next), "=a" (id), "+c" (size), |
3472 |
+ "=m" (*desc) |
3473 |
+ : "D" (desc), "d" (SMAP), "a" (0xe820)); |
3474 |
+@@ -65,7 +65,7 @@ static int detect_memory_e801(void) |
3475 |
+ |
3476 |
+ bx = cx = dx = 0; |
3477 |
+ ax = 0xe801; |
3478 |
+- asm("stc; int $0x15; setc %0" |
3479 |
++ asm volatile("stc; int $0x15; setc %0" |
3480 |
+ : "=m" (err), "+a" (ax), "+b" (bx), "+c" (cx), "+d" (dx)); |
3481 |
+ |
3482 |
+ if (err) |
3483 |
+@@ -95,7 +95,7 @@ static int detect_memory_88(void) |
3484 |
+ u8 err; |
3485 |
+ |
3486 |
+ ax = 0x8800; |
3487 |
+- asm("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax)); |
3488 |
++ asm volatile("stc; int $0x15; setc %0" : "=bcdm" (err), "+a" (ax)); |
3489 |
+ |
3490 |
+ boot_params.screen_info.ext_mem_k = ax; |
3491 |
+ |
3492 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/video.c linux-2.6.28.8/arch/x86/boot/video.c |
3493 |
+--- linux-2.6.28.8/arch/x86/boot/video.c 2009-02-06 16:47:45.000000000 -0500 |
3494 |
++++ linux-2.6.28.8/arch/x86/boot/video.c 2009-02-21 09:37:48.000000000 -0500 |
3495 |
+@@ -23,7 +23,7 @@ static void store_cursor_position(void) |
3496 |
+ |
3497 |
+ ax = 0x0300; |
3498 |
+ bx = 0; |
3499 |
+- asm(INT10 |
3500 |
++ asm volatile(INT10 |
3501 |
+ : "=d" (curpos), "+a" (ax), "+b" (bx) |
3502 |
+ : : "ecx", "esi", "edi"); |
3503 |
+ |
3504 |
+@@ -38,7 +38,7 @@ static void store_video_mode(void) |
3505 |
+ /* N.B.: the saving of the video page here is a bit silly, |
3506 |
+ since we pretty much assume page 0 everywhere. */ |
3507 |
+ ax = 0x0f00; |
3508 |
+- asm(INT10 |
3509 |
++ asm volatile(INT10 |
3510 |
+ : "+a" (ax), "=b" (page) |
3511 |
+ : : "ecx", "edx", "esi", "edi"); |
3512 |
+ |
3513 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/video-vesa.c linux-2.6.28.8/arch/x86/boot/video-vesa.c |
3514 |
+--- linux-2.6.28.8/arch/x86/boot/video-vesa.c 2009-02-06 16:47:45.000000000 -0500 |
3515 |
++++ linux-2.6.28.8/arch/x86/boot/video-vesa.c 2009-02-21 09:37:48.000000000 -0500 |
3516 |
+@@ -41,7 +41,7 @@ static int vesa_probe(void) |
3517 |
+ |
3518 |
+ ax = 0x4f00; |
3519 |
+ di = (size_t)&vginfo; |
3520 |
+- asm(INT10 |
3521 |
++ asm volatile(INT10 |
3522 |
+ : "+a" (ax), "+D" (di), "=m" (vginfo) |
3523 |
+ : : "ebx", "ecx", "edx", "esi"); |
3524 |
+ |
3525 |
+@@ -68,7 +68,7 @@ static int vesa_probe(void) |
3526 |
+ ax = 0x4f01; |
3527 |
+ cx = mode; |
3528 |
+ di = (size_t)&vminfo; |
3529 |
+- asm(INT10 |
3530 |
++ asm volatile(INT10 |
3531 |
+ : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo) |
3532 |
+ : : "ebx", "edx", "esi"); |
3533 |
+ |
3534 |
+@@ -120,7 +120,7 @@ static int vesa_set_mode(struct mode_inf |
3535 |
+ ax = 0x4f01; |
3536 |
+ cx = vesa_mode; |
3537 |
+ di = (size_t)&vminfo; |
3538 |
+- asm(INT10 |
3539 |
++ asm volatile(INT10 |
3540 |
+ : "+a" (ax), "+c" (cx), "+D" (di), "=m" (vminfo) |
3541 |
+ : : "ebx", "edx", "esi"); |
3542 |
+ |
3543 |
+@@ -202,19 +202,20 @@ static void vesa_dac_set_8bits(void) |
3544 |
+ /* Save the VESA protected mode info */ |
3545 |
+ static void vesa_store_pm_info(void) |
3546 |
+ { |
3547 |
+- u16 ax, bx, di, es; |
3548 |
++ u16 ax, bx, cx, di, es; |
3549 |
+ |
3550 |
+ ax = 0x4f0a; |
3551 |
+- bx = di = 0; |
3552 |
+- asm("pushw %%es; "INT10"; movw %%es,%0; popw %%es" |
3553 |
+- : "=d" (es), "+a" (ax), "+b" (bx), "+D" (di) |
3554 |
+- : : "ecx", "esi"); |
3555 |
++ bx = cx = di = 0; |
3556 |
++ asm volatile("pushw %%es; "INT10"; movw %%es,%0; popw %%es" |
3557 |
++ : "=d" (es), "+a" (ax), "+b" (bx), "+c" (cx), "+D" (di) |
3558 |
++ : : "esi"); |
3559 |
+ |
3560 |
+ if (ax != 0x004f) |
3561 |
+ return; |
3562 |
+ |
3563 |
+ boot_params.screen_info.vesapm_seg = es; |
3564 |
+ boot_params.screen_info.vesapm_off = di; |
3565 |
++ boot_params.screen_info.vesapm_size = cx; |
3566 |
+ } |
3567 |
+ |
3568 |
+ /* |
3569 |
+@@ -268,7 +269,7 @@ void vesa_store_edid(void) |
3570 |
+ /* Note: The VBE DDC spec is different from the main VESA spec; |
3571 |
+ we genuinely have to assume all registers are destroyed here. */ |
3572 |
+ |
3573 |
+- asm("pushw %%es; movw %2,%%es; "INT10"; popw %%es" |
3574 |
++ asm volatile("pushw %%es; movw %2,%%es; "INT10"; popw %%es" |
3575 |
+ : "+a" (ax), "+b" (bx) |
3576 |
+ : "c" (cx), "D" (di) |
3577 |
+ : "esi"); |
3578 |
+@@ -284,7 +285,7 @@ void vesa_store_edid(void) |
3579 |
+ cx = 0; /* Controller 0 */ |
3580 |
+ dx = 0; /* EDID block number */ |
3581 |
+ di =(size_t) &boot_params.edid_info; /* (ES:)Pointer to block */ |
3582 |
+- asm(INT10 |
3583 |
++ asm volatile(INT10 |
3584 |
+ : "+a" (ax), "+b" (bx), "+d" (dx), "=m" (boot_params.edid_info) |
3585 |
+ : "c" (cx), "D" (di) |
3586 |
+ : "esi"); |
3587 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/video-vga.c linux-2.6.28.8/arch/x86/boot/video-vga.c |
3588 |
+--- linux-2.6.28.8/arch/x86/boot/video-vga.c 2009-02-06 16:47:45.000000000 -0500 |
3589 |
++++ linux-2.6.28.8/arch/x86/boot/video-vga.c 2009-02-21 09:37:48.000000000 -0500 |
3590 |
+@@ -225,7 +225,7 @@ static int vga_probe(void) |
3591 |
+ }; |
3592 |
+ u8 vga_flag; |
3593 |
+ |
3594 |
+- asm(INT10 |
3595 |
++ asm volatile(INT10 |
3596 |
+ : "=b" (ega_bx) |
3597 |
+ : "a" (0x1200), "b" (0x10) /* Check EGA/VGA */ |
3598 |
+ : "ecx", "edx", "esi", "edi"); |
3599 |
+@@ -237,7 +237,7 @@ static int vga_probe(void) |
3600 |
+ /* If we have MDA/CGA/HGC then BL will be unchanged at 0x10 */ |
3601 |
+ if ((u8)ega_bx != 0x10) { |
3602 |
+ /* EGA/VGA */ |
3603 |
+- asm(INT10 |
3604 |
++ asm volatile(INT10 |
3605 |
+ : "=a" (vga_flag) |
3606 |
+ : "a" (0x1a00) |
3607 |
+ : "ebx", "ecx", "edx", "esi", "edi"); |
3608 |
+diff -urNp linux-2.6.28.8/arch/x86/boot/voyager.c linux-2.6.28.8/arch/x86/boot/voyager.c |
3609 |
+--- linux-2.6.28.8/arch/x86/boot/voyager.c 2009-02-06 16:47:45.000000000 -0500 |
3610 |
++++ linux-2.6.28.8/arch/x86/boot/voyager.c 2009-02-21 09:37:48.000000000 -0500 |
3611 |
+@@ -23,7 +23,7 @@ int query_voyager(void) |
3612 |
+ |
3613 |
+ data_ptr[0] = 0xff; /* Flag on config not found(?) */ |
3614 |
+ |
3615 |
+- asm("pushw %%es ; " |
3616 |
++ asm volatile("pushw %%es ; " |
3617 |
+ "int $0x15 ; " |
3618 |
+ "setc %0 ; " |
3619 |
+ "movw %%es, %1 ; " |
3620 |
+diff -urNp linux-2.6.28.8/arch/x86/ia32/ia32_signal.c linux-2.6.28.8/arch/x86/ia32/ia32_signal.c |
3621 |
+--- linux-2.6.28.8/arch/x86/ia32/ia32_signal.c 2009-02-06 16:47:45.000000000 -0500 |
3622 |
++++ linux-2.6.28.8/arch/x86/ia32/ia32_signal.c 2009-02-21 09:37:48.000000000 -0500 |
3623 |
+@@ -518,6 +518,7 @@ int ia32_setup_rt_frame(int sig, struct |
3624 |
+ __NR_ia32_rt_sigreturn, |
3625 |
+ 0x80cd, |
3626 |
+ 0, |
3627 |
++ 0 |
3628 |
+ }; |
3629 |
+ |
3630 |
+ frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate); |
3631 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/alternative.h linux-2.6.28.8/arch/x86/include/asm/alternative.h |
3632 |
+--- linux-2.6.28.8/arch/x86/include/asm/alternative.h 2009-02-06 16:47:45.000000000 -0500 |
3633 |
++++ linux-2.6.28.8/arch/x86/include/asm/alternative.h 2009-02-21 09:37:48.000000000 -0500 |
3634 |
+@@ -96,7 +96,7 @@ const unsigned char *const *find_nop_tab |
3635 |
+ " .byte 662b-661b\n" /* sourcelen */ \ |
3636 |
+ " .byte 664f-663f\n" /* replacementlen */ \ |
3637 |
+ ".previous\n" \ |
3638 |
+- ".section .altinstr_replacement,\"ax\"\n" \ |
3639 |
++ ".section .altinstr_replacement,\"a\"\n" \ |
3640 |
+ "663:\n\t" newinstr "\n664:\n" /* replacement */ \ |
3641 |
+ ".previous" :: "i" (feature) : "memory") |
3642 |
+ |
3643 |
+@@ -120,7 +120,7 @@ const unsigned char *const *find_nop_tab |
3644 |
+ " .byte 662b-661b\n" /* sourcelen */ \ |
3645 |
+ " .byte 664f-663f\n" /* replacementlen */ \ |
3646 |
+ ".previous\n" \ |
3647 |
+- ".section .altinstr_replacement,\"ax\"\n" \ |
3648 |
++ ".section .altinstr_replacement,\"a\"\n" \ |
3649 |
+ "663:\n\t" newinstr "\n664:\n" /* replacement */ \ |
3650 |
+ ".previous" :: "i" (feature), ##input) |
3651 |
+ |
3652 |
+@@ -135,7 +135,7 @@ const unsigned char *const *find_nop_tab |
3653 |
+ " .byte 662b-661b\n" /* sourcelen */ \ |
3654 |
+ " .byte 664f-663f\n" /* replacementlen */ \ |
3655 |
+ ".previous\n" \ |
3656 |
+- ".section .altinstr_replacement,\"ax\"\n" \ |
3657 |
++ ".section .altinstr_replacement,\"a\"\n" \ |
3658 |
+ "663:\n\t" newinstr "\n664:\n" /* replacement */ \ |
3659 |
+ ".previous" : output : [feat] "i" (feature), ##input) |
3660 |
+ |
3661 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_32.h linux-2.6.28.8/arch/x86/include/asm/atomic_32.h |
3662 |
+--- linux-2.6.28.8/arch/x86/include/asm/atomic_32.h 2009-02-06 16:47:45.000000000 -0500 |
3663 |
++++ linux-2.6.28.8/arch/x86/include/asm/atomic_32.h 2009-02-21 09:37:48.000000000 -0500 |
3664 |
+@@ -47,7 +47,29 @@ typedef struct { |
3665 |
+ */ |
3666 |
+ static inline void atomic_add(int i, atomic_t *v) |
3667 |
+ { |
3668 |
+- asm volatile(LOCK_PREFIX "addl %1,%0" |
3669 |
++ asm volatile(LOCK_PREFIX "addl %1,%0\n" |
3670 |
++ |
3671 |
++#ifdef CONFIG_PAX_REFCOUNT |
3672 |
++ "jno 0f\n" |
3673 |
++ LOCK_PREFIX "subl %1,%0\n" |
3674 |
++ "into\n0:\n" |
3675 |
++ _ASM_EXTABLE(0b, 0b) |
3676 |
++#endif |
3677 |
++ |
3678 |
++ : "+m" (v->counter) |
3679 |
++ : "ir" (i)); |
3680 |
++} |
3681 |
++ |
3682 |
++/** |
3683 |
++ * atomic_add_unchecked - add integer to atomic variable |
3684 |
++ * @i: integer value to add |
3685 |
++ * @v: pointer of type atomic_t |
3686 |
++ * |
3687 |
++ * Atomically adds @i to @v. |
3688 |
++ */ |
3689 |
++static inline void atomic_add_unchecked(int i, atomic_t *v) |
3690 |
++{ |
3691 |
++ asm volatile(LOCK_PREFIX "addl %1,%0\n" |
3692 |
+ : "+m" (v->counter) |
3693 |
+ : "ir" (i)); |
3694 |
+ } |
3695 |
+@@ -61,7 +83,15 @@ static inline void atomic_add(int i, ato |
3696 |
+ */ |
3697 |
+ static inline void atomic_sub(int i, atomic_t *v) |
3698 |
+ { |
3699 |
+- asm volatile(LOCK_PREFIX "subl %1,%0" |
3700 |
++ asm volatile(LOCK_PREFIX "subl %1,%0\n" |
3701 |
++ |
3702 |
++#ifdef CONFIG_PAX_REFCOUNT |
3703 |
++ "jno 0f\n" |
3704 |
++ LOCK_PREFIX "addl %1,%0\n" |
3705 |
++ "into\n0:\n" |
3706 |
++ _ASM_EXTABLE(0b, 0b) |
3707 |
++#endif |
3708 |
++ |
3709 |
+ : "+m" (v->counter) |
3710 |
+ : "ir" (i)); |
3711 |
+ } |
3712 |
+@@ -79,7 +109,16 @@ static inline int atomic_sub_and_test(in |
3713 |
+ { |
3714 |
+ unsigned char c; |
3715 |
+ |
3716 |
+- asm volatile(LOCK_PREFIX "subl %2,%0; sete %1" |
3717 |
++ asm volatile(LOCK_PREFIX "subl %2,%0\n" |
3718 |
++ |
3719 |
++#ifdef CONFIG_PAX_REFCOUNT |
3720 |
++ "jno 0f\n" |
3721 |
++ LOCK_PREFIX "addl %2,%0\n" |
3722 |
++ "into\n0:\n" |
3723 |
++ _ASM_EXTABLE(0b, 0b) |
3724 |
++#endif |
3725 |
++ |
3726 |
++ "sete %1\n" |
3727 |
+ : "+m" (v->counter), "=qm" (c) |
3728 |
+ : "ir" (i) : "memory"); |
3729 |
+ return c; |
3730 |
+@@ -93,7 +132,18 @@ static inline int atomic_sub_and_test(in |
3731 |
+ */ |
3732 |
+ static inline void atomic_inc(atomic_t *v) |
3733 |
+ { |
3734 |
+- asm volatile(LOCK_PREFIX "incl %0" |
3735 |
++ asm volatile(LOCK_PREFIX "incl %0\n" |
3736 |
++ |
3737 |
++#ifdef CONFIG_PAX_REFCOUNT |
3738 |
++ "into\n0:\n" |
3739 |
++ ".pushsection .fixup,\"ax\"\n" |
3740 |
++ "1:\n" |
3741 |
++ LOCK_PREFIX "decl %0\n" |
3742 |
++ "jmp 0b\n" |
3743 |
++ ".popsection\n" |
3744 |
++ _ASM_EXTABLE(0b, 1b) |
3745 |
++#endif |
3746 |
++ |
3747 |
+ : "+m" (v->counter)); |
3748 |
+ } |
3749 |
+ |
3750 |
+@@ -105,7 +155,18 @@ static inline void atomic_inc(atomic_t * |
3751 |
+ */ |
3752 |
+ static inline void atomic_dec(atomic_t *v) |
3753 |
+ { |
3754 |
+- asm volatile(LOCK_PREFIX "decl %0" |
3755 |
++ asm volatile(LOCK_PREFIX "decl %0\n" |
3756 |
++ |
3757 |
++#ifdef CONFIG_PAX_REFCOUNT |
3758 |
++ "into\n0:\n" |
3759 |
++ ".pushsection .fixup,\"ax\"\n" |
3760 |
++ "1: \n" |
3761 |
++ LOCK_PREFIX "incl %0\n" |
3762 |
++ "jmp 0b\n" |
3763 |
++ ".popsection\n" |
3764 |
++ _ASM_EXTABLE(0b, 1b) |
3765 |
++#endif |
3766 |
++ |
3767 |
+ : "+m" (v->counter)); |
3768 |
+ } |
3769 |
+ |
3770 |
+@@ -121,7 +182,19 @@ static inline int atomic_dec_and_test(at |
3771 |
+ { |
3772 |
+ unsigned char c; |
3773 |
+ |
3774 |
+- asm volatile(LOCK_PREFIX "decl %0; sete %1" |
3775 |
++ asm volatile(LOCK_PREFIX "decl %0\n" |
3776 |
++ |
3777 |
++#ifdef CONFIG_PAX_REFCOUNT |
3778 |
++ "into\n0:\n" |
3779 |
++ ".pushsection .fixup,\"ax\"\n" |
3780 |
++ "1: \n" |
3781 |
++ LOCK_PREFIX "incl %0\n" |
3782 |
++ "jmp 0b\n" |
3783 |
++ ".popsection\n" |
3784 |
++ _ASM_EXTABLE(0b, 1b) |
3785 |
++#endif |
3786 |
++ |
3787 |
++ "sete %1\n" |
3788 |
+ : "+m" (v->counter), "=qm" (c) |
3789 |
+ : : "memory"); |
3790 |
+ return c != 0; |
3791 |
+@@ -139,7 +212,19 @@ static inline int atomic_inc_and_test(at |
3792 |
+ { |
3793 |
+ unsigned char c; |
3794 |
+ |
3795 |
+- asm volatile(LOCK_PREFIX "incl %0; sete %1" |
3796 |
++ asm volatile(LOCK_PREFIX "incl %0\n" |
3797 |
++ |
3798 |
++#ifdef CONFIG_PAX_REFCOUNT |
3799 |
++ "into\n0:\n" |
3800 |
++ ".pushsection .fixup,\"ax\"\n" |
3801 |
++ "1: \n" |
3802 |
++ LOCK_PREFIX "decl %0\n" |
3803 |
++ "jmp 0b\n" |
3804 |
++ ".popsection\n" |
3805 |
++ _ASM_EXTABLE(0b, 1b) |
3806 |
++#endif |
3807 |
++ |
3808 |
++ "sete %1\n" |
3809 |
+ : "+m" (v->counter), "=qm" (c) |
3810 |
+ : : "memory"); |
3811 |
+ return c != 0; |
3812 |
+@@ -158,7 +243,16 @@ static inline int atomic_add_negative(in |
3813 |
+ { |
3814 |
+ unsigned char c; |
3815 |
+ |
3816 |
+- asm volatile(LOCK_PREFIX "addl %2,%0; sets %1" |
3817 |
++ asm volatile(LOCK_PREFIX "addl %2,%0\n" |
3818 |
++ |
3819 |
++#ifdef CONFIG_PAX_REFCOUNT |
3820 |
++ "jno 0f\n" |
3821 |
++ LOCK_PREFIX "subl %2,%0\n" |
3822 |
++ "into\n0:\n" |
3823 |
++ _ASM_EXTABLE(0b, 0b) |
3824 |
++#endif |
3825 |
++ |
3826 |
++ "sets %1\n" |
3827 |
+ : "+m" (v->counter), "=qm" (c) |
3828 |
+ : "ir" (i) : "memory"); |
3829 |
+ return c; |
3830 |
+@@ -181,7 +275,15 @@ static inline int atomic_add_return(int |
3831 |
+ #endif |
3832 |
+ /* Modern 486+ processor */ |
3833 |
+ __i = i; |
3834 |
+- asm volatile(LOCK_PREFIX "xaddl %0, %1" |
3835 |
++ asm volatile(LOCK_PREFIX "xaddl %0, %1\n" |
3836 |
++ |
3837 |
++#ifdef CONFIG_PAX_REFCOUNT |
3838 |
++ "jno 0f\n" |
3839 |
++ "movl %0, %1\n" |
3840 |
++ "into\n0:\n" |
3841 |
++ _ASM_EXTABLE(0b, 0b) |
3842 |
++#endif |
3843 |
++ |
3844 |
+ : "+r" (i), "+m" (v->counter) |
3845 |
+ : : "memory"); |
3846 |
+ return i + __i; |
3847 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/atomic_64.h linux-2.6.28.8/arch/x86/include/asm/atomic_64.h |
3848 |
+--- linux-2.6.28.8/arch/x86/include/asm/atomic_64.h 2009-02-06 16:47:45.000000000 -0500 |
3849 |
++++ linux-2.6.28.8/arch/x86/include/asm/atomic_64.h 2009-02-21 09:37:48.000000000 -0500 |
3850 |
+@@ -48,7 +48,29 @@ typedef struct { |
3851 |
+ */ |
3852 |
+ static inline void atomic_add(int i, atomic_t *v) |
3853 |
+ { |
3854 |
+- asm volatile(LOCK_PREFIX "addl %1,%0" |
3855 |
++ asm volatile(LOCK_PREFIX "addl %1,%0\n" |
3856 |
++ |
3857 |
++#ifdef CONFIG_PAX_REFCOUNT |
3858 |
++ "jno 0f\n" |
3859 |
++ LOCK_PREFIX "subl %1,%0\n" |
3860 |
++ "int $4\n0:\n" |
3861 |
++ _ASM_EXTABLE(0b, 0b) |
3862 |
++#endif |
3863 |
++ |
3864 |
++ : "=m" (v->counter) |
3865 |
++ : "ir" (i), "m" (v->counter)); |
3866 |
++} |
3867 |
++ |
3868 |
++/** |
3869 |
++ * atomic_add_unchecked - add integer to atomic variable |
3870 |
++ * @i: integer value to add |
3871 |
++ * @v: pointer of type atomic_t |
3872 |
++ * |
3873 |
++ * Atomically adds @i to @v. |
3874 |
++ */ |
3875 |
++static inline void atomic_add_unchecked(int i, atomic_t *v) |
3876 |
++{ |
3877 |
++ asm volatile(LOCK_PREFIX "addl %1,%0\n" |
3878 |
+ : "=m" (v->counter) |
3879 |
+ : "ir" (i), "m" (v->counter)); |
3880 |
+ } |
3881 |
+@@ -62,7 +84,15 @@ static inline void atomic_add(int i, ato |
3882 |
+ */ |
3883 |
+ static inline void atomic_sub(int i, atomic_t *v) |
3884 |
+ { |
3885 |
+- asm volatile(LOCK_PREFIX "subl %1,%0" |
3886 |
++ asm volatile(LOCK_PREFIX "subl %1,%0\n" |
3887 |
++ |
3888 |
++#ifdef CONFIG_PAX_REFCOUNT |
3889 |
++ "jno 0f\n" |
3890 |
++ LOCK_PREFIX "addl %1,%0\n" |
3891 |
++ "int $4\n0:\n" |
3892 |
++ _ASM_EXTABLE(0b, 0b) |
3893 |
++#endif |
3894 |
++ |
3895 |
+ : "=m" (v->counter) |
3896 |
+ : "ir" (i), "m" (v->counter)); |
3897 |
+ } |
3898 |
+@@ -80,7 +110,16 @@ static inline int atomic_sub_and_test(in |
3899 |
+ { |
3900 |
+ unsigned char c; |
3901 |
+ |
3902 |
+- asm volatile(LOCK_PREFIX "subl %2,%0; sete %1" |
3903 |
++ asm volatile(LOCK_PREFIX "subl %2,%0\n" |
3904 |
++ |
3905 |
++#ifdef CONFIG_PAX_REFCOUNT |
3906 |
++ "jno 0f\n" |
3907 |
++ LOCK_PREFIX "addl %2,%0\n" |
3908 |
++ "int $4\n0:\n" |
3909 |
++ _ASM_EXTABLE(0b, 0b) |
3910 |
++#endif |
3911 |
++ |
3912 |
++ "sete %1\n" |
3913 |
+ : "=m" (v->counter), "=qm" (c) |
3914 |
+ : "ir" (i), "m" (v->counter) : "memory"); |
3915 |
+ return c; |
3916 |
+@@ -94,7 +133,19 @@ static inline int atomic_sub_and_test(in |
3917 |
+ */ |
3918 |
+ static inline void atomic_inc(atomic_t *v) |
3919 |
+ { |
3920 |
+- asm volatile(LOCK_PREFIX "incl %0" |
3921 |
++ asm volatile(LOCK_PREFIX "incl %0\n" |
3922 |
++ |
3923 |
++#ifdef CONFIG_PAX_REFCOUNT |
3924 |
++ "jno 0f\n" |
3925 |
++ "int $4\n0:\n" |
3926 |
++ ".pushsection .fixup,\"ax\"\n" |
3927 |
++ "1:\n" |
3928 |
++ LOCK_PREFIX "decl %0\n" |
3929 |
++ "jmp 0b\n" |
3930 |
++ ".popsection\n" |
3931 |
++ _ASM_EXTABLE(0b, 1b) |
3932 |
++#endif |
3933 |
++ |
3934 |
+ : "=m" (v->counter) |
3935 |
+ : "m" (v->counter)); |
3936 |
+ } |
3937 |
+@@ -107,7 +158,19 @@ static inline void atomic_inc(atomic_t * |
3938 |
+ */ |
3939 |
+ static inline void atomic_dec(atomic_t *v) |
3940 |
+ { |
3941 |
+- asm volatile(LOCK_PREFIX "decl %0" |
3942 |
++ asm volatile(LOCK_PREFIX "decl %0\n" |
3943 |
++ |
3944 |
++#ifdef CONFIG_PAX_REFCOUNT |
3945 |
++ "jno 0f\n" |
3946 |
++ "int $4\n0:\n" |
3947 |
++ ".pushsection .fixup,\"ax\"\n" |
3948 |
++ "1: \n" |
3949 |
++ LOCK_PREFIX "incl %0\n" |
3950 |
++ "jmp 0b\n" |
3951 |
++ ".popsection\n" |
3952 |
++ _ASM_EXTABLE(0b, 1b) |
3953 |
++#endif |
3954 |
++ |
3955 |
+ : "=m" (v->counter) |
3956 |
+ : "m" (v->counter)); |
3957 |
+ } |
3958 |
+@@ -124,7 +187,20 @@ static inline int atomic_dec_and_test(at |
3959 |
+ { |
3960 |
+ unsigned char c; |
3961 |
+ |
3962 |
+- asm volatile(LOCK_PREFIX "decl %0; sete %1" |
3963 |
++ asm volatile(LOCK_PREFIX "decl %0\n" |
3964 |
++ |
3965 |
++#ifdef CONFIG_PAX_REFCOUNT |
3966 |
++ "jno 0f\n" |
3967 |
++ "int $4\n0:\n" |
3968 |
++ ".pushsection .fixup,\"ax\"\n" |
3969 |
++ "1: \n" |
3970 |
++ LOCK_PREFIX "incl %0\n" |
3971 |
++ "jmp 0b\n" |
3972 |
++ ".popsection\n" |
3973 |
++ _ASM_EXTABLE(0b, 1b) |
3974 |
++#endif |
3975 |
++ |
3976 |
++ "sete %1\n" |
3977 |
+ : "=m" (v->counter), "=qm" (c) |
3978 |
+ : "m" (v->counter) : "memory"); |
3979 |
+ return c != 0; |
3980 |
+@@ -142,7 +218,20 @@ static inline int atomic_inc_and_test(at |
3981 |
+ { |
3982 |
+ unsigned char c; |
3983 |
+ |
3984 |
+- asm volatile(LOCK_PREFIX "incl %0; sete %1" |
3985 |
++ asm volatile(LOCK_PREFIX "incl %0\n" |
3986 |
++ |
3987 |
++#ifdef CONFIG_PAX_REFCOUNT |
3988 |
++ "jno 0f\n" |
3989 |
++ "int $4\n0:\n" |
3990 |
++ ".pushsection .fixup,\"ax\"\n" |
3991 |
++ "1: \n" |
3992 |
++ LOCK_PREFIX "decl %0\n" |
3993 |
++ "jmp 0b\n" |
3994 |
++ ".popsection\n" |
3995 |
++ _ASM_EXTABLE(0b, 1b) |
3996 |
++#endif |
3997 |
++ |
3998 |
++ "sete %1\n" |
3999 |
+ : "=m" (v->counter), "=qm" (c) |
4000 |
+ : "m" (v->counter) : "memory"); |
4001 |
+ return c != 0; |
4002 |
+@@ -161,7 +250,16 @@ static inline int atomic_add_negative(in |
4003 |
+ { |
4004 |
+ unsigned char c; |
4005 |
+ |
4006 |
+- asm volatile(LOCK_PREFIX "addl %2,%0; sets %1" |
4007 |
++ asm volatile(LOCK_PREFIX "addl %2,%0\n" |
4008 |
++ |
4009 |
++#ifdef CONFIG_PAX_REFCOUNT |
4010 |
++ "jno 0f\n" |
4011 |
++ LOCK_PREFIX "subl %2,%0\n" |
4012 |
++ "int $4\n0:\n" |
4013 |
++ _ASM_EXTABLE(0b, 0b) |
4014 |
++#endif |
4015 |
++ |
4016 |
++ "sets %1\n" |
4017 |
+ : "=m" (v->counter), "=qm" (c) |
4018 |
+ : "ir" (i), "m" (v->counter) : "memory"); |
4019 |
+ return c; |
4020 |
+@@ -177,7 +275,15 @@ static inline int atomic_add_negative(in |
4021 |
+ static inline int atomic_add_return(int i, atomic_t *v) |
4022 |
+ { |
4023 |
+ int __i = i; |
4024 |
+- asm volatile(LOCK_PREFIX "xaddl %0, %1" |
4025 |
++ asm volatile(LOCK_PREFIX "xaddl %0, %1\n" |
4026 |
++ |
4027 |
++#ifdef CONFIG_PAX_REFCOUNT |
4028 |
++ "jno 0f\n" |
4029 |
++ "movl %0, %1\n" |
4030 |
++ "int $4\n0:\n" |
4031 |
++ _ASM_EXTABLE(0b, 0b) |
4032 |
++#endif |
4033 |
++ |
4034 |
+ : "+r" (i), "+m" (v->counter) |
4035 |
+ : : "memory"); |
4036 |
+ return i + __i; |
4037 |
+@@ -226,7 +332,15 @@ typedef struct { |
4038 |
+ */ |
4039 |
+ static inline void atomic64_add(long i, atomic64_t *v) |
4040 |
+ { |
4041 |
+- asm volatile(LOCK_PREFIX "addq %1,%0" |
4042 |
++ asm volatile(LOCK_PREFIX "addq %1,%0\n" |
4043 |
++ |
4044 |
++#ifdef CONFIG_PAX_REFCOUNT |
4045 |
++ "jno 0f\n" |
4046 |
++ LOCK_PREFIX "subq %1,%0\n" |
4047 |
++ "int $4\n0:\n" |
4048 |
++ _ASM_EXTABLE(0b, 0b) |
4049 |
++#endif |
4050 |
++ |
4051 |
+ : "=m" (v->counter) |
4052 |
+ : "er" (i), "m" (v->counter)); |
4053 |
+ } |
4054 |
+@@ -240,7 +354,15 @@ static inline void atomic64_add(long i, |
4055 |
+ */ |
4056 |
+ static inline void atomic64_sub(long i, atomic64_t *v) |
4057 |
+ { |
4058 |
+- asm volatile(LOCK_PREFIX "subq %1,%0" |
4059 |
++ asm volatile(LOCK_PREFIX "subq %1,%0\n" |
4060 |
++ |
4061 |
++#ifdef CONFIG_PAX_REFCOUNT |
4062 |
++ "jno 0f\n" |
4063 |
++ LOCK_PREFIX "addq %1,%0\n" |
4064 |
++ "int $4\n0:\n" |
4065 |
++ _ASM_EXTABLE(0b, 0b) |
4066 |
++#endif |
4067 |
++ |
4068 |
+ : "=m" (v->counter) |
4069 |
+ : "er" (i), "m" (v->counter)); |
4070 |
+ } |
4071 |
+@@ -258,7 +380,16 @@ static inline int atomic64_sub_and_test( |
4072 |
+ { |
4073 |
+ unsigned char c; |
4074 |
+ |
4075 |
+- asm volatile(LOCK_PREFIX "subq %2,%0; sete %1" |
4076 |
++ asm volatile(LOCK_PREFIX "subq %2,%0\n" |
4077 |
++ |
4078 |
++#ifdef CONFIG_PAX_REFCOUNT |
4079 |
++ "jno 0f\n" |
4080 |
++ LOCK_PREFIX "addq %2,%0\n" |
4081 |
++ "int $4\n0:\n" |
4082 |
++ _ASM_EXTABLE(0b, 0b) |
4083 |
++#endif |
4084 |
++ |
4085 |
++ "sete %1\n" |
4086 |
+ : "=m" (v->counter), "=qm" (c) |
4087 |
+ : "er" (i), "m" (v->counter) : "memory"); |
4088 |
+ return c; |
4089 |
+@@ -272,7 +403,19 @@ static inline int atomic64_sub_and_test( |
4090 |
+ */ |
4091 |
+ static inline void atomic64_inc(atomic64_t *v) |
4092 |
+ { |
4093 |
+- asm volatile(LOCK_PREFIX "incq %0" |
4094 |
++ asm volatile(LOCK_PREFIX "incq %0\n" |
4095 |
++ |
4096 |
++#ifdef CONFIG_PAX_REFCOUNT |
4097 |
++ "jno 0f\n" |
4098 |
++ "int $4\n0:\n" |
4099 |
++ ".pushsection .fixup,\"ax\"\n" |
4100 |
++ "1:\n" |
4101 |
++ LOCK_PREFIX "decq %0\n" |
4102 |
++ "jmp 0b\n" |
4103 |
++ ".popsection\n" |
4104 |
++ _ASM_EXTABLE(0b, 1b) |
4105 |
++#endif |
4106 |
++ |
4107 |
+ : "=m" (v->counter) |
4108 |
+ : "m" (v->counter)); |
4109 |
+ } |
4110 |
+@@ -285,7 +428,19 @@ static inline void atomic64_inc(atomic64 |
4111 |
+ */ |
4112 |
+ static inline void atomic64_dec(atomic64_t *v) |
4113 |
+ { |
4114 |
+- asm volatile(LOCK_PREFIX "decq %0" |
4115 |
++ asm volatile(LOCK_PREFIX "decq %0\n" |
4116 |
++ |
4117 |
++#ifdef CONFIG_PAX_REFCOUNT |
4118 |
++ "jno 0f\n" |
4119 |
++ "int $4\n0:\n" |
4120 |
++ ".pushsection .fixup,\"ax\"\n" |
4121 |
++ "1: \n" |
4122 |
++ LOCK_PREFIX "incq %0\n" |
4123 |
++ "jmp 0b\n" |
4124 |
++ ".popsection\n" |
4125 |
++ _ASM_EXTABLE(0b, 1b) |
4126 |
++#endif |
4127 |
++ |
4128 |
+ : "=m" (v->counter) |
4129 |
+ : "m" (v->counter)); |
4130 |
+ } |
4131 |
+@@ -302,7 +457,20 @@ static inline int atomic64_dec_and_test( |
4132 |
+ { |
4133 |
+ unsigned char c; |
4134 |
+ |
4135 |
+- asm volatile(LOCK_PREFIX "decq %0; sete %1" |
4136 |
++ asm volatile(LOCK_PREFIX "decq %0\n" |
4137 |
++ |
4138 |
++#ifdef CONFIG_PAX_REFCOUNT |
4139 |
++ "jno 0f\n" |
4140 |
++ "int $4\n0:\n" |
4141 |
++ ".pushsection .fixup,\"ax\"\n" |
4142 |
++ "1: \n" |
4143 |
++ LOCK_PREFIX "incq %0\n" |
4144 |
++ "jmp 0b\n" |
4145 |
++ ".popsection\n" |
4146 |
++ _ASM_EXTABLE(0b, 1b) |
4147 |
++#endif |
4148 |
++ |
4149 |
++ "sete %1\n" |
4150 |
+ : "=m" (v->counter), "=qm" (c) |
4151 |
+ : "m" (v->counter) : "memory"); |
4152 |
+ return c != 0; |
4153 |
+@@ -320,7 +488,20 @@ static inline int atomic64_inc_and_test( |
4154 |
+ { |
4155 |
+ unsigned char c; |
4156 |
+ |
4157 |
+- asm volatile(LOCK_PREFIX "incq %0; sete %1" |
4158 |
++ asm volatile(LOCK_PREFIX "incq %0\n" |
4159 |
++ |
4160 |
++#ifdef CONFIG_PAX_REFCOUNT |
4161 |
++ "jno 0f\n" |
4162 |
++ "int $4\n0:\n" |
4163 |
++ ".pushsection .fixup,\"ax\"\n" |
4164 |
++ "1: \n" |
4165 |
++ LOCK_PREFIX "decq %0\n" |
4166 |
++ "jmp 0b\n" |
4167 |
++ ".popsection\n" |
4168 |
++ _ASM_EXTABLE(0b, 1b) |
4169 |
++#endif |
4170 |
++ |
4171 |
++ "sete %1\n" |
4172 |
+ : "=m" (v->counter), "=qm" (c) |
4173 |
+ : "m" (v->counter) : "memory"); |
4174 |
+ return c != 0; |
4175 |
+@@ -339,7 +520,16 @@ static inline int atomic64_add_negative( |
4176 |
+ { |
4177 |
+ unsigned char c; |
4178 |
+ |
4179 |
+- asm volatile(LOCK_PREFIX "addq %2,%0; sets %1" |
4180 |
++ asm volatile(LOCK_PREFIX "addq %2,%0\n" |
4181 |
++ |
4182 |
++#ifdef CONFIG_PAX_REFCOUNT |
4183 |
++ "jno 0f\n" |
4184 |
++ LOCK_PREFIX "subq %2,%0\n" |
4185 |
++ "int $4\n0:\n" |
4186 |
++ _ASM_EXTABLE(0b, 0b) |
4187 |
++#endif |
4188 |
++ |
4189 |
++ "sets %1\n" |
4190 |
+ : "=m" (v->counter), "=qm" (c) |
4191 |
+ : "er" (i), "m" (v->counter) : "memory"); |
4192 |
+ return c; |
4193 |
+@@ -355,7 +545,15 @@ static inline int atomic64_add_negative( |
4194 |
+ static inline long atomic64_add_return(long i, atomic64_t *v) |
4195 |
+ { |
4196 |
+ long __i = i; |
4197 |
+- asm volatile(LOCK_PREFIX "xaddq %0, %1;" |
4198 |
++ asm volatile(LOCK_PREFIX "xaddq %0, %1\n" |
4199 |
++ |
4200 |
++#ifdef CONFIG_PAX_REFCOUNT |
4201 |
++ "jno 0f\n" |
4202 |
++ "movq %0, %1\n" |
4203 |
++ "int $4\n0:\n" |
4204 |
++ _ASM_EXTABLE(0b, 0b) |
4205 |
++#endif |
4206 |
++ |
4207 |
+ : "+r" (i), "+m" (v->counter) |
4208 |
+ : : "memory"); |
4209 |
+ return i + __i; |
4210 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/boot.h linux-2.6.28.8/arch/x86/include/asm/boot.h |
4211 |
+--- linux-2.6.28.8/arch/x86/include/asm/boot.h 2009-02-06 16:47:45.000000000 -0500 |
4212 |
++++ linux-2.6.28.8/arch/x86/include/asm/boot.h 2009-02-21 09:37:48.000000000 -0500 |
4213 |
+@@ -11,10 +11,15 @@ |
4214 |
+ #define ASK_VGA 0xfffd /* ask for it at bootup */ |
4215 |
+ |
4216 |
+ /* Physical address where kernel should be loaded. */ |
4217 |
+-#define LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ |
4218 |
++#define ____LOAD_PHYSICAL_ADDR ((CONFIG_PHYSICAL_START \ |
4219 |
+ + (CONFIG_PHYSICAL_ALIGN - 1)) \ |
4220 |
+ & ~(CONFIG_PHYSICAL_ALIGN - 1)) |
4221 |
+ |
4222 |
++#ifndef __ASSEMBLY__ |
4223 |
++extern unsigned char __LOAD_PHYSICAL_ADDR[]; |
4224 |
++#define LOAD_PHYSICAL_ADDR ((unsigned long)__LOAD_PHYSICAL_ADDR) |
4225 |
++#endif |
4226 |
++ |
4227 |
+ #ifdef CONFIG_X86_64 |
4228 |
+ #define BOOT_HEAP_SIZE 0x7000 |
4229 |
+ #define BOOT_STACK_SIZE 0x4000 |
4230 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/cache.h linux-2.6.28.8/arch/x86/include/asm/cache.h |
4231 |
+--- linux-2.6.28.8/arch/x86/include/asm/cache.h 2009-02-06 16:47:45.000000000 -0500 |
4232 |
++++ linux-2.6.28.8/arch/x86/include/asm/cache.h 2009-02-21 09:37:48.000000000 -0500 |
4233 |
+@@ -6,6 +6,7 @@ |
4234 |
+ #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) |
4235 |
+ |
4236 |
+ #define __read_mostly __attribute__((__section__(".data.read_mostly"))) |
4237 |
++#define __read_only __attribute__((__section__(".data.read_only"))) |
4238 |
+ |
4239 |
+ #ifdef CONFIG_X86_VSMP |
4240 |
+ /* vSMP Internode cacheline shift */ |
4241 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/checksum_32.h linux-2.6.28.8/arch/x86/include/asm/checksum_32.h |
4242 |
+--- linux-2.6.28.8/arch/x86/include/asm/checksum_32.h 2009-02-06 16:47:45.000000000 -0500 |
4243 |
++++ linux-2.6.28.8/arch/x86/include/asm/checksum_32.h 2009-02-21 09:37:48.000000000 -0500 |
4244 |
+@@ -31,6 +31,14 @@ asmlinkage __wsum csum_partial_copy_gene |
4245 |
+ int len, __wsum sum, |
4246 |
+ int *src_err_ptr, int *dst_err_ptr); |
4247 |
+ |
4248 |
++asmlinkage __wsum csum_partial_copy_generic_to_user(const void *src, void *dst, |
4249 |
++ int len, __wsum sum, |
4250 |
++ int *src_err_ptr, int *dst_err_ptr); |
4251 |
++ |
4252 |
++asmlinkage __wsum csum_partial_copy_generic_from_user(const void *src, void *dst, |
4253 |
++ int len, __wsum sum, |
4254 |
++ int *src_err_ptr, int *dst_err_ptr); |
4255 |
++ |
4256 |
+ /* |
4257 |
+ * Note: when you get a NULL pointer exception here this means someone |
4258 |
+ * passed in an incorrect kernel address to one of these functions. |
4259 |
+@@ -50,7 +58,7 @@ static inline __wsum csum_partial_copy_f |
4260 |
+ int *err_ptr) |
4261 |
+ { |
4262 |
+ might_sleep(); |
4263 |
+- return csum_partial_copy_generic((__force void *)src, dst, |
4264 |
++ return csum_partial_copy_generic_from_user((__force void *)src, dst, |
4265 |
+ len, sum, err_ptr, NULL); |
4266 |
+ } |
4267 |
+ |
4268 |
+@@ -177,7 +185,7 @@ static inline __wsum csum_and_copy_to_us |
4269 |
+ { |
4270 |
+ might_sleep(); |
4271 |
+ if (access_ok(VERIFY_WRITE, dst, len)) |
4272 |
+- return csum_partial_copy_generic(src, (__force void *)dst, |
4273 |
++ return csum_partial_copy_generic_to_user(src, (__force void *)dst, |
4274 |
+ len, sum, NULL, err_ptr); |
4275 |
+ |
4276 |
+ if (len) |
4277 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/cpufeature.h linux-2.6.28.8/arch/x86/include/asm/cpufeature.h |
4278 |
+--- linux-2.6.28.8/arch/x86/include/asm/cpufeature.h 2009-02-06 16:47:45.000000000 -0500 |
4279 |
++++ linux-2.6.28.8/arch/x86/include/asm/cpufeature.h 2009-02-21 09:37:48.000000000 -0500 |
4280 |
+@@ -80,7 +80,6 @@ |
4281 |
+ #define X86_FEATURE_UP (3*32+ 9) /* smp kernel running on up */ |
4282 |
+ #define X86_FEATURE_FXSAVE_LEAK (3*32+10) /* "" FXSAVE leaks FOP/FIP/FOP */ |
4283 |
+ #define X86_FEATURE_ARCH_PERFMON (3*32+11) /* Intel Architectural PerfMon */ |
4284 |
+-#define X86_FEATURE_NOPL (3*32+20) /* The NOPL (0F 1F) instructions */ |
4285 |
+ #define X86_FEATURE_PEBS (3*32+12) /* Precise-Event Based Sampling */ |
4286 |
+ #define X86_FEATURE_BTS (3*32+13) /* Branch Trace Store */ |
4287 |
+ #define X86_FEATURE_SYSCALL32 (3*32+14) /* "" syscall in ia32 userspace */ |
4288 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/desc.h linux-2.6.28.8/arch/x86/include/asm/desc.h |
4289 |
+--- linux-2.6.28.8/arch/x86/include/asm/desc.h 2009-02-06 16:47:45.000000000 -0500 |
4290 |
++++ linux-2.6.28.8/arch/x86/include/asm/desc.h 2009-02-21 09:37:48.000000000 -0500 |
4291 |
+@@ -16,6 +16,7 @@ static inline void fill_ldt(struct desc_ |
4292 |
+ desc->base1 = (info->base_addr & 0x00ff0000) >> 16; |
4293 |
+ desc->type = (info->read_exec_only ^ 1) << 1; |
4294 |
+ desc->type |= info->contents << 2; |
4295 |
++ desc->type |= info->seg_not_present ^ 1; |
4296 |
+ desc->s = 1; |
4297 |
+ desc->dpl = 0x3; |
4298 |
+ desc->p = info->seg_not_present ^ 1; |
4299 |
+@@ -32,16 +33,12 @@ static inline void fill_ldt(struct desc_ |
4300 |
+ } |
4301 |
+ |
4302 |
+ extern struct desc_ptr idt_descr; |
4303 |
+-extern gate_desc idt_table[]; |
4304 |
+- |
4305 |
+-struct gdt_page { |
4306 |
+- struct desc_struct gdt[GDT_ENTRIES]; |
4307 |
+-} __attribute__((aligned(PAGE_SIZE))); |
4308 |
+-DECLARE_PER_CPU(struct gdt_page, gdt_page); |
4309 |
++extern gate_desc idt_table[256]; |
4310 |
+ |
4311 |
++extern struct desc_struct cpu_gdt_table[NR_CPUS][PAGE_SIZE / sizeof(struct desc_struct)]; |
4312 |
+ static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu) |
4313 |
+ { |
4314 |
+- return per_cpu(gdt_page, cpu).gdt; |
4315 |
++ return cpu_gdt_table[cpu]; |
4316 |
+ } |
4317 |
+ |
4318 |
+ #ifdef CONFIG_X86_64 |
4319 |
+@@ -115,19 +112,48 @@ static inline void paravirt_free_ldt(str |
4320 |
+ static inline void native_write_idt_entry(gate_desc *idt, int entry, |
4321 |
+ const gate_desc *gate) |
4322 |
+ { |
4323 |
++ |
4324 |
++#ifdef CONFIG_PAX_KERNEXEC |
4325 |
++ unsigned long cr0; |
4326 |
++ |
4327 |
++ pax_open_kernel(cr0); |
4328 |
++#endif |
4329 |
++ |
4330 |
+ memcpy(&idt[entry], gate, sizeof(*gate)); |
4331 |
++ |
4332 |
++#ifdef CONFIG_PAX_KERNEXEC |
4333 |
++ pax_close_kernel(cr0); |
4334 |
++#endif |
4335 |
++ |
4336 |
+ } |
4337 |
+ |
4338 |
+ static inline void native_write_ldt_entry(struct desc_struct *ldt, int entry, |
4339 |
+ const void *desc) |
4340 |
+ { |
4341 |
++ |
4342 |
++#ifdef CONFIG_PAX_KERNEXEC |
4343 |
++ unsigned long cr0; |
4344 |
++ |
4345 |
++ pax_open_kernel(cr0); |
4346 |
++#endif |
4347 |
++ |
4348 |
+ memcpy(&ldt[entry], desc, 8); |
4349 |
++ |
4350 |
++#ifdef CONFIG_PAX_KERNEXEC |
4351 |
++ pax_close_kernel(cr0); |
4352 |
++#endif |
4353 |
++ |
4354 |
+ } |
4355 |
+ |
4356 |
+ static inline void native_write_gdt_entry(struct desc_struct *gdt, int entry, |
4357 |
+ const void *desc, int type) |
4358 |
+ { |
4359 |
+ unsigned int size; |
4360 |
++ |
4361 |
++#ifdef CONFIG_PAX_KERNEXEC |
4362 |
++ unsigned long cr0; |
4363 |
++#endif |
4364 |
++ |
4365 |
+ switch (type) { |
4366 |
+ case DESC_TSS: |
4367 |
+ size = sizeof(tss_desc); |
4368 |
+@@ -139,7 +165,17 @@ static inline void native_write_gdt_entr |
4369 |
+ size = sizeof(struct desc_struct); |
4370 |
+ break; |
4371 |
+ } |
4372 |
++ |
4373 |
++#ifdef CONFIG_PAX_KERNEXEC |
4374 |
++ pax_open_kernel(cr0); |
4375 |
++#endif |
4376 |
++ |
4377 |
+ memcpy(&gdt[entry], desc, size); |
4378 |
++ |
4379 |
++#ifdef CONFIG_PAX_KERNEXEC |
4380 |
++ pax_close_kernel(cr0); |
4381 |
++#endif |
4382 |
++ |
4383 |
+ } |
4384 |
+ |
4385 |
+ static inline void pack_descriptor(struct desc_struct *desc, unsigned long base, |
4386 |
+@@ -211,7 +247,19 @@ static inline void native_set_ldt(const |
4387 |
+ |
4388 |
+ static inline void native_load_tr_desc(void) |
4389 |
+ { |
4390 |
++ |
4391 |
++#ifdef CONFIG_PAX_KERNEXEC |
4392 |
++ unsigned long cr0; |
4393 |
++ |
4394 |
++ pax_open_kernel(cr0); |
4395 |
++#endif |
4396 |
++ |
4397 |
+ asm volatile("ltr %w0"::"q" (GDT_ENTRY_TSS*8)); |
4398 |
++ |
4399 |
++#ifdef CONFIG_PAX_KERNEXEC |
4400 |
++ pax_close_kernel(cr0); |
4401 |
++#endif |
4402 |
++ |
4403 |
+ } |
4404 |
+ |
4405 |
+ static inline void native_load_gdt(const struct desc_ptr *dtr) |
4406 |
+@@ -246,8 +294,19 @@ static inline void native_load_tls(struc |
4407 |
+ unsigned int i; |
4408 |
+ struct desc_struct *gdt = get_cpu_gdt_table(cpu); |
4409 |
+ |
4410 |
++#ifdef CONFIG_PAX_KERNEXEC |
4411 |
++ unsigned long cr0; |
4412 |
++ |
4413 |
++ pax_open_kernel(cr0); |
4414 |
++#endif |
4415 |
++ |
4416 |
+ for (i = 0; i < GDT_ENTRY_TLS_ENTRIES; i++) |
4417 |
+ gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i]; |
4418 |
++ |
4419 |
++#ifdef CONFIG_PAX_KERNEXEC |
4420 |
++ pax_close_kernel(cr0); |
4421 |
++#endif |
4422 |
++ |
4423 |
+ } |
4424 |
+ |
4425 |
+ #define _LDT_empty(info) \ |
4426 |
+@@ -381,6 +440,18 @@ static inline void set_system_intr_gate_ |
4427 |
+ _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS); |
4428 |
+ } |
4429 |
+ |
4430 |
++#ifdef CONFIG_X86_32 |
4431 |
++static inline void set_user_cs(unsigned long base, unsigned long limit, int cpu) |
4432 |
++{ |
4433 |
++ struct desc_struct d; |
4434 |
++ |
4435 |
++ if (likely(limit)) |
4436 |
++ limit = (limit - 1UL) >> PAGE_SHIFT; |
4437 |
++ pack_descriptor(&d, base, limit, 0xFB, 0xC); |
4438 |
++ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_DEFAULT_USER_CS, &d, DESCTYPE_S); |
4439 |
++} |
4440 |
++#endif |
4441 |
++ |
4442 |
+ #else |
4443 |
+ /* |
4444 |
+ * GET_DESC_BASE reads the descriptor base of the specified segment. |
4445 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/e820.h linux-2.6.28.8/arch/x86/include/asm/e820.h |
4446 |
+--- linux-2.6.28.8/arch/x86/include/asm/e820.h 2009-02-06 16:47:45.000000000 -0500 |
4447 |
++++ linux-2.6.28.8/arch/x86/include/asm/e820.h 2009-02-21 09:37:48.000000000 -0500 |
4448 |
+@@ -134,7 +134,7 @@ extern char *memory_setup(void); |
4449 |
+ #define ISA_END_ADDRESS 0x100000 |
4450 |
+ #define is_ISA_range(s, e) ((s) >= ISA_START_ADDRESS && (e) < ISA_END_ADDRESS) |
4451 |
+ |
4452 |
+-#define BIOS_BEGIN 0x000a0000 |
4453 |
++#define BIOS_BEGIN 0x000c0000 |
4454 |
+ #define BIOS_END 0x00100000 |
4455 |
+ |
4456 |
+ #ifdef __KERNEL__ |
4457 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/elf.h linux-2.6.28.8/arch/x86/include/asm/elf.h |
4458 |
+--- linux-2.6.28.8/arch/x86/include/asm/elf.h 2009-02-06 16:47:45.000000000 -0500 |
4459 |
++++ linux-2.6.28.8/arch/x86/include/asm/elf.h 2009-02-21 09:37:48.000000000 -0500 |
4460 |
+@@ -252,7 +252,25 @@ extern int force_personality32; |
4461 |
+ the loader. We need to make sure that it is out of the way of the program |
4462 |
+ that it will "exec", and that there is sufficient room for the brk. */ |
4463 |
+ |
4464 |
++#ifdef CONFIG_PAX_SEGMEXEC |
4465 |
++#define ELF_ET_DYN_BASE ((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3*2 : TASK_SIZE/3*2) |
4466 |
++#else |
4467 |
+ #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) |
4468 |
++#endif |
4469 |
++ |
4470 |
++#ifdef CONFIG_PAX_ASLR |
4471 |
++#ifdef CONFIG_X86_32 |
4472 |
++#define PAX_ELF_ET_DYN_BASE 0x10000000UL |
4473 |
++ |
4474 |
++#define PAX_DELTA_MMAP_LEN (current->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16) |
4475 |
++#define PAX_DELTA_STACK_LEN (current->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16) |
4476 |
++#else |
4477 |
++#define PAX_ELF_ET_DYN_BASE 0x400000UL |
4478 |
++ |
4479 |
++#define PAX_DELTA_MMAP_LEN ((test_thread_flag(TIF_IA32)) ? 16 : 32) |
4480 |
++#define PAX_DELTA_STACK_LEN ((test_thread_flag(TIF_IA32)) ? 16 : 32) |
4481 |
++#endif |
4482 |
++#endif |
4483 |
+ |
4484 |
+ /* This yields a mask that user programs can use to figure out what |
4485 |
+ instruction set this CPU supports. This could be done in user space, |
4486 |
+@@ -304,8 +322,7 @@ do { \ |
4487 |
+ #define ARCH_DLINFO \ |
4488 |
+ do { \ |
4489 |
+ if (vdso_enabled) \ |
4490 |
+- NEW_AUX_ENT(AT_SYSINFO_EHDR, \ |
4491 |
+- (unsigned long)current->mm->context.vdso); \ |
4492 |
++ NEW_AUX_ENT(AT_SYSINFO_EHDR, current->mm->context.vdso);\ |
4493 |
+ } while (0) |
4494 |
+ |
4495 |
+ #define AT_SYSINFO 32 |
4496 |
+@@ -316,7 +333,7 @@ do { \ |
4497 |
+ |
4498 |
+ #endif /* !CONFIG_X86_32 */ |
4499 |
+ |
4500 |
+-#define VDSO_CURRENT_BASE ((unsigned long)current->mm->context.vdso) |
4501 |
++#define VDSO_CURRENT_BASE (current->mm->context.vdso) |
4502 |
+ |
4503 |
+ #define VDSO_ENTRY \ |
4504 |
+ ((unsigned long)VDSO32_SYMBOL(VDSO_CURRENT_BASE, vsyscall)) |
4505 |
+@@ -330,7 +347,4 @@ extern int arch_setup_additional_pages(s |
4506 |
+ extern int syscall32_setup_pages(struct linux_binprm *, int exstack); |
4507 |
+ #define compat_arch_setup_additional_pages syscall32_setup_pages |
4508 |
+ |
4509 |
+-extern unsigned long arch_randomize_brk(struct mm_struct *mm); |
4510 |
+-#define arch_randomize_brk arch_randomize_brk |
4511 |
+- |
4512 |
+ #endif /* _ASM_X86_ELF_H */ |
4513 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/futex.h linux-2.6.28.8/arch/x86/include/asm/futex.h |
4514 |
+--- linux-2.6.28.8/arch/x86/include/asm/futex.h 2009-02-06 16:47:45.000000000 -0500 |
4515 |
++++ linux-2.6.28.8/arch/x86/include/asm/futex.h 2009-02-21 09:37:48.000000000 -0500 |
4516 |
+@@ -11,6 +11,40 @@ |
4517 |
+ #include <asm/processor.h> |
4518 |
+ #include <asm/system.h> |
4519 |
+ |
4520 |
++#ifdef CONFIG_X86_32 |
4521 |
++#define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \ |
4522 |
++ asm volatile( \ |
4523 |
++ "movw\t%w6, %%ds\n" \ |
4524 |
++ "1:\t" insn "\n" \ |
4525 |
++ "2:\tpushl\t%%ss\n" \ |
4526 |
++ "\tpopl\t%%ds\n" \ |
4527 |
++ "\t.section .fixup,\"ax\"\n" \ |
4528 |
++ "3:\tmov\t%3, %1\n" \ |
4529 |
++ "\tjmp\t2b\n" \ |
4530 |
++ "\t.previous\n" \ |
4531 |
++ _ASM_EXTABLE(1b, 3b) \ |
4532 |
++ : "=r" (oldval), "=r" (ret), "+m" (*uaddr) \ |
4533 |
++ : "i" (-EFAULT), "0" (oparg), "1" (0), "r" (__USER_DS)) |
4534 |
++ |
4535 |
++#define __futex_atomic_op2(insn, ret, oldval, uaddr, oparg) \ |
4536 |
++ asm volatile("movw\t%w7, %%es\n" \ |
4537 |
++ "1:\tmovl\t%%es:%2, %0\n" \ |
4538 |
++ "\tmovl\t%0, %3\n" \ |
4539 |
++ "\t" insn "\n" \ |
4540 |
++ "2:\t" LOCK_PREFIX "cmpxchgl %3, %%es:%2\n"\ |
4541 |
++ "\tjnz\t1b\n" \ |
4542 |
++ "3:\tpushl\t%%ss\n" \ |
4543 |
++ "\tpopl\t%%es\n" \ |
4544 |
++ "\t.section .fixup,\"ax\"\n" \ |
4545 |
++ "4:\tmov\t%5, %1\n" \ |
4546 |
++ "\tjmp\t3b\n" \ |
4547 |
++ "\t.previous\n" \ |
4548 |
++ _ASM_EXTABLE(1b, 4b) \ |
4549 |
++ _ASM_EXTABLE(2b, 4b) \ |
4550 |
++ : "=&a" (oldval), "=&r" (ret), \ |
4551 |
++ "+m" (*uaddr), "=&r" (tem) \ |
4552 |
++ : "r" (oparg), "i" (-EFAULT), "1" (0), "r" (__USER_DS)) |
4553 |
++#else |
4554 |
+ #define __futex_atomic_op1(insn, ret, oldval, uaddr, oparg) \ |
4555 |
+ asm volatile("1:\t" insn "\n" \ |
4556 |
+ "2:\t.section .fixup,\"ax\"\n" \ |
4557 |
+@@ -36,8 +70,9 @@ |
4558 |
+ : "=&a" (oldval), "=&r" (ret), \ |
4559 |
+ "+m" (*uaddr), "=&r" (tem) \ |
4560 |
+ : "r" (oparg), "i" (-EFAULT), "1" (0)) |
4561 |
++#endif |
4562 |
+ |
4563 |
+-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr) |
4564 |
++static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr) |
4565 |
+ { |
4566 |
+ int op = (encoded_op >> 28) & 7; |
4567 |
+ int cmp = (encoded_op >> 24) & 15; |
4568 |
+@@ -61,11 +96,20 @@ static inline int futex_atomic_op_inuser |
4569 |
+ |
4570 |
+ switch (op) { |
4571 |
+ case FUTEX_OP_SET: |
4572 |
++#ifdef CONFIG_X86_32 |
4573 |
++ __futex_atomic_op1("xchgl %0, %%ds:%2", ret, oldval, uaddr, oparg); |
4574 |
++#else |
4575 |
+ __futex_atomic_op1("xchgl %0, %2", ret, oldval, uaddr, oparg); |
4576 |
++#endif |
4577 |
+ break; |
4578 |
+ case FUTEX_OP_ADD: |
4579 |
++#ifdef CONFIG_X86_32 |
4580 |
++ __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %%ds:%2", ret, oldval, |
4581 |
++ uaddr, oparg); |
4582 |
++#else |
4583 |
+ __futex_atomic_op1(LOCK_PREFIX "xaddl %0, %2", ret, oldval, |
4584 |
+ uaddr, oparg); |
4585 |
++#endif |
4586 |
+ break; |
4587 |
+ case FUTEX_OP_OR: |
4588 |
+ __futex_atomic_op2("orl %4, %3", ret, oldval, uaddr, oparg); |
4589 |
+@@ -109,7 +153,7 @@ static inline int futex_atomic_op_inuser |
4590 |
+ return ret; |
4591 |
+ } |
4592 |
+ |
4593 |
+-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, |
4594 |
++static inline int futex_atomic_cmpxchg_inatomic(u32 __user *uaddr, int oldval, |
4595 |
+ int newval) |
4596 |
+ { |
4597 |
+ |
4598 |
+@@ -122,14 +166,27 @@ static inline int futex_atomic_cmpxchg_i |
4599 |
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int))) |
4600 |
+ return -EFAULT; |
4601 |
+ |
4602 |
+- asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n" |
4603 |
++ asm volatile( |
4604 |
++#ifdef CONFIG_X86_32 |
4605 |
++ "\tmovw %w5, %%ds\n" |
4606 |
++ "1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n" |
4607 |
++ "2:\tpushl %%ss\n" |
4608 |
++ "\tpopl %%ds\n" |
4609 |
++ "\t.section .fixup, \"ax\"\n" |
4610 |
++#else |
4611 |
++ "1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n" |
4612 |
+ "2:\t.section .fixup, \"ax\"\n" |
4613 |
++#endif |
4614 |
+ "3:\tmov %2, %0\n" |
4615 |
+ "\tjmp 2b\n" |
4616 |
+ "\t.previous\n" |
4617 |
+ _ASM_EXTABLE(1b, 3b) |
4618 |
+ : "=a" (oldval), "+m" (*uaddr) |
4619 |
++#ifdef CONFIG_X86_32 |
4620 |
++ : "i" (-EFAULT), "r" (newval), "0" (oldval), "r" (__USER_DS) |
4621 |
++#else |
4622 |
+ : "i" (-EFAULT), "r" (newval), "0" (oldval) |
4623 |
++#endif |
4624 |
+ : "memory" |
4625 |
+ ); |
4626 |
+ |
4627 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/i387.h linux-2.6.28.8/arch/x86/include/asm/i387.h |
4628 |
+--- linux-2.6.28.8/arch/x86/include/asm/i387.h 2009-02-06 16:47:45.000000000 -0500 |
4629 |
++++ linux-2.6.28.8/arch/x86/include/asm/i387.h 2009-02-21 09:37:48.000000000 -0500 |
4630 |
+@@ -197,13 +197,8 @@ static inline void restore_fpu(struct ta |
4631 |
+ } |
4632 |
+ |
4633 |
+ /* We need a safe address that is cheap to find and that is already |
4634 |
+- in L1 during context switch. The best choices are unfortunately |
4635 |
+- different for UP and SMP */ |
4636 |
+-#ifdef CONFIG_SMP |
4637 |
+-#define safe_address (__per_cpu_offset[0]) |
4638 |
+-#else |
4639 |
+-#define safe_address (kstat_cpu(0).cpustat.user) |
4640 |
+-#endif |
4641 |
++ in L1 during context switch. */ |
4642 |
++#define safe_address (init_tss[smp_processor_id()].x86_tss.sp0) |
4643 |
+ |
4644 |
+ /* |
4645 |
+ * These must be called with preempt disabled |
4646 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/io_64.h linux-2.6.28.8/arch/x86/include/asm/io_64.h |
4647 |
+--- linux-2.6.28.8/arch/x86/include/asm/io_64.h 2009-02-06 16:47:45.000000000 -0500 |
4648 |
++++ linux-2.6.28.8/arch/x86/include/asm/io_64.h 2009-02-21 09:37:48.000000000 -0500 |
4649 |
+@@ -158,6 +158,17 @@ static inline void *phys_to_virt(unsigne |
4650 |
+ } |
4651 |
+ #endif |
4652 |
+ |
4653 |
++#define ARCH_HAS_VALID_PHYS_ADDR_RANGE |
4654 |
++static inline int valid_phys_addr_range (unsigned long addr, size_t count) |
4655 |
++{ |
4656 |
++ return ((addr + count + PAGE_SIZE - 1) >> PAGE_SHIFT) < (1 << (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) ? 1 : 0; |
4657 |
++} |
4658 |
++ |
4659 |
++static inline int valid_mmap_phys_addr_range (unsigned long pfn, size_t count) |
4660 |
++{ |
4661 |
++ return (pfn + (count >> PAGE_SHIFT)) < (1 << (boot_cpu_data.x86_phys_bits - PAGE_SHIFT)) ? 1 : 0; |
4662 |
++} |
4663 |
++ |
4664 |
+ /* |
4665 |
+ * Change "struct page" to physical address. |
4666 |
+ */ |
4667 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/irqflags.h linux-2.6.28.8/arch/x86/include/asm/irqflags.h |
4668 |
+--- linux-2.6.28.8/arch/x86/include/asm/irqflags.h 2009-02-06 16:47:45.000000000 -0500 |
4669 |
++++ linux-2.6.28.8/arch/x86/include/asm/irqflags.h 2009-02-21 09:37:48.000000000 -0500 |
4670 |
+@@ -141,6 +141,8 @@ static inline unsigned long __raw_local_ |
4671 |
+ #define INTERRUPT_RETURN iret |
4672 |
+ #define ENABLE_INTERRUPTS_SYSEXIT sti; sysexit |
4673 |
+ #define GET_CR0_INTO_EAX movl %cr0, %eax |
4674 |
++#define GET_CR0_INTO_EDX movl %cr0, %edx |
4675 |
++#define SET_CR0_FROM_EDX movl %edx, %cr0 |
4676 |
+ #endif |
4677 |
+ |
4678 |
+ |
4679 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/kmap_types.h linux-2.6.28.8/arch/x86/include/asm/kmap_types.h |
4680 |
+--- linux-2.6.28.8/arch/x86/include/asm/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
4681 |
++++ linux-2.6.28.8/arch/x86/include/asm/kmap_types.h 2009-02-21 09:37:48.000000000 -0500 |
4682 |
+@@ -21,7 +21,8 @@ D(9) KM_IRQ0, |
4683 |
+ D(10) KM_IRQ1, |
4684 |
+ D(11) KM_SOFTIRQ0, |
4685 |
+ D(12) KM_SOFTIRQ1, |
4686 |
+-D(13) KM_TYPE_NR |
4687 |
++D(13) KM_CLEARPAGE, |
4688 |
++D(14) KM_TYPE_NR |
4689 |
+ }; |
4690 |
+ |
4691 |
+ #undef D |
4692 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/kvm_host.h linux-2.6.28.8/arch/x86/include/asm/kvm_host.h |
4693 |
+--- linux-2.6.28.8/arch/x86/include/asm/kvm_host.h 2009-02-06 16:47:45.000000000 -0500 |
4694 |
++++ linux-2.6.28.8/arch/x86/include/asm/kvm_host.h 2009-02-21 09:37:48.000000000 -0500 |
4695 |
+@@ -479,7 +479,7 @@ struct kvm_x86_ops { |
4696 |
+ int (*get_tdp_level)(void); |
4697 |
+ }; |
4698 |
+ |
4699 |
+-extern struct kvm_x86_ops *kvm_x86_ops; |
4700 |
++extern const struct kvm_x86_ops *kvm_x86_ops; |
4701 |
+ |
4702 |
+ int kvm_mmu_module_init(void); |
4703 |
+ void kvm_mmu_module_exit(void); |
4704 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/linkage.h linux-2.6.28.8/arch/x86/include/asm/linkage.h |
4705 |
+--- linux-2.6.28.8/arch/x86/include/asm/linkage.h 2009-02-06 16:47:45.000000000 -0500 |
4706 |
++++ linux-2.6.28.8/arch/x86/include/asm/linkage.h 2009-02-21 09:37:48.000000000 -0500 |
4707 |
+@@ -7,6 +7,11 @@ |
4708 |
+ #ifdef CONFIG_X86_64 |
4709 |
+ #define __ALIGN .p2align 4,,15 |
4710 |
+ #define __ALIGN_STR ".p2align 4,,15" |
4711 |
++#else |
4712 |
++#ifdef CONFIG_X86_ALIGNMENT_16 |
4713 |
++#define __ALIGN .align 16,0x90 |
4714 |
++#define __ALIGN_STR ".align 16,0x90" |
4715 |
++#endif |
4716 |
+ #endif |
4717 |
+ |
4718 |
+ #ifdef CONFIG_X86_32 |
4719 |
+@@ -52,10 +57,5 @@ |
4720 |
+ |
4721 |
+ #endif |
4722 |
+ |
4723 |
+-#ifdef CONFIG_X86_ALIGNMENT_16 |
4724 |
+-#define __ALIGN .align 16,0x90 |
4725 |
+-#define __ALIGN_STR ".align 16,0x90" |
4726 |
+-#endif |
4727 |
+- |
4728 |
+ #endif /* _ASM_X86_LINKAGE_H */ |
4729 |
+ |
4730 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/local.h linux-2.6.28.8/arch/x86/include/asm/local.h |
4731 |
+--- linux-2.6.28.8/arch/x86/include/asm/local.h 2009-02-06 16:47:45.000000000 -0500 |
4732 |
++++ linux-2.6.28.8/arch/x86/include/asm/local.h 2009-02-21 09:37:48.000000000 -0500 |
4733 |
+@@ -18,26 +18,90 @@ typedef struct { |
4734 |
+ |
4735 |
+ static inline void local_inc(local_t *l) |
4736 |
+ { |
4737 |
+- asm volatile(_ASM_INC "%0" |
4738 |
++ asm volatile(_ASM_INC "%0\n" |
4739 |
++ |
4740 |
++#ifdef CONFIG_PAX_REFCOUNT |
4741 |
++#ifdef CONFIG_X86_32 |
4742 |
++ "into\n0:\n" |
4743 |
++#else |
4744 |
++ "jno 0f\n" |
4745 |
++ "int $4\n0:\n" |
4746 |
++#endif |
4747 |
++ ".pushsection .fixup,\"ax\"\n" |
4748 |
++ "1:\n" |
4749 |
++ _ASM_DEC "%0\n" |
4750 |
++ "jmp 0b\n" |
4751 |
++ ".popsection\n" |
4752 |
++ _ASM_EXTABLE(0b, 1b) |
4753 |
++#endif |
4754 |
++ |
4755 |
+ : "+m" (l->a.counter)); |
4756 |
+ } |
4757 |
+ |
4758 |
+ static inline void local_dec(local_t *l) |
4759 |
+ { |
4760 |
+- asm volatile(_ASM_DEC "%0" |
4761 |
++ asm volatile(_ASM_DEC "%0\n" |
4762 |
++ |
4763 |
++#ifdef CONFIG_PAX_REFCOUNT |
4764 |
++#ifdef CONFIG_X86_32 |
4765 |
++ "into\n0:\n" |
4766 |
++#else |
4767 |
++ "jno 0f\n" |
4768 |
++ "int $4\n0:\n" |
4769 |
++#endif |
4770 |
++ ".pushsection .fixup,\"ax\"\n" |
4771 |
++ "1:\n" |
4772 |
++ _ASM_INC "%0\n" |
4773 |
++ "jmp 0b\n" |
4774 |
++ ".popsection\n" |
4775 |
++ _ASM_EXTABLE(0b, 1b) |
4776 |
++#endif |
4777 |
++ |
4778 |
+ : "+m" (l->a.counter)); |
4779 |
+ } |
4780 |
+ |
4781 |
+ static inline void local_add(long i, local_t *l) |
4782 |
+ { |
4783 |
+- asm volatile(_ASM_ADD "%1,%0" |
4784 |
++ asm volatile(_ASM_ADD "%1,%0\n" |
4785 |
++ |
4786 |
++#ifdef CONFIG_PAX_REFCOUNT |
4787 |
++#ifdef CONFIG_X86_32 |
4788 |
++ "into\n0:\n" |
4789 |
++#else |
4790 |
++ "jno 0f\n" |
4791 |
++ "int $4\n0:\n" |
4792 |
++#endif |
4793 |
++ ".pushsection .fixup,\"ax\"\n" |
4794 |
++ "1:\n" |
4795 |
++ _ASM_SUB "%1,%0\n" |
4796 |
++ "jmp 0b\n" |
4797 |
++ ".popsection\n" |
4798 |
++ _ASM_EXTABLE(0b, 1b) |
4799 |
++#endif |
4800 |
++ |
4801 |
+ : "+m" (l->a.counter) |
4802 |
+ : "ir" (i)); |
4803 |
+ } |
4804 |
+ |
4805 |
+ static inline void local_sub(long i, local_t *l) |
4806 |
+ { |
4807 |
+- asm volatile(_ASM_SUB "%1,%0" |
4808 |
++ asm volatile(_ASM_SUB "%1,%0\n" |
4809 |
++ |
4810 |
++#ifdef CONFIG_PAX_REFCOUNT |
4811 |
++#ifdef CONFIG_X86_32 |
4812 |
++ "into\n0:\n" |
4813 |
++#else |
4814 |
++ "jno 0f\n" |
4815 |
++ "int $4\n0:\n" |
4816 |
++#endif |
4817 |
++ ".pushsection .fixup,\"ax\"\n" |
4818 |
++ "1:\n" |
4819 |
++ _ASM_ADD "%1,%0\n" |
4820 |
++ "jmp 0b\n" |
4821 |
++ ".popsection\n" |
4822 |
++ _ASM_EXTABLE(0b, 1b) |
4823 |
++#endif |
4824 |
++ |
4825 |
+ : "+m" (l->a.counter) |
4826 |
+ : "ir" (i)); |
4827 |
+ } |
4828 |
+@@ -55,7 +119,24 @@ static inline int local_sub_and_test(lon |
4829 |
+ { |
4830 |
+ unsigned char c; |
4831 |
+ |
4832 |
+- asm volatile(_ASM_SUB "%2,%0; sete %1" |
4833 |
++ asm volatile(_ASM_SUB "%2,%0\n" |
4834 |
++ |
4835 |
++#ifdef CONFIG_PAX_REFCOUNT |
4836 |
++#ifdef CONFIG_X86_32 |
4837 |
++ "into\n0:\n" |
4838 |
++#else |
4839 |
++ "jno 0f\n" |
4840 |
++ "int $4\n0:\n" |
4841 |
++#endif |
4842 |
++ ".pushsection .fixup,\"ax\"\n" |
4843 |
++ "1:\n" |
4844 |
++ _ASM_ADD "%2,%0\n" |
4845 |
++ "jmp 0b\n" |
4846 |
++ ".popsection\n" |
4847 |
++ _ASM_EXTABLE(0b, 1b) |
4848 |
++#endif |
4849 |
++ |
4850 |
++ "sete %1\n" |
4851 |
+ : "+m" (l->a.counter), "=qm" (c) |
4852 |
+ : "ir" (i) : "memory"); |
4853 |
+ return c; |
4854 |
+@@ -73,7 +154,24 @@ static inline int local_dec_and_test(loc |
4855 |
+ { |
4856 |
+ unsigned char c; |
4857 |
+ |
4858 |
+- asm volatile(_ASM_DEC "%0; sete %1" |
4859 |
++ asm volatile(_ASM_DEC "%0\n" |
4860 |
++ |
4861 |
++#ifdef CONFIG_PAX_REFCOUNT |
4862 |
++#ifdef CONFIG_X86_32 |
4863 |
++ "into\n0:\n" |
4864 |
++#else |
4865 |
++ "jno 0f\n" |
4866 |
++ "int $4\n0:\n" |
4867 |
++#endif |
4868 |
++ ".pushsection .fixup,\"ax\"\n" |
4869 |
++ "1:\n" |
4870 |
++ _ASM_INC "%0\n" |
4871 |
++ "jmp 0b\n" |
4872 |
++ ".popsection\n" |
4873 |
++ _ASM_EXTABLE(0b, 1b) |
4874 |
++#endif |
4875 |
++ |
4876 |
++ "sete %1\n" |
4877 |
+ : "+m" (l->a.counter), "=qm" (c) |
4878 |
+ : : "memory"); |
4879 |
+ return c != 0; |
4880 |
+@@ -91,7 +189,24 @@ static inline int local_inc_and_test(loc |
4881 |
+ { |
4882 |
+ unsigned char c; |
4883 |
+ |
4884 |
+- asm volatile(_ASM_INC "%0; sete %1" |
4885 |
++ asm volatile(_ASM_INC "%0\n" |
4886 |
++ |
4887 |
++#ifdef CONFIG_PAX_REFCOUNT |
4888 |
++#ifdef CONFIG_X86_32 |
4889 |
++ "into\n0:\n" |
4890 |
++#else |
4891 |
++ "jno 0f\n" |
4892 |
++ "int $4\n0:\n" |
4893 |
++#endif |
4894 |
++ ".pushsection .fixup,\"ax\"\n" |
4895 |
++ "1:\n" |
4896 |
++ _ASM_DEC "%0\n" |
4897 |
++ "jmp 0b\n" |
4898 |
++ ".popsection\n" |
4899 |
++ _ASM_EXTABLE(0b, 1b) |
4900 |
++#endif |
4901 |
++ |
4902 |
++ "sete %1\n" |
4903 |
+ : "+m" (l->a.counter), "=qm" (c) |
4904 |
+ : : "memory"); |
4905 |
+ return c != 0; |
4906 |
+@@ -110,7 +225,24 @@ static inline int local_add_negative(lon |
4907 |
+ { |
4908 |
+ unsigned char c; |
4909 |
+ |
4910 |
+- asm volatile(_ASM_ADD "%2,%0; sets %1" |
4911 |
++ asm volatile(_ASM_ADD "%2,%0\n" |
4912 |
++ |
4913 |
++#ifdef CONFIG_PAX_REFCOUNT |
4914 |
++#ifdef CONFIG_X86_32 |
4915 |
++ "into\n0:\n" |
4916 |
++#else |
4917 |
++ "jno 0f\n" |
4918 |
++ "int $4\n0:\n" |
4919 |
++#endif |
4920 |
++ ".pushsection .fixup,\"ax\"\n" |
4921 |
++ "1:\n" |
4922 |
++ _ASM_SUB "%2,%0\n" |
4923 |
++ "jmp 0b\n" |
4924 |
++ ".popsection\n" |
4925 |
++ _ASM_EXTABLE(0b, 1b) |
4926 |
++#endif |
4927 |
++ |
4928 |
++ "sets %1\n" |
4929 |
+ : "+m" (l->a.counter), "=qm" (c) |
4930 |
+ : "ir" (i) : "memory"); |
4931 |
+ return c; |
4932 |
+@@ -133,7 +265,23 @@ static inline long local_add_return(long |
4933 |
+ #endif |
4934 |
+ /* Modern 486+ processor */ |
4935 |
+ __i = i; |
4936 |
+- asm volatile(_ASM_XADD "%0, %1;" |
4937 |
++ asm volatile(_ASM_XADD "%0, %1\n" |
4938 |
++ |
4939 |
++#ifdef CONFIG_PAX_REFCOUNT |
4940 |
++#ifdef CONFIG_X86_32 |
4941 |
++ "into\n0:\n" |
4942 |
++#else |
4943 |
++ "jno 0f\n" |
4944 |
++ "int $4\n0:\n" |
4945 |
++#endif |
4946 |
++ ".pushsection .fixup,\"ax\"\n" |
4947 |
++ "1:\n" |
4948 |
++ _ASM_MOV "%0,%1\n" |
4949 |
++ "jmp 0b\n" |
4950 |
++ ".popsection\n" |
4951 |
++ _ASM_EXTABLE(0b, 1b) |
4952 |
++#endif |
4953 |
++ |
4954 |
+ : "+r" (i), "+m" (l->a.counter) |
4955 |
+ : : "memory"); |
4956 |
+ return i + __i; |
4957 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/mach-default/apm.h linux-2.6.28.8/arch/x86/include/asm/mach-default/apm.h |
4958 |
+--- linux-2.6.28.8/arch/x86/include/asm/mach-default/apm.h 2009-02-06 16:47:45.000000000 -0500 |
4959 |
++++ linux-2.6.28.8/arch/x86/include/asm/mach-default/apm.h 2009-02-21 09:37:48.000000000 -0500 |
4960 |
+@@ -34,7 +34,7 @@ static inline void apm_bios_call_asm(u32 |
4961 |
+ __asm__ __volatile__(APM_DO_ZERO_SEGS |
4962 |
+ "pushl %%edi\n\t" |
4963 |
+ "pushl %%ebp\n\t" |
4964 |
+- "lcall *%%cs:apm_bios_entry\n\t" |
4965 |
++ "lcall *%%ss:apm_bios_entry\n\t" |
4966 |
+ "setc %%al\n\t" |
4967 |
+ "popl %%ebp\n\t" |
4968 |
+ "popl %%edi\n\t" |
4969 |
+@@ -58,7 +58,7 @@ static inline u8 apm_bios_call_simple_as |
4970 |
+ __asm__ __volatile__(APM_DO_ZERO_SEGS |
4971 |
+ "pushl %%edi\n\t" |
4972 |
+ "pushl %%ebp\n\t" |
4973 |
+- "lcall *%%cs:apm_bios_entry\n\t" |
4974 |
++ "lcall *%%ss:apm_bios_entry\n\t" |
4975 |
+ "setc %%bl\n\t" |
4976 |
+ "popl %%ebp\n\t" |
4977 |
+ "popl %%edi\n\t" |
4978 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/mman.h linux-2.6.28.8/arch/x86/include/asm/mman.h |
4979 |
+--- linux-2.6.28.8/arch/x86/include/asm/mman.h 2009-02-06 16:47:45.000000000 -0500 |
4980 |
++++ linux-2.6.28.8/arch/x86/include/asm/mman.h 2009-02-21 09:37:48.000000000 -0500 |
4981 |
+@@ -17,4 +17,14 @@ |
4982 |
+ #define MCL_CURRENT 1 /* lock all current mappings */ |
4983 |
+ #define MCL_FUTURE 2 /* lock all future mappings */ |
4984 |
+ |
4985 |
++#ifdef __KERNEL__ |
4986 |
++#ifndef __ASSEMBLY__ |
4987 |
++#ifdef CONFIG_X86_32 |
4988 |
++#define arch_mmap_check i386_mmap_check |
4989 |
++int i386_mmap_check(unsigned long addr, unsigned long len, |
4990 |
++ unsigned long flags); |
4991 |
++#endif |
4992 |
++#endif |
4993 |
++#endif |
4994 |
++ |
4995 |
+ #endif /* _ASM_X86_MMAN_H */ |
4996 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/mmu_context_32.h linux-2.6.28.8/arch/x86/include/asm/mmu_context_32.h |
4997 |
+--- linux-2.6.28.8/arch/x86/include/asm/mmu_context_32.h 2009-02-06 16:47:45.000000000 -0500 |
4998 |
++++ linux-2.6.28.8/arch/x86/include/asm/mmu_context_32.h 2009-02-21 09:37:48.000000000 -0500 |
4999 |
+@@ -33,6 +33,22 @@ static inline void switch_mm(struct mm_s |
5000 |
+ */ |
5001 |
+ if (unlikely(prev->context.ldt != next->context.ldt)) |
5002 |
+ load_LDT_nolock(&next->context); |
5003 |
++ |
5004 |
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP) |
5005 |
++ if (!nx_enabled) { |
5006 |
++ smp_mb__before_clear_bit(); |
5007 |
++ cpu_clear(cpu, prev->context.cpu_user_cs_mask); |
5008 |
++ smp_mb__after_clear_bit(); |
5009 |
++ cpu_set(cpu, next->context.cpu_user_cs_mask); |
5010 |
++ } |
5011 |
++#endif |
5012 |
++ |
5013 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
5014 |
++ if (unlikely(prev->context.user_cs_base != next->context.user_cs_base || |
5015 |
++ prev->context.user_cs_limit != next->context.user_cs_limit)) |
5016 |
++ set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu); |
5017 |
++#endif |
5018 |
++ |
5019 |
+ } |
5020 |
+ #ifdef CONFIG_SMP |
5021 |
+ else { |
5022 |
+@@ -45,6 +61,19 @@ static inline void switch_mm(struct mm_s |
5023 |
+ */ |
5024 |
+ load_cr3(next->pgd); |
5025 |
+ load_LDT_nolock(&next->context); |
5026 |
++ |
5027 |
++#ifdef CONFIG_PAX_PAGEEXEC |
5028 |
++ if (!nx_enabled) |
5029 |
++ cpu_set(cpu, next->context.cpu_user_cs_mask); |
5030 |
++#endif |
5031 |
++ |
5032 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
5033 |
++#ifdef CONFIG_PAX_PAGEEXEC |
5034 |
++ if (!((next->pax_flags & MF_PAX_PAGEEXEC) && nx_enabled)) |
5035 |
++#endif |
5036 |
++ set_user_cs(next->context.user_cs_base, next->context.user_cs_limit, cpu); |
5037 |
++#endif |
5038 |
++ |
5039 |
+ } |
5040 |
+ } |
5041 |
+ #endif |
5042 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/mmu.h linux-2.6.28.8/arch/x86/include/asm/mmu.h |
5043 |
+--- linux-2.6.28.8/arch/x86/include/asm/mmu.h 2009-02-06 16:47:45.000000000 -0500 |
5044 |
++++ linux-2.6.28.8/arch/x86/include/asm/mmu.h 2009-02-21 09:37:48.000000000 -0500 |
5045 |
+@@ -9,10 +9,23 @@ |
5046 |
+ * we put the segment information here. |
5047 |
+ */ |
5048 |
+ typedef struct { |
5049 |
+- void *ldt; |
5050 |
++ struct desc_struct *ldt; |
5051 |
+ int size; |
5052 |
+ struct mutex lock; |
5053 |
+- void *vdso; |
5054 |
++ unsigned long vdso; |
5055 |
++ |
5056 |
++#ifdef CONFIG_X86_32 |
5057 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
5058 |
++ unsigned long user_cs_base; |
5059 |
++ unsigned long user_cs_limit; |
5060 |
++ |
5061 |
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP) |
5062 |
++ cpumask_t cpu_user_cs_mask; |
5063 |
++#endif |
5064 |
++ |
5065 |
++#endif |
5066 |
++#endif |
5067 |
++ |
5068 |
+ } mm_context_t; |
5069 |
+ |
5070 |
+ #ifdef CONFIG_SMP |
5071 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/module.h linux-2.6.28.8/arch/x86/include/asm/module.h |
5072 |
+--- linux-2.6.28.8/arch/x86/include/asm/module.h 2009-02-06 16:47:45.000000000 -0500 |
5073 |
++++ linux-2.6.28.8/arch/x86/include/asm/module.h 2009-02-21 09:37:48.000000000 -0500 |
5074 |
+@@ -74,7 +74,12 @@ struct mod_arch_specific {}; |
5075 |
+ # else |
5076 |
+ # define MODULE_STACKSIZE "" |
5077 |
+ # endif |
5078 |
+-# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE |
5079 |
++# ifdef CONFIG_GRKERNSEC |
5080 |
++# define MODULE_GRSEC "GRSECURITY " |
5081 |
++# else |
5082 |
++# define MODULE_GRSEC "" |
5083 |
++# endif |
5084 |
++# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_STACKSIZE MODULE_GRSEC |
5085 |
+ #endif |
5086 |
+ |
5087 |
+ #endif /* _ASM_X86_MODULE_H */ |
5088 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/page_32.h linux-2.6.28.8/arch/x86/include/asm/page_32.h |
5089 |
+--- linux-2.6.28.8/arch/x86/include/asm/page_32.h 2009-02-06 16:47:45.000000000 -0500 |
5090 |
++++ linux-2.6.28.8/arch/x86/include/asm/page_32.h 2009-02-21 09:37:48.000000000 -0500 |
5091 |
+@@ -13,6 +13,23 @@ |
5092 |
+ */ |
5093 |
+ #define __PAGE_OFFSET _AC(CONFIG_PAGE_OFFSET, UL) |
5094 |
+ |
5095 |
++#ifdef CONFIG_PAX_KERNEXEC |
5096 |
++#ifndef __ASSEMBLY__ |
5097 |
++extern unsigned char MODULES_VADDR[]; |
5098 |
++extern unsigned char MODULES_END[]; |
5099 |
++extern unsigned char KERNEL_TEXT_OFFSET[]; |
5100 |
++#define ktla_ktva(addr) (addr + (unsigned long)KERNEL_TEXT_OFFSET) |
5101 |
++#define ktva_ktla(addr) (addr - (unsigned long)KERNEL_TEXT_OFFSET) |
5102 |
++#endif |
5103 |
++#else |
5104 |
++#define ktla_ktva(addr) (addr) |
5105 |
++#define ktva_ktla(addr) (addr) |
5106 |
++#endif |
5107 |
++ |
5108 |
++#ifdef CONFIG_PAX_PAGEEXEC |
5109 |
++#define CONFIG_ARCH_TRACK_EXEC_LIMIT 1 |
5110 |
++#endif |
5111 |
++ |
5112 |
+ #ifdef CONFIG_4KSTACKS |
5113 |
+ #define THREAD_ORDER 0 |
5114 |
+ #else |
5115 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/page_64.h linux-2.6.28.8/arch/x86/include/asm/page_64.h |
5116 |
+--- linux-2.6.28.8/arch/x86/include/asm/page_64.h 2009-02-06 16:47:45.000000000 -0500 |
5117 |
++++ linux-2.6.28.8/arch/x86/include/asm/page_64.h 2009-02-21 09:37:48.000000000 -0500 |
5118 |
+@@ -49,6 +49,9 @@ |
5119 |
+ #define __START_KERNEL (__START_KERNEL_map + __PHYSICAL_START) |
5120 |
+ #define __START_KERNEL_map _AC(0xffffffff80000000, UL) |
5121 |
+ |
5122 |
++#define ktla_ktva(addr) (addr) |
5123 |
++#define ktva_ktla(addr) (addr) |
5124 |
++ |
5125 |
+ /* See Documentation/x86_64/mm.txt for a description of the memory map. */ |
5126 |
+ #define __PHYSICAL_MASK_SHIFT 46 |
5127 |
+ #define __VIRTUAL_MASK_SHIFT 48 |
5128 |
+@@ -101,5 +104,6 @@ extern void init_extra_mapping_wb(unsign |
5129 |
+ #define pfn_valid(pfn) ((pfn) < max_pfn) |
5130 |
+ #endif |
5131 |
+ |
5132 |
++#define nx_enabled (1) |
5133 |
+ |
5134 |
+ #endif /* _ASM_X86_PAGE_64_H */ |
5135 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/paravirt.h linux-2.6.28.8/arch/x86/include/asm/paravirt.h |
5136 |
+--- linux-2.6.28.8/arch/x86/include/asm/paravirt.h 2009-03-07 10:24:49.000000000 -0500 |
5137 |
++++ linux-2.6.28.8/arch/x86/include/asm/paravirt.h 2009-03-07 10:29:51.000000000 -0500 |
5138 |
+@@ -1557,7 +1557,7 @@ static inline unsigned long __raw_local_ |
5139 |
+ #define PV_RESTORE_REGS popl %edx; popl %ecx; popl %edi; popl %eax |
5140 |
+ #define PARA_PATCH(struct, off) ((PARAVIRT_PATCH_##struct + (off)) / 4) |
5141 |
+ #define PARA_SITE(ptype, clobbers, ops) _PVSITE(ptype, clobbers, ops, .long, 4) |
5142 |
+-#define PARA_INDIRECT(addr) *%cs:addr |
5143 |
++#define PARA_INDIRECT(addr) *%ss:addr |
5144 |
+ #endif |
5145 |
+ |
5146 |
+ #define INTERRUPT_RETURN \ |
5147 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/pda.h linux-2.6.28.8/arch/x86/include/asm/pda.h |
5148 |
+--- linux-2.6.28.8/arch/x86/include/asm/pda.h 2009-02-06 16:47:45.000000000 -0500 |
5149 |
++++ linux-2.6.28.8/arch/x86/include/asm/pda.h 2009-02-21 09:37:48.000000000 -0500 |
5150 |
+@@ -16,11 +16,9 @@ struct x8664_pda { |
5151 |
+ unsigned long oldrsp; /* 24 user rsp for system call */ |
5152 |
+ int irqcount; /* 32 Irq nesting counter. Starts -1 */ |
5153 |
+ unsigned int cpunumber; /* 36 Logical CPU number */ |
5154 |
+-#ifdef CONFIG_CC_STACKPROTECTOR |
5155 |
+ unsigned long stack_canary; /* 40 stack canary value */ |
5156 |
+ /* gcc-ABI: this canary MUST be at |
5157 |
+ offset 40!!! */ |
5158 |
+-#endif |
5159 |
+ char *irqstackptr; |
5160 |
+ short nodenumber; /* number of current node (32k max) */ |
5161 |
+ short in_bootmem; /* pda lives in bootmem */ |
5162 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/percpu.h linux-2.6.28.8/arch/x86/include/asm/percpu.h |
5163 |
+--- linux-2.6.28.8/arch/x86/include/asm/percpu.h 2009-02-06 16:47:45.000000000 -0500 |
5164 |
++++ linux-2.6.28.8/arch/x86/include/asm/percpu.h 2009-02-21 09:37:48.000000000 -0500 |
5165 |
+@@ -93,6 +93,12 @@ DECLARE_PER_CPU(struct x8664_pda, pda); |
5166 |
+ |
5167 |
+ #define __my_cpu_offset x86_read_percpu(this_cpu_off) |
5168 |
+ |
5169 |
++#include <asm-generic/sections.h> |
5170 |
++#include <linux/threads.h> |
5171 |
++#define __per_cpu_offset __per_cpu_offset |
5172 |
++extern unsigned long __per_cpu_offset[NR_CPUS]; |
5173 |
++#define per_cpu_offset(x) (__per_cpu_offset[x] + (unsigned long)__per_cpu_start) |
5174 |
++ |
5175 |
+ /* fs segment starts at (positive) offset == __per_cpu_offset[cpu] */ |
5176 |
+ #define __percpu_seg "%%fs:" |
5177 |
+ |
5178 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgalloc.h linux-2.6.28.8/arch/x86/include/asm/pgalloc.h |
5179 |
+--- linux-2.6.28.8/arch/x86/include/asm/pgalloc.h 2009-02-06 16:47:45.000000000 -0500 |
5180 |
++++ linux-2.6.28.8/arch/x86/include/asm/pgalloc.h 2009-02-21 09:37:48.000000000 -0500 |
5181 |
+@@ -52,7 +52,7 @@ static inline void pmd_populate_kernel(s |
5182 |
+ pmd_t *pmd, pte_t *pte) |
5183 |
+ { |
5184 |
+ paravirt_alloc_pte(mm, __pa(pte) >> PAGE_SHIFT); |
5185 |
+- set_pmd(pmd, __pmd(__pa(pte) | _PAGE_TABLE)); |
5186 |
++ set_pmd(pmd, __pmd(__pa(pte) | _KERNPG_TABLE)); |
5187 |
+ } |
5188 |
+ |
5189 |
+ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, |
5190 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable-2level.h linux-2.6.28.8/arch/x86/include/asm/pgtable-2level.h |
5191 |
+--- linux-2.6.28.8/arch/x86/include/asm/pgtable-2level.h 2009-02-06 16:47:45.000000000 -0500 |
5192 |
++++ linux-2.6.28.8/arch/x86/include/asm/pgtable-2level.h 2009-02-21 09:37:48.000000000 -0500 |
5193 |
+@@ -18,7 +18,19 @@ static inline void native_set_pte(pte_t |
5194 |
+ |
5195 |
+ static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) |
5196 |
+ { |
5197 |
++ |
5198 |
++#ifdef CONFIG_PAX_KERNEXEC |
5199 |
++ unsigned long cr0; |
5200 |
++ |
5201 |
++ pax_open_kernel(cr0); |
5202 |
++#endif |
5203 |
++ |
5204 |
+ *pmdp = pmd; |
5205 |
++ |
5206 |
++#ifdef CONFIG_PAX_KERNEXEC |
5207 |
++ pax_close_kernel(cr0); |
5208 |
++#endif |
5209 |
++ |
5210 |
+ } |
5211 |
+ |
5212 |
+ static inline void native_set_pte_atomic(pte_t *ptep, pte_t pte) |
5213 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable_32.h linux-2.6.28.8/arch/x86/include/asm/pgtable_32.h |
5214 |
+--- linux-2.6.28.8/arch/x86/include/asm/pgtable_32.h 2009-02-06 16:47:45.000000000 -0500 |
5215 |
++++ linux-2.6.28.8/arch/x86/include/asm/pgtable_32.h 2009-02-21 09:37:48.000000000 -0500 |
5216 |
+@@ -25,8 +25,6 @@ |
5217 |
+ struct mm_struct; |
5218 |
+ struct vm_area_struct; |
5219 |
+ |
5220 |
+-extern pgd_t swapper_pg_dir[1024]; |
5221 |
+- |
5222 |
+ static inline void pgtable_cache_init(void) { } |
5223 |
+ static inline void check_pgt_cache(void) { } |
5224 |
+ void paging_init(void); |
5225 |
+@@ -46,6 +44,11 @@ extern void set_pmd_pfn(unsigned long, u |
5226 |
+ # include <asm/pgtable-2level-defs.h> |
5227 |
+ #endif |
5228 |
+ |
5229 |
++extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; |
5230 |
++#ifdef CONFIG_X86_PAE |
5231 |
++extern pmd_t swapper_pm_dir[PTRS_PER_PGD][PTRS_PER_PMD]; |
5232 |
++#endif |
5233 |
++ |
5234 |
+ #define PGDIR_SIZE (1UL << PGDIR_SHIFT) |
5235 |
+ #define PGDIR_MASK (~(PGDIR_SIZE - 1)) |
5236 |
+ |
5237 |
+@@ -83,7 +86,7 @@ extern void set_pmd_pfn(unsigned long, u |
5238 |
+ #undef TEST_ACCESS_OK |
5239 |
+ |
5240 |
+ /* The boot page tables (all created as a single array) */ |
5241 |
+-extern unsigned long pg0[]; |
5242 |
++extern pte_t pg0[]; |
5243 |
+ |
5244 |
+ #define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE)) |
5245 |
+ |
5246 |
+@@ -175,6 +178,9 @@ do { \ |
5247 |
+ |
5248 |
+ #endif /* !__ASSEMBLY__ */ |
5249 |
+ |
5250 |
++#define HAVE_ARCH_UNMAPPED_AREA |
5251 |
++#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN |
5252 |
++ |
5253 |
+ /* |
5254 |
+ * kern_addr_valid() is (1) for FLATMEM and (0) for |
5255 |
+ * SPARSEMEM and DISCONTIGMEM |
5256 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable-3level.h linux-2.6.28.8/arch/x86/include/asm/pgtable-3level.h |
5257 |
+--- linux-2.6.28.8/arch/x86/include/asm/pgtable-3level.h 2009-02-06 16:47:45.000000000 -0500 |
5258 |
++++ linux-2.6.28.8/arch/x86/include/asm/pgtable-3level.h 2009-02-21 09:37:48.000000000 -0500 |
5259 |
+@@ -70,12 +70,36 @@ static inline void native_set_pte_atomic |
5260 |
+ |
5261 |
+ static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) |
5262 |
+ { |
5263 |
++ |
5264 |
++#ifdef CONFIG_PAX_KERNEXEC |
5265 |
++ unsigned long cr0; |
5266 |
++ |
5267 |
++ pax_open_kernel(cr0); |
5268 |
++#endif |
5269 |
++ |
5270 |
+ set_64bit((unsigned long long *)(pmdp), native_pmd_val(pmd)); |
5271 |
++ |
5272 |
++#ifdef CONFIG_PAX_KERNEXEC |
5273 |
++ pax_close_kernel(cr0); |
5274 |
++#endif |
5275 |
++ |
5276 |
+ } |
5277 |
+ |
5278 |
+ static inline void native_set_pud(pud_t *pudp, pud_t pud) |
5279 |
+ { |
5280 |
++ |
5281 |
++#ifdef CONFIG_PAX_KERNEXEC |
5282 |
++ unsigned long cr0; |
5283 |
++ |
5284 |
++ pax_open_kernel(cr0); |
5285 |
++#endif |
5286 |
++ |
5287 |
+ set_64bit((unsigned long long *)(pudp), native_pud_val(pud)); |
5288 |
++ |
5289 |
++#ifdef CONFIG_PAX_KERNEXEC |
5290 |
++ pax_close_kernel(cr0); |
5291 |
++#endif |
5292 |
++ |
5293 |
+ } |
5294 |
+ |
5295 |
+ /* |
5296 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable_64.h linux-2.6.28.8/arch/x86/include/asm/pgtable_64.h |
5297 |
+--- linux-2.6.28.8/arch/x86/include/asm/pgtable_64.h 2009-02-06 16:47:45.000000000 -0500 |
5298 |
++++ linux-2.6.28.8/arch/x86/include/asm/pgtable_64.h 2009-02-21 09:37:48.000000000 -0500 |
5299 |
+@@ -15,9 +15,12 @@ |
5300 |
+ |
5301 |
+ extern pud_t level3_kernel_pgt[512]; |
5302 |
+ extern pud_t level3_ident_pgt[512]; |
5303 |
++extern pud_t level3_vmalloc_pgt[512]; |
5304 |
++extern pud_t level3_vmemmap_pgt[512]; |
5305 |
+ extern pmd_t level2_kernel_pgt[512]; |
5306 |
+ extern pmd_t level2_fixmap_pgt[512]; |
5307 |
+-extern pmd_t level2_ident_pgt[512]; |
5308 |
++extern pmd_t level2_ident_pgt[512*4]; |
5309 |
++extern pte_t level1_fixmap_pgt[512]; |
5310 |
+ extern pgd_t init_level4_pgt[]; |
5311 |
+ |
5312 |
+ #define swapper_pg_dir init_level4_pgt |
5313 |
+@@ -106,7 +109,19 @@ static inline pte_t native_ptep_get_and_ |
5314 |
+ |
5315 |
+ static inline void native_set_pmd(pmd_t *pmdp, pmd_t pmd) |
5316 |
+ { |
5317 |
++ |
5318 |
++#ifdef CONFIG_PAX_KERNEXEC |
5319 |
++ unsigned long cr0; |
5320 |
++ |
5321 |
++ pax_open_kernel(cr0); |
5322 |
++#endif |
5323 |
++ |
5324 |
+ *pmdp = pmd; |
5325 |
++ |
5326 |
++#ifdef CONFIG_PAX_KERNEXEC |
5327 |
++ pax_close_kernel(cr0); |
5328 |
++#endif |
5329 |
++ |
5330 |
+ } |
5331 |
+ |
5332 |
+ static inline void native_pmd_clear(pmd_t *pmd) |
5333 |
+@@ -158,17 +173,17 @@ static inline void native_pgd_clear(pgd_ |
5334 |
+ |
5335 |
+ static inline int pgd_bad(pgd_t pgd) |
5336 |
+ { |
5337 |
+- return (pgd_val(pgd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; |
5338 |
++ return (pgd_val(pgd) & ~(PTE_PFN_MASK | _PAGE_USER | _PAGE_NX)) != _KERNPG_TABLE; |
5339 |
+ } |
5340 |
+ |
5341 |
+ static inline int pud_bad(pud_t pud) |
5342 |
+ { |
5343 |
+- return (pud_val(pud) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; |
5344 |
++ return (pud_val(pud) & ~(PTE_PFN_MASK | _PAGE_USER | _PAGE_NX)) != _KERNPG_TABLE; |
5345 |
+ } |
5346 |
+ |
5347 |
+ static inline int pmd_bad(pmd_t pmd) |
5348 |
+ { |
5349 |
+- return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER)) != _KERNPG_TABLE; |
5350 |
++ return (pmd_val(pmd) & ~(PTE_PFN_MASK | _PAGE_USER | _PAGE_NX)) != _KERNPG_TABLE; |
5351 |
+ } |
5352 |
+ |
5353 |
+ #define pte_none(x) (!pte_val((x))) |
5354 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/pgtable.h linux-2.6.28.8/arch/x86/include/asm/pgtable.h |
5355 |
+--- linux-2.6.28.8/arch/x86/include/asm/pgtable.h 2009-02-06 16:47:45.000000000 -0500 |
5356 |
++++ linux-2.6.28.8/arch/x86/include/asm/pgtable.h 2009-02-21 09:37:48.000000000 -0500 |
5357 |
+@@ -14,12 +14,11 @@ |
5358 |
+ #define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page */ |
5359 |
+ #define _PAGE_BIT_PAT 7 /* on 4KB pages */ |
5360 |
+ #define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */ |
5361 |
+-#define _PAGE_BIT_UNUSED1 9 /* available for programmer */ |
5362 |
++#define _PAGE_BIT_SPECIAL 9 /* special mappings, no associated struct page */ |
5363 |
+ #define _PAGE_BIT_IOMAP 10 /* flag used to indicate IO mapping */ |
5364 |
+ #define _PAGE_BIT_UNUSED3 11 |
5365 |
+ #define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */ |
5366 |
+-#define _PAGE_BIT_SPECIAL _PAGE_BIT_UNUSED1 |
5367 |
+-#define _PAGE_BIT_CPA_TEST _PAGE_BIT_UNUSED1 |
5368 |
++#define _PAGE_BIT_CPA_TEST _PAGE_BIT_SPECIAL |
5369 |
+ #define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */ |
5370 |
+ |
5371 |
+ #define _PAGE_PRESENT (_AT(pteval_t, 1) << _PAGE_BIT_PRESENT) |
5372 |
+@@ -31,7 +30,6 @@ |
5373 |
+ #define _PAGE_DIRTY (_AT(pteval_t, 1) << _PAGE_BIT_DIRTY) |
5374 |
+ #define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE) |
5375 |
+ #define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL) |
5376 |
+-#define _PAGE_UNUSED1 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1) |
5377 |
+ #define _PAGE_IOMAP (_AT(pteval_t, 1) << _PAGE_BIT_IOMAP) |
5378 |
+ #define _PAGE_UNUSED3 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3) |
5379 |
+ #define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT) |
5380 |
+@@ -43,7 +41,7 @@ |
5381 |
+ #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) |
5382 |
+ #define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX) |
5383 |
+ #else |
5384 |
+-#define _PAGE_NX (_AT(pteval_t, 0)) |
5385 |
++#define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3) |
5386 |
+ #endif |
5387 |
+ |
5388 |
+ /* If _PAGE_PRESENT is clear, we use these: */ |
5389 |
+@@ -83,6 +81,9 @@ |
5390 |
+ #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \ |
5391 |
+ _PAGE_ACCESSED) |
5392 |
+ |
5393 |
++#define PAGE_READONLY_NOEXEC PAGE_READONLY |
5394 |
++#define PAGE_SHARED_NOEXEC PAGE_SHARED |
5395 |
++ |
5396 |
+ #define __PAGE_KERNEL_EXEC \ |
5397 |
+ (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_GLOBAL) |
5398 |
+ #define __PAGE_KERNEL (__PAGE_KERNEL_EXEC | _PAGE_NX) |
5399 |
+@@ -94,7 +95,7 @@ |
5400 |
+ #define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT) |
5401 |
+ #define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD) |
5402 |
+ #define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER) |
5403 |
+-#define __PAGE_KERNEL_VSYSCALL_NOCACHE (__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT) |
5404 |
++#define __PAGE_KERNEL_VSYSCALL_NOCACHE (__PAGE_KERNEL_RO | _PAGE_PCD | _PAGE_PWT | _PAGE_USER) |
5405 |
+ #define __PAGE_KERNEL_LARGE (__PAGE_KERNEL | _PAGE_PSE) |
5406 |
+ #define __PAGE_KERNEL_LARGE_NOCACHE (__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE) |
5407 |
+ #define __PAGE_KERNEL_LARGE_EXEC (__PAGE_KERNEL_EXEC | _PAGE_PSE) |
5408 |
+@@ -153,7 +154,7 @@ |
5409 |
+ * bits are combined, this will alow user to access the high address mapped |
5410 |
+ * VDSO in the presence of CONFIG_COMPAT_VDSO |
5411 |
+ */ |
5412 |
+-#define PTE_IDENT_ATTR 0x003 /* PRESENT+RW */ |
5413 |
++#define PTE_IDENT_ATTR 0x063 /* PRESENT+RW+DIRTY+ACCESSED */ |
5414 |
+ #define PDE_IDENT_ATTR 0x067 /* PRESENT+RW+USER+DIRTY+ACCESSED */ |
5415 |
+ #define PGD_IDENT_ATTR 0x001 /* PRESENT (no other attributes) */ |
5416 |
+ #endif |
5417 |
+@@ -170,10 +171,17 @@ extern unsigned long empty_zero_page[PAG |
5418 |
+ extern spinlock_t pgd_lock; |
5419 |
+ extern struct list_head pgd_list; |
5420 |
+ |
5421 |
++extern pteval_t __supported_pte_mask; |
5422 |
++ |
5423 |
+ /* |
5424 |
+ * The following only work if pte_present() is true. |
5425 |
+ * Undefined behaviour if not.. |
5426 |
+ */ |
5427 |
++static inline int pte_user(pte_t pte) |
5428 |
++{ |
5429 |
++ return pte_val(pte) & _PAGE_USER; |
5430 |
++} |
5431 |
++ |
5432 |
+ static inline int pte_dirty(pte_t pte) |
5433 |
+ { |
5434 |
+ return pte_flags(pte) & _PAGE_DIRTY; |
5435 |
+@@ -242,9 +250,29 @@ static inline pte_t pte_wrprotect(pte_t |
5436 |
+ return __pte(pte_val(pte) & ~_PAGE_RW); |
5437 |
+ } |
5438 |
+ |
5439 |
++static inline pte_t pte_mkread(pte_t pte) |
5440 |
++{ |
5441 |
++ return __pte(pte_val(pte) | _PAGE_USER); |
5442 |
++} |
5443 |
++ |
5444 |
+ static inline pte_t pte_mkexec(pte_t pte) |
5445 |
+ { |
5446 |
+- return __pte(pte_val(pte) & ~_PAGE_NX); |
5447 |
++#ifdef CONFIG_X86_PAE |
5448 |
++ if (__supported_pte_mask & _PAGE_NX) |
5449 |
++ return __pte(pte_val(pte) & ~(pteval_t)_PAGE_NX); |
5450 |
++ else |
5451 |
++#endif |
5452 |
++ return __pte(pte_val(pte) | _PAGE_USER); |
5453 |
++} |
5454 |
++ |
5455 |
++static inline pte_t pte_exprotect(pte_t pte) |
5456 |
++{ |
5457 |
++#ifdef CONFIG_X86_PAE |
5458 |
++ if (__supported_pte_mask & _PAGE_NX) |
5459 |
++ return __pte(pte_val(pte) | _PAGE_NX); |
5460 |
++ else |
5461 |
++#endif |
5462 |
++ return __pte(pte_val(pte) & ~_PAGE_USER); |
5463 |
+ } |
5464 |
+ |
5465 |
+ static inline pte_t pte_mkdirty(pte_t pte) |
5466 |
+@@ -287,8 +315,6 @@ static inline pte_t pte_mkspecial(pte_t |
5467 |
+ return __pte(pte_val(pte) | _PAGE_SPECIAL); |
5468 |
+ } |
5469 |
+ |
5470 |
+-extern pteval_t __supported_pte_mask; |
5471 |
+- |
5472 |
+ static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot) |
5473 |
+ { |
5474 |
+ return __pte((((phys_addr_t)page_nr << PAGE_SHIFT) | |
5475 |
+@@ -552,7 +578,19 @@ static inline void ptep_set_wrprotect(st |
5476 |
+ */ |
5477 |
+ static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count) |
5478 |
+ { |
5479 |
+- memcpy(dst, src, count * sizeof(pgd_t)); |
5480 |
++ |
5481 |
++#ifdef CONFIG_PAX_KERNEXEC |
5482 |
++ unsigned long cr0; |
5483 |
++ |
5484 |
++ pax_open_kernel(cr0); |
5485 |
++#endif |
5486 |
++ |
5487 |
++ memcpy(dst, src, count * sizeof(pgd_t)); |
5488 |
++ |
5489 |
++#ifdef CONFIG_PAX_KERNEXEC |
5490 |
++ pax_close_kernel(cr0); |
5491 |
++#endif |
5492 |
++ |
5493 |
+ } |
5494 |
+ |
5495 |
+ |
5496 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/processor.h linux-2.6.28.8/arch/x86/include/asm/processor.h |
5497 |
+--- linux-2.6.28.8/arch/x86/include/asm/processor.h 2009-03-07 10:24:49.000000000 -0500 |
5498 |
++++ linux-2.6.28.8/arch/x86/include/asm/processor.h 2009-03-07 10:29:51.000000000 -0500 |
5499 |
+@@ -271,7 +271,7 @@ struct tss_struct { |
5500 |
+ |
5501 |
+ } ____cacheline_aligned; |
5502 |
+ |
5503 |
+-DECLARE_PER_CPU(struct tss_struct, init_tss); |
5504 |
++extern struct tss_struct init_tss[NR_CPUS]; |
5505 |
+ |
5506 |
+ /* |
5507 |
+ * Save the original ist values for checking stack pointers during debugging |
5508 |
+@@ -822,11 +822,20 @@ static inline void spin_lock_prefetch(co |
5509 |
+ * User space process size: 3GB (default). |
5510 |
+ */ |
5511 |
+ #define TASK_SIZE PAGE_OFFSET |
5512 |
++ |
5513 |
++#ifdef CONFIG_PAX_SEGMEXEC |
5514 |
++#define SEGMEXEC_TASK_SIZE (TASK_SIZE / 2) |
5515 |
++#endif |
5516 |
++ |
5517 |
++#ifdef CONFIG_PAX_SEGMEXEC |
5518 |
++#define STACK_TOP ((current->mm->pax_flags & MF_PAX_SEGMEXEC)?SEGMEXEC_TASK_SIZE:TASK_SIZE) |
5519 |
++#else |
5520 |
+ #define STACK_TOP TASK_SIZE |
5521 |
+-#define STACK_TOP_MAX STACK_TOP |
5522 |
++#endif |
5523 |
++#define STACK_TOP_MAX TASK_SIZE |
5524 |
+ |
5525 |
+ #define INIT_THREAD { \ |
5526 |
+- .sp0 = sizeof(init_stack) + (long)&init_stack, \ |
5527 |
++ .sp0 = sizeof(init_stack) + (long)&init_stack - 8, \ |
5528 |
+ .vm86_info = NULL, \ |
5529 |
+ .sysenter_cs = __KERNEL_CS, \ |
5530 |
+ .io_bitmap_ptr = NULL, \ |
5531 |
+@@ -841,7 +850,7 @@ static inline void spin_lock_prefetch(co |
5532 |
+ */ |
5533 |
+ #define INIT_TSS { \ |
5534 |
+ .x86_tss = { \ |
5535 |
+- .sp0 = sizeof(init_stack) + (long)&init_stack, \ |
5536 |
++ .sp0 = sizeof(init_stack) + (long)&init_stack - 8, \ |
5537 |
+ .ss0 = __KERNEL_DS, \ |
5538 |
+ .ss1 = __KERNEL_CS, \ |
5539 |
+ .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \ |
5540 |
+@@ -852,11 +861,7 @@ static inline void spin_lock_prefetch(co |
5541 |
+ extern unsigned long thread_saved_pc(struct task_struct *tsk); |
5542 |
+ |
5543 |
+ #define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long)) |
5544 |
+-#define KSTK_TOP(info) \ |
5545 |
+-({ \ |
5546 |
+- unsigned long *__ptr = (unsigned long *)(info); \ |
5547 |
+- (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \ |
5548 |
+-}) |
5549 |
++#define KSTK_TOP(info) ((info)->task.thread.sp0) |
5550 |
+ |
5551 |
+ /* |
5552 |
+ * The below -8 is to reserve 8 bytes on top of the ring0 stack. |
5553 |
+@@ -871,7 +876,7 @@ extern unsigned long thread_saved_pc(str |
5554 |
+ #define task_pt_regs(task) \ |
5555 |
+ ({ \ |
5556 |
+ struct pt_regs *__regs__; \ |
5557 |
+- __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \ |
5558 |
++ __regs__ = (struct pt_regs *)((task)->thread.sp0); \ |
5559 |
+ __regs__ - 1; \ |
5560 |
+ }) |
5561 |
+ |
5562 |
+@@ -887,7 +892,7 @@ extern unsigned long thread_saved_pc(str |
5563 |
+ * space during mmap's. |
5564 |
+ */ |
5565 |
+ #define IA32_PAGE_OFFSET ((current->personality & ADDR_LIMIT_3GB) ? \ |
5566 |
+- 0xc0000000 : 0xFFFFe000) |
5567 |
++ 0xc0000000 : 0xFFFFf000) |
5568 |
+ |
5569 |
+ #define TASK_SIZE (test_thread_flag(TIF_IA32) ? \ |
5570 |
+ IA32_PAGE_OFFSET : TASK_SIZE64) |
5571 |
+@@ -924,6 +929,10 @@ extern void start_thread(struct pt_regs |
5572 |
+ */ |
5573 |
+ #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) |
5574 |
+ |
5575 |
++#ifdef CONFIG_PAX_SEGMEXEC |
5576 |
++#define SEGMEXEC_TASK_UNMAPPED_BASE (PAGE_ALIGN(SEGMEXEC_TASK_SIZE / 3)) |
5577 |
++#endif |
5578 |
++ |
5579 |
+ #define KSTK_EIP(task) (task_pt_regs(task)->ip) |
5580 |
+ |
5581 |
+ /* Get/set a process' ability to use the timestamp counter instruction */ |
5582 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/ptrace.h linux-2.6.28.8/arch/x86/include/asm/ptrace.h |
5583 |
+--- linux-2.6.28.8/arch/x86/include/asm/ptrace.h 2009-02-06 16:47:45.000000000 -0500 |
5584 |
++++ linux-2.6.28.8/arch/x86/include/asm/ptrace.h 2009-02-21 09:37:48.000000000 -0500 |
5585 |
+@@ -187,28 +187,29 @@ static inline unsigned long regs_return_ |
5586 |
+ } |
5587 |
+ |
5588 |
+ /* |
5589 |
+- * user_mode_vm(regs) determines whether a register set came from user mode. |
5590 |
++ * user_mode(regs) determines whether a register set came from user mode. |
5591 |
+ * This is true if V8086 mode was enabled OR if the register set was from |
5592 |
+ * protected mode with RPL-3 CS value. This tricky test checks that with |
5593 |
+ * one comparison. Many places in the kernel can bypass this full check |
5594 |
+- * if they have already ruled out V8086 mode, so user_mode(regs) can be used. |
5595 |
++ * if they have already ruled out V8086 mode, so user_mode_novm(regs) can |
5596 |
++ * be used. |
5597 |
+ */ |
5598 |
+-static inline int user_mode(struct pt_regs *regs) |
5599 |
++static inline int user_mode_novm(struct pt_regs *regs) |
5600 |
+ { |
5601 |
+ #ifdef CONFIG_X86_32 |
5602 |
+ return (regs->cs & SEGMENT_RPL_MASK) == USER_RPL; |
5603 |
+ #else |
5604 |
+- return !!(regs->cs & 3); |
5605 |
++ return !!(regs->cs & SEGMENT_RPL_MASK); |
5606 |
+ #endif |
5607 |
+ } |
5608 |
+ |
5609 |
+-static inline int user_mode_vm(struct pt_regs *regs) |
5610 |
++static inline int user_mode(struct pt_regs *regs) |
5611 |
+ { |
5612 |
+ #ifdef CONFIG_X86_32 |
5613 |
+ return ((regs->cs & SEGMENT_RPL_MASK) | (regs->flags & X86_VM_MASK)) >= |
5614 |
+ USER_RPL; |
5615 |
+ #else |
5616 |
+- return user_mode(regs); |
5617 |
++ return user_mode_novm(regs); |
5618 |
+ #endif |
5619 |
+ } |
5620 |
+ |
5621 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/reboot.h linux-2.6.28.8/arch/x86/include/asm/reboot.h |
5622 |
+--- linux-2.6.28.8/arch/x86/include/asm/reboot.h 2009-02-06 16:47:45.000000000 -0500 |
5623 |
++++ linux-2.6.28.8/arch/x86/include/asm/reboot.h 2009-02-21 09:37:48.000000000 -0500 |
5624 |
+@@ -16,6 +16,6 @@ extern struct machine_ops machine_ops; |
5625 |
+ |
5626 |
+ void native_machine_crash_shutdown(struct pt_regs *regs); |
5627 |
+ void native_machine_shutdown(void); |
5628 |
+-void machine_real_restart(const unsigned char *code, int length); |
5629 |
++void machine_real_restart(const unsigned char *code, unsigned int length); |
5630 |
+ |
5631 |
+ #endif /* _ASM_X86_REBOOT_H */ |
5632 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/rwsem.h linux-2.6.28.8/arch/x86/include/asm/rwsem.h |
5633 |
+--- linux-2.6.28.8/arch/x86/include/asm/rwsem.h 2009-02-06 16:47:45.000000000 -0500 |
5634 |
++++ linux-2.6.28.8/arch/x86/include/asm/rwsem.h 2009-02-21 09:37:48.000000000 -0500 |
5635 |
+@@ -106,10 +106,26 @@ static inline void __down_read(struct rw |
5636 |
+ { |
5637 |
+ asm volatile("# beginning down_read\n\t" |
5638 |
+ LOCK_PREFIX " incl (%%eax)\n\t" |
5639 |
++ |
5640 |
++#ifdef CONFIG_PAX_REFCOUNT |
5641 |
++#ifdef CONFIG_X86_32 |
5642 |
++ "into\n0:\n" |
5643 |
++#else |
5644 |
++ "jno 0f\n" |
5645 |
++ "int $4\n0:\n" |
5646 |
++#endif |
5647 |
++ ".pushsection .fixup,\"ax\"\n" |
5648 |
++ "1:\n" |
5649 |
++ LOCK_PREFIX "decl (%%eax)\n" |
5650 |
++ "jmp 0b\n" |
5651 |
++ ".popsection\n" |
5652 |
++ _ASM_EXTABLE(0b, 1b) |
5653 |
++#endif |
5654 |
++ |
5655 |
+ /* adds 0x00000001, returns the old value */ |
5656 |
+- " jns 1f\n" |
5657 |
++ " jns 2f\n" |
5658 |
+ " call call_rwsem_down_read_failed\n" |
5659 |
+- "1:\n\t" |
5660 |
++ "2:\n\t" |
5661 |
+ "# ending down_read\n\t" |
5662 |
+ : "+m" (sem->count) |
5663 |
+ : "a" (sem) |
5664 |
+@@ -124,13 +140,29 @@ static inline int __down_read_trylock(st |
5665 |
+ __s32 result, tmp; |
5666 |
+ asm volatile("# beginning __down_read_trylock\n\t" |
5667 |
+ " movl %0,%1\n\t" |
5668 |
+- "1:\n\t" |
5669 |
++ "2:\n\t" |
5670 |
+ " movl %1,%2\n\t" |
5671 |
+ " addl %3,%2\n\t" |
5672 |
+- " jle 2f\n\t" |
5673 |
++ |
5674 |
++#ifdef CONFIG_PAX_REFCOUNT |
5675 |
++#ifdef CONFIG_X86_32 |
5676 |
++ "into\n0:\n" |
5677 |
++#else |
5678 |
++ "jno 0f\n" |
5679 |
++ "int $4\n0:\n" |
5680 |
++#endif |
5681 |
++ ".pushsection .fixup,\"ax\"\n" |
5682 |
++ "1:\n" |
5683 |
++ "subl %3,%2\n" |
5684 |
++ "jmp 0b\n" |
5685 |
++ ".popsection\n" |
5686 |
++ _ASM_EXTABLE(0b, 1b) |
5687 |
++#endif |
5688 |
++ |
5689 |
++ " jle 3f\n\t" |
5690 |
+ LOCK_PREFIX " cmpxchgl %2,%0\n\t" |
5691 |
+- " jnz 1b\n\t" |
5692 |
+- "2:\n\t" |
5693 |
++ " jnz 2b\n\t" |
5694 |
++ "3:\n\t" |
5695 |
+ "# ending __down_read_trylock\n\t" |
5696 |
+ : "+m" (sem->count), "=&a" (result), "=&r" (tmp) |
5697 |
+ : "i" (RWSEM_ACTIVE_READ_BIAS) |
5698 |
+@@ -148,12 +180,28 @@ static inline void __down_write_nested(s |
5699 |
+ tmp = RWSEM_ACTIVE_WRITE_BIAS; |
5700 |
+ asm volatile("# beginning down_write\n\t" |
5701 |
+ LOCK_PREFIX " xadd %%edx,(%%eax)\n\t" |
5702 |
++ |
5703 |
++#ifdef CONFIG_PAX_REFCOUNT |
5704 |
++#ifdef CONFIG_X86_32 |
5705 |
++ "into\n0:\n" |
5706 |
++#else |
5707 |
++ "jno 0f\n" |
5708 |
++ "int $4\n0:\n" |
5709 |
++#endif |
5710 |
++ ".pushsection .fixup,\"ax\"\n" |
5711 |
++ "1:\n" |
5712 |
++ "movl %%edx,(%%eax)\n" |
5713 |
++ "jmp 0b\n" |
5714 |
++ ".popsection\n" |
5715 |
++ _ASM_EXTABLE(0b, 1b) |
5716 |
++#endif |
5717 |
++ |
5718 |
+ /* subtract 0x0000ffff, returns the old value */ |
5719 |
+ " testl %%edx,%%edx\n\t" |
5720 |
+ /* was the count 0 before? */ |
5721 |
+- " jz 1f\n" |
5722 |
++ " jz 2f\n" |
5723 |
+ " call call_rwsem_down_write_failed\n" |
5724 |
+- "1:\n" |
5725 |
++ "2:\n" |
5726 |
+ "# ending down_write" |
5727 |
+ : "+m" (sem->count), "=d" (tmp) |
5728 |
+ : "a" (sem), "1" (tmp) |
5729 |
+@@ -186,10 +234,26 @@ static inline void __up_read(struct rw_s |
5730 |
+ __s32 tmp = -RWSEM_ACTIVE_READ_BIAS; |
5731 |
+ asm volatile("# beginning __up_read\n\t" |
5732 |
+ LOCK_PREFIX " xadd %%edx,(%%eax)\n\t" |
5733 |
++ |
5734 |
++#ifdef CONFIG_PAX_REFCOUNT |
5735 |
++#ifdef CONFIG_X86_32 |
5736 |
++ "into\n0:\n" |
5737 |
++#else |
5738 |
++ "jno 0f\n" |
5739 |
++ "int $4\n0:\n" |
5740 |
++#endif |
5741 |
++ ".pushsection .fixup,\"ax\"\n" |
5742 |
++ "1:\n" |
5743 |
++ "movl %%edx,(%%eax)\n" |
5744 |
++ "jmp 0b\n" |
5745 |
++ ".popsection\n" |
5746 |
++ _ASM_EXTABLE(0b, 1b) |
5747 |
++#endif |
5748 |
++ |
5749 |
+ /* subtracts 1, returns the old value */ |
5750 |
+- " jns 1f\n\t" |
5751 |
++ " jns 2f\n\t" |
5752 |
+ " call call_rwsem_wake\n" |
5753 |
+- "1:\n" |
5754 |
++ "2:\n" |
5755 |
+ "# ending __up_read\n" |
5756 |
+ : "+m" (sem->count), "=d" (tmp) |
5757 |
+ : "a" (sem), "1" (tmp) |
5758 |
+@@ -204,11 +268,27 @@ static inline void __up_write(struct rw_ |
5759 |
+ asm volatile("# beginning __up_write\n\t" |
5760 |
+ " movl %2,%%edx\n\t" |
5761 |
+ LOCK_PREFIX " xaddl %%edx,(%%eax)\n\t" |
5762 |
++ |
5763 |
++#ifdef CONFIG_PAX_REFCOUNT |
5764 |
++#ifdef CONFIG_X86_32 |
5765 |
++ "into\n0:\n" |
5766 |
++#else |
5767 |
++ "jno 0f\n" |
5768 |
++ "int $4\n0:\n" |
5769 |
++#endif |
5770 |
++ ".pushsection .fixup,\"ax\"\n" |
5771 |
++ "1:\n" |
5772 |
++ "movl %%edx,(%%eax)\n" |
5773 |
++ "jmp 0b\n" |
5774 |
++ ".popsection\n" |
5775 |
++ _ASM_EXTABLE(0b, 1b) |
5776 |
++#endif |
5777 |
++ |
5778 |
+ /* tries to transition |
5779 |
+ 0xffff0001 -> 0x00000000 */ |
5780 |
+- " jz 1f\n" |
5781 |
++ " jz 2f\n" |
5782 |
+ " call call_rwsem_wake\n" |
5783 |
+- "1:\n\t" |
5784 |
++ "2:\n\t" |
5785 |
+ "# ending __up_write\n" |
5786 |
+ : "+m" (sem->count) |
5787 |
+ : "a" (sem), "i" (-RWSEM_ACTIVE_WRITE_BIAS) |
5788 |
+@@ -222,10 +302,26 @@ static inline void __downgrade_write(str |
5789 |
+ { |
5790 |
+ asm volatile("# beginning __downgrade_write\n\t" |
5791 |
+ LOCK_PREFIX " addl %2,(%%eax)\n\t" |
5792 |
++ |
5793 |
++#ifdef CONFIG_PAX_REFCOUNT |
5794 |
++#ifdef CONFIG_X86_32 |
5795 |
++ "into\n0:\n" |
5796 |
++#else |
5797 |
++ "jno 0f\n" |
5798 |
++ "int $4\n0:\n" |
5799 |
++#endif |
5800 |
++ ".pushsection .fixup,\"ax\"\n" |
5801 |
++ "1:\n" |
5802 |
++ LOCK_PREFIX "subl %2,(%%eax)\n" |
5803 |
++ "jmp 0b\n" |
5804 |
++ ".popsection\n" |
5805 |
++ _ASM_EXTABLE(0b, 1b) |
5806 |
++#endif |
5807 |
++ |
5808 |
+ /* transitions 0xZZZZ0001 -> 0xYYYY0001 */ |
5809 |
+- " jns 1f\n\t" |
5810 |
++ " jns 2f\n\t" |
5811 |
+ " call call_rwsem_downgrade_wake\n" |
5812 |
+- "1:\n\t" |
5813 |
++ "2:\n\t" |
5814 |
+ "# ending __downgrade_write\n" |
5815 |
+ : "+m" (sem->count) |
5816 |
+ : "a" (sem), "i" (-RWSEM_WAITING_BIAS) |
5817 |
+@@ -237,7 +333,23 @@ static inline void __downgrade_write(str |
5818 |
+ */ |
5819 |
+ static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem) |
5820 |
+ { |
5821 |
+- asm volatile(LOCK_PREFIX "addl %1,%0" |
5822 |
++ asm volatile(LOCK_PREFIX "addl %1,%0\n" |
5823 |
++ |
5824 |
++#ifdef CONFIG_PAX_REFCOUNT |
5825 |
++#ifdef CONFIG_X86_32 |
5826 |
++ "into\n0:\n" |
5827 |
++#else |
5828 |
++ "jno 0f\n" |
5829 |
++ "int $4\n0:\n" |
5830 |
++#endif |
5831 |
++ ".pushsection .fixup,\"ax\"\n" |
5832 |
++ "1:\n" |
5833 |
++ LOCK_PREFIX "subl %1,%0\n" |
5834 |
++ "jmp 0b\n" |
5835 |
++ ".popsection\n" |
5836 |
++ _ASM_EXTABLE(0b, 1b) |
5837 |
++#endif |
5838 |
++ |
5839 |
+ : "+m" (sem->count) |
5840 |
+ : "ir" (delta)); |
5841 |
+ } |
5842 |
+@@ -249,7 +361,23 @@ static inline int rwsem_atomic_update(in |
5843 |
+ { |
5844 |
+ int tmp = delta; |
5845 |
+ |
5846 |
+- asm volatile(LOCK_PREFIX "xadd %0,%1" |
5847 |
++ asm volatile(LOCK_PREFIX "xadd %0,%1\n" |
5848 |
++ |
5849 |
++#ifdef CONFIG_PAX_REFCOUNT |
5850 |
++#ifdef CONFIG_X86_32 |
5851 |
++ "into\n0:\n" |
5852 |
++#else |
5853 |
++ "jno 0f\n" |
5854 |
++ "int $4\n0:\n" |
5855 |
++#endif |
5856 |
++ ".pushsection .fixup,\"ax\"\n" |
5857 |
++ "1:\n" |
5858 |
++ "movl %0,%1\n" |
5859 |
++ "jmp 0b\n" |
5860 |
++ ".popsection\n" |
5861 |
++ _ASM_EXTABLE(0b, 1b) |
5862 |
++#endif |
5863 |
++ |
5864 |
+ : "+r" (tmp), "+m" (sem->count) |
5865 |
+ : : "memory"); |
5866 |
+ |
5867 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/segment.h linux-2.6.28.8/arch/x86/include/asm/segment.h |
5868 |
+--- linux-2.6.28.8/arch/x86/include/asm/segment.h 2009-02-06 16:47:45.000000000 -0500 |
5869 |
++++ linux-2.6.28.8/arch/x86/include/asm/segment.h 2009-02-21 09:37:48.000000000 -0500 |
5870 |
+@@ -88,13 +88,19 @@ |
5871 |
+ #define GDT_ENTRY_ESPFIX_SS (GDT_ENTRY_KERNEL_BASE + 14) |
5872 |
+ #define __ESPFIX_SS (GDT_ENTRY_ESPFIX_SS * 8) |
5873 |
+ |
5874 |
+-#define GDT_ENTRY_PERCPU (GDT_ENTRY_KERNEL_BASE + 15) |
5875 |
++#define GDT_ENTRY_PERCPU (GDT_ENTRY_KERNEL_BASE + 15) |
5876 |
+ #ifdef CONFIG_SMP |
5877 |
+ #define __KERNEL_PERCPU (GDT_ENTRY_PERCPU * 8) |
5878 |
+ #else |
5879 |
+ #define __KERNEL_PERCPU 0 |
5880 |
+ #endif |
5881 |
+ |
5882 |
++#define GDT_ENTRY_PCIBIOS_CS (GDT_ENTRY_KERNEL_BASE + 16) |
5883 |
++#define __PCIBIOS_CS (GDT_ENTRY_PCIBIOS_CS * 8) |
5884 |
++ |
5885 |
++#define GDT_ENTRY_PCIBIOS_DS (GDT_ENTRY_KERNEL_BASE + 17) |
5886 |
++#define __PCIBIOS_DS (GDT_ENTRY_PCIBIOS_DS * 8) |
5887 |
++ |
5888 |
+ #define GDT_ENTRY_DOUBLEFAULT_TSS 31 |
5889 |
+ |
5890 |
+ /* |
5891 |
+@@ -132,7 +138,7 @@ |
5892 |
+ */ |
5893 |
+ |
5894 |
+ /* Matches PNP_CS32 and PNP_CS16 (they must be consecutive) */ |
5895 |
+-#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xf4) == GDT_ENTRY_PNPBIOS_BASE * 8) |
5896 |
++#define SEGMENT_IS_PNP_CODE(x) (((x) & 0xFFFCU) == PNP_CS32 || ((x) & 0xFFFCU) == PNP_CS16) |
5897 |
+ |
5898 |
+ |
5899 |
+ #else |
5900 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/spinlock.h linux-2.6.28.8/arch/x86/include/asm/spinlock.h |
5901 |
+--- linux-2.6.28.8/arch/x86/include/asm/spinlock.h 2009-02-06 16:47:45.000000000 -0500 |
5902 |
++++ linux-2.6.28.8/arch/x86/include/asm/spinlock.h 2009-02-21 09:37:48.000000000 -0500 |
5903 |
+@@ -310,18 +310,50 @@ static inline int __raw_write_can_lock(r |
5904 |
+ static inline void __raw_read_lock(raw_rwlock_t *rw) |
5905 |
+ { |
5906 |
+ asm volatile(LOCK_PREFIX " subl $1,(%0)\n\t" |
5907 |
+- "jns 1f\n" |
5908 |
+- "call __read_lock_failed\n\t" |
5909 |
++ |
5910 |
++#ifdef CONFIG_PAX_REFCOUNT |
5911 |
++#ifdef CONFIG_X86_32 |
5912 |
++ "into\n0:\n" |
5913 |
++#else |
5914 |
++ "jno 0f\n" |
5915 |
++ "int $4\n0:\n" |
5916 |
++#endif |
5917 |
++ ".pushsection .fixup,\"ax\"\n" |
5918 |
+ "1:\n" |
5919 |
++ LOCK_PREFIX " addl $1,(%0)\n" |
5920 |
++ "jmp 0b\n" |
5921 |
++ ".popsection\n" |
5922 |
++ _ASM_EXTABLE(0b, 1b) |
5923 |
++#endif |
5924 |
++ |
5925 |
++ "jns 2f\n" |
5926 |
++ "call __read_lock_failed\n\t" |
5927 |
++ "2:\n" |
5928 |
+ ::LOCK_PTR_REG (rw) : "memory"); |
5929 |
+ } |
5930 |
+ |
5931 |
+ static inline void __raw_write_lock(raw_rwlock_t *rw) |
5932 |
+ { |
5933 |
+ asm volatile(LOCK_PREFIX " subl %1,(%0)\n\t" |
5934 |
+- "jz 1f\n" |
5935 |
+- "call __write_lock_failed\n\t" |
5936 |
++ |
5937 |
++#ifdef CONFIG_PAX_REFCOUNT |
5938 |
++#ifdef CONFIG_X86_32 |
5939 |
++ "into\n0:\n" |
5940 |
++#else |
5941 |
++ "jno 0f\n" |
5942 |
++ "int $4\n0:\n" |
5943 |
++#endif |
5944 |
++ ".pushsection .fixup,\"ax\"\n" |
5945 |
+ "1:\n" |
5946 |
++ LOCK_PREFIX " addl %1,(%0)\n" |
5947 |
++ "jmp 0b\n" |
5948 |
++ ".popsection\n" |
5949 |
++ _ASM_EXTABLE(0b, 1b) |
5950 |
++#endif |
5951 |
++ |
5952 |
++ "jz 2f\n" |
5953 |
++ "call __write_lock_failed\n\t" |
5954 |
++ "2:\n" |
5955 |
+ ::LOCK_PTR_REG (rw), "i" (RW_LOCK_BIAS) : "memory"); |
5956 |
+ } |
5957 |
+ |
5958 |
+@@ -348,12 +380,45 @@ static inline int __raw_write_trylock(ra |
5959 |
+ |
5960 |
+ static inline void __raw_read_unlock(raw_rwlock_t *rw) |
5961 |
+ { |
5962 |
+- asm volatile(LOCK_PREFIX "incl %0" :"+m" (rw->lock) : : "memory"); |
5963 |
++ asm volatile(LOCK_PREFIX "incl %0\n" |
5964 |
++ |
5965 |
++#ifdef CONFIG_PAX_REFCOUNT |
5966 |
++#ifdef CONFIG_X86_32 |
5967 |
++ "into\n0:\n" |
5968 |
++#else |
5969 |
++ "jno 0f\n" |
5970 |
++ "int $4\n0:\n" |
5971 |
++#endif |
5972 |
++ ".pushsection .fixup,\"ax\"\n" |
5973 |
++ "1:\n" |
5974 |
++ LOCK_PREFIX "decl %0\n" |
5975 |
++ "jmp 0b\n" |
5976 |
++ ".popsection\n" |
5977 |
++ _ASM_EXTABLE(0b, 1b) |
5978 |
++#endif |
5979 |
++ |
5980 |
++ :"+m" (rw->lock) : : "memory"); |
5981 |
+ } |
5982 |
+ |
5983 |
+ static inline void __raw_write_unlock(raw_rwlock_t *rw) |
5984 |
+ { |
5985 |
+- asm volatile(LOCK_PREFIX "addl %1, %0" |
5986 |
++ asm volatile(LOCK_PREFIX "addl %1, %0\n" |
5987 |
++ |
5988 |
++#ifdef CONFIG_PAX_REFCOUNT |
5989 |
++#ifdef CONFIG_X86_32 |
5990 |
++ "into\n0:\n" |
5991 |
++#else |
5992 |
++ "jno 0f\n" |
5993 |
++ "int $4\n0:\n" |
5994 |
++#endif |
5995 |
++ ".pushsection .fixup,\"ax\"\n" |
5996 |
++ "1:\n" |
5997 |
++ LOCK_PREFIX "subl %1,%0\n" |
5998 |
++ "jmp 0b\n" |
5999 |
++ ".popsection\n" |
6000 |
++ _ASM_EXTABLE(0b, 1b) |
6001 |
++#endif |
6002 |
++ |
6003 |
+ : "+m" (rw->lock) : "i" (RW_LOCK_BIAS) : "memory"); |
6004 |
+ } |
6005 |
+ |
6006 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/system.h linux-2.6.28.8/arch/x86/include/asm/system.h |
6007 |
+--- linux-2.6.28.8/arch/x86/include/asm/system.h 2009-02-06 16:47:45.000000000 -0500 |
6008 |
++++ linux-2.6.28.8/arch/x86/include/asm/system.h 2009-02-21 09:37:48.000000000 -0500 |
6009 |
+@@ -95,6 +95,8 @@ do { \ |
6010 |
+ ".globl thread_return\n" \ |
6011 |
+ "thread_return:\n\t" \ |
6012 |
+ "movq %%gs:%P[pda_pcurrent],%%rsi\n\t" \ |
6013 |
++ "movq %P[task_canary](%%rsi),%%r8\n\t" \ |
6014 |
++ "movq %%r8,%%gs:%P[pda_canary]\n\t" \ |
6015 |
+ "movq %P[thread_info](%%rsi),%%r8\n\t" \ |
6016 |
+ LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ |
6017 |
+ "movq %%rax,%%rdi\n\t" \ |
6018 |
+@@ -106,7 +108,9 @@ do { \ |
6019 |
+ [ti_flags] "i" (offsetof(struct thread_info, flags)), \ |
6020 |
+ [tif_fork] "i" (TIF_FORK), \ |
6021 |
+ [thread_info] "i" (offsetof(struct task_struct, stack)), \ |
6022 |
+- [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)) \ |
6023 |
++ [task_canary] "i" (offsetof(struct task_struct, stack_canary)), \ |
6024 |
++ [pda_pcurrent] "i" (offsetof(struct x8664_pda, pcurrent)), \ |
6025 |
++ [pda_canary] "i" (offsetof(struct x8664_pda, stack_canary))\ |
6026 |
+ : "memory", "cc" __EXTRA_CLOBBER) |
6027 |
+ #endif |
6028 |
+ |
6029 |
+@@ -169,7 +173,7 @@ static inline unsigned long get_limit(un |
6030 |
+ { |
6031 |
+ unsigned long __limit; |
6032 |
+ asm("lsll %1,%0" : "=r" (__limit) : "r" (segment)); |
6033 |
+- return __limit + 1; |
6034 |
++ return __limit; |
6035 |
+ } |
6036 |
+ |
6037 |
+ static inline void native_clts(void) |
6038 |
+@@ -295,6 +299,21 @@ static inline void native_wbinvd(void) |
6039 |
+ |
6040 |
+ #define stts() write_cr0(read_cr0() | X86_CR0_TS) |
6041 |
+ |
6042 |
++#define pax_open_kernel(cr0) \ |
6043 |
++do { \ |
6044 |
++ typecheck(unsigned long, cr0); \ |
6045 |
++ preempt_disable(); \ |
6046 |
++ cr0 = read_cr0(); \ |
6047 |
++ write_cr0(cr0 & ~X86_CR0_WP); \ |
6048 |
++} while (0) |
6049 |
++ |
6050 |
++#define pax_close_kernel(cr0) \ |
6051 |
++do { \ |
6052 |
++ typecheck(unsigned long, cr0); \ |
6053 |
++ write_cr0(cr0); \ |
6054 |
++ preempt_enable_no_resched(); \ |
6055 |
++} while (0) |
6056 |
++ |
6057 |
+ #endif /* __KERNEL__ */ |
6058 |
+ |
6059 |
+ static inline void clflush(volatile void *__p) |
6060 |
+@@ -309,7 +328,7 @@ void enable_hlt(void); |
6061 |
+ |
6062 |
+ void cpu_idle_wait(void); |
6063 |
+ |
6064 |
+-extern unsigned long arch_align_stack(unsigned long sp); |
6065 |
++#define arch_align_stack(x) ((x) & ~0xfUL) |
6066 |
+ extern void free_init_pages(char *what, unsigned long begin, unsigned long end); |
6067 |
+ |
6068 |
+ void default_idle(void); |
6069 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess_64.h linux-2.6.28.8/arch/x86/include/asm/uaccess_64.h |
6070 |
+--- linux-2.6.28.8/arch/x86/include/asm/uaccess_64.h 2009-02-06 16:47:45.000000000 -0500 |
6071 |
++++ linux-2.6.28.8/arch/x86/include/asm/uaccess_64.h 2009-02-21 09:37:48.000000000 -0500 |
6072 |
+@@ -10,6 +10,8 @@ |
6073 |
+ #include <linux/lockdep.h> |
6074 |
+ #include <asm/page.h> |
6075 |
+ |
6076 |
++#define set_fs(x) (current_thread_info()->addr_limit = (x)) |
6077 |
++ |
6078 |
+ /* |
6079 |
+ * Copy To/From Userspace |
6080 |
+ */ |
6081 |
+diff -urNp linux-2.6.28.8/arch/x86/include/asm/uaccess.h linux-2.6.28.8/arch/x86/include/asm/uaccess.h |
6082 |
+--- linux-2.6.28.8/arch/x86/include/asm/uaccess.h 2009-02-06 16:47:45.000000000 -0500 |
6083 |
++++ linux-2.6.28.8/arch/x86/include/asm/uaccess.h 2009-02-21 09:37:48.000000000 -0500 |
6084 |
+@@ -10,6 +10,7 @@ |
6085 |
+ #include <linux/string.h> |
6086 |
+ #include <asm/asm.h> |
6087 |
+ #include <asm/page.h> |
6088 |
++#include <asm/segment.h> |
6089 |
+ |
6090 |
+ #define VERIFY_READ 0 |
6091 |
+ #define VERIFY_WRITE 1 |
6092 |
+@@ -29,7 +30,12 @@ |
6093 |
+ |
6094 |
+ #define get_ds() (KERNEL_DS) |
6095 |
+ #define get_fs() (current_thread_info()->addr_limit) |
6096 |
++#ifdef CONFIG_X86_32 |
6097 |
++void __set_fs(mm_segment_t x, int cpu); |
6098 |
++void set_fs(mm_segment_t x); |
6099 |
++#else |
6100 |
+ #define set_fs(x) (current_thread_info()->addr_limit = (x)) |
6101 |
++#endif |
6102 |
+ |
6103 |
+ #define segment_eq(a, b) ((a).seg == (b).seg) |
6104 |
+ |
6105 |
+@@ -186,9 +192,12 @@ extern int __get_user_bad(void); |
6106 |
+ |
6107 |
+ #ifdef CONFIG_X86_32 |
6108 |
+ #define __put_user_u64(x, addr, err) \ |
6109 |
+- asm volatile("1: movl %%eax,0(%2)\n" \ |
6110 |
+- "2: movl %%edx,4(%2)\n" \ |
6111 |
++ asm volatile(" movw %w5,%%ds\n" \ |
6112 |
++ "1: movl %%eax,%%ds:0(%2)\n" \ |
6113 |
++ "2: movl %%edx,%%ds:4(%2)\n" \ |
6114 |
+ "3:\n" \ |
6115 |
++ " pushl %%ss\n" \ |
6116 |
++ " popl %%ds\n" \ |
6117 |
+ ".section .fixup,\"ax\"\n" \ |
6118 |
+ "4: movl %3,%0\n" \ |
6119 |
+ " jmp 3b\n" \ |
6120 |
+@@ -196,7 +205,8 @@ extern int __get_user_bad(void); |
6121 |
+ _ASM_EXTABLE(1b, 4b) \ |
6122 |
+ _ASM_EXTABLE(2b, 4b) \ |
6123 |
+ : "=r" (err) \ |
6124 |
+- : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err)) |
6125 |
++ : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err), \ |
6126 |
++ "r"(__USER_DS)) |
6127 |
+ |
6128 |
+ #define __put_user_x8(x, ptr, __ret_pu) \ |
6129 |
+ asm volatile("call __put_user_8" : "=a" (__ret_pu) \ |
6130 |
+@@ -336,6 +346,22 @@ do { \ |
6131 |
+ } \ |
6132 |
+ } while (0) |
6133 |
+ |
6134 |
++#ifdef CONFIG_X86_32 |
6135 |
++#define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \ |
6136 |
++ asm volatile(" movw %w5,%%ds\n" \ |
6137 |
++ "1: mov"itype" %%ds:%2,%"rtype"1\n" \ |
6138 |
++ "2:\n" \ |
6139 |
++ " pushl %%ss\n" \ |
6140 |
++ " popl %%ds\n" \ |
6141 |
++ ".section .fixup,\"ax\"\n" \ |
6142 |
++ "3: movl %3,%0\n" \ |
6143 |
++ " xor"itype" %"rtype"1,%"rtype"1\n" \ |
6144 |
++ " jmp 2b\n" \ |
6145 |
++ ".previous\n" \ |
6146 |
++ _ASM_EXTABLE(1b, 3b) \ |
6147 |
++ : "=r" (err), ltype (x) \ |
6148 |
++ : "m" (__m(addr)), "i" (errret), "0" (err), "r"(__USER_DS)) |
6149 |
++#else |
6150 |
+ #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \ |
6151 |
+ asm volatile("1: mov"itype" %2,%"rtype"1\n" \ |
6152 |
+ "2:\n" \ |
6153 |
+@@ -347,6 +373,7 @@ do { \ |
6154 |
+ _ASM_EXTABLE(1b, 3b) \ |
6155 |
+ : "=r" (err), ltype(x) \ |
6156 |
+ : "m" (__m(addr)), "i" (errret), "0" (err)) |
6157 |
++#endif |
6158 |
+ |
6159 |
+ #define __put_user_nocheck(x, ptr, size) \ |
6160 |
+ ({ \ |
6161 |
+@@ -373,6 +400,22 @@ struct __large_struct { unsigned long bu |
6162 |
+ * we do not write to any memory gcc knows about, so there are no |
6163 |
+ * aliasing issues. |
6164 |
+ */ |
6165 |
++#ifdef CONFIG_X86_32 |
6166 |
++#define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \ |
6167 |
++ asm volatile(" movw %w5,%%ds\n" \ |
6168 |
++ "1: mov"itype" %"rtype"1,%%ds:%2\n" \ |
6169 |
++ "2:\n" \ |
6170 |
++ " pushl %%ss\n" \ |
6171 |
++ " popl %%ds\n" \ |
6172 |
++ ".section .fixup,\"ax\"\n" \ |
6173 |
++ "3: movl %3,%0\n" \ |
6174 |
++ " jmp 2b\n" \ |
6175 |
++ ".previous\n" \ |
6176 |
++ _ASM_EXTABLE(1b, 3b) \ |
6177 |
++ : "=r"(err) \ |
6178 |
++ : ltype (x), "m" (__m(addr)), "i" (errret), "0" (err),\ |
6179 |
++ "r"(__USER_DS)) |
6180 |
++#else |
6181 |
+ #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \ |
6182 |
+ asm volatile("1: mov"itype" %"rtype"1,%2\n" \ |
6183 |
+ "2:\n" \ |
6184 |
+@@ -383,6 +426,7 @@ struct __large_struct { unsigned long bu |
6185 |
+ _ASM_EXTABLE(1b, 3b) \ |
6186 |
+ : "=r"(err) \ |
6187 |
+ : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err)) |
6188 |
++#endif |
6189 |
+ /** |
6190 |
+ * __get_user: - Get a simple variable from user space, with less checking. |
6191 |
+ * @x: Variable to store result. |
6192 |
+@@ -443,6 +487,7 @@ extern struct movsl_mask { |
6193 |
+ |
6194 |
+ #define ARCH_HAS_NOCACHE_UACCESS 1 |
6195 |
+ |
6196 |
++#define ARCH_HAS_SORT_EXTABLE |
6197 |
+ #ifdef CONFIG_X86_32 |
6198 |
+ # include "uaccess_32.h" |
6199 |
+ #else |
6200 |
+diff -urNp linux-2.6.28.8/arch/x86/Kconfig linux-2.6.28.8/arch/x86/Kconfig |
6201 |
+--- linux-2.6.28.8/arch/x86/Kconfig 2009-02-06 16:47:45.000000000 -0500 |
6202 |
++++ linux-2.6.28.8/arch/x86/Kconfig 2009-02-21 09:37:48.000000000 -0500 |
6203 |
+@@ -935,7 +935,7 @@ config PAGE_OFFSET |
6204 |
+ hex |
6205 |
+ default 0xB0000000 if VMSPLIT_3G_OPT |
6206 |
+ default 0x80000000 if VMSPLIT_2G |
6207 |
+- default 0x78000000 if VMSPLIT_2G_OPT |
6208 |
++ default 0x70000000 if VMSPLIT_2G_OPT |
6209 |
+ default 0x40000000 if VMSPLIT_1G |
6210 |
+ default 0xC0000000 |
6211 |
+ depends on X86_32 |
6212 |
+@@ -1337,8 +1337,7 @@ config KEXEC_JUMP |
6213 |
+ config PHYSICAL_START |
6214 |
+ hex "Physical address where the kernel is loaded" if (EMBEDDED || CRASH_DUMP) |
6215 |
+ default "0x1000000" if X86_NUMAQ |
6216 |
+- default "0x200000" if X86_64 |
6217 |
+- default "0x100000" |
6218 |
++ default "0x200000" |
6219 |
+ help |
6220 |
+ This gives the physical address where the kernel is loaded. |
6221 |
+ |
6222 |
+@@ -1430,9 +1429,9 @@ config HOTPLUG_CPU |
6223 |
+ Say N if you want to disable CPU hotplug. |
6224 |
+ |
6225 |
+ config COMPAT_VDSO |
6226 |
+- def_bool y |
6227 |
++ def_bool n |
6228 |
+ prompt "Compat VDSO support" |
6229 |
+- depends on X86_32 || IA32_EMULATION |
6230 |
++ depends on (X86_32 || IA32_EMULATION) && !PAX_NOEXEC |
6231 |
+ help |
6232 |
+ Map the 32-bit VDSO to the predictable old-style address too. |
6233 |
+ ---help--- |
6234 |
+diff -urNp linux-2.6.28.8/arch/x86/Kconfig.cpu linux-2.6.28.8/arch/x86/Kconfig.cpu |
6235 |
+--- linux-2.6.28.8/arch/x86/Kconfig.cpu 2009-02-06 16:47:45.000000000 -0500 |
6236 |
++++ linux-2.6.28.8/arch/x86/Kconfig.cpu 2009-02-21 09:37:48.000000000 -0500 |
6237 |
+@@ -331,7 +331,7 @@ config X86_PPRO_FENCE |
6238 |
+ |
6239 |
+ config X86_F00F_BUG |
6240 |
+ def_bool y |
6241 |
+- depends on M586MMX || M586TSC || M586 || M486 || M386 |
6242 |
++ depends on (M586MMX || M586TSC || M586 || M486 || M386) && !PAX_KERNEXEC |
6243 |
+ |
6244 |
+ config X86_WP_WORKS_OK |
6245 |
+ def_bool y |
6246 |
+@@ -351,7 +351,7 @@ config X86_POPAD_OK |
6247 |
+ |
6248 |
+ config X86_ALIGNMENT_16 |
6249 |
+ def_bool y |
6250 |
+- depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 |
6251 |
++ depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MCORE2 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1 |
6252 |
+ |
6253 |
+ config X86_INTEL_USERCOPY |
6254 |
+ def_bool y |
6255 |
+@@ -397,7 +397,7 @@ config X86_CMPXCHG64 |
6256 |
+ # generates cmov. |
6257 |
+ config X86_CMOV |
6258 |
+ def_bool y |
6259 |
+- depends on (MK8 || MK7 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64) |
6260 |
++ depends on (MK8 || MK7 || MCORE2 || MPSC || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7 || MCRUSOE || MEFFICEON || X86_64) |
6261 |
+ |
6262 |
+ config X86_MINIMUM_CPU_FAMILY |
6263 |
+ int |
6264 |
+diff -urNp linux-2.6.28.8/arch/x86/Kconfig.debug linux-2.6.28.8/arch/x86/Kconfig.debug |
6265 |
+--- linux-2.6.28.8/arch/x86/Kconfig.debug 2009-02-06 16:47:45.000000000 -0500 |
6266 |
++++ linux-2.6.28.8/arch/x86/Kconfig.debug 2009-02-21 09:37:48.000000000 -0500 |
6267 |
+@@ -107,7 +107,7 @@ config X86_PTDUMP |
6268 |
+ config DEBUG_RODATA |
6269 |
+ bool "Write protect kernel read-only data structures" |
6270 |
+ default y |
6271 |
+- depends on DEBUG_KERNEL |
6272 |
++ depends on DEBUG_KERNEL && BROKEN |
6273 |
+ help |
6274 |
+ Mark the kernel read-only data as write-protected in the pagetables, |
6275 |
+ in order to catch accidental (and incorrect) writes to such const |
6276 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/boot.c linux-2.6.28.8/arch/x86/kernel/acpi/boot.c |
6277 |
+--- linux-2.6.28.8/arch/x86/kernel/acpi/boot.c 2009-02-06 16:47:45.000000000 -0500 |
6278 |
++++ linux-2.6.28.8/arch/x86/kernel/acpi/boot.c 2009-02-21 09:37:48.000000000 -0500 |
6279 |
+@@ -1645,7 +1645,7 @@ static struct dmi_system_id __initdata a |
6280 |
+ DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6715b"), |
6281 |
+ }, |
6282 |
+ }, |
6283 |
+- {} |
6284 |
++ { NULL, NULL, {{0, {0}}}, NULL} |
6285 |
+ }; |
6286 |
+ |
6287 |
+ /* |
6288 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/realmode/wakeup.S linux-2.6.28.8/arch/x86/kernel/acpi/realmode/wakeup.S |
6289 |
+--- linux-2.6.28.8/arch/x86/kernel/acpi/realmode/wakeup.S 2009-02-06 16:47:45.000000000 -0500 |
6290 |
++++ linux-2.6.28.8/arch/x86/kernel/acpi/realmode/wakeup.S 2009-02-21 09:37:48.000000000 -0500 |
6291 |
+@@ -104,7 +104,7 @@ _start: |
6292 |
+ movl %eax, %ecx |
6293 |
+ orl %edx, %ecx |
6294 |
+ jz 1f |
6295 |
+- movl $0xc0000080, %ecx |
6296 |
++ mov $MSR_EFER, %ecx |
6297 |
+ wrmsr |
6298 |
+ 1: |
6299 |
+ |
6300 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/sleep.c linux-2.6.28.8/arch/x86/kernel/acpi/sleep.c |
6301 |
+--- linux-2.6.28.8/arch/x86/kernel/acpi/sleep.c 2009-02-06 16:47:45.000000000 -0500 |
6302 |
++++ linux-2.6.28.8/arch/x86/kernel/acpi/sleep.c 2009-02-21 09:37:48.000000000 -0500 |
6303 |
+@@ -37,6 +37,10 @@ int acpi_save_state_mem(void) |
6304 |
+ { |
6305 |
+ struct wakeup_header *header; |
6306 |
+ |
6307 |
++#if defined(CONFIG_64BIT) && defined(CONFIG_SMP) && defined(CONFIG_PAX_KERNEXEC) |
6308 |
++ unsigned long cr0; |
6309 |
++#endif |
6310 |
++ |
6311 |
+ if (!acpi_realmode) { |
6312 |
+ printk(KERN_ERR "Could not allocate memory during boot, " |
6313 |
+ "S3 disabled\n"); |
6314 |
+@@ -99,8 +103,18 @@ int acpi_save_state_mem(void) |
6315 |
+ header->trampoline_segment = setup_trampoline() >> 4; |
6316 |
+ #ifdef CONFIG_SMP |
6317 |
+ stack_start.sp = temp_stack + sizeof(temp_stack); |
6318 |
++ |
6319 |
++#ifdef CONFIG_PAX_KERNEXEC |
6320 |
++ pax_open_kernel(cr0); |
6321 |
++#endif |
6322 |
++ |
6323 |
+ early_gdt_descr.address = |
6324 |
+ (unsigned long)get_cpu_gdt_table(smp_processor_id()); |
6325 |
++ |
6326 |
++#ifdef CONFIG_PAX_KERNEXEC |
6327 |
++ pax_close_kernel(cr0); |
6328 |
++#endif |
6329 |
++ |
6330 |
+ #endif |
6331 |
+ initial_code = (unsigned long)wakeup_long64; |
6332 |
+ saved_magic = 0x123456789abcdef0; |
6333 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/acpi/wakeup_32.S linux-2.6.28.8/arch/x86/kernel/acpi/wakeup_32.S |
6334 |
+--- linux-2.6.28.8/arch/x86/kernel/acpi/wakeup_32.S 2009-02-06 16:47:45.000000000 -0500 |
6335 |
++++ linux-2.6.28.8/arch/x86/kernel/acpi/wakeup_32.S 2009-02-21 09:37:48.000000000 -0500 |
6336 |
+@@ -30,13 +30,11 @@ wakeup_pmode_return: |
6337 |
+ # and restore the stack ... but you need gdt for this to work |
6338 |
+ movl saved_context_esp, %esp |
6339 |
+ |
6340 |
+- movl %cs:saved_magic, %eax |
6341 |
+- cmpl $0x12345678, %eax |
6342 |
++ cmpl $0x12345678, saved_magic |
6343 |
+ jne bogus_magic |
6344 |
+ |
6345 |
+ # jump to place where we left off |
6346 |
+- movl saved_eip, %eax |
6347 |
+- jmp *%eax |
6348 |
++ jmp *(saved_eip) |
6349 |
+ |
6350 |
+ bogus_magic: |
6351 |
+ jmp bogus_magic |
6352 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/alternative.c linux-2.6.28.8/arch/x86/kernel/alternative.c |
6353 |
+--- linux-2.6.28.8/arch/x86/kernel/alternative.c 2009-02-06 16:47:45.000000000 -0500 |
6354 |
++++ linux-2.6.28.8/arch/x86/kernel/alternative.c 2009-02-21 09:37:48.000000000 -0500 |
6355 |
+@@ -393,7 +393,7 @@ void apply_paravirt(struct paravirt_patc |
6356 |
+ |
6357 |
+ BUG_ON(p->len > MAX_PATCH_LEN); |
6358 |
+ /* prep the buffer with the original instructions */ |
6359 |
+- memcpy(insnbuf, p->instr, p->len); |
6360 |
++ memcpy(insnbuf, ktla_ktva(p->instr), p->len); |
6361 |
+ used = pv_init_ops.patch(p->instrtype, p->clobbers, insnbuf, |
6362 |
+ (unsigned long)p->instr, p->len); |
6363 |
+ |
6364 |
+@@ -473,11 +473,26 @@ void __init alternative_instructions(voi |
6365 |
+ * instructions. And on the local CPU you need to be protected again NMI or MCE |
6366 |
+ * handlers seeing an inconsistent instruction while you patch. |
6367 |
+ */ |
6368 |
+-void *text_poke_early(void *addr, const void *opcode, size_t len) |
6369 |
++void *__kprobes text_poke_early(void *addr, const void *opcode, size_t len) |
6370 |
+ { |
6371 |
+ unsigned long flags; |
6372 |
++ |
6373 |
++#ifdef CONFIG_PAX_KERNEXEC |
6374 |
++ unsigned long cr0; |
6375 |
++#endif |
6376 |
++ |
6377 |
+ local_irq_save(flags); |
6378 |
+- memcpy(addr, opcode, len); |
6379 |
++ |
6380 |
++#ifdef CONFIG_PAX_KERNEXEC |
6381 |
++ pax_open_kernel(cr0); |
6382 |
++#endif |
6383 |
++ |
6384 |
++ memcpy(ktla_ktva(addr), opcode, len); |
6385 |
++ |
6386 |
++#ifdef CONFIG_PAX_KERNEXEC |
6387 |
++ pax_close_kernel(cr0); |
6388 |
++#endif |
6389 |
++ |
6390 |
+ local_irq_restore(flags); |
6391 |
+ sync_core(); |
6392 |
+ /* Could also do a CLFLUSH here to speed up CPU recovery; but |
6393 |
+@@ -498,33 +513,27 @@ void *text_poke_early(void *addr, const |
6394 |
+ */ |
6395 |
+ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) |
6396 |
+ { |
6397 |
+- unsigned long flags; |
6398 |
+- char *vaddr; |
6399 |
+- int nr_pages = 2; |
6400 |
++ unsigned char *vaddr = ktla_ktva(addr); |
6401 |
+ struct page *pages[2]; |
6402 |
+- int i; |
6403 |
++ size_t i; |
6404 |
++ |
6405 |
++ if (!core_kernel_text((unsigned long)addr) |
6406 |
+ |
6407 |
+- if (!core_kernel_text((unsigned long)addr)) { |
6408 |
+- pages[0] = vmalloc_to_page(addr); |
6409 |
+- pages[1] = vmalloc_to_page(addr + PAGE_SIZE); |
6410 |
++#if defined(CONFIG_X86_32) && defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) |
6411 |
++ && (vaddr < MODULES_VADDR || MODULES_END < vaddr) |
6412 |
++#endif |
6413 |
++ |
6414 |
++ ) { |
6415 |
++ pages[0] = vmalloc_to_page(vaddr); |
6416 |
++ pages[1] = vmalloc_to_page(vaddr + PAGE_SIZE); |
6417 |
+ } else { |
6418 |
+- pages[0] = virt_to_page(addr); |
6419 |
++ pages[0] = virt_to_page(vaddr); |
6420 |
+ WARN_ON(!PageReserved(pages[0])); |
6421 |
+- pages[1] = virt_to_page(addr + PAGE_SIZE); |
6422 |
++ pages[1] = virt_to_page(vaddr + PAGE_SIZE); |
6423 |
+ } |
6424 |
+ BUG_ON(!pages[0]); |
6425 |
+- if (!pages[1]) |
6426 |
+- nr_pages = 1; |
6427 |
+- vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); |
6428 |
+- BUG_ON(!vaddr); |
6429 |
+- local_irq_save(flags); |
6430 |
+- memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); |
6431 |
+- local_irq_restore(flags); |
6432 |
+- vunmap(vaddr); |
6433 |
+- sync_core(); |
6434 |
+- /* Could also do a CLFLUSH here to speed up CPU recovery; but |
6435 |
+- that causes hangs on some VIA CPUs. */ |
6436 |
++ text_poke_early(addr, opcode, len); |
6437 |
+ for (i = 0; i < len; i++) |
6438 |
+- BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]); |
6439 |
++ BUG_ON((vaddr)[i] != ((unsigned char *)opcode)[i]); |
6440 |
+ return addr; |
6441 |
+ } |
6442 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/apm_32.c linux-2.6.28.8/arch/x86/kernel/apm_32.c |
6443 |
+--- linux-2.6.28.8/arch/x86/kernel/apm_32.c 2009-02-06 16:47:45.000000000 -0500 |
6444 |
++++ linux-2.6.28.8/arch/x86/kernel/apm_32.c 2009-02-21 09:37:48.000000000 -0500 |
6445 |
+@@ -407,7 +407,7 @@ static DECLARE_WAIT_QUEUE_HEAD(apm_waitq |
6446 |
+ static DECLARE_WAIT_QUEUE_HEAD(apm_suspend_waitqueue); |
6447 |
+ static struct apm_user *user_list; |
6448 |
+ static DEFINE_SPINLOCK(user_list_lock); |
6449 |
+-static const struct desc_struct bad_bios_desc = { { { 0, 0x00409200 } } }; |
6450 |
++static const struct desc_struct bad_bios_desc = { { { 0, 0x00409300 } } }; |
6451 |
+ |
6452 |
+ static const char driver_version[] = "1.16ac"; /* no spaces */ |
6453 |
+ |
6454 |
+@@ -602,19 +602,42 @@ static u8 apm_bios_call(u32 func, u32 eb |
6455 |
+ struct desc_struct save_desc_40; |
6456 |
+ struct desc_struct *gdt; |
6457 |
+ |
6458 |
++#ifdef CONFIG_PAX_KERNEXEC |
6459 |
++ unsigned long cr0; |
6460 |
++#endif |
6461 |
++ |
6462 |
+ cpus = apm_save_cpus(); |
6463 |
+ |
6464 |
+ cpu = get_cpu(); |
6465 |
+ gdt = get_cpu_gdt_table(cpu); |
6466 |
+ save_desc_40 = gdt[0x40 / 8]; |
6467 |
++ |
6468 |
++#ifdef CONFIG_PAX_KERNEXEC |
6469 |
++ pax_open_kernel(cr0); |
6470 |
++#endif |
6471 |
++ |
6472 |
+ gdt[0x40 / 8] = bad_bios_desc; |
6473 |
+ |
6474 |
++#ifdef CONFIG_PAX_KERNEXEC |
6475 |
++ pax_close_kernel(cr0); |
6476 |
++#endif |
6477 |
++ |
6478 |
+ apm_irq_save(flags); |
6479 |
+ APM_DO_SAVE_SEGS; |
6480 |
+ apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi); |
6481 |
+ APM_DO_RESTORE_SEGS; |
6482 |
+ apm_irq_restore(flags); |
6483 |
++ |
6484 |
++#ifdef CONFIG_PAX_KERNEXEC |
6485 |
++ pax_open_kernel(cr0); |
6486 |
++#endif |
6487 |
++ |
6488 |
+ gdt[0x40 / 8] = save_desc_40; |
6489 |
++ |
6490 |
++#ifdef CONFIG_PAX_KERNEXEC |
6491 |
++ pax_close_kernel(cr0); |
6492 |
++#endif |
6493 |
++ |
6494 |
+ put_cpu(); |
6495 |
+ apm_restore_cpus(cpus); |
6496 |
+ |
6497 |
+@@ -645,19 +668,42 @@ static u8 apm_bios_call_simple(u32 func, |
6498 |
+ struct desc_struct save_desc_40; |
6499 |
+ struct desc_struct *gdt; |
6500 |
+ |
6501 |
++#ifdef CONFIG_PAX_KERNEXEC |
6502 |
++ unsigned long cr0; |
6503 |
++#endif |
6504 |
++ |
6505 |
+ cpus = apm_save_cpus(); |
6506 |
+ |
6507 |
+ cpu = get_cpu(); |
6508 |
+ gdt = get_cpu_gdt_table(cpu); |
6509 |
+ save_desc_40 = gdt[0x40 / 8]; |
6510 |
++ |
6511 |
++#ifdef CONFIG_PAX_KERNEXEC |
6512 |
++ pax_open_kernel(cr0); |
6513 |
++#endif |
6514 |
++ |
6515 |
+ gdt[0x40 / 8] = bad_bios_desc; |
6516 |
+ |
6517 |
++#ifdef CONFIG_PAX_KERNEXEC |
6518 |
++ pax_close_kernel(cr0); |
6519 |
++#endif |
6520 |
++ |
6521 |
+ apm_irq_save(flags); |
6522 |
+ APM_DO_SAVE_SEGS; |
6523 |
+ error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax); |
6524 |
+ APM_DO_RESTORE_SEGS; |
6525 |
+ apm_irq_restore(flags); |
6526 |
++ |
6527 |
++#ifdef CONFIG_PAX_KERNEXEC |
6528 |
++ pax_open_kernel(cr0); |
6529 |
++#endif |
6530 |
++ |
6531 |
+ gdt[0x40 / 8] = save_desc_40; |
6532 |
++ |
6533 |
++#ifdef CONFIG_PAX_KERNEXEC |
6534 |
++ pax_close_kernel(cr0); |
6535 |
++#endif |
6536 |
++ |
6537 |
+ put_cpu(); |
6538 |
+ apm_restore_cpus(cpus); |
6539 |
+ return error; |
6540 |
+@@ -929,7 +975,7 @@ recalc: |
6541 |
+ |
6542 |
+ static void apm_power_off(void) |
6543 |
+ { |
6544 |
+- unsigned char po_bios_call[] = { |
6545 |
++ const unsigned char po_bios_call[] = { |
6546 |
+ 0xb8, 0x00, 0x10, /* movw $0x1000,ax */ |
6547 |
+ 0x8e, 0xd0, /* movw ax,ss */ |
6548 |
+ 0xbc, 0x00, 0xf0, /* movw $0xf000,sp */ |
6549 |
+@@ -1876,7 +1922,10 @@ static const struct file_operations apm_ |
6550 |
+ static struct miscdevice apm_device = { |
6551 |
+ APM_MINOR_DEV, |
6552 |
+ "apm_bios", |
6553 |
+- &apm_bios_fops |
6554 |
++ &apm_bios_fops, |
6555 |
++ {NULL, NULL}, |
6556 |
++ NULL, |
6557 |
++ NULL |
6558 |
+ }; |
6559 |
+ |
6560 |
+ |
6561 |
+@@ -2197,7 +2246,7 @@ static struct dmi_system_id __initdata a |
6562 |
+ { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), }, |
6563 |
+ }, |
6564 |
+ |
6565 |
+- { } |
6566 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL} |
6567 |
+ }; |
6568 |
+ |
6569 |
+ /* |
6570 |
+@@ -2215,6 +2264,10 @@ static int __init apm_init(void) |
6571 |
+ struct desc_struct *gdt; |
6572 |
+ int err; |
6573 |
+ |
6574 |
++#ifdef CONFIG_PAX_KERNEXEC |
6575 |
++ unsigned long cr0; |
6576 |
++#endif |
6577 |
++ |
6578 |
+ dmi_check_system(apm_dmi_table); |
6579 |
+ |
6580 |
+ if (apm_info.bios.version == 0 || paravirt_enabled() || machine_is_olpc()) { |
6581 |
+@@ -2288,9 +2341,18 @@ static int __init apm_init(void) |
6582 |
+ * This is for buggy BIOS's that refer to (real mode) segment 0x40 |
6583 |
+ * even though they are called in protected mode. |
6584 |
+ */ |
6585 |
++ |
6586 |
++#ifdef CONFIG_PAX_KERNEXEC |
6587 |
++ pax_open_kernel(cr0); |
6588 |
++#endif |
6589 |
++ |
6590 |
+ set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); |
6591 |
+ _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); |
6592 |
+ |
6593 |
++#ifdef CONFIG_PAX_KERNEXEC |
6594 |
++ pax_close_kernel(cr0); |
6595 |
++#endif |
6596 |
++ |
6597 |
+ /* |
6598 |
+ * Set up the long jump entry point to the APM BIOS, which is called |
6599 |
+ * from inline assembly. |
6600 |
+@@ -2309,6 +2371,11 @@ static int __init apm_init(void) |
6601 |
+ * code to that CPU. |
6602 |
+ */ |
6603 |
+ gdt = get_cpu_gdt_table(0); |
6604 |
++ |
6605 |
++#ifdef CONFIG_PAX_KERNEXEC |
6606 |
++ pax_open_kernel(cr0); |
6607 |
++#endif |
6608 |
++ |
6609 |
+ set_base(gdt[APM_CS >> 3], |
6610 |
+ __va((unsigned long)apm_info.bios.cseg << 4)); |
6611 |
+ set_base(gdt[APM_CS_16 >> 3], |
6612 |
+@@ -2316,6 +2383,10 @@ static int __init apm_init(void) |
6613 |
+ set_base(gdt[APM_DS >> 3], |
6614 |
+ __va((unsigned long)apm_info.bios.dseg << 4)); |
6615 |
+ |
6616 |
++#ifdef CONFIG_PAX_KERNEXEC |
6617 |
++ pax_close_kernel(cr0); |
6618 |
++#endif |
6619 |
++ |
6620 |
+ proc_create("apm", 0, NULL, &apm_file_ops); |
6621 |
+ |
6622 |
+ kapmd_task = kthread_create(apm, NULL, "kapmd"); |
6623 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/asm-offsets_32.c linux-2.6.28.8/arch/x86/kernel/asm-offsets_32.c |
6624 |
+--- linux-2.6.28.8/arch/x86/kernel/asm-offsets_32.c 2009-02-06 16:47:45.000000000 -0500 |
6625 |
++++ linux-2.6.28.8/arch/x86/kernel/asm-offsets_32.c 2009-02-21 09:37:48.000000000 -0500 |
6626 |
+@@ -100,6 +100,7 @@ void foo(void) |
6627 |
+ DEFINE(PTRS_PER_PTE, PTRS_PER_PTE); |
6628 |
+ DEFINE(PTRS_PER_PMD, PTRS_PER_PMD); |
6629 |
+ DEFINE(PTRS_PER_PGD, PTRS_PER_PGD); |
6630 |
++ DEFINE(PERCPU_MODULE_RESERVE, PERCPU_MODULE_RESERVE); |
6631 |
+ |
6632 |
+ OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx); |
6633 |
+ |
6634 |
+@@ -113,6 +114,7 @@ void foo(void) |
6635 |
+ OFFSET(PV_CPU_iret, pv_cpu_ops, iret); |
6636 |
+ OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit); |
6637 |
+ OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0); |
6638 |
++ OFFSET(PV_CPU_write_cr0, pv_cpu_ops, write_cr0); |
6639 |
+ #endif |
6640 |
+ |
6641 |
+ #ifdef CONFIG_XEN |
6642 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/asm-offsets_64.c linux-2.6.28.8/arch/x86/kernel/asm-offsets_64.c |
6643 |
+--- linux-2.6.28.8/arch/x86/kernel/asm-offsets_64.c 2009-02-06 16:47:45.000000000 -0500 |
6644 |
++++ linux-2.6.28.8/arch/x86/kernel/asm-offsets_64.c 2009-02-21 09:37:48.000000000 -0500 |
6645 |
+@@ -122,6 +122,7 @@ int main(void) |
6646 |
+ ENTRY(cr8); |
6647 |
+ BLANK(); |
6648 |
+ #undef ENTRY |
6649 |
++ DEFINE(TSS_size, sizeof(struct tss_struct)); |
6650 |
+ DEFINE(TSS_ist, offsetof(struct tss_struct, x86_tss.ist)); |
6651 |
+ BLANK(); |
6652 |
+ DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx)); |
6653 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/common.c linux-2.6.28.8/arch/x86/kernel/cpu/common.c |
6654 |
+--- linux-2.6.28.8/arch/x86/kernel/cpu/common.c 2009-02-06 16:47:45.000000000 -0500 |
6655 |
++++ linux-2.6.28.8/arch/x86/kernel/cpu/common.c 2009-02-21 09:37:48.000000000 -0500 |
6656 |
+@@ -2,7 +2,6 @@ |
6657 |
+ #include <linux/kernel.h> |
6658 |
+ #include <linux/sched.h> |
6659 |
+ #include <linux/string.h> |
6660 |
+-#include <linux/bootmem.h> |
6661 |
+ #include <linux/bitops.h> |
6662 |
+ #include <linux/module.h> |
6663 |
+ #include <linux/kgdb.h> |
6664 |
+@@ -41,59 +40,6 @@ |
6665 |
+ |
6666 |
+ static struct cpu_dev *this_cpu __cpuinitdata; |
6667 |
+ |
6668 |
+-#ifdef CONFIG_X86_64 |
6669 |
+-/* We need valid kernel segments for data and code in long mode too |
6670 |
+- * IRET will check the segment types kkeil 2000/10/28 |
6671 |
+- * Also sysret mandates a special GDT layout |
6672 |
+- */ |
6673 |
+-/* The TLS descriptors are currently at a different place compared to i386. |
6674 |
+- Hopefully nobody expects them at a fixed place (Wine?) */ |
6675 |
+-DEFINE_PER_CPU(struct gdt_page, gdt_page) = { .gdt = { |
6676 |
+- [GDT_ENTRY_KERNEL32_CS] = { { { 0x0000ffff, 0x00cf9b00 } } }, |
6677 |
+- [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00af9b00 } } }, |
6678 |
+- [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9300 } } }, |
6679 |
+- [GDT_ENTRY_DEFAULT_USER32_CS] = { { { 0x0000ffff, 0x00cffb00 } } }, |
6680 |
+- [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff300 } } }, |
6681 |
+- [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00affb00 } } }, |
6682 |
+-} }; |
6683 |
+-#else |
6684 |
+-DEFINE_PER_CPU_PAGE_ALIGNED(struct gdt_page, gdt_page) = { .gdt = { |
6685 |
+- [GDT_ENTRY_KERNEL_CS] = { { { 0x0000ffff, 0x00cf9a00 } } }, |
6686 |
+- [GDT_ENTRY_KERNEL_DS] = { { { 0x0000ffff, 0x00cf9200 } } }, |
6687 |
+- [GDT_ENTRY_DEFAULT_USER_CS] = { { { 0x0000ffff, 0x00cffa00 } } }, |
6688 |
+- [GDT_ENTRY_DEFAULT_USER_DS] = { { { 0x0000ffff, 0x00cff200 } } }, |
6689 |
+- /* |
6690 |
+- * Segments used for calling PnP BIOS have byte granularity. |
6691 |
+- * They code segments and data segments have fixed 64k limits, |
6692 |
+- * the transfer segment sizes are set at run time. |
6693 |
+- */ |
6694 |
+- /* 32-bit code */ |
6695 |
+- [GDT_ENTRY_PNPBIOS_CS32] = { { { 0x0000ffff, 0x00409a00 } } }, |
6696 |
+- /* 16-bit code */ |
6697 |
+- [GDT_ENTRY_PNPBIOS_CS16] = { { { 0x0000ffff, 0x00009a00 } } }, |
6698 |
+- /* 16-bit data */ |
6699 |
+- [GDT_ENTRY_PNPBIOS_DS] = { { { 0x0000ffff, 0x00009200 } } }, |
6700 |
+- /* 16-bit data */ |
6701 |
+- [GDT_ENTRY_PNPBIOS_TS1] = { { { 0x00000000, 0x00009200 } } }, |
6702 |
+- /* 16-bit data */ |
6703 |
+- [GDT_ENTRY_PNPBIOS_TS2] = { { { 0x00000000, 0x00009200 } } }, |
6704 |
+- /* |
6705 |
+- * The APM segments have byte granularity and their bases |
6706 |
+- * are set at run time. All have 64k limits. |
6707 |
+- */ |
6708 |
+- /* 32-bit code */ |
6709 |
+- [GDT_ENTRY_APMBIOS_BASE] = { { { 0x0000ffff, 0x00409a00 } } }, |
6710 |
+- /* 16-bit code */ |
6711 |
+- [GDT_ENTRY_APMBIOS_BASE+1] = { { { 0x0000ffff, 0x00009a00 } } }, |
6712 |
+- /* data */ |
6713 |
+- [GDT_ENTRY_APMBIOS_BASE+2] = { { { 0x0000ffff, 0x00409200 } } }, |
6714 |
+- |
6715 |
+- [GDT_ENTRY_ESPFIX_SS] = { { { 0x00000000, 0x00c09200 } } }, |
6716 |
+- [GDT_ENTRY_PERCPU] = { { { 0x00000000, 0x00000000 } } }, |
6717 |
+-} }; |
6718 |
+-#endif |
6719 |
+-EXPORT_PER_CPU_SYMBOL_GPL(gdt_page); |
6720 |
+- |
6721 |
+ #ifdef CONFIG_X86_32 |
6722 |
+ static int cachesize_override __cpuinitdata = -1; |
6723 |
+ static int disable_x86_serial_nr __cpuinitdata = 1; |
6724 |
+@@ -227,7 +173,7 @@ void switch_to_new_gdt(void) |
6725 |
+ { |
6726 |
+ struct desc_ptr gdt_descr; |
6727 |
+ |
6728 |
+- gdt_descr.address = (long)get_cpu_gdt_table(smp_processor_id()); |
6729 |
++ gdt_descr.address = (unsigned long)get_cpu_gdt_table(smp_processor_id()); |
6730 |
+ gdt_descr.size = GDT_SIZE - 1; |
6731 |
+ load_gdt(&gdt_descr); |
6732 |
+ #ifdef CONFIG_X86_32 |
6733 |
+@@ -687,6 +633,10 @@ static void __cpuinit identify_cpu(struc |
6734 |
+ * we do "generic changes." |
6735 |
+ */ |
6736 |
+ |
6737 |
++#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) |
6738 |
++ setup_clear_cpu_cap(X86_FEATURE_SEP); |
6739 |
++#endif |
6740 |
++ |
6741 |
+ /* If the model name is still unset, do table lookup. */ |
6742 |
+ if (!c->x86_model_id[0]) { |
6743 |
+ char *p; |
6744 |
+@@ -854,13 +804,13 @@ static __init int setup_disablecpuid(cha |
6745 |
+ } |
6746 |
+ __setup("clearcpuid=", setup_disablecpuid); |
6747 |
+ |
6748 |
+-cpumask_t cpu_initialized __cpuinitdata = CPU_MASK_NONE; |
6749 |
++cpumask_t cpu_initialized = CPU_MASK_NONE; |
6750 |
+ |
6751 |
+ #ifdef CONFIG_X86_64 |
6752 |
+ struct x8664_pda **_cpu_pda __read_mostly; |
6753 |
+ EXPORT_SYMBOL(_cpu_pda); |
6754 |
+ |
6755 |
+-struct desc_ptr idt_descr = { 256 * 16 - 1, (unsigned long) idt_table }; |
6756 |
++struct desc_ptr idt_descr __read_only = { 256 * 16 - 1, (unsigned long) idt_table }; |
6757 |
+ |
6758 |
+ char boot_cpu_stack[IRQSTACKSIZE] __page_aligned_bss; |
6759 |
+ |
6760 |
+@@ -959,7 +909,7 @@ struct pt_regs * __cpuinit idle_regs(str |
6761 |
+ void __cpuinit cpu_init(void) |
6762 |
+ { |
6763 |
+ int cpu = stack_smp_processor_id(); |
6764 |
+- struct tss_struct *t = &per_cpu(init_tss, cpu); |
6765 |
++ struct tss_struct *t = init_tss + cpu; |
6766 |
+ struct orig_ist *orig_ist = &per_cpu(orig_ist, cpu); |
6767 |
+ unsigned long v; |
6768 |
+ char *estacks = NULL; |
6769 |
+@@ -1080,7 +1030,7 @@ void __cpuinit cpu_init(void) |
6770 |
+ { |
6771 |
+ int cpu = smp_processor_id(); |
6772 |
+ struct task_struct *curr = current; |
6773 |
+- struct tss_struct *t = &per_cpu(init_tss, cpu); |
6774 |
++ struct tss_struct *t = init_tss + cpu; |
6775 |
+ struct thread_struct *thread = &curr->thread; |
6776 |
+ |
6777 |
+ if (cpu_test_and_set(cpu, cpu_initialized)) { |
6778 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c |
6779 |
+--- linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2009-02-06 16:47:45.000000000 -0500 |
6780 |
++++ linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c 2009-02-21 09:37:48.000000000 -0500 |
6781 |
+@@ -561,7 +561,7 @@ static const struct dmi_system_id sw_any |
6782 |
+ DMI_MATCH(DMI_PRODUCT_NAME, "X6DLP"), |
6783 |
+ }, |
6784 |
+ }, |
6785 |
+- { } |
6786 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL } |
6787 |
+ }; |
6788 |
+ #endif |
6789 |
+ |
6790 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c |
6791 |
+--- linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c 2009-02-06 16:47:45.000000000 -0500 |
6792 |
++++ linux-2.6.28.8/arch/x86/kernel/cpu/cpufreq/speedstep-centrino.c 2009-02-21 09:37:48.000000000 -0500 |
6793 |
+@@ -225,7 +225,7 @@ static struct cpu_model models[] = |
6794 |
+ { &cpu_ids[CPU_MP4HT_D0], NULL, 0, NULL }, |
6795 |
+ { &cpu_ids[CPU_MP4HT_E0], NULL, 0, NULL }, |
6796 |
+ |
6797 |
+- { NULL, } |
6798 |
++ { NULL, NULL, 0, NULL} |
6799 |
+ }; |
6800 |
+ #undef _BANIAS |
6801 |
+ #undef BANIAS |
6802 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/intel.c linux-2.6.28.8/arch/x86/kernel/cpu/intel.c |
6803 |
+--- linux-2.6.28.8/arch/x86/kernel/cpu/intel.c 2009-02-06 16:47:45.000000000 -0500 |
6804 |
++++ linux-2.6.28.8/arch/x86/kernel/cpu/intel.c 2009-02-21 09:37:48.000000000 -0500 |
6805 |
+@@ -72,7 +72,7 @@ static void __cpuinit trap_init_f00f_bug |
6806 |
+ * Update the IDT descriptor and reload the IDT so that |
6807 |
+ * it uses the read-only mapped virtual address. |
6808 |
+ */ |
6809 |
+- idt_descr.address = fix_to_virt(FIX_F00F_IDT); |
6810 |
++ idt_descr.address = (struct desc_struct *)fix_to_virt(FIX_F00F_IDT); |
6811 |
+ load_idt(&idt_descr); |
6812 |
+ } |
6813 |
+ #endif |
6814 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/mcheck/mce_64.c linux-2.6.28.8/arch/x86/kernel/cpu/mcheck/mce_64.c |
6815 |
+--- linux-2.6.28.8/arch/x86/kernel/cpu/mcheck/mce_64.c 2009-02-06 16:47:45.000000000 -0500 |
6816 |
++++ linux-2.6.28.8/arch/x86/kernel/cpu/mcheck/mce_64.c 2009-02-21 09:37:48.000000000 -0500 |
6817 |
+@@ -678,6 +678,7 @@ static struct miscdevice mce_log_device |
6818 |
+ MISC_MCELOG_MINOR, |
6819 |
+ "mcelog", |
6820 |
+ &mce_chrdev_ops, |
6821 |
++ {NULL, NULL}, NULL, NULL |
6822 |
+ }; |
6823 |
+ |
6824 |
+ static unsigned long old_cr4 __initdata; |
6825 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/cpu/mtrr/generic.c linux-2.6.28.8/arch/x86/kernel/cpu/mtrr/generic.c |
6826 |
+--- linux-2.6.28.8/arch/x86/kernel/cpu/mtrr/generic.c 2009-02-06 16:47:45.000000000 -0500 |
6827 |
++++ linux-2.6.28.8/arch/x86/kernel/cpu/mtrr/generic.c 2009-02-21 09:37:48.000000000 -0500 |
6828 |
+@@ -31,11 +31,11 @@ static struct fixed_range_block fixed_ra |
6829 |
+ { MTRRfix64K_00000_MSR, 1 }, /* one 64k MTRR */ |
6830 |
+ { MTRRfix16K_80000_MSR, 2 }, /* two 16k MTRRs */ |
6831 |
+ { MTRRfix4K_C0000_MSR, 8 }, /* eight 4k MTRRs */ |
6832 |
+- {} |
6833 |
++ { 0, 0 } |
6834 |
+ }; |
6835 |
+ |
6836 |
+ static unsigned long smp_changes_mask; |
6837 |
+-static struct mtrr_state mtrr_state = {}; |
6838 |
++static struct mtrr_state mtrr_state; |
6839 |
+ static int mtrr_state_set; |
6840 |
+ u64 mtrr_tom2; |
6841 |
+ |
6842 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/crash.c linux-2.6.28.8/arch/x86/kernel/crash.c |
6843 |
+--- linux-2.6.28.8/arch/x86/kernel/crash.c 2009-02-06 16:47:45.000000000 -0500 |
6844 |
++++ linux-2.6.28.8/arch/x86/kernel/crash.c 2009-02-21 09:37:48.000000000 -0500 |
6845 |
+@@ -59,7 +59,7 @@ static int crash_nmi_callback(struct not |
6846 |
+ local_irq_disable(); |
6847 |
+ |
6848 |
+ #ifdef CONFIG_X86_32 |
6849 |
+- if (!user_mode_vm(regs)) { |
6850 |
++ if (!user_mode(regs)) { |
6851 |
+ crash_fixup_ss_esp(&fixed_regs, regs); |
6852 |
+ regs = &fixed_regs; |
6853 |
+ } |
6854 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/doublefault_32.c linux-2.6.28.8/arch/x86/kernel/doublefault_32.c |
6855 |
+--- linux-2.6.28.8/arch/x86/kernel/doublefault_32.c 2009-02-06 16:47:45.000000000 -0500 |
6856 |
++++ linux-2.6.28.8/arch/x86/kernel/doublefault_32.c 2009-02-21 09:37:48.000000000 -0500 |
6857 |
+@@ -11,7 +11,7 @@ |
6858 |
+ |
6859 |
+ #define DOUBLEFAULT_STACKSIZE (1024) |
6860 |
+ static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE]; |
6861 |
+-#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE) |
6862 |
++#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE-2) |
6863 |
+ |
6864 |
+ #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + MAXMEM) |
6865 |
+ |
6866 |
+@@ -21,7 +21,7 @@ static void doublefault_fn(void) |
6867 |
+ unsigned long gdt, tss; |
6868 |
+ |
6869 |
+ store_gdt(&gdt_desc); |
6870 |
+- gdt = gdt_desc.address; |
6871 |
++ gdt = (unsigned long)gdt_desc.address; |
6872 |
+ |
6873 |
+ printk(KERN_EMERG "PANIC: double fault, gdt at %08lx [%d bytes]\n", gdt, gdt_desc.size); |
6874 |
+ |
6875 |
+@@ -60,10 +60,10 @@ struct tss_struct doublefault_tss __cach |
6876 |
+ /* 0x2 bit is always set */ |
6877 |
+ .flags = X86_EFLAGS_SF | 0x2, |
6878 |
+ .sp = STACK_START, |
6879 |
+- .es = __USER_DS, |
6880 |
++ .es = __KERNEL_DS, |
6881 |
+ .cs = __KERNEL_CS, |
6882 |
+ .ss = __KERNEL_DS, |
6883 |
+- .ds = __USER_DS, |
6884 |
++ .ds = __KERNEL_DS, |
6885 |
+ .fs = __KERNEL_PERCPU, |
6886 |
+ |
6887 |
+ .__cr3 = __pa_nodebug(swapper_pg_dir), |
6888 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c |
6889 |
+--- linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c 2009-02-06 16:47:45.000000000 -0500 |
6890 |
++++ linux-2.6.28.8/arch/x86/kernel/dumpstack_32.c 2009-02-21 09:37:48.000000000 -0500 |
6891 |
+@@ -238,11 +238,12 @@ void show_registers(struct pt_regs *regs |
6892 |
+ * When in-kernel, we also print out the stack and code at the |
6893 |
+ * time of the fault.. |
6894 |
+ */ |
6895 |
+- if (!user_mode_vm(regs)) { |
6896 |
++ if (!user_mode(regs)) { |
6897 |
+ unsigned int code_prologue = code_bytes * 43 / 64; |
6898 |
+ unsigned int code_len = code_bytes; |
6899 |
+ unsigned char c; |
6900 |
+ u8 *ip; |
6901 |
++ unsigned long cs_base = get_desc_base(&get_cpu_gdt_table(smp_processor_id())[(0xffff & regs->cs) >> 3]); |
6902 |
+ |
6903 |
+ printk(KERN_EMERG "Stack:\n"); |
6904 |
+ show_stack_log_lvl(NULL, regs, ®s->sp, |
6905 |
+@@ -250,10 +251,10 @@ void show_registers(struct pt_regs *regs |
6906 |
+ |
6907 |
+ printk(KERN_EMERG "Code: "); |
6908 |
+ |
6909 |
+- ip = (u8 *)regs->ip - code_prologue; |
6910 |
++ ip = (u8 *)regs->ip - code_prologue + cs_base; |
6911 |
+ if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) { |
6912 |
+ /* try starting at IP */ |
6913 |
+- ip = (u8 *)regs->ip; |
6914 |
++ ip = (u8 *)regs->ip + cs_base; |
6915 |
+ code_len = code_len - code_prologue + 1; |
6916 |
+ } |
6917 |
+ for (i = 0; i < code_len; i++, ip++) { |
6918 |
+@@ -262,7 +263,7 @@ void show_registers(struct pt_regs *regs |
6919 |
+ printk(" Bad EIP value."); |
6920 |
+ break; |
6921 |
+ } |
6922 |
+- if (ip == (u8 *)regs->ip) |
6923 |
++ if (ip == (u8 *)regs->ip + cs_base) |
6924 |
+ printk("<%02x> ", c); |
6925 |
+ else |
6926 |
+ printk("%02x ", c); |
6927 |
+@@ -275,6 +276,7 @@ int is_valid_bugaddr(unsigned long ip) |
6928 |
+ { |
6929 |
+ unsigned short ud2; |
6930 |
+ |
6931 |
++ ip = ktla_ktva(ip); |
6932 |
+ if (ip < PAGE_OFFSET) |
6933 |
+ return 0; |
6934 |
+ if (probe_kernel_address((unsigned short *)ip, ud2)) |
6935 |
+@@ -410,7 +412,7 @@ die_nmi(char *str, struct pt_regs *regs, |
6936 |
+ * If we are in kernel we are probably nested up pretty bad |
6937 |
+ * and might aswell get out now while we still can: |
6938 |
+ */ |
6939 |
+- if (!user_mode_vm(regs)) { |
6940 |
++ if (!user_mode(regs)) { |
6941 |
+ current->thread.trap_no = 2; |
6942 |
+ crash_kexec(regs); |
6943 |
+ } |
6944 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/efi_32.c linux-2.6.28.8/arch/x86/kernel/efi_32.c |
6945 |
+--- linux-2.6.28.8/arch/x86/kernel/efi_32.c 2009-02-06 16:47:45.000000000 -0500 |
6946 |
++++ linux-2.6.28.8/arch/x86/kernel/efi_32.c 2009-02-21 09:37:48.000000000 -0500 |
6947 |
+@@ -38,70 +38,38 @@ |
6948 |
+ */ |
6949 |
+ |
6950 |
+ static unsigned long efi_rt_eflags; |
6951 |
+-static pgd_t efi_bak_pg_dir_pointer[2]; |
6952 |
++static pgd_t __initdata efi_bak_pg_dir_pointer[KERNEL_PGD_PTRS]; |
6953 |
+ |
6954 |
+-void efi_call_phys_prelog(void) |
6955 |
++void __init efi_call_phys_prelog(void) |
6956 |
+ { |
6957 |
+- unsigned long cr4; |
6958 |
+- unsigned long temp; |
6959 |
+ struct desc_ptr gdt_descr; |
6960 |
+ |
6961 |
+ local_irq_save(efi_rt_eflags); |
6962 |
+ |
6963 |
+- /* |
6964 |
+- * If I don't have PAE, I should just duplicate two entries in page |
6965 |
+- * directory. If I have PAE, I just need to duplicate one entry in |
6966 |
+- * page directory. |
6967 |
+- */ |
6968 |
+- cr4 = read_cr4_safe(); |
6969 |
+ |
6970 |
+- if (cr4 & X86_CR4_PAE) { |
6971 |
+- efi_bak_pg_dir_pointer[0].pgd = |
6972 |
+- swapper_pg_dir[pgd_index(0)].pgd; |
6973 |
+- swapper_pg_dir[0].pgd = |
6974 |
+- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; |
6975 |
+- } else { |
6976 |
+- efi_bak_pg_dir_pointer[0].pgd = |
6977 |
+- swapper_pg_dir[pgd_index(0)].pgd; |
6978 |
+- efi_bak_pg_dir_pointer[1].pgd = |
6979 |
+- swapper_pg_dir[pgd_index(0x400000)].pgd; |
6980 |
+- swapper_pg_dir[pgd_index(0)].pgd = |
6981 |
+- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd; |
6982 |
+- temp = PAGE_OFFSET + 0x400000; |
6983 |
+- swapper_pg_dir[pgd_index(0x400000)].pgd = |
6984 |
+- swapper_pg_dir[pgd_index(temp)].pgd; |
6985 |
+- } |
6986 |
++ clone_pgd_range(efi_bak_pg_dir_pointer, swapper_pg_dir, KERNEL_PGD_PTRS); |
6987 |
++ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY, |
6988 |
++ min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); |
6989 |
+ |
6990 |
+ /* |
6991 |
+ * After the lock is released, the original page table is restored. |
6992 |
+ */ |
6993 |
+ __flush_tlb_all(); |
6994 |
+ |
6995 |
+- gdt_descr.address = __pa(get_cpu_gdt_table(0)); |
6996 |
++ gdt_descr.address = (struct desc_struct *)__pa(get_cpu_gdt_table(0)); |
6997 |
+ gdt_descr.size = GDT_SIZE - 1; |
6998 |
+ load_gdt(&gdt_descr); |
6999 |
+ } |
7000 |
+ |
7001 |
+-void efi_call_phys_epilog(void) |
7002 |
++void __init efi_call_phys_epilog(void) |
7003 |
+ { |
7004 |
+- unsigned long cr4; |
7005 |
+ struct desc_ptr gdt_descr; |
7006 |
+ |
7007 |
+- gdt_descr.address = (unsigned long)get_cpu_gdt_table(0); |
7008 |
++ gdt_descr.address = get_cpu_gdt_table(0); |
7009 |
+ gdt_descr.size = GDT_SIZE - 1; |
7010 |
+ load_gdt(&gdt_descr); |
7011 |
+ |
7012 |
+- cr4 = read_cr4_safe(); |
7013 |
+- |
7014 |
+- if (cr4 & X86_CR4_PAE) { |
7015 |
+- swapper_pg_dir[pgd_index(0)].pgd = |
7016 |
+- efi_bak_pg_dir_pointer[0].pgd; |
7017 |
+- } else { |
7018 |
+- swapper_pg_dir[pgd_index(0)].pgd = |
7019 |
+- efi_bak_pg_dir_pointer[0].pgd; |
7020 |
+- swapper_pg_dir[pgd_index(0x400000)].pgd = |
7021 |
+- efi_bak_pg_dir_pointer[1].pgd; |
7022 |
+- } |
7023 |
++ clone_pgd_range(swapper_pg_dir, efi_bak_pg_dir_pointer, KERNEL_PGD_PTRS); |
7024 |
+ |
7025 |
+ /* |
7026 |
+ * After the lock is released, the original page table is restored. |
7027 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/efi_stub_32.S linux-2.6.28.8/arch/x86/kernel/efi_stub_32.S |
7028 |
+--- linux-2.6.28.8/arch/x86/kernel/efi_stub_32.S 2009-02-06 16:47:45.000000000 -0500 |
7029 |
++++ linux-2.6.28.8/arch/x86/kernel/efi_stub_32.S 2009-02-21 09:37:48.000000000 -0500 |
7030 |
+@@ -6,6 +6,7 @@ |
7031 |
+ */ |
7032 |
+ |
7033 |
+ #include <linux/linkage.h> |
7034 |
++#include <linux/init.h> |
7035 |
+ #include <asm/page.h> |
7036 |
+ |
7037 |
+ /* |
7038 |
+@@ -20,7 +21,7 @@ |
7039 |
+ * service functions will comply with gcc calling convention, too. |
7040 |
+ */ |
7041 |
+ |
7042 |
+-.text |
7043 |
++__INIT |
7044 |
+ ENTRY(efi_call_phys) |
7045 |
+ /* |
7046 |
+ * 0. The function can only be called in Linux kernel. So CS has been |
7047 |
+@@ -36,9 +37,7 @@ ENTRY(efi_call_phys) |
7048 |
+ * The mapping of lower virtual memory has been created in prelog and |
7049 |
+ * epilog. |
7050 |
+ */ |
7051 |
+- movl $1f, %edx |
7052 |
+- subl $__PAGE_OFFSET, %edx |
7053 |
+- jmp *%edx |
7054 |
++ jmp 1f-__PAGE_OFFSET |
7055 |
+ 1: |
7056 |
+ |
7057 |
+ /* |
7058 |
+@@ -47,14 +46,8 @@ ENTRY(efi_call_phys) |
7059 |
+ * parameter 2, ..., param n. To make things easy, we save the return |
7060 |
+ * address of efi_call_phys in a global variable. |
7061 |
+ */ |
7062 |
+- popl %edx |
7063 |
+- movl %edx, saved_return_addr |
7064 |
+- /* get the function pointer into ECX*/ |
7065 |
+- popl %ecx |
7066 |
+- movl %ecx, efi_rt_function_ptr |
7067 |
+- movl $2f, %edx |
7068 |
+- subl $__PAGE_OFFSET, %edx |
7069 |
+- pushl %edx |
7070 |
++ popl (saved_return_addr) |
7071 |
++ popl (efi_rt_function_ptr) |
7072 |
+ |
7073 |
+ /* |
7074 |
+ * 3. Clear PG bit in %CR0. |
7075 |
+@@ -73,9 +66,8 @@ ENTRY(efi_call_phys) |
7076 |
+ /* |
7077 |
+ * 5. Call the physical function. |
7078 |
+ */ |
7079 |
+- jmp *%ecx |
7080 |
++ call *(efi_rt_function_ptr-__PAGE_OFFSET) |
7081 |
+ |
7082 |
+-2: |
7083 |
+ /* |
7084 |
+ * 6. After EFI runtime service returns, control will return to |
7085 |
+ * following instruction. We'd better readjust stack pointer first. |
7086 |
+@@ -88,34 +80,27 @@ ENTRY(efi_call_phys) |
7087 |
+ movl %cr0, %edx |
7088 |
+ orl $0x80000000, %edx |
7089 |
+ movl %edx, %cr0 |
7090 |
+- jmp 1f |
7091 |
+-1: |
7092 |
++ |
7093 |
+ /* |
7094 |
+ * 8. Now restore the virtual mode from flat mode by |
7095 |
+ * adding EIP with PAGE_OFFSET. |
7096 |
+ */ |
7097 |
+- movl $1f, %edx |
7098 |
+- jmp *%edx |
7099 |
++ jmp 1f+__PAGE_OFFSET |
7100 |
+ 1: |
7101 |
+ |
7102 |
+ /* |
7103 |
+ * 9. Balance the stack. And because EAX contain the return value, |
7104 |
+ * we'd better not clobber it. |
7105 |
+ */ |
7106 |
+- leal efi_rt_function_ptr, %edx |
7107 |
+- movl (%edx), %ecx |
7108 |
+- pushl %ecx |
7109 |
++ pushl (efi_rt_function_ptr) |
7110 |
+ |
7111 |
+ /* |
7112 |
+- * 10. Push the saved return address onto the stack and return. |
7113 |
++ * 10. Return to the saved return address. |
7114 |
+ */ |
7115 |
+- leal saved_return_addr, %edx |
7116 |
+- movl (%edx), %ecx |
7117 |
+- pushl %ecx |
7118 |
+- ret |
7119 |
++ jmpl *(saved_return_addr) |
7120 |
+ .previous |
7121 |
+ |
7122 |
+-.data |
7123 |
++__INITDATA |
7124 |
+ saved_return_addr: |
7125 |
+ .long 0 |
7126 |
+ efi_rt_function_ptr: |
7127 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/entry_32.S linux-2.6.28.8/arch/x86/kernel/entry_32.S |
7128 |
+--- linux-2.6.28.8/arch/x86/kernel/entry_32.S 2009-02-06 16:47:45.000000000 -0500 |
7129 |
++++ linux-2.6.28.8/arch/x86/kernel/entry_32.S 2009-02-21 09:37:48.000000000 -0500 |
7130 |
+@@ -101,7 +101,7 @@ |
7131 |
+ #define resume_userspace_sig resume_userspace |
7132 |
+ #endif |
7133 |
+ |
7134 |
+-#define SAVE_ALL \ |
7135 |
++#define __SAVE_ALL(_DS) \ |
7136 |
+ cld; \ |
7137 |
+ pushl %fs; \ |
7138 |
+ CFI_ADJUST_CFA_OFFSET 4;\ |
7139 |
+@@ -133,12 +133,26 @@ |
7140 |
+ pushl %ebx; \ |
7141 |
+ CFI_ADJUST_CFA_OFFSET 4;\ |
7142 |
+ CFI_REL_OFFSET ebx, 0;\ |
7143 |
+- movl $(__USER_DS), %edx; \ |
7144 |
++ movl $(_DS), %edx; \ |
7145 |
+ movl %edx, %ds; \ |
7146 |
+ movl %edx, %es; \ |
7147 |
+ movl $(__KERNEL_PERCPU), %edx; \ |
7148 |
+ movl %edx, %fs |
7149 |
+ |
7150 |
++#ifdef CONFIG_PAX_KERNEXEC |
7151 |
++#define SAVE_ALL \ |
7152 |
++ __SAVE_ALL(__KERNEL_DS); \ |
7153 |
++ GET_CR0_INTO_EDX; \ |
7154 |
++ movl %edx, %esi; \ |
7155 |
++ orl $X86_CR0_WP, %edx; \ |
7156 |
++ xorl %edx, %esi; \ |
7157 |
++ SET_CR0_FROM_EDX |
7158 |
++#elif defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_MEMORY_UDEREF) |
7159 |
++#define SAVE_ALL __SAVE_ALL(__KERNEL_DS) |
7160 |
++#else |
7161 |
++#define SAVE_ALL __SAVE_ALL(__USER_DS) |
7162 |
++#endif |
7163 |
++ |
7164 |
+ #define RESTORE_INT_REGS \ |
7165 |
+ popl %ebx; \ |
7166 |
+ CFI_ADJUST_CFA_OFFSET -4;\ |
7167 |
+@@ -229,6 +243,11 @@ ENTRY(ret_from_fork) |
7168 |
+ CFI_ADJUST_CFA_OFFSET 4 |
7169 |
+ popfl |
7170 |
+ CFI_ADJUST_CFA_OFFSET -4 |
7171 |
++ |
7172 |
++#ifdef CONFIG_PAX_KERNEXEC |
7173 |
++ xorl %esi, %esi |
7174 |
++#endif |
7175 |
++ |
7176 |
+ jmp syscall_exit |
7177 |
+ CFI_ENDPROC |
7178 |
+ END(ret_from_fork) |
7179 |
+@@ -252,7 +271,17 @@ check_userspace: |
7180 |
+ movb PT_CS(%esp), %al |
7181 |
+ andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax |
7182 |
+ cmpl $USER_RPL, %eax |
7183 |
++ |
7184 |
++#ifdef CONFIG_PAX_KERNEXEC |
7185 |
++ jae resume_userspace |
7186 |
++ |
7187 |
++ GET_CR0_INTO_EDX |
7188 |
++ xorl %esi, %edx |
7189 |
++ SET_CR0_FROM_EDX |
7190 |
++ jmp resume_kernel |
7191 |
++#else |
7192 |
+ jb resume_kernel # not returning to v8086 or userspace |
7193 |
++#endif |
7194 |
+ |
7195 |
+ ENTRY(resume_userspace) |
7196 |
+ LOCKDEP_SYS_EXIT |
7197 |
+@@ -314,10 +343,9 @@ sysenter_past_esp: |
7198 |
+ /*CFI_REL_OFFSET cs, 0*/ |
7199 |
+ /* |
7200 |
+ * Push current_thread_info()->sysenter_return to the stack. |
7201 |
+- * A tiny bit of offset fixup is necessary - 4*4 means the 4 words |
7202 |
+- * pushed above; +8 corresponds to copy_thread's esp0 setting. |
7203 |
+ */ |
7204 |
+- pushl (TI_sysenter_return-THREAD_SIZE+8+4*4)(%esp) |
7205 |
++ GET_THREAD_INFO(%ebp) |
7206 |
++ pushl TI_sysenter_return(%ebp) |
7207 |
+ CFI_ADJUST_CFA_OFFSET 4 |
7208 |
+ CFI_REL_OFFSET eip, 0 |
7209 |
+ |
7210 |
+@@ -330,9 +358,19 @@ sysenter_past_esp: |
7211 |
+ * Load the potential sixth argument from user stack. |
7212 |
+ * Careful about security. |
7213 |
+ */ |
7214 |
++ movl PT_OLDESP(%esp),%ebp |
7215 |
++ |
7216 |
++#ifdef CONFIG_PAX_MEMORY_UDEREF |
7217 |
++ mov PT_OLDSS(%esp),%ds |
7218 |
++1: movl %ds:(%ebp),%ebp |
7219 |
++ push %ss |
7220 |
++ pop %ds |
7221 |
++#else |
7222 |
+ cmpl $__PAGE_OFFSET-3,%ebp |
7223 |
+ jae syscall_fault |
7224 |
+ 1: movl (%ebp),%ebp |
7225 |
++#endif |
7226 |
++ |
7227 |
+ movl %ebp,PT_EBP(%esp) |
7228 |
+ .section __ex_table,"a" |
7229 |
+ .align 4 |
7230 |
+@@ -356,12 +394,23 @@ sysenter_do_call: |
7231 |
+ testw $_TIF_ALLWORK_MASK, %cx |
7232 |
+ jne sysexit_audit |
7233 |
+ sysenter_exit: |
7234 |
++ |
7235 |
++#ifdef CONFIG_PAX_RANDKSTACK |
7236 |
++ pushl %eax |
7237 |
++ CFI_ADJUST_CFA_OFFSET 4 |
7238 |
++ call pax_randomize_kstack |
7239 |
++ popl %eax |
7240 |
++ CFI_ADJUST_CFA_OFFSET -4 |
7241 |
++#endif |
7242 |
++ |
7243 |
+ /* if something modifies registers it must also disable sysexit */ |
7244 |
+ movl PT_EIP(%esp), %edx |
7245 |
+ movl PT_OLDESP(%esp), %ecx |
7246 |
+ xorl %ebp,%ebp |
7247 |
+ TRACE_IRQS_ON |
7248 |
+ 1: mov PT_FS(%esp), %fs |
7249 |
++2: mov PT_DS(%esp), %ds |
7250 |
++3: mov PT_ES(%esp), %es |
7251 |
+ ENABLE_INTERRUPTS_SYSEXIT |
7252 |
+ |
7253 |
+ #ifdef CONFIG_AUDITSYSCALL |
7254 |
+@@ -404,11 +453,17 @@ sysexit_audit: |
7255 |
+ |
7256 |
+ CFI_ENDPROC |
7257 |
+ .pushsection .fixup,"ax" |
7258 |
+-2: movl $0,PT_FS(%esp) |
7259 |
++4: movl $0,PT_FS(%esp) |
7260 |
++ jmp 1b |
7261 |
++5: movl $0,PT_DS(%esp) |
7262 |
++ jmp 1b |
7263 |
++6: movl $0,PT_ES(%esp) |
7264 |
+ jmp 1b |
7265 |
+ .section __ex_table,"a" |
7266 |
+ .align 4 |
7267 |
+- .long 1b,2b |
7268 |
++ .long 1b,4b |
7269 |
++ .long 2b,5b |
7270 |
++ .long 3b,6b |
7271 |
+ .popsection |
7272 |
+ ENDPROC(ia32_sysenter_target) |
7273 |
+ |
7274 |
+@@ -438,6 +493,10 @@ syscall_exit: |
7275 |
+ testw $_TIF_ALLWORK_MASK, %cx # current->work |
7276 |
+ jne syscall_exit_work |
7277 |
+ |
7278 |
++#ifdef CONFIG_PAX_RANDKSTACK |
7279 |
++ call pax_randomize_kstack |
7280 |
++#endif |
7281 |
++ |
7282 |
+ restore_all: |
7283 |
+ movl PT_EFLAGS(%esp), %eax # mix EFLAGS, SS and CS |
7284 |
+ # Warning: PT_OLDSS(%esp) contains the wrong/random values if we |
7285 |
+@@ -531,25 +590,19 @@ work_resched: |
7286 |
+ |
7287 |
+ work_notifysig: # deal with pending signals and |
7288 |
+ # notify-resume requests |
7289 |
++ movl %esp, %eax |
7290 |
+ #ifdef CONFIG_VM86 |
7291 |
+ testl $X86_EFLAGS_VM, PT_EFLAGS(%esp) |
7292 |
+- movl %esp, %eax |
7293 |
+- jne work_notifysig_v86 # returning to kernel-space or |
7294 |
++ jz 1f # returning to kernel-space or |
7295 |
+ # vm86-space |
7296 |
+- xorl %edx, %edx |
7297 |
+- call do_notify_resume |
7298 |
+- jmp resume_userspace_sig |
7299 |
+ |
7300 |
+- ALIGN |
7301 |
+-work_notifysig_v86: |
7302 |
+ pushl %ecx # save ti_flags for do_notify_resume |
7303 |
+ CFI_ADJUST_CFA_OFFSET 4 |
7304 |
+ call save_v86_state # %eax contains pt_regs pointer |
7305 |
+ popl %ecx |
7306 |
+ CFI_ADJUST_CFA_OFFSET -4 |
7307 |
+ movl %eax, %esp |
7308 |
+-#else |
7309 |
+- movl %esp, %eax |
7310 |
++1: |
7311 |
+ #endif |
7312 |
+ xorl %edx, %edx |
7313 |
+ call do_notify_resume |
7314 |
+@@ -584,6 +637,10 @@ END(syscall_exit_work) |
7315 |
+ |
7316 |
+ RING0_INT_FRAME # can't unwind into user space anyway |
7317 |
+ syscall_fault: |
7318 |
++#ifdef CONFIG_PAX_MEMORY_UDEREF |
7319 |
++ push %ss |
7320 |
++ pop %ds |
7321 |
++#endif |
7322 |
+ GET_THREAD_INFO(%ebp) |
7323 |
+ movl $-EFAULT,PT_EAX(%esp) |
7324 |
+ jmp resume_userspace |
7325 |
+@@ -595,17 +652,24 @@ syscall_badsys: |
7326 |
+ END(syscall_badsys) |
7327 |
+ CFI_ENDPROC |
7328 |
+ |
7329 |
+-#define FIXUP_ESPFIX_STACK \ |
7330 |
+- /* since we are on a wrong stack, we cant make it a C code :( */ \ |
7331 |
+- PER_CPU(gdt_page, %ebx); \ |
7332 |
+- GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \ |
7333 |
+- addl %esp, %eax; \ |
7334 |
+- pushl $__KERNEL_DS; \ |
7335 |
+- CFI_ADJUST_CFA_OFFSET 4; \ |
7336 |
+- pushl %eax; \ |
7337 |
+- CFI_ADJUST_CFA_OFFSET 4; \ |
7338 |
+- lss (%esp), %esp; \ |
7339 |
++.macro FIXUP_ESPFIX_STACK |
7340 |
++ /* since we are on a wrong stack, we cant make it a C code :( */ |
7341 |
++#ifdef CONFIG_SMP |
7342 |
++ movl PER_CPU_VAR(cpu_number), %ebx; |
7343 |
++ shll $PAGE_SHIFT_asm, %ebx; |
7344 |
++ addl $cpu_gdt_table, %ebx; |
7345 |
++#else |
7346 |
++ movl $cpu_gdt_table, %ebx; |
7347 |
++#endif |
7348 |
++ GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); |
7349 |
++ addl %esp, %eax; |
7350 |
++ pushl $__KERNEL_DS; |
7351 |
++ CFI_ADJUST_CFA_OFFSET 4; |
7352 |
++ pushl %eax; |
7353 |
++ CFI_ADJUST_CFA_OFFSET 4; |
7354 |
++ lss (%esp), %esp; |
7355 |
+ CFI_ADJUST_CFA_OFFSET -8; |
7356 |
++.endm |
7357 |
+ #define UNWIND_ESPFIX_STACK \ |
7358 |
+ movl %ss, %eax; \ |
7359 |
+ /* see if on espfix stack */ \ |
7360 |
+@@ -622,7 +686,7 @@ END(syscall_badsys) |
7361 |
+ * Build the entry stubs and pointer table with |
7362 |
+ * some assembler magic. |
7363 |
+ */ |
7364 |
+-.section .rodata,"a" |
7365 |
++.section .rodata,"a",@progbits |
7366 |
+ ENTRY(interrupt) |
7367 |
+ .text |
7368 |
+ |
7369 |
+@@ -722,12 +786,21 @@ error_code: |
7370 |
+ popl %ecx |
7371 |
+ CFI_ADJUST_CFA_OFFSET -4 |
7372 |
+ /*CFI_REGISTER es, ecx*/ |
7373 |
++ |
7374 |
++#ifdef CONFIG_PAX_KERNEXEC |
7375 |
++ GET_CR0_INTO_EDX |
7376 |
++ movl %edx, %esi |
7377 |
++ orl $X86_CR0_WP, %edx |
7378 |
++ xorl %edx, %esi |
7379 |
++ SET_CR0_FROM_EDX |
7380 |
++#endif |
7381 |
++ |
7382 |
+ movl PT_FS(%esp), %edi # get the function address |
7383 |
+ movl PT_ORIG_EAX(%esp), %edx # get the error code |
7384 |
+ movl $-1, PT_ORIG_EAX(%esp) # no syscall to restart |
7385 |
+ mov %ecx, PT_FS(%esp) |
7386 |
+ /*CFI_REL_OFFSET fs, ES*/ |
7387 |
+- movl $(__USER_DS), %ecx |
7388 |
++ movl $(__KERNEL_DS), %ecx |
7389 |
+ movl %ecx, %ds |
7390 |
+ movl %ecx, %es |
7391 |
+ TRACE_IRQS_OFF |
7392 |
+@@ -853,6 +926,13 @@ nmi_stack_correct: |
7393 |
+ xorl %edx,%edx # zero error code |
7394 |
+ movl %esp,%eax # pt_regs pointer |
7395 |
+ call do_nmi |
7396 |
++ |
7397 |
++#ifdef CONFIG_PAX_KERNEXEC |
7398 |
++ GET_CR0_INTO_EDX |
7399 |
++ xorl %esi, %edx |
7400 |
++ SET_CR0_FROM_EDX |
7401 |
++#endif |
7402 |
++ |
7403 |
+ jmp restore_nocheck_notrace |
7404 |
+ CFI_ENDPROC |
7405 |
+ |
7406 |
+@@ -894,6 +974,13 @@ nmi_espfix_stack: |
7407 |
+ FIXUP_ESPFIX_STACK # %eax == %esp |
7408 |
+ xorl %edx,%edx # zero error code |
7409 |
+ call do_nmi |
7410 |
++ |
7411 |
++#ifdef CONFIG_PAX_KERNEXEC |
7412 |
++ GET_CR0_INTO_EDX |
7413 |
++ xorl %esi, %edx |
7414 |
++ SET_CR0_FROM_EDX |
7415 |
++#endif |
7416 |
++ |
7417 |
+ RESTORE_REGS |
7418 |
+ lss 12+4(%esp), %esp # back to espfix stack |
7419 |
+ CFI_ADJUST_CFA_OFFSET -24 |
7420 |
+@@ -1206,7 +1293,6 @@ END(mcount) |
7421 |
+ #endif /* CONFIG_DYNAMIC_FTRACE */ |
7422 |
+ #endif /* CONFIG_FUNCTION_TRACER */ |
7423 |
+ |
7424 |
+-.section .rodata,"a" |
7425 |
+ #include "syscall_table_32.S" |
7426 |
+ |
7427 |
+ syscall_table_size=(.-sys_call_table) |
7428 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/entry_64.S linux-2.6.28.8/arch/x86/kernel/entry_64.S |
7429 |
+--- linux-2.6.28.8/arch/x86/kernel/entry_64.S 2009-02-06 16:47:45.000000000 -0500 |
7430 |
++++ linux-2.6.28.8/arch/x86/kernel/entry_64.S 2009-02-21 09:37:48.000000000 -0500 |
7431 |
+@@ -911,7 +911,8 @@ END(spurious_interrupt) |
7432 |
+ xorl %ebx,%ebx |
7433 |
+ 1: |
7434 |
+ .if \ist |
7435 |
+- movq %gs:pda_data_offset, %rbp |
7436 |
++ imul $TSS_size, %gs:pda_cpunumber, %ebp |
7437 |
++ lea init_tss(%rbp), %rbp |
7438 |
+ .endif |
7439 |
+ .if \irqtrace |
7440 |
+ TRACE_IRQS_OFF |
7441 |
+@@ -920,11 +921,11 @@ END(spurious_interrupt) |
7442 |
+ movq ORIG_RAX(%rsp),%rsi |
7443 |
+ movq $-1,ORIG_RAX(%rsp) |
7444 |
+ .if \ist |
7445 |
+- subq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) |
7446 |
++ subq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp) |
7447 |
+ .endif |
7448 |
+ call \sym |
7449 |
+ .if \ist |
7450 |
+- addq $EXCEPTION_STKSZ, per_cpu__init_tss + TSS_ist + (\ist - 1) * 8(%rbp) |
7451 |
++ addq $EXCEPTION_STKSZ, TSS_ist + (\ist - 1) * 8(%rbp) |
7452 |
+ .endif |
7453 |
+ DISABLE_INTERRUPTS(CLBR_NONE) |
7454 |
+ .if \irqtrace |
7455 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/ftrace.c linux-2.6.28.8/arch/x86/kernel/ftrace.c |
7456 |
+--- linux-2.6.28.8/arch/x86/kernel/ftrace.c 2009-02-06 16:47:45.000000000 -0500 |
7457 |
++++ linux-2.6.28.8/arch/x86/kernel/ftrace.c 2009-02-21 09:37:48.000000000 -0500 |
7458 |
+@@ -95,9 +95,9 @@ int ftrace_update_ftrace_func(ftrace_fun |
7459 |
+ unsigned char old[MCOUNT_INSN_SIZE], *new; |
7460 |
+ int ret; |
7461 |
+ |
7462 |
+- memcpy(old, &ftrace_call, MCOUNT_INSN_SIZE); |
7463 |
++ memcpy(old, (void *)ktla_ktva((unsigned long)ftrace_call), MCOUNT_INSN_SIZE); |
7464 |
+ new = ftrace_call_replace(ip, (unsigned long)func); |
7465 |
+- ret = ftrace_modify_code(ip, old, new); |
7466 |
++ ret = ftrace_modify_code(ktla_ktva(ip), old, new); |
7467 |
+ |
7468 |
+ return ret; |
7469 |
+ } |
7470 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/head32.c linux-2.6.28.8/arch/x86/kernel/head32.c |
7471 |
+--- linux-2.6.28.8/arch/x86/kernel/head32.c 2009-02-06 16:47:45.000000000 -0500 |
7472 |
++++ linux-2.6.28.8/arch/x86/kernel/head32.c 2009-02-21 09:37:48.000000000 -0500 |
7473 |
+@@ -12,10 +12,11 @@ |
7474 |
+ #include <asm/sections.h> |
7475 |
+ #include <asm/e820.h> |
7476 |
+ #include <asm/bios_ebda.h> |
7477 |
++#include <asm/boot.h> |
7478 |
+ |
7479 |
+ void __init i386_start_kernel(void) |
7480 |
+ { |
7481 |
+- reserve_early(__pa_symbol(&_text), __pa_symbol(&_end), "TEXT DATA BSS"); |
7482 |
++ reserve_early(LOAD_PHYSICAL_ADDR, __pa_symbol(&_end), "TEXT DATA BSS"); |
7483 |
+ |
7484 |
+ #ifdef CONFIG_BLK_DEV_INITRD |
7485 |
+ /* Reserve INITRD */ |
7486 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/head_32.S linux-2.6.28.8/arch/x86/kernel/head_32.S |
7487 |
+--- linux-2.6.28.8/arch/x86/kernel/head_32.S 2009-02-06 16:47:45.000000000 -0500 |
7488 |
++++ linux-2.6.28.8/arch/x86/kernel/head_32.S 2009-02-21 09:37:48.000000000 -0500 |
7489 |
+@@ -19,6 +19,7 @@ |
7490 |
+ #include <asm/asm-offsets.h> |
7491 |
+ #include <asm/setup.h> |
7492 |
+ #include <asm/processor-flags.h> |
7493 |
++#include <asm/msr-index.h> |
7494 |
+ |
7495 |
+ /* Physical address */ |
7496 |
+ #define pa(X) ((X) - __PAGE_OFFSET) |
7497 |
+@@ -64,17 +65,22 @@ LOW_PAGES = 1<<(32-PAGE_SHIFT_asm) |
7498 |
+ LOW_PAGES = LOW_PAGES + 0x1000000 |
7499 |
+ #endif |
7500 |
+ |
7501 |
+-#if PTRS_PER_PMD > 1 |
7502 |
+-PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PMD) + PTRS_PER_PGD |
7503 |
+-#else |
7504 |
+-PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PGD) |
7505 |
+-#endif |
7506 |
++PAGE_TABLE_SIZE = (LOW_PAGES / PTRS_PER_PTE) |
7507 |
+ BOOTBITMAP_SIZE = LOW_PAGES / 8 |
7508 |
+ ALLOCATOR_SLOP = 4 |
7509 |
+ |
7510 |
+ INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + (PAGE_TABLE_SIZE + ALLOCATOR_SLOP)*PAGE_SIZE_asm |
7511 |
+ |
7512 |
+ /* |
7513 |
++ * Real beginning of normal "text" segment |
7514 |
++ */ |
7515 |
++ENTRY(stext) |
7516 |
++ENTRY(_stext) |
7517 |
++ |
7518 |
++.section .text.startup,"ax",@progbits |
7519 |
++ ljmp $(__BOOT_CS),$phys_startup_32 |
7520 |
++ |
7521 |
++/* |
7522 |
+ * 32-bit kernel entrypoint; only used by the boot CPU. On entry, |
7523 |
+ * %esi points to the real-mode code as a 32-bit pointer. |
7524 |
+ * CS and DS must be 4 GB flat segments, but we don't depend on |
7525 |
+@@ -82,6 +88,12 @@ INIT_MAP_BEYOND_END = BOOTBITMAP_SIZE + |
7526 |
+ * can. |
7527 |
+ */ |
7528 |
+ .section .text.head,"ax",@progbits |
7529 |
++ |
7530 |
++#ifdef CONFIG_PAX_KERNEXEC |
7531 |
++/* PaX: fill first page in .text with int3 to catch NULL derefs in kernel mode */ |
7532 |
++.fill 4096,1,0xcc |
7533 |
++#endif |
7534 |
++ |
7535 |
+ ENTRY(startup_32) |
7536 |
+ /* test KEEP_SEGMENTS flag to see if the bootloader is asking |
7537 |
+ us to not reload segments */ |
7538 |
+@@ -99,6 +111,56 @@ ENTRY(startup_32) |
7539 |
+ movl %eax,%gs |
7540 |
+ 2: |
7541 |
+ |
7542 |
++ movl $pa(cpu_gdt_table),%edi |
7543 |
++ movl $__per_cpu_start,%eax |
7544 |
++ movw %ax,__KERNEL_PERCPU + 2(%edi) |
7545 |
++ rorl $16,%eax |
7546 |
++ movb %al,__KERNEL_PERCPU + 4(%edi) |
7547 |
++ movb %ah,__KERNEL_PERCPU + 7(%edi) |
7548 |
++ movl $__per_cpu_end + PERCPU_MODULE_RESERVE - 1,%eax |
7549 |
++ subl $__per_cpu_start,%eax |
7550 |
++ movw %ax,__KERNEL_PERCPU + 0(%edi) |
7551 |
++ |
7552 |
++#ifdef CONFIG_PAX_MEMORY_UDEREF |
7553 |
++ /* check for VMware */ |
7554 |
++ movl $0x564d5868,%eax |
7555 |
++ xorl %ebx,%ebx |
7556 |
++ movl $0xa,%ecx |
7557 |
++ movl $0x5658,%edx |
7558 |
++ in (%dx),%eax |
7559 |
++ cmpl $0x564d5868,%ebx |
7560 |
++ jz 2f |
7561 |
++ |
7562 |
++ movl $NR_CPUS,%ecx |
7563 |
++ movl $pa(cpu_gdt_table),%edi |
7564 |
++1: |
7565 |
++ movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c09700),GDT_ENTRY_KERNEL_DS * 8 + 4(%edi) |
7566 |
++ addl $PAGE_SIZE_asm,%edi |
7567 |
++ loop 1b |
7568 |
++2: |
7569 |
++#endif |
7570 |
++ |
7571 |
++#ifdef CONFIG_PAX_KERNEXEC |
7572 |
++ movl $pa(boot_gdt),%edi |
7573 |
++ movl $KERNEL_TEXT_OFFSET,%eax |
7574 |
++ movw %ax,__BOOT_CS + 2(%edi) |
7575 |
++ rorl $16,%eax |
7576 |
++ movb %al,__BOOT_CS + 4(%edi) |
7577 |
++ movb %ah,__BOOT_CS + 7(%edi) |
7578 |
++ rorl $16,%eax |
7579 |
++ |
7580 |
++ movl $NR_CPUS,%ecx |
7581 |
++ movl $pa(cpu_gdt_table),%edi |
7582 |
++1: |
7583 |
++ movw %ax,__KERNEL_CS + 2(%edi) |
7584 |
++ rorl $16,%eax |
7585 |
++ movb %al,__KERNEL_CS + 4(%edi) |
7586 |
++ movb %ah,__KERNEL_CS + 7(%edi) |
7587 |
++ rorl $16,%eax |
7588 |
++ addl $PAGE_SIZE_asm,%edi |
7589 |
++ loop 1b |
7590 |
++#endif |
7591 |
++ |
7592 |
+ /* |
7593 |
+ * Clear BSS first so that there are no surprises... |
7594 |
+ */ |
7595 |
+@@ -142,9 +204,7 @@ ENTRY(startup_32) |
7596 |
+ cmpl $num_subarch_entries, %eax |
7597 |
+ jae bad_subarch |
7598 |
+ |
7599 |
+- movl pa(subarch_entries)(,%eax,4), %eax |
7600 |
+- subl $__PAGE_OFFSET, %eax |
7601 |
+- jmp *%eax |
7602 |
++ jmp *pa(subarch_entries)(,%eax,4) |
7603 |
+ |
7604 |
+ bad_subarch: |
7605 |
+ WEAK(lguest_entry) |
7606 |
+@@ -156,9 +216,9 @@ WEAK(xen_entry) |
7607 |
+ __INITDATA |
7608 |
+ |
7609 |
+ subarch_entries: |
7610 |
+- .long default_entry /* normal x86/PC */ |
7611 |
+- .long lguest_entry /* lguest hypervisor */ |
7612 |
+- .long xen_entry /* Xen hypervisor */ |
7613 |
++ .long pa(default_entry) /* normal x86/PC */ |
7614 |
++ .long pa(lguest_entry) /* lguest hypervisor */ |
7615 |
++ .long pa(xen_entry) /* Xen hypervisor */ |
7616 |
+ num_subarch_entries = (. - subarch_entries) / 4 |
7617 |
+ .previous |
7618 |
+ #endif /* CONFIG_PARAVIRT */ |
7619 |
+@@ -220,8 +280,7 @@ default_entry: |
7620 |
+ movl %eax, pa(max_pfn_mapped) |
7621 |
+ |
7622 |
+ /* Do early initialization of the fixmap area */ |
7623 |
+- movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax |
7624 |
+- movl %eax,pa(swapper_pg_pmd+0x1000*KPMDS-8) |
7625 |
++ movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,pa(swapper_pg_pmd+0x1000*KPMDS-8) |
7626 |
+ #else /* Not PAE */ |
7627 |
+ |
7628 |
+ page_pde_offset = (__PAGE_OFFSET >> 20); |
7629 |
+@@ -253,8 +312,7 @@ page_pde_offset = (__PAGE_OFFSET >> 20); |
7630 |
+ movl %eax, pa(max_pfn_mapped) |
7631 |
+ |
7632 |
+ /* Do early initialization of the fixmap area */ |
7633 |
+- movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,%eax |
7634 |
+- movl %eax,pa(swapper_pg_dir+0xffc) |
7635 |
++ movl $pa(swapper_pg_fixmap)+PDE_IDENT_ATTR,pa(swapper_pg_dir+0xffc) |
7636 |
+ #endif |
7637 |
+ jmp 3f |
7638 |
+ /* |
7639 |
+@@ -318,13 +376,16 @@ ENTRY(startup_32_smp) |
7640 |
+ jnc 6f |
7641 |
+ |
7642 |
+ /* Setup EFER (Extended Feature Enable Register) */ |
7643 |
+- movl $0xc0000080, %ecx |
7644 |
++ movl $MSR_EFER, %ecx |
7645 |
+ rdmsr |
7646 |
+ |
7647 |
+ btsl $11, %eax |
7648 |
+ /* Make changes effective */ |
7649 |
+ wrmsr |
7650 |
+ |
7651 |
++ btsl $_PAGE_BIT_NX-32,pa(__supported_pte_mask+4) |
7652 |
++ movl $1,pa(nx_enabled) |
7653 |
++ |
7654 |
+ 6: |
7655 |
+ |
7656 |
+ /* |
7657 |
+@@ -350,9 +411,7 @@ ENTRY(startup_32_smp) |
7658 |
+ |
7659 |
+ #ifdef CONFIG_SMP |
7660 |
+ cmpb $0, ready |
7661 |
+- jz 1f /* Initial CPU cleans BSS */ |
7662 |
+- jmp checkCPUtype |
7663 |
+-1: |
7664 |
++ jnz checkCPUtype /* Initial CPU cleans BSS */ |
7665 |
+ #endif /* CONFIG_SMP */ |
7666 |
+ |
7667 |
+ /* |
7668 |
+@@ -429,12 +488,12 @@ is386: movl $2,%ecx # set MP |
7669 |
+ ljmp $(__KERNEL_CS),$1f |
7670 |
+ 1: movl $(__KERNEL_DS),%eax # reload all the segment registers |
7671 |
+ movl %eax,%ss # after changing gdt. |
7672 |
+- movl %eax,%fs # gets reset once there's real percpu |
7673 |
+- |
7674 |
+- movl $(__USER_DS),%eax # DS/ES contains default USER segment |
7675 |
+ movl %eax,%ds |
7676 |
+ movl %eax,%es |
7677 |
+ |
7678 |
++ movl $(__KERNEL_PERCPU), %eax |
7679 |
++ movl %eax,%fs # set this cpu's percpu |
7680 |
++ |
7681 |
+ xorl %eax,%eax # Clear GS and LDT |
7682 |
+ movl %eax,%gs |
7683 |
+ lldt %ax |
7684 |
+@@ -444,12 +503,6 @@ is386: movl $2,%ecx # set MP |
7685 |
+ #ifdef CONFIG_SMP |
7686 |
+ movb ready, %cl |
7687 |
+ movb $1, ready |
7688 |
+- cmpb $0,%cl # the first CPU calls start_kernel |
7689 |
+- je 1f |
7690 |
+- movl $(__KERNEL_PERCPU), %eax |
7691 |
+- movl %eax,%fs # set this cpu's percpu |
7692 |
+- movl (stack_start), %esp |
7693 |
+-1: |
7694 |
+ #endif /* CONFIG_SMP */ |
7695 |
+ jmp *(initial_code) |
7696 |
+ |
7697 |
+@@ -535,15 +588,15 @@ early_page_fault: |
7698 |
+ jmp early_fault |
7699 |
+ |
7700 |
+ early_fault: |
7701 |
+- cld |
7702 |
+ #ifdef CONFIG_PRINTK |
7703 |
++ cmpl $2,%ss:early_recursion_flag |
7704 |
++ je hlt_loop |
7705 |
++ incl %ss:early_recursion_flag |
7706 |
++ cld |
7707 |
+ pusha |
7708 |
+ movl $(__KERNEL_DS),%eax |
7709 |
+ movl %eax,%ds |
7710 |
+ movl %eax,%es |
7711 |
+- cmpl $2,early_recursion_flag |
7712 |
+- je hlt_loop |
7713 |
+- incl early_recursion_flag |
7714 |
+ movl %cr2,%eax |
7715 |
+ pushl %eax |
7716 |
+ pushl %edx /* trapno */ |
7717 |
+@@ -553,8 +606,8 @@ early_fault: |
7718 |
+ #else |
7719 |
+ call printk |
7720 |
+ #endif |
7721 |
+-#endif |
7722 |
+ call dump_stack |
7723 |
++#endif |
7724 |
+ hlt_loop: |
7725 |
+ hlt |
7726 |
+ jmp hlt_loop |
7727 |
+@@ -562,8 +615,11 @@ hlt_loop: |
7728 |
+ /* This is the default interrupt "handler" :-) */ |
7729 |
+ ALIGN |
7730 |
+ ignore_int: |
7731 |
+- cld |
7732 |
+ #ifdef CONFIG_PRINTK |
7733 |
++ cmpl $2,%ss:early_recursion_flag |
7734 |
++ je hlt_loop |
7735 |
++ incl %ss:early_recursion_flag |
7736 |
++ cld |
7737 |
+ pushl %eax |
7738 |
+ pushl %ecx |
7739 |
+ pushl %edx |
7740 |
+@@ -572,9 +628,6 @@ ignore_int: |
7741 |
+ movl $(__KERNEL_DS),%eax |
7742 |
+ movl %eax,%ds |
7743 |
+ movl %eax,%es |
7744 |
+- cmpl $2,early_recursion_flag |
7745 |
+- je hlt_loop |
7746 |
+- incl early_recursion_flag |
7747 |
+ pushl 16(%esp) |
7748 |
+ pushl 24(%esp) |
7749 |
+ pushl 32(%esp) |
7750 |
+@@ -599,36 +652,41 @@ ignore_int: |
7751 |
+ ENTRY(initial_code) |
7752 |
+ .long i386_start_kernel |
7753 |
+ |
7754 |
+-.section .text |
7755 |
+-/* |
7756 |
+- * Real beginning of normal "text" segment |
7757 |
+- */ |
7758 |
+-ENTRY(stext) |
7759 |
+-ENTRY(_stext) |
7760 |
+- |
7761 |
+ /* |
7762 |
+ * BSS section |
7763 |
+ */ |
7764 |
+-.section ".bss.page_aligned","wa" |
7765 |
+- .align PAGE_SIZE_asm |
7766 |
+ #ifdef CONFIG_X86_PAE |
7767 |
++.section .swapper_pg_pmd,"a",@progbits |
7768 |
+ swapper_pg_pmd: |
7769 |
+ .fill 1024*KPMDS,4,0 |
7770 |
+ #else |
7771 |
++.section .swapper_pg_dir,"a",@progbits |
7772 |
+ ENTRY(swapper_pg_dir) |
7773 |
+ .fill 1024,4,0 |
7774 |
+ #endif |
7775 |
+ swapper_pg_fixmap: |
7776 |
+ .fill 1024,4,0 |
7777 |
++ |
7778 |
++.section .empty_zero_page,"a",@progbits |
7779 |
+ ENTRY(empty_zero_page) |
7780 |
+ .fill 4096,1,0 |
7781 |
++ |
7782 |
++/* |
7783 |
++ * The IDT has to be page-aligned to simplify the Pentium |
7784 |
++ * F0 0F bug workaround.. We have a special link segment |
7785 |
++ * for this. |
7786 |
++ */ |
7787 |
++.section .idt,"a",@progbits |
7788 |
++ENTRY(idt_table) |
7789 |
++ .fill 256,8,0 |
7790 |
++ |
7791 |
+ /* |
7792 |
+ * This starts the data section. |
7793 |
+ */ |
7794 |
++.data |
7795 |
++ |
7796 |
+ #ifdef CONFIG_X86_PAE |
7797 |
+-.section ".data.page_aligned","wa" |
7798 |
+- /* Page-aligned for the benefit of paravirt? */ |
7799 |
+- .align PAGE_SIZE_asm |
7800 |
++.section .swapper_pg_dir,"a",@progbits |
7801 |
+ ENTRY(swapper_pg_dir) |
7802 |
+ .long pa(swapper_pg_pmd+PGD_IDENT_ATTR),0 /* low identity map */ |
7803 |
+ # if KPMDS == 3 |
7804 |
+@@ -651,11 +709,12 @@ ENTRY(swapper_pg_dir) |
7805 |
+ |
7806 |
+ .data |
7807 |
+ ENTRY(stack_start) |
7808 |
+- .long init_thread_union+THREAD_SIZE |
7809 |
++ .long init_thread_union+THREAD_SIZE-8 |
7810 |
+ .long __BOOT_DS |
7811 |
+ |
7812 |
+ ready: .byte 0 |
7813 |
+ |
7814 |
++.section .rodata,"a",@progbits |
7815 |
+ early_recursion_flag: |
7816 |
+ .long 0 |
7817 |
+ |
7818 |
+@@ -691,7 +750,7 @@ fault_msg: |
7819 |
+ .word 0 # 32 bit align gdt_desc.address |
7820 |
+ boot_gdt_descr: |
7821 |
+ .word __BOOT_DS+7 |
7822 |
+- .long boot_gdt - __PAGE_OFFSET |
7823 |
++ .long pa(boot_gdt) |
7824 |
+ |
7825 |
+ .word 0 # 32-bit align idt_desc.address |
7826 |
+ idt_descr: |
7827 |
+@@ -702,7 +761,7 @@ idt_descr: |
7828 |
+ .word 0 # 32 bit align gdt_desc.address |
7829 |
+ ENTRY(early_gdt_descr) |
7830 |
+ .word GDT_ENTRIES*8-1 |
7831 |
+- .long per_cpu__gdt_page /* Overwritten for secondary CPUs */ |
7832 |
++ .long cpu_gdt_table /* Overwritten for secondary CPUs */ |
7833 |
+ |
7834 |
+ /* |
7835 |
+ * The boot_gdt must mirror the equivalent in setup.S and is |
7836 |
+@@ -711,5 +770,59 @@ ENTRY(early_gdt_descr) |
7837 |
+ .align L1_CACHE_BYTES |
7838 |
+ ENTRY(boot_gdt) |
7839 |
+ .fill GDT_ENTRY_BOOT_CS,8,0 |
7840 |
+- .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */ |
7841 |
+- .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */ |
7842 |
++ .quad 0x00cf9b000000ffff /* kernel 4GB code at 0x00000000 */ |
7843 |
++ .quad 0x00cf93000000ffff /* kernel 4GB data at 0x00000000 */ |
7844 |
++ |
7845 |
++ .align PAGE_SIZE_asm |
7846 |
++ENTRY(cpu_gdt_table) |
7847 |
++ .rept NR_CPUS |
7848 |
++ .quad 0x0000000000000000 /* NULL descriptor */ |
7849 |
++ .quad 0x0000000000000000 /* 0x0b reserved */ |
7850 |
++ .quad 0x0000000000000000 /* 0x13 reserved */ |
7851 |
++ .quad 0x0000000000000000 /* 0x1b reserved */ |
7852 |
++ .quad 0x0000000000000000 /* 0x20 unused */ |
7853 |
++ .quad 0x0000000000000000 /* 0x28 unused */ |
7854 |
++ .quad 0x0000000000000000 /* 0x33 TLS entry 1 */ |
7855 |
++ .quad 0x0000000000000000 /* 0x3b TLS entry 2 */ |
7856 |
++ .quad 0x0000000000000000 /* 0x43 TLS entry 3 */ |
7857 |
++ .quad 0x0000000000000000 /* 0x4b reserved */ |
7858 |
++ .quad 0x0000000000000000 /* 0x53 reserved */ |
7859 |
++ .quad 0x0000000000000000 /* 0x5b reserved */ |
7860 |
++ |
7861 |
++ .quad 0x00cf9b000000ffff /* 0x60 kernel 4GB code at 0x00000000 */ |
7862 |
++ .quad 0x00cf93000000ffff /* 0x68 kernel 4GB data at 0x00000000 */ |
7863 |
++ .quad 0x00cffb000000ffff /* 0x73 user 4GB code at 0x00000000 */ |
7864 |
++ .quad 0x00cff3000000ffff /* 0x7b user 4GB data at 0x00000000 */ |
7865 |
++ |
7866 |
++ .quad 0x0000000000000000 /* 0x80 TSS descriptor */ |
7867 |
++ .quad 0x0000000000000000 /* 0x88 LDT descriptor */ |
7868 |
++ |
7869 |
++ /* |
7870 |
++ * Segments used for calling PnP BIOS have byte granularity. |
7871 |
++ * The code segments and data segments have fixed 64k limits, |
7872 |
++ * the transfer segment sizes are set at run time. |
7873 |
++ */ |
7874 |
++ .quad 0x00409b000000ffff /* 0x90 32-bit code */ |
7875 |
++ .quad 0x00009b000000ffff /* 0x98 16-bit code */ |
7876 |
++ .quad 0x000093000000ffff /* 0xa0 16-bit data */ |
7877 |
++ .quad 0x0000930000000000 /* 0xa8 16-bit data */ |
7878 |
++ .quad 0x0000930000000000 /* 0xb0 16-bit data */ |
7879 |
++ |
7880 |
++ /* |
7881 |
++ * The APM segments have byte granularity and their bases |
7882 |
++ * are set at run time. All have 64k limits. |
7883 |
++ */ |
7884 |
++ .quad 0x00409b000000ffff /* 0xb8 APM CS code */ |
7885 |
++ .quad 0x00009b000000ffff /* 0xc0 APM CS 16 code (16 bit) */ |
7886 |
++ .quad 0x004093000000ffff /* 0xc8 APM DS data */ |
7887 |
++ |
7888 |
++ .quad 0x00c0930000000000 /* 0xd0 - ESPFIX SS */ |
7889 |
++ .quad 0x0040930000000000 /* 0xd8 - PERCPU */ |
7890 |
++ .quad 0x0000000000000000 /* 0xe0 - PCIBIOS_CS */ |
7891 |
++ .quad 0x0000000000000000 /* 0xe8 - PCIBIOS_DS */ |
7892 |
++ .quad 0x0000000000000000 /* 0xf0 - unused */ |
7893 |
++ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ |
7894 |
++ |
7895 |
++ /* Be sure this is zeroed to avoid false validations in Xen */ |
7896 |
++ .fill PAGE_SIZE_asm - GDT_SIZE,1,0 |
7897 |
++ .endr |
7898 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/head64.c linux-2.6.28.8/arch/x86/kernel/head64.c |
7899 |
+--- linux-2.6.28.8/arch/x86/kernel/head64.c 2009-02-06 16:47:45.000000000 -0500 |
7900 |
++++ linux-2.6.28.8/arch/x86/kernel/head64.c 2009-02-21 09:37:48.000000000 -0500 |
7901 |
+@@ -93,6 +93,8 @@ void __init x86_64_start_kernel(char * r |
7902 |
+ /* clear bss before set_intr_gate with early_idt_handler */ |
7903 |
+ clear_bss(); |
7904 |
+ |
7905 |
++ x86_64_init_pda(); |
7906 |
++ |
7907 |
+ /* Make NULL pointers segfault */ |
7908 |
+ zap_identity_mappings(); |
7909 |
+ |
7910 |
+@@ -111,8 +113,6 @@ void __init x86_64_start_kernel(char * r |
7911 |
+ if (console_loglevel == 10) |
7912 |
+ early_printk("Kernel alive\n"); |
7913 |
+ |
7914 |
+- x86_64_init_pda(); |
7915 |
+- |
7916 |
+ x86_64_start_reservations(real_mode_data); |
7917 |
+ } |
7918 |
+ |
7919 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/head_64.S linux-2.6.28.8/arch/x86/kernel/head_64.S |
7920 |
+--- linux-2.6.28.8/arch/x86/kernel/head_64.S 2009-02-06 16:47:45.000000000 -0500 |
7921 |
++++ linux-2.6.28.8/arch/x86/kernel/head_64.S 2009-02-21 09:37:48.000000000 -0500 |
7922 |
+@@ -38,6 +38,10 @@ L4_PAGE_OFFSET = pgd_index(__PAGE_OFFSET |
7923 |
+ L3_PAGE_OFFSET = pud_index(__PAGE_OFFSET) |
7924 |
+ L4_START_KERNEL = pgd_index(__START_KERNEL_map) |
7925 |
+ L3_START_KERNEL = pud_index(__START_KERNEL_map) |
7926 |
++L4_VMALLOC_START = pgd_index(VMALLOC_START) |
7927 |
++L3_VMALLOC_START = pud_index(VMALLOC_START) |
7928 |
++L4_VMEMMAP_START = pgd_index(VMEMMAP_START) |
7929 |
++L3_VMEMMAP_START = pud_index(VMEMMAP_START) |
7930 |
+ |
7931 |
+ .text |
7932 |
+ .section .text.head |
7933 |
+@@ -85,35 +89,22 @@ startup_64: |
7934 |
+ */ |
7935 |
+ addq %rbp, init_level4_pgt + 0(%rip) |
7936 |
+ addq %rbp, init_level4_pgt + (L4_PAGE_OFFSET*8)(%rip) |
7937 |
++ addq %rbp, init_level4_pgt + (L4_VMALLOC_START*8)(%rip) |
7938 |
++ addq %rbp, init_level4_pgt + (L4_VMEMMAP_START*8)(%rip) |
7939 |
+ addq %rbp, init_level4_pgt + (L4_START_KERNEL*8)(%rip) |
7940 |
+ |
7941 |
+ addq %rbp, level3_ident_pgt + 0(%rip) |
7942 |
++ addq %rbp, level3_ident_pgt + 8(%rip) |
7943 |
++ addq %rbp, level3_ident_pgt + 16(%rip) |
7944 |
++ addq %rbp, level3_ident_pgt + 24(%rip) |
7945 |
+ |
7946 |
+- addq %rbp, level3_kernel_pgt + (510*8)(%rip) |
7947 |
+- addq %rbp, level3_kernel_pgt + (511*8)(%rip) |
7948 |
++ addq %rbp, level3_vmemmap_pgt + (L3_VMEMMAP_START*8)(%rip) |
7949 |
+ |
7950 |
+- addq %rbp, level2_fixmap_pgt + (506*8)(%rip) |
7951 |
++ addq %rbp, level3_kernel_pgt + (L3_START_KERNEL*8)(%rip) |
7952 |
++ addq %rbp, level3_kernel_pgt + (L3_START_KERNEL*8+8)(%rip) |
7953 |
+ |
7954 |
+- /* Add an Identity mapping if I am above 1G */ |
7955 |
+- leaq _text(%rip), %rdi |
7956 |
+- andq $PMD_PAGE_MASK, %rdi |
7957 |
+- |
7958 |
+- movq %rdi, %rax |
7959 |
+- shrq $PUD_SHIFT, %rax |
7960 |
+- andq $(PTRS_PER_PUD - 1), %rax |
7961 |
+- jz ident_complete |
7962 |
+- |
7963 |
+- leaq (level2_spare_pgt - __START_KERNEL_map + _KERNPG_TABLE)(%rbp), %rdx |
7964 |
+- leaq level3_ident_pgt(%rip), %rbx |
7965 |
+- movq %rdx, 0(%rbx, %rax, 8) |
7966 |
+- |
7967 |
+- movq %rdi, %rax |
7968 |
+- shrq $PMD_SHIFT, %rax |
7969 |
+- andq $(PTRS_PER_PMD - 1), %rax |
7970 |
+- leaq __PAGE_KERNEL_IDENT_LARGE_EXEC(%rdi), %rdx |
7971 |
+- leaq level2_spare_pgt(%rip), %rbx |
7972 |
+- movq %rdx, 0(%rbx, %rax, 8) |
7973 |
+-ident_complete: |
7974 |
++ addq %rbp, level2_fixmap_pgt + (506*8)(%rip) |
7975 |
++ addq %rbp, level2_fixmap_pgt + (507*8)(%rip) |
7976 |
+ |
7977 |
+ /* |
7978 |
+ * Fixup the kernel text+data virtual addresses. Note that |
7979 |
+@@ -187,6 +178,10 @@ ENTRY(secondary_startup_64) |
7980 |
+ btl $20,%edi /* No Execute supported? */ |
7981 |
+ jnc 1f |
7982 |
+ btsl $_EFER_NX, %eax |
7983 |
++ leaq init_level4_pgt(%rip), %rdi |
7984 |
++ btsq $_PAGE_BIT_NX, 8*L4_PAGE_OFFSET(%rdi) |
7985 |
++ btsq $_PAGE_BIT_NX, 8*L4_VMALLOC_START(%rdi) |
7986 |
++ btsq $_PAGE_BIT_NX, 8*L4_VMEMMAP_START(%rdi) |
7987 |
+ 1: wrmsr /* Make changes effective */ |
7988 |
+ |
7989 |
+ /* Setup cr0 */ |
7990 |
+@@ -257,16 +252,16 @@ ENTRY(secondary_startup_64) |
7991 |
+ .align 8 |
7992 |
+ ENTRY(initial_code) |
7993 |
+ .quad x86_64_start_kernel |
7994 |
+- __FINITDATA |
7995 |
+ |
7996 |
+ ENTRY(stack_start) |
7997 |
+ .quad init_thread_union+THREAD_SIZE-8 |
7998 |
+ .word 0 |
7999 |
++ __FINITDATA |
8000 |
+ |
8001 |
+ bad_address: |
8002 |
+ jmp bad_address |
8003 |
+ |
8004 |
+- .section ".init.text","ax" |
8005 |
++ __INIT |
8006 |
+ #ifdef CONFIG_EARLY_PRINTK |
8007 |
+ .globl early_idt_handlers |
8008 |
+ early_idt_handlers: |
8009 |
+@@ -311,18 +306,23 @@ ENTRY(early_idt_handler) |
8010 |
+ #endif /* EARLY_PRINTK */ |
8011 |
+ 1: hlt |
8012 |
+ jmp 1b |
8013 |
++ .previous |
8014 |
+ |
8015 |
+ #ifdef CONFIG_EARLY_PRINTK |
8016 |
++ __INITDATA |
8017 |
+ early_recursion_flag: |
8018 |
+ .long 0 |
8019 |
++ .previous |
8020 |
+ |
8021 |
++ .section .rodata,"a",@progbits |
8022 |
+ early_idt_msg: |
8023 |
+ .asciz "PANIC: early exception %02lx rip %lx:%lx error %lx cr2 %lx\n" |
8024 |
+ early_idt_ripmsg: |
8025 |
+ .asciz "RIP %s\n" |
8026 |
+-#endif /* CONFIG_EARLY_PRINTK */ |
8027 |
+ .previous |
8028 |
++#endif /* CONFIG_EARLY_PRINTK */ |
8029 |
+ |
8030 |
++ .section .rodata,"a",@progbits |
8031 |
+ .balign PAGE_SIZE |
8032 |
+ |
8033 |
+ #define NEXT_PAGE(name) \ |
8034 |
+@@ -347,13 +347,27 @@ NEXT_PAGE(init_level4_pgt) |
8035 |
+ .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE |
8036 |
+ .org init_level4_pgt + L4_PAGE_OFFSET*8, 0 |
8037 |
+ .quad level3_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE |
8038 |
++ .org init_level4_pgt + L4_VMALLOC_START*8, 0 |
8039 |
++ .quad level3_vmalloc_pgt - __START_KERNEL_map + _KERNPG_TABLE |
8040 |
++ .org init_level4_pgt + L4_VMEMMAP_START*8, 0 |
8041 |
++ .quad level3_vmemmap_pgt - __START_KERNEL_map + _KERNPG_TABLE |
8042 |
+ .org init_level4_pgt + L4_START_KERNEL*8, 0 |
8043 |
+ /* (2^48-(2*1024*1024*1024))/(2^39) = 511 */ |
8044 |
+ .quad level3_kernel_pgt - __START_KERNEL_map + _PAGE_TABLE |
8045 |
+ |
8046 |
+ NEXT_PAGE(level3_ident_pgt) |
8047 |
+ .quad level2_ident_pgt - __START_KERNEL_map + _KERNPG_TABLE |
8048 |
+- .fill 511,8,0 |
8049 |
++ .quad level2_ident_pgt + PAGE_SIZE - __START_KERNEL_map + _KERNPG_TABLE |
8050 |
++ .quad level2_ident_pgt + 2*PAGE_SIZE - __START_KERNEL_map + _KERNPG_TABLE |
8051 |
++ .quad level2_ident_pgt + 3*PAGE_SIZE - __START_KERNEL_map + _KERNPG_TABLE |
8052 |
++ .fill 508,8,0 |
8053 |
++ |
8054 |
++NEXT_PAGE(level3_vmalloc_pgt) |
8055 |
++ .fill 512,8,0 |
8056 |
++ |
8057 |
++NEXT_PAGE(level3_vmemmap_pgt) |
8058 |
++ .fill L3_VMEMMAP_START,8,0 |
8059 |
++ .quad level2_vmemmap_pgt - __START_KERNEL_map + _KERNPG_TABLE |
8060 |
+ |
8061 |
+ NEXT_PAGE(level3_kernel_pgt) |
8062 |
+ .fill L3_START_KERNEL,8,0 |
8063 |
+@@ -361,20 +375,27 @@ NEXT_PAGE(level3_kernel_pgt) |
8064 |
+ .quad level2_kernel_pgt - __START_KERNEL_map + _KERNPG_TABLE |
8065 |
+ .quad level2_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE |
8066 |
+ |
8067 |
++NEXT_PAGE(level2_vmemmap_pgt) |
8068 |
++ .fill 512,8,0 |
8069 |
++ |
8070 |
+ NEXT_PAGE(level2_fixmap_pgt) |
8071 |
+ .fill 506,8,0 |
8072 |
+ .quad level1_fixmap_pgt - __START_KERNEL_map + _PAGE_TABLE |
8073 |
+- /* 8MB reserved for vsyscalls + a 2MB hole = 4 + 1 entries */ |
8074 |
+- .fill 5,8,0 |
8075 |
++ .quad level1_vsyscall_pgt - __START_KERNEL_map + _PAGE_TABLE |
8076 |
++ /* 6MB reserved for vsyscalls + a 2MB hole = 3 + 1 entries */ |
8077 |
++ .fill 4,8,0 |
8078 |
+ |
8079 |
+ NEXT_PAGE(level1_fixmap_pgt) |
8080 |
+ .fill 512,8,0 |
8081 |
+ |
8082 |
+-NEXT_PAGE(level2_ident_pgt) |
8083 |
+- /* Since I easily can, map the first 1G. |
8084 |
++NEXT_PAGE(level1_vsyscall_pgt) |
8085 |
++ .fill 512,8,0 |
8086 |
++ |
8087 |
++ /* Since I easily can, map the first 4G. |
8088 |
+ * Don't set NX because code runs from these pages. |
8089 |
+ */ |
8090 |
+- PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, PTRS_PER_PMD) |
8091 |
++NEXT_PAGE(level2_ident_pgt) |
8092 |
++ PMDS(0, __PAGE_KERNEL_IDENT_LARGE_EXEC, 4*PTRS_PER_PMD) |
8093 |
+ |
8094 |
+ NEXT_PAGE(level2_kernel_pgt) |
8095 |
+ /* |
8096 |
+@@ -387,32 +408,48 @@ NEXT_PAGE(level2_kernel_pgt) |
8097 |
+ * If you want to increase this then increase MODULES_VADDR |
8098 |
+ * too.) |
8099 |
+ */ |
8100 |
+- PMDS(0, __PAGE_KERNEL_LARGE_EXEC, |
8101 |
+- KERNEL_IMAGE_SIZE/PMD_SIZE) |
8102 |
+- |
8103 |
+-NEXT_PAGE(level2_spare_pgt) |
8104 |
+- .fill 512, 8, 0 |
8105 |
++ PMDS(0, __PAGE_KERNEL_LARGE_EXEC, KERNEL_IMAGE_SIZE/PMD_SIZE) |
8106 |
+ |
8107 |
+ #undef PMDS |
8108 |
+ #undef NEXT_PAGE |
8109 |
+ |
8110 |
+- .data |
8111 |
++ .align PAGE_SIZE |
8112 |
++ENTRY(cpu_gdt_table) |
8113 |
++ .rept NR_CPUS |
8114 |
++ .quad 0x0000000000000000 /* NULL descriptor */ |
8115 |
++ .quad 0x00cf9b000000ffff /* __KERNEL32_CS */ |
8116 |
++ .quad 0x00af9b000000ffff /* __KERNEL_CS */ |
8117 |
++ .quad 0x00cf93000000ffff /* __KERNEL_DS */ |
8118 |
++ .quad 0x00cffb000000ffff /* __USER32_CS */ |
8119 |
++ .quad 0x00cff3000000ffff /* __USER_DS, __USER32_DS */ |
8120 |
++ .quad 0x00affb000000ffff /* __USER_CS */ |
8121 |
++ .quad 0x0 /* unused */ |
8122 |
++ .quad 0,0 /* TSS */ |
8123 |
++ .quad 0,0 /* LDT */ |
8124 |
++ .quad 0,0,0 /* three TLS descriptors */ |
8125 |
++ .quad 0x0000f40000000000 /* node/CPU stored in limit */ |
8126 |
++ /* asm/segment.h:GDT_ENTRIES must match this */ |
8127 |
++ |
8128 |
++ /* zero the remaining page */ |
8129 |
++ .fill PAGE_SIZE / 8 - GDT_ENTRIES,8,0 |
8130 |
++ .endr |
8131 |
++ |
8132 |
+ .align 16 |
8133 |
+ .globl early_gdt_descr |
8134 |
+ early_gdt_descr: |
8135 |
+ .word GDT_ENTRIES*8-1 |
8136 |
+- .quad per_cpu__gdt_page |
8137 |
++ .quad cpu_gdt_table |
8138 |
+ |
8139 |
+ ENTRY(phys_base) |
8140 |
+ /* This must match the first entry in level2_kernel_pgt */ |
8141 |
+ .quad 0x0000000000000000 |
8142 |
+ |
8143 |
+ #include "../../x86/xen/xen-head.S" |
8144 |
+- |
8145 |
+- .section .bss, "aw", @nobits |
8146 |
++ |
8147 |
++ .section .rodata,"a",@progbits |
8148 |
+ .align L1_CACHE_BYTES |
8149 |
+ ENTRY(idt_table) |
8150 |
+- .skip 256 * 16 |
8151 |
++ .fill 512,8,0 |
8152 |
+ |
8153 |
+ .section .bss.page_aligned, "aw", @nobits |
8154 |
+ .align PAGE_SIZE |
8155 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/i386_ksyms_32.c linux-2.6.28.8/arch/x86/kernel/i386_ksyms_32.c |
8156 |
+--- linux-2.6.28.8/arch/x86/kernel/i386_ksyms_32.c 2009-02-06 16:47:45.000000000 -0500 |
8157 |
++++ linux-2.6.28.8/arch/x86/kernel/i386_ksyms_32.c 2009-02-21 09:37:48.000000000 -0500 |
8158 |
+@@ -10,8 +10,12 @@ |
8159 |
+ EXPORT_SYMBOL(mcount); |
8160 |
+ #endif |
8161 |
+ |
8162 |
++EXPORT_SYMBOL_GPL(cpu_gdt_table); |
8163 |
++ |
8164 |
+ /* Networking helper routines. */ |
8165 |
+ EXPORT_SYMBOL(csum_partial_copy_generic); |
8166 |
++EXPORT_SYMBOL(csum_partial_copy_generic_to_user); |
8167 |
++EXPORT_SYMBOL(csum_partial_copy_generic_from_user); |
8168 |
+ |
8169 |
+ EXPORT_SYMBOL(__get_user_1); |
8170 |
+ EXPORT_SYMBOL(__get_user_2); |
8171 |
+@@ -26,3 +30,7 @@ EXPORT_SYMBOL(strstr); |
8172 |
+ |
8173 |
+ EXPORT_SYMBOL(csum_partial); |
8174 |
+ EXPORT_SYMBOL(empty_zero_page); |
8175 |
++ |
8176 |
++#ifdef CONFIG_PAX_KERNEXEC |
8177 |
++EXPORT_SYMBOL(KERNEL_TEXT_OFFSET); |
8178 |
++#endif |
8179 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/init_task.c linux-2.6.28.8/arch/x86/kernel/init_task.c |
8180 |
+--- linux-2.6.28.8/arch/x86/kernel/init_task.c 2009-02-06 16:47:45.000000000 -0500 |
8181 |
++++ linux-2.6.28.8/arch/x86/kernel/init_task.c 2009-02-21 09:37:48.000000000 -0500 |
8182 |
+@@ -42,5 +42,5 @@ EXPORT_SYMBOL(init_task); |
8183 |
+ * section. Since TSS's are completely CPU-local, we want them |
8184 |
+ * on exact cacheline boundaries, to eliminate cacheline ping-pong. |
8185 |
+ */ |
8186 |
+-DEFINE_PER_CPU_SHARED_ALIGNED(struct tss_struct, init_tss) = INIT_TSS; |
8187 |
+- |
8188 |
++struct tss_struct init_tss[NR_CPUS] ____cacheline_internodealigned_in_smp = { [0 ... NR_CPUS-1] = INIT_TSS }; |
8189 |
++EXPORT_SYMBOL(init_tss); |
8190 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/ioport.c linux-2.6.28.8/arch/x86/kernel/ioport.c |
8191 |
+--- linux-2.6.28.8/arch/x86/kernel/ioport.c 2009-02-06 16:47:45.000000000 -0500 |
8192 |
++++ linux-2.6.28.8/arch/x86/kernel/ioport.c 2009-02-21 09:37:48.000000000 -0500 |
8193 |
+@@ -6,6 +6,7 @@ |
8194 |
+ #include <linux/sched.h> |
8195 |
+ #include <linux/kernel.h> |
8196 |
+ #include <linux/capability.h> |
8197 |
++#include <linux/security.h> |
8198 |
+ #include <linux/errno.h> |
8199 |
+ #include <linux/types.h> |
8200 |
+ #include <linux/ioport.h> |
8201 |
+@@ -41,6 +42,12 @@ asmlinkage long sys_ioperm(unsigned long |
8202 |
+ |
8203 |
+ if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) |
8204 |
+ return -EINVAL; |
8205 |
++#ifdef CONFIG_GRKERNSEC_IO |
8206 |
++ if (turn_on) { |
8207 |
++ gr_handle_ioperm(); |
8208 |
++ return -EPERM; |
8209 |
++ } |
8210 |
++#endif |
8211 |
+ if (turn_on && !capable(CAP_SYS_RAWIO)) |
8212 |
+ return -EPERM; |
8213 |
+ |
8214 |
+@@ -67,7 +74,7 @@ asmlinkage long sys_ioperm(unsigned long |
8215 |
+ * because the ->io_bitmap_max value must match the bitmap |
8216 |
+ * contents: |
8217 |
+ */ |
8218 |
+- tss = &per_cpu(init_tss, get_cpu()); |
8219 |
++ tss = init_tss + get_cpu(); |
8220 |
+ |
8221 |
+ set_bitmap(t->io_bitmap_ptr, from, num, !turn_on); |
8222 |
+ |
8223 |
+@@ -122,8 +129,13 @@ static int do_iopl(unsigned int level, s |
8224 |
+ return -EINVAL; |
8225 |
+ /* Trying to gain more privileges? */ |
8226 |
+ if (level > old) { |
8227 |
++#ifdef CONFIG_GRKERNSEC_IO |
8228 |
++ gr_handle_iopl(); |
8229 |
++ return -EPERM; |
8230 |
++#else |
8231 |
+ if (!capable(CAP_SYS_RAWIO)) |
8232 |
+ return -EPERM; |
8233 |
++#endif |
8234 |
+ } |
8235 |
+ regs->flags = (regs->flags & ~X86_EFLAGS_IOPL) | (level << 12); |
8236 |
+ |
8237 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/irq_32.c linux-2.6.28.8/arch/x86/kernel/irq_32.c |
8238 |
+--- linux-2.6.28.8/arch/x86/kernel/irq_32.c 2009-02-06 16:47:45.000000000 -0500 |
8239 |
++++ linux-2.6.28.8/arch/x86/kernel/irq_32.c 2009-02-21 09:37:48.000000000 -0500 |
8240 |
+@@ -93,7 +93,7 @@ execute_on_irq_stack(int overflow, struc |
8241 |
+ return 0; |
8242 |
+ |
8243 |
+ /* build the stack frame on the IRQ stack */ |
8244 |
+- isp = (u32 *) ((char*)irqctx + sizeof(*irqctx)); |
8245 |
++ isp = (u32 *) ((char*)irqctx + sizeof(*irqctx) - 8); |
8246 |
+ irqctx->tinfo.task = curctx->tinfo.task; |
8247 |
+ irqctx->tinfo.previous_esp = current_stack_pointer; |
8248 |
+ |
8249 |
+@@ -174,7 +174,7 @@ asmlinkage void do_softirq(void) |
8250 |
+ irqctx->tinfo.previous_esp = current_stack_pointer; |
8251 |
+ |
8252 |
+ /* build the stack frame on the softirq stack */ |
8253 |
+- isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); |
8254 |
++ isp = (u32*) ((char*)irqctx + sizeof(*irqctx) - 8); |
8255 |
+ |
8256 |
+ call_on_stack(__do_softirq, isp); |
8257 |
+ /* |
8258 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/kprobes.c linux-2.6.28.8/arch/x86/kernel/kprobes.c |
8259 |
+--- linux-2.6.28.8/arch/x86/kernel/kprobes.c 2009-02-06 16:47:45.000000000 -0500 |
8260 |
++++ linux-2.6.28.8/arch/x86/kernel/kprobes.c 2009-02-21 09:37:48.000000000 -0500 |
8261 |
+@@ -166,9 +166,24 @@ static void __kprobes set_jmp_op(void *f |
8262 |
+ char op; |
8263 |
+ s32 raddr; |
8264 |
+ } __attribute__((packed)) * jop; |
8265 |
+- jop = (struct __arch_jmp_op *)from; |
8266 |
++ |
8267 |
++#ifdef CONFIG_PAX_KERNEXEC |
8268 |
++ unsigned long cr0; |
8269 |
++#endif |
8270 |
++ |
8271 |
++ jop = (struct __arch_jmp_op *)(ktla_ktva(from)); |
8272 |
++ |
8273 |
++#ifdef CONFIG_PAX_KERNEXEC |
8274 |
++ pax_open_kernel(cr0); |
8275 |
++#endif |
8276 |
++ |
8277 |
+ jop->raddr = (s32)((long)(to) - ((long)(from) + 5)); |
8278 |
+ jop->op = RELATIVEJUMP_INSTRUCTION; |
8279 |
++ |
8280 |
++#ifdef CONFIG_PAX_KERNEXEC |
8281 |
++ pax_close_kernel(cr0); |
8282 |
++#endif |
8283 |
++ |
8284 |
+ } |
8285 |
+ |
8286 |
+ /* |
8287 |
+@@ -342,16 +357,29 @@ static void __kprobes fix_riprel(struct |
8288 |
+ |
8289 |
+ static void __kprobes arch_copy_kprobe(struct kprobe *p) |
8290 |
+ { |
8291 |
+- memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); |
8292 |
++ |
8293 |
++#ifdef CONFIG_PAX_KERNEXEC |
8294 |
++ unsigned long cr0; |
8295 |
++#endif |
8296 |
++ |
8297 |
++#ifdef CONFIG_PAX_KERNEXEC |
8298 |
++ pax_open_kernel(cr0); |
8299 |
++#endif |
8300 |
++ |
8301 |
++ memcpy(p->ainsn.insn, ktla_ktva(p->addr), MAX_INSN_SIZE * sizeof(kprobe_opcode_t)); |
8302 |
++ |
8303 |
++#ifdef CONFIG_PAX_KERNEXEC |
8304 |
++ pax_close_kernel(cr0); |
8305 |
++#endif |
8306 |
+ |
8307 |
+ fix_riprel(p); |
8308 |
+ |
8309 |
+- if (can_boost(p->addr)) |
8310 |
++ if (can_boost(ktla_ktva(p->addr))) |
8311 |
+ p->ainsn.boostable = 0; |
8312 |
+ else |
8313 |
+ p->ainsn.boostable = -1; |
8314 |
+ |
8315 |
+- p->opcode = *p->addr; |
8316 |
++ p->opcode = *(ktla_ktva(p->addr)); |
8317 |
+ } |
8318 |
+ |
8319 |
+ int __kprobes arch_prepare_kprobe(struct kprobe *p) |
8320 |
+@@ -428,7 +456,7 @@ static void __kprobes prepare_singlestep |
8321 |
+ if (p->opcode == BREAKPOINT_INSTRUCTION) |
8322 |
+ regs->ip = (unsigned long)p->addr; |
8323 |
+ else |
8324 |
+- regs->ip = (unsigned long)p->ainsn.insn; |
8325 |
++ regs->ip = ktva_ktla((unsigned long)p->ainsn.insn); |
8326 |
+ } |
8327 |
+ |
8328 |
+ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri, |
8329 |
+@@ -449,7 +477,7 @@ static void __kprobes setup_singlestep(s |
8330 |
+ if (p->ainsn.boostable == 1 && !p->post_handler) { |
8331 |
+ /* Boost up -- we can execute copied instructions directly */ |
8332 |
+ reset_current_kprobe(); |
8333 |
+- regs->ip = (unsigned long)p->ainsn.insn; |
8334 |
++ regs->ip = ktva_ktla((unsigned long)p->ainsn.insn); |
8335 |
+ preempt_enable_no_resched(); |
8336 |
+ return; |
8337 |
+ } |
8338 |
+@@ -519,7 +547,7 @@ static int __kprobes kprobe_handler(stru |
8339 |
+ struct kprobe_ctlblk *kcb; |
8340 |
+ |
8341 |
+ addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t)); |
8342 |
+- if (*addr != BREAKPOINT_INSTRUCTION) { |
8343 |
++ if (*(kprobe_opcode_t *)ktla_ktva((unsigned long)addr) != BREAKPOINT_INSTRUCTION) { |
8344 |
+ /* |
8345 |
+ * The breakpoint instruction was removed right |
8346 |
+ * after we hit it. Another cpu has removed |
8347 |
+@@ -770,7 +798,7 @@ static void __kprobes resume_execution(s |
8348 |
+ struct pt_regs *regs, struct kprobe_ctlblk *kcb) |
8349 |
+ { |
8350 |
+ unsigned long *tos = stack_addr(regs); |
8351 |
+- unsigned long copy_ip = (unsigned long)p->ainsn.insn; |
8352 |
++ unsigned long copy_ip = ktva_ktla((unsigned long)p->ainsn.insn); |
8353 |
+ unsigned long orig_ip = (unsigned long)p->addr; |
8354 |
+ kprobe_opcode_t *insn = p->ainsn.insn; |
8355 |
+ |
8356 |
+@@ -953,7 +981,7 @@ int __kprobes kprobe_exceptions_notify(s |
8357 |
+ struct die_args *args = data; |
8358 |
+ int ret = NOTIFY_DONE; |
8359 |
+ |
8360 |
+- if (args->regs && user_mode_vm(args->regs)) |
8361 |
++ if (args->regs && user_mode(args->regs)) |
8362 |
+ return ret; |
8363 |
+ |
8364 |
+ switch (val) { |
8365 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/ldt.c linux-2.6.28.8/arch/x86/kernel/ldt.c |
8366 |
+--- linux-2.6.28.8/arch/x86/kernel/ldt.c 2009-02-06 16:47:45.000000000 -0500 |
8367 |
++++ linux-2.6.28.8/arch/x86/kernel/ldt.c 2009-02-21 09:37:48.000000000 -0500 |
8368 |
+@@ -66,13 +66,13 @@ static int alloc_ldt(mm_context_t *pc, i |
8369 |
+ if (reload) { |
8370 |
+ #ifdef CONFIG_SMP |
8371 |
+ preempt_disable(); |
8372 |
+- load_LDT(pc); |
8373 |
++ load_LDT_nolock(pc); |
8374 |
+ if (!cpus_equal(current->mm->cpu_vm_mask, |
8375 |
+ cpumask_of_cpu(smp_processor_id()))) |
8376 |
+ smp_call_function(flush_ldt, current->mm, 1); |
8377 |
+ preempt_enable(); |
8378 |
+ #else |
8379 |
+- load_LDT(pc); |
8380 |
++ load_LDT_nolock(pc); |
8381 |
+ #endif |
8382 |
+ } |
8383 |
+ if (oldsize) { |
8384 |
+@@ -94,7 +94,7 @@ static inline int copy_ldt(mm_context_t |
8385 |
+ return err; |
8386 |
+ |
8387 |
+ for(i = 0; i < old->size; i++) |
8388 |
+- write_ldt_entry(new->ldt, i, old->ldt + i * LDT_ENTRY_SIZE); |
8389 |
++ write_ldt_entry(new->ldt, i, old->ldt + i); |
8390 |
+ return 0; |
8391 |
+ } |
8392 |
+ |
8393 |
+@@ -115,6 +115,24 @@ int init_new_context(struct task_struct |
8394 |
+ retval = copy_ldt(&mm->context, &old_mm->context); |
8395 |
+ mutex_unlock(&old_mm->context.lock); |
8396 |
+ } |
8397 |
++ |
8398 |
++ if (tsk == current) { |
8399 |
++ mm->context.vdso = ~0UL; |
8400 |
++ |
8401 |
++#ifdef CONFIG_X86_32 |
8402 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
8403 |
++ mm->context.user_cs_base = 0UL; |
8404 |
++ mm->context.user_cs_limit = ~0UL; |
8405 |
++ |
8406 |
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP) |
8407 |
++ cpus_clear(mm->context.cpu_user_cs_mask); |
8408 |
++#endif |
8409 |
++ |
8410 |
++#endif |
8411 |
++#endif |
8412 |
++ |
8413 |
++ } |
8414 |
++ |
8415 |
+ return retval; |
8416 |
+ } |
8417 |
+ |
8418 |
+@@ -229,6 +247,13 @@ static int write_ldt(void __user *ptr, u |
8419 |
+ } |
8420 |
+ } |
8421 |
+ |
8422 |
++#ifdef CONFIG_PAX_SEGMEXEC |
8423 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (ldt_info.contents & MODIFY_LDT_CONTENTS_CODE)) { |
8424 |
++ error = -EINVAL; |
8425 |
++ goto out_unlock; |
8426 |
++ } |
8427 |
++#endif |
8428 |
++ |
8429 |
+ fill_ldt(&ldt, &ldt_info); |
8430 |
+ if (oldmode) |
8431 |
+ ldt.avl = 0; |
8432 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/machine_kexec_32.c linux-2.6.28.8/arch/x86/kernel/machine_kexec_32.c |
8433 |
+--- linux-2.6.28.8/arch/x86/kernel/machine_kexec_32.c 2009-02-06 16:47:45.000000000 -0500 |
8434 |
++++ linux-2.6.28.8/arch/x86/kernel/machine_kexec_32.c 2009-02-21 09:37:48.000000000 -0500 |
8435 |
+@@ -34,7 +34,7 @@ static u32 kexec_pmd1[1024] PAGE_ALIGNED |
8436 |
+ static u32 kexec_pte0[1024] PAGE_ALIGNED; |
8437 |
+ static u32 kexec_pte1[1024] PAGE_ALIGNED; |
8438 |
+ |
8439 |
+-static void set_idt(void *newidt, __u16 limit) |
8440 |
++static void set_idt(struct desc_struct *newidt, __u16 limit) |
8441 |
+ { |
8442 |
+ struct desc_ptr curidt; |
8443 |
+ |
8444 |
+@@ -46,7 +46,7 @@ static void set_idt(void *newidt, __u16 |
8445 |
+ } |
8446 |
+ |
8447 |
+ |
8448 |
+-static void set_gdt(void *newgdt, __u16 limit) |
8449 |
++static void set_gdt(struct desc_struct *newgdt, __u16 limit) |
8450 |
+ { |
8451 |
+ struct desc_ptr curgdt; |
8452 |
+ |
8453 |
+@@ -145,7 +145,7 @@ void machine_kexec(struct kimage *image) |
8454 |
+ } |
8455 |
+ |
8456 |
+ control_page = page_address(image->control_code_page); |
8457 |
+- memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE); |
8458 |
++ memcpy(control_page, (void *)ktla_ktva((unsigned long)relocate_kernel), KEXEC_CONTROL_CODE_MAX_SIZE); |
8459 |
+ |
8460 |
+ relocate_kernel_ptr = control_page; |
8461 |
+ page_list[PA_CONTROL_PAGE] = __pa(control_page); |
8462 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/module_32.c linux-2.6.28.8/arch/x86/kernel/module_32.c |
8463 |
+--- linux-2.6.28.8/arch/x86/kernel/module_32.c 2009-02-06 16:47:45.000000000 -0500 |
8464 |
++++ linux-2.6.28.8/arch/x86/kernel/module_32.c 2009-02-21 09:37:48.000000000 -0500 |
8465 |
+@@ -23,6 +23,9 @@ |
8466 |
+ #include <linux/kernel.h> |
8467 |
+ #include <linux/bug.h> |
8468 |
+ |
8469 |
++#include <asm/desc.h> |
8470 |
++#include <asm/pgtable.h> |
8471 |
++ |
8472 |
+ #if 0 |
8473 |
+ #define DEBUGP printk |
8474 |
+ #else |
8475 |
+@@ -33,9 +36,31 @@ void *module_alloc(unsigned long size) |
8476 |
+ { |
8477 |
+ if (size == 0) |
8478 |
+ return NULL; |
8479 |
++ |
8480 |
++#ifdef CONFIG_PAX_KERNEXEC |
8481 |
++ return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL); |
8482 |
++#else |
8483 |
+ return vmalloc_exec(size); |
8484 |
++#endif |
8485 |
++ |
8486 |
+ } |
8487 |
+ |
8488 |
++#ifdef CONFIG_PAX_KERNEXEC |
8489 |
++void *module_alloc_exec(unsigned long size) |
8490 |
++{ |
8491 |
++ struct vm_struct *area; |
8492 |
++ |
8493 |
++ if (size == 0) |
8494 |
++ return NULL; |
8495 |
++ |
8496 |
++ area = __get_vm_area(size, VM_ALLOC, (unsigned long)&MODULES_VADDR, (unsigned long)&MODULES_END); |
8497 |
++ if (area) |
8498 |
++ return area->addr; |
8499 |
++ |
8500 |
++ return NULL; |
8501 |
++} |
8502 |
++EXPORT_SYMBOL(module_alloc_exec); |
8503 |
++#endif |
8504 |
+ |
8505 |
+ /* Free memory returned from module_alloc */ |
8506 |
+ void module_free(struct module *mod, void *module_region) |
8507 |
+@@ -45,6 +70,45 @@ void module_free(struct module *mod, voi |
8508 |
+ table entries. */ |
8509 |
+ } |
8510 |
+ |
8511 |
++#ifdef CONFIG_PAX_KERNEXEC |
8512 |
++void module_free_exec(struct module *mod, void *module_region) |
8513 |
++{ |
8514 |
++ struct vm_struct **p, *tmp; |
8515 |
++ |
8516 |
++ if (!module_region) |
8517 |
++ return; |
8518 |
++ |
8519 |
++ if ((PAGE_SIZE-1) & (unsigned long)module_region) { |
8520 |
++ printk(KERN_ERR "Trying to module_free_exec() bad address (%p)\n", module_region); |
8521 |
++ WARN_ON(1); |
8522 |
++ return; |
8523 |
++ } |
8524 |
++ |
8525 |
++ write_lock(&vmlist_lock); |
8526 |
++ for (p = &vmlist; (tmp = *p) != NULL; p = &tmp->next) |
8527 |
++ if (tmp->addr == module_region) |
8528 |
++ break; |
8529 |
++ |
8530 |
++ if (tmp) { |
8531 |
++ unsigned long cr0; |
8532 |
++ |
8533 |
++ pax_open_kernel(cr0); |
8534 |
++ memset(tmp->addr, 0xCC, tmp->size); |
8535 |
++ pax_close_kernel(cr0); |
8536 |
++ |
8537 |
++ *p = tmp->next; |
8538 |
++ kfree(tmp); |
8539 |
++ } |
8540 |
++ write_unlock(&vmlist_lock); |
8541 |
++ |
8542 |
++ if (!tmp) { |
8543 |
++ printk(KERN_ERR "Trying to module_free_exec() nonexistent vm area (%p)\n", |
8544 |
++ module_region); |
8545 |
++ WARN_ON(1); |
8546 |
++ } |
8547 |
++} |
8548 |
++#endif |
8549 |
++ |
8550 |
+ /* We don't need anything special. */ |
8551 |
+ int module_frob_arch_sections(Elf_Ehdr *hdr, |
8552 |
+ Elf_Shdr *sechdrs, |
8553 |
+@@ -63,14 +127,20 @@ int apply_relocate(Elf32_Shdr *sechdrs, |
8554 |
+ unsigned int i; |
8555 |
+ Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; |
8556 |
+ Elf32_Sym *sym; |
8557 |
+- uint32_t *location; |
8558 |
++ uint32_t *plocation, location; |
8559 |
++ |
8560 |
++#ifdef CONFIG_PAX_KERNEXEC |
8561 |
++ unsigned long cr0; |
8562 |
++#endif |
8563 |
+ |
8564 |
+ DEBUGP("Applying relocate section %u to %u\n", relsec, |
8565 |
+ sechdrs[relsec].sh_info); |
8566 |
+ for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { |
8567 |
+ /* This is where to make the change */ |
8568 |
+- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr |
8569 |
+- + rel[i].r_offset; |
8570 |
++ plocation = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset; |
8571 |
++ location = (uint32_t)plocation; |
8572 |
++ if (sechdrs[sechdrs[relsec].sh_info].sh_flags & SHF_EXECINSTR) |
8573 |
++ plocation = ktla_ktva((void *)plocation); |
8574 |
+ /* This is the symbol it is referring to. Note that all |
8575 |
+ undefined symbols have been resolved. */ |
8576 |
+ sym = (Elf32_Sym *)sechdrs[symindex].sh_addr |
8577 |
+@@ -78,12 +148,32 @@ int apply_relocate(Elf32_Shdr *sechdrs, |
8578 |
+ |
8579 |
+ switch (ELF32_R_TYPE(rel[i].r_info)) { |
8580 |
+ case R_386_32: |
8581 |
++ |
8582 |
++#ifdef CONFIG_PAX_KERNEXEC |
8583 |
++ pax_open_kernel(cr0); |
8584 |
++#endif |
8585 |
++ |
8586 |
+ /* We add the value into the location given */ |
8587 |
+- *location += sym->st_value; |
8588 |
++ *plocation += sym->st_value; |
8589 |
++ |
8590 |
++#ifdef CONFIG_PAX_KERNEXEC |
8591 |
++ pax_close_kernel(cr0); |
8592 |
++#endif |
8593 |
++ |
8594 |
+ break; |
8595 |
+ case R_386_PC32: |
8596 |
++ |
8597 |
++#ifdef CONFIG_PAX_KERNEXEC |
8598 |
++ pax_open_kernel(cr0); |
8599 |
++#endif |
8600 |
++ |
8601 |
+ /* Add the value, subtract its postition */ |
8602 |
+- *location += sym->st_value - (uint32_t)location; |
8603 |
++ *plocation += sym->st_value - location; |
8604 |
++ |
8605 |
++#ifdef CONFIG_PAX_KERNEXEC |
8606 |
++ pax_close_kernel(cr0); |
8607 |
++#endif |
8608 |
++ |
8609 |
+ break; |
8610 |
+ default: |
8611 |
+ printk(KERN_ERR "module %s: Unknown relocation: %u\n", |
8612 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/module_64.c linux-2.6.28.8/arch/x86/kernel/module_64.c |
8613 |
+--- linux-2.6.28.8/arch/x86/kernel/module_64.c 2009-02-06 16:47:45.000000000 -0500 |
8614 |
++++ linux-2.6.28.8/arch/x86/kernel/module_64.c 2009-02-21 09:37:48.000000000 -0500 |
8615 |
+@@ -40,7 +40,7 @@ void module_free(struct module *mod, voi |
8616 |
+ table entries. */ |
8617 |
+ } |
8618 |
+ |
8619 |
+-void *module_alloc(unsigned long size) |
8620 |
++static void *__module_alloc(unsigned long size, pgprot_t prot) |
8621 |
+ { |
8622 |
+ struct vm_struct *area; |
8623 |
+ |
8624 |
+@@ -54,8 +54,31 @@ void *module_alloc(unsigned long size) |
8625 |
+ if (!area) |
8626 |
+ return NULL; |
8627 |
+ |
8628 |
+- return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC); |
8629 |
++ return __vmalloc_area(area, GFP_KERNEL | __GFP_ZERO, prot); |
8630 |
++} |
8631 |
++ |
8632 |
++#ifdef CONFIG_PAX_KERNEXEC |
8633 |
++void *module_alloc(unsigned long size) |
8634 |
++{ |
8635 |
++ return __module_alloc(size, PAGE_KERNEL); |
8636 |
++} |
8637 |
++ |
8638 |
++void module_free_exec(struct module *mod, void *module_region) |
8639 |
++{ |
8640 |
++ module_free(mod, module_region); |
8641 |
++} |
8642 |
++ |
8643 |
++void *module_alloc_exec(unsigned long size) |
8644 |
++{ |
8645 |
++ return __module_alloc(size, PAGE_KERNEL_RX); |
8646 |
+ } |
8647 |
++#else |
8648 |
++void *module_alloc(unsigned long size) |
8649 |
++{ |
8650 |
++ return __module_alloc(size, PAGE_KERNEL_EXEC); |
8651 |
++} |
8652 |
++#endif |
8653 |
++ |
8654 |
+ #endif |
8655 |
+ |
8656 |
+ /* We don't need anything special. */ |
8657 |
+@@ -77,7 +100,11 @@ int apply_relocate_add(Elf64_Shdr *sechd |
8658 |
+ Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; |
8659 |
+ Elf64_Sym *sym; |
8660 |
+ void *loc; |
8661 |
+- u64 val; |
8662 |
++ u64 val; |
8663 |
++ |
8664 |
++#ifdef CONFIG_PAX_KERNEXEC |
8665 |
++ unsigned long cr0; |
8666 |
++#endif |
8667 |
+ |
8668 |
+ DEBUGP("Applying relocate section %u to %u\n", relsec, |
8669 |
+ sechdrs[relsec].sh_info); |
8670 |
+@@ -101,21 +128,61 @@ int apply_relocate_add(Elf64_Shdr *sechd |
8671 |
+ case R_X86_64_NONE: |
8672 |
+ break; |
8673 |
+ case R_X86_64_64: |
8674 |
++ |
8675 |
++#ifdef CONFIG_PAX_KERNEXEC |
8676 |
++ pax_open_kernel(cr0); |
8677 |
++#endif |
8678 |
++ |
8679 |
+ *(u64 *)loc = val; |
8680 |
++ |
8681 |
++#ifdef CONFIG_PAX_KERNEXEC |
8682 |
++ pax_close_kernel(cr0); |
8683 |
++#endif |
8684 |
++ |
8685 |
+ break; |
8686 |
+ case R_X86_64_32: |
8687 |
++ |
8688 |
++#ifdef CONFIG_PAX_KERNEXEC |
8689 |
++ pax_open_kernel(cr0); |
8690 |
++#endif |
8691 |
++ |
8692 |
+ *(u32 *)loc = val; |
8693 |
++ |
8694 |
++#ifdef CONFIG_PAX_KERNEXEC |
8695 |
++ pax_close_kernel(cr0); |
8696 |
++#endif |
8697 |
++ |
8698 |
+ if (val != *(u32 *)loc) |
8699 |
+ goto overflow; |
8700 |
+ break; |
8701 |
+ case R_X86_64_32S: |
8702 |
++ |
8703 |
++#ifdef CONFIG_PAX_KERNEXEC |
8704 |
++ pax_open_kernel(cr0); |
8705 |
++#endif |
8706 |
++ |
8707 |
+ *(s32 *)loc = val; |
8708 |
++ |
8709 |
++#ifdef CONFIG_PAX_KERNEXEC |
8710 |
++ pax_close_kernel(cr0); |
8711 |
++#endif |
8712 |
++ |
8713 |
+ if ((s64)val != *(s32 *)loc) |
8714 |
+ goto overflow; |
8715 |
+ break; |
8716 |
+ case R_X86_64_PC32: |
8717 |
+ val -= (u64)loc; |
8718 |
++ |
8719 |
++#ifdef CONFIG_PAX_KERNEXEC |
8720 |
++ pax_open_kernel(cr0); |
8721 |
++#endif |
8722 |
++ |
8723 |
+ *(u32 *)loc = val; |
8724 |
++ |
8725 |
++#ifdef CONFIG_PAX_KERNEXEC |
8726 |
++ pax_close_kernel(cr0); |
8727 |
++#endif |
8728 |
++ |
8729 |
+ #if 0 |
8730 |
+ if ((s64)val != *(s32 *)loc) |
8731 |
+ goto overflow; |
8732 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt.c linux-2.6.28.8/arch/x86/kernel/paravirt.c |
8733 |
+--- linux-2.6.28.8/arch/x86/kernel/paravirt.c 2009-03-07 10:24:49.000000000 -0500 |
8734 |
++++ linux-2.6.28.8/arch/x86/kernel/paravirt.c 2009-03-07 10:34:42.000000000 -0500 |
8735 |
+@@ -44,7 +44,7 @@ void _paravirt_nop(void) |
8736 |
+ { |
8737 |
+ } |
8738 |
+ |
8739 |
+-static void __init default_banner(void) |
8740 |
++static void default_banner(void) |
8741 |
+ { |
8742 |
+ printk(KERN_INFO "Booting paravirtualized kernel on %s\n", |
8743 |
+ pv_info.name); |
8744 |
+@@ -164,7 +164,7 @@ unsigned paravirt_patch_insns(void *insn |
8745 |
+ if (insn_len > len || start == NULL) |
8746 |
+ insn_len = len; |
8747 |
+ else |
8748 |
+- memcpy(insnbuf, start, insn_len); |
8749 |
++ memcpy(insnbuf, ktla_ktva(start), insn_len); |
8750 |
+ |
8751 |
+ return insn_len; |
8752 |
+ } |
8753 |
+@@ -292,21 +292,21 @@ void arch_flush_lazy_cpu_mode(void) |
8754 |
+ preempt_enable(); |
8755 |
+ } |
8756 |
+ |
8757 |
+-struct pv_info pv_info = { |
8758 |
++struct pv_info pv_info __read_only = { |
8759 |
+ .name = "bare hardware", |
8760 |
+ .paravirt_enabled = 0, |
8761 |
+ .kernel_rpl = 0, |
8762 |
+ .shared_kernel_pmd = 1, /* Only used when CONFIG_X86_PAE is set */ |
8763 |
+ }; |
8764 |
+ |
8765 |
+-struct pv_init_ops pv_init_ops = { |
8766 |
++struct pv_init_ops pv_init_ops __read_only = { |
8767 |
+ .patch = native_patch, |
8768 |
+ .banner = default_banner, |
8769 |
+ .arch_setup = paravirt_nop, |
8770 |
+ .memory_setup = machine_specific_memory_setup, |
8771 |
+ }; |
8772 |
+ |
8773 |
+-struct pv_time_ops pv_time_ops = { |
8774 |
++struct pv_time_ops pv_time_ops __read_only = { |
8775 |
+ .time_init = hpet_time_init, |
8776 |
+ .get_wallclock = native_get_wallclock, |
8777 |
+ .set_wallclock = native_set_wallclock, |
8778 |
+@@ -314,7 +314,7 @@ struct pv_time_ops pv_time_ops = { |
8779 |
+ .get_tsc_khz = native_calibrate_tsc, |
8780 |
+ }; |
8781 |
+ |
8782 |
+-struct pv_irq_ops pv_irq_ops = { |
8783 |
++struct pv_irq_ops pv_irq_ops __read_only = { |
8784 |
+ .init_IRQ = native_init_IRQ, |
8785 |
+ .save_fl = native_save_fl, |
8786 |
+ .restore_fl = native_restore_fl, |
8787 |
+@@ -327,7 +327,7 @@ struct pv_irq_ops pv_irq_ops = { |
8788 |
+ #endif |
8789 |
+ }; |
8790 |
+ |
8791 |
+-struct pv_cpu_ops pv_cpu_ops = { |
8792 |
++struct pv_cpu_ops pv_cpu_ops __read_only = { |
8793 |
+ .cpuid = native_cpuid, |
8794 |
+ .get_debugreg = native_get_debugreg, |
8795 |
+ .set_debugreg = native_set_debugreg, |
8796 |
+@@ -389,7 +389,7 @@ struct pv_cpu_ops pv_cpu_ops = { |
8797 |
+ }, |
8798 |
+ }; |
8799 |
+ |
8800 |
+-struct pv_apic_ops pv_apic_ops = { |
8801 |
++struct pv_apic_ops pv_apic_ops __read_only = { |
8802 |
+ #ifdef CONFIG_X86_LOCAL_APIC |
8803 |
+ .setup_boot_clock = setup_boot_APIC_clock, |
8804 |
+ .setup_secondary_clock = setup_secondary_APIC_clock, |
8805 |
+@@ -397,7 +397,7 @@ struct pv_apic_ops pv_apic_ops = { |
8806 |
+ #endif |
8807 |
+ }; |
8808 |
+ |
8809 |
+-struct pv_mmu_ops pv_mmu_ops = { |
8810 |
++struct pv_mmu_ops pv_mmu_ops __read_only = { |
8811 |
+ #ifndef CONFIG_X86_64 |
8812 |
+ .pagetable_setup_start = native_pagetable_setup_start, |
8813 |
+ .pagetable_setup_done = native_pagetable_setup_done, |
8814 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/paravirt-spinlocks.c linux-2.6.28.8/arch/x86/kernel/paravirt-spinlocks.c |
8815 |
+--- linux-2.6.28.8/arch/x86/kernel/paravirt-spinlocks.c 2009-02-06 16:47:45.000000000 -0500 |
8816 |
++++ linux-2.6.28.8/arch/x86/kernel/paravirt-spinlocks.c 2009-02-21 09:37:48.000000000 -0500 |
8817 |
+@@ -13,7 +13,7 @@ default_spin_lock_flags(raw_spinlock_t * |
8818 |
+ __raw_spin_lock(lock); |
8819 |
+ } |
8820 |
+ |
8821 |
+-struct pv_lock_ops pv_lock_ops = { |
8822 |
++struct pv_lock_ops pv_lock_ops __read_only = { |
8823 |
+ #ifdef CONFIG_SMP |
8824 |
+ .spin_is_locked = __ticket_spin_is_locked, |
8825 |
+ .spin_is_contended = __ticket_spin_is_contended, |
8826 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/process_32.c linux-2.6.28.8/arch/x86/kernel/process_32.c |
8827 |
+--- linux-2.6.28.8/arch/x86/kernel/process_32.c 2009-02-06 16:47:45.000000000 -0500 |
8828 |
++++ linux-2.6.28.8/arch/x86/kernel/process_32.c 2009-02-21 09:37:48.000000000 -0500 |
8829 |
+@@ -65,8 +65,10 @@ asmlinkage void ret_from_fork(void) __as |
8830 |
+ DEFINE_PER_CPU(struct task_struct *, current_task) = &init_task; |
8831 |
+ EXPORT_PER_CPU_SYMBOL(current_task); |
8832 |
+ |
8833 |
++#ifdef CONFIG_SMP |
8834 |
+ DEFINE_PER_CPU(int, cpu_number); |
8835 |
+ EXPORT_PER_CPU_SYMBOL(cpu_number); |
8836 |
++#endif |
8837 |
+ |
8838 |
+ /* |
8839 |
+ * Return saved PC of a blocked thread. |
8840 |
+@@ -74,6 +76,7 @@ EXPORT_PER_CPU_SYMBOL(cpu_number); |
8841 |
+ unsigned long thread_saved_pc(struct task_struct *tsk) |
8842 |
+ { |
8843 |
+ return ((unsigned long *)tsk->thread.sp)[3]; |
8844 |
++//XXX return tsk->thread.eip; |
8845 |
+ } |
8846 |
+ |
8847 |
+ #ifndef CONFIG_SMP |
8848 |
+@@ -131,7 +134,7 @@ void __show_regs(struct pt_regs *regs, i |
8849 |
+ unsigned short ss, gs; |
8850 |
+ const char *board; |
8851 |
+ |
8852 |
+- if (user_mode_vm(regs)) { |
8853 |
++ if (user_mode(regs)) { |
8854 |
+ sp = regs->sp; |
8855 |
+ ss = regs->ss & 0xffff; |
8856 |
+ savesegment(gs, gs); |
8857 |
+@@ -212,8 +215,8 @@ int kernel_thread(int (*fn)(void *), voi |
8858 |
+ regs.bx = (unsigned long) fn; |
8859 |
+ regs.dx = (unsigned long) arg; |
8860 |
+ |
8861 |
+- regs.ds = __USER_DS; |
8862 |
+- regs.es = __USER_DS; |
8863 |
++ regs.ds = __KERNEL_DS; |
8864 |
++ regs.es = __KERNEL_DS; |
8865 |
+ regs.fs = __KERNEL_PERCPU; |
8866 |
+ regs.orig_ax = -1; |
8867 |
+ regs.ip = (unsigned long) kernel_thread_helper; |
8868 |
+@@ -235,7 +238,7 @@ void exit_thread(void) |
8869 |
+ struct task_struct *tsk = current; |
8870 |
+ struct thread_struct *t = &tsk->thread; |
8871 |
+ int cpu = get_cpu(); |
8872 |
+- struct tss_struct *tss = &per_cpu(init_tss, cpu); |
8873 |
++ struct tss_struct *tss = init_tss + cpu; |
8874 |
+ |
8875 |
+ kfree(t->io_bitmap_ptr); |
8876 |
+ t->io_bitmap_ptr = NULL; |
8877 |
+@@ -264,6 +267,7 @@ void flush_thread(void) |
8878 |
+ { |
8879 |
+ struct task_struct *tsk = current; |
8880 |
+ |
8881 |
++ loadsegment(gs, 0); |
8882 |
+ tsk->thread.debugreg0 = 0; |
8883 |
+ tsk->thread.debugreg1 = 0; |
8884 |
+ tsk->thread.debugreg2 = 0; |
8885 |
+@@ -303,7 +307,7 @@ int copy_thread(int nr, unsigned long cl |
8886 |
+ struct task_struct *tsk; |
8887 |
+ int err; |
8888 |
+ |
8889 |
+- childregs = task_pt_regs(p); |
8890 |
++ childregs = task_stack_page(p) + THREAD_SIZE - sizeof(struct pt_regs) - 8; |
8891 |
+ *childregs = *regs; |
8892 |
+ childregs->ax = 0; |
8893 |
+ childregs->sp = sp; |
8894 |
+@@ -332,6 +336,7 @@ int copy_thread(int nr, unsigned long cl |
8895 |
+ * Set a new TLS for the child thread? |
8896 |
+ */ |
8897 |
+ if (clone_flags & CLONE_SETTLS) |
8898 |
++//XXX needs set_fs()? |
8899 |
+ err = do_set_thread_area(p, -1, |
8900 |
+ (struct user_desc __user *)childregs->si, 0); |
8901 |
+ |
8902 |
+@@ -553,7 +558,7 @@ struct task_struct * __switch_to(struct |
8903 |
+ struct thread_struct *prev = &prev_p->thread, |
8904 |
+ *next = &next_p->thread; |
8905 |
+ int cpu = smp_processor_id(); |
8906 |
+- struct tss_struct *tss = &per_cpu(init_tss, cpu); |
8907 |
++ struct tss_struct *tss = init_tss + cpu; |
8908 |
+ |
8909 |
+ /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ |
8910 |
+ |
8911 |
+@@ -581,6 +586,11 @@ struct task_struct * __switch_to(struct |
8912 |
+ */ |
8913 |
+ savesegment(gs, prev->gs); |
8914 |
+ |
8915 |
++#ifdef CONFIG_PAX_MEMORY_UDEREF |
8916 |
++ if (!segment_eq(task_thread_info(prev_p)->addr_limit, task_thread_info(next_p)->addr_limit)) |
8917 |
++ __set_fs(task_thread_info(next_p)->addr_limit, cpu); |
8918 |
++#endif |
8919 |
++ |
8920 |
+ /* |
8921 |
+ * Load the per-thread Thread-Local Storage descriptor. |
8922 |
+ */ |
8923 |
+@@ -719,15 +729,27 @@ unsigned long get_wchan(struct task_stru |
8924 |
+ return 0; |
8925 |
+ } |
8926 |
+ |
8927 |
+-unsigned long arch_align_stack(unsigned long sp) |
8928 |
++#ifdef CONFIG_PAX_RANDKSTACK |
8929 |
++asmlinkage void pax_randomize_kstack(void) |
8930 |
+ { |
8931 |
+- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) |
8932 |
+- sp -= get_random_int() % 8192; |
8933 |
+- return sp & ~0xf; |
8934 |
+-} |
8935 |
++ struct thread_struct *thread = ¤t->thread; |
8936 |
++ unsigned long time; |
8937 |
+ |
8938 |
+-unsigned long arch_randomize_brk(struct mm_struct *mm) |
8939 |
+-{ |
8940 |
+- unsigned long range_end = mm->brk + 0x02000000; |
8941 |
+- return randomize_range(mm->brk, range_end, 0) ? : mm->brk; |
8942 |
++ if (!randomize_va_space) |
8943 |
++ return; |
8944 |
++ |
8945 |
++ rdtscl(time); |
8946 |
++ |
8947 |
++ /* P4 seems to return a 0 LSB, ignore it */ |
8948 |
++#ifdef CONFIG_MPENTIUM4 |
8949 |
++ time &= 0x1EUL; |
8950 |
++ time <<= 2; |
8951 |
++#else |
8952 |
++ time &= 0xFUL; |
8953 |
++ time <<= 3; |
8954 |
++#endif |
8955 |
++ |
8956 |
++ thread->sp0 ^= time; |
8957 |
++ load_sp0(init_tss + smp_processor_id(), thread); |
8958 |
+ } |
8959 |
++#endif |
8960 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/process_64.c linux-2.6.28.8/arch/x86/kernel/process_64.c |
8961 |
+--- linux-2.6.28.8/arch/x86/kernel/process_64.c 2009-02-06 16:47:45.000000000 -0500 |
8962 |
++++ linux-2.6.28.8/arch/x86/kernel/process_64.c 2009-02-21 09:37:48.000000000 -0500 |
8963 |
+@@ -109,6 +109,8 @@ static inline void play_dead(void) |
8964 |
+ void cpu_idle(void) |
8965 |
+ { |
8966 |
+ current_thread_info()->status |= TS_POLLING; |
8967 |
++ current->stack_canary = pax_get_random_long(); |
8968 |
++ write_pda(stack_canary, current->stack_canary); |
8969 |
+ /* endless idle loop with no priority at all */ |
8970 |
+ while (1) { |
8971 |
+ tick_nohz_stop_sched_tick(1); |
8972 |
+@@ -223,7 +225,7 @@ void exit_thread(void) |
8973 |
+ struct thread_struct *t = &me->thread; |
8974 |
+ |
8975 |
+ if (me->thread.io_bitmap_ptr) { |
8976 |
+- struct tss_struct *tss = &per_cpu(init_tss, get_cpu()); |
8977 |
++ struct tss_struct *tss = init_tss + get_cpu(); |
8978 |
+ |
8979 |
+ kfree(t->io_bitmap_ptr); |
8980 |
+ t->io_bitmap_ptr = NULL; |
8981 |
+@@ -558,7 +560,7 @@ __switch_to(struct task_struct *prev_p, |
8982 |
+ struct thread_struct *prev = &prev_p->thread; |
8983 |
+ struct thread_struct *next = &next_p->thread; |
8984 |
+ int cpu = smp_processor_id(); |
8985 |
+- struct tss_struct *tss = &per_cpu(init_tss, cpu); |
8986 |
++ struct tss_struct *tss = init_tss + cpu; |
8987 |
+ unsigned fsindex, gsindex; |
8988 |
+ |
8989 |
+ /* we're going to use this soon, after a few expensive things */ |
8990 |
+@@ -647,7 +649,6 @@ __switch_to(struct task_struct *prev_p, |
8991 |
+ (unsigned long)task_stack_page(next_p) + |
8992 |
+ THREAD_SIZE - PDA_STACKOFFSET); |
8993 |
+ #ifdef CONFIG_CC_STACKPROTECTOR |
8994 |
+- write_pda(stack_canary, next_p->stack_canary); |
8995 |
+ /* |
8996 |
+ * Build time only check to make sure the stack_canary is at |
8997 |
+ * offset 40 in the pda; this is a gcc ABI requirement |
8998 |
+@@ -746,12 +747,11 @@ unsigned long get_wchan(struct task_stru |
8999 |
+ if (!p || p == current || p->state == TASK_RUNNING) |
9000 |
+ return 0; |
9001 |
+ stack = (unsigned long)task_stack_page(p); |
9002 |
+- if (p->thread.sp < stack || p->thread.sp >= stack+THREAD_SIZE) |
9003 |
++ if (p->thread.sp < stack || p->thread.sp > stack+THREAD_SIZE-8-sizeof(u64)) |
9004 |
+ return 0; |
9005 |
+ fp = *(u64 *)(p->thread.sp); |
9006 |
+ do { |
9007 |
+- if (fp < (unsigned long)stack || |
9008 |
+- fp >= (unsigned long)stack+THREAD_SIZE) |
9009 |
++ if (fp < stack || fp > stack+THREAD_SIZE-8-sizeof(u64)) |
9010 |
+ return 0; |
9011 |
+ ip = *(u64 *)(fp+8); |
9012 |
+ if (!in_sched_functions(ip)) |
9013 |
+@@ -860,16 +860,3 @@ long sys_arch_prctl(int code, unsigned l |
9014 |
+ { |
9015 |
+ return do_arch_prctl(current, code, addr); |
9016 |
+ } |
9017 |
+- |
9018 |
+-unsigned long arch_align_stack(unsigned long sp) |
9019 |
+-{ |
9020 |
+- if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) |
9021 |
+- sp -= get_random_int() % 8192; |
9022 |
+- return sp & ~0xf; |
9023 |
+-} |
9024 |
+- |
9025 |
+-unsigned long arch_randomize_brk(struct mm_struct *mm) |
9026 |
+-{ |
9027 |
+- unsigned long range_end = mm->brk + 0x02000000; |
9028 |
+- return randomize_range(mm->brk, range_end, 0) ? : mm->brk; |
9029 |
+-} |
9030 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/ptrace.c linux-2.6.28.8/arch/x86/kernel/ptrace.c |
9031 |
+--- linux-2.6.28.8/arch/x86/kernel/ptrace.c 2009-03-07 10:24:49.000000000 -0500 |
9032 |
++++ linux-2.6.28.8/arch/x86/kernel/ptrace.c 2009-03-07 10:29:51.000000000 -0500 |
9033 |
+@@ -1502,7 +1502,7 @@ void send_sigtrap(struct task_struct *ts |
9034 |
+ info.si_code = si_code; |
9035 |
+ |
9036 |
+ /* User-mode ip? */ |
9037 |
+- info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; |
9038 |
++ info.si_addr = user_mode(regs) ? (void __user *) regs->ip : NULL; |
9039 |
+ |
9040 |
+ /* Send us the fake SIGTRAP */ |
9041 |
+ force_sig_info(SIGTRAP, &info, tsk); |
9042 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/reboot.c linux-2.6.28.8/arch/x86/kernel/reboot.c |
9043 |
+--- linux-2.6.28.8/arch/x86/kernel/reboot.c 2009-03-07 10:24:49.000000000 -0500 |
9044 |
++++ linux-2.6.28.8/arch/x86/kernel/reboot.c 2009-03-07 10:32:37.000000000 -0500 |
9045 |
+@@ -28,7 +28,7 @@ void (*pm_power_off)(void); |
9046 |
+ EXPORT_SYMBOL(pm_power_off); |
9047 |
+ |
9048 |
+ static const struct desc_ptr no_idt = {}; |
9049 |
+-static int reboot_mode; |
9050 |
++static unsigned short reboot_mode; |
9051 |
+ enum reboot_type reboot_type = BOOT_KBD; |
9052 |
+ int reboot_force; |
9053 |
+ |
9054 |
+@@ -210,7 +210,7 @@ static struct dmi_system_id __initdata r |
9055 |
+ DMI_MATCH(DMI_PRODUCT_NAME, "Dell XPS710"), |
9056 |
+ }, |
9057 |
+ }, |
9058 |
+- { } |
9059 |
++ { NULL, NULL, {{0, {0}}}, NULL} |
9060 |
+ }; |
9061 |
+ |
9062 |
+ static int __init reboot_init(void) |
9063 |
+@@ -226,12 +226,12 @@ core_initcall(reboot_init); |
9064 |
+ controller to pulse the CPU reset line, which is more thorough, but |
9065 |
+ doesn't work with at least one type of 486 motherboard. It is easy |
9066 |
+ to stop this code working; hence the copious comments. */ |
9067 |
+-static const unsigned long long |
9068 |
+-real_mode_gdt_entries [3] = |
9069 |
++static struct desc_struct |
9070 |
++real_mode_gdt_entries [3] __read_only = |
9071 |
+ { |
9072 |
+- 0x0000000000000000ULL, /* Null descriptor */ |
9073 |
+- 0x00009b000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */ |
9074 |
+- 0x000093000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ |
9075 |
++ {{{0x00000000, 0x00000000}}}, /* Null descriptor */ |
9076 |
++ {{{0x0000ffff, 0x00009b00}}}, /* 16-bit real-mode 64k code at 0x00000000 */ |
9077 |
++ {{{0x0100ffff, 0x00009300}}} /* 16-bit real-mode 64k data at 0x00000100 */ |
9078 |
+ }; |
9079 |
+ |
9080 |
+ static const struct desc_ptr |
9081 |
+@@ -280,7 +280,7 @@ static const unsigned char jump_to_bios |
9082 |
+ * specified by the code and length parameters. |
9083 |
+ * We assume that length will aways be less that 100! |
9084 |
+ */ |
9085 |
+-void machine_real_restart(const unsigned char *code, int length) |
9086 |
++void machine_real_restart(const unsigned char *code, unsigned int length) |
9087 |
+ { |
9088 |
+ local_irq_disable(); |
9089 |
+ |
9090 |
+@@ -300,8 +300,8 @@ void machine_real_restart(const unsigned |
9091 |
+ /* Remap the kernel at virtual address zero, as well as offset zero |
9092 |
+ from the kernel segment. This assumes the kernel segment starts at |
9093 |
+ virtual address PAGE_OFFSET. */ |
9094 |
+- memcpy(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY, |
9095 |
+- sizeof(swapper_pg_dir [0]) * KERNEL_PGD_PTRS); |
9096 |
++ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY, |
9097 |
++ min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); |
9098 |
+ |
9099 |
+ /* |
9100 |
+ * Use `swapper_pg_dir' as our page directory. |
9101 |
+@@ -313,16 +313,15 @@ void machine_real_restart(const unsigned |
9102 |
+ boot)". This seems like a fairly standard thing that gets set by |
9103 |
+ REBOOT.COM programs, and the previous reset routine did this |
9104 |
+ too. */ |
9105 |
+- *((unsigned short *)0x472) = reboot_mode; |
9106 |
++ *(unsigned short *)(__va(0x472)) = reboot_mode; |
9107 |
+ |
9108 |
+ /* For the switch to real mode, copy some code to low memory. It has |
9109 |
+ to be in the first 64k because it is running in 16-bit mode, and it |
9110 |
+ has to have the same physical and virtual address, because it turns |
9111 |
+ off paging. Copy it near the end of the first page, out of the way |
9112 |
+ of BIOS variables. */ |
9113 |
+- memcpy((void *)(0x1000 - sizeof(real_mode_switch) - 100), |
9114 |
+- real_mode_switch, sizeof (real_mode_switch)); |
9115 |
+- memcpy((void *)(0x1000 - 100), code, length); |
9116 |
++ memcpy(__va(0x1000 - sizeof (real_mode_switch) - 100), real_mode_switch, sizeof (real_mode_switch)); |
9117 |
++ memcpy(__va(0x1000 - 100), code, length); |
9118 |
+ |
9119 |
+ /* Set up the IDT for real mode. */ |
9120 |
+ load_idt(&real_mode_idt); |
9121 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/setup.c linux-2.6.28.8/arch/x86/kernel/setup.c |
9122 |
+--- linux-2.6.28.8/arch/x86/kernel/setup.c 2009-02-06 16:47:45.000000000 -0500 |
9123 |
++++ linux-2.6.28.8/arch/x86/kernel/setup.c 2009-02-21 09:37:48.000000000 -0500 |
9124 |
+@@ -738,6 +738,7 @@ void start_periodic_check_for_corruption |
9125 |
+ } |
9126 |
+ #endif |
9127 |
+ |
9128 |
++#ifdef CONFIG_X86_RESERVE_LOW_64K |
9129 |
+ static int __init dmi_low_memory_corruption(const struct dmi_system_id *d) |
9130 |
+ { |
9131 |
+ printk(KERN_NOTICE |
9132 |
+@@ -749,6 +750,7 @@ static int __init dmi_low_memory_corrupt |
9133 |
+ |
9134 |
+ return 0; |
9135 |
+ } |
9136 |
++#endif |
9137 |
+ |
9138 |
+ /* List of systems that have known low memory corruption BIOS problems */ |
9139 |
+ static struct dmi_system_id __initdata bad_bios_dmi_table[] = { |
9140 |
+@@ -845,8 +847,8 @@ void __init setup_arch(char **cmdline_p) |
9141 |
+ |
9142 |
+ if (!boot_params.hdr.root_flags) |
9143 |
+ root_mountflags &= ~MS_RDONLY; |
9144 |
+- init_mm.start_code = (unsigned long) _text; |
9145 |
+- init_mm.end_code = (unsigned long) _etext; |
9146 |
++ init_mm.start_code = ktla_ktva((unsigned long) _text); |
9147 |
++ init_mm.end_code = ktla_ktva((unsigned long) _etext); |
9148 |
+ init_mm.end_data = (unsigned long) _edata; |
9149 |
+ #ifdef CONFIG_X86_32 |
9150 |
+ init_mm.brk = init_pg_tables_end + PAGE_OFFSET; |
9151 |
+@@ -854,9 +856,9 @@ void __init setup_arch(char **cmdline_p) |
9152 |
+ init_mm.brk = (unsigned long) &_end; |
9153 |
+ #endif |
9154 |
+ |
9155 |
+- code_resource.start = virt_to_phys(_text); |
9156 |
+- code_resource.end = virt_to_phys(_etext)-1; |
9157 |
+- data_resource.start = virt_to_phys(_etext); |
9158 |
++ code_resource.start = virt_to_phys(ktla_ktva(_text)); |
9159 |
++ code_resource.end = virt_to_phys(ktla_ktva(_etext))-1; |
9160 |
++ data_resource.start = virt_to_phys(_data); |
9161 |
+ data_resource.end = virt_to_phys(_edata)-1; |
9162 |
+ bss_resource.start = virt_to_phys(&__bss_start); |
9163 |
+ bss_resource.end = virt_to_phys(&__bss_stop)-1; |
9164 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/setup_percpu.c linux-2.6.28.8/arch/x86/kernel/setup_percpu.c |
9165 |
+--- linux-2.6.28.8/arch/x86/kernel/setup_percpu.c 2009-02-06 16:47:45.000000000 -0500 |
9166 |
++++ linux-2.6.28.8/arch/x86/kernel/setup_percpu.c 2009-02-21 09:37:48.000000000 -0500 |
9167 |
+@@ -179,7 +179,11 @@ void __init setup_per_cpu_areas(void) |
9168 |
+ cpu, node, __pa(ptr)); |
9169 |
+ } |
9170 |
+ #endif |
9171 |
++#ifdef CONFIG_X86_32 |
9172 |
++ __per_cpu_offset[cpu] = ptr - __per_cpu_start; |
9173 |
++#else |
9174 |
+ per_cpu_offset(cpu) = ptr - __per_cpu_start; |
9175 |
++#endif |
9176 |
+ memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start); |
9177 |
+ } |
9178 |
+ |
9179 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/signal_32.c linux-2.6.28.8/arch/x86/kernel/signal_32.c |
9180 |
+--- linux-2.6.28.8/arch/x86/kernel/signal_32.c 2009-02-06 16:47:45.000000000 -0500 |
9181 |
++++ linux-2.6.28.8/arch/x86/kernel/signal_32.c 2009-02-21 09:37:48.000000000 -0500 |
9182 |
+@@ -367,9 +367,9 @@ __setup_frame(int sig, struct k_sigactio |
9183 |
+ } |
9184 |
+ |
9185 |
+ if (current->mm->context.vdso) |
9186 |
+- restorer = VDSO32_SYMBOL(current->mm->context.vdso, sigreturn); |
9187 |
++ restorer = (void __user *)VDSO32_SYMBOL(current->mm->context.vdso, sigreturn); |
9188 |
+ else |
9189 |
+- restorer = &frame->retcode; |
9190 |
++ restorer = (void __user *)&frame->retcode; |
9191 |
+ if (ka->sa.sa_flags & SA_RESTORER) |
9192 |
+ restorer = ka->sa.sa_restorer; |
9193 |
+ |
9194 |
+@@ -442,7 +442,7 @@ static int __setup_rt_frame(int sig, str |
9195 |
+ return -EFAULT; |
9196 |
+ |
9197 |
+ /* Set up to return from userspace. */ |
9198 |
+- restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); |
9199 |
++ restorer = (void __user *)VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn); |
9200 |
+ if (ka->sa.sa_flags & SA_RESTORER) |
9201 |
+ restorer = ka->sa.sa_restorer; |
9202 |
+ err |= __put_user(restorer, &frame->pretcode); |
9203 |
+@@ -612,7 +612,7 @@ static void do_signal(struct pt_regs *re |
9204 |
+ * X86_32: vm86 regs switched out by assembly code before reaching |
9205 |
+ * here, so testing against kernel CS suffices. |
9206 |
+ */ |
9207 |
+- if (!user_mode(regs)) |
9208 |
++ if (!user_mode_novm(regs)) |
9209 |
+ return; |
9210 |
+ |
9211 |
+ if (current_thread_info()->status & TS_RESTORE_SIGMASK) |
9212 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/signal_64.c linux-2.6.28.8/arch/x86/kernel/signal_64.c |
9213 |
+--- linux-2.6.28.8/arch/x86/kernel/signal_64.c 2009-02-06 16:47:45.000000000 -0500 |
9214 |
++++ linux-2.6.28.8/arch/x86/kernel/signal_64.c 2009-02-21 09:37:48.000000000 -0500 |
9215 |
+@@ -239,8 +239,8 @@ static int __setup_rt_frame(int sig, str |
9216 |
+ err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me); |
9217 |
+ err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate); |
9218 |
+ if (sizeof(*set) == 16) { |
9219 |
+- __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); |
9220 |
+- __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); |
9221 |
++ err |= __put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]); |
9222 |
++ err |= __put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]); |
9223 |
+ } else |
9224 |
+ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
9225 |
+ |
9226 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/smpboot.c linux-2.6.28.8/arch/x86/kernel/smpboot.c |
9227 |
+--- linux-2.6.28.8/arch/x86/kernel/smpboot.c 2009-02-06 16:47:45.000000000 -0500 |
9228 |
++++ linux-2.6.28.8/arch/x86/kernel/smpboot.c 2009-02-21 09:37:48.000000000 -0500 |
9229 |
+@@ -814,6 +814,11 @@ static int __cpuinit do_boot_cpu(int api |
9230 |
+ .cpu = cpu, |
9231 |
+ .done = COMPLETION_INITIALIZER_ONSTACK(c_idle.done), |
9232 |
+ }; |
9233 |
++ |
9234 |
++#ifdef CONFIG_PAX_KERNEXEC |
9235 |
++ unsigned long cr0; |
9236 |
++#endif |
9237 |
++ |
9238 |
+ INIT_WORK(&c_idle.work, do_fork_idle); |
9239 |
+ |
9240 |
+ #ifdef CONFIG_X86_64 |
9241 |
+@@ -864,7 +869,17 @@ do_rest: |
9242 |
+ cpu_pda(cpu)->pcurrent = c_idle.idle; |
9243 |
+ clear_tsk_thread_flag(c_idle.idle, TIF_FORK); |
9244 |
+ #endif |
9245 |
++ |
9246 |
++#ifdef CONFIG_PAX_KERNEXEC |
9247 |
++ pax_open_kernel(cr0); |
9248 |
++#endif |
9249 |
++ |
9250 |
+ early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); |
9251 |
++ |
9252 |
++#ifdef CONFIG_PAX_KERNEXEC |
9253 |
++ pax_close_kernel(cr0); |
9254 |
++#endif |
9255 |
++ |
9256 |
+ initial_code = (unsigned long)start_secondary; |
9257 |
+ stack_start.sp = (void *) c_idle.idle->thread.sp; |
9258 |
+ |
9259 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/smpcommon.c linux-2.6.28.8/arch/x86/kernel/smpcommon.c |
9260 |
+--- linux-2.6.28.8/arch/x86/kernel/smpcommon.c 2009-02-06 16:47:45.000000000 -0500 |
9261 |
++++ linux-2.6.28.8/arch/x86/kernel/smpcommon.c 2009-02-21 09:37:48.000000000 -0500 |
9262 |
+@@ -3,9 +3,10 @@ |
9263 |
+ */ |
9264 |
+ #include <linux/module.h> |
9265 |
+ #include <asm/smp.h> |
9266 |
++#include <asm/sections.h> |
9267 |
+ |
9268 |
+ #ifdef CONFIG_X86_32 |
9269 |
+-DEFINE_PER_CPU(unsigned long, this_cpu_off); |
9270 |
++DEFINE_PER_CPU(unsigned long, this_cpu_off) = (unsigned long)__per_cpu_start; |
9271 |
+ EXPORT_PER_CPU_SYMBOL(this_cpu_off); |
9272 |
+ |
9273 |
+ /* |
9274 |
+@@ -15,16 +16,19 @@ EXPORT_PER_CPU_SYMBOL(this_cpu_off); |
9275 |
+ */ |
9276 |
+ __cpuinit void init_gdt(int cpu) |
9277 |
+ { |
9278 |
+- struct desc_struct gdt; |
9279 |
++ struct desc_struct d, *gdt = get_cpu_gdt_table(cpu); |
9280 |
++ unsigned long base, limit; |
9281 |
+ |
9282 |
+- pack_descriptor(&gdt, __per_cpu_offset[cpu], 0xFFFFF, |
9283 |
+- 0x2 | DESCTYPE_S, 0x8); |
9284 |
+- gdt.s = 1; |
9285 |
++ base = per_cpu_offset(cpu); |
9286 |
++ limit = PERCPU_ENOUGH_ROOM - 1; |
9287 |
++ if (limit < 64*1024) |
9288 |
++ pack_descriptor(&d, base, limit, 0x80 | DESCTYPE_S | 0x3, 0x4); |
9289 |
++ else |
9290 |
++ pack_descriptor(&d, base, limit >> PAGE_SHIFT, 0x80 | DESCTYPE_S | 0x3, 0xC); |
9291 |
+ |
9292 |
+- write_gdt_entry(get_cpu_gdt_table(cpu), |
9293 |
+- GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S); |
9294 |
++ write_gdt_entry(gdt, GDT_ENTRY_PERCPU, &d, DESCTYPE_S); |
9295 |
+ |
9296 |
+- per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; |
9297 |
++ per_cpu(this_cpu_off, cpu) = base; |
9298 |
+ per_cpu(cpu_number, cpu) = cpu; |
9299 |
+ } |
9300 |
+ #endif |
9301 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/step.c linux-2.6.28.8/arch/x86/kernel/step.c |
9302 |
+--- linux-2.6.28.8/arch/x86/kernel/step.c 2009-02-06 16:47:45.000000000 -0500 |
9303 |
++++ linux-2.6.28.8/arch/x86/kernel/step.c 2009-02-21 09:37:48.000000000 -0500 |
9304 |
+@@ -23,22 +23,20 @@ unsigned long convert_ip_to_linear(struc |
9305 |
+ * and APM bios ones we just ignore here. |
9306 |
+ */ |
9307 |
+ if ((seg & SEGMENT_TI_MASK) == SEGMENT_LDT) { |
9308 |
+- u32 *desc; |
9309 |
++ struct desc_struct *desc; |
9310 |
+ unsigned long base; |
9311 |
+ |
9312 |
+- seg &= ~7UL; |
9313 |
++ seg >>= 3; |
9314 |
+ |
9315 |
+ mutex_lock(&child->mm->context.lock); |
9316 |
+- if (unlikely((seg >> 3) >= child->mm->context.size)) |
9317 |
+- addr = -1L; /* bogus selector, access would fault */ |
9318 |
++ if (unlikely(seg >= child->mm->context.size)) |
9319 |
++ addr = -EINVAL; |
9320 |
+ else { |
9321 |
+- desc = child->mm->context.ldt + seg; |
9322 |
+- base = ((desc[0] >> 16) | |
9323 |
+- ((desc[1] & 0xff) << 16) | |
9324 |
+- (desc[1] & 0xff000000)); |
9325 |
++ desc = &child->mm->context.ldt[seg]; |
9326 |
++ base = (desc->a >> 16) | ((desc->b & 0xff) << 16) | (desc->b & 0xff000000); |
9327 |
+ |
9328 |
+ /* 16-bit code segment? */ |
9329 |
+- if (!((desc[1] >> 22) & 1)) |
9330 |
++ if (!((desc->b >> 22) & 1)) |
9331 |
+ addr &= 0xffff; |
9332 |
+ addr += base; |
9333 |
+ } |
9334 |
+@@ -54,6 +52,9 @@ static int is_setting_trap_flag(struct t |
9335 |
+ unsigned char opcode[15]; |
9336 |
+ unsigned long addr = convert_ip_to_linear(child, regs); |
9337 |
+ |
9338 |
++ if (addr == -EINVAL) |
9339 |
++ return 0; |
9340 |
++ |
9341 |
+ copied = access_process_vm(child, addr, opcode, sizeof(opcode), 0); |
9342 |
+ for (i = 0; i < copied; i++) { |
9343 |
+ switch (opcode[i]) { |
9344 |
+@@ -75,7 +76,7 @@ static int is_setting_trap_flag(struct t |
9345 |
+ |
9346 |
+ #ifdef CONFIG_X86_64 |
9347 |
+ case 0x40 ... 0x4f: |
9348 |
+- if (regs->cs != __USER_CS) |
9349 |
++ if ((regs->cs & 0xffff) != __USER_CS) |
9350 |
+ /* 32-bit mode: register increment */ |
9351 |
+ return 0; |
9352 |
+ /* 64-bit mode: REX prefix */ |
9353 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/syscall_table_32.S linux-2.6.28.8/arch/x86/kernel/syscall_table_32.S |
9354 |
+--- linux-2.6.28.8/arch/x86/kernel/syscall_table_32.S 2009-02-06 16:47:45.000000000 -0500 |
9355 |
++++ linux-2.6.28.8/arch/x86/kernel/syscall_table_32.S 2009-02-21 09:37:48.000000000 -0500 |
9356 |
+@@ -1,3 +1,4 @@ |
9357 |
++.section .rodata,"a",@progbits |
9358 |
+ ENTRY(sys_call_table) |
9359 |
+ .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ |
9360 |
+ .long sys_exit |
9361 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/sys_i386_32.c linux-2.6.28.8/arch/x86/kernel/sys_i386_32.c |
9362 |
+--- linux-2.6.28.8/arch/x86/kernel/sys_i386_32.c 2009-02-06 16:47:45.000000000 -0500 |
9363 |
++++ linux-2.6.28.8/arch/x86/kernel/sys_i386_32.c 2009-02-21 09:37:48.000000000 -0500 |
9364 |
+@@ -24,6 +24,21 @@ |
9365 |
+ |
9366 |
+ #include <asm/syscalls.h> |
9367 |
+ |
9368 |
++int i386_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) |
9369 |
++{ |
9370 |
++ unsigned long pax_task_size = TASK_SIZE; |
9371 |
++ |
9372 |
++#ifdef CONFIG_PAX_SEGMEXEC |
9373 |
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) |
9374 |
++ pax_task_size = SEGMEXEC_TASK_SIZE; |
9375 |
++#endif |
9376 |
++ |
9377 |
++ if (len > pax_task_size || addr > pax_task_size - len) |
9378 |
++ return -EINVAL; |
9379 |
++ |
9380 |
++ return 0; |
9381 |
++} |
9382 |
++ |
9383 |
+ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, |
9384 |
+ unsigned long prot, unsigned long flags, |
9385 |
+ unsigned long fd, unsigned long pgoff) |
9386 |
+@@ -83,6 +98,205 @@ out: |
9387 |
+ return err; |
9388 |
+ } |
9389 |
+ |
9390 |
++unsigned long |
9391 |
++arch_get_unmapped_area(struct file *filp, unsigned long addr, |
9392 |
++ unsigned long len, unsigned long pgoff, unsigned long flags) |
9393 |
++{ |
9394 |
++ struct mm_struct *mm = current->mm; |
9395 |
++ struct vm_area_struct *vma; |
9396 |
++ unsigned long start_addr, pax_task_size = TASK_SIZE; |
9397 |
++ |
9398 |
++#ifdef CONFIG_PAX_SEGMEXEC |
9399 |
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) |
9400 |
++ pax_task_size = SEGMEXEC_TASK_SIZE; |
9401 |
++#endif |
9402 |
++ |
9403 |
++ if (len > pax_task_size) |
9404 |
++ return -ENOMEM; |
9405 |
++ |
9406 |
++ if (flags & MAP_FIXED) |
9407 |
++ return addr; |
9408 |
++ |
9409 |
++#ifdef CONFIG_PAX_RANDMMAP |
9410 |
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) |
9411 |
++#endif |
9412 |
++ |
9413 |
++ if (addr) { |
9414 |
++ addr = PAGE_ALIGN(addr); |
9415 |
++ vma = find_vma(mm, addr); |
9416 |
++ if (pax_task_size - len >= addr && |
9417 |
++ (!vma || addr + len <= vma->vm_start)) |
9418 |
++ return addr; |
9419 |
++ } |
9420 |
++ if (len > mm->cached_hole_size) { |
9421 |
++ start_addr = addr = mm->free_area_cache; |
9422 |
++ } else { |
9423 |
++ start_addr = addr = mm->mmap_base; |
9424 |
++ mm->cached_hole_size = 0; |
9425 |
++ } |
9426 |
++ |
9427 |
++#ifdef CONFIG_PAX_PAGEEXEC |
9428 |
++ if (!nx_enabled && (mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE) && start_addr >= mm->mmap_base) { |
9429 |
++ start_addr = 0x00110000UL; |
9430 |
++ |
9431 |
++#ifdef CONFIG_PAX_RANDMMAP |
9432 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
9433 |
++ start_addr += mm->delta_mmap & 0x03FFF000UL; |
9434 |
++#endif |
9435 |
++ |
9436 |
++ if (mm->start_brk <= start_addr && start_addr < mm->mmap_base) |
9437 |
++ start_addr = addr = mm->mmap_base; |
9438 |
++ else |
9439 |
++ addr = start_addr; |
9440 |
++ } |
9441 |
++#endif |
9442 |
++ |
9443 |
++full_search: |
9444 |
++ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { |
9445 |
++ /* At this point: (!vma || addr < vma->vm_end). */ |
9446 |
++ if (pax_task_size - len < addr) { |
9447 |
++ /* |
9448 |
++ * Start a new search - just in case we missed |
9449 |
++ * some holes. |
9450 |
++ */ |
9451 |
++ if (start_addr != mm->mmap_base) { |
9452 |
++ start_addr = addr = mm->mmap_base; |
9453 |
++ mm->cached_hole_size = 0; |
9454 |
++ goto full_search; |
9455 |
++ } |
9456 |
++ return -ENOMEM; |
9457 |
++ } |
9458 |
++ if (!vma || addr + len <= vma->vm_start) { |
9459 |
++ /* |
9460 |
++ * Remember the place where we stopped the search: |
9461 |
++ */ |
9462 |
++ mm->free_area_cache = addr + len; |
9463 |
++ return addr; |
9464 |
++ } |
9465 |
++ if (addr + mm->cached_hole_size < vma->vm_start) |
9466 |
++ mm->cached_hole_size = vma->vm_start - addr; |
9467 |
++ addr = vma->vm_end; |
9468 |
++ if (mm->start_brk <= addr && addr < mm->mmap_base) { |
9469 |
++ start_addr = addr = mm->mmap_base; |
9470 |
++ mm->cached_hole_size = 0; |
9471 |
++ goto full_search; |
9472 |
++ } |
9473 |
++ } |
9474 |
++} |
9475 |
++ |
9476 |
++unsigned long |
9477 |
++arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0, |
9478 |
++ const unsigned long len, const unsigned long pgoff, |
9479 |
++ const unsigned long flags) |
9480 |
++{ |
9481 |
++ struct vm_area_struct *vma; |
9482 |
++ struct mm_struct *mm = current->mm; |
9483 |
++ unsigned long base = mm->mmap_base, addr = addr0, pax_task_size = TASK_SIZE; |
9484 |
++ |
9485 |
++#ifdef CONFIG_PAX_SEGMEXEC |
9486 |
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) |
9487 |
++ pax_task_size = SEGMEXEC_TASK_SIZE; |
9488 |
++#endif |
9489 |
++ |
9490 |
++ /* requested length too big for entire address space */ |
9491 |
++ if (len > pax_task_size) |
9492 |
++ return -ENOMEM; |
9493 |
++ |
9494 |
++ if (flags & MAP_FIXED) |
9495 |
++ return addr; |
9496 |
++ |
9497 |
++#ifdef CONFIG_PAX_PAGEEXEC |
9498 |
++ if (!nx_enabled && (mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE)) |
9499 |
++ goto bottomup; |
9500 |
++#endif |
9501 |
++ |
9502 |
++#ifdef CONFIG_PAX_RANDMMAP |
9503 |
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) |
9504 |
++#endif |
9505 |
++ |
9506 |
++ /* requesting a specific address */ |
9507 |
++ if (addr) { |
9508 |
++ addr = PAGE_ALIGN(addr); |
9509 |
++ vma = find_vma(mm, addr); |
9510 |
++ if (pax_task_size - len >= addr && |
9511 |
++ (!vma || addr + len <= vma->vm_start)) |
9512 |
++ return addr; |
9513 |
++ } |
9514 |
++ |
9515 |
++ /* check if free_area_cache is useful for us */ |
9516 |
++ if (len <= mm->cached_hole_size) { |
9517 |
++ mm->cached_hole_size = 0; |
9518 |
++ mm->free_area_cache = mm->mmap_base; |
9519 |
++ } |
9520 |
++ |
9521 |
++ /* either no address requested or can't fit in requested address hole */ |
9522 |
++ addr = mm->free_area_cache; |
9523 |
++ |
9524 |
++ /* make sure it can fit in the remaining address space */ |
9525 |
++ if (addr > len) { |
9526 |
++ vma = find_vma(mm, addr-len); |
9527 |
++ if (!vma || addr <= vma->vm_start) |
9528 |
++ /* remember the address as a hint for next time */ |
9529 |
++ return (mm->free_area_cache = addr-len); |
9530 |
++ } |
9531 |
++ |
9532 |
++ if (mm->mmap_base < len) |
9533 |
++ goto bottomup; |
9534 |
++ |
9535 |
++ addr = mm->mmap_base-len; |
9536 |
++ |
9537 |
++ do { |
9538 |
++ /* |
9539 |
++ * Lookup failure means no vma is above this address, |
9540 |
++ * else if new region fits below vma->vm_start, |
9541 |
++ * return with success: |
9542 |
++ */ |
9543 |
++ vma = find_vma(mm, addr); |
9544 |
++ if (!vma || addr+len <= vma->vm_start) |
9545 |
++ /* remember the address as a hint for next time */ |
9546 |
++ return (mm->free_area_cache = addr); |
9547 |
++ |
9548 |
++ /* remember the largest hole we saw so far */ |
9549 |
++ if (addr + mm->cached_hole_size < vma->vm_start) |
9550 |
++ mm->cached_hole_size = vma->vm_start - addr; |
9551 |
++ |
9552 |
++ /* try just below the current vma->vm_start */ |
9553 |
++ addr = vma->vm_start-len; |
9554 |
++ } while (len < vma->vm_start); |
9555 |
++ |
9556 |
++bottomup: |
9557 |
++ /* |
9558 |
++ * A failed mmap() very likely causes application failure, |
9559 |
++ * so fall back to the bottom-up function here. This scenario |
9560 |
++ * can happen with large stack limits and large mmap() |
9561 |
++ * allocations. |
9562 |
++ */ |
9563 |
++ |
9564 |
++#ifdef CONFIG_PAX_SEGMEXEC |
9565 |
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) |
9566 |
++ mm->mmap_base = SEGMEXEC_TASK_UNMAPPED_BASE; |
9567 |
++ else |
9568 |
++#endif |
9569 |
++ |
9570 |
++ mm->mmap_base = TASK_UNMAPPED_BASE; |
9571 |
++ |
9572 |
++#ifdef CONFIG_PAX_RANDMMAP |
9573 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
9574 |
++ mm->mmap_base += mm->delta_mmap; |
9575 |
++#endif |
9576 |
++ |
9577 |
++ mm->free_area_cache = mm->mmap_base; |
9578 |
++ mm->cached_hole_size = ~0UL; |
9579 |
++ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); |
9580 |
++ /* |
9581 |
++ * Restore the topdown base: |
9582 |
++ */ |
9583 |
++ mm->mmap_base = base; |
9584 |
++ mm->free_area_cache = base; |
9585 |
++ mm->cached_hole_size = ~0UL; |
9586 |
++ |
9587 |
++ return addr; |
9588 |
++} |
9589 |
+ |
9590 |
+ struct sel_arg_struct { |
9591 |
+ unsigned long n; |
9592 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/sys_x86_64.c linux-2.6.28.8/arch/x86/kernel/sys_x86_64.c |
9593 |
+--- linux-2.6.28.8/arch/x86/kernel/sys_x86_64.c 2009-02-06 16:47:45.000000000 -0500 |
9594 |
++++ linux-2.6.28.8/arch/x86/kernel/sys_x86_64.c 2009-02-21 09:37:48.000000000 -0500 |
9595 |
+@@ -47,8 +47,8 @@ out: |
9596 |
+ return error; |
9597 |
+ } |
9598 |
+ |
9599 |
+-static void find_start_end(unsigned long flags, unsigned long *begin, |
9600 |
+- unsigned long *end) |
9601 |
++static void find_start_end(struct mm_struct *mm, unsigned long flags, |
9602 |
++ unsigned long *begin, unsigned long *end) |
9603 |
+ { |
9604 |
+ if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) { |
9605 |
+ unsigned long new_begin; |
9606 |
+@@ -67,7 +67,7 @@ static void find_start_end(unsigned long |
9607 |
+ *begin = new_begin; |
9608 |
+ } |
9609 |
+ } else { |
9610 |
+- *begin = TASK_UNMAPPED_BASE; |
9611 |
++ *begin = mm->mmap_base; |
9612 |
+ *end = TASK_SIZE; |
9613 |
+ } |
9614 |
+ } |
9615 |
+@@ -84,11 +84,15 @@ arch_get_unmapped_area(struct file *filp |
9616 |
+ if (flags & MAP_FIXED) |
9617 |
+ return addr; |
9618 |
+ |
9619 |
+- find_start_end(flags, &begin, &end); |
9620 |
++ find_start_end(mm, flags, &begin, &end); |
9621 |
+ |
9622 |
+ if (len > end) |
9623 |
+ return -ENOMEM; |
9624 |
+ |
9625 |
++#ifdef CONFIG_PAX_RANDMMAP |
9626 |
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) |
9627 |
++#endif |
9628 |
++ |
9629 |
+ if (addr) { |
9630 |
+ addr = PAGE_ALIGN(addr); |
9631 |
+ vma = find_vma(mm, addr); |
9632 |
+@@ -143,7 +147,7 @@ arch_get_unmapped_area_topdown(struct fi |
9633 |
+ { |
9634 |
+ struct vm_area_struct *vma; |
9635 |
+ struct mm_struct *mm = current->mm; |
9636 |
+- unsigned long addr = addr0; |
9637 |
++ unsigned long base = mm->mmap_base, addr = addr0; |
9638 |
+ |
9639 |
+ /* requested length too big for entire address space */ |
9640 |
+ if (len > TASK_SIZE) |
9641 |
+@@ -156,6 +160,10 @@ arch_get_unmapped_area_topdown(struct fi |
9642 |
+ if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) |
9643 |
+ goto bottomup; |
9644 |
+ |
9645 |
++#ifdef CONFIG_PAX_RANDMMAP |
9646 |
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) |
9647 |
++#endif |
9648 |
++ |
9649 |
+ /* requesting a specific address */ |
9650 |
+ if (addr) { |
9651 |
+ addr = PAGE_ALIGN(addr); |
9652 |
+@@ -213,13 +221,21 @@ bottomup: |
9653 |
+ * can happen with large stack limits and large mmap() |
9654 |
+ * allocations. |
9655 |
+ */ |
9656 |
++ mm->mmap_base = TASK_UNMAPPED_BASE; |
9657 |
++ |
9658 |
++#ifdef CONFIG_PAX_RANDMMAP |
9659 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
9660 |
++ mm->mmap_base += mm->delta_mmap; |
9661 |
++#endif |
9662 |
++ |
9663 |
++ mm->free_area_cache = mm->mmap_base; |
9664 |
+ mm->cached_hole_size = ~0UL; |
9665 |
+- mm->free_area_cache = TASK_UNMAPPED_BASE; |
9666 |
+ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); |
9667 |
+ /* |
9668 |
+ * Restore the topdown base: |
9669 |
+ */ |
9670 |
+- mm->free_area_cache = mm->mmap_base; |
9671 |
++ mm->mmap_base = base; |
9672 |
++ mm->free_area_cache = base; |
9673 |
+ mm->cached_hole_size = ~0UL; |
9674 |
+ |
9675 |
+ return addr; |
9676 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/time_32.c linux-2.6.28.8/arch/x86/kernel/time_32.c |
9677 |
+--- linux-2.6.28.8/arch/x86/kernel/time_32.c 2009-02-06 16:47:45.000000000 -0500 |
9678 |
++++ linux-2.6.28.8/arch/x86/kernel/time_32.c 2009-02-21 09:37:48.000000000 -0500 |
9679 |
+@@ -47,22 +47,32 @@ unsigned long profile_pc(struct pt_regs |
9680 |
+ unsigned long pc = instruction_pointer(regs); |
9681 |
+ |
9682 |
+ #ifdef CONFIG_SMP |
9683 |
+- if (!user_mode_vm(regs) && in_lock_functions(pc)) { |
9684 |
++ if (!user_mode(regs) && in_lock_functions(pc)) { |
9685 |
+ #ifdef CONFIG_FRAME_POINTER |
9686 |
+- return *(unsigned long *)(regs->bp + sizeof(long)); |
9687 |
++ return ktla_ktva(*(unsigned long *)(regs->bp + sizeof(long))); |
9688 |
+ #else |
9689 |
+ unsigned long *sp = (unsigned long *)®s->sp; |
9690 |
+ |
9691 |
+ /* Return address is either directly at stack pointer |
9692 |
+ or above a saved flags. Eflags has bits 22-31 zero, |
9693 |
+ kernel addresses don't. */ |
9694 |
++ |
9695 |
++#ifdef CONFIG_PAX_KERNEXEC |
9696 |
++ return ktla_ktva(sp[0]); |
9697 |
++#else |
9698 |
+ if (sp[0] >> 22) |
9699 |
+ return sp[0]; |
9700 |
+ if (sp[1] >> 22) |
9701 |
+ return sp[1]; |
9702 |
+ #endif |
9703 |
++ |
9704 |
++#endif |
9705 |
+ } |
9706 |
+ #endif |
9707 |
++ |
9708 |
++ if (!user_mode(regs)) |
9709 |
++ pc = ktla_ktva(pc); |
9710 |
++ |
9711 |
+ return pc; |
9712 |
+ } |
9713 |
+ EXPORT_SYMBOL(profile_pc); |
9714 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/time_64.c linux-2.6.28.8/arch/x86/kernel/time_64.c |
9715 |
+--- linux-2.6.28.8/arch/x86/kernel/time_64.c 2009-02-06 16:47:45.000000000 -0500 |
9716 |
++++ linux-2.6.28.8/arch/x86/kernel/time_64.c 2009-02-21 09:37:48.000000000 -0500 |
9717 |
+@@ -34,7 +34,7 @@ unsigned long profile_pc(struct pt_regs |
9718 |
+ /* Assume the lock function has either no stack frame or a copy |
9719 |
+ of flags from PUSHF |
9720 |
+ Eflags always has bits 22 and up cleared unlike kernel addresses. */ |
9721 |
+- if (!user_mode_vm(regs) && in_lock_functions(pc)) { |
9722 |
++ if (!user_mode(regs) && in_lock_functions(pc)) { |
9723 |
+ #ifdef CONFIG_FRAME_POINTER |
9724 |
+ return *(unsigned long *)(regs->bp + sizeof(long)); |
9725 |
+ #else |
9726 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/tlb_32.c linux-2.6.28.8/arch/x86/kernel/tlb_32.c |
9727 |
+--- linux-2.6.28.8/arch/x86/kernel/tlb_32.c 2009-02-06 16:47:45.000000000 -0500 |
9728 |
++++ linux-2.6.28.8/arch/x86/kernel/tlb_32.c 2009-02-21 09:37:48.000000000 -0500 |
9729 |
+@@ -5,7 +5,7 @@ |
9730 |
+ #include <asm/tlbflush.h> |
9731 |
+ |
9732 |
+ DEFINE_PER_CPU(struct tlb_state, cpu_tlbstate) |
9733 |
+- ____cacheline_aligned = { &init_mm, 0, }; |
9734 |
++ ____cacheline_aligned = { &init_mm, 0, {0} }; |
9735 |
+ |
9736 |
+ /* must come after the send_IPI functions above for inlining */ |
9737 |
+ #include <mach_ipi.h> |
9738 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/tls.c linux-2.6.28.8/arch/x86/kernel/tls.c |
9739 |
+--- linux-2.6.28.8/arch/x86/kernel/tls.c 2009-02-06 16:47:45.000000000 -0500 |
9740 |
++++ linux-2.6.28.8/arch/x86/kernel/tls.c 2009-02-21 09:37:48.000000000 -0500 |
9741 |
+@@ -85,6 +85,11 @@ int do_set_thread_area(struct task_struc |
9742 |
+ if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX) |
9743 |
+ return -EINVAL; |
9744 |
+ |
9745 |
++#ifdef CONFIG_PAX_SEGMEXEC |
9746 |
++ if ((p->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE)) |
9747 |
++ return -EINVAL; |
9748 |
++#endif |
9749 |
++ |
9750 |
+ set_tls_desc(p, idx, &info, 1); |
9751 |
+ |
9752 |
+ return 0; |
9753 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/traps.c linux-2.6.28.8/arch/x86/kernel/traps.c |
9754 |
+--- linux-2.6.28.8/arch/x86/kernel/traps.c 2009-03-07 10:24:49.000000000 -0500 |
9755 |
++++ linux-2.6.28.8/arch/x86/kernel/traps.c 2009-03-07 10:29:51.000000000 -0500 |
9756 |
+@@ -79,14 +79,6 @@ asmlinkage int system_call(void); |
9757 |
+ |
9758 |
+ /* Do we ignore FPU interrupts ? */ |
9759 |
+ char ignore_fpu_irq; |
9760 |
+- |
9761 |
+-/* |
9762 |
+- * The IDT has to be page-aligned to simplify the Pentium |
9763 |
+- * F0 0F bug workaround.. We have a special link segment |
9764 |
+- * for this. |
9765 |
+- */ |
9766 |
+-gate_desc idt_table[256] |
9767 |
+- __attribute__((__section__(".data.idt"))) = { { { { 0, 0 } } }, }; |
9768 |
+ #endif |
9769 |
+ |
9770 |
+ static int ignore_nmis; |
9771 |
+@@ -121,7 +113,7 @@ static inline void preempt_conditional_c |
9772 |
+ static inline void |
9773 |
+ die_if_kernel(const char *str, struct pt_regs *regs, long err) |
9774 |
+ { |
9775 |
+- if (!user_mode_vm(regs)) |
9776 |
++ if (!user_mode(regs)) |
9777 |
+ die(str, regs, err); |
9778 |
+ } |
9779 |
+ |
9780 |
+@@ -138,7 +130,7 @@ static int lazy_iobitmap_copy(void) |
9781 |
+ int cpu; |
9782 |
+ |
9783 |
+ cpu = get_cpu(); |
9784 |
+- tss = &per_cpu(init_tss, cpu); |
9785 |
++ tss = init_tss + cpu; |
9786 |
+ thread = ¤t->thread; |
9787 |
+ |
9788 |
+ if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY && |
9789 |
+@@ -174,7 +166,7 @@ do_trap(int trapnr, int signr, char *str |
9790 |
+ struct task_struct *tsk = current; |
9791 |
+ |
9792 |
+ #ifdef CONFIG_X86_32 |
9793 |
+- if (regs->flags & X86_VM_MASK) { |
9794 |
++ if (v8086_mode(regs)) { |
9795 |
+ /* |
9796 |
+ * traps 0, 1, 3, 4, and 5 should be forwarded to vm86. |
9797 |
+ * On nmi (interrupt 2), do_trap should not be called. |
9798 |
+@@ -185,7 +177,7 @@ do_trap(int trapnr, int signr, char *str |
9799 |
+ } |
9800 |
+ #endif |
9801 |
+ |
9802 |
+- if (!user_mode(regs)) |
9803 |
++ if (!user_mode_novm(regs)) |
9804 |
+ goto kernel_trap; |
9805 |
+ |
9806 |
+ #ifdef CONFIG_X86_32 |
9807 |
+@@ -227,6 +219,12 @@ kernel_trap: |
9808 |
+ tsk->thread.trap_no = trapnr; |
9809 |
+ die(str, regs, error_code); |
9810 |
+ } |
9811 |
++ |
9812 |
++#ifdef CONFIG_PAX_REFCOUNT |
9813 |
++ if (trapnr == 4) |
9814 |
++ pax_report_refcount_overflow(regs); |
9815 |
++#endif |
9816 |
++ |
9817 |
+ return; |
9818 |
+ |
9819 |
+ #ifdef CONFIG_X86_32 |
9820 |
+@@ -318,14 +316,30 @@ do_general_protection(struct pt_regs *re |
9821 |
+ return; |
9822 |
+ } |
9823 |
+ |
9824 |
+- if (regs->flags & X86_VM_MASK) |
9825 |
++ if (v8086_mode(regs)) |
9826 |
+ goto gp_in_vm86; |
9827 |
+ #endif |
9828 |
+ |
9829 |
+ tsk = current; |
9830 |
+- if (!user_mode(regs)) |
9831 |
++ if (!user_mode_novm(regs)) |
9832 |
+ goto gp_in_kernel; |
9833 |
+ |
9834 |
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC) |
9835 |
++ if (!nx_enabled && tsk->mm && (tsk->mm->pax_flags & MF_PAX_PAGEEXEC)) { |
9836 |
++ struct mm_struct *mm = tsk->mm; |
9837 |
++ unsigned long limit; |
9838 |
++ |
9839 |
++ down_write(&mm->mmap_sem); |
9840 |
++ limit = mm->context.user_cs_limit; |
9841 |
++ if (limit < TASK_SIZE) { |
9842 |
++ track_exec_limit(mm, limit, TASK_SIZE, VM_EXEC); |
9843 |
++ up_write(&mm->mmap_sem); |
9844 |
++ return; |
9845 |
++ } |
9846 |
++ up_write(&mm->mmap_sem); |
9847 |
++ } |
9848 |
++#endif |
9849 |
++ |
9850 |
+ tsk->thread.error_code = error_code; |
9851 |
+ tsk->thread.trap_no = 13; |
9852 |
+ |
9853 |
+@@ -358,6 +372,13 @@ gp_in_kernel: |
9854 |
+ if (notify_die(DIE_GPF, "general protection fault", regs, |
9855 |
+ error_code, 13, SIGSEGV) == NOTIFY_STOP) |
9856 |
+ return; |
9857 |
++ |
9858 |
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) |
9859 |
++ if ((regs->cs & 0xFFFF) == __KERNEL_CS) |
9860 |
++ die("PAX: suspicious general protection fault", regs, error_code); |
9861 |
++ else |
9862 |
++#endif |
9863 |
++ |
9864 |
+ die("general protection fault", regs, error_code); |
9865 |
+ } |
9866 |
+ |
9867 |
+@@ -604,7 +625,7 @@ dotraplinkage void __kprobes do_debug(st |
9868 |
+ } |
9869 |
+ |
9870 |
+ #ifdef CONFIG_X86_32 |
9871 |
+- if (regs->flags & X86_VM_MASK) |
9872 |
++ if (v8086_mode(regs)) |
9873 |
+ goto debug_vm86; |
9874 |
+ #endif |
9875 |
+ |
9876 |
+@@ -616,7 +637,7 @@ dotraplinkage void __kprobes do_debug(st |
9877 |
+ * kernel space (but re-enable TF when returning to user mode). |
9878 |
+ */ |
9879 |
+ if (condition & DR_STEP) { |
9880 |
+- if (!user_mode(regs)) |
9881 |
++ if (!user_mode_novm(regs)) |
9882 |
+ goto clear_TF_reenable; |
9883 |
+ } |
9884 |
+ |
9885 |
+@@ -808,7 +829,7 @@ do_simd_coprocessor_error(struct pt_regs |
9886 |
+ * Handle strange cache flush from user space exception |
9887 |
+ * in all other cases. This is undocumented behaviour. |
9888 |
+ */ |
9889 |
+- if (regs->flags & X86_VM_MASK) { |
9890 |
++ if (v8086_mode(regs)) { |
9891 |
+ handle_vm86_fault((struct kernel_vm86_regs *)regs, error_code); |
9892 |
+ return; |
9893 |
+ } |
9894 |
+@@ -837,19 +858,14 @@ do_spurious_interrupt_bug(struct pt_regs |
9895 |
+ #ifdef CONFIG_X86_32 |
9896 |
+ unsigned long patch_espfix_desc(unsigned long uesp, unsigned long kesp) |
9897 |
+ { |
9898 |
+- struct desc_struct *gdt = get_cpu_gdt_table(smp_processor_id()); |
9899 |
+ unsigned long base = (kesp - uesp) & -THREAD_SIZE; |
9900 |
+ unsigned long new_kesp = kesp - base; |
9901 |
+ unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT; |
9902 |
+- __u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS]; |
9903 |
++ struct desc_struct ss; |
9904 |
+ |
9905 |
+ /* Set up base for espfix segment */ |
9906 |
+- desc &= 0x00f0ff0000000000ULL; |
9907 |
+- desc |= ((((__u64)base) << 16) & 0x000000ffffff0000ULL) | |
9908 |
+- ((((__u64)base) << 32) & 0xff00000000000000ULL) | |
9909 |
+- ((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) | |
9910 |
+- (lim_pages & 0xffff); |
9911 |
+- *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc; |
9912 |
++ pack_descriptor(&ss, base, lim_pages, 0x93, 0xC); |
9913 |
++ write_gdt_entry(get_cpu_gdt_table(smp_processor_id()), GDT_ENTRY_ESPFIX_SS, &ss, DESCTYPE_S); |
9914 |
+ |
9915 |
+ return new_kesp; |
9916 |
+ } |
9917 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/tsc.c linux-2.6.28.8/arch/x86/kernel/tsc.c |
9918 |
+--- linux-2.6.28.8/arch/x86/kernel/tsc.c 2009-02-06 16:47:45.000000000 -0500 |
9919 |
++++ linux-2.6.28.8/arch/x86/kernel/tsc.c 2009-02-21 09:37:48.000000000 -0500 |
9920 |
+@@ -728,7 +728,7 @@ static struct dmi_system_id __initdata b |
9921 |
+ DMI_MATCH(DMI_BOARD_NAME, "2635FA0"), |
9922 |
+ }, |
9923 |
+ }, |
9924 |
+- {} |
9925 |
++ { NULL, NULL, {{0, {0}}}, NULL} |
9926 |
+ }; |
9927 |
+ |
9928 |
+ /* |
9929 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/vm86_32.c linux-2.6.28.8/arch/x86/kernel/vm86_32.c |
9930 |
+--- linux-2.6.28.8/arch/x86/kernel/vm86_32.c 2009-02-06 16:47:45.000000000 -0500 |
9931 |
++++ linux-2.6.28.8/arch/x86/kernel/vm86_32.c 2009-02-21 09:37:48.000000000 -0500 |
9932 |
+@@ -148,7 +148,7 @@ struct pt_regs *save_v86_state(struct ke |
9933 |
+ do_exit(SIGSEGV); |
9934 |
+ } |
9935 |
+ |
9936 |
+- tss = &per_cpu(init_tss, get_cpu()); |
9937 |
++ tss = init_tss + get_cpu(); |
9938 |
+ current->thread.sp0 = current->thread.saved_sp0; |
9939 |
+ current->thread.sysenter_cs = __KERNEL_CS; |
9940 |
+ load_sp0(tss, ¤t->thread); |
9941 |
+@@ -325,7 +325,7 @@ static void do_sys_vm86(struct kernel_vm |
9942 |
+ tsk->thread.saved_fs = info->regs32->fs; |
9943 |
+ savesegment(gs, tsk->thread.saved_gs); |
9944 |
+ |
9945 |
+- tss = &per_cpu(init_tss, get_cpu()); |
9946 |
++ tss = init_tss + get_cpu(); |
9947 |
+ tsk->thread.sp0 = (unsigned long) &info->VM86_TSS_ESP0; |
9948 |
+ if (cpu_has_sep) |
9949 |
+ tsk->thread.sysenter_cs = 0; |
9950 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/vmi_32.c linux-2.6.28.8/arch/x86/kernel/vmi_32.c |
9951 |
+--- linux-2.6.28.8/arch/x86/kernel/vmi_32.c 2009-02-08 00:54:27.000000000 -0500 |
9952 |
++++ linux-2.6.28.8/arch/x86/kernel/vmi_32.c 2009-02-21 09:37:48.000000000 -0500 |
9953 |
+@@ -102,18 +102,43 @@ static unsigned patch_internal(int call, |
9954 |
+ { |
9955 |
+ u64 reloc; |
9956 |
+ struct vmi_relocation_info *const rel = (struct vmi_relocation_info *)&reloc; |
9957 |
++ |
9958 |
++#ifdef CONFIG_PAX_KERNEXEC |
9959 |
++ unsigned long cr0; |
9960 |
++#endif |
9961 |
++ |
9962 |
+ reloc = call_vrom_long_func(vmi_rom, get_reloc, call); |
9963 |
+ switch(rel->type) { |
9964 |
+ case VMI_RELOCATION_CALL_REL: |
9965 |
+ BUG_ON(len < 5); |
9966 |
++ |
9967 |
++#ifdef CONFIG_PAX_KERNEXEC |
9968 |
++ pax_open_kernel(cr0); |
9969 |
++#endif |
9970 |
++ |
9971 |
+ *(char *)insnbuf = MNEM_CALL; |
9972 |
+ patch_offset(insnbuf, ip, (unsigned long)rel->eip); |
9973 |
++ |
9974 |
++#ifdef CONFIG_PAX_KERNEXEC |
9975 |
++ pax_close_kernel(cr0); |
9976 |
++#endif |
9977 |
++ |
9978 |
+ return 5; |
9979 |
+ |
9980 |
+ case VMI_RELOCATION_JUMP_REL: |
9981 |
+ BUG_ON(len < 5); |
9982 |
++ |
9983 |
++#ifdef CONFIG_PAX_KERNEXEC |
9984 |
++ pax_open_kernel(cr0); |
9985 |
++#endif |
9986 |
++ |
9987 |
+ *(char *)insnbuf = MNEM_JMP; |
9988 |
+ patch_offset(insnbuf, ip, (unsigned long)rel->eip); |
9989 |
++ |
9990 |
++#ifdef CONFIG_PAX_KERNEXEC |
9991 |
++ pax_close_kernel(cr0); |
9992 |
++#endif |
9993 |
++ |
9994 |
+ return 5; |
9995 |
+ |
9996 |
+ case VMI_RELOCATION_NOP: |
9997 |
+@@ -526,14 +551,14 @@ static void vmi_set_pud(pud_t *pudp, pud |
9998 |
+ |
9999 |
+ static void vmi_pte_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) |
10000 |
+ { |
10001 |
+- const pte_t pte = { .pte = 0 }; |
10002 |
++ const pte_t pte = __pte(0ULL); |
10003 |
+ vmi_check_page_type(__pa(ptep) >> PAGE_SHIFT, VMI_PAGE_PTE); |
10004 |
+ vmi_ops.set_pte(pte, ptep, vmi_flags_addr(mm, addr, VMI_PAGE_PT, 0)); |
10005 |
+ } |
10006 |
+ |
10007 |
+ static void vmi_pmd_clear(pmd_t *pmd) |
10008 |
+ { |
10009 |
+- const pte_t pte = { .pte = 0 }; |
10010 |
++ const pte_t pte = __pte(0ULL); |
10011 |
+ vmi_check_page_type(__pa(pmd) >> PAGE_SHIFT, VMI_PAGE_PMD); |
10012 |
+ vmi_ops.set_pte(pte, (pte_t *)pmd, VMI_PAGE_PD); |
10013 |
+ } |
10014 |
+@@ -562,8 +587,8 @@ vmi_startup_ipi_hook(int phys_apicid, un |
10015 |
+ ap.ss = __KERNEL_DS; |
10016 |
+ ap.esp = (unsigned long) start_esp; |
10017 |
+ |
10018 |
+- ap.ds = __USER_DS; |
10019 |
+- ap.es = __USER_DS; |
10020 |
++ ap.ds = __KERNEL_DS; |
10021 |
++ ap.es = __KERNEL_DS; |
10022 |
+ ap.fs = __KERNEL_PERCPU; |
10023 |
+ ap.gs = 0; |
10024 |
+ |
10025 |
+@@ -758,12 +783,20 @@ static inline int __init activate_vmi(vo |
10026 |
+ u64 reloc; |
10027 |
+ const struct vmi_relocation_info *rel = (struct vmi_relocation_info *)&reloc; |
10028 |
+ |
10029 |
++#ifdef CONFIG_PAX_KERNEXEC |
10030 |
++ unsigned long cr0; |
10031 |
++#endif |
10032 |
++ |
10033 |
+ if (call_vrom_func(vmi_rom, vmi_init) != 0) { |
10034 |
+ printk(KERN_ERR "VMI ROM failed to initialize!"); |
10035 |
+ return 0; |
10036 |
+ } |
10037 |
+ savesegment(cs, kernel_cs); |
10038 |
+ |
10039 |
++#ifdef CONFIG_PAX_KERNEXEC |
10040 |
++ pax_open_kernel(cr0); |
10041 |
++#endif |
10042 |
++ |
10043 |
+ pv_info.paravirt_enabled = 1; |
10044 |
+ pv_info.kernel_rpl = kernel_cs & SEGMENT_RPL_MASK; |
10045 |
+ pv_info.name = "vmi"; |
10046 |
+@@ -954,6 +987,10 @@ static inline int __init activate_vmi(vo |
10047 |
+ |
10048 |
+ para_fill(pv_irq_ops.safe_halt, Halt); |
10049 |
+ |
10050 |
++#ifdef CONFIG_PAX_KERNEXEC |
10051 |
++ pax_close_kernel(cr0); |
10052 |
++#endif |
10053 |
++ |
10054 |
+ /* |
10055 |
+ * Alternative instruction rewriting doesn't happen soon enough |
10056 |
+ * to convert VMI_IRET to a call instead of a jump; so we have |
10057 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S |
10058 |
+--- linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S 2009-02-06 16:47:45.000000000 -0500 |
10059 |
++++ linux-2.6.28.8/arch/x86/kernel/vmlinux_32.lds.S 2009-03-07 10:35:39.000000000 -0500 |
10060 |
+@@ -15,6 +15,20 @@ |
10061 |
+ #include <asm/page.h> |
10062 |
+ #include <asm/cache.h> |
10063 |
+ #include <asm/boot.h> |
10064 |
++#include <asm/segment.h> |
10065 |
++ |
10066 |
++#ifdef CONFIG_X86_PAE |
10067 |
++#define PMD_SHIFT 21 |
10068 |
++#else |
10069 |
++#define PMD_SHIFT 22 |
10070 |
++#endif |
10071 |
++#define PMD_SIZE (1 << PMD_SHIFT) |
10072 |
++ |
10073 |
++#ifdef CONFIG_PAX_KERNEXEC |
10074 |
++#define __KERNEL_TEXT_OFFSET (__PAGE_OFFSET + (((____LOAD_PHYSICAL_ADDR + 2*(PMD_SIZE - 1)) - 1) & ~(PMD_SIZE - 1))) |
10075 |
++#else |
10076 |
++#define __KERNEL_TEXT_OFFSET 0 |
10077 |
++#endif |
10078 |
+ |
10079 |
+ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") |
10080 |
+ OUTPUT_ARCH(i386) |
10081 |
+@@ -22,81 +36,23 @@ ENTRY(phys_startup_32) |
10082 |
+ jiffies = jiffies_64; |
10083 |
+ |
10084 |
+ PHDRS { |
10085 |
+- text PT_LOAD FLAGS(5); /* R_E */ |
10086 |
+- data PT_LOAD FLAGS(7); /* RWE */ |
10087 |
+- note PT_NOTE FLAGS(0); /* ___ */ |
10088 |
++ initdata PT_LOAD FLAGS(6); /* RW_ */ |
10089 |
++ percpu PT_LOAD FLAGS(6); /* RW_ */ |
10090 |
++ inittext PT_LOAD FLAGS(5); /* R_E */ |
10091 |
++ text PT_LOAD FLAGS(5); /* R_E */ |
10092 |
++ rodata PT_LOAD FLAGS(4); /* R__ */ |
10093 |
++ data PT_LOAD FLAGS(6); /* RW_ */ |
10094 |
++ note PT_NOTE FLAGS(0); /* ___ */ |
10095 |
+ } |
10096 |
+ SECTIONS |
10097 |
+ { |
10098 |
+- . = LOAD_OFFSET + LOAD_PHYSICAL_ADDR; |
10099 |
+- phys_startup_32 = startup_32 - LOAD_OFFSET; |
10100 |
+- |
10101 |
+- .text.head : AT(ADDR(.text.head) - LOAD_OFFSET) { |
10102 |
+- _text = .; /* Text and read-only data */ |
10103 |
+- *(.text.head) |
10104 |
+- } :text = 0x9090 |
10105 |
+- |
10106 |
+- /* read-only */ |
10107 |
+- .text : AT(ADDR(.text) - LOAD_OFFSET) { |
10108 |
+- . = ALIGN(PAGE_SIZE); /* not really needed, already page aligned */ |
10109 |
+- *(.text.page_aligned) |
10110 |
+- TEXT_TEXT |
10111 |
+- SCHED_TEXT |
10112 |
+- LOCK_TEXT |
10113 |
+- KPROBES_TEXT |
10114 |
+- *(.fixup) |
10115 |
+- *(.gnu.warning) |
10116 |
+- _etext = .; /* End of text section */ |
10117 |
+- } :text = 0x9090 |
10118 |
+- |
10119 |
+- NOTES :text :note |
10120 |
+- |
10121 |
+- . = ALIGN(16); /* Exception table */ |
10122 |
+- __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { |
10123 |
+- __start___ex_table = .; |
10124 |
+- *(__ex_table) |
10125 |
+- __stop___ex_table = .; |
10126 |
+- } :text = 0x9090 |
10127 |
+- |
10128 |
+- RODATA |
10129 |
+- |
10130 |
+- /* writeable */ |
10131 |
+- . = ALIGN(PAGE_SIZE); |
10132 |
+- .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ |
10133 |
+- DATA_DATA |
10134 |
+- CONSTRUCTORS |
10135 |
+- } :data |
10136 |
+- |
10137 |
+- . = ALIGN(PAGE_SIZE); |
10138 |
+- .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { |
10139 |
+- __nosave_begin = .; |
10140 |
+- *(.data.nosave) |
10141 |
+- . = ALIGN(PAGE_SIZE); |
10142 |
+- __nosave_end = .; |
10143 |
+- } |
10144 |
++ . = LOAD_OFFSET + ____LOAD_PHYSICAL_ADDR; |
10145 |
+ |
10146 |
+- . = ALIGN(PAGE_SIZE); |
10147 |
+- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { |
10148 |
+- *(.data.page_aligned) |
10149 |
+- *(.data.idt) |
10150 |
+- } |
10151 |
+- |
10152 |
+- . = ALIGN(32); |
10153 |
+- .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { |
10154 |
+- *(.data.cacheline_aligned) |
10155 |
+- } |
10156 |
+- |
10157 |
+- /* rarely changed data like cpu maps */ |
10158 |
+- . = ALIGN(32); |
10159 |
+- .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { |
10160 |
+- *(.data.read_mostly) |
10161 |
+- _edata = .; /* End of data section */ |
10162 |
+- } |
10163 |
+- |
10164 |
+- . = ALIGN(THREAD_SIZE); /* init_task */ |
10165 |
+- .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { |
10166 |
+- *(.data.init_task) |
10167 |
+- } |
10168 |
++ .text.startup : AT(ADDR(.text.startup) - LOAD_OFFSET) { |
10169 |
++ __LOAD_PHYSICAL_ADDR = . - LOAD_OFFSET; |
10170 |
++ phys_startup_32 = startup_32 - LOAD_OFFSET + __KERNEL_TEXT_OFFSET; |
10171 |
++ *(.text.startup) |
10172 |
++ } :initdata |
10173 |
+ |
10174 |
+ /* might get freed after init */ |
10175 |
+ . = ALIGN(PAGE_SIZE); |
10176 |
+@@ -114,14 +70,8 @@ SECTIONS |
10177 |
+ . = ALIGN(PAGE_SIZE); |
10178 |
+ |
10179 |
+ /* will be freed after init */ |
10180 |
+- . = ALIGN(PAGE_SIZE); /* Init code and data */ |
10181 |
+- .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { |
10182 |
+- __init_begin = .; |
10183 |
+- _sinittext = .; |
10184 |
+- INIT_TEXT |
10185 |
+- _einittext = .; |
10186 |
+- } |
10187 |
+ .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { |
10188 |
++ __init_begin = .; |
10189 |
+ INIT_DATA |
10190 |
+ } |
10191 |
+ . = ALIGN(16); |
10192 |
+@@ -161,11 +111,6 @@ SECTIONS |
10193 |
+ *(.parainstructions) |
10194 |
+ __parainstructions_end = .; |
10195 |
+ } |
10196 |
+- /* .exit.text is discard at runtime, not link time, to deal with references |
10197 |
+- from .altinstructions and .eh_frame */ |
10198 |
+- .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { |
10199 |
+- EXIT_TEXT |
10200 |
+- } |
10201 |
+ .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { |
10202 |
+ EXIT_DATA |
10203 |
+ } |
10204 |
+@@ -178,18 +123,138 @@ SECTIONS |
10205 |
+ } |
10206 |
+ #endif |
10207 |
+ . = ALIGN(PAGE_SIZE); |
10208 |
+- .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { |
10209 |
+- __per_cpu_start = .; |
10210 |
+- *(.data.percpu.page_aligned) |
10211 |
++ per_cpu_start = .; |
10212 |
++ .data.percpu (0) : AT(ADDR(.data.percpu) - LOAD_OFFSET + per_cpu_start) { |
10213 |
++ __per_cpu_start = . + per_cpu_start; |
10214 |
++ LONG(0) |
10215 |
+ *(.data.percpu) |
10216 |
+ *(.data.percpu.shared_aligned) |
10217 |
+- __per_cpu_end = .; |
10218 |
+- } |
10219 |
++ . = ALIGN(PAGE_SIZE); |
10220 |
++ *(.data.percpu.page_aligned) |
10221 |
++ __per_cpu_end = . + per_cpu_start; |
10222 |
++ } :percpu |
10223 |
++ . += per_cpu_start; |
10224 |
+ . = ALIGN(PAGE_SIZE); |
10225 |
+ /* freed after init ends here */ |
10226 |
+ |
10227 |
++ . = ALIGN(PAGE_SIZE); /* Init code and data */ |
10228 |
++ .init.text (. - __KERNEL_TEXT_OFFSET) : AT(ADDR(.init.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { |
10229 |
++ _sinittext = .; |
10230 |
++ INIT_TEXT |
10231 |
++ _einittext = .; |
10232 |
++ } :inittext |
10233 |
++ |
10234 |
++ /* .exit.text is discard at runtime, not link time, to deal with references |
10235 |
++ from .altinstructions and .eh_frame */ |
10236 |
++ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { |
10237 |
++ EXIT_TEXT |
10238 |
++ } |
10239 |
++ |
10240 |
++ .filler : AT(ADDR(.filler) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { |
10241 |
++ BYTE(0) |
10242 |
++ . = ALIGN(2*PMD_SIZE) - 1; |
10243 |
++ } |
10244 |
++ |
10245 |
++ /* freed after init ends here */ |
10246 |
++ |
10247 |
++ .text.head : AT(ADDR(.text.head) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { |
10248 |
++ __init_end = . + __KERNEL_TEXT_OFFSET; |
10249 |
++ KERNEL_TEXT_OFFSET = . + __KERNEL_TEXT_OFFSET; |
10250 |
++ _text = .; /* Text and read-only data */ |
10251 |
++ *(.text.head) |
10252 |
++ } :text = 0x9090 |
10253 |
++ |
10254 |
++ /* read-only */ |
10255 |
++ .text : AT(ADDR(.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { |
10256 |
++ . = ALIGN(PAGE_SIZE); /* not really needed, already page aligned */ |
10257 |
++ *(.text.page_aligned) |
10258 |
++ TEXT_TEXT |
10259 |
++ SCHED_TEXT |
10260 |
++ LOCK_TEXT |
10261 |
++ KPROBES_TEXT |
10262 |
++ *(.fixup) |
10263 |
++ *(.gnu.warning) |
10264 |
++ _etext = .; /* End of text section */ |
10265 |
++ } :text = 0x9090 |
10266 |
++ |
10267 |
++ . += __KERNEL_TEXT_OFFSET; |
10268 |
++ |
10269 |
++ . = ALIGN(4096); |
10270 |
++ NOTES :rodata :note |
10271 |
++ |
10272 |
++ . = ALIGN(16); /* Exception table */ |
10273 |
++ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { |
10274 |
++ __start___ex_table = .; |
10275 |
++ *(__ex_table) |
10276 |
++ __stop___ex_table = .; |
10277 |
++ } :rodata |
10278 |
++ |
10279 |
++ RO_DATA(PAGE_SIZE) |
10280 |
++ |
10281 |
++ . = ALIGN(PAGE_SIZE); |
10282 |
++ .rodata.page_aligned : AT(ADDR(.rodata.page_aligned) - LOAD_OFFSET) { |
10283 |
++ *(.idt) |
10284 |
++ . = ALIGN(PAGE_SIZE); |
10285 |
++ *(.empty_zero_page) |
10286 |
++ *(.swapper_pg_pmd) |
10287 |
++ *(.swapper_pg_dir) |
10288 |
++ |
10289 |
++#if defined(CONFIG_PAX_KERNEXEC) && !defined(CONFIG_MODULES) |
10290 |
++ . = ALIGN(PMD_SIZE); |
10291 |
++#endif |
10292 |
++ |
10293 |
++ } |
10294 |
++ |
10295 |
++#if defined(CONFIG_PAX_KERNEXEC) && defined(CONFIG_MODULES) |
10296 |
++ . = ALIGN(PAGE_SIZE); |
10297 |
++ .module.text : AT(ADDR(.module.text) - LOAD_OFFSET) { |
10298 |
++ MODULES_VADDR = .; |
10299 |
++ BYTE(0) |
10300 |
++ . += (6 * 1024 * 1024); |
10301 |
++ . = ALIGN(PMD_SIZE); |
10302 |
++ MODULES_END = . - 1; |
10303 |
++ } |
10304 |
++#endif |
10305 |
++ |
10306 |
++ /* writeable */ |
10307 |
++ . = ALIGN(PAGE_SIZE); |
10308 |
++ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ |
10309 |
++ _data = .; |
10310 |
++ DATA_DATA |
10311 |
++ CONSTRUCTORS |
10312 |
++ } :data |
10313 |
++ |
10314 |
++ . = ALIGN(PAGE_SIZE); |
10315 |
++ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { |
10316 |
++ __nosave_begin = .; |
10317 |
++ *(.data.nosave) |
10318 |
++ . = ALIGN(PAGE_SIZE); |
10319 |
++ __nosave_end = .; |
10320 |
++ } |
10321 |
++ |
10322 |
++ . = ALIGN(PAGE_SIZE); |
10323 |
++ .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { |
10324 |
++ *(.data.page_aligned) |
10325 |
++ } |
10326 |
++ |
10327 |
++ . = ALIGN(32); |
10328 |
++ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { |
10329 |
++ *(.data.cacheline_aligned) |
10330 |
++ } |
10331 |
++ |
10332 |
++ /* rarely changed data like cpu maps */ |
10333 |
++ . = ALIGN(32); |
10334 |
++ .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { |
10335 |
++ *(.data.read_mostly) |
10336 |
++ _edata = .; /* End of data section */ |
10337 |
++ } |
10338 |
++ |
10339 |
++ . = ALIGN(THREAD_SIZE); /* init_task */ |
10340 |
++ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { |
10341 |
++ *(.data.init_task) |
10342 |
++ } |
10343 |
++ |
10344 |
+ .bss : AT(ADDR(.bss) - LOAD_OFFSET) { |
10345 |
+- __init_end = .; |
10346 |
+ __bss_start = .; /* BSS */ |
10347 |
+ *(.bss.page_aligned) |
10348 |
+ *(.bss) |
10349 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S |
10350 |
+--- linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S 2009-02-06 16:47:45.000000000 -0500 |
10351 |
++++ linux-2.6.28.8/arch/x86/kernel/vmlinux_64.lds.S 2009-02-21 09:37:48.000000000 -0500 |
10352 |
+@@ -16,7 +16,7 @@ jiffies_64 = jiffies; |
10353 |
+ _proxy_pda = 1; |
10354 |
+ PHDRS { |
10355 |
+ text PT_LOAD FLAGS(5); /* R_E */ |
10356 |
+- data PT_LOAD FLAGS(7); /* RWE */ |
10357 |
++ data PT_LOAD FLAGS(6); /* RW_ */ |
10358 |
+ user PT_LOAD FLAGS(7); /* RWE */ |
10359 |
+ data.init PT_LOAD FLAGS(7); /* RWE */ |
10360 |
+ note PT_NOTE FLAGS(0); /* ___ */ |
10361 |
+@@ -49,17 +49,20 @@ SECTIONS |
10362 |
+ __stop___ex_table = .; |
10363 |
+ } :text = 0x9090 |
10364 |
+ |
10365 |
+- RODATA |
10366 |
++ RO_DATA(PAGE_SIZE) |
10367 |
+ |
10368 |
++#ifdef CONFIG_PAX_KERNEXEC |
10369 |
++ . = ALIGN(2*1024*1024); /* Align data segment to PMD size boundary */ |
10370 |
++#else |
10371 |
+ . = ALIGN(PAGE_SIZE); /* Align data segment to page size boundary */ |
10372 |
++#endif |
10373 |
+ /* Data */ |
10374 |
++ _data = .; |
10375 |
+ .data : AT(ADDR(.data) - LOAD_OFFSET) { |
10376 |
+ DATA_DATA |
10377 |
+ CONSTRUCTORS |
10378 |
+ } :data |
10379 |
+ |
10380 |
+- _edata = .; /* End of data section */ |
10381 |
+- |
10382 |
+ . = ALIGN(PAGE_SIZE); |
10383 |
+ . = ALIGN(CONFIG_X86_L1_CACHE_BYTES); |
10384 |
+ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) { |
10385 |
+@@ -70,9 +73,27 @@ SECTIONS |
10386 |
+ *(.data.read_mostly) |
10387 |
+ } |
10388 |
+ |
10389 |
++ . = ALIGN(THREAD_SIZE); /* init_task */ |
10390 |
++ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { |
10391 |
++ *(.data.init_task) |
10392 |
++ } |
10393 |
++ |
10394 |
++ . = ALIGN(PAGE_SIZE); |
10395 |
++ .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { |
10396 |
++ *(.data.page_aligned) |
10397 |
++ } |
10398 |
++ |
10399 |
++ . = ALIGN(PAGE_SIZE); |
10400 |
++ __nosave_begin = .; |
10401 |
++ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) } |
10402 |
++ . = ALIGN(PAGE_SIZE); |
10403 |
++ __nosave_end = .; |
10404 |
++ |
10405 |
++ _edata = .; /* End of data section */ |
10406 |
++ |
10407 |
+ #define VSYSCALL_ADDR (-10*1024*1024) |
10408 |
+-#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data.read_mostly) + SIZEOF(.data.read_mostly) + 4095) & ~(4095)) |
10409 |
+-#define VSYSCALL_VIRT_ADDR ((ADDR(.data.read_mostly) + SIZEOF(.data.read_mostly) + 4095) & ~(4095)) |
10410 |
++#define VSYSCALL_PHYS_ADDR ((LOADADDR(.data_nosave) + SIZEOF(.data_nosave) + 4095) & ~(4095)) |
10411 |
++#define VSYSCALL_VIRT_ADDR ((ADDR(.data_nosave) + SIZEOF(.data_nosave) + 4095) & ~(4095)) |
10412 |
+ |
10413 |
+ #define VLOAD_OFFSET (VSYSCALL_ADDR - VSYSCALL_PHYS_ADDR) |
10414 |
+ #define VLOAD(x) (ADDR(x) - VLOAD_OFFSET) |
10415 |
+@@ -120,23 +141,13 @@ SECTIONS |
10416 |
+ #undef VVIRT_OFFSET |
10417 |
+ #undef VVIRT |
10418 |
+ |
10419 |
+- . = ALIGN(THREAD_SIZE); /* init_task */ |
10420 |
+- .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) { |
10421 |
+- *(.data.init_task) |
10422 |
+- }:data.init |
10423 |
+- |
10424 |
+- . = ALIGN(PAGE_SIZE); |
10425 |
+- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) { |
10426 |
+- *(.data.page_aligned) |
10427 |
+- } |
10428 |
+- |
10429 |
+ /* might get freed after init */ |
10430 |
+ . = ALIGN(PAGE_SIZE); |
10431 |
+ __smp_alt_begin = .; |
10432 |
+ __smp_locks = .; |
10433 |
+ .smp_locks : AT(ADDR(.smp_locks) - LOAD_OFFSET) { |
10434 |
+ *(.smp_locks) |
10435 |
+- } |
10436 |
++ } :data.init |
10437 |
+ __smp_locks_end = .; |
10438 |
+ . = ALIGN(PAGE_SIZE); |
10439 |
+ __smp_alt_end = .; |
10440 |
+@@ -212,16 +223,11 @@ SECTIONS |
10441 |
+ . = ALIGN(PAGE_SIZE); |
10442 |
+ __init_end = .; |
10443 |
+ |
10444 |
+- . = ALIGN(PAGE_SIZE); |
10445 |
+- __nosave_begin = .; |
10446 |
+- .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) } |
10447 |
+- . = ALIGN(PAGE_SIZE); |
10448 |
+- __nosave_end = .; |
10449 |
+- |
10450 |
+ __bss_start = .; /* BSS */ |
10451 |
+ .bss : AT(ADDR(.bss) - LOAD_OFFSET) { |
10452 |
+ *(.bss.page_aligned) |
10453 |
+ *(.bss) |
10454 |
++ . = ALIGN(2*1024*1024); |
10455 |
+ } |
10456 |
+ __bss_stop = .; |
10457 |
+ |
10458 |
+diff -urNp linux-2.6.28.8/arch/x86/kernel/vsyscall_64.c linux-2.6.28.8/arch/x86/kernel/vsyscall_64.c |
10459 |
+--- linux-2.6.28.8/arch/x86/kernel/vsyscall_64.c 2009-02-06 16:47:45.000000000 -0500 |
10460 |
++++ linux-2.6.28.8/arch/x86/kernel/vsyscall_64.c 2009-02-21 09:37:48.000000000 -0500 |
10461 |
+@@ -236,13 +236,13 @@ static ctl_table kernel_table2[] = { |
10462 |
+ .data = &vsyscall_gtod_data.sysctl_enabled, .maxlen = sizeof(int), |
10463 |
+ .mode = 0644, |
10464 |
+ .proc_handler = vsyscall_sysctl_change }, |
10465 |
+- {} |
10466 |
++ { 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } |
10467 |
+ }; |
10468 |
+ |
10469 |
+ static ctl_table kernel_root_table2[] = { |
10470 |
+ { .ctl_name = CTL_KERN, .procname = "kernel", .mode = 0555, |
10471 |
+ .child = kernel_table2 }, |
10472 |
+- {} |
10473 |
++ { 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } |
10474 |
+ }; |
10475 |
+ #endif |
10476 |
+ |
10477 |
+diff -urNp linux-2.6.28.8/arch/x86/kvm/svm.c linux-2.6.28.8/arch/x86/kvm/svm.c |
10478 |
+--- linux-2.6.28.8/arch/x86/kvm/svm.c 2009-02-06 16:47:45.000000000 -0500 |
10479 |
++++ linux-2.6.28.8/arch/x86/kvm/svm.c 2009-02-21 09:37:48.000000000 -0500 |
10480 |
+@@ -1505,7 +1505,19 @@ static void reload_tss(struct kvm_vcpu * |
10481 |
+ int cpu = raw_smp_processor_id(); |
10482 |
+ |
10483 |
+ struct svm_cpu_data *svm_data = per_cpu(svm_data, cpu); |
10484 |
++ |
10485 |
++#ifdef CONFIG_PAX_KERNEXEC |
10486 |
++ unsigned long cr0; |
10487 |
++ |
10488 |
++ pax_open_kernel(cr0); |
10489 |
++#endif |
10490 |
++ |
10491 |
+ svm_data->tss_desc->type = 9; /* available 32/64-bit TSS */ |
10492 |
++ |
10493 |
++#ifdef CONFIG_PAX_KERNEXEC |
10494 |
++ pax_close_kernel(cr0); |
10495 |
++#endif |
10496 |
++ |
10497 |
+ load_TR_desc(); |
10498 |
+ } |
10499 |
+ |
10500 |
+@@ -1912,7 +1924,7 @@ static int get_npt_level(void) |
10501 |
+ #endif |
10502 |
+ } |
10503 |
+ |
10504 |
+-static struct kvm_x86_ops svm_x86_ops = { |
10505 |
++static const struct kvm_x86_ops svm_x86_ops = { |
10506 |
+ .cpu_has_kvm_support = has_svm, |
10507 |
+ .disabled_by_bios = is_disabled, |
10508 |
+ .hardware_setup = svm_hardware_setup, |
10509 |
+diff -urNp linux-2.6.28.8/arch/x86/kvm/vmx.c linux-2.6.28.8/arch/x86/kvm/vmx.c |
10510 |
+--- linux-2.6.28.8/arch/x86/kvm/vmx.c 2009-02-06 16:47:45.000000000 -0500 |
10511 |
++++ linux-2.6.28.8/arch/x86/kvm/vmx.c 2009-02-21 09:37:48.000000000 -0500 |
10512 |
+@@ -122,7 +122,7 @@ static struct vmcs_config { |
10513 |
+ u32 vmentry_ctrl; |
10514 |
+ } vmcs_config; |
10515 |
+ |
10516 |
+-struct vmx_capability { |
10517 |
++static struct vmx_capability { |
10518 |
+ u32 ept; |
10519 |
+ u32 vpid; |
10520 |
+ } vmx_capability; |
10521 |
+@@ -491,9 +491,23 @@ static void reload_tss(void) |
10522 |
+ struct descriptor_table gdt; |
10523 |
+ struct desc_struct *descs; |
10524 |
+ |
10525 |
++#ifdef CONFIG_PAX_KERNEXEC |
10526 |
++ unsigned long cr0; |
10527 |
++#endif |
10528 |
++ |
10529 |
+ kvm_get_gdt(&gdt); |
10530 |
+ descs = (void *)gdt.base; |
10531 |
++ |
10532 |
++#ifdef CONFIG_PAX_KERNEXEC |
10533 |
++ pax_open_kernel(cr0); |
10534 |
++#endif |
10535 |
++ |
10536 |
+ descs[GDT_ENTRY_TSS].type = 9; /* available TSS */ |
10537 |
++ |
10538 |
++#ifdef CONFIG_PAX_KERNEXEC |
10539 |
++ pax_close_kernel(cr0); |
10540 |
++#endif |
10541 |
++ |
10542 |
+ load_TR_desc(); |
10543 |
+ } |
10544 |
+ |
10545 |
+@@ -2164,7 +2178,7 @@ static int vmx_vcpu_setup(struct vcpu_vm |
10546 |
+ vmcs_writel(HOST_IDTR_BASE, dt.base); /* 22.2.4 */ |
10547 |
+ |
10548 |
+ asm("mov $.Lkvm_vmx_return, %0" : "=r"(kvm_vmx_return)); |
10549 |
+- vmcs_writel(HOST_RIP, kvm_vmx_return); /* 22.2.5 */ |
10550 |
++ vmcs_writel(HOST_RIP, ktla_ktva(kvm_vmx_return)); /* 22.2.5 */ |
10551 |
+ vmcs_write32(VM_EXIT_MSR_STORE_COUNT, 0); |
10552 |
+ vmcs_write32(VM_EXIT_MSR_LOAD_COUNT, 0); |
10553 |
+ vmcs_write32(VM_ENTRY_MSR_LOAD_COUNT, 0); |
10554 |
+@@ -3267,6 +3281,12 @@ static void vmx_vcpu_run(struct kvm_vcpu |
10555 |
+ "jmp .Lkvm_vmx_return \n\t" |
10556 |
+ ".Llaunched: " __ex(ASM_VMX_VMRESUME) "\n\t" |
10557 |
+ ".Lkvm_vmx_return: " |
10558 |
++ |
10559 |
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) |
10560 |
++ "ljmp %[cs],$.Lkvm_vmx_return2\n\t" |
10561 |
++ ".Lkvm_vmx_return2: " |
10562 |
++#endif |
10563 |
++ |
10564 |
+ /* Save guest registers, load host registers, keep flags */ |
10565 |
+ "xchg %0, (%%"R"sp) \n\t" |
10566 |
+ "mov %%"R"ax, %c[rax](%0) \n\t" |
10567 |
+@@ -3313,6 +3333,11 @@ static void vmx_vcpu_run(struct kvm_vcpu |
10568 |
+ [r15]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R15])), |
10569 |
+ #endif |
10570 |
+ [cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2)) |
10571 |
++ |
10572 |
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) |
10573 |
++ ,[cs]"i"(__KERNEL_CS) |
10574 |
++#endif |
10575 |
++ |
10576 |
+ : "cc", "memory" |
10577 |
+ , R"bx", R"di", R"si" |
10578 |
+ #ifdef CONFIG_X86_64 |
10579 |
+@@ -3331,7 +3356,7 @@ static void vmx_vcpu_run(struct kvm_vcpu |
10580 |
+ (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & |
10581 |
+ (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS)) == 0; |
10582 |
+ |
10583 |
+- asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS)); |
10584 |
++ asm("mov %0, %%ds; mov %0, %%es" : : "r"(__KERNEL_DS)); |
10585 |
+ vmx->launched = 1; |
10586 |
+ |
10587 |
+ intr_info = vmcs_read32(VM_EXIT_INTR_INFO); |
10588 |
+@@ -3455,7 +3480,7 @@ static int get_ept_level(void) |
10589 |
+ return VMX_EPT_DEFAULT_GAW + 1; |
10590 |
+ } |
10591 |
+ |
10592 |
+-static struct kvm_x86_ops vmx_x86_ops = { |
10593 |
++static const struct kvm_x86_ops vmx_x86_ops = { |
10594 |
+ .cpu_has_kvm_support = cpu_has_kvm_support, |
10595 |
+ .disabled_by_bios = vmx_disabled_by_bios, |
10596 |
+ .hardware_setup = hardware_setup, |
10597 |
+diff -urNp linux-2.6.28.8/arch/x86/kvm/x86.c linux-2.6.28.8/arch/x86/kvm/x86.c |
10598 |
+--- linux-2.6.28.8/arch/x86/kvm/x86.c 2009-02-06 16:47:45.000000000 -0500 |
10599 |
++++ linux-2.6.28.8/arch/x86/kvm/x86.c 2009-02-21 09:37:48.000000000 -0500 |
10600 |
+@@ -68,41 +68,41 @@ static u64 __read_mostly efer_reserved_b |
10601 |
+ static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid, |
10602 |
+ struct kvm_cpuid_entry2 __user *entries); |
10603 |
+ |
10604 |
+-struct kvm_x86_ops *kvm_x86_ops; |
10605 |
++const struct kvm_x86_ops *kvm_x86_ops; |
10606 |
+ EXPORT_SYMBOL_GPL(kvm_x86_ops); |
10607 |
+ |
10608 |
+ struct kvm_stats_debugfs_item debugfs_entries[] = { |
10609 |
+- { "pf_fixed", VCPU_STAT(pf_fixed) }, |
10610 |
+- { "pf_guest", VCPU_STAT(pf_guest) }, |
10611 |
+- { "tlb_flush", VCPU_STAT(tlb_flush) }, |
10612 |
+- { "invlpg", VCPU_STAT(invlpg) }, |
10613 |
+- { "exits", VCPU_STAT(exits) }, |
10614 |
+- { "io_exits", VCPU_STAT(io_exits) }, |
10615 |
+- { "mmio_exits", VCPU_STAT(mmio_exits) }, |
10616 |
+- { "signal_exits", VCPU_STAT(signal_exits) }, |
10617 |
+- { "irq_window", VCPU_STAT(irq_window_exits) }, |
10618 |
+- { "nmi_window", VCPU_STAT(nmi_window_exits) }, |
10619 |
+- { "halt_exits", VCPU_STAT(halt_exits) }, |
10620 |
+- { "halt_wakeup", VCPU_STAT(halt_wakeup) }, |
10621 |
+- { "hypercalls", VCPU_STAT(hypercalls) }, |
10622 |
+- { "request_irq", VCPU_STAT(request_irq_exits) }, |
10623 |
+- { "irq_exits", VCPU_STAT(irq_exits) }, |
10624 |
+- { "host_state_reload", VCPU_STAT(host_state_reload) }, |
10625 |
+- { "efer_reload", VCPU_STAT(efer_reload) }, |
10626 |
+- { "fpu_reload", VCPU_STAT(fpu_reload) }, |
10627 |
+- { "insn_emulation", VCPU_STAT(insn_emulation) }, |
10628 |
+- { "insn_emulation_fail", VCPU_STAT(insn_emulation_fail) }, |
10629 |
+- { "irq_injections", VCPU_STAT(irq_injections) }, |
10630 |
+- { "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped) }, |
10631 |
+- { "mmu_pte_write", VM_STAT(mmu_pte_write) }, |
10632 |
+- { "mmu_pte_updated", VM_STAT(mmu_pte_updated) }, |
10633 |
+- { "mmu_pde_zapped", VM_STAT(mmu_pde_zapped) }, |
10634 |
+- { "mmu_flooded", VM_STAT(mmu_flooded) }, |
10635 |
+- { "mmu_recycled", VM_STAT(mmu_recycled) }, |
10636 |
+- { "mmu_cache_miss", VM_STAT(mmu_cache_miss) }, |
10637 |
+- { "mmu_unsync", VM_STAT(mmu_unsync) }, |
10638 |
+- { "remote_tlb_flush", VM_STAT(remote_tlb_flush) }, |
10639 |
+- { "largepages", VM_STAT(lpages) }, |
10640 |
++ { "pf_fixed", VCPU_STAT(pf_fixed), NULL }, |
10641 |
++ { "pf_guest", VCPU_STAT(pf_guest), NULL }, |
10642 |
++ { "tlb_flush", VCPU_STAT(tlb_flush), NULL }, |
10643 |
++ { "invlpg", VCPU_STAT(invlpg), NULL }, |
10644 |
++ { "exits", VCPU_STAT(exits), NULL }, |
10645 |
++ { "io_exits", VCPU_STAT(io_exits), NULL }, |
10646 |
++ { "mmio_exits", VCPU_STAT(mmio_exits), NULL }, |
10647 |
++ { "signal_exits", VCPU_STAT(signal_exits), NULL }, |
10648 |
++ { "irq_window", VCPU_STAT(irq_window_exits), NULL }, |
10649 |
++ { "nmi_window", VCPU_STAT(nmi_window_exits), NULL }, |
10650 |
++ { "halt_exits", VCPU_STAT(halt_exits), NULL }, |
10651 |
++ { "halt_wakeup", VCPU_STAT(halt_wakeup), NULL }, |
10652 |
++ { "hypercalls", VCPU_STAT(hypercalls), NULL }, |
10653 |
++ { "request_irq", VCPU_STAT(request_irq_exits), NULL }, |
10654 |
++ { "irq_exits", VCPU_STAT(irq_exits), NULL }, |
10655 |
++ { "host_state_reload", VCPU_STAT(host_state_reload), NULL }, |
10656 |
++ { "efer_reload", VCPU_STAT(efer_reload), NULL }, |
10657 |
++ { "fpu_reload", VCPU_STAT(fpu_reload), NULL }, |
10658 |
++ { "insn_emulation", VCPU_STAT(insn_emulation), NULL }, |
10659 |
++ { "insn_emulation_fail", VCPU_STAT(insn_emulation_fail), NULL }, |
10660 |
++ { "irq_injections", VCPU_STAT(irq_injections), NULL }, |
10661 |
++ { "mmu_shadow_zapped", VM_STAT(mmu_shadow_zapped), NULL }, |
10662 |
++ { "mmu_pte_write", VM_STAT(mmu_pte_write), NULL }, |
10663 |
++ { "mmu_pte_updated", VM_STAT(mmu_pte_updated), NULL }, |
10664 |
++ { "mmu_pde_zapped", VM_STAT(mmu_pde_zapped), NULL }, |
10665 |
++ { "mmu_flooded", VM_STAT(mmu_flooded), NULL }, |
10666 |
++ { "mmu_recycled", VM_STAT(mmu_recycled), NULL }, |
10667 |
++ { "mmu_cache_miss", VM_STAT(mmu_cache_miss), NULL }, |
10668 |
++ { "mmu_unsync", VM_STAT(mmu_unsync), NULL }, |
10669 |
++ { "remote_tlb_flush", VM_STAT(remote_tlb_flush), NULL }, |
10670 |
++ { "largepages", VM_STAT(lpages), NULL }, |
10671 |
+ { NULL } |
10672 |
+ }; |
10673 |
+ |
10674 |
+@@ -1304,7 +1304,7 @@ static int kvm_vcpu_ioctl_set_lapic(stru |
10675 |
+ static int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, |
10676 |
+ struct kvm_interrupt *irq) |
10677 |
+ { |
10678 |
+- if (irq->irq < 0 || irq->irq >= 256) |
10679 |
++ if (irq->irq >= 256) |
10680 |
+ return -EINVAL; |
10681 |
+ if (irqchip_in_kernel(vcpu->kvm)) |
10682 |
+ return -ENXIO; |
10683 |
+@@ -2509,10 +2509,10 @@ int kvm_emulate_pio_string(struct kvm_vc |
10684 |
+ } |
10685 |
+ EXPORT_SYMBOL_GPL(kvm_emulate_pio_string); |
10686 |
+ |
10687 |
+-int kvm_arch_init(void *opaque) |
10688 |
++int kvm_arch_init(const void *opaque) |
10689 |
+ { |
10690 |
+ int r; |
10691 |
+- struct kvm_x86_ops *ops = (struct kvm_x86_ops *)opaque; |
10692 |
++ const struct kvm_x86_ops *ops = (const struct kvm_x86_ops *)opaque; |
10693 |
+ |
10694 |
+ if (kvm_x86_ops) { |
10695 |
+ printk(KERN_ERR "kvm: already loaded the other module\n"); |
10696 |
+diff -urNp linux-2.6.28.8/arch/x86/lib/checksum_32.S linux-2.6.28.8/arch/x86/lib/checksum_32.S |
10697 |
+--- linux-2.6.28.8/arch/x86/lib/checksum_32.S 2009-02-06 16:47:45.000000000 -0500 |
10698 |
++++ linux-2.6.28.8/arch/x86/lib/checksum_32.S 2009-02-21 09:37:48.000000000 -0500 |
10699 |
+@@ -28,7 +28,8 @@ |
10700 |
+ #include <linux/linkage.h> |
10701 |
+ #include <asm/dwarf2.h> |
10702 |
+ #include <asm/errno.h> |
10703 |
+- |
10704 |
++#include <asm/segment.h> |
10705 |
++ |
10706 |
+ /* |
10707 |
+ * computes a partial checksum, e.g. for TCP/UDP fragments |
10708 |
+ */ |
10709 |
+@@ -304,9 +305,22 @@ unsigned int csum_partial_copy_generic ( |
10710 |
+ |
10711 |
+ #define ARGBASE 16 |
10712 |
+ #define FP 12 |
10713 |
+- |
10714 |
+-ENTRY(csum_partial_copy_generic) |
10715 |
++ |
10716 |
++ENTRY(csum_partial_copy_generic_to_user) |
10717 |
+ CFI_STARTPROC |
10718 |
++ pushl $(__USER_DS) |
10719 |
++ CFI_ADJUST_CFA_OFFSET 4 |
10720 |
++ popl %es |
10721 |
++ CFI_ADJUST_CFA_OFFSET -4 |
10722 |
++ jmp csum_partial_copy_generic |
10723 |
++ |
10724 |
++ENTRY(csum_partial_copy_generic_from_user) |
10725 |
++ pushl $(__USER_DS) |
10726 |
++ CFI_ADJUST_CFA_OFFSET 4 |
10727 |
++ popl %ds |
10728 |
++ CFI_ADJUST_CFA_OFFSET -4 |
10729 |
++ |
10730 |
++ENTRY(csum_partial_copy_generic) |
10731 |
+ subl $4,%esp |
10732 |
+ CFI_ADJUST_CFA_OFFSET 4 |
10733 |
+ pushl %edi |
10734 |
+@@ -331,7 +345,7 @@ ENTRY(csum_partial_copy_generic) |
10735 |
+ jmp 4f |
10736 |
+ SRC(1: movw (%esi), %bx ) |
10737 |
+ addl $2, %esi |
10738 |
+-DST( movw %bx, (%edi) ) |
10739 |
++DST( movw %bx, %es:(%edi) ) |
10740 |
+ addl $2, %edi |
10741 |
+ addw %bx, %ax |
10742 |
+ adcl $0, %eax |
10743 |
+@@ -343,30 +357,30 @@ DST( movw %bx, (%edi) ) |
10744 |
+ SRC(1: movl (%esi), %ebx ) |
10745 |
+ SRC( movl 4(%esi), %edx ) |
10746 |
+ adcl %ebx, %eax |
10747 |
+-DST( movl %ebx, (%edi) ) |
10748 |
++DST( movl %ebx, %es:(%edi) ) |
10749 |
+ adcl %edx, %eax |
10750 |
+-DST( movl %edx, 4(%edi) ) |
10751 |
++DST( movl %edx, %es:4(%edi) ) |
10752 |
+ |
10753 |
+ SRC( movl 8(%esi), %ebx ) |
10754 |
+ SRC( movl 12(%esi), %edx ) |
10755 |
+ adcl %ebx, %eax |
10756 |
+-DST( movl %ebx, 8(%edi) ) |
10757 |
++DST( movl %ebx, %es:8(%edi) ) |
10758 |
+ adcl %edx, %eax |
10759 |
+-DST( movl %edx, 12(%edi) ) |
10760 |
++DST( movl %edx, %es:12(%edi) ) |
10761 |
+ |
10762 |
+ SRC( movl 16(%esi), %ebx ) |
10763 |
+ SRC( movl 20(%esi), %edx ) |
10764 |
+ adcl %ebx, %eax |
10765 |
+-DST( movl %ebx, 16(%edi) ) |
10766 |
++DST( movl %ebx, %es:16(%edi) ) |
10767 |
+ adcl %edx, %eax |
10768 |
+-DST( movl %edx, 20(%edi) ) |
10769 |
++DST( movl %edx, %es:20(%edi) ) |
10770 |
+ |
10771 |
+ SRC( movl 24(%esi), %ebx ) |
10772 |
+ SRC( movl 28(%esi), %edx ) |
10773 |
+ adcl %ebx, %eax |
10774 |
+-DST( movl %ebx, 24(%edi) ) |
10775 |
++DST( movl %ebx, %es:24(%edi) ) |
10776 |
+ adcl %edx, %eax |
10777 |
+-DST( movl %edx, 28(%edi) ) |
10778 |
++DST( movl %edx, %es:28(%edi) ) |
10779 |
+ |
10780 |
+ lea 32(%esi), %esi |
10781 |
+ lea 32(%edi), %edi |
10782 |
+@@ -380,7 +394,7 @@ DST( movl %edx, 28(%edi) ) |
10783 |
+ shrl $2, %edx # This clears CF |
10784 |
+ SRC(3: movl (%esi), %ebx ) |
10785 |
+ adcl %ebx, %eax |
10786 |
+-DST( movl %ebx, (%edi) ) |
10787 |
++DST( movl %ebx, %es:(%edi) ) |
10788 |
+ lea 4(%esi), %esi |
10789 |
+ lea 4(%edi), %edi |
10790 |
+ dec %edx |
10791 |
+@@ -392,12 +406,12 @@ DST( movl %ebx, (%edi) ) |
10792 |
+ jb 5f |
10793 |
+ SRC( movw (%esi), %cx ) |
10794 |
+ leal 2(%esi), %esi |
10795 |
+-DST( movw %cx, (%edi) ) |
10796 |
++DST( movw %cx, %es:(%edi) ) |
10797 |
+ leal 2(%edi), %edi |
10798 |
+ je 6f |
10799 |
+ shll $16,%ecx |
10800 |
+ SRC(5: movb (%esi), %cl ) |
10801 |
+-DST( movb %cl, (%edi) ) |
10802 |
++DST( movb %cl, %es:(%edi) ) |
10803 |
+ 6: addl %ecx, %eax |
10804 |
+ adcl $0, %eax |
10805 |
+ 7: |
10806 |
+@@ -408,7 +422,7 @@ DST( movb %cl, (%edi) ) |
10807 |
+ |
10808 |
+ 6001: |
10809 |
+ movl ARGBASE+20(%esp), %ebx # src_err_ptr |
10810 |
+- movl $-EFAULT, (%ebx) |
10811 |
++ movl $-EFAULT, %ss:(%ebx) |
10812 |
+ |
10813 |
+ # zero the complete destination - computing the rest |
10814 |
+ # is too much work |
10815 |
+@@ -421,11 +435,19 @@ DST( movb %cl, (%edi) ) |
10816 |
+ |
10817 |
+ 6002: |
10818 |
+ movl ARGBASE+24(%esp), %ebx # dst_err_ptr |
10819 |
+- movl $-EFAULT,(%ebx) |
10820 |
++ movl $-EFAULT,%ss:(%ebx) |
10821 |
+ jmp 5000b |
10822 |
+ |
10823 |
+ .previous |
10824 |
+ |
10825 |
++ pushl %ss |
10826 |
++ CFI_ADJUST_CFA_OFFSET 4 |
10827 |
++ popl %ds |
10828 |
++ CFI_ADJUST_CFA_OFFSET -4 |
10829 |
++ pushl %ss |
10830 |
++ CFI_ADJUST_CFA_OFFSET 4 |
10831 |
++ popl %es |
10832 |
++ CFI_ADJUST_CFA_OFFSET -4 |
10833 |
+ popl %ebx |
10834 |
+ CFI_ADJUST_CFA_OFFSET -4 |
10835 |
+ CFI_RESTORE ebx |
10836 |
+@@ -439,26 +461,41 @@ DST( movb %cl, (%edi) ) |
10837 |
+ CFI_ADJUST_CFA_OFFSET -4 |
10838 |
+ ret |
10839 |
+ CFI_ENDPROC |
10840 |
+-ENDPROC(csum_partial_copy_generic) |
10841 |
++ENDPROC(csum_partial_copy_generic_to_user) |
10842 |
+ |
10843 |
+ #else |
10844 |
+ |
10845 |
+ /* Version for PentiumII/PPro */ |
10846 |
+ |
10847 |
+ #define ROUND1(x) \ |
10848 |
++ nop; nop; nop; \ |
10849 |
+ SRC(movl x(%esi), %ebx ) ; \ |
10850 |
+ addl %ebx, %eax ; \ |
10851 |
+- DST(movl %ebx, x(%edi) ) ; |
10852 |
++ DST(movl %ebx, %es:x(%edi)) ; |
10853 |
+ |
10854 |
+ #define ROUND(x) \ |
10855 |
++ nop; nop; nop; \ |
10856 |
+ SRC(movl x(%esi), %ebx ) ; \ |
10857 |
+ adcl %ebx, %eax ; \ |
10858 |
+- DST(movl %ebx, x(%edi) ) ; |
10859 |
++ DST(movl %ebx, %es:x(%edi)) ; |
10860 |
+ |
10861 |
+ #define ARGBASE 12 |
10862 |
+- |
10863 |
+-ENTRY(csum_partial_copy_generic) |
10864 |
++ |
10865 |
++ENTRY(csum_partial_copy_generic_to_user) |
10866 |
+ CFI_STARTPROC |
10867 |
++ pushl $(__USER_DS) |
10868 |
++ CFI_ADJUST_CFA_OFFSET 4 |
10869 |
++ popl %es |
10870 |
++ CFI_ADJUST_CFA_OFFSET -4 |
10871 |
++ jmp csum_partial_copy_generic |
10872 |
++ |
10873 |
++ENTRY(csum_partial_copy_generic_from_user) |
10874 |
++ pushl $(__USER_DS) |
10875 |
++ CFI_ADJUST_CFA_OFFSET 4 |
10876 |
++ popl %ds |
10877 |
++ CFI_ADJUST_CFA_OFFSET -4 |
10878 |
++ |
10879 |
++ENTRY(csum_partial_copy_generic) |
10880 |
+ pushl %ebx |
10881 |
+ CFI_ADJUST_CFA_OFFSET 4 |
10882 |
+ CFI_REL_OFFSET ebx, 0 |
10883 |
+@@ -482,7 +519,7 @@ ENTRY(csum_partial_copy_generic) |
10884 |
+ subl %ebx, %edi |
10885 |
+ lea -1(%esi),%edx |
10886 |
+ andl $-32,%edx |
10887 |
+- lea 3f(%ebx,%ebx), %ebx |
10888 |
++ lea 3f(%ebx,%ebx,2), %ebx |
10889 |
+ testl %esi, %esi |
10890 |
+ jmp *%ebx |
10891 |
+ 1: addl $64,%esi |
10892 |
+@@ -503,19 +540,19 @@ ENTRY(csum_partial_copy_generic) |
10893 |
+ jb 5f |
10894 |
+ SRC( movw (%esi), %dx ) |
10895 |
+ leal 2(%esi), %esi |
10896 |
+-DST( movw %dx, (%edi) ) |
10897 |
++DST( movw %dx, %es:(%edi) ) |
10898 |
+ leal 2(%edi), %edi |
10899 |
+ je 6f |
10900 |
+ shll $16,%edx |
10901 |
+ 5: |
10902 |
+ SRC( movb (%esi), %dl ) |
10903 |
+-DST( movb %dl, (%edi) ) |
10904 |
++DST( movb %dl, %es:(%edi) ) |
10905 |
+ 6: addl %edx, %eax |
10906 |
+ adcl $0, %eax |
10907 |
+ 7: |
10908 |
+ .section .fixup, "ax" |
10909 |
+ 6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr |
10910 |
+- movl $-EFAULT, (%ebx) |
10911 |
++ movl $-EFAULT, %ss:(%ebx) |
10912 |
+ # zero the complete destination (computing the rest is too much work) |
10913 |
+ movl ARGBASE+8(%esp),%edi # dst |
10914 |
+ movl ARGBASE+12(%esp),%ecx # len |
10915 |
+@@ -523,10 +560,18 @@ DST( movb %dl, (%edi) ) |
10916 |
+ rep; stosb |
10917 |
+ jmp 7b |
10918 |
+ 6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr |
10919 |
+- movl $-EFAULT, (%ebx) |
10920 |
++ movl $-EFAULT, %ss:(%ebx) |
10921 |
+ jmp 7b |
10922 |
+ .previous |
10923 |
+ |
10924 |
++ pushl %ss |
10925 |
++ CFI_ADJUST_CFA_OFFSET 4 |
10926 |
++ popl %ds |
10927 |
++ CFI_ADJUST_CFA_OFFSET -4 |
10928 |
++ pushl %ss |
10929 |
++ CFI_ADJUST_CFA_OFFSET 4 |
10930 |
++ popl %es |
10931 |
++ CFI_ADJUST_CFA_OFFSET -4 |
10932 |
+ popl %esi |
10933 |
+ CFI_ADJUST_CFA_OFFSET -4 |
10934 |
+ CFI_RESTORE esi |
10935 |
+@@ -538,7 +583,7 @@ DST( movb %dl, (%edi) ) |
10936 |
+ CFI_RESTORE ebx |
10937 |
+ ret |
10938 |
+ CFI_ENDPROC |
10939 |
+-ENDPROC(csum_partial_copy_generic) |
10940 |
++ENDPROC(csum_partial_copy_generic_to_user) |
10941 |
+ |
10942 |
+ #undef ROUND |
10943 |
+ #undef ROUND1 |
10944 |
+diff -urNp linux-2.6.28.8/arch/x86/lib/clear_page_64.S linux-2.6.28.8/arch/x86/lib/clear_page_64.S |
10945 |
+--- linux-2.6.28.8/arch/x86/lib/clear_page_64.S 2009-02-06 16:47:45.000000000 -0500 |
10946 |
++++ linux-2.6.28.8/arch/x86/lib/clear_page_64.S 2009-02-21 09:37:48.000000000 -0500 |
10947 |
+@@ -44,7 +44,7 @@ ENDPROC(clear_page) |
10948 |
+ |
10949 |
+ #include <asm/cpufeature.h> |
10950 |
+ |
10951 |
+- .section .altinstr_replacement,"ax" |
10952 |
++ .section .altinstr_replacement,"a" |
10953 |
+ 1: .byte 0xeb /* jmp <disp8> */ |
10954 |
+ .byte (clear_page_c - clear_page) - (2f - 1b) /* offset */ |
10955 |
+ 2: |
10956 |
+diff -urNp linux-2.6.28.8/arch/x86/lib/copy_page_64.S linux-2.6.28.8/arch/x86/lib/copy_page_64.S |
10957 |
+--- linux-2.6.28.8/arch/x86/lib/copy_page_64.S 2009-02-06 16:47:45.000000000 -0500 |
10958 |
++++ linux-2.6.28.8/arch/x86/lib/copy_page_64.S 2009-02-21 09:37:48.000000000 -0500 |
10959 |
+@@ -104,7 +104,7 @@ ENDPROC(copy_page) |
10960 |
+ |
10961 |
+ #include <asm/cpufeature.h> |
10962 |
+ |
10963 |
+- .section .altinstr_replacement,"ax" |
10964 |
++ .section .altinstr_replacement,"a" |
10965 |
+ 1: .byte 0xeb /* jmp <disp8> */ |
10966 |
+ .byte (copy_page_c - copy_page) - (2f - 1b) /* offset */ |
10967 |
+ 2: |
10968 |
+diff -urNp linux-2.6.28.8/arch/x86/lib/copy_user_64.S linux-2.6.28.8/arch/x86/lib/copy_user_64.S |
10969 |
+--- linux-2.6.28.8/arch/x86/lib/copy_user_64.S 2009-02-06 16:47:45.000000000 -0500 |
10970 |
++++ linux-2.6.28.8/arch/x86/lib/copy_user_64.S 2009-02-21 09:37:48.000000000 -0500 |
10971 |
+@@ -21,7 +21,7 @@ |
10972 |
+ .byte 0xe9 /* 32bit jump */ |
10973 |
+ .long \orig-1f /* by default jump to orig */ |
10974 |
+ 1: |
10975 |
+- .section .altinstr_replacement,"ax" |
10976 |
++ .section .altinstr_replacement,"a" |
10977 |
+ 2: .byte 0xe9 /* near jump with 32bit immediate */ |
10978 |
+ .long \alt-1b /* offset */ /* or alternatively to alt */ |
10979 |
+ .previous |
10980 |
+@@ -106,6 +106,8 @@ ENDPROC(__copy_from_user_inatomic) |
10981 |
+ ENTRY(bad_from_user) |
10982 |
+ bad_from_user: |
10983 |
+ CFI_STARTPROC |
10984 |
++ testl %edx,%edx |
10985 |
++ js bad_to_user |
10986 |
+ movl %edx,%ecx |
10987 |
+ xorl %eax,%eax |
10988 |
+ rep |
10989 |
+diff -urNp linux-2.6.28.8/arch/x86/lib/getuser.S linux-2.6.28.8/arch/x86/lib/getuser.S |
10990 |
+--- linux-2.6.28.8/arch/x86/lib/getuser.S 2009-02-06 16:47:45.000000000 -0500 |
10991 |
++++ linux-2.6.28.8/arch/x86/lib/getuser.S 2009-02-21 09:37:48.000000000 -0500 |
10992 |
+@@ -33,6 +33,7 @@ |
10993 |
+ #include <asm/asm-offsets.h> |
10994 |
+ #include <asm/thread_info.h> |
10995 |
+ #include <asm/asm.h> |
10996 |
++#include <asm/segment.h> |
10997 |
+ |
10998 |
+ .text |
10999 |
+ ENTRY(__get_user_1) |
11000 |
+@@ -40,7 +41,19 @@ ENTRY(__get_user_1) |
11001 |
+ GET_THREAD_INFO(%_ASM_DX) |
11002 |
+ cmp TI_addr_limit(%_ASM_DX),%_ASM_AX |
11003 |
+ jae bad_get_user |
11004 |
++ |
11005 |
++#ifdef CONFIG_X86_32 |
11006 |
++ pushl $(__USER_DS) |
11007 |
++ popl %ds |
11008 |
++#endif |
11009 |
++ |
11010 |
+ 1: movzb (%_ASM_AX),%edx |
11011 |
++ |
11012 |
++#ifdef CONFIG_X86_32 |
11013 |
++ pushl %ss |
11014 |
++ pop %ds |
11015 |
++#endif |
11016 |
++ |
11017 |
+ xor %eax,%eax |
11018 |
+ ret |
11019 |
+ CFI_ENDPROC |
11020 |
+@@ -53,7 +66,19 @@ ENTRY(__get_user_2) |
11021 |
+ GET_THREAD_INFO(%_ASM_DX) |
11022 |
+ cmp TI_addr_limit(%_ASM_DX),%_ASM_AX |
11023 |
+ jae bad_get_user |
11024 |
++ |
11025 |
++#ifdef CONFIG_X86_32 |
11026 |
++ pushl $(__USER_DS) |
11027 |
++ popl %ds |
11028 |
++#endif |
11029 |
++ |
11030 |
+ 2: movzwl -1(%_ASM_AX),%edx |
11031 |
++ |
11032 |
++#ifdef CONFIG_X86_32 |
11033 |
++ pushl %ss |
11034 |
++ pop %ds |
11035 |
++#endif |
11036 |
++ |
11037 |
+ xor %eax,%eax |
11038 |
+ ret |
11039 |
+ CFI_ENDPROC |
11040 |
+@@ -66,7 +91,19 @@ ENTRY(__get_user_4) |
11041 |
+ GET_THREAD_INFO(%_ASM_DX) |
11042 |
+ cmp TI_addr_limit(%_ASM_DX),%_ASM_AX |
11043 |
+ jae bad_get_user |
11044 |
++ |
11045 |
++#ifdef CONFIG_X86_32 |
11046 |
++ pushl $(__USER_DS) |
11047 |
++ popl %ds |
11048 |
++#endif |
11049 |
++ |
11050 |
+ 3: mov -3(%_ASM_AX),%edx |
11051 |
++ |
11052 |
++#ifdef CONFIG_X86_32 |
11053 |
++ pushl %ss |
11054 |
++ pop %ds |
11055 |
++#endif |
11056 |
++ |
11057 |
+ xor %eax,%eax |
11058 |
+ ret |
11059 |
+ CFI_ENDPROC |
11060 |
+@@ -89,6 +126,12 @@ ENDPROC(__get_user_8) |
11061 |
+ |
11062 |
+ bad_get_user: |
11063 |
+ CFI_STARTPROC |
11064 |
++ |
11065 |
++#ifdef CONFIG_X86_32 |
11066 |
++ pushl %ss |
11067 |
++ pop %ds |
11068 |
++#endif |
11069 |
++ |
11070 |
+ xor %edx,%edx |
11071 |
+ mov $(-EFAULT),%_ASM_AX |
11072 |
+ ret |
11073 |
+diff -urNp linux-2.6.28.8/arch/x86/lib/memcpy_64.S linux-2.6.28.8/arch/x86/lib/memcpy_64.S |
11074 |
+--- linux-2.6.28.8/arch/x86/lib/memcpy_64.S 2009-02-06 16:47:45.000000000 -0500 |
11075 |
++++ linux-2.6.28.8/arch/x86/lib/memcpy_64.S 2009-02-21 09:37:48.000000000 -0500 |
11076 |
+@@ -114,7 +114,7 @@ ENDPROC(__memcpy) |
11077 |
+ /* Some CPUs run faster using the string copy instructions. |
11078 |
+ It is also a lot simpler. Use this when possible */ |
11079 |
+ |
11080 |
+- .section .altinstr_replacement,"ax" |
11081 |
++ .section .altinstr_replacement,"a" |
11082 |
+ 1: .byte 0xeb /* jmp <disp8> */ |
11083 |
+ .byte (memcpy_c - memcpy) - (2f - 1b) /* offset */ |
11084 |
+ 2: |
11085 |
+diff -urNp linux-2.6.28.8/arch/x86/lib/memset_64.S linux-2.6.28.8/arch/x86/lib/memset_64.S |
11086 |
+--- linux-2.6.28.8/arch/x86/lib/memset_64.S 2009-02-06 16:47:45.000000000 -0500 |
11087 |
++++ linux-2.6.28.8/arch/x86/lib/memset_64.S 2009-02-21 09:37:48.000000000 -0500 |
11088 |
+@@ -118,7 +118,7 @@ ENDPROC(__memset) |
11089 |
+ |
11090 |
+ #include <asm/cpufeature.h> |
11091 |
+ |
11092 |
+- .section .altinstr_replacement,"ax" |
11093 |
++ .section .altinstr_replacement,"a" |
11094 |
+ 1: .byte 0xeb /* jmp <disp8> */ |
11095 |
+ .byte (memset_c - memset) - (2f - 1b) /* offset */ |
11096 |
+ 2: |
11097 |
+diff -urNp linux-2.6.28.8/arch/x86/lib/mmx_32.c linux-2.6.28.8/arch/x86/lib/mmx_32.c |
11098 |
+--- linux-2.6.28.8/arch/x86/lib/mmx_32.c 2009-02-06 16:47:45.000000000 -0500 |
11099 |
++++ linux-2.6.28.8/arch/x86/lib/mmx_32.c 2009-02-21 09:37:48.000000000 -0500 |
11100 |
+@@ -29,6 +29,7 @@ void *_mmx_memcpy(void *to, const void * |
11101 |
+ { |
11102 |
+ void *p; |
11103 |
+ int i; |
11104 |
++ unsigned long cr0; |
11105 |
+ |
11106 |
+ if (unlikely(in_interrupt())) |
11107 |
+ return __memcpy(to, from, len); |
11108 |
+@@ -39,44 +40,72 @@ void *_mmx_memcpy(void *to, const void * |
11109 |
+ kernel_fpu_begin(); |
11110 |
+ |
11111 |
+ __asm__ __volatile__ ( |
11112 |
+- "1: prefetch (%0)\n" /* This set is 28 bytes */ |
11113 |
+- " prefetch 64(%0)\n" |
11114 |
+- " prefetch 128(%0)\n" |
11115 |
+- " prefetch 192(%0)\n" |
11116 |
+- " prefetch 256(%0)\n" |
11117 |
++ "1: prefetch (%1)\n" /* This set is 28 bytes */ |
11118 |
++ " prefetch 64(%1)\n" |
11119 |
++ " prefetch 128(%1)\n" |
11120 |
++ " prefetch 192(%1)\n" |
11121 |
++ " prefetch 256(%1)\n" |
11122 |
+ "2: \n" |
11123 |
+ ".section .fixup, \"ax\"\n" |
11124 |
+- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ |
11125 |
++ "3: \n" |
11126 |
++ |
11127 |
++#ifdef CONFIG_PAX_KERNEXEC |
11128 |
++ " movl %%cr0, %0\n" |
11129 |
++ " movl %0, %%eax\n" |
11130 |
++ " andl $0xFFFEFFFF, %%eax\n" |
11131 |
++ " movl %%eax, %%cr0\n" |
11132 |
++#endif |
11133 |
++ |
11134 |
++ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ |
11135 |
++ |
11136 |
++#ifdef CONFIG_PAX_KERNEXEC |
11137 |
++ " movl %0, %%cr0\n" |
11138 |
++#endif |
11139 |
++ |
11140 |
+ " jmp 2b\n" |
11141 |
+ ".previous\n" |
11142 |
+ _ASM_EXTABLE(1b, 3b) |
11143 |
+- : : "r" (from)); |
11144 |
++ : "=&r" (cr0) : "r" (from) : "ax"); |
11145 |
+ |
11146 |
+ for ( ; i > 5; i--) { |
11147 |
+ __asm__ __volatile__ ( |
11148 |
+- "1: prefetch 320(%0)\n" |
11149 |
+- "2: movq (%0), %%mm0\n" |
11150 |
+- " movq 8(%0), %%mm1\n" |
11151 |
+- " movq 16(%0), %%mm2\n" |
11152 |
+- " movq 24(%0), %%mm3\n" |
11153 |
+- " movq %%mm0, (%1)\n" |
11154 |
+- " movq %%mm1, 8(%1)\n" |
11155 |
+- " movq %%mm2, 16(%1)\n" |
11156 |
+- " movq %%mm3, 24(%1)\n" |
11157 |
+- " movq 32(%0), %%mm0\n" |
11158 |
+- " movq 40(%0), %%mm1\n" |
11159 |
+- " movq 48(%0), %%mm2\n" |
11160 |
+- " movq 56(%0), %%mm3\n" |
11161 |
+- " movq %%mm0, 32(%1)\n" |
11162 |
+- " movq %%mm1, 40(%1)\n" |
11163 |
+- " movq %%mm2, 48(%1)\n" |
11164 |
+- " movq %%mm3, 56(%1)\n" |
11165 |
++ "1: prefetch 320(%1)\n" |
11166 |
++ "2: movq (%1), %%mm0\n" |
11167 |
++ " movq 8(%1), %%mm1\n" |
11168 |
++ " movq 16(%1), %%mm2\n" |
11169 |
++ " movq 24(%1), %%mm3\n" |
11170 |
++ " movq %%mm0, (%2)\n" |
11171 |
++ " movq %%mm1, 8(%2)\n" |
11172 |
++ " movq %%mm2, 16(%2)\n" |
11173 |
++ " movq %%mm3, 24(%2)\n" |
11174 |
++ " movq 32(%1), %%mm0\n" |
11175 |
++ " movq 40(%1), %%mm1\n" |
11176 |
++ " movq 48(%1), %%mm2\n" |
11177 |
++ " movq 56(%1), %%mm3\n" |
11178 |
++ " movq %%mm0, 32(%2)\n" |
11179 |
++ " movq %%mm1, 40(%2)\n" |
11180 |
++ " movq %%mm2, 48(%2)\n" |
11181 |
++ " movq %%mm3, 56(%2)\n" |
11182 |
+ ".section .fixup, \"ax\"\n" |
11183 |
+- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ |
11184 |
++ "3:\n" |
11185 |
++ |
11186 |
++#ifdef CONFIG_PAX_KERNEXEC |
11187 |
++ " movl %%cr0, %0\n" |
11188 |
++ " movl %0, %%eax\n" |
11189 |
++ " andl $0xFFFEFFFF, %%eax\n" |
11190 |
++ " movl %%eax, %%cr0\n" |
11191 |
++#endif |
11192 |
++ |
11193 |
++ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */ |
11194 |
++ |
11195 |
++#ifdef CONFIG_PAX_KERNEXEC |
11196 |
++ " movl %0, %%cr0\n" |
11197 |
++#endif |
11198 |
++ |
11199 |
+ " jmp 2b\n" |
11200 |
+ ".previous\n" |
11201 |
+ _ASM_EXTABLE(1b, 3b) |
11202 |
+- : : "r" (from), "r" (to) : "memory"); |
11203 |
++ : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax"); |
11204 |
+ |
11205 |
+ from += 64; |
11206 |
+ to += 64; |
11207 |
+@@ -158,6 +187,7 @@ static void fast_clear_page(void *page) |
11208 |
+ static void fast_copy_page(void *to, void *from) |
11209 |
+ { |
11210 |
+ int i; |
11211 |
++ unsigned long cr0; |
11212 |
+ |
11213 |
+ kernel_fpu_begin(); |
11214 |
+ |
11215 |
+@@ -166,42 +196,70 @@ static void fast_copy_page(void *to, voi |
11216 |
+ * but that is for later. -AV |
11217 |
+ */ |
11218 |
+ __asm__ __volatile__( |
11219 |
+- "1: prefetch (%0)\n" |
11220 |
+- " prefetch 64(%0)\n" |
11221 |
+- " prefetch 128(%0)\n" |
11222 |
+- " prefetch 192(%0)\n" |
11223 |
+- " prefetch 256(%0)\n" |
11224 |
++ "1: prefetch (%1)\n" |
11225 |
++ " prefetch 64(%1)\n" |
11226 |
++ " prefetch 128(%1)\n" |
11227 |
++ " prefetch 192(%1)\n" |
11228 |
++ " prefetch 256(%1)\n" |
11229 |
+ "2: \n" |
11230 |
+ ".section .fixup, \"ax\"\n" |
11231 |
+- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ |
11232 |
++ "3: \n" |
11233 |
++ |
11234 |
++#ifdef CONFIG_PAX_KERNEXEC |
11235 |
++ " movl %%cr0, %0\n" |
11236 |
++ " movl %0, %%eax\n" |
11237 |
++ " andl $0xFFFEFFFF, %%eax\n" |
11238 |
++ " movl %%eax, %%cr0\n" |
11239 |
++#endif |
11240 |
++ |
11241 |
++ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ |
11242 |
++ |
11243 |
++#ifdef CONFIG_PAX_KERNEXEC |
11244 |
++ " movl %0, %%cr0\n" |
11245 |
++#endif |
11246 |
++ |
11247 |
+ " jmp 2b\n" |
11248 |
+ ".previous\n" |
11249 |
+- _ASM_EXTABLE(1b, 3b) : : "r" (from)); |
11250 |
++ _ASM_EXTABLE(1b, 3b) : "=&r" (cr0) : "r" (from) : "ax"); |
11251 |
+ |
11252 |
+ for (i = 0; i < (4096-320)/64; i++) { |
11253 |
+ __asm__ __volatile__ ( |
11254 |
+- "1: prefetch 320(%0)\n" |
11255 |
+- "2: movq (%0), %%mm0\n" |
11256 |
+- " movntq %%mm0, (%1)\n" |
11257 |
+- " movq 8(%0), %%mm1\n" |
11258 |
+- " movntq %%mm1, 8(%1)\n" |
11259 |
+- " movq 16(%0), %%mm2\n" |
11260 |
+- " movntq %%mm2, 16(%1)\n" |
11261 |
+- " movq 24(%0), %%mm3\n" |
11262 |
+- " movntq %%mm3, 24(%1)\n" |
11263 |
+- " movq 32(%0), %%mm4\n" |
11264 |
+- " movntq %%mm4, 32(%1)\n" |
11265 |
+- " movq 40(%0), %%mm5\n" |
11266 |
+- " movntq %%mm5, 40(%1)\n" |
11267 |
+- " movq 48(%0), %%mm6\n" |
11268 |
+- " movntq %%mm6, 48(%1)\n" |
11269 |
+- " movq 56(%0), %%mm7\n" |
11270 |
+- " movntq %%mm7, 56(%1)\n" |
11271 |
++ "1: prefetch 320(%1)\n" |
11272 |
++ "2: movq (%1), %%mm0\n" |
11273 |
++ " movntq %%mm0, (%2)\n" |
11274 |
++ " movq 8(%1), %%mm1\n" |
11275 |
++ " movntq %%mm1, 8(%2)\n" |
11276 |
++ " movq 16(%1), %%mm2\n" |
11277 |
++ " movntq %%mm2, 16(%2)\n" |
11278 |
++ " movq 24(%1), %%mm3\n" |
11279 |
++ " movntq %%mm3, 24(%2)\n" |
11280 |
++ " movq 32(%1), %%mm4\n" |
11281 |
++ " movntq %%mm4, 32(%2)\n" |
11282 |
++ " movq 40(%1), %%mm5\n" |
11283 |
++ " movntq %%mm5, 40(%2)\n" |
11284 |
++ " movq 48(%1), %%mm6\n" |
11285 |
++ " movntq %%mm6, 48(%2)\n" |
11286 |
++ " movq 56(%1), %%mm7\n" |
11287 |
++ " movntq %%mm7, 56(%2)\n" |
11288 |
+ ".section .fixup, \"ax\"\n" |
11289 |
+- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ |
11290 |
++ "3:\n" |
11291 |
++ |
11292 |
++#ifdef CONFIG_PAX_KERNEXEC |
11293 |
++ " movl %%cr0, %0\n" |
11294 |
++ " movl %0, %%eax\n" |
11295 |
++ " andl $0xFFFEFFFF, %%eax\n" |
11296 |
++ " movl %%eax, %%cr0\n" |
11297 |
++#endif |
11298 |
++ |
11299 |
++ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */ |
11300 |
++ |
11301 |
++#ifdef CONFIG_PAX_KERNEXEC |
11302 |
++ " movl %0, %%cr0\n" |
11303 |
++#endif |
11304 |
++ |
11305 |
+ " jmp 2b\n" |
11306 |
+ ".previous\n" |
11307 |
+- _ASM_EXTABLE(1b, 3b) : : "r" (from), "r" (to) : "memory"); |
11308 |
++ _ASM_EXTABLE(1b, 3b) : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax"); |
11309 |
+ |
11310 |
+ from += 64; |
11311 |
+ to += 64; |
11312 |
+@@ -280,47 +338,76 @@ static void fast_clear_page(void *page) |
11313 |
+ static void fast_copy_page(void *to, void *from) |
11314 |
+ { |
11315 |
+ int i; |
11316 |
++ unsigned long cr0; |
11317 |
+ |
11318 |
+ kernel_fpu_begin(); |
11319 |
+ |
11320 |
+ __asm__ __volatile__ ( |
11321 |
+- "1: prefetch (%0)\n" |
11322 |
+- " prefetch 64(%0)\n" |
11323 |
+- " prefetch 128(%0)\n" |
11324 |
+- " prefetch 192(%0)\n" |
11325 |
+- " prefetch 256(%0)\n" |
11326 |
++ "1: prefetch (%1)\n" |
11327 |
++ " prefetch 64(%1)\n" |
11328 |
++ " prefetch 128(%1)\n" |
11329 |
++ " prefetch 192(%1)\n" |
11330 |
++ " prefetch 256(%1)\n" |
11331 |
+ "2: \n" |
11332 |
+ ".section .fixup, \"ax\"\n" |
11333 |
+- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ |
11334 |
++ "3: \n" |
11335 |
++ |
11336 |
++#ifdef CONFIG_PAX_KERNEXEC |
11337 |
++ " movl %%cr0, %0\n" |
11338 |
++ " movl %0, %%eax\n" |
11339 |
++ " andl $0xFFFEFFFF, %%eax\n" |
11340 |
++ " movl %%eax, %%cr0\n" |
11341 |
++#endif |
11342 |
++ |
11343 |
++ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */ |
11344 |
++ |
11345 |
++#ifdef CONFIG_PAX_KERNEXEC |
11346 |
++ " movl %0, %%cr0\n" |
11347 |
++#endif |
11348 |
++ |
11349 |
+ " jmp 2b\n" |
11350 |
+ ".previous\n" |
11351 |
+- _ASM_EXTABLE(1b, 3b) : : "r" (from)); |
11352 |
++ _ASM_EXTABLE(1b, 3b) : "=&r" (cr0) : "r" (from) : "ax"); |
11353 |
+ |
11354 |
+ for (i = 0; i < 4096/64; i++) { |
11355 |
+ __asm__ __volatile__ ( |
11356 |
+- "1: prefetch 320(%0)\n" |
11357 |
+- "2: movq (%0), %%mm0\n" |
11358 |
+- " movq 8(%0), %%mm1\n" |
11359 |
+- " movq 16(%0), %%mm2\n" |
11360 |
+- " movq 24(%0), %%mm3\n" |
11361 |
+- " movq %%mm0, (%1)\n" |
11362 |
+- " movq %%mm1, 8(%1)\n" |
11363 |
+- " movq %%mm2, 16(%1)\n" |
11364 |
+- " movq %%mm3, 24(%1)\n" |
11365 |
+- " movq 32(%0), %%mm0\n" |
11366 |
+- " movq 40(%0), %%mm1\n" |
11367 |
+- " movq 48(%0), %%mm2\n" |
11368 |
+- " movq 56(%0), %%mm3\n" |
11369 |
+- " movq %%mm0, 32(%1)\n" |
11370 |
+- " movq %%mm1, 40(%1)\n" |
11371 |
+- " movq %%mm2, 48(%1)\n" |
11372 |
+- " movq %%mm3, 56(%1)\n" |
11373 |
++ "1: prefetch 320(%1)\n" |
11374 |
++ "2: movq (%1), %%mm0\n" |
11375 |
++ " movq 8(%1), %%mm1\n" |
11376 |
++ " movq 16(%1), %%mm2\n" |
11377 |
++ " movq 24(%1), %%mm3\n" |
11378 |
++ " movq %%mm0, (%2)\n" |
11379 |
++ " movq %%mm1, 8(%2)\n" |
11380 |
++ " movq %%mm2, 16(%2)\n" |
11381 |
++ " movq %%mm3, 24(%2)\n" |
11382 |
++ " movq 32(%1), %%mm0\n" |
11383 |
++ " movq 40(%1), %%mm1\n" |
11384 |
++ " movq 48(%1), %%mm2\n" |
11385 |
++ " movq 56(%1), %%mm3\n" |
11386 |
++ " movq %%mm0, 32(%2)\n" |
11387 |
++ " movq %%mm1, 40(%2)\n" |
11388 |
++ " movq %%mm2, 48(%2)\n" |
11389 |
++ " movq %%mm3, 56(%2)\n" |
11390 |
+ ".section .fixup, \"ax\"\n" |
11391 |
+- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */ |
11392 |
++ "3:\n" |
11393 |
++ |
11394 |
++#ifdef CONFIG_PAX_KERNEXEC |
11395 |
++ " movl %%cr0, %0\n" |
11396 |
++ " movl %0, %%eax\n" |
11397 |
++ " andl $0xFFFEFFFF, %%eax\n" |
11398 |
++ " movl %%eax, %%cr0\n" |
11399 |
++#endif |
11400 |
++ |
11401 |
++ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */ |
11402 |
++ |
11403 |
++#ifdef CONFIG_PAX_KERNEXEC |
11404 |
++ " movl %0, %%cr0\n" |
11405 |
++#endif |
11406 |
++ |
11407 |
+ " jmp 2b\n" |
11408 |
+ ".previous\n" |
11409 |
+ _ASM_EXTABLE(1b, 3b) |
11410 |
+- : : "r" (from), "r" (to) : "memory"); |
11411 |
++ : "=&r" (cr0) : "r" (from), "r" (to) : "memory", "ax"); |
11412 |
+ |
11413 |
+ from += 64; |
11414 |
+ to += 64; |
11415 |
+diff -urNp linux-2.6.28.8/arch/x86/lib/putuser.S linux-2.6.28.8/arch/x86/lib/putuser.S |
11416 |
+--- linux-2.6.28.8/arch/x86/lib/putuser.S 2009-02-06 16:47:45.000000000 -0500 |
11417 |
++++ linux-2.6.28.8/arch/x86/lib/putuser.S 2009-02-21 09:37:48.000000000 -0500 |
11418 |
+@@ -15,6 +15,7 @@ |
11419 |
+ #include <asm/thread_info.h> |
11420 |
+ #include <asm/errno.h> |
11421 |
+ #include <asm/asm.h> |
11422 |
++#include <asm/segment.h> |
11423 |
+ |
11424 |
+ |
11425 |
+ /* |
11426 |
+@@ -39,7 +40,19 @@ ENTRY(__put_user_1) |
11427 |
+ ENTER |
11428 |
+ cmp TI_addr_limit(%_ASM_BX),%_ASM_CX |
11429 |
+ jae bad_put_user |
11430 |
++ |
11431 |
++#ifdef CONFIG_X86_32 |
11432 |
++ pushl $(__USER_DS) |
11433 |
++ popl %ds |
11434 |
++#endif |
11435 |
++ |
11436 |
+ 1: movb %al,(%_ASM_CX) |
11437 |
++ |
11438 |
++#ifdef CONFIG_X86_32 |
11439 |
++ pushl %ss |
11440 |
++ popl %ds |
11441 |
++#endif |
11442 |
++ |
11443 |
+ xor %eax,%eax |
11444 |
+ EXIT |
11445 |
+ ENDPROC(__put_user_1) |
11446 |
+@@ -50,7 +63,19 @@ ENTRY(__put_user_2) |
11447 |
+ sub $1,%_ASM_BX |
11448 |
+ cmp %_ASM_BX,%_ASM_CX |
11449 |
+ jae bad_put_user |
11450 |
++ |
11451 |
++#ifdef CONFIG_X86_32 |
11452 |
++ pushl $(__USER_DS) |
11453 |
++ popl %ds |
11454 |
++#endif |
11455 |
++ |
11456 |
+ 2: movw %ax,(%_ASM_CX) |
11457 |
++ |
11458 |
++#ifdef CONFIG_X86_32 |
11459 |
++ pushl %ss |
11460 |
++ popl %ds |
11461 |
++#endif |
11462 |
++ |
11463 |
+ xor %eax,%eax |
11464 |
+ EXIT |
11465 |
+ ENDPROC(__put_user_2) |
11466 |
+@@ -61,7 +86,19 @@ ENTRY(__put_user_4) |
11467 |
+ sub $3,%_ASM_BX |
11468 |
+ cmp %_ASM_BX,%_ASM_CX |
11469 |
+ jae bad_put_user |
11470 |
++ |
11471 |
++#ifdef CONFIG_X86_32 |
11472 |
++ pushl $(__USER_DS) |
11473 |
++ popl %ds |
11474 |
++#endif |
11475 |
++ |
11476 |
+ 3: movl %eax,(%_ASM_CX) |
11477 |
++ |
11478 |
++#ifdef CONFIG_X86_32 |
11479 |
++ pushl %ss |
11480 |
++ popl %ds |
11481 |
++#endif |
11482 |
++ |
11483 |
+ xor %eax,%eax |
11484 |
+ EXIT |
11485 |
+ ENDPROC(__put_user_4) |
11486 |
+@@ -72,16 +109,34 @@ ENTRY(__put_user_8) |
11487 |
+ sub $7,%_ASM_BX |
11488 |
+ cmp %_ASM_BX,%_ASM_CX |
11489 |
+ jae bad_put_user |
11490 |
++ |
11491 |
++#ifdef CONFIG_X86_32 |
11492 |
++ pushl $(__USER_DS) |
11493 |
++ popl %ds |
11494 |
++#endif |
11495 |
++ |
11496 |
+ 4: mov %_ASM_AX,(%_ASM_CX) |
11497 |
+ #ifdef CONFIG_X86_32 |
11498 |
+ 5: movl %edx,4(%_ASM_CX) |
11499 |
+ #endif |
11500 |
++ |
11501 |
++#ifdef CONFIG_X86_32 |
11502 |
++ pushl %ss |
11503 |
++ popl %ds |
11504 |
++#endif |
11505 |
++ |
11506 |
+ xor %eax,%eax |
11507 |
+ EXIT |
11508 |
+ ENDPROC(__put_user_8) |
11509 |
+ |
11510 |
+ bad_put_user: |
11511 |
+ CFI_STARTPROC |
11512 |
++ |
11513 |
++#ifdef CONFIG_X86_32 |
11514 |
++ pushl %ss |
11515 |
++ popl %ds |
11516 |
++#endif |
11517 |
++ |
11518 |
+ movl $-EFAULT,%eax |
11519 |
+ EXIT |
11520 |
+ END(bad_put_user) |
11521 |
+diff -urNp linux-2.6.28.8/arch/x86/lib/usercopy_32.c linux-2.6.28.8/arch/x86/lib/usercopy_32.c |
11522 |
+--- linux-2.6.28.8/arch/x86/lib/usercopy_32.c 2009-02-06 16:47:45.000000000 -0500 |
11523 |
++++ linux-2.6.28.8/arch/x86/lib/usercopy_32.c 2009-02-21 09:39:27.000000000 -0500 |
11524 |
+@@ -36,31 +36,38 @@ static inline int __movsl_is_ok(unsigned |
11525 |
+ * Copy a null terminated string from userspace. |
11526 |
+ */ |
11527 |
+ |
11528 |
+-#define __do_strncpy_from_user(dst, src, count, res) \ |
11529 |
+-do { \ |
11530 |
+- int __d0, __d1, __d2; \ |
11531 |
+- might_sleep(); \ |
11532 |
+- __asm__ __volatile__( \ |
11533 |
+- " testl %1,%1\n" \ |
11534 |
+- " jz 2f\n" \ |
11535 |
+- "0: lodsb\n" \ |
11536 |
+- " stosb\n" \ |
11537 |
+- " testb %%al,%%al\n" \ |
11538 |
+- " jz 1f\n" \ |
11539 |
+- " decl %1\n" \ |
11540 |
+- " jnz 0b\n" \ |
11541 |
+- "1: subl %1,%0\n" \ |
11542 |
+- "2:\n" \ |
11543 |
+- ".section .fixup,\"ax\"\n" \ |
11544 |
+- "3: movl %5,%0\n" \ |
11545 |
+- " jmp 2b\n" \ |
11546 |
+- ".previous\n" \ |
11547 |
+- _ASM_EXTABLE(0b,3b) \ |
11548 |
+- : "=&d"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1), \ |
11549 |
+- "=&D" (__d2) \ |
11550 |
+- : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \ |
11551 |
+- : "memory"); \ |
11552 |
+-} while (0) |
11553 |
++static long __do_strncpy_from_user(char *dst, const char __user *src, long count) |
11554 |
++{ |
11555 |
++ int __d0, __d1, __d2; |
11556 |
++ long res = -EFAULT; |
11557 |
++ |
11558 |
++ might_sleep(); |
11559 |
++ __asm__ __volatile__( |
11560 |
++ " movw %w10,%%ds\n" |
11561 |
++ " testl %1,%1\n" |
11562 |
++ " jz 2f\n" |
11563 |
++ "0: lodsb\n" |
11564 |
++ " stosb\n" |
11565 |
++ " testb %%al,%%al\n" |
11566 |
++ " jz 1f\n" |
11567 |
++ " decl %1\n" |
11568 |
++ " jnz 0b\n" |
11569 |
++ "1: subl %1,%0\n" |
11570 |
++ "2:\n" |
11571 |
++ " pushl %%ss\n" |
11572 |
++ " popl %%ds\n" |
11573 |
++ ".section .fixup,\"ax\"\n" |
11574 |
++ "3: movl %5,%0\n" |
11575 |
++ " jmp 2b\n" |
11576 |
++ ".previous\n" |
11577 |
++ _ASM_EXTABLE(0b,3b) |
11578 |
++ : "=&d"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1), |
11579 |
++ "=&D" (__d2) |
11580 |
++ : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst), |
11581 |
++ "r"(__USER_DS) |
11582 |
++ : "memory"); |
11583 |
++ return res; |
11584 |
++} |
11585 |
+ |
11586 |
+ /** |
11587 |
+ * __strncpy_from_user: - Copy a NUL terminated string from userspace, with less checking. |
11588 |
+@@ -85,9 +92,7 @@ do { \ |
11589 |
+ long |
11590 |
+ __strncpy_from_user(char *dst, const char __user *src, long count) |
11591 |
+ { |
11592 |
+- long res; |
11593 |
+- __do_strncpy_from_user(dst, src, count, res); |
11594 |
+- return res; |
11595 |
++ return __do_strncpy_from_user(dst, src, count); |
11596 |
+ } |
11597 |
+ EXPORT_SYMBOL(__strncpy_from_user); |
11598 |
+ |
11599 |
+@@ -114,7 +119,7 @@ strncpy_from_user(char *dst, const char |
11600 |
+ { |
11601 |
+ long res = -EFAULT; |
11602 |
+ if (access_ok(VERIFY_READ, src, 1)) |
11603 |
+- __do_strncpy_from_user(dst, src, count, res); |
11604 |
++ res = __do_strncpy_from_user(dst, src, count); |
11605 |
+ return res; |
11606 |
+ } |
11607 |
+ EXPORT_SYMBOL(strncpy_from_user); |
11608 |
+@@ -123,24 +128,30 @@ EXPORT_SYMBOL(strncpy_from_user); |
11609 |
+ * Zero Userspace |
11610 |
+ */ |
11611 |
+ |
11612 |
+-#define __do_clear_user(addr,size) \ |
11613 |
+-do { \ |
11614 |
+- int __d0; \ |
11615 |
+- might_sleep(); \ |
11616 |
+- __asm__ __volatile__( \ |
11617 |
+- "0: rep; stosl\n" \ |
11618 |
+- " movl %2,%0\n" \ |
11619 |
+- "1: rep; stosb\n" \ |
11620 |
+- "2:\n" \ |
11621 |
+- ".section .fixup,\"ax\"\n" \ |
11622 |
+- "3: lea 0(%2,%0,4),%0\n" \ |
11623 |
+- " jmp 2b\n" \ |
11624 |
+- ".previous\n" \ |
11625 |
+- _ASM_EXTABLE(0b,3b) \ |
11626 |
+- _ASM_EXTABLE(1b,2b) \ |
11627 |
+- : "=&c"(size), "=&D" (__d0) \ |
11628 |
+- : "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0)); \ |
11629 |
+-} while (0) |
11630 |
++static unsigned long __do_clear_user(void __user *addr, unsigned long size) |
11631 |
++{ |
11632 |
++ int __d0; |
11633 |
++ |
11634 |
++ might_sleep(); |
11635 |
++ __asm__ __volatile__( |
11636 |
++ " movw %w6,%%es\n" |
11637 |
++ "0: rep; stosl\n" |
11638 |
++ " movl %2,%0\n" |
11639 |
++ "1: rep; stosb\n" |
11640 |
++ "2:\n" |
11641 |
++ " pushl %%ss\n" |
11642 |
++ " popl %%es\n" |
11643 |
++ ".section .fixup,\"ax\"\n" |
11644 |
++ "3: lea 0(%2,%0,4),%0\n" |
11645 |
++ " jmp 2b\n" |
11646 |
++ ".previous\n" |
11647 |
++ _ASM_EXTABLE(0b,3b) |
11648 |
++ _ASM_EXTABLE(1b,2b) |
11649 |
++ : "=&c"(size), "=&D" (__d0) |
11650 |
++ : "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0), |
11651 |
++ "r"(__USER_DS)); |
11652 |
++ return size; |
11653 |
++} |
11654 |
+ |
11655 |
+ /** |
11656 |
+ * clear_user: - Zero a block of memory in user space. |
11657 |
+@@ -157,7 +168,7 @@ clear_user(void __user *to, unsigned lon |
11658 |
+ { |
11659 |
+ might_sleep(); |
11660 |
+ if (access_ok(VERIFY_WRITE, to, n)) |
11661 |
+- __do_clear_user(to, n); |
11662 |
++ n = __do_clear_user(to, n); |
11663 |
+ return n; |
11664 |
+ } |
11665 |
+ EXPORT_SYMBOL(clear_user); |
11666 |
+@@ -176,8 +187,7 @@ EXPORT_SYMBOL(clear_user); |
11667 |
+ unsigned long |
11668 |
+ __clear_user(void __user *to, unsigned long n) |
11669 |
+ { |
11670 |
+- __do_clear_user(to, n); |
11671 |
+- return n; |
11672 |
++ return __do_clear_user(to, n); |
11673 |
+ } |
11674 |
+ EXPORT_SYMBOL(__clear_user); |
11675 |
+ |
11676 |
+@@ -200,14 +210,17 @@ long strnlen_user(const char __user *s, |
11677 |
+ might_sleep(); |
11678 |
+ |
11679 |
+ __asm__ __volatile__( |
11680 |
++ " movw %w8,%%es\n" |
11681 |
+ " testl %0, %0\n" |
11682 |
+ " jz 3f\n" |
11683 |
+- " andl %0,%%ecx\n" |
11684 |
++ " movl %0,%%ecx\n" |
11685 |
+ "0: repne; scasb\n" |
11686 |
+ " setne %%al\n" |
11687 |
+ " subl %%ecx,%0\n" |
11688 |
+ " addl %0,%%eax\n" |
11689 |
+ "1:\n" |
11690 |
++ " pushl %%ss\n" |
11691 |
++ " popl %%es\n" |
11692 |
+ ".section .fixup,\"ax\"\n" |
11693 |
+ "2: xorl %%eax,%%eax\n" |
11694 |
+ " jmp 1b\n" |
11695 |
+@@ -219,7 +232,7 @@ long strnlen_user(const char __user *s, |
11696 |
+ " .long 0b,2b\n" |
11697 |
+ ".previous" |
11698 |
+ :"=&r" (n), "=&D" (s), "=&a" (res), "=&c" (tmp) |
11699 |
+- :"0" (n), "1" (s), "2" (0), "3" (mask) |
11700 |
++ :"0" (n), "1" (s), "2" (0), "3" (mask), "r" (__USER_DS) |
11701 |
+ :"cc"); |
11702 |
+ return res & mask; |
11703 |
+ } |
11704 |
+@@ -227,10 +240,11 @@ EXPORT_SYMBOL(strnlen_user); |
11705 |
+ |
11706 |
+ #ifdef CONFIG_X86_INTEL_USERCOPY |
11707 |
+ static unsigned long |
11708 |
+-__copy_user_intel(void __user *to, const void *from, unsigned long size) |
11709 |
++__generic_copy_to_user_intel(void __user *to, const void *from, unsigned long size) |
11710 |
+ { |
11711 |
+ int d0, d1; |
11712 |
+ __asm__ __volatile__( |
11713 |
++ " movw %w6, %%es\n" |
11714 |
+ " .align 2,0x90\n" |
11715 |
+ "1: movl 32(%4), %%eax\n" |
11716 |
+ " cmpl $67, %0\n" |
11717 |
+@@ -239,36 +253,36 @@ __copy_user_intel(void __user *to, const |
11718 |
+ " .align 2,0x90\n" |
11719 |
+ "3: movl 0(%4), %%eax\n" |
11720 |
+ "4: movl 4(%4), %%edx\n" |
11721 |
+- "5: movl %%eax, 0(%3)\n" |
11722 |
+- "6: movl %%edx, 4(%3)\n" |
11723 |
++ "5: movl %%eax, %%es:0(%3)\n" |
11724 |
++ "6: movl %%edx, %%es:4(%3)\n" |
11725 |
+ "7: movl 8(%4), %%eax\n" |
11726 |
+ "8: movl 12(%4),%%edx\n" |
11727 |
+- "9: movl %%eax, 8(%3)\n" |
11728 |
+- "10: movl %%edx, 12(%3)\n" |
11729 |
++ "9: movl %%eax, %%es:8(%3)\n" |
11730 |
++ "10: movl %%edx, %%es:12(%3)\n" |
11731 |
+ "11: movl 16(%4), %%eax\n" |
11732 |
+ "12: movl 20(%4), %%edx\n" |
11733 |
+- "13: movl %%eax, 16(%3)\n" |
11734 |
+- "14: movl %%edx, 20(%3)\n" |
11735 |
++ "13: movl %%eax, %%es:16(%3)\n" |
11736 |
++ "14: movl %%edx, %%es:20(%3)\n" |
11737 |
+ "15: movl 24(%4), %%eax\n" |
11738 |
+ "16: movl 28(%4), %%edx\n" |
11739 |
+- "17: movl %%eax, 24(%3)\n" |
11740 |
+- "18: movl %%edx, 28(%3)\n" |
11741 |
++ "17: movl %%eax, %%es:24(%3)\n" |
11742 |
++ "18: movl %%edx, %%es:28(%3)\n" |
11743 |
+ "19: movl 32(%4), %%eax\n" |
11744 |
+ "20: movl 36(%4), %%edx\n" |
11745 |
+- "21: movl %%eax, 32(%3)\n" |
11746 |
+- "22: movl %%edx, 36(%3)\n" |
11747 |
++ "21: movl %%eax, %%es:32(%3)\n" |
11748 |
++ "22: movl %%edx, %%es:36(%3)\n" |
11749 |
+ "23: movl 40(%4), %%eax\n" |
11750 |
+ "24: movl 44(%4), %%edx\n" |
11751 |
+- "25: movl %%eax, 40(%3)\n" |
11752 |
+- "26: movl %%edx, 44(%3)\n" |
11753 |
++ "25: movl %%eax, %%es:40(%3)\n" |
11754 |
++ "26: movl %%edx, %%es:44(%3)\n" |
11755 |
+ "27: movl 48(%4), %%eax\n" |
11756 |
+ "28: movl 52(%4), %%edx\n" |
11757 |
+- "29: movl %%eax, 48(%3)\n" |
11758 |
+- "30: movl %%edx, 52(%3)\n" |
11759 |
++ "29: movl %%eax, %%es:48(%3)\n" |
11760 |
++ "30: movl %%edx, %%es:52(%3)\n" |
11761 |
+ "31: movl 56(%4), %%eax\n" |
11762 |
+ "32: movl 60(%4), %%edx\n" |
11763 |
+- "33: movl %%eax, 56(%3)\n" |
11764 |
+- "34: movl %%edx, 60(%3)\n" |
11765 |
++ "33: movl %%eax, %%es:56(%3)\n" |
11766 |
++ "34: movl %%edx, %%es:60(%3)\n" |
11767 |
+ " addl $-64, %0\n" |
11768 |
+ " addl $64, %4\n" |
11769 |
+ " addl $64, %3\n" |
11770 |
+@@ -282,6 +296,8 @@ __copy_user_intel(void __user *to, const |
11771 |
+ "36: movl %%eax, %0\n" |
11772 |
+ "37: rep; movsb\n" |
11773 |
+ "100:\n" |
11774 |
++ " pushl %%ss\n" |
11775 |
++ " popl %%es\n" |
11776 |
+ ".section .fixup,\"ax\"\n" |
11777 |
+ "101: lea 0(%%eax,%0,4),%0\n" |
11778 |
+ " jmp 100b\n" |
11779 |
+@@ -328,7 +344,117 @@ __copy_user_intel(void __user *to, const |
11780 |
+ " .long 99b,101b\n" |
11781 |
+ ".previous" |
11782 |
+ : "=&c"(size), "=&D" (d0), "=&S" (d1) |
11783 |
+- : "1"(to), "2"(from), "0"(size) |
11784 |
++ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS) |
11785 |
++ : "eax", "edx", "memory"); |
11786 |
++ return size; |
11787 |
++} |
11788 |
++ |
11789 |
++static unsigned long |
11790 |
++__generic_copy_from_user_intel(void *to, const void __user *from, unsigned long size) |
11791 |
++{ |
11792 |
++ int d0, d1; |
11793 |
++ __asm__ __volatile__( |
11794 |
++ " movw %w6, %%ds\n" |
11795 |
++ " .align 2,0x90\n" |
11796 |
++ "1: movl 32(%4), %%eax\n" |
11797 |
++ " cmpl $67, %0\n" |
11798 |
++ " jbe 3f\n" |
11799 |
++ "2: movl 64(%4), %%eax\n" |
11800 |
++ " .align 2,0x90\n" |
11801 |
++ "3: movl 0(%4), %%eax\n" |
11802 |
++ "4: movl 4(%4), %%edx\n" |
11803 |
++ "5: movl %%eax, %%es:0(%3)\n" |
11804 |
++ "6: movl %%edx, %%es:4(%3)\n" |
11805 |
++ "7: movl 8(%4), %%eax\n" |
11806 |
++ "8: movl 12(%4),%%edx\n" |
11807 |
++ "9: movl %%eax, %%es:8(%3)\n" |
11808 |
++ "10: movl %%edx, %%es:12(%3)\n" |
11809 |
++ "11: movl 16(%4), %%eax\n" |
11810 |
++ "12: movl 20(%4), %%edx\n" |
11811 |
++ "13: movl %%eax, %%es:16(%3)\n" |
11812 |
++ "14: movl %%edx, %%es:20(%3)\n" |
11813 |
++ "15: movl 24(%4), %%eax\n" |
11814 |
++ "16: movl 28(%4), %%edx\n" |
11815 |
++ "17: movl %%eax, %%es:24(%3)\n" |
11816 |
++ "18: movl %%edx, %%es:28(%3)\n" |
11817 |
++ "19: movl 32(%4), %%eax\n" |
11818 |
++ "20: movl 36(%4), %%edx\n" |
11819 |
++ "21: movl %%eax, %%es:32(%3)\n" |
11820 |
++ "22: movl %%edx, %%es:36(%3)\n" |
11821 |
++ "23: movl 40(%4), %%eax\n" |
11822 |
++ "24: movl 44(%4), %%edx\n" |
11823 |
++ "25: movl %%eax, %%es:40(%3)\n" |
11824 |
++ "26: movl %%edx, %%es:44(%3)\n" |
11825 |
++ "27: movl 48(%4), %%eax\n" |
11826 |
++ "28: movl 52(%4), %%edx\n" |
11827 |
++ "29: movl %%eax, %%es:48(%3)\n" |
11828 |
++ "30: movl %%edx, %%es:52(%3)\n" |
11829 |
++ "31: movl 56(%4), %%eax\n" |
11830 |
++ "32: movl 60(%4), %%edx\n" |
11831 |
++ "33: movl %%eax, %%es:56(%3)\n" |
11832 |
++ "34: movl %%edx, %%es:60(%3)\n" |
11833 |
++ " addl $-64, %0\n" |
11834 |
++ " addl $64, %4\n" |
11835 |
++ " addl $64, %3\n" |
11836 |
++ " cmpl $63, %0\n" |
11837 |
++ " ja 1b\n" |
11838 |
++ "35: movl %0, %%eax\n" |
11839 |
++ " shrl $2, %0\n" |
11840 |
++ " andl $3, %%eax\n" |
11841 |
++ " cld\n" |
11842 |
++ "99: rep; movsl\n" |
11843 |
++ "36: movl %%eax, %0\n" |
11844 |
++ "37: rep; movsb\n" |
11845 |
++ "100:\n" |
11846 |
++ " pushl %%ss\n" |
11847 |
++ " popl %%ds\n" |
11848 |
++ ".section .fixup,\"ax\"\n" |
11849 |
++ "101: lea 0(%%eax,%0,4),%0\n" |
11850 |
++ " jmp 100b\n" |
11851 |
++ ".previous\n" |
11852 |
++ ".section __ex_table,\"a\"\n" |
11853 |
++ " .align 4\n" |
11854 |
++ " .long 1b,100b\n" |
11855 |
++ " .long 2b,100b\n" |
11856 |
++ " .long 3b,100b\n" |
11857 |
++ " .long 4b,100b\n" |
11858 |
++ " .long 5b,100b\n" |
11859 |
++ " .long 6b,100b\n" |
11860 |
++ " .long 7b,100b\n" |
11861 |
++ " .long 8b,100b\n" |
11862 |
++ " .long 9b,100b\n" |
11863 |
++ " .long 10b,100b\n" |
11864 |
++ " .long 11b,100b\n" |
11865 |
++ " .long 12b,100b\n" |
11866 |
++ " .long 13b,100b\n" |
11867 |
++ " .long 14b,100b\n" |
11868 |
++ " .long 15b,100b\n" |
11869 |
++ " .long 16b,100b\n" |
11870 |
++ " .long 17b,100b\n" |
11871 |
++ " .long 18b,100b\n" |
11872 |
++ " .long 19b,100b\n" |
11873 |
++ " .long 20b,100b\n" |
11874 |
++ " .long 21b,100b\n" |
11875 |
++ " .long 22b,100b\n" |
11876 |
++ " .long 23b,100b\n" |
11877 |
++ " .long 24b,100b\n" |
11878 |
++ " .long 25b,100b\n" |
11879 |
++ " .long 26b,100b\n" |
11880 |
++ " .long 27b,100b\n" |
11881 |
++ " .long 28b,100b\n" |
11882 |
++ " .long 29b,100b\n" |
11883 |
++ " .long 30b,100b\n" |
11884 |
++ " .long 31b,100b\n" |
11885 |
++ " .long 32b,100b\n" |
11886 |
++ " .long 33b,100b\n" |
11887 |
++ " .long 34b,100b\n" |
11888 |
++ " .long 35b,100b\n" |
11889 |
++ " .long 36b,100b\n" |
11890 |
++ " .long 37b,100b\n" |
11891 |
++ " .long 99b,101b\n" |
11892 |
++ ".previous" |
11893 |
++ : "=&c"(size), "=&D" (d0), "=&S" (d1) |
11894 |
++ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS) |
11895 |
+ : "eax", "edx", "memory"); |
11896 |
+ return size; |
11897 |
+ } |
11898 |
+@@ -338,6 +464,7 @@ __copy_user_zeroing_intel(void *to, cons |
11899 |
+ { |
11900 |
+ int d0, d1; |
11901 |
+ __asm__ __volatile__( |
11902 |
++ " movw %w6, %%ds\n" |
11903 |
+ " .align 2,0x90\n" |
11904 |
+ "0: movl 32(%4), %%eax\n" |
11905 |
+ " cmpl $67, %0\n" |
11906 |
+@@ -346,36 +473,36 @@ __copy_user_zeroing_intel(void *to, cons |
11907 |
+ " .align 2,0x90\n" |
11908 |
+ "2: movl 0(%4), %%eax\n" |
11909 |
+ "21: movl 4(%4), %%edx\n" |
11910 |
+- " movl %%eax, 0(%3)\n" |
11911 |
+- " movl %%edx, 4(%3)\n" |
11912 |
++ " movl %%eax, %%es:0(%3)\n" |
11913 |
++ " movl %%edx, %%es:4(%3)\n" |
11914 |
+ "3: movl 8(%4), %%eax\n" |
11915 |
+ "31: movl 12(%4),%%edx\n" |
11916 |
+- " movl %%eax, 8(%3)\n" |
11917 |
+- " movl %%edx, 12(%3)\n" |
11918 |
++ " movl %%eax, %%es:8(%3)\n" |
11919 |
++ " movl %%edx, %%es:12(%3)\n" |
11920 |
+ "4: movl 16(%4), %%eax\n" |
11921 |
+ "41: movl 20(%4), %%edx\n" |
11922 |
+- " movl %%eax, 16(%3)\n" |
11923 |
+- " movl %%edx, 20(%3)\n" |
11924 |
++ " movl %%eax, %%es:16(%3)\n" |
11925 |
++ " movl %%edx, %%es:20(%3)\n" |
11926 |
+ "10: movl 24(%4), %%eax\n" |
11927 |
+ "51: movl 28(%4), %%edx\n" |
11928 |
+- " movl %%eax, 24(%3)\n" |
11929 |
+- " movl %%edx, 28(%3)\n" |
11930 |
++ " movl %%eax, %%es:24(%3)\n" |
11931 |
++ " movl %%edx, %%es:28(%3)\n" |
11932 |
+ "11: movl 32(%4), %%eax\n" |
11933 |
+ "61: movl 36(%4), %%edx\n" |
11934 |
+- " movl %%eax, 32(%3)\n" |
11935 |
+- " movl %%edx, 36(%3)\n" |
11936 |
++ " movl %%eax, %%es:32(%3)\n" |
11937 |
++ " movl %%edx, %%es:36(%3)\n" |
11938 |
+ "12: movl 40(%4), %%eax\n" |
11939 |
+ "71: movl 44(%4), %%edx\n" |
11940 |
+- " movl %%eax, 40(%3)\n" |
11941 |
+- " movl %%edx, 44(%3)\n" |
11942 |
++ " movl %%eax, %%es:40(%3)\n" |
11943 |
++ " movl %%edx, %%es:44(%3)\n" |
11944 |
+ "13: movl 48(%4), %%eax\n" |
11945 |
+ "81: movl 52(%4), %%edx\n" |
11946 |
+- " movl %%eax, 48(%3)\n" |
11947 |
+- " movl %%edx, 52(%3)\n" |
11948 |
++ " movl %%eax, %%es:48(%3)\n" |
11949 |
++ " movl %%edx, %%es:52(%3)\n" |
11950 |
+ "14: movl 56(%4), %%eax\n" |
11951 |
+ "91: movl 60(%4), %%edx\n" |
11952 |
+- " movl %%eax, 56(%3)\n" |
11953 |
+- " movl %%edx, 60(%3)\n" |
11954 |
++ " movl %%eax, %%es:56(%3)\n" |
11955 |
++ " movl %%edx, %%es:60(%3)\n" |
11956 |
+ " addl $-64, %0\n" |
11957 |
+ " addl $64, %4\n" |
11958 |
+ " addl $64, %3\n" |
11959 |
+@@ -389,6 +516,8 @@ __copy_user_zeroing_intel(void *to, cons |
11960 |
+ " movl %%eax,%0\n" |
11961 |
+ "7: rep; movsb\n" |
11962 |
+ "8:\n" |
11963 |
++ " pushl %%ss\n" |
11964 |
++ " popl %%ds\n" |
11965 |
+ ".section .fixup,\"ax\"\n" |
11966 |
+ "9: lea 0(%%eax,%0,4),%0\n" |
11967 |
+ "16: pushl %0\n" |
11968 |
+@@ -423,7 +552,7 @@ __copy_user_zeroing_intel(void *to, cons |
11969 |
+ " .long 7b,16b\n" |
11970 |
+ ".previous" |
11971 |
+ : "=&c"(size), "=&D" (d0), "=&S" (d1) |
11972 |
+- : "1"(to), "2"(from), "0"(size) |
11973 |
++ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS) |
11974 |
+ : "eax", "edx", "memory"); |
11975 |
+ return size; |
11976 |
+ } |
11977 |
+@@ -439,6 +568,7 @@ static unsigned long __copy_user_zeroing |
11978 |
+ int d0, d1; |
11979 |
+ |
11980 |
+ __asm__ __volatile__( |
11981 |
++ " movw %w6, %%ds\n" |
11982 |
+ " .align 2,0x90\n" |
11983 |
+ "0: movl 32(%4), %%eax\n" |
11984 |
+ " cmpl $67, %0\n" |
11985 |
+@@ -447,36 +577,36 @@ static unsigned long __copy_user_zeroing |
11986 |
+ " .align 2,0x90\n" |
11987 |
+ "2: movl 0(%4), %%eax\n" |
11988 |
+ "21: movl 4(%4), %%edx\n" |
11989 |
+- " movnti %%eax, 0(%3)\n" |
11990 |
+- " movnti %%edx, 4(%3)\n" |
11991 |
++ " movnti %%eax, %%es:0(%3)\n" |
11992 |
++ " movnti %%edx, %%es:4(%3)\n" |
11993 |
+ "3: movl 8(%4), %%eax\n" |
11994 |
+ "31: movl 12(%4),%%edx\n" |
11995 |
+- " movnti %%eax, 8(%3)\n" |
11996 |
+- " movnti %%edx, 12(%3)\n" |
11997 |
++ " movnti %%eax, %%es:8(%3)\n" |
11998 |
++ " movnti %%edx, %%es:12(%3)\n" |
11999 |
+ "4: movl 16(%4), %%eax\n" |
12000 |
+ "41: movl 20(%4), %%edx\n" |
12001 |
+- " movnti %%eax, 16(%3)\n" |
12002 |
+- " movnti %%edx, 20(%3)\n" |
12003 |
++ " movnti %%eax, %%es:16(%3)\n" |
12004 |
++ " movnti %%edx, %%es:20(%3)\n" |
12005 |
+ "10: movl 24(%4), %%eax\n" |
12006 |
+ "51: movl 28(%4), %%edx\n" |
12007 |
+- " movnti %%eax, 24(%3)\n" |
12008 |
+- " movnti %%edx, 28(%3)\n" |
12009 |
++ " movnti %%eax, %%es:24(%3)\n" |
12010 |
++ " movnti %%edx, %%es:28(%3)\n" |
12011 |
+ "11: movl 32(%4), %%eax\n" |
12012 |
+ "61: movl 36(%4), %%edx\n" |
12013 |
+- " movnti %%eax, 32(%3)\n" |
12014 |
+- " movnti %%edx, 36(%3)\n" |
12015 |
++ " movnti %%eax, %%es:32(%3)\n" |
12016 |
++ " movnti %%edx, %%es:36(%3)\n" |
12017 |
+ "12: movl 40(%4), %%eax\n" |
12018 |
+ "71: movl 44(%4), %%edx\n" |
12019 |
+- " movnti %%eax, 40(%3)\n" |
12020 |
+- " movnti %%edx, 44(%3)\n" |
12021 |
++ " movnti %%eax, %%es:40(%3)\n" |
12022 |
++ " movnti %%edx, %%es:44(%3)\n" |
12023 |
+ "13: movl 48(%4), %%eax\n" |
12024 |
+ "81: movl 52(%4), %%edx\n" |
12025 |
+- " movnti %%eax, 48(%3)\n" |
12026 |
+- " movnti %%edx, 52(%3)\n" |
12027 |
++ " movnti %%eax, %%es:48(%3)\n" |
12028 |
++ " movnti %%edx, %%es:52(%3)\n" |
12029 |
+ "14: movl 56(%4), %%eax\n" |
12030 |
+ "91: movl 60(%4), %%edx\n" |
12031 |
+- " movnti %%eax, 56(%3)\n" |
12032 |
+- " movnti %%edx, 60(%3)\n" |
12033 |
++ " movnti %%eax, %%es:56(%3)\n" |
12034 |
++ " movnti %%edx, %%es:60(%3)\n" |
12035 |
+ " addl $-64, %0\n" |
12036 |
+ " addl $64, %4\n" |
12037 |
+ " addl $64, %3\n" |
12038 |
+@@ -491,6 +621,8 @@ static unsigned long __copy_user_zeroing |
12039 |
+ " movl %%eax,%0\n" |
12040 |
+ "7: rep; movsb\n" |
12041 |
+ "8:\n" |
12042 |
++ " pushl %%ss\n" |
12043 |
++ " popl %%ds\n" |
12044 |
+ ".section .fixup,\"ax\"\n" |
12045 |
+ "9: lea 0(%%eax,%0,4),%0\n" |
12046 |
+ "16: pushl %0\n" |
12047 |
+@@ -525,7 +657,7 @@ static unsigned long __copy_user_zeroing |
12048 |
+ " .long 7b,16b\n" |
12049 |
+ ".previous" |
12050 |
+ : "=&c"(size), "=&D" (d0), "=&S" (d1) |
12051 |
+- : "1"(to), "2"(from), "0"(size) |
12052 |
++ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS) |
12053 |
+ : "eax", "edx", "memory"); |
12054 |
+ return size; |
12055 |
+ } |
12056 |
+@@ -536,6 +668,7 @@ static unsigned long __copy_user_intel_n |
12057 |
+ int d0, d1; |
12058 |
+ |
12059 |
+ __asm__ __volatile__( |
12060 |
++ " movw %w6, %%ds\n" |
12061 |
+ " .align 2,0x90\n" |
12062 |
+ "0: movl 32(%4), %%eax\n" |
12063 |
+ " cmpl $67, %0\n" |
12064 |
+@@ -544,36 +677,36 @@ static unsigned long __copy_user_intel_n |
12065 |
+ " .align 2,0x90\n" |
12066 |
+ "2: movl 0(%4), %%eax\n" |
12067 |
+ "21: movl 4(%4), %%edx\n" |
12068 |
+- " movnti %%eax, 0(%3)\n" |
12069 |
+- " movnti %%edx, 4(%3)\n" |
12070 |
++ " movnti %%eax, %%es:0(%3)\n" |
12071 |
++ " movnti %%edx, %%es:4(%3)\n" |
12072 |
+ "3: movl 8(%4), %%eax\n" |
12073 |
+ "31: movl 12(%4),%%edx\n" |
12074 |
+- " movnti %%eax, 8(%3)\n" |
12075 |
+- " movnti %%edx, 12(%3)\n" |
12076 |
++ " movnti %%eax, %%es:8(%3)\n" |
12077 |
++ " movnti %%edx, %%es:12(%3)\n" |
12078 |
+ "4: movl 16(%4), %%eax\n" |
12079 |
+ "41: movl 20(%4), %%edx\n" |
12080 |
+- " movnti %%eax, 16(%3)\n" |
12081 |
+- " movnti %%edx, 20(%3)\n" |
12082 |
++ " movnti %%eax, %%es:16(%3)\n" |
12083 |
++ " movnti %%edx, %%es:20(%3)\n" |
12084 |
+ "10: movl 24(%4), %%eax\n" |
12085 |
+ "51: movl 28(%4), %%edx\n" |
12086 |
+- " movnti %%eax, 24(%3)\n" |
12087 |
+- " movnti %%edx, 28(%3)\n" |
12088 |
++ " movnti %%eax, %%es:24(%3)\n" |
12089 |
++ " movnti %%edx, %%es:28(%3)\n" |
12090 |
+ "11: movl 32(%4), %%eax\n" |
12091 |
+ "61: movl 36(%4), %%edx\n" |
12092 |
+- " movnti %%eax, 32(%3)\n" |
12093 |
+- " movnti %%edx, 36(%3)\n" |
12094 |
++ " movnti %%eax, %%es:32(%3)\n" |
12095 |
++ " movnti %%edx, %%es:36(%3)\n" |
12096 |
+ "12: movl 40(%4), %%eax\n" |
12097 |
+ "71: movl 44(%4), %%edx\n" |
12098 |
+- " movnti %%eax, 40(%3)\n" |
12099 |
+- " movnti %%edx, 44(%3)\n" |
12100 |
++ " movnti %%eax, %%es:40(%3)\n" |
12101 |
++ " movnti %%edx, %%es:44(%3)\n" |
12102 |
+ "13: movl 48(%4), %%eax\n" |
12103 |
+ "81: movl 52(%4), %%edx\n" |
12104 |
+- " movnti %%eax, 48(%3)\n" |
12105 |
+- " movnti %%edx, 52(%3)\n" |
12106 |
++ " movnti %%eax, %%es:48(%3)\n" |
12107 |
++ " movnti %%edx, %%es:52(%3)\n" |
12108 |
+ "14: movl 56(%4), %%eax\n" |
12109 |
+ "91: movl 60(%4), %%edx\n" |
12110 |
+- " movnti %%eax, 56(%3)\n" |
12111 |
+- " movnti %%edx, 60(%3)\n" |
12112 |
++ " movnti %%eax, %%es:56(%3)\n" |
12113 |
++ " movnti %%edx, %%es:60(%3)\n" |
12114 |
+ " addl $-64, %0\n" |
12115 |
+ " addl $64, %4\n" |
12116 |
+ " addl $64, %3\n" |
12117 |
+@@ -588,6 +721,8 @@ static unsigned long __copy_user_intel_n |
12118 |
+ " movl %%eax,%0\n" |
12119 |
+ "7: rep; movsb\n" |
12120 |
+ "8:\n" |
12121 |
++ " pushl %%ss\n" |
12122 |
++ " popl %%ds\n" |
12123 |
+ ".section .fixup,\"ax\"\n" |
12124 |
+ "9: lea 0(%%eax,%0,4),%0\n" |
12125 |
+ "16: jmp 8b\n" |
12126 |
+@@ -616,7 +751,7 @@ static unsigned long __copy_user_intel_n |
12127 |
+ " .long 7b,16b\n" |
12128 |
+ ".previous" |
12129 |
+ : "=&c"(size), "=&D" (d0), "=&S" (d1) |
12130 |
+- : "1"(to), "2"(from), "0"(size) |
12131 |
++ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS) |
12132 |
+ : "eax", "edx", "memory"); |
12133 |
+ return size; |
12134 |
+ } |
12135 |
+@@ -629,90 +764,146 @@ static unsigned long __copy_user_intel_n |
12136 |
+ */ |
12137 |
+ unsigned long __copy_user_zeroing_intel(void *to, const void __user *from, |
12138 |
+ unsigned long size); |
12139 |
+-unsigned long __copy_user_intel(void __user *to, const void *from, |
12140 |
++unsigned long __generic_copy_to_user_intel(void __user *to, const void *from, |
12141 |
++ unsigned long size); |
12142 |
++unsigned long __generic_copy_from_user_intel(void *to, const void __user *from, |
12143 |
+ unsigned long size); |
12144 |
+ unsigned long __copy_user_zeroing_intel_nocache(void *to, |
12145 |
+ const void __user *from, unsigned long size); |
12146 |
+ #endif /* CONFIG_X86_INTEL_USERCOPY */ |
12147 |
+ |
12148 |
+ /* Generic arbitrary sized copy. */ |
12149 |
+-#define __copy_user(to, from, size) \ |
12150 |
+-do { \ |
12151 |
+- int __d0, __d1, __d2; \ |
12152 |
+- __asm__ __volatile__( \ |
12153 |
+- " cmp $7,%0\n" \ |
12154 |
+- " jbe 1f\n" \ |
12155 |
+- " movl %1,%0\n" \ |
12156 |
+- " negl %0\n" \ |
12157 |
+- " andl $7,%0\n" \ |
12158 |
+- " subl %0,%3\n" \ |
12159 |
+- "4: rep; movsb\n" \ |
12160 |
+- " movl %3,%0\n" \ |
12161 |
+- " shrl $2,%0\n" \ |
12162 |
+- " andl $3,%3\n" \ |
12163 |
+- " .align 2,0x90\n" \ |
12164 |
+- "0: rep; movsl\n" \ |
12165 |
+- " movl %3,%0\n" \ |
12166 |
+- "1: rep; movsb\n" \ |
12167 |
+- "2:\n" \ |
12168 |
+- ".section .fixup,\"ax\"\n" \ |
12169 |
+- "5: addl %3,%0\n" \ |
12170 |
+- " jmp 2b\n" \ |
12171 |
+- "3: lea 0(%3,%0,4),%0\n" \ |
12172 |
+- " jmp 2b\n" \ |
12173 |
+- ".previous\n" \ |
12174 |
+- ".section __ex_table,\"a\"\n" \ |
12175 |
+- " .align 4\n" \ |
12176 |
+- " .long 4b,5b\n" \ |
12177 |
+- " .long 0b,3b\n" \ |
12178 |
+- " .long 1b,2b\n" \ |
12179 |
+- ".previous" \ |
12180 |
+- : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \ |
12181 |
+- : "3"(size), "0"(size), "1"(to), "2"(from) \ |
12182 |
+- : "memory"); \ |
12183 |
+-} while (0) |
12184 |
+- |
12185 |
+-#define __copy_user_zeroing(to, from, size) \ |
12186 |
+-do { \ |
12187 |
+- int __d0, __d1, __d2; \ |
12188 |
+- __asm__ __volatile__( \ |
12189 |
+- " cmp $7,%0\n" \ |
12190 |
+- " jbe 1f\n" \ |
12191 |
+- " movl %1,%0\n" \ |
12192 |
+- " negl %0\n" \ |
12193 |
+- " andl $7,%0\n" \ |
12194 |
+- " subl %0,%3\n" \ |
12195 |
+- "4: rep; movsb\n" \ |
12196 |
+- " movl %3,%0\n" \ |
12197 |
+- " shrl $2,%0\n" \ |
12198 |
+- " andl $3,%3\n" \ |
12199 |
+- " .align 2,0x90\n" \ |
12200 |
+- "0: rep; movsl\n" \ |
12201 |
+- " movl %3,%0\n" \ |
12202 |
+- "1: rep; movsb\n" \ |
12203 |
+- "2:\n" \ |
12204 |
+- ".section .fixup,\"ax\"\n" \ |
12205 |
+- "5: addl %3,%0\n" \ |
12206 |
+- " jmp 6f\n" \ |
12207 |
+- "3: lea 0(%3,%0,4),%0\n" \ |
12208 |
+- "6: pushl %0\n" \ |
12209 |
+- " pushl %%eax\n" \ |
12210 |
+- " xorl %%eax,%%eax\n" \ |
12211 |
+- " rep; stosb\n" \ |
12212 |
+- " popl %%eax\n" \ |
12213 |
+- " popl %0\n" \ |
12214 |
+- " jmp 2b\n" \ |
12215 |
+- ".previous\n" \ |
12216 |
+- ".section __ex_table,\"a\"\n" \ |
12217 |
+- " .align 4\n" \ |
12218 |
+- " .long 4b,5b\n" \ |
12219 |
+- " .long 0b,3b\n" \ |
12220 |
+- " .long 1b,6b\n" \ |
12221 |
+- ".previous" \ |
12222 |
+- : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \ |
12223 |
+- : "3"(size), "0"(size), "1"(to), "2"(from) \ |
12224 |
+- : "memory"); \ |
12225 |
+-} while (0) |
12226 |
++static unsigned long |
12227 |
++__generic_copy_to_user(void __user *to, const void *from, unsigned long size) |
12228 |
++{ |
12229 |
++ int __d0, __d1, __d2; |
12230 |
++ |
12231 |
++ __asm__ __volatile__( |
12232 |
++ " movw %w8,%%es\n" |
12233 |
++ " cmp $7,%0\n" |
12234 |
++ " jbe 1f\n" |
12235 |
++ " movl %1,%0\n" |
12236 |
++ " negl %0\n" |
12237 |
++ " andl $7,%0\n" |
12238 |
++ " subl %0,%3\n" |
12239 |
++ "4: rep; movsb\n" |
12240 |
++ " movl %3,%0\n" |
12241 |
++ " shrl $2,%0\n" |
12242 |
++ " andl $3,%3\n" |
12243 |
++ " .align 2,0x90\n" |
12244 |
++ "0: rep; movsl\n" |
12245 |
++ " movl %3,%0\n" |
12246 |
++ "1: rep; movsb\n" |
12247 |
++ "2:\n" |
12248 |
++ " pushl %%ss\n" |
12249 |
++ " popl %%es\n" |
12250 |
++ ".section .fixup,\"ax\"\n" |
12251 |
++ "5: addl %3,%0\n" |
12252 |
++ " jmp 2b\n" |
12253 |
++ "3: lea 0(%3,%0,4),%0\n" |
12254 |
++ " jmp 2b\n" |
12255 |
++ ".previous\n" |
12256 |
++ ".section __ex_table,\"a\"\n" |
12257 |
++ " .align 4\n" |
12258 |
++ " .long 4b,5b\n" |
12259 |
++ " .long 0b,3b\n" |
12260 |
++ " .long 1b,2b\n" |
12261 |
++ ".previous" |
12262 |
++ : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) |
12263 |
++ : "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS) |
12264 |
++ : "memory"); |
12265 |
++ return size; |
12266 |
++} |
12267 |
++ |
12268 |
++static unsigned long |
12269 |
++__generic_copy_from_user(void *to, const void __user *from, unsigned long size) |
12270 |
++{ |
12271 |
++ int __d0, __d1, __d2; |
12272 |
++ |
12273 |
++ __asm__ __volatile__( |
12274 |
++ " movw %w8,%%ds\n" |
12275 |
++ " cmp $7,%0\n" |
12276 |
++ " jbe 1f\n" |
12277 |
++ " movl %1,%0\n" |
12278 |
++ " negl %0\n" |
12279 |
++ " andl $7,%0\n" |
12280 |
++ " subl %0,%3\n" |
12281 |
++ "4: rep; movsb\n" |
12282 |
++ " movl %3,%0\n" |
12283 |
++ " shrl $2,%0\n" |
12284 |
++ " andl $3,%3\n" |
12285 |
++ " .align 2,0x90\n" |
12286 |
++ "0: rep; movsl\n" |
12287 |
++ " movl %3,%0\n" |
12288 |
++ "1: rep; movsb\n" |
12289 |
++ "2:\n" |
12290 |
++ " pushl %%ss\n" |
12291 |
++ " popl %%ds\n" |
12292 |
++ ".section .fixup,\"ax\"\n" |
12293 |
++ "5: addl %3,%0\n" |
12294 |
++ " jmp 2b\n" |
12295 |
++ "3: lea 0(%3,%0,4),%0\n" |
12296 |
++ " jmp 2b\n" |
12297 |
++ ".previous\n" |
12298 |
++ ".section __ex_table,\"a\"\n" |
12299 |
++ " .align 4\n" |
12300 |
++ " .long 4b,5b\n" |
12301 |
++ " .long 0b,3b\n" |
12302 |
++ " .long 1b,2b\n" |
12303 |
++ ".previous" |
12304 |
++ : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) |
12305 |
++ : "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS) |
12306 |
++ : "memory"); |
12307 |
++ return size; |
12308 |
++} |
12309 |
++ |
12310 |
++static unsigned long |
12311 |
++__copy_user_zeroing(void *to, const void __user *from, unsigned long size) |
12312 |
++{ |
12313 |
++ int __d0, __d1, __d2; |
12314 |
++ |
12315 |
++ __asm__ __volatile__( |
12316 |
++ " movw %w8,%%ds\n" |
12317 |
++ " cmp $7,%0\n" |
12318 |
++ " jbe 1f\n" |
12319 |
++ " movl %1,%0\n" |
12320 |
++ " negl %0\n" |
12321 |
++ " andl $7,%0\n" |
12322 |
++ " subl %0,%3\n" |
12323 |
++ "4: rep; movsb\n" |
12324 |
++ " movl %3,%0\n" |
12325 |
++ " shrl $2,%0\n" |
12326 |
++ " andl $3,%3\n" |
12327 |
++ " .align 2,0x90\n" |
12328 |
++ "0: rep; movsl\n" |
12329 |
++ " movl %3,%0\n" |
12330 |
++ "1: rep; movsb\n" |
12331 |
++ "2:\n" |
12332 |
++ " pushl %%ss\n" |
12333 |
++ " popl %%ds\n" |
12334 |
++ ".section .fixup,\"ax\"\n" |
12335 |
++ "5: addl %3,%0\n" |
12336 |
++ " jmp 6f\n" |
12337 |
++ "3: lea 0(%3,%0,4),%0\n" |
12338 |
++ "6: pushl %0\n" |
12339 |
++ " pushl %%eax\n" |
12340 |
++ " xorl %%eax,%%eax\n" |
12341 |
++ " rep; stosb\n" |
12342 |
++ " popl %%eax\n" |
12343 |
++ " popl %0\n" |
12344 |
++ " jmp 2b\n" |
12345 |
++ ".previous\n" |
12346 |
++ ".section __ex_table,\"a\"\n" |
12347 |
++ " .align 4\n" |
12348 |
++ " .long 4b,5b\n" |
12349 |
++ " .long 0b,3b\n" |
12350 |
++ " .long 1b,6b\n" |
12351 |
++ ".previous" |
12352 |
++ : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) |
12353 |
++ : "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS) |
12354 |
++ : "memory"); |
12355 |
++ return size; |
12356 |
++} |
12357 |
+ |
12358 |
+ unsigned long __copy_to_user_ll(void __user *to, const void *from, |
12359 |
+ unsigned long n) |
12360 |
+@@ -775,9 +966,9 @@ survive: |
12361 |
+ } |
12362 |
+ #endif |
12363 |
+ if (movsl_is_ok(to, from, n)) |
12364 |
+- __copy_user(to, from, n); |
12365 |
++ n = __generic_copy_to_user(to, from, n); |
12366 |
+ else |
12367 |
+- n = __copy_user_intel(to, from, n); |
12368 |
++ n = __generic_copy_to_user_intel(to, from, n); |
12369 |
+ return n; |
12370 |
+ } |
12371 |
+ EXPORT_SYMBOL(__copy_to_user_ll); |
12372 |
+@@ -786,7 +977,7 @@ unsigned long __copy_from_user_ll(void * |
12373 |
+ unsigned long n) |
12374 |
+ { |
12375 |
+ if (movsl_is_ok(to, from, n)) |
12376 |
+- __copy_user_zeroing(to, from, n); |
12377 |
++ n = __copy_user_zeroing(to, from, n); |
12378 |
+ else |
12379 |
+ n = __copy_user_zeroing_intel(to, from, n); |
12380 |
+ return n; |
12381 |
+@@ -797,10 +988,9 @@ unsigned long __copy_from_user_ll_nozero |
12382 |
+ unsigned long n) |
12383 |
+ { |
12384 |
+ if (movsl_is_ok(to, from, n)) |
12385 |
+- __copy_user(to, from, n); |
12386 |
++ n = __generic_copy_from_user(to, from, n); |
12387 |
+ else |
12388 |
+- n = __copy_user_intel((void __user *)to, |
12389 |
+- (const void *)from, n); |
12390 |
++ n = __generic_copy_from_user_intel(to, from, n); |
12391 |
+ return n; |
12392 |
+ } |
12393 |
+ EXPORT_SYMBOL(__copy_from_user_ll_nozero); |
12394 |
+@@ -812,9 +1002,9 @@ unsigned long __copy_from_user_ll_nocach |
12395 |
+ if (n > 64 && cpu_has_xmm2) |
12396 |
+ n = __copy_user_zeroing_intel_nocache(to, from, n); |
12397 |
+ else |
12398 |
+- __copy_user_zeroing(to, from, n); |
12399 |
++ n = __copy_user_zeroing(to, from, n); |
12400 |
+ #else |
12401 |
+- __copy_user_zeroing(to, from, n); |
12402 |
++ n = __copy_user_zeroing(to, from, n); |
12403 |
+ #endif |
12404 |
+ return n; |
12405 |
+ } |
12406 |
+@@ -827,9 +1017,9 @@ unsigned long __copy_from_user_ll_nocach |
12407 |
+ if (n > 64 && cpu_has_xmm2) |
12408 |
+ n = __copy_user_intel_nocache(to, from, n); |
12409 |
+ else |
12410 |
+- __copy_user(to, from, n); |
12411 |
++ n = __generic_copy_from_user(to, from, n); |
12412 |
+ #else |
12413 |
+- __copy_user(to, from, n); |
12414 |
++ n = __generic_copy_from_user(to, from, n); |
12415 |
+ #endif |
12416 |
+ return n; |
12417 |
+ } |
12418 |
+@@ -878,8 +1068,35 @@ copy_from_user(void *to, const void __us |
12419 |
+ { |
12420 |
+ if (access_ok(VERIFY_READ, from, n)) |
12421 |
+ n = __copy_from_user(to, from, n); |
12422 |
+- else |
12423 |
++ else if ((long)n > 0) |
12424 |
+ memset(to, 0, n); |
12425 |
+ return n; |
12426 |
+ } |
12427 |
+ EXPORT_SYMBOL(copy_from_user); |
12428 |
++ |
12429 |
++#ifdef CONFIG_PAX_MEMORY_UDEREF |
12430 |
++void __set_fs(mm_segment_t x, int cpu) |
12431 |
++{ |
12432 |
++ unsigned long limit = x.seg; |
12433 |
++ struct desc_struct d; |
12434 |
++ |
12435 |
++ current_thread_info()->addr_limit = x; |
12436 |
++ if (likely(limit)) |
12437 |
++ limit = (limit - 1UL) >> PAGE_SHIFT; |
12438 |
++ pack_descriptor(&d, 0UL, limit, 0xF3, 0xC); |
12439 |
++ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_DEFAULT_USER_DS, &d, DESCTYPE_S); |
12440 |
++} |
12441 |
++ |
12442 |
++void set_fs(mm_segment_t x) |
12443 |
++{ |
12444 |
++ __set_fs(x, get_cpu()); |
12445 |
++ put_cpu_no_resched(); |
12446 |
++} |
12447 |
++#else |
12448 |
++void set_fs(mm_segment_t x) |
12449 |
++{ |
12450 |
++ current_thread_info()->addr_limit = x; |
12451 |
++} |
12452 |
++#endif |
12453 |
++ |
12454 |
++EXPORT_SYMBOL(set_fs); |
12455 |
+diff -urNp linux-2.6.28.8/arch/x86/mach-voyager/voyager_basic.c linux-2.6.28.8/arch/x86/mach-voyager/voyager_basic.c |
12456 |
+--- linux-2.6.28.8/arch/x86/mach-voyager/voyager_basic.c 2009-02-06 16:47:45.000000000 -0500 |
12457 |
++++ linux-2.6.28.8/arch/x86/mach-voyager/voyager_basic.c 2009-02-21 09:37:48.000000000 -0500 |
12458 |
+@@ -123,7 +123,7 @@ int __init voyager_memory_detect(int reg |
12459 |
+ __u8 cmos[4]; |
12460 |
+ ClickMap_t *map; |
12461 |
+ unsigned long map_addr; |
12462 |
+- unsigned long old; |
12463 |
++ pte_t old; |
12464 |
+ |
12465 |
+ if (region >= CLICK_ENTRIES) { |
12466 |
+ printk("Voyager: Illegal ClickMap region %d\n", region); |
12467 |
+@@ -138,7 +138,7 @@ int __init voyager_memory_detect(int reg |
12468 |
+ |
12469 |
+ /* steal page 0 for this */ |
12470 |
+ old = pg0[0]; |
12471 |
+- pg0[0] = ((map_addr & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT); |
12472 |
++ pg0[0] = __pte((map_addr & PAGE_MASK) | _PAGE_RW | _PAGE_PRESENT); |
12473 |
+ local_flush_tlb(); |
12474 |
+ /* now clear everything out but page 0 */ |
12475 |
+ map = (ClickMap_t *) (map_addr & (~PAGE_MASK)); |
12476 |
+diff -urNp linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c |
12477 |
+--- linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c 2009-02-06 16:47:45.000000000 -0500 |
12478 |
++++ linux-2.6.28.8/arch/x86/mach-voyager/voyager_smp.c 2009-02-21 09:37:48.000000000 -0500 |
12479 |
+@@ -521,6 +521,10 @@ static void __init do_boot_cpu(__u8 cpu) |
12480 |
+ __u32 *hijack_vector; |
12481 |
+ __u32 start_phys_address = setup_trampoline(); |
12482 |
+ |
12483 |
++#ifdef CONFIG_PAX_KERNEXEC |
12484 |
++ unsigned long cr0; |
12485 |
++#endif |
12486 |
++ |
12487 |
+ /* There's a clever trick to this: The linux trampoline is |
12488 |
+ * compiled to begin at absolute location zero, so make the |
12489 |
+ * address zero but have the data segment selector compensate |
12490 |
+@@ -540,7 +544,17 @@ static void __init do_boot_cpu(__u8 cpu) |
12491 |
+ |
12492 |
+ init_gdt(cpu); |
12493 |
+ per_cpu(current_task, cpu) = idle; |
12494 |
+- early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); |
12495 |
++ |
12496 |
++#ifdef CONFIG_PAX_KERNEXEC |
12497 |
++ pax_open_kernel(cr0); |
12498 |
++#endif |
12499 |
++ |
12500 |
++ early_gdt_descr.address = get_cpu_gdt_table(cpu); |
12501 |
++ |
12502 |
++#ifdef CONFIG_PAX_KERNEXEC |
12503 |
++ pax_close_kernel(cr0); |
12504 |
++#endif |
12505 |
++ |
12506 |
+ irq_ctx_init(cpu); |
12507 |
+ |
12508 |
+ /* Note: Don't modify initial ss override */ |
12509 |
+@@ -1154,7 +1168,7 @@ void smp_local_timer_interrupt(void) |
12510 |
+ per_cpu(prof_counter, cpu); |
12511 |
+ } |
12512 |
+ |
12513 |
+- update_process_times(user_mode_vm(get_irq_regs())); |
12514 |
++ update_process_times(user_mode(get_irq_regs())); |
12515 |
+ } |
12516 |
+ |
12517 |
+ if (((1 << cpu) & voyager_extended_vic_processors) == 0) |
12518 |
+diff -urNp linux-2.6.28.8/arch/x86/Makefile linux-2.6.28.8/arch/x86/Makefile |
12519 |
+--- linux-2.6.28.8/arch/x86/Makefile 2009-02-06 16:47:45.000000000 -0500 |
12520 |
++++ linux-2.6.28.8/arch/x86/Makefile 2009-02-21 09:37:48.000000000 -0500 |
12521 |
+@@ -232,3 +232,12 @@ endef |
12522 |
+ CLEAN_FILES += arch/x86/boot/fdimage \ |
12523 |
+ arch/x86/boot/image.iso \ |
12524 |
+ arch/x86/boot/mtools.conf |
12525 |
++ |
12526 |
++define OLD_LD |
12527 |
++ |
12528 |
++*** ${VERSION}.${PATCHLEVEL} PaX kernels no longer build correctly with old versions of binutils. |
12529 |
++*** Please upgrade your binutils to 2.18 or newer |
12530 |
++endef |
12531 |
++ |
12532 |
++archprepare: |
12533 |
++ $(if $(LDFLAGS_BUILD_ID),,$(error $(OLD_LD))) |
12534 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/extable.c linux-2.6.28.8/arch/x86/mm/extable.c |
12535 |
+--- linux-2.6.28.8/arch/x86/mm/extable.c 2009-02-06 16:47:45.000000000 -0500 |
12536 |
++++ linux-2.6.28.8/arch/x86/mm/extable.c 2009-02-21 09:37:48.000000000 -0500 |
12537 |
+@@ -1,14 +1,62 @@ |
12538 |
+ #include <linux/module.h> |
12539 |
+ #include <linux/spinlock.h> |
12540 |
++#include <linux/sort.h> |
12541 |
+ #include <asm/uaccess.h> |
12542 |
+ |
12543 |
++/* |
12544 |
++ * The exception table needs to be sorted so that the binary |
12545 |
++ * search that we use to find entries in it works properly. |
12546 |
++ * This is used both for the kernel exception table and for |
12547 |
++ * the exception tables of modules that get loaded. |
12548 |
++ */ |
12549 |
++static int cmp_ex(const void *a, const void *b) |
12550 |
++{ |
12551 |
++ const struct exception_table_entry *x = a, *y = b; |
12552 |
++ |
12553 |
++ /* avoid overflow */ |
12554 |
++ if (x->insn > y->insn) |
12555 |
++ return 1; |
12556 |
++ if (x->insn < y->insn) |
12557 |
++ return -1; |
12558 |
++ return 0; |
12559 |
++} |
12560 |
++ |
12561 |
++static void swap_ex(void *a, void *b, int size) |
12562 |
++{ |
12563 |
++ struct exception_table_entry t, *x = a, *y = b; |
12564 |
++ |
12565 |
++#ifdef CONFIG_PAX_KERNEXEC |
12566 |
++ unsigned long cr0; |
12567 |
++#endif |
12568 |
++ |
12569 |
++ t = *x; |
12570 |
++ |
12571 |
++#ifdef CONFIG_PAX_KERNEXEC |
12572 |
++ pax_open_kernel(cr0); |
12573 |
++#endif |
12574 |
++ |
12575 |
++ *x = *y; |
12576 |
++ *y = t; |
12577 |
++ |
12578 |
++#ifdef CONFIG_PAX_KERNEXEC |
12579 |
++ pax_close_kernel(cr0); |
12580 |
++#endif |
12581 |
++ |
12582 |
++} |
12583 |
++ |
12584 |
++void sort_extable(struct exception_table_entry *start, |
12585 |
++ struct exception_table_entry *finish) |
12586 |
++{ |
12587 |
++ sort(start, finish - start, sizeof(struct exception_table_entry), |
12588 |
++ cmp_ex, swap_ex); |
12589 |
++} |
12590 |
+ |
12591 |
+ int fixup_exception(struct pt_regs *regs) |
12592 |
+ { |
12593 |
+ const struct exception_table_entry *fixup; |
12594 |
+ |
12595 |
+ #ifdef CONFIG_PNPBIOS |
12596 |
+- if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) { |
12597 |
++ if (unlikely(!v8086_mode(regs) && SEGMENT_IS_PNP_CODE(regs->cs))) { |
12598 |
+ extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp; |
12599 |
+ extern u32 pnp_bios_is_utter_crap; |
12600 |
+ pnp_bios_is_utter_crap = 1; |
12601 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/fault.c linux-2.6.28.8/arch/x86/mm/fault.c |
12602 |
+--- linux-2.6.28.8/arch/x86/mm/fault.c 2009-02-07 16:10:45.000000000 -0500 |
12603 |
++++ linux-2.6.28.8/arch/x86/mm/fault.c 2009-02-21 09:37:48.000000000 -0500 |
12604 |
+@@ -26,6 +26,8 @@ |
12605 |
+ #include <linux/kprobes.h> |
12606 |
+ #include <linux/uaccess.h> |
12607 |
+ #include <linux/kdebug.h> |
12608 |
++#include <linux/unistd.h> |
12609 |
++#include <linux/compiler.h> |
12610 |
+ |
12611 |
+ #include <asm/system.h> |
12612 |
+ #include <asm/desc.h> |
12613 |
+@@ -67,7 +69,7 @@ static inline int notify_page_fault(stru |
12614 |
+ int ret = 0; |
12615 |
+ |
12616 |
+ /* kprobe_running() needs smp_processor_id() */ |
12617 |
+- if (!user_mode_vm(regs)) { |
12618 |
++ if (!user_mode(regs)) { |
12619 |
+ preempt_disable(); |
12620 |
+ if (kprobe_running() && kprobe_fault_handler(regs, 14)) |
12621 |
+ ret = 1; |
12622 |
+@@ -265,6 +267,30 @@ bad: |
12623 |
+ #endif |
12624 |
+ } |
12625 |
+ |
12626 |
++#ifdef CONFIG_PAX_EMUTRAMP |
12627 |
++static int pax_handle_fetch_fault(struct pt_regs *regs); |
12628 |
++#endif |
12629 |
++ |
12630 |
++#ifdef CONFIG_PAX_PAGEEXEC |
12631 |
++static inline pmd_t * pax_get_pmd(struct mm_struct *mm, unsigned long address) |
12632 |
++{ |
12633 |
++ pgd_t *pgd; |
12634 |
++ pud_t *pud; |
12635 |
++ pmd_t *pmd; |
12636 |
++ |
12637 |
++ pgd = pgd_offset(mm, address); |
12638 |
++ if (!pgd_present(*pgd)) |
12639 |
++ return NULL; |
12640 |
++ pud = pud_offset(pgd, address); |
12641 |
++ if (!pud_present(*pud)) |
12642 |
++ return NULL; |
12643 |
++ pmd = pmd_offset(pud, address); |
12644 |
++ if (!pmd_present(*pmd)) |
12645 |
++ return NULL; |
12646 |
++ return pmd; |
12647 |
++} |
12648 |
++#endif |
12649 |
++ |
12650 |
+ #ifdef CONFIG_X86_32 |
12651 |
+ static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address) |
12652 |
+ { |
12653 |
+@@ -351,7 +377,7 @@ static int is_errata93(struct pt_regs *r |
12654 |
+ static int is_errata100(struct pt_regs *regs, unsigned long address) |
12655 |
+ { |
12656 |
+ #ifdef CONFIG_X86_64 |
12657 |
+- if ((regs->cs == __USER32_CS || (regs->cs & (1<<2))) && |
12658 |
++ if ((regs->cs == __USER32_CS || (regs->cs & SEGMENT_LDT)) && |
12659 |
+ (address >> 32)) |
12660 |
+ return 1; |
12661 |
+ #endif |
12662 |
+@@ -386,14 +412,31 @@ static void show_fault_oops(struct pt_re |
12663 |
+ #endif |
12664 |
+ |
12665 |
+ #ifdef CONFIG_X86_PAE |
12666 |
+- if (error_code & PF_INSTR) { |
12667 |
++ if (nx_enabled && (error_code & PF_INSTR)) { |
12668 |
+ unsigned int level; |
12669 |
+ pte_t *pte = lookup_address(address, &level); |
12670 |
+ |
12671 |
+ if (pte && pte_present(*pte) && !pte_exec(*pte)) |
12672 |
+ printk(KERN_CRIT "kernel tried to execute " |
12673 |
+ "NX-protected page - exploit attempt? " |
12674 |
+- "(uid: %d)\n", current->uid); |
12675 |
++ "(uid: %d, task: %s, pid: %d)\n", |
12676 |
++ current->uid, current->comm, task_pid_nr(current)); |
12677 |
++ } |
12678 |
++#endif |
12679 |
++ |
12680 |
++#ifdef CONFIG_PAX_KERNEXEC |
12681 |
++#ifdef CONFIG_MODULES |
12682 |
++ if (init_mm.start_code <= address && address < (unsigned long)MODULES_END) |
12683 |
++#else |
12684 |
++ if (init_mm.start_code <= address && address < init_mm.end_code) |
12685 |
++#endif |
12686 |
++ { |
12687 |
++ if (current->signal->curr_ip) |
12688 |
++ printk(KERN_ERR "PAX: From %u.%u.%u.%u: %s:%d, uid/euid: %u/%u, attempted to modify kernel code\n", |
12689 |
++ NIPQUAD(current->signal->curr_ip), current->comm, task_pid_nr(current), current->uid, current->euid); |
12690 |
++ else |
12691 |
++ printk(KERN_ERR "PAX: %s:%d, uid/euid: %u/%u, attempted to modify kernel code\n", |
12692 |
++ current->comm, task_pid_nr(current), current->uid, current->euid); |
12693 |
+ } |
12694 |
+ #endif |
12695 |
+ |
12696 |
+@@ -585,20 +628,26 @@ void __kprobes do_page_fault(struct pt_r |
12697 |
+ struct task_struct *tsk; |
12698 |
+ struct mm_struct *mm; |
12699 |
+ struct vm_area_struct *vma; |
12700 |
+- unsigned long address; |
12701 |
+ int write, si_code; |
12702 |
+ int fault; |
12703 |
+ #ifdef CONFIG_X86_64 |
12704 |
+ unsigned long flags; |
12705 |
+ #endif |
12706 |
+ |
12707 |
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC) |
12708 |
++ pte_t *pte; |
12709 |
++ pmd_t *pmd; |
12710 |
++ spinlock_t *ptl; |
12711 |
++ unsigned char pte_mask; |
12712 |
++#endif |
12713 |
++ |
12714 |
++ /* get the address */ |
12715 |
++ const unsigned long address = read_cr2(); |
12716 |
++ |
12717 |
+ tsk = current; |
12718 |
+ mm = tsk->mm; |
12719 |
+ prefetchw(&mm->mmap_sem); |
12720 |
+ |
12721 |
+- /* get the address */ |
12722 |
+- address = read_cr2(); |
12723 |
+- |
12724 |
+ si_code = SEGV_MAPERR; |
12725 |
+ |
12726 |
+ if (unlikely(kmmio_fault(regs, address))) |
12727 |
+@@ -651,7 +700,7 @@ void __kprobes do_page_fault(struct pt_r |
12728 |
+ * User-mode registers count as a user access even for any |
12729 |
+ * potential system fault or CPU buglet. |
12730 |
+ */ |
12731 |
+- if (user_mode_vm(regs)) { |
12732 |
++ if (user_mode(regs)) { |
12733 |
+ local_irq_enable(); |
12734 |
+ error_code |= PF_USER; |
12735 |
+ } else if (regs->flags & X86_EFLAGS_IF) |
12736 |
+@@ -667,7 +716,7 @@ void __kprobes do_page_fault(struct pt_r |
12737 |
+ * atomic region then we must not take the fault. |
12738 |
+ */ |
12739 |
+ if (unlikely(in_atomic() || !mm)) |
12740 |
+- goto bad_area_nosemaphore; |
12741 |
++ goto bad_area_nopax; |
12742 |
+ |
12743 |
+ again: |
12744 |
+ /* |
12745 |
+@@ -689,10 +738,104 @@ again: |
12746 |
+ if (!down_read_trylock(&mm->mmap_sem)) { |
12747 |
+ if ((error_code & PF_USER) == 0 && |
12748 |
+ !search_exception_tables(regs->ip)) |
12749 |
+- goto bad_area_nosemaphore; |
12750 |
++ goto bad_area_nopax; |
12751 |
+ down_read(&mm->mmap_sem); |
12752 |
+ } |
12753 |
+ |
12754 |
++#if defined(CONFIG_X86_32) && defined(CONFIG_PAX_PAGEEXEC) |
12755 |
++ if (nx_enabled || (error_code & (PF_PROT|PF_USER)) != (PF_PROT|PF_USER) || v8086_mode(regs) || |
12756 |
++ !(mm->pax_flags & MF_PAX_PAGEEXEC)) |
12757 |
++ goto not_pax_fault; |
12758 |
++ |
12759 |
++ /* PaX: it's our fault, let's handle it if we can */ |
12760 |
++ |
12761 |
++ /* PaX: take a look at read faults before acquiring any locks */ |
12762 |
++ if (unlikely(!(error_code & PF_WRITE) && (regs->ip == address))) { |
12763 |
++ /* instruction fetch attempt from a protected page in user mode */ |
12764 |
++ up_read(&mm->mmap_sem); |
12765 |
++ |
12766 |
++#ifdef CONFIG_PAX_EMUTRAMP |
12767 |
++ switch (pax_handle_fetch_fault(regs)) { |
12768 |
++ case 2: |
12769 |
++ return; |
12770 |
++ } |
12771 |
++#endif |
12772 |
++ |
12773 |
++ pax_report_fault(regs, (void *)regs->ip, (void *)regs->sp); |
12774 |
++ do_group_exit(SIGKILL); |
12775 |
++ } |
12776 |
++ |
12777 |
++ pmd = pax_get_pmd(mm, address); |
12778 |
++ if (unlikely(!pmd)) |
12779 |
++ goto not_pax_fault; |
12780 |
++ |
12781 |
++ pte = pte_offset_map_lock(mm, pmd, address, &ptl); |
12782 |
++ if (unlikely(!(pte_val(*pte) & _PAGE_PRESENT) || pte_user(*pte))) { |
12783 |
++ pte_unmap_unlock(pte, ptl); |
12784 |
++ goto not_pax_fault; |
12785 |
++ } |
12786 |
++ |
12787 |
++ if (unlikely((error_code & PF_WRITE) && !pte_write(*pte))) { |
12788 |
++ /* write attempt to a protected page in user mode */ |
12789 |
++ pte_unmap_unlock(pte, ptl); |
12790 |
++ goto not_pax_fault; |
12791 |
++ } |
12792 |
++ |
12793 |
++#ifdef CONFIG_SMP |
12794 |
++ if (likely(address > get_limit(regs->cs) && cpu_isset(smp_processor_id(), mm->context.cpu_user_cs_mask))) |
12795 |
++#else |
12796 |
++ if (likely(address > get_limit(regs->cs))) |
12797 |
++#endif |
12798 |
++ { |
12799 |
++ set_pte(pte, pte_mkread(*pte)); |
12800 |
++ __flush_tlb_one(address); |
12801 |
++ pte_unmap_unlock(pte, ptl); |
12802 |
++ up_read(&mm->mmap_sem); |
12803 |
++ return; |
12804 |
++ } |
12805 |
++ |
12806 |
++ pte_mask = _PAGE_ACCESSED | _PAGE_USER | ((error_code & PF_WRITE) << (_PAGE_BIT_DIRTY-1)); |
12807 |
++ |
12808 |
++ /* |
12809 |
++ * PaX: fill DTLB with user rights and retry |
12810 |
++ */ |
12811 |
++ __asm__ __volatile__ ( |
12812 |
++#ifdef CONFIG_PAX_MEMORY_UDEREF |
12813 |
++ "movw %w4,%%es\n" |
12814 |
++#endif |
12815 |
++ "orb %2,(%1)\n" |
12816 |
++#if defined(CONFIG_M586) || defined(CONFIG_M586TSC) |
12817 |
++/* |
12818 |
++ * PaX: let this uncommented 'invlpg' remind us on the behaviour of Intel's |
12819 |
++ * (and AMD's) TLBs. namely, they do not cache PTEs that would raise *any* |
12820 |
++ * page fault when examined during a TLB load attempt. this is true not only |
12821 |
++ * for PTEs holding a non-present entry but also present entries that will |
12822 |
++ * raise a page fault (such as those set up by PaX, or the copy-on-write |
12823 |
++ * mechanism). in effect it means that we do *not* need to flush the TLBs |
12824 |
++ * for our target pages since their PTEs are simply not in the TLBs at all. |
12825 |
++ |
12826 |
++ * the best thing in omitting it is that we gain around 15-20% speed in the |
12827 |
++ * fast path of the page fault handler and can get rid of tracing since we |
12828 |
++ * can no longer flush unintended entries. |
12829 |
++ */ |
12830 |
++ "invlpg (%0)\n" |
12831 |
++#endif |
12832 |
++ "testb $0,%%es:(%0)\n" |
12833 |
++ "xorb %3,(%1)\n" |
12834 |
++#ifdef CONFIG_PAX_MEMORY_UDEREF |
12835 |
++ "pushl %%ss\n" |
12836 |
++ "popl %%es\n" |
12837 |
++#endif |
12838 |
++ : |
12839 |
++ : "r" (address), "r" (pte), "q" (pte_mask), "i" (_PAGE_USER), "r" (__USER_DS) |
12840 |
++ : "memory", "cc"); |
12841 |
++ pte_unmap_unlock(pte, ptl); |
12842 |
++ up_read(&mm->mmap_sem); |
12843 |
++ return; |
12844 |
++ |
12845 |
++not_pax_fault: |
12846 |
++#endif |
12847 |
++ |
12848 |
+ vma = find_vma(mm, address); |
12849 |
+ if (!vma) |
12850 |
+ goto bad_area; |
12851 |
+@@ -700,16 +843,20 @@ again: |
12852 |
+ goto good_area; |
12853 |
+ if (!(vma->vm_flags & VM_GROWSDOWN)) |
12854 |
+ goto bad_area; |
12855 |
+- if (error_code & PF_USER) { |
12856 |
+- /* |
12857 |
+- * Accessing the stack below %sp is always a bug. |
12858 |
+- * The large cushion allows instructions like enter |
12859 |
+- * and pusha to work. ("enter $65535,$31" pushes |
12860 |
+- * 32 pointers and then decrements %sp by 65535.) |
12861 |
+- */ |
12862 |
+- if (address + 65536 + 32 * sizeof(unsigned long) < regs->sp) |
12863 |
+- goto bad_area; |
12864 |
+- } |
12865 |
++ /* |
12866 |
++ * Accessing the stack below %sp is always a bug. |
12867 |
++ * The large cushion allows instructions like enter |
12868 |
++ * and pusha to work. ("enter $65535,$31" pushes |
12869 |
++ * 32 pointers and then decrements %sp by 65535.) |
12870 |
++ */ |
12871 |
++ if (address + 65536 + 32 * sizeof(unsigned long) < task_pt_regs(tsk)->sp) |
12872 |
++ goto bad_area; |
12873 |
++ |
12874 |
++#ifdef CONFIG_PAX_SEGMEXEC |
12875 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && vma->vm_end - SEGMEXEC_TASK_SIZE - 1 < address - SEGMEXEC_TASK_SIZE - 1) |
12876 |
++ goto bad_area; |
12877 |
++#endif |
12878 |
++ |
12879 |
+ if (expand_stack(vma, address)) |
12880 |
+ goto bad_area; |
12881 |
+ /* |
12882 |
+@@ -719,6 +866,8 @@ again: |
12883 |
+ good_area: |
12884 |
+ si_code = SEGV_ACCERR; |
12885 |
+ write = 0; |
12886 |
++ if (nx_enabled && (error_code & PF_INSTR) && !(vma->vm_flags & VM_EXEC)) |
12887 |
++ goto bad_area; |
12888 |
+ switch (error_code & (PF_PROT|PF_WRITE)) { |
12889 |
+ default: /* 3: write, present */ |
12890 |
+ /* fall through */ |
12891 |
+@@ -773,6 +922,54 @@ bad_area: |
12892 |
+ up_read(&mm->mmap_sem); |
12893 |
+ |
12894 |
+ bad_area_nosemaphore: |
12895 |
++ |
12896 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
12897 |
++ if (mm && (error_code & PF_USER)) { |
12898 |
++ unsigned long ip = regs->ip; |
12899 |
++ |
12900 |
++ if (v8086_mode(regs)) |
12901 |
++ ip = ((regs->cs & 0xffff) << 4) + (regs->ip & 0xffff); |
12902 |
++ |
12903 |
++ /* |
12904 |
++ * It's possible to have interrupts off here. |
12905 |
++ */ |
12906 |
++ local_irq_enable(); |
12907 |
++ |
12908 |
++#ifdef CONFIG_PAX_PAGEEXEC |
12909 |
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && |
12910 |
++ ((nx_enabled && (error_code & PF_INSTR)) || (!(error_code & (PF_PROT | PF_WRITE)) && regs->ip == address))) { |
12911 |
++ |
12912 |
++#ifdef CONFIG_PAX_EMUTRAMP |
12913 |
++ switch (pax_handle_fetch_fault(regs)) { |
12914 |
++ case 2: |
12915 |
++ return; |
12916 |
++ } |
12917 |
++#endif |
12918 |
++ |
12919 |
++ pax_report_fault(regs, (void *)regs->ip, (void *)regs->sp); |
12920 |
++ do_group_exit(SIGKILL); |
12921 |
++ } |
12922 |
++#endif |
12923 |
++ |
12924 |
++#ifdef CONFIG_PAX_SEGMEXEC |
12925 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && !(error_code & (PF_PROT | PF_WRITE)) && (regs->ip + SEGMEXEC_TASK_SIZE == address)) { |
12926 |
++ |
12927 |
++#ifdef CONFIG_PAX_EMUTRAMP |
12928 |
++ switch (pax_handle_fetch_fault(regs)) { |
12929 |
++ case 2: |
12930 |
++ return; |
12931 |
++ } |
12932 |
++#endif |
12933 |
++ |
12934 |
++ pax_report_fault(regs, (void *)regs->ip, (void *)regs->sp); |
12935 |
++ do_group_exit(SIGKILL); |
12936 |
++ } |
12937 |
++#endif |
12938 |
++ |
12939 |
++ } |
12940 |
++#endif |
12941 |
++ |
12942 |
++bad_area_nopax: |
12943 |
+ /* User mode accesses just cause a SIGSEGV */ |
12944 |
+ if (error_code & PF_USER) { |
12945 |
+ /* |
12946 |
+@@ -851,7 +1048,7 @@ no_context: |
12947 |
+ #ifdef CONFIG_X86_32 |
12948 |
+ die("Oops", regs, error_code); |
12949 |
+ bust_spinlocks(0); |
12950 |
+- do_exit(SIGKILL); |
12951 |
++ do_group_exit(SIGKILL); |
12952 |
+ #else |
12953 |
+ if (__die("Oops", regs, error_code)) |
12954 |
+ regs = NULL; |
12955 |
+@@ -944,3 +1141,174 @@ void vmalloc_sync_all(void) |
12956 |
+ } |
12957 |
+ #endif |
12958 |
+ } |
12959 |
++ |
12960 |
++#ifdef CONFIG_PAX_EMUTRAMP |
12961 |
++static int pax_handle_fetch_fault_32(struct pt_regs *regs) |
12962 |
++{ |
12963 |
++ int err; |
12964 |
++ |
12965 |
++ do { /* PaX: gcc trampoline emulation #1 */ |
12966 |
++ unsigned char mov1, mov2; |
12967 |
++ unsigned short jmp; |
12968 |
++ unsigned int addr1, addr2; |
12969 |
++ |
12970 |
++#ifdef CONFIG_X86_64 |
12971 |
++ if ((regs->ip + 11) >> 32) |
12972 |
++ break; |
12973 |
++#endif |
12974 |
++ |
12975 |
++ err = get_user(mov1, (unsigned char __user *)regs->ip); |
12976 |
++ err |= get_user(addr1, (unsigned int __user *)(regs->ip + 1)); |
12977 |
++ err |= get_user(mov2, (unsigned char __user *)(regs->ip + 5)); |
12978 |
++ err |= get_user(addr2, (unsigned int __user *)(regs->ip + 6)); |
12979 |
++ err |= get_user(jmp, (unsigned short __user *)(regs->ip + 10)); |
12980 |
++ |
12981 |
++ if (err) |
12982 |
++ break; |
12983 |
++ |
12984 |
++ if (mov1 == 0xB9 && mov2 == 0xB8 && jmp == 0xE0FF) { |
12985 |
++ regs->cx = addr1; |
12986 |
++ regs->ax = addr2; |
12987 |
++ regs->ip = addr2; |
12988 |
++ return 2; |
12989 |
++ } |
12990 |
++ } while (0); |
12991 |
++ |
12992 |
++ do { /* PaX: gcc trampoline emulation #2 */ |
12993 |
++ unsigned char mov, jmp; |
12994 |
++ unsigned int addr1, addr2; |
12995 |
++ |
12996 |
++#ifdef CONFIG_X86_64 |
12997 |
++ if ((regs->ip + 9) >> 32) |
12998 |
++ break; |
12999 |
++#endif |
13000 |
++ |
13001 |
++ err = get_user(mov, (unsigned char __user *)regs->ip); |
13002 |
++ err |= get_user(addr1, (unsigned int __user *)(regs->ip + 1)); |
13003 |
++ err |= get_user(jmp, (unsigned char __user *)(regs->ip + 5)); |
13004 |
++ err |= get_user(addr2, (unsigned int __user *)(regs->ip + 6)); |
13005 |
++ |
13006 |
++ if (err) |
13007 |
++ break; |
13008 |
++ |
13009 |
++ if (mov == 0xB9 && jmp == 0xE9) { |
13010 |
++ regs->cx = addr1; |
13011 |
++ regs->ip = (unsigned int)(regs->ip + addr2 + 10); |
13012 |
++ return 2; |
13013 |
++ } |
13014 |
++ } while (0); |
13015 |
++ |
13016 |
++ return 1; /* PaX in action */ |
13017 |
++} |
13018 |
++ |
13019 |
++#ifdef CONFIG_X86_64 |
13020 |
++static int pax_handle_fetch_fault_64(struct pt_regs *regs) |
13021 |
++{ |
13022 |
++ int err; |
13023 |
++ |
13024 |
++ do { /* PaX: gcc trampoline emulation #1 */ |
13025 |
++ unsigned short mov1, mov2, jmp1; |
13026 |
++ unsigned char jmp2; |
13027 |
++ unsigned int addr1; |
13028 |
++ unsigned long addr2; |
13029 |
++ |
13030 |
++ err = get_user(mov1, (unsigned short __user *)regs->ip); |
13031 |
++ err |= get_user(addr1, (unsigned int __user *)(regs->ip + 2)); |
13032 |
++ err |= get_user(mov2, (unsigned short __user *)(regs->ip + 6)); |
13033 |
++ err |= get_user(addr2, (unsigned long __user *)(regs->ip + 8)); |
13034 |
++ err |= get_user(jmp1, (unsigned short __user *)(regs->ip + 16)); |
13035 |
++ err |= get_user(jmp2, (unsigned char __user *)(regs->ip + 18)); |
13036 |
++ |
13037 |
++ if (err) |
13038 |
++ break; |
13039 |
++ |
13040 |
++ if (mov1 == 0xBB41 && mov2 == 0xBA49 && jmp1 == 0xFF49 && jmp2 == 0xE3) { |
13041 |
++ regs->r11 = addr1; |
13042 |
++ regs->r10 = addr2; |
13043 |
++ regs->ip = addr1; |
13044 |
++ return 2; |
13045 |
++ } |
13046 |
++ } while (0); |
13047 |
++ |
13048 |
++ do { /* PaX: gcc trampoline emulation #2 */ |
13049 |
++ unsigned short mov1, mov2, jmp1; |
13050 |
++ unsigned char jmp2; |
13051 |
++ unsigned long addr1, addr2; |
13052 |
++ |
13053 |
++ err = get_user(mov1, (unsigned short __user *)regs->ip); |
13054 |
++ err |= get_user(addr1, (unsigned long __user *)(regs->ip + 2)); |
13055 |
++ err |= get_user(mov2, (unsigned short __user *)(regs->ip + 10)); |
13056 |
++ err |= get_user(addr2, (unsigned long __user *)(regs->ip + 12)); |
13057 |
++ err |= get_user(jmp1, (unsigned short __user *)(regs->ip + 20)); |
13058 |
++ err |= get_user(jmp2, (unsigned char __user *)(regs->ip + 22)); |
13059 |
++ |
13060 |
++ if (err) |
13061 |
++ break; |
13062 |
++ |
13063 |
++ if (mov1 == 0xBB49 && mov2 == 0xBA49 && jmp1 == 0xFF49 && jmp2 == 0xE3) { |
13064 |
++ regs->r11 = addr1; |
13065 |
++ regs->r10 = addr2; |
13066 |
++ regs->ip = addr1; |
13067 |
++ return 2; |
13068 |
++ } |
13069 |
++ } while (0); |
13070 |
++ |
13071 |
++ return 1; /* PaX in action */ |
13072 |
++} |
13073 |
++#endif |
13074 |
++ |
13075 |
++/* |
13076 |
++ * PaX: decide what to do with offenders (regs->ip = fault address) |
13077 |
++ * |
13078 |
++ * returns 1 when task should be killed |
13079 |
++ * 2 when gcc trampoline was detected |
13080 |
++ */ |
13081 |
++static int pax_handle_fetch_fault(struct pt_regs *regs) |
13082 |
++{ |
13083 |
++ if (v8086_mode(regs)) |
13084 |
++ return 1; |
13085 |
++ |
13086 |
++ if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP)) |
13087 |
++ return 1; |
13088 |
++ |
13089 |
++#ifdef CONFIG_X86_32 |
13090 |
++ return pax_handle_fetch_fault_32(regs); |
13091 |
++#else |
13092 |
++ if (regs->cs == __USER32_CS || (regs->cs & SEGMENT_LDT)) |
13093 |
++ return pax_handle_fetch_fault_32(regs); |
13094 |
++ else |
13095 |
++ return pax_handle_fetch_fault_64(regs); |
13096 |
++#endif |
13097 |
++} |
13098 |
++#endif |
13099 |
++ |
13100 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
13101 |
++void pax_report_insns(void *pc, void *sp) |
13102 |
++{ |
13103 |
++ long i; |
13104 |
++ |
13105 |
++ printk(KERN_ERR "PAX: bytes at PC: "); |
13106 |
++ for (i = 0; i < 20; i++) { |
13107 |
++ unsigned char c; |
13108 |
++ if (get_user(c, (unsigned char __user *)pc+i)) |
13109 |
++ printk(KERN_CONT "?? "); |
13110 |
++ else |
13111 |
++ printk(KERN_CONT "%02x ", c); |
13112 |
++ } |
13113 |
++ printk("\n"); |
13114 |
++ |
13115 |
++ printk(KERN_ERR "PAX: bytes at SP-%lu: ", (unsigned long)sizeof(long)); |
13116 |
++ for (i = -1; i < 80 / sizeof(long); i++) { |
13117 |
++ unsigned long c; |
13118 |
++ if (get_user(c, (unsigned long __user *)sp+i)) |
13119 |
++#ifdef CONFIG_X86_32 |
13120 |
++ printk(KERN_CONT "???????? "); |
13121 |
++#else |
13122 |
++ printk(KERN_CONT "???????????????? "); |
13123 |
++#endif |
13124 |
++ else |
13125 |
++ printk(KERN_CONT "%0*lx ", 2 * (int)sizeof(long), c); |
13126 |
++ } |
13127 |
++ printk("\n"); |
13128 |
++} |
13129 |
++#endif |
13130 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/highmem_32.c linux-2.6.28.8/arch/x86/mm/highmem_32.c |
13131 |
+--- linux-2.6.28.8/arch/x86/mm/highmem_32.c 2009-02-06 16:47:45.000000000 -0500 |
13132 |
++++ linux-2.6.28.8/arch/x86/mm/highmem_32.c 2009-02-21 09:37:48.000000000 -0500 |
13133 |
+@@ -74,6 +74,10 @@ void *kmap_atomic_prot(struct page *page |
13134 |
+ enum fixed_addresses idx; |
13135 |
+ unsigned long vaddr; |
13136 |
+ |
13137 |
++#ifdef CONFIG_PAX_KERNEXEC |
13138 |
++ unsigned long cr0; |
13139 |
++#endif |
13140 |
++ |
13141 |
+ /* even !CONFIG_PREEMPT needs this, for in_atomic in do_page_fault */ |
13142 |
+ pagefault_disable(); |
13143 |
+ |
13144 |
+@@ -85,7 +89,17 @@ void *kmap_atomic_prot(struct page *page |
13145 |
+ idx = type + KM_TYPE_NR*smp_processor_id(); |
13146 |
+ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
13147 |
+ BUG_ON(!pte_none(*(kmap_pte-idx))); |
13148 |
++ |
13149 |
++#ifdef CONFIG_PAX_KERNEXEC |
13150 |
++ pax_open_kernel(cr0); |
13151 |
++#endif |
13152 |
++ |
13153 |
+ set_pte(kmap_pte-idx, mk_pte(page, prot)); |
13154 |
++ |
13155 |
++#ifdef CONFIG_PAX_KERNEXEC |
13156 |
++ pax_close_kernel(cr0); |
13157 |
++#endif |
13158 |
++ |
13159 |
+ arch_flush_lazy_mmu_mode(); |
13160 |
+ |
13161 |
+ return (void *)vaddr; |
13162 |
+@@ -101,15 +115,29 @@ void kunmap_atomic(void *kvaddr, enum km |
13163 |
+ unsigned long vaddr = (unsigned long) kvaddr & PAGE_MASK; |
13164 |
+ enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id(); |
13165 |
+ |
13166 |
++#ifdef CONFIG_PAX_KERNEXEC |
13167 |
++ unsigned long cr0; |
13168 |
++#endif |
13169 |
++ |
13170 |
+ /* |
13171 |
+ * Force other mappings to Oops if they'll try to access this pte |
13172 |
+ * without first remap it. Keeping stale mappings around is a bad idea |
13173 |
+ * also, in case the page changes cacheability attributes or becomes |
13174 |
+ * a protected page in a hypervisor. |
13175 |
+ */ |
13176 |
+- if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) |
13177 |
++ if (vaddr == __fix_to_virt(FIX_KMAP_BEGIN+idx)) { |
13178 |
++ |
13179 |
++#ifdef CONFIG_PAX_KERNEXEC |
13180 |
++ pax_open_kernel(cr0); |
13181 |
++#endif |
13182 |
++ |
13183 |
+ kpte_clear_flush(kmap_pte-idx, vaddr); |
13184 |
+- else { |
13185 |
++ |
13186 |
++#ifdef CONFIG_PAX_KERNEXEC |
13187 |
++ pax_close_kernel(cr0); |
13188 |
++#endif |
13189 |
++ |
13190 |
++ } else { |
13191 |
+ #ifdef CONFIG_DEBUG_HIGHMEM |
13192 |
+ BUG_ON(vaddr < PAGE_OFFSET); |
13193 |
+ BUG_ON(vaddr >= (unsigned long)high_memory); |
13194 |
+@@ -128,11 +156,25 @@ void *kmap_atomic_pfn(unsigned long pfn, |
13195 |
+ enum fixed_addresses idx; |
13196 |
+ unsigned long vaddr; |
13197 |
+ |
13198 |
++#ifdef CONFIG_PAX_KERNEXEC |
13199 |
++ unsigned long cr0; |
13200 |
++#endif |
13201 |
++ |
13202 |
+ pagefault_disable(); |
13203 |
+ |
13204 |
+ idx = type + KM_TYPE_NR*smp_processor_id(); |
13205 |
+ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx); |
13206 |
++ |
13207 |
++#ifdef CONFIG_PAX_KERNEXEC |
13208 |
++ pax_open_kernel(cr0); |
13209 |
++#endif |
13210 |
++ |
13211 |
+ set_pte(kmap_pte-idx, pfn_pte(pfn, kmap_prot)); |
13212 |
++ |
13213 |
++#ifdef CONFIG_PAX_KERNEXEC |
13214 |
++ pax_close_kernel(cr0); |
13215 |
++#endif |
13216 |
++ |
13217 |
+ arch_flush_lazy_mmu_mode(); |
13218 |
+ |
13219 |
+ return (void*) vaddr; |
13220 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/hugetlbpage.c linux-2.6.28.8/arch/x86/mm/hugetlbpage.c |
13221 |
+--- linux-2.6.28.8/arch/x86/mm/hugetlbpage.c 2009-02-06 16:47:45.000000000 -0500 |
13222 |
++++ linux-2.6.28.8/arch/x86/mm/hugetlbpage.c 2009-02-21 09:37:48.000000000 -0500 |
13223 |
+@@ -263,13 +263,18 @@ static unsigned long hugetlb_get_unmappe |
13224 |
+ struct hstate *h = hstate_file(file); |
13225 |
+ struct mm_struct *mm = current->mm; |
13226 |
+ struct vm_area_struct *vma; |
13227 |
+- unsigned long start_addr; |
13228 |
++ unsigned long start_addr, pax_task_size = TASK_SIZE; |
13229 |
++ |
13230 |
++#ifdef CONFIG_PAX_SEGMEXEC |
13231 |
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) |
13232 |
++ pax_task_size = SEGMEXEC_TASK_SIZE; |
13233 |
++#endif |
13234 |
+ |
13235 |
+ if (len > mm->cached_hole_size) { |
13236 |
+- start_addr = mm->free_area_cache; |
13237 |
++ start_addr = mm->free_area_cache; |
13238 |
+ } else { |
13239 |
+- start_addr = TASK_UNMAPPED_BASE; |
13240 |
+- mm->cached_hole_size = 0; |
13241 |
++ start_addr = mm->mmap_base; |
13242 |
++ mm->cached_hole_size = 0; |
13243 |
+ } |
13244 |
+ |
13245 |
+ full_search: |
13246 |
+@@ -277,13 +282,13 @@ full_search: |
13247 |
+ |
13248 |
+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) { |
13249 |
+ /* At this point: (!vma || addr < vma->vm_end). */ |
13250 |
+- if (TASK_SIZE - len < addr) { |
13251 |
++ if (pax_task_size - len < addr) { |
13252 |
+ /* |
13253 |
+ * Start a new search - just in case we missed |
13254 |
+ * some holes. |
13255 |
+ */ |
13256 |
+- if (start_addr != TASK_UNMAPPED_BASE) { |
13257 |
+- start_addr = TASK_UNMAPPED_BASE; |
13258 |
++ if (start_addr != mm->mmap_base) { |
13259 |
++ start_addr = mm->mmap_base; |
13260 |
+ mm->cached_hole_size = 0; |
13261 |
+ goto full_search; |
13262 |
+ } |
13263 |
+@@ -306,9 +311,8 @@ static unsigned long hugetlb_get_unmappe |
13264 |
+ struct hstate *h = hstate_file(file); |
13265 |
+ struct mm_struct *mm = current->mm; |
13266 |
+ struct vm_area_struct *vma, *prev_vma; |
13267 |
+- unsigned long base = mm->mmap_base, addr = addr0; |
13268 |
++ unsigned long base = mm->mmap_base, addr; |
13269 |
+ unsigned long largest_hole = mm->cached_hole_size; |
13270 |
+- int first_time = 1; |
13271 |
+ |
13272 |
+ /* don't allow allocations above current base */ |
13273 |
+ if (mm->free_area_cache > base) |
13274 |
+@@ -318,7 +322,7 @@ static unsigned long hugetlb_get_unmappe |
13275 |
+ largest_hole = 0; |
13276 |
+ mm->free_area_cache = base; |
13277 |
+ } |
13278 |
+-try_again: |
13279 |
++ |
13280 |
+ /* make sure it can fit in the remaining address space */ |
13281 |
+ if (mm->free_area_cache < len) |
13282 |
+ goto fail; |
13283 |
+@@ -360,22 +364,26 @@ try_again: |
13284 |
+ |
13285 |
+ fail: |
13286 |
+ /* |
13287 |
+- * if hint left us with no space for the requested |
13288 |
+- * mapping then try again: |
13289 |
+- */ |
13290 |
+- if (first_time) { |
13291 |
+- mm->free_area_cache = base; |
13292 |
+- largest_hole = 0; |
13293 |
+- first_time = 0; |
13294 |
+- goto try_again; |
13295 |
+- } |
13296 |
+- /* |
13297 |
+ * A failed mmap() very likely causes application failure, |
13298 |
+ * so fall back to the bottom-up function here. This scenario |
13299 |
+ * can happen with large stack limits and large mmap() |
13300 |
+ * allocations. |
13301 |
+ */ |
13302 |
+- mm->free_area_cache = TASK_UNMAPPED_BASE; |
13303 |
++ |
13304 |
++#ifdef CONFIG_PAX_SEGMEXEC |
13305 |
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) |
13306 |
++ mm->mmap_base = SEGMEXEC_TASK_UNMAPPED_BASE; |
13307 |
++ else |
13308 |
++#endif |
13309 |
++ |
13310 |
++ mm->mmap_base = TASK_UNMAPPED_BASE; |
13311 |
++ |
13312 |
++#ifdef CONFIG_PAX_RANDMMAP |
13313 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
13314 |
++ mm->mmap_base += mm->delta_mmap; |
13315 |
++#endif |
13316 |
++ |
13317 |
++ mm->free_area_cache = mm->mmap_base; |
13318 |
+ mm->cached_hole_size = ~0UL; |
13319 |
+ addr = hugetlb_get_unmapped_area_bottomup(file, addr0, |
13320 |
+ len, pgoff, flags); |
13321 |
+@@ -383,6 +391,7 @@ fail: |
13322 |
+ /* |
13323 |
+ * Restore the topdown base: |
13324 |
+ */ |
13325 |
++ mm->mmap_base = base; |
13326 |
+ mm->free_area_cache = base; |
13327 |
+ mm->cached_hole_size = ~0UL; |
13328 |
+ |
13329 |
+@@ -396,10 +405,17 @@ hugetlb_get_unmapped_area(struct file *f |
13330 |
+ struct hstate *h = hstate_file(file); |
13331 |
+ struct mm_struct *mm = current->mm; |
13332 |
+ struct vm_area_struct *vma; |
13333 |
++ unsigned long pax_task_size = TASK_SIZE; |
13334 |
+ |
13335 |
+ if (len & ~huge_page_mask(h)) |
13336 |
+ return -EINVAL; |
13337 |
+- if (len > TASK_SIZE) |
13338 |
++ |
13339 |
++#ifdef CONFIG_PAX_SEGMEXEC |
13340 |
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) |
13341 |
++ pax_task_size = SEGMEXEC_TASK_SIZE; |
13342 |
++#endif |
13343 |
++ |
13344 |
++ if (len > pax_task_size) |
13345 |
+ return -ENOMEM; |
13346 |
+ |
13347 |
+ if (flags & MAP_FIXED) { |
13348 |
+@@ -411,7 +427,7 @@ hugetlb_get_unmapped_area(struct file *f |
13349 |
+ if (addr) { |
13350 |
+ addr = ALIGN(addr, huge_page_size(h)); |
13351 |
+ vma = find_vma(mm, addr); |
13352 |
+- if (TASK_SIZE - len >= addr && |
13353 |
++ if (pax_task_size - len >= addr && |
13354 |
+ (!vma || addr + len <= vma->vm_start)) |
13355 |
+ return addr; |
13356 |
+ } |
13357 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/init_32.c linux-2.6.28.8/arch/x86/mm/init_32.c |
13358 |
+--- linux-2.6.28.8/arch/x86/mm/init_32.c 2009-02-06 16:47:45.000000000 -0500 |
13359 |
++++ linux-2.6.28.8/arch/x86/mm/init_32.c 2009-02-21 09:37:48.000000000 -0500 |
13360 |
+@@ -49,6 +49,7 @@ |
13361 |
+ #include <asm/setup.h> |
13362 |
+ #include <asm/cacheflush.h> |
13363 |
+ #include <asm/smp.h> |
13364 |
++#include <asm/desc.h> |
13365 |
+ |
13366 |
+ unsigned int __VMALLOC_RESERVE = 128 << 20; |
13367 |
+ |
13368 |
+@@ -82,35 +83,6 @@ static __init void *alloc_low_page(unsig |
13369 |
+ } |
13370 |
+ |
13371 |
+ /* |
13372 |
+- * Creates a middle page table and puts a pointer to it in the |
13373 |
+- * given global directory entry. This only returns the gd entry |
13374 |
+- * in non-PAE compilation mode, since the middle layer is folded. |
13375 |
+- */ |
13376 |
+-static pmd_t * __init one_md_table_init(pgd_t *pgd) |
13377 |
+-{ |
13378 |
+- pud_t *pud; |
13379 |
+- pmd_t *pmd_table; |
13380 |
+- |
13381 |
+-#ifdef CONFIG_X86_PAE |
13382 |
+- unsigned long phys; |
13383 |
+- if (!(pgd_val(*pgd) & _PAGE_PRESENT)) { |
13384 |
+- if (after_init_bootmem) |
13385 |
+- pmd_table = (pmd_t *)alloc_bootmem_low_pages(PAGE_SIZE); |
13386 |
+- else |
13387 |
+- pmd_table = (pmd_t *)alloc_low_page(&phys); |
13388 |
+- paravirt_alloc_pmd(&init_mm, __pa(pmd_table) >> PAGE_SHIFT); |
13389 |
+- set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT)); |
13390 |
+- pud = pud_offset(pgd, 0); |
13391 |
+- BUG_ON(pmd_table != pmd_offset(pud, 0)); |
13392 |
+- } |
13393 |
+-#endif |
13394 |
+- pud = pud_offset(pgd, 0); |
13395 |
+- pmd_table = pmd_offset(pud, 0); |
13396 |
+- |
13397 |
+- return pmd_table; |
13398 |
+-} |
13399 |
+- |
13400 |
+-/* |
13401 |
+ * Create a page table and place a pointer to it in a middle page |
13402 |
+ * directory entry: |
13403 |
+ */ |
13404 |
+@@ -132,7 +104,11 @@ static pte_t * __init one_page_table_ini |
13405 |
+ } |
13406 |
+ |
13407 |
+ paravirt_alloc_pte(&init_mm, __pa(page_table) >> PAGE_SHIFT); |
13408 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
13409 |
++ set_pmd(pmd, __pmd(__pa(page_table) | _KERNPG_TABLE)); |
13410 |
++#else |
13411 |
+ set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE)); |
13412 |
++#endif |
13413 |
+ BUG_ON(page_table != pte_offset_kernel(pmd, 0)); |
13414 |
+ } |
13415 |
+ |
13416 |
+@@ -154,6 +130,7 @@ page_table_range_init(unsigned long star |
13417 |
+ int pgd_idx, pmd_idx; |
13418 |
+ unsigned long vaddr; |
13419 |
+ pgd_t *pgd; |
13420 |
++ pud_t *pud; |
13421 |
+ pmd_t *pmd; |
13422 |
+ |
13423 |
+ vaddr = start; |
13424 |
+@@ -162,8 +139,13 @@ page_table_range_init(unsigned long star |
13425 |
+ pgd = pgd_base + pgd_idx; |
13426 |
+ |
13427 |
+ for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) { |
13428 |
+- pmd = one_md_table_init(pgd); |
13429 |
+- pmd = pmd + pmd_index(vaddr); |
13430 |
++ pud = pud_offset(pgd, vaddr); |
13431 |
++ pmd = pmd_offset(pud, vaddr); |
13432 |
++ |
13433 |
++#ifdef CONFIG_X86_PAE |
13434 |
++ paravirt_alloc_pmd(&init_mm, __pa(pmd) >> PAGE_SHIFT); |
13435 |
++#endif |
13436 |
++ |
13437 |
+ for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); |
13438 |
+ pmd++, pmd_idx++) { |
13439 |
+ one_page_table_init(pmd); |
13440 |
+@@ -174,11 +156,23 @@ page_table_range_init(unsigned long star |
13441 |
+ } |
13442 |
+ } |
13443 |
+ |
13444 |
+-static inline int is_kernel_text(unsigned long addr) |
13445 |
++static inline int is_kernel_text(unsigned long start, unsigned long end) |
13446 |
+ { |
13447 |
+- if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end) |
13448 |
+- return 1; |
13449 |
+- return 0; |
13450 |
++ unsigned long etext; |
13451 |
++ |
13452 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) |
13453 |
++ etext = ktva_ktla((unsigned long)&MODULES_END); |
13454 |
++#else |
13455 |
++ etext = (unsigned long)&_etext; |
13456 |
++#endif |
13457 |
++ |
13458 |
++ if ((start > ktla_ktva(etext) || |
13459 |
++ end <= ktla_ktva((unsigned long)_stext)) && |
13460 |
++ (start > ktla_ktva((unsigned long)_einittext) || |
13461 |
++ end <= ktla_ktva((unsigned long)_sinittext)) && |
13462 |
++ (start > (unsigned long)__va(0xfffff) || end <= (unsigned long)__va(0xc0000))) |
13463 |
++ return 0; |
13464 |
++ return 1; |
13465 |
+ } |
13466 |
+ |
13467 |
+ /* |
13468 |
+@@ -191,9 +185,10 @@ static void __init kernel_physical_mappi |
13469 |
+ unsigned long end_pfn, |
13470 |
+ int use_pse) |
13471 |
+ { |
13472 |
+- int pgd_idx, pmd_idx, pte_ofs; |
13473 |
++ unsigned int pgd_idx, pmd_idx, pte_ofs; |
13474 |
+ unsigned long pfn; |
13475 |
+ pgd_t *pgd; |
13476 |
++ pud_t *pud; |
13477 |
+ pmd_t *pmd; |
13478 |
+ pte_t *pte; |
13479 |
+ unsigned pages_2m, pages_4k; |
13480 |
+@@ -223,8 +218,13 @@ repeat: |
13481 |
+ pfn = start_pfn; |
13482 |
+ pgd_idx = pgd_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET); |
13483 |
+ pgd = pgd_base + pgd_idx; |
13484 |
+- for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) { |
13485 |
+- pmd = one_md_table_init(pgd); |
13486 |
++ for (; pgd_idx < PTRS_PER_PGD && pfn < max_low_pfn; pgd++, pgd_idx++) { |
13487 |
++ pud = pud_offset(pgd, 0); |
13488 |
++ pmd = pmd_offset(pud, 0); |
13489 |
++ |
13490 |
++#ifdef CONFIG_X86_PAE |
13491 |
++ paravirt_alloc_pmd(&init_mm, __pa(pmd) >> PAGE_SHIFT); |
13492 |
++#endif |
13493 |
+ |
13494 |
+ if (pfn >= end_pfn) |
13495 |
+ continue; |
13496 |
+@@ -236,14 +236,13 @@ repeat: |
13497 |
+ #endif |
13498 |
+ for (; pmd_idx < PTRS_PER_PMD && pfn < end_pfn; |
13499 |
+ pmd++, pmd_idx++) { |
13500 |
+- unsigned int addr = pfn * PAGE_SIZE + PAGE_OFFSET; |
13501 |
++ unsigned long address = pfn * PAGE_SIZE + PAGE_OFFSET; |
13502 |
+ |
13503 |
+ /* |
13504 |
+ * Map with big pages if possible, otherwise |
13505 |
+ * create normal page tables: |
13506 |
+ */ |
13507 |
+ if (use_pse) { |
13508 |
+- unsigned int addr2; |
13509 |
+ pgprot_t prot = PAGE_KERNEL_LARGE; |
13510 |
+ /* |
13511 |
+ * first pass will use the same initial |
13512 |
+@@ -253,11 +252,7 @@ repeat: |
13513 |
+ __pgprot(PTE_IDENT_ATTR | |
13514 |
+ _PAGE_PSE); |
13515 |
+ |
13516 |
+- addr2 = (pfn + PTRS_PER_PTE-1) * PAGE_SIZE + |
13517 |
+- PAGE_OFFSET + PAGE_SIZE-1; |
13518 |
+- |
13519 |
+- if (is_kernel_text(addr) || |
13520 |
+- is_kernel_text(addr2)) |
13521 |
++ if (is_kernel_text(address, address + PMD_SIZE)) |
13522 |
+ prot = PAGE_KERNEL_LARGE_EXEC; |
13523 |
+ |
13524 |
+ pages_2m++; |
13525 |
+@@ -274,7 +269,7 @@ repeat: |
13526 |
+ pte_ofs = pte_index((pfn<<PAGE_SHIFT) + PAGE_OFFSET); |
13527 |
+ pte += pte_ofs; |
13528 |
+ for (; pte_ofs < PTRS_PER_PTE && pfn < end_pfn; |
13529 |
+- pte++, pfn++, pte_ofs++, addr += PAGE_SIZE) { |
13530 |
++ pte++, pfn++, pte_ofs++, address += PAGE_SIZE) { |
13531 |
+ pgprot_t prot = PAGE_KERNEL; |
13532 |
+ /* |
13533 |
+ * first pass will use the same initial |
13534 |
+@@ -282,7 +277,7 @@ repeat: |
13535 |
+ */ |
13536 |
+ pgprot_t init_prot = __pgprot(PTE_IDENT_ATTR); |
13537 |
+ |
13538 |
+- if (is_kernel_text(addr)) |
13539 |
++ if (is_kernel_text(address, address + PAGE_SIZE)) |
13540 |
+ prot = PAGE_KERNEL_EXEC; |
13541 |
+ |
13542 |
+ pages_4k++; |
13543 |
+@@ -327,7 +322,9 @@ repeat: |
13544 |
+ */ |
13545 |
+ int devmem_is_allowed(unsigned long pagenr) |
13546 |
+ { |
13547 |
+- if (pagenr <= 256) |
13548 |
++ if (!pagenr) |
13549 |
++ return 1; |
13550 |
++ if ((ISA_START_ADDRESS >> PAGE_SHIFT) <= pagenr && pagenr < (ISA_END_ADDRESS >> PAGE_SHIFT)) |
13551 |
+ return 1; |
13552 |
+ if (!page_is_ram(pagenr)) |
13553 |
+ return 1; |
13554 |
+@@ -460,7 +457,7 @@ void __init native_pagetable_setup_start |
13555 |
+ |
13556 |
+ pud = pud_offset(pgd, va); |
13557 |
+ pmd = pmd_offset(pud, va); |
13558 |
+- if (!pmd_present(*pmd)) |
13559 |
++ if (!pmd_present(*pmd) || pmd_huge(*pmd)) |
13560 |
+ break; |
13561 |
+ |
13562 |
+ pte = pte_offset_kernel(pmd, va); |
13563 |
+@@ -512,9 +509,7 @@ static void __init early_ioremap_page_ta |
13564 |
+ |
13565 |
+ static void __init pagetable_init(void) |
13566 |
+ { |
13567 |
+- pgd_t *pgd_base = swapper_pg_dir; |
13568 |
+- |
13569 |
+- permanent_kmaps_init(pgd_base); |
13570 |
++ permanent_kmaps_init(swapper_pg_dir); |
13571 |
+ } |
13572 |
+ |
13573 |
+ #ifdef CONFIG_ACPI_SLEEP |
13574 |
+@@ -522,12 +517,12 @@ static void __init pagetable_init(void) |
13575 |
+ * ACPI suspend needs this for resume, because things like the intel-agp |
13576 |
+ * driver might have split up a kernel 4MB mapping. |
13577 |
+ */ |
13578 |
+-char swsusp_pg_dir[PAGE_SIZE] |
13579 |
++pgd_t swsusp_pg_dir[PTRS_PER_PGD] |
13580 |
+ __attribute__ ((aligned(PAGE_SIZE))); |
13581 |
+ |
13582 |
+ static inline void save_pg_dir(void) |
13583 |
+ { |
13584 |
+- memcpy(swsusp_pg_dir, swapper_pg_dir, PAGE_SIZE); |
13585 |
++ clone_pgd_range(swsusp_pg_dir, swapper_pg_dir, PTRS_PER_PGD); |
13586 |
+ } |
13587 |
+ #else /* !CONFIG_ACPI_SLEEP */ |
13588 |
+ static inline void save_pg_dir(void) |
13589 |
+@@ -557,13 +552,11 @@ void zap_low_mappings(void) |
13590 |
+ |
13591 |
+ int nx_enabled; |
13592 |
+ |
13593 |
+-pteval_t __supported_pte_mask __read_mostly = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP); |
13594 |
++pteval_t __supported_pte_mask __read_only = ~(_PAGE_NX | _PAGE_GLOBAL | _PAGE_IOMAP); |
13595 |
+ EXPORT_SYMBOL_GPL(__supported_pte_mask); |
13596 |
+ |
13597 |
+ #ifdef CONFIG_X86_PAE |
13598 |
+ |
13599 |
+-static int disable_nx __initdata; |
13600 |
+- |
13601 |
+ /* |
13602 |
+ * noexec = on|off |
13603 |
+ * |
13604 |
+@@ -572,40 +565,33 @@ static int disable_nx __initdata; |
13605 |
+ * on Enable |
13606 |
+ * off Disable |
13607 |
+ */ |
13608 |
++#if !defined(CONFIG_PAX_PAGEEXEC) |
13609 |
+ static int __init noexec_setup(char *str) |
13610 |
+ { |
13611 |
+ if (!str || !strcmp(str, "on")) { |
13612 |
+- if (cpu_has_nx) { |
13613 |
+- __supported_pte_mask |= _PAGE_NX; |
13614 |
+- disable_nx = 0; |
13615 |
+- } |
13616 |
++ if (cpu_has_nx) |
13617 |
++ nx_enabled = 1; |
13618 |
+ } else { |
13619 |
+- if (!strcmp(str, "off")) { |
13620 |
+- disable_nx = 1; |
13621 |
+- __supported_pte_mask &= ~_PAGE_NX; |
13622 |
+- } else { |
13623 |
++ if (!strcmp(str, "off")) |
13624 |
++ nx_enabled = 0; |
13625 |
++ else |
13626 |
+ return -EINVAL; |
13627 |
+- } |
13628 |
+ } |
13629 |
+ |
13630 |
+ return 0; |
13631 |
+ } |
13632 |
+ early_param("noexec", noexec_setup); |
13633 |
++#endif |
13634 |
+ |
13635 |
+ static void __init set_nx(void) |
13636 |
+ { |
13637 |
+- unsigned int v[4], l, h; |
13638 |
+- |
13639 |
+- if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) { |
13640 |
+- cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]); |
13641 |
++ if (!nx_enabled && cpu_has_nx) { |
13642 |
++ unsigned l, h; |
13643 |
+ |
13644 |
+- if ((v[3] & (1 << 20)) && !disable_nx) { |
13645 |
+- rdmsr(MSR_EFER, l, h); |
13646 |
+- l |= EFER_NX; |
13647 |
+- wrmsr(MSR_EFER, l, h); |
13648 |
+- nx_enabled = 1; |
13649 |
+- __supported_pte_mask |= _PAGE_NX; |
13650 |
+- } |
13651 |
++ __supported_pte_mask &= ~_PAGE_NX; |
13652 |
++ rdmsr(MSR_EFER, l, h); |
13653 |
++ l &= ~EFER_NX; |
13654 |
++ wrmsr(MSR_EFER, l, h); |
13655 |
+ } |
13656 |
+ } |
13657 |
+ #endif |
13658 |
+@@ -988,7 +974,7 @@ void __init mem_init(void) |
13659 |
+ set_highmem_pages_init(); |
13660 |
+ |
13661 |
+ codesize = (unsigned long) &_etext - (unsigned long) &_text; |
13662 |
+- datasize = (unsigned long) &_edata - (unsigned long) &_etext; |
13663 |
++ datasize = (unsigned long) &_edata - (unsigned long) &_data; |
13664 |
+ initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; |
13665 |
+ |
13666 |
+ kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); |
13667 |
+@@ -1034,10 +1020,10 @@ void __init mem_init(void) |
13668 |
+ ((unsigned long)&__init_end - |
13669 |
+ (unsigned long)&__init_begin) >> 10, |
13670 |
+ |
13671 |
+- (unsigned long)&_etext, (unsigned long)&_edata, |
13672 |
+- ((unsigned long)&_edata - (unsigned long)&_etext) >> 10, |
13673 |
++ (unsigned long)&_data, (unsigned long)&_edata, |
13674 |
++ ((unsigned long)&_edata - (unsigned long)&_data) >> 10, |
13675 |
+ |
13676 |
+- (unsigned long)&_text, (unsigned long)&_etext, |
13677 |
++ ktla_ktva((unsigned long)&_text), ktla_ktva((unsigned long)&_etext), |
13678 |
+ ((unsigned long)&_etext - (unsigned long)&_text) >> 10); |
13679 |
+ |
13680 |
+ #ifdef CONFIG_HIGHMEM |
13681 |
+@@ -1166,6 +1152,46 @@ void free_init_pages(char *what, unsigne |
13682 |
+ |
13683 |
+ void free_initmem(void) |
13684 |
+ { |
13685 |
++ |
13686 |
++#ifdef CONFIG_PAX_KERNEXEC |
13687 |
++ /* PaX: limit KERNEL_CS to actual size */ |
13688 |
++ unsigned long addr, limit; |
13689 |
++ struct desc_struct d; |
13690 |
++ int cpu; |
13691 |
++ pgd_t *pgd; |
13692 |
++ pud_t *pud; |
13693 |
++ pmd_t *pmd; |
13694 |
++ |
13695 |
++#ifdef CONFIG_MODULES |
13696 |
++ limit = ktva_ktla((unsigned long)&MODULES_END); |
13697 |
++#else |
13698 |
++ limit = (unsigned long)&_etext; |
13699 |
++#endif |
13700 |
++ limit = (limit - 1UL) >> PAGE_SHIFT; |
13701 |
++ |
13702 |
++ for (cpu = 0; cpu < NR_CPUS; cpu++) { |
13703 |
++ pack_descriptor(&d, get_desc_base(&get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS]), limit, 0x9B, 0xC); |
13704 |
++ write_gdt_entry(get_cpu_gdt_table(cpu), GDT_ENTRY_KERNEL_CS, &d, DESCTYPE_S); |
13705 |
++ } |
13706 |
++ |
13707 |
++ /* PaX: make KERNEL_CS read-only */ |
13708 |
++ for (addr = ktla_ktva((unsigned long)&_text); addr < (unsigned long)&_data; addr += PMD_SIZE) { |
13709 |
++ pgd = pgd_offset_k(addr); |
13710 |
++ pud = pud_offset(pgd, addr); |
13711 |
++ pmd = pmd_offset(pud, addr); |
13712 |
++ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW)); |
13713 |
++ } |
13714 |
++#ifdef CONFIG_X86_PAE |
13715 |
++ for (addr = (unsigned long)&__init_begin; addr < (unsigned long)&__init_end; addr += PMD_SIZE) { |
13716 |
++ pgd = pgd_offset_k(addr); |
13717 |
++ pud = pud_offset(pgd, addr); |
13718 |
++ pmd = pmd_offset(pud, addr); |
13719 |
++ set_pmd(pmd, __pmd(pmd_val(*pmd) | (_PAGE_NX & __supported_pte_mask))); |
13720 |
++ } |
13721 |
++#endif |
13722 |
++ flush_tlb_all(); |
13723 |
++#endif |
13724 |
++ |
13725 |
+ free_init_pages("unused kernel memory", |
13726 |
+ (unsigned long)(&__init_begin), |
13727 |
+ (unsigned long)(&__init_end)); |
13728 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/init_64.c linux-2.6.28.8/arch/x86/mm/init_64.c |
13729 |
+--- linux-2.6.28.8/arch/x86/mm/init_64.c 2009-02-06 16:47:45.000000000 -0500 |
13730 |
++++ linux-2.6.28.8/arch/x86/mm/init_64.c 2009-02-21 09:37:48.000000000 -0500 |
13731 |
+@@ -175,6 +175,10 @@ set_pte_vaddr_pud(pud_t *pud_page, unsig |
13732 |
+ pmd_t *pmd; |
13733 |
+ pte_t *pte; |
13734 |
+ |
13735 |
++#ifdef CONFIG_PAX_KERNEXEC |
13736 |
++ unsigned long cr0; |
13737 |
++#endif |
13738 |
++ |
13739 |
+ pud = pud_page + pud_index(vaddr); |
13740 |
+ if (pud_none(*pud)) { |
13741 |
+ pmd = (pmd_t *) spp_getpage(); |
13742 |
+@@ -196,8 +200,17 @@ set_pte_vaddr_pud(pud_t *pud_page, unsig |
13743 |
+ } |
13744 |
+ |
13745 |
+ pte = pte_offset_kernel(pmd, vaddr); |
13746 |
++ |
13747 |
++#ifdef CONFIG_PAX_KERNEXEC |
13748 |
++ pax_open_kernel(cr0); |
13749 |
++#endif |
13750 |
++ |
13751 |
+ set_pte(pte, new_pte); |
13752 |
+ |
13753 |
++#ifdef CONFIG_PAX_KERNEXEC |
13754 |
++ pax_close_kernel(cr0); |
13755 |
++#endif |
13756 |
++ |
13757 |
+ /* |
13758 |
+ * It's enough to flush this one mapping. |
13759 |
+ * (PGE mappings get flushed as well) |
13760 |
+@@ -238,14 +251,12 @@ static void __init __init_extra_mapping( |
13761 |
+ pgd = pgd_offset_k((unsigned long)__va(phys)); |
13762 |
+ if (pgd_none(*pgd)) { |
13763 |
+ pud = (pud_t *) spp_getpage(); |
13764 |
+- set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE | |
13765 |
+- _PAGE_USER)); |
13766 |
++ set_pgd(pgd, __pgd(__pa(pud) | _PAGE_TABLE)); |
13767 |
+ } |
13768 |
+ pud = pud_offset(pgd, (unsigned long)__va(phys)); |
13769 |
+ if (pud_none(*pud)) { |
13770 |
+ pmd = (pmd_t *) spp_getpage(); |
13771 |
+- set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE | |
13772 |
+- _PAGE_USER)); |
13773 |
++ set_pud(pud, __pud(__pa(pmd) | _PAGE_TABLE)); |
13774 |
+ } |
13775 |
+ pmd = pmd_offset(pud, phys); |
13776 |
+ BUG_ON(!pmd_none(*pmd)); |
13777 |
+@@ -886,7 +897,9 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to |
13778 |
+ */ |
13779 |
+ int devmem_is_allowed(unsigned long pagenr) |
13780 |
+ { |
13781 |
+- if (pagenr <= 256) |
13782 |
++ if (!pagenr) |
13783 |
++ return 1; |
13784 |
++ if ((ISA_START_ADDRESS >> PAGE_SHIFT) <= pagenr && pagenr < (ISA_END_ADDRESS >> PAGE_SHIFT)) |
13785 |
+ return 1; |
13786 |
+ if (!page_is_ram(pagenr)) |
13787 |
+ return 1; |
13788 |
+@@ -977,6 +990,39 @@ void free_init_pages(char *what, unsigne |
13789 |
+ |
13790 |
+ void free_initmem(void) |
13791 |
+ { |
13792 |
++ |
13793 |
++#ifdef CONFIG_PAX_KERNEXEC |
13794 |
++ unsigned long addr, end; |
13795 |
++ pgd_t *pgd; |
13796 |
++ pud_t *pud; |
13797 |
++ pmd_t *pmd; |
13798 |
++ |
13799 |
++ /* PaX: make kernel code/rodata read-only, rest non-executable */ |
13800 |
++ for (addr = __START_KERNEL_map; addr < __START_KERNEL_map + KERNEL_IMAGE_SIZE; addr += PMD_SIZE) { |
13801 |
++ pgd = pgd_offset_k(addr); |
13802 |
++ pud = pud_offset(pgd, addr); |
13803 |
++ pmd = pmd_offset(pud, addr); |
13804 |
++ if ((unsigned long)_text <= addr && addr < (unsigned long)_data) |
13805 |
++ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW)); |
13806 |
++ else |
13807 |
++ set_pmd(pmd, __pmd(pmd_val(*pmd) | (_PAGE_NX & __supported_pte_mask))); |
13808 |
++ } |
13809 |
++ |
13810 |
++ addr = (unsigned long)__va(__pa(__START_KERNEL_map)); |
13811 |
++ end = addr + KERNEL_IMAGE_SIZE; |
13812 |
++ for (; addr < end; addr += PMD_SIZE) { |
13813 |
++ pgd = pgd_offset_k(addr); |
13814 |
++ pud = pud_offset(pgd, addr); |
13815 |
++ pmd = pmd_offset(pud, addr); |
13816 |
++ if ((unsigned long)__va(__pa(_text)) <= addr && addr < (unsigned long)__va(__pa(_data))) |
13817 |
++ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW)); |
13818 |
++ else |
13819 |
++ set_pmd(pmd, __pmd(pmd_val(*pmd) | (_PAGE_NX & __supported_pte_mask))); |
13820 |
++ } |
13821 |
++ |
13822 |
++ flush_tlb_all(); |
13823 |
++#endif |
13824 |
++ |
13825 |
+ free_init_pages("unused kernel memory", |
13826 |
+ (unsigned long)(&__init_begin), |
13827 |
+ (unsigned long)(&__init_end)); |
13828 |
+@@ -1149,7 +1195,7 @@ int in_gate_area_no_task(unsigned long a |
13829 |
+ |
13830 |
+ const char *arch_vma_name(struct vm_area_struct *vma) |
13831 |
+ { |
13832 |
+- if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) |
13833 |
++ if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso) |
13834 |
+ return "[vdso]"; |
13835 |
+ if (vma == &gate_vma) |
13836 |
+ return "[vsyscall]"; |
13837 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/ioremap.c linux-2.6.28.8/arch/x86/mm/ioremap.c |
13838 |
+--- linux-2.6.28.8/arch/x86/mm/ioremap.c 2009-02-06 16:47:45.000000000 -0500 |
13839 |
++++ linux-2.6.28.8/arch/x86/mm/ioremap.c 2009-02-21 09:37:48.000000000 -0500 |
13840 |
+@@ -114,8 +114,8 @@ int page_is_ram(unsigned long pagenr) |
13841 |
+ * Second special case: Some BIOSen report the PC BIOS |
13842 |
+ * area (640->1Mb) as ram even though it is not. |
13843 |
+ */ |
13844 |
+- if (pagenr >= (BIOS_BEGIN >> PAGE_SHIFT) && |
13845 |
+- pagenr < (BIOS_END >> PAGE_SHIFT)) |
13846 |
++ if (pagenr >= (ISA_START_ADDRESS >> PAGE_SHIFT) && |
13847 |
++ pagenr < (ISA_END_ADDRESS >> PAGE_SHIFT)) |
13848 |
+ return 0; |
13849 |
+ |
13850 |
+ for (i = 0; i < e820.nr_map; i++) { |
13851 |
+@@ -293,6 +293,8 @@ static void __iomem *__ioremap_caller(re |
13852 |
+ break; |
13853 |
+ } |
13854 |
+ |
13855 |
++ prot = canon_pgprot(prot); |
13856 |
++ |
13857 |
+ /* |
13858 |
+ * Ok, go for it.. |
13859 |
+ */ |
13860 |
+@@ -508,7 +510,7 @@ static int __init early_ioremap_debug_se |
13861 |
+ early_param("early_ioremap_debug", early_ioremap_debug_setup); |
13862 |
+ |
13863 |
+ static __initdata int after_paging_init; |
13864 |
+-static pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __page_aligned_bss; |
13865 |
++static __initdata pte_t bm_pte[PAGE_SIZE/sizeof(pte_t)] __aligned(PAGE_SIZE); |
13866 |
+ |
13867 |
+ static inline pmd_t * __init early_ioremap_pmd(unsigned long addr) |
13868 |
+ { |
13869 |
+@@ -523,7 +525,11 @@ static inline pmd_t * __init early_iorem |
13870 |
+ |
13871 |
+ static inline pte_t * __init early_ioremap_pte(unsigned long addr) |
13872 |
+ { |
13873 |
++#ifdef CONFIG_X86_32 |
13874 |
+ return &bm_pte[pte_index(addr)]; |
13875 |
++#else |
13876 |
++ return &level1_fixmap_pgt[pte_index(addr)]; |
13877 |
++#endif |
13878 |
+ } |
13879 |
+ |
13880 |
+ void __init early_ioremap_init(void) |
13881 |
+@@ -534,8 +540,10 @@ void __init early_ioremap_init(void) |
13882 |
+ printk(KERN_INFO "early_ioremap_init()\n"); |
13883 |
+ |
13884 |
+ pmd = early_ioremap_pmd(fix_to_virt(FIX_BTMAP_BEGIN)); |
13885 |
++#ifdef CONFIG_X86_32 |
13886 |
+ memset(bm_pte, 0, sizeof(bm_pte)); |
13887 |
+ pmd_populate_kernel(&init_mm, pmd, bm_pte); |
13888 |
++#endif |
13889 |
+ |
13890 |
+ /* |
13891 |
+ * The boot-ioremap range spans multiple pmds, for which |
13892 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/mmap.c linux-2.6.28.8/arch/x86/mm/mmap.c |
13893 |
+--- linux-2.6.28.8/arch/x86/mm/mmap.c 2009-02-06 16:47:45.000000000 -0500 |
13894 |
++++ linux-2.6.28.8/arch/x86/mm/mmap.c 2009-02-21 09:37:48.000000000 -0500 |
13895 |
+@@ -36,7 +36,7 @@ |
13896 |
+ * Leave an at least ~128 MB hole. |
13897 |
+ */ |
13898 |
+ #define MIN_GAP (128*1024*1024) |
13899 |
+-#define MAX_GAP (TASK_SIZE/6*5) |
13900 |
++#define MAX_GAP (pax_task_size/6*5) |
13901 |
+ |
13902 |
+ /* |
13903 |
+ * True on X86_32 or when emulating IA32 on X86_64 |
13904 |
+@@ -81,27 +81,40 @@ static unsigned long mmap_rnd(void) |
13905 |
+ return rnd << PAGE_SHIFT; |
13906 |
+ } |
13907 |
+ |
13908 |
+-static unsigned long mmap_base(void) |
13909 |
++static unsigned long mmap_base(struct mm_struct *mm) |
13910 |
+ { |
13911 |
+ unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur; |
13912 |
++ unsigned long pax_task_size = TASK_SIZE; |
13913 |
++ |
13914 |
++#ifdef CONFIG_PAX_SEGMEXEC |
13915 |
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) |
13916 |
++ pax_task_size = SEGMEXEC_TASK_SIZE; |
13917 |
++#endif |
13918 |
+ |
13919 |
+ if (gap < MIN_GAP) |
13920 |
+ gap = MIN_GAP; |
13921 |
+ else if (gap > MAX_GAP) |
13922 |
+ gap = MAX_GAP; |
13923 |
+ |
13924 |
+- return PAGE_ALIGN(TASK_SIZE - gap - mmap_rnd()); |
13925 |
++ return PAGE_ALIGN(pax_task_size - gap - mmap_rnd()); |
13926 |
+ } |
13927 |
+ |
13928 |
+ /* |
13929 |
+ * Bottom-up (legacy) layout on X86_32 did not support randomization, X86_64 |
13930 |
+ * does, but not when emulating X86_32 |
13931 |
+ */ |
13932 |
+-static unsigned long mmap_legacy_base(void) |
13933 |
++static unsigned long mmap_legacy_base(struct mm_struct *mm) |
13934 |
+ { |
13935 |
+- if (mmap_is_ia32()) |
13936 |
++ if (mmap_is_ia32()) { |
13937 |
++ |
13938 |
++#ifdef CONFIG_PAX_SEGMEXEC |
13939 |
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) |
13940 |
++ return SEGMEXEC_TASK_UNMAPPED_BASE; |
13941 |
++ else |
13942 |
++#endif |
13943 |
++ |
13944 |
+ return TASK_UNMAPPED_BASE; |
13945 |
+- else |
13946 |
++ } else |
13947 |
+ return TASK_UNMAPPED_BASE + mmap_rnd(); |
13948 |
+ } |
13949 |
+ |
13950 |
+@@ -112,11 +125,23 @@ static unsigned long mmap_legacy_base(vo |
13951 |
+ void arch_pick_mmap_layout(struct mm_struct *mm) |
13952 |
+ { |
13953 |
+ if (mmap_is_legacy()) { |
13954 |
+- mm->mmap_base = mmap_legacy_base(); |
13955 |
++ mm->mmap_base = mmap_legacy_base(mm); |
13956 |
++ |
13957 |
++#ifdef CONFIG_PAX_RANDMMAP |
13958 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
13959 |
++ mm->mmap_base += mm->delta_mmap; |
13960 |
++#endif |
13961 |
++ |
13962 |
+ mm->get_unmapped_area = arch_get_unmapped_area; |
13963 |
+ mm->unmap_area = arch_unmap_area; |
13964 |
+ } else { |
13965 |
+- mm->mmap_base = mmap_base(); |
13966 |
++ mm->mmap_base = mmap_base(mm); |
13967 |
++ |
13968 |
++#ifdef CONFIG_PAX_RANDMMAP |
13969 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
13970 |
++ mm->mmap_base -= mm->delta_mmap + mm->delta_stack; |
13971 |
++#endif |
13972 |
++ |
13973 |
+ mm->get_unmapped_area = arch_get_unmapped_area_topdown; |
13974 |
+ mm->unmap_area = arch_unmap_area_topdown; |
13975 |
+ } |
13976 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/numa_32.c linux-2.6.28.8/arch/x86/mm/numa_32.c |
13977 |
+--- linux-2.6.28.8/arch/x86/mm/numa_32.c 2009-02-06 16:47:45.000000000 -0500 |
13978 |
++++ linux-2.6.28.8/arch/x86/mm/numa_32.c 2009-02-21 09:37:48.000000000 -0500 |
13979 |
+@@ -98,7 +98,6 @@ unsigned long node_memmap_size_bytes(int |
13980 |
+ } |
13981 |
+ #endif |
13982 |
+ |
13983 |
+-extern unsigned long find_max_low_pfn(void); |
13984 |
+ extern unsigned long highend_pfn, highstart_pfn; |
13985 |
+ |
13986 |
+ #define LARGE_PAGE_BYTES (PTRS_PER_PTE * PAGE_SIZE) |
13987 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/pageattr.c linux-2.6.28.8/arch/x86/mm/pageattr.c |
13988 |
+--- linux-2.6.28.8/arch/x86/mm/pageattr.c 2009-02-20 22:26:38.000000000 -0500 |
13989 |
++++ linux-2.6.28.8/arch/x86/mm/pageattr.c 2009-02-21 09:37:48.000000000 -0500 |
13990 |
+@@ -20,6 +20,7 @@ |
13991 |
+ #include <asm/pgalloc.h> |
13992 |
+ #include <asm/proto.h> |
13993 |
+ #include <asm/pat.h> |
13994 |
++#include <asm/desc.h> |
13995 |
+ |
13996 |
+ /* |
13997 |
+ * The current flushing context - we pass it instead of 5 arguments: |
13998 |
+@@ -259,7 +260,7 @@ static inline pgprot_t static_protection |
13999 |
+ * Does not cover __inittext since that is gone later on. On |
14000 |
+ * 64bit we do not enforce !NX on the low mapping |
14001 |
+ */ |
14002 |
+- if (within(address, (unsigned long)_text, (unsigned long)_etext)) |
14003 |
++ if (within(address, ktla_ktva((unsigned long)_text), ktla_ktva((unsigned long)_etext))) |
14004 |
+ pgprot_val(forbidden) |= _PAGE_NX; |
14005 |
+ |
14006 |
+ /* |
14007 |
+@@ -321,8 +322,20 @@ EXPORT_SYMBOL_GPL(lookup_address); |
14008 |
+ */ |
14009 |
+ static void __set_pmd_pte(pte_t *kpte, unsigned long address, pte_t pte) |
14010 |
+ { |
14011 |
++ |
14012 |
++#ifdef CONFIG_PAX_KERNEXEC |
14013 |
++ unsigned long cr0; |
14014 |
++ |
14015 |
++ pax_open_kernel(cr0); |
14016 |
++#endif |
14017 |
++ |
14018 |
+ /* change init_mm */ |
14019 |
+ set_pte_atomic(kpte, pte); |
14020 |
++ |
14021 |
++#ifdef CONFIG_PAX_KERNEXEC |
14022 |
++ pax_close_kernel(cr0); |
14023 |
++#endif |
14024 |
++ |
14025 |
+ #ifdef CONFIG_X86_32 |
14026 |
+ if (!SHARED_KERNEL_PMD) { |
14027 |
+ struct page *page; |
14028 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/pageattr-test.c linux-2.6.28.8/arch/x86/mm/pageattr-test.c |
14029 |
+--- linux-2.6.28.8/arch/x86/mm/pageattr-test.c 2009-02-06 16:47:45.000000000 -0500 |
14030 |
++++ linux-2.6.28.8/arch/x86/mm/pageattr-test.c 2009-03-07 10:35:39.000000000 -0500 |
14031 |
+@@ -36,7 +36,7 @@ enum { |
14032 |
+ |
14033 |
+ static int pte_testbit(pte_t pte) |
14034 |
+ { |
14035 |
+- return pte_flags(pte) & _PAGE_UNUSED1; |
14036 |
++ return pte_flags(pte) & _PAGE_CPA_TEST; |
14037 |
+ } |
14038 |
+ |
14039 |
+ struct split_state { |
14040 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/pat.c linux-2.6.28.8/arch/x86/mm/pat.c |
14041 |
+--- linux-2.6.28.8/arch/x86/mm/pat.c 2009-02-06 16:47:45.000000000 -0500 |
14042 |
++++ linux-2.6.28.8/arch/x86/mm/pat.c 2009-03-07 14:05:58.000000000 -0500 |
14043 |
+@@ -491,7 +491,7 @@ pgprot_t phys_mem_access_prot(struct fil |
14044 |
+ return vma_prot; |
14045 |
+ } |
14046 |
+ |
14047 |
+-#ifdef CONFIG_STRICT_DEVMEM |
14048 |
++#ifndef CONFIG_STRICT_DEVMEM |
14049 |
+ /* This check is done in drivers/char/mem.c in case of STRICT_DEVMEM*/ |
14050 |
+ static inline int range_is_allowed(unsigned long pfn, unsigned long size) |
14051 |
+ { |
14052 |
+diff -urNp linux-2.6.28.8/arch/x86/mm/pgtable_32.c linux-2.6.28.8/arch/x86/mm/pgtable_32.c |
14053 |
+--- linux-2.6.28.8/arch/x86/mm/pgtable_32.c 2009-02-06 16:47:45.000000000 -0500 |
14054 |
++++ linux-2.6.28.8/arch/x86/mm/pgtable_32.c 2009-02-21 09:37:48.000000000 -0500 |
14055 |
+@@ -31,6 +31,10 @@ void set_pte_vaddr(unsigned long vaddr, |
14056 |
+ pmd_t *pmd; |
14057 |
+ pte_t *pte; |
14058 |
+ |
14059 |
++#ifdef CONFIG_PAX_KERNEXEC |
14060 |
++ unsigned long cr0; |
14061 |
++#endif |
14062 |
++ |
14063 |
+ pgd = swapper_pg_dir + pgd_index(vaddr); |
14064 |
+ if (pgd_none(*pgd)) { |
14065 |
+ BUG(); |
14066 |
+@@ -47,11 +51,20 @@ void set_pte_vaddr(unsigned long vaddr, |
14067 |
+ return; |
14068 |
+ } |
14069 |
+ pte = pte_offset_kernel(pmd, vaddr); |
14070 |
++ |
14071 |
++#ifdef CONFIG_PAX_KERNEXEC |
14072 |
++ pax_open_kernel(cr0); |
14073 |
++#endif |
14074 |
++ |
14075 |
+ if (pte_val(pteval)) |
14076 |
+ set_pte_present(&init_mm, vaddr, pte, pteval); |
14077 |
+ else |
14078 |
+ pte_clear(&init_mm, vaddr, pte); |
14079 |
+ |
14080 |
++#ifdef CONFIG_PAX_KERNEXEC |
14081 |
++ pax_close_kernel(cr0); |
14082 |
++#endif |
14083 |
++ |
14084 |
+ /* |
14085 |
+ * It's enough to flush this one mapping. |
14086 |
+ * (PGE mappings get flushed as well) |
14087 |
+diff -urNp linux-2.6.28.8/arch/x86/oprofile/backtrace.c linux-2.6.28.8/arch/x86/oprofile/backtrace.c |
14088 |
+--- linux-2.6.28.8/arch/x86/oprofile/backtrace.c 2009-02-06 16:47:45.000000000 -0500 |
14089 |
++++ linux-2.6.28.8/arch/x86/oprofile/backtrace.c 2009-02-21 09:37:48.000000000 -0500 |
14090 |
+@@ -37,7 +37,7 @@ static void backtrace_address(void *data |
14091 |
+ unsigned int *depth = data; |
14092 |
+ |
14093 |
+ if ((*depth)--) |
14094 |
+- oprofile_add_trace(addr); |
14095 |
++ oprofile_add_trace(ktla_ktva(addr)); |
14096 |
+ } |
14097 |
+ |
14098 |
+ static struct stacktrace_ops backtrace_ops = { |
14099 |
+@@ -78,7 +78,7 @@ x86_backtrace(struct pt_regs * const reg |
14100 |
+ struct frame_head *head = (struct frame_head *)frame_pointer(regs); |
14101 |
+ unsigned long stack = kernel_trap_sp(regs); |
14102 |
+ |
14103 |
+- if (!user_mode_vm(regs)) { |
14104 |
++ if (!user_mode(regs)) { |
14105 |
+ if (depth) |
14106 |
+ dump_trace(NULL, regs, (unsigned long *)stack, 0, |
14107 |
+ &backtrace_ops, &depth); |
14108 |
+diff -urNp linux-2.6.28.8/arch/x86/oprofile/op_model_p4.c linux-2.6.28.8/arch/x86/oprofile/op_model_p4.c |
14109 |
+--- linux-2.6.28.8/arch/x86/oprofile/op_model_p4.c 2009-02-06 16:47:45.000000000 -0500 |
14110 |
++++ linux-2.6.28.8/arch/x86/oprofile/op_model_p4.c 2009-02-21 09:37:48.000000000 -0500 |
14111 |
+@@ -48,7 +48,7 @@ static inline void setup_num_counters(vo |
14112 |
+ #endif |
14113 |
+ } |
14114 |
+ |
14115 |
+-static int inline addr_increment(void) |
14116 |
++static inline int addr_increment(void) |
14117 |
+ { |
14118 |
+ #ifdef CONFIG_SMP |
14119 |
+ return smp_num_siblings == 2 ? 2 : 1; |
14120 |
+diff -urNp linux-2.6.28.8/arch/x86/pci/common.c linux-2.6.28.8/arch/x86/pci/common.c |
14121 |
+--- linux-2.6.28.8/arch/x86/pci/common.c 2009-02-06 16:47:45.000000000 -0500 |
14122 |
++++ linux-2.6.28.8/arch/x86/pci/common.c 2009-02-21 09:37:48.000000000 -0500 |
14123 |
+@@ -362,7 +362,7 @@ static struct dmi_system_id __devinitdat |
14124 |
+ DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL585 G2"), |
14125 |
+ }, |
14126 |
+ }, |
14127 |
+- {} |
14128 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL} |
14129 |
+ }; |
14130 |
+ |
14131 |
+ void __init dmi_check_pciprobe(void) |
14132 |
+diff -urNp linux-2.6.28.8/arch/x86/pci/fixup.c linux-2.6.28.8/arch/x86/pci/fixup.c |
14133 |
+--- linux-2.6.28.8/arch/x86/pci/fixup.c 2009-02-06 16:47:45.000000000 -0500 |
14134 |
++++ linux-2.6.28.8/arch/x86/pci/fixup.c 2009-02-21 09:37:48.000000000 -0500 |
14135 |
+@@ -365,7 +365,7 @@ static struct dmi_system_id __devinitdat |
14136 |
+ DMI_MATCH(DMI_PRODUCT_NAME, "MS-6702E"), |
14137 |
+ }, |
14138 |
+ }, |
14139 |
+- {} |
14140 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL } |
14141 |
+ }; |
14142 |
+ |
14143 |
+ /* |
14144 |
+@@ -436,7 +436,7 @@ static struct dmi_system_id __devinitdat |
14145 |
+ DMI_MATCH(DMI_PRODUCT_VERSION, "PSA40U"), |
14146 |
+ }, |
14147 |
+ }, |
14148 |
+- { } |
14149 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL } |
14150 |
+ }; |
14151 |
+ |
14152 |
+ static void __devinit pci_pre_fixup_toshiba_ohci1394(struct pci_dev *dev) |
14153 |
+diff -urNp linux-2.6.28.8/arch/x86/pci/irq.c linux-2.6.28.8/arch/x86/pci/irq.c |
14154 |
+--- linux-2.6.28.8/arch/x86/pci/irq.c 2009-02-06 16:47:45.000000000 -0500 |
14155 |
++++ linux-2.6.28.8/arch/x86/pci/irq.c 2009-02-21 09:37:48.000000000 -0500 |
14156 |
+@@ -544,7 +544,7 @@ static __init int intel_router_probe(str |
14157 |
+ static struct pci_device_id __initdata pirq_440gx[] = { |
14158 |
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_0) }, |
14159 |
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443GX_2) }, |
14160 |
+- { }, |
14161 |
++ { PCI_DEVICE(0, 0) } |
14162 |
+ }; |
14163 |
+ |
14164 |
+ /* 440GX has a proprietary PIRQ router -- don't use it */ |
14165 |
+@@ -1148,7 +1148,7 @@ static struct dmi_system_id __initdata p |
14166 |
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 360"), |
14167 |
+ }, |
14168 |
+ }, |
14169 |
+- { } |
14170 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL } |
14171 |
+ }; |
14172 |
+ |
14173 |
+ int __init pcibios_irq_init(void) |
14174 |
+diff -urNp linux-2.6.28.8/arch/x86/pci/pcbios.c linux-2.6.28.8/arch/x86/pci/pcbios.c |
14175 |
+--- linux-2.6.28.8/arch/x86/pci/pcbios.c 2009-02-06 16:47:45.000000000 -0500 |
14176 |
++++ linux-2.6.28.8/arch/x86/pci/pcbios.c 2009-02-21 09:37:48.000000000 -0500 |
14177 |
+@@ -57,50 +57,120 @@ union bios32 { |
14178 |
+ static struct { |
14179 |
+ unsigned long address; |
14180 |
+ unsigned short segment; |
14181 |
+-} bios32_indirect = { 0, __KERNEL_CS }; |
14182 |
++} bios32_indirect __read_only = { 0, __PCIBIOS_CS }; |
14183 |
+ |
14184 |
+ /* |
14185 |
+ * Returns the entry point for the given service, NULL on error |
14186 |
+ */ |
14187 |
+ |
14188 |
+-static unsigned long bios32_service(unsigned long service) |
14189 |
++static unsigned long __devinit bios32_service(unsigned long service) |
14190 |
+ { |
14191 |
+ unsigned char return_code; /* %al */ |
14192 |
+ unsigned long address; /* %ebx */ |
14193 |
+ unsigned long length; /* %ecx */ |
14194 |
+ unsigned long entry; /* %edx */ |
14195 |
+ unsigned long flags; |
14196 |
++ struct desc_struct d, *gdt; |
14197 |
++ |
14198 |
++#ifdef CONFIG_PAX_KERNEXEC |
14199 |
++ unsigned long cr0; |
14200 |
++#endif |
14201 |
+ |
14202 |
+ local_irq_save(flags); |
14203 |
+- __asm__("lcall *(%%edi); cld" |
14204 |
++ |
14205 |
++ gdt = get_cpu_gdt_table(smp_processor_id()); |
14206 |
++ |
14207 |
++#ifdef CONFIG_PAX_KERNEXEC |
14208 |
++ pax_open_kernel(cr0); |
14209 |
++#endif |
14210 |
++ |
14211 |
++ pack_descriptor(&d, 0UL, 0xFFFFFUL, 0x9B, 0xC); |
14212 |
++ write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_CS, &d, DESCTYPE_S); |
14213 |
++ pack_descriptor(&d, 0UL, 0xFFFFFUL, 0x93, 0xC); |
14214 |
++ write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_DS, &d, DESCTYPE_S); |
14215 |
++ |
14216 |
++#ifdef CONFIG_PAX_KERNEXEC |
14217 |
++ pax_close_kernel(cr0); |
14218 |
++#endif |
14219 |
++ |
14220 |
++ __asm__("movw %w7, %%ds; lcall *(%%edi); push %%ss; pop %%ds; cld" |
14221 |
+ : "=a" (return_code), |
14222 |
+ "=b" (address), |
14223 |
+ "=c" (length), |
14224 |
+ "=d" (entry) |
14225 |
+ : "0" (service), |
14226 |
+ "1" (0), |
14227 |
+- "D" (&bios32_indirect)); |
14228 |
++ "D" (&bios32_indirect), |
14229 |
++ "r"(__PCIBIOS_DS) |
14230 |
++ : "memory"); |
14231 |
++ |
14232 |
++#ifdef CONFIG_PAX_KERNEXEC |
14233 |
++ pax_open_kernel(cr0); |
14234 |
++#endif |
14235 |
++ |
14236 |
++ gdt[GDT_ENTRY_PCIBIOS_CS].a = 0; |
14237 |
++ gdt[GDT_ENTRY_PCIBIOS_CS].b = 0; |
14238 |
++ gdt[GDT_ENTRY_PCIBIOS_DS].a = 0; |
14239 |
++ gdt[GDT_ENTRY_PCIBIOS_DS].b = 0; |
14240 |
++ |
14241 |
++#ifdef CONFIG_PAX_KERNEXEC |
14242 |
++ pax_close_kernel(cr0); |
14243 |
++#endif |
14244 |
++ |
14245 |
+ local_irq_restore(flags); |
14246 |
+ |
14247 |
+ switch (return_code) { |
14248 |
+- case 0: |
14249 |
+- return address + entry; |
14250 |
+- case 0x80: /* Not present */ |
14251 |
+- printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service); |
14252 |
+- return 0; |
14253 |
+- default: /* Shouldn't happen */ |
14254 |
+- printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n", |
14255 |
+- service, return_code); |
14256 |
++ case 0: { |
14257 |
++ int cpu; |
14258 |
++ unsigned char flags; |
14259 |
++ |
14260 |
++ printk(KERN_INFO "bios32_service: base:%08lx length:%08lx entry:%08lx\n", address, length, entry); |
14261 |
++ if (address >= 0xFFFF0 || length > 0x100000 - address || length <= entry) { |
14262 |
++ printk(KERN_WARNING "bios32_service: not valid\n"); |
14263 |
+ return 0; |
14264 |
++ } |
14265 |
++ address = address + PAGE_OFFSET; |
14266 |
++ length += 16UL; /* some BIOSs underreport this... */ |
14267 |
++ flags = 4; |
14268 |
++ if (length >= 64*1024*1024) { |
14269 |
++ length >>= PAGE_SHIFT; |
14270 |
++ flags |= 8; |
14271 |
++ } |
14272 |
++ |
14273 |
++#ifdef CONFIG_PAX_KERNEXEC |
14274 |
++ pax_open_kernel(cr0); |
14275 |
++#endif |
14276 |
++ |
14277 |
++ for (cpu = 0; cpu < NR_CPUS; cpu++) { |
14278 |
++ gdt = get_cpu_gdt_table(cpu); |
14279 |
++ pack_descriptor(&d, address, length, 0x9b, flags); |
14280 |
++ write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_CS, &d, DESCTYPE_S); |
14281 |
++ pack_descriptor(&d, address, length, 0x93, flags); |
14282 |
++ write_gdt_entry(gdt, GDT_ENTRY_PCIBIOS_DS, &d, DESCTYPE_S); |
14283 |
++ } |
14284 |
++ |
14285 |
++#ifdef CONFIG_PAX_KERNEXEC |
14286 |
++ pax_close_kernel(cr0); |
14287 |
++#endif |
14288 |
++ |
14289 |
++ return entry; |
14290 |
++ } |
14291 |
++ case 0x80: /* Not present */ |
14292 |
++ printk(KERN_WARNING "bios32_service(0x%lx): not present\n", service); |
14293 |
++ return 0; |
14294 |
++ default: /* Shouldn't happen */ |
14295 |
++ printk(KERN_WARNING "bios32_service(0x%lx): returned 0x%x -- BIOS bug!\n", |
14296 |
++ service, return_code); |
14297 |
++ return 0; |
14298 |
+ } |
14299 |
+ } |
14300 |
+ |
14301 |
+ static struct { |
14302 |
+ unsigned long address; |
14303 |
+ unsigned short segment; |
14304 |
+-} pci_indirect = { 0, __KERNEL_CS }; |
14305 |
++} pci_indirect __read_only = { 0, __PCIBIOS_CS }; |
14306 |
+ |
14307 |
+-static int pci_bios_present; |
14308 |
++static int pci_bios_present __read_only; |
14309 |
+ |
14310 |
+ static int __devinit check_pcibios(void) |
14311 |
+ { |
14312 |
+@@ -109,11 +179,13 @@ static int __devinit check_pcibios(void) |
14313 |
+ unsigned long flags, pcibios_entry; |
14314 |
+ |
14315 |
+ if ((pcibios_entry = bios32_service(PCI_SERVICE))) { |
14316 |
+- pci_indirect.address = pcibios_entry + PAGE_OFFSET; |
14317 |
++ pci_indirect.address = pcibios_entry; |
14318 |
+ |
14319 |
+ local_irq_save(flags); |
14320 |
+- __asm__( |
14321 |
+- "lcall *(%%edi); cld\n\t" |
14322 |
++ __asm__("movw %w6, %%ds\n\t" |
14323 |
++ "lcall *%%ss:(%%edi); cld\n\t" |
14324 |
++ "push %%ss\n\t" |
14325 |
++ "pop %%ds\n\t" |
14326 |
+ "jc 1f\n\t" |
14327 |
+ "xor %%ah, %%ah\n" |
14328 |
+ "1:" |
14329 |
+@@ -122,7 +194,8 @@ static int __devinit check_pcibios(void) |
14330 |
+ "=b" (ebx), |
14331 |
+ "=c" (ecx) |
14332 |
+ : "1" (PCIBIOS_PCI_BIOS_PRESENT), |
14333 |
+- "D" (&pci_indirect) |
14334 |
++ "D" (&pci_indirect), |
14335 |
++ "r" (__PCIBIOS_DS) |
14336 |
+ : "memory"); |
14337 |
+ local_irq_restore(flags); |
14338 |
+ |
14339 |
+@@ -166,7 +239,10 @@ static int pci_bios_read(unsigned int se |
14340 |
+ |
14341 |
+ switch (len) { |
14342 |
+ case 1: |
14343 |
+- __asm__("lcall *(%%esi); cld\n\t" |
14344 |
++ __asm__("movw %w6, %%ds\n\t" |
14345 |
++ "lcall *%%ss:(%%esi); cld\n\t" |
14346 |
++ "push %%ss\n\t" |
14347 |
++ "pop %%ds\n\t" |
14348 |
+ "jc 1f\n\t" |
14349 |
+ "xor %%ah, %%ah\n" |
14350 |
+ "1:" |
14351 |
+@@ -175,7 +251,8 @@ static int pci_bios_read(unsigned int se |
14352 |
+ : "1" (PCIBIOS_READ_CONFIG_BYTE), |
14353 |
+ "b" (bx), |
14354 |
+ "D" ((long)reg), |
14355 |
+- "S" (&pci_indirect)); |
14356 |
++ "S" (&pci_indirect), |
14357 |
++ "r" (__PCIBIOS_DS)); |
14358 |
+ /* |
14359 |
+ * Zero-extend the result beyond 8 bits, do not trust the |
14360 |
+ * BIOS having done it: |
14361 |
+@@ -183,7 +260,10 @@ static int pci_bios_read(unsigned int se |
14362 |
+ *value &= 0xff; |
14363 |
+ break; |
14364 |
+ case 2: |
14365 |
+- __asm__("lcall *(%%esi); cld\n\t" |
14366 |
++ __asm__("movw %w6, %%ds\n\t" |
14367 |
++ "lcall *%%ss:(%%esi); cld\n\t" |
14368 |
++ "push %%ss\n\t" |
14369 |
++ "pop %%ds\n\t" |
14370 |
+ "jc 1f\n\t" |
14371 |
+ "xor %%ah, %%ah\n" |
14372 |
+ "1:" |
14373 |
+@@ -192,7 +272,8 @@ static int pci_bios_read(unsigned int se |
14374 |
+ : "1" (PCIBIOS_READ_CONFIG_WORD), |
14375 |
+ "b" (bx), |
14376 |
+ "D" ((long)reg), |
14377 |
+- "S" (&pci_indirect)); |
14378 |
++ "S" (&pci_indirect), |
14379 |
++ "r" (__PCIBIOS_DS)); |
14380 |
+ /* |
14381 |
+ * Zero-extend the result beyond 16 bits, do not trust the |
14382 |
+ * BIOS having done it: |
14383 |
+@@ -200,7 +281,10 @@ static int pci_bios_read(unsigned int se |
14384 |
+ *value &= 0xffff; |
14385 |
+ break; |
14386 |
+ case 4: |
14387 |
+- __asm__("lcall *(%%esi); cld\n\t" |
14388 |
++ __asm__("movw %w6, %%ds\n\t" |
14389 |
++ "lcall *%%ss:(%%esi); cld\n\t" |
14390 |
++ "push %%ss\n\t" |
14391 |
++ "pop %%ds\n\t" |
14392 |
+ "jc 1f\n\t" |
14393 |
+ "xor %%ah, %%ah\n" |
14394 |
+ "1:" |
14395 |
+@@ -209,7 +293,8 @@ static int pci_bios_read(unsigned int se |
14396 |
+ : "1" (PCIBIOS_READ_CONFIG_DWORD), |
14397 |
+ "b" (bx), |
14398 |
+ "D" ((long)reg), |
14399 |
+- "S" (&pci_indirect)); |
14400 |
++ "S" (&pci_indirect), |
14401 |
++ "r" (__PCIBIOS_DS)); |
14402 |
+ break; |
14403 |
+ } |
14404 |
+ |
14405 |
+@@ -232,7 +317,10 @@ static int pci_bios_write(unsigned int s |
14406 |
+ |
14407 |
+ switch (len) { |
14408 |
+ case 1: |
14409 |
+- __asm__("lcall *(%%esi); cld\n\t" |
14410 |
++ __asm__("movw %w6, %%ds\n\t" |
14411 |
++ "lcall *%%ss:(%%esi); cld\n\t" |
14412 |
++ "push %%ss\n\t" |
14413 |
++ "pop %%ds\n\t" |
14414 |
+ "jc 1f\n\t" |
14415 |
+ "xor %%ah, %%ah\n" |
14416 |
+ "1:" |
14417 |
+@@ -241,10 +329,14 @@ static int pci_bios_write(unsigned int s |
14418 |
+ "c" (value), |
14419 |
+ "b" (bx), |
14420 |
+ "D" ((long)reg), |
14421 |
+- "S" (&pci_indirect)); |
14422 |
++ "S" (&pci_indirect), |
14423 |
++ "r" (__PCIBIOS_DS)); |
14424 |
+ break; |
14425 |
+ case 2: |
14426 |
+- __asm__("lcall *(%%esi); cld\n\t" |
14427 |
++ __asm__("movw %w6, %%ds\n\t" |
14428 |
++ "lcall *%%ss:(%%esi); cld\n\t" |
14429 |
++ "push %%ss\n\t" |
14430 |
++ "pop %%ds\n\t" |
14431 |
+ "jc 1f\n\t" |
14432 |
+ "xor %%ah, %%ah\n" |
14433 |
+ "1:" |
14434 |
+@@ -253,10 +345,14 @@ static int pci_bios_write(unsigned int s |
14435 |
+ "c" (value), |
14436 |
+ "b" (bx), |
14437 |
+ "D" ((long)reg), |
14438 |
+- "S" (&pci_indirect)); |
14439 |
++ "S" (&pci_indirect), |
14440 |
++ "r" (__PCIBIOS_DS)); |
14441 |
+ break; |
14442 |
+ case 4: |
14443 |
+- __asm__("lcall *(%%esi); cld\n\t" |
14444 |
++ __asm__("movw %w6, %%ds\n\t" |
14445 |
++ "lcall *%%ss:(%%esi); cld\n\t" |
14446 |
++ "push %%ss\n\t" |
14447 |
++ "pop %%ds\n\t" |
14448 |
+ "jc 1f\n\t" |
14449 |
+ "xor %%ah, %%ah\n" |
14450 |
+ "1:" |
14451 |
+@@ -265,7 +361,8 @@ static int pci_bios_write(unsigned int s |
14452 |
+ "c" (value), |
14453 |
+ "b" (bx), |
14454 |
+ "D" ((long)reg), |
14455 |
+- "S" (&pci_indirect)); |
14456 |
++ "S" (&pci_indirect), |
14457 |
++ "r" (__PCIBIOS_DS)); |
14458 |
+ break; |
14459 |
+ } |
14460 |
+ |
14461 |
+@@ -369,10 +466,13 @@ struct irq_routing_table * pcibios_get_i |
14462 |
+ |
14463 |
+ DBG("PCI: Fetching IRQ routing table... "); |
14464 |
+ __asm__("push %%es\n\t" |
14465 |
++ "movw %w8, %%ds\n\t" |
14466 |
+ "push %%ds\n\t" |
14467 |
+ "pop %%es\n\t" |
14468 |
+- "lcall *(%%esi); cld\n\t" |
14469 |
++ "lcall *%%ss:(%%esi); cld\n\t" |
14470 |
+ "pop %%es\n\t" |
14471 |
++ "push %%ss\n\t" |
14472 |
++ "pop %%ds\n" |
14473 |
+ "jc 1f\n\t" |
14474 |
+ "xor %%ah, %%ah\n" |
14475 |
+ "1:" |
14476 |
+@@ -383,7 +483,8 @@ struct irq_routing_table * pcibios_get_i |
14477 |
+ "1" (0), |
14478 |
+ "D" ((long) &opt), |
14479 |
+ "S" (&pci_indirect), |
14480 |
+- "m" (opt) |
14481 |
++ "m" (opt), |
14482 |
++ "r" (__PCIBIOS_DS) |
14483 |
+ : "memory"); |
14484 |
+ DBG("OK ret=%d, size=%d, map=%x\n", ret, opt.size, map); |
14485 |
+ if (ret & 0xff00) |
14486 |
+@@ -407,7 +508,10 @@ int pcibios_set_irq_routing(struct pci_d |
14487 |
+ { |
14488 |
+ int ret; |
14489 |
+ |
14490 |
+- __asm__("lcall *(%%esi); cld\n\t" |
14491 |
++ __asm__("movw %w5, %%ds\n\t" |
14492 |
++ "lcall *%%ss:(%%esi); cld\n\t" |
14493 |
++ "push %%ss\n\t" |
14494 |
++ "pop %%ds\n" |
14495 |
+ "jc 1f\n\t" |
14496 |
+ "xor %%ah, %%ah\n" |
14497 |
+ "1:" |
14498 |
+@@ -415,7 +519,8 @@ int pcibios_set_irq_routing(struct pci_d |
14499 |
+ : "0" (PCIBIOS_SET_PCI_HW_INT), |
14500 |
+ "b" ((dev->bus->number << 8) | dev->devfn), |
14501 |
+ "c" ((irq << 8) | (pin + 10)), |
14502 |
+- "S" (&pci_indirect)); |
14503 |
++ "S" (&pci_indirect), |
14504 |
++ "r" (__PCIBIOS_DS)); |
14505 |
+ return !(ret & 0xff00); |
14506 |
+ } |
14507 |
+ EXPORT_SYMBOL(pcibios_set_irq_routing); |
14508 |
+diff -urNp linux-2.6.28.8/arch/x86/power/cpu_32.c linux-2.6.28.8/arch/x86/power/cpu_32.c |
14509 |
+--- linux-2.6.28.8/arch/x86/power/cpu_32.c 2009-02-06 16:47:45.000000000 -0500 |
14510 |
++++ linux-2.6.28.8/arch/x86/power/cpu_32.c 2009-02-21 09:37:48.000000000 -0500 |
14511 |
+@@ -67,7 +67,7 @@ static void do_fpu_end(void) |
14512 |
+ static void fix_processor_context(void) |
14513 |
+ { |
14514 |
+ int cpu = smp_processor_id(); |
14515 |
+- struct tss_struct *t = &per_cpu(init_tss, cpu); |
14516 |
++ struct tss_struct *t = init_tss + cpu; |
14517 |
+ |
14518 |
+ set_tss_desc(cpu, t); /* |
14519 |
+ * This just modifies memory; should not be |
14520 |
+diff -urNp linux-2.6.28.8/arch/x86/power/cpu_64.c linux-2.6.28.8/arch/x86/power/cpu_64.c |
14521 |
+--- linux-2.6.28.8/arch/x86/power/cpu_64.c 2009-02-06 16:47:45.000000000 -0500 |
14522 |
++++ linux-2.6.28.8/arch/x86/power/cpu_64.c 2009-02-21 09:37:48.000000000 -0500 |
14523 |
+@@ -143,7 +143,11 @@ void restore_processor_state(void) |
14524 |
+ static void fix_processor_context(void) |
14525 |
+ { |
14526 |
+ int cpu = smp_processor_id(); |
14527 |
+- struct tss_struct *t = &per_cpu(init_tss, cpu); |
14528 |
++ struct tss_struct *t = init_tss + cpu; |
14529 |
++ |
14530 |
++#ifdef CONFIG_PAX_KERNEXEC |
14531 |
++ unsigned long cr0; |
14532 |
++#endif |
14533 |
+ |
14534 |
+ /* |
14535 |
+ * This just modifies memory; should not be necessary. But... This |
14536 |
+@@ -152,8 +156,16 @@ static void fix_processor_context(void) |
14537 |
+ */ |
14538 |
+ set_tss_desc(cpu, t); |
14539 |
+ |
14540 |
++#ifdef CONFIG_PAX_KERNEXEC |
14541 |
++ pax_open_kernel(cr0); |
14542 |
++#endif |
14543 |
++ |
14544 |
+ get_cpu_gdt_table(cpu)[GDT_ENTRY_TSS].type = 9; |
14545 |
+ |
14546 |
++#ifdef CONFIG_PAX_KERNEXEC |
14547 |
++ pax_close_kernel(cr0); |
14548 |
++#endif |
14549 |
++ |
14550 |
+ syscall_init(); /* This sets MSR_*STAR and related */ |
14551 |
+ load_TR_desc(); /* This does ltr */ |
14552 |
+ load_LDT(¤t->active_mm->context); /* This does lldt */ |
14553 |
+diff -urNp linux-2.6.28.8/arch/x86/vdso/vdso32-setup.c linux-2.6.28.8/arch/x86/vdso/vdso32-setup.c |
14554 |
+--- linux-2.6.28.8/arch/x86/vdso/vdso32-setup.c 2009-02-06 16:47:45.000000000 -0500 |
14555 |
++++ linux-2.6.28.8/arch/x86/vdso/vdso32-setup.c 2009-02-21 09:37:48.000000000 -0500 |
14556 |
+@@ -226,7 +226,7 @@ static inline void map_compat_vdso(int m |
14557 |
+ void enable_sep_cpu(void) |
14558 |
+ { |
14559 |
+ int cpu = get_cpu(); |
14560 |
+- struct tss_struct *tss = &per_cpu(init_tss, cpu); |
14561 |
++ struct tss_struct *tss = init_tss + cpu; |
14562 |
+ |
14563 |
+ if (!boot_cpu_has(X86_FEATURE_SEP)) { |
14564 |
+ put_cpu(); |
14565 |
+@@ -249,7 +249,7 @@ static int __init gate_vma_init(void) |
14566 |
+ gate_vma.vm_start = FIXADDR_USER_START; |
14567 |
+ gate_vma.vm_end = FIXADDR_USER_END; |
14568 |
+ gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC; |
14569 |
+- gate_vma.vm_page_prot = __P101; |
14570 |
++ gate_vma.vm_page_prot = vm_get_page_prot(gate_vma.vm_flags); |
14571 |
+ /* |
14572 |
+ * Make sure the vDSO gets into every core dump. |
14573 |
+ * Dumping its contents makes post-mortem fully interpretable later |
14574 |
+@@ -331,7 +331,7 @@ int arch_setup_additional_pages(struct l |
14575 |
+ if (compat) |
14576 |
+ addr = VDSO_HIGH_BASE; |
14577 |
+ else { |
14578 |
+- addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, 0); |
14579 |
++ addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, MAP_EXECUTABLE); |
14580 |
+ if (IS_ERR_VALUE(addr)) { |
14581 |
+ ret = addr; |
14582 |
+ goto up_fail; |
14583 |
+@@ -358,7 +358,7 @@ int arch_setup_additional_pages(struct l |
14584 |
+ goto up_fail; |
14585 |
+ } |
14586 |
+ |
14587 |
+- current->mm->context.vdso = (void *)addr; |
14588 |
++ current->mm->context.vdso = addr; |
14589 |
+ current_thread_info()->sysenter_return = |
14590 |
+ VDSO32_SYMBOL(addr, SYSENTER_RETURN); |
14591 |
+ |
14592 |
+@@ -384,7 +384,7 @@ static ctl_table abi_table2[] = { |
14593 |
+ .mode = 0644, |
14594 |
+ .proc_handler = proc_dointvec |
14595 |
+ }, |
14596 |
+- {} |
14597 |
++ { 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } |
14598 |
+ }; |
14599 |
+ |
14600 |
+ static ctl_table abi_root_table2[] = { |
14601 |
+@@ -394,7 +394,7 @@ static ctl_table abi_root_table2[] = { |
14602 |
+ .mode = 0555, |
14603 |
+ .child = abi_table2 |
14604 |
+ }, |
14605 |
+- {} |
14606 |
++ { 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } |
14607 |
+ }; |
14608 |
+ |
14609 |
+ static __init int ia32_binfmt_init(void) |
14610 |
+@@ -409,8 +409,14 @@ __initcall(ia32_binfmt_init); |
14611 |
+ |
14612 |
+ const char *arch_vma_name(struct vm_area_struct *vma) |
14613 |
+ { |
14614 |
+- if (vma->vm_mm && vma->vm_start == (long)vma->vm_mm->context.vdso) |
14615 |
++ if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso) |
14616 |
+ return "[vdso]"; |
14617 |
++ |
14618 |
++#ifdef CONFIG_PAX_SEGMEXEC |
14619 |
++ if (vma->vm_mm && vma->vm_mirror && vma->vm_mirror->vm_start == vma->vm_mm->context.vdso) |
14620 |
++ return "[vdso]"; |
14621 |
++#endif |
14622 |
++ |
14623 |
+ return NULL; |
14624 |
+ } |
14625 |
+ |
14626 |
+@@ -419,7 +425,7 @@ struct vm_area_struct *get_gate_vma(stru |
14627 |
+ struct mm_struct *mm = tsk->mm; |
14628 |
+ |
14629 |
+ /* Check to see if this task was created in compat vdso mode */ |
14630 |
+- if (mm && mm->context.vdso == (void *)VDSO_HIGH_BASE) |
14631 |
++ if (mm && mm->context.vdso == VDSO_HIGH_BASE) |
14632 |
+ return &gate_vma; |
14633 |
+ return NULL; |
14634 |
+ } |
14635 |
+diff -urNp linux-2.6.28.8/arch/x86/vdso/vma.c linux-2.6.28.8/arch/x86/vdso/vma.c |
14636 |
+--- linux-2.6.28.8/arch/x86/vdso/vma.c 2009-02-06 16:47:45.000000000 -0500 |
14637 |
++++ linux-2.6.28.8/arch/x86/vdso/vma.c 2009-02-21 09:37:48.000000000 -0500 |
14638 |
+@@ -123,7 +123,7 @@ int arch_setup_additional_pages(struct l |
14639 |
+ if (ret) |
14640 |
+ goto up_fail; |
14641 |
+ |
14642 |
+- current->mm->context.vdso = (void *)addr; |
14643 |
++ current->mm->context.vdso = addr; |
14644 |
+ up_fail: |
14645 |
+ up_write(&mm->mmap_sem); |
14646 |
+ return ret; |
14647 |
+diff -urNp linux-2.6.28.8/arch/x86/xen/enlighten.c linux-2.6.28.8/arch/x86/xen/enlighten.c |
14648 |
+--- linux-2.6.28.8/arch/x86/xen/enlighten.c 2009-03-07 10:24:49.000000000 -0500 |
14649 |
++++ linux-2.6.28.8/arch/x86/xen/enlighten.c 2009-03-07 10:29:51.000000000 -0500 |
14650 |
+@@ -318,7 +318,7 @@ static void xen_set_ldt(const void *addr |
14651 |
+ static void xen_load_gdt(const struct desc_ptr *dtr) |
14652 |
+ { |
14653 |
+ unsigned long *frames; |
14654 |
+- unsigned long va = dtr->address; |
14655 |
++ unsigned long va = (unsigned long)dtr->address; |
14656 |
+ unsigned int size = dtr->size + 1; |
14657 |
+ unsigned pages = (size + PAGE_SIZE - 1) / PAGE_SIZE; |
14658 |
+ int f; |
14659 |
+@@ -333,7 +333,7 @@ static void xen_load_gdt(const struct de |
14660 |
+ mcs = xen_mc_entry(sizeof(*frames) * pages); |
14661 |
+ frames = mcs.args; |
14662 |
+ |
14663 |
+- for (f = 0; va < dtr->address + size; va += PAGE_SIZE, f++) { |
14664 |
++ for (f = 0; va < (unsigned long)dtr->address + size; va += PAGE_SIZE, f++) { |
14665 |
+ frames[f] = virt_to_mfn(va); |
14666 |
+ make_lowmem_page_readonly((void *)va); |
14667 |
+ } |
14668 |
+@@ -441,7 +441,7 @@ static void xen_write_idt_entry(gate_des |
14669 |
+ |
14670 |
+ preempt_disable(); |
14671 |
+ |
14672 |
+- start = __get_cpu_var(idt_desc).address; |
14673 |
++ start = (unsigned long)__get_cpu_var(idt_desc).address; |
14674 |
+ end = start + __get_cpu_var(idt_desc).size + 1; |
14675 |
+ |
14676 |
+ xen_mc_flush(); |
14677 |
+@@ -1526,6 +1526,8 @@ static __init pgd_t *xen_setup_kernel_pa |
14678 |
+ convert_pfn_mfn(init_level4_pgt); |
14679 |
+ convert_pfn_mfn(level3_ident_pgt); |
14680 |
+ convert_pfn_mfn(level3_kernel_pgt); |
14681 |
++ convert_pfn_mfn(level3_vmalloc_pgt); |
14682 |
++ convert_pfn_mfn(level3_vmemmap_pgt); |
14683 |
+ |
14684 |
+ l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd); |
14685 |
+ l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud); |
14686 |
+@@ -1544,9 +1546,12 @@ static __init pgd_t *xen_setup_kernel_pa |
14687 |
+ set_page_prot(init_level4_pgt, PAGE_KERNEL_RO); |
14688 |
+ set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO); |
14689 |
+ set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO); |
14690 |
++ set_page_prot(level3_vmalloc_pgt, PAGE_KERNEL_RO); |
14691 |
++ set_page_prot(level3_vmemmap_pgt, PAGE_KERNEL_RO); |
14692 |
+ set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO); |
14693 |
+ set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO); |
14694 |
+ set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO); |
14695 |
++ set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO); |
14696 |
+ |
14697 |
+ /* Pin down new L4 */ |
14698 |
+ pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE, |
14699 |
+diff -urNp linux-2.6.28.8/arch/x86/xen/smp.c linux-2.6.28.8/arch/x86/xen/smp.c |
14700 |
+--- linux-2.6.28.8/arch/x86/xen/smp.c 2009-02-06 16:47:45.000000000 -0500 |
14701 |
++++ linux-2.6.28.8/arch/x86/xen/smp.c 2009-02-21 09:37:48.000000000 -0500 |
14702 |
+@@ -171,11 +171,6 @@ static void __init xen_smp_prepare_boot_ |
14703 |
+ { |
14704 |
+ BUG_ON(smp_processor_id() != 0); |
14705 |
+ native_smp_prepare_boot_cpu(); |
14706 |
+- |
14707 |
+- /* We've switched to the "real" per-cpu gdt, so make sure the |
14708 |
+- old memory can be recycled */ |
14709 |
+- make_lowmem_page_readwrite(&per_cpu_var(gdt_page)); |
14710 |
+- |
14711 |
+ xen_setup_vcpu_info_placement(); |
14712 |
+ } |
14713 |
+ |
14714 |
+@@ -231,8 +226,8 @@ cpu_initialize_context(unsigned int cpu, |
14715 |
+ gdt = get_cpu_gdt_table(cpu); |
14716 |
+ |
14717 |
+ ctxt->flags = VGCF_IN_KERNEL; |
14718 |
+- ctxt->user_regs.ds = __USER_DS; |
14719 |
+- ctxt->user_regs.es = __USER_DS; |
14720 |
++ ctxt->user_regs.ds = __KERNEL_DS; |
14721 |
++ ctxt->user_regs.es = __KERNEL_DS; |
14722 |
+ ctxt->user_regs.ss = __KERNEL_DS; |
14723 |
+ #ifdef CONFIG_X86_32 |
14724 |
+ ctxt->user_regs.fs = __KERNEL_PERCPU; |
14725 |
+diff -urNp linux-2.6.28.8/crypto/async_tx/async_tx.c linux-2.6.28.8/crypto/async_tx/async_tx.c |
14726 |
+--- linux-2.6.28.8/crypto/async_tx/async_tx.c 2009-02-06 16:47:45.000000000 -0500 |
14727 |
++++ linux-2.6.28.8/crypto/async_tx/async_tx.c 2009-02-21 09:37:48.000000000 -0500 |
14728 |
+@@ -358,8 +358,8 @@ async_tx_init(void) |
14729 |
+ err: |
14730 |
+ printk(KERN_ERR "async_tx: initialization failure\n"); |
14731 |
+ |
14732 |
+- while (--cap >= 0) |
14733 |
+- free_percpu(channel_table[cap]); |
14734 |
++ while (cap) |
14735 |
++ free_percpu(channel_table[--cap]); |
14736 |
+ |
14737 |
+ return 1; |
14738 |
+ } |
14739 |
+diff -urNp linux-2.6.28.8/crypto/lrw.c linux-2.6.28.8/crypto/lrw.c |
14740 |
+--- linux-2.6.28.8/crypto/lrw.c 2009-02-06 16:47:45.000000000 -0500 |
14741 |
++++ linux-2.6.28.8/crypto/lrw.c 2009-02-21 09:37:48.000000000 -0500 |
14742 |
+@@ -54,7 +54,7 @@ static int setkey(struct crypto_tfm *par |
14743 |
+ struct priv *ctx = crypto_tfm_ctx(parent); |
14744 |
+ struct crypto_cipher *child = ctx->child; |
14745 |
+ int err, i; |
14746 |
+- be128 tmp = { 0 }; |
14747 |
++ be128 tmp = { 0, 0 }; |
14748 |
+ int bsize = crypto_cipher_blocksize(child); |
14749 |
+ |
14750 |
+ crypto_cipher_clear_flags(child, CRYPTO_TFM_REQ_MASK); |
14751 |
+diff -urNp linux-2.6.28.8/Documentation/dontdiff linux-2.6.28.8/Documentation/dontdiff |
14752 |
+--- linux-2.6.28.8/Documentation/dontdiff 2009-02-06 16:47:45.000000000 -0500 |
14753 |
++++ linux-2.6.28.8/Documentation/dontdiff 2009-02-21 09:37:48.000000000 -0500 |
14754 |
+@@ -3,6 +3,7 @@ |
14755 |
+ *.bin |
14756 |
+ *.cpio |
14757 |
+ *.csp |
14758 |
++*.dbg |
14759 |
+ *.dsp |
14760 |
+ *.dvi |
14761 |
+ *.elf |
14762 |
+@@ -49,6 +50,10 @@ |
14763 |
+ 53c700_d.h |
14764 |
+ CVS |
14765 |
+ ChangeSet |
14766 |
++GPATH |
14767 |
++GRTAGS |
14768 |
++GSYMS |
14769 |
++GTAGS |
14770 |
+ Image |
14771 |
+ Kerntypes |
14772 |
+ Module.markers |
14773 |
+@@ -62,7 +67,6 @@ aic7*reg_print.c* |
14774 |
+ aic7*seq.h* |
14775 |
+ aicasm |
14776 |
+ aicdb.h* |
14777 |
+-asm |
14778 |
+ asm-offsets.h |
14779 |
+ asm_offsets.h |
14780 |
+ autoconf.h* |
14781 |
+@@ -77,6 +81,7 @@ btfixupprep |
14782 |
+ build |
14783 |
+ bvmlinux |
14784 |
+ bzImage* |
14785 |
++capflags.c |
14786 |
+ classlist.h* |
14787 |
+ comp*.log |
14788 |
+ compile.h* |
14789 |
+@@ -188,12 +193,15 @@ version.h* |
14790 |
+ vmlinux |
14791 |
+ vmlinux-* |
14792 |
+ vmlinux.aout |
14793 |
++vmlinux.bin.all |
14794 |
+ vmlinux.lds |
14795 |
++vmlinux.relocs |
14796 |
+ vsyscall.lds |
14797 |
+ vsyscall_32.lds |
14798 |
+ wanxlfw.inc |
14799 |
+ uImage |
14800 |
+ unifdef |
14801 |
++utsrelease.h |
14802 |
+ wakeup.bin |
14803 |
+ wakeup.elf |
14804 |
+ wakeup.lds |
14805 |
+diff -urNp linux-2.6.28.8/drivers/acpi/blacklist.c linux-2.6.28.8/drivers/acpi/blacklist.c |
14806 |
+--- linux-2.6.28.8/drivers/acpi/blacklist.c 2009-02-06 16:47:45.000000000 -0500 |
14807 |
++++ linux-2.6.28.8/drivers/acpi/blacklist.c 2009-02-21 09:37:48.000000000 -0500 |
14808 |
+@@ -71,7 +71,7 @@ static struct acpi_blacklist_item acpi_b |
14809 |
+ {"IBM ", "TP600E ", 0x00000105, ACPI_SIG_DSDT, less_than_or_equal, |
14810 |
+ "Incorrect _ADR", 1}, |
14811 |
+ |
14812 |
+- {""} |
14813 |
++ {"", "", 0, 0, 0, all_versions, 0} |
14814 |
+ }; |
14815 |
+ |
14816 |
+ #if CONFIG_ACPI_BLACKLIST_YEAR |
14817 |
+diff -urNp linux-2.6.28.8/drivers/acpi/osl.c linux-2.6.28.8/drivers/acpi/osl.c |
14818 |
+--- linux-2.6.28.8/drivers/acpi/osl.c 2009-02-06 16:47:45.000000000 -0500 |
14819 |
++++ linux-2.6.28.8/drivers/acpi/osl.c 2009-02-21 09:37:48.000000000 -0500 |
14820 |
+@@ -483,6 +483,8 @@ acpi_os_read_memory(acpi_physical_addres |
14821 |
+ void __iomem *virt_addr; |
14822 |
+ |
14823 |
+ virt_addr = ioremap(phys_addr, width); |
14824 |
++ if (!virt_addr) |
14825 |
++ return AE_NO_MEMORY; |
14826 |
+ if (!value) |
14827 |
+ value = &dummy; |
14828 |
+ |
14829 |
+@@ -511,6 +513,8 @@ acpi_os_write_memory(acpi_physical_addre |
14830 |
+ void __iomem *virt_addr; |
14831 |
+ |
14832 |
+ virt_addr = ioremap(phys_addr, width); |
14833 |
++ if (!virt_addr) |
14834 |
++ return AE_NO_MEMORY; |
14835 |
+ |
14836 |
+ switch (width) { |
14837 |
+ case 8: |
14838 |
+diff -urNp linux-2.6.28.8/drivers/acpi/processor_core.c linux-2.6.28.8/drivers/acpi/processor_core.c |
14839 |
+--- linux-2.6.28.8/drivers/acpi/processor_core.c 2009-02-06 16:47:45.000000000 -0500 |
14840 |
++++ linux-2.6.28.8/drivers/acpi/processor_core.c 2009-02-21 09:37:48.000000000 -0500 |
14841 |
+@@ -678,7 +678,7 @@ static int __cpuinit acpi_processor_star |
14842 |
+ return 0; |
14843 |
+ } |
14844 |
+ |
14845 |
+- BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); |
14846 |
++ BUG_ON(pr->id >= nr_cpu_ids); |
14847 |
+ |
14848 |
+ /* |
14849 |
+ * Buggy BIOS check |
14850 |
+diff -urNp linux-2.6.28.8/drivers/acpi/processor_idle.c linux-2.6.28.8/drivers/acpi/processor_idle.c |
14851 |
+--- linux-2.6.28.8/drivers/acpi/processor_idle.c 2009-02-06 16:47:45.000000000 -0500 |
14852 |
++++ linux-2.6.28.8/drivers/acpi/processor_idle.c 2009-02-21 09:37:48.000000000 -0500 |
14853 |
+@@ -181,7 +181,7 @@ static struct dmi_system_id __cpuinitdat |
14854 |
+ DMI_MATCH(DMI_BIOS_VENDOR,"Phoenix Technologies LTD"), |
14855 |
+ DMI_MATCH(DMI_BIOS_VERSION,"SHE845M0.86C.0013.D.0302131307")}, |
14856 |
+ (void *)2}, |
14857 |
+- {}, |
14858 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL}, |
14859 |
+ }; |
14860 |
+ |
14861 |
+ static inline u32 ticks_elapsed(u32 t1, u32 t2) |
14862 |
+diff -urNp linux-2.6.28.8/drivers/acpi/tables/tbfadt.c linux-2.6.28.8/drivers/acpi/tables/tbfadt.c |
14863 |
+--- linux-2.6.28.8/drivers/acpi/tables/tbfadt.c 2009-02-06 16:47:45.000000000 -0500 |
14864 |
++++ linux-2.6.28.8/drivers/acpi/tables/tbfadt.c 2009-02-21 09:37:48.000000000 -0500 |
14865 |
+@@ -48,7 +48,7 @@ |
14866 |
+ ACPI_MODULE_NAME("tbfadt") |
14867 |
+ |
14868 |
+ /* Local prototypes */ |
14869 |
+-static void inline |
14870 |
++static inline void |
14871 |
+ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
14872 |
+ u8 byte_width, u64 address); |
14873 |
+ |
14874 |
+@@ -122,7 +122,7 @@ static struct acpi_fadt_info fadt_info_t |
14875 |
+ * |
14876 |
+ ******************************************************************************/ |
14877 |
+ |
14878 |
+-static void inline |
14879 |
++static inline void |
14880 |
+ acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
14881 |
+ u8 byte_width, u64 address) |
14882 |
+ { |
14883 |
+diff -urNp linux-2.6.28.8/drivers/ata/ahci.c linux-2.6.28.8/drivers/ata/ahci.c |
14884 |
+--- linux-2.6.28.8/drivers/ata/ahci.c 2009-02-06 16:47:45.000000000 -0500 |
14885 |
++++ linux-2.6.28.8/drivers/ata/ahci.c 2009-02-21 09:37:48.000000000 -0500 |
14886 |
+@@ -606,7 +606,7 @@ static const struct pci_device_id ahci_p |
14887 |
+ { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, |
14888 |
+ PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, |
14889 |
+ |
14890 |
+- { } /* terminate list */ |
14891 |
++ { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ |
14892 |
+ }; |
14893 |
+ |
14894 |
+ |
14895 |
+diff -urNp linux-2.6.28.8/drivers/ata/ata_piix.c linux-2.6.28.8/drivers/ata/ata_piix.c |
14896 |
+--- linux-2.6.28.8/drivers/ata/ata_piix.c 2009-02-06 16:47:45.000000000 -0500 |
14897 |
++++ linux-2.6.28.8/drivers/ata/ata_piix.c 2009-02-21 09:37:48.000000000 -0500 |
14898 |
+@@ -289,7 +289,7 @@ static const struct pci_device_id piix_p |
14899 |
+ { 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, |
14900 |
+ /* SATA Controller IDE (PCH) */ |
14901 |
+ { 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, |
14902 |
+- { } /* terminate list */ |
14903 |
++ { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ |
14904 |
+ }; |
14905 |
+ |
14906 |
+ static struct pci_driver piix_pci_driver = { |
14907 |
+@@ -593,7 +593,7 @@ static const struct ich_laptop ich_lapto |
14908 |
+ { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */ |
14909 |
+ { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */ |
14910 |
+ /* end marker */ |
14911 |
+- { 0, } |
14912 |
++ { 0, 0, 0 } |
14913 |
+ }; |
14914 |
+ |
14915 |
+ /** |
14916 |
+@@ -1052,7 +1052,7 @@ static int piix_broken_suspend(void) |
14917 |
+ }, |
14918 |
+ }, |
14919 |
+ |
14920 |
+- { } /* terminate list */ |
14921 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL } /* terminate list */ |
14922 |
+ }; |
14923 |
+ static const char *oemstrs[] = { |
14924 |
+ "Tecra M3,", |
14925 |
+diff -urNp linux-2.6.28.8/drivers/ata/libata-core.c linux-2.6.28.8/drivers/ata/libata-core.c |
14926 |
+--- linux-2.6.28.8/drivers/ata/libata-core.c 2009-03-07 10:24:49.000000000 -0500 |
14927 |
++++ linux-2.6.28.8/drivers/ata/libata-core.c 2009-03-07 10:29:51.000000000 -0500 |
14928 |
+@@ -807,7 +807,7 @@ static const struct ata_xfer_ent { |
14929 |
+ { ATA_SHIFT_PIO, ATA_NR_PIO_MODES, XFER_PIO_0 }, |
14930 |
+ { ATA_SHIFT_MWDMA, ATA_NR_MWDMA_MODES, XFER_MW_DMA_0 }, |
14931 |
+ { ATA_SHIFT_UDMA, ATA_NR_UDMA_MODES, XFER_UDMA_0 }, |
14932 |
+- { -1, }, |
14933 |
++ { -1, 0, 0 } |
14934 |
+ }; |
14935 |
+ |
14936 |
+ /** |
14937 |
+@@ -2983,7 +2983,7 @@ static const struct ata_timing ata_timin |
14938 |
+ { XFER_UDMA_5, 0, 0, 0, 0, 0, 0, 0, 20 }, |
14939 |
+ { XFER_UDMA_6, 0, 0, 0, 0, 0, 0, 0, 15 }, |
14940 |
+ |
14941 |
+- { 0xFF } |
14942 |
++ { 0xFF, 0, 0, 0, 0, 0, 0, 0, 0 } |
14943 |
+ }; |
14944 |
+ |
14945 |
+ #define ENOUGH(v, unit) (((v)-1)/(unit)+1) |
14946 |
+@@ -4149,7 +4149,7 @@ static const struct ata_blacklist_entry |
14947 |
+ { "MTRON MSP-SATA*", NULL, ATA_HORKAGE_BRIDGE_OK, }, |
14948 |
+ |
14949 |
+ /* End Marker */ |
14950 |
+- { } |
14951 |
++ { NULL, NULL, 0 } |
14952 |
+ }; |
14953 |
+ |
14954 |
+ static int strn_pattern_cmp(const char *patt, const char *name, int wildchar) |
14955 |
+diff -urNp linux-2.6.28.8/drivers/char/agp/frontend.c linux-2.6.28.8/drivers/char/agp/frontend.c |
14956 |
+--- linux-2.6.28.8/drivers/char/agp/frontend.c 2009-02-06 16:47:45.000000000 -0500 |
14957 |
++++ linux-2.6.28.8/drivers/char/agp/frontend.c 2009-02-21 09:37:48.000000000 -0500 |
14958 |
+@@ -824,7 +824,7 @@ static int agpioc_reserve_wrap(struct ag |
14959 |
+ if (copy_from_user(&reserve, arg, sizeof(struct agp_region))) |
14960 |
+ return -EFAULT; |
14961 |
+ |
14962 |
+- if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment)) |
14963 |
++ if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment_priv)) |
14964 |
+ return -EFAULT; |
14965 |
+ |
14966 |
+ client = agp_find_client_by_pid(reserve.pid); |
14967 |
+diff -urNp linux-2.6.28.8/drivers/char/agp/intel-agp.c linux-2.6.28.8/drivers/char/agp/intel-agp.c |
14968 |
+--- linux-2.6.28.8/drivers/char/agp/intel-agp.c 2009-03-07 10:24:49.000000000 -0500 |
14969 |
++++ linux-2.6.28.8/drivers/char/agp/intel-agp.c 2009-03-07 10:29:51.000000000 -0500 |
14970 |
+@@ -2369,7 +2369,7 @@ static struct pci_device_id agp_intel_pc |
14971 |
+ ID(PCI_DEVICE_ID_INTEL_Q45_HB), |
14972 |
+ ID(PCI_DEVICE_ID_INTEL_G45_HB), |
14973 |
+ ID(PCI_DEVICE_ID_INTEL_G41_HB), |
14974 |
+- { } |
14975 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
14976 |
+ }; |
14977 |
+ |
14978 |
+ MODULE_DEVICE_TABLE(pci, agp_intel_pci_table); |
14979 |
+diff -urNp linux-2.6.28.8/drivers/char/hpet.c linux-2.6.28.8/drivers/char/hpet.c |
14980 |
+--- linux-2.6.28.8/drivers/char/hpet.c 2009-02-06 16:47:45.000000000 -0500 |
14981 |
++++ linux-2.6.28.8/drivers/char/hpet.c 2009-02-21 09:37:48.000000000 -0500 |
14982 |
+@@ -975,7 +975,7 @@ static struct acpi_driver hpet_acpi_driv |
14983 |
+ }, |
14984 |
+ }; |
14985 |
+ |
14986 |
+-static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops }; |
14987 |
++static struct miscdevice hpet_misc = { HPET_MINOR, "hpet", &hpet_fops, {NULL, NULL}, NULL, NULL }; |
14988 |
+ |
14989 |
+ static int __init hpet_init(void) |
14990 |
+ { |
14991 |
+diff -urNp linux-2.6.28.8/drivers/char/keyboard.c linux-2.6.28.8/drivers/char/keyboard.c |
14992 |
+--- linux-2.6.28.8/drivers/char/keyboard.c 2009-02-06 16:47:45.000000000 -0500 |
14993 |
++++ linux-2.6.28.8/drivers/char/keyboard.c 2009-02-21 09:37:48.000000000 -0500 |
14994 |
+@@ -635,6 +635,16 @@ static void k_spec(struct vc_data *vc, u |
14995 |
+ kbd->kbdmode == VC_MEDIUMRAW) && |
14996 |
+ value != KVAL(K_SAK)) |
14997 |
+ return; /* SAK is allowed even in raw mode */ |
14998 |
++ |
14999 |
++#if defined(CONFIG_GRKERNSEC_PROC) || defined(CONFIG_GRKERNSEC_PROC_MEMMAP) |
15000 |
++ { |
15001 |
++ void *func = fn_handler[value]; |
15002 |
++ if (func == fn_show_state || func == fn_show_ptregs || |
15003 |
++ func == fn_show_mem) |
15004 |
++ return; |
15005 |
++ } |
15006 |
++#endif |
15007 |
++ |
15008 |
+ fn_handler[value](vc); |
15009 |
+ } |
15010 |
+ |
15011 |
+@@ -1388,7 +1398,7 @@ static const struct input_device_id kbd_ |
15012 |
+ .evbit = { BIT_MASK(EV_SND) }, |
15013 |
+ }, |
15014 |
+ |
15015 |
+- { }, /* Terminating entry */ |
15016 |
++ { 0 }, /* Terminating entry */ |
15017 |
+ }; |
15018 |
+ |
15019 |
+ MODULE_DEVICE_TABLE(input, kbd_ids); |
15020 |
+diff -urNp linux-2.6.28.8/drivers/char/mem.c linux-2.6.28.8/drivers/char/mem.c |
15021 |
+--- linux-2.6.28.8/drivers/char/mem.c 2009-02-06 16:47:45.000000000 -0500 |
15022 |
++++ linux-2.6.28.8/drivers/char/mem.c 2009-02-21 09:37:48.000000000 -0500 |
15023 |
+@@ -18,6 +18,7 @@ |
15024 |
+ #include <linux/raw.h> |
15025 |
+ #include <linux/tty.h> |
15026 |
+ #include <linux/capability.h> |
15027 |
++#include <linux/security.h> |
15028 |
+ #include <linux/ptrace.h> |
15029 |
+ #include <linux/device.h> |
15030 |
+ #include <linux/highmem.h> |
15031 |
+@@ -35,6 +36,10 @@ |
15032 |
+ # include <linux/efi.h> |
15033 |
+ #endif |
15034 |
+ |
15035 |
++#ifdef CONFIG_GRKERNSEC |
15036 |
++extern struct file_operations grsec_fops; |
15037 |
++#endif |
15038 |
++ |
15039 |
+ /* |
15040 |
+ * Architectures vary in how they handle caching for addresses |
15041 |
+ * outside of main memory. |
15042 |
+@@ -192,6 +197,11 @@ static ssize_t write_mem(struct file * f |
15043 |
+ if (!valid_phys_addr_range(p, count)) |
15044 |
+ return -EFAULT; |
15045 |
+ |
15046 |
++#ifdef CONFIG_GRKERNSEC_KMEM |
15047 |
++ gr_handle_mem_write(); |
15048 |
++ return -EPERM; |
15049 |
++#endif |
15050 |
++ |
15051 |
+ written = 0; |
15052 |
+ |
15053 |
+ #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED |
15054 |
+@@ -350,6 +360,11 @@ static int mmap_mem(struct file * file, |
15055 |
+ &vma->vm_page_prot)) |
15056 |
+ return -EINVAL; |
15057 |
+ |
15058 |
++#ifdef CONFIG_GRKERNSEC_KMEM |
15059 |
++ if (gr_handle_mem_mmap(vma->vm_pgoff << PAGE_SHIFT, vma)) |
15060 |
++ return -EPERM; |
15061 |
++#endif |
15062 |
++ |
15063 |
+ vma->vm_page_prot = phys_mem_access_prot(file, vma->vm_pgoff, |
15064 |
+ size, |
15065 |
+ vma->vm_page_prot); |
15066 |
+@@ -588,6 +603,11 @@ static ssize_t write_kmem(struct file * |
15067 |
+ ssize_t written; |
15068 |
+ char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ |
15069 |
+ |
15070 |
++#ifdef CONFIG_GRKERNSEC_KMEM |
15071 |
++ gr_handle_kmem_write(); |
15072 |
++ return -EPERM; |
15073 |
++#endif |
15074 |
++ |
15075 |
+ if (p < (unsigned long) high_memory) { |
15076 |
+ |
15077 |
+ wrote = count; |
15078 |
+@@ -791,6 +811,16 @@ static loff_t memory_lseek(struct file * |
15079 |
+ |
15080 |
+ static int open_port(struct inode * inode, struct file * filp) |
15081 |
+ { |
15082 |
++#ifdef CONFIG_GRKERNSEC_KMEM |
15083 |
++ gr_handle_open_port(); |
15084 |
++ return -EPERM; |
15085 |
++#endif |
15086 |
++ |
15087 |
++ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; |
15088 |
++} |
15089 |
++ |
15090 |
++static int open_mem(struct inode * inode, struct file * filp) |
15091 |
++{ |
15092 |
+ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; |
15093 |
+ } |
15094 |
+ |
15095 |
+@@ -798,7 +828,6 @@ static int open_port(struct inode * inod |
15096 |
+ #define full_lseek null_lseek |
15097 |
+ #define write_zero write_null |
15098 |
+ #define read_full read_zero |
15099 |
+-#define open_mem open_port |
15100 |
+ #define open_kmem open_mem |
15101 |
+ #define open_oldmem open_mem |
15102 |
+ |
15103 |
+@@ -938,6 +967,11 @@ static int memory_open(struct inode * in |
15104 |
+ filp->f_op = &oldmem_fops; |
15105 |
+ break; |
15106 |
+ #endif |
15107 |
++#ifdef CONFIG_GRKERNSEC |
15108 |
++ case 13: |
15109 |
++ filp->f_op = &grsec_fops; |
15110 |
++ break; |
15111 |
++#endif |
15112 |
+ default: |
15113 |
+ unlock_kernel(); |
15114 |
+ return -ENXIO; |
15115 |
+@@ -974,6 +1008,9 @@ static const struct { |
15116 |
+ #ifdef CONFIG_CRASH_DUMP |
15117 |
+ {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops}, |
15118 |
+ #endif |
15119 |
++#ifdef CONFIG_GRKERNSEC |
15120 |
++ {13,"grsec", S_IRUSR | S_IWUGO, &grsec_fops}, |
15121 |
++#endif |
15122 |
+ }; |
15123 |
+ |
15124 |
+ static struct class *mem_class; |
15125 |
+diff -urNp linux-2.6.28.8/drivers/char/nvram.c linux-2.6.28.8/drivers/char/nvram.c |
15126 |
+--- linux-2.6.28.8/drivers/char/nvram.c 2009-02-06 16:47:45.000000000 -0500 |
15127 |
++++ linux-2.6.28.8/drivers/char/nvram.c 2009-02-21 09:37:48.000000000 -0500 |
15128 |
+@@ -433,7 +433,10 @@ static const struct file_operations nvra |
15129 |
+ static struct miscdevice nvram_dev = { |
15130 |
+ NVRAM_MINOR, |
15131 |
+ "nvram", |
15132 |
+- &nvram_fops |
15133 |
++ &nvram_fops, |
15134 |
++ {NULL, NULL}, |
15135 |
++ NULL, |
15136 |
++ NULL |
15137 |
+ }; |
15138 |
+ |
15139 |
+ static int __init |
15140 |
+diff -urNp linux-2.6.28.8/drivers/char/random.c linux-2.6.28.8/drivers/char/random.c |
15141 |
+--- linux-2.6.28.8/drivers/char/random.c 2009-02-06 16:47:45.000000000 -0500 |
15142 |
++++ linux-2.6.28.8/drivers/char/random.c 2009-02-21 09:37:48.000000000 -0500 |
15143 |
+@@ -249,8 +249,13 @@ |
15144 |
+ /* |
15145 |
+ * Configuration information |
15146 |
+ */ |
15147 |
++#ifdef CONFIG_GRKERNSEC_RANDNET |
15148 |
++#define INPUT_POOL_WORDS 512 |
15149 |
++#define OUTPUT_POOL_WORDS 128 |
15150 |
++#else |
15151 |
+ #define INPUT_POOL_WORDS 128 |
15152 |
+ #define OUTPUT_POOL_WORDS 32 |
15153 |
++#endif |
15154 |
+ #define SEC_XFER_SIZE 512 |
15155 |
+ |
15156 |
+ /* |
15157 |
+@@ -287,10 +292,17 @@ static struct poolinfo { |
15158 |
+ int poolwords; |
15159 |
+ int tap1, tap2, tap3, tap4, tap5; |
15160 |
+ } poolinfo_table[] = { |
15161 |
++#ifdef CONFIG_GRKERNSEC_RANDNET |
15162 |
++ /* x^512 + x^411 + x^308 + x^208 +x^104 + x + 1 -- 225 */ |
15163 |
++ { 512, 411, 308, 208, 104, 1 }, |
15164 |
++ /* x^128 + x^103 + x^76 + x^51 + x^25 + x + 1 -- 105 */ |
15165 |
++ { 128, 103, 76, 51, 25, 1 }, |
15166 |
++#else |
15167 |
+ /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */ |
15168 |
+ { 128, 103, 76, 51, 25, 1 }, |
15169 |
+ /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */ |
15170 |
+ { 32, 26, 20, 14, 7, 1 }, |
15171 |
++#endif |
15172 |
+ #if 0 |
15173 |
+ /* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */ |
15174 |
+ { 2048, 1638, 1231, 819, 411, 1 }, |
15175 |
+@@ -1185,7 +1197,7 @@ EXPORT_SYMBOL(generate_random_uuid); |
15176 |
+ #include <linux/sysctl.h> |
15177 |
+ |
15178 |
+ static int min_read_thresh = 8, min_write_thresh; |
15179 |
+-static int max_read_thresh = INPUT_POOL_WORDS * 32; |
15180 |
++static int max_read_thresh = OUTPUT_POOL_WORDS * 32; |
15181 |
+ static int max_write_thresh = INPUT_POOL_WORDS * 32; |
15182 |
+ static char sysctl_bootid[16]; |
15183 |
+ |
15184 |
+diff -urNp linux-2.6.28.8/drivers/char/tpm/tpm.c linux-2.6.28.8/drivers/char/tpm/tpm.c |
15185 |
+--- linux-2.6.28.8/drivers/char/tpm/tpm.c 2009-02-06 16:47:45.000000000 -0500 |
15186 |
++++ linux-2.6.28.8/drivers/char/tpm/tpm.c 2009-02-21 09:37:48.000000000 -0500 |
15187 |
+@@ -1035,7 +1035,7 @@ ssize_t tpm_write(struct file *file, con |
15188 |
+ |
15189 |
+ mutex_lock(&chip->buffer_mutex); |
15190 |
+ |
15191 |
+- if (in_size > TPM_BUFSIZE) |
15192 |
++ if (in_size > (unsigned int)TPM_BUFSIZE) |
15193 |
+ in_size = TPM_BUFSIZE; |
15194 |
+ |
15195 |
+ if (copy_from_user |
15196 |
+diff -urNp linux-2.6.28.8/drivers/char/vt_ioctl.c linux-2.6.28.8/drivers/char/vt_ioctl.c |
15197 |
+--- linux-2.6.28.8/drivers/char/vt_ioctl.c 2009-02-06 16:47:45.000000000 -0500 |
15198 |
++++ linux-2.6.28.8/drivers/char/vt_ioctl.c 2009-02-21 09:37:48.000000000 -0500 |
15199 |
+@@ -96,6 +96,12 @@ do_kdsk_ioctl(int cmd, struct kbentry __ |
15200 |
+ case KDSKBENT: |
15201 |
+ if (!perm) |
15202 |
+ return -EPERM; |
15203 |
++ |
15204 |
++#ifdef CONFIG_GRKERNSEC |
15205 |
++ if (!capable(CAP_SYS_TTY_CONFIG)) |
15206 |
++ return -EPERM; |
15207 |
++#endif |
15208 |
++ |
15209 |
+ if (!i && v == K_NOSUCHMAP) { |
15210 |
+ /* deallocate map */ |
15211 |
+ key_map = key_maps[s]; |
15212 |
+@@ -236,6 +242,13 @@ do_kdgkb_ioctl(int cmd, struct kbsentry |
15213 |
+ goto reterr; |
15214 |
+ } |
15215 |
+ |
15216 |
++#ifdef CONFIG_GRKERNSEC |
15217 |
++ if (!capable(CAP_SYS_TTY_CONFIG)) { |
15218 |
++ ret = -EPERM; |
15219 |
++ goto reterr; |
15220 |
++ } |
15221 |
++#endif |
15222 |
++ |
15223 |
+ q = func_table[i]; |
15224 |
+ first_free = funcbufptr + (funcbufsize - funcbufleft); |
15225 |
+ for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) |
15226 |
+diff -urNp linux-2.6.28.8/drivers/edac/edac_core.h linux-2.6.28.8/drivers/edac/edac_core.h |
15227 |
+--- linux-2.6.28.8/drivers/edac/edac_core.h 2009-02-06 16:47:45.000000000 -0500 |
15228 |
++++ linux-2.6.28.8/drivers/edac/edac_core.h 2009-02-21 09:37:48.000000000 -0500 |
15229 |
+@@ -85,11 +85,11 @@ extern int edac_debug_level; |
15230 |
+ |
15231 |
+ #else /* !CONFIG_EDAC_DEBUG */ |
15232 |
+ |
15233 |
+-#define debugf0( ... ) |
15234 |
+-#define debugf1( ... ) |
15235 |
+-#define debugf2( ... ) |
15236 |
+-#define debugf3( ... ) |
15237 |
+-#define debugf4( ... ) |
15238 |
++#define debugf0( ... ) do {} while (0) |
15239 |
++#define debugf1( ... ) do {} while (0) |
15240 |
++#define debugf2( ... ) do {} while (0) |
15241 |
++#define debugf3( ... ) do {} while (0) |
15242 |
++#define debugf4( ... ) do {} while (0) |
15243 |
+ |
15244 |
+ #endif /* !CONFIG_EDAC_DEBUG */ |
15245 |
+ |
15246 |
+diff -urNp linux-2.6.28.8/drivers/firmware/dmi_scan.c linux-2.6.28.8/drivers/firmware/dmi_scan.c |
15247 |
+--- linux-2.6.28.8/drivers/firmware/dmi_scan.c 2009-02-06 16:47:45.000000000 -0500 |
15248 |
++++ linux-2.6.28.8/drivers/firmware/dmi_scan.c 2009-02-21 09:37:48.000000000 -0500 |
15249 |
+@@ -389,11 +389,6 @@ void __init dmi_scan_machine(void) |
15250 |
+ } |
15251 |
+ } |
15252 |
+ else { |
15253 |
+- /* |
15254 |
+- * no iounmap() for that ioremap(); it would be a no-op, but |
15255 |
+- * it's so early in setup that sucker gets confused into doing |
15256 |
+- * what it shouldn't if we actually call it. |
15257 |
+- */ |
15258 |
+ p = dmi_ioremap(0xF0000, 0x10000); |
15259 |
+ if (p == NULL) |
15260 |
+ goto error; |
15261 |
+diff -urNp linux-2.6.28.8/drivers/hwmon/fscpos.c linux-2.6.28.8/drivers/hwmon/fscpos.c |
15262 |
+--- linux-2.6.28.8/drivers/hwmon/fscpos.c 2009-02-06 16:47:45.000000000 -0500 |
15263 |
++++ linux-2.6.28.8/drivers/hwmon/fscpos.c 2009-02-21 09:37:48.000000000 -0500 |
15264 |
+@@ -240,7 +240,6 @@ static ssize_t set_pwm(struct i2c_client |
15265 |
+ unsigned long v = simple_strtoul(buf, NULL, 10); |
15266 |
+ |
15267 |
+ /* Range: 0..255 */ |
15268 |
+- if (v < 0) v = 0; |
15269 |
+ if (v > 255) v = 255; |
15270 |
+ |
15271 |
+ mutex_lock(&data->update_lock); |
15272 |
+diff -urNp linux-2.6.28.8/drivers/hwmon/k8temp.c linux-2.6.28.8/drivers/hwmon/k8temp.c |
15273 |
+--- linux-2.6.28.8/drivers/hwmon/k8temp.c 2009-02-06 16:47:45.000000000 -0500 |
15274 |
++++ linux-2.6.28.8/drivers/hwmon/k8temp.c 2009-02-21 09:37:48.000000000 -0500 |
15275 |
+@@ -130,7 +130,7 @@ static DEVICE_ATTR(name, S_IRUGO, show_n |
15276 |
+ |
15277 |
+ static struct pci_device_id k8temp_ids[] = { |
15278 |
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, |
15279 |
+- { 0 }, |
15280 |
++ { 0, 0, 0, 0, 0, 0, 0 }, |
15281 |
+ }; |
15282 |
+ |
15283 |
+ MODULE_DEVICE_TABLE(pci, k8temp_ids); |
15284 |
+diff -urNp linux-2.6.28.8/drivers/hwmon/sis5595.c linux-2.6.28.8/drivers/hwmon/sis5595.c |
15285 |
+--- linux-2.6.28.8/drivers/hwmon/sis5595.c 2009-02-06 16:47:45.000000000 -0500 |
15286 |
++++ linux-2.6.28.8/drivers/hwmon/sis5595.c 2009-02-21 09:37:48.000000000 -0500 |
15287 |
+@@ -698,7 +698,7 @@ static struct sis5595_data *sis5595_upda |
15288 |
+ |
15289 |
+ static struct pci_device_id sis5595_pci_ids[] = { |
15290 |
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, |
15291 |
+- { 0, } |
15292 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
15293 |
+ }; |
15294 |
+ |
15295 |
+ MODULE_DEVICE_TABLE(pci, sis5595_pci_ids); |
15296 |
+diff -urNp linux-2.6.28.8/drivers/hwmon/via686a.c linux-2.6.28.8/drivers/hwmon/via686a.c |
15297 |
+--- linux-2.6.28.8/drivers/hwmon/via686a.c 2009-02-06 16:47:45.000000000 -0500 |
15298 |
++++ linux-2.6.28.8/drivers/hwmon/via686a.c 2009-02-21 09:37:48.000000000 -0500 |
15299 |
+@@ -768,7 +768,7 @@ static struct via686a_data *via686a_upda |
15300 |
+ |
15301 |
+ static struct pci_device_id via686a_pci_ids[] = { |
15302 |
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) }, |
15303 |
+- { 0, } |
15304 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
15305 |
+ }; |
15306 |
+ |
15307 |
+ MODULE_DEVICE_TABLE(pci, via686a_pci_ids); |
15308 |
+diff -urNp linux-2.6.28.8/drivers/hwmon/vt8231.c linux-2.6.28.8/drivers/hwmon/vt8231.c |
15309 |
+--- linux-2.6.28.8/drivers/hwmon/vt8231.c 2009-02-06 16:47:45.000000000 -0500 |
15310 |
++++ linux-2.6.28.8/drivers/hwmon/vt8231.c 2009-02-21 09:37:48.000000000 -0500 |
15311 |
+@@ -698,7 +698,7 @@ static struct platform_driver vt8231_dri |
15312 |
+ |
15313 |
+ static struct pci_device_id vt8231_pci_ids[] = { |
15314 |
+ { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) }, |
15315 |
+- { 0, } |
15316 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
15317 |
+ }; |
15318 |
+ |
15319 |
+ MODULE_DEVICE_TABLE(pci, vt8231_pci_ids); |
15320 |
+diff -urNp linux-2.6.28.8/drivers/hwmon/w83791d.c linux-2.6.28.8/drivers/hwmon/w83791d.c |
15321 |
+--- linux-2.6.28.8/drivers/hwmon/w83791d.c 2009-02-06 16:47:45.000000000 -0500 |
15322 |
++++ linux-2.6.28.8/drivers/hwmon/w83791d.c 2009-02-21 09:37:48.000000000 -0500 |
15323 |
+@@ -327,8 +327,8 @@ static int w83791d_detect(struct i2c_cli |
15324 |
+ struct i2c_board_info *info); |
15325 |
+ static int w83791d_remove(struct i2c_client *client); |
15326 |
+ |
15327 |
+-static int w83791d_read(struct i2c_client *client, u8 register); |
15328 |
+-static int w83791d_write(struct i2c_client *client, u8 register, u8 value); |
15329 |
++static int w83791d_read(struct i2c_client *client, u8 reg); |
15330 |
++static int w83791d_write(struct i2c_client *client, u8 reg, u8 value); |
15331 |
+ static struct w83791d_data *w83791d_update_device(struct device *dev); |
15332 |
+ |
15333 |
+ #ifdef DEBUG |
15334 |
+diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-i801.c linux-2.6.28.8/drivers/i2c/busses/i2c-i801.c |
15335 |
+--- linux-2.6.28.8/drivers/i2c/busses/i2c-i801.c 2009-02-06 16:47:45.000000000 -0500 |
15336 |
++++ linux-2.6.28.8/drivers/i2c/busses/i2c-i801.c 2009-02-21 09:37:48.000000000 -0500 |
15337 |
+@@ -578,7 +578,7 @@ static struct pci_device_id i801_ids[] = |
15338 |
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_4) }, |
15339 |
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH10_5) }, |
15340 |
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH_SMBUS) }, |
15341 |
+- { 0, } |
15342 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
15343 |
+ }; |
15344 |
+ |
15345 |
+ MODULE_DEVICE_TABLE (pci, i801_ids); |
15346 |
+diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-piix4.c linux-2.6.28.8/drivers/i2c/busses/i2c-piix4.c |
15347 |
+--- linux-2.6.28.8/drivers/i2c/busses/i2c-piix4.c 2009-02-06 16:47:45.000000000 -0500 |
15348 |
++++ linux-2.6.28.8/drivers/i2c/busses/i2c-piix4.c 2009-02-21 09:37:48.000000000 -0500 |
15349 |
+@@ -123,7 +123,7 @@ static struct dmi_system_id __devinitdat |
15350 |
+ .ident = "IBM", |
15351 |
+ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), }, |
15352 |
+ }, |
15353 |
+- { }, |
15354 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, NULL)}, NULL }, |
15355 |
+ }; |
15356 |
+ |
15357 |
+ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev, |
15358 |
+@@ -424,7 +424,7 @@ static struct pci_device_id piix4_ids[] |
15359 |
+ PCI_DEVICE_ID_SERVERWORKS_CSB6) }, |
15360 |
+ { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, |
15361 |
+ PCI_DEVICE_ID_SERVERWORKS_HT1000SB) }, |
15362 |
+- { 0, } |
15363 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
15364 |
+ }; |
15365 |
+ |
15366 |
+ MODULE_DEVICE_TABLE (pci, piix4_ids); |
15367 |
+diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-sis630.c linux-2.6.28.8/drivers/i2c/busses/i2c-sis630.c |
15368 |
+--- linux-2.6.28.8/drivers/i2c/busses/i2c-sis630.c 2009-02-06 16:47:45.000000000 -0500 |
15369 |
++++ linux-2.6.28.8/drivers/i2c/busses/i2c-sis630.c 2009-02-21 09:37:48.000000000 -0500 |
15370 |
+@@ -472,7 +472,7 @@ static struct i2c_adapter sis630_adapter |
15371 |
+ static struct pci_device_id sis630_ids[] __devinitdata = { |
15372 |
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, |
15373 |
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_LPC) }, |
15374 |
+- { 0, } |
15375 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
15376 |
+ }; |
15377 |
+ |
15378 |
+ MODULE_DEVICE_TABLE (pci, sis630_ids); |
15379 |
+diff -urNp linux-2.6.28.8/drivers/i2c/busses/i2c-sis96x.c linux-2.6.28.8/drivers/i2c/busses/i2c-sis96x.c |
15380 |
+--- linux-2.6.28.8/drivers/i2c/busses/i2c-sis96x.c 2009-02-06 16:47:45.000000000 -0500 |
15381 |
++++ linux-2.6.28.8/drivers/i2c/busses/i2c-sis96x.c 2009-02-21 09:37:48.000000000 -0500 |
15382 |
+@@ -248,7 +248,7 @@ static struct i2c_adapter sis96x_adapter |
15383 |
+ |
15384 |
+ static struct pci_device_id sis96x_ids[] = { |
15385 |
+ { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_SMBUS) }, |
15386 |
+- { 0, } |
15387 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
15388 |
+ }; |
15389 |
+ |
15390 |
+ MODULE_DEVICE_TABLE (pci, sis96x_ids); |
15391 |
+diff -urNp linux-2.6.28.8/drivers/ieee1394/dv1394.c linux-2.6.28.8/drivers/ieee1394/dv1394.c |
15392 |
+--- linux-2.6.28.8/drivers/ieee1394/dv1394.c 2009-02-06 16:47:45.000000000 -0500 |
15393 |
++++ linux-2.6.28.8/drivers/ieee1394/dv1394.c 2009-02-21 09:37:48.000000000 -0500 |
15394 |
+@@ -739,7 +739,7 @@ static void frame_prepare(struct video_c |
15395 |
+ based upon DIF section and sequence |
15396 |
+ */ |
15397 |
+ |
15398 |
+-static void inline |
15399 |
++static inline void |
15400 |
+ frame_put_packet (struct frame *f, struct packet *p) |
15401 |
+ { |
15402 |
+ int section_type = p->data[0] >> 5; /* section type is in bits 5 - 7 */ |
15403 |
+@@ -2177,7 +2177,7 @@ static struct ieee1394_device_id dv1394_ |
15404 |
+ .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff, |
15405 |
+ .version = AVC_SW_VERSION_ENTRY & 0xffffff |
15406 |
+ }, |
15407 |
+- { } |
15408 |
++ { 0, 0, 0, 0, 0, 0 } |
15409 |
+ }; |
15410 |
+ |
15411 |
+ MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table); |
15412 |
+diff -urNp linux-2.6.28.8/drivers/ieee1394/eth1394.c linux-2.6.28.8/drivers/ieee1394/eth1394.c |
15413 |
+--- linux-2.6.28.8/drivers/ieee1394/eth1394.c 2009-02-06 16:47:45.000000000 -0500 |
15414 |
++++ linux-2.6.28.8/drivers/ieee1394/eth1394.c 2009-02-21 09:37:48.000000000 -0500 |
15415 |
+@@ -451,7 +451,7 @@ static struct ieee1394_device_id eth1394 |
15416 |
+ .specifier_id = ETHER1394_GASP_SPECIFIER_ID, |
15417 |
+ .version = ETHER1394_GASP_VERSION, |
15418 |
+ }, |
15419 |
+- {} |
15420 |
++ { 0, 0, 0, 0, 0, 0 } |
15421 |
+ }; |
15422 |
+ |
15423 |
+ MODULE_DEVICE_TABLE(ieee1394, eth1394_id_table); |
15424 |
+diff -urNp linux-2.6.28.8/drivers/ieee1394/hosts.c linux-2.6.28.8/drivers/ieee1394/hosts.c |
15425 |
+--- linux-2.6.28.8/drivers/ieee1394/hosts.c 2009-02-06 16:47:45.000000000 -0500 |
15426 |
++++ linux-2.6.28.8/drivers/ieee1394/hosts.c 2009-02-21 09:37:48.000000000 -0500 |
15427 |
+@@ -78,6 +78,7 @@ static int dummy_isoctl(struct hpsb_iso |
15428 |
+ } |
15429 |
+ |
15430 |
+ static struct hpsb_host_driver dummy_driver = { |
15431 |
++ .name = "dummy", |
15432 |
+ .transmit_packet = dummy_transmit_packet, |
15433 |
+ .devctl = dummy_devctl, |
15434 |
+ .isoctl = dummy_isoctl |
15435 |
+diff -urNp linux-2.6.28.8/drivers/ieee1394/ohci1394.c linux-2.6.28.8/drivers/ieee1394/ohci1394.c |
15436 |
+--- linux-2.6.28.8/drivers/ieee1394/ohci1394.c 2009-02-06 16:47:45.000000000 -0500 |
15437 |
++++ linux-2.6.28.8/drivers/ieee1394/ohci1394.c 2009-02-21 09:37:48.000000000 -0500 |
15438 |
+@@ -147,9 +147,9 @@ printk(level "%s: " fmt "\n" , OHCI1394_ |
15439 |
+ printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args) |
15440 |
+ |
15441 |
+ /* Module Parameters */ |
15442 |
+-static int phys_dma = 1; |
15443 |
++static int phys_dma; |
15444 |
+ module_param(phys_dma, int, 0444); |
15445 |
+-MODULE_PARM_DESC(phys_dma, "Enable physical DMA (default = 1)."); |
15446 |
++MODULE_PARM_DESC(phys_dma, "Enable physical DMA (default = 0)."); |
15447 |
+ |
15448 |
+ static void dma_trm_tasklet(unsigned long data); |
15449 |
+ static void dma_trm_reset(struct dma_trm_ctx *d); |
15450 |
+@@ -3437,7 +3437,7 @@ static struct pci_device_id ohci1394_pci |
15451 |
+ .subvendor = PCI_ANY_ID, |
15452 |
+ .subdevice = PCI_ANY_ID, |
15453 |
+ }, |
15454 |
+- { 0, }, |
15455 |
++ { 0, 0, 0, 0, 0, 0, 0 }, |
15456 |
+ }; |
15457 |
+ |
15458 |
+ MODULE_DEVICE_TABLE(pci, ohci1394_pci_tbl); |
15459 |
+diff -urNp linux-2.6.28.8/drivers/ieee1394/raw1394.c linux-2.6.28.8/drivers/ieee1394/raw1394.c |
15460 |
+--- linux-2.6.28.8/drivers/ieee1394/raw1394.c 2009-02-06 16:47:45.000000000 -0500 |
15461 |
++++ linux-2.6.28.8/drivers/ieee1394/raw1394.c 2009-02-21 09:37:48.000000000 -0500 |
15462 |
+@@ -2995,7 +2995,7 @@ static struct ieee1394_device_id raw1394 |
15463 |
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, |
15464 |
+ .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, |
15465 |
+ .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff}, |
15466 |
+- {} |
15467 |
++ { 0, 0, 0, 0, 0, 0 } |
15468 |
+ }; |
15469 |
+ |
15470 |
+ MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table); |
15471 |
+diff -urNp linux-2.6.28.8/drivers/ieee1394/sbp2.c linux-2.6.28.8/drivers/ieee1394/sbp2.c |
15472 |
+--- linux-2.6.28.8/drivers/ieee1394/sbp2.c 2009-02-07 16:10:45.000000000 -0500 |
15473 |
++++ linux-2.6.28.8/drivers/ieee1394/sbp2.c 2009-02-21 09:37:48.000000000 -0500 |
15474 |
+@@ -290,7 +290,7 @@ static struct ieee1394_device_id sbp2_id |
15475 |
+ .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, |
15476 |
+ .specifier_id = SBP2_UNIT_SPEC_ID_ENTRY & 0xffffff, |
15477 |
+ .version = SBP2_SW_VERSION_ENTRY & 0xffffff}, |
15478 |
+- {} |
15479 |
++ { 0, 0, 0, 0, 0, 0 } |
15480 |
+ }; |
15481 |
+ MODULE_DEVICE_TABLE(ieee1394, sbp2_id_table); |
15482 |
+ |
15483 |
+@@ -2110,7 +2110,7 @@ MODULE_DESCRIPTION("IEEE-1394 SBP-2 prot |
15484 |
+ MODULE_SUPPORTED_DEVICE(SBP2_DEVICE_NAME); |
15485 |
+ MODULE_LICENSE("GPL"); |
15486 |
+ |
15487 |
+-static int sbp2_module_init(void) |
15488 |
++static int __init sbp2_module_init(void) |
15489 |
+ { |
15490 |
+ int ret; |
15491 |
+ |
15492 |
+diff -urNp linux-2.6.28.8/drivers/ieee1394/video1394.c linux-2.6.28.8/drivers/ieee1394/video1394.c |
15493 |
+--- linux-2.6.28.8/drivers/ieee1394/video1394.c 2009-02-06 16:47:45.000000000 -0500 |
15494 |
++++ linux-2.6.28.8/drivers/ieee1394/video1394.c 2009-02-21 09:37:48.000000000 -0500 |
15495 |
+@@ -1310,7 +1310,7 @@ static struct ieee1394_device_id video13 |
15496 |
+ .specifier_id = CAMERA_UNIT_SPEC_ID_ENTRY & 0xffffff, |
15497 |
+ .version = (CAMERA_SW_VERSION_ENTRY + 2) & 0xffffff |
15498 |
+ }, |
15499 |
+- { } |
15500 |
++ { 0, 0, 0, 0, 0, 0 } |
15501 |
+ }; |
15502 |
+ |
15503 |
+ MODULE_DEVICE_TABLE(ieee1394, video1394_id_table); |
15504 |
+diff -urNp linux-2.6.28.8/drivers/input/keyboard/atkbd.c linux-2.6.28.8/drivers/input/keyboard/atkbd.c |
15505 |
+--- linux-2.6.28.8/drivers/input/keyboard/atkbd.c 2009-02-06 16:47:45.000000000 -0500 |
15506 |
++++ linux-2.6.28.8/drivers/input/keyboard/atkbd.c 2009-02-21 09:37:48.000000000 -0500 |
15507 |
+@@ -1164,7 +1164,7 @@ static struct serio_device_id atkbd_seri |
15508 |
+ .id = SERIO_ANY, |
15509 |
+ .extra = SERIO_ANY, |
15510 |
+ }, |
15511 |
+- { 0 } |
15512 |
++ { 0, 0, 0, 0 } |
15513 |
+ }; |
15514 |
+ |
15515 |
+ MODULE_DEVICE_TABLE(serio, atkbd_serio_ids); |
15516 |
+diff -urNp linux-2.6.28.8/drivers/input/mouse/lifebook.c linux-2.6.28.8/drivers/input/mouse/lifebook.c |
15517 |
+--- linux-2.6.28.8/drivers/input/mouse/lifebook.c 2009-02-06 16:47:45.000000000 -0500 |
15518 |
++++ linux-2.6.28.8/drivers/input/mouse/lifebook.c 2009-02-21 09:37:48.000000000 -0500 |
15519 |
+@@ -110,7 +110,7 @@ static const struct dmi_system_id lifebo |
15520 |
+ DMI_MATCH(DMI_PRODUCT_NAME, "LifeBook B142"), |
15521 |
+ }, |
15522 |
+ }, |
15523 |
+- { } |
15524 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL} |
15525 |
+ }; |
15526 |
+ |
15527 |
+ static psmouse_ret_t lifebook_process_byte(struct psmouse *psmouse) |
15528 |
+diff -urNp linux-2.6.28.8/drivers/input/mouse/psmouse-base.c linux-2.6.28.8/drivers/input/mouse/psmouse-base.c |
15529 |
+--- linux-2.6.28.8/drivers/input/mouse/psmouse-base.c 2009-02-06 16:47:45.000000000 -0500 |
15530 |
++++ linux-2.6.28.8/drivers/input/mouse/psmouse-base.c 2009-02-21 09:37:48.000000000 -0500 |
15531 |
+@@ -1378,7 +1378,7 @@ static struct serio_device_id psmouse_se |
15532 |
+ .id = SERIO_ANY, |
15533 |
+ .extra = SERIO_ANY, |
15534 |
+ }, |
15535 |
+- { 0 } |
15536 |
++ { 0, 0, 0, 0 } |
15537 |
+ }; |
15538 |
+ |
15539 |
+ MODULE_DEVICE_TABLE(serio, psmouse_serio_ids); |
15540 |
+diff -urNp linux-2.6.28.8/drivers/input/mouse/synaptics.c linux-2.6.28.8/drivers/input/mouse/synaptics.c |
15541 |
+--- linux-2.6.28.8/drivers/input/mouse/synaptics.c 2009-02-06 16:47:45.000000000 -0500 |
15542 |
++++ linux-2.6.28.8/drivers/input/mouse/synaptics.c 2009-02-21 09:37:48.000000000 -0500 |
15543 |
+@@ -417,7 +417,7 @@ static void synaptics_process_packet(str |
15544 |
+ break; |
15545 |
+ case 2: |
15546 |
+ if (SYN_MODEL_PEN(priv->model_id)) |
15547 |
+- ; /* Nothing, treat a pen as a single finger */ |
15548 |
++ break; /* Nothing, treat a pen as a single finger */ |
15549 |
+ break; |
15550 |
+ case 4 ... 15: |
15551 |
+ if (SYN_CAP_PALMDETECT(priv->capabilities)) |
15552 |
+@@ -624,7 +624,7 @@ static const struct dmi_system_id toshib |
15553 |
+ DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"), |
15554 |
+ }, |
15555 |
+ }, |
15556 |
+- { } |
15557 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL } |
15558 |
+ }; |
15559 |
+ #endif |
15560 |
+ |
15561 |
+diff -urNp linux-2.6.28.8/drivers/input/mousedev.c linux-2.6.28.8/drivers/input/mousedev.c |
15562 |
+--- linux-2.6.28.8/drivers/input/mousedev.c 2009-02-06 16:47:45.000000000 -0500 |
15563 |
++++ linux-2.6.28.8/drivers/input/mousedev.c 2009-02-21 09:37:48.000000000 -0500 |
15564 |
+@@ -1063,7 +1063,7 @@ static struct input_handler mousedev_han |
15565 |
+ |
15566 |
+ #ifdef CONFIG_INPUT_MOUSEDEV_PSAUX |
15567 |
+ static struct miscdevice psaux_mouse = { |
15568 |
+- PSMOUSE_MINOR, "psaux", &mousedev_fops |
15569 |
++ PSMOUSE_MINOR, "psaux", &mousedev_fops, {NULL, NULL}, NULL, NULL |
15570 |
+ }; |
15571 |
+ static int psaux_registered; |
15572 |
+ #endif |
15573 |
+diff -urNp linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h |
15574 |
+--- linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h 2009-02-06 16:47:45.000000000 -0500 |
15575 |
++++ linux-2.6.28.8/drivers/input/serio/i8042-x86ia64io.h 2009-02-21 09:37:48.000000000 -0500 |
15576 |
+@@ -143,7 +143,7 @@ static struct dmi_system_id __initdata i |
15577 |
+ DMI_MATCH(DMI_PRODUCT_VERSION, "M606"), |
15578 |
+ }, |
15579 |
+ }, |
15580 |
+- { } |
15581 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL } |
15582 |
+ }; |
15583 |
+ |
15584 |
+ /* |
15585 |
+@@ -351,7 +351,7 @@ static struct dmi_system_id __initdata i |
15586 |
+ DMI_MATCH(DMI_PRODUCT_NAME, "HEL80I"), |
15587 |
+ }, |
15588 |
+ }, |
15589 |
+- { } |
15590 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL } |
15591 |
+ }; |
15592 |
+ |
15593 |
+ #ifdef CONFIG_PNP |
15594 |
+@@ -363,7 +363,7 @@ static struct dmi_system_id __initdata i |
15595 |
+ DMI_MATCH(DMI_BOARD_VENDOR, "Intel Corporation"), |
15596 |
+ }, |
15597 |
+ }, |
15598 |
+- { } |
15599 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL } |
15600 |
+ }; |
15601 |
+ #endif |
15602 |
+ |
15603 |
+@@ -430,7 +430,7 @@ static struct dmi_system_id __initdata i |
15604 |
+ DMI_MATCH(DMI_PRODUCT_NAME, "TravelMate 4280"), |
15605 |
+ }, |
15606 |
+ }, |
15607 |
+- { } |
15608 |
++ { NULL, NULL, {DMI_MATCH(DMI_NONE, {0})}, NULL } |
15609 |
+ }; |
15610 |
+ |
15611 |
+ #endif /* CONFIG_X86 */ |
15612 |
+diff -urNp linux-2.6.28.8/drivers/input/serio/serio_raw.c linux-2.6.28.8/drivers/input/serio/serio_raw.c |
15613 |
+--- linux-2.6.28.8/drivers/input/serio/serio_raw.c 2009-02-06 16:47:45.000000000 -0500 |
15614 |
++++ linux-2.6.28.8/drivers/input/serio/serio_raw.c 2009-02-21 09:37:48.000000000 -0500 |
15615 |
+@@ -378,7 +378,7 @@ static struct serio_device_id serio_raw_ |
15616 |
+ .id = SERIO_ANY, |
15617 |
+ .extra = SERIO_ANY, |
15618 |
+ }, |
15619 |
+- { 0 } |
15620 |
++ { 0, 0, 0, 0 } |
15621 |
+ }; |
15622 |
+ |
15623 |
+ MODULE_DEVICE_TABLE(serio, serio_raw_serio_ids); |
15624 |
+diff -urNp linux-2.6.28.8/drivers/lguest/core.c linux-2.6.28.8/drivers/lguest/core.c |
15625 |
+--- linux-2.6.28.8/drivers/lguest/core.c 2009-02-06 16:47:45.000000000 -0500 |
15626 |
++++ linux-2.6.28.8/drivers/lguest/core.c 2009-03-07 10:28:24.000000000 -0500 |
15627 |
+@@ -80,9 +80,17 @@ static __init int map_switcher(void) |
15628 |
+ * (SWITCHER_ADDR). We might not get it in theory, but in practice |
15629 |
+ * it's worked so far. The end address needs +1 because __get_vm_area |
15630 |
+ * allocates an extra guard page, so we need space for that. */ |
15631 |
++ |
15632 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) |
15633 |
++ switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE, |
15634 |
++ VM_ALLOC | VM_KERNEXEC, SWITCHER_ADDR, SWITCHER_ADDR |
15635 |
++ + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE); |
15636 |
++#else |
15637 |
+ switcher_vma = __get_vm_area(TOTAL_SWITCHER_PAGES * PAGE_SIZE, |
15638 |
+ VM_ALLOC, SWITCHER_ADDR, SWITCHER_ADDR |
15639 |
+ + (TOTAL_SWITCHER_PAGES+1) * PAGE_SIZE); |
15640 |
++#endif |
15641 |
++ |
15642 |
+ if (!switcher_vma) { |
15643 |
+ err = -ENOMEM; |
15644 |
+ printk("lguest: could not map switcher pages high\n"); |
15645 |
+diff -urNp linux-2.6.28.8/drivers/md/bitmap.c linux-2.6.28.8/drivers/md/bitmap.c |
15646 |
+--- linux-2.6.28.8/drivers/md/bitmap.c 2009-02-06 16:47:45.000000000 -0500 |
15647 |
++++ linux-2.6.28.8/drivers/md/bitmap.c 2009-02-21 09:37:48.000000000 -0500 |
15648 |
+@@ -57,7 +57,7 @@ |
15649 |
+ # if DEBUG > 0 |
15650 |
+ # define PRINTK(x...) printk(KERN_DEBUG x) |
15651 |
+ # else |
15652 |
+-# define PRINTK(x...) |
15653 |
++# define PRINTK(x...) do {} while (0) |
15654 |
+ # endif |
15655 |
+ #endif |
15656 |
+ |
15657 |
+diff -urNp linux-2.6.28.8/drivers/mtd/devices/doc2000.c linux-2.6.28.8/drivers/mtd/devices/doc2000.c |
15658 |
+--- linux-2.6.28.8/drivers/mtd/devices/doc2000.c 2009-02-06 16:47:45.000000000 -0500 |
15659 |
++++ linux-2.6.28.8/drivers/mtd/devices/doc2000.c 2009-02-21 09:37:48.000000000 -0500 |
15660 |
+@@ -777,7 +777,7 @@ static int doc_write(struct mtd_info *mt |
15661 |
+ |
15662 |
+ /* The ECC will not be calculated correctly if less than 512 is written */ |
15663 |
+ /* DBB- |
15664 |
+- if (len != 0x200 && eccbuf) |
15665 |
++ if (len != 0x200) |
15666 |
+ printk(KERN_WARNING |
15667 |
+ "ECC needs a full sector write (adr: %lx size %lx)\n", |
15668 |
+ (long) to, (long) len); |
15669 |
+diff -urNp linux-2.6.28.8/drivers/mtd/devices/doc2001.c linux-2.6.28.8/drivers/mtd/devices/doc2001.c |
15670 |
+--- linux-2.6.28.8/drivers/mtd/devices/doc2001.c 2009-02-06 16:47:45.000000000 -0500 |
15671 |
++++ linux-2.6.28.8/drivers/mtd/devices/doc2001.c 2009-02-21 09:37:48.000000000 -0500 |
15672 |
+@@ -396,6 +396,8 @@ static int doc_read (struct mtd_info *mt |
15673 |
+ /* Don't allow read past end of device */ |
15674 |
+ if (from >= this->totlen) |
15675 |
+ return -EINVAL; |
15676 |
++ if (!len) |
15677 |
++ return -EINVAL; |
15678 |
+ |
15679 |
+ /* Don't allow a single read to cross a 512-byte block boundary */ |
15680 |
+ if (from + len > ((from | 0x1ff) + 1)) |
15681 |
+diff -urNp linux-2.6.28.8/drivers/mtd/devices/slram.c linux-2.6.28.8/drivers/mtd/devices/slram.c |
15682 |
+--- linux-2.6.28.8/drivers/mtd/devices/slram.c 2009-02-06 16:47:45.000000000 -0500 |
15683 |
++++ linux-2.6.28.8/drivers/mtd/devices/slram.c 2009-02-21 09:37:48.000000000 -0500 |
15684 |
+@@ -273,7 +273,7 @@ static int parse_cmdline(char *devname, |
15685 |
+ } |
15686 |
+ T("slram: devname=%s, devstart=0x%lx, devlength=0x%lx\n", |
15687 |
+ devname, devstart, devlength); |
15688 |
+- if ((devstart < 0) || (devlength < 0) || (devlength % SLRAM_BLK_SZ != 0)) { |
15689 |
++ if (devlength % SLRAM_BLK_SZ != 0) { |
15690 |
+ E("slram: Illegal start / length parameter.\n"); |
15691 |
+ return(-EINVAL); |
15692 |
+ } |
15693 |
+diff -urNp linux-2.6.28.8/drivers/mtd/ubi/build.c linux-2.6.28.8/drivers/mtd/ubi/build.c |
15694 |
+--- linux-2.6.28.8/drivers/mtd/ubi/build.c 2009-02-06 16:47:45.000000000 -0500 |
15695 |
++++ linux-2.6.28.8/drivers/mtd/ubi/build.c 2009-02-21 09:37:48.000000000 -0500 |
15696 |
+@@ -1104,7 +1104,7 @@ static int __init bytes_str_to_int(const |
15697 |
+ unsigned long result; |
15698 |
+ |
15699 |
+ result = simple_strtoul(str, &endp, 0); |
15700 |
+- if (str == endp || result < 0) { |
15701 |
++ if (str == endp) { |
15702 |
+ printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n", |
15703 |
+ str); |
15704 |
+ return -EINVAL; |
15705 |
+diff -urNp linux-2.6.28.8/drivers/net/eepro100.c linux-2.6.28.8/drivers/net/eepro100.c |
15706 |
+--- linux-2.6.28.8/drivers/net/eepro100.c 2009-02-06 16:47:45.000000000 -0500 |
15707 |
++++ linux-2.6.28.8/drivers/net/eepro100.c 2009-02-21 09:37:48.000000000 -0500 |
15708 |
+@@ -47,7 +47,7 @@ static int rxdmacount /* = 0 */; |
15709 |
+ # define rx_align(skb) skb_reserve((skb), 2) |
15710 |
+ # define RxFD_ALIGNMENT __attribute__ ((aligned (2), packed)) |
15711 |
+ #else |
15712 |
+-# define rx_align(skb) |
15713 |
++# define rx_align(skb) do {} while (0) |
15714 |
+ # define RxFD_ALIGNMENT |
15715 |
+ #endif |
15716 |
+ |
15717 |
+@@ -2334,33 +2334,33 @@ static void __devexit eepro100_remove_on |
15718 |
+ } |
15719 |
+ |
15720 |
+ static struct pci_device_id eepro100_pci_tbl[] = { |
15721 |
+- { PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, }, |
15722 |
+- { PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, }, |
15723 |
+- { PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, }, |
15724 |
+- { PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, }, |
15725 |
+- { PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, }, |
15726 |
+- { PCI_VENDOR_ID_INTEL, 0x1032, PCI_ANY_ID, PCI_ANY_ID, }, |
15727 |
+- { PCI_VENDOR_ID_INTEL, 0x1033, PCI_ANY_ID, PCI_ANY_ID, }, |
15728 |
+- { PCI_VENDOR_ID_INTEL, 0x1034, PCI_ANY_ID, PCI_ANY_ID, }, |
15729 |
+- { PCI_VENDOR_ID_INTEL, 0x1035, PCI_ANY_ID, PCI_ANY_ID, }, |
15730 |
+- { PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, }, |
15731 |
+- { PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, }, |
15732 |
+- { PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, }, |
15733 |
+- { PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, }, |
15734 |
+- { PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, }, |
15735 |
+- { PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, }, |
15736 |
+- { PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, }, |
15737 |
+- { PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, }, |
15738 |
+- { PCI_VENDOR_ID_INTEL, 0x103E, PCI_ANY_ID, PCI_ANY_ID, }, |
15739 |
+- { PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, }, |
15740 |
+- { PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, }, |
15741 |
+- { PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, }, |
15742 |
+- { PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, }, |
15743 |
+- { PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, }, |
15744 |
+- { PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, }, |
15745 |
+- { PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, }, |
15746 |
+- { PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, }, |
15747 |
+- { 0,} |
15748 |
++ { PCI_VENDOR_ID_INTEL, 0x1229, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15749 |
++ { PCI_VENDOR_ID_INTEL, 0x1209, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15750 |
++ { PCI_VENDOR_ID_INTEL, 0x1029, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15751 |
++ { PCI_VENDOR_ID_INTEL, 0x1030, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15752 |
++ { PCI_VENDOR_ID_INTEL, 0x1031, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15753 |
++ { PCI_VENDOR_ID_INTEL, 0x1032, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15754 |
++ { PCI_VENDOR_ID_INTEL, 0x1033, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15755 |
++ { PCI_VENDOR_ID_INTEL, 0x1034, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15756 |
++ { PCI_VENDOR_ID_INTEL, 0x1035, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15757 |
++ { PCI_VENDOR_ID_INTEL, 0x1036, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15758 |
++ { PCI_VENDOR_ID_INTEL, 0x1037, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15759 |
++ { PCI_VENDOR_ID_INTEL, 0x1038, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15760 |
++ { PCI_VENDOR_ID_INTEL, 0x1039, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15761 |
++ { PCI_VENDOR_ID_INTEL, 0x103A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15762 |
++ { PCI_VENDOR_ID_INTEL, 0x103B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15763 |
++ { PCI_VENDOR_ID_INTEL, 0x103C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15764 |
++ { PCI_VENDOR_ID_INTEL, 0x103D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15765 |
++ { PCI_VENDOR_ID_INTEL, 0x103E, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15766 |
++ { PCI_VENDOR_ID_INTEL, 0x1050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15767 |
++ { PCI_VENDOR_ID_INTEL, 0x1059, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15768 |
++ { PCI_VENDOR_ID_INTEL, 0x1227, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15769 |
++ { PCI_VENDOR_ID_INTEL, 0x2449, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15770 |
++ { PCI_VENDOR_ID_INTEL, 0x2459, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15771 |
++ { PCI_VENDOR_ID_INTEL, 0x245D, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15772 |
++ { PCI_VENDOR_ID_INTEL, 0x5200, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15773 |
++ { PCI_VENDOR_ID_INTEL, 0x5201, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, |
15774 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
15775 |
+ }; |
15776 |
+ MODULE_DEVICE_TABLE(pci, eepro100_pci_tbl); |
15777 |
+ |
15778 |
+diff -urNp linux-2.6.28.8/drivers/net/irda/vlsi_ir.c linux-2.6.28.8/drivers/net/irda/vlsi_ir.c |
15779 |
+--- linux-2.6.28.8/drivers/net/irda/vlsi_ir.c 2009-02-06 16:47:45.000000000 -0500 |
15780 |
++++ linux-2.6.28.8/drivers/net/irda/vlsi_ir.c 2009-02-21 09:37:48.000000000 -0500 |
15781 |
+@@ -906,13 +906,12 @@ static int vlsi_hard_start_xmit(struct s |
15782 |
+ /* no race - tx-ring already empty */ |
15783 |
+ vlsi_set_baud(idev, iobase); |
15784 |
+ netif_wake_queue(ndev); |
15785 |
+- } |
15786 |
+- else |
15787 |
+- ; |
15788 |
++ } else { |
15789 |
+ /* keep the speed change pending like it would |
15790 |
+ * for any len>0 packet. tx completion interrupt |
15791 |
+ * will apply it when the tx ring becomes empty. |
15792 |
+ */ |
15793 |
++ } |
15794 |
+ spin_unlock_irqrestore(&idev->lock, flags); |
15795 |
+ dev_kfree_skb_any(skb); |
15796 |
+ return 0; |
15797 |
+diff -urNp linux-2.6.28.8/drivers/net/pcnet32.c linux-2.6.28.8/drivers/net/pcnet32.c |
15798 |
+--- linux-2.6.28.8/drivers/net/pcnet32.c 2009-02-06 16:47:45.000000000 -0500 |
15799 |
++++ linux-2.6.28.8/drivers/net/pcnet32.c 2009-02-21 09:37:48.000000000 -0500 |
15800 |
+@@ -78,7 +78,7 @@ static int cards_found; |
15801 |
+ /* |
15802 |
+ * VLB I/O addresses |
15803 |
+ */ |
15804 |
+-static unsigned int pcnet32_portlist[] __initdata = |
15805 |
++static unsigned int pcnet32_portlist[] __devinitdata = |
15806 |
+ { 0x300, 0x320, 0x340, 0x360, 0 }; |
15807 |
+ |
15808 |
+ static int pcnet32_debug = 0; |
15809 |
+diff -urNp linux-2.6.28.8/drivers/net/tg3.h linux-2.6.28.8/drivers/net/tg3.h |
15810 |
+--- linux-2.6.28.8/drivers/net/tg3.h 2009-02-06 16:47:45.000000000 -0500 |
15811 |
++++ linux-2.6.28.8/drivers/net/tg3.h 2009-02-21 09:37:48.000000000 -0500 |
15812 |
+@@ -102,6 +102,7 @@ |
15813 |
+ #define CHIPREV_ID_5750_A0 0x4000 |
15814 |
+ #define CHIPREV_ID_5750_A1 0x4001 |
15815 |
+ #define CHIPREV_ID_5750_A3 0x4003 |
15816 |
++#define CHIPREV_ID_5750_C1 0x4201 |
15817 |
+ #define CHIPREV_ID_5750_C2 0x4202 |
15818 |
+ #define CHIPREV_ID_5752_A0_HW 0x5000 |
15819 |
+ #define CHIPREV_ID_5752_A0 0x6000 |
15820 |
+diff -urNp linux-2.6.28.8/drivers/net/wireless/iwlwifi/iwl3945-base.c linux-2.6.28.8/drivers/net/wireless/iwlwifi/iwl3945-base.c |
15821 |
+--- linux-2.6.28.8/drivers/net/wireless/iwlwifi/iwl3945-base.c 2009-02-06 16:47:45.000000000 -0500 |
15822 |
++++ linux-2.6.28.8/drivers/net/wireless/iwlwifi/iwl3945-base.c 2009-02-21 09:37:48.000000000 -0500 |
15823 |
+@@ -785,7 +785,7 @@ static int iwl3945_send_cmd_sync(struct |
15824 |
+ IWL_ERROR("Error: Response NULL in '%s'\n", |
15825 |
+ get_cmd_string(cmd->id)); |
15826 |
+ ret = -EIO; |
15827 |
+- goto out; |
15828 |
++ goto cancel; |
15829 |
+ } |
15830 |
+ |
15831 |
+ ret = 0; |
15832 |
+diff -urNp linux-2.6.28.8/drivers/pci/hotplug/cpqphp_nvram.c linux-2.6.28.8/drivers/pci/hotplug/cpqphp_nvram.c |
15833 |
+--- linux-2.6.28.8/drivers/pci/hotplug/cpqphp_nvram.c 2009-02-06 16:47:45.000000000 -0500 |
15834 |
++++ linux-2.6.28.8/drivers/pci/hotplug/cpqphp_nvram.c 2009-02-21 09:37:48.000000000 -0500 |
15835 |
+@@ -425,9 +425,13 @@ static u32 store_HRT (void __iomem *rom_ |
15836 |
+ |
15837 |
+ void compaq_nvram_init (void __iomem *rom_start) |
15838 |
+ { |
15839 |
++ |
15840 |
++#ifndef CONFIG_PAX_KERNEXEC |
15841 |
+ if (rom_start) { |
15842 |
+ compaq_int15_entry_point = (rom_start + ROM_INT15_PHY_ADDR - ROM_PHY_ADDR); |
15843 |
+ } |
15844 |
++#endif |
15845 |
++ |
15846 |
+ dbg("int15 entry = %p\n", compaq_int15_entry_point); |
15847 |
+ |
15848 |
+ /* initialize our int15 lock */ |
15849 |
+diff -urNp linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv.c linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv.c |
15850 |
+--- linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv.c 2009-02-06 16:47:45.000000000 -0500 |
15851 |
++++ linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv.c 2009-02-21 09:37:48.000000000 -0500 |
15852 |
+@@ -59,7 +59,7 @@ static struct pcie_port_service_id aer_i |
15853 |
+ .port_type = PCIE_RC_PORT, |
15854 |
+ .service_type = PCIE_PORT_SERVICE_AER, |
15855 |
+ }, |
15856 |
+- { /* end: all zeroes */ } |
15857 |
++ { 0, 0, 0, 0, 0, 0, 0, 0, 0 } |
15858 |
+ }; |
15859 |
+ |
15860 |
+ static struct pci_error_handlers aer_error_handlers = { |
15861 |
+diff -urNp linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv_core.c linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv_core.c |
15862 |
+--- linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv_core.c 2009-03-07 10:24:49.000000000 -0500 |
15863 |
++++ linux-2.6.28.8/drivers/pci/pcie/aer/aerdrv_core.c 2009-03-07 10:29:51.000000000 -0500 |
15864 |
+@@ -667,7 +667,7 @@ static void aer_isr_one_error(struct pci |
15865 |
+ struct aer_err_source *e_src) |
15866 |
+ { |
15867 |
+ struct device *s_device; |
15868 |
+- struct aer_err_info e_info = {0, 0, 0,}; |
15869 |
++ struct aer_err_info e_info = {0, 0, 0, {0, 0, 0, 0}}; |
15870 |
+ int i; |
15871 |
+ u16 id; |
15872 |
+ |
15873 |
+diff -urNp linux-2.6.28.8/drivers/pci/pcie/portdrv_pci.c linux-2.6.28.8/drivers/pci/pcie/portdrv_pci.c |
15874 |
+--- linux-2.6.28.8/drivers/pci/pcie/portdrv_pci.c 2009-03-07 10:24:49.000000000 -0500 |
15875 |
++++ linux-2.6.28.8/drivers/pci/pcie/portdrv_pci.c 2009-03-07 10:29:51.000000000 -0500 |
15876 |
+@@ -263,7 +263,7 @@ static void pcie_portdrv_err_resume(stru |
15877 |
+ static const struct pci_device_id port_pci_ids[] = { { |
15878 |
+ /* handle any PCI-Express port */ |
15879 |
+ PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0), |
15880 |
+- }, { /* end: all zeroes */ } |
15881 |
++ }, { 0, 0, 0, 0, 0, 0, 0 } |
15882 |
+ }; |
15883 |
+ MODULE_DEVICE_TABLE(pci, port_pci_ids); |
15884 |
+ |
15885 |
+diff -urNp linux-2.6.28.8/drivers/pci/proc.c linux-2.6.28.8/drivers/pci/proc.c |
15886 |
+--- linux-2.6.28.8/drivers/pci/proc.c 2009-02-06 16:47:45.000000000 -0500 |
15887 |
++++ linux-2.6.28.8/drivers/pci/proc.c 2009-02-21 09:37:48.000000000 -0500 |
15888 |
+@@ -470,7 +470,16 @@ static const struct file_operations proc |
15889 |
+ static int __init pci_proc_init(void) |
15890 |
+ { |
15891 |
+ struct pci_dev *dev = NULL; |
15892 |
++ |
15893 |
++#ifdef CONFIG_GRKERNSEC_PROC_ADD |
15894 |
++#ifdef CONFIG_GRKERNSEC_PROC_USER |
15895 |
++ proc_bus_pci_dir = proc_mkdir_mode("bus/pci", S_IRUSR | S_IXUSR, NULL); |
15896 |
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
15897 |
++ proc_bus_pci_dir = proc_mkdir_mode("bus/pci", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL); |
15898 |
++#endif |
15899 |
++#else |
15900 |
+ proc_bus_pci_dir = proc_mkdir("bus/pci", NULL); |
15901 |
++#endif |
15902 |
+ proc_create("devices", 0, proc_bus_pci_dir, |
15903 |
+ &proc_bus_pci_dev_operations); |
15904 |
+ proc_initialized = 1; |
15905 |
+diff -urNp linux-2.6.28.8/drivers/pcmcia/ti113x.h linux-2.6.28.8/drivers/pcmcia/ti113x.h |
15906 |
+--- linux-2.6.28.8/drivers/pcmcia/ti113x.h 2009-02-06 16:47:45.000000000 -0500 |
15907 |
++++ linux-2.6.28.8/drivers/pcmcia/ti113x.h 2009-02-21 09:37:48.000000000 -0500 |
15908 |
+@@ -903,7 +903,7 @@ static struct pci_device_id ene_tune_tbl |
15909 |
+ DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID, |
15910 |
+ ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE), |
15911 |
+ |
15912 |
+- {} |
15913 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
15914 |
+ }; |
15915 |
+ |
15916 |
+ static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus) |
15917 |
+diff -urNp linux-2.6.28.8/drivers/pcmcia/yenta_socket.c linux-2.6.28.8/drivers/pcmcia/yenta_socket.c |
15918 |
+--- linux-2.6.28.8/drivers/pcmcia/yenta_socket.c 2009-02-06 16:47:45.000000000 -0500 |
15919 |
++++ linux-2.6.28.8/drivers/pcmcia/yenta_socket.c 2009-02-21 09:37:48.000000000 -0500 |
15920 |
+@@ -1366,7 +1366,7 @@ static struct pci_device_id yenta_table |
15921 |
+ |
15922 |
+ /* match any cardbus bridge */ |
15923 |
+ CB_ID(PCI_ANY_ID, PCI_ANY_ID, DEFAULT), |
15924 |
+- { /* all zeroes */ } |
15925 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
15926 |
+ }; |
15927 |
+ MODULE_DEVICE_TABLE(pci, yenta_table); |
15928 |
+ |
15929 |
+diff -urNp linux-2.6.28.8/drivers/pnp/pnpbios/bioscalls.c linux-2.6.28.8/drivers/pnp/pnpbios/bioscalls.c |
15930 |
+--- linux-2.6.28.8/drivers/pnp/pnpbios/bioscalls.c 2009-02-06 16:47:45.000000000 -0500 |
15931 |
++++ linux-2.6.28.8/drivers/pnp/pnpbios/bioscalls.c 2009-02-21 09:37:48.000000000 -0500 |
15932 |
+@@ -60,7 +60,7 @@ set_base(gdt[(selname) >> 3], (u32)(addr |
15933 |
+ set_limit(gdt[(selname) >> 3], size); \ |
15934 |
+ } while(0) |
15935 |
+ |
15936 |
+-static struct desc_struct bad_bios_desc; |
15937 |
++static struct desc_struct bad_bios_desc __read_only; |
15938 |
+ |
15939 |
+ /* |
15940 |
+ * At some point we want to use this stack frame pointer to unwind |
15941 |
+@@ -87,6 +87,10 @@ static inline u16 call_pnp_bios(u16 func |
15942 |
+ struct desc_struct save_desc_40; |
15943 |
+ int cpu; |
15944 |
+ |
15945 |
++#ifdef CONFIG_PAX_KERNEXEC |
15946 |
++ unsigned long cr0; |
15947 |
++#endif |
15948 |
++ |
15949 |
+ /* |
15950 |
+ * PnP BIOSes are generally not terribly re-entrant. |
15951 |
+ * Also, don't rely on them to save everything correctly. |
15952 |
+@@ -96,8 +100,17 @@ static inline u16 call_pnp_bios(u16 func |
15953 |
+ |
15954 |
+ cpu = get_cpu(); |
15955 |
+ save_desc_40 = get_cpu_gdt_table(cpu)[0x40 / 8]; |
15956 |
++ |
15957 |
++#ifdef CONFIG_PAX_KERNEXEC |
15958 |
++ pax_open_kernel(cr0); |
15959 |
++#endif |
15960 |
++ |
15961 |
+ get_cpu_gdt_table(cpu)[0x40 / 8] = bad_bios_desc; |
15962 |
+ |
15963 |
++#ifdef CONFIG_PAX_KERNEXEC |
15964 |
++ pax_close_kernel(cr0); |
15965 |
++#endif |
15966 |
++ |
15967 |
+ /* On some boxes IRQ's during PnP BIOS calls are deadly. */ |
15968 |
+ spin_lock_irqsave(&pnp_bios_lock, flags); |
15969 |
+ |
15970 |
+@@ -134,7 +147,16 @@ static inline u16 call_pnp_bios(u16 func |
15971 |
+ :"memory"); |
15972 |
+ spin_unlock_irqrestore(&pnp_bios_lock, flags); |
15973 |
+ |
15974 |
++#ifdef CONFIG_PAX_KERNEXEC |
15975 |
++ pax_open_kernel(cr0); |
15976 |
++#endif |
15977 |
++ |
15978 |
+ get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40; |
15979 |
++ |
15980 |
++#ifdef CONFIG_PAX_KERNEXEC |
15981 |
++ pax_close_kernel(cr0); |
15982 |
++#endif |
15983 |
++ |
15984 |
+ put_cpu(); |
15985 |
+ |
15986 |
+ /* If we get here and this is set then the PnP BIOS faulted on us. */ |
15987 |
+@@ -468,16 +490,24 @@ int pnp_bios_read_escd(char *data, u32 n |
15988 |
+ return status; |
15989 |
+ } |
15990 |
+ |
15991 |
+-void pnpbios_calls_init(union pnp_bios_install_struct *header) |
15992 |
++void __init pnpbios_calls_init(union pnp_bios_install_struct *header) |
15993 |
+ { |
15994 |
+ int i; |
15995 |
+ |
15996 |
++#ifdef CONFIG_PAX_KERNEXEC |
15997 |
++ unsigned long cr0; |
15998 |
++#endif |
15999 |
++ |
16000 |
+ spin_lock_init(&pnp_bios_lock); |
16001 |
+ pnp_bios_callpoint.offset = header->fields.pm16offset; |
16002 |
+ pnp_bios_callpoint.segment = PNP_CS16; |
16003 |
+ |
16004 |
++#ifdef CONFIG_PAX_KERNEXEC |
16005 |
++ pax_open_kernel(cr0); |
16006 |
++#endif |
16007 |
++ |
16008 |
+ bad_bios_desc.a = 0; |
16009 |
+- bad_bios_desc.b = 0x00409200; |
16010 |
++ bad_bios_desc.b = 0x00409300; |
16011 |
+ |
16012 |
+ set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); |
16013 |
+ _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); |
16014 |
+@@ -491,4 +521,9 @@ void pnpbios_calls_init(union pnp_bios_i |
16015 |
+ set_base(gdt[GDT_ENTRY_PNPBIOS_DS], |
16016 |
+ __va(header->fields.pm16dseg)); |
16017 |
+ } |
16018 |
++ |
16019 |
++#ifdef CONFIG_PAX_KERNEXEC |
16020 |
++ pax_close_kernel(cr0); |
16021 |
++#endif |
16022 |
++ |
16023 |
+ } |
16024 |
+diff -urNp linux-2.6.28.8/drivers/pnp/quirks.c linux-2.6.28.8/drivers/pnp/quirks.c |
16025 |
+--- linux-2.6.28.8/drivers/pnp/quirks.c 2009-02-06 16:47:45.000000000 -0500 |
16026 |
++++ linux-2.6.28.8/drivers/pnp/quirks.c 2009-02-21 09:37:48.000000000 -0500 |
16027 |
+@@ -327,7 +327,7 @@ static struct pnp_fixup pnp_fixups[] = { |
16028 |
+ /* PnP resources that might overlap PCI BARs */ |
16029 |
+ {"PNP0c01", quirk_system_pci_resources}, |
16030 |
+ {"PNP0c02", quirk_system_pci_resources}, |
16031 |
+- {""} |
16032 |
++ {"", NULL} |
16033 |
+ }; |
16034 |
+ |
16035 |
+ void pnp_fixup_device(struct pnp_dev *dev) |
16036 |
+diff -urNp linux-2.6.28.8/drivers/pnp/resource.c linux-2.6.28.8/drivers/pnp/resource.c |
16037 |
+--- linux-2.6.28.8/drivers/pnp/resource.c 2009-02-06 16:47:45.000000000 -0500 |
16038 |
++++ linux-2.6.28.8/drivers/pnp/resource.c 2009-02-21 09:37:48.000000000 -0500 |
16039 |
+@@ -355,7 +355,7 @@ int pnp_check_irq(struct pnp_dev *dev, s |
16040 |
+ return 1; |
16041 |
+ |
16042 |
+ /* check if the resource is valid */ |
16043 |
+- if (*irq < 0 || *irq > 15) |
16044 |
++ if (*irq > 15) |
16045 |
+ return 0; |
16046 |
+ |
16047 |
+ /* check if the resource is reserved */ |
16048 |
+@@ -419,7 +419,7 @@ int pnp_check_dma(struct pnp_dev *dev, s |
16049 |
+ return 1; |
16050 |
+ |
16051 |
+ /* check if the resource is valid */ |
16052 |
+- if (*dma < 0 || *dma == 4 || *dma > 7) |
16053 |
++ if (*dma == 4 || *dma > 7) |
16054 |
+ return 0; |
16055 |
+ |
16056 |
+ /* check if the resource is reserved */ |
16057 |
+diff -urNp linux-2.6.28.8/drivers/scsi/scsi_logging.h linux-2.6.28.8/drivers/scsi/scsi_logging.h |
16058 |
+--- linux-2.6.28.8/drivers/scsi/scsi_logging.h 2009-02-06 16:47:45.000000000 -0500 |
16059 |
++++ linux-2.6.28.8/drivers/scsi/scsi_logging.h 2009-02-21 09:37:48.000000000 -0500 |
16060 |
+@@ -51,7 +51,7 @@ do { \ |
16061 |
+ } while (0); \ |
16062 |
+ } while (0) |
16063 |
+ #else |
16064 |
+-#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) |
16065 |
++#define SCSI_CHECK_LOGGING(SHIFT, BITS, LEVEL, CMD) do {} while (0) |
16066 |
+ #endif /* CONFIG_SCSI_LOGGING */ |
16067 |
+ |
16068 |
+ /* |
16069 |
+diff -urNp linux-2.6.28.8/drivers/serial/8250_pci.c linux-2.6.28.8/drivers/serial/8250_pci.c |
16070 |
+--- linux-2.6.28.8/drivers/serial/8250_pci.c 2009-03-07 10:24:49.000000000 -0500 |
16071 |
++++ linux-2.6.28.8/drivers/serial/8250_pci.c 2009-03-07 10:29:51.000000000 -0500 |
16072 |
+@@ -3138,7 +3138,7 @@ static struct pci_device_id serial_pci_t |
16073 |
+ PCI_ANY_ID, PCI_ANY_ID, |
16074 |
+ PCI_CLASS_COMMUNICATION_MULTISERIAL << 8, |
16075 |
+ 0xffff00, pbn_default }, |
16076 |
+- { 0, } |
16077 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
16078 |
+ }; |
16079 |
+ |
16080 |
+ static struct pci_driver serial_pci_driver = { |
16081 |
+diff -urNp linux-2.6.28.8/drivers/usb/class/cdc-acm.c linux-2.6.28.8/drivers/usb/class/cdc-acm.c |
16082 |
+--- linux-2.6.28.8/drivers/usb/class/cdc-acm.c 2009-03-07 10:24:49.000000000 -0500 |
16083 |
++++ linux-2.6.28.8/drivers/usb/class/cdc-acm.c 2009-03-07 10:29:51.000000000 -0500 |
16084 |
+@@ -1388,7 +1388,7 @@ static struct usb_device_id acm_ids[] = |
16085 |
+ USB_CDC_ACM_PROTO_AT_CDMA) }, |
16086 |
+ |
16087 |
+ /* NOTE: COMM/ACM/0xff is likely MSFT RNDIS ... NOT a modem!! */ |
16088 |
+- { } |
16089 |
++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } |
16090 |
+ }; |
16091 |
+ |
16092 |
+ MODULE_DEVICE_TABLE (usb, acm_ids); |
16093 |
+diff -urNp linux-2.6.28.8/drivers/usb/class/usblp.c linux-2.6.28.8/drivers/usb/class/usblp.c |
16094 |
+--- linux-2.6.28.8/drivers/usb/class/usblp.c 2009-02-06 16:47:45.000000000 -0500 |
16095 |
++++ linux-2.6.28.8/drivers/usb/class/usblp.c 2009-02-21 09:37:48.000000000 -0500 |
16096 |
+@@ -227,7 +227,7 @@ static const struct quirk_printer_struct |
16097 |
+ { 0x0409, 0xf1be, USBLP_QUIRK_BIDIR }, /* NEC Picty800 (HP OEM) */ |
16098 |
+ { 0x0482, 0x0010, USBLP_QUIRK_BIDIR }, /* Kyocera Mita FS 820, by zut <kernel@×××.de> */ |
16099 |
+ { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */ |
16100 |
+- { 0, 0 } |
16101 |
++ { 0, 0, 0 } |
16102 |
+ }; |
16103 |
+ |
16104 |
+ static int usblp_wwait(struct usblp *usblp, int nonblock); |
16105 |
+@@ -1402,7 +1402,7 @@ static struct usb_device_id usblp_ids [] |
16106 |
+ { USB_INTERFACE_INFO(7, 1, 2) }, |
16107 |
+ { USB_INTERFACE_INFO(7, 1, 3) }, |
16108 |
+ { USB_DEVICE(0x04b8, 0x0202) }, /* Seiko Epson Receipt Printer M129C */ |
16109 |
+- { } /* Terminating entry */ |
16110 |
++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminating entry */ |
16111 |
+ }; |
16112 |
+ |
16113 |
+ MODULE_DEVICE_TABLE (usb, usblp_ids); |
16114 |
+diff -urNp linux-2.6.28.8/drivers/usb/core/hub.c linux-2.6.28.8/drivers/usb/core/hub.c |
16115 |
+--- linux-2.6.28.8/drivers/usb/core/hub.c 2009-02-06 16:47:45.000000000 -0500 |
16116 |
++++ linux-2.6.28.8/drivers/usb/core/hub.c 2009-02-21 09:37:48.000000000 -0500 |
16117 |
+@@ -3194,7 +3194,7 @@ static struct usb_device_id hub_id_table |
16118 |
+ .bDeviceClass = USB_CLASS_HUB}, |
16119 |
+ { .match_flags = USB_DEVICE_ID_MATCH_INT_CLASS, |
16120 |
+ .bInterfaceClass = USB_CLASS_HUB}, |
16121 |
+- { } /* Terminating entry */ |
16122 |
++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } /* Terminating entry */ |
16123 |
+ }; |
16124 |
+ |
16125 |
+ MODULE_DEVICE_TABLE (usb, hub_id_table); |
16126 |
+diff -urNp linux-2.6.28.8/drivers/usb/host/ehci-pci.c linux-2.6.28.8/drivers/usb/host/ehci-pci.c |
16127 |
+--- linux-2.6.28.8/drivers/usb/host/ehci-pci.c 2009-02-06 16:47:45.000000000 -0500 |
16128 |
++++ linux-2.6.28.8/drivers/usb/host/ehci-pci.c 2009-02-21 09:37:48.000000000 -0500 |
16129 |
+@@ -414,7 +414,7 @@ static const struct pci_device_id pci_id |
16130 |
+ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0), |
16131 |
+ .driver_data = (unsigned long) &ehci_pci_hc_driver, |
16132 |
+ }, |
16133 |
+- { /* end: all zeroes */ } |
16134 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
16135 |
+ }; |
16136 |
+ MODULE_DEVICE_TABLE(pci, pci_ids); |
16137 |
+ |
16138 |
+diff -urNp linux-2.6.28.8/drivers/usb/host/uhci-hcd.c linux-2.6.28.8/drivers/usb/host/uhci-hcd.c |
16139 |
+--- linux-2.6.28.8/drivers/usb/host/uhci-hcd.c 2009-02-06 16:47:45.000000000 -0500 |
16140 |
++++ linux-2.6.28.8/drivers/usb/host/uhci-hcd.c 2009-02-21 09:37:48.000000000 -0500 |
16141 |
+@@ -927,7 +927,7 @@ static const struct pci_device_id uhci_p |
16142 |
+ /* handle any USB UHCI controller */ |
16143 |
+ PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_UHCI, ~0), |
16144 |
+ .driver_data = (unsigned long) &uhci_driver, |
16145 |
+- }, { /* end: all zeroes */ } |
16146 |
++ }, { 0, 0, 0, 0, 0, 0, 0 } |
16147 |
+ }; |
16148 |
+ |
16149 |
+ MODULE_DEVICE_TABLE(pci, uhci_pci_ids); |
16150 |
+diff -urNp linux-2.6.28.8/drivers/usb/storage/debug.h linux-2.6.28.8/drivers/usb/storage/debug.h |
16151 |
+--- linux-2.6.28.8/drivers/usb/storage/debug.h 2009-02-06 16:47:45.000000000 -0500 |
16152 |
++++ linux-2.6.28.8/drivers/usb/storage/debug.h 2009-02-21 09:37:48.000000000 -0500 |
16153 |
+@@ -54,9 +54,9 @@ void usb_stor_show_sense( unsigned char |
16154 |
+ #define US_DEBUGPX(x...) printk( x ) |
16155 |
+ #define US_DEBUG(x) x |
16156 |
+ #else |
16157 |
+-#define US_DEBUGP(x...) |
16158 |
+-#define US_DEBUGPX(x...) |
16159 |
+-#define US_DEBUG(x) |
16160 |
++#define US_DEBUGP(x...) do {} while (0) |
16161 |
++#define US_DEBUGPX(x...) do {} while (0) |
16162 |
++#define US_DEBUG(x) do {} while (0) |
16163 |
+ #endif |
16164 |
+ |
16165 |
+ #endif |
16166 |
+diff -urNp linux-2.6.28.8/drivers/usb/storage/usb.c linux-2.6.28.8/drivers/usb/storage/usb.c |
16167 |
+--- linux-2.6.28.8/drivers/usb/storage/usb.c 2009-02-06 16:47:45.000000000 -0500 |
16168 |
++++ linux-2.6.28.8/drivers/usb/storage/usb.c 2009-02-21 09:37:48.000000000 -0500 |
16169 |
+@@ -139,7 +139,7 @@ static struct usb_device_id storage_usb_ |
16170 |
+ #undef COMPLIANT_DEV |
16171 |
+ #undef USUAL_DEV |
16172 |
+ /* Terminating entry */ |
16173 |
+- { } |
16174 |
++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } |
16175 |
+ }; |
16176 |
+ |
16177 |
+ MODULE_DEVICE_TABLE (usb, storage_usb_ids); |
16178 |
+@@ -182,7 +182,7 @@ static struct us_unusual_dev us_unusual_ |
16179 |
+ # undef USUAL_DEV |
16180 |
+ |
16181 |
+ /* Terminating entry */ |
16182 |
+- { NULL } |
16183 |
++ { NULL, NULL, 0, 0, NULL } |
16184 |
+ }; |
16185 |
+ |
16186 |
+ |
16187 |
+diff -urNp linux-2.6.28.8/drivers/uwb/wlp/messages.c linux-2.6.28.8/drivers/uwb/wlp/messages.c |
16188 |
+--- linux-2.6.28.8/drivers/uwb/wlp/messages.c 2009-02-06 16:47:45.000000000 -0500 |
16189 |
++++ linux-2.6.28.8/drivers/uwb/wlp/messages.c 2009-02-21 09:37:48.000000000 -0500 |
16190 |
+@@ -988,7 +988,7 @@ int wlp_parse_f0(struct wlp *wlp, struct |
16191 |
+ size_t len = skb->len; |
16192 |
+ size_t used; |
16193 |
+ ssize_t result; |
16194 |
+- struct wlp_nonce enonce, rnonce; |
16195 |
++ struct wlp_nonce enonce = {{0}}, rnonce = {{0}}; |
16196 |
+ enum wlp_assc_error assc_err; |
16197 |
+ char enonce_buf[WLP_WSS_NONCE_STRSIZE]; |
16198 |
+ char rnonce_buf[WLP_WSS_NONCE_STRSIZE]; |
16199 |
+diff -urNp linux-2.6.28.8/drivers/video/fbcmap.c linux-2.6.28.8/drivers/video/fbcmap.c |
16200 |
+--- linux-2.6.28.8/drivers/video/fbcmap.c 2009-02-06 16:47:45.000000000 -0500 |
16201 |
++++ linux-2.6.28.8/drivers/video/fbcmap.c 2009-02-21 09:37:48.000000000 -0500 |
16202 |
+@@ -250,8 +250,7 @@ int fb_set_user_cmap(struct fb_cmap_user |
16203 |
+ int rc, size = cmap->len * sizeof(u16); |
16204 |
+ struct fb_cmap umap; |
16205 |
+ |
16206 |
+- if (cmap->start < 0 || (!info->fbops->fb_setcolreg && |
16207 |
+- !info->fbops->fb_setcmap)) |
16208 |
++ if (!info->fbops->fb_setcolreg && !info->fbops->fb_setcmap) |
16209 |
+ return -EINVAL; |
16210 |
+ |
16211 |
+ memset(&umap, 0, sizeof(struct fb_cmap)); |
16212 |
+diff -urNp linux-2.6.28.8/drivers/video/fbmem.c linux-2.6.28.8/drivers/video/fbmem.c |
16213 |
+--- linux-2.6.28.8/drivers/video/fbmem.c 2009-02-06 16:47:45.000000000 -0500 |
16214 |
++++ linux-2.6.28.8/drivers/video/fbmem.c 2009-02-21 09:37:48.000000000 -0500 |
16215 |
+@@ -393,7 +393,7 @@ static void fb_do_show_logo(struct fb_in |
16216 |
+ image->dx += image->width + 8; |
16217 |
+ } |
16218 |
+ } else if (rotate == FB_ROTATE_UD) { |
16219 |
+- for (x = 0; x < num && image->dx >= 0; x++) { |
16220 |
++ for (x = 0; x < num && (__s32)image->dx >= 0; x++) { |
16221 |
+ info->fbops->fb_imageblit(info, image); |
16222 |
+ image->dx -= image->width + 8; |
16223 |
+ } |
16224 |
+@@ -405,7 +405,7 @@ static void fb_do_show_logo(struct fb_in |
16225 |
+ image->dy += image->height + 8; |
16226 |
+ } |
16227 |
+ } else if (rotate == FB_ROTATE_CCW) { |
16228 |
+- for (x = 0; x < num && image->dy >= 0; x++) { |
16229 |
++ for (x = 0; x < num && (__s32)image->dy >= 0; x++) { |
16230 |
+ info->fbops->fb_imageblit(info, image); |
16231 |
+ image->dy -= image->height + 8; |
16232 |
+ } |
16233 |
+@@ -1090,7 +1090,7 @@ static long do_fb_ioctl(struct fb_info * |
16234 |
+ ret = -EINVAL; |
16235 |
+ break; |
16236 |
+ } |
16237 |
+- if (con2fb.framebuffer < 0 || con2fb.framebuffer >= FB_MAX) { |
16238 |
++ if (con2fb.framebuffer >= FB_MAX) { |
16239 |
+ ret = -EINVAL; |
16240 |
+ break; |
16241 |
+ } |
16242 |
+diff -urNp linux-2.6.28.8/drivers/video/fbmon.c linux-2.6.28.8/drivers/video/fbmon.c |
16243 |
+--- linux-2.6.28.8/drivers/video/fbmon.c 2009-02-06 16:47:45.000000000 -0500 |
16244 |
++++ linux-2.6.28.8/drivers/video/fbmon.c 2009-02-21 09:37:48.000000000 -0500 |
16245 |
+@@ -45,7 +45,7 @@ |
16246 |
+ #ifdef DEBUG |
16247 |
+ #define DPRINTK(fmt, args...) printk(fmt,## args) |
16248 |
+ #else |
16249 |
+-#define DPRINTK(fmt, args...) |
16250 |
++#define DPRINTK(fmt, args...) do {} while (0) |
16251 |
+ #endif |
16252 |
+ |
16253 |
+ #define FBMON_FIX_HEADER 1 |
16254 |
+diff -urNp linux-2.6.28.8/drivers/video/i810/i810_accel.c linux-2.6.28.8/drivers/video/i810/i810_accel.c |
16255 |
+--- linux-2.6.28.8/drivers/video/i810/i810_accel.c 2009-02-06 16:47:45.000000000 -0500 |
16256 |
++++ linux-2.6.28.8/drivers/video/i810/i810_accel.c 2009-02-21 09:37:48.000000000 -0500 |
16257 |
+@@ -73,6 +73,7 @@ static inline int wait_for_space(struct |
16258 |
+ } |
16259 |
+ } |
16260 |
+ printk("ringbuffer lockup!!!\n"); |
16261 |
++ printk("head:%u tail:%u iring.size:%u space:%u\n", head, tail, par->iring.size, space); |
16262 |
+ i810_report_error(mmio); |
16263 |
+ par->dev_flags |= LOCKUP; |
16264 |
+ info->pixmap.scan_align = 1; |
16265 |
+diff -urNp linux-2.6.28.8/drivers/video/i810/i810_main.c linux-2.6.28.8/drivers/video/i810/i810_main.c |
16266 |
+--- linux-2.6.28.8/drivers/video/i810/i810_main.c 2009-02-06 16:47:45.000000000 -0500 |
16267 |
++++ linux-2.6.28.8/drivers/video/i810/i810_main.c 2009-03-07 14:10:58.000000000 -0500 |
16268 |
+@@ -120,7 +120,7 @@ static struct pci_device_id i810fb_pci_t |
16269 |
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 }, |
16270 |
+ { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC, |
16271 |
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 }, |
16272 |
+- { 0 }, |
16273 |
++ { 0, 0, 0, 0, 0, 0, 0 }, |
16274 |
+ }; |
16275 |
+ |
16276 |
+ static struct pci_driver i810fb_driver = { |
16277 |
+diff -urNp linux-2.6.28.8/drivers/video/modedb.c linux-2.6.28.8/drivers/video/modedb.c |
16278 |
+--- linux-2.6.28.8/drivers/video/modedb.c 2009-02-06 16:47:45.000000000 -0500 |
16279 |
++++ linux-2.6.28.8/drivers/video/modedb.c 2009-02-21 09:37:48.000000000 -0500 |
16280 |
+@@ -38,232 +38,232 @@ static const struct fb_videomode modedb[ |
16281 |
+ { |
16282 |
+ /* 640x400 @ 70 Hz, 31.5 kHz hsync */ |
16283 |
+ NULL, 70, 640, 400, 39721, 40, 24, 39, 9, 96, 2, |
16284 |
+- 0, FB_VMODE_NONINTERLACED |
16285 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16286 |
+ }, { |
16287 |
+ /* 640x480 @ 60 Hz, 31.5 kHz hsync */ |
16288 |
+ NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2, |
16289 |
+- 0, FB_VMODE_NONINTERLACED |
16290 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16291 |
+ }, { |
16292 |
+ /* 800x600 @ 56 Hz, 35.15 kHz hsync */ |
16293 |
+ NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2, |
16294 |
+- 0, FB_VMODE_NONINTERLACED |
16295 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16296 |
+ }, { |
16297 |
+ /* 1024x768 @ 87 Hz interlaced, 35.5 kHz hsync */ |
16298 |
+ NULL, 87, 1024, 768, 22271, 56, 24, 33, 8, 160, 8, |
16299 |
+- 0, FB_VMODE_INTERLACED |
16300 |
++ 0, FB_VMODE_INTERLACED, FB_MODE_IS_UNKNOWN |
16301 |
+ }, { |
16302 |
+ /* 640x400 @ 85 Hz, 37.86 kHz hsync */ |
16303 |
+ NULL, 85, 640, 400, 31746, 96, 32, 41, 1, 64, 3, |
16304 |
+- FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16305 |
++ FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16306 |
+ }, { |
16307 |
+ /* 640x480 @ 72 Hz, 36.5 kHz hsync */ |
16308 |
+ NULL, 72, 640, 480, 31746, 144, 40, 30, 8, 40, 3, |
16309 |
+- 0, FB_VMODE_NONINTERLACED |
16310 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16311 |
+ }, { |
16312 |
+ /* 640x480 @ 75 Hz, 37.50 kHz hsync */ |
16313 |
+ NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, |
16314 |
+- 0, FB_VMODE_NONINTERLACED |
16315 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16316 |
+ }, { |
16317 |
+ /* 800x600 @ 60 Hz, 37.8 kHz hsync */ |
16318 |
+ NULL, 60, 800, 600, 25000, 88, 40, 23, 1, 128, 4, |
16319 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16320 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16321 |
+ }, { |
16322 |
+ /* 640x480 @ 85 Hz, 43.27 kHz hsync */ |
16323 |
+ NULL, 85, 640, 480, 27777, 80, 56, 25, 1, 56, 3, |
16324 |
+- 0, FB_VMODE_NONINTERLACED |
16325 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16326 |
+ }, { |
16327 |
+ /* 1152x864 @ 89 Hz interlaced, 44 kHz hsync */ |
16328 |
+ NULL, 89, 1152, 864, 15384, 96, 16, 110, 1, 216, 10, |
16329 |
+- 0, FB_VMODE_INTERLACED |
16330 |
++ 0, FB_VMODE_INTERLACED, FB_MODE_IS_UNKNOWN |
16331 |
+ }, { |
16332 |
+ /* 800x600 @ 72 Hz, 48.0 kHz hsync */ |
16333 |
+ NULL, 72, 800, 600, 20000, 64, 56, 23, 37, 120, 6, |
16334 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16335 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16336 |
+ }, { |
16337 |
+ /* 1024x768 @ 60 Hz, 48.4 kHz hsync */ |
16338 |
+ NULL, 60, 1024, 768, 15384, 168, 8, 29, 3, 144, 6, |
16339 |
+- 0, FB_VMODE_NONINTERLACED |
16340 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16341 |
+ }, { |
16342 |
+ /* 640x480 @ 100 Hz, 53.01 kHz hsync */ |
16343 |
+ NULL, 100, 640, 480, 21834, 96, 32, 36, 8, 96, 6, |
16344 |
+- 0, FB_VMODE_NONINTERLACED |
16345 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16346 |
+ }, { |
16347 |
+ /* 1152x864 @ 60 Hz, 53.5 kHz hsync */ |
16348 |
+ NULL, 60, 1152, 864, 11123, 208, 64, 16, 4, 256, 8, |
16349 |
+- 0, FB_VMODE_NONINTERLACED |
16350 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16351 |
+ }, { |
16352 |
+ /* 800x600 @ 85 Hz, 55.84 kHz hsync */ |
16353 |
+ NULL, 85, 800, 600, 16460, 160, 64, 36, 16, 64, 5, |
16354 |
+- 0, FB_VMODE_NONINTERLACED |
16355 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16356 |
+ }, { |
16357 |
+ /* 1024x768 @ 70 Hz, 56.5 kHz hsync */ |
16358 |
+ NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, |
16359 |
+- 0, FB_VMODE_NONINTERLACED |
16360 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16361 |
+ }, { |
16362 |
+ /* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */ |
16363 |
+ NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, |
16364 |
+- 0, FB_VMODE_INTERLACED |
16365 |
++ 0, FB_VMODE_INTERLACED, FB_MODE_IS_UNKNOWN |
16366 |
+ }, { |
16367 |
+ /* 800x600 @ 100 Hz, 64.02 kHz hsync */ |
16368 |
+ NULL, 100, 800, 600, 14357, 160, 64, 30, 4, 64, 6, |
16369 |
+- 0, FB_VMODE_NONINTERLACED |
16370 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16371 |
+ }, { |
16372 |
+ /* 1024x768 @ 76 Hz, 62.5 kHz hsync */ |
16373 |
+ NULL, 76, 1024, 768, 11764, 208, 8, 36, 16, 120, 3, |
16374 |
+- 0, FB_VMODE_NONINTERLACED |
16375 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16376 |
+ }, { |
16377 |
+ /* 1152x864 @ 70 Hz, 62.4 kHz hsync */ |
16378 |
+ NULL, 70, 1152, 864, 10869, 106, 56, 20, 1, 160, 10, |
16379 |
+- 0, FB_VMODE_NONINTERLACED |
16380 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16381 |
+ }, { |
16382 |
+ /* 1280x1024 @ 61 Hz, 64.2 kHz hsync */ |
16383 |
+ NULL, 61, 1280, 1024, 9090, 200, 48, 26, 1, 184, 3, |
16384 |
+- 0, FB_VMODE_NONINTERLACED |
16385 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16386 |
+ }, { |
16387 |
+ /* 1400x1050 @ 60Hz, 63.9 kHz hsync */ |
16388 |
+ NULL, 60, 1400, 1050, 9259, 136, 40, 13, 1, 112, 3, |
16389 |
+- 0, FB_VMODE_NONINTERLACED |
16390 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16391 |
+ }, { |
16392 |
+ /* 1400x1050 @ 75,107 Hz, 82,392 kHz +hsync +vsync*/ |
16393 |
+ NULL, 75, 1400, 1050, 7190, 120, 56, 23, 10, 112, 13, |
16394 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16395 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16396 |
+ }, { |
16397 |
+ /* 1400x1050 @ 60 Hz, ? kHz +hsync +vsync*/ |
16398 |
+ NULL, 60, 1400, 1050, 9259, 128, 40, 12, 0, 112, 3, |
16399 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16400 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16401 |
+ }, { |
16402 |
+ /* 1024x768 @ 85 Hz, 70.24 kHz hsync */ |
16403 |
+ NULL, 85, 1024, 768, 10111, 192, 32, 34, 14, 160, 6, |
16404 |
+- 0, FB_VMODE_NONINTERLACED |
16405 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16406 |
+ }, { |
16407 |
+ /* 1152x864 @ 78 Hz, 70.8 kHz hsync */ |
16408 |
+ NULL, 78, 1152, 864, 9090, 228, 88, 32, 0, 84, 12, |
16409 |
+- 0, FB_VMODE_NONINTERLACED |
16410 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16411 |
+ }, { |
16412 |
+ /* 1280x1024 @ 70 Hz, 74.59 kHz hsync */ |
16413 |
+ NULL, 70, 1280, 1024, 7905, 224, 32, 28, 8, 160, 8, |
16414 |
+- 0, FB_VMODE_NONINTERLACED |
16415 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16416 |
+ }, { |
16417 |
+ /* 1600x1200 @ 60Hz, 75.00 kHz hsync */ |
16418 |
+ NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, |
16419 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16420 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16421 |
+ }, { |
16422 |
+ /* 1152x864 @ 84 Hz, 76.0 kHz hsync */ |
16423 |
+ NULL, 84, 1152, 864, 7407, 184, 312, 32, 0, 128, 12, |
16424 |
+- 0, FB_VMODE_NONINTERLACED |
16425 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16426 |
+ }, { |
16427 |
+ /* 1280x1024 @ 74 Hz, 78.85 kHz hsync */ |
16428 |
+ NULL, 74, 1280, 1024, 7407, 256, 32, 34, 3, 144, 3, |
16429 |
+- 0, FB_VMODE_NONINTERLACED |
16430 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16431 |
+ }, { |
16432 |
+ /* 1024x768 @ 100Hz, 80.21 kHz hsync */ |
16433 |
+ NULL, 100, 1024, 768, 8658, 192, 32, 21, 3, 192, 10, |
16434 |
+- 0, FB_VMODE_NONINTERLACED |
16435 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16436 |
+ }, { |
16437 |
+ /* 1280x1024 @ 76 Hz, 81.13 kHz hsync */ |
16438 |
+ NULL, 76, 1280, 1024, 7407, 248, 32, 34, 3, 104, 3, |
16439 |
+- 0, FB_VMODE_NONINTERLACED |
16440 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16441 |
+ }, { |
16442 |
+ /* 1600x1200 @ 70 Hz, 87.50 kHz hsync */ |
16443 |
+ NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, |
16444 |
+- 0, FB_VMODE_NONINTERLACED |
16445 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16446 |
+ }, { |
16447 |
+ /* 1152x864 @ 100 Hz, 89.62 kHz hsync */ |
16448 |
+ NULL, 100, 1152, 864, 7264, 224, 32, 17, 2, 128, 19, |
16449 |
+- 0, FB_VMODE_NONINTERLACED |
16450 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16451 |
+ }, { |
16452 |
+ /* 1280x1024 @ 85 Hz, 91.15 kHz hsync */ |
16453 |
+ NULL, 85, 1280, 1024, 6349, 224, 64, 44, 1, 160, 3, |
16454 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16455 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16456 |
+ }, { |
16457 |
+ /* 1600x1200 @ 75 Hz, 93.75 kHz hsync */ |
16458 |
+ NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, |
16459 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16460 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16461 |
+ }, { |
16462 |
+ /* 1680x1050 @ 60 Hz, 65.191 kHz hsync */ |
16463 |
+ NULL, 60, 1680, 1050, 6848, 280, 104, 30, 3, 176, 6, |
16464 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16465 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16466 |
+ }, { |
16467 |
+ /* 1600x1200 @ 85 Hz, 105.77 kHz hsync */ |
16468 |
+ NULL, 85, 1600, 1200, 4545, 272, 16, 37, 4, 192, 3, |
16469 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16470 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16471 |
+ }, { |
16472 |
+ /* 1280x1024 @ 100 Hz, 107.16 kHz hsync */ |
16473 |
+ NULL, 100, 1280, 1024, 5502, 256, 32, 26, 7, 128, 15, |
16474 |
+- 0, FB_VMODE_NONINTERLACED |
16475 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16476 |
+ }, { |
16477 |
+ /* 1800x1440 @ 64Hz, 96.15 kHz hsync */ |
16478 |
+ NULL, 64, 1800, 1440, 4347, 304, 96, 46, 1, 192, 3, |
16479 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16480 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16481 |
+ }, { |
16482 |
+ /* 1800x1440 @ 70Hz, 104.52 kHz hsync */ |
16483 |
+ NULL, 70, 1800, 1440, 4000, 304, 96, 46, 1, 192, 3, |
16484 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16485 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16486 |
+ }, { |
16487 |
+ /* 512x384 @ 78 Hz, 31.50 kHz hsync */ |
16488 |
+ NULL, 78, 512, 384, 49603, 48, 16, 16, 1, 64, 3, |
16489 |
+- 0, FB_VMODE_NONINTERLACED |
16490 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16491 |
+ }, { |
16492 |
+ /* 512x384 @ 85 Hz, 34.38 kHz hsync */ |
16493 |
+ NULL, 85, 512, 384, 45454, 48, 16, 16, 1, 64, 3, |
16494 |
+- 0, FB_VMODE_NONINTERLACED |
16495 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16496 |
+ }, { |
16497 |
+ /* 320x200 @ 70 Hz, 31.5 kHz hsync, 8:5 aspect ratio */ |
16498 |
+ NULL, 70, 320, 200, 79440, 16, 16, 20, 4, 48, 1, |
16499 |
+- 0, FB_VMODE_DOUBLE |
16500 |
++ 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN |
16501 |
+ }, { |
16502 |
+ /* 320x240 @ 60 Hz, 31.5 kHz hsync, 4:3 aspect ratio */ |
16503 |
+ NULL, 60, 320, 240, 79440, 16, 16, 16, 5, 48, 1, |
16504 |
+- 0, FB_VMODE_DOUBLE |
16505 |
++ 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN |
16506 |
+ }, { |
16507 |
+ /* 320x240 @ 72 Hz, 36.5 kHz hsync */ |
16508 |
+ NULL, 72, 320, 240, 63492, 16, 16, 16, 4, 48, 2, |
16509 |
+- 0, FB_VMODE_DOUBLE |
16510 |
++ 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN |
16511 |
+ }, { |
16512 |
+ /* 400x300 @ 56 Hz, 35.2 kHz hsync, 4:3 aspect ratio */ |
16513 |
+ NULL, 56, 400, 300, 55555, 64, 16, 10, 1, 32, 1, |
16514 |
+- 0, FB_VMODE_DOUBLE |
16515 |
++ 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN |
16516 |
+ }, { |
16517 |
+ /* 400x300 @ 60 Hz, 37.8 kHz hsync */ |
16518 |
+ NULL, 60, 400, 300, 50000, 48, 16, 11, 1, 64, 2, |
16519 |
+- 0, FB_VMODE_DOUBLE |
16520 |
++ 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN |
16521 |
+ }, { |
16522 |
+ /* 400x300 @ 72 Hz, 48.0 kHz hsync */ |
16523 |
+ NULL, 72, 400, 300, 40000, 32, 24, 11, 19, 64, 3, |
16524 |
+- 0, FB_VMODE_DOUBLE |
16525 |
++ 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN |
16526 |
+ }, { |
16527 |
+ /* 480x300 @ 56 Hz, 35.2 kHz hsync, 8:5 aspect ratio */ |
16528 |
+ NULL, 56, 480, 300, 46176, 80, 16, 10, 1, 40, 1, |
16529 |
+- 0, FB_VMODE_DOUBLE |
16530 |
++ 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN |
16531 |
+ }, { |
16532 |
+ /* 480x300 @ 60 Hz, 37.8 kHz hsync */ |
16533 |
+ NULL, 60, 480, 300, 41858, 56, 16, 11, 1, 80, 2, |
16534 |
+- 0, FB_VMODE_DOUBLE |
16535 |
++ 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN |
16536 |
+ }, { |
16537 |
+ /* 480x300 @ 63 Hz, 39.6 kHz hsync */ |
16538 |
+ NULL, 63, 480, 300, 40000, 56, 16, 11, 1, 80, 2, |
16539 |
+- 0, FB_VMODE_DOUBLE |
16540 |
++ 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN |
16541 |
+ }, { |
16542 |
+ /* 480x300 @ 72 Hz, 48.0 kHz hsync */ |
16543 |
+ NULL, 72, 480, 300, 33386, 40, 24, 11, 19, 80, 3, |
16544 |
+- 0, FB_VMODE_DOUBLE |
16545 |
++ 0, FB_VMODE_DOUBLE, FB_MODE_IS_UNKNOWN |
16546 |
+ }, { |
16547 |
+ /* 1920x1200 @ 60 Hz, 74.5 Khz hsync */ |
16548 |
+ NULL, 60, 1920, 1200, 5177, 128, 336, 1, 38, 208, 3, |
16549 |
+ FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, |
16550 |
+- FB_VMODE_NONINTERLACED |
16551 |
++ FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16552 |
+ }, { |
16553 |
+ /* 1152x768, 60 Hz, PowerBook G4 Titanium I and II */ |
16554 |
+ NULL, 60, 1152, 768, 14047, 158, 26, 29, 3, 136, 6, |
16555 |
+- FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED |
16556 |
++ FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16557 |
+ }, { |
16558 |
+ /* 1366x768, 60 Hz, 47.403 kHz hsync, WXGA 16:9 aspect ratio */ |
16559 |
+ NULL, 60, 1366, 768, 13806, 120, 10, 14, 3, 32, 5, |
16560 |
+- 0, FB_VMODE_NONINTERLACED |
16561 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16562 |
+ }, { |
16563 |
+ /* 1280x800, 60 Hz, 47.403 kHz hsync, WXGA 16:10 aspect ratio */ |
16564 |
+ NULL, 60, 1280, 800, 12048, 200, 64, 24, 1, 136, 3, |
16565 |
+- 0, FB_VMODE_NONINTERLACED |
16566 |
++ 0, FB_VMODE_NONINTERLACED, FB_MODE_IS_UNKNOWN |
16567 |
+ }, |
16568 |
+ }; |
16569 |
+ |
16570 |
+diff -urNp linux-2.6.28.8/drivers/video/uvesafb.c linux-2.6.28.8/drivers/video/uvesafb.c |
16571 |
+--- linux-2.6.28.8/drivers/video/uvesafb.c 2009-02-06 16:47:45.000000000 -0500 |
16572 |
++++ linux-2.6.28.8/drivers/video/uvesafb.c 2009-02-21 09:37:48.000000000 -0500 |
16573 |
+@@ -18,6 +18,7 @@ |
16574 |
+ #include <linux/fb.h> |
16575 |
+ #include <linux/io.h> |
16576 |
+ #include <linux/mutex.h> |
16577 |
++#include <linux/moduleloader.h> |
16578 |
+ #include <video/edid.h> |
16579 |
+ #include <video/uvesafb.h> |
16580 |
+ #ifdef CONFIG_X86 |
16581 |
+@@ -117,7 +118,7 @@ static int uvesafb_helper_start(void) |
16582 |
+ NULL, |
16583 |
+ }; |
16584 |
+ |
16585 |
+- return call_usermodehelper(v86d_path, argv, envp, 1); |
16586 |
++ return call_usermodehelper(v86d_path, argv, envp, UMH_WAIT_PROC); |
16587 |
+ } |
16588 |
+ |
16589 |
+ /* |
16590 |
+@@ -574,10 +575,34 @@ static int __devinit uvesafb_vbe_getpmi( |
16591 |
+ if ((task->t.regs.eax & 0xffff) != 0x4f || task->t.regs.es < 0xc000) { |
16592 |
+ par->pmi_setpal = par->ypan = 0; |
16593 |
+ } else { |
16594 |
++ |
16595 |
++#ifdef CONFIG_PAX_KERNEXEC |
16596 |
++#ifdef CONFIG_MODULES |
16597 |
++ unsigned long cr0; |
16598 |
++ |
16599 |
++ par->pmi_code = module_alloc_exec((u16)task->t.regs.ecx); |
16600 |
++#endif |
16601 |
++ if (!par->pmi_code) { |
16602 |
++ par->pmi_setpal = par->ypan = 0; |
16603 |
++ return 0; |
16604 |
++ } |
16605 |
++#endif |
16606 |
++ |
16607 |
+ par->pmi_base = (u16 *)phys_to_virt(((u32)task->t.regs.es << 4) |
16608 |
+ + task->t.regs.edi); |
16609 |
++ |
16610 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) |
16611 |
++ pax_open_kernel(cr0); |
16612 |
++ memcpy(par->pmi_code, par->pmi_base, (u16)task->t.regs.ecx); |
16613 |
++ pax_close_kernel(cr0); |
16614 |
++ |
16615 |
++ par->pmi_start = ktva_ktla(par->pmi_code + par->pmi_base[1]); |
16616 |
++ par->pmi_pal = ktva_ktla(par->pmi_code + par->pmi_base[2]); |
16617 |
++#else |
16618 |
+ par->pmi_start = (u8 *)par->pmi_base + par->pmi_base[1]; |
16619 |
+ par->pmi_pal = (u8 *)par->pmi_base + par->pmi_base[2]; |
16620 |
++#endif |
16621 |
++ |
16622 |
+ printk(KERN_INFO "uvesafb: protected mode interface info at " |
16623 |
+ "%04x:%04x\n", |
16624 |
+ (u16)task->t.regs.es, (u16)task->t.regs.edi); |
16625 |
+@@ -1832,6 +1857,11 @@ out: |
16626 |
+ if (par->vbe_modes) |
16627 |
+ kfree(par->vbe_modes); |
16628 |
+ |
16629 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) |
16630 |
++ if (par->pmi_code) |
16631 |
++ module_free_exec(NULL, par->pmi_code); |
16632 |
++#endif |
16633 |
++ |
16634 |
+ framebuffer_release(info); |
16635 |
+ return err; |
16636 |
+ } |
16637 |
+@@ -1858,6 +1888,12 @@ static int uvesafb_remove(struct platfor |
16638 |
+ kfree(par->vbe_state_orig); |
16639 |
+ if (par->vbe_state_saved) |
16640 |
+ kfree(par->vbe_state_saved); |
16641 |
++ |
16642 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) |
16643 |
++ if (par->pmi_code) |
16644 |
++ module_free_exec(NULL, par->pmi_code); |
16645 |
++#endif |
16646 |
++ |
16647 |
+ } |
16648 |
+ |
16649 |
+ framebuffer_release(info); |
16650 |
+diff -urNp linux-2.6.28.8/drivers/video/vesafb.c linux-2.6.28.8/drivers/video/vesafb.c |
16651 |
+--- linux-2.6.28.8/drivers/video/vesafb.c 2009-02-06 16:47:45.000000000 -0500 |
16652 |
++++ linux-2.6.28.8/drivers/video/vesafb.c 2009-02-21 09:37:48.000000000 -0500 |
16653 |
+@@ -9,6 +9,7 @@ |
16654 |
+ */ |
16655 |
+ |
16656 |
+ #include <linux/module.h> |
16657 |
++#include <linux/moduleloader.h> |
16658 |
+ #include <linux/kernel.h> |
16659 |
+ #include <linux/errno.h> |
16660 |
+ #include <linux/string.h> |
16661 |
+@@ -53,8 +54,8 @@ static int vram_remap __initdata; /* |
16662 |
+ static int vram_total __initdata; /* Set total amount of memory */ |
16663 |
+ static int pmi_setpal __read_mostly = 1; /* pmi for palette changes ??? */ |
16664 |
+ static int ypan __read_mostly; /* 0..nothing, 1..ypan, 2..ywrap */ |
16665 |
+-static void (*pmi_start)(void) __read_mostly; |
16666 |
+-static void (*pmi_pal) (void) __read_mostly; |
16667 |
++static void (*pmi_start)(void) __read_only; |
16668 |
++static void (*pmi_pal) (void) __read_only; |
16669 |
+ static int depth __read_mostly; |
16670 |
+ static int vga_compat __read_mostly; |
16671 |
+ /* --------------------------------------------------------------------- */ |
16672 |
+@@ -224,6 +225,7 @@ static int __init vesafb_probe(struct pl |
16673 |
+ unsigned int size_vmode; |
16674 |
+ unsigned int size_remap; |
16675 |
+ unsigned int size_total; |
16676 |
++ void *pmi_code = NULL; |
16677 |
+ |
16678 |
+ if (screen_info.orig_video_isVGA != VIDEO_TYPE_VLFB) |
16679 |
+ return -ENODEV; |
16680 |
+@@ -266,10 +268,6 @@ static int __init vesafb_probe(struct pl |
16681 |
+ size_remap = size_total; |
16682 |
+ vesafb_fix.smem_len = size_remap; |
16683 |
+ |
16684 |
+-#ifndef __i386__ |
16685 |
+- screen_info.vesapm_seg = 0; |
16686 |
+-#endif |
16687 |
+- |
16688 |
+ if (!request_mem_region(vesafb_fix.smem_start, size_total, "vesafb")) { |
16689 |
+ printk(KERN_WARNING |
16690 |
+ "vesafb: cannot reserve video memory at 0x%lx\n", |
16691 |
+@@ -302,9 +300,21 @@ static int __init vesafb_probe(struct pl |
16692 |
+ printk(KERN_INFO "vesafb: mode is %dx%dx%d, linelength=%d, pages=%d\n", |
16693 |
+ vesafb_defined.xres, vesafb_defined.yres, vesafb_defined.bits_per_pixel, vesafb_fix.line_length, screen_info.pages); |
16694 |
+ |
16695 |
++#ifdef __i386__ |
16696 |
++ |
16697 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) |
16698 |
++ pmi_code = module_alloc_exec(screen_info.vesapm_size); |
16699 |
++ if (!pmi_code) |
16700 |
++#elif !defined(CONFIG_PAX_KERNEXEC) |
16701 |
++ if (0) |
16702 |
++#endif |
16703 |
++ |
16704 |
++#endif |
16705 |
++ screen_info.vesapm_seg = 0; |
16706 |
++ |
16707 |
+ if (screen_info.vesapm_seg) { |
16708 |
+- printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x\n", |
16709 |
+- screen_info.vesapm_seg,screen_info.vesapm_off); |
16710 |
++ printk(KERN_INFO "vesafb: protected mode interface info at %04x:%04x %04x bytes\n", |
16711 |
++ screen_info.vesapm_seg,screen_info.vesapm_off,screen_info.vesapm_size); |
16712 |
+ } |
16713 |
+ |
16714 |
+ if (screen_info.vesapm_seg < 0xc000) |
16715 |
+@@ -312,9 +322,29 @@ static int __init vesafb_probe(struct pl |
16716 |
+ |
16717 |
+ if (ypan || pmi_setpal) { |
16718 |
+ unsigned short *pmi_base; |
16719 |
+- pmi_base = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off); |
16720 |
+- pmi_start = (void*)((char*)pmi_base + pmi_base[1]); |
16721 |
+- pmi_pal = (void*)((char*)pmi_base + pmi_base[2]); |
16722 |
++ |
16723 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) |
16724 |
++ unsigned long cr0; |
16725 |
++#endif |
16726 |
++ |
16727 |
++ pmi_base = (unsigned short*)phys_to_virt(((unsigned long)screen_info.vesapm_seg << 4) + screen_info.vesapm_off); |
16728 |
++ |
16729 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) |
16730 |
++ pax_open_kernel(cr0); |
16731 |
++ memcpy(pmi_code, pmi_base, screen_info.vesapm_size); |
16732 |
++#else |
16733 |
++ pmi_code = pmi_base; |
16734 |
++#endif |
16735 |
++ |
16736 |
++ pmi_start = (void*)((char*)pmi_code + pmi_base[1]); |
16737 |
++ pmi_pal = (void*)((char*)pmi_code + pmi_base[2]); |
16738 |
++ |
16739 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) |
16740 |
++ pmi_start = ktva_ktla(pmi_start); |
16741 |
++ pmi_pal = ktva_ktla(pmi_pal); |
16742 |
++ pax_close_kernel(cr0); |
16743 |
++#endif |
16744 |
++ |
16745 |
+ printk(KERN_INFO "vesafb: pmi: set display start = %p, set palette = %p\n",pmi_start,pmi_pal); |
16746 |
+ if (pmi_base[3]) { |
16747 |
+ printk(KERN_INFO "vesafb: pmi: ports = "); |
16748 |
+@@ -456,6 +486,11 @@ static int __init vesafb_probe(struct pl |
16749 |
+ info->node, info->fix.id); |
16750 |
+ return 0; |
16751 |
+ err: |
16752 |
++ |
16753 |
++#if defined(__i386__) && defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC) |
16754 |
++ module_free_exec(NULL, pmi_code); |
16755 |
++#endif |
16756 |
++ |
16757 |
+ if (info->screen_base) |
16758 |
+ iounmap(info->screen_base); |
16759 |
+ framebuffer_release(info); |
16760 |
+diff -urNp linux-2.6.28.8/fs/9p/vfs_inode.c linux-2.6.28.8/fs/9p/vfs_inode.c |
16761 |
+--- linux-2.6.28.8/fs/9p/vfs_inode.c 2009-02-06 16:47:45.000000000 -0500 |
16762 |
++++ linux-2.6.28.8/fs/9p/vfs_inode.c 2009-02-21 09:37:48.000000000 -0500 |
16763 |
+@@ -1021,7 +1021,7 @@ static void *v9fs_vfs_follow_link(struct |
16764 |
+ static void |
16765 |
+ v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) |
16766 |
+ { |
16767 |
+- char *s = nd_get_link(nd); |
16768 |
++ const char *s = nd_get_link(nd); |
16769 |
+ |
16770 |
+ P9_DPRINTK(P9_DEBUG_VFS, " %s %s\n", dentry->d_name.name, |
16771 |
+ IS_ERR(s) ? "<error>" : s); |
16772 |
+diff -urNp linux-2.6.28.8/fs/aio.c linux-2.6.28.8/fs/aio.c |
16773 |
+--- linux-2.6.28.8/fs/aio.c 2009-02-06 16:47:45.000000000 -0500 |
16774 |
++++ linux-2.6.28.8/fs/aio.c 2009-02-21 09:37:48.000000000 -0500 |
16775 |
+@@ -114,7 +114,7 @@ static int aio_setup_ring(struct kioctx |
16776 |
+ size += sizeof(struct io_event) * nr_events; |
16777 |
+ nr_pages = (size + PAGE_SIZE-1) >> PAGE_SHIFT; |
16778 |
+ |
16779 |
+- if (nr_pages < 0) |
16780 |
++ if (nr_pages <= 0) |
16781 |
+ return -EINVAL; |
16782 |
+ |
16783 |
+ nr_events = (PAGE_SIZE * nr_pages - sizeof(struct aio_ring)) / sizeof(struct io_event); |
16784 |
+diff -urNp linux-2.6.28.8/fs/autofs4/symlink.c linux-2.6.28.8/fs/autofs4/symlink.c |
16785 |
+--- linux-2.6.28.8/fs/autofs4/symlink.c 2009-02-06 16:47:45.000000000 -0500 |
16786 |
++++ linux-2.6.28.8/fs/autofs4/symlink.c 2009-02-21 09:37:48.000000000 -0500 |
16787 |
+@@ -15,7 +15,7 @@ |
16788 |
+ static void *autofs4_follow_link(struct dentry *dentry, struct nameidata *nd) |
16789 |
+ { |
16790 |
+ struct autofs_info *ino = autofs4_dentry_ino(dentry); |
16791 |
+- nd_set_link(nd, (char *)ino->u.symlink); |
16792 |
++ nd_set_link(nd, ino->u.symlink); |
16793 |
+ return NULL; |
16794 |
+ } |
16795 |
+ |
16796 |
+diff -urNp linux-2.6.28.8/fs/befs/linuxvfs.c linux-2.6.28.8/fs/befs/linuxvfs.c |
16797 |
+--- linux-2.6.28.8/fs/befs/linuxvfs.c 2009-02-06 16:47:45.000000000 -0500 |
16798 |
++++ linux-2.6.28.8/fs/befs/linuxvfs.c 2009-02-21 09:37:48.000000000 -0500 |
16799 |
+@@ -490,7 +490,7 @@ static void befs_put_link(struct dentry |
16800 |
+ { |
16801 |
+ befs_inode_info *befs_ino = BEFS_I(dentry->d_inode); |
16802 |
+ if (befs_ino->i_flags & BEFS_LONG_SYMLINK) { |
16803 |
+- char *link = nd_get_link(nd); |
16804 |
++ const char *link = nd_get_link(nd); |
16805 |
+ if (!IS_ERR(link)) |
16806 |
+ kfree(link); |
16807 |
+ } |
16808 |
+diff -urNp linux-2.6.28.8/fs/binfmt_aout.c linux-2.6.28.8/fs/binfmt_aout.c |
16809 |
+--- linux-2.6.28.8/fs/binfmt_aout.c 2009-02-06 16:47:45.000000000 -0500 |
16810 |
++++ linux-2.6.28.8/fs/binfmt_aout.c 2009-02-21 09:37:48.000000000 -0500 |
16811 |
+@@ -16,6 +16,7 @@ |
16812 |
+ #include <linux/string.h> |
16813 |
+ #include <linux/fs.h> |
16814 |
+ #include <linux/file.h> |
16815 |
++#include <linux/security.h> |
16816 |
+ #include <linux/stat.h> |
16817 |
+ #include <linux/fcntl.h> |
16818 |
+ #include <linux/ptrace.h> |
16819 |
+@@ -124,18 +125,22 @@ static int aout_core_dump(long signr, st |
16820 |
+ /* If the size of the dump file exceeds the rlimit, then see what would happen |
16821 |
+ if we wrote the stack, but not the data area. */ |
16822 |
+ #ifdef __sparc__ |
16823 |
++ gr_learn_resource(current, RLIMIT_CORE, dump.u_dsize + dump.u_ssize, 1); |
16824 |
+ if ((dump.u_dsize + dump.u_ssize) > limit) |
16825 |
+ dump.u_dsize = 0; |
16826 |
+ #else |
16827 |
++ gr_learn_resource(current, RLIMIT_CORE, (dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE, 1); |
16828 |
+ if ((dump.u_dsize + dump.u_ssize+1) * PAGE_SIZE > limit) |
16829 |
+ dump.u_dsize = 0; |
16830 |
+ #endif |
16831 |
+ |
16832 |
+ /* Make sure we have enough room to write the stack and data areas. */ |
16833 |
+ #ifdef __sparc__ |
16834 |
++ gr_learn_resource(current, RLIMIT_CORE, dump.u_ssize, 1); |
16835 |
+ if (dump.u_ssize > limit) |
16836 |
+ dump.u_ssize = 0; |
16837 |
+ #else |
16838 |
++ gr_learn_resource(current, RLIMIT_CORE, (dump.u_ssize + 1) * PAGE_SIZE, 1); |
16839 |
+ if ((dump.u_ssize + 1) * PAGE_SIZE > limit) |
16840 |
+ dump.u_ssize = 0; |
16841 |
+ #endif |
16842 |
+@@ -291,6 +296,8 @@ static int load_aout_binary(struct linux |
16843 |
+ rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; |
16844 |
+ if (rlim >= RLIM_INFINITY) |
16845 |
+ rlim = ~0; |
16846 |
++ |
16847 |
++ gr_learn_resource(current, RLIMIT_DATA, ex.a_data + ex.a_bss, 1); |
16848 |
+ if (ex.a_data + ex.a_bss > rlim) |
16849 |
+ return -ENOMEM; |
16850 |
+ |
16851 |
+@@ -322,6 +329,28 @@ static int load_aout_binary(struct linux |
16852 |
+ |
16853 |
+ compute_creds(bprm); |
16854 |
+ current->flags &= ~PF_FORKNOEXEC; |
16855 |
++ |
16856 |
++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) |
16857 |
++ current->mm->pax_flags = 0UL; |
16858 |
++#endif |
16859 |
++ |
16860 |
++#ifdef CONFIG_PAX_PAGEEXEC |
16861 |
++ if (!(N_FLAGS(ex) & F_PAX_PAGEEXEC)) { |
16862 |
++ current->mm->pax_flags |= MF_PAX_PAGEEXEC; |
16863 |
++ |
16864 |
++#ifdef CONFIG_PAX_EMUTRAMP |
16865 |
++ if (N_FLAGS(ex) & F_PAX_EMUTRAMP) |
16866 |
++ current->mm->pax_flags |= MF_PAX_EMUTRAMP; |
16867 |
++#endif |
16868 |
++ |
16869 |
++#ifdef CONFIG_PAX_MPROTECT |
16870 |
++ if (!(N_FLAGS(ex) & F_PAX_MPROTECT)) |
16871 |
++ current->mm->pax_flags |= MF_PAX_MPROTECT; |
16872 |
++#endif |
16873 |
++ |
16874 |
++ } |
16875 |
++#endif |
16876 |
++ |
16877 |
+ #ifdef __sparc__ |
16878 |
+ if (N_MAGIC(ex) == NMAGIC) { |
16879 |
+ loff_t pos = fd_offset; |
16880 |
+@@ -413,7 +442,7 @@ static int load_aout_binary(struct linux |
16881 |
+ |
16882 |
+ down_write(¤t->mm->mmap_sem); |
16883 |
+ error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, |
16884 |
+- PROT_READ | PROT_WRITE | PROT_EXEC, |
16885 |
++ PROT_READ | PROT_WRITE, |
16886 |
+ MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, |
16887 |
+ fd_offset + ex.a_text); |
16888 |
+ up_write(¤t->mm->mmap_sem); |
16889 |
+diff -urNp linux-2.6.28.8/fs/binfmt_elf.c linux-2.6.28.8/fs/binfmt_elf.c |
16890 |
+--- linux-2.6.28.8/fs/binfmt_elf.c 2009-02-07 16:10:45.000000000 -0500 |
16891 |
++++ linux-2.6.28.8/fs/binfmt_elf.c 2009-03-07 04:29:14.000000000 -0500 |
16892 |
+@@ -42,6 +42,10 @@ |
16893 |
+ #include <asm/param.h> |
16894 |
+ #include <asm/page.h> |
16895 |
+ |
16896 |
++#ifdef CONFIG_PAX_SEGMEXEC |
16897 |
++#include <asm/desc.h> |
16898 |
++#endif |
16899 |
++ |
16900 |
+ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); |
16901 |
+ static int load_elf_library(struct file *); |
16902 |
+ static unsigned long elf_map(struct file *, unsigned long, struct elf_phdr *, |
16903 |
+@@ -57,6 +61,10 @@ static int elf_core_dump(long signr, str |
16904 |
+ #define elf_core_dump NULL |
16905 |
+ #endif |
16906 |
+ |
16907 |
++#ifdef CONFIG_PAX_MPROTECT |
16908 |
++static void elf_handle_mprotect(struct vm_area_struct *vma, unsigned long newflags); |
16909 |
++#endif |
16910 |
++ |
16911 |
+ #if ELF_EXEC_PAGESIZE > PAGE_SIZE |
16912 |
+ #define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE |
16913 |
+ #else |
16914 |
+@@ -76,6 +84,11 @@ static struct linux_binfmt elf_format = |
16915 |
+ .load_binary = load_elf_binary, |
16916 |
+ .load_shlib = load_elf_library, |
16917 |
+ .core_dump = elf_core_dump, |
16918 |
++ |
16919 |
++#ifdef CONFIG_PAX_MPROTECT |
16920 |
++ .handle_mprotect= elf_handle_mprotect, |
16921 |
++#endif |
16922 |
++ |
16923 |
+ .min_coredump = ELF_EXEC_PAGESIZE, |
16924 |
+ .hasvdso = 1 |
16925 |
+ }; |
16926 |
+@@ -84,6 +97,8 @@ static struct linux_binfmt elf_format = |
16927 |
+ |
16928 |
+ static int set_brk(unsigned long start, unsigned long end) |
16929 |
+ { |
16930 |
++ unsigned long e = end; |
16931 |
++ |
16932 |
+ start = ELF_PAGEALIGN(start); |
16933 |
+ end = ELF_PAGEALIGN(end); |
16934 |
+ if (end > start) { |
16935 |
+@@ -94,7 +109,7 @@ static int set_brk(unsigned long start, |
16936 |
+ if (BAD_ADDR(addr)) |
16937 |
+ return addr; |
16938 |
+ } |
16939 |
+- current->mm->start_brk = current->mm->brk = end; |
16940 |
++ current->mm->start_brk = current->mm->brk = e; |
16941 |
+ return 0; |
16942 |
+ } |
16943 |
+ |
16944 |
+@@ -380,10 +395,10 @@ static unsigned long load_elf_interp(str |
16945 |
+ { |
16946 |
+ struct elf_phdr *elf_phdata; |
16947 |
+ struct elf_phdr *eppnt; |
16948 |
+- unsigned long load_addr = 0; |
16949 |
++ unsigned long load_addr = 0, pax_task_size = TASK_SIZE; |
16950 |
+ int load_addr_set = 0; |
16951 |
+ unsigned long last_bss = 0, elf_bss = 0; |
16952 |
+- unsigned long error = ~0UL; |
16953 |
++ unsigned long error = -EINVAL; |
16954 |
+ unsigned long total_size; |
16955 |
+ int retval, i, size; |
16956 |
+ |
16957 |
+@@ -429,6 +444,11 @@ static unsigned long load_elf_interp(str |
16958 |
+ goto out_close; |
16959 |
+ } |
16960 |
+ |
16961 |
++#ifdef CONFIG_PAX_SEGMEXEC |
16962 |
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) |
16963 |
++ pax_task_size = SEGMEXEC_TASK_SIZE; |
16964 |
++#endif |
16965 |
++ |
16966 |
+ eppnt = elf_phdata; |
16967 |
+ for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { |
16968 |
+ if (eppnt->p_type == PT_LOAD) { |
16969 |
+@@ -472,8 +492,8 @@ static unsigned long load_elf_interp(str |
16970 |
+ k = load_addr + eppnt->p_vaddr; |
16971 |
+ if (BAD_ADDR(k) || |
16972 |
+ eppnt->p_filesz > eppnt->p_memsz || |
16973 |
+- eppnt->p_memsz > TASK_SIZE || |
16974 |
+- TASK_SIZE - eppnt->p_memsz < k) { |
16975 |
++ eppnt->p_memsz > pax_task_size || |
16976 |
++ pax_task_size - eppnt->p_memsz < k) { |
16977 |
+ error = -ENOMEM; |
16978 |
+ goto out_close; |
16979 |
+ } |
16980 |
+@@ -527,6 +547,177 @@ out: |
16981 |
+ return error; |
16982 |
+ } |
16983 |
+ |
16984 |
++#if (defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)) && defined(CONFIG_PAX_SOFTMODE) |
16985 |
++static unsigned long pax_parse_softmode(const struct elf_phdr * const elf_phdata) |
16986 |
++{ |
16987 |
++ unsigned long pax_flags = 0UL; |
16988 |
++ |
16989 |
++#ifdef CONFIG_PAX_PAGEEXEC |
16990 |
++ if (elf_phdata->p_flags & PF_PAGEEXEC) |
16991 |
++ pax_flags |= MF_PAX_PAGEEXEC; |
16992 |
++#endif |
16993 |
++ |
16994 |
++#ifdef CONFIG_PAX_SEGMEXEC |
16995 |
++ if (elf_phdata->p_flags & PF_SEGMEXEC) |
16996 |
++ pax_flags |= MF_PAX_SEGMEXEC; |
16997 |
++#endif |
16998 |
++ |
16999 |
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) |
17000 |
++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { |
17001 |
++ if (nx_enabled) |
17002 |
++ pax_flags &= ~MF_PAX_SEGMEXEC; |
17003 |
++ else |
17004 |
++ pax_flags &= ~MF_PAX_PAGEEXEC; |
17005 |
++ } |
17006 |
++#endif |
17007 |
++ |
17008 |
++#ifdef CONFIG_PAX_EMUTRAMP |
17009 |
++ if (elf_phdata->p_flags & PF_EMUTRAMP) |
17010 |
++ pax_flags |= MF_PAX_EMUTRAMP; |
17011 |
++#endif |
17012 |
++ |
17013 |
++#ifdef CONFIG_PAX_MPROTECT |
17014 |
++ if (elf_phdata->p_flags & PF_MPROTECT) |
17015 |
++ pax_flags |= MF_PAX_MPROTECT; |
17016 |
++#endif |
17017 |
++ |
17018 |
++#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) |
17019 |
++ if (randomize_va_space && (elf_phdata->p_flags & PF_RANDMMAP)) |
17020 |
++ pax_flags |= MF_PAX_RANDMMAP; |
17021 |
++#endif |
17022 |
++ |
17023 |
++ return pax_flags; |
17024 |
++} |
17025 |
++#endif |
17026 |
++ |
17027 |
++#ifdef CONFIG_PAX_PT_PAX_FLAGS |
17028 |
++static unsigned long pax_parse_hardmode(const struct elf_phdr * const elf_phdata) |
17029 |
++{ |
17030 |
++ unsigned long pax_flags = 0UL; |
17031 |
++ |
17032 |
++#ifdef CONFIG_PAX_PAGEEXEC |
17033 |
++ if (!(elf_phdata->p_flags & PF_NOPAGEEXEC)) |
17034 |
++ pax_flags |= MF_PAX_PAGEEXEC; |
17035 |
++#endif |
17036 |
++ |
17037 |
++#ifdef CONFIG_PAX_SEGMEXEC |
17038 |
++ if (!(elf_phdata->p_flags & PF_NOSEGMEXEC)) |
17039 |
++ pax_flags |= MF_PAX_SEGMEXEC; |
17040 |
++#endif |
17041 |
++ |
17042 |
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) |
17043 |
++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { |
17044 |
++ if (nx_enabled) |
17045 |
++ pax_flags &= ~MF_PAX_SEGMEXEC; |
17046 |
++ else |
17047 |
++ pax_flags &= ~MF_PAX_PAGEEXEC; |
17048 |
++ } |
17049 |
++#endif |
17050 |
++ |
17051 |
++#ifdef CONFIG_PAX_EMUTRAMP |
17052 |
++ if (!(elf_phdata->p_flags & PF_NOEMUTRAMP)) |
17053 |
++ pax_flags |= MF_PAX_EMUTRAMP; |
17054 |
++#endif |
17055 |
++ |
17056 |
++#ifdef CONFIG_PAX_MPROTECT |
17057 |
++ if (!(elf_phdata->p_flags & PF_NOMPROTECT)) |
17058 |
++ pax_flags |= MF_PAX_MPROTECT; |
17059 |
++#endif |
17060 |
++ |
17061 |
++#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) |
17062 |
++ if (randomize_va_space && !(elf_phdata->p_flags & PF_NORANDMMAP)) |
17063 |
++ pax_flags |= MF_PAX_RANDMMAP; |
17064 |
++#endif |
17065 |
++ |
17066 |
++ return pax_flags; |
17067 |
++} |
17068 |
++#endif |
17069 |
++ |
17070 |
++#ifdef CONFIG_PAX_EI_PAX |
17071 |
++static unsigned long pax_parse_ei_pax(const struct elfhdr * const elf_ex) |
17072 |
++{ |
17073 |
++ unsigned long pax_flags = 0UL; |
17074 |
++ |
17075 |
++#ifdef CONFIG_PAX_PAGEEXEC |
17076 |
++ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_PAGEEXEC)) |
17077 |
++ pax_flags |= MF_PAX_PAGEEXEC; |
17078 |
++#endif |
17079 |
++ |
17080 |
++#ifdef CONFIG_PAX_SEGMEXEC |
17081 |
++ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_SEGMEXEC)) |
17082 |
++ pax_flags |= MF_PAX_SEGMEXEC; |
17083 |
++#endif |
17084 |
++ |
17085 |
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_PAX_SEGMEXEC) |
17086 |
++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) == (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { |
17087 |
++ if (nx_enabled) |
17088 |
++ pax_flags &= ~MF_PAX_SEGMEXEC; |
17089 |
++ else |
17090 |
++ pax_flags &= ~MF_PAX_PAGEEXEC; |
17091 |
++ } |
17092 |
++#endif |
17093 |
++ |
17094 |
++#ifdef CONFIG_PAX_EMUTRAMP |
17095 |
++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && (elf_ex->e_ident[EI_PAX] & EF_PAX_EMUTRAMP)) |
17096 |
++ pax_flags |= MF_PAX_EMUTRAMP; |
17097 |
++#endif |
17098 |
++ |
17099 |
++#ifdef CONFIG_PAX_MPROTECT |
17100 |
++ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && !(elf_ex->e_ident[EI_PAX] & EF_PAX_MPROTECT)) |
17101 |
++ pax_flags |= MF_PAX_MPROTECT; |
17102 |
++#endif |
17103 |
++ |
17104 |
++#ifdef CONFIG_PAX_ASLR |
17105 |
++ if (randomize_va_space && !(elf_ex->e_ident[EI_PAX] & EF_PAX_RANDMMAP)) |
17106 |
++ pax_flags |= MF_PAX_RANDMMAP; |
17107 |
++#endif |
17108 |
++ |
17109 |
++ return pax_flags; |
17110 |
++} |
17111 |
++#endif |
17112 |
++ |
17113 |
++#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS) |
17114 |
++static long pax_parse_elf_flags(const struct elfhdr * const elf_ex, const struct elf_phdr * const elf_phdata) |
17115 |
++{ |
17116 |
++ unsigned long pax_flags = 0UL; |
17117 |
++ |
17118 |
++#ifdef CONFIG_PAX_PT_PAX_FLAGS |
17119 |
++ unsigned long i; |
17120 |
++#endif |
17121 |
++ |
17122 |
++#ifdef CONFIG_PAX_EI_PAX |
17123 |
++ pax_flags = pax_parse_ei_pax(elf_ex); |
17124 |
++#endif |
17125 |
++ |
17126 |
++#ifdef CONFIG_PAX_PT_PAX_FLAGS |
17127 |
++ for (i = 0UL; i < elf_ex->e_phnum; i++) |
17128 |
++ if (elf_phdata[i].p_type == PT_PAX_FLAGS) { |
17129 |
++ if (((elf_phdata[i].p_flags & PF_PAGEEXEC) && (elf_phdata[i].p_flags & PF_NOPAGEEXEC)) || |
17130 |
++ ((elf_phdata[i].p_flags & PF_SEGMEXEC) && (elf_phdata[i].p_flags & PF_NOSEGMEXEC)) || |
17131 |
++ ((elf_phdata[i].p_flags & PF_EMUTRAMP) && (elf_phdata[i].p_flags & PF_NOEMUTRAMP)) || |
17132 |
++ ((elf_phdata[i].p_flags & PF_MPROTECT) && (elf_phdata[i].p_flags & PF_NOMPROTECT)) || |
17133 |
++ ((elf_phdata[i].p_flags & PF_RANDMMAP) && (elf_phdata[i].p_flags & PF_NORANDMMAP))) |
17134 |
++ return -EINVAL; |
17135 |
++ |
17136 |
++#ifdef CONFIG_PAX_SOFTMODE |
17137 |
++ if (pax_softmode) |
17138 |
++ pax_flags = pax_parse_softmode(&elf_phdata[i]); |
17139 |
++ else |
17140 |
++#endif |
17141 |
++ |
17142 |
++ pax_flags = pax_parse_hardmode(&elf_phdata[i]); |
17143 |
++ break; |
17144 |
++ } |
17145 |
++#endif |
17146 |
++ |
17147 |
++ if (0 > pax_check_flags(&pax_flags)) |
17148 |
++ return -EINVAL; |
17149 |
++ |
17150 |
++ current->mm->pax_flags = pax_flags; |
17151 |
++ return 0; |
17152 |
++} |
17153 |
++#endif |
17154 |
++ |
17155 |
+ /* |
17156 |
+ * These are the functions used to load ELF style executables and shared |
17157 |
+ * libraries. There is no binary dependent code anywhere else. |
17158 |
+@@ -543,6 +734,11 @@ static unsigned long randomize_stack_top |
17159 |
+ { |
17160 |
+ unsigned int random_variable = 0; |
17161 |
+ |
17162 |
++#ifdef CONFIG_PAX_RANDUSTACK |
17163 |
++ if (randomize_va_space) |
17164 |
++ return stack_top - current->mm->delta_stack; |
17165 |
++#endif |
17166 |
++ |
17167 |
+ if ((current->flags & PF_RANDOMIZE) && |
17168 |
+ !(current->personality & ADDR_NO_RANDOMIZE)) { |
17169 |
+ random_variable = get_random_int() & STACK_RND_MASK; |
17170 |
+@@ -561,7 +757,7 @@ static int load_elf_binary(struct linux_ |
17171 |
+ unsigned long load_addr = 0, load_bias = 0; |
17172 |
+ int load_addr_set = 0; |
17173 |
+ char * elf_interpreter = NULL; |
17174 |
+- unsigned long error; |
17175 |
++ unsigned long error = 0; |
17176 |
+ struct elf_phdr *elf_ppnt, *elf_phdata; |
17177 |
+ unsigned long elf_bss, elf_brk; |
17178 |
+ int elf_exec_fileno; |
17179 |
+@@ -572,11 +768,11 @@ static int load_elf_binary(struct linux_ |
17180 |
+ unsigned long start_code, end_code, start_data, end_data; |
17181 |
+ unsigned long reloc_func_desc = 0; |
17182 |
+ int executable_stack = EXSTACK_DEFAULT; |
17183 |
+- unsigned long def_flags = 0; |
17184 |
+ struct { |
17185 |
+ struct elfhdr elf_ex; |
17186 |
+ struct elfhdr interp_elf_ex; |
17187 |
+ } *loc; |
17188 |
++ unsigned long pax_task_size = TASK_SIZE; |
17189 |
+ |
17190 |
+ loc = kmalloc(sizeof(*loc), GFP_KERNEL); |
17191 |
+ if (!loc) { |
17192 |
+@@ -744,11 +940,80 @@ static int load_elf_binary(struct linux_ |
17193 |
+ |
17194 |
+ /* OK, This is the point of no return */ |
17195 |
+ current->flags &= ~PF_FORKNOEXEC; |
17196 |
+- current->mm->def_flags = def_flags; |
17197 |
++ |
17198 |
++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) |
17199 |
++ current->mm->pax_flags = 0UL; |
17200 |
++#endif |
17201 |
++ |
17202 |
++#ifdef CONFIG_PAX_DLRESOLVE |
17203 |
++ current->mm->call_dl_resolve = 0UL; |
17204 |
++#endif |
17205 |
++ |
17206 |
++#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT) |
17207 |
++ current->mm->call_syscall = 0UL; |
17208 |
++#endif |
17209 |
++ |
17210 |
++#ifdef CONFIG_PAX_ASLR |
17211 |
++ current->mm->delta_mmap = 0UL; |
17212 |
++ current->mm->delta_stack = 0UL; |
17213 |
++#endif |
17214 |
++ |
17215 |
++ current->mm->def_flags = 0; |
17216 |
++ |
17217 |
++#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS) |
17218 |
++ if (0 > pax_parse_elf_flags(&loc->elf_ex, elf_phdata)) { |
17219 |
++ send_sig(SIGKILL, current, 0); |
17220 |
++ goto out_free_dentry; |
17221 |
++ } |
17222 |
++#endif |
17223 |
++ |
17224 |
++#ifdef CONFIG_PAX_HAVE_ACL_FLAGS |
17225 |
++ pax_set_initial_flags(bprm); |
17226 |
++#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS) |
17227 |
++ if (pax_set_initial_flags_func) |
17228 |
++ (pax_set_initial_flags_func)(bprm); |
17229 |
++#endif |
17230 |
++ |
17231 |
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT |
17232 |
++ if ((current->mm->pax_flags & MF_PAX_PAGEEXEC) && !nx_enabled) { |
17233 |
++ current->mm->context.user_cs_limit = PAGE_SIZE; |
17234 |
++ current->mm->def_flags |= VM_PAGEEXEC; |
17235 |
++ } |
17236 |
++#endif |
17237 |
++ |
17238 |
++#ifdef CONFIG_PAX_SEGMEXEC |
17239 |
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) { |
17240 |
++ current->mm->context.user_cs_base = SEGMEXEC_TASK_SIZE; |
17241 |
++ current->mm->context.user_cs_limit = TASK_SIZE-SEGMEXEC_TASK_SIZE; |
17242 |
++ pax_task_size = SEGMEXEC_TASK_SIZE; |
17243 |
++ } |
17244 |
++#endif |
17245 |
++ |
17246 |
++#if defined(CONFIG_ARCH_TRACK_EXEC_LIMIT) || defined(CONFIG_PAX_SEGMEXEC) |
17247 |
++ if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { |
17248 |
++ set_user_cs(current->mm->context.user_cs_base, current->mm->context.user_cs_limit, get_cpu()); |
17249 |
++ put_cpu_no_resched(); |
17250 |
++ } |
17251 |
++#endif |
17252 |
++ |
17253 |
++#ifdef CONFIG_PAX_ASLR |
17254 |
++ if (current->mm->pax_flags & MF_PAX_RANDMMAP) { |
17255 |
++ current->mm->delta_mmap = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN)-1)) << PAGE_SHIFT; |
17256 |
++ current->mm->delta_stack = (pax_get_random_long() & ((1UL << PAX_DELTA_STACK_LEN)-1)) << PAGE_SHIFT; |
17257 |
++ } |
17258 |
++#endif |
17259 |
+ |
17260 |
+ /* Do this immediately, since STACK_TOP as used in setup_arg_pages |
17261 |
+ may depend on the personality. */ |
17262 |
+ SET_PERSONALITY(loc->elf_ex); |
17263 |
++ |
17264 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
17265 |
++ if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { |
17266 |
++ executable_stack = EXSTACK_DISABLE_X; |
17267 |
++ current->personality &= ~READ_IMPLIES_EXEC; |
17268 |
++ } else |
17269 |
++#endif |
17270 |
++ |
17271 |
+ if (elf_read_implies_exec(loc->elf_ex, executable_stack)) |
17272 |
+ current->personality |= READ_IMPLIES_EXEC; |
17273 |
+ |
17274 |
+@@ -829,6 +1094,20 @@ static int load_elf_binary(struct linux_ |
17275 |
+ #else |
17276 |
+ load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); |
17277 |
+ #endif |
17278 |
++ |
17279 |
++#ifdef CONFIG_PAX_RANDMMAP |
17280 |
++ /* PaX: randomize base address at the default exe base if requested */ |
17281 |
++ if ((current->mm->pax_flags & MF_PAX_RANDMMAP) && elf_interpreter) { |
17282 |
++#ifdef CONFIG_SPARC64 |
17283 |
++ load_bias = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN) - 1)) << (PAGE_SHIFT+1); |
17284 |
++#else |
17285 |
++ load_bias = (pax_get_random_long() & ((1UL << PAX_DELTA_MMAP_LEN) - 1)) << PAGE_SHIFT; |
17286 |
++#endif |
17287 |
++ load_bias = ELF_PAGESTART(PAX_ELF_ET_DYN_BASE - vaddr + load_bias); |
17288 |
++ elf_flags |= MAP_FIXED; |
17289 |
++ } |
17290 |
++#endif |
17291 |
++ |
17292 |
+ } |
17293 |
+ |
17294 |
+ error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, |
17295 |
+@@ -861,9 +1140,9 @@ static int load_elf_binary(struct linux_ |
17296 |
+ * allowed task size. Note that p_filesz must always be |
17297 |
+ * <= p_memsz so it is only necessary to check p_memsz. |
17298 |
+ */ |
17299 |
+- if (BAD_ADDR(k) || elf_ppnt->p_filesz > elf_ppnt->p_memsz || |
17300 |
+- elf_ppnt->p_memsz > TASK_SIZE || |
17301 |
+- TASK_SIZE - elf_ppnt->p_memsz < k) { |
17302 |
++ if (k >= pax_task_size || elf_ppnt->p_filesz > elf_ppnt->p_memsz || |
17303 |
++ elf_ppnt->p_memsz > pax_task_size || |
17304 |
++ pax_task_size - elf_ppnt->p_memsz < k) { |
17305 |
+ /* set_brk can never work. Avoid overflows. */ |
17306 |
+ send_sig(SIGKILL, current, 0); |
17307 |
+ retval = -EINVAL; |
17308 |
+@@ -891,6 +1170,11 @@ static int load_elf_binary(struct linux_ |
17309 |
+ start_data += load_bias; |
17310 |
+ end_data += load_bias; |
17311 |
+ |
17312 |
++#ifdef CONFIG_PAX_RANDMMAP |
17313 |
++ if (current->mm->pax_flags & MF_PAX_RANDMMAP) |
17314 |
++ elf_brk += PAGE_SIZE + ((pax_get_random_long() & ~PAGE_MASK) << 4); |
17315 |
++#endif |
17316 |
++ |
17317 |
+ /* Calling set_brk effectively mmaps the pages that we need |
17318 |
+ * for the bss and break sections. We must do this before |
17319 |
+ * mapping in the interpreter, to make sure it doesn't wind |
17320 |
+@@ -902,9 +1186,11 @@ static int load_elf_binary(struct linux_ |
17321 |
+ goto out_free_dentry; |
17322 |
+ } |
17323 |
+ if (likely(elf_bss != elf_brk) && unlikely(padzero(elf_bss))) { |
17324 |
+- send_sig(SIGSEGV, current, 0); |
17325 |
+- retval = -EFAULT; /* Nobody gets to see this, but.. */ |
17326 |
+- goto out_free_dentry; |
17327 |
++ /* |
17328 |
++ * This bss-zeroing can fail if the ELF |
17329 |
++ * file specifies odd protections. So |
17330 |
++ * we don't check the return value |
17331 |
++ */ |
17332 |
+ } |
17333 |
+ |
17334 |
+ if (elf_interpreter) { |
17335 |
+@@ -1141,8 +1427,10 @@ static int dump_seek(struct file *file, |
17336 |
+ unsigned long n = off; |
17337 |
+ if (n > PAGE_SIZE) |
17338 |
+ n = PAGE_SIZE; |
17339 |
+- if (!dump_write(file, buf, n)) |
17340 |
++ if (!dump_write(file, buf, n)) { |
17341 |
++ free_page((unsigned long)buf); |
17342 |
+ return 0; |
17343 |
++ } |
17344 |
+ off -= n; |
17345 |
+ } |
17346 |
+ free_page((unsigned long)buf); |
17347 |
+@@ -1154,7 +1442,7 @@ static int dump_seek(struct file *file, |
17348 |
+ * Decide what to dump of a segment, part, all or none. |
17349 |
+ */ |
17350 |
+ static unsigned long vma_dump_size(struct vm_area_struct *vma, |
17351 |
+- unsigned long mm_flags) |
17352 |
++ unsigned long mm_flags, long signr) |
17353 |
+ { |
17354 |
+ #define FILTER(type) (mm_flags & (1UL << MMF_DUMP_##type)) |
17355 |
+ |
17356 |
+@@ -1188,7 +1476,7 @@ static unsigned long vma_dump_size(struc |
17357 |
+ if (vma->vm_file == NULL) |
17358 |
+ return 0; |
17359 |
+ |
17360 |
+- if (FILTER(MAPPED_PRIVATE)) |
17361 |
++ if (signr == SIGKILL || FILTER(MAPPED_PRIVATE)) |
17362 |
+ goto whole; |
17363 |
+ |
17364 |
+ /* |
17365 |
+@@ -1284,8 +1572,11 @@ static int writenote(struct memelfnote * |
17366 |
+ #undef DUMP_WRITE |
17367 |
+ |
17368 |
+ #define DUMP_WRITE(addr, nr) \ |
17369 |
++ do { \ |
17370 |
++ gr_learn_resource(current, RLIMIT_CORE, size + (nr), 1); \ |
17371 |
+ if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ |
17372 |
+- goto end_coredump; |
17373 |
++ goto end_coredump; \ |
17374 |
++ } while (0); |
17375 |
+ #define DUMP_SEEK(off) \ |
17376 |
+ if (!dump_seek(file, (off))) \ |
17377 |
+ goto end_coredump; |
17378 |
+@@ -1986,7 +2277,7 @@ static int elf_core_dump(long signr, str |
17379 |
+ phdr.p_offset = offset; |
17380 |
+ phdr.p_vaddr = vma->vm_start; |
17381 |
+ phdr.p_paddr = 0; |
17382 |
+- phdr.p_filesz = vma_dump_size(vma, mm_flags); |
17383 |
++ phdr.p_filesz = vma_dump_size(vma, mm_flags, signr); |
17384 |
+ phdr.p_memsz = vma->vm_end - vma->vm_start; |
17385 |
+ offset += phdr.p_filesz; |
17386 |
+ phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; |
17387 |
+@@ -2018,7 +2309,7 @@ static int elf_core_dump(long signr, str |
17388 |
+ unsigned long addr; |
17389 |
+ unsigned long end; |
17390 |
+ |
17391 |
+- end = vma->vm_start + vma_dump_size(vma, mm_flags); |
17392 |
++ end = vma->vm_start + vma_dump_size(vma, mm_flags, signr); |
17393 |
+ |
17394 |
+ for (addr = vma->vm_start; addr < end; addr += PAGE_SIZE) { |
17395 |
+ struct page *page; |
17396 |
+@@ -2038,6 +2329,7 @@ static int elf_core_dump(long signr, str |
17397 |
+ flush_cache_page(tmp_vma, addr, |
17398 |
+ page_to_pfn(page)); |
17399 |
+ kaddr = kmap(page); |
17400 |
++ gr_learn_resource(current, RLIMIT_CORE, size + PAGE_SIZE, 1); |
17401 |
+ if ((size += PAGE_SIZE) > limit || |
17402 |
+ !dump_write(file, kaddr, |
17403 |
+ PAGE_SIZE)) { |
17404 |
+@@ -2068,6 +2360,99 @@ out: |
17405 |
+ |
17406 |
+ #endif /* USE_ELF_CORE_DUMP */ |
17407 |
+ |
17408 |
++#ifdef CONFIG_PAX_MPROTECT |
17409 |
++/* PaX: non-PIC ELF libraries need relocations on their executable segments |
17410 |
++ * therefore we'll grant them VM_MAYWRITE once during their life. Similarly |
17411 |
++ * we'll remove VM_MAYWRITE for good on RELRO segments. |
17412 |
++ * |
17413 |
++ * The checks favour ld-linux.so behaviour which operates on a per ELF segment |
17414 |
++ * basis because we want to allow the common case and not the special ones. |
17415 |
++ */ |
17416 |
++static void elf_handle_mprotect(struct vm_area_struct *vma, unsigned long newflags) |
17417 |
++{ |
17418 |
++ struct elfhdr elf_h; |
17419 |
++ struct elf_phdr elf_p; |
17420 |
++ unsigned long i; |
17421 |
++ unsigned long oldflags; |
17422 |
++ bool is_textrel_rw, is_textrel_rx, is_relro; |
17423 |
++ |
17424 |
++ if (!(vma->vm_mm->pax_flags & MF_PAX_MPROTECT)) |
17425 |
++ return; |
17426 |
++ |
17427 |
++ oldflags = vma->vm_flags & (VM_MAYEXEC | VM_MAYWRITE | VM_MAYREAD | VM_EXEC | VM_WRITE | VM_READ); |
17428 |
++ newflags &= VM_MAYEXEC | VM_MAYWRITE | VM_MAYREAD | VM_EXEC | VM_WRITE | VM_READ; |
17429 |
++ |
17430 |
++#ifdef CONFIG_PAX_NOELFRELOCS |
17431 |
++ is_textrel_rw = false; |
17432 |
++ is_textrel_rx = false; |
17433 |
++#else |
17434 |
++ /* possible TEXTREL */ |
17435 |
++ is_textrel_rw = vma->vm_file && !vma->anon_vma && oldflags == (VM_MAYEXEC | VM_MAYREAD | VM_EXEC | VM_READ) && newflags == (VM_WRITE | VM_READ); |
17436 |
++ is_textrel_rx = vma->vm_file && vma->anon_vma && oldflags == (VM_MAYEXEC | VM_MAYWRITE | VM_MAYREAD | VM_WRITE | VM_READ) && newflags == (VM_EXEC | VM_READ); |
17437 |
++#endif |
17438 |
++ |
17439 |
++ /* possible RELRO */ |
17440 |
++ is_relro = vma->vm_file && vma->anon_vma && oldflags == (VM_MAYWRITE | VM_MAYREAD | VM_READ) && newflags == (VM_MAYWRITE | VM_MAYREAD | VM_READ); |
17441 |
++ |
17442 |
++ if (!is_textrel_rw && !is_textrel_rx && !is_relro) |
17443 |
++ return; |
17444 |
++ |
17445 |
++ if (sizeof(elf_h) != kernel_read(vma->vm_file, 0UL, (char *)&elf_h, sizeof(elf_h)) || |
17446 |
++ memcmp(elf_h.e_ident, ELFMAG, SELFMAG) || |
17447 |
++ |
17448 |
++#ifdef CONFIG_PAX_ETEXECRELOCS |
17449 |
++ ((is_textrel_rw || is_textrel_rx) && (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC)) || |
17450 |
++#else |
17451 |
++ ((is_textrel_rw || is_textrel_rx) && elf_h.e_type != ET_DYN) || |
17452 |
++#endif |
17453 |
++ |
17454 |
++ (is_relro && (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC)) || |
17455 |
++ !elf_check_arch(&elf_h) || |
17456 |
++ elf_h.e_phentsize != sizeof(struct elf_phdr) || |
17457 |
++ elf_h.e_phnum > 65536UL / sizeof(struct elf_phdr)) |
17458 |
++ return; |
17459 |
++ |
17460 |
++ for (i = 0UL; i < elf_h.e_phnum; i++) { |
17461 |
++ if (sizeof(elf_p) != kernel_read(vma->vm_file, elf_h.e_phoff + i*sizeof(elf_p), (char *)&elf_p, sizeof(elf_p))) |
17462 |
++ return; |
17463 |
++ switch (elf_p.p_type) { |
17464 |
++ case PT_DYNAMIC: { |
17465 |
++ elf_addr_t dyn_offset = 0UL; |
17466 |
++ elf_dyn dyn; |
17467 |
++ |
17468 |
++ if (!is_textrel_rw && !is_textrel_rx) |
17469 |
++ continue; |
17470 |
++ dyn_offset = elf_p.p_offset; |
17471 |
++ i = 0UL; |
17472 |
++ do { |
17473 |
++ if (sizeof(dyn) != kernel_read(vma->vm_file, dyn_offset + i*sizeof(dyn), (char *)&dyn, sizeof(dyn))) |
17474 |
++ return; |
17475 |
++ if (dyn.d_tag == DT_TEXTREL || (dyn.d_tag == DT_FLAGS && (dyn.d_un.d_val & DF_TEXTREL))) { |
17476 |
++ gr_log_textrel(vma); |
17477 |
++ if (is_textrel_rw) |
17478 |
++ vma->vm_flags |= VM_MAYWRITE; |
17479 |
++ else |
17480 |
++ /* PaX: disallow write access after relocs are done, hopefully noone else needs it... */ |
17481 |
++ vma->vm_flags &= ~VM_MAYWRITE; |
17482 |
++ return; |
17483 |
++ } |
17484 |
++ i++; |
17485 |
++ } while (dyn.d_tag != DT_NULL); |
17486 |
++ return; |
17487 |
++ } |
17488 |
++ |
17489 |
++ case PT_GNU_RELRO: |
17490 |
++ if (!is_relro) |
17491 |
++ continue; |
17492 |
++ if ((elf_p.p_offset >> PAGE_SHIFT) == vma->vm_pgoff && ELF_PAGEALIGN(elf_p.p_memsz) == vma->vm_end - vma->vm_start) { |
17493 |
++ vma->vm_flags &= ~VM_MAYWRITE; |
17494 |
++ } |
17495 |
++ return; |
17496 |
++ } |
17497 |
++ } |
17498 |
++} |
17499 |
++#endif |
17500 |
++ |
17501 |
+ static int __init init_elf_binfmt(void) |
17502 |
+ { |
17503 |
+ return register_binfmt(&elf_format); |
17504 |
+diff -urNp linux-2.6.28.8/fs/binfmt_flat.c linux-2.6.28.8/fs/binfmt_flat.c |
17505 |
+--- linux-2.6.28.8/fs/binfmt_flat.c 2009-02-06 16:47:45.000000000 -0500 |
17506 |
++++ linux-2.6.28.8/fs/binfmt_flat.c 2009-02-21 09:37:48.000000000 -0500 |
17507 |
+@@ -561,7 +561,9 @@ static int load_flat_file(struct linux_b |
17508 |
+ realdatastart = (unsigned long) -ENOMEM; |
17509 |
+ printk("Unable to allocate RAM for process data, errno %d\n", |
17510 |
+ (int)-realdatastart); |
17511 |
++ down_write(¤t->mm->mmap_sem); |
17512 |
+ do_munmap(current->mm, textpos, text_len); |
17513 |
++ up_write(¤t->mm->mmap_sem); |
17514 |
+ ret = realdatastart; |
17515 |
+ goto err; |
17516 |
+ } |
17517 |
+@@ -583,8 +585,10 @@ static int load_flat_file(struct linux_b |
17518 |
+ } |
17519 |
+ if (result >= (unsigned long)-4096) { |
17520 |
+ printk("Unable to read data+bss, errno %d\n", (int)-result); |
17521 |
++ down_write(¤t->mm->mmap_sem); |
17522 |
+ do_munmap(current->mm, textpos, text_len); |
17523 |
+ do_munmap(current->mm, realdatastart, data_len + extra); |
17524 |
++ up_write(¤t->mm->mmap_sem); |
17525 |
+ ret = result; |
17526 |
+ goto err; |
17527 |
+ } |
17528 |
+@@ -657,8 +661,10 @@ static int load_flat_file(struct linux_b |
17529 |
+ } |
17530 |
+ if (result >= (unsigned long)-4096) { |
17531 |
+ printk("Unable to read code+data+bss, errno %d\n",(int)-result); |
17532 |
++ down_write(¤t->mm->mmap_sem); |
17533 |
+ do_munmap(current->mm, textpos, text_len + data_len + extra + |
17534 |
+ MAX_SHARED_LIBS * sizeof(unsigned long)); |
17535 |
++ up_write(¤t->mm->mmap_sem); |
17536 |
+ ret = result; |
17537 |
+ goto err; |
17538 |
+ } |
17539 |
+diff -urNp linux-2.6.28.8/fs/binfmt_misc.c linux-2.6.28.8/fs/binfmt_misc.c |
17540 |
+--- linux-2.6.28.8/fs/binfmt_misc.c 2009-02-06 16:47:45.000000000 -0500 |
17541 |
++++ linux-2.6.28.8/fs/binfmt_misc.c 2009-02-21 09:37:48.000000000 -0500 |
17542 |
+@@ -696,7 +696,7 @@ static int bm_fill_super(struct super_bl |
17543 |
+ static struct tree_descr bm_files[] = { |
17544 |
+ [2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO}, |
17545 |
+ [3] = {"register", &bm_register_operations, S_IWUSR}, |
17546 |
+- /* last one */ {""} |
17547 |
++ /* last one */ {"", NULL, 0} |
17548 |
+ }; |
17549 |
+ int err = simple_fill_super(sb, 0x42494e4d, bm_files); |
17550 |
+ if (!err) |
17551 |
+diff -urNp linux-2.6.28.8/fs/bio.c linux-2.6.28.8/fs/bio.c |
17552 |
+--- linux-2.6.28.8/fs/bio.c 2009-02-06 16:47:45.000000000 -0500 |
17553 |
++++ linux-2.6.28.8/fs/bio.c 2009-02-21 09:37:48.000000000 -0500 |
17554 |
+@@ -554,7 +554,7 @@ static int __bio_copy_iov(struct bio *bi |
17555 |
+ |
17556 |
+ while (bv_len && iov_idx < iov_count) { |
17557 |
+ unsigned int bytes; |
17558 |
+- char *iov_addr; |
17559 |
++ char __user *iov_addr; |
17560 |
+ |
17561 |
+ bytes = min_t(unsigned int, |
17562 |
+ iov[iov_idx].iov_len - iov_off, bv_len); |
17563 |
+diff -urNp linux-2.6.28.8/fs/buffer.c linux-2.6.28.8/fs/buffer.c |
17564 |
+--- linux-2.6.28.8/fs/buffer.c 2009-02-06 16:47:45.000000000 -0500 |
17565 |
++++ linux-2.6.28.8/fs/buffer.c 2009-02-21 09:37:48.000000000 -0500 |
17566 |
+@@ -25,6 +25,7 @@ |
17567 |
+ #include <linux/percpu.h> |
17568 |
+ #include <linux/slab.h> |
17569 |
+ #include <linux/capability.h> |
17570 |
++#include <linux/security.h> |
17571 |
+ #include <linux/blkdev.h> |
17572 |
+ #include <linux/file.h> |
17573 |
+ #include <linux/quotaops.h> |
17574 |
+@@ -2249,6 +2250,7 @@ int generic_cont_expand_simple(struct in |
17575 |
+ |
17576 |
+ err = -EFBIG; |
17577 |
+ limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; |
17578 |
++ gr_learn_resource(current, RLIMIT_FSIZE, (unsigned long) size, 1); |
17579 |
+ if (limit != RLIM_INFINITY && size > (loff_t)limit) { |
17580 |
+ send_sig(SIGXFSZ, current, 0); |
17581 |
+ goto out; |
17582 |
+diff -urNp linux-2.6.28.8/fs/cifs/cifs_uniupr.h linux-2.6.28.8/fs/cifs/cifs_uniupr.h |
17583 |
+--- linux-2.6.28.8/fs/cifs/cifs_uniupr.h 2009-02-06 16:47:45.000000000 -0500 |
17584 |
++++ linux-2.6.28.8/fs/cifs/cifs_uniupr.h 2009-02-21 09:37:48.000000000 -0500 |
17585 |
+@@ -132,7 +132,7 @@ const struct UniCaseRange CifsUniUpperRa |
17586 |
+ {0x0490, 0x04cc, UniCaseRangeU0490}, |
17587 |
+ {0x1e00, 0x1ffc, UniCaseRangeU1e00}, |
17588 |
+ {0xff40, 0xff5a, UniCaseRangeUff40}, |
17589 |
+- {0} |
17590 |
++ {0, 0, NULL} |
17591 |
+ }; |
17592 |
+ #endif |
17593 |
+ |
17594 |
+diff -urNp linux-2.6.28.8/fs/cifs/link.c linux-2.6.28.8/fs/cifs/link.c |
17595 |
+--- linux-2.6.28.8/fs/cifs/link.c 2009-02-06 16:47:45.000000000 -0500 |
17596 |
++++ linux-2.6.28.8/fs/cifs/link.c 2009-02-21 09:37:48.000000000 -0500 |
17597 |
+@@ -318,7 +318,7 @@ cifs_readlink(struct dentry *direntry, c |
17598 |
+ |
17599 |
+ void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie) |
17600 |
+ { |
17601 |
+- char *p = nd_get_link(nd); |
17602 |
++ const char *p = nd_get_link(nd); |
17603 |
+ if (!IS_ERR(p)) |
17604 |
+ kfree(p); |
17605 |
+ } |
17606 |
+diff -urNp linux-2.6.28.8/fs/compat.c linux-2.6.28.8/fs/compat.c |
17607 |
+--- linux-2.6.28.8/fs/compat.c 2009-02-06 16:47:45.000000000 -0500 |
17608 |
++++ linux-2.6.28.8/fs/compat.c 2009-02-21 09:37:48.000000000 -0500 |
17609 |
+@@ -1331,14 +1331,12 @@ static int compat_copy_strings(int argc, |
17610 |
+ if (!kmapped_page || kpos != (pos & PAGE_MASK)) { |
17611 |
+ struct page *page; |
17612 |
+ |
17613 |
+-#ifdef CONFIG_STACK_GROWSUP |
17614 |
+ ret = expand_stack_downwards(bprm->vma, pos); |
17615 |
+ if (ret < 0) { |
17616 |
+ /* We've exceed the stack rlimit. */ |
17617 |
+ ret = -E2BIG; |
17618 |
+ goto out; |
17619 |
+ } |
17620 |
+-#endif |
17621 |
+ ret = get_user_pages(current, bprm->mm, pos, |
17622 |
+ 1, 1, 1, &page, NULL); |
17623 |
+ if (ret <= 0) { |
17624 |
+@@ -1384,6 +1382,11 @@ int compat_do_execve(char * filename, |
17625 |
+ compat_uptr_t __user *envp, |
17626 |
+ struct pt_regs * regs) |
17627 |
+ { |
17628 |
++#ifdef CONFIG_GRKERNSEC |
17629 |
++ struct file *old_exec_file; |
17630 |
++ struct acl_subject_label *old_acl; |
17631 |
++ struct rlimit old_rlim[RLIM_NLIMITS]; |
17632 |
++#endif |
17633 |
+ struct linux_binprm *bprm; |
17634 |
+ struct file *file; |
17635 |
+ int retval; |
17636 |
+@@ -1404,6 +1407,14 @@ int compat_do_execve(char * filename, |
17637 |
+ bprm->filename = filename; |
17638 |
+ bprm->interp = filename; |
17639 |
+ |
17640 |
++ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes), 1); |
17641 |
++ retval = -EAGAIN; |
17642 |
++ if (gr_handle_nproc()) |
17643 |
++ goto out_file; |
17644 |
++ retval = -EACCES; |
17645 |
++ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) |
17646 |
++ goto out_file; |
17647 |
++ |
17648 |
+ retval = bprm_mm_init(bprm); |
17649 |
+ if (retval) |
17650 |
+ goto out_file; |
17651 |
+@@ -1437,8 +1448,36 @@ int compat_do_execve(char * filename, |
17652 |
+ if (retval < 0) |
17653 |
+ goto out; |
17654 |
+ |
17655 |
++ if (!gr_tpe_allow(file)) { |
17656 |
++ retval = -EACCES; |
17657 |
++ goto out; |
17658 |
++ } |
17659 |
++ |
17660 |
++ if (gr_check_crash_exec(file)) { |
17661 |
++ retval = -EACCES; |
17662 |
++ goto out; |
17663 |
++ } |
17664 |
++ |
17665 |
++ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt); |
17666 |
++ |
17667 |
++ gr_handle_exec_args(bprm, (char __user * __user *)argv); |
17668 |
++ |
17669 |
++#ifdef CONFIG_GRKERNSEC |
17670 |
++ old_acl = current->acl; |
17671 |
++ memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim)); |
17672 |
++ old_exec_file = current->exec_file; |
17673 |
++ get_file(file); |
17674 |
++ current->exec_file = file; |
17675 |
++#endif |
17676 |
++ |
17677 |
++ gr_set_proc_label(file->f_dentry, file->f_vfsmnt); |
17678 |
++ |
17679 |
+ retval = search_binary_handler(bprm, regs); |
17680 |
+ if (retval >= 0) { |
17681 |
++#ifdef CONFIG_GRKERNSEC |
17682 |
++ if (old_exec_file) |
17683 |
++ fput(old_exec_file); |
17684 |
++#endif |
17685 |
+ /* execve success */ |
17686 |
+ security_bprm_free(bprm); |
17687 |
+ acct_update_integrals(current); |
17688 |
+@@ -1446,6 +1485,13 @@ int compat_do_execve(char * filename, |
17689 |
+ return retval; |
17690 |
+ } |
17691 |
+ |
17692 |
++#ifdef CONFIG_GRKERNSEC |
17693 |
++ current->acl = old_acl; |
17694 |
++ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim)); |
17695 |
++ fput(current->exec_file); |
17696 |
++ current->exec_file = old_exec_file; |
17697 |
++#endif |
17698 |
++ |
17699 |
+ out: |
17700 |
+ if (bprm->security) |
17701 |
+ security_bprm_free(bprm); |
17702 |
+diff -urNp linux-2.6.28.8/fs/compat_ioctl.c linux-2.6.28.8/fs/compat_ioctl.c |
17703 |
+--- linux-2.6.28.8/fs/compat_ioctl.c 2009-03-07 10:24:49.000000000 -0500 |
17704 |
++++ linux-2.6.28.8/fs/compat_ioctl.c 2009-03-07 10:29:51.000000000 -0500 |
17705 |
+@@ -1832,15 +1832,15 @@ struct ioctl_trans { |
17706 |
+ }; |
17707 |
+ |
17708 |
+ #define HANDLE_IOCTL(cmd,handler) \ |
17709 |
+- { (cmd), (ioctl_trans_handler_t)(handler) }, |
17710 |
++ { (cmd), (ioctl_trans_handler_t)(handler), NULL }, |
17711 |
+ |
17712 |
+ /* pointer to compatible structure or no argument */ |
17713 |
+ #define COMPATIBLE_IOCTL(cmd) \ |
17714 |
+- { (cmd), do_ioctl32_pointer }, |
17715 |
++ { (cmd), do_ioctl32_pointer, NULL }, |
17716 |
+ |
17717 |
+ /* argument is an unsigned long integer, not a pointer */ |
17718 |
+ #define ULONG_IOCTL(cmd) \ |
17719 |
+- { (cmd), (ioctl_trans_handler_t)sys_ioctl }, |
17720 |
++ { (cmd), (ioctl_trans_handler_t)sys_ioctl, NULL }, |
17721 |
+ |
17722 |
+ /* ioctl should not be warned about even if it's not implemented. |
17723 |
+ Valid reasons to use this: |
17724 |
+diff -urNp linux-2.6.28.8/fs/debugfs/inode.c linux-2.6.28.8/fs/debugfs/inode.c |
17725 |
+--- linux-2.6.28.8/fs/debugfs/inode.c 2009-02-06 16:47:45.000000000 -0500 |
17726 |
++++ linux-2.6.28.8/fs/debugfs/inode.c 2009-02-21 09:37:48.000000000 -0500 |
17727 |
+@@ -120,7 +120,7 @@ static inline int debugfs_positive(struc |
17728 |
+ |
17729 |
+ static int debug_fill_super(struct super_block *sb, void *data, int silent) |
17730 |
+ { |
17731 |
+- static struct tree_descr debug_files[] = {{""}}; |
17732 |
++ static struct tree_descr debug_files[] = {{"", NULL, 0}}; |
17733 |
+ |
17734 |
+ return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files); |
17735 |
+ } |
17736 |
+diff -urNp linux-2.6.28.8/fs/exec.c linux-2.6.28.8/fs/exec.c |
17737 |
+--- linux-2.6.28.8/fs/exec.c 2009-02-06 16:47:45.000000000 -0500 |
17738 |
++++ linux-2.6.28.8/fs/exec.c 2009-02-21 09:37:48.000000000 -0500 |
17739 |
+@@ -51,6 +51,12 @@ |
17740 |
+ #include <linux/audit.h> |
17741 |
+ #include <linux/tracehook.h> |
17742 |
+ #include <linux/kmod.h> |
17743 |
++#include <linux/random.h> |
17744 |
++ |
17745 |
++#ifdef CONFIG_PAX_REFCOUNT |
17746 |
++#include <linux/kallsyms.h> |
17747 |
++#include <linux/kdebug.h> |
17748 |
++#endif |
17749 |
+ |
17750 |
+ #include <asm/uaccess.h> |
17751 |
+ #include <asm/mmu_context.h> |
17752 |
+@@ -61,6 +67,11 @@ |
17753 |
+ #include <linux/a.out.h> |
17754 |
+ #endif |
17755 |
+ |
17756 |
++#ifdef CONFIG_PAX_HOOK_ACL_FLAGS |
17757 |
++void (*pax_set_initial_flags_func)(struct linux_binprm *bprm); |
17758 |
++EXPORT_SYMBOL(pax_set_initial_flags_func); |
17759 |
++#endif |
17760 |
++ |
17761 |
+ int core_uses_pid; |
17762 |
+ char core_pattern[CORENAME_MAX_SIZE] = "core"; |
17763 |
+ int suid_dumpable = 0; |
17764 |
+@@ -169,18 +180,10 @@ static struct page *get_arg_page(struct |
17765 |
+ int write) |
17766 |
+ { |
17767 |
+ struct page *page; |
17768 |
+- int ret; |
17769 |
+ |
17770 |
+-#ifdef CONFIG_STACK_GROWSUP |
17771 |
+- if (write) { |
17772 |
+- ret = expand_stack_downwards(bprm->vma, pos); |
17773 |
+- if (ret < 0) |
17774 |
+- return NULL; |
17775 |
+- } |
17776 |
+-#endif |
17777 |
+- ret = get_user_pages(current, bprm->mm, pos, |
17778 |
+- 1, write, 1, &page, NULL); |
17779 |
+- if (ret <= 0) |
17780 |
++ if (0 > expand_stack_downwards(bprm->vma, pos)) |
17781 |
++ return NULL; |
17782 |
++ if (0 >= get_user_pages(current, bprm->mm, pos, 1, write, 1, &page, NULL)) |
17783 |
+ return NULL; |
17784 |
+ |
17785 |
+ if (write) { |
17786 |
+@@ -253,6 +256,11 @@ static int __bprm_mm_init(struct linux_b |
17787 |
+ vma->vm_start = vma->vm_end - PAGE_SIZE; |
17788 |
+ |
17789 |
+ vma->vm_flags = VM_STACK_FLAGS; |
17790 |
++ |
17791 |
++#ifdef CONFIG_PAX_SEGMEXEC |
17792 |
++ vma->vm_flags &= ~(VM_EXEC | VM_MAYEXEC); |
17793 |
++#endif |
17794 |
++ |
17795 |
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
17796 |
+ err = insert_vm_struct(mm, vma); |
17797 |
+ if (err) { |
17798 |
+@@ -265,6 +273,11 @@ static int __bprm_mm_init(struct linux_b |
17799 |
+ |
17800 |
+ bprm->p = vma->vm_end - sizeof(void *); |
17801 |
+ |
17802 |
++#ifdef CONFIG_PAX_RANDUSTACK |
17803 |
++ if (randomize_va_space) |
17804 |
++ bprm->p ^= (pax_get_random_long() & ~15) & ~PAGE_MASK; |
17805 |
++#endif |
17806 |
++ |
17807 |
+ return 0; |
17808 |
+ |
17809 |
+ err: |
17810 |
+@@ -528,6 +541,10 @@ static int shift_arg_pages(struct vm_are |
17811 |
+ if (vma != find_vma(mm, new_start)) |
17812 |
+ return -EFAULT; |
17813 |
+ |
17814 |
++#ifdef CONFIG_PAX_SEGMEXEC |
17815 |
++ BUG_ON(pax_find_mirror_vma(vma)); |
17816 |
++#endif |
17817 |
++ |
17818 |
+ /* |
17819 |
+ * cover the whole range: [new_start, old_end) |
17820 |
+ */ |
17821 |
+@@ -616,6 +633,14 @@ int setup_arg_pages(struct linux_binprm |
17822 |
+ bprm->exec -= stack_shift; |
17823 |
+ |
17824 |
+ down_write(&mm->mmap_sem); |
17825 |
++ |
17826 |
++ /* Move stack pages down in memory. */ |
17827 |
++ if (stack_shift) { |
17828 |
++ ret = shift_arg_pages(vma, stack_shift); |
17829 |
++ if (ret) |
17830 |
++ goto out_unlock; |
17831 |
++ } |
17832 |
++ |
17833 |
+ vm_flags = VM_STACK_FLAGS; |
17834 |
+ |
17835 |
+ /* |
17836 |
+@@ -629,21 +654,24 @@ int setup_arg_pages(struct linux_binprm |
17837 |
+ vm_flags &= ~VM_EXEC; |
17838 |
+ vm_flags |= mm->def_flags; |
17839 |
+ |
17840 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
17841 |
++ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { |
17842 |
++ vm_flags &= ~VM_EXEC; |
17843 |
++ |
17844 |
++#ifdef CONFIG_PAX_MPROTECT |
17845 |
++ if (mm->pax_flags & MF_PAX_MPROTECT) |
17846 |
++ vm_flags &= ~VM_MAYEXEC; |
17847 |
++#endif |
17848 |
++ |
17849 |
++ } |
17850 |
++#endif |
17851 |
++ |
17852 |
+ ret = mprotect_fixup(vma, &prev, vma->vm_start, vma->vm_end, |
17853 |
+ vm_flags); |
17854 |
+ if (ret) |
17855 |
+ goto out_unlock; |
17856 |
+ BUG_ON(prev != vma); |
17857 |
+ |
17858 |
+- /* Move stack pages down in memory. */ |
17859 |
+- if (stack_shift) { |
17860 |
+- ret = shift_arg_pages(vma, stack_shift); |
17861 |
+- if (ret) { |
17862 |
+- up_write(&mm->mmap_sem); |
17863 |
+- return ret; |
17864 |
+- } |
17865 |
+- } |
17866 |
+- |
17867 |
+ #ifdef CONFIG_STACK_GROWSUP |
17868 |
+ stack_base = vma->vm_end + EXTRA_STACK_VM_PAGES * PAGE_SIZE; |
17869 |
+ #else |
17870 |
+@@ -655,7 +683,7 @@ int setup_arg_pages(struct linux_binprm |
17871 |
+ |
17872 |
+ out_unlock: |
17873 |
+ up_write(&mm->mmap_sem); |
17874 |
+- return 0; |
17875 |
++ return ret; |
17876 |
+ } |
17877 |
+ EXPORT_SYMBOL(setup_arg_pages); |
17878 |
+ |
17879 |
+@@ -1281,6 +1309,11 @@ int do_execve(char * filename, |
17880 |
+ char __user *__user *envp, |
17881 |
+ struct pt_regs * regs) |
17882 |
+ { |
17883 |
++#ifdef CONFIG_GRKERNSEC |
17884 |
++ struct file *old_exec_file; |
17885 |
++ struct acl_subject_label *old_acl; |
17886 |
++ struct rlimit old_rlim[RLIM_NLIMITS]; |
17887 |
++#endif |
17888 |
+ struct linux_binprm *bprm; |
17889 |
+ struct file *file; |
17890 |
+ struct files_struct *displaced; |
17891 |
+@@ -1300,6 +1333,20 @@ int do_execve(char * filename, |
17892 |
+ if (IS_ERR(file)) |
17893 |
+ goto out_kfree; |
17894 |
+ |
17895 |
++ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes), 1); |
17896 |
++ |
17897 |
++ if (gr_handle_nproc()) { |
17898 |
++ allow_write_access(file); |
17899 |
++ fput(file); |
17900 |
++ return -EAGAIN; |
17901 |
++ } |
17902 |
++ |
17903 |
++ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) { |
17904 |
++ allow_write_access(file); |
17905 |
++ fput(file); |
17906 |
++ return -EACCES; |
17907 |
++ } |
17908 |
++ |
17909 |
+ sched_exec(); |
17910 |
+ |
17911 |
+ bprm->file = file; |
17912 |
+@@ -1339,9 +1386,39 @@ int do_execve(char * filename, |
17913 |
+ if (retval < 0) |
17914 |
+ goto out; |
17915 |
+ |
17916 |
++ if (!gr_tpe_allow(file)) { |
17917 |
++ retval = -EACCES; |
17918 |
++ goto out; |
17919 |
++ } |
17920 |
++ |
17921 |
++ if (gr_check_crash_exec(file)) { |
17922 |
++ retval = -EACCES; |
17923 |
++ goto out; |
17924 |
++ } |
17925 |
++ |
17926 |
++ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt); |
17927 |
++ |
17928 |
++ gr_handle_exec_args(bprm, argv); |
17929 |
++ |
17930 |
++#ifdef CONFIG_GRKERNSEC |
17931 |
++ old_acl = current->acl; |
17932 |
++ memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim)); |
17933 |
++ old_exec_file = current->exec_file; |
17934 |
++ get_file(file); |
17935 |
++ current->exec_file = file; |
17936 |
++#endif |
17937 |
++ |
17938 |
++ retval = gr_set_proc_label(file->f_dentry, file->f_vfsmnt); |
17939 |
++ if (retval < 0) |
17940 |
++ goto out_fail; |
17941 |
++ |
17942 |
+ current->flags &= ~PF_KTHREAD; |
17943 |
+ retval = search_binary_handler(bprm,regs); |
17944 |
+ if (retval >= 0) { |
17945 |
++#ifdef CONFIG_GRKERNSEC |
17946 |
++ if (old_exec_file) |
17947 |
++ fput(old_exec_file); |
17948 |
++#endif |
17949 |
+ /* execve success */ |
17950 |
+ security_bprm_free(bprm); |
17951 |
+ acct_update_integrals(current); |
17952 |
+@@ -1351,6 +1428,14 @@ int do_execve(char * filename, |
17953 |
+ return retval; |
17954 |
+ } |
17955 |
+ |
17956 |
++out_fail: |
17957 |
++#ifdef CONFIG_GRKERNSEC |
17958 |
++ current->acl = old_acl; |
17959 |
++ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim)); |
17960 |
++ fput(current->exec_file); |
17961 |
++ current->exec_file = old_exec_file; |
17962 |
++#endif |
17963 |
++ |
17964 |
+ out: |
17965 |
+ if (bprm->security) |
17966 |
+ security_bprm_free(bprm); |
17967 |
+@@ -1513,6 +1598,129 @@ out: |
17968 |
+ return ispipe; |
17969 |
+ } |
17970 |
+ |
17971 |
++int pax_check_flags(unsigned long *flags) |
17972 |
++{ |
17973 |
++ int retval = 0; |
17974 |
++ |
17975 |
++#if !defined(CONFIG_X86_32) || !defined(CONFIG_PAX_SEGMEXEC) |
17976 |
++ if (*flags & MF_PAX_SEGMEXEC) |
17977 |
++ { |
17978 |
++ *flags &= ~MF_PAX_SEGMEXEC; |
17979 |
++ retval = -EINVAL; |
17980 |
++ } |
17981 |
++#endif |
17982 |
++ |
17983 |
++ if ((*flags & MF_PAX_PAGEEXEC) |
17984 |
++ |
17985 |
++#ifdef CONFIG_PAX_PAGEEXEC |
17986 |
++ && (*flags & MF_PAX_SEGMEXEC) |
17987 |
++#endif |
17988 |
++ |
17989 |
++ ) |
17990 |
++ { |
17991 |
++ *flags &= ~MF_PAX_PAGEEXEC; |
17992 |
++ retval = -EINVAL; |
17993 |
++ } |
17994 |
++ |
17995 |
++ if ((*flags & MF_PAX_MPROTECT) |
17996 |
++ |
17997 |
++#ifdef CONFIG_PAX_MPROTECT |
17998 |
++ && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) |
17999 |
++#endif |
18000 |
++ |
18001 |
++ ) |
18002 |
++ { |
18003 |
++ *flags &= ~MF_PAX_MPROTECT; |
18004 |
++ retval = -EINVAL; |
18005 |
++ } |
18006 |
++ |
18007 |
++ if ((*flags & MF_PAX_EMUTRAMP) |
18008 |
++ |
18009 |
++#ifdef CONFIG_PAX_EMUTRAMP |
18010 |
++ && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) |
18011 |
++#endif |
18012 |
++ |
18013 |
++ ) |
18014 |
++ { |
18015 |
++ *flags &= ~MF_PAX_EMUTRAMP; |
18016 |
++ retval = -EINVAL; |
18017 |
++ } |
18018 |
++ |
18019 |
++ return retval; |
18020 |
++} |
18021 |
++ |
18022 |
++EXPORT_SYMBOL(pax_check_flags); |
18023 |
++ |
18024 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
18025 |
++void pax_report_fault(struct pt_regs *regs, void *pc, void *sp) |
18026 |
++{ |
18027 |
++ struct task_struct *tsk = current; |
18028 |
++ struct mm_struct *mm = current->mm; |
18029 |
++ char *buffer_exec = (char *)__get_free_page(GFP_KERNEL); |
18030 |
++ char *buffer_fault = (char *)__get_free_page(GFP_KERNEL); |
18031 |
++ char *path_exec = NULL; |
18032 |
++ char *path_fault = NULL; |
18033 |
++ unsigned long start = 0UL, end = 0UL, offset = 0UL; |
18034 |
++ |
18035 |
++ if (buffer_exec && buffer_fault) { |
18036 |
++ struct vm_area_struct *vma, *vma_exec = NULL, *vma_fault = NULL; |
18037 |
++ |
18038 |
++ down_read(&mm->mmap_sem); |
18039 |
++ vma = mm->mmap; |
18040 |
++ while (vma && (!vma_exec || !vma_fault)) { |
18041 |
++ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) |
18042 |
++ vma_exec = vma; |
18043 |
++ if (vma->vm_start <= (unsigned long)pc && (unsigned long)pc < vma->vm_end) |
18044 |
++ vma_fault = vma; |
18045 |
++ vma = vma->vm_next; |
18046 |
++ } |
18047 |
++ if (vma_exec) { |
18048 |
++ path_exec = d_path(&vma_exec->vm_file->f_path, buffer_exec, PAGE_SIZE); |
18049 |
++ if (IS_ERR(path_exec)) |
18050 |
++ path_exec = "<path too long>"; |
18051 |
++ } |
18052 |
++ if (vma_fault) { |
18053 |
++ start = vma_fault->vm_start; |
18054 |
++ end = vma_fault->vm_end; |
18055 |
++ offset = vma_fault->vm_pgoff << PAGE_SHIFT; |
18056 |
++ if (vma_fault->vm_file) { |
18057 |
++ path_fault = d_path(&vma_fault->vm_file->f_path, buffer_fault, PAGE_SIZE); |
18058 |
++ if (IS_ERR(path_fault)) |
18059 |
++ path_fault = "<path too long>"; |
18060 |
++ } else |
18061 |
++ path_fault = "<anonymous mapping>"; |
18062 |
++ } |
18063 |
++ up_read(&mm->mmap_sem); |
18064 |
++ } |
18065 |
++ if (tsk->signal->curr_ip) |
18066 |
++ printk(KERN_ERR "PAX: From %u.%u.%u.%u: execution attempt in: %s, %08lx-%08lx %08lx\n", NIPQUAD(tsk->signal->curr_ip), path_fault, start, end, offset); |
18067 |
++ else |
18068 |
++ printk(KERN_ERR "PAX: execution attempt in: %s, %08lx-%08lx %08lx\n", path_fault, start, end, offset); |
18069 |
++ printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, " |
18070 |
++ "PC: %p, SP: %p\n", path_exec, tsk->comm, task_pid_nr(tsk), |
18071 |
++ tsk->uid, tsk->euid, pc, sp); |
18072 |
++ free_page((unsigned long)buffer_exec); |
18073 |
++ free_page((unsigned long)buffer_fault); |
18074 |
++ pax_report_insns(pc, sp); |
18075 |
++ do_coredump(SIGKILL, SIGKILL, regs); |
18076 |
++} |
18077 |
++#endif |
18078 |
++ |
18079 |
++#ifdef CONFIG_PAX_REFCOUNT |
18080 |
++void pax_report_refcount_overflow(struct pt_regs *regs) |
18081 |
++{ |
18082 |
++ if (current->signal->curr_ip) |
18083 |
++ printk(KERN_ERR "PAX: From %u.%u.%u.%u: refcount overflow detected in: %s:%d, uid/euid: %u/%u\n", |
18084 |
++ NIPQUAD(current->signal->curr_ip), current->comm, task_pid_nr(current), current->uid, current->euid); |
18085 |
++ else |
18086 |
++ printk(KERN_ERR "PAX: refcount overflow detected in: %s:%d, uid/euid: %u/%u\n", |
18087 |
++ current->comm, task_pid_nr(current), current->uid, current->euid); |
18088 |
++ print_symbol(KERN_ERR "PAX: refcount overflow occured at: %s\n", instruction_pointer(regs)); |
18089 |
++ show_registers(regs); |
18090 |
++ force_sig_specific(SIGKILL, current); |
18091 |
++} |
18092 |
++#endif |
18093 |
++ |
18094 |
+ static int zap_process(struct task_struct *start) |
18095 |
+ { |
18096 |
+ struct task_struct *t; |
18097 |
+@@ -1759,6 +1967,10 @@ int do_coredump(long signr, int exit_cod |
18098 |
+ */ |
18099 |
+ clear_thread_flag(TIF_SIGPENDING); |
18100 |
+ |
18101 |
++ if (signr == SIGKILL || signr == SIGILL) |
18102 |
++ gr_handle_brute_attach(current); |
18103 |
++ gr_learn_resource(current, RLIMIT_CORE, binfmt->min_coredump, 1); |
18104 |
++ |
18105 |
+ /* |
18106 |
+ * lock_kernel() because format_corename() is controlled by sysctl, which |
18107 |
+ * uses lock_kernel() |
18108 |
+@@ -1779,6 +1991,8 @@ int do_coredump(long signr, int exit_cod |
18109 |
+ |
18110 |
+ if (ispipe) { |
18111 |
+ helper_argv = argv_split(GFP_KERNEL, corename+1, &helper_argc); |
18112 |
++ if (!helper_argv) |
18113 |
++ goto fail_unlock; |
18114 |
+ /* Terminate the string before the first option */ |
18115 |
+ delimit = strchr(corename, ' '); |
18116 |
+ if (delimit) |
18117 |
+diff -urNp linux-2.6.28.8/fs/ext2/balloc.c linux-2.6.28.8/fs/ext2/balloc.c |
18118 |
+--- linux-2.6.28.8/fs/ext2/balloc.c 2009-02-06 16:47:45.000000000 -0500 |
18119 |
++++ linux-2.6.28.8/fs/ext2/balloc.c 2009-02-21 09:37:49.000000000 -0500 |
18120 |
+@@ -1192,7 +1192,7 @@ static int ext2_has_free_blocks(struct e |
18121 |
+ |
18122 |
+ free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter); |
18123 |
+ root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count); |
18124 |
+- if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) && |
18125 |
++ if (free_blocks < root_blocks + 1 && !capable_nolog(CAP_SYS_RESOURCE) && |
18126 |
+ sbi->s_resuid != current->fsuid && |
18127 |
+ (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) { |
18128 |
+ return 0; |
18129 |
+diff -urNp linux-2.6.28.8/fs/ext3/balloc.c linux-2.6.28.8/fs/ext3/balloc.c |
18130 |
+--- linux-2.6.28.8/fs/ext3/balloc.c 2009-02-06 16:47:45.000000000 -0500 |
18131 |
++++ linux-2.6.28.8/fs/ext3/balloc.c 2009-02-21 09:37:49.000000000 -0500 |
18132 |
+@@ -1421,7 +1421,7 @@ static int ext3_has_free_blocks(struct e |
18133 |
+ |
18134 |
+ free_blocks = percpu_counter_read_positive(&sbi->s_freeblocks_counter); |
18135 |
+ root_blocks = le32_to_cpu(sbi->s_es->s_r_blocks_count); |
18136 |
+- if (free_blocks < root_blocks + 1 && !capable(CAP_SYS_RESOURCE) && |
18137 |
++ if (free_blocks < root_blocks + 1 && !capable_nolog(CAP_SYS_RESOURCE) && |
18138 |
+ sbi->s_resuid != current->fsuid && |
18139 |
+ (sbi->s_resgid == 0 || !in_group_p (sbi->s_resgid))) { |
18140 |
+ return 0; |
18141 |
+diff -urNp linux-2.6.28.8/fs/ext3/namei.c linux-2.6.28.8/fs/ext3/namei.c |
18142 |
+--- linux-2.6.28.8/fs/ext3/namei.c 2009-02-06 16:47:45.000000000 -0500 |
18143 |
++++ linux-2.6.28.8/fs/ext3/namei.c 2009-02-21 09:37:49.000000000 -0500 |
18144 |
+@@ -1156,9 +1156,9 @@ static struct ext3_dir_entry_2 *do_split |
18145 |
+ u32 hash2; |
18146 |
+ struct dx_map_entry *map; |
18147 |
+ char *data1 = (*bh)->b_data, *data2; |
18148 |
+- unsigned split, move, size, i; |
18149 |
++ unsigned split, move, size; |
18150 |
+ struct ext3_dir_entry_2 *de = NULL, *de2; |
18151 |
+- int err = 0; |
18152 |
++ int i, err = 0; |
18153 |
+ |
18154 |
+ bh2 = ext3_append (handle, dir, &newblock, &err); |
18155 |
+ if (!(bh2)) { |
18156 |
+diff -urNp linux-2.6.28.8/fs/ext3/xattr.c linux-2.6.28.8/fs/ext3/xattr.c |
18157 |
+--- linux-2.6.28.8/fs/ext3/xattr.c 2009-02-06 16:47:45.000000000 -0500 |
18158 |
++++ linux-2.6.28.8/fs/ext3/xattr.c 2009-02-21 09:37:49.000000000 -0500 |
18159 |
+@@ -89,8 +89,8 @@ |
18160 |
+ printk("\n"); \ |
18161 |
+ } while (0) |
18162 |
+ #else |
18163 |
+-# define ea_idebug(f...) |
18164 |
+-# define ea_bdebug(f...) |
18165 |
++# define ea_idebug(f...) do {} while (0) |
18166 |
++# define ea_bdebug(f...) do {} while (0) |
18167 |
+ #endif |
18168 |
+ |
18169 |
+ static void ext3_xattr_cache_insert(struct buffer_head *); |
18170 |
+diff -urNp linux-2.6.28.8/fs/ext4/balloc.c linux-2.6.28.8/fs/ext4/balloc.c |
18171 |
+--- linux-2.6.28.8/fs/ext4/balloc.c 2009-02-20 22:26:39.000000000 -0500 |
18172 |
++++ linux-2.6.28.8/fs/ext4/balloc.c 2009-02-21 09:37:49.000000000 -0500 |
18173 |
+@@ -576,7 +576,7 @@ int ext4_has_free_blocks(struct ext4_sb_ |
18174 |
+ /* Hm, nope. Are (enough) root reserved blocks available? */ |
18175 |
+ if (sbi->s_resuid == current->fsuid || |
18176 |
+ ((sbi->s_resgid != 0) && in_group_p(sbi->s_resgid)) || |
18177 |
+- capable(CAP_SYS_RESOURCE)) { |
18178 |
++ capable_nolog(CAP_SYS_RESOURCE)) { |
18179 |
+ if (free_blocks >= (nblocks + dirty_blocks)) |
18180 |
+ return 1; |
18181 |
+ } |
18182 |
+diff -urNp linux-2.6.28.8/fs/ext4/namei.c linux-2.6.28.8/fs/ext4/namei.c |
18183 |
+--- linux-2.6.28.8/fs/ext4/namei.c 2009-02-20 22:26:39.000000000 -0500 |
18184 |
++++ linux-2.6.28.8/fs/ext4/namei.c 2009-02-21 09:37:49.000000000 -0500 |
18185 |
+@@ -1171,9 +1171,9 @@ static struct ext4_dir_entry_2 *do_split |
18186 |
+ u32 hash2; |
18187 |
+ struct dx_map_entry *map; |
18188 |
+ char *data1 = (*bh)->b_data, *data2; |
18189 |
+- unsigned split, move, size, i; |
18190 |
++ unsigned split, move, size; |
18191 |
+ struct ext4_dir_entry_2 *de = NULL, *de2; |
18192 |
+- int err = 0; |
18193 |
++ int i, err = 0; |
18194 |
+ |
18195 |
+ bh2 = ext4_append (handle, dir, &newblock, &err); |
18196 |
+ if (!(bh2)) { |
18197 |
+diff -urNp linux-2.6.28.8/fs/fcntl.c linux-2.6.28.8/fs/fcntl.c |
18198 |
+--- linux-2.6.28.8/fs/fcntl.c 2009-02-06 16:47:45.000000000 -0500 |
18199 |
++++ linux-2.6.28.8/fs/fcntl.c 2009-02-21 09:37:49.000000000 -0500 |
18200 |
+@@ -266,6 +266,7 @@ static long do_fcntl(int fd, unsigned in |
18201 |
+ switch (cmd) { |
18202 |
+ case F_DUPFD: |
18203 |
+ case F_DUPFD_CLOEXEC: |
18204 |
++ gr_learn_resource(current, RLIMIT_NOFILE, arg, 0); |
18205 |
+ if (arg >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
18206 |
+ break; |
18207 |
+ err = alloc_fd(arg, cmd == F_DUPFD_CLOEXEC ? O_CLOEXEC : 0); |
18208 |
+@@ -411,7 +412,8 @@ static inline int sigio_perm(struct task |
18209 |
+ return (((fown->euid == 0) || |
18210 |
+ (fown->euid == p->suid) || (fown->euid == p->uid) || |
18211 |
+ (fown->uid == p->suid) || (fown->uid == p->uid)) && |
18212 |
+- !security_file_send_sigiotask(p, fown, sig)); |
18213 |
++ !security_file_send_sigiotask(p, fown, sig) && |
18214 |
++ !gr_check_protected_task(p) && !gr_pid_is_chrooted(p)); |
18215 |
+ } |
18216 |
+ |
18217 |
+ static void send_sigio_to_task(struct task_struct *p, |
18218 |
+diff -urNp linux-2.6.28.8/fs/file.c linux-2.6.28.8/fs/file.c |
18219 |
+--- linux-2.6.28.8/fs/file.c 2009-02-06 16:47:45.000000000 -0500 |
18220 |
++++ linux-2.6.28.8/fs/file.c 2009-02-21 09:37:49.000000000 -0500 |
18221 |
+@@ -13,6 +13,7 @@ |
18222 |
+ #include <linux/slab.h> |
18223 |
+ #include <linux/vmalloc.h> |
18224 |
+ #include <linux/file.h> |
18225 |
++#include <linux/security.h> |
18226 |
+ #include <linux/fdtable.h> |
18227 |
+ #include <linux/bitops.h> |
18228 |
+ #include <linux/interrupt.h> |
18229 |
+@@ -256,6 +257,8 @@ int expand_files(struct files_struct *fi |
18230 |
+ * N.B. For clone tasks sharing a files structure, this test |
18231 |
+ * will limit the total number of files that can be opened. |
18232 |
+ */ |
18233 |
++ |
18234 |
++ gr_learn_resource(current, RLIMIT_NOFILE, nr, 0); |
18235 |
+ if (nr >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
18236 |
+ return -EMFILE; |
18237 |
+ |
18238 |
+diff -urNp linux-2.6.28.8/fs/fuse/control.c linux-2.6.28.8/fs/fuse/control.c |
18239 |
+--- linux-2.6.28.8/fs/fuse/control.c 2009-02-06 16:47:45.000000000 -0500 |
18240 |
++++ linux-2.6.28.8/fs/fuse/control.c 2009-02-21 09:37:49.000000000 -0500 |
18241 |
+@@ -159,7 +159,7 @@ void fuse_ctl_remove_conn(struct fuse_co |
18242 |
+ |
18243 |
+ static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent) |
18244 |
+ { |
18245 |
+- struct tree_descr empty_descr = {""}; |
18246 |
++ struct tree_descr empty_descr = {"", NULL, 0}; |
18247 |
+ struct fuse_conn *fc; |
18248 |
+ int err; |
18249 |
+ |
18250 |
+diff -urNp linux-2.6.28.8/fs/fuse/dir.c linux-2.6.28.8/fs/fuse/dir.c |
18251 |
+--- linux-2.6.28.8/fs/fuse/dir.c 2009-02-06 16:47:45.000000000 -0500 |
18252 |
++++ linux-2.6.28.8/fs/fuse/dir.c 2009-02-21 09:37:49.000000000 -0500 |
18253 |
+@@ -1072,7 +1072,7 @@ static char *read_link(struct dentry *de |
18254 |
+ return link; |
18255 |
+ } |
18256 |
+ |
18257 |
+-static void free_link(char *link) |
18258 |
++static void free_link(const char *link) |
18259 |
+ { |
18260 |
+ if (!IS_ERR(link)) |
18261 |
+ free_page((unsigned long) link); |
18262 |
+diff -urNp linux-2.6.28.8/fs/hfs/inode.c linux-2.6.28.8/fs/hfs/inode.c |
18263 |
+--- linux-2.6.28.8/fs/hfs/inode.c 2009-02-06 16:47:45.000000000 -0500 |
18264 |
++++ linux-2.6.28.8/fs/hfs/inode.c 2009-02-21 09:37:49.000000000 -0500 |
18265 |
+@@ -419,7 +419,7 @@ int hfs_write_inode(struct inode *inode, |
18266 |
+ |
18267 |
+ if (S_ISDIR(main_inode->i_mode)) { |
18268 |
+ if (fd.entrylength < sizeof(struct hfs_cat_dir)) |
18269 |
+- /* panic? */; |
18270 |
++ {/* panic? */} |
18271 |
+ hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, |
18272 |
+ sizeof(struct hfs_cat_dir)); |
18273 |
+ if (rec.type != HFS_CDR_DIR || |
18274 |
+@@ -440,7 +440,7 @@ int hfs_write_inode(struct inode *inode, |
18275 |
+ sizeof(struct hfs_cat_file)); |
18276 |
+ } else { |
18277 |
+ if (fd.entrylength < sizeof(struct hfs_cat_file)) |
18278 |
+- /* panic? */; |
18279 |
++ {/* panic? */} |
18280 |
+ hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, |
18281 |
+ sizeof(struct hfs_cat_file)); |
18282 |
+ if (rec.type != HFS_CDR_FIL || |
18283 |
+diff -urNp linux-2.6.28.8/fs/hfsplus/inode.c linux-2.6.28.8/fs/hfsplus/inode.c |
18284 |
+--- linux-2.6.28.8/fs/hfsplus/inode.c 2009-02-06 16:47:45.000000000 -0500 |
18285 |
++++ linux-2.6.28.8/fs/hfsplus/inode.c 2009-02-21 09:37:49.000000000 -0500 |
18286 |
+@@ -406,7 +406,7 @@ int hfsplus_cat_read_inode(struct inode |
18287 |
+ struct hfsplus_cat_folder *folder = &entry.folder; |
18288 |
+ |
18289 |
+ if (fd->entrylength < sizeof(struct hfsplus_cat_folder)) |
18290 |
+- /* panic? */; |
18291 |
++ {/* panic? */} |
18292 |
+ hfs_bnode_read(fd->bnode, &entry, fd->entryoffset, |
18293 |
+ sizeof(struct hfsplus_cat_folder)); |
18294 |
+ hfsplus_get_perms(inode, &folder->permissions, 1); |
18295 |
+@@ -423,7 +423,7 @@ int hfsplus_cat_read_inode(struct inode |
18296 |
+ struct hfsplus_cat_file *file = &entry.file; |
18297 |
+ |
18298 |
+ if (fd->entrylength < sizeof(struct hfsplus_cat_file)) |
18299 |
+- /* panic? */; |
18300 |
++ {/* panic? */} |
18301 |
+ hfs_bnode_read(fd->bnode, &entry, fd->entryoffset, |
18302 |
+ sizeof(struct hfsplus_cat_file)); |
18303 |
+ |
18304 |
+@@ -479,7 +479,7 @@ int hfsplus_cat_write_inode(struct inode |
18305 |
+ struct hfsplus_cat_folder *folder = &entry.folder; |
18306 |
+ |
18307 |
+ if (fd.entrylength < sizeof(struct hfsplus_cat_folder)) |
18308 |
+- /* panic? */; |
18309 |
++ {/* panic? */} |
18310 |
+ hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, |
18311 |
+ sizeof(struct hfsplus_cat_folder)); |
18312 |
+ /* simple node checks? */ |
18313 |
+@@ -501,7 +501,7 @@ int hfsplus_cat_write_inode(struct inode |
18314 |
+ struct hfsplus_cat_file *file = &entry.file; |
18315 |
+ |
18316 |
+ if (fd.entrylength < sizeof(struct hfsplus_cat_file)) |
18317 |
+- /* panic? */; |
18318 |
++ {/* panic? */} |
18319 |
+ hfs_bnode_read(fd.bnode, &entry, fd.entryoffset, |
18320 |
+ sizeof(struct hfsplus_cat_file)); |
18321 |
+ hfsplus_inode_write_fork(inode, &file->data_fork); |
18322 |
+diff -urNp linux-2.6.28.8/fs/jffs2/debug.h linux-2.6.28.8/fs/jffs2/debug.h |
18323 |
+--- linux-2.6.28.8/fs/jffs2/debug.h 2009-02-06 16:47:45.000000000 -0500 |
18324 |
++++ linux-2.6.28.8/fs/jffs2/debug.h 2009-02-21 09:37:49.000000000 -0500 |
18325 |
+@@ -52,13 +52,13 @@ |
18326 |
+ #if CONFIG_JFFS2_FS_DEBUG > 0 |
18327 |
+ #define D1(x) x |
18328 |
+ #else |
18329 |
+-#define D1(x) |
18330 |
++#define D1(x) do {} while (0); |
18331 |
+ #endif |
18332 |
+ |
18333 |
+ #if CONFIG_JFFS2_FS_DEBUG > 1 |
18334 |
+ #define D2(x) x |
18335 |
+ #else |
18336 |
+-#define D2(x) |
18337 |
++#define D2(x) do {} while (0); |
18338 |
+ #endif |
18339 |
+ |
18340 |
+ /* The prefixes of JFFS2 messages */ |
18341 |
+@@ -114,73 +114,73 @@ |
18342 |
+ #ifdef JFFS2_DBG_READINODE_MESSAGES |
18343 |
+ #define dbg_readinode(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18344 |
+ #else |
18345 |
+-#define dbg_readinode(fmt, ...) |
18346 |
++#define dbg_readinode(fmt, ...) do {} while (0) |
18347 |
+ #endif |
18348 |
+ #ifdef JFFS2_DBG_READINODE2_MESSAGES |
18349 |
+ #define dbg_readinode2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18350 |
+ #else |
18351 |
+-#define dbg_readinode2(fmt, ...) |
18352 |
++#define dbg_readinode2(fmt, ...) do {} while (0) |
18353 |
+ #endif |
18354 |
+ |
18355 |
+ /* Fragtree build debugging messages */ |
18356 |
+ #ifdef JFFS2_DBG_FRAGTREE_MESSAGES |
18357 |
+ #define dbg_fragtree(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18358 |
+ #else |
18359 |
+-#define dbg_fragtree(fmt, ...) |
18360 |
++#define dbg_fragtree(fmt, ...) do {} while (0) |
18361 |
+ #endif |
18362 |
+ #ifdef JFFS2_DBG_FRAGTREE2_MESSAGES |
18363 |
+ #define dbg_fragtree2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18364 |
+ #else |
18365 |
+-#define dbg_fragtree2(fmt, ...) |
18366 |
++#define dbg_fragtree2(fmt, ...) do {} while (0) |
18367 |
+ #endif |
18368 |
+ |
18369 |
+ /* Directory entry list manilulation debugging messages */ |
18370 |
+ #ifdef JFFS2_DBG_DENTLIST_MESSAGES |
18371 |
+ #define dbg_dentlist(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18372 |
+ #else |
18373 |
+-#define dbg_dentlist(fmt, ...) |
18374 |
++#define dbg_dentlist(fmt, ...) do {} while (0) |
18375 |
+ #endif |
18376 |
+ |
18377 |
+ /* Print the messages about manipulating node_refs */ |
18378 |
+ #ifdef JFFS2_DBG_NODEREF_MESSAGES |
18379 |
+ #define dbg_noderef(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18380 |
+ #else |
18381 |
+-#define dbg_noderef(fmt, ...) |
18382 |
++#define dbg_noderef(fmt, ...) do {} while (0) |
18383 |
+ #endif |
18384 |
+ |
18385 |
+ /* Manipulations with the list of inodes (JFFS2 inocache) */ |
18386 |
+ #ifdef JFFS2_DBG_INOCACHE_MESSAGES |
18387 |
+ #define dbg_inocache(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18388 |
+ #else |
18389 |
+-#define dbg_inocache(fmt, ...) |
18390 |
++#define dbg_inocache(fmt, ...) do {} while (0) |
18391 |
+ #endif |
18392 |
+ |
18393 |
+ /* Summary debugging messages */ |
18394 |
+ #ifdef JFFS2_DBG_SUMMARY_MESSAGES |
18395 |
+ #define dbg_summary(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18396 |
+ #else |
18397 |
+-#define dbg_summary(fmt, ...) |
18398 |
++#define dbg_summary(fmt, ...) do {} while (0) |
18399 |
+ #endif |
18400 |
+ |
18401 |
+ /* File system build messages */ |
18402 |
+ #ifdef JFFS2_DBG_FSBUILD_MESSAGES |
18403 |
+ #define dbg_fsbuild(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18404 |
+ #else |
18405 |
+-#define dbg_fsbuild(fmt, ...) |
18406 |
++#define dbg_fsbuild(fmt, ...) do {} while (0) |
18407 |
+ #endif |
18408 |
+ |
18409 |
+ /* Watch the object allocations */ |
18410 |
+ #ifdef JFFS2_DBG_MEMALLOC_MESSAGES |
18411 |
+ #define dbg_memalloc(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18412 |
+ #else |
18413 |
+-#define dbg_memalloc(fmt, ...) |
18414 |
++#define dbg_memalloc(fmt, ...) do {} while (0) |
18415 |
+ #endif |
18416 |
+ |
18417 |
+ /* Watch the XATTR subsystem */ |
18418 |
+ #ifdef JFFS2_DBG_XATTR_MESSAGES |
18419 |
+ #define dbg_xattr(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) |
18420 |
+ #else |
18421 |
+-#define dbg_xattr(fmt, ...) |
18422 |
++#define dbg_xattr(fmt, ...) do {} while (0) |
18423 |
+ #endif |
18424 |
+ |
18425 |
+ /* "Sanity" checks */ |
18426 |
+diff -urNp linux-2.6.28.8/fs/jffs2/erase.c linux-2.6.28.8/fs/jffs2/erase.c |
18427 |
+--- linux-2.6.28.8/fs/jffs2/erase.c 2009-02-06 16:47:45.000000000 -0500 |
18428 |
++++ linux-2.6.28.8/fs/jffs2/erase.c 2009-02-21 09:37:49.000000000 -0500 |
18429 |
+@@ -431,7 +431,8 @@ static void jffs2_mark_erased_block(stru |
18430 |
+ struct jffs2_unknown_node marker = { |
18431 |
+ .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), |
18432 |
+ .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), |
18433 |
+- .totlen = cpu_to_je32(c->cleanmarker_size) |
18434 |
++ .totlen = cpu_to_je32(c->cleanmarker_size), |
18435 |
++ .hdr_crc = cpu_to_je32(0) |
18436 |
+ }; |
18437 |
+ |
18438 |
+ jffs2_prealloc_raw_node_refs(c, jeb, 1); |
18439 |
+diff -urNp linux-2.6.28.8/fs/jffs2/summary.h linux-2.6.28.8/fs/jffs2/summary.h |
18440 |
+--- linux-2.6.28.8/fs/jffs2/summary.h 2009-02-06 16:47:45.000000000 -0500 |
18441 |
++++ linux-2.6.28.8/fs/jffs2/summary.h 2009-02-21 09:37:49.000000000 -0500 |
18442 |
+@@ -194,18 +194,18 @@ int jffs2_sum_scan_sumnode(struct jffs2_ |
18443 |
+ |
18444 |
+ #define jffs2_sum_active() (0) |
18445 |
+ #define jffs2_sum_init(a) (0) |
18446 |
+-#define jffs2_sum_exit(a) |
18447 |
+-#define jffs2_sum_disable_collecting(a) |
18448 |
++#define jffs2_sum_exit(a) do {} while (0) |
18449 |
++#define jffs2_sum_disable_collecting(a) do {} while (0) |
18450 |
+ #define jffs2_sum_is_disabled(a) (0) |
18451 |
+-#define jffs2_sum_reset_collected(a) |
18452 |
++#define jffs2_sum_reset_collected(a) do {} while (0) |
18453 |
+ #define jffs2_sum_add_kvec(a,b,c,d) (0) |
18454 |
+-#define jffs2_sum_move_collected(a,b) |
18455 |
++#define jffs2_sum_move_collected(a,b) do {} while (0) |
18456 |
+ #define jffs2_sum_write_sumnode(a) (0) |
18457 |
+-#define jffs2_sum_add_padding_mem(a,b) |
18458 |
+-#define jffs2_sum_add_inode_mem(a,b,c) |
18459 |
+-#define jffs2_sum_add_dirent_mem(a,b,c) |
18460 |
+-#define jffs2_sum_add_xattr_mem(a,b,c) |
18461 |
+-#define jffs2_sum_add_xref_mem(a,b,c) |
18462 |
++#define jffs2_sum_add_padding_mem(a,b) do {} while (0) |
18463 |
++#define jffs2_sum_add_inode_mem(a,b,c) do {} while (0) |
18464 |
++#define jffs2_sum_add_dirent_mem(a,b,c) do {} while (0) |
18465 |
++#define jffs2_sum_add_xattr_mem(a,b,c) do {} while (0) |
18466 |
++#define jffs2_sum_add_xref_mem(a,b,c) do {} while (0) |
18467 |
+ #define jffs2_sum_scan_sumnode(a,b,c,d,e) (0) |
18468 |
+ |
18469 |
+ #endif /* CONFIG_JFFS2_SUMMARY */ |
18470 |
+diff -urNp linux-2.6.28.8/fs/jffs2/wbuf.c linux-2.6.28.8/fs/jffs2/wbuf.c |
18471 |
+--- linux-2.6.28.8/fs/jffs2/wbuf.c 2009-02-06 16:47:45.000000000 -0500 |
18472 |
++++ linux-2.6.28.8/fs/jffs2/wbuf.c 2009-02-21 09:37:49.000000000 -0500 |
18473 |
+@@ -1012,7 +1012,8 @@ static const struct jffs2_unknown_node o |
18474 |
+ { |
18475 |
+ .magic = constant_cpu_to_je16(JFFS2_MAGIC_BITMASK), |
18476 |
+ .nodetype = constant_cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), |
18477 |
+- .totlen = constant_cpu_to_je32(8) |
18478 |
++ .totlen = constant_cpu_to_je32(8), |
18479 |
++ .hdr_crc = constant_cpu_to_je32(0) |
18480 |
+ }; |
18481 |
+ |
18482 |
+ /* |
18483 |
+diff -urNp linux-2.6.28.8/fs/locks.c linux-2.6.28.8/fs/locks.c |
18484 |
+--- linux-2.6.28.8/fs/locks.c 2009-02-06 16:47:45.000000000 -0500 |
18485 |
++++ linux-2.6.28.8/fs/locks.c 2009-02-21 09:37:49.000000000 -0500 |
18486 |
+@@ -2006,16 +2006,16 @@ void locks_remove_flock(struct file *fil |
18487 |
+ return; |
18488 |
+ |
18489 |
+ if (filp->f_op && filp->f_op->flock) { |
18490 |
+- struct file_lock fl = { |
18491 |
++ struct file_lock flock = { |
18492 |
+ .fl_pid = current->tgid, |
18493 |
+ .fl_file = filp, |
18494 |
+ .fl_flags = FL_FLOCK, |
18495 |
+ .fl_type = F_UNLCK, |
18496 |
+ .fl_end = OFFSET_MAX, |
18497 |
+ }; |
18498 |
+- filp->f_op->flock(filp, F_SETLKW, &fl); |
18499 |
+- if (fl.fl_ops && fl.fl_ops->fl_release_private) |
18500 |
+- fl.fl_ops->fl_release_private(&fl); |
18501 |
++ filp->f_op->flock(filp, F_SETLKW, &flock); |
18502 |
++ if (flock.fl_ops && flock.fl_ops->fl_release_private) |
18503 |
++ flock.fl_ops->fl_release_private(&flock); |
18504 |
+ } |
18505 |
+ |
18506 |
+ lock_kernel(); |
18507 |
+diff -urNp linux-2.6.28.8/fs/namei.c linux-2.6.28.8/fs/namei.c |
18508 |
+--- linux-2.6.28.8/fs/namei.c 2009-02-06 16:47:45.000000000 -0500 |
18509 |
++++ linux-2.6.28.8/fs/namei.c 2009-03-07 04:29:14.000000000 -0500 |
18510 |
+@@ -633,7 +633,7 @@ static __always_inline int __do_follow_l |
18511 |
+ cookie = dentry->d_inode->i_op->follow_link(dentry, nd); |
18512 |
+ error = PTR_ERR(cookie); |
18513 |
+ if (!IS_ERR(cookie)) { |
18514 |
+- char *s = nd_get_link(nd); |
18515 |
++ const char *s = nd_get_link(nd); |
18516 |
+ error = 0; |
18517 |
+ if (s) |
18518 |
+ error = __vfs_follow_link(nd, s); |
18519 |
+@@ -664,6 +664,13 @@ static inline int do_follow_link(struct |
18520 |
+ err = security_inode_follow_link(path->dentry, nd); |
18521 |
+ if (err) |
18522 |
+ goto loop; |
18523 |
++ |
18524 |
++ if (gr_handle_follow_link(path->dentry->d_parent->d_inode, |
18525 |
++ path->dentry->d_inode, path->dentry, nd->path.mnt)) { |
18526 |
++ err = -EACCES; |
18527 |
++ goto loop; |
18528 |
++ } |
18529 |
++ |
18530 |
+ current->link_count++; |
18531 |
+ current->total_link_count++; |
18532 |
+ nd->depth++; |
18533 |
+@@ -1012,11 +1019,18 @@ return_reval: |
18534 |
+ break; |
18535 |
+ } |
18536 |
+ return_base: |
18537 |
++ if (!gr_acl_handle_hidden_file(nd->path.dentry, nd->path.mnt)) { |
18538 |
++ path_put(&nd->path); |
18539 |
++ return -ENOENT; |
18540 |
++ } |
18541 |
+ return 0; |
18542 |
+ out_dput: |
18543 |
+ path_put_conditional(&next, nd); |
18544 |
+ break; |
18545 |
+ } |
18546 |
++ if (!gr_acl_handle_hidden_file(nd->path.dentry, nd->path.mnt)) |
18547 |
++ err = -ENOENT; |
18548 |
++ |
18549 |
+ path_put(&nd->path); |
18550 |
+ return_err: |
18551 |
+ return err; |
18552 |
+@@ -1582,9 +1596,17 @@ static int __open_namei_create(struct na |
18553 |
+ int error; |
18554 |
+ struct dentry *dir = nd->path.dentry; |
18555 |
+ |
18556 |
++ if (!gr_acl_handle_creat(path->dentry, nd->path.dentry, nd->path.mnt, flag, mode)) { |
18557 |
++ error = -EACCES; |
18558 |
++ goto out_unlock_dput; |
18559 |
++ } |
18560 |
++ |
18561 |
+ if (!IS_POSIXACL(dir->d_inode)) |
18562 |
+ mode &= ~current->fs->umask; |
18563 |
+ error = vfs_create(dir->d_inode, path->dentry, mode, nd); |
18564 |
++ if (!error) |
18565 |
++ gr_handle_create(path->dentry, nd->path.mnt); |
18566 |
++out_unlock_dput: |
18567 |
+ mutex_unlock(&dir->d_inode->i_mutex); |
18568 |
+ dput(nd->path.dentry); |
18569 |
+ nd->path.dentry = path->dentry; |
18570 |
+@@ -1665,6 +1687,17 @@ struct file *do_filp_open(int dfd, const |
18571 |
+ &nd, flag); |
18572 |
+ if (error) |
18573 |
+ return ERR_PTR(error); |
18574 |
++ |
18575 |
++ if (gr_handle_rawio(nd.path.dentry->d_inode)) { |
18576 |
++ error = -EPERM; |
18577 |
++ goto exit; |
18578 |
++ } |
18579 |
++ |
18580 |
++ if (!gr_acl_handle_open(nd.path.dentry, nd.path.mnt, flag)) { |
18581 |
++ error = -EACCES; |
18582 |
++ goto exit; |
18583 |
++ } |
18584 |
++ |
18585 |
+ goto ok; |
18586 |
+ } |
18587 |
+ |
18588 |
+@@ -1737,6 +1770,20 @@ do_last: |
18589 |
+ /* |
18590 |
+ * It already exists. |
18591 |
+ */ |
18592 |
++ |
18593 |
++ if (gr_handle_rawio(path.dentry->d_inode)) { |
18594 |
++ error = -EPERM; |
18595 |
++ goto exit_mutex_unlock; |
18596 |
++ } |
18597 |
++ if (!gr_acl_handle_open(path.dentry, nd.path.mnt, flag)) { |
18598 |
++ error = -EACCES; |
18599 |
++ goto exit_mutex_unlock; |
18600 |
++ } |
18601 |
++ if (gr_handle_fifo(path.dentry, nd.path.mnt, dir, flag, acc_mode)) { |
18602 |
++ error = -EACCES; |
18603 |
++ goto exit_mutex_unlock; |
18604 |
++ } |
18605 |
++ |
18606 |
+ mutex_unlock(&dir->d_inode->i_mutex); |
18607 |
+ audit_inode(pathname, path.dentry); |
18608 |
+ |
18609 |
+@@ -1822,6 +1869,13 @@ do_link: |
18610 |
+ error = security_inode_follow_link(path.dentry, &nd); |
18611 |
+ if (error) |
18612 |
+ goto exit_dput; |
18613 |
++ |
18614 |
++ if (gr_handle_follow_link(path.dentry->d_parent->d_inode, path.dentry->d_inode, |
18615 |
++ path.dentry, nd.path.mnt)) { |
18616 |
++ error = -EACCES; |
18617 |
++ goto exit_dput; |
18618 |
++ } |
18619 |
++ |
18620 |
+ error = __do_follow_link(&path, &nd); |
18621 |
+ if (error) { |
18622 |
+ /* Does someone understand code flow here? Or it is only |
18623 |
+@@ -1994,6 +2048,17 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const |
18624 |
+ error = may_mknod(mode); |
18625 |
+ if (error) |
18626 |
+ goto out_dput; |
18627 |
++ |
18628 |
++ if (gr_handle_chroot_mknod(dentry, nd.path.mnt, mode)) { |
18629 |
++ error = -EPERM; |
18630 |
++ goto out_dput; |
18631 |
++ } |
18632 |
++ |
18633 |
++ if (!gr_acl_handle_mknod(dentry, nd.path.dentry, nd.path.mnt, mode)) { |
18634 |
++ error = -EACCES; |
18635 |
++ goto out_dput; |
18636 |
++ } |
18637 |
++ |
18638 |
+ error = mnt_want_write(nd.path.mnt); |
18639 |
+ if (error) |
18640 |
+ goto out_dput; |
18641 |
+@@ -2010,6 +2075,9 @@ SYSCALL_DEFINE4(mknodat, int, dfd, const |
18642 |
+ break; |
18643 |
+ } |
18644 |
+ mnt_drop_write(nd.path.mnt); |
18645 |
++ |
18646 |
++ if (!error) |
18647 |
++ gr_handle_create(dentry, nd.path.mnt); |
18648 |
+ out_dput: |
18649 |
+ dput(dentry); |
18650 |
+ out_unlock: |
18651 |
+@@ -2063,6 +2131,11 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const |
18652 |
+ if (IS_ERR(dentry)) |
18653 |
+ goto out_unlock; |
18654 |
+ |
18655 |
++ if (!gr_acl_handle_mkdir(dentry, nd.path.dentry, nd.path.mnt)) { |
18656 |
++ error = -EACCES; |
18657 |
++ goto out_dput; |
18658 |
++ } |
18659 |
++ |
18660 |
+ if (!IS_POSIXACL(nd.path.dentry->d_inode)) |
18661 |
+ mode &= ~current->fs->umask; |
18662 |
+ error = mnt_want_write(nd.path.mnt); |
18663 |
+@@ -2070,6 +2143,10 @@ SYSCALL_DEFINE3(mkdirat, int, dfd, const |
18664 |
+ goto out_dput; |
18665 |
+ error = vfs_mkdir(nd.path.dentry->d_inode, dentry, mode); |
18666 |
+ mnt_drop_write(nd.path.mnt); |
18667 |
++ |
18668 |
++ if (!error) |
18669 |
++ gr_handle_create(dentry, nd.path.mnt); |
18670 |
++ |
18671 |
+ out_dput: |
18672 |
+ dput(dentry); |
18673 |
+ out_unlock: |
18674 |
+@@ -2151,6 +2228,8 @@ static long do_rmdir(int dfd, const char |
18675 |
+ char * name; |
18676 |
+ struct dentry *dentry; |
18677 |
+ struct nameidata nd; |
18678 |
++ ino_t saved_ino = 0; |
18679 |
++ dev_t saved_dev = 0; |
18680 |
+ |
18681 |
+ error = user_path_parent(dfd, pathname, &nd, &name); |
18682 |
+ if (error) |
18683 |
+@@ -2175,11 +2254,26 @@ static long do_rmdir(int dfd, const char |
18684 |
+ error = PTR_ERR(dentry); |
18685 |
+ if (IS_ERR(dentry)) |
18686 |
+ goto exit2; |
18687 |
++ |
18688 |
++ if (dentry->d_inode != NULL) { |
18689 |
++ if (dentry->d_inode->i_nlink <= 1) { |
18690 |
++ saved_ino = dentry->d_inode->i_ino; |
18691 |
++ saved_dev = dentry->d_inode->i_sb->s_dev; |
18692 |
++ } |
18693 |
++ |
18694 |
++ if (!gr_acl_handle_rmdir(dentry, nd.path.mnt)) { |
18695 |
++ error = -EACCES; |
18696 |
++ goto exit3; |
18697 |
++ } |
18698 |
++ } |
18699 |
++ |
18700 |
+ error = mnt_want_write(nd.path.mnt); |
18701 |
+ if (error) |
18702 |
+ goto exit3; |
18703 |
+ error = vfs_rmdir(nd.path.dentry->d_inode, dentry); |
18704 |
+ mnt_drop_write(nd.path.mnt); |
18705 |
++ if (!error && (saved_dev || saved_ino)) |
18706 |
++ gr_handle_delete(saved_ino, saved_dev); |
18707 |
+ exit3: |
18708 |
+ dput(dentry); |
18709 |
+ exit2: |
18710 |
+@@ -2239,6 +2333,8 @@ static long do_unlinkat(int dfd, const c |
18711 |
+ struct dentry *dentry; |
18712 |
+ struct nameidata nd; |
18713 |
+ struct inode *inode = NULL; |
18714 |
++ ino_t saved_ino = 0; |
18715 |
++ dev_t saved_dev = 0; |
18716 |
+ |
18717 |
+ error = user_path_parent(dfd, pathname, &nd, &name); |
18718 |
+ if (error) |
18719 |
+@@ -2258,12 +2354,25 @@ static long do_unlinkat(int dfd, const c |
18720 |
+ if (nd.last.name[nd.last.len]) |
18721 |
+ goto slashes; |
18722 |
+ inode = dentry->d_inode; |
18723 |
+- if (inode) |
18724 |
++ if (inode) { |
18725 |
++ if (inode->i_nlink <= 1) { |
18726 |
++ saved_ino = inode->i_ino; |
18727 |
++ saved_dev = inode->i_sb->s_dev; |
18728 |
++ } |
18729 |
++ |
18730 |
+ atomic_inc(&inode->i_count); |
18731 |
++ |
18732 |
++ if (!gr_acl_handle_unlink(dentry, nd.path.mnt)) { |
18733 |
++ error = -EACCES; |
18734 |
++ goto exit2; |
18735 |
++ } |
18736 |
++ } |
18737 |
+ error = mnt_want_write(nd.path.mnt); |
18738 |
+ if (error) |
18739 |
+ goto exit2; |
18740 |
+ error = vfs_unlink(nd.path.dentry->d_inode, dentry); |
18741 |
++ if (!error && (saved_ino || saved_dev)) |
18742 |
++ gr_handle_delete(saved_ino, saved_dev); |
18743 |
+ mnt_drop_write(nd.path.mnt); |
18744 |
+ exit2: |
18745 |
+ dput(dentry); |
18746 |
+@@ -2341,10 +2450,17 @@ SYSCALL_DEFINE3(symlinkat, const char __ |
18747 |
+ if (IS_ERR(dentry)) |
18748 |
+ goto out_unlock; |
18749 |
+ |
18750 |
++ if (!gr_acl_handle_symlink(dentry, nd.path.dentry, nd.path.mnt, from)) { |
18751 |
++ error = -EACCES; |
18752 |
++ goto out_dput; |
18753 |
++ } |
18754 |
++ |
18755 |
+ error = mnt_want_write(nd.path.mnt); |
18756 |
+ if (error) |
18757 |
+ goto out_dput; |
18758 |
+ error = vfs_symlink(nd.path.dentry->d_inode, dentry, from); |
18759 |
++ if (!error) |
18760 |
++ gr_handle_create(dentry, nd.path.mnt); |
18761 |
+ mnt_drop_write(nd.path.mnt); |
18762 |
+ out_dput: |
18763 |
+ dput(dentry); |
18764 |
+@@ -2437,10 +2553,26 @@ SYSCALL_DEFINE5(linkat, int, olddfd, con |
18765 |
+ error = PTR_ERR(new_dentry); |
18766 |
+ if (IS_ERR(new_dentry)) |
18767 |
+ goto out_unlock; |
18768 |
++ |
18769 |
++ if (gr_handle_hardlink(old_path.dentry, old_path.mnt, |
18770 |
++ old_path.dentry->d_inode, |
18771 |
++ old_path.dentry->d_inode->i_mode, to)) { |
18772 |
++ error = -EACCES; |
18773 |
++ goto out_dput; |
18774 |
++ } |
18775 |
++ |
18776 |
++ if (!gr_acl_handle_link(new_dentry, nd.path.dentry, nd.path.mnt, |
18777 |
++ old_path.dentry, old_path.mnt, to)) { |
18778 |
++ error = -EACCES; |
18779 |
++ goto out_dput; |
18780 |
++ } |
18781 |
++ |
18782 |
+ error = mnt_want_write(nd.path.mnt); |
18783 |
+ if (error) |
18784 |
+ goto out_dput; |
18785 |
+ error = vfs_link(old_path.dentry, nd.path.dentry->d_inode, new_dentry); |
18786 |
++ if (!error) |
18787 |
++ gr_handle_create(new_dentry, nd.path.mnt); |
18788 |
+ mnt_drop_write(nd.path.mnt); |
18789 |
+ out_dput: |
18790 |
+ dput(new_dentry); |
18791 |
+@@ -2673,11 +2805,21 @@ SYSCALL_DEFINE4(renameat, int, olddfd, c |
18792 |
+ if (new_dentry == trap) |
18793 |
+ goto exit5; |
18794 |
+ |
18795 |
++ error = gr_acl_handle_rename(new_dentry, new_dir, newnd.path.mnt, |
18796 |
++ old_dentry, old_dir->d_inode, oldnd.path.mnt, |
18797 |
++ to); |
18798 |
++ if (error) |
18799 |
++ goto exit5; |
18800 |
++ |
18801 |
+ error = mnt_want_write(oldnd.path.mnt); |
18802 |
+ if (error) |
18803 |
+ goto exit5; |
18804 |
+ error = vfs_rename(old_dir->d_inode, old_dentry, |
18805 |
+ new_dir->d_inode, new_dentry); |
18806 |
++ if (!error) |
18807 |
++ gr_handle_rename(old_dir->d_inode, new_dir->d_inode, old_dentry, |
18808 |
++ new_dentry, oldnd.path.mnt, new_dentry->d_inode ? 1 : 0); |
18809 |
++ |
18810 |
+ mnt_drop_write(oldnd.path.mnt); |
18811 |
+ exit5: |
18812 |
+ dput(new_dentry); |
18813 |
+diff -urNp linux-2.6.28.8/fs/namespace.c linux-2.6.28.8/fs/namespace.c |
18814 |
+--- linux-2.6.28.8/fs/namespace.c 2009-02-06 16:47:45.000000000 -0500 |
18815 |
++++ linux-2.6.28.8/fs/namespace.c 2009-02-21 09:37:49.000000000 -0500 |
18816 |
+@@ -1094,6 +1094,8 @@ static int do_umount(struct vfsmount *mn |
18817 |
+ lock_kernel(); |
18818 |
+ retval = do_remount_sb(sb, MS_RDONLY, NULL, 0); |
18819 |
+ unlock_kernel(); |
18820 |
++ |
18821 |
++ gr_log_remount(mnt->mnt_devname, retval); |
18822 |
+ } |
18823 |
+ up_write(&sb->s_umount); |
18824 |
+ return retval; |
18825 |
+@@ -1117,6 +1119,9 @@ static int do_umount(struct vfsmount *mn |
18826 |
+ security_sb_umount_busy(mnt); |
18827 |
+ up_write(&namespace_sem); |
18828 |
+ release_mounts(&umount_list); |
18829 |
++ |
18830 |
++ gr_log_unmount(mnt->mnt_devname, retval); |
18831 |
++ |
18832 |
+ return retval; |
18833 |
+ } |
18834 |
+ |
18835 |
+@@ -1946,6 +1951,11 @@ long do_mount(char *dev_name, char *dir_ |
18836 |
+ if (retval) |
18837 |
+ goto dput_out; |
18838 |
+ |
18839 |
++ if (gr_handle_chroot_mount(path.dentry, path.mnt, dev_name)) { |
18840 |
++ retval = -EPERM; |
18841 |
++ goto dput_out; |
18842 |
++ } |
18843 |
++ |
18844 |
+ if (flags & MS_REMOUNT) |
18845 |
+ retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags, |
18846 |
+ data_page); |
18847 |
+@@ -1960,6 +1970,9 @@ long do_mount(char *dev_name, char *dir_ |
18848 |
+ dev_name, data_page); |
18849 |
+ dput_out: |
18850 |
+ path_put(&path); |
18851 |
++ |
18852 |
++ gr_log_mount(dev_name, dir_name, retval); |
18853 |
++ |
18854 |
+ return retval; |
18855 |
+ } |
18856 |
+ |
18857 |
+@@ -2071,6 +2084,9 @@ SYSCALL_DEFINE5(mount, char __user *, de |
18858 |
+ if (retval < 0) |
18859 |
+ goto out3; |
18860 |
+ |
18861 |
++ if (gr_handle_chroot_pivot()) |
18862 |
++ return -EPERM; |
18863 |
++ |
18864 |
+ lock_kernel(); |
18865 |
+ retval = do_mount((char *)dev_page, dir_page, (char *)type_page, |
18866 |
+ flags, (void *)data_page); |
18867 |
+diff -urNp linux-2.6.28.8/fs/nfs/nfs4proc.c linux-2.6.28.8/fs/nfs/nfs4proc.c |
18868 |
+--- linux-2.6.28.8/fs/nfs/nfs4proc.c 2009-02-06 16:47:45.000000000 -0500 |
18869 |
++++ linux-2.6.28.8/fs/nfs/nfs4proc.c 2009-02-21 09:37:49.000000000 -0500 |
18870 |
+@@ -653,7 +653,7 @@ static int _nfs4_do_open_reclaim(struct |
18871 |
+ static int nfs4_do_open_reclaim(struct nfs_open_context *ctx, struct nfs4_state *state) |
18872 |
+ { |
18873 |
+ struct nfs_server *server = NFS_SERVER(state->inode); |
18874 |
+- struct nfs4_exception exception = { }; |
18875 |
++ struct nfs4_exception exception = {0, 0}; |
18876 |
+ int err; |
18877 |
+ do { |
18878 |
+ err = _nfs4_do_open_reclaim(ctx, state); |
18879 |
+@@ -695,7 +695,7 @@ static int _nfs4_open_delegation_recall( |
18880 |
+ |
18881 |
+ int nfs4_open_delegation_recall(struct nfs_open_context *ctx, struct nfs4_state *state, const nfs4_stateid *stateid) |
18882 |
+ { |
18883 |
+- struct nfs4_exception exception = { }; |
18884 |
++ struct nfs4_exception exception = {0, 0}; |
18885 |
+ struct nfs_server *server = NFS_SERVER(state->inode); |
18886 |
+ int err; |
18887 |
+ do { |
18888 |
+@@ -988,7 +988,7 @@ static int _nfs4_open_expired(struct nfs |
18889 |
+ static inline int nfs4_do_open_expired(struct nfs_open_context *ctx, struct nfs4_state *state) |
18890 |
+ { |
18891 |
+ struct nfs_server *server = NFS_SERVER(state->inode); |
18892 |
+- struct nfs4_exception exception = { }; |
18893 |
++ struct nfs4_exception exception = {0, 0}; |
18894 |
+ int err; |
18895 |
+ |
18896 |
+ do { |
18897 |
+@@ -1090,7 +1090,7 @@ out_err: |
18898 |
+ |
18899 |
+ static struct nfs4_state *nfs4_do_open(struct inode *dir, struct path *path, int flags, struct iattr *sattr, struct rpc_cred *cred) |
18900 |
+ { |
18901 |
+- struct nfs4_exception exception = { }; |
18902 |
++ struct nfs4_exception exception = {0, 0}; |
18903 |
+ struct nfs4_state *res; |
18904 |
+ int status; |
18905 |
+ |
18906 |
+@@ -1181,7 +1181,7 @@ static int nfs4_do_setattr(struct inode |
18907 |
+ struct nfs4_state *state) |
18908 |
+ { |
18909 |
+ struct nfs_server *server = NFS_SERVER(inode); |
18910 |
+- struct nfs4_exception exception = { }; |
18911 |
++ struct nfs4_exception exception = {0, 0}; |
18912 |
+ int err; |
18913 |
+ do { |
18914 |
+ err = nfs4_handle_exception(server, |
18915 |
+@@ -1494,7 +1494,7 @@ static int _nfs4_server_capabilities(str |
18916 |
+ |
18917 |
+ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) |
18918 |
+ { |
18919 |
+- struct nfs4_exception exception = { }; |
18920 |
++ struct nfs4_exception exception = {0, 0}; |
18921 |
+ int err; |
18922 |
+ do { |
18923 |
+ err = nfs4_handle_exception(server, |
18924 |
+@@ -1527,7 +1527,7 @@ static int _nfs4_lookup_root(struct nfs_ |
18925 |
+ static int nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, |
18926 |
+ struct nfs_fsinfo *info) |
18927 |
+ { |
18928 |
+- struct nfs4_exception exception = { }; |
18929 |
++ struct nfs4_exception exception = {0, 0}; |
18930 |
+ int err; |
18931 |
+ do { |
18932 |
+ err = nfs4_handle_exception(server, |
18933 |
+@@ -1616,7 +1616,7 @@ static int _nfs4_proc_getattr(struct nfs |
18934 |
+ |
18935 |
+ static int nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
18936 |
+ { |
18937 |
+- struct nfs4_exception exception = { }; |
18938 |
++ struct nfs4_exception exception = {0, 0}; |
18939 |
+ int err; |
18940 |
+ do { |
18941 |
+ err = nfs4_handle_exception(server, |
18942 |
+@@ -1704,7 +1704,7 @@ static int nfs4_proc_lookupfh(struct nfs |
18943 |
+ struct qstr *name, struct nfs_fh *fhandle, |
18944 |
+ struct nfs_fattr *fattr) |
18945 |
+ { |
18946 |
+- struct nfs4_exception exception = { }; |
18947 |
++ struct nfs4_exception exception = {0, 0}; |
18948 |
+ int err; |
18949 |
+ do { |
18950 |
+ err = _nfs4_proc_lookupfh(server, dirfh, name, fhandle, fattr); |
18951 |
+@@ -1733,7 +1733,7 @@ static int _nfs4_proc_lookup(struct inod |
18952 |
+ |
18953 |
+ static int nfs4_proc_lookup(struct inode *dir, struct qstr *name, struct nfs_fh *fhandle, struct nfs_fattr *fattr) |
18954 |
+ { |
18955 |
+- struct nfs4_exception exception = { }; |
18956 |
++ struct nfs4_exception exception = {0, 0}; |
18957 |
+ int err; |
18958 |
+ do { |
18959 |
+ err = nfs4_handle_exception(NFS_SERVER(dir), |
18960 |
+@@ -1797,7 +1797,7 @@ static int _nfs4_proc_access(struct inod |
18961 |
+ |
18962 |
+ static int nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry) |
18963 |
+ { |
18964 |
+- struct nfs4_exception exception = { }; |
18965 |
++ struct nfs4_exception exception = {0, 0}; |
18966 |
+ int err; |
18967 |
+ do { |
18968 |
+ err = nfs4_handle_exception(NFS_SERVER(inode), |
18969 |
+@@ -1852,7 +1852,7 @@ static int _nfs4_proc_readlink(struct in |
18970 |
+ static int nfs4_proc_readlink(struct inode *inode, struct page *page, |
18971 |
+ unsigned int pgbase, unsigned int pglen) |
18972 |
+ { |
18973 |
+- struct nfs4_exception exception = { }; |
18974 |
++ struct nfs4_exception exception = {0, 0}; |
18975 |
+ int err; |
18976 |
+ do { |
18977 |
+ err = nfs4_handle_exception(NFS_SERVER(inode), |
18978 |
+@@ -1949,7 +1949,7 @@ static int _nfs4_proc_remove(struct inod |
18979 |
+ |
18980 |
+ static int nfs4_proc_remove(struct inode *dir, struct qstr *name) |
18981 |
+ { |
18982 |
+- struct nfs4_exception exception = { }; |
18983 |
++ struct nfs4_exception exception = {0, 0}; |
18984 |
+ int err; |
18985 |
+ do { |
18986 |
+ err = nfs4_handle_exception(NFS_SERVER(dir), |
18987 |
+@@ -2021,7 +2021,7 @@ static int _nfs4_proc_rename(struct inod |
18988 |
+ static int nfs4_proc_rename(struct inode *old_dir, struct qstr *old_name, |
18989 |
+ struct inode *new_dir, struct qstr *new_name) |
18990 |
+ { |
18991 |
+- struct nfs4_exception exception = { }; |
18992 |
++ struct nfs4_exception exception = {0, 0}; |
18993 |
+ int err; |
18994 |
+ do { |
18995 |
+ err = nfs4_handle_exception(NFS_SERVER(old_dir), |
18996 |
+@@ -2068,7 +2068,7 @@ static int _nfs4_proc_link(struct inode |
18997 |
+ |
18998 |
+ static int nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr *name) |
18999 |
+ { |
19000 |
+- struct nfs4_exception exception = { }; |
19001 |
++ struct nfs4_exception exception = {0, 0}; |
19002 |
+ int err; |
19003 |
+ do { |
19004 |
+ err = nfs4_handle_exception(NFS_SERVER(inode), |
19005 |
+@@ -2159,7 +2159,7 @@ out: |
19006 |
+ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, |
19007 |
+ struct page *page, unsigned int len, struct iattr *sattr) |
19008 |
+ { |
19009 |
+- struct nfs4_exception exception = { }; |
19010 |
++ struct nfs4_exception exception = {0, 0}; |
19011 |
+ int err; |
19012 |
+ do { |
19013 |
+ err = nfs4_handle_exception(NFS_SERVER(dir), |
19014 |
+@@ -2190,7 +2190,7 @@ out: |
19015 |
+ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, |
19016 |
+ struct iattr *sattr) |
19017 |
+ { |
19018 |
+- struct nfs4_exception exception = { }; |
19019 |
++ struct nfs4_exception exception = {0, 0}; |
19020 |
+ int err; |
19021 |
+ do { |
19022 |
+ err = nfs4_handle_exception(NFS_SERVER(dir), |
19023 |
+@@ -2239,7 +2239,7 @@ static int _nfs4_proc_readdir(struct den |
19024 |
+ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, |
19025 |
+ u64 cookie, struct page *page, unsigned int count, int plus) |
19026 |
+ { |
19027 |
+- struct nfs4_exception exception = { }; |
19028 |
++ struct nfs4_exception exception = {0, 0}; |
19029 |
+ int err; |
19030 |
+ do { |
19031 |
+ err = nfs4_handle_exception(NFS_SERVER(dentry->d_inode), |
19032 |
+@@ -2287,7 +2287,7 @@ out: |
19033 |
+ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, |
19034 |
+ struct iattr *sattr, dev_t rdev) |
19035 |
+ { |
19036 |
+- struct nfs4_exception exception = { }; |
19037 |
++ struct nfs4_exception exception = {0, 0}; |
19038 |
+ int err; |
19039 |
+ do { |
19040 |
+ err = nfs4_handle_exception(NFS_SERVER(dir), |
19041 |
+@@ -2316,7 +2316,7 @@ static int _nfs4_proc_statfs(struct nfs_ |
19042 |
+ |
19043 |
+ static int nfs4_proc_statfs(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsstat *fsstat) |
19044 |
+ { |
19045 |
+- struct nfs4_exception exception = { }; |
19046 |
++ struct nfs4_exception exception = {0, 0}; |
19047 |
+ int err; |
19048 |
+ do { |
19049 |
+ err = nfs4_handle_exception(server, |
19050 |
+@@ -2344,7 +2344,7 @@ static int _nfs4_do_fsinfo(struct nfs_se |
19051 |
+ |
19052 |
+ static int nfs4_do_fsinfo(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fsinfo *fsinfo) |
19053 |
+ { |
19054 |
+- struct nfs4_exception exception = { }; |
19055 |
++ struct nfs4_exception exception = {0, 0}; |
19056 |
+ int err; |
19057 |
+ |
19058 |
+ do { |
19059 |
+@@ -2387,7 +2387,7 @@ static int _nfs4_proc_pathconf(struct nf |
19060 |
+ static int nfs4_proc_pathconf(struct nfs_server *server, struct nfs_fh *fhandle, |
19061 |
+ struct nfs_pathconf *pathconf) |
19062 |
+ { |
19063 |
+- struct nfs4_exception exception = { }; |
19064 |
++ struct nfs4_exception exception = {0, 0}; |
19065 |
+ int err; |
19066 |
+ |
19067 |
+ do { |
19068 |
+@@ -2674,7 +2674,7 @@ out_free: |
19069 |
+ |
19070 |
+ static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) |
19071 |
+ { |
19072 |
+- struct nfs4_exception exception = { }; |
19073 |
++ struct nfs4_exception exception = {0, 0}; |
19074 |
+ ssize_t ret; |
19075 |
+ do { |
19076 |
+ ret = __nfs4_get_acl_uncached(inode, buf, buflen); |
19077 |
+@@ -2731,7 +2731,7 @@ static int __nfs4_proc_set_acl(struct in |
19078 |
+ |
19079 |
+ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) |
19080 |
+ { |
19081 |
+- struct nfs4_exception exception = { }; |
19082 |
++ struct nfs4_exception exception = {0, 0}; |
19083 |
+ int err; |
19084 |
+ do { |
19085 |
+ err = nfs4_handle_exception(NFS_SERVER(inode), |
19086 |
+@@ -3022,7 +3022,7 @@ out: |
19087 |
+ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4_stateid *stateid, int issync) |
19088 |
+ { |
19089 |
+ struct nfs_server *server = NFS_SERVER(inode); |
19090 |
+- struct nfs4_exception exception = { }; |
19091 |
++ struct nfs4_exception exception = {0, 0}; |
19092 |
+ int err; |
19093 |
+ do { |
19094 |
+ err = _nfs4_proc_delegreturn(inode, cred, stateid, issync); |
19095 |
+@@ -3097,7 +3097,7 @@ out: |
19096 |
+ |
19097 |
+ static int nfs4_proc_getlk(struct nfs4_state *state, int cmd, struct file_lock *request) |
19098 |
+ { |
19099 |
+- struct nfs4_exception exception = { }; |
19100 |
++ struct nfs4_exception exception = {0, 0}; |
19101 |
+ int err; |
19102 |
+ |
19103 |
+ do { |
19104 |
+@@ -3447,7 +3447,7 @@ static int _nfs4_do_setlk(struct nfs4_st |
19105 |
+ static int nfs4_lock_reclaim(struct nfs4_state *state, struct file_lock *request) |
19106 |
+ { |
19107 |
+ struct nfs_server *server = NFS_SERVER(state->inode); |
19108 |
+- struct nfs4_exception exception = { }; |
19109 |
++ struct nfs4_exception exception = {0, 0}; |
19110 |
+ int err; |
19111 |
+ |
19112 |
+ do { |
19113 |
+@@ -3465,7 +3465,7 @@ static int nfs4_lock_reclaim(struct nfs4 |
19114 |
+ static int nfs4_lock_expired(struct nfs4_state *state, struct file_lock *request) |
19115 |
+ { |
19116 |
+ struct nfs_server *server = NFS_SERVER(state->inode); |
19117 |
+- struct nfs4_exception exception = { }; |
19118 |
++ struct nfs4_exception exception = {0, 0}; |
19119 |
+ int err; |
19120 |
+ |
19121 |
+ err = nfs4_set_lock_state(state, request); |
19122 |
+@@ -3526,7 +3526,7 @@ out: |
19123 |
+ |
19124 |
+ static int nfs4_proc_setlk(struct nfs4_state *state, int cmd, struct file_lock *request) |
19125 |
+ { |
19126 |
+- struct nfs4_exception exception = { }; |
19127 |
++ struct nfs4_exception exception = {0, 0}; |
19128 |
+ int err; |
19129 |
+ |
19130 |
+ do { |
19131 |
+@@ -3576,7 +3576,7 @@ nfs4_proc_lock(struct file *filp, int cm |
19132 |
+ int nfs4_lock_delegation_recall(struct nfs4_state *state, struct file_lock *fl) |
19133 |
+ { |
19134 |
+ struct nfs_server *server = NFS_SERVER(state->inode); |
19135 |
+- struct nfs4_exception exception = { }; |
19136 |
++ struct nfs4_exception exception = {0, 0}; |
19137 |
+ int err; |
19138 |
+ |
19139 |
+ err = nfs4_set_lock_state(state, fl); |
19140 |
+diff -urNp linux-2.6.28.8/fs/nfsd/export.c linux-2.6.28.8/fs/nfsd/export.c |
19141 |
+--- linux-2.6.28.8/fs/nfsd/export.c 2009-02-06 16:47:45.000000000 -0500 |
19142 |
++++ linux-2.6.28.8/fs/nfsd/export.c 2009-02-21 09:37:49.000000000 -0500 |
19143 |
+@@ -472,7 +472,7 @@ static int secinfo_parse(char **mesg, ch |
19144 |
+ * probably discover the problem when someone fails to |
19145 |
+ * authenticate. |
19146 |
+ */ |
19147 |
+- if (f->pseudoflavor < 0) |
19148 |
++ if ((s32)f->pseudoflavor < 0) |
19149 |
+ return -EINVAL; |
19150 |
+ err = get_int(mesg, &f->flags); |
19151 |
+ if (err) |
19152 |
+diff -urNp linux-2.6.28.8/fs/nls/nls_base.c linux-2.6.28.8/fs/nls/nls_base.c |
19153 |
+--- linux-2.6.28.8/fs/nls/nls_base.c 2009-02-06 16:47:45.000000000 -0500 |
19154 |
++++ linux-2.6.28.8/fs/nls/nls_base.c 2009-02-21 09:37:49.000000000 -0500 |
19155 |
+@@ -40,7 +40,7 @@ static const struct utf8_table utf8_tabl |
19156 |
+ {0xF8, 0xF0, 3*6, 0x1FFFFF, 0x10000, /* 4 byte sequence */}, |
19157 |
+ {0xFC, 0xF8, 4*6, 0x3FFFFFF, 0x200000, /* 5 byte sequence */}, |
19158 |
+ {0xFE, 0xFC, 5*6, 0x7FFFFFFF, 0x4000000, /* 6 byte sequence */}, |
19159 |
+- {0, /* end of table */} |
19160 |
++ {0, 0, 0, 0, 0, /* end of table */} |
19161 |
+ }; |
19162 |
+ |
19163 |
+ int |
19164 |
+diff -urNp linux-2.6.28.8/fs/ntfs/file.c linux-2.6.28.8/fs/ntfs/file.c |
19165 |
+--- linux-2.6.28.8/fs/ntfs/file.c 2009-02-06 16:47:45.000000000 -0500 |
19166 |
++++ linux-2.6.28.8/fs/ntfs/file.c 2009-02-21 09:37:49.000000000 -0500 |
19167 |
+@@ -2291,6 +2291,6 @@ const struct inode_operations ntfs_file_ |
19168 |
+ #endif /* NTFS_RW */ |
19169 |
+ }; |
19170 |
+ |
19171 |
+-const struct file_operations ntfs_empty_file_ops = {}; |
19172 |
++const struct file_operations ntfs_empty_file_ops; |
19173 |
+ |
19174 |
+-const struct inode_operations ntfs_empty_inode_ops = {}; |
19175 |
++const struct inode_operations ntfs_empty_inode_ops; |
19176 |
+diff -urNp linux-2.6.28.8/fs/open.c linux-2.6.28.8/fs/open.c |
19177 |
+--- linux-2.6.28.8/fs/open.c 2009-02-06 16:47:45.000000000 -0500 |
19178 |
++++ linux-2.6.28.8/fs/open.c 2009-02-21 09:37:49.000000000 -0500 |
19179 |
+@@ -205,6 +205,9 @@ int do_truncate(struct dentry *dentry, l |
19180 |
+ if (length < 0) |
19181 |
+ return -EINVAL; |
19182 |
+ |
19183 |
++ if (filp && !gr_acl_handle_truncate(dentry, filp->f_path.mnt)) |
19184 |
++ return -EACCES; |
19185 |
++ |
19186 |
+ newattrs.ia_size = length; |
19187 |
+ newattrs.ia_valid = ATTR_SIZE | time_attrs; |
19188 |
+ if (filp) { |
19189 |
+@@ -510,6 +513,9 @@ SYSCALL_DEFINE3(faccessat, int, dfd, con |
19190 |
+ if (__mnt_is_readonly(path.mnt)) |
19191 |
+ res = -EROFS; |
19192 |
+ |
19193 |
++ if (!res && !gr_acl_handle_access(path.dentry, path.mnt, mode)) |
19194 |
++ res = -EACCES; |
19195 |
++ |
19196 |
+ out_path_release: |
19197 |
+ path_put(&path); |
19198 |
+ out: |
19199 |
+@@ -540,6 +546,8 @@ SYSCALL_DEFINE1(chdir, const char __user |
19200 |
+ if (error) |
19201 |
+ goto dput_and_out; |
19202 |
+ |
19203 |
++ gr_log_chdir(path.dentry, path.mnt); |
19204 |
++ |
19205 |
+ set_fs_pwd(current->fs, &path); |
19206 |
+ |
19207 |
+ dput_and_out: |
19208 |
+@@ -566,6 +574,13 @@ SYSCALL_DEFINE1(fchdir, unsigned int, fd |
19209 |
+ goto out_putf; |
19210 |
+ |
19211 |
+ error = inode_permission(inode, MAY_EXEC | MAY_ACCESS); |
19212 |
++ |
19213 |
++ if (!error && !gr_chroot_fchdir(file->f_path.dentry, file->f_path.mnt)) |
19214 |
++ error = -EPERM; |
19215 |
++ |
19216 |
++ if (!error) |
19217 |
++ gr_log_chdir(file->f_path.dentry, file->f_path.mnt); |
19218 |
++ |
19219 |
+ if (!error) |
19220 |
+ set_fs_pwd(current->fs, &file->f_path); |
19221 |
+ out_putf: |
19222 |
+@@ -591,7 +606,14 @@ SYSCALL_DEFINE1(chroot, const char __use |
19223 |
+ if (!capable(CAP_SYS_CHROOT)) |
19224 |
+ goto dput_and_out; |
19225 |
+ |
19226 |
++ if (gr_handle_chroot_chroot(path.dentry, path.mnt)) |
19227 |
++ goto dput_and_out; |
19228 |
++ |
19229 |
+ set_fs_root(current->fs, &path); |
19230 |
++ |
19231 |
++ gr_handle_chroot_caps(current); |
19232 |
++ gr_handle_chroot_chdir(&path); |
19233 |
++ |
19234 |
+ error = 0; |
19235 |
+ dput_and_out: |
19236 |
+ path_put(&path); |
19237 |
+@@ -619,13 +641,28 @@ SYSCALL_DEFINE2(fchmod, unsigned int, fd |
19238 |
+ err = mnt_want_write(file->f_path.mnt); |
19239 |
+ if (err) |
19240 |
+ goto out_putf; |
19241 |
++ |
19242 |
++ if (!gr_acl_handle_fchmod(dentry, file->f_path.mnt, mode)) { |
19243 |
++ err = -EACCES; |
19244 |
++ goto out_drop_write; |
19245 |
++ } |
19246 |
++ |
19247 |
+ mutex_lock(&inode->i_mutex); |
19248 |
+ if (mode == (mode_t) -1) |
19249 |
+ mode = inode->i_mode; |
19250 |
++ |
19251 |
++ if (gr_handle_chroot_chmod(dentry, file->f_path.mnt, mode)) { |
19252 |
++ err = -EPERM; |
19253 |
++ mutex_unlock(&inode->i_mutex); |
19254 |
++ goto out_drop_write; |
19255 |
++ } |
19256 |
++ |
19257 |
+ newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
19258 |
+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
19259 |
+ err = notify_change(dentry, &newattrs); |
19260 |
+ mutex_unlock(&inode->i_mutex); |
19261 |
++ |
19262 |
++out_drop_write: |
19263 |
+ mnt_drop_write(file->f_path.mnt); |
19264 |
+ out_putf: |
19265 |
+ fput(file); |
19266 |
+@@ -648,13 +685,28 @@ SYSCALL_DEFINE3(fchmodat, int, dfd, cons |
19267 |
+ error = mnt_want_write(path.mnt); |
19268 |
+ if (error) |
19269 |
+ goto dput_and_out; |
19270 |
++ |
19271 |
++ if (!gr_acl_handle_chmod(path.dentry, path.mnt, mode)) { |
19272 |
++ error = -EACCES; |
19273 |
++ goto out_drop_write; |
19274 |
++ } |
19275 |
++ |
19276 |
+ mutex_lock(&inode->i_mutex); |
19277 |
+ if (mode == (mode_t) -1) |
19278 |
+ mode = inode->i_mode; |
19279 |
++ |
19280 |
++ if (gr_handle_chroot_chmod(path.dentry, path.mnt, mode)) { |
19281 |
++ error = -EACCES; |
19282 |
++ mutex_unlock(&inode->i_mutex); |
19283 |
++ goto out_drop_write; |
19284 |
++ } |
19285 |
++ |
19286 |
+ newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); |
19287 |
+ newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; |
19288 |
+ error = notify_change(path.dentry, &newattrs); |
19289 |
+ mutex_unlock(&inode->i_mutex); |
19290 |
++ |
19291 |
++out_drop_write: |
19292 |
+ mnt_drop_write(path.mnt); |
19293 |
+ dput_and_out: |
19294 |
+ path_put(&path); |
19295 |
+@@ -667,12 +719,15 @@ SYSCALL_DEFINE2(chmod, const char __user |
19296 |
+ return sys_fchmodat(AT_FDCWD, filename, mode); |
19297 |
+ } |
19298 |
+ |
19299 |
+-static int chown_common(struct dentry * dentry, uid_t user, gid_t group) |
19300 |
++static int chown_common(struct dentry * dentry, uid_t user, gid_t group, struct vfsmount *mnt) |
19301 |
+ { |
19302 |
+ struct inode *inode = dentry->d_inode; |
19303 |
+ int error; |
19304 |
+ struct iattr newattrs; |
19305 |
+ |
19306 |
++ if (!gr_acl_handle_chown(dentry, mnt)) |
19307 |
++ return -EACCES; |
19308 |
++ |
19309 |
+ newattrs.ia_valid = ATTR_CTIME; |
19310 |
+ if (user != (uid_t) -1) { |
19311 |
+ newattrs.ia_valid |= ATTR_UID; |
19312 |
+@@ -703,7 +758,7 @@ SYSCALL_DEFINE3(chown, const char __user |
19313 |
+ error = mnt_want_write(path.mnt); |
19314 |
+ if (error) |
19315 |
+ goto out_release; |
19316 |
+- error = chown_common(path.dentry, user, group); |
19317 |
++ error = chown_common(path.dentry, user, group, path.mnt); |
19318 |
+ mnt_drop_write(path.mnt); |
19319 |
+ out_release: |
19320 |
+ path_put(&path); |
19321 |
+@@ -728,7 +783,7 @@ SYSCALL_DEFINE5(fchownat, int, dfd, cons |
19322 |
+ error = mnt_want_write(path.mnt); |
19323 |
+ if (error) |
19324 |
+ goto out_release; |
19325 |
+- error = chown_common(path.dentry, user, group); |
19326 |
++ error = chown_common(path.dentry, user, group, path.mnt); |
19327 |
+ mnt_drop_write(path.mnt); |
19328 |
+ out_release: |
19329 |
+ path_put(&path); |
19330 |
+@@ -747,7 +802,7 @@ SYSCALL_DEFINE3(lchown, const char __use |
19331 |
+ error = mnt_want_write(path.mnt); |
19332 |
+ if (error) |
19333 |
+ goto out_release; |
19334 |
+- error = chown_common(path.dentry, user, group); |
19335 |
++ error = chown_common(path.dentry, user, group, path.mnt); |
19336 |
+ mnt_drop_write(path.mnt); |
19337 |
+ out_release: |
19338 |
+ path_put(&path); |
19339 |
+@@ -770,7 +825,7 @@ SYSCALL_DEFINE3(fchown, unsigned int, fd |
19340 |
+ goto out_fput; |
19341 |
+ dentry = file->f_path.dentry; |
19342 |
+ audit_inode(NULL, dentry); |
19343 |
+- error = chown_common(dentry, user, group); |
19344 |
++ error = chown_common(dentry, user, group, file->f_path.mnt); |
19345 |
+ mnt_drop_write(file->f_path.mnt); |
19346 |
+ out_fput: |
19347 |
+ fput(file); |
19348 |
+diff -urNp linux-2.6.28.8/fs/pipe.c linux-2.6.28.8/fs/pipe.c |
19349 |
+--- linux-2.6.28.8/fs/pipe.c 2009-03-07 10:24:49.000000000 -0500 |
19350 |
++++ linux-2.6.28.8/fs/pipe.c 2009-03-07 14:13:22.000000000 -0500 |
19351 |
+@@ -848,7 +848,7 @@ void free_pipe_info(struct inode *inode) |
19352 |
+ inode->i_pipe = NULL; |
19353 |
+ } |
19354 |
+ |
19355 |
+-static struct vfsmount *pipe_mnt __read_mostly; |
19356 |
++struct vfsmount *pipe_mnt __read_mostly; |
19357 |
+ static int pipefs_delete_dentry(struct dentry *dentry) |
19358 |
+ { |
19359 |
+ /* |
19360 |
+diff -urNp linux-2.6.28.8/fs/proc/array.c linux-2.6.28.8/fs/proc/array.c |
19361 |
+--- linux-2.6.28.8/fs/proc/array.c 2009-02-06 16:47:45.000000000 -0500 |
19362 |
++++ linux-2.6.28.8/fs/proc/array.c 2009-02-21 09:37:49.000000000 -0500 |
19363 |
+@@ -308,6 +308,21 @@ static inline void task_context_switch_c |
19364 |
+ p->nivcsw); |
19365 |
+ } |
19366 |
+ |
19367 |
++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) |
19368 |
++static inline void task_pax(struct seq_file *m, struct task_struct *p) |
19369 |
++{ |
19370 |
++ if (p->mm) |
19371 |
++ seq_printf(m, "PaX:\t%c%c%c%c%c\n", |
19372 |
++ p->mm->pax_flags & MF_PAX_PAGEEXEC ? 'P' : 'p', |
19373 |
++ p->mm->pax_flags & MF_PAX_EMUTRAMP ? 'E' : 'e', |
19374 |
++ p->mm->pax_flags & MF_PAX_MPROTECT ? 'M' : 'm', |
19375 |
++ p->mm->pax_flags & MF_PAX_RANDMMAP ? 'R' : 'r', |
19376 |
++ p->mm->pax_flags & MF_PAX_SEGMEXEC ? 'S' : 's'); |
19377 |
++ else |
19378 |
++ seq_printf(m, "PaX:\t-----\n"); |
19379 |
++} |
19380 |
++#endif |
19381 |
++ |
19382 |
+ int proc_pid_status(struct seq_file *m, struct pid_namespace *ns, |
19383 |
+ struct pid *pid, struct task_struct *task) |
19384 |
+ { |
19385 |
+@@ -327,9 +342,20 @@ int proc_pid_status(struct seq_file *m, |
19386 |
+ task_show_regs(m, task); |
19387 |
+ #endif |
19388 |
+ task_context_switch_counts(m, task); |
19389 |
++ |
19390 |
++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) |
19391 |
++ task_pax(m, task); |
19392 |
++#endif |
19393 |
++ |
19394 |
+ return 0; |
19395 |
+ } |
19396 |
+ |
19397 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
19398 |
++#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \ |
19399 |
++ (_mm->pax_flags & MF_PAX_RANDMMAP || \ |
19400 |
++ _mm->pax_flags & MF_PAX_SEGMEXEC)) |
19401 |
++#endif |
19402 |
++ |
19403 |
+ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns, |
19404 |
+ struct pid *pid, struct task_struct *task, int whole) |
19405 |
+ { |
19406 |
+@@ -422,6 +448,19 @@ static int do_task_stat(struct seq_file |
19407 |
+ gtime = task_gtime(task); |
19408 |
+ } |
19409 |
+ |
19410 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
19411 |
++ if (PAX_RAND_FLAGS(mm)) { |
19412 |
++ eip = 0; |
19413 |
++ esp = 0; |
19414 |
++ wchan = 0; |
19415 |
++ } |
19416 |
++#endif |
19417 |
++#ifdef CONFIG_GRKERNSEC_HIDESYM |
19418 |
++ wchan = 0; |
19419 |
++ eip =0; |
19420 |
++ esp =0; |
19421 |
++#endif |
19422 |
++ |
19423 |
+ /* scale priority and nice values from timeslices to -20..20 */ |
19424 |
+ /* to make it look like a "normal" Unix priority/nice value */ |
19425 |
+ priority = task_prio(task); |
19426 |
+@@ -462,9 +501,15 @@ static int do_task_stat(struct seq_file |
19427 |
+ vsize, |
19428 |
+ mm ? get_mm_rss(mm) : 0, |
19429 |
+ rsslim, |
19430 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
19431 |
++ PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->start_code : 0), |
19432 |
++ PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->end_code : 0), |
19433 |
++ PAX_RAND_FLAGS(mm) ? 0 : (mm ? mm->start_stack : 0), |
19434 |
++#else |
19435 |
+ mm ? mm->start_code : 0, |
19436 |
+ mm ? mm->end_code : 0, |
19437 |
+ mm ? mm->start_stack : 0, |
19438 |
++#endif |
19439 |
+ esp, |
19440 |
+ eip, |
19441 |
+ /* The signal information here is obsolete. |
19442 |
+@@ -517,3 +562,10 @@ int proc_pid_statm(struct seq_file *m, s |
19443 |
+ |
19444 |
+ return 0; |
19445 |
+ } |
19446 |
++ |
19447 |
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR |
19448 |
++int proc_pid_ipaddr(struct task_struct *task, char *buffer) |
19449 |
++{ |
19450 |
++ return sprintf(buffer, "%u.%u.%u.%u\n", NIPQUAD(task->signal->curr_ip)); |
19451 |
++} |
19452 |
++#endif |
19453 |
+diff -urNp linux-2.6.28.8/fs/proc/base.c linux-2.6.28.8/fs/proc/base.c |
19454 |
+--- linux-2.6.28.8/fs/proc/base.c 2009-02-06 16:47:45.000000000 -0500 |
19455 |
++++ linux-2.6.28.8/fs/proc/base.c 2009-03-07 05:50:38.000000000 -0500 |
19456 |
+@@ -225,6 +225,9 @@ static int check_mem_permission(struct t |
19457 |
+ if (task == current) |
19458 |
+ return 0; |
19459 |
+ |
19460 |
++ if (gr_handle_proc_ptrace(task) || gr_acl_handle_procpidmem(task)) |
19461 |
++ return -EPERM; |
19462 |
++ |
19463 |
+ /* |
19464 |
+ * If current is actively ptrace'ing, and would also be |
19465 |
+ * permitted to freshly attach with ptrace now, permit it. |
19466 |
+@@ -302,15 +305,29 @@ out: |
19467 |
+ return res; |
19468 |
+ } |
19469 |
+ |
19470 |
+-static int proc_pid_auxv(struct task_struct *task, char *buffer) |
19471 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
19472 |
++#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \ |
19473 |
++ (_mm->pax_flags & MF_PAX_RANDMMAP || \ |
19474 |
++ _mm->pax_flags & MF_PAX_SEGMEXEC)) |
19475 |
++#endif |
19476 |
++ |
19477 |
++static |
19478 |
++int proc_pid_auxv(struct task_struct *task, char *buffer) |
19479 |
+ { |
19480 |
+ int res = 0; |
19481 |
+ struct mm_struct *mm = get_task_mm(task); |
19482 |
+ if (mm) { |
19483 |
+ unsigned int nwords = 0; |
19484 |
+- do |
19485 |
++ |
19486 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
19487 |
++ if (PAX_RAND_FLAGS(mm)) { |
19488 |
++ mmput(mm); |
19489 |
++ return res; |
19490 |
++ } |
19491 |
++#endif |
19492 |
++ do { |
19493 |
+ nwords += 2; |
19494 |
+- while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */ |
19495 |
++ } while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */ |
19496 |
+ res = nwords * sizeof(mm->saved_auxv[0]); |
19497 |
+ if (res > PAGE_SIZE) |
19498 |
+ res = PAGE_SIZE; |
19499 |
+@@ -502,7 +519,7 @@ static int proc_pid_limits(struct task_s |
19500 |
+ return count; |
19501 |
+ } |
19502 |
+ |
19503 |
+-#ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
19504 |
++#if defined(CONFIG_HAVE_ARCH_TRACEHOOK) && !defined(CONFIG_GRKERNSEC_PROC_MEMMAP) |
19505 |
+ static int proc_pid_syscall(struct task_struct *task, char *buffer) |
19506 |
+ { |
19507 |
+ long nr; |
19508 |
+@@ -1429,7 +1446,11 @@ static struct inode *proc_pid_make_inode |
19509 |
+ inode->i_gid = 0; |
19510 |
+ if (task_dumpable(task)) { |
19511 |
+ inode->i_uid = task->euid; |
19512 |
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP |
19513 |
++ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID; |
19514 |
++#else |
19515 |
+ inode->i_gid = task->egid; |
19516 |
++#endif |
19517 |
+ } |
19518 |
+ security_task_to_inode(task, inode); |
19519 |
+ |
19520 |
+@@ -1445,17 +1466,45 @@ static int pid_getattr(struct vfsmount * |
19521 |
+ { |
19522 |
+ struct inode *inode = dentry->d_inode; |
19523 |
+ struct task_struct *task; |
19524 |
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
19525 |
++ struct task_struct *tmp = current; |
19526 |
++#endif |
19527 |
++ |
19528 |
+ generic_fillattr(inode, stat); |
19529 |
+ |
19530 |
+ rcu_read_lock(); |
19531 |
+ stat->uid = 0; |
19532 |
+ stat->gid = 0; |
19533 |
+ task = pid_task(proc_pid(inode), PIDTYPE_PID); |
19534 |
+- if (task) { |
19535 |
++ |
19536 |
++ if (task && (gr_pid_is_chrooted(task) || gr_check_hidden_task(task))) { |
19537 |
++ rcu_read_unlock(); |
19538 |
++ return -ENOENT; |
19539 |
++ } |
19540 |
++ |
19541 |
++ |
19542 |
++ if (task |
19543 |
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
19544 |
++ && (!tmp->uid || (tmp->uid == task->uid) |
19545 |
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP |
19546 |
++ || in_group_p(CONFIG_GRKERNSEC_PROC_GID) |
19547 |
++#endif |
19548 |
++ ) |
19549 |
++#endif |
19550 |
++ ) { |
19551 |
+ if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || |
19552 |
++#ifdef CONFIG_GRKERNSEC_PROC_USER |
19553 |
++ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IXUSR)) || |
19554 |
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
19555 |
++ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IRGRP|S_IXUSR|S_IXGRP)) || |
19556 |
++#endif |
19557 |
+ task_dumpable(task)) { |
19558 |
+ stat->uid = task->euid; |
19559 |
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP |
19560 |
++ stat->gid = CONFIG_GRKERNSEC_PROC_GID; |
19561 |
++#else |
19562 |
+ stat->gid = task->egid; |
19563 |
++#endif |
19564 |
+ } |
19565 |
+ } |
19566 |
+ rcu_read_unlock(); |
19567 |
+@@ -1483,11 +1532,21 @@ static int pid_revalidate(struct dentry |
19568 |
+ { |
19569 |
+ struct inode *inode = dentry->d_inode; |
19570 |
+ struct task_struct *task = get_proc_task(inode); |
19571 |
++ |
19572 |
+ if (task) { |
19573 |
+ if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) || |
19574 |
++#ifdef CONFIG_GRKERNSEC_PROC_USER |
19575 |
++ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IXUSR)) || |
19576 |
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
19577 |
++ (inode->i_mode == (S_IFDIR|S_IRUSR|S_IRGRP|S_IXUSR|S_IXGRP)) || |
19578 |
++#endif |
19579 |
+ task_dumpable(task)) { |
19580 |
+ inode->i_uid = task->euid; |
19581 |
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP |
19582 |
++ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID; |
19583 |
++#else |
19584 |
+ inode->i_gid = task->egid; |
19585 |
++#endif |
19586 |
+ } else { |
19587 |
+ inode->i_uid = 0; |
19588 |
+ inode->i_gid = 0; |
19589 |
+@@ -1855,12 +1914,22 @@ static const struct file_operations proc |
19590 |
+ static int proc_fd_permission(struct inode *inode, int mask) |
19591 |
+ { |
19592 |
+ int rv; |
19593 |
++ struct task_struct *task; |
19594 |
+ |
19595 |
+ rv = generic_permission(inode, mask, NULL); |
19596 |
+- if (rv == 0) |
19597 |
+- return 0; |
19598 |
++ |
19599 |
+ if (task_pid(current) == proc_pid(inode)) |
19600 |
+ rv = 0; |
19601 |
++ |
19602 |
++ task = get_proc_task(inode); |
19603 |
++ if (task == NULL) |
19604 |
++ return rv; |
19605 |
++ |
19606 |
++ if (gr_acl_handle_procpidmem(task)) |
19607 |
++ rv = -EACCES; |
19608 |
++ |
19609 |
++ put_task_struct(task); |
19610 |
++ |
19611 |
+ return rv; |
19612 |
+ } |
19613 |
+ |
19614 |
+@@ -1971,6 +2040,9 @@ static struct dentry *proc_pident_lookup |
19615 |
+ if (!task) |
19616 |
+ goto out_no_task; |
19617 |
+ |
19618 |
++ if (gr_pid_is_chrooted(task) || gr_check_hidden_task(task)) |
19619 |
++ goto out; |
19620 |
++ |
19621 |
+ /* |
19622 |
+ * Yes, it does not scale. And it should not. Don't add |
19623 |
+ * new entries into /proc/<tgid>/ without very good reasons. |
19624 |
+@@ -2015,6 +2087,9 @@ static int proc_pident_readdir(struct fi |
19625 |
+ if (!task) |
19626 |
+ goto out_no_task; |
19627 |
+ |
19628 |
++ if (gr_pid_is_chrooted(task) || gr_check_hidden_task(task)) |
19629 |
++ goto out; |
19630 |
++ |
19631 |
+ ret = 0; |
19632 |
+ i = filp->f_pos; |
19633 |
+ switch (i) { |
19634 |
+@@ -2377,6 +2452,9 @@ static struct dentry *proc_base_lookup(s |
19635 |
+ if (p > last) |
19636 |
+ goto out; |
19637 |
+ |
19638 |
++ if (gr_pid_is_chrooted(task) || gr_check_hidden_task(task)) |
19639 |
++ goto out; |
19640 |
++ |
19641 |
+ error = proc_base_instantiate(dir, dentry, task, p); |
19642 |
+ |
19643 |
+ out: |
19644 |
+@@ -2463,7 +2541,7 @@ static const struct pid_entry tgid_base_ |
19645 |
+ #ifdef CONFIG_SCHED_DEBUG |
19646 |
+ REG("sched", S_IRUGO|S_IWUSR, pid_sched), |
19647 |
+ #endif |
19648 |
+-#ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
19649 |
++#if defined(CONFIG_HAVE_ARCH_TRACEHOOK) && !defined(CONFIG_GRKERNSEC_PROC_MEMMAP) |
19650 |
+ INF("syscall", S_IRUSR, pid_syscall), |
19651 |
+ #endif |
19652 |
+ INF("cmdline", S_IRUGO, pid_cmdline), |
19653 |
+@@ -2518,6 +2596,9 @@ static const struct pid_entry tgid_base_ |
19654 |
+ #ifdef CONFIG_TASK_IO_ACCOUNTING |
19655 |
+ INF("io", S_IRUGO, tgid_io_accounting), |
19656 |
+ #endif |
19657 |
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR |
19658 |
++ INF("ipaddr", S_IRUSR, pid_ipaddr), |
19659 |
++#endif |
19660 |
+ }; |
19661 |
+ |
19662 |
+ static int proc_tgid_base_readdir(struct file * filp, |
19663 |
+@@ -2647,7 +2728,14 @@ static struct dentry *proc_pid_instantia |
19664 |
+ if (!inode) |
19665 |
+ goto out; |
19666 |
+ |
19667 |
++#ifdef CONFIG_GRKERNSEC_PROC_USER |
19668 |
++ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR; |
19669 |
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
19670 |
++ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID; |
19671 |
++ inode->i_mode = S_IFDIR|S_IRUSR|S_IRGRP|S_IXUSR|S_IXGRP; |
19672 |
++#else |
19673 |
+ inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; |
19674 |
++#endif |
19675 |
+ inode->i_op = &proc_tgid_base_inode_operations; |
19676 |
+ inode->i_fop = &proc_tgid_base_operations; |
19677 |
+ inode->i_flags|=S_IMMUTABLE; |
19678 |
+@@ -2689,7 +2777,11 @@ struct dentry *proc_pid_lookup(struct in |
19679 |
+ if (!task) |
19680 |
+ goto out; |
19681 |
+ |
19682 |
++ if (gr_check_hidden_task(task)) |
19683 |
++ goto out_put_task; |
19684 |
++ |
19685 |
+ result = proc_pid_instantiate(dir, dentry, task, NULL); |
19686 |
++out_put_task: |
19687 |
+ put_task_struct(task); |
19688 |
+ out: |
19689 |
+ return result; |
19690 |
+@@ -2754,6 +2846,9 @@ int proc_pid_readdir(struct file * filp, |
19691 |
+ { |
19692 |
+ unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY; |
19693 |
+ struct task_struct *reaper = get_proc_task(filp->f_path.dentry->d_inode); |
19694 |
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
19695 |
++ struct task_struct *tmp = current; |
19696 |
++#endif |
19697 |
+ struct tgid_iter iter; |
19698 |
+ struct pid_namespace *ns; |
19699 |
+ |
19700 |
+@@ -2772,6 +2867,17 @@ int proc_pid_readdir(struct file * filp, |
19701 |
+ for (iter = next_tgid(ns, iter); |
19702 |
+ iter.task; |
19703 |
+ iter.tgid += 1, iter = next_tgid(ns, iter)) { |
19704 |
++ if (gr_pid_is_chrooted(iter.task) || gr_check_hidden_task(iter.task) |
19705 |
++#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
19706 |
++ || (tmp->uid && (iter.task->uid != tmp->uid) |
19707 |
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP |
19708 |
++ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID) |
19709 |
++#endif |
19710 |
++ ) |
19711 |
++#endif |
19712 |
++ ) |
19713 |
++ continue; |
19714 |
++ |
19715 |
+ filp->f_pos = iter.tgid + TGID_OFFSET; |
19716 |
+ if (proc_pid_fill_cache(filp, dirent, filldir, iter) < 0) { |
19717 |
+ put_task_struct(iter.task); |
19718 |
+@@ -2799,7 +2905,7 @@ static const struct pid_entry tid_base_s |
19719 |
+ #ifdef CONFIG_SCHED_DEBUG |
19720 |
+ REG("sched", S_IRUGO|S_IWUSR, pid_sched), |
19721 |
+ #endif |
19722 |
+-#ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
19723 |
++#if defined(CONFIG_HAVE_ARCH_TRACEHOOK) && !defined(CONFIG_GRKERNSEC_PROC_MEMMAP) |
19724 |
+ INF("syscall", S_IRUSR, pid_syscall), |
19725 |
+ #endif |
19726 |
+ INF("cmdline", S_IRUGO, pid_cmdline), |
19727 |
+diff -urNp linux-2.6.28.8/fs/proc/cmdline.c linux-2.6.28.8/fs/proc/cmdline.c |
19728 |
+--- linux-2.6.28.8/fs/proc/cmdline.c 2009-02-06 16:47:45.000000000 -0500 |
19729 |
++++ linux-2.6.28.8/fs/proc/cmdline.c 2009-02-21 09:37:49.000000000 -0500 |
19730 |
+@@ -23,7 +23,11 @@ static const struct file_operations cmdl |
19731 |
+ |
19732 |
+ static int __init proc_cmdline_init(void) |
19733 |
+ { |
19734 |
++#ifdef CONFIG_GRKERNSEC_PROC_ADD |
19735 |
++ proc_create_grsec("cmdline", 0, NULL, &cmdline_proc_fops); |
19736 |
++#else |
19737 |
+ proc_create("cmdline", 0, NULL, &cmdline_proc_fops); |
19738 |
++#endif |
19739 |
+ return 0; |
19740 |
+ } |
19741 |
+ module_init(proc_cmdline_init); |
19742 |
+diff -urNp linux-2.6.28.8/fs/proc/devices.c linux-2.6.28.8/fs/proc/devices.c |
19743 |
+--- linux-2.6.28.8/fs/proc/devices.c 2009-02-06 16:47:45.000000000 -0500 |
19744 |
++++ linux-2.6.28.8/fs/proc/devices.c 2009-02-21 09:37:49.000000000 -0500 |
19745 |
+@@ -64,7 +64,11 @@ static const struct file_operations proc |
19746 |
+ |
19747 |
+ static int __init proc_devices_init(void) |
19748 |
+ { |
19749 |
++#ifdef CONFIG_GRKERNSEC_PROC_ADD |
19750 |
++ proc_create_grsec("devices", 0, NULL, &proc_devinfo_operations); |
19751 |
++#else |
19752 |
+ proc_create("devices", 0, NULL, &proc_devinfo_operations); |
19753 |
++#endif |
19754 |
+ return 0; |
19755 |
+ } |
19756 |
+ module_init(proc_devices_init); |
19757 |
+diff -urNp linux-2.6.28.8/fs/proc/inode.c linux-2.6.28.8/fs/proc/inode.c |
19758 |
+--- linux-2.6.28.8/fs/proc/inode.c 2009-02-06 16:47:45.000000000 -0500 |
19759 |
++++ linux-2.6.28.8/fs/proc/inode.c 2009-02-21 09:37:49.000000000 -0500 |
19760 |
+@@ -466,7 +466,11 @@ struct inode *proc_get_inode(struct supe |
19761 |
+ if (de->mode) { |
19762 |
+ inode->i_mode = de->mode; |
19763 |
+ inode->i_uid = de->uid; |
19764 |
++#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP |
19765 |
++ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID; |
19766 |
++#else |
19767 |
+ inode->i_gid = de->gid; |
19768 |
++#endif |
19769 |
+ } |
19770 |
+ if (de->size) |
19771 |
+ inode->i_size = de->size; |
19772 |
+diff -urNp linux-2.6.28.8/fs/proc/internal.h linux-2.6.28.8/fs/proc/internal.h |
19773 |
+--- linux-2.6.28.8/fs/proc/internal.h 2009-02-06 16:47:45.000000000 -0500 |
19774 |
++++ linux-2.6.28.8/fs/proc/internal.h 2009-02-21 09:37:49.000000000 -0500 |
19775 |
+@@ -53,6 +53,9 @@ extern int proc_pid_status(struct seq_fi |
19776 |
+ struct pid *pid, struct task_struct *task); |
19777 |
+ extern int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns, |
19778 |
+ struct pid *pid, struct task_struct *task); |
19779 |
++#ifdef CONFIG_GRKERNSEC_PROC_IPADDR |
19780 |
++extern int proc_pid_ipaddr(struct task_struct *task, char *buffer); |
19781 |
++#endif |
19782 |
+ extern loff_t mem_lseek(struct file *file, loff_t offset, int orig); |
19783 |
+ |
19784 |
+ extern const struct file_operations proc_maps_operations; |
19785 |
+diff -urNp linux-2.6.28.8/fs/proc/Kconfig linux-2.6.28.8/fs/proc/Kconfig |
19786 |
+--- linux-2.6.28.8/fs/proc/Kconfig 2009-02-06 16:47:45.000000000 -0500 |
19787 |
++++ linux-2.6.28.8/fs/proc/Kconfig 2009-02-21 09:37:49.000000000 -0500 |
19788 |
+@@ -30,12 +30,12 @@ config PROC_FS |
19789 |
+ |
19790 |
+ config PROC_KCORE |
19791 |
+ bool "/proc/kcore support" if !ARM |
19792 |
+- depends on PROC_FS && MMU |
19793 |
++ depends on PROC_FS && MMU && !GRKERNSEC_PROC_ADD |
19794 |
+ |
19795 |
+ config PROC_VMCORE |
19796 |
+ bool "/proc/vmcore support (EXPERIMENTAL)" |
19797 |
+- depends on PROC_FS && CRASH_DUMP |
19798 |
+- default y |
19799 |
++ depends on PROC_FS && CRASH_DUMP && !GRKERNSEC |
19800 |
++ default n |
19801 |
+ help |
19802 |
+ Exports the dump image of crashed kernel in ELF format. |
19803 |
+ |
19804 |
+@@ -59,8 +59,8 @@ config PROC_SYSCTL |
19805 |
+ limited in memory. |
19806 |
+ |
19807 |
+ config PROC_PAGE_MONITOR |
19808 |
+- default y |
19809 |
+- depends on PROC_FS && MMU |
19810 |
++ default n |
19811 |
++ depends on PROC_FS && MMU && !GRKERNSEC |
19812 |
+ bool "Enable /proc page monitoring" if EMBEDDED |
19813 |
+ help |
19814 |
+ Various /proc files exist to monitor process memory utilization: |
19815 |
+diff -urNp linux-2.6.28.8/fs/proc/kcore.c linux-2.6.28.8/fs/proc/kcore.c |
19816 |
+--- linux-2.6.28.8/fs/proc/kcore.c 2009-02-06 16:47:45.000000000 -0500 |
19817 |
++++ linux-2.6.28.8/fs/proc/kcore.c 2009-02-21 09:37:49.000000000 -0500 |
19818 |
+@@ -404,10 +404,12 @@ read_kcore(struct file *file, char __use |
19819 |
+ |
19820 |
+ static int __init proc_kcore_init(void) |
19821 |
+ { |
19822 |
++#if !defined(CONFIG_GRKERNSEC_PROC_ADD) |
19823 |
+ proc_root_kcore = proc_create("kcore", S_IRUSR, NULL, &proc_kcore_operations); |
19824 |
+ if (proc_root_kcore) |
19825 |
+ proc_root_kcore->size = |
19826 |
+ (size_t)high_memory - PAGE_OFFSET + PAGE_SIZE; |
19827 |
++#endif |
19828 |
+ return 0; |
19829 |
+ } |
19830 |
+ module_init(proc_kcore_init); |
19831 |
+diff -urNp linux-2.6.28.8/fs/proc/proc_net.c linux-2.6.28.8/fs/proc/proc_net.c |
19832 |
+--- linux-2.6.28.8/fs/proc/proc_net.c 2009-02-06 16:47:45.000000000 -0500 |
19833 |
++++ linux-2.6.28.8/fs/proc/proc_net.c 2009-02-21 09:37:49.000000000 -0500 |
19834 |
+@@ -106,6 +106,14 @@ static struct net *get_proc_task_net(str |
19835 |
+ struct nsproxy *ns; |
19836 |
+ struct net *net = NULL; |
19837 |
+ |
19838 |
++#ifdef CONFIG_GRKERNSEC_PROC_USER |
19839 |
++ if (current->fsuid) |
19840 |
++ return net; |
19841 |
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
19842 |
++ if (current->fsuid && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)) |
19843 |
++ return net; |
19844 |
++#endif |
19845 |
++ |
19846 |
+ rcu_read_lock(); |
19847 |
+ task = pid_task(proc_pid(dir), PIDTYPE_PID); |
19848 |
+ if (task != NULL) { |
19849 |
+diff -urNp linux-2.6.28.8/fs/proc/proc_sysctl.c linux-2.6.28.8/fs/proc/proc_sysctl.c |
19850 |
+--- linux-2.6.28.8/fs/proc/proc_sysctl.c 2009-02-06 16:47:45.000000000 -0500 |
19851 |
++++ linux-2.6.28.8/fs/proc/proc_sysctl.c 2009-02-21 09:37:49.000000000 -0500 |
19852 |
+@@ -7,6 +7,8 @@ |
19853 |
+ #include <linux/security.h> |
19854 |
+ #include "internal.h" |
19855 |
+ |
19856 |
++extern __u32 gr_handle_sysctl(const struct ctl_table *table, const int op); |
19857 |
++ |
19858 |
+ static struct dentry_operations proc_sys_dentry_operations; |
19859 |
+ static const struct file_operations proc_sys_file_operations; |
19860 |
+ static const struct inode_operations proc_sys_inode_operations; |
19861 |
+@@ -110,6 +112,9 @@ static struct dentry *proc_sys_lookup(st |
19862 |
+ if (!p) |
19863 |
+ goto out; |
19864 |
+ |
19865 |
++ if (gr_handle_sysctl(p, MAY_EXEC)) |
19866 |
++ goto out; |
19867 |
++ |
19868 |
+ err = ERR_PTR(-ENOMEM); |
19869 |
+ inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p); |
19870 |
+ if (h) |
19871 |
+@@ -229,6 +234,9 @@ static int scan(struct ctl_table_header |
19872 |
+ if (*pos < file->f_pos) |
19873 |
+ continue; |
19874 |
+ |
19875 |
++ if (gr_handle_sysctl(table, 0)) |
19876 |
++ continue; |
19877 |
++ |
19878 |
+ res = proc_sys_fill_cache(file, dirent, filldir, head, table); |
19879 |
+ if (res) |
19880 |
+ return res; |
19881 |
+@@ -345,6 +353,9 @@ static int proc_sys_getattr(struct vfsmo |
19882 |
+ if (IS_ERR(head)) |
19883 |
+ return PTR_ERR(head); |
19884 |
+ |
19885 |
++ if (table && gr_handle_sysctl(table, MAY_EXEC)) |
19886 |
++ return -ENOENT; |
19887 |
++ |
19888 |
+ generic_fillattr(inode, stat); |
19889 |
+ if (table) |
19890 |
+ stat->mode = (stat->mode & S_IFMT) | table->mode; |
19891 |
+diff -urNp linux-2.6.28.8/fs/proc/root.c linux-2.6.28.8/fs/proc/root.c |
19892 |
+--- linux-2.6.28.8/fs/proc/root.c 2009-02-06 16:47:45.000000000 -0500 |
19893 |
++++ linux-2.6.28.8/fs/proc/root.c 2009-02-21 09:37:49.000000000 -0500 |
19894 |
+@@ -135,7 +135,15 @@ void __init proc_root_init(void) |
19895 |
+ #ifdef CONFIG_PROC_DEVICETREE |
19896 |
+ proc_device_tree_init(); |
19897 |
+ #endif |
19898 |
++#ifdef CONFIG_GRKERNSEC_PROC_ADD |
19899 |
++#ifdef CONFIG_GRKERNSEC_PROC_USER |
19900 |
++ proc_mkdir_mode("bus", S_IRUSR | S_IXUSR, NULL); |
19901 |
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
19902 |
++ proc_mkdir_mode("bus", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL); |
19903 |
++#endif |
19904 |
++#else |
19905 |
+ proc_mkdir("bus", NULL); |
19906 |
++#endif |
19907 |
+ proc_sys_init(); |
19908 |
+ } |
19909 |
+ |
19910 |
+diff -urNp linux-2.6.28.8/fs/proc/task_mmu.c linux-2.6.28.8/fs/proc/task_mmu.c |
19911 |
+--- linux-2.6.28.8/fs/proc/task_mmu.c 2009-02-06 16:47:45.000000000 -0500 |
19912 |
++++ linux-2.6.28.8/fs/proc/task_mmu.c 2009-02-21 09:37:49.000000000 -0500 |
19913 |
+@@ -46,15 +46,26 @@ void task_mem(struct seq_file *m, struct |
19914 |
+ "VmStk:\t%8lu kB\n" |
19915 |
+ "VmExe:\t%8lu kB\n" |
19916 |
+ "VmLib:\t%8lu kB\n" |
19917 |
+- "VmPTE:\t%8lu kB\n", |
19918 |
+- hiwater_vm << (PAGE_SHIFT-10), |
19919 |
++ "VmPTE:\t%8lu kB\n" |
19920 |
++ |
19921 |
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT |
19922 |
++ "CsBase:\t%8lx\nCsLim:\t%8lx\n" |
19923 |
++#endif |
19924 |
++ |
19925 |
++ ,hiwater_vm << (PAGE_SHIFT-10), |
19926 |
+ (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10), |
19927 |
+ mm->locked_vm << (PAGE_SHIFT-10), |
19928 |
+ hiwater_rss << (PAGE_SHIFT-10), |
19929 |
+ total_rss << (PAGE_SHIFT-10), |
19930 |
+ data << (PAGE_SHIFT-10), |
19931 |
+ mm->stack_vm << (PAGE_SHIFT-10), text, lib, |
19932 |
+- (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10); |
19933 |
++ (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10 |
19934 |
++ |
19935 |
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT |
19936 |
++ , mm->context.user_cs_base, mm->context.user_cs_limit |
19937 |
++#endif |
19938 |
++ |
19939 |
++ ); |
19940 |
+ } |
19941 |
+ |
19942 |
+ unsigned long task_vsize(struct mm_struct *mm) |
19943 |
+@@ -198,6 +209,12 @@ static int do_maps_open(struct inode *in |
19944 |
+ return ret; |
19945 |
+ } |
19946 |
+ |
19947 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
19948 |
++#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \ |
19949 |
++ (_mm->pax_flags & MF_PAX_RANDMMAP || \ |
19950 |
++ _mm->pax_flags & MF_PAX_SEGMEXEC)) |
19951 |
++#endif |
19952 |
++ |
19953 |
+ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) |
19954 |
+ { |
19955 |
+ struct mm_struct *mm = vma->vm_mm; |
19956 |
+@@ -214,13 +231,22 @@ static void show_map_vma(struct seq_file |
19957 |
+ } |
19958 |
+ |
19959 |
+ seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n", |
19960 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
19961 |
++ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_start, |
19962 |
++ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_end, |
19963 |
++#else |
19964 |
+ vma->vm_start, |
19965 |
+ vma->vm_end, |
19966 |
++#endif |
19967 |
+ flags & VM_READ ? 'r' : '-', |
19968 |
+ flags & VM_WRITE ? 'w' : '-', |
19969 |
+ flags & VM_EXEC ? 'x' : '-', |
19970 |
+ flags & VM_MAYSHARE ? 's' : 'p', |
19971 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
19972 |
++ PAX_RAND_FLAGS(mm) ? 0UL : ((loff_t)vma->vm_pgoff) << PAGE_SHIFT, |
19973 |
++#else |
19974 |
+ ((loff_t)vma->vm_pgoff) << PAGE_SHIFT, |
19975 |
++#endif |
19976 |
+ MAJOR(dev), MINOR(dev), ino, &len); |
19977 |
+ |
19978 |
+ /* |
19979 |
+@@ -234,11 +260,11 @@ static void show_map_vma(struct seq_file |
19980 |
+ const char *name = arch_vma_name(vma); |
19981 |
+ if (!name) { |
19982 |
+ if (mm) { |
19983 |
+- if (vma->vm_start <= mm->start_brk && |
19984 |
+- vma->vm_end >= mm->brk) { |
19985 |
++ if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { |
19986 |
+ name = "[heap]"; |
19987 |
+- } else if (vma->vm_start <= mm->start_stack && |
19988 |
+- vma->vm_end >= mm->start_stack) { |
19989 |
++ } else if ((vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP)) || |
19990 |
++ (vma->vm_start <= mm->start_stack && |
19991 |
++ vma->vm_end >= mm->start_stack)) { |
19992 |
+ name = "[stack]"; |
19993 |
+ } |
19994 |
+ } else { |
19995 |
+@@ -381,9 +407,16 @@ static int show_smap(struct seq_file *m, |
19996 |
+ }; |
19997 |
+ |
19998 |
+ memset(&mss, 0, sizeof mss); |
19999 |
+- mss.vma = vma; |
20000 |
+- if (vma->vm_mm && !is_vm_hugetlb_page(vma)) |
20001 |
+- walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); |
20002 |
++ |
20003 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
20004 |
++ if (!PAX_RAND_FLAGS(vma->vm_mm)) { |
20005 |
++#endif |
20006 |
++ mss.vma = vma; |
20007 |
++ if (vma->vm_mm && !is_vm_hugetlb_page(vma)) |
20008 |
++ walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); |
20009 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
20010 |
++ } |
20011 |
++#endif |
20012 |
+ |
20013 |
+ show_map_vma(m, vma); |
20014 |
+ |
20015 |
+@@ -397,7 +430,11 @@ static int show_smap(struct seq_file *m, |
20016 |
+ "Private_Dirty: %8lu kB\n" |
20017 |
+ "Referenced: %8lu kB\n" |
20018 |
+ "Swap: %8lu kB\n", |
20019 |
++#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP |
20020 |
++ PAX_RAND_FLAGS(vma->vm_mm) ? 0UL : (vma->vm_end - vma->vm_start) >> 10, |
20021 |
++#else |
20022 |
+ (vma->vm_end - vma->vm_start) >> 10, |
20023 |
++#endif |
20024 |
+ mss.resident >> 10, |
20025 |
+ (unsigned long)(mss.pss >> (10 + PSS_SHIFT)), |
20026 |
+ mss.shared_clean >> 10, |
20027 |
+diff -urNp linux-2.6.28.8/fs/readdir.c linux-2.6.28.8/fs/readdir.c |
20028 |
+--- linux-2.6.28.8/fs/readdir.c 2009-02-06 16:47:45.000000000 -0500 |
20029 |
++++ linux-2.6.28.8/fs/readdir.c 2009-02-21 09:37:49.000000000 -0500 |
20030 |
+@@ -16,6 +16,7 @@ |
20031 |
+ #include <linux/security.h> |
20032 |
+ #include <linux/syscalls.h> |
20033 |
+ #include <linux/unistd.h> |
20034 |
++#include <linux/namei.h> |
20035 |
+ |
20036 |
+ #include <asm/uaccess.h> |
20037 |
+ |
20038 |
+@@ -67,6 +68,7 @@ struct old_linux_dirent { |
20039 |
+ |
20040 |
+ struct readdir_callback { |
20041 |
+ struct old_linux_dirent __user * dirent; |
20042 |
++ struct file * file; |
20043 |
+ int result; |
20044 |
+ }; |
20045 |
+ |
20046 |
+@@ -84,6 +86,10 @@ static int fillonedir(void * __buf, cons |
20047 |
+ buf->result = -EOVERFLOW; |
20048 |
+ return -EOVERFLOW; |
20049 |
+ } |
20050 |
++ |
20051 |
++ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino)) |
20052 |
++ return 0; |
20053 |
++ |
20054 |
+ buf->result++; |
20055 |
+ dirent = buf->dirent; |
20056 |
+ if (!access_ok(VERIFY_WRITE, dirent, |
20057 |
+@@ -116,6 +122,7 @@ SYSCALL_DEFINE3(old_readdir, unsigned in |
20058 |
+ |
20059 |
+ buf.result = 0; |
20060 |
+ buf.dirent = dirent; |
20061 |
++ buf.file = file; |
20062 |
+ |
20063 |
+ error = vfs_readdir(file, fillonedir, &buf); |
20064 |
+ if (buf.result) |
20065 |
+@@ -142,6 +149,7 @@ struct linux_dirent { |
20066 |
+ struct getdents_callback { |
20067 |
+ struct linux_dirent __user * current_dir; |
20068 |
+ struct linux_dirent __user * previous; |
20069 |
++ struct file * file; |
20070 |
+ int count; |
20071 |
+ int error; |
20072 |
+ }; |
20073 |
+@@ -162,6 +170,10 @@ static int filldir(void * __buf, const c |
20074 |
+ buf->error = -EOVERFLOW; |
20075 |
+ return -EOVERFLOW; |
20076 |
+ } |
20077 |
++ |
20078 |
++ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino)) |
20079 |
++ return 0; |
20080 |
++ |
20081 |
+ dirent = buf->previous; |
20082 |
+ if (dirent) { |
20083 |
+ if (__put_user(offset, &dirent->d_off)) |
20084 |
+@@ -209,6 +221,7 @@ SYSCALL_DEFINE3(getdents, unsigned int, |
20085 |
+ buf.previous = NULL; |
20086 |
+ buf.count = count; |
20087 |
+ buf.error = 0; |
20088 |
++ buf.file = file; |
20089 |
+ |
20090 |
+ error = vfs_readdir(file, filldir, &buf); |
20091 |
+ if (error >= 0) |
20092 |
+@@ -228,6 +241,7 @@ out: |
20093 |
+ struct getdents_callback64 { |
20094 |
+ struct linux_dirent64 __user * current_dir; |
20095 |
+ struct linux_dirent64 __user * previous; |
20096 |
++ struct file *file; |
20097 |
+ int count; |
20098 |
+ int error; |
20099 |
+ }; |
20100 |
+@@ -242,6 +256,10 @@ static int filldir64(void * __buf, const |
20101 |
+ buf->error = -EINVAL; /* only used if we fail.. */ |
20102 |
+ if (reclen > buf->count) |
20103 |
+ return -EINVAL; |
20104 |
++ |
20105 |
++ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino)) |
20106 |
++ return 0; |
20107 |
++ |
20108 |
+ dirent = buf->previous; |
20109 |
+ if (dirent) { |
20110 |
+ if (__put_user(offset, &dirent->d_off)) |
20111 |
+@@ -289,6 +307,7 @@ SYSCALL_DEFINE3(getdents64, unsigned int |
20112 |
+ |
20113 |
+ buf.current_dir = dirent; |
20114 |
+ buf.previous = NULL; |
20115 |
++ buf.file = file; |
20116 |
+ buf.count = count; |
20117 |
+ buf.error = 0; |
20118 |
+ |
20119 |
+diff -urNp linux-2.6.28.8/fs/select.c linux-2.6.28.8/fs/select.c |
20120 |
+--- linux-2.6.28.8/fs/select.c 2009-02-06 16:47:45.000000000 -0500 |
20121 |
++++ linux-2.6.28.8/fs/select.c 2009-02-21 09:37:49.000000000 -0500 |
20122 |
+@@ -19,6 +19,7 @@ |
20123 |
+ #include <linux/module.h> |
20124 |
+ #include <linux/slab.h> |
20125 |
+ #include <linux/poll.h> |
20126 |
++#include <linux/security.h> |
20127 |
+ #include <linux/personality.h> /* for STICKY_TIMEOUTS */ |
20128 |
+ #include <linux/file.h> |
20129 |
+ #include <linux/fdtable.h> |
20130 |
+@@ -733,6 +734,7 @@ int do_sys_poll(struct pollfd __user *uf |
20131 |
+ struct poll_list *walk = head; |
20132 |
+ unsigned long todo = nfds; |
20133 |
+ |
20134 |
++ gr_learn_resource(current, RLIMIT_NOFILE, nfds, 1); |
20135 |
+ if (nfds > current->signal->rlim[RLIMIT_NOFILE].rlim_cur) |
20136 |
+ return -EINVAL; |
20137 |
+ |
20138 |
+diff -urNp linux-2.6.28.8/fs/smbfs/symlink.c linux-2.6.28.8/fs/smbfs/symlink.c |
20139 |
+--- linux-2.6.28.8/fs/smbfs/symlink.c 2009-02-06 16:47:45.000000000 -0500 |
20140 |
++++ linux-2.6.28.8/fs/smbfs/symlink.c 2009-02-21 09:37:49.000000000 -0500 |
20141 |
+@@ -55,7 +55,7 @@ static void *smb_follow_link(struct dent |
20142 |
+ |
20143 |
+ static void smb_put_link(struct dentry *dentry, struct nameidata *nd, void *p) |
20144 |
+ { |
20145 |
+- char *s = nd_get_link(nd); |
20146 |
++ const char *s = nd_get_link(nd); |
20147 |
+ if (!IS_ERR(s)) |
20148 |
+ __putname(s); |
20149 |
+ } |
20150 |
+diff -urNp linux-2.6.28.8/fs/sysfs/symlink.c linux-2.6.28.8/fs/sysfs/symlink.c |
20151 |
+--- linux-2.6.28.8/fs/sysfs/symlink.c 2009-02-06 16:47:45.000000000 -0500 |
20152 |
++++ linux-2.6.28.8/fs/sysfs/symlink.c 2009-02-21 09:37:49.000000000 -0500 |
20153 |
+@@ -200,7 +200,7 @@ static void *sysfs_follow_link(struct de |
20154 |
+ |
20155 |
+ static void sysfs_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) |
20156 |
+ { |
20157 |
+- char *page = nd_get_link(nd); |
20158 |
++ const char *page = nd_get_link(nd); |
20159 |
+ if (!IS_ERR(page)) |
20160 |
+ free_page((unsigned long)page); |
20161 |
+ } |
20162 |
+diff -urNp linux-2.6.28.8/fs/udf/balloc.c linux-2.6.28.8/fs/udf/balloc.c |
20163 |
+--- linux-2.6.28.8/fs/udf/balloc.c 2009-02-06 16:47:45.000000000 -0500 |
20164 |
++++ linux-2.6.28.8/fs/udf/balloc.c 2009-02-21 09:37:49.000000000 -0500 |
20165 |
+@@ -169,9 +169,7 @@ static void udf_bitmap_free_blocks(struc |
20166 |
+ unsigned long overflow; |
20167 |
+ |
20168 |
+ mutex_lock(&sbi->s_alloc_mutex); |
20169 |
+- if (bloc.logicalBlockNum < 0 || |
20170 |
+- (bloc.logicalBlockNum + count) > |
20171 |
+- sbi->s_partmaps[bloc.partitionReferenceNum].s_partition_len) { |
20172 |
++ if (bloc.logicalBlockNum + count > sbi->s_partmaps[bloc.partitionReferenceNum].s_partition_len) { |
20173 |
+ udf_debug("%d < %d || %d + %d > %d\n", |
20174 |
+ bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, |
20175 |
+ sbi->s_partmaps[bloc.partitionReferenceNum]. |
20176 |
+@@ -239,7 +237,7 @@ static int udf_bitmap_prealloc_blocks(st |
20177 |
+ |
20178 |
+ mutex_lock(&sbi->s_alloc_mutex); |
20179 |
+ part_len = sbi->s_partmaps[partition].s_partition_len; |
20180 |
+- if (first_block < 0 || first_block >= part_len) |
20181 |
++ if (first_block >= part_len) |
20182 |
+ goto out; |
20183 |
+ |
20184 |
+ if (first_block + block_count > part_len) |
20185 |
+@@ -300,7 +298,7 @@ static int udf_bitmap_new_block(struct s |
20186 |
+ mutex_lock(&sbi->s_alloc_mutex); |
20187 |
+ |
20188 |
+ repeat: |
20189 |
+- if (goal < 0 || goal >= sbi->s_partmaps[partition].s_partition_len) |
20190 |
++ if (goal >= sbi->s_partmaps[partition].s_partition_len) |
20191 |
+ goal = 0; |
20192 |
+ |
20193 |
+ nr_groups = bitmap->s_nr_groups; |
20194 |
+@@ -438,9 +436,7 @@ static void udf_table_free_blocks(struct |
20195 |
+ struct udf_inode_info *iinfo; |
20196 |
+ |
20197 |
+ mutex_lock(&sbi->s_alloc_mutex); |
20198 |
+- if (bloc.logicalBlockNum < 0 || |
20199 |
+- (bloc.logicalBlockNum + count) > |
20200 |
+- sbi->s_partmaps[bloc.partitionReferenceNum].s_partition_len) { |
20201 |
++ if (bloc.logicalBlockNum + count > sbi->s_partmaps[bloc.partitionReferenceNum].s_partition_len) { |
20202 |
+ udf_debug("%d < %d || %d + %d > %d\n", |
20203 |
+ bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, |
20204 |
+ sbi->s_partmaps[bloc.partitionReferenceNum]. |
20205 |
+@@ -671,8 +667,7 @@ static int udf_table_prealloc_blocks(str |
20206 |
+ int8_t etype = -1; |
20207 |
+ struct udf_inode_info *iinfo; |
20208 |
+ |
20209 |
+- if (first_block < 0 || |
20210 |
+- first_block >= sbi->s_partmaps[partition].s_partition_len) |
20211 |
++ if (first_block >= sbi->s_partmaps[partition].s_partition_len) |
20212 |
+ return 0; |
20213 |
+ |
20214 |
+ iinfo = UDF_I(table); |
20215 |
+@@ -750,7 +745,7 @@ static int udf_table_new_block(struct su |
20216 |
+ return newblock; |
20217 |
+ |
20218 |
+ mutex_lock(&sbi->s_alloc_mutex); |
20219 |
+- if (goal < 0 || goal >= sbi->s_partmaps[partition].s_partition_len) |
20220 |
++ if (goal >= sbi->s_partmaps[partition].s_partition_len) |
20221 |
+ goal = 0; |
20222 |
+ |
20223 |
+ /* We search for the closest matching block to goal. If we find |
20224 |
+diff -urNp linux-2.6.28.8/fs/ufs/inode.c linux-2.6.28.8/fs/ufs/inode.c |
20225 |
+--- linux-2.6.28.8/fs/ufs/inode.c 2009-02-06 16:47:45.000000000 -0500 |
20226 |
++++ linux-2.6.28.8/fs/ufs/inode.c 2009-02-21 09:37:49.000000000 -0500 |
20227 |
+@@ -56,9 +56,7 @@ static int ufs_block_to_path(struct inod |
20228 |
+ |
20229 |
+ |
20230 |
+ UFSD("ptrs=uspi->s_apb = %d,double_blocks=%ld \n",ptrs,double_blocks); |
20231 |
+- if (i_block < 0) { |
20232 |
+- ufs_warning(inode->i_sb, "ufs_block_to_path", "block < 0"); |
20233 |
+- } else if (i_block < direct_blocks) { |
20234 |
++ if (i_block < direct_blocks) { |
20235 |
+ offsets[n++] = i_block; |
20236 |
+ } else if ((i_block -= direct_blocks) < indirect_blocks) { |
20237 |
+ offsets[n++] = UFS_IND_BLOCK; |
20238 |
+@@ -440,8 +438,6 @@ int ufs_getfrag_block(struct inode *inod |
20239 |
+ lock_kernel(); |
20240 |
+ |
20241 |
+ UFSD("ENTER, ino %lu, fragment %llu\n", inode->i_ino, (unsigned long long)fragment); |
20242 |
+- if (fragment < 0) |
20243 |
+- goto abort_negative; |
20244 |
+ if (fragment > |
20245 |
+ ((UFS_NDADDR + uspi->s_apb + uspi->s_2apb + uspi->s_3apb) |
20246 |
+ << uspi->s_fpbshift)) |
20247 |
+@@ -504,10 +500,6 @@ abort: |
20248 |
+ unlock_kernel(); |
20249 |
+ return err; |
20250 |
+ |
20251 |
+-abort_negative: |
20252 |
+- ufs_warning(sb, "ufs_get_block", "block < 0"); |
20253 |
+- goto abort; |
20254 |
+- |
20255 |
+ abort_too_big: |
20256 |
+ ufs_warning(sb, "ufs_get_block", "block > big"); |
20257 |
+ goto abort; |
20258 |
+diff -urNp linux-2.6.28.8/fs/utimes.c linux-2.6.28.8/fs/utimes.c |
20259 |
+--- linux-2.6.28.8/fs/utimes.c 2009-02-06 16:47:45.000000000 -0500 |
20260 |
++++ linux-2.6.28.8/fs/utimes.c 2009-02-21 09:37:49.000000000 -0500 |
20261 |
+@@ -1,6 +1,7 @@ |
20262 |
+ #include <linux/compiler.h> |
20263 |
+ #include <linux/file.h> |
20264 |
+ #include <linux/fs.h> |
20265 |
++#include <linux/security.h> |
20266 |
+ #include <linux/linkage.h> |
20267 |
+ #include <linux/mount.h> |
20268 |
+ #include <linux/namei.h> |
20269 |
+@@ -101,6 +102,12 @@ static int utimes_common(struct path *pa |
20270 |
+ goto mnt_drop_write_and_out; |
20271 |
+ } |
20272 |
+ } |
20273 |
++ |
20274 |
++ if (!gr_acl_handle_utime(path->dentry, path->mnt)) { |
20275 |
++ error = -EACCES; |
20276 |
++ goto mnt_drop_write_and_out; |
20277 |
++ } |
20278 |
++ |
20279 |
+ mutex_lock(&inode->i_mutex); |
20280 |
+ error = notify_change(path->dentry, &newattrs); |
20281 |
+ mutex_unlock(&inode->i_mutex); |
20282 |
+diff -urNp linux-2.6.28.8/fs/xfs/linux-2.6/xfs_iops.c linux-2.6.28.8/fs/xfs/linux-2.6/xfs_iops.c |
20283 |
+--- linux-2.6.28.8/fs/xfs/linux-2.6/xfs_iops.c 2009-02-06 16:47:45.000000000 -0500 |
20284 |
++++ linux-2.6.28.8/fs/xfs/linux-2.6/xfs_iops.c 2009-02-21 09:37:49.000000000 -0500 |
20285 |
+@@ -500,7 +500,7 @@ xfs_vn_put_link( |
20286 |
+ struct nameidata *nd, |
20287 |
+ void *p) |
20288 |
+ { |
20289 |
+- char *s = nd_get_link(nd); |
20290 |
++ const char *s = nd_get_link(nd); |
20291 |
+ |
20292 |
+ if (!IS_ERR(s)) |
20293 |
+ kfree(s); |
20294 |
+diff -urNp linux-2.6.28.8/fs/xfs/xfs_bmap.c linux-2.6.28.8/fs/xfs/xfs_bmap.c |
20295 |
+--- linux-2.6.28.8/fs/xfs/xfs_bmap.c 2009-02-06 16:47:45.000000000 -0500 |
20296 |
++++ linux-2.6.28.8/fs/xfs/xfs_bmap.c 2009-02-21 09:37:49.000000000 -0500 |
20297 |
+@@ -360,7 +360,7 @@ xfs_bmap_validate_ret( |
20298 |
+ int nmap, |
20299 |
+ int ret_nmap); |
20300 |
+ #else |
20301 |
+-#define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap) |
20302 |
++#define xfs_bmap_validate_ret(bno,len,flags,mval,onmap,nmap) do {} while (0) |
20303 |
+ #endif /* DEBUG */ |
20304 |
+ |
20305 |
+ #if defined(XFS_RW_TRACE) |
20306 |
+diff -urNp linux-2.6.28.8/grsecurity/gracl_alloc.c linux-2.6.28.8/grsecurity/gracl_alloc.c |
20307 |
+--- linux-2.6.28.8/grsecurity/gracl_alloc.c 1969-12-31 19:00:00.000000000 -0500 |
20308 |
++++ linux-2.6.28.8/grsecurity/gracl_alloc.c 2009-02-21 09:37:49.000000000 -0500 |
20309 |
+@@ -0,0 +1,91 @@ |
20310 |
++#include <linux/kernel.h> |
20311 |
++#include <linux/mm.h> |
20312 |
++#include <linux/slab.h> |
20313 |
++#include <linux/vmalloc.h> |
20314 |
++#include <linux/gracl.h> |
20315 |
++#include <linux/grsecurity.h> |
20316 |
++ |
20317 |
++static unsigned long alloc_stack_next = 1; |
20318 |
++static unsigned long alloc_stack_size = 1; |
20319 |
++static void **alloc_stack; |
20320 |
++ |
20321 |
++static __inline__ int |
20322 |
++alloc_pop(void) |
20323 |
++{ |
20324 |
++ if (alloc_stack_next == 1) |
20325 |
++ return 0; |
20326 |
++ |
20327 |
++ kfree(alloc_stack[alloc_stack_next - 2]); |
20328 |
++ |
20329 |
++ alloc_stack_next--; |
20330 |
++ |
20331 |
++ return 1; |
20332 |
++} |
20333 |
++ |
20334 |
++static __inline__ void |
20335 |
++alloc_push(void *buf) |
20336 |
++{ |
20337 |
++ if (alloc_stack_next >= alloc_stack_size) |
20338 |
++ BUG(); |
20339 |
++ |
20340 |
++ alloc_stack[alloc_stack_next - 1] = buf; |
20341 |
++ |
20342 |
++ alloc_stack_next++; |
20343 |
++ |
20344 |
++ return; |
20345 |
++} |
20346 |
++ |
20347 |
++void * |
20348 |
++acl_alloc(unsigned long len) |
20349 |
++{ |
20350 |
++ void *ret; |
20351 |
++ |
20352 |
++ if (len > PAGE_SIZE) |
20353 |
++ BUG(); |
20354 |
++ |
20355 |
++ ret = kmalloc(len, GFP_KERNEL); |
20356 |
++ |
20357 |
++ if (ret) |
20358 |
++ alloc_push(ret); |
20359 |
++ |
20360 |
++ return ret; |
20361 |
++} |
20362 |
++ |
20363 |
++void |
20364 |
++acl_free_all(void) |
20365 |
++{ |
20366 |
++ if (gr_acl_is_enabled() || !alloc_stack) |
20367 |
++ return; |
20368 |
++ |
20369 |
++ while (alloc_pop()) ; |
20370 |
++ |
20371 |
++ if (alloc_stack) { |
20372 |
++ if ((alloc_stack_size * sizeof (void *)) <= PAGE_SIZE) |
20373 |
++ kfree(alloc_stack); |
20374 |
++ else |
20375 |
++ vfree(alloc_stack); |
20376 |
++ } |
20377 |
++ |
20378 |
++ alloc_stack = NULL; |
20379 |
++ alloc_stack_size = 1; |
20380 |
++ alloc_stack_next = 1; |
20381 |
++ |
20382 |
++ return; |
20383 |
++} |
20384 |
++ |
20385 |
++int |
20386 |
++acl_alloc_stack_init(unsigned long size) |
20387 |
++{ |
20388 |
++ if ((size * sizeof (void *)) <= PAGE_SIZE) |
20389 |
++ alloc_stack = |
20390 |
++ (void **) kmalloc(size * sizeof (void *), GFP_KERNEL); |
20391 |
++ else |
20392 |
++ alloc_stack = (void **) vmalloc(size * sizeof (void *)); |
20393 |
++ |
20394 |
++ alloc_stack_size = size; |
20395 |
++ |
20396 |
++ if (!alloc_stack) |
20397 |
++ return 0; |
20398 |
++ else |
20399 |
++ return 1; |
20400 |
++} |
20401 |
+diff -urNp linux-2.6.28.8/grsecurity/gracl.c linux-2.6.28.8/grsecurity/gracl.c |
20402 |
+--- linux-2.6.28.8/grsecurity/gracl.c 1969-12-31 19:00:00.000000000 -0500 |
20403 |
++++ linux-2.6.28.8/grsecurity/gracl.c 2009-02-21 09:37:49.000000000 -0500 |
20404 |
+@@ -0,0 +1,3722 @@ |
20405 |
++#include <linux/kernel.h> |
20406 |
++#include <linux/module.h> |
20407 |
++#include <linux/sched.h> |
20408 |
++#include <linux/mm.h> |
20409 |
++#include <linux/file.h> |
20410 |
++#include <linux/fs.h> |
20411 |
++#include <linux/namei.h> |
20412 |
++#include <linux/mount.h> |
20413 |
++#include <linux/tty.h> |
20414 |
++#include <linux/proc_fs.h> |
20415 |
++#include <linux/smp_lock.h> |
20416 |
++#include <linux/slab.h> |
20417 |
++#include <linux/vmalloc.h> |
20418 |
++#include <linux/types.h> |
20419 |
++#include <linux/sysctl.h> |
20420 |
++#include <linux/netdevice.h> |
20421 |
++#include <linux/ptrace.h> |
20422 |
++#include <linux/gracl.h> |
20423 |
++#include <linux/gralloc.h> |
20424 |
++#include <linux/grsecurity.h> |
20425 |
++#include <linux/grinternal.h> |
20426 |
++#include <linux/pid_namespace.h> |
20427 |
++#include <linux/fdtable.h> |
20428 |
++#include <linux/percpu.h> |
20429 |
++ |
20430 |
++#include <asm/uaccess.h> |
20431 |
++#include <asm/errno.h> |
20432 |
++#include <asm/mman.h> |
20433 |
++ |
20434 |
++static struct acl_role_db acl_role_set; |
20435 |
++static struct name_db name_set; |
20436 |
++static struct inodev_db inodev_set; |
20437 |
++ |
20438 |
++/* for keeping track of userspace pointers used for subjects, so we |
20439 |
++ can share references in the kernel as well |
20440 |
++*/ |
20441 |
++ |
20442 |
++static struct dentry *real_root; |
20443 |
++static struct vfsmount *real_root_mnt; |
20444 |
++ |
20445 |
++static struct acl_subj_map_db subj_map_set; |
20446 |
++ |
20447 |
++static struct acl_role_label *default_role; |
20448 |
++ |
20449 |
++static u16 acl_sp_role_value; |
20450 |
++ |
20451 |
++extern char *gr_shared_page[4]; |
20452 |
++static DECLARE_MUTEX(gr_dev_sem); |
20453 |
++DEFINE_RWLOCK(gr_inode_lock); |
20454 |
++ |
20455 |
++struct gr_arg *gr_usermode; |
20456 |
++ |
20457 |
++static unsigned int gr_status = GR_STATUS_INIT; |
20458 |
++ |
20459 |
++extern int chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum); |
20460 |
++extern void gr_clear_learn_entries(void); |
20461 |
++ |
20462 |
++#ifdef CONFIG_GRKERNSEC_RESLOG |
20463 |
++extern void gr_log_resource(const struct task_struct *task, |
20464 |
++ const int res, const unsigned long wanted, const int gt); |
20465 |
++#endif |
20466 |
++ |
20467 |
++unsigned char *gr_system_salt; |
20468 |
++unsigned char *gr_system_sum; |
20469 |
++ |
20470 |
++static struct sprole_pw **acl_special_roles = NULL; |
20471 |
++static __u16 num_sprole_pws = 0; |
20472 |
++ |
20473 |
++static struct acl_role_label *kernel_role = NULL; |
20474 |
++ |
20475 |
++static unsigned int gr_auth_attempts = 0; |
20476 |
++static unsigned long gr_auth_expires = 0UL; |
20477 |
++ |
20478 |
++extern struct vfsmount *sock_mnt; |
20479 |
++extern struct vfsmount *pipe_mnt; |
20480 |
++extern struct vfsmount *shm_mnt; |
20481 |
++static struct acl_object_label *fakefs_obj; |
20482 |
++ |
20483 |
++extern int gr_init_uidset(void); |
20484 |
++extern void gr_free_uidset(void); |
20485 |
++extern void gr_remove_uid(uid_t uid); |
20486 |
++extern int gr_find_uid(uid_t uid); |
20487 |
++ |
20488 |
++__inline__ int |
20489 |
++gr_acl_is_enabled(void) |
20490 |
++{ |
20491 |
++ return (gr_status & GR_READY); |
20492 |
++} |
20493 |
++ |
20494 |
++char gr_roletype_to_char(void) |
20495 |
++{ |
20496 |
++ switch (current->role->roletype & |
20497 |
++ (GR_ROLE_DEFAULT | GR_ROLE_USER | GR_ROLE_GROUP | |
20498 |
++ GR_ROLE_SPECIAL)) { |
20499 |
++ case GR_ROLE_DEFAULT: |
20500 |
++ return 'D'; |
20501 |
++ case GR_ROLE_USER: |
20502 |
++ return 'U'; |
20503 |
++ case GR_ROLE_GROUP: |
20504 |
++ return 'G'; |
20505 |
++ case GR_ROLE_SPECIAL: |
20506 |
++ return 'S'; |
20507 |
++ } |
20508 |
++ |
20509 |
++ return 'X'; |
20510 |
++} |
20511 |
++ |
20512 |
++__inline__ int |
20513 |
++gr_acl_tpe_check(void) |
20514 |
++{ |
20515 |
++ if (unlikely(!(gr_status & GR_READY))) |
20516 |
++ return 0; |
20517 |
++ if (current->role->roletype & GR_ROLE_TPE) |
20518 |
++ return 1; |
20519 |
++ else |
20520 |
++ return 0; |
20521 |
++} |
20522 |
++ |
20523 |
++int |
20524 |
++gr_handle_rawio(const struct inode *inode) |
20525 |
++{ |
20526 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS |
20527 |
++ if (inode && S_ISBLK(inode->i_mode) && |
20528 |
++ grsec_enable_chroot_caps && proc_is_chrooted(current) && |
20529 |
++ !capable(CAP_SYS_RAWIO)) |
20530 |
++ return 1; |
20531 |
++#endif |
20532 |
++ return 0; |
20533 |
++} |
20534 |
++ |
20535 |
++static int |
20536 |
++gr_streq(const char *a, const char *b, const unsigned int lena, const unsigned int lenb) |
20537 |
++{ |
20538 |
++ int i; |
20539 |
++ unsigned long *l1; |
20540 |
++ unsigned long *l2; |
20541 |
++ unsigned char *c1; |
20542 |
++ unsigned char *c2; |
20543 |
++ int num_longs; |
20544 |
++ |
20545 |
++ if (likely(lena != lenb)) |
20546 |
++ return 0; |
20547 |
++ |
20548 |
++ l1 = (unsigned long *)a; |
20549 |
++ l2 = (unsigned long *)b; |
20550 |
++ |
20551 |
++ num_longs = lena / sizeof(unsigned long); |
20552 |
++ |
20553 |
++ for (i = num_longs; i--; l1++, l2++) { |
20554 |
++ if (unlikely(*l1 != *l2)) |
20555 |
++ return 0; |
20556 |
++ } |
20557 |
++ |
20558 |
++ c1 = (unsigned char *) l1; |
20559 |
++ c2 = (unsigned char *) l2; |
20560 |
++ |
20561 |
++ i = lena - (num_longs * sizeof(unsigned long)); |
20562 |
++ |
20563 |
++ for (; i--; c1++, c2++) { |
20564 |
++ if (unlikely(*c1 != *c2)) |
20565 |
++ return 0; |
20566 |
++ } |
20567 |
++ |
20568 |
++ return 1; |
20569 |
++} |
20570 |
++ |
20571 |
++static char * __our_d_path(struct dentry *dentry, struct vfsmount *vfsmnt, |
20572 |
++ struct dentry *root, struct vfsmount *rootmnt, |
20573 |
++ char *buffer, int buflen) |
20574 |
++{ |
20575 |
++ char * end = buffer+buflen; |
20576 |
++ char * retval; |
20577 |
++ int namelen; |
20578 |
++ |
20579 |
++ *--end = '\0'; |
20580 |
++ buflen--; |
20581 |
++ |
20582 |
++ if (buflen < 1) |
20583 |
++ goto Elong; |
20584 |
++ /* Get '/' right */ |
20585 |
++ retval = end-1; |
20586 |
++ *retval = '/'; |
20587 |
++ |
20588 |
++ for (;;) { |
20589 |
++ struct dentry * parent; |
20590 |
++ |
20591 |
++ if (dentry == root && vfsmnt == rootmnt) |
20592 |
++ break; |
20593 |
++ if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) { |
20594 |
++ /* Global root? */ |
20595 |
++ spin_lock(&vfsmount_lock); |
20596 |
++ if (vfsmnt->mnt_parent == vfsmnt) { |
20597 |
++ spin_unlock(&vfsmount_lock); |
20598 |
++ goto global_root; |
20599 |
++ } |
20600 |
++ dentry = vfsmnt->mnt_mountpoint; |
20601 |
++ vfsmnt = vfsmnt->mnt_parent; |
20602 |
++ spin_unlock(&vfsmount_lock); |
20603 |
++ continue; |
20604 |
++ } |
20605 |
++ parent = dentry->d_parent; |
20606 |
++ prefetch(parent); |
20607 |
++ namelen = dentry->d_name.len; |
20608 |
++ buflen -= namelen + 1; |
20609 |
++ if (buflen < 0) |
20610 |
++ goto Elong; |
20611 |
++ end -= namelen; |
20612 |
++ memcpy(end, dentry->d_name.name, namelen); |
20613 |
++ *--end = '/'; |
20614 |
++ retval = end; |
20615 |
++ dentry = parent; |
20616 |
++ } |
20617 |
++ |
20618 |
++ return retval; |
20619 |
++ |
20620 |
++global_root: |
20621 |
++ namelen = dentry->d_name.len; |
20622 |
++ buflen -= namelen; |
20623 |
++ if (buflen < 0) |
20624 |
++ goto Elong; |
20625 |
++ retval -= namelen-1; /* hit the slash */ |
20626 |
++ memcpy(retval, dentry->d_name.name, namelen); |
20627 |
++ return retval; |
20628 |
++Elong: |
20629 |
++ return ERR_PTR(-ENAMETOOLONG); |
20630 |
++} |
20631 |
++ |
20632 |
++static char * |
20633 |
++gen_full_path(struct dentry *dentry, struct vfsmount *vfsmnt, |
20634 |
++ struct dentry *root, struct vfsmount *rootmnt, char *buf, int buflen) |
20635 |
++{ |
20636 |
++ char *retval; |
20637 |
++ |
20638 |
++ retval = __our_d_path(dentry, vfsmnt, root, rootmnt, buf, buflen); |
20639 |
++ if (unlikely(IS_ERR(retval))) |
20640 |
++ retval = strcpy(buf, "<path too long>"); |
20641 |
++ else if (unlikely(retval[1] == '/' && retval[2] == '\0')) |
20642 |
++ retval[1] = '\0'; |
20643 |
++ |
20644 |
++ return retval; |
20645 |
++} |
20646 |
++ |
20647 |
++static char * |
20648 |
++__d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt, |
20649 |
++ char *buf, int buflen) |
20650 |
++{ |
20651 |
++ char *res; |
20652 |
++ |
20653 |
++ /* we can use real_root, real_root_mnt, because this is only called |
20654 |
++ by the RBAC system */ |
20655 |
++ res = gen_full_path((struct dentry *)dentry, (struct vfsmount *)vfsmnt, real_root, real_root_mnt, buf, buflen); |
20656 |
++ |
20657 |
++ return res; |
20658 |
++} |
20659 |
++ |
20660 |
++static char * |
20661 |
++d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt, |
20662 |
++ char *buf, int buflen) |
20663 |
++{ |
20664 |
++ char *res; |
20665 |
++ struct dentry *root; |
20666 |
++ struct vfsmount *rootmnt; |
20667 |
++ struct task_struct *reaper = current->nsproxy->pid_ns->child_reaper; |
20668 |
++ |
20669 |
++ /* we can't use real_root, real_root_mnt, because they belong only to the RBAC system */ |
20670 |
++ read_lock(&reaper->fs->lock); |
20671 |
++ root = dget(reaper->fs->root.dentry); |
20672 |
++ rootmnt = mntget(reaper->fs->root.mnt); |
20673 |
++ read_unlock(&reaper->fs->lock); |
20674 |
++ |
20675 |
++ spin_lock(&dcache_lock); |
20676 |
++ res = gen_full_path((struct dentry *)dentry, (struct vfsmount *)vfsmnt, root, rootmnt, buf, buflen); |
20677 |
++ spin_unlock(&dcache_lock); |
20678 |
++ |
20679 |
++ dput(root); |
20680 |
++ mntput(rootmnt); |
20681 |
++ return res; |
20682 |
++} |
20683 |
++ |
20684 |
++static char * |
20685 |
++gr_to_filename_rbac(const struct dentry *dentry, const struct vfsmount *mnt) |
20686 |
++{ |
20687 |
++ char *ret; |
20688 |
++ spin_lock(&dcache_lock); |
20689 |
++ ret = __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()), |
20690 |
++ PAGE_SIZE); |
20691 |
++ spin_unlock(&dcache_lock); |
20692 |
++ return ret; |
20693 |
++} |
20694 |
++ |
20695 |
++char * |
20696 |
++gr_to_filename_nolock(const struct dentry *dentry, const struct vfsmount *mnt) |
20697 |
++{ |
20698 |
++ return __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()), |
20699 |
++ PAGE_SIZE); |
20700 |
++} |
20701 |
++ |
20702 |
++char * |
20703 |
++gr_to_filename(const struct dentry *dentry, const struct vfsmount *mnt) |
20704 |
++{ |
20705 |
++ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()), |
20706 |
++ PAGE_SIZE); |
20707 |
++} |
20708 |
++ |
20709 |
++char * |
20710 |
++gr_to_filename1(const struct dentry *dentry, const struct vfsmount *mnt) |
20711 |
++{ |
20712 |
++ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[1], smp_processor_id()), |
20713 |
++ PAGE_SIZE); |
20714 |
++} |
20715 |
++ |
20716 |
++char * |
20717 |
++gr_to_filename2(const struct dentry *dentry, const struct vfsmount *mnt) |
20718 |
++{ |
20719 |
++ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[2], smp_processor_id()), |
20720 |
++ PAGE_SIZE); |
20721 |
++} |
20722 |
++ |
20723 |
++char * |
20724 |
++gr_to_filename3(const struct dentry *dentry, const struct vfsmount *mnt) |
20725 |
++{ |
20726 |
++ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[3], smp_processor_id()), |
20727 |
++ PAGE_SIZE); |
20728 |
++} |
20729 |
++ |
20730 |
++__inline__ __u32 |
20731 |
++to_gr_audit(const __u32 reqmode) |
20732 |
++{ |
20733 |
++ /* masks off auditable permission flags, then shifts them to create |
20734 |
++ auditing flags, and adds the special case of append auditing if |
20735 |
++ we're requesting write */ |
20736 |
++ return (((reqmode & ~GR_AUDITS) << 10) | ((reqmode & GR_WRITE) ? GR_AUDIT_APPEND : 0)); |
20737 |
++} |
20738 |
++ |
20739 |
++struct acl_subject_label * |
20740 |
++lookup_subject_map(const struct acl_subject_label *userp) |
20741 |
++{ |
20742 |
++ unsigned int index = shash(userp, subj_map_set.s_size); |
20743 |
++ struct subject_map *match; |
20744 |
++ |
20745 |
++ match = subj_map_set.s_hash[index]; |
20746 |
++ |
20747 |
++ while (match && match->user != userp) |
20748 |
++ match = match->next; |
20749 |
++ |
20750 |
++ if (match != NULL) |
20751 |
++ return match->kernel; |
20752 |
++ else |
20753 |
++ return NULL; |
20754 |
++} |
20755 |
++ |
20756 |
++static void |
20757 |
++insert_subj_map_entry(struct subject_map *subjmap) |
20758 |
++{ |
20759 |
++ unsigned int index = shash(subjmap->user, subj_map_set.s_size); |
20760 |
++ struct subject_map **curr; |
20761 |
++ |
20762 |
++ subjmap->prev = NULL; |
20763 |
++ |
20764 |
++ curr = &subj_map_set.s_hash[index]; |
20765 |
++ if (*curr != NULL) |
20766 |
++ (*curr)->prev = subjmap; |
20767 |
++ |
20768 |
++ subjmap->next = *curr; |
20769 |
++ *curr = subjmap; |
20770 |
++ |
20771 |
++ return; |
20772 |
++} |
20773 |
++ |
20774 |
++static struct acl_role_label * |
20775 |
++lookup_acl_role_label(const struct task_struct *task, const uid_t uid, |
20776 |
++ const gid_t gid) |
20777 |
++{ |
20778 |
++ unsigned int index = rhash(uid, GR_ROLE_USER, acl_role_set.r_size); |
20779 |
++ struct acl_role_label *match; |
20780 |
++ struct role_allowed_ip *ipp; |
20781 |
++ unsigned int x; |
20782 |
++ |
20783 |
++ match = acl_role_set.r_hash[index]; |
20784 |
++ |
20785 |
++ while (match) { |
20786 |
++ if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_USER)) == (GR_ROLE_DOMAIN | GR_ROLE_USER)) { |
20787 |
++ for (x = 0; x < match->domain_child_num; x++) { |
20788 |
++ if (match->domain_children[x] == uid) |
20789 |
++ goto found; |
20790 |
++ } |
20791 |
++ } else if (match->uidgid == uid && match->roletype & GR_ROLE_USER) |
20792 |
++ break; |
20793 |
++ match = match->next; |
20794 |
++ } |
20795 |
++found: |
20796 |
++ if (match == NULL) { |
20797 |
++ try_group: |
20798 |
++ index = rhash(gid, GR_ROLE_GROUP, acl_role_set.r_size); |
20799 |
++ match = acl_role_set.r_hash[index]; |
20800 |
++ |
20801 |
++ while (match) { |
20802 |
++ if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) == (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) { |
20803 |
++ for (x = 0; x < match->domain_child_num; x++) { |
20804 |
++ if (match->domain_children[x] == gid) |
20805 |
++ goto found2; |
20806 |
++ } |
20807 |
++ } else if (match->uidgid == gid && match->roletype & GR_ROLE_GROUP) |
20808 |
++ break; |
20809 |
++ match = match->next; |
20810 |
++ } |
20811 |
++found2: |
20812 |
++ if (match == NULL) |
20813 |
++ match = default_role; |
20814 |
++ if (match->allowed_ips == NULL) |
20815 |
++ return match; |
20816 |
++ else { |
20817 |
++ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) { |
20818 |
++ if (likely |
20819 |
++ ((ntohl(task->signal->curr_ip) & ipp->netmask) == |
20820 |
++ (ntohl(ipp->addr) & ipp->netmask))) |
20821 |
++ return match; |
20822 |
++ } |
20823 |
++ match = default_role; |
20824 |
++ } |
20825 |
++ } else if (match->allowed_ips == NULL) { |
20826 |
++ return match; |
20827 |
++ } else { |
20828 |
++ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) { |
20829 |
++ if (likely |
20830 |
++ ((ntohl(task->signal->curr_ip) & ipp->netmask) == |
20831 |
++ (ntohl(ipp->addr) & ipp->netmask))) |
20832 |
++ return match; |
20833 |
++ } |
20834 |
++ goto try_group; |
20835 |
++ } |
20836 |
++ |
20837 |
++ return match; |
20838 |
++} |
20839 |
++ |
20840 |
++struct acl_subject_label * |
20841 |
++lookup_acl_subj_label(const ino_t ino, const dev_t dev, |
20842 |
++ const struct acl_role_label *role) |
20843 |
++{ |
20844 |
++ unsigned int index = fhash(ino, dev, role->subj_hash_size); |
20845 |
++ struct acl_subject_label *match; |
20846 |
++ |
20847 |
++ match = role->subj_hash[index]; |
20848 |
++ |
20849 |
++ while (match && (match->inode != ino || match->device != dev || |
20850 |
++ (match->mode & GR_DELETED))) { |
20851 |
++ match = match->next; |
20852 |
++ } |
20853 |
++ |
20854 |
++ if (match && !(match->mode & GR_DELETED)) |
20855 |
++ return match; |
20856 |
++ else |
20857 |
++ return NULL; |
20858 |
++} |
20859 |
++ |
20860 |
++static struct acl_object_label * |
20861 |
++lookup_acl_obj_label(const ino_t ino, const dev_t dev, |
20862 |
++ const struct acl_subject_label *subj) |
20863 |
++{ |
20864 |
++ unsigned int index = fhash(ino, dev, subj->obj_hash_size); |
20865 |
++ struct acl_object_label *match; |
20866 |
++ |
20867 |
++ match = subj->obj_hash[index]; |
20868 |
++ |
20869 |
++ while (match && (match->inode != ino || match->device != dev || |
20870 |
++ (match->mode & GR_DELETED))) { |
20871 |
++ match = match->next; |
20872 |
++ } |
20873 |
++ |
20874 |
++ if (match && !(match->mode & GR_DELETED)) |
20875 |
++ return match; |
20876 |
++ else |
20877 |
++ return NULL; |
20878 |
++} |
20879 |
++ |
20880 |
++static struct acl_object_label * |
20881 |
++lookup_acl_obj_label_create(const ino_t ino, const dev_t dev, |
20882 |
++ const struct acl_subject_label *subj) |
20883 |
++{ |
20884 |
++ unsigned int index = fhash(ino, dev, subj->obj_hash_size); |
20885 |
++ struct acl_object_label *match; |
20886 |
++ |
20887 |
++ match = subj->obj_hash[index]; |
20888 |
++ |
20889 |
++ while (match && (match->inode != ino || match->device != dev || |
20890 |
++ !(match->mode & GR_DELETED))) { |
20891 |
++ match = match->next; |
20892 |
++ } |
20893 |
++ |
20894 |
++ if (match && (match->mode & GR_DELETED)) |
20895 |
++ return match; |
20896 |
++ |
20897 |
++ match = subj->obj_hash[index]; |
20898 |
++ |
20899 |
++ while (match && (match->inode != ino || match->device != dev || |
20900 |
++ (match->mode & GR_DELETED))) { |
20901 |
++ match = match->next; |
20902 |
++ } |
20903 |
++ |
20904 |
++ if (match && !(match->mode & GR_DELETED)) |
20905 |
++ return match; |
20906 |
++ else |
20907 |
++ return NULL; |
20908 |
++} |
20909 |
++ |
20910 |
++static struct name_entry * |
20911 |
++lookup_name_entry(const char *name) |
20912 |
++{ |
20913 |
++ unsigned int len = strlen(name); |
20914 |
++ unsigned int key = full_name_hash(name, len); |
20915 |
++ unsigned int index = key % name_set.n_size; |
20916 |
++ struct name_entry *match; |
20917 |
++ |
20918 |
++ match = name_set.n_hash[index]; |
20919 |
++ |
20920 |
++ while (match && (match->key != key || !gr_streq(match->name, name, match->len, len))) |
20921 |
++ match = match->next; |
20922 |
++ |
20923 |
++ return match; |
20924 |
++} |
20925 |
++ |
20926 |
++static struct name_entry * |
20927 |
++lookup_name_entry_create(const char *name) |
20928 |
++{ |
20929 |
++ unsigned int len = strlen(name); |
20930 |
++ unsigned int key = full_name_hash(name, len); |
20931 |
++ unsigned int index = key % name_set.n_size; |
20932 |
++ struct name_entry *match; |
20933 |
++ |
20934 |
++ match = name_set.n_hash[index]; |
20935 |
++ |
20936 |
++ while (match && (match->key != key || !gr_streq(match->name, name, match->len, len) || |
20937 |
++ !match->deleted)) |
20938 |
++ match = match->next; |
20939 |
++ |
20940 |
++ if (match && match->deleted) |
20941 |
++ return match; |
20942 |
++ |
20943 |
++ match = name_set.n_hash[index]; |
20944 |
++ |
20945 |
++ while (match && (match->key != key || !gr_streq(match->name, name, match->len, len) || |
20946 |
++ match->deleted)) |
20947 |
++ match = match->next; |
20948 |
++ |
20949 |
++ if (match && !match->deleted) |
20950 |
++ return match; |
20951 |
++ else |
20952 |
++ return NULL; |
20953 |
++} |
20954 |
++ |
20955 |
++static struct inodev_entry * |
20956 |
++lookup_inodev_entry(const ino_t ino, const dev_t dev) |
20957 |
++{ |
20958 |
++ unsigned int index = fhash(ino, dev, inodev_set.i_size); |
20959 |
++ struct inodev_entry *match; |
20960 |
++ |
20961 |
++ match = inodev_set.i_hash[index]; |
20962 |
++ |
20963 |
++ while (match && (match->nentry->inode != ino || match->nentry->device != dev)) |
20964 |
++ match = match->next; |
20965 |
++ |
20966 |
++ return match; |
20967 |
++} |
20968 |
++ |
20969 |
++static void |
20970 |
++insert_inodev_entry(struct inodev_entry *entry) |
20971 |
++{ |
20972 |
++ unsigned int index = fhash(entry->nentry->inode, entry->nentry->device, |
20973 |
++ inodev_set.i_size); |
20974 |
++ struct inodev_entry **curr; |
20975 |
++ |
20976 |
++ entry->prev = NULL; |
20977 |
++ |
20978 |
++ curr = &inodev_set.i_hash[index]; |
20979 |
++ if (*curr != NULL) |
20980 |
++ (*curr)->prev = entry; |
20981 |
++ |
20982 |
++ entry->next = *curr; |
20983 |
++ *curr = entry; |
20984 |
++ |
20985 |
++ return; |
20986 |
++} |
20987 |
++ |
20988 |
++static void |
20989 |
++__insert_acl_role_label(struct acl_role_label *role, uid_t uidgid) |
20990 |
++{ |
20991 |
++ unsigned int index = |
20992 |
++ rhash(uidgid, role->roletype & (GR_ROLE_USER | GR_ROLE_GROUP), acl_role_set.r_size); |
20993 |
++ struct acl_role_label **curr; |
20994 |
++ |
20995 |
++ role->prev = NULL; |
20996 |
++ |
20997 |
++ curr = &acl_role_set.r_hash[index]; |
20998 |
++ if (*curr != NULL) |
20999 |
++ (*curr)->prev = role; |
21000 |
++ |
21001 |
++ role->next = *curr; |
21002 |
++ *curr = role; |
21003 |
++ |
21004 |
++ return; |
21005 |
++} |
21006 |
++ |
21007 |
++static void |
21008 |
++insert_acl_role_label(struct acl_role_label *role) |
21009 |
++{ |
21010 |
++ int i; |
21011 |
++ |
21012 |
++ if (role->roletype & GR_ROLE_DOMAIN) { |
21013 |
++ for (i = 0; i < role->domain_child_num; i++) |
21014 |
++ __insert_acl_role_label(role, role->domain_children[i]); |
21015 |
++ } else |
21016 |
++ __insert_acl_role_label(role, role->uidgid); |
21017 |
++} |
21018 |
++ |
21019 |
++static int |
21020 |
++insert_name_entry(char *name, const ino_t inode, const dev_t device, __u8 deleted) |
21021 |
++{ |
21022 |
++ struct name_entry **curr, *nentry; |
21023 |
++ struct inodev_entry *ientry; |
21024 |
++ unsigned int len = strlen(name); |
21025 |
++ unsigned int key = full_name_hash(name, len); |
21026 |
++ unsigned int index = key % name_set.n_size; |
21027 |
++ |
21028 |
++ curr = &name_set.n_hash[index]; |
21029 |
++ |
21030 |
++ while (*curr && ((*curr)->key != key || !gr_streq((*curr)->name, name, (*curr)->len, len))) |
21031 |
++ curr = &((*curr)->next); |
21032 |
++ |
21033 |
++ if (*curr != NULL) |
21034 |
++ return 1; |
21035 |
++ |
21036 |
++ nentry = acl_alloc(sizeof (struct name_entry)); |
21037 |
++ if (nentry == NULL) |
21038 |
++ return 0; |
21039 |
++ ientry = acl_alloc(sizeof (struct inodev_entry)); |
21040 |
++ if (ientry == NULL) |
21041 |
++ return 0; |
21042 |
++ ientry->nentry = nentry; |
21043 |
++ |
21044 |
++ nentry->key = key; |
21045 |
++ nentry->name = name; |
21046 |
++ nentry->inode = inode; |
21047 |
++ nentry->device = device; |
21048 |
++ nentry->len = len; |
21049 |
++ nentry->deleted = deleted; |
21050 |
++ |
21051 |
++ nentry->prev = NULL; |
21052 |
++ curr = &name_set.n_hash[index]; |
21053 |
++ if (*curr != NULL) |
21054 |
++ (*curr)->prev = nentry; |
21055 |
++ nentry->next = *curr; |
21056 |
++ *curr = nentry; |
21057 |
++ |
21058 |
++ /* insert us into the table searchable by inode/dev */ |
21059 |
++ insert_inodev_entry(ientry); |
21060 |
++ |
21061 |
++ return 1; |
21062 |
++} |
21063 |
++ |
21064 |
++static void |
21065 |
++insert_acl_obj_label(struct acl_object_label *obj, |
21066 |
++ struct acl_subject_label *subj) |
21067 |
++{ |
21068 |
++ unsigned int index = |
21069 |
++ fhash(obj->inode, obj->device, subj->obj_hash_size); |
21070 |
++ struct acl_object_label **curr; |
21071 |
++ |
21072 |
++ |
21073 |
++ obj->prev = NULL; |
21074 |
++ |
21075 |
++ curr = &subj->obj_hash[index]; |
21076 |
++ if (*curr != NULL) |
21077 |
++ (*curr)->prev = obj; |
21078 |
++ |
21079 |
++ obj->next = *curr; |
21080 |
++ *curr = obj; |
21081 |
++ |
21082 |
++ return; |
21083 |
++} |
21084 |
++ |
21085 |
++static void |
21086 |
++insert_acl_subj_label(struct acl_subject_label *obj, |
21087 |
++ struct acl_role_label *role) |
21088 |
++{ |
21089 |
++ unsigned int index = fhash(obj->inode, obj->device, role->subj_hash_size); |
21090 |
++ struct acl_subject_label **curr; |
21091 |
++ |
21092 |
++ obj->prev = NULL; |
21093 |
++ |
21094 |
++ curr = &role->subj_hash[index]; |
21095 |
++ if (*curr != NULL) |
21096 |
++ (*curr)->prev = obj; |
21097 |
++ |
21098 |
++ obj->next = *curr; |
21099 |
++ *curr = obj; |
21100 |
++ |
21101 |
++ return; |
21102 |
++} |
21103 |
++ |
21104 |
++/* allocating chained hash tables, so optimal size is where lambda ~ 1 */ |
21105 |
++ |
21106 |
++static void * |
21107 |
++create_table(__u32 * len, int elementsize) |
21108 |
++{ |
21109 |
++ unsigned int table_sizes[] = { |
21110 |
++ 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381, |
21111 |
++ 32749, 65521, 131071, 262139, 524287, 1048573, 2097143, |
21112 |
++ 4194301, 8388593, 16777213, 33554393, 67108859, 134217689, |
21113 |
++ 268435399, 536870909, 1073741789, 2147483647 |
21114 |
++ }; |
21115 |
++ void *newtable = NULL; |
21116 |
++ unsigned int pwr = 0; |
21117 |
++ |
21118 |
++ while ((pwr < ((sizeof (table_sizes) / sizeof (table_sizes[0])) - 1)) && |
21119 |
++ table_sizes[pwr] <= *len) |
21120 |
++ pwr++; |
21121 |
++ |
21122 |
++ if (table_sizes[pwr] <= *len) |
21123 |
++ return newtable; |
21124 |
++ |
21125 |
++ if ((table_sizes[pwr] * elementsize) <= PAGE_SIZE) |
21126 |
++ newtable = |
21127 |
++ kmalloc(table_sizes[pwr] * elementsize, GFP_KERNEL); |
21128 |
++ else |
21129 |
++ newtable = vmalloc(table_sizes[pwr] * elementsize); |
21130 |
++ |
21131 |
++ *len = table_sizes[pwr]; |
21132 |
++ |
21133 |
++ return newtable; |
21134 |
++} |
21135 |
++ |
21136 |
++static int |
21137 |
++init_variables(const struct gr_arg *arg) |
21138 |
++{ |
21139 |
++ struct task_struct *reaper = current->nsproxy->pid_ns->child_reaper; |
21140 |
++ unsigned int stacksize; |
21141 |
++ |
21142 |
++ subj_map_set.s_size = arg->role_db.num_subjects; |
21143 |
++ acl_role_set.r_size = arg->role_db.num_roles + arg->role_db.num_domain_children; |
21144 |
++ name_set.n_size = arg->role_db.num_objects; |
21145 |
++ inodev_set.i_size = arg->role_db.num_objects; |
21146 |
++ |
21147 |
++ if (!subj_map_set.s_size || !acl_role_set.r_size || |
21148 |
++ !name_set.n_size || !inodev_set.i_size) |
21149 |
++ return 1; |
21150 |
++ |
21151 |
++ if (!gr_init_uidset()) |
21152 |
++ return 1; |
21153 |
++ |
21154 |
++ /* set up the stack that holds allocation info */ |
21155 |
++ |
21156 |
++ stacksize = arg->role_db.num_pointers + 5; |
21157 |
++ |
21158 |
++ if (!acl_alloc_stack_init(stacksize)) |
21159 |
++ return 1; |
21160 |
++ |
21161 |
++ /* grab reference for the real root dentry and vfsmount */ |
21162 |
++ read_lock(&reaper->fs->lock); |
21163 |
++ real_root_mnt = mntget(reaper->fs->root.mnt); |
21164 |
++ real_root = dget(reaper->fs->root.dentry); |
21165 |
++ read_unlock(&reaper->fs->lock); |
21166 |
++ |
21167 |
++ fakefs_obj = acl_alloc(sizeof(struct acl_object_label)); |
21168 |
++ if (fakefs_obj == NULL) |
21169 |
++ return 1; |
21170 |
++ fakefs_obj->mode = GR_FIND | GR_READ | GR_WRITE | GR_EXEC; |
21171 |
++ |
21172 |
++ subj_map_set.s_hash = |
21173 |
++ (struct subject_map **) create_table(&subj_map_set.s_size, sizeof(void *)); |
21174 |
++ acl_role_set.r_hash = |
21175 |
++ (struct acl_role_label **) create_table(&acl_role_set.r_size, sizeof(void *)); |
21176 |
++ name_set.n_hash = (struct name_entry **) create_table(&name_set.n_size, sizeof(void *)); |
21177 |
++ inodev_set.i_hash = |
21178 |
++ (struct inodev_entry **) create_table(&inodev_set.i_size, sizeof(void *)); |
21179 |
++ |
21180 |
++ if (!subj_map_set.s_hash || !acl_role_set.r_hash || |
21181 |
++ !name_set.n_hash || !inodev_set.i_hash) |
21182 |
++ return 1; |
21183 |
++ |
21184 |
++ memset(subj_map_set.s_hash, 0, |
21185 |
++ sizeof(struct subject_map *) * subj_map_set.s_size); |
21186 |
++ memset(acl_role_set.r_hash, 0, |
21187 |
++ sizeof (struct acl_role_label *) * acl_role_set.r_size); |
21188 |
++ memset(name_set.n_hash, 0, |
21189 |
++ sizeof (struct name_entry *) * name_set.n_size); |
21190 |
++ memset(inodev_set.i_hash, 0, |
21191 |
++ sizeof (struct inodev_entry *) * inodev_set.i_size); |
21192 |
++ |
21193 |
++ return 0; |
21194 |
++} |
21195 |
++ |
21196 |
++/* free information not needed after startup |
21197 |
++ currently contains user->kernel pointer mappings for subjects |
21198 |
++*/ |
21199 |
++ |
21200 |
++static void |
21201 |
++free_init_variables(void) |
21202 |
++{ |
21203 |
++ __u32 i; |
21204 |
++ |
21205 |
++ if (subj_map_set.s_hash) { |
21206 |
++ for (i = 0; i < subj_map_set.s_size; i++) { |
21207 |
++ if (subj_map_set.s_hash[i]) { |
21208 |
++ kfree(subj_map_set.s_hash[i]); |
21209 |
++ subj_map_set.s_hash[i] = NULL; |
21210 |
++ } |
21211 |
++ } |
21212 |
++ |
21213 |
++ if ((subj_map_set.s_size * sizeof (struct subject_map *)) <= |
21214 |
++ PAGE_SIZE) |
21215 |
++ kfree(subj_map_set.s_hash); |
21216 |
++ else |
21217 |
++ vfree(subj_map_set.s_hash); |
21218 |
++ } |
21219 |
++ |
21220 |
++ return; |
21221 |
++} |
21222 |
++ |
21223 |
++static void |
21224 |
++free_variables(void) |
21225 |
++{ |
21226 |
++ struct acl_subject_label *s; |
21227 |
++ struct acl_role_label *r; |
21228 |
++ struct task_struct *task, *task2; |
21229 |
++ unsigned int i, x; |
21230 |
++ |
21231 |
++ gr_clear_learn_entries(); |
21232 |
++ |
21233 |
++ read_lock(&tasklist_lock); |
21234 |
++ do_each_thread(task2, task) { |
21235 |
++ task->acl_sp_role = 0; |
21236 |
++ task->acl_role_id = 0; |
21237 |
++ task->acl = NULL; |
21238 |
++ task->role = NULL; |
21239 |
++ } while_each_thread(task2, task); |
21240 |
++ read_unlock(&tasklist_lock); |
21241 |
++ |
21242 |
++ /* release the reference to the real root dentry and vfsmount */ |
21243 |
++ if (real_root) |
21244 |
++ dput(real_root); |
21245 |
++ real_root = NULL; |
21246 |
++ if (real_root_mnt) |
21247 |
++ mntput(real_root_mnt); |
21248 |
++ real_root_mnt = NULL; |
21249 |
++ |
21250 |
++ /* free all object hash tables */ |
21251 |
++ |
21252 |
++ FOR_EACH_ROLE_START(r, i) |
21253 |
++ if (r->subj_hash == NULL) |
21254 |
++ break; |
21255 |
++ FOR_EACH_SUBJECT_START(r, s, x) |
21256 |
++ if (s->obj_hash == NULL) |
21257 |
++ break; |
21258 |
++ if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE) |
21259 |
++ kfree(s->obj_hash); |
21260 |
++ else |
21261 |
++ vfree(s->obj_hash); |
21262 |
++ FOR_EACH_SUBJECT_END(s, x) |
21263 |
++ FOR_EACH_NESTED_SUBJECT_START(r, s) |
21264 |
++ if (s->obj_hash == NULL) |
21265 |
++ break; |
21266 |
++ if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE) |
21267 |
++ kfree(s->obj_hash); |
21268 |
++ else |
21269 |
++ vfree(s->obj_hash); |
21270 |
++ FOR_EACH_NESTED_SUBJECT_END(s) |
21271 |
++ if ((r->subj_hash_size * sizeof (struct acl_subject_label *)) <= PAGE_SIZE) |
21272 |
++ kfree(r->subj_hash); |
21273 |
++ else |
21274 |
++ vfree(r->subj_hash); |
21275 |
++ r->subj_hash = NULL; |
21276 |
++ FOR_EACH_ROLE_END(r,i) |
21277 |
++ |
21278 |
++ acl_free_all(); |
21279 |
++ |
21280 |
++ if (acl_role_set.r_hash) { |
21281 |
++ if ((acl_role_set.r_size * sizeof (struct acl_role_label *)) <= |
21282 |
++ PAGE_SIZE) |
21283 |
++ kfree(acl_role_set.r_hash); |
21284 |
++ else |
21285 |
++ vfree(acl_role_set.r_hash); |
21286 |
++ } |
21287 |
++ if (name_set.n_hash) { |
21288 |
++ if ((name_set.n_size * sizeof (struct name_entry *)) <= |
21289 |
++ PAGE_SIZE) |
21290 |
++ kfree(name_set.n_hash); |
21291 |
++ else |
21292 |
++ vfree(name_set.n_hash); |
21293 |
++ } |
21294 |
++ |
21295 |
++ if (inodev_set.i_hash) { |
21296 |
++ if ((inodev_set.i_size * sizeof (struct inodev_entry *)) <= |
21297 |
++ PAGE_SIZE) |
21298 |
++ kfree(inodev_set.i_hash); |
21299 |
++ else |
21300 |
++ vfree(inodev_set.i_hash); |
21301 |
++ } |
21302 |
++ |
21303 |
++ gr_free_uidset(); |
21304 |
++ |
21305 |
++ memset(&name_set, 0, sizeof (struct name_db)); |
21306 |
++ memset(&inodev_set, 0, sizeof (struct inodev_db)); |
21307 |
++ memset(&acl_role_set, 0, sizeof (struct acl_role_db)); |
21308 |
++ memset(&subj_map_set, 0, sizeof (struct acl_subj_map_db)); |
21309 |
++ |
21310 |
++ default_role = NULL; |
21311 |
++ |
21312 |
++ return; |
21313 |
++} |
21314 |
++ |
21315 |
++static __u32 |
21316 |
++count_user_objs(struct acl_object_label *userp) |
21317 |
++{ |
21318 |
++ struct acl_object_label o_tmp; |
21319 |
++ __u32 num = 0; |
21320 |
++ |
21321 |
++ while (userp) { |
21322 |
++ if (copy_from_user(&o_tmp, userp, |
21323 |
++ sizeof (struct acl_object_label))) |
21324 |
++ break; |
21325 |
++ |
21326 |
++ userp = o_tmp.prev; |
21327 |
++ num++; |
21328 |
++ } |
21329 |
++ |
21330 |
++ return num; |
21331 |
++} |
21332 |
++ |
21333 |
++static struct acl_subject_label * |
21334 |
++do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role); |
21335 |
++ |
21336 |
++static int |
21337 |
++copy_user_glob(struct acl_object_label *obj) |
21338 |
++{ |
21339 |
++ struct acl_object_label *g_tmp, **guser; |
21340 |
++ unsigned int len; |
21341 |
++ char *tmp; |
21342 |
++ |
21343 |
++ if (obj->globbed == NULL) |
21344 |
++ return 0; |
21345 |
++ |
21346 |
++ guser = &obj->globbed; |
21347 |
++ while (*guser) { |
21348 |
++ g_tmp = (struct acl_object_label *) |
21349 |
++ acl_alloc(sizeof (struct acl_object_label)); |
21350 |
++ if (g_tmp == NULL) |
21351 |
++ return -ENOMEM; |
21352 |
++ |
21353 |
++ if (copy_from_user(g_tmp, *guser, |
21354 |
++ sizeof (struct acl_object_label))) |
21355 |
++ return -EFAULT; |
21356 |
++ |
21357 |
++ len = strnlen_user(g_tmp->filename, PATH_MAX); |
21358 |
++ |
21359 |
++ if (!len || len >= PATH_MAX) |
21360 |
++ return -EINVAL; |
21361 |
++ |
21362 |
++ if ((tmp = (char *) acl_alloc(len)) == NULL) |
21363 |
++ return -ENOMEM; |
21364 |
++ |
21365 |
++ if (copy_from_user(tmp, g_tmp->filename, len)) |
21366 |
++ return -EFAULT; |
21367 |
++ |
21368 |
++ g_tmp->filename = tmp; |
21369 |
++ |
21370 |
++ *guser = g_tmp; |
21371 |
++ guser = &(g_tmp->next); |
21372 |
++ } |
21373 |
++ |
21374 |
++ return 0; |
21375 |
++} |
21376 |
++ |
21377 |
++static int |
21378 |
++copy_user_objs(struct acl_object_label *userp, struct acl_subject_label *subj, |
21379 |
++ struct acl_role_label *role) |
21380 |
++{ |
21381 |
++ struct acl_object_label *o_tmp; |
21382 |
++ unsigned int len; |
21383 |
++ int ret; |
21384 |
++ char *tmp; |
21385 |
++ |
21386 |
++ while (userp) { |
21387 |
++ if ((o_tmp = (struct acl_object_label *) |
21388 |
++ acl_alloc(sizeof (struct acl_object_label))) == NULL) |
21389 |
++ return -ENOMEM; |
21390 |
++ |
21391 |
++ if (copy_from_user(o_tmp, userp, |
21392 |
++ sizeof (struct acl_object_label))) |
21393 |
++ return -EFAULT; |
21394 |
++ |
21395 |
++ userp = o_tmp->prev; |
21396 |
++ |
21397 |
++ len = strnlen_user(o_tmp->filename, PATH_MAX); |
21398 |
++ |
21399 |
++ if (!len || len >= PATH_MAX) |
21400 |
++ return -EINVAL; |
21401 |
++ |
21402 |
++ if ((tmp = (char *) acl_alloc(len)) == NULL) |
21403 |
++ return -ENOMEM; |
21404 |
++ |
21405 |
++ if (copy_from_user(tmp, o_tmp->filename, len)) |
21406 |
++ return -EFAULT; |
21407 |
++ |
21408 |
++ o_tmp->filename = tmp; |
21409 |
++ |
21410 |
++ insert_acl_obj_label(o_tmp, subj); |
21411 |
++ if (!insert_name_entry(o_tmp->filename, o_tmp->inode, |
21412 |
++ o_tmp->device, (o_tmp->mode & GR_DELETED) ? 1 : 0)) |
21413 |
++ return -ENOMEM; |
21414 |
++ |
21415 |
++ ret = copy_user_glob(o_tmp); |
21416 |
++ if (ret) |
21417 |
++ return ret; |
21418 |
++ |
21419 |
++ if (o_tmp->nested) { |
21420 |
++ o_tmp->nested = do_copy_user_subj(o_tmp->nested, role); |
21421 |
++ if (IS_ERR(o_tmp->nested)) |
21422 |
++ return PTR_ERR(o_tmp->nested); |
21423 |
++ |
21424 |
++ /* insert into nested subject list */ |
21425 |
++ o_tmp->nested->next = role->hash->first; |
21426 |
++ role->hash->first = o_tmp->nested; |
21427 |
++ } |
21428 |
++ } |
21429 |
++ |
21430 |
++ return 0; |
21431 |
++} |
21432 |
++ |
21433 |
++static __u32 |
21434 |
++count_user_subjs(struct acl_subject_label *userp) |
21435 |
++{ |
21436 |
++ struct acl_subject_label s_tmp; |
21437 |
++ __u32 num = 0; |
21438 |
++ |
21439 |
++ while (userp) { |
21440 |
++ if (copy_from_user(&s_tmp, userp, |
21441 |
++ sizeof (struct acl_subject_label))) |
21442 |
++ break; |
21443 |
++ |
21444 |
++ userp = s_tmp.prev; |
21445 |
++ /* do not count nested subjects against this count, since |
21446 |
++ they are not included in the hash table, but are |
21447 |
++ attached to objects. We have already counted |
21448 |
++ the subjects in userspace for the allocation |
21449 |
++ stack |
21450 |
++ */ |
21451 |
++ if (!(s_tmp.mode & GR_NESTED)) |
21452 |
++ num++; |
21453 |
++ } |
21454 |
++ |
21455 |
++ return num; |
21456 |
++} |
21457 |
++ |
21458 |
++static int |
21459 |
++copy_user_allowedips(struct acl_role_label *rolep) |
21460 |
++{ |
21461 |
++ struct role_allowed_ip *ruserip, *rtmp = NULL, *rlast; |
21462 |
++ |
21463 |
++ ruserip = rolep->allowed_ips; |
21464 |
++ |
21465 |
++ while (ruserip) { |
21466 |
++ rlast = rtmp; |
21467 |
++ |
21468 |
++ if ((rtmp = (struct role_allowed_ip *) |
21469 |
++ acl_alloc(sizeof (struct role_allowed_ip))) == NULL) |
21470 |
++ return -ENOMEM; |
21471 |
++ |
21472 |
++ if (copy_from_user(rtmp, ruserip, |
21473 |
++ sizeof (struct role_allowed_ip))) |
21474 |
++ return -EFAULT; |
21475 |
++ |
21476 |
++ ruserip = rtmp->prev; |
21477 |
++ |
21478 |
++ if (!rlast) { |
21479 |
++ rtmp->prev = NULL; |
21480 |
++ rolep->allowed_ips = rtmp; |
21481 |
++ } else { |
21482 |
++ rlast->next = rtmp; |
21483 |
++ rtmp->prev = rlast; |
21484 |
++ } |
21485 |
++ |
21486 |
++ if (!ruserip) |
21487 |
++ rtmp->next = NULL; |
21488 |
++ } |
21489 |
++ |
21490 |
++ return 0; |
21491 |
++} |
21492 |
++ |
21493 |
++static int |
21494 |
++copy_user_transitions(struct acl_role_label *rolep) |
21495 |
++{ |
21496 |
++ struct role_transition *rusertp, *rtmp = NULL, *rlast; |
21497 |
++ |
21498 |
++ unsigned int len; |
21499 |
++ char *tmp; |
21500 |
++ |
21501 |
++ rusertp = rolep->transitions; |
21502 |
++ |
21503 |
++ while (rusertp) { |
21504 |
++ rlast = rtmp; |
21505 |
++ |
21506 |
++ if ((rtmp = (struct role_transition *) |
21507 |
++ acl_alloc(sizeof (struct role_transition))) == NULL) |
21508 |
++ return -ENOMEM; |
21509 |
++ |
21510 |
++ if (copy_from_user(rtmp, rusertp, |
21511 |
++ sizeof (struct role_transition))) |
21512 |
++ return -EFAULT; |
21513 |
++ |
21514 |
++ rusertp = rtmp->prev; |
21515 |
++ |
21516 |
++ len = strnlen_user(rtmp->rolename, GR_SPROLE_LEN); |
21517 |
++ |
21518 |
++ if (!len || len >= GR_SPROLE_LEN) |
21519 |
++ return -EINVAL; |
21520 |
++ |
21521 |
++ if ((tmp = (char *) acl_alloc(len)) == NULL) |
21522 |
++ return -ENOMEM; |
21523 |
++ |
21524 |
++ if (copy_from_user(tmp, rtmp->rolename, len)) |
21525 |
++ return -EFAULT; |
21526 |
++ |
21527 |
++ rtmp->rolename = tmp; |
21528 |
++ |
21529 |
++ if (!rlast) { |
21530 |
++ rtmp->prev = NULL; |
21531 |
++ rolep->transitions = rtmp; |
21532 |
++ } else { |
21533 |
++ rlast->next = rtmp; |
21534 |
++ rtmp->prev = rlast; |
21535 |
++ } |
21536 |
++ |
21537 |
++ if (!rusertp) |
21538 |
++ rtmp->next = NULL; |
21539 |
++ } |
21540 |
++ |
21541 |
++ return 0; |
21542 |
++} |
21543 |
++ |
21544 |
++static struct acl_subject_label * |
21545 |
++do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role) |
21546 |
++{ |
21547 |
++ struct acl_subject_label *s_tmp = NULL, *s_tmp2; |
21548 |
++ unsigned int len; |
21549 |
++ char *tmp; |
21550 |
++ __u32 num_objs; |
21551 |
++ struct acl_ip_label **i_tmp, *i_utmp2; |
21552 |
++ struct gr_hash_struct ghash; |
21553 |
++ struct subject_map *subjmap; |
21554 |
++ unsigned int i_num; |
21555 |
++ int err; |
21556 |
++ |
21557 |
++ s_tmp = lookup_subject_map(userp); |
21558 |
++ |
21559 |
++ /* we've already copied this subject into the kernel, just return |
21560 |
++ the reference to it, and don't copy it over again |
21561 |
++ */ |
21562 |
++ if (s_tmp) |
21563 |
++ return(s_tmp); |
21564 |
++ |
21565 |
++ if ((s_tmp = (struct acl_subject_label *) |
21566 |
++ acl_alloc(sizeof (struct acl_subject_label))) == NULL) |
21567 |
++ return ERR_PTR(-ENOMEM); |
21568 |
++ |
21569 |
++ subjmap = (struct subject_map *)kmalloc(sizeof (struct subject_map), GFP_KERNEL); |
21570 |
++ if (subjmap == NULL) |
21571 |
++ return ERR_PTR(-ENOMEM); |
21572 |
++ |
21573 |
++ subjmap->user = userp; |
21574 |
++ subjmap->kernel = s_tmp; |
21575 |
++ insert_subj_map_entry(subjmap); |
21576 |
++ |
21577 |
++ if (copy_from_user(s_tmp, userp, |
21578 |
++ sizeof (struct acl_subject_label))) |
21579 |
++ return ERR_PTR(-EFAULT); |
21580 |
++ |
21581 |
++ len = strnlen_user(s_tmp->filename, PATH_MAX); |
21582 |
++ |
21583 |
++ if (!len || len >= PATH_MAX) |
21584 |
++ return ERR_PTR(-EINVAL); |
21585 |
++ |
21586 |
++ if ((tmp = (char *) acl_alloc(len)) == NULL) |
21587 |
++ return ERR_PTR(-ENOMEM); |
21588 |
++ |
21589 |
++ if (copy_from_user(tmp, s_tmp->filename, len)) |
21590 |
++ return ERR_PTR(-EFAULT); |
21591 |
++ |
21592 |
++ s_tmp->filename = tmp; |
21593 |
++ |
21594 |
++ if (!strcmp(s_tmp->filename, "/")) |
21595 |
++ role->root_label = s_tmp; |
21596 |
++ |
21597 |
++ if (copy_from_user(&ghash, s_tmp->hash, sizeof(struct gr_hash_struct))) |
21598 |
++ return ERR_PTR(-EFAULT); |
21599 |
++ |
21600 |
++ /* copy user and group transition tables */ |
21601 |
++ |
21602 |
++ if (s_tmp->user_trans_num) { |
21603 |
++ uid_t *uidlist; |
21604 |
++ |
21605 |
++ uidlist = (uid_t *)acl_alloc(s_tmp->user_trans_num * sizeof(uid_t)); |
21606 |
++ if (uidlist == NULL) |
21607 |
++ return ERR_PTR(-ENOMEM); |
21608 |
++ if (copy_from_user(uidlist, s_tmp->user_transitions, s_tmp->user_trans_num * sizeof(uid_t))) |
21609 |
++ return ERR_PTR(-EFAULT); |
21610 |
++ |
21611 |
++ s_tmp->user_transitions = uidlist; |
21612 |
++ } |
21613 |
++ |
21614 |
++ if (s_tmp->group_trans_num) { |
21615 |
++ gid_t *gidlist; |
21616 |
++ |
21617 |
++ gidlist = (gid_t *)acl_alloc(s_tmp->group_trans_num * sizeof(gid_t)); |
21618 |
++ if (gidlist == NULL) |
21619 |
++ return ERR_PTR(-ENOMEM); |
21620 |
++ if (copy_from_user(gidlist, s_tmp->group_transitions, s_tmp->group_trans_num * sizeof(gid_t))) |
21621 |
++ return ERR_PTR(-EFAULT); |
21622 |
++ |
21623 |
++ s_tmp->group_transitions = gidlist; |
21624 |
++ } |
21625 |
++ |
21626 |
++ /* set up object hash table */ |
21627 |
++ num_objs = count_user_objs(ghash.first); |
21628 |
++ |
21629 |
++ s_tmp->obj_hash_size = num_objs; |
21630 |
++ s_tmp->obj_hash = |
21631 |
++ (struct acl_object_label **) |
21632 |
++ create_table(&(s_tmp->obj_hash_size), sizeof(void *)); |
21633 |
++ |
21634 |
++ if (!s_tmp->obj_hash) |
21635 |
++ return ERR_PTR(-ENOMEM); |
21636 |
++ |
21637 |
++ memset(s_tmp->obj_hash, 0, |
21638 |
++ s_tmp->obj_hash_size * |
21639 |
++ sizeof (struct acl_object_label *)); |
21640 |
++ |
21641 |
++ /* add in objects */ |
21642 |
++ err = copy_user_objs(ghash.first, s_tmp, role); |
21643 |
++ |
21644 |
++ if (err) |
21645 |
++ return ERR_PTR(err); |
21646 |
++ |
21647 |
++ /* set pointer for parent subject */ |
21648 |
++ if (s_tmp->parent_subject) { |
21649 |
++ s_tmp2 = do_copy_user_subj(s_tmp->parent_subject, role); |
21650 |
++ |
21651 |
++ if (IS_ERR(s_tmp2)) |
21652 |
++ return s_tmp2; |
21653 |
++ |
21654 |
++ s_tmp->parent_subject = s_tmp2; |
21655 |
++ } |
21656 |
++ |
21657 |
++ /* add in ip acls */ |
21658 |
++ |
21659 |
++ if (!s_tmp->ip_num) { |
21660 |
++ s_tmp->ips = NULL; |
21661 |
++ goto insert; |
21662 |
++ } |
21663 |
++ |
21664 |
++ i_tmp = |
21665 |
++ (struct acl_ip_label **) acl_alloc(s_tmp->ip_num * |
21666 |
++ sizeof (struct |
21667 |
++ acl_ip_label *)); |
21668 |
++ |
21669 |
++ if (!i_tmp) |
21670 |
++ return ERR_PTR(-ENOMEM); |
21671 |
++ |
21672 |
++ for (i_num = 0; i_num < s_tmp->ip_num; i_num++) { |
21673 |
++ *(i_tmp + i_num) = |
21674 |
++ (struct acl_ip_label *) |
21675 |
++ acl_alloc(sizeof (struct acl_ip_label)); |
21676 |
++ if (!*(i_tmp + i_num)) |
21677 |
++ return ERR_PTR(-ENOMEM); |
21678 |
++ |
21679 |
++ if (copy_from_user |
21680 |
++ (&i_utmp2, s_tmp->ips + i_num, |
21681 |
++ sizeof (struct acl_ip_label *))) |
21682 |
++ return ERR_PTR(-EFAULT); |
21683 |
++ |
21684 |
++ if (copy_from_user |
21685 |
++ (*(i_tmp + i_num), i_utmp2, |
21686 |
++ sizeof (struct acl_ip_label))) |
21687 |
++ return ERR_PTR(-EFAULT); |
21688 |
++ |
21689 |
++ if ((*(i_tmp + i_num))->iface == NULL) |
21690 |
++ continue; |
21691 |
++ |
21692 |
++ len = strnlen_user((*(i_tmp + i_num))->iface, IFNAMSIZ); |
21693 |
++ if (!len || len >= IFNAMSIZ) |
21694 |
++ return ERR_PTR(-EINVAL); |
21695 |
++ tmp = acl_alloc(len); |
21696 |
++ if (tmp == NULL) |
21697 |
++ return ERR_PTR(-ENOMEM); |
21698 |
++ if (copy_from_user(tmp, (*(i_tmp + i_num))->iface, len)) |
21699 |
++ return ERR_PTR(-EFAULT); |
21700 |
++ (*(i_tmp + i_num))->iface = tmp; |
21701 |
++ } |
21702 |
++ |
21703 |
++ s_tmp->ips = i_tmp; |
21704 |
++ |
21705 |
++insert: |
21706 |
++ if (!insert_name_entry(s_tmp->filename, s_tmp->inode, |
21707 |
++ s_tmp->device, (s_tmp->mode & GR_DELETED) ? 1 : 0)) |
21708 |
++ return ERR_PTR(-ENOMEM); |
21709 |
++ |
21710 |
++ return s_tmp; |
21711 |
++} |
21712 |
++ |
21713 |
++static int |
21714 |
++copy_user_subjs(struct acl_subject_label *userp, struct acl_role_label *role) |
21715 |
++{ |
21716 |
++ struct acl_subject_label s_pre; |
21717 |
++ struct acl_subject_label * ret; |
21718 |
++ int err; |
21719 |
++ |
21720 |
++ while (userp) { |
21721 |
++ if (copy_from_user(&s_pre, userp, |
21722 |
++ sizeof (struct acl_subject_label))) |
21723 |
++ return -EFAULT; |
21724 |
++ |
21725 |
++ /* do not add nested subjects here, add |
21726 |
++ while parsing objects |
21727 |
++ */ |
21728 |
++ |
21729 |
++ if (s_pre.mode & GR_NESTED) { |
21730 |
++ userp = s_pre.prev; |
21731 |
++ continue; |
21732 |
++ } |
21733 |
++ |
21734 |
++ ret = do_copy_user_subj(userp, role); |
21735 |
++ |
21736 |
++ err = PTR_ERR(ret); |
21737 |
++ if (IS_ERR(ret)) |
21738 |
++ return err; |
21739 |
++ |
21740 |
++ insert_acl_subj_label(ret, role); |
21741 |
++ |
21742 |
++ userp = s_pre.prev; |
21743 |
++ } |
21744 |
++ |
21745 |
++ return 0; |
21746 |
++} |
21747 |
++ |
21748 |
++static int |
21749 |
++copy_user_acl(struct gr_arg *arg) |
21750 |
++{ |
21751 |
++ struct acl_role_label *r_tmp = NULL, **r_utmp, *r_utmp2; |
21752 |
++ struct sprole_pw *sptmp; |
21753 |
++ struct gr_hash_struct *ghash; |
21754 |
++ uid_t *domainlist; |
21755 |
++ unsigned int r_num; |
21756 |
++ unsigned int len; |
21757 |
++ char *tmp; |
21758 |
++ int err = 0; |
21759 |
++ __u16 i; |
21760 |
++ __u32 num_subjs; |
21761 |
++ |
21762 |
++ /* we need a default and kernel role */ |
21763 |
++ if (arg->role_db.num_roles < 2) |
21764 |
++ return -EINVAL; |
21765 |
++ |
21766 |
++ /* copy special role authentication info from userspace */ |
21767 |
++ |
21768 |
++ num_sprole_pws = arg->num_sprole_pws; |
21769 |
++ acl_special_roles = (struct sprole_pw **) acl_alloc(num_sprole_pws * sizeof(struct sprole_pw *)); |
21770 |
++ |
21771 |
++ if (!acl_special_roles) { |
21772 |
++ err = -ENOMEM; |
21773 |
++ goto cleanup; |
21774 |
++ } |
21775 |
++ |
21776 |
++ for (i = 0; i < num_sprole_pws; i++) { |
21777 |
++ sptmp = (struct sprole_pw *) acl_alloc(sizeof(struct sprole_pw)); |
21778 |
++ if (!sptmp) { |
21779 |
++ err = -ENOMEM; |
21780 |
++ goto cleanup; |
21781 |
++ } |
21782 |
++ if (copy_from_user(sptmp, arg->sprole_pws + i, |
21783 |
++ sizeof (struct sprole_pw))) { |
21784 |
++ err = -EFAULT; |
21785 |
++ goto cleanup; |
21786 |
++ } |
21787 |
++ |
21788 |
++ len = |
21789 |
++ strnlen_user(sptmp->rolename, GR_SPROLE_LEN); |
21790 |
++ |
21791 |
++ if (!len || len >= GR_SPROLE_LEN) { |
21792 |
++ err = -EINVAL; |
21793 |
++ goto cleanup; |
21794 |
++ } |
21795 |
++ |
21796 |
++ if ((tmp = (char *) acl_alloc(len)) == NULL) { |
21797 |
++ err = -ENOMEM; |
21798 |
++ goto cleanup; |
21799 |
++ } |
21800 |
++ |
21801 |
++ if (copy_from_user(tmp, sptmp->rolename, len)) { |
21802 |
++ err = -EFAULT; |
21803 |
++ goto cleanup; |
21804 |
++ } |
21805 |
++ |
21806 |
++#ifdef CONFIG_GRKERNSEC_ACL_DEBUG |
21807 |
++ printk(KERN_ALERT "Copying special role %s\n", tmp); |
21808 |
++#endif |
21809 |
++ sptmp->rolename = tmp; |
21810 |
++ acl_special_roles[i] = sptmp; |
21811 |
++ } |
21812 |
++ |
21813 |
++ r_utmp = (struct acl_role_label **) arg->role_db.r_table; |
21814 |
++ |
21815 |
++ for (r_num = 0; r_num < arg->role_db.num_roles; r_num++) { |
21816 |
++ r_tmp = acl_alloc(sizeof (struct acl_role_label)); |
21817 |
++ |
21818 |
++ if (!r_tmp) { |
21819 |
++ err = -ENOMEM; |
21820 |
++ goto cleanup; |
21821 |
++ } |
21822 |
++ |
21823 |
++ if (copy_from_user(&r_utmp2, r_utmp + r_num, |
21824 |
++ sizeof (struct acl_role_label *))) { |
21825 |
++ err = -EFAULT; |
21826 |
++ goto cleanup; |
21827 |
++ } |
21828 |
++ |
21829 |
++ if (copy_from_user(r_tmp, r_utmp2, |
21830 |
++ sizeof (struct acl_role_label))) { |
21831 |
++ err = -EFAULT; |
21832 |
++ goto cleanup; |
21833 |
++ } |
21834 |
++ |
21835 |
++ len = strnlen_user(r_tmp->rolename, GR_SPROLE_LEN); |
21836 |
++ |
21837 |
++ if (!len || len >= PATH_MAX) { |
21838 |
++ err = -EINVAL; |
21839 |
++ goto cleanup; |
21840 |
++ } |
21841 |
++ |
21842 |
++ if ((tmp = (char *) acl_alloc(len)) == NULL) { |
21843 |
++ err = -ENOMEM; |
21844 |
++ goto cleanup; |
21845 |
++ } |
21846 |
++ if (copy_from_user(tmp, r_tmp->rolename, len)) { |
21847 |
++ err = -EFAULT; |
21848 |
++ goto cleanup; |
21849 |
++ } |
21850 |
++ r_tmp->rolename = tmp; |
21851 |
++ |
21852 |
++ if (!strcmp(r_tmp->rolename, "default") |
21853 |
++ && (r_tmp->roletype & GR_ROLE_DEFAULT)) { |
21854 |
++ default_role = r_tmp; |
21855 |
++ } else if (!strcmp(r_tmp->rolename, ":::kernel:::")) { |
21856 |
++ kernel_role = r_tmp; |
21857 |
++ } |
21858 |
++ |
21859 |
++ if ((ghash = (struct gr_hash_struct *) acl_alloc(sizeof(struct gr_hash_struct))) == NULL) { |
21860 |
++ err = -ENOMEM; |
21861 |
++ goto cleanup; |
21862 |
++ } |
21863 |
++ if (copy_from_user(ghash, r_tmp->hash, sizeof(struct gr_hash_struct))) { |
21864 |
++ err = -EFAULT; |
21865 |
++ goto cleanup; |
21866 |
++ } |
21867 |
++ |
21868 |
++ r_tmp->hash = ghash; |
21869 |
++ |
21870 |
++ num_subjs = count_user_subjs(r_tmp->hash->first); |
21871 |
++ |
21872 |
++ r_tmp->subj_hash_size = num_subjs; |
21873 |
++ r_tmp->subj_hash = |
21874 |
++ (struct acl_subject_label **) |
21875 |
++ create_table(&(r_tmp->subj_hash_size), sizeof(void *)); |
21876 |
++ |
21877 |
++ if (!r_tmp->subj_hash) { |
21878 |
++ err = -ENOMEM; |
21879 |
++ goto cleanup; |
21880 |
++ } |
21881 |
++ |
21882 |
++ err = copy_user_allowedips(r_tmp); |
21883 |
++ if (err) |
21884 |
++ goto cleanup; |
21885 |
++ |
21886 |
++ /* copy domain info */ |
21887 |
++ if (r_tmp->domain_children != NULL) { |
21888 |
++ domainlist = acl_alloc(r_tmp->domain_child_num * sizeof(uid_t)); |
21889 |
++ if (domainlist == NULL) { |
21890 |
++ err = -ENOMEM; |
21891 |
++ goto cleanup; |
21892 |
++ } |
21893 |
++ if (copy_from_user(domainlist, r_tmp->domain_children, r_tmp->domain_child_num * sizeof(uid_t))) { |
21894 |
++ err = -EFAULT; |
21895 |
++ goto cleanup; |
21896 |
++ } |
21897 |
++ r_tmp->domain_children = domainlist; |
21898 |
++ } |
21899 |
++ |
21900 |
++ err = copy_user_transitions(r_tmp); |
21901 |
++ if (err) |
21902 |
++ goto cleanup; |
21903 |
++ |
21904 |
++ memset(r_tmp->subj_hash, 0, |
21905 |
++ r_tmp->subj_hash_size * |
21906 |
++ sizeof (struct acl_subject_label *)); |
21907 |
++ |
21908 |
++ err = copy_user_subjs(r_tmp->hash->first, r_tmp); |
21909 |
++ |
21910 |
++ if (err) |
21911 |
++ goto cleanup; |
21912 |
++ |
21913 |
++ /* set nested subject list to null */ |
21914 |
++ r_tmp->hash->first = NULL; |
21915 |
++ |
21916 |
++ insert_acl_role_label(r_tmp); |
21917 |
++ } |
21918 |
++ |
21919 |
++ goto return_err; |
21920 |
++ cleanup: |
21921 |
++ free_variables(); |
21922 |
++ return_err: |
21923 |
++ return err; |
21924 |
++ |
21925 |
++} |
21926 |
++ |
21927 |
++static int |
21928 |
++gracl_init(struct gr_arg *args) |
21929 |
++{ |
21930 |
++ int error = 0; |
21931 |
++ |
21932 |
++ memcpy(gr_system_salt, args->salt, GR_SALT_LEN); |
21933 |
++ memcpy(gr_system_sum, args->sum, GR_SHA_LEN); |
21934 |
++ |
21935 |
++ if (init_variables(args)) { |
21936 |
++ gr_log_str(GR_DONT_AUDIT_GOOD, GR_INITF_ACL_MSG, GR_VERSION); |
21937 |
++ error = -ENOMEM; |
21938 |
++ free_variables(); |
21939 |
++ goto out; |
21940 |
++ } |
21941 |
++ |
21942 |
++ error = copy_user_acl(args); |
21943 |
++ free_init_variables(); |
21944 |
++ if (error) { |
21945 |
++ free_variables(); |
21946 |
++ goto out; |
21947 |
++ } |
21948 |
++ |
21949 |
++ if ((error = gr_set_acls(0))) { |
21950 |
++ free_variables(); |
21951 |
++ goto out; |
21952 |
++ } |
21953 |
++ |
21954 |
++ gr_status |= GR_READY; |
21955 |
++ out: |
21956 |
++ return error; |
21957 |
++} |
21958 |
++ |
21959 |
++/* derived from glibc fnmatch() 0: match, 1: no match*/ |
21960 |
++ |
21961 |
++static int |
21962 |
++glob_match(const char *p, const char *n) |
21963 |
++{ |
21964 |
++ char c; |
21965 |
++ |
21966 |
++ while ((c = *p++) != '\0') { |
21967 |
++ switch (c) { |
21968 |
++ case '?': |
21969 |
++ if (*n == '\0') |
21970 |
++ return 1; |
21971 |
++ else if (*n == '/') |
21972 |
++ return 1; |
21973 |
++ break; |
21974 |
++ case '\\': |
21975 |
++ if (*n != c) |
21976 |
++ return 1; |
21977 |
++ break; |
21978 |
++ case '*': |
21979 |
++ for (c = *p++; c == '?' || c == '*'; c = *p++) { |
21980 |
++ if (*n == '/') |
21981 |
++ return 1; |
21982 |
++ else if (c == '?') { |
21983 |
++ if (*n == '\0') |
21984 |
++ return 1; |
21985 |
++ else |
21986 |
++ ++n; |
21987 |
++ } |
21988 |
++ } |
21989 |
++ if (c == '\0') { |
21990 |
++ return 0; |
21991 |
++ } else { |
21992 |
++ const char *endp; |
21993 |
++ |
21994 |
++ if ((endp = strchr(n, '/')) == NULL) |
21995 |
++ endp = n + strlen(n); |
21996 |
++ |
21997 |
++ if (c == '[') { |
21998 |
++ for (--p; n < endp; ++n) |
21999 |
++ if (!glob_match(p, n)) |
22000 |
++ return 0; |
22001 |
++ } else if (c == '/') { |
22002 |
++ while (*n != '\0' && *n != '/') |
22003 |
++ ++n; |
22004 |
++ if (*n == '/' && !glob_match(p, n + 1)) |
22005 |
++ return 0; |
22006 |
++ } else { |
22007 |
++ for (--p; n < endp; ++n) |
22008 |
++ if (*n == c && !glob_match(p, n)) |
22009 |
++ return 0; |
22010 |
++ } |
22011 |
++ |
22012 |
++ return 1; |
22013 |
++ } |
22014 |
++ case '[': |
22015 |
++ { |
22016 |
++ int not; |
22017 |
++ char cold; |
22018 |
++ |
22019 |
++ if (*n == '\0' || *n == '/') |
22020 |
++ return 1; |
22021 |
++ |
22022 |
++ not = (*p == '!' || *p == '^'); |
22023 |
++ if (not) |
22024 |
++ ++p; |
22025 |
++ |
22026 |
++ c = *p++; |
22027 |
++ for (;;) { |
22028 |
++ unsigned char fn = (unsigned char)*n; |
22029 |
++ |
22030 |
++ if (c == '\0') |
22031 |
++ return 1; |
22032 |
++ else { |
22033 |
++ if (c == fn) |
22034 |
++ goto matched; |
22035 |
++ cold = c; |
22036 |
++ c = *p++; |
22037 |
++ |
22038 |
++ if (c == '-' && *p != ']') { |
22039 |
++ unsigned char cend = *p++; |
22040 |
++ |
22041 |
++ if (cend == '\0') |
22042 |
++ return 1; |
22043 |
++ |
22044 |
++ if (cold <= fn && fn <= cend) |
22045 |
++ goto matched; |
22046 |
++ |
22047 |
++ c = *p++; |
22048 |
++ } |
22049 |
++ } |
22050 |
++ |
22051 |
++ if (c == ']') |
22052 |
++ break; |
22053 |
++ } |
22054 |
++ if (!not) |
22055 |
++ return 1; |
22056 |
++ break; |
22057 |
++ matched: |
22058 |
++ while (c != ']') { |
22059 |
++ if (c == '\0') |
22060 |
++ return 1; |
22061 |
++ |
22062 |
++ c = *p++; |
22063 |
++ } |
22064 |
++ if (not) |
22065 |
++ return 1; |
22066 |
++ } |
22067 |
++ break; |
22068 |
++ default: |
22069 |
++ if (c != *n) |
22070 |
++ return 1; |
22071 |
++ } |
22072 |
++ |
22073 |
++ ++n; |
22074 |
++ } |
22075 |
++ |
22076 |
++ if (*n == '\0') |
22077 |
++ return 0; |
22078 |
++ |
22079 |
++ if (*n == '/') |
22080 |
++ return 0; |
22081 |
++ |
22082 |
++ return 1; |
22083 |
++} |
22084 |
++ |
22085 |
++static struct acl_object_label * |
22086 |
++chk_glob_label(struct acl_object_label *globbed, |
22087 |
++ struct dentry *dentry, struct vfsmount *mnt, char **path) |
22088 |
++{ |
22089 |
++ struct acl_object_label *tmp; |
22090 |
++ |
22091 |
++ if (*path == NULL) |
22092 |
++ *path = gr_to_filename_nolock(dentry, mnt); |
22093 |
++ |
22094 |
++ tmp = globbed; |
22095 |
++ |
22096 |
++ while (tmp) { |
22097 |
++ if (!glob_match(tmp->filename, *path)) |
22098 |
++ return tmp; |
22099 |
++ tmp = tmp->next; |
22100 |
++ } |
22101 |
++ |
22102 |
++ return NULL; |
22103 |
++} |
22104 |
++ |
22105 |
++static struct acl_object_label * |
22106 |
++__full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt, |
22107 |
++ const ino_t curr_ino, const dev_t curr_dev, |
22108 |
++ const struct acl_subject_label *subj, char **path) |
22109 |
++{ |
22110 |
++ struct acl_subject_label *tmpsubj; |
22111 |
++ struct acl_object_label *retval; |
22112 |
++ struct acl_object_label *retval2; |
22113 |
++ |
22114 |
++ tmpsubj = (struct acl_subject_label *) subj; |
22115 |
++ read_lock(&gr_inode_lock); |
22116 |
++ do { |
22117 |
++ retval = lookup_acl_obj_label(curr_ino, curr_dev, tmpsubj); |
22118 |
++ if (retval) { |
22119 |
++ if (retval->globbed) { |
22120 |
++ retval2 = chk_glob_label(retval->globbed, (struct dentry *)orig_dentry, |
22121 |
++ (struct vfsmount *)orig_mnt, path); |
22122 |
++ if (retval2) |
22123 |
++ retval = retval2; |
22124 |
++ } |
22125 |
++ break; |
22126 |
++ } |
22127 |
++ } while ((tmpsubj = tmpsubj->parent_subject)); |
22128 |
++ read_unlock(&gr_inode_lock); |
22129 |
++ |
22130 |
++ return retval; |
22131 |
++} |
22132 |
++ |
22133 |
++static __inline__ struct acl_object_label * |
22134 |
++full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt, |
22135 |
++ const struct dentry *curr_dentry, |
22136 |
++ const struct acl_subject_label *subj, char **path) |
22137 |
++{ |
22138 |
++ return __full_lookup(orig_dentry, orig_mnt, |
22139 |
++ curr_dentry->d_inode->i_ino, |
22140 |
++ curr_dentry->d_inode->i_sb->s_dev, subj, path); |
22141 |
++} |
22142 |
++ |
22143 |
++static struct acl_object_label * |
22144 |
++__chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt, |
22145 |
++ const struct acl_subject_label *subj, char *path) |
22146 |
++{ |
22147 |
++ struct dentry *dentry = (struct dentry *) l_dentry; |
22148 |
++ struct vfsmount *mnt = (struct vfsmount *) l_mnt; |
22149 |
++ struct acl_object_label *retval; |
22150 |
++ |
22151 |
++ spin_lock(&dcache_lock); |
22152 |
++ |
22153 |
++ if (unlikely(mnt == shm_mnt || mnt == pipe_mnt || mnt == sock_mnt || |
22154 |
++ /* ignore Eric Biederman */ |
22155 |
++ IS_PRIVATE(l_dentry->d_inode))) { |
22156 |
++ retval = fakefs_obj; |
22157 |
++ goto out; |
22158 |
++ } |
22159 |
++ |
22160 |
++ for (;;) { |
22161 |
++ if (dentry == real_root && mnt == real_root_mnt) |
22162 |
++ break; |
22163 |
++ |
22164 |
++ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) { |
22165 |
++ if (mnt->mnt_parent == mnt) |
22166 |
++ break; |
22167 |
++ |
22168 |
++ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path); |
22169 |
++ if (retval != NULL) |
22170 |
++ goto out; |
22171 |
++ |
22172 |
++ dentry = mnt->mnt_mountpoint; |
22173 |
++ mnt = mnt->mnt_parent; |
22174 |
++ continue; |
22175 |
++ } |
22176 |
++ |
22177 |
++ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path); |
22178 |
++ if (retval != NULL) |
22179 |
++ goto out; |
22180 |
++ |
22181 |
++ dentry = dentry->d_parent; |
22182 |
++ } |
22183 |
++ |
22184 |
++ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path); |
22185 |
++ |
22186 |
++ if (retval == NULL) |
22187 |
++ retval = full_lookup(l_dentry, l_mnt, real_root, subj, &path); |
22188 |
++out: |
22189 |
++ spin_unlock(&dcache_lock); |
22190 |
++ return retval; |
22191 |
++} |
22192 |
++ |
22193 |
++static __inline__ struct acl_object_label * |
22194 |
++chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt, |
22195 |
++ const struct acl_subject_label *subj) |
22196 |
++{ |
22197 |
++ char *path = NULL; |
22198 |
++ return __chk_obj_label(l_dentry, l_mnt, subj, path); |
22199 |
++} |
22200 |
++ |
22201 |
++static __inline__ struct acl_object_label * |
22202 |
++chk_obj_create_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt, |
22203 |
++ const struct acl_subject_label *subj, char *path) |
22204 |
++{ |
22205 |
++ return __chk_obj_label(l_dentry, l_mnt, subj, path); |
22206 |
++} |
22207 |
++ |
22208 |
++static struct acl_subject_label * |
22209 |
++chk_subj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt, |
22210 |
++ const struct acl_role_label *role) |
22211 |
++{ |
22212 |
++ struct dentry *dentry = (struct dentry *) l_dentry; |
22213 |
++ struct vfsmount *mnt = (struct vfsmount *) l_mnt; |
22214 |
++ struct acl_subject_label *retval; |
22215 |
++ |
22216 |
++ spin_lock(&dcache_lock); |
22217 |
++ |
22218 |
++ for (;;) { |
22219 |
++ if (dentry == real_root && mnt == real_root_mnt) |
22220 |
++ break; |
22221 |
++ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) { |
22222 |
++ if (mnt->mnt_parent == mnt) |
22223 |
++ break; |
22224 |
++ |
22225 |
++ read_lock(&gr_inode_lock); |
22226 |
++ retval = |
22227 |
++ lookup_acl_subj_label(dentry->d_inode->i_ino, |
22228 |
++ dentry->d_inode->i_sb->s_dev, role); |
22229 |
++ read_unlock(&gr_inode_lock); |
22230 |
++ if (retval != NULL) |
22231 |
++ goto out; |
22232 |
++ |
22233 |
++ dentry = mnt->mnt_mountpoint; |
22234 |
++ mnt = mnt->mnt_parent; |
22235 |
++ continue; |
22236 |
++ } |
22237 |
++ |
22238 |
++ read_lock(&gr_inode_lock); |
22239 |
++ retval = lookup_acl_subj_label(dentry->d_inode->i_ino, |
22240 |
++ dentry->d_inode->i_sb->s_dev, role); |
22241 |
++ read_unlock(&gr_inode_lock); |
22242 |
++ if (retval != NULL) |
22243 |
++ goto out; |
22244 |
++ |
22245 |
++ dentry = dentry->d_parent; |
22246 |
++ } |
22247 |
++ |
22248 |
++ read_lock(&gr_inode_lock); |
22249 |
++ retval = lookup_acl_subj_label(dentry->d_inode->i_ino, |
22250 |
++ dentry->d_inode->i_sb->s_dev, role); |
22251 |
++ read_unlock(&gr_inode_lock); |
22252 |
++ |
22253 |
++ if (unlikely(retval == NULL)) { |
22254 |
++ read_lock(&gr_inode_lock); |
22255 |
++ retval = lookup_acl_subj_label(real_root->d_inode->i_ino, |
22256 |
++ real_root->d_inode->i_sb->s_dev, role); |
22257 |
++ read_unlock(&gr_inode_lock); |
22258 |
++ } |
22259 |
++out: |
22260 |
++ spin_unlock(&dcache_lock); |
22261 |
++ |
22262 |
++ return retval; |
22263 |
++} |
22264 |
++ |
22265 |
++static void |
22266 |
++gr_log_learn(const struct task_struct *task, const struct dentry *dentry, const struct vfsmount *mnt, const __u32 mode) |
22267 |
++{ |
22268 |
++ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, task->role->roletype, |
22269 |
++ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry, |
22270 |
++ task->exec_file->f_path.mnt) : task->acl->filename, task->acl->filename, |
22271 |
++ 1, 1, gr_to_filename(dentry, mnt), (unsigned long) mode, NIPQUAD(task->signal->curr_ip)); |
22272 |
++ |
22273 |
++ return; |
22274 |
++} |
22275 |
++ |
22276 |
++static void |
22277 |
++gr_log_learn_sysctl(const struct task_struct *task, const char *path, const __u32 mode) |
22278 |
++{ |
22279 |
++ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, task->role->roletype, |
22280 |
++ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry, |
22281 |
++ task->exec_file->f_path.mnt) : task->acl->filename, task->acl->filename, |
22282 |
++ 1, 1, path, (unsigned long) mode, NIPQUAD(task->signal->curr_ip)); |
22283 |
++ |
22284 |
++ return; |
22285 |
++} |
22286 |
++ |
22287 |
++static void |
22288 |
++gr_log_learn_id_change(const struct task_struct *task, const char type, const unsigned int real, |
22289 |
++ const unsigned int effective, const unsigned int fs) |
22290 |
++{ |
22291 |
++ security_learn(GR_ID_LEARN_MSG, task->role->rolename, task->role->roletype, |
22292 |
++ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_path.dentry, |
22293 |
++ task->exec_file->f_path.mnt) : task->acl->filename, task->acl->filename, |
22294 |
++ type, real, effective, fs, NIPQUAD(task->signal->curr_ip)); |
22295 |
++ |
22296 |
++ return; |
22297 |
++} |
22298 |
++ |
22299 |
++__u32 |
22300 |
++gr_check_link(const struct dentry * new_dentry, |
22301 |
++ const struct dentry * parent_dentry, |
22302 |
++ const struct vfsmount * parent_mnt, |
22303 |
++ const struct dentry * old_dentry, const struct vfsmount * old_mnt) |
22304 |
++{ |
22305 |
++ struct acl_object_label *obj; |
22306 |
++ __u32 oldmode, newmode; |
22307 |
++ __u32 needmode; |
22308 |
++ |
22309 |
++ if (unlikely(!(gr_status & GR_READY))) |
22310 |
++ return (GR_CREATE | GR_LINK); |
22311 |
++ |
22312 |
++ obj = chk_obj_label(old_dentry, old_mnt, current->acl); |
22313 |
++ oldmode = obj->mode; |
22314 |
++ |
22315 |
++ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) |
22316 |
++ oldmode |= (GR_CREATE | GR_LINK); |
22317 |
++ |
22318 |
++ needmode = GR_CREATE | GR_AUDIT_CREATE | GR_SUPPRESS; |
22319 |
++ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID)) |
22320 |
++ needmode |= GR_SETID | GR_AUDIT_SETID; |
22321 |
++ |
22322 |
++ newmode = |
22323 |
++ gr_check_create(new_dentry, parent_dentry, parent_mnt, |
22324 |
++ oldmode | needmode); |
22325 |
++ |
22326 |
++ needmode = newmode & (GR_FIND | GR_APPEND | GR_WRITE | GR_EXEC | |
22327 |
++ GR_SETID | GR_READ | GR_FIND | GR_DELETE | |
22328 |
++ GR_INHERIT | GR_AUDIT_INHERIT); |
22329 |
++ |
22330 |
++ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID) && !(newmode & GR_SETID)) |
22331 |
++ goto bad; |
22332 |
++ |
22333 |
++ if ((oldmode & needmode) != needmode) |
22334 |
++ goto bad; |
22335 |
++ |
22336 |
++ needmode = oldmode & (GR_NOPTRACE | GR_PTRACERD | GR_INHERIT | GR_AUDITS); |
22337 |
++ if ((newmode & needmode) != needmode) |
22338 |
++ goto bad; |
22339 |
++ |
22340 |
++ if ((newmode & (GR_CREATE | GR_LINK)) == (GR_CREATE | GR_LINK)) |
22341 |
++ return newmode; |
22342 |
++bad: |
22343 |
++ needmode = oldmode; |
22344 |
++ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID)) |
22345 |
++ needmode |= GR_SETID; |
22346 |
++ |
22347 |
++ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) { |
22348 |
++ gr_log_learn(current, old_dentry, old_mnt, needmode); |
22349 |
++ return (GR_CREATE | GR_LINK); |
22350 |
++ } else if (newmode & GR_SUPPRESS) |
22351 |
++ return GR_SUPPRESS; |
22352 |
++ else |
22353 |
++ return 0; |
22354 |
++} |
22355 |
++ |
22356 |
++__u32 |
22357 |
++gr_search_file(const struct dentry * dentry, const __u32 mode, |
22358 |
++ const struct vfsmount * mnt) |
22359 |
++{ |
22360 |
++ __u32 retval = mode; |
22361 |
++ struct acl_subject_label *curracl; |
22362 |
++ struct acl_object_label *currobj; |
22363 |
++ |
22364 |
++ if (unlikely(!(gr_status & GR_READY))) |
22365 |
++ return (mode & ~GR_AUDITS); |
22366 |
++ |
22367 |
++ curracl = current->acl; |
22368 |
++ |
22369 |
++ currobj = chk_obj_label(dentry, mnt, curracl); |
22370 |
++ retval = currobj->mode & mode; |
22371 |
++ |
22372 |
++ if (unlikely |
22373 |
++ ((curracl->mode & (GR_LEARN | GR_INHERITLEARN)) && !(mode & GR_NOPTRACE) |
22374 |
++ && (retval != (mode & ~(GR_AUDITS | GR_SUPPRESS))))) { |
22375 |
++ __u32 new_mode = mode; |
22376 |
++ |
22377 |
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS); |
22378 |
++ |
22379 |
++ retval = new_mode; |
22380 |
++ |
22381 |
++ if (new_mode & GR_EXEC && curracl->mode & GR_INHERITLEARN) |
22382 |
++ new_mode |= GR_INHERIT; |
22383 |
++ |
22384 |
++ if (!(mode & GR_NOLEARN)) |
22385 |
++ gr_log_learn(current, dentry, mnt, new_mode); |
22386 |
++ } |
22387 |
++ |
22388 |
++ return retval; |
22389 |
++} |
22390 |
++ |
22391 |
++__u32 |
22392 |
++gr_check_create(const struct dentry * new_dentry, const struct dentry * parent, |
22393 |
++ const struct vfsmount * mnt, const __u32 mode) |
22394 |
++{ |
22395 |
++ struct name_entry *match; |
22396 |
++ struct acl_object_label *matchpo; |
22397 |
++ struct acl_subject_label *curracl; |
22398 |
++ char *path; |
22399 |
++ __u32 retval; |
22400 |
++ |
22401 |
++ if (unlikely(!(gr_status & GR_READY))) |
22402 |
++ return (mode & ~GR_AUDITS); |
22403 |
++ |
22404 |
++ preempt_disable(); |
22405 |
++ path = gr_to_filename_rbac(new_dentry, mnt); |
22406 |
++ match = lookup_name_entry_create(path); |
22407 |
++ |
22408 |
++ if (!match) |
22409 |
++ goto check_parent; |
22410 |
++ |
22411 |
++ curracl = current->acl; |
22412 |
++ |
22413 |
++ read_lock(&gr_inode_lock); |
22414 |
++ matchpo = lookup_acl_obj_label_create(match->inode, match->device, curracl); |
22415 |
++ read_unlock(&gr_inode_lock); |
22416 |
++ |
22417 |
++ if (matchpo) { |
22418 |
++ if ((matchpo->mode & mode) != |
22419 |
++ (mode & ~(GR_AUDITS | GR_SUPPRESS)) |
22420 |
++ && curracl->mode & (GR_LEARN | GR_INHERITLEARN)) { |
22421 |
++ __u32 new_mode = mode; |
22422 |
++ |
22423 |
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS); |
22424 |
++ |
22425 |
++ gr_log_learn(current, new_dentry, mnt, new_mode); |
22426 |
++ |
22427 |
++ preempt_enable(); |
22428 |
++ return new_mode; |
22429 |
++ } |
22430 |
++ preempt_enable(); |
22431 |
++ return (matchpo->mode & mode); |
22432 |
++ } |
22433 |
++ |
22434 |
++ check_parent: |
22435 |
++ curracl = current->acl; |
22436 |
++ |
22437 |
++ matchpo = chk_obj_create_label(parent, mnt, curracl, path); |
22438 |
++ retval = matchpo->mode & mode; |
22439 |
++ |
22440 |
++ if ((retval != (mode & ~(GR_AUDITS | GR_SUPPRESS))) |
22441 |
++ && (curracl->mode & (GR_LEARN | GR_INHERITLEARN))) { |
22442 |
++ __u32 new_mode = mode; |
22443 |
++ |
22444 |
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS); |
22445 |
++ |
22446 |
++ gr_log_learn(current, new_dentry, mnt, new_mode); |
22447 |
++ preempt_enable(); |
22448 |
++ return new_mode; |
22449 |
++ } |
22450 |
++ |
22451 |
++ preempt_enable(); |
22452 |
++ return retval; |
22453 |
++} |
22454 |
++ |
22455 |
++int |
22456 |
++gr_check_hidden_task(const struct task_struct *task) |
22457 |
++{ |
22458 |
++ if (unlikely(!(gr_status & GR_READY))) |
22459 |
++ return 0; |
22460 |
++ |
22461 |
++ if (!(task->acl->mode & GR_PROCFIND) && !(current->acl->mode & GR_VIEW)) |
22462 |
++ return 1; |
22463 |
++ |
22464 |
++ return 0; |
22465 |
++} |
22466 |
++ |
22467 |
++int |
22468 |
++gr_check_protected_task(const struct task_struct *task) |
22469 |
++{ |
22470 |
++ if (unlikely(!(gr_status & GR_READY) || !task)) |
22471 |
++ return 0; |
22472 |
++ |
22473 |
++ if ((task->acl->mode & GR_PROTECTED) && !(current->acl->mode & GR_KILL) && |
22474 |
++ task->acl != current->acl) |
22475 |
++ return 1; |
22476 |
++ |
22477 |
++ return 0; |
22478 |
++} |
22479 |
++ |
22480 |
++void |
22481 |
++gr_copy_label(struct task_struct *tsk) |
22482 |
++{ |
22483 |
++ tsk->signal->used_accept = 0; |
22484 |
++ tsk->acl_sp_role = 0; |
22485 |
++ tsk->acl_role_id = current->acl_role_id; |
22486 |
++ tsk->acl = current->acl; |
22487 |
++ tsk->role = current->role; |
22488 |
++ tsk->signal->curr_ip = current->signal->curr_ip; |
22489 |
++ if (current->exec_file) |
22490 |
++ get_file(current->exec_file); |
22491 |
++ tsk->exec_file = current->exec_file; |
22492 |
++ tsk->is_writable = current->is_writable; |
22493 |
++ if (unlikely(current->signal->used_accept)) |
22494 |
++ current->signal->curr_ip = 0; |
22495 |
++ |
22496 |
++ return; |
22497 |
++} |
22498 |
++ |
22499 |
++static void |
22500 |
++gr_set_proc_res(struct task_struct *task) |
22501 |
++{ |
22502 |
++ struct acl_subject_label *proc; |
22503 |
++ unsigned short i; |
22504 |
++ |
22505 |
++ proc = task->acl; |
22506 |
++ |
22507 |
++ if (proc->mode & (GR_LEARN | GR_INHERITLEARN)) |
22508 |
++ return; |
22509 |
++ |
22510 |
++ for (i = 0; i < (GR_NLIMITS - 1); i++) { |
22511 |
++ if (!(proc->resmask & (1 << i))) |
22512 |
++ continue; |
22513 |
++ |
22514 |
++ task->signal->rlim[i].rlim_cur = proc->res[i].rlim_cur; |
22515 |
++ task->signal->rlim[i].rlim_max = proc->res[i].rlim_max; |
22516 |
++ } |
22517 |
++ |
22518 |
++ return; |
22519 |
++} |
22520 |
++ |
22521 |
++int |
22522 |
++gr_check_user_change(int real, int effective, int fs) |
22523 |
++{ |
22524 |
++ unsigned int i; |
22525 |
++ __u16 num; |
22526 |
++ uid_t *uidlist; |
22527 |
++ int curuid; |
22528 |
++ int realok = 0; |
22529 |
++ int effectiveok = 0; |
22530 |
++ int fsok = 0; |
22531 |
++ |
22532 |
++ if (unlikely(!(gr_status & GR_READY))) |
22533 |
++ return 0; |
22534 |
++ |
22535 |
++ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) |
22536 |
++ gr_log_learn_id_change(current, 'u', real, effective, fs); |
22537 |
++ |
22538 |
++ num = current->acl->user_trans_num; |
22539 |
++ uidlist = current->acl->user_transitions; |
22540 |
++ |
22541 |
++ if (uidlist == NULL) |
22542 |
++ return 0; |
22543 |
++ |
22544 |
++ if (real == -1) |
22545 |
++ realok = 1; |
22546 |
++ if (effective == -1) |
22547 |
++ effectiveok = 1; |
22548 |
++ if (fs == -1) |
22549 |
++ fsok = 1; |
22550 |
++ |
22551 |
++ if (current->acl->user_trans_type & GR_ID_ALLOW) { |
22552 |
++ for (i = 0; i < num; i++) { |
22553 |
++ curuid = (int)uidlist[i]; |
22554 |
++ if (real == curuid) |
22555 |
++ realok = 1; |
22556 |
++ if (effective == curuid) |
22557 |
++ effectiveok = 1; |
22558 |
++ if (fs == curuid) |
22559 |
++ fsok = 1; |
22560 |
++ } |
22561 |
++ } else if (current->acl->user_trans_type & GR_ID_DENY) { |
22562 |
++ for (i = 0; i < num; i++) { |
22563 |
++ curuid = (int)uidlist[i]; |
22564 |
++ if (real == curuid) |
22565 |
++ break; |
22566 |
++ if (effective == curuid) |
22567 |
++ break; |
22568 |
++ if (fs == curuid) |
22569 |
++ break; |
22570 |
++ } |
22571 |
++ /* not in deny list */ |
22572 |
++ if (i == num) { |
22573 |
++ realok = 1; |
22574 |
++ effectiveok = 1; |
22575 |
++ fsok = 1; |
22576 |
++ } |
22577 |
++ } |
22578 |
++ |
22579 |
++ if (realok && effectiveok && fsok) |
22580 |
++ return 0; |
22581 |
++ else { |
22582 |
++ gr_log_int(GR_DONT_AUDIT, GR_USRCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real); |
22583 |
++ return 1; |
22584 |
++ } |
22585 |
++} |
22586 |
++ |
22587 |
++int |
22588 |
++gr_check_group_change(int real, int effective, int fs) |
22589 |
++{ |
22590 |
++ unsigned int i; |
22591 |
++ __u16 num; |
22592 |
++ gid_t *gidlist; |
22593 |
++ int curgid; |
22594 |
++ int realok = 0; |
22595 |
++ int effectiveok = 0; |
22596 |
++ int fsok = 0; |
22597 |
++ |
22598 |
++ if (unlikely(!(gr_status & GR_READY))) |
22599 |
++ return 0; |
22600 |
++ |
22601 |
++ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) |
22602 |
++ gr_log_learn_id_change(current, 'g', real, effective, fs); |
22603 |
++ |
22604 |
++ num = current->acl->group_trans_num; |
22605 |
++ gidlist = current->acl->group_transitions; |
22606 |
++ |
22607 |
++ if (gidlist == NULL) |
22608 |
++ return 0; |
22609 |
++ |
22610 |
++ if (real == -1) |
22611 |
++ realok = 1; |
22612 |
++ if (effective == -1) |
22613 |
++ effectiveok = 1; |
22614 |
++ if (fs == -1) |
22615 |
++ fsok = 1; |
22616 |
++ |
22617 |
++ if (current->acl->group_trans_type & GR_ID_ALLOW) { |
22618 |
++ for (i = 0; i < num; i++) { |
22619 |
++ curgid = (int)gidlist[i]; |
22620 |
++ if (real == curgid) |
22621 |
++ realok = 1; |
22622 |
++ if (effective == curgid) |
22623 |
++ effectiveok = 1; |
22624 |
++ if (fs == curgid) |
22625 |
++ fsok = 1; |
22626 |
++ } |
22627 |
++ } else if (current->acl->group_trans_type & GR_ID_DENY) { |
22628 |
++ for (i = 0; i < num; i++) { |
22629 |
++ curgid = (int)gidlist[i]; |
22630 |
++ if (real == curgid) |
22631 |
++ break; |
22632 |
++ if (effective == curgid) |
22633 |
++ break; |
22634 |
++ if (fs == curgid) |
22635 |
++ break; |
22636 |
++ } |
22637 |
++ /* not in deny list */ |
22638 |
++ if (i == num) { |
22639 |
++ realok = 1; |
22640 |
++ effectiveok = 1; |
22641 |
++ fsok = 1; |
22642 |
++ } |
22643 |
++ } |
22644 |
++ |
22645 |
++ if (realok && effectiveok && fsok) |
22646 |
++ return 0; |
22647 |
++ else { |
22648 |
++ gr_log_int(GR_DONT_AUDIT, GR_GRPCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real); |
22649 |
++ return 1; |
22650 |
++ } |
22651 |
++} |
22652 |
++ |
22653 |
++void |
22654 |
++gr_set_role_label(struct task_struct *task, const uid_t uid, const uid_t gid) |
22655 |
++{ |
22656 |
++ struct acl_role_label *role = task->role; |
22657 |
++ struct acl_subject_label *subj = NULL; |
22658 |
++ struct acl_object_label *obj; |
22659 |
++ struct file *filp; |
22660 |
++ |
22661 |
++ if (unlikely(!(gr_status & GR_READY))) |
22662 |
++ return; |
22663 |
++ |
22664 |
++ filp = task->exec_file; |
22665 |
++ |
22666 |
++ /* kernel process, we'll give them the kernel role */ |
22667 |
++ if (unlikely(!filp)) { |
22668 |
++ task->role = kernel_role; |
22669 |
++ task->acl = kernel_role->root_label; |
22670 |
++ return; |
22671 |
++ } else if (!task->role || !(task->role->roletype & GR_ROLE_SPECIAL)) |
22672 |
++ role = lookup_acl_role_label(task, uid, gid); |
22673 |
++ |
22674 |
++ /* perform subject lookup in possibly new role |
22675 |
++ we can use this result below in the case where role == task->role |
22676 |
++ */ |
22677 |
++ subj = chk_subj_label(filp->f_path.dentry, filp->f_path.mnt, role); |
22678 |
++ |
22679 |
++ /* if we changed uid/gid, but result in the same role |
22680 |
++ and are using inheritance, don't lose the inherited subject |
22681 |
++ if current subject is other than what normal lookup |
22682 |
++ would result in, we arrived via inheritance, don't |
22683 |
++ lose subject |
22684 |
++ */ |
22685 |
++ if (role != task->role || (!(task->acl->mode & GR_INHERITLEARN) && |
22686 |
++ (subj == task->acl))) |
22687 |
++ task->acl = subj; |
22688 |
++ |
22689 |
++ task->role = role; |
22690 |
++ |
22691 |
++ task->is_writable = 0; |
22692 |
++ |
22693 |
++ /* ignore additional mmap checks for processes that are writable |
22694 |
++ by the default ACL */ |
22695 |
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, default_role->root_label); |
22696 |
++ if (unlikely(obj->mode & GR_WRITE)) |
22697 |
++ task->is_writable = 1; |
22698 |
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, task->role->root_label); |
22699 |
++ if (unlikely(obj->mode & GR_WRITE)) |
22700 |
++ task->is_writable = 1; |
22701 |
++ |
22702 |
++#ifdef CONFIG_GRKERNSEC_ACL_DEBUG |
22703 |
++ printk(KERN_ALERT "Set role label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename); |
22704 |
++#endif |
22705 |
++ |
22706 |
++ gr_set_proc_res(task); |
22707 |
++ |
22708 |
++ return; |
22709 |
++} |
22710 |
++ |
22711 |
++int |
22712 |
++gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt) |
22713 |
++{ |
22714 |
++ struct task_struct *task = current; |
22715 |
++ struct acl_subject_label *newacl; |
22716 |
++ struct acl_object_label *obj; |
22717 |
++ __u32 retmode; |
22718 |
++ |
22719 |
++ if (unlikely(!(gr_status & GR_READY))) |
22720 |
++ return 0; |
22721 |
++ |
22722 |
++ newacl = chk_subj_label(dentry, mnt, task->role); |
22723 |
++ |
22724 |
++ task_lock(task); |
22725 |
++ if (((task->ptrace & PT_PTRACED) && !(task->acl->mode & |
22726 |
++ GR_POVERRIDE) && (task->acl != newacl) && |
22727 |
++ !(task->role->roletype & GR_ROLE_GOD) && |
22728 |
++ !gr_search_file(dentry, GR_PTRACERD, mnt) && |
22729 |
++ !(task->acl->mode & (GR_LEARN | GR_INHERITLEARN))) || |
22730 |
++ (atomic_read(&task->fs->count) > 1 || |
22731 |
++ atomic_read(&task->files->count) > 1 || |
22732 |
++ atomic_read(&task->sighand->count) > 1)) { |
22733 |
++ task_unlock(task); |
22734 |
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_PTRACE_EXEC_ACL_MSG, dentry, mnt); |
22735 |
++ return -EACCES; |
22736 |
++ } |
22737 |
++ task_unlock(task); |
22738 |
++ |
22739 |
++ obj = chk_obj_label(dentry, mnt, task->acl); |
22740 |
++ retmode = obj->mode & (GR_INHERIT | GR_AUDIT_INHERIT); |
22741 |
++ |
22742 |
++ if (!(task->acl->mode & GR_INHERITLEARN) && |
22743 |
++ ((newacl->mode & GR_LEARN) || !(retmode & GR_INHERIT))) { |
22744 |
++ if (obj->nested) |
22745 |
++ task->acl = obj->nested; |
22746 |
++ else |
22747 |
++ task->acl = newacl; |
22748 |
++ } else if (retmode & GR_INHERIT && retmode & GR_AUDIT_INHERIT) |
22749 |
++ gr_log_str_fs(GR_DO_AUDIT, GR_INHERIT_ACL_MSG, task->acl->filename, dentry, mnt); |
22750 |
++ |
22751 |
++ task->is_writable = 0; |
22752 |
++ |
22753 |
++ /* ignore additional mmap checks for processes that are writable |
22754 |
++ by the default ACL */ |
22755 |
++ obj = chk_obj_label(dentry, mnt, default_role->root_label); |
22756 |
++ if (unlikely(obj->mode & GR_WRITE)) |
22757 |
++ task->is_writable = 1; |
22758 |
++ obj = chk_obj_label(dentry, mnt, task->role->root_label); |
22759 |
++ if (unlikely(obj->mode & GR_WRITE)) |
22760 |
++ task->is_writable = 1; |
22761 |
++ |
22762 |
++ gr_set_proc_res(task); |
22763 |
++ |
22764 |
++#ifdef CONFIG_GRKERNSEC_ACL_DEBUG |
22765 |
++ printk(KERN_ALERT "Set subject label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename); |
22766 |
++#endif |
22767 |
++ return 0; |
22768 |
++} |
22769 |
++ |
22770 |
++/* always called with valid inodev ptr */ |
22771 |
++static void |
22772 |
++do_handle_delete(struct inodev_entry *inodev, const ino_t ino, const dev_t dev) |
22773 |
++{ |
22774 |
++ struct acl_object_label *matchpo; |
22775 |
++ struct acl_subject_label *matchps; |
22776 |
++ struct acl_subject_label *subj; |
22777 |
++ struct acl_role_label *role; |
22778 |
++ unsigned int i, x; |
22779 |
++ |
22780 |
++ FOR_EACH_ROLE_START(role, i) |
22781 |
++ FOR_EACH_SUBJECT_START(role, subj, x) |
22782 |
++ if ((matchpo = lookup_acl_obj_label(ino, dev, subj)) != NULL) |
22783 |
++ matchpo->mode |= GR_DELETED; |
22784 |
++ FOR_EACH_SUBJECT_END(subj,x) |
22785 |
++ FOR_EACH_NESTED_SUBJECT_START(role, subj) |
22786 |
++ if (subj->inode == ino && subj->device == dev) |
22787 |
++ subj->mode |= GR_DELETED; |
22788 |
++ FOR_EACH_NESTED_SUBJECT_END(subj) |
22789 |
++ if ((matchps = lookup_acl_subj_label(ino, dev, role)) != NULL) |
22790 |
++ matchps->mode |= GR_DELETED; |
22791 |
++ FOR_EACH_ROLE_END(role,i) |
22792 |
++ |
22793 |
++ inodev->nentry->deleted = 1; |
22794 |
++ |
22795 |
++ return; |
22796 |
++} |
22797 |
++ |
22798 |
++void |
22799 |
++gr_handle_delete(const ino_t ino, const dev_t dev) |
22800 |
++{ |
22801 |
++ struct inodev_entry *inodev; |
22802 |
++ |
22803 |
++ if (unlikely(!(gr_status & GR_READY))) |
22804 |
++ return; |
22805 |
++ |
22806 |
++ write_lock(&gr_inode_lock); |
22807 |
++ inodev = lookup_inodev_entry(ino, dev); |
22808 |
++ if (inodev != NULL) |
22809 |
++ do_handle_delete(inodev, ino, dev); |
22810 |
++ write_unlock(&gr_inode_lock); |
22811 |
++ |
22812 |
++ return; |
22813 |
++} |
22814 |
++ |
22815 |
++static void |
22816 |
++update_acl_obj_label(const ino_t oldinode, const dev_t olddevice, |
22817 |
++ const ino_t newinode, const dev_t newdevice, |
22818 |
++ struct acl_subject_label *subj) |
22819 |
++{ |
22820 |
++ unsigned int index = fhash(oldinode, olddevice, subj->obj_hash_size); |
22821 |
++ struct acl_object_label *match; |
22822 |
++ |
22823 |
++ match = subj->obj_hash[index]; |
22824 |
++ |
22825 |
++ while (match && (match->inode != oldinode || |
22826 |
++ match->device != olddevice || |
22827 |
++ !(match->mode & GR_DELETED))) |
22828 |
++ match = match->next; |
22829 |
++ |
22830 |
++ if (match && (match->inode == oldinode) |
22831 |
++ && (match->device == olddevice) |
22832 |
++ && (match->mode & GR_DELETED)) { |
22833 |
++ if (match->prev == NULL) { |
22834 |
++ subj->obj_hash[index] = match->next; |
22835 |
++ if (match->next != NULL) |
22836 |
++ match->next->prev = NULL; |
22837 |
++ } else { |
22838 |
++ match->prev->next = match->next; |
22839 |
++ if (match->next != NULL) |
22840 |
++ match->next->prev = match->prev; |
22841 |
++ } |
22842 |
++ match->prev = NULL; |
22843 |
++ match->next = NULL; |
22844 |
++ match->inode = newinode; |
22845 |
++ match->device = newdevice; |
22846 |
++ match->mode &= ~GR_DELETED; |
22847 |
++ |
22848 |
++ insert_acl_obj_label(match, subj); |
22849 |
++ } |
22850 |
++ |
22851 |
++ return; |
22852 |
++} |
22853 |
++ |
22854 |
++static void |
22855 |
++update_acl_subj_label(const ino_t oldinode, const dev_t olddevice, |
22856 |
++ const ino_t newinode, const dev_t newdevice, |
22857 |
++ struct acl_role_label *role) |
22858 |
++{ |
22859 |
++ unsigned int index = fhash(oldinode, olddevice, role->subj_hash_size); |
22860 |
++ struct acl_subject_label *match; |
22861 |
++ |
22862 |
++ match = role->subj_hash[index]; |
22863 |
++ |
22864 |
++ while (match && (match->inode != oldinode || |
22865 |
++ match->device != olddevice || |
22866 |
++ !(match->mode & GR_DELETED))) |
22867 |
++ match = match->next; |
22868 |
++ |
22869 |
++ if (match && (match->inode == oldinode) |
22870 |
++ && (match->device == olddevice) |
22871 |
++ && (match->mode & GR_DELETED)) { |
22872 |
++ if (match->prev == NULL) { |
22873 |
++ role->subj_hash[index] = match->next; |
22874 |
++ if (match->next != NULL) |
22875 |
++ match->next->prev = NULL; |
22876 |
++ } else { |
22877 |
++ match->prev->next = match->next; |
22878 |
++ if (match->next != NULL) |
22879 |
++ match->next->prev = match->prev; |
22880 |
++ } |
22881 |
++ match->prev = NULL; |
22882 |
++ match->next = NULL; |
22883 |
++ match->inode = newinode; |
22884 |
++ match->device = newdevice; |
22885 |
++ match->mode &= ~GR_DELETED; |
22886 |
++ |
22887 |
++ insert_acl_subj_label(match, role); |
22888 |
++ } |
22889 |
++ |
22890 |
++ return; |
22891 |
++} |
22892 |
++ |
22893 |
++static void |
22894 |
++update_inodev_entry(const ino_t oldinode, const dev_t olddevice, |
22895 |
++ const ino_t newinode, const dev_t newdevice) |
22896 |
++{ |
22897 |
++ unsigned int index = fhash(oldinode, olddevice, inodev_set.i_size); |
22898 |
++ struct inodev_entry *match; |
22899 |
++ |
22900 |
++ match = inodev_set.i_hash[index]; |
22901 |
++ |
22902 |
++ while (match && (match->nentry->inode != oldinode || |
22903 |
++ match->nentry->device != olddevice || !match->nentry->deleted)) |
22904 |
++ match = match->next; |
22905 |
++ |
22906 |
++ if (match && (match->nentry->inode == oldinode) |
22907 |
++ && (match->nentry->device == olddevice) && |
22908 |
++ match->nentry->deleted) { |
22909 |
++ if (match->prev == NULL) { |
22910 |
++ inodev_set.i_hash[index] = match->next; |
22911 |
++ if (match->next != NULL) |
22912 |
++ match->next->prev = NULL; |
22913 |
++ } else { |
22914 |
++ match->prev->next = match->next; |
22915 |
++ if (match->next != NULL) |
22916 |
++ match->next->prev = match->prev; |
22917 |
++ } |
22918 |
++ match->prev = NULL; |
22919 |
++ match->next = NULL; |
22920 |
++ match->nentry->inode = newinode; |
22921 |
++ match->nentry->device = newdevice; |
22922 |
++ match->nentry->deleted = 0; |
22923 |
++ |
22924 |
++ insert_inodev_entry(match); |
22925 |
++ } |
22926 |
++ |
22927 |
++ return; |
22928 |
++} |
22929 |
++ |
22930 |
++static void |
22931 |
++do_handle_create(const struct name_entry *matchn, const struct dentry *dentry, |
22932 |
++ const struct vfsmount *mnt) |
22933 |
++{ |
22934 |
++ struct acl_subject_label *subj; |
22935 |
++ struct acl_role_label *role; |
22936 |
++ unsigned int i, x; |
22937 |
++ |
22938 |
++ FOR_EACH_ROLE_START(role, i) |
22939 |
++ update_acl_subj_label(matchn->inode, matchn->device, |
22940 |
++ dentry->d_inode->i_ino, |
22941 |
++ dentry->d_inode->i_sb->s_dev, role); |
22942 |
++ |
22943 |
++ FOR_EACH_NESTED_SUBJECT_START(role, subj) |
22944 |
++ if ((subj->inode == dentry->d_inode->i_ino) && |
22945 |
++ (subj->device == dentry->d_inode->i_sb->s_dev)) { |
22946 |
++ subj->inode = dentry->d_inode->i_ino; |
22947 |
++ subj->device = dentry->d_inode->i_sb->s_dev; |
22948 |
++ } |
22949 |
++ FOR_EACH_NESTED_SUBJECT_END(subj) |
22950 |
++ FOR_EACH_SUBJECT_START(role, subj, x) |
22951 |
++ update_acl_obj_label(matchn->inode, matchn->device, |
22952 |
++ dentry->d_inode->i_ino, |
22953 |
++ dentry->d_inode->i_sb->s_dev, subj); |
22954 |
++ FOR_EACH_SUBJECT_END(subj,x) |
22955 |
++ FOR_EACH_ROLE_END(role,i) |
22956 |
++ |
22957 |
++ update_inodev_entry(matchn->inode, matchn->device, |
22958 |
++ dentry->d_inode->i_ino, dentry->d_inode->i_sb->s_dev); |
22959 |
++ |
22960 |
++ return; |
22961 |
++} |
22962 |
++ |
22963 |
++void |
22964 |
++gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt) |
22965 |
++{ |
22966 |
++ struct name_entry *matchn; |
22967 |
++ |
22968 |
++ if (unlikely(!(gr_status & GR_READY))) |
22969 |
++ return; |
22970 |
++ |
22971 |
++ preempt_disable(); |
22972 |
++ matchn = lookup_name_entry(gr_to_filename_rbac(dentry, mnt)); |
22973 |
++ |
22974 |
++ if (unlikely((unsigned long)matchn)) { |
22975 |
++ write_lock(&gr_inode_lock); |
22976 |
++ do_handle_create(matchn, dentry, mnt); |
22977 |
++ write_unlock(&gr_inode_lock); |
22978 |
++ } |
22979 |
++ preempt_enable(); |
22980 |
++ |
22981 |
++ return; |
22982 |
++} |
22983 |
++ |
22984 |
++void |
22985 |
++gr_handle_rename(struct inode *old_dir, struct inode *new_dir, |
22986 |
++ struct dentry *old_dentry, |
22987 |
++ struct dentry *new_dentry, |
22988 |
++ struct vfsmount *mnt, const __u8 replace) |
22989 |
++{ |
22990 |
++ struct name_entry *matchn; |
22991 |
++ struct inodev_entry *inodev; |
22992 |
++ |
22993 |
++ /* vfs_rename swaps the name and parent link for old_dentry and |
22994 |
++ new_dentry |
22995 |
++ at this point, old_dentry has the new name, parent link, and inode |
22996 |
++ for the renamed file |
22997 |
++ if a file is being replaced by a rename, new_dentry has the inode |
22998 |
++ and name for the replaced file |
22999 |
++ */ |
23000 |
++ |
23001 |
++ if (unlikely(!(gr_status & GR_READY))) |
23002 |
++ return; |
23003 |
++ |
23004 |
++ preempt_disable(); |
23005 |
++ matchn = lookup_name_entry(gr_to_filename_rbac(old_dentry, mnt)); |
23006 |
++ |
23007 |
++ /* we wouldn't have to check d_inode if it weren't for |
23008 |
++ NFS silly-renaming |
23009 |
++ */ |
23010 |
++ |
23011 |
++ write_lock(&gr_inode_lock); |
23012 |
++ if (unlikely(replace && new_dentry->d_inode)) { |
23013 |
++ inodev = lookup_inodev_entry(new_dentry->d_inode->i_ino, |
23014 |
++ new_dentry->d_inode->i_sb->s_dev); |
23015 |
++ if (inodev != NULL && (new_dentry->d_inode->i_nlink <= 1)) |
23016 |
++ do_handle_delete(inodev, new_dentry->d_inode->i_ino, |
23017 |
++ new_dentry->d_inode->i_sb->s_dev); |
23018 |
++ } |
23019 |
++ |
23020 |
++ inodev = lookup_inodev_entry(old_dentry->d_inode->i_ino, |
23021 |
++ old_dentry->d_inode->i_sb->s_dev); |
23022 |
++ if (inodev != NULL && (old_dentry->d_inode->i_nlink <= 1)) |
23023 |
++ do_handle_delete(inodev, old_dentry->d_inode->i_ino, |
23024 |
++ old_dentry->d_inode->i_sb->s_dev); |
23025 |
++ |
23026 |
++ if (unlikely((unsigned long)matchn)) |
23027 |
++ do_handle_create(matchn, old_dentry, mnt); |
23028 |
++ |
23029 |
++ write_unlock(&gr_inode_lock); |
23030 |
++ preempt_enable(); |
23031 |
++ |
23032 |
++ return; |
23033 |
++} |
23034 |
++ |
23035 |
++static int |
23036 |
++lookup_special_role_auth(__u16 mode, const char *rolename, unsigned char **salt, |
23037 |
++ unsigned char **sum) |
23038 |
++{ |
23039 |
++ struct acl_role_label *r; |
23040 |
++ struct role_allowed_ip *ipp; |
23041 |
++ struct role_transition *trans; |
23042 |
++ unsigned int i; |
23043 |
++ int found = 0; |
23044 |
++ |
23045 |
++ /* check transition table */ |
23046 |
++ |
23047 |
++ for (trans = current->role->transitions; trans; trans = trans->next) { |
23048 |
++ if (!strcmp(rolename, trans->rolename)) { |
23049 |
++ found = 1; |
23050 |
++ break; |
23051 |
++ } |
23052 |
++ } |
23053 |
++ |
23054 |
++ if (!found) |
23055 |
++ return 0; |
23056 |
++ |
23057 |
++ /* handle special roles that do not require authentication |
23058 |
++ and check ip */ |
23059 |
++ |
23060 |
++ FOR_EACH_ROLE_START(r, i) |
23061 |
++ if (!strcmp(rolename, r->rolename) && |
23062 |
++ (r->roletype & GR_ROLE_SPECIAL)) { |
23063 |
++ found = 0; |
23064 |
++ if (r->allowed_ips != NULL) { |
23065 |
++ for (ipp = r->allowed_ips; ipp; ipp = ipp->next) { |
23066 |
++ if ((ntohl(current->signal->curr_ip) & ipp->netmask) == |
23067 |
++ (ntohl(ipp->addr) & ipp->netmask)) |
23068 |
++ found = 1; |
23069 |
++ } |
23070 |
++ } else |
23071 |
++ found = 2; |
23072 |
++ if (!found) |
23073 |
++ return 0; |
23074 |
++ |
23075 |
++ if (((mode == GR_SPROLE) && (r->roletype & GR_ROLE_NOPW)) || |
23076 |
++ ((mode == GR_SPROLEPAM) && (r->roletype & GR_ROLE_PAM))) { |
23077 |
++ *salt = NULL; |
23078 |
++ *sum = NULL; |
23079 |
++ return 1; |
23080 |
++ } |
23081 |
++ } |
23082 |
++ FOR_EACH_ROLE_END(r,i) |
23083 |
++ |
23084 |
++ for (i = 0; i < num_sprole_pws; i++) { |
23085 |
++ if (!strcmp(rolename, acl_special_roles[i]->rolename)) { |
23086 |
++ *salt = acl_special_roles[i]->salt; |
23087 |
++ *sum = acl_special_roles[i]->sum; |
23088 |
++ return 1; |
23089 |
++ } |
23090 |
++ } |
23091 |
++ |
23092 |
++ return 0; |
23093 |
++} |
23094 |
++ |
23095 |
++static void |
23096 |
++assign_special_role(char *rolename) |
23097 |
++{ |
23098 |
++ struct acl_object_label *obj; |
23099 |
++ struct acl_role_label *r; |
23100 |
++ struct acl_role_label *assigned = NULL; |
23101 |
++ struct task_struct *tsk; |
23102 |
++ struct file *filp; |
23103 |
++ unsigned int i; |
23104 |
++ |
23105 |
++ FOR_EACH_ROLE_START(r, i) |
23106 |
++ if (!strcmp(rolename, r->rolename) && |
23107 |
++ (r->roletype & GR_ROLE_SPECIAL)) |
23108 |
++ assigned = r; |
23109 |
++ FOR_EACH_ROLE_END(r,i) |
23110 |
++ |
23111 |
++ if (!assigned) |
23112 |
++ return; |
23113 |
++ |
23114 |
++ read_lock(&tasklist_lock); |
23115 |
++ read_lock(&grsec_exec_file_lock); |
23116 |
++ |
23117 |
++ tsk = current->parent; |
23118 |
++ if (tsk == NULL) |
23119 |
++ goto out_unlock; |
23120 |
++ |
23121 |
++ filp = tsk->exec_file; |
23122 |
++ if (filp == NULL) |
23123 |
++ goto out_unlock; |
23124 |
++ |
23125 |
++ tsk->is_writable = 0; |
23126 |
++ |
23127 |
++ tsk->acl_sp_role = 1; |
23128 |
++ tsk->acl_role_id = ++acl_sp_role_value; |
23129 |
++ tsk->role = assigned; |
23130 |
++ tsk->acl = chk_subj_label(filp->f_path.dentry, filp->f_path.mnt, tsk->role); |
23131 |
++ |
23132 |
++ /* ignore additional mmap checks for processes that are writable |
23133 |
++ by the default ACL */ |
23134 |
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, default_role->root_label); |
23135 |
++ if (unlikely(obj->mode & GR_WRITE)) |
23136 |
++ tsk->is_writable = 1; |
23137 |
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, tsk->role->root_label); |
23138 |
++ if (unlikely(obj->mode & GR_WRITE)) |
23139 |
++ tsk->is_writable = 1; |
23140 |
++ |
23141 |
++#ifdef CONFIG_GRKERNSEC_ACL_DEBUG |
23142 |
++ printk(KERN_ALERT "Assigning special role:%s subject:%s to process (%s:%d)\n", tsk->role->rolename, tsk->acl->filename, tsk->comm, tsk->pid); |
23143 |
++#endif |
23144 |
++ |
23145 |
++out_unlock: |
23146 |
++ read_unlock(&grsec_exec_file_lock); |
23147 |
++ read_unlock(&tasklist_lock); |
23148 |
++ return; |
23149 |
++} |
23150 |
++ |
23151 |
++int gr_check_secure_terminal(struct task_struct *task) |
23152 |
++{ |
23153 |
++ struct task_struct *p, *p2, *p3; |
23154 |
++ struct files_struct *files; |
23155 |
++ struct fdtable *fdt; |
23156 |
++ struct file *our_file = NULL, *file; |
23157 |
++ int i; |
23158 |
++ |
23159 |
++ if (task->signal->tty == NULL) |
23160 |
++ return 1; |
23161 |
++ |
23162 |
++ files = get_files_struct(task); |
23163 |
++ if (files != NULL) { |
23164 |
++ rcu_read_lock(); |
23165 |
++ fdt = files_fdtable(files); |
23166 |
++ for (i=0; i < fdt->max_fds; i++) { |
23167 |
++ file = fcheck_files(files, i); |
23168 |
++ if (file && (our_file == NULL) && (file->private_data == task->signal->tty)) { |
23169 |
++ get_file(file); |
23170 |
++ our_file = file; |
23171 |
++ } |
23172 |
++ } |
23173 |
++ rcu_read_unlock(); |
23174 |
++ put_files_struct(files); |
23175 |
++ } |
23176 |
++ |
23177 |
++ if (our_file == NULL) |
23178 |
++ return 1; |
23179 |
++ |
23180 |
++ read_lock(&tasklist_lock); |
23181 |
++ do_each_thread(p2, p) { |
23182 |
++ files = get_files_struct(p); |
23183 |
++ if (files == NULL || |
23184 |
++ (p->signal && p->signal->tty == task->signal->tty)) { |
23185 |
++ if (files != NULL) |
23186 |
++ put_files_struct(files); |
23187 |
++ continue; |
23188 |
++ } |
23189 |
++ rcu_read_lock(); |
23190 |
++ fdt = files_fdtable(files); |
23191 |
++ for (i=0; i < fdt->max_fds; i++) { |
23192 |
++ file = fcheck_files(files, i); |
23193 |
++ if (file && S_ISCHR(file->f_path.dentry->d_inode->i_mode) && |
23194 |
++ file->f_path.dentry->d_inode->i_rdev == our_file->f_path.dentry->d_inode->i_rdev) { |
23195 |
++ p3 = task; |
23196 |
++ while (p3->pid > 0) { |
23197 |
++ if (p3 == p) |
23198 |
++ break; |
23199 |
++ p3 = p3->parent; |
23200 |
++ } |
23201 |
++ if (p3 == p) |
23202 |
++ break; |
23203 |
++ gr_log_ttysniff(GR_DONT_AUDIT_GOOD, GR_TTYSNIFF_ACL_MSG, p); |
23204 |
++ gr_handle_alertkill(p); |
23205 |
++ rcu_read_unlock(); |
23206 |
++ put_files_struct(files); |
23207 |
++ read_unlock(&tasklist_lock); |
23208 |
++ fput(our_file); |
23209 |
++ return 0; |
23210 |
++ } |
23211 |
++ } |
23212 |
++ rcu_read_unlock(); |
23213 |
++ put_files_struct(files); |
23214 |
++ } while_each_thread(p2, p); |
23215 |
++ read_unlock(&tasklist_lock); |
23216 |
++ |
23217 |
++ fput(our_file); |
23218 |
++ return 1; |
23219 |
++} |
23220 |
++ |
23221 |
++ssize_t |
23222 |
++write_grsec_handler(struct file *file, const char * buf, size_t count, loff_t *ppos) |
23223 |
++{ |
23224 |
++ struct gr_arg_wrapper uwrap; |
23225 |
++ unsigned char *sprole_salt; |
23226 |
++ unsigned char *sprole_sum; |
23227 |
++ int error = sizeof (struct gr_arg_wrapper); |
23228 |
++ int error2 = 0; |
23229 |
++ |
23230 |
++ down(&gr_dev_sem); |
23231 |
++ |
23232 |
++ if ((gr_status & GR_READY) && !(current->acl->mode & GR_KERNELAUTH)) { |
23233 |
++ error = -EPERM; |
23234 |
++ goto out; |
23235 |
++ } |
23236 |
++ |
23237 |
++ if (count != sizeof (struct gr_arg_wrapper)) { |
23238 |
++ gr_log_int_int(GR_DONT_AUDIT_GOOD, GR_DEV_ACL_MSG, (int)count, (int)sizeof(struct gr_arg_wrapper)); |
23239 |
++ error = -EINVAL; |
23240 |
++ goto out; |
23241 |
++ } |
23242 |
++ |
23243 |
++ |
23244 |
++ if (gr_auth_expires && time_after_eq(get_seconds(), gr_auth_expires)) { |
23245 |
++ gr_auth_expires = 0; |
23246 |
++ gr_auth_attempts = 0; |
23247 |
++ } |
23248 |
++ |
23249 |
++ if (copy_from_user(&uwrap, buf, sizeof (struct gr_arg_wrapper))) { |
23250 |
++ error = -EFAULT; |
23251 |
++ goto out; |
23252 |
++ } |
23253 |
++ |
23254 |
++ if ((uwrap.version != GRSECURITY_VERSION) || (uwrap.size != sizeof(struct gr_arg))) { |
23255 |
++ error = -EINVAL; |
23256 |
++ goto out; |
23257 |
++ } |
23258 |
++ |
23259 |
++ if (copy_from_user(gr_usermode, uwrap.arg, sizeof (struct gr_arg))) { |
23260 |
++ error = -EFAULT; |
23261 |
++ goto out; |
23262 |
++ } |
23263 |
++ |
23264 |
++ if (gr_usermode->mode != GR_SPROLE && gr_usermode->mode != GR_SPROLEPAM && |
23265 |
++ gr_auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES && |
23266 |
++ time_after(gr_auth_expires, get_seconds())) { |
23267 |
++ error = -EBUSY; |
23268 |
++ goto out; |
23269 |
++ } |
23270 |
++ |
23271 |
++ /* if non-root trying to do anything other than use a special role, |
23272 |
++ do not attempt authentication, do not count towards authentication |
23273 |
++ locking |
23274 |
++ */ |
23275 |
++ |
23276 |
++ if (gr_usermode->mode != GR_SPROLE && gr_usermode->mode != GR_STATUS && |
23277 |
++ gr_usermode->mode != GR_UNSPROLE && gr_usermode->mode != GR_SPROLEPAM && |
23278 |
++ current->uid) { |
23279 |
++ error = -EPERM; |
23280 |
++ goto out; |
23281 |
++ } |
23282 |
++ |
23283 |
++ /* ensure pw and special role name are null terminated */ |
23284 |
++ |
23285 |
++ gr_usermode->pw[GR_PW_LEN - 1] = '\0'; |
23286 |
++ gr_usermode->sp_role[GR_SPROLE_LEN - 1] = '\0'; |
23287 |
++ |
23288 |
++ /* Okay. |
23289 |
++ * We have our enough of the argument structure..(we have yet |
23290 |
++ * to copy_from_user the tables themselves) . Copy the tables |
23291 |
++ * only if we need them, i.e. for loading operations. */ |
23292 |
++ |
23293 |
++ switch (gr_usermode->mode) { |
23294 |
++ case GR_STATUS: |
23295 |
++ if (gr_status & GR_READY) { |
23296 |
++ error = 1; |
23297 |
++ if (!gr_check_secure_terminal(current)) |
23298 |
++ error = 3; |
23299 |
++ } else |
23300 |
++ error = 2; |
23301 |
++ goto out; |
23302 |
++ case GR_SHUTDOWN: |
23303 |
++ if ((gr_status & GR_READY) |
23304 |
++ && !(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) { |
23305 |
++ gr_status &= ~GR_READY; |
23306 |
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTS_ACL_MSG); |
23307 |
++ free_variables(); |
23308 |
++ memset(gr_usermode, 0, sizeof (struct gr_arg)); |
23309 |
++ memset(gr_system_salt, 0, GR_SALT_LEN); |
23310 |
++ memset(gr_system_sum, 0, GR_SHA_LEN); |
23311 |
++ } else if (gr_status & GR_READY) { |
23312 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_SHUTF_ACL_MSG); |
23313 |
++ error = -EPERM; |
23314 |
++ } else { |
23315 |
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTI_ACL_MSG); |
23316 |
++ error = -EAGAIN; |
23317 |
++ } |
23318 |
++ break; |
23319 |
++ case GR_ENABLE: |
23320 |
++ if (!(gr_status & GR_READY) && !(error2 = gracl_init(gr_usermode))) |
23321 |
++ gr_log_str(GR_DONT_AUDIT_GOOD, GR_ENABLE_ACL_MSG, GR_VERSION); |
23322 |
++ else { |
23323 |
++ if (gr_status & GR_READY) |
23324 |
++ error = -EAGAIN; |
23325 |
++ else |
23326 |
++ error = error2; |
23327 |
++ gr_log_str(GR_DONT_AUDIT, GR_ENABLEF_ACL_MSG, GR_VERSION); |
23328 |
++ } |
23329 |
++ break; |
23330 |
++ case GR_RELOAD: |
23331 |
++ if (!(gr_status & GR_READY)) { |
23332 |
++ gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOADI_ACL_MSG, GR_VERSION); |
23333 |
++ error = -EAGAIN; |
23334 |
++ } else if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) { |
23335 |
++ lock_kernel(); |
23336 |
++ gr_status &= ~GR_READY; |
23337 |
++ free_variables(); |
23338 |
++ if (!(error2 = gracl_init(gr_usermode))) { |
23339 |
++ unlock_kernel(); |
23340 |
++ gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOAD_ACL_MSG, GR_VERSION); |
23341 |
++ } else { |
23342 |
++ unlock_kernel(); |
23343 |
++ error = error2; |
23344 |
++ gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION); |
23345 |
++ } |
23346 |
++ } else { |
23347 |
++ gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION); |
23348 |
++ error = -EPERM; |
23349 |
++ } |
23350 |
++ break; |
23351 |
++ case GR_SEGVMOD: |
23352 |
++ if (unlikely(!(gr_status & GR_READY))) { |
23353 |
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODI_ACL_MSG); |
23354 |
++ error = -EAGAIN; |
23355 |
++ break; |
23356 |
++ } |
23357 |
++ |
23358 |
++ if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) { |
23359 |
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODS_ACL_MSG); |
23360 |
++ if (gr_usermode->segv_device && gr_usermode->segv_inode) { |
23361 |
++ struct acl_subject_label *segvacl; |
23362 |
++ segvacl = |
23363 |
++ lookup_acl_subj_label(gr_usermode->segv_inode, |
23364 |
++ gr_usermode->segv_device, |
23365 |
++ current->role); |
23366 |
++ if (segvacl) { |
23367 |
++ segvacl->crashes = 0; |
23368 |
++ segvacl->expires = 0; |
23369 |
++ } |
23370 |
++ } else if (gr_find_uid(gr_usermode->segv_uid) >= 0) { |
23371 |
++ gr_remove_uid(gr_usermode->segv_uid); |
23372 |
++ } |
23373 |
++ } else { |
23374 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_SEGVMODF_ACL_MSG); |
23375 |
++ error = -EPERM; |
23376 |
++ } |
23377 |
++ break; |
23378 |
++ case GR_SPROLE: |
23379 |
++ case GR_SPROLEPAM: |
23380 |
++ if (unlikely(!(gr_status & GR_READY))) { |
23381 |
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SPROLEI_ACL_MSG); |
23382 |
++ error = -EAGAIN; |
23383 |
++ break; |
23384 |
++ } |
23385 |
++ |
23386 |
++ if (current->role->expires && time_after_eq(get_seconds(), current->role->expires)) { |
23387 |
++ current->role->expires = 0; |
23388 |
++ current->role->auth_attempts = 0; |
23389 |
++ } |
23390 |
++ |
23391 |
++ if (current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES && |
23392 |
++ time_after(current->role->expires, get_seconds())) { |
23393 |
++ error = -EBUSY; |
23394 |
++ goto out; |
23395 |
++ } |
23396 |
++ |
23397 |
++ if (lookup_special_role_auth |
23398 |
++ (gr_usermode->mode, gr_usermode->sp_role, &sprole_salt, &sprole_sum) |
23399 |
++ && ((!sprole_salt && !sprole_sum) |
23400 |
++ || !(chkpw(gr_usermode, sprole_salt, sprole_sum)))) { |
23401 |
++ char *p = ""; |
23402 |
++ assign_special_role(gr_usermode->sp_role); |
23403 |
++ read_lock(&tasklist_lock); |
23404 |
++ if (current->parent) |
23405 |
++ p = current->parent->role->rolename; |
23406 |
++ read_unlock(&tasklist_lock); |
23407 |
++ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLES_ACL_MSG, |
23408 |
++ p, acl_sp_role_value); |
23409 |
++ } else { |
23410 |
++ gr_log_str(GR_DONT_AUDIT, GR_SPROLEF_ACL_MSG, gr_usermode->sp_role); |
23411 |
++ error = -EPERM; |
23412 |
++ if(!(current->role->auth_attempts++)) |
23413 |
++ current->role->expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT; |
23414 |
++ |
23415 |
++ goto out; |
23416 |
++ } |
23417 |
++ break; |
23418 |
++ case GR_UNSPROLE: |
23419 |
++ if (unlikely(!(gr_status & GR_READY))) { |
23420 |
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_UNSPROLEI_ACL_MSG); |
23421 |
++ error = -EAGAIN; |
23422 |
++ break; |
23423 |
++ } |
23424 |
++ |
23425 |
++ if (current->role->roletype & GR_ROLE_SPECIAL) { |
23426 |
++ char *p = ""; |
23427 |
++ int i = 0; |
23428 |
++ |
23429 |
++ read_lock(&tasklist_lock); |
23430 |
++ if (current->parent) { |
23431 |
++ p = current->parent->role->rolename; |
23432 |
++ i = current->parent->acl_role_id; |
23433 |
++ } |
23434 |
++ read_unlock(&tasklist_lock); |
23435 |
++ |
23436 |
++ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_UNSPROLES_ACL_MSG, p, i); |
23437 |
++ gr_set_acls(1); |
23438 |
++ } else { |
23439 |
++ gr_log_str(GR_DONT_AUDIT, GR_UNSPROLEF_ACL_MSG, current->role->rolename); |
23440 |
++ error = -EPERM; |
23441 |
++ goto out; |
23442 |
++ } |
23443 |
++ break; |
23444 |
++ default: |
23445 |
++ gr_log_int(GR_DONT_AUDIT, GR_INVMODE_ACL_MSG, gr_usermode->mode); |
23446 |
++ error = -EINVAL; |
23447 |
++ break; |
23448 |
++ } |
23449 |
++ |
23450 |
++ if (error != -EPERM) |
23451 |
++ goto out; |
23452 |
++ |
23453 |
++ if(!(gr_auth_attempts++)) |
23454 |
++ gr_auth_expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT; |
23455 |
++ |
23456 |
++ out: |
23457 |
++ up(&gr_dev_sem); |
23458 |
++ return error; |
23459 |
++} |
23460 |
++ |
23461 |
++int |
23462 |
++gr_set_acls(const int type) |
23463 |
++{ |
23464 |
++ struct acl_object_label *obj; |
23465 |
++ struct task_struct *task, *task2; |
23466 |
++ struct file *filp; |
23467 |
++ struct acl_role_label *role = current->role; |
23468 |
++ __u16 acl_role_id = current->acl_role_id; |
23469 |
++ |
23470 |
++ read_lock(&tasklist_lock); |
23471 |
++ read_lock(&grsec_exec_file_lock); |
23472 |
++ do_each_thread(task2, task) { |
23473 |
++ /* check to see if we're called from the exit handler, |
23474 |
++ if so, only replace ACLs that have inherited the admin |
23475 |
++ ACL */ |
23476 |
++ |
23477 |
++ if (type && (task->role != role || |
23478 |
++ task->acl_role_id != acl_role_id)) |
23479 |
++ continue; |
23480 |
++ |
23481 |
++ task->acl_role_id = 0; |
23482 |
++ task->acl_sp_role = 0; |
23483 |
++ |
23484 |
++ if ((filp = task->exec_file)) { |
23485 |
++ task->role = lookup_acl_role_label(task, task->uid, task->gid); |
23486 |
++ |
23487 |
++ task->acl = |
23488 |
++ chk_subj_label(filp->f_path.dentry, filp->f_path.mnt, |
23489 |
++ task->role); |
23490 |
++ if (task->acl) { |
23491 |
++ struct acl_subject_label *curr; |
23492 |
++ curr = task->acl; |
23493 |
++ |
23494 |
++ task->is_writable = 0; |
23495 |
++ /* ignore additional mmap checks for processes that are writable |
23496 |
++ by the default ACL */ |
23497 |
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, default_role->root_label); |
23498 |
++ if (unlikely(obj->mode & GR_WRITE)) |
23499 |
++ task->is_writable = 1; |
23500 |
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, task->role->root_label); |
23501 |
++ if (unlikely(obj->mode & GR_WRITE)) |
23502 |
++ task->is_writable = 1; |
23503 |
++ |
23504 |
++ gr_set_proc_res(task); |
23505 |
++ |
23506 |
++#ifdef CONFIG_GRKERNSEC_ACL_DEBUG |
23507 |
++ printk(KERN_ALERT "gr_set_acls for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename); |
23508 |
++#endif |
23509 |
++ } else { |
23510 |
++ read_unlock(&grsec_exec_file_lock); |
23511 |
++ read_unlock(&tasklist_lock); |
23512 |
++ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_DEFACL_MSG, task->comm, task->pid); |
23513 |
++ return 1; |
23514 |
++ } |
23515 |
++ } else { |
23516 |
++ // it's a kernel process |
23517 |
++ task->role = kernel_role; |
23518 |
++ task->acl = kernel_role->root_label; |
23519 |
++#ifdef CONFIG_GRKERNSEC_ACL_HIDEKERN |
23520 |
++ task->acl->mode &= ~GR_PROCFIND; |
23521 |
++#endif |
23522 |
++ } |
23523 |
++ } while_each_thread(task2, task); |
23524 |
++ read_unlock(&grsec_exec_file_lock); |
23525 |
++ read_unlock(&tasklist_lock); |
23526 |
++ return 0; |
23527 |
++} |
23528 |
++ |
23529 |
++void |
23530 |
++gr_learn_resource(const struct task_struct *task, |
23531 |
++ const int res, const unsigned long wanted, const int gt) |
23532 |
++{ |
23533 |
++ struct acl_subject_label *acl; |
23534 |
++ |
23535 |
++ if (unlikely((gr_status & GR_READY) && |
23536 |
++ task->acl && (task->acl->mode & (GR_LEARN | GR_INHERITLEARN)))) |
23537 |
++ goto skip_reslog; |
23538 |
++ |
23539 |
++#ifdef CONFIG_GRKERNSEC_RESLOG |
23540 |
++ gr_log_resource(task, res, wanted, gt); |
23541 |
++#endif |
23542 |
++ skip_reslog: |
23543 |
++ |
23544 |
++ if (unlikely(!(gr_status & GR_READY) || !wanted)) |
23545 |
++ return; |
23546 |
++ |
23547 |
++ acl = task->acl; |
23548 |
++ |
23549 |
++ if (likely(!acl || !(acl->mode & (GR_LEARN | GR_INHERITLEARN)) || |
23550 |
++ !(acl->resmask & (1 << (unsigned short) res)))) |
23551 |
++ return; |
23552 |
++ |
23553 |
++ if (wanted >= acl->res[res].rlim_cur) { |
23554 |
++ unsigned long res_add; |
23555 |
++ |
23556 |
++ res_add = wanted; |
23557 |
++ switch (res) { |
23558 |
++ case RLIMIT_CPU: |
23559 |
++ res_add += GR_RLIM_CPU_BUMP; |
23560 |
++ break; |
23561 |
++ case RLIMIT_FSIZE: |
23562 |
++ res_add += GR_RLIM_FSIZE_BUMP; |
23563 |
++ break; |
23564 |
++ case RLIMIT_DATA: |
23565 |
++ res_add += GR_RLIM_DATA_BUMP; |
23566 |
++ break; |
23567 |
++ case RLIMIT_STACK: |
23568 |
++ res_add += GR_RLIM_STACK_BUMP; |
23569 |
++ break; |
23570 |
++ case RLIMIT_CORE: |
23571 |
++ res_add += GR_RLIM_CORE_BUMP; |
23572 |
++ break; |
23573 |
++ case RLIMIT_RSS: |
23574 |
++ res_add += GR_RLIM_RSS_BUMP; |
23575 |
++ break; |
23576 |
++ case RLIMIT_NPROC: |
23577 |
++ res_add += GR_RLIM_NPROC_BUMP; |
23578 |
++ break; |
23579 |
++ case RLIMIT_NOFILE: |
23580 |
++ res_add += GR_RLIM_NOFILE_BUMP; |
23581 |
++ break; |
23582 |
++ case RLIMIT_MEMLOCK: |
23583 |
++ res_add += GR_RLIM_MEMLOCK_BUMP; |
23584 |
++ break; |
23585 |
++ case RLIMIT_AS: |
23586 |
++ res_add += GR_RLIM_AS_BUMP; |
23587 |
++ break; |
23588 |
++ case RLIMIT_LOCKS: |
23589 |
++ res_add += GR_RLIM_LOCKS_BUMP; |
23590 |
++ break; |
23591 |
++ } |
23592 |
++ |
23593 |
++ acl->res[res].rlim_cur = res_add; |
23594 |
++ |
23595 |
++ if (wanted > acl->res[res].rlim_max) |
23596 |
++ acl->res[res].rlim_max = res_add; |
23597 |
++ |
23598 |
++ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, |
23599 |
++ task->role->roletype, acl->filename, |
23600 |
++ acl->res[res].rlim_cur, acl->res[res].rlim_max, |
23601 |
++ "", (unsigned long) res); |
23602 |
++ } |
23603 |
++ |
23604 |
++ return; |
23605 |
++} |
23606 |
++ |
23607 |
++#ifdef CONFIG_PAX_HAVE_ACL_FLAGS |
23608 |
++void |
23609 |
++pax_set_initial_flags(struct linux_binprm *bprm) |
23610 |
++{ |
23611 |
++ struct task_struct *task = current; |
23612 |
++ struct acl_subject_label *proc; |
23613 |
++ unsigned long flags; |
23614 |
++ |
23615 |
++ if (unlikely(!(gr_status & GR_READY))) |
23616 |
++ return; |
23617 |
++ |
23618 |
++ flags = pax_get_flags(task); |
23619 |
++ |
23620 |
++ proc = task->acl; |
23621 |
++ |
23622 |
++ if (proc->pax_flags & GR_PAX_DISABLE_PAGEEXEC) |
23623 |
++ flags &= ~MF_PAX_PAGEEXEC; |
23624 |
++ if (proc->pax_flags & GR_PAX_DISABLE_SEGMEXEC) |
23625 |
++ flags &= ~MF_PAX_SEGMEXEC; |
23626 |
++ if (proc->pax_flags & GR_PAX_DISABLE_RANDMMAP) |
23627 |
++ flags &= ~MF_PAX_RANDMMAP; |
23628 |
++ if (proc->pax_flags & GR_PAX_DISABLE_EMUTRAMP) |
23629 |
++ flags &= ~MF_PAX_EMUTRAMP; |
23630 |
++ if (proc->pax_flags & GR_PAX_DISABLE_MPROTECT) |
23631 |
++ flags &= ~MF_PAX_MPROTECT; |
23632 |
++ |
23633 |
++ if (proc->pax_flags & GR_PAX_ENABLE_PAGEEXEC) |
23634 |
++ flags |= MF_PAX_PAGEEXEC; |
23635 |
++ if (proc->pax_flags & GR_PAX_ENABLE_SEGMEXEC) |
23636 |
++ flags |= MF_PAX_SEGMEXEC; |
23637 |
++ if (proc->pax_flags & GR_PAX_ENABLE_RANDMMAP) |
23638 |
++ flags |= MF_PAX_RANDMMAP; |
23639 |
++ if (proc->pax_flags & GR_PAX_ENABLE_EMUTRAMP) |
23640 |
++ flags |= MF_PAX_EMUTRAMP; |
23641 |
++ if (proc->pax_flags & GR_PAX_ENABLE_MPROTECT) |
23642 |
++ flags |= MF_PAX_MPROTECT; |
23643 |
++ |
23644 |
++ pax_set_flags(task, flags); |
23645 |
++ |
23646 |
++ return; |
23647 |
++} |
23648 |
++#endif |
23649 |
++ |
23650 |
++#ifdef CONFIG_SYSCTL |
23651 |
++/* Eric Biederman likes breaking userland ABI and every inode-based security |
23652 |
++ system to save 35kb of memory */ |
23653 |
++ |
23654 |
++/* we modify the passed in filename, but adjust it back before returning */ |
23655 |
++static struct acl_object_label *gr_lookup_by_name(char *name, unsigned int len) |
23656 |
++{ |
23657 |
++ struct name_entry *nmatch; |
23658 |
++ char *p, *lastp = NULL; |
23659 |
++ struct acl_object_label *obj = NULL, *tmp; |
23660 |
++ struct acl_subject_label *tmpsubj; |
23661 |
++ char c = '\0'; |
23662 |
++ |
23663 |
++ read_lock(&gr_inode_lock); |
23664 |
++ |
23665 |
++ p = name + len - 1; |
23666 |
++ do { |
23667 |
++ nmatch = lookup_name_entry(name); |
23668 |
++ if (lastp != NULL) |
23669 |
++ *lastp = c; |
23670 |
++ |
23671 |
++ if (nmatch == NULL) |
23672 |
++ goto next_component; |
23673 |
++ tmpsubj = current->acl; |
23674 |
++ do { |
23675 |
++ obj = lookup_acl_obj_label(nmatch->inode, nmatch->device, tmpsubj); |
23676 |
++ if (obj != NULL) { |
23677 |
++ tmp = obj->globbed; |
23678 |
++ while (tmp) { |
23679 |
++ if (!glob_match(tmp->filename, name)) { |
23680 |
++ obj = tmp; |
23681 |
++ goto found_obj; |
23682 |
++ } |
23683 |
++ tmp = tmp->next; |
23684 |
++ } |
23685 |
++ goto found_obj; |
23686 |
++ } |
23687 |
++ } while ((tmpsubj = tmpsubj->parent_subject)); |
23688 |
++next_component: |
23689 |
++ /* end case */ |
23690 |
++ if (p == name) |
23691 |
++ break; |
23692 |
++ |
23693 |
++ while (*p != '/') |
23694 |
++ p--; |
23695 |
++ if (p == name) |
23696 |
++ lastp = p + 1; |
23697 |
++ else { |
23698 |
++ lastp = p; |
23699 |
++ p--; |
23700 |
++ } |
23701 |
++ c = *lastp; |
23702 |
++ *lastp = '\0'; |
23703 |
++ } while (1); |
23704 |
++found_obj: |
23705 |
++ read_unlock(&gr_inode_lock); |
23706 |
++ /* obj returned will always be non-null */ |
23707 |
++ return obj; |
23708 |
++} |
23709 |
++ |
23710 |
++/* returns 0 when allowing, non-zero on error |
23711 |
++ op of 0 is used for readdir, so we don't log the names of hidden files |
23712 |
++*/ |
23713 |
++__u32 |
23714 |
++gr_handle_sysctl(const struct ctl_table *table, const int op) |
23715 |
++{ |
23716 |
++ ctl_table *tmp; |
23717 |
++ const char *proc_sys = "/proc/sys"; |
23718 |
++ char *path; |
23719 |
++ struct acl_object_label *obj; |
23720 |
++ unsigned short len = 0, pos = 0, depth = 0, i; |
23721 |
++ __u32 err = 0; |
23722 |
++ __u32 mode = 0; |
23723 |
++ |
23724 |
++ if (unlikely(!(gr_status & GR_READY))) |
23725 |
++ return 0; |
23726 |
++ |
23727 |
++ /* for now, ignore operations on non-sysctl entries if it's not a |
23728 |
++ readdir*/ |
23729 |
++ if (table->child != NULL && op != 0) |
23730 |
++ return 0; |
23731 |
++ |
23732 |
++ mode |= GR_FIND; |
23733 |
++ /* it's only a read if it's an entry, read on dirs is for readdir */ |
23734 |
++ if (op & MAY_READ) |
23735 |
++ mode |= GR_READ; |
23736 |
++ if (op & MAY_WRITE) |
23737 |
++ mode |= GR_WRITE; |
23738 |
++ |
23739 |
++ preempt_disable(); |
23740 |
++ |
23741 |
++ path = per_cpu_ptr(gr_shared_page[0], smp_processor_id()); |
23742 |
++ |
23743 |
++ /* it's only a read/write if it's an actual entry, not a dir |
23744 |
++ (which are opened for readdir) |
23745 |
++ */ |
23746 |
++ |
23747 |
++ /* convert the requested sysctl entry into a pathname */ |
23748 |
++ |
23749 |
++ for (tmp = (ctl_table *)table; tmp != NULL; tmp = tmp->parent) { |
23750 |
++ len += strlen(tmp->procname); |
23751 |
++ len++; |
23752 |
++ depth++; |
23753 |
++ } |
23754 |
++ |
23755 |
++ if ((len + depth + strlen(proc_sys) + 1) > PAGE_SIZE) { |
23756 |
++ /* deny */ |
23757 |
++ goto out; |
23758 |
++ } |
23759 |
++ |
23760 |
++ memset(path, 0, PAGE_SIZE); |
23761 |
++ |
23762 |
++ memcpy(path, proc_sys, strlen(proc_sys)); |
23763 |
++ |
23764 |
++ pos += strlen(proc_sys); |
23765 |
++ |
23766 |
++ for (; depth > 0; depth--) { |
23767 |
++ path[pos] = '/'; |
23768 |
++ pos++; |
23769 |
++ for (i = 1, tmp = (ctl_table *)table; tmp != NULL; tmp = tmp->parent) { |
23770 |
++ if (depth == i) { |
23771 |
++ memcpy(path + pos, tmp->procname, |
23772 |
++ strlen(tmp->procname)); |
23773 |
++ pos += strlen(tmp->procname); |
23774 |
++ } |
23775 |
++ i++; |
23776 |
++ } |
23777 |
++ } |
23778 |
++ |
23779 |
++ obj = gr_lookup_by_name(path, pos); |
23780 |
++ err = obj->mode & (mode | to_gr_audit(mode) | GR_SUPPRESS); |
23781 |
++ |
23782 |
++ if (unlikely((current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) && |
23783 |
++ ((err & mode) != mode))) { |
23784 |
++ __u32 new_mode = mode; |
23785 |
++ |
23786 |
++ new_mode &= ~(GR_AUDITS | GR_SUPPRESS); |
23787 |
++ |
23788 |
++ err = 0; |
23789 |
++ gr_log_learn_sysctl(current, path, new_mode); |
23790 |
++ } else if (!(err & GR_FIND) && !(err & GR_SUPPRESS) && op != 0) { |
23791 |
++ gr_log_hidden_sysctl(GR_DONT_AUDIT, GR_HIDDEN_ACL_MSG, path); |
23792 |
++ err = -ENOENT; |
23793 |
++ } else if (!(err & GR_FIND)) { |
23794 |
++ err = -ENOENT; |
23795 |
++ } else if (((err & mode) & ~GR_FIND) != (mode & ~GR_FIND) && !(err & GR_SUPPRESS)) { |
23796 |
++ gr_log_str4(GR_DONT_AUDIT, GR_SYSCTL_ACL_MSG, "denied", |
23797 |
++ path, (mode & GR_READ) ? " reading" : "", |
23798 |
++ (mode & GR_WRITE) ? " writing" : ""); |
23799 |
++ err = -EACCES; |
23800 |
++ } else if ((err & mode) != mode) { |
23801 |
++ err = -EACCES; |
23802 |
++ } else if ((((err & mode) & ~GR_FIND) == (mode & ~GR_FIND)) && (err & GR_AUDITS)) { |
23803 |
++ gr_log_str4(GR_DO_AUDIT, GR_SYSCTL_ACL_MSG, "successful", |
23804 |
++ path, (mode & GR_READ) ? " reading" : "", |
23805 |
++ (mode & GR_WRITE) ? " writing" : ""); |
23806 |
++ err = 0; |
23807 |
++ } else |
23808 |
++ err = 0; |
23809 |
++ |
23810 |
++ out: |
23811 |
++ preempt_enable(); |
23812 |
++ |
23813 |
++ return err; |
23814 |
++} |
23815 |
++#endif |
23816 |
++ |
23817 |
++int |
23818 |
++gr_handle_proc_ptrace(struct task_struct *task) |
23819 |
++{ |
23820 |
++ struct file *filp; |
23821 |
++ struct task_struct *tmp = task; |
23822 |
++ struct task_struct *curtemp = current; |
23823 |
++ __u32 retmode; |
23824 |
++ |
23825 |
++ if (unlikely(!(gr_status & GR_READY))) |
23826 |
++ return 0; |
23827 |
++ |
23828 |
++ read_lock(&tasklist_lock); |
23829 |
++ read_lock(&grsec_exec_file_lock); |
23830 |
++ filp = task->exec_file; |
23831 |
++ |
23832 |
++ while (tmp->pid > 0) { |
23833 |
++ if (tmp == curtemp) |
23834 |
++ break; |
23835 |
++ tmp = tmp->parent; |
23836 |
++ } |
23837 |
++ |
23838 |
++ if (!filp || (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE))) { |
23839 |
++ read_unlock(&grsec_exec_file_lock); |
23840 |
++ read_unlock(&tasklist_lock); |
23841 |
++ return 1; |
23842 |
++ } |
23843 |
++ |
23844 |
++ retmode = gr_search_file(filp->f_path.dentry, GR_NOPTRACE, filp->f_path.mnt); |
23845 |
++ read_unlock(&grsec_exec_file_lock); |
23846 |
++ read_unlock(&tasklist_lock); |
23847 |
++ |
23848 |
++ if (retmode & GR_NOPTRACE) |
23849 |
++ return 1; |
23850 |
++ |
23851 |
++ if (!(current->acl->mode & GR_POVERRIDE) && !(current->role->roletype & GR_ROLE_GOD) |
23852 |
++ && (current->acl != task->acl || (current->acl != current->role->root_label |
23853 |
++ && current->pid != task->pid))) |
23854 |
++ return 1; |
23855 |
++ |
23856 |
++ return 0; |
23857 |
++} |
23858 |
++ |
23859 |
++int |
23860 |
++gr_handle_ptrace(struct task_struct *task, const long request) |
23861 |
++{ |
23862 |
++ struct task_struct *tmp = task; |
23863 |
++ struct task_struct *curtemp = current; |
23864 |
++ __u32 retmode; |
23865 |
++ |
23866 |
++ if (unlikely(!(gr_status & GR_READY))) |
23867 |
++ return 0; |
23868 |
++ |
23869 |
++ read_lock(&tasklist_lock); |
23870 |
++ while (tmp->pid > 0) { |
23871 |
++ if (tmp == curtemp) |
23872 |
++ break; |
23873 |
++ tmp = tmp->parent; |
23874 |
++ } |
23875 |
++ |
23876 |
++ if (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE)) { |
23877 |
++ read_unlock(&tasklist_lock); |
23878 |
++ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task); |
23879 |
++ return 1; |
23880 |
++ } |
23881 |
++ read_unlock(&tasklist_lock); |
23882 |
++ |
23883 |
++ read_lock(&grsec_exec_file_lock); |
23884 |
++ if (unlikely(!task->exec_file)) { |
23885 |
++ read_unlock(&grsec_exec_file_lock); |
23886 |
++ return 0; |
23887 |
++ } |
23888 |
++ |
23889 |
++ retmode = gr_search_file(task->exec_file->f_path.dentry, GR_PTRACERD | GR_NOPTRACE, task->exec_file->f_path.mnt); |
23890 |
++ read_unlock(&grsec_exec_file_lock); |
23891 |
++ |
23892 |
++ if (retmode & GR_NOPTRACE) { |
23893 |
++ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task); |
23894 |
++ return 1; |
23895 |
++ } |
23896 |
++ |
23897 |
++ if (retmode & GR_PTRACERD) { |
23898 |
++ switch (request) { |
23899 |
++ case PTRACE_POKETEXT: |
23900 |
++ case PTRACE_POKEDATA: |
23901 |
++ case PTRACE_POKEUSR: |
23902 |
++#if !defined(CONFIG_PPC32) && !defined(CONFIG_PPC64) && !defined(CONFIG_PARISC) && !defined(CONFIG_ALPHA) && !defined(CONFIG_IA64) |
23903 |
++ case PTRACE_SETREGS: |
23904 |
++ case PTRACE_SETFPREGS: |
23905 |
++#endif |
23906 |
++#ifdef CONFIG_X86 |
23907 |
++ case PTRACE_SETFPXREGS: |
23908 |
++#endif |
23909 |
++#ifdef CONFIG_ALTIVEC |
23910 |
++ case PTRACE_SETVRREGS: |
23911 |
++#endif |
23912 |
++ return 1; |
23913 |
++ default: |
23914 |
++ return 0; |
23915 |
++ } |
23916 |
++ } else if (!(current->acl->mode & GR_POVERRIDE) && |
23917 |
++ !(current->role->roletype & GR_ROLE_GOD) && |
23918 |
++ (current->acl != task->acl)) { |
23919 |
++ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task); |
23920 |
++ return 1; |
23921 |
++ } |
23922 |
++ |
23923 |
++ return 0; |
23924 |
++} |
23925 |
++ |
23926 |
++static int is_writable_mmap(const struct file *filp) |
23927 |
++{ |
23928 |
++ struct task_struct *task = current; |
23929 |
++ struct acl_object_label *obj, *obj2; |
23930 |
++ |
23931 |
++ if (gr_status & GR_READY && !(task->acl->mode & GR_OVERRIDE) && |
23932 |
++ !task->is_writable && S_ISREG(filp->f_path.dentry->d_inode->i_mode)) { |
23933 |
++ obj = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, default_role->root_label); |
23934 |
++ obj2 = chk_obj_label(filp->f_path.dentry, filp->f_path.mnt, |
23935 |
++ task->role->root_label); |
23936 |
++ if (unlikely((obj->mode & GR_WRITE) || (obj2->mode & GR_WRITE))) { |
23937 |
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_WRITLIB_ACL_MSG, filp->f_path.dentry, filp->f_path.mnt); |
23938 |
++ return 1; |
23939 |
++ } |
23940 |
++ } |
23941 |
++ return 0; |
23942 |
++} |
23943 |
++ |
23944 |
++int |
23945 |
++gr_acl_handle_mmap(const struct file *file, const unsigned long prot) |
23946 |
++{ |
23947 |
++ __u32 mode; |
23948 |
++ |
23949 |
++ if (unlikely(!file || !(prot & PROT_EXEC))) |
23950 |
++ return 1; |
23951 |
++ |
23952 |
++ if (is_writable_mmap(file)) |
23953 |
++ return 0; |
23954 |
++ |
23955 |
++ mode = |
23956 |
++ gr_search_file(file->f_path.dentry, |
23957 |
++ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS, |
23958 |
++ file->f_path.mnt); |
23959 |
++ |
23960 |
++ if (!gr_tpe_allow(file)) |
23961 |
++ return 0; |
23962 |
++ |
23963 |
++ if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) { |
23964 |
++ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MMAP_ACL_MSG, file->f_path.dentry, file->f_path.mnt); |
23965 |
++ return 0; |
23966 |
++ } else if (unlikely(!(mode & GR_EXEC))) { |
23967 |
++ return 0; |
23968 |
++ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) { |
23969 |
++ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MMAP_ACL_MSG, file->f_path.dentry, file->f_path.mnt); |
23970 |
++ return 1; |
23971 |
++ } |
23972 |
++ |
23973 |
++ return 1; |
23974 |
++} |
23975 |
++ |
23976 |
++int |
23977 |
++gr_acl_handle_mprotect(const struct file *file, const unsigned long prot) |
23978 |
++{ |
23979 |
++ __u32 mode; |
23980 |
++ |
23981 |
++ if (unlikely(!file || !(prot & PROT_EXEC))) |
23982 |
++ return 1; |
23983 |
++ |
23984 |
++ if (is_writable_mmap(file)) |
23985 |
++ return 0; |
23986 |
++ |
23987 |
++ mode = |
23988 |
++ gr_search_file(file->f_path.dentry, |
23989 |
++ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS, |
23990 |
++ file->f_path.mnt); |
23991 |
++ |
23992 |
++ if (!gr_tpe_allow(file)) |
23993 |
++ return 0; |
23994 |
++ |
23995 |
++ if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) { |
23996 |
++ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MPROTECT_ACL_MSG, file->f_path.dentry, file->f_path.mnt); |
23997 |
++ return 0; |
23998 |
++ } else if (unlikely(!(mode & GR_EXEC))) { |
23999 |
++ return 0; |
24000 |
++ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) { |
24001 |
++ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MPROTECT_ACL_MSG, file->f_path.dentry, file->f_path.mnt); |
24002 |
++ return 1; |
24003 |
++ } |
24004 |
++ |
24005 |
++ return 1; |
24006 |
++} |
24007 |
++ |
24008 |
++void |
24009 |
++gr_acl_handle_psacct(struct task_struct *task, const long code) |
24010 |
++{ |
24011 |
++ unsigned long runtime; |
24012 |
++ unsigned long cputime; |
24013 |
++ unsigned int wday, cday; |
24014 |
++ __u8 whr, chr; |
24015 |
++ __u8 wmin, cmin; |
24016 |
++ __u8 wsec, csec; |
24017 |
++ struct timespec timeval; |
24018 |
++ |
24019 |
++ if (unlikely(!(gr_status & GR_READY) || !task->acl || |
24020 |
++ !(task->acl->mode & GR_PROCACCT))) |
24021 |
++ return; |
24022 |
++ |
24023 |
++ do_posix_clock_monotonic_gettime(&timeval); |
24024 |
++ runtime = timeval.tv_sec - task->start_time.tv_sec; |
24025 |
++ wday = runtime / (3600 * 24); |
24026 |
++ runtime -= wday * (3600 * 24); |
24027 |
++ whr = runtime / 3600; |
24028 |
++ runtime -= whr * 3600; |
24029 |
++ wmin = runtime / 60; |
24030 |
++ runtime -= wmin * 60; |
24031 |
++ wsec = runtime; |
24032 |
++ |
24033 |
++ cputime = (task->utime + task->stime) / HZ; |
24034 |
++ cday = cputime / (3600 * 24); |
24035 |
++ cputime -= cday * (3600 * 24); |
24036 |
++ chr = cputime / 3600; |
24037 |
++ cputime -= chr * 3600; |
24038 |
++ cmin = cputime / 60; |
24039 |
++ cputime -= cmin * 60; |
24040 |
++ csec = cputime; |
24041 |
++ |
24042 |
++ gr_log_procacct(GR_DO_AUDIT, GR_ACL_PROCACCT_MSG, task, wday, whr, wmin, wsec, cday, chr, cmin, csec, code); |
24043 |
++ |
24044 |
++ return; |
24045 |
++} |
24046 |
++ |
24047 |
++void gr_set_kernel_label(struct task_struct *task) |
24048 |
++{ |
24049 |
++ if (gr_status & GR_READY) { |
24050 |
++ task->role = kernel_role; |
24051 |
++ task->acl = kernel_role->root_label; |
24052 |
++ } |
24053 |
++ return; |
24054 |
++} |
24055 |
++ |
24056 |
++int gr_acl_handle_filldir(const struct file *file, const char *name, const unsigned int namelen, const ino_t ino) |
24057 |
++{ |
24058 |
++ struct task_struct *task = current; |
24059 |
++ struct dentry *dentry = file->f_path.dentry; |
24060 |
++ struct vfsmount *mnt = file->f_path.mnt; |
24061 |
++ struct acl_object_label *obj, *tmp; |
24062 |
++ struct acl_subject_label *subj; |
24063 |
++ unsigned int bufsize; |
24064 |
++ int is_not_root; |
24065 |
++ char *path; |
24066 |
++ |
24067 |
++ if (unlikely(!(gr_status & GR_READY))) |
24068 |
++ return 1; |
24069 |
++ |
24070 |
++ if (task->acl->mode & (GR_LEARN | GR_INHERITLEARN)) |
24071 |
++ return 1; |
24072 |
++ |
24073 |
++ /* ignore Eric Biederman */ |
24074 |
++ if (IS_PRIVATE(dentry->d_inode)) |
24075 |
++ return 1; |
24076 |
++ |
24077 |
++ subj = task->acl; |
24078 |
++ do { |
24079 |
++ obj = lookup_acl_obj_label(ino, dentry->d_inode->i_sb->s_dev, subj); |
24080 |
++ if (obj != NULL) |
24081 |
++ return (obj->mode & GR_FIND) ? 1 : 0; |
24082 |
++ } while ((subj = subj->parent_subject)); |
24083 |
++ |
24084 |
++ obj = chk_obj_label(dentry, mnt, task->acl); |
24085 |
++ if (obj->globbed == NULL) |
24086 |
++ return (obj->mode & GR_FIND) ? 1 : 0; |
24087 |
++ |
24088 |
++ is_not_root = ((obj->filename[0] == '/') && |
24089 |
++ (obj->filename[1] == '\0')) ? 0 : 1; |
24090 |
++ bufsize = PAGE_SIZE - namelen - is_not_root; |
24091 |
++ |
24092 |
++ /* check bufsize > PAGE_SIZE || bufsize == 0 */ |
24093 |
++ if (unlikely((bufsize - 1) > (PAGE_SIZE - 1))) |
24094 |
++ return 1; |
24095 |
++ |
24096 |
++ preempt_disable(); |
24097 |
++ path = d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()), |
24098 |
++ bufsize); |
24099 |
++ |
24100 |
++ bufsize = strlen(path); |
24101 |
++ |
24102 |
++ /* if base is "/", don't append an additional slash */ |
24103 |
++ if (is_not_root) |
24104 |
++ *(path + bufsize) = '/'; |
24105 |
++ memcpy(path + bufsize + is_not_root, name, namelen); |
24106 |
++ *(path + bufsize + namelen + is_not_root) = '\0'; |
24107 |
++ |
24108 |
++ tmp = obj->globbed; |
24109 |
++ while (tmp) { |
24110 |
++ if (!glob_match(tmp->filename, path)) { |
24111 |
++ preempt_enable(); |
24112 |
++ return (tmp->mode & GR_FIND) ? 1 : 0; |
24113 |
++ } |
24114 |
++ tmp = tmp->next; |
24115 |
++ } |
24116 |
++ preempt_enable(); |
24117 |
++ return (obj->mode & GR_FIND) ? 1 : 0; |
24118 |
++} |
24119 |
++ |
24120 |
++EXPORT_SYMBOL(gr_learn_resource); |
24121 |
++EXPORT_SYMBOL(gr_set_kernel_label); |
24122 |
++#ifdef CONFIG_SECURITY |
24123 |
++EXPORT_SYMBOL(gr_check_user_change); |
24124 |
++EXPORT_SYMBOL(gr_check_group_change); |
24125 |
++#endif |
24126 |
++ |
24127 |
+diff -urNp linux-2.6.28.8/grsecurity/gracl_cap.c linux-2.6.28.8/grsecurity/gracl_cap.c |
24128 |
+--- linux-2.6.28.8/grsecurity/gracl_cap.c 1969-12-31 19:00:00.000000000 -0500 |
24129 |
++++ linux-2.6.28.8/grsecurity/gracl_cap.c 2009-02-21 09:37:49.000000000 -0500 |
24130 |
+@@ -0,0 +1,129 @@ |
24131 |
++#include <linux/kernel.h> |
24132 |
++#include <linux/module.h> |
24133 |
++#include <linux/sched.h> |
24134 |
++#include <linux/gracl.h> |
24135 |
++#include <linux/grsecurity.h> |
24136 |
++#include <linux/grinternal.h> |
24137 |
++ |
24138 |
++static const char *captab_log[] = { |
24139 |
++ "CAP_CHOWN", |
24140 |
++ "CAP_DAC_OVERRIDE", |
24141 |
++ "CAP_DAC_READ_SEARCH", |
24142 |
++ "CAP_FOWNER", |
24143 |
++ "CAP_FSETID", |
24144 |
++ "CAP_KILL", |
24145 |
++ "CAP_SETGID", |
24146 |
++ "CAP_SETUID", |
24147 |
++ "CAP_SETPCAP", |
24148 |
++ "CAP_LINUX_IMMUTABLE", |
24149 |
++ "CAP_NET_BIND_SERVICE", |
24150 |
++ "CAP_NET_BROADCAST", |
24151 |
++ "CAP_NET_ADMIN", |
24152 |
++ "CAP_NET_RAW", |
24153 |
++ "CAP_IPC_LOCK", |
24154 |
++ "CAP_IPC_OWNER", |
24155 |
++ "CAP_SYS_MODULE", |
24156 |
++ "CAP_SYS_RAWIO", |
24157 |
++ "CAP_SYS_CHROOT", |
24158 |
++ "CAP_SYS_PTRACE", |
24159 |
++ "CAP_SYS_PACCT", |
24160 |
++ "CAP_SYS_ADMIN", |
24161 |
++ "CAP_SYS_BOOT", |
24162 |
++ "CAP_SYS_NICE", |
24163 |
++ "CAP_SYS_RESOURCE", |
24164 |
++ "CAP_SYS_TIME", |
24165 |
++ "CAP_SYS_TTY_CONFIG", |
24166 |
++ "CAP_MKNOD", |
24167 |
++ "CAP_LEASE", |
24168 |
++ "CAP_AUDIT_WRITE", |
24169 |
++ "CAP_AUDIT_CONTROL", |
24170 |
++ "CAP_SETFCAP", |
24171 |
++ "CAP_MAC_OVERRIDE", |
24172 |
++ "CAP_MAC_ADMIN" |
24173 |
++}; |
24174 |
++ |
24175 |
++EXPORT_SYMBOL(gr_task_is_capable); |
24176 |
++EXPORT_SYMBOL(gr_is_capable_nolog); |
24177 |
++ |
24178 |
++int |
24179 |
++gr_task_is_capable(struct task_struct *task, const int cap) |
24180 |
++{ |
24181 |
++ struct acl_subject_label *curracl; |
24182 |
++ kernel_cap_t cap_drop = __cap_empty_set, cap_mask = __cap_empty_set; |
24183 |
++ |
24184 |
++ if (!gr_acl_is_enabled()) |
24185 |
++ return 1; |
24186 |
++ |
24187 |
++ curracl = task->acl; |
24188 |
++ |
24189 |
++ cap_drop = curracl->cap_lower; |
24190 |
++ cap_mask = curracl->cap_mask; |
24191 |
++ |
24192 |
++ while ((curracl = curracl->parent_subject)) { |
24193 |
++ /* if the cap isn't specified in the current computed mask but is specified in the |
24194 |
++ current level subject, and is lowered in the current level subject, then add |
24195 |
++ it to the set of dropped capabilities |
24196 |
++ otherwise, add the current level subject's mask to the current computed mask |
24197 |
++ */ |
24198 |
++ if (!cap_raised(cap_mask, cap) && cap_raised(curracl->cap_mask, cap)) { |
24199 |
++ cap_raise(cap_mask, cap); |
24200 |
++ if (cap_raised(curracl->cap_lower, cap)) |
24201 |
++ cap_raise(cap_drop, cap); |
24202 |
++ } |
24203 |
++ } |
24204 |
++ |
24205 |
++ if (!cap_raised(cap_drop, cap)) |
24206 |
++ return 1; |
24207 |
++ |
24208 |
++ curracl = task->acl; |
24209 |
++ |
24210 |
++ if ((curracl->mode & (GR_LEARN | GR_INHERITLEARN)) |
24211 |
++ && cap_raised(task->cap_effective, cap)) { |
24212 |
++ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, |
24213 |
++ task->role->roletype, task->uid, |
24214 |
++ task->gid, task->exec_file ? |
24215 |
++ gr_to_filename(task->exec_file->f_path.dentry, |
24216 |
++ task->exec_file->f_path.mnt) : curracl->filename, |
24217 |
++ curracl->filename, 0UL, |
24218 |
++ 0UL, "", (unsigned long) cap, NIPQUAD(task->signal->curr_ip)); |
24219 |
++ return 1; |
24220 |
++ } |
24221 |
++ |
24222 |
++ if ((cap >= 0) && (cap < (sizeof(captab_log)/sizeof(captab_log[0]))) && cap_raised(task->cap_effective, cap)) |
24223 |
++ gr_log_cap(GR_DONT_AUDIT, GR_CAP_ACL_MSG, task, captab_log[cap]); |
24224 |
++ return 0; |
24225 |
++} |
24226 |
++ |
24227 |
++int |
24228 |
++gr_is_capable_nolog(const int cap) |
24229 |
++{ |
24230 |
++ struct acl_subject_label *curracl; |
24231 |
++ kernel_cap_t cap_drop = __cap_empty_set, cap_mask = __cap_empty_set; |
24232 |
++ |
24233 |
++ if (!gr_acl_is_enabled()) |
24234 |
++ return 1; |
24235 |
++ |
24236 |
++ curracl = current->acl; |
24237 |
++ |
24238 |
++ cap_drop = curracl->cap_lower; |
24239 |
++ cap_mask = curracl->cap_mask; |
24240 |
++ |
24241 |
++ while ((curracl = curracl->parent_subject)) { |
24242 |
++ /* if the cap isn't specified in the current computed mask but is specified in the |
24243 |
++ current level subject, and is lowered in the current level subject, then add |
24244 |
++ it to the set of dropped capabilities |
24245 |
++ otherwise, add the current level subject's mask to the current computed mask |
24246 |
++ */ |
24247 |
++ if (!cap_raised(cap_mask, cap) && cap_raised(curracl->cap_mask, cap)) { |
24248 |
++ cap_raise(cap_mask, cap); |
24249 |
++ if (cap_raised(curracl->cap_lower, cap)) |
24250 |
++ cap_raise(cap_drop, cap); |
24251 |
++ } |
24252 |
++ } |
24253 |
++ |
24254 |
++ if (!cap_raised(cap_drop, cap)) |
24255 |
++ return 1; |
24256 |
++ |
24257 |
++ return 0; |
24258 |
++} |
24259 |
++ |
24260 |
+diff -urNp linux-2.6.28.8/grsecurity/gracl_fs.c linux-2.6.28.8/grsecurity/gracl_fs.c |
24261 |
+--- linux-2.6.28.8/grsecurity/gracl_fs.c 1969-12-31 19:00:00.000000000 -0500 |
24262 |
++++ linux-2.6.28.8/grsecurity/gracl_fs.c 2009-02-21 09:37:49.000000000 -0500 |
24263 |
+@@ -0,0 +1,423 @@ |
24264 |
++#include <linux/kernel.h> |
24265 |
++#include <linux/sched.h> |
24266 |
++#include <linux/types.h> |
24267 |
++#include <linux/fs.h> |
24268 |
++#include <linux/file.h> |
24269 |
++#include <linux/stat.h> |
24270 |
++#include <linux/grsecurity.h> |
24271 |
++#include <linux/grinternal.h> |
24272 |
++#include <linux/gracl.h> |
24273 |
++ |
24274 |
++__u32 |
24275 |
++gr_acl_handle_hidden_file(const struct dentry * dentry, |
24276 |
++ const struct vfsmount * mnt) |
24277 |
++{ |
24278 |
++ __u32 mode; |
24279 |
++ |
24280 |
++ if (unlikely(!dentry->d_inode)) |
24281 |
++ return GR_FIND; |
24282 |
++ |
24283 |
++ mode = |
24284 |
++ gr_search_file(dentry, GR_FIND | GR_AUDIT_FIND | GR_SUPPRESS, mnt); |
24285 |
++ |
24286 |
++ if (unlikely(mode & GR_FIND && mode & GR_AUDIT_FIND)) { |
24287 |
++ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt); |
24288 |
++ return mode; |
24289 |
++ } else if (unlikely(!(mode & GR_FIND) && !(mode & GR_SUPPRESS))) { |
24290 |
++ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt); |
24291 |
++ return 0; |
24292 |
++ } else if (unlikely(!(mode & GR_FIND))) |
24293 |
++ return 0; |
24294 |
++ |
24295 |
++ return GR_FIND; |
24296 |
++} |
24297 |
++ |
24298 |
++__u32 |
24299 |
++gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt, |
24300 |
++ const int fmode) |
24301 |
++{ |
24302 |
++ __u32 reqmode = GR_FIND; |
24303 |
++ __u32 mode; |
24304 |
++ |
24305 |
++ if (unlikely(!dentry->d_inode)) |
24306 |
++ return reqmode; |
24307 |
++ |
24308 |
++ if (unlikely(fmode & O_APPEND)) |
24309 |
++ reqmode |= GR_APPEND; |
24310 |
++ else if (unlikely(fmode & FMODE_WRITE)) |
24311 |
++ reqmode |= GR_WRITE; |
24312 |
++ if (likely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY))) |
24313 |
++ reqmode |= GR_READ; |
24314 |
++ |
24315 |
++ mode = |
24316 |
++ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, |
24317 |
++ mnt); |
24318 |
++ |
24319 |
++ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) { |
24320 |
++ gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt, |
24321 |
++ reqmode & GR_READ ? " reading" : "", |
24322 |
++ reqmode & GR_WRITE ? " writing" : reqmode & |
24323 |
++ GR_APPEND ? " appending" : ""); |
24324 |
++ return reqmode; |
24325 |
++ } else |
24326 |
++ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS))) |
24327 |
++ { |
24328 |
++ gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt, |
24329 |
++ reqmode & GR_READ ? " reading" : "", |
24330 |
++ reqmode & GR_WRITE ? " writing" : reqmode & |
24331 |
++ GR_APPEND ? " appending" : ""); |
24332 |
++ return 0; |
24333 |
++ } else if (unlikely((mode & reqmode) != reqmode)) |
24334 |
++ return 0; |
24335 |
++ |
24336 |
++ return reqmode; |
24337 |
++} |
24338 |
++ |
24339 |
++__u32 |
24340 |
++gr_acl_handle_creat(const struct dentry * dentry, |
24341 |
++ const struct dentry * p_dentry, |
24342 |
++ const struct vfsmount * p_mnt, const int fmode, |
24343 |
++ const int imode) |
24344 |
++{ |
24345 |
++ __u32 reqmode = GR_WRITE | GR_CREATE; |
24346 |
++ __u32 mode; |
24347 |
++ |
24348 |
++ if (unlikely(fmode & O_APPEND)) |
24349 |
++ reqmode |= GR_APPEND; |
24350 |
++ if (unlikely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY))) |
24351 |
++ reqmode |= GR_READ; |
24352 |
++ if (unlikely((fmode & O_CREAT) && (imode & (S_ISUID | S_ISGID)))) |
24353 |
++ reqmode |= GR_SETID; |
24354 |
++ |
24355 |
++ mode = |
24356 |
++ gr_check_create(dentry, p_dentry, p_mnt, |
24357 |
++ reqmode | to_gr_audit(reqmode) | GR_SUPPRESS); |
24358 |
++ |
24359 |
++ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) { |
24360 |
++ gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt, |
24361 |
++ reqmode & GR_READ ? " reading" : "", |
24362 |
++ reqmode & GR_WRITE ? " writing" : reqmode & |
24363 |
++ GR_APPEND ? " appending" : ""); |
24364 |
++ return reqmode; |
24365 |
++ } else |
24366 |
++ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS))) |
24367 |
++ { |
24368 |
++ gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt, |
24369 |
++ reqmode & GR_READ ? " reading" : "", |
24370 |
++ reqmode & GR_WRITE ? " writing" : reqmode & |
24371 |
++ GR_APPEND ? " appending" : ""); |
24372 |
++ return 0; |
24373 |
++ } else if (unlikely((mode & reqmode) != reqmode)) |
24374 |
++ return 0; |
24375 |
++ |
24376 |
++ return reqmode; |
24377 |
++} |
24378 |
++ |
24379 |
++__u32 |
24380 |
++gr_acl_handle_access(const struct dentry * dentry, const struct vfsmount * mnt, |
24381 |
++ const int fmode) |
24382 |
++{ |
24383 |
++ __u32 mode, reqmode = GR_FIND; |
24384 |
++ |
24385 |
++ if ((fmode & S_IXOTH) && !S_ISDIR(dentry->d_inode->i_mode)) |
24386 |
++ reqmode |= GR_EXEC; |
24387 |
++ if (fmode & S_IWOTH) |
24388 |
++ reqmode |= GR_WRITE; |
24389 |
++ if (fmode & S_IROTH) |
24390 |
++ reqmode |= GR_READ; |
24391 |
++ |
24392 |
++ mode = |
24393 |
++ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, |
24394 |
++ mnt); |
24395 |
++ |
24396 |
++ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) { |
24397 |
++ gr_log_fs_rbac_mode3(GR_DO_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt, |
24398 |
++ reqmode & GR_READ ? " reading" : "", |
24399 |
++ reqmode & GR_WRITE ? " writing" : "", |
24400 |
++ reqmode & GR_EXEC ? " executing" : ""); |
24401 |
++ return reqmode; |
24402 |
++ } else |
24403 |
++ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS))) |
24404 |
++ { |
24405 |
++ gr_log_fs_rbac_mode3(GR_DONT_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt, |
24406 |
++ reqmode & GR_READ ? " reading" : "", |
24407 |
++ reqmode & GR_WRITE ? " writing" : "", |
24408 |
++ reqmode & GR_EXEC ? " executing" : ""); |
24409 |
++ return 0; |
24410 |
++ } else if (unlikely((mode & reqmode) != reqmode)) |
24411 |
++ return 0; |
24412 |
++ |
24413 |
++ return reqmode; |
24414 |
++} |
24415 |
++ |
24416 |
++static __u32 generic_fs_handler(const struct dentry *dentry, const struct vfsmount *mnt, __u32 reqmode, const char *fmt) |
24417 |
++{ |
24418 |
++ __u32 mode; |
24419 |
++ |
24420 |
++ mode = gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, mnt); |
24421 |
++ |
24422 |
++ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) { |
24423 |
++ gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, dentry, mnt); |
24424 |
++ return mode; |
24425 |
++ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) { |
24426 |
++ gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, dentry, mnt); |
24427 |
++ return 0; |
24428 |
++ } else if (unlikely((mode & (reqmode)) != (reqmode))) |
24429 |
++ return 0; |
24430 |
++ |
24431 |
++ return (reqmode); |
24432 |
++} |
24433 |
++ |
24434 |
++__u32 |
24435 |
++gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt) |
24436 |
++{ |
24437 |
++ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_RMDIR_ACL_MSG); |
24438 |
++} |
24439 |
++ |
24440 |
++__u32 |
24441 |
++gr_acl_handle_unlink(const struct dentry *dentry, const struct vfsmount *mnt) |
24442 |
++{ |
24443 |
++ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_UNLINK_ACL_MSG); |
24444 |
++} |
24445 |
++ |
24446 |
++__u32 |
24447 |
++gr_acl_handle_truncate(const struct dentry *dentry, const struct vfsmount *mnt) |
24448 |
++{ |
24449 |
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_TRUNCATE_ACL_MSG); |
24450 |
++} |
24451 |
++ |
24452 |
++__u32 |
24453 |
++gr_acl_handle_utime(const struct dentry *dentry, const struct vfsmount *mnt) |
24454 |
++{ |
24455 |
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_ATIME_ACL_MSG); |
24456 |
++} |
24457 |
++ |
24458 |
++__u32 |
24459 |
++gr_acl_handle_fchmod(const struct dentry *dentry, const struct vfsmount *mnt, |
24460 |
++ mode_t mode) |
24461 |
++{ |
24462 |
++ if (unlikely(dentry->d_inode && S_ISSOCK(dentry->d_inode->i_mode))) |
24463 |
++ return 1; |
24464 |
++ |
24465 |
++ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) { |
24466 |
++ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID, |
24467 |
++ GR_FCHMOD_ACL_MSG); |
24468 |
++ } else { |
24469 |
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_FCHMOD_ACL_MSG); |
24470 |
++ } |
24471 |
++} |
24472 |
++ |
24473 |
++__u32 |
24474 |
++gr_acl_handle_chmod(const struct dentry *dentry, const struct vfsmount *mnt, |
24475 |
++ mode_t mode) |
24476 |
++{ |
24477 |
++ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) { |
24478 |
++ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID, |
24479 |
++ GR_CHMOD_ACL_MSG); |
24480 |
++ } else { |
24481 |
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHMOD_ACL_MSG); |
24482 |
++ } |
24483 |
++} |
24484 |
++ |
24485 |
++__u32 |
24486 |
++gr_acl_handle_chown(const struct dentry *dentry, const struct vfsmount *mnt) |
24487 |
++{ |
24488 |
++ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHOWN_ACL_MSG); |
24489 |
++} |
24490 |
++ |
24491 |
++__u32 |
24492 |
++gr_acl_handle_execve(const struct dentry *dentry, const struct vfsmount *mnt) |
24493 |
++{ |
24494 |
++ return generic_fs_handler(dentry, mnt, GR_EXEC, GR_EXEC_ACL_MSG); |
24495 |
++} |
24496 |
++ |
24497 |
++__u32 |
24498 |
++gr_acl_handle_unix(const struct dentry *dentry, const struct vfsmount *mnt) |
24499 |
++{ |
24500 |
++ return generic_fs_handler(dentry, mnt, GR_READ | GR_WRITE, |
24501 |
++ GR_UNIXCONNECT_ACL_MSG); |
24502 |
++} |
24503 |
++ |
24504 |
++/* hardlinks require at minimum create permission, |
24505 |
++ any additional privilege required is based on the |
24506 |
++ privilege of the file being linked to |
24507 |
++*/ |
24508 |
++__u32 |
24509 |
++gr_acl_handle_link(const struct dentry * new_dentry, |
24510 |
++ const struct dentry * parent_dentry, |
24511 |
++ const struct vfsmount * parent_mnt, |
24512 |
++ const struct dentry * old_dentry, |
24513 |
++ const struct vfsmount * old_mnt, const char *to) |
24514 |
++{ |
24515 |
++ __u32 mode; |
24516 |
++ __u32 needmode = GR_CREATE | GR_LINK; |
24517 |
++ __u32 needaudit = GR_AUDIT_CREATE | GR_AUDIT_LINK; |
24518 |
++ |
24519 |
++ mode = |
24520 |
++ gr_check_link(new_dentry, parent_dentry, parent_mnt, old_dentry, |
24521 |
++ old_mnt); |
24522 |
++ |
24523 |
++ if (unlikely(((mode & needmode) == needmode) && (mode & needaudit))) { |
24524 |
++ gr_log_fs_rbac_str(GR_DO_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to); |
24525 |
++ return mode; |
24526 |
++ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) { |
24527 |
++ gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to); |
24528 |
++ return 0; |
24529 |
++ } else if (unlikely((mode & needmode) != needmode)) |
24530 |
++ return 0; |
24531 |
++ |
24532 |
++ return 1; |
24533 |
++} |
24534 |
++ |
24535 |
++__u32 |
24536 |
++gr_acl_handle_symlink(const struct dentry * new_dentry, |
24537 |
++ const struct dentry * parent_dentry, |
24538 |
++ const struct vfsmount * parent_mnt, const char *from) |
24539 |
++{ |
24540 |
++ __u32 needmode = GR_WRITE | GR_CREATE; |
24541 |
++ __u32 mode; |
24542 |
++ |
24543 |
++ mode = |
24544 |
++ gr_check_create(new_dentry, parent_dentry, parent_mnt, |
24545 |
++ GR_CREATE | GR_AUDIT_CREATE | |
24546 |
++ GR_WRITE | GR_AUDIT_WRITE | GR_SUPPRESS); |
24547 |
++ |
24548 |
++ if (unlikely(mode & GR_WRITE && mode & GR_AUDITS)) { |
24549 |
++ gr_log_fs_str_rbac(GR_DO_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt); |
24550 |
++ return mode; |
24551 |
++ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) { |
24552 |
++ gr_log_fs_str_rbac(GR_DONT_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt); |
24553 |
++ return 0; |
24554 |
++ } else if (unlikely((mode & needmode) != needmode)) |
24555 |
++ return 0; |
24556 |
++ |
24557 |
++ return (GR_WRITE | GR_CREATE); |
24558 |
++} |
24559 |
++ |
24560 |
++static __u32 generic_fs_create_handler(const struct dentry *new_dentry, const struct dentry *parent_dentry, const struct vfsmount *parent_mnt, __u32 reqmode, const char *fmt) |
24561 |
++{ |
24562 |
++ __u32 mode; |
24563 |
++ |
24564 |
++ mode = gr_check_create(new_dentry, parent_dentry, parent_mnt, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS); |
24565 |
++ |
24566 |
++ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) { |
24567 |
++ gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, new_dentry, parent_mnt); |
24568 |
++ return mode; |
24569 |
++ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) { |
24570 |
++ gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, new_dentry, parent_mnt); |
24571 |
++ return 0; |
24572 |
++ } else if (unlikely((mode & (reqmode)) != (reqmode))) |
24573 |
++ return 0; |
24574 |
++ |
24575 |
++ return (reqmode); |
24576 |
++} |
24577 |
++ |
24578 |
++__u32 |
24579 |
++gr_acl_handle_mknod(const struct dentry * new_dentry, |
24580 |
++ const struct dentry * parent_dentry, |
24581 |
++ const struct vfsmount * parent_mnt, |
24582 |
++ const int mode) |
24583 |
++{ |
24584 |
++ __u32 reqmode = GR_WRITE | GR_CREATE; |
24585 |
++ if (unlikely(mode & (S_ISUID | S_ISGID))) |
24586 |
++ reqmode |= GR_SETID; |
24587 |
++ |
24588 |
++ return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt, |
24589 |
++ reqmode, GR_MKNOD_ACL_MSG); |
24590 |
++} |
24591 |
++ |
24592 |
++__u32 |
24593 |
++gr_acl_handle_mkdir(const struct dentry *new_dentry, |
24594 |
++ const struct dentry *parent_dentry, |
24595 |
++ const struct vfsmount *parent_mnt) |
24596 |
++{ |
24597 |
++ return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt, |
24598 |
++ GR_WRITE | GR_CREATE, GR_MKDIR_ACL_MSG); |
24599 |
++} |
24600 |
++ |
24601 |
++#define RENAME_CHECK_SUCCESS(old, new) \ |
24602 |
++ (((old & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)) && \ |
24603 |
++ ((new & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ))) |
24604 |
++ |
24605 |
++int |
24606 |
++gr_acl_handle_rename(struct dentry *new_dentry, |
24607 |
++ struct dentry *parent_dentry, |
24608 |
++ const struct vfsmount *parent_mnt, |
24609 |
++ struct dentry *old_dentry, |
24610 |
++ struct inode *old_parent_inode, |
24611 |
++ struct vfsmount *old_mnt, const char *newname) |
24612 |
++{ |
24613 |
++ __u32 comp1, comp2; |
24614 |
++ int error = 0; |
24615 |
++ |
24616 |
++ if (unlikely(!gr_acl_is_enabled())) |
24617 |
++ return 0; |
24618 |
++ |
24619 |
++ if (!new_dentry->d_inode) { |
24620 |
++ comp1 = gr_check_create(new_dentry, parent_dentry, parent_mnt, |
24621 |
++ GR_READ | GR_WRITE | GR_CREATE | GR_AUDIT_READ | |
24622 |
++ GR_AUDIT_WRITE | GR_AUDIT_CREATE | GR_SUPPRESS); |
24623 |
++ comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE | |
24624 |
++ GR_DELETE | GR_AUDIT_DELETE | |
24625 |
++ GR_AUDIT_READ | GR_AUDIT_WRITE | |
24626 |
++ GR_SUPPRESS, old_mnt); |
24627 |
++ } else { |
24628 |
++ comp1 = gr_search_file(new_dentry, GR_READ | GR_WRITE | |
24629 |
++ GR_CREATE | GR_DELETE | |
24630 |
++ GR_AUDIT_CREATE | GR_AUDIT_DELETE | |
24631 |
++ GR_AUDIT_READ | GR_AUDIT_WRITE | |
24632 |
++ GR_SUPPRESS, parent_mnt); |
24633 |
++ comp2 = |
24634 |
++ gr_search_file(old_dentry, |
24635 |
++ GR_READ | GR_WRITE | GR_AUDIT_READ | |
24636 |
++ GR_DELETE | GR_AUDIT_DELETE | |
24637 |
++ GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt); |
24638 |
++ } |
24639 |
++ |
24640 |
++ if (RENAME_CHECK_SUCCESS(comp1, comp2) && |
24641 |
++ ((comp1 & GR_AUDITS) || (comp2 & GR_AUDITS))) |
24642 |
++ gr_log_fs_rbac_str(GR_DO_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname); |
24643 |
++ else if (!RENAME_CHECK_SUCCESS(comp1, comp2) && !(comp1 & GR_SUPPRESS) |
24644 |
++ && !(comp2 & GR_SUPPRESS)) { |
24645 |
++ gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname); |
24646 |
++ error = -EACCES; |
24647 |
++ } else if (unlikely(!RENAME_CHECK_SUCCESS(comp1, comp2))) |
24648 |
++ error = -EACCES; |
24649 |
++ |
24650 |
++ return error; |
24651 |
++} |
24652 |
++ |
24653 |
++void |
24654 |
++gr_acl_handle_exit(void) |
24655 |
++{ |
24656 |
++ u16 id; |
24657 |
++ char *rolename; |
24658 |
++ struct file *exec_file; |
24659 |
++ |
24660 |
++ if (unlikely(current->acl_sp_role && gr_acl_is_enabled())) { |
24661 |
++ id = current->acl_role_id; |
24662 |
++ rolename = current->role->rolename; |
24663 |
++ gr_set_acls(1); |
24664 |
++ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLEL_ACL_MSG, rolename, id); |
24665 |
++ } |
24666 |
++ |
24667 |
++ write_lock(&grsec_exec_file_lock); |
24668 |
++ exec_file = current->exec_file; |
24669 |
++ current->exec_file = NULL; |
24670 |
++ write_unlock(&grsec_exec_file_lock); |
24671 |
++ |
24672 |
++ if (exec_file) |
24673 |
++ fput(exec_file); |
24674 |
++} |
24675 |
++ |
24676 |
++int |
24677 |
++gr_acl_handle_procpidmem(const struct task_struct *task) |
24678 |
++{ |
24679 |
++ if (unlikely(!gr_acl_is_enabled())) |
24680 |
++ return 0; |
24681 |
++ |
24682 |
++ if (task != current && task->acl->mode & GR_PROTPROCFD) |
24683 |
++ return -EACCES; |
24684 |
++ |
24685 |
++ return 0; |
24686 |
++} |
24687 |
+diff -urNp linux-2.6.28.8/grsecurity/gracl_ip.c linux-2.6.28.8/grsecurity/gracl_ip.c |
24688 |
+--- linux-2.6.28.8/grsecurity/gracl_ip.c 1969-12-31 19:00:00.000000000 -0500 |
24689 |
++++ linux-2.6.28.8/grsecurity/gracl_ip.c 2009-02-21 09:37:49.000000000 -0500 |
24690 |
+@@ -0,0 +1,338 @@ |
24691 |
++#include <linux/kernel.h> |
24692 |
++#include <asm/uaccess.h> |
24693 |
++#include <asm/errno.h> |
24694 |
++#include <net/sock.h> |
24695 |
++#include <linux/file.h> |
24696 |
++#include <linux/fs.h> |
24697 |
++#include <linux/net.h> |
24698 |
++#include <linux/in.h> |
24699 |
++#include <linux/skbuff.h> |
24700 |
++#include <linux/ip.h> |
24701 |
++#include <linux/udp.h> |
24702 |
++#include <linux/smp_lock.h> |
24703 |
++#include <linux/types.h> |
24704 |
++#include <linux/sched.h> |
24705 |
++#include <linux/netdevice.h> |
24706 |
++#include <linux/inetdevice.h> |
24707 |
++#include <linux/gracl.h> |
24708 |
++#include <linux/grsecurity.h> |
24709 |
++#include <linux/grinternal.h> |
24710 |
++ |
24711 |
++#define GR_BIND 0x01 |
24712 |
++#define GR_CONNECT 0x02 |
24713 |
++#define GR_INVERT 0x04 |
24714 |
++#define GR_BINDOVERRIDE 0x08 |
24715 |
++#define GR_CONNECTOVERRIDE 0x10 |
24716 |
++ |
24717 |
++static const char * gr_protocols[256] = { |
24718 |
++ "ip", "icmp", "igmp", "ggp", "ipencap", "st", "tcp", "cbt", |
24719 |
++ "egp", "igp", "bbn-rcc", "nvp", "pup", "argus", "emcon", "xnet", |
24720 |
++ "chaos", "udp", "mux", "dcn", "hmp", "prm", "xns-idp", "trunk-1", |
24721 |
++ "trunk-2", "leaf-1", "leaf-2", "rdp", "irtp", "iso-tp4", "netblt", "mfe-nsp", |
24722 |
++ "merit-inp", "sep", "3pc", "idpr", "xtp", "ddp", "idpr-cmtp", "tp++", |
24723 |
++ "il", "ipv6", "sdrp", "ipv6-route", "ipv6-frag", "idrp", "rsvp", "gre", |
24724 |
++ "mhrp", "bna", "ipv6-crypt", "ipv6-auth", "i-nlsp", "swipe", "narp", "mobile", |
24725 |
++ "tlsp", "skip", "ipv6-icmp", "ipv6-nonxt", "ipv6-opts", "unknown:61", "cftp", "unknown:63", |
24726 |
++ "sat-expak", "kryptolan", "rvd", "ippc", "unknown:68", "sat-mon", "visa", "ipcv", |
24727 |
++ "cpnx", "cphb", "wsn", "pvp", "br-sat-mon", "sun-nd", "wb-mon", "wb-expak", |
24728 |
++ "iso-ip", "vmtp", "secure-vmtp", "vines", "ttp", "nfsnet-igp", "dgp", "tcf", |
24729 |
++ "eigrp", "ospf", "sprite-rpc", "larp", "mtp", "ax.25", "ipip", "micp", |
24730 |
++ "scc-sp", "etherip", "encap", "unknown:99", "gmtp", "ifmp", "pnni", "pim", |
24731 |
++ "aris", "scps", "qnx", "a/n", "ipcomp", "snp", "compaq-peer", "ipx-in-ip", |
24732 |
++ "vrrp", "pgm", "unknown:114", "l2tp", "ddx", "iatp", "stp", "srp", |
24733 |
++ "uti", "smp", "sm", "ptp", "isis", "fire", "crtp", "crdup", |
24734 |
++ "sscopmce", "iplt", "sps", "pipe", "sctp", "fc", "unkown:134", "unknown:135", |
24735 |
++ "unknown:136", "unknown:137", "unknown:138", "unknown:139", "unknown:140", "unknown:141", "unknown:142", "unknown:143", |
24736 |
++ "unknown:144", "unknown:145", "unknown:146", "unknown:147", "unknown:148", "unknown:149", "unknown:150", "unknown:151", |
24737 |
++ "unknown:152", "unknown:153", "unknown:154", "unknown:155", "unknown:156", "unknown:157", "unknown:158", "unknown:159", |
24738 |
++ "unknown:160", "unknown:161", "unknown:162", "unknown:163", "unknown:164", "unknown:165", "unknown:166", "unknown:167", |
24739 |
++ "unknown:168", "unknown:169", "unknown:170", "unknown:171", "unknown:172", "unknown:173", "unknown:174", "unknown:175", |
24740 |
++ "unknown:176", "unknown:177", "unknown:178", "unknown:179", "unknown:180", "unknown:181", "unknown:182", "unknown:183", |
24741 |
++ "unknown:184", "unknown:185", "unknown:186", "unknown:187", "unknown:188", "unknown:189", "unknown:190", "unknown:191", |
24742 |
++ "unknown:192", "unknown:193", "unknown:194", "unknown:195", "unknown:196", "unknown:197", "unknown:198", "unknown:199", |
24743 |
++ "unknown:200", "unknown:201", "unknown:202", "unknown:203", "unknown:204", "unknown:205", "unknown:206", "unknown:207", |
24744 |
++ "unknown:208", "unknown:209", "unknown:210", "unknown:211", "unknown:212", "unknown:213", "unknown:214", "unknown:215", |
24745 |
++ "unknown:216", "unknown:217", "unknown:218", "unknown:219", "unknown:220", "unknown:221", "unknown:222", "unknown:223", |
24746 |
++ "unknown:224", "unknown:225", "unknown:226", "unknown:227", "unknown:228", "unknown:229", "unknown:230", "unknown:231", |
24747 |
++ "unknown:232", "unknown:233", "unknown:234", "unknown:235", "unknown:236", "unknown:237", "unknown:238", "unknown:239", |
24748 |
++ "unknown:240", "unknown:241", "unknown:242", "unknown:243", "unknown:244", "unknown:245", "unknown:246", "unknown:247", |
24749 |
++ "unknown:248", "unknown:249", "unknown:250", "unknown:251", "unknown:252", "unknown:253", "unknown:254", "unknown:255", |
24750 |
++ }; |
24751 |
++ |
24752 |
++static const char * gr_socktypes[11] = { |
24753 |
++ "unknown:0", "stream", "dgram", "raw", "rdm", "seqpacket", "unknown:6", |
24754 |
++ "unknown:7", "unknown:8", "unknown:9", "packet" |
24755 |
++ }; |
24756 |
++ |
24757 |
++const char * |
24758 |
++gr_proto_to_name(unsigned char proto) |
24759 |
++{ |
24760 |
++ return gr_protocols[proto]; |
24761 |
++} |
24762 |
++ |
24763 |
++const char * |
24764 |
++gr_socktype_to_name(unsigned char type) |
24765 |
++{ |
24766 |
++ return gr_socktypes[type]; |
24767 |
++} |
24768 |
++ |
24769 |
++int |
24770 |
++gr_search_socket(const int domain, const int type, const int protocol) |
24771 |
++{ |
24772 |
++ struct acl_subject_label *curr; |
24773 |
++ |
24774 |
++ if (unlikely(!gr_acl_is_enabled())) |
24775 |
++ goto exit; |
24776 |
++ |
24777 |
++ if ((domain < 0) || (type < 0) || (protocol < 0) || (domain != PF_INET) |
24778 |
++ || (domain >= NPROTO) || (type >= SOCK_MAX) || (protocol > 255)) |
24779 |
++ goto exit; // let the kernel handle it |
24780 |
++ |
24781 |
++ curr = current->acl; |
24782 |
++ |
24783 |
++ if (!curr->ips) |
24784 |
++ goto exit; |
24785 |
++ |
24786 |
++ if ((curr->ip_type & (1 << type)) && |
24787 |
++ (curr->ip_proto[protocol / 32] & (1 << (protocol % 32)))) |
24788 |
++ goto exit; |
24789 |
++ |
24790 |
++ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) { |
24791 |
++ /* we don't place acls on raw sockets , and sometimes |
24792 |
++ dgram/ip sockets are opened for ioctl and not |
24793 |
++ bind/connect, so we'll fake a bind learn log */ |
24794 |
++ if (type == SOCK_RAW || type == SOCK_PACKET) { |
24795 |
++ __u32 fakeip = 0; |
24796 |
++ security_learn(GR_IP_LEARN_MSG, current->role->rolename, |
24797 |
++ current->role->roletype, current->uid, |
24798 |
++ current->gid, current->exec_file ? |
24799 |
++ gr_to_filename(current->exec_file->f_path.dentry, |
24800 |
++ current->exec_file->f_path.mnt) : |
24801 |
++ curr->filename, curr->filename, |
24802 |
++ NIPQUAD(fakeip), 0, type, |
24803 |
++ protocol, GR_CONNECT, |
24804 |
++NIPQUAD(current->signal->curr_ip)); |
24805 |
++ } else if ((type == SOCK_DGRAM) && (protocol == IPPROTO_IP)) { |
24806 |
++ __u32 fakeip = 0; |
24807 |
++ security_learn(GR_IP_LEARN_MSG, current->role->rolename, |
24808 |
++ current->role->roletype, current->uid, |
24809 |
++ current->gid, current->exec_file ? |
24810 |
++ gr_to_filename(current->exec_file->f_path.dentry, |
24811 |
++ current->exec_file->f_path.mnt) : |
24812 |
++ curr->filename, curr->filename, |
24813 |
++ NIPQUAD(fakeip), 0, type, |
24814 |
++ protocol, GR_BIND, NIPQUAD(current->signal->curr_ip)); |
24815 |
++ } |
24816 |
++ /* we'll log when they use connect or bind */ |
24817 |
++ goto exit; |
24818 |
++ } |
24819 |
++ |
24820 |
++ gr_log_str3(GR_DONT_AUDIT, GR_SOCK_MSG, "inet", |
24821 |
++ gr_socktype_to_name(type), gr_proto_to_name(protocol)); |
24822 |
++ |
24823 |
++ return 0; |
24824 |
++ exit: |
24825 |
++ return 1; |
24826 |
++} |
24827 |
++ |
24828 |
++int check_ip_policy(struct acl_ip_label *ip, __u32 ip_addr, __u16 ip_port, __u8 protocol, const int mode, const int type, __u32 our_addr, __u32 our_netmask) |
24829 |
++{ |
24830 |
++ if ((ip->mode & mode) && |
24831 |
++ (ip_port >= ip->low) && |
24832 |
++ (ip_port <= ip->high) && |
24833 |
++ ((ntohl(ip_addr) & our_netmask) == |
24834 |
++ (ntohl(our_addr) & our_netmask)) |
24835 |
++ && (ip->proto[protocol / 32] & (1 << (protocol % 32))) |
24836 |
++ && (ip->type & (1 << type))) { |
24837 |
++ if (ip->mode & GR_INVERT) |
24838 |
++ return 2; // specifically denied |
24839 |
++ else |
24840 |
++ return 1; // allowed |
24841 |
++ } |
24842 |
++ |
24843 |
++ return 0; // not specifically allowed, may continue parsing |
24844 |
++} |
24845 |
++ |
24846 |
++static int |
24847 |
++gr_search_connectbind(const int full_mode, struct sock *sk, |
24848 |
++ struct sockaddr_in *addr, const int type) |
24849 |
++{ |
24850 |
++ char iface[IFNAMSIZ] = {0}; |
24851 |
++ struct acl_subject_label *curr; |
24852 |
++ struct acl_ip_label *ip; |
24853 |
++ struct inet_sock *isk; |
24854 |
++ struct net_device *dev; |
24855 |
++ struct in_device *idev; |
24856 |
++ unsigned long i; |
24857 |
++ int ret; |
24858 |
++ int mode = full_mode & (GR_BIND | GR_CONNECT); |
24859 |
++ __u32 ip_addr = 0; |
24860 |
++ __u32 our_addr; |
24861 |
++ __u32 our_netmask; |
24862 |
++ char *p; |
24863 |
++ __u16 ip_port = 0; |
24864 |
++ |
24865 |
++ if (unlikely(!gr_acl_is_enabled() || sk->sk_family != PF_INET)) |
24866 |
++ return 0; |
24867 |
++ |
24868 |
++ curr = current->acl; |
24869 |
++ isk = inet_sk(sk); |
24870 |
++ |
24871 |
++ /* INADDR_ANY overriding for binds, inaddr_any_override is already in network order */ |
24872 |
++ if ((full_mode & GR_BINDOVERRIDE) && addr->sin_addr.s_addr == htonl(INADDR_ANY) && curr->inaddr_any_override != 0) |
24873 |
++ addr->sin_addr.s_addr = curr->inaddr_any_override; |
24874 |
++ if ((full_mode & GR_CONNECT) && isk->saddr == htonl(INADDR_ANY) && curr->inaddr_any_override != 0) { |
24875 |
++ struct sockaddr_in saddr; |
24876 |
++ int err; |
24877 |
++ |
24878 |
++ saddr.sin_family = AF_INET; |
24879 |
++ saddr.sin_addr.s_addr = curr->inaddr_any_override; |
24880 |
++ saddr.sin_port = isk->sport; |
24881 |
++ |
24882 |
++ err = security_socket_bind(sk->sk_socket, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)); |
24883 |
++ if (err) |
24884 |
++ return err; |
24885 |
++ |
24886 |
++ err = sk->sk_socket->ops->bind(sk->sk_socket, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)); |
24887 |
++ if (err) |
24888 |
++ return err; |
24889 |
++ } |
24890 |
++ |
24891 |
++ if (!curr->ips) |
24892 |
++ return 0; |
24893 |
++ |
24894 |
++ ip_addr = addr->sin_addr.s_addr; |
24895 |
++ ip_port = ntohs(addr->sin_port); |
24896 |
++ |
24897 |
++ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) { |
24898 |
++ security_learn(GR_IP_LEARN_MSG, current->role->rolename, |
24899 |
++ current->role->roletype, current->uid, |
24900 |
++ current->gid, current->exec_file ? |
24901 |
++ gr_to_filename(current->exec_file->f_path.dentry, |
24902 |
++ current->exec_file->f_path.mnt) : |
24903 |
++ curr->filename, curr->filename, |
24904 |
++ NIPQUAD(ip_addr), ip_port, type, |
24905 |
++ sk->sk_protocol, mode, NIPQUAD(current->signal->curr_ip)); |
24906 |
++ return 0; |
24907 |
++ } |
24908 |
++ |
24909 |
++ for (i = 0; i < curr->ip_num; i++) { |
24910 |
++ ip = *(curr->ips + i); |
24911 |
++ if (ip->iface != NULL) { |
24912 |
++ strncpy(iface, ip->iface, IFNAMSIZ - 1); |
24913 |
++ p = strchr(iface, ':'); |
24914 |
++ if (p != NULL) |
24915 |
++ *p = '\0'; |
24916 |
++ dev = dev_get_by_name(sock_net(sk), iface); |
24917 |
++ if (dev == NULL) |
24918 |
++ continue; |
24919 |
++ idev = in_dev_get(dev); |
24920 |
++ if (idev == NULL) { |
24921 |
++ dev_put(dev); |
24922 |
++ continue; |
24923 |
++ } |
24924 |
++ rcu_read_lock(); |
24925 |
++ for_ifa(idev) { |
24926 |
++ if (!strcmp(ip->iface, ifa->ifa_label)) { |
24927 |
++ our_addr = ifa->ifa_address; |
24928 |
++ our_netmask = 0xffffffff; |
24929 |
++ ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask); |
24930 |
++ if (ret == 1) { |
24931 |
++ rcu_read_unlock(); |
24932 |
++ in_dev_put(idev); |
24933 |
++ dev_put(dev); |
24934 |
++ return 0; |
24935 |
++ } else if (ret == 2) { |
24936 |
++ rcu_read_unlock(); |
24937 |
++ in_dev_put(idev); |
24938 |
++ dev_put(dev); |
24939 |
++ goto denied; |
24940 |
++ } |
24941 |
++ } |
24942 |
++ } endfor_ifa(idev); |
24943 |
++ rcu_read_unlock(); |
24944 |
++ in_dev_put(idev); |
24945 |
++ dev_put(dev); |
24946 |
++ } else { |
24947 |
++ our_addr = ip->addr; |
24948 |
++ our_netmask = ip->netmask; |
24949 |
++ ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask); |
24950 |
++ if (ret == 1) |
24951 |
++ return 0; |
24952 |
++ else if (ret == 2) |
24953 |
++ goto denied; |
24954 |
++ } |
24955 |
++ } |
24956 |
++ |
24957 |
++denied: |
24958 |
++ if (mode == GR_BIND) |
24959 |
++ gr_log_int5_str2(GR_DONT_AUDIT, GR_BIND_ACL_MSG, NIPQUAD(ip_addr), ip_port, gr_socktype_to_name(type), gr_proto_to_name(sk->sk_protocol)); |
24960 |
++ else if (mode == GR_CONNECT) |
24961 |
++ gr_log_int5_str2(GR_DONT_AUDIT, GR_CONNECT_ACL_MSG, NIPQUAD(ip_addr), ip_port, gr_socktype_to_name(type), gr_proto_to_name(sk->sk_protocol)); |
24962 |
++ |
24963 |
++ return -EACCES; |
24964 |
++} |
24965 |
++ |
24966 |
++int |
24967 |
++gr_search_connect(struct socket *sock, struct sockaddr_in *addr) |
24968 |
++{ |
24969 |
++ return gr_search_connectbind(GR_CONNECT | GR_CONNECTOVERRIDE, sock->sk, addr, sock->type); |
24970 |
++} |
24971 |
++ |
24972 |
++int |
24973 |
++gr_search_bind(struct socket *sock, struct sockaddr_in *addr) |
24974 |
++{ |
24975 |
++ return gr_search_connectbind(GR_BIND | GR_BINDOVERRIDE, sock->sk, addr, sock->type); |
24976 |
++} |
24977 |
++ |
24978 |
++int gr_search_listen(struct socket *sock) |
24979 |
++{ |
24980 |
++ struct sock *sk = sock->sk; |
24981 |
++ struct sockaddr_in addr; |
24982 |
++ |
24983 |
++ addr.sin_addr.s_addr = inet_sk(sk)->saddr; |
24984 |
++ addr.sin_port = inet_sk(sk)->sport; |
24985 |
++ |
24986 |
++ return gr_search_connectbind(GR_BIND | GR_CONNECTOVERRIDE, sock->sk, &addr, sock->type); |
24987 |
++} |
24988 |
++ |
24989 |
++int gr_search_accept(struct socket *sock) |
24990 |
++{ |
24991 |
++ struct sock *sk = sock->sk; |
24992 |
++ struct sockaddr_in addr; |
24993 |
++ |
24994 |
++ addr.sin_addr.s_addr = inet_sk(sk)->saddr; |
24995 |
++ addr.sin_port = inet_sk(sk)->sport; |
24996 |
++ |
24997 |
++ return gr_search_connectbind(GR_BIND | GR_CONNECTOVERRIDE, sock->sk, &addr, sock->type); |
24998 |
++} |
24999 |
++ |
25000 |
++int |
25001 |
++gr_search_udp_sendmsg(struct sock *sk, struct sockaddr_in *addr) |
25002 |
++{ |
25003 |
++ if (addr) |
25004 |
++ return gr_search_connectbind(GR_CONNECT, sk, addr, SOCK_DGRAM); |
25005 |
++ else { |
25006 |
++ struct sockaddr_in sin; |
25007 |
++ const struct inet_sock *inet = inet_sk(sk); |
25008 |
++ |
25009 |
++ sin.sin_addr.s_addr = inet->daddr; |
25010 |
++ sin.sin_port = inet->dport; |
25011 |
++ |
25012 |
++ return gr_search_connectbind(GR_CONNECT | GR_CONNECTOVERRIDE, sk, &sin, SOCK_DGRAM); |
25013 |
++ } |
25014 |
++} |
25015 |
++ |
25016 |
++int |
25017 |
++gr_search_udp_recvmsg(struct sock *sk, const struct sk_buff *skb) |
25018 |
++{ |
25019 |
++ struct sockaddr_in sin; |
25020 |
++ |
25021 |
++ if (unlikely(skb->len < sizeof (struct udphdr))) |
25022 |
++ return 0; // skip this packet |
25023 |
++ |
25024 |
++ sin.sin_addr.s_addr = ip_hdr(skb)->saddr; |
25025 |
++ sin.sin_port = udp_hdr(skb)->source; |
25026 |
++ |
25027 |
++ return gr_search_connectbind(GR_CONNECT | GR_CONNECTOVERRIDE, sk, &sin, SOCK_DGRAM); |
25028 |
++} |
25029 |
+diff -urNp linux-2.6.28.8/grsecurity/gracl_learn.c linux-2.6.28.8/grsecurity/gracl_learn.c |
25030 |
+--- linux-2.6.28.8/grsecurity/gracl_learn.c 1969-12-31 19:00:00.000000000 -0500 |
25031 |
++++ linux-2.6.28.8/grsecurity/gracl_learn.c 2009-02-21 09:37:49.000000000 -0500 |
25032 |
+@@ -0,0 +1,211 @@ |
25033 |
++#include <linux/kernel.h> |
25034 |
++#include <linux/mm.h> |
25035 |
++#include <linux/sched.h> |
25036 |
++#include <linux/poll.h> |
25037 |
++#include <linux/smp_lock.h> |
25038 |
++#include <linux/string.h> |
25039 |
++#include <linux/file.h> |
25040 |
++#include <linux/types.h> |
25041 |
++#include <linux/vmalloc.h> |
25042 |
++#include <linux/grinternal.h> |
25043 |
++ |
25044 |
++extern ssize_t write_grsec_handler(struct file * file, const char __user * buf, |
25045 |
++ size_t count, loff_t *ppos); |
25046 |
++extern int gr_acl_is_enabled(void); |
25047 |
++ |
25048 |
++static DECLARE_WAIT_QUEUE_HEAD(learn_wait); |
25049 |
++static int gr_learn_attached; |
25050 |
++ |
25051 |
++/* use a 512k buffer */ |
25052 |
++#define LEARN_BUFFER_SIZE (512 * 1024) |
25053 |
++ |
25054 |
++static DEFINE_SPINLOCK(gr_learn_lock); |
25055 |
++static DECLARE_MUTEX(gr_learn_user_sem); |
25056 |
++ |
25057 |
++/* we need to maintain two buffers, so that the kernel context of grlearn |
25058 |
++ uses a semaphore around the userspace copying, and the other kernel contexts |
25059 |
++ use a spinlock when copying into the buffer, since they cannot sleep |
25060 |
++*/ |
25061 |
++static char *learn_buffer; |
25062 |
++static char *learn_buffer_user; |
25063 |
++static int learn_buffer_len; |
25064 |
++static int learn_buffer_user_len; |
25065 |
++ |
25066 |
++static ssize_t |
25067 |
++read_learn(struct file *file, char __user * buf, size_t count, loff_t * ppos) |
25068 |
++{ |
25069 |
++ DECLARE_WAITQUEUE(wait, current); |
25070 |
++ ssize_t retval = 0; |
25071 |
++ |
25072 |
++ add_wait_queue(&learn_wait, &wait); |
25073 |
++ set_current_state(TASK_INTERRUPTIBLE); |
25074 |
++ do { |
25075 |
++ down(&gr_learn_user_sem); |
25076 |
++ spin_lock(&gr_learn_lock); |
25077 |
++ if (learn_buffer_len) |
25078 |
++ break; |
25079 |
++ spin_unlock(&gr_learn_lock); |
25080 |
++ up(&gr_learn_user_sem); |
25081 |
++ if (file->f_flags & O_NONBLOCK) { |
25082 |
++ retval = -EAGAIN; |
25083 |
++ goto out; |
25084 |
++ } |
25085 |
++ if (signal_pending(current)) { |
25086 |
++ retval = -ERESTARTSYS; |
25087 |
++ goto out; |
25088 |
++ } |
25089 |
++ |
25090 |
++ schedule(); |
25091 |
++ } while (1); |
25092 |
++ |
25093 |
++ memcpy(learn_buffer_user, learn_buffer, learn_buffer_len); |
25094 |
++ learn_buffer_user_len = learn_buffer_len; |
25095 |
++ retval = learn_buffer_len; |
25096 |
++ learn_buffer_len = 0; |
25097 |
++ |
25098 |
++ spin_unlock(&gr_learn_lock); |
25099 |
++ |
25100 |
++ if (copy_to_user(buf, learn_buffer_user, learn_buffer_user_len)) |
25101 |
++ retval = -EFAULT; |
25102 |
++ |
25103 |
++ up(&gr_learn_user_sem); |
25104 |
++out: |
25105 |
++ set_current_state(TASK_RUNNING); |
25106 |
++ remove_wait_queue(&learn_wait, &wait); |
25107 |
++ return retval; |
25108 |
++} |
25109 |
++ |
25110 |
++static unsigned int |
25111 |
++poll_learn(struct file * file, poll_table * wait) |
25112 |
++{ |
25113 |
++ poll_wait(file, &learn_wait, wait); |
25114 |
++ |
25115 |
++ if (learn_buffer_len) |
25116 |
++ return (POLLIN | POLLRDNORM); |
25117 |
++ |
25118 |
++ return 0; |
25119 |
++} |
25120 |
++ |
25121 |
++void |
25122 |
++gr_clear_learn_entries(void) |
25123 |
++{ |
25124 |
++ char *tmp; |
25125 |
++ |
25126 |
++ down(&gr_learn_user_sem); |
25127 |
++ if (learn_buffer != NULL) { |
25128 |
++ spin_lock(&gr_learn_lock); |
25129 |
++ tmp = learn_buffer; |
25130 |
++ learn_buffer = NULL; |
25131 |
++ spin_unlock(&gr_learn_lock); |
25132 |
++ vfree(learn_buffer); |
25133 |
++ } |
25134 |
++ if (learn_buffer_user != NULL) { |
25135 |
++ vfree(learn_buffer_user); |
25136 |
++ learn_buffer_user = NULL; |
25137 |
++ } |
25138 |
++ learn_buffer_len = 0; |
25139 |
++ up(&gr_learn_user_sem); |
25140 |
++ |
25141 |
++ return; |
25142 |
++} |
25143 |
++ |
25144 |
++void |
25145 |
++gr_add_learn_entry(const char *fmt, ...) |
25146 |
++{ |
25147 |
++ va_list args; |
25148 |
++ unsigned int len; |
25149 |
++ |
25150 |
++ if (!gr_learn_attached) |
25151 |
++ return; |
25152 |
++ |
25153 |
++ spin_lock(&gr_learn_lock); |
25154 |
++ |
25155 |
++ /* leave a gap at the end so we know when it's "full" but don't have to |
25156 |
++ compute the exact length of the string we're trying to append |
25157 |
++ */ |
25158 |
++ if (learn_buffer_len > LEARN_BUFFER_SIZE - 16384) { |
25159 |
++ spin_unlock(&gr_learn_lock); |
25160 |
++ wake_up_interruptible(&learn_wait); |
25161 |
++ return; |
25162 |
++ } |
25163 |
++ if (learn_buffer == NULL) { |
25164 |
++ spin_unlock(&gr_learn_lock); |
25165 |
++ return; |
25166 |
++ } |
25167 |
++ |
25168 |
++ va_start(args, fmt); |
25169 |
++ len = vsnprintf(learn_buffer + learn_buffer_len, LEARN_BUFFER_SIZE - learn_buffer_len, fmt, args); |
25170 |
++ va_end(args); |
25171 |
++ |
25172 |
++ learn_buffer_len += len + 1; |
25173 |
++ |
25174 |
++ spin_unlock(&gr_learn_lock); |
25175 |
++ wake_up_interruptible(&learn_wait); |
25176 |
++ |
25177 |
++ return; |
25178 |
++} |
25179 |
++ |
25180 |
++static int |
25181 |
++open_learn(struct inode *inode, struct file *file) |
25182 |
++{ |
25183 |
++ if (file->f_mode & FMODE_READ && gr_learn_attached) |
25184 |
++ return -EBUSY; |
25185 |
++ if (file->f_mode & FMODE_READ) { |
25186 |
++ int retval = 0; |
25187 |
++ down(&gr_learn_user_sem); |
25188 |
++ if (learn_buffer == NULL) |
25189 |
++ learn_buffer = vmalloc(LEARN_BUFFER_SIZE); |
25190 |
++ if (learn_buffer_user == NULL) |
25191 |
++ learn_buffer_user = vmalloc(LEARN_BUFFER_SIZE); |
25192 |
++ if (learn_buffer == NULL) { |
25193 |
++ retval = -ENOMEM; |
25194 |
++ goto out_error; |
25195 |
++ } |
25196 |
++ if (learn_buffer_user == NULL) { |
25197 |
++ retval = -ENOMEM; |
25198 |
++ goto out_error; |
25199 |
++ } |
25200 |
++ learn_buffer_len = 0; |
25201 |
++ learn_buffer_user_len = 0; |
25202 |
++ gr_learn_attached = 1; |
25203 |
++out_error: |
25204 |
++ up(&gr_learn_user_sem); |
25205 |
++ return retval; |
25206 |
++ } |
25207 |
++ return 0; |
25208 |
++} |
25209 |
++ |
25210 |
++static int |
25211 |
++close_learn(struct inode *inode, struct file *file) |
25212 |
++{ |
25213 |
++ char *tmp; |
25214 |
++ |
25215 |
++ if (file->f_mode & FMODE_READ) { |
25216 |
++ down(&gr_learn_user_sem); |
25217 |
++ if (learn_buffer != NULL) { |
25218 |
++ spin_lock(&gr_learn_lock); |
25219 |
++ tmp = learn_buffer; |
25220 |
++ learn_buffer = NULL; |
25221 |
++ spin_unlock(&gr_learn_lock); |
25222 |
++ vfree(tmp); |
25223 |
++ } |
25224 |
++ if (learn_buffer_user != NULL) { |
25225 |
++ vfree(learn_buffer_user); |
25226 |
++ learn_buffer_user = NULL; |
25227 |
++ } |
25228 |
++ learn_buffer_len = 0; |
25229 |
++ learn_buffer_user_len = 0; |
25230 |
++ gr_learn_attached = 0; |
25231 |
++ up(&gr_learn_user_sem); |
25232 |
++ } |
25233 |
++ |
25234 |
++ return 0; |
25235 |
++} |
25236 |
++ |
25237 |
++struct file_operations grsec_fops = { |
25238 |
++ .read = read_learn, |
25239 |
++ .write = write_grsec_handler, |
25240 |
++ .open = open_learn, |
25241 |
++ .release = close_learn, |
25242 |
++ .poll = poll_learn, |
25243 |
++}; |
25244 |
+diff -urNp linux-2.6.28.8/grsecurity/gracl_res.c linux-2.6.28.8/grsecurity/gracl_res.c |
25245 |
+--- linux-2.6.28.8/grsecurity/gracl_res.c 1969-12-31 19:00:00.000000000 -0500 |
25246 |
++++ linux-2.6.28.8/grsecurity/gracl_res.c 2009-02-21 09:37:49.000000000 -0500 |
25247 |
+@@ -0,0 +1,45 @@ |
25248 |
++#include <linux/kernel.h> |
25249 |
++#include <linux/sched.h> |
25250 |
++#include <linux/gracl.h> |
25251 |
++#include <linux/grinternal.h> |
25252 |
++ |
25253 |
++static const char *restab_log[] = { |
25254 |
++ [RLIMIT_CPU] = "RLIMIT_CPU", |
25255 |
++ [RLIMIT_FSIZE] = "RLIMIT_FSIZE", |
25256 |
++ [RLIMIT_DATA] = "RLIMIT_DATA", |
25257 |
++ [RLIMIT_STACK] = "RLIMIT_STACK", |
25258 |
++ [RLIMIT_CORE] = "RLIMIT_CORE", |
25259 |
++ [RLIMIT_RSS] = "RLIMIT_RSS", |
25260 |
++ [RLIMIT_NPROC] = "RLIMIT_NPROC", |
25261 |
++ [RLIMIT_NOFILE] = "RLIMIT_NOFILE", |
25262 |
++ [RLIMIT_MEMLOCK] = "RLIMIT_MEMLOCK", |
25263 |
++ [RLIMIT_AS] = "RLIMIT_AS", |
25264 |
++ [RLIMIT_LOCKS] = "RLIMIT_LOCKS", |
25265 |
++ [RLIMIT_LOCKS + 1] = "RLIMIT_CRASH" |
25266 |
++}; |
25267 |
++ |
25268 |
++void |
25269 |
++gr_log_resource(const struct task_struct *task, |
25270 |
++ const int res, const unsigned long wanted, const int gt) |
25271 |
++{ |
25272 |
++ if (res == RLIMIT_NPROC && |
25273 |
++ (cap_raised(task->cap_effective, CAP_SYS_ADMIN) || |
25274 |
++ cap_raised(task->cap_effective, CAP_SYS_RESOURCE))) |
25275 |
++ return; |
25276 |
++ else if (res == RLIMIT_MEMLOCK && |
25277 |
++ cap_raised(task->cap_effective, CAP_IPC_LOCK)) |
25278 |
++ return; |
25279 |
++ |
25280 |
++ if (!gr_acl_is_enabled() && !grsec_resource_logging) |
25281 |
++ return; |
25282 |
++ |
25283 |
++ preempt_disable(); |
25284 |
++ |
25285 |
++ if (unlikely(((gt && wanted > task->signal->rlim[res].rlim_cur) || |
25286 |
++ (!gt && wanted >= task->signal->rlim[res].rlim_cur)) && |
25287 |
++ task->signal->rlim[res].rlim_cur != RLIM_INFINITY)) |
25288 |
++ gr_log_res_ulong2_str(GR_DONT_AUDIT, GR_RESOURCE_MSG, task, wanted, restab_log[res], task->signal->rlim[res].rlim_cur); |
25289 |
++ preempt_enable_no_resched(); |
25290 |
++ |
25291 |
++ return; |
25292 |
++} |
25293 |
+diff -urNp linux-2.6.28.8/grsecurity/gracl_segv.c linux-2.6.28.8/grsecurity/gracl_segv.c |
25294 |
+--- linux-2.6.28.8/grsecurity/gracl_segv.c 1969-12-31 19:00:00.000000000 -0500 |
25295 |
++++ linux-2.6.28.8/grsecurity/gracl_segv.c 2009-02-21 09:37:49.000000000 -0500 |
25296 |
+@@ -0,0 +1,304 @@ |
25297 |
++#include <linux/kernel.h> |
25298 |
++#include <linux/mm.h> |
25299 |
++#include <asm/uaccess.h> |
25300 |
++#include <asm/errno.h> |
25301 |
++#include <asm/mman.h> |
25302 |
++#include <net/sock.h> |
25303 |
++#include <linux/file.h> |
25304 |
++#include <linux/fs.h> |
25305 |
++#include <linux/net.h> |
25306 |
++#include <linux/in.h> |
25307 |
++#include <linux/smp_lock.h> |
25308 |
++#include <linux/slab.h> |
25309 |
++#include <linux/types.h> |
25310 |
++#include <linux/sched.h> |
25311 |
++#include <linux/timer.h> |
25312 |
++#include <linux/gracl.h> |
25313 |
++#include <linux/grsecurity.h> |
25314 |
++#include <linux/grinternal.h> |
25315 |
++ |
25316 |
++static struct crash_uid *uid_set; |
25317 |
++static unsigned short uid_used; |
25318 |
++static DEFINE_SPINLOCK(gr_uid_lock); |
25319 |
++extern rwlock_t gr_inode_lock; |
25320 |
++extern struct acl_subject_label * |
25321 |
++ lookup_acl_subj_label(const ino_t inode, const dev_t dev, |
25322 |
++ struct acl_role_label *role); |
25323 |
++extern int specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t); |
25324 |
++ |
25325 |
++int |
25326 |
++gr_init_uidset(void) |
25327 |
++{ |
25328 |
++ uid_set = |
25329 |
++ kmalloc(GR_UIDTABLE_MAX * sizeof (struct crash_uid), GFP_KERNEL); |
25330 |
++ uid_used = 0; |
25331 |
++ |
25332 |
++ return uid_set ? 1 : 0; |
25333 |
++} |
25334 |
++ |
25335 |
++void |
25336 |
++gr_free_uidset(void) |
25337 |
++{ |
25338 |
++ if (uid_set) |
25339 |
++ kfree(uid_set); |
25340 |
++ |
25341 |
++ return; |
25342 |
++} |
25343 |
++ |
25344 |
++int |
25345 |
++gr_find_uid(const uid_t uid) |
25346 |
++{ |
25347 |
++ struct crash_uid *tmp = uid_set; |
25348 |
++ uid_t buid; |
25349 |
++ int low = 0, high = uid_used - 1, mid; |
25350 |
++ |
25351 |
++ while (high >= low) { |
25352 |
++ mid = (low + high) >> 1; |
25353 |
++ buid = tmp[mid].uid; |
25354 |
++ if (buid == uid) |
25355 |
++ return mid; |
25356 |
++ if (buid > uid) |
25357 |
++ high = mid - 1; |
25358 |
++ if (buid < uid) |
25359 |
++ low = mid + 1; |
25360 |
++ } |
25361 |
++ |
25362 |
++ return -1; |
25363 |
++} |
25364 |
++ |
25365 |
++static __inline__ void |
25366 |
++gr_insertsort(void) |
25367 |
++{ |
25368 |
++ unsigned short i, j; |
25369 |
++ struct crash_uid index; |
25370 |
++ |
25371 |
++ for (i = 1; i < uid_used; i++) { |
25372 |
++ index = uid_set[i]; |
25373 |
++ j = i; |
25374 |
++ while ((j > 0) && uid_set[j - 1].uid > index.uid) { |
25375 |
++ uid_set[j] = uid_set[j - 1]; |
25376 |
++ j--; |
25377 |
++ } |
25378 |
++ uid_set[j] = index; |
25379 |
++ } |
25380 |
++ |
25381 |
++ return; |
25382 |
++} |
25383 |
++ |
25384 |
++static __inline__ void |
25385 |
++gr_insert_uid(const uid_t uid, const unsigned long expires) |
25386 |
++{ |
25387 |
++ int loc; |
25388 |
++ |
25389 |
++ if (uid_used == GR_UIDTABLE_MAX) |
25390 |
++ return; |
25391 |
++ |
25392 |
++ loc = gr_find_uid(uid); |
25393 |
++ |
25394 |
++ if (loc >= 0) { |
25395 |
++ uid_set[loc].expires = expires; |
25396 |
++ return; |
25397 |
++ } |
25398 |
++ |
25399 |
++ uid_set[uid_used].uid = uid; |
25400 |
++ uid_set[uid_used].expires = expires; |
25401 |
++ uid_used++; |
25402 |
++ |
25403 |
++ gr_insertsort(); |
25404 |
++ |
25405 |
++ return; |
25406 |
++} |
25407 |
++ |
25408 |
++void |
25409 |
++gr_remove_uid(const unsigned short loc) |
25410 |
++{ |
25411 |
++ unsigned short i; |
25412 |
++ |
25413 |
++ for (i = loc + 1; i < uid_used; i++) |
25414 |
++ uid_set[i - 1] = uid_set[i]; |
25415 |
++ |
25416 |
++ uid_used--; |
25417 |
++ |
25418 |
++ return; |
25419 |
++} |
25420 |
++ |
25421 |
++int |
25422 |
++gr_check_crash_uid(const uid_t uid) |
25423 |
++{ |
25424 |
++ int loc; |
25425 |
++ int ret = 0; |
25426 |
++ |
25427 |
++ if (unlikely(!gr_acl_is_enabled())) |
25428 |
++ return 0; |
25429 |
++ |
25430 |
++ spin_lock(&gr_uid_lock); |
25431 |
++ loc = gr_find_uid(uid); |
25432 |
++ |
25433 |
++ if (loc < 0) |
25434 |
++ goto out_unlock; |
25435 |
++ |
25436 |
++ if (time_before_eq(uid_set[loc].expires, get_seconds())) |
25437 |
++ gr_remove_uid(loc); |
25438 |
++ else |
25439 |
++ ret = 1; |
25440 |
++ |
25441 |
++out_unlock: |
25442 |
++ spin_unlock(&gr_uid_lock); |
25443 |
++ return ret; |
25444 |
++} |
25445 |
++ |
25446 |
++static __inline__ int |
25447 |
++proc_is_setxid(const struct task_struct *task) |
25448 |
++{ |
25449 |
++ if (task->uid != task->euid || task->uid != task->suid || |
25450 |
++ task->uid != task->fsuid) |
25451 |
++ return 1; |
25452 |
++ if (task->gid != task->egid || task->gid != task->sgid || |
25453 |
++ task->gid != task->fsgid) |
25454 |
++ return 1; |
25455 |
++ |
25456 |
++ return 0; |
25457 |
++} |
25458 |
++static __inline__ int |
25459 |
++gr_fake_force_sig(int sig, struct task_struct *t) |
25460 |
++{ |
25461 |
++ unsigned long int flags; |
25462 |
++ int ret, blocked, ignored; |
25463 |
++ struct k_sigaction *action; |
25464 |
++ |
25465 |
++ spin_lock_irqsave(&t->sighand->siglock, flags); |
25466 |
++ action = &t->sighand->action[sig-1]; |
25467 |
++ ignored = action->sa.sa_handler == SIG_IGN; |
25468 |
++ blocked = sigismember(&t->blocked, sig); |
25469 |
++ if (blocked || ignored) { |
25470 |
++ action->sa.sa_handler = SIG_DFL; |
25471 |
++ if (blocked) { |
25472 |
++ sigdelset(&t->blocked, sig); |
25473 |
++ recalc_sigpending_and_wake(t); |
25474 |
++ } |
25475 |
++ } |
25476 |
++ if (action->sa.sa_handler == SIG_DFL) |
25477 |
++ t->signal->flags &= ~SIGNAL_UNKILLABLE; |
25478 |
++ ret = specific_send_sig_info(sig, SEND_SIG_PRIV, t); |
25479 |
++ |
25480 |
++ spin_unlock_irqrestore(&t->sighand->siglock, flags); |
25481 |
++ |
25482 |
++ return ret; |
25483 |
++} |
25484 |
++ |
25485 |
++void |
25486 |
++gr_handle_crash(struct task_struct *task, const int sig) |
25487 |
++{ |
25488 |
++ struct acl_subject_label *curr; |
25489 |
++ struct acl_subject_label *curr2; |
25490 |
++ struct task_struct *tsk, *tsk2; |
25491 |
++ |
25492 |
++ if (sig != SIGSEGV && sig != SIGKILL && sig != SIGBUS && sig != SIGILL) |
25493 |
++ return; |
25494 |
++ |
25495 |
++ if (unlikely(!gr_acl_is_enabled())) |
25496 |
++ return; |
25497 |
++ |
25498 |
++ curr = task->acl; |
25499 |
++ |
25500 |
++ if (!(curr->resmask & (1 << GR_CRASH_RES))) |
25501 |
++ return; |
25502 |
++ |
25503 |
++ if (time_before_eq(curr->expires, get_seconds())) { |
25504 |
++ curr->expires = 0; |
25505 |
++ curr->crashes = 0; |
25506 |
++ } |
25507 |
++ |
25508 |
++ curr->crashes++; |
25509 |
++ |
25510 |
++ if (!curr->expires) |
25511 |
++ curr->expires = get_seconds() + curr->res[GR_CRASH_RES].rlim_max; |
25512 |
++ |
25513 |
++ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) && |
25514 |
++ time_after(curr->expires, get_seconds())) { |
25515 |
++ if (task->uid && proc_is_setxid(task)) { |
25516 |
++ gr_log_crash1(GR_DONT_AUDIT, GR_SEGVSTART_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max); |
25517 |
++ spin_lock(&gr_uid_lock); |
25518 |
++ gr_insert_uid(task->uid, curr->expires); |
25519 |
++ spin_unlock(&gr_uid_lock); |
25520 |
++ curr->expires = 0; |
25521 |
++ curr->crashes = 0; |
25522 |
++ read_lock(&tasklist_lock); |
25523 |
++ do_each_thread(tsk2, tsk) { |
25524 |
++ if (tsk != task && tsk->uid == task->uid) |
25525 |
++ gr_fake_force_sig(SIGKILL, tsk); |
25526 |
++ } while_each_thread(tsk2, tsk); |
25527 |
++ read_unlock(&tasklist_lock); |
25528 |
++ } else { |
25529 |
++ gr_log_crash2(GR_DONT_AUDIT, GR_SEGVNOSUID_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max); |
25530 |
++ read_lock(&tasklist_lock); |
25531 |
++ do_each_thread(tsk2, tsk) { |
25532 |
++ if (likely(tsk != task)) { |
25533 |
++ curr2 = tsk->acl; |
25534 |
++ |
25535 |
++ if (curr2->device == curr->device && |
25536 |
++ curr2->inode == curr->inode) |
25537 |
++ gr_fake_force_sig(SIGKILL, tsk); |
25538 |
++ } |
25539 |
++ } while_each_thread(tsk2, tsk); |
25540 |
++ read_unlock(&tasklist_lock); |
25541 |
++ } |
25542 |
++ } |
25543 |
++ |
25544 |
++ return; |
25545 |
++} |
25546 |
++ |
25547 |
++int |
25548 |
++gr_check_crash_exec(const struct file *filp) |
25549 |
++{ |
25550 |
++ struct acl_subject_label *curr; |
25551 |
++ |
25552 |
++ if (unlikely(!gr_acl_is_enabled())) |
25553 |
++ return 0; |
25554 |
++ |
25555 |
++ read_lock(&gr_inode_lock); |
25556 |
++ curr = lookup_acl_subj_label(filp->f_path.dentry->d_inode->i_ino, |
25557 |
++ filp->f_path.dentry->d_inode->i_sb->s_dev, |
25558 |
++ current->role); |
25559 |
++ read_unlock(&gr_inode_lock); |
25560 |
++ |
25561 |
++ if (!curr || !(curr->resmask & (1 << GR_CRASH_RES)) || |
25562 |
++ (!curr->crashes && !curr->expires)) |
25563 |
++ return 0; |
25564 |
++ |
25565 |
++ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) && |
25566 |
++ time_after(curr->expires, get_seconds())) |
25567 |
++ return 1; |
25568 |
++ else if (time_before_eq(curr->expires, get_seconds())) { |
25569 |
++ curr->crashes = 0; |
25570 |
++ curr->expires = 0; |
25571 |
++ } |
25572 |
++ |
25573 |
++ return 0; |
25574 |
++} |
25575 |
++ |
25576 |
++void |
25577 |
++gr_handle_alertkill(struct task_struct *task) |
25578 |
++{ |
25579 |
++ struct acl_subject_label *curracl; |
25580 |
++ __u32 curr_ip; |
25581 |
++ struct task_struct *p, *p2; |
25582 |
++ |
25583 |
++ if (unlikely(!gr_acl_is_enabled())) |
25584 |
++ return; |
25585 |
++ |
25586 |
++ curracl = task->acl; |
25587 |
++ curr_ip = task->signal->curr_ip; |
25588 |
++ |
25589 |
++ if ((curracl->mode & GR_KILLIPPROC) && curr_ip) { |
25590 |
++ read_lock(&tasklist_lock); |
25591 |
++ do_each_thread(p2, p) { |
25592 |
++ if (p->signal->curr_ip == curr_ip) |
25593 |
++ gr_fake_force_sig(SIGKILL, p); |
25594 |
++ } while_each_thread(p2, p); |
25595 |
++ read_unlock(&tasklist_lock); |
25596 |
++ } else if (curracl->mode & GR_KILLPROC) |
25597 |
++ gr_fake_force_sig(SIGKILL, task); |
25598 |
++ |
25599 |
++ return; |
25600 |
++} |
25601 |
+diff -urNp linux-2.6.28.8/grsecurity/gracl_shm.c linux-2.6.28.8/grsecurity/gracl_shm.c |
25602 |
+--- linux-2.6.28.8/grsecurity/gracl_shm.c 1969-12-31 19:00:00.000000000 -0500 |
25603 |
++++ linux-2.6.28.8/grsecurity/gracl_shm.c 2009-02-21 09:37:49.000000000 -0500 |
25604 |
+@@ -0,0 +1,33 @@ |
25605 |
++#include <linux/kernel.h> |
25606 |
++#include <linux/mm.h> |
25607 |
++#include <linux/sched.h> |
25608 |
++#include <linux/file.h> |
25609 |
++#include <linux/ipc.h> |
25610 |
++#include <linux/gracl.h> |
25611 |
++#include <linux/grsecurity.h> |
25612 |
++#include <linux/grinternal.h> |
25613 |
++ |
25614 |
++int |
25615 |
++gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid, |
25616 |
++ const time_t shm_createtime, const uid_t cuid, const int shmid) |
25617 |
++{ |
25618 |
++ struct task_struct *task; |
25619 |
++ |
25620 |
++ if (!gr_acl_is_enabled()) |
25621 |
++ return 1; |
25622 |
++ |
25623 |
++ task = find_task_by_vpid(shm_cprid); |
25624 |
++ |
25625 |
++ if (unlikely(!task)) |
25626 |
++ task = find_task_by_vpid(shm_lapid); |
25627 |
++ |
25628 |
++ if (unlikely(task && (time_before_eq((unsigned long)task->start_time.tv_sec, (unsigned long)shm_createtime) || |
25629 |
++ (task->pid == shm_lapid)) && |
25630 |
++ (task->acl->mode & GR_PROTSHM) && |
25631 |
++ (task->acl != current->acl))) { |
25632 |
++ gr_log_int3(GR_DONT_AUDIT, GR_SHMAT_ACL_MSG, cuid, shm_cprid, shmid); |
25633 |
++ return 0; |
25634 |
++ } |
25635 |
++ |
25636 |
++ return 1; |
25637 |
++} |
25638 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_chdir.c linux-2.6.28.8/grsecurity/grsec_chdir.c |
25639 |
+--- linux-2.6.28.8/grsecurity/grsec_chdir.c 1969-12-31 19:00:00.000000000 -0500 |
25640 |
++++ linux-2.6.28.8/grsecurity/grsec_chdir.c 2009-02-21 09:37:49.000000000 -0500 |
25641 |
+@@ -0,0 +1,19 @@ |
25642 |
++#include <linux/kernel.h> |
25643 |
++#include <linux/sched.h> |
25644 |
++#include <linux/fs.h> |
25645 |
++#include <linux/file.h> |
25646 |
++#include <linux/grsecurity.h> |
25647 |
++#include <linux/grinternal.h> |
25648 |
++ |
25649 |
++void |
25650 |
++gr_log_chdir(const struct dentry *dentry, const struct vfsmount *mnt) |
25651 |
++{ |
25652 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR |
25653 |
++ if ((grsec_enable_chdir && grsec_enable_group && |
25654 |
++ in_group_p(grsec_audit_gid)) || (grsec_enable_chdir && |
25655 |
++ !grsec_enable_group)) { |
25656 |
++ gr_log_fs_generic(GR_DO_AUDIT, GR_CHDIR_AUDIT_MSG, dentry, mnt); |
25657 |
++ } |
25658 |
++#endif |
25659 |
++ return; |
25660 |
++} |
25661 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_chroot.c linux-2.6.28.8/grsecurity/grsec_chroot.c |
25662 |
+--- linux-2.6.28.8/grsecurity/grsec_chroot.c 1969-12-31 19:00:00.000000000 -0500 |
25663 |
++++ linux-2.6.28.8/grsecurity/grsec_chroot.c 2009-02-21 09:37:49.000000000 -0500 |
25664 |
+@@ -0,0 +1,336 @@ |
25665 |
++#include <linux/kernel.h> |
25666 |
++#include <linux/module.h> |
25667 |
++#include <linux/sched.h> |
25668 |
++#include <linux/file.h> |
25669 |
++#include <linux/fs.h> |
25670 |
++#include <linux/mount.h> |
25671 |
++#include <linux/types.h> |
25672 |
++#include <linux/pid_namespace.h> |
25673 |
++#include <linux/grsecurity.h> |
25674 |
++#include <linux/grinternal.h> |
25675 |
++ |
25676 |
++int |
25677 |
++gr_handle_chroot_unix(const pid_t pid) |
25678 |
++{ |
25679 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX |
25680 |
++ struct pid *spid = NULL; |
25681 |
++ |
25682 |
++ if (unlikely(!grsec_enable_chroot_unix)) |
25683 |
++ return 1; |
25684 |
++ |
25685 |
++ if (likely(!proc_is_chrooted(current))) |
25686 |
++ return 1; |
25687 |
++ |
25688 |
++ read_lock(&tasklist_lock); |
25689 |
++ |
25690 |
++ spid = find_vpid(pid); |
25691 |
++ if (spid) { |
25692 |
++ struct task_struct *p; |
25693 |
++ p = pid_task(spid, PIDTYPE_PID); |
25694 |
++ task_lock(p); |
25695 |
++ if (unlikely(!have_same_root(current, p))) { |
25696 |
++ task_unlock(p); |
25697 |
++ read_unlock(&tasklist_lock); |
25698 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_UNIX_CHROOT_MSG); |
25699 |
++ return 0; |
25700 |
++ } |
25701 |
++ task_unlock(p); |
25702 |
++ } |
25703 |
++ read_unlock(&tasklist_lock); |
25704 |
++#endif |
25705 |
++ return 1; |
25706 |
++} |
25707 |
++ |
25708 |
++int |
25709 |
++gr_handle_chroot_nice(void) |
25710 |
++{ |
25711 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE |
25712 |
++ if (grsec_enable_chroot_nice && proc_is_chrooted(current)) { |
25713 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_NICE_CHROOT_MSG); |
25714 |
++ return -EPERM; |
25715 |
++ } |
25716 |
++#endif |
25717 |
++ return 0; |
25718 |
++} |
25719 |
++ |
25720 |
++int |
25721 |
++gr_handle_chroot_setpriority(struct task_struct *p, const int niceval) |
25722 |
++{ |
25723 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE |
25724 |
++ if (grsec_enable_chroot_nice && (niceval < task_nice(p)) |
25725 |
++ && proc_is_chrooted(current)) { |
25726 |
++ gr_log_str_int(GR_DONT_AUDIT, GR_PRIORITY_CHROOT_MSG, p->comm, p->pid); |
25727 |
++ return -EACCES; |
25728 |
++ } |
25729 |
++#endif |
25730 |
++ return 0; |
25731 |
++} |
25732 |
++ |
25733 |
++int |
25734 |
++gr_handle_chroot_rawio(const struct inode *inode) |
25735 |
++{ |
25736 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS |
25737 |
++ if (grsec_enable_chroot_caps && proc_is_chrooted(current) && |
25738 |
++ inode && S_ISBLK(inode->i_mode) && !capable(CAP_SYS_RAWIO)) |
25739 |
++ return 1; |
25740 |
++#endif |
25741 |
++ return 0; |
25742 |
++} |
25743 |
++ |
25744 |
++int |
25745 |
++gr_pid_is_chrooted(struct task_struct *p) |
25746 |
++{ |
25747 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK |
25748 |
++ if (!grsec_enable_chroot_findtask || !proc_is_chrooted(current) || p == NULL) |
25749 |
++ return 0; |
25750 |
++ |
25751 |
++ task_lock(p); |
25752 |
++ if ((p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) || |
25753 |
++ !have_same_root(current, p)) { |
25754 |
++ task_unlock(p); |
25755 |
++ return 1; |
25756 |
++ } |
25757 |
++ task_unlock(p); |
25758 |
++#endif |
25759 |
++ return 0; |
25760 |
++} |
25761 |
++ |
25762 |
++EXPORT_SYMBOL(gr_pid_is_chrooted); |
25763 |
++ |
25764 |
++#if defined(CONFIG_GRKERNSEC_CHROOT_DOUBLE) || defined(CONFIG_GRKERNSEC_CHROOT_FCHDIR) |
25765 |
++int gr_is_outside_chroot(const struct dentry *u_dentry, const struct vfsmount *u_mnt) |
25766 |
++{ |
25767 |
++ struct dentry *dentry = (struct dentry *)u_dentry; |
25768 |
++ struct vfsmount *mnt = (struct vfsmount *)u_mnt; |
25769 |
++ struct dentry *realroot; |
25770 |
++ struct vfsmount *realrootmnt; |
25771 |
++ struct dentry *currentroot; |
25772 |
++ struct vfsmount *currentmnt; |
25773 |
++ struct task_struct *reaper = current->nsproxy->pid_ns->child_reaper; |
25774 |
++ int ret = 1; |
25775 |
++ |
25776 |
++ read_lock(&reaper->fs->lock); |
25777 |
++ realrootmnt = mntget(reaper->fs->root.mnt); |
25778 |
++ realroot = dget(reaper->fs->root.dentry); |
25779 |
++ read_unlock(&reaper->fs->lock); |
25780 |
++ |
25781 |
++ read_lock(¤t->fs->lock); |
25782 |
++ currentmnt = mntget(current->fs->root.mnt); |
25783 |
++ currentroot = dget(current->fs->root.dentry); |
25784 |
++ read_unlock(¤t->fs->lock); |
25785 |
++ |
25786 |
++ spin_lock(&dcache_lock); |
25787 |
++ for (;;) { |
25788 |
++ if (unlikely((dentry == realroot && mnt == realrootmnt) |
25789 |
++ || (dentry == currentroot && mnt == currentmnt))) |
25790 |
++ break; |
25791 |
++ if (unlikely(dentry == mnt->mnt_root || IS_ROOT(dentry))) { |
25792 |
++ if (mnt->mnt_parent == mnt) |
25793 |
++ break; |
25794 |
++ dentry = mnt->mnt_mountpoint; |
25795 |
++ mnt = mnt->mnt_parent; |
25796 |
++ continue; |
25797 |
++ } |
25798 |
++ dentry = dentry->d_parent; |
25799 |
++ } |
25800 |
++ spin_unlock(&dcache_lock); |
25801 |
++ |
25802 |
++ dput(currentroot); |
25803 |
++ mntput(currentmnt); |
25804 |
++ |
25805 |
++ /* access is outside of chroot */ |
25806 |
++ if (dentry == realroot && mnt == realrootmnt) |
25807 |
++ ret = 0; |
25808 |
++ |
25809 |
++ dput(realroot); |
25810 |
++ mntput(realrootmnt); |
25811 |
++ return ret; |
25812 |
++} |
25813 |
++#endif |
25814 |
++ |
25815 |
++int |
25816 |
++gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt) |
25817 |
++{ |
25818 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR |
25819 |
++ if (!grsec_enable_chroot_fchdir) |
25820 |
++ return 1; |
25821 |
++ |
25822 |
++ if (!proc_is_chrooted(current)) |
25823 |
++ return 1; |
25824 |
++ else if (!gr_is_outside_chroot(u_dentry, u_mnt)) { |
25825 |
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_FCHDIR_MSG, u_dentry, u_mnt); |
25826 |
++ return 0; |
25827 |
++ } |
25828 |
++#endif |
25829 |
++ return 1; |
25830 |
++} |
25831 |
++ |
25832 |
++int |
25833 |
++gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid, |
25834 |
++ const time_t shm_createtime) |
25835 |
++{ |
25836 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT |
25837 |
++ struct pid *pid = NULL; |
25838 |
++ time_t starttime; |
25839 |
++ |
25840 |
++ if (unlikely(!grsec_enable_chroot_shmat)) |
25841 |
++ return 1; |
25842 |
++ |
25843 |
++ if (likely(!proc_is_chrooted(current))) |
25844 |
++ return 1; |
25845 |
++ |
25846 |
++ read_lock(&tasklist_lock); |
25847 |
++ |
25848 |
++ pid = find_vpid(shm_cprid); |
25849 |
++ if (pid) { |
25850 |
++ struct task_struct *p; |
25851 |
++ p = pid_task(pid, PIDTYPE_PID); |
25852 |
++ task_lock(p); |
25853 |
++ starttime = p->start_time.tv_sec; |
25854 |
++ if (unlikely(!have_same_root(current, p) && |
25855 |
++ time_before_eq((unsigned long)starttime, (unsigned long)shm_createtime))) { |
25856 |
++ task_unlock(p); |
25857 |
++ read_unlock(&tasklist_lock); |
25858 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG); |
25859 |
++ return 0; |
25860 |
++ } |
25861 |
++ task_unlock(p); |
25862 |
++ } else { |
25863 |
++ pid = find_vpid(shm_lapid); |
25864 |
++ if (pid) { |
25865 |
++ struct task_struct *p; |
25866 |
++ p = pid_task(pid, PIDTYPE_PID); |
25867 |
++ task_lock(p); |
25868 |
++ if (unlikely(!have_same_root(current, p))) { |
25869 |
++ task_unlock(p); |
25870 |
++ read_unlock(&tasklist_lock); |
25871 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG); |
25872 |
++ return 0; |
25873 |
++ } |
25874 |
++ task_unlock(p); |
25875 |
++ } |
25876 |
++ } |
25877 |
++ |
25878 |
++ read_unlock(&tasklist_lock); |
25879 |
++#endif |
25880 |
++ return 1; |
25881 |
++} |
25882 |
++ |
25883 |
++void |
25884 |
++gr_log_chroot_exec(const struct dentry *dentry, const struct vfsmount *mnt) |
25885 |
++{ |
25886 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG |
25887 |
++ if (grsec_enable_chroot_execlog && proc_is_chrooted(current)) |
25888 |
++ gr_log_fs_generic(GR_DO_AUDIT, GR_EXEC_CHROOT_MSG, dentry, mnt); |
25889 |
++#endif |
25890 |
++ return; |
25891 |
++} |
25892 |
++ |
25893 |
++int |
25894 |
++gr_handle_chroot_mknod(const struct dentry *dentry, |
25895 |
++ const struct vfsmount *mnt, const int mode) |
25896 |
++{ |
25897 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD |
25898 |
++ if (grsec_enable_chroot_mknod && !S_ISFIFO(mode) && !S_ISREG(mode) && |
25899 |
++ proc_is_chrooted(current)) { |
25900 |
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_MKNOD_CHROOT_MSG, dentry, mnt); |
25901 |
++ return -EPERM; |
25902 |
++ } |
25903 |
++#endif |
25904 |
++ return 0; |
25905 |
++} |
25906 |
++ |
25907 |
++int |
25908 |
++gr_handle_chroot_mount(const struct dentry *dentry, |
25909 |
++ const struct vfsmount *mnt, const char *dev_name) |
25910 |
++{ |
25911 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT |
25912 |
++ if (grsec_enable_chroot_mount && proc_is_chrooted(current)) { |
25913 |
++ gr_log_str_fs(GR_DONT_AUDIT, GR_MOUNT_CHROOT_MSG, dev_name, dentry, mnt); |
25914 |
++ return -EPERM; |
25915 |
++ } |
25916 |
++#endif |
25917 |
++ return 0; |
25918 |
++} |
25919 |
++ |
25920 |
++int |
25921 |
++gr_handle_chroot_pivot(void) |
25922 |
++{ |
25923 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT |
25924 |
++ if (grsec_enable_chroot_pivot && proc_is_chrooted(current)) { |
25925 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_PIVOT_CHROOT_MSG); |
25926 |
++ return -EPERM; |
25927 |
++ } |
25928 |
++#endif |
25929 |
++ return 0; |
25930 |
++} |
25931 |
++ |
25932 |
++int |
25933 |
++gr_handle_chroot_chroot(const struct dentry *dentry, const struct vfsmount *mnt) |
25934 |
++{ |
25935 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE |
25936 |
++ if (grsec_enable_chroot_double && proc_is_chrooted(current) && |
25937 |
++ !gr_is_outside_chroot(dentry, mnt)) { |
25938 |
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_CHROOT_MSG, dentry, mnt); |
25939 |
++ return -EPERM; |
25940 |
++ } |
25941 |
++#endif |
25942 |
++ return 0; |
25943 |
++} |
25944 |
++ |
25945 |
++void |
25946 |
++gr_handle_chroot_caps(struct task_struct *task) |
25947 |
++{ |
25948 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS |
25949 |
++ if (grsec_enable_chroot_caps && proc_is_chrooted(task)) { |
25950 |
++ kernel_cap_t chroot_caps = GR_CHROOT_CAPS; |
25951 |
++ task->cap_permitted = |
25952 |
++ cap_drop(task->cap_permitted, chroot_caps); |
25953 |
++ task->cap_inheritable = |
25954 |
++ cap_drop(task->cap_inheritable, chroot_caps); |
25955 |
++ task->cap_effective = |
25956 |
++ cap_drop(task->cap_effective, chroot_caps); |
25957 |
++ } |
25958 |
++#endif |
25959 |
++ return; |
25960 |
++} |
25961 |
++ |
25962 |
++int |
25963 |
++gr_handle_chroot_sysctl(const int op) |
25964 |
++{ |
25965 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL |
25966 |
++ if (grsec_enable_chroot_sysctl && proc_is_chrooted(current) |
25967 |
++ && (op & MAY_WRITE)) |
25968 |
++ return -EACCES; |
25969 |
++#endif |
25970 |
++ return 0; |
25971 |
++} |
25972 |
++ |
25973 |
++void |
25974 |
++gr_handle_chroot_chdir(struct path *path) |
25975 |
++{ |
25976 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR |
25977 |
++ if (grsec_enable_chroot_chdir) |
25978 |
++ set_fs_pwd(current->fs, path); |
25979 |
++#endif |
25980 |
++ return; |
25981 |
++} |
25982 |
++ |
25983 |
++int |
25984 |
++gr_handle_chroot_chmod(const struct dentry *dentry, |
25985 |
++ const struct vfsmount *mnt, const int mode) |
25986 |
++{ |
25987 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD |
25988 |
++ if (grsec_enable_chroot_chmod && |
25989 |
++ ((mode & S_ISUID) || ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) && |
25990 |
++ proc_is_chrooted(current)) { |
25991 |
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHMOD_CHROOT_MSG, dentry, mnt); |
25992 |
++ return -EPERM; |
25993 |
++ } |
25994 |
++#endif |
25995 |
++ return 0; |
25996 |
++} |
25997 |
++ |
25998 |
++#ifdef CONFIG_SECURITY |
25999 |
++EXPORT_SYMBOL(gr_handle_chroot_caps); |
26000 |
++#endif |
26001 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_disabled.c linux-2.6.28.8/grsecurity/grsec_disabled.c |
26002 |
+--- linux-2.6.28.8/grsecurity/grsec_disabled.c 1969-12-31 19:00:00.000000000 -0500 |
26003 |
++++ linux-2.6.28.8/grsecurity/grsec_disabled.c 2009-03-07 14:23:04.000000000 -0500 |
26004 |
+@@ -0,0 +1,418 @@ |
26005 |
++#include <linux/kernel.h> |
26006 |
++#include <linux/module.h> |
26007 |
++#include <linux/sched.h> |
26008 |
++#include <linux/file.h> |
26009 |
++#include <linux/fs.h> |
26010 |
++#include <linux/kdev_t.h> |
26011 |
++#include <linux/net.h> |
26012 |
++#include <linux/in.h> |
26013 |
++#include <linux/ip.h> |
26014 |
++#include <linux/skbuff.h> |
26015 |
++#include <linux/sysctl.h> |
26016 |
++ |
26017 |
++#ifdef CONFIG_PAX_HAVE_ACL_FLAGS |
26018 |
++void |
26019 |
++pax_set_initial_flags(struct linux_binprm *bprm) |
26020 |
++{ |
26021 |
++ return; |
26022 |
++} |
26023 |
++#endif |
26024 |
++ |
26025 |
++#ifdef CONFIG_SYSCTL |
26026 |
++__u32 |
26027 |
++gr_handle_sysctl(const struct ctl_table * table, const int op) |
26028 |
++{ |
26029 |
++ return 0; |
26030 |
++} |
26031 |
++#endif |
26032 |
++ |
26033 |
++int |
26034 |
++gr_acl_is_enabled(void) |
26035 |
++{ |
26036 |
++ return 0; |
26037 |
++} |
26038 |
++ |
26039 |
++int |
26040 |
++gr_handle_rawio(const struct inode *inode) |
26041 |
++{ |
26042 |
++ return 0; |
26043 |
++} |
26044 |
++ |
26045 |
++void |
26046 |
++gr_acl_handle_psacct(struct task_struct *task, const long code) |
26047 |
++{ |
26048 |
++ return; |
26049 |
++} |
26050 |
++ |
26051 |
++int |
26052 |
++gr_handle_ptrace(struct task_struct *task, const long request) |
26053 |
++{ |
26054 |
++ return 0; |
26055 |
++} |
26056 |
++ |
26057 |
++int |
26058 |
++gr_handle_proc_ptrace(struct task_struct *task) |
26059 |
++{ |
26060 |
++ return 0; |
26061 |
++} |
26062 |
++ |
26063 |
++void |
26064 |
++gr_learn_resource(const struct task_struct *task, |
26065 |
++ const int res, const unsigned long wanted, const int gt) |
26066 |
++{ |
26067 |
++ return; |
26068 |
++} |
26069 |
++ |
26070 |
++int |
26071 |
++gr_set_acls(const int type) |
26072 |
++{ |
26073 |
++ return 0; |
26074 |
++} |
26075 |
++ |
26076 |
++int |
26077 |
++gr_check_hidden_task(const struct task_struct *tsk) |
26078 |
++{ |
26079 |
++ return 0; |
26080 |
++} |
26081 |
++ |
26082 |
++int |
26083 |
++gr_check_protected_task(const struct task_struct *task) |
26084 |
++{ |
26085 |
++ return 0; |
26086 |
++} |
26087 |
++ |
26088 |
++void |
26089 |
++gr_copy_label(struct task_struct *tsk) |
26090 |
++{ |
26091 |
++ return; |
26092 |
++} |
26093 |
++ |
26094 |
++void |
26095 |
++gr_set_pax_flags(struct task_struct *task) |
26096 |
++{ |
26097 |
++ return; |
26098 |
++} |
26099 |
++ |
26100 |
++int |
26101 |
++gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt) |
26102 |
++{ |
26103 |
++ return 0; |
26104 |
++} |
26105 |
++ |
26106 |
++void |
26107 |
++gr_handle_delete(const ino_t ino, const dev_t dev) |
26108 |
++{ |
26109 |
++ return; |
26110 |
++} |
26111 |
++ |
26112 |
++void |
26113 |
++gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt) |
26114 |
++{ |
26115 |
++ return; |
26116 |
++} |
26117 |
++ |
26118 |
++void |
26119 |
++gr_handle_crash(struct task_struct *task, const int sig) |
26120 |
++{ |
26121 |
++ return; |
26122 |
++} |
26123 |
++ |
26124 |
++int |
26125 |
++gr_check_crash_exec(const struct file *filp) |
26126 |
++{ |
26127 |
++ return 0; |
26128 |
++} |
26129 |
++ |
26130 |
++int |
26131 |
++gr_check_crash_uid(const uid_t uid) |
26132 |
++{ |
26133 |
++ return 0; |
26134 |
++} |
26135 |
++ |
26136 |
++void |
26137 |
++gr_handle_rename(struct inode *old_dir, struct inode *new_dir, |
26138 |
++ struct dentry *old_dentry, |
26139 |
++ struct dentry *new_dentry, |
26140 |
++ struct vfsmount *mnt, const __u8 replace) |
26141 |
++{ |
26142 |
++ return; |
26143 |
++} |
26144 |
++ |
26145 |
++int |
26146 |
++gr_search_socket(const int family, const int type, const int protocol) |
26147 |
++{ |
26148 |
++ return 1; |
26149 |
++} |
26150 |
++ |
26151 |
++int |
26152 |
++gr_search_connectbind(const int mode, const struct socket *sock, |
26153 |
++ const struct sockaddr_in *addr) |
26154 |
++{ |
26155 |
++ return 0; |
26156 |
++} |
26157 |
++ |
26158 |
++int |
26159 |
++gr_task_is_capable(struct task_struct *task, const int cap) |
26160 |
++{ |
26161 |
++ return 1; |
26162 |
++} |
26163 |
++ |
26164 |
++int |
26165 |
++gr_is_capable_nolog(const int cap) |
26166 |
++{ |
26167 |
++ return 1; |
26168 |
++} |
26169 |
++ |
26170 |
++void |
26171 |
++gr_handle_alertkill(struct task_struct *task) |
26172 |
++{ |
26173 |
++ return; |
26174 |
++} |
26175 |
++ |
26176 |
++__u32 |
26177 |
++gr_acl_handle_execve(const struct dentry * dentry, const struct vfsmount * mnt) |
26178 |
++{ |
26179 |
++ return 1; |
26180 |
++} |
26181 |
++ |
26182 |
++__u32 |
26183 |
++gr_acl_handle_hidden_file(const struct dentry * dentry, |
26184 |
++ const struct vfsmount * mnt) |
26185 |
++{ |
26186 |
++ return 1; |
26187 |
++} |
26188 |
++ |
26189 |
++__u32 |
26190 |
++gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt, |
26191 |
++ const int fmode) |
26192 |
++{ |
26193 |
++ return 1; |
26194 |
++} |
26195 |
++ |
26196 |
++__u32 |
26197 |
++gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt) |
26198 |
++{ |
26199 |
++ return 1; |
26200 |
++} |
26201 |
++ |
26202 |
++__u32 |
26203 |
++gr_acl_handle_unlink(const struct dentry * dentry, const struct vfsmount * mnt) |
26204 |
++{ |
26205 |
++ return 1; |
26206 |
++} |
26207 |
++ |
26208 |
++int |
26209 |
++gr_acl_handle_mmap(const struct file *file, const unsigned long prot, |
26210 |
++ unsigned int *vm_flags) |
26211 |
++{ |
26212 |
++ return 1; |
26213 |
++} |
26214 |
++ |
26215 |
++__u32 |
26216 |
++gr_acl_handle_truncate(const struct dentry * dentry, |
26217 |
++ const struct vfsmount * mnt) |
26218 |
++{ |
26219 |
++ return 1; |
26220 |
++} |
26221 |
++ |
26222 |
++__u32 |
26223 |
++gr_acl_handle_utime(const struct dentry * dentry, const struct vfsmount * mnt) |
26224 |
++{ |
26225 |
++ return 1; |
26226 |
++} |
26227 |
++ |
26228 |
++__u32 |
26229 |
++gr_acl_handle_access(const struct dentry * dentry, |
26230 |
++ const struct vfsmount * mnt, const int fmode) |
26231 |
++{ |
26232 |
++ return 1; |
26233 |
++} |
26234 |
++ |
26235 |
++__u32 |
26236 |
++gr_acl_handle_fchmod(const struct dentry * dentry, const struct vfsmount * mnt, |
26237 |
++ mode_t mode) |
26238 |
++{ |
26239 |
++ return 1; |
26240 |
++} |
26241 |
++ |
26242 |
++__u32 |
26243 |
++gr_acl_handle_chmod(const struct dentry * dentry, const struct vfsmount * mnt, |
26244 |
++ mode_t mode) |
26245 |
++{ |
26246 |
++ return 1; |
26247 |
++} |
26248 |
++ |
26249 |
++__u32 |
26250 |
++gr_acl_handle_chown(const struct dentry * dentry, const struct vfsmount * mnt) |
26251 |
++{ |
26252 |
++ return 1; |
26253 |
++} |
26254 |
++ |
26255 |
++void |
26256 |
++grsecurity_init(void) |
26257 |
++{ |
26258 |
++ return; |
26259 |
++} |
26260 |
++ |
26261 |
++__u32 |
26262 |
++gr_acl_handle_mknod(const struct dentry * new_dentry, |
26263 |
++ const struct dentry * parent_dentry, |
26264 |
++ const struct vfsmount * parent_mnt, |
26265 |
++ const int mode) |
26266 |
++{ |
26267 |
++ return 1; |
26268 |
++} |
26269 |
++ |
26270 |
++__u32 |
26271 |
++gr_acl_handle_mkdir(const struct dentry * new_dentry, |
26272 |
++ const struct dentry * parent_dentry, |
26273 |
++ const struct vfsmount * parent_mnt) |
26274 |
++{ |
26275 |
++ return 1; |
26276 |
++} |
26277 |
++ |
26278 |
++__u32 |
26279 |
++gr_acl_handle_symlink(const struct dentry * new_dentry, |
26280 |
++ const struct dentry * parent_dentry, |
26281 |
++ const struct vfsmount * parent_mnt, const char *from) |
26282 |
++{ |
26283 |
++ return 1; |
26284 |
++} |
26285 |
++ |
26286 |
++__u32 |
26287 |
++gr_acl_handle_link(const struct dentry * new_dentry, |
26288 |
++ const struct dentry * parent_dentry, |
26289 |
++ const struct vfsmount * parent_mnt, |
26290 |
++ const struct dentry * old_dentry, |
26291 |
++ const struct vfsmount * old_mnt, const char *to) |
26292 |
++{ |
26293 |
++ return 1; |
26294 |
++} |
26295 |
++ |
26296 |
++int |
26297 |
++gr_acl_handle_rename(const struct dentry *new_dentry, |
26298 |
++ const struct dentry *parent_dentry, |
26299 |
++ const struct vfsmount *parent_mnt, |
26300 |
++ const struct dentry *old_dentry, |
26301 |
++ const struct inode *old_parent_inode, |
26302 |
++ const struct vfsmount *old_mnt, const char *newname) |
26303 |
++{ |
26304 |
++ return 0; |
26305 |
++} |
26306 |
++ |
26307 |
++int |
26308 |
++gr_acl_handle_filldir(const struct file *file, const char *name, |
26309 |
++ const int namelen, const ino_t ino) |
26310 |
++{ |
26311 |
++ return 1; |
26312 |
++} |
26313 |
++ |
26314 |
++int |
26315 |
++gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid, |
26316 |
++ const time_t shm_createtime, const uid_t cuid, const int shmid) |
26317 |
++{ |
26318 |
++ return 1; |
26319 |
++} |
26320 |
++ |
26321 |
++int |
26322 |
++gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr) |
26323 |
++{ |
26324 |
++ return 0; |
26325 |
++} |
26326 |
++ |
26327 |
++int |
26328 |
++gr_search_accept(const struct socket *sock) |
26329 |
++{ |
26330 |
++ return 0; |
26331 |
++} |
26332 |
++ |
26333 |
++int |
26334 |
++gr_search_listen(const struct socket *sock) |
26335 |
++{ |
26336 |
++ return 0; |
26337 |
++} |
26338 |
++ |
26339 |
++int |
26340 |
++gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr) |
26341 |
++{ |
26342 |
++ return 0; |
26343 |
++} |
26344 |
++ |
26345 |
++__u32 |
26346 |
++gr_acl_handle_unix(const struct dentry * dentry, const struct vfsmount * mnt) |
26347 |
++{ |
26348 |
++ return 1; |
26349 |
++} |
26350 |
++ |
26351 |
++__u32 |
26352 |
++gr_acl_handle_creat(const struct dentry * dentry, |
26353 |
++ const struct dentry * p_dentry, |
26354 |
++ const struct vfsmount * p_mnt, const int fmode, |
26355 |
++ const int imode) |
26356 |
++{ |
26357 |
++ return 1; |
26358 |
++} |
26359 |
++ |
26360 |
++void |
26361 |
++gr_acl_handle_exit(void) |
26362 |
++{ |
26363 |
++ return; |
26364 |
++} |
26365 |
++ |
26366 |
++int |
26367 |
++gr_acl_handle_mprotect(const struct file *file, const unsigned long prot) |
26368 |
++{ |
26369 |
++ return 1; |
26370 |
++} |
26371 |
++ |
26372 |
++void |
26373 |
++gr_set_role_label(const uid_t uid, const gid_t gid) |
26374 |
++{ |
26375 |
++ return; |
26376 |
++} |
26377 |
++ |
26378 |
++int |
26379 |
++gr_acl_handle_procpidmem(const struct task_struct *task) |
26380 |
++{ |
26381 |
++ return 0; |
26382 |
++} |
26383 |
++ |
26384 |
++int |
26385 |
++gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb) |
26386 |
++{ |
26387 |
++ return 0; |
26388 |
++} |
26389 |
++ |
26390 |
++int |
26391 |
++gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr) |
26392 |
++{ |
26393 |
++ return 0; |
26394 |
++} |
26395 |
++ |
26396 |
++void |
26397 |
++gr_set_kernel_label(struct task_struct *task) |
26398 |
++{ |
26399 |
++ return; |
26400 |
++} |
26401 |
++ |
26402 |
++int |
26403 |
++gr_check_user_change(int real, int effective, int fs) |
26404 |
++{ |
26405 |
++ return 0; |
26406 |
++} |
26407 |
++ |
26408 |
++int |
26409 |
++gr_check_group_change(int real, int effective, int fs) |
26410 |
++{ |
26411 |
++ return 0; |
26412 |
++} |
26413 |
++ |
26414 |
++ |
26415 |
++EXPORT_SYMBOL(gr_task_is_capable); |
26416 |
++EXPORT_SYMBOL(gr_is_capable_nolog); |
26417 |
++EXPORT_SYMBOL(gr_learn_resource); |
26418 |
++EXPORT_SYMBOL(gr_set_kernel_label); |
26419 |
++#ifdef CONFIG_SECURITY |
26420 |
++EXPORT_SYMBOL(gr_check_user_change); |
26421 |
++EXPORT_SYMBOL(gr_check_group_change); |
26422 |
++#endif |
26423 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_exec.c linux-2.6.28.8/grsecurity/grsec_exec.c |
26424 |
+--- linux-2.6.28.8/grsecurity/grsec_exec.c 1969-12-31 19:00:00.000000000 -0500 |
26425 |
++++ linux-2.6.28.8/grsecurity/grsec_exec.c 2009-02-21 09:37:49.000000000 -0500 |
26426 |
+@@ -0,0 +1,88 @@ |
26427 |
++#include <linux/kernel.h> |
26428 |
++#include <linux/sched.h> |
26429 |
++#include <linux/file.h> |
26430 |
++#include <linux/binfmts.h> |
26431 |
++#include <linux/smp_lock.h> |
26432 |
++#include <linux/fs.h> |
26433 |
++#include <linux/types.h> |
26434 |
++#include <linux/grdefs.h> |
26435 |
++#include <linux/grinternal.h> |
26436 |
++#include <linux/capability.h> |
26437 |
++ |
26438 |
++#include <asm/uaccess.h> |
26439 |
++ |
26440 |
++#ifdef CONFIG_GRKERNSEC_EXECLOG |
26441 |
++static char gr_exec_arg_buf[132]; |
26442 |
++static DECLARE_MUTEX(gr_exec_arg_sem); |
26443 |
++#endif |
26444 |
++ |
26445 |
++int |
26446 |
++gr_handle_nproc(void) |
26447 |
++{ |
26448 |
++#ifdef CONFIG_GRKERNSEC_EXECVE |
26449 |
++ if (grsec_enable_execve && current->user && |
26450 |
++ (atomic_read(¤t->user->processes) > |
26451 |
++ current->signal->rlim[RLIMIT_NPROC].rlim_cur) && |
26452 |
++ !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) { |
26453 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_NPROC_MSG); |
26454 |
++ return -EAGAIN; |
26455 |
++ } |
26456 |
++#endif |
26457 |
++ return 0; |
26458 |
++} |
26459 |
++ |
26460 |
++void |
26461 |
++gr_handle_exec_args(struct linux_binprm *bprm, const char __user *__user *argv) |
26462 |
++{ |
26463 |
++#ifdef CONFIG_GRKERNSEC_EXECLOG |
26464 |
++ char *grarg = gr_exec_arg_buf; |
26465 |
++ unsigned int i, x, execlen = 0; |
26466 |
++ char c; |
26467 |
++ |
26468 |
++ if (!((grsec_enable_execlog && grsec_enable_group && |
26469 |
++ in_group_p(grsec_audit_gid)) |
26470 |
++ || (grsec_enable_execlog && !grsec_enable_group))) |
26471 |
++ return; |
26472 |
++ |
26473 |
++ down(&gr_exec_arg_sem); |
26474 |
++ memset(grarg, 0, sizeof(gr_exec_arg_buf)); |
26475 |
++ |
26476 |
++ if (unlikely(argv == NULL)) |
26477 |
++ goto log; |
26478 |
++ |
26479 |
++ for (i = 0; i < bprm->argc && execlen < 128; i++) { |
26480 |
++ const char __user *p; |
26481 |
++ unsigned int len; |
26482 |
++ |
26483 |
++ if (copy_from_user(&p, argv + i, sizeof(p))) |
26484 |
++ goto log; |
26485 |
++ if (!p) |
26486 |
++ goto log; |
26487 |
++ len = strnlen_user(p, 128 - execlen); |
26488 |
++ if (len > 128 - execlen) |
26489 |
++ len = 128 - execlen; |
26490 |
++ else if (len > 0) |
26491 |
++ len--; |
26492 |
++ if (copy_from_user(grarg + execlen, p, len)) |
26493 |
++ goto log; |
26494 |
++ |
26495 |
++ /* rewrite unprintable characters */ |
26496 |
++ for (x = 0; x < len; x++) { |
26497 |
++ c = *(grarg + execlen + x); |
26498 |
++ if (c < 32 || c > 126) |
26499 |
++ *(grarg + execlen + x) = ' '; |
26500 |
++ } |
26501 |
++ |
26502 |
++ execlen += len; |
26503 |
++ *(grarg + execlen) = ' '; |
26504 |
++ *(grarg + execlen + 1) = '\0'; |
26505 |
++ execlen++; |
26506 |
++ } |
26507 |
++ |
26508 |
++ log: |
26509 |
++ gr_log_fs_str(GR_DO_AUDIT, GR_EXEC_AUDIT_MSG, bprm->file->f_path.dentry, |
26510 |
++ bprm->file->f_path.mnt, grarg); |
26511 |
++ up(&gr_exec_arg_sem); |
26512 |
++#endif |
26513 |
++ return; |
26514 |
++} |
26515 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_fifo.c linux-2.6.28.8/grsecurity/grsec_fifo.c |
26516 |
+--- linux-2.6.28.8/grsecurity/grsec_fifo.c 1969-12-31 19:00:00.000000000 -0500 |
26517 |
++++ linux-2.6.28.8/grsecurity/grsec_fifo.c 2009-02-21 09:37:49.000000000 -0500 |
26518 |
+@@ -0,0 +1,22 @@ |
26519 |
++#include <linux/kernel.h> |
26520 |
++#include <linux/sched.h> |
26521 |
++#include <linux/fs.h> |
26522 |
++#include <linux/file.h> |
26523 |
++#include <linux/grinternal.h> |
26524 |
++ |
26525 |
++int |
26526 |
++gr_handle_fifo(const struct dentry *dentry, const struct vfsmount *mnt, |
26527 |
++ const struct dentry *dir, const int flag, const int acc_mode) |
26528 |
++{ |
26529 |
++#ifdef CONFIG_GRKERNSEC_FIFO |
26530 |
++ if (grsec_enable_fifo && S_ISFIFO(dentry->d_inode->i_mode) && |
26531 |
++ !(flag & O_EXCL) && (dir->d_inode->i_mode & S_ISVTX) && |
26532 |
++ (dentry->d_inode->i_uid != dir->d_inode->i_uid) && |
26533 |
++ (current->fsuid != dentry->d_inode->i_uid)) { |
26534 |
++ if (!generic_permission(dentry->d_inode, acc_mode, NULL)) |
26535 |
++ gr_log_fs_int2(GR_DONT_AUDIT, GR_FIFO_MSG, dentry, mnt, dentry->d_inode->i_uid, dentry->d_inode->i_gid); |
26536 |
++ return -EACCES; |
26537 |
++ } |
26538 |
++#endif |
26539 |
++ return 0; |
26540 |
++} |
26541 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_fork.c linux-2.6.28.8/grsecurity/grsec_fork.c |
26542 |
+--- linux-2.6.28.8/grsecurity/grsec_fork.c 1969-12-31 19:00:00.000000000 -0500 |
26543 |
++++ linux-2.6.28.8/grsecurity/grsec_fork.c 2009-02-21 09:37:49.000000000 -0500 |
26544 |
+@@ -0,0 +1,15 @@ |
26545 |
++#include <linux/kernel.h> |
26546 |
++#include <linux/sched.h> |
26547 |
++#include <linux/grsecurity.h> |
26548 |
++#include <linux/grinternal.h> |
26549 |
++#include <linux/errno.h> |
26550 |
++ |
26551 |
++void |
26552 |
++gr_log_forkfail(const int retval) |
26553 |
++{ |
26554 |
++#ifdef CONFIG_GRKERNSEC_FORKFAIL |
26555 |
++ if (grsec_enable_forkfail && retval != -ERESTARTNOINTR) |
26556 |
++ gr_log_int(GR_DONT_AUDIT, GR_FAILFORK_MSG, retval); |
26557 |
++#endif |
26558 |
++ return; |
26559 |
++} |
26560 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_init.c linux-2.6.28.8/grsecurity/grsec_init.c |
26561 |
+--- linux-2.6.28.8/grsecurity/grsec_init.c 1969-12-31 19:00:00.000000000 -0500 |
26562 |
++++ linux-2.6.28.8/grsecurity/grsec_init.c 2009-02-21 09:37:49.000000000 -0500 |
26563 |
+@@ -0,0 +1,230 @@ |
26564 |
++#include <linux/kernel.h> |
26565 |
++#include <linux/sched.h> |
26566 |
++#include <linux/mm.h> |
26567 |
++#include <linux/smp_lock.h> |
26568 |
++#include <linux/gracl.h> |
26569 |
++#include <linux/slab.h> |
26570 |
++#include <linux/vmalloc.h> |
26571 |
++#include <linux/percpu.h> |
26572 |
++ |
26573 |
++int grsec_enable_link; |
26574 |
++int grsec_enable_dmesg; |
26575 |
++int grsec_enable_fifo; |
26576 |
++int grsec_enable_execve; |
26577 |
++int grsec_enable_execlog; |
26578 |
++int grsec_enable_signal; |
26579 |
++int grsec_enable_forkfail; |
26580 |
++int grsec_enable_time; |
26581 |
++int grsec_enable_audit_textrel; |
26582 |
++int grsec_enable_group; |
26583 |
++int grsec_audit_gid; |
26584 |
++int grsec_enable_chdir; |
26585 |
++int grsec_enable_audit_ipc; |
26586 |
++int grsec_enable_mount; |
26587 |
++int grsec_enable_chroot_findtask; |
26588 |
++int grsec_enable_chroot_mount; |
26589 |
++int grsec_enable_chroot_shmat; |
26590 |
++int grsec_enable_chroot_fchdir; |
26591 |
++int grsec_enable_chroot_double; |
26592 |
++int grsec_enable_chroot_pivot; |
26593 |
++int grsec_enable_chroot_chdir; |
26594 |
++int grsec_enable_chroot_chmod; |
26595 |
++int grsec_enable_chroot_mknod; |
26596 |
++int grsec_enable_chroot_nice; |
26597 |
++int grsec_enable_chroot_execlog; |
26598 |
++int grsec_enable_chroot_caps; |
26599 |
++int grsec_enable_chroot_sysctl; |
26600 |
++int grsec_enable_chroot_unix; |
26601 |
++int grsec_enable_tpe; |
26602 |
++int grsec_tpe_gid; |
26603 |
++int grsec_enable_tpe_all; |
26604 |
++int grsec_enable_socket_all; |
26605 |
++int grsec_socket_all_gid; |
26606 |
++int grsec_enable_socket_client; |
26607 |
++int grsec_socket_client_gid; |
26608 |
++int grsec_enable_socket_server; |
26609 |
++int grsec_socket_server_gid; |
26610 |
++int grsec_resource_logging; |
26611 |
++int grsec_lock; |
26612 |
++ |
26613 |
++DEFINE_SPINLOCK(grsec_alert_lock); |
26614 |
++unsigned long grsec_alert_wtime = 0; |
26615 |
++unsigned long grsec_alert_fyet = 0; |
26616 |
++ |
26617 |
++DEFINE_SPINLOCK(grsec_audit_lock); |
26618 |
++ |
26619 |
++DEFINE_RWLOCK(grsec_exec_file_lock); |
26620 |
++ |
26621 |
++char *gr_shared_page[4]; |
26622 |
++ |
26623 |
++char *gr_alert_log_fmt; |
26624 |
++char *gr_audit_log_fmt; |
26625 |
++char *gr_alert_log_buf; |
26626 |
++char *gr_audit_log_buf; |
26627 |
++ |
26628 |
++extern struct gr_arg *gr_usermode; |
26629 |
++extern unsigned char *gr_system_salt; |
26630 |
++extern unsigned char *gr_system_sum; |
26631 |
++ |
26632 |
++void |
26633 |
++grsecurity_init(void) |
26634 |
++{ |
26635 |
++ int j; |
26636 |
++ /* create the per-cpu shared pages */ |
26637 |
++ |
26638 |
++#ifdef CONFIG_X86 |
26639 |
++ memset((char *)(0x41a + PAGE_OFFSET), 0, 36); |
26640 |
++#endif |
26641 |
++ |
26642 |
++ for (j = 0; j < 4; j++) { |
26643 |
++ gr_shared_page[j] = (char *)__alloc_percpu(PAGE_SIZE); |
26644 |
++ if (gr_shared_page[j] == NULL) { |
26645 |
++ panic("Unable to allocate grsecurity shared page"); |
26646 |
++ return; |
26647 |
++ } |
26648 |
++ } |
26649 |
++ |
26650 |
++ /* allocate log buffers */ |
26651 |
++ gr_alert_log_fmt = kmalloc(512, GFP_KERNEL); |
26652 |
++ if (!gr_alert_log_fmt) { |
26653 |
++ panic("Unable to allocate grsecurity alert log format buffer"); |
26654 |
++ return; |
26655 |
++ } |
26656 |
++ gr_audit_log_fmt = kmalloc(512, GFP_KERNEL); |
26657 |
++ if (!gr_audit_log_fmt) { |
26658 |
++ panic("Unable to allocate grsecurity audit log format buffer"); |
26659 |
++ return; |
26660 |
++ } |
26661 |
++ gr_alert_log_buf = (char *) get_zeroed_page(GFP_KERNEL); |
26662 |
++ if (!gr_alert_log_buf) { |
26663 |
++ panic("Unable to allocate grsecurity alert log buffer"); |
26664 |
++ return; |
26665 |
++ } |
26666 |
++ gr_audit_log_buf = (char *) get_zeroed_page(GFP_KERNEL); |
26667 |
++ if (!gr_audit_log_buf) { |
26668 |
++ panic("Unable to allocate grsecurity audit log buffer"); |
26669 |
++ return; |
26670 |
++ } |
26671 |
++ |
26672 |
++ /* allocate memory for authentication structure */ |
26673 |
++ gr_usermode = kmalloc(sizeof(struct gr_arg), GFP_KERNEL); |
26674 |
++ gr_system_salt = kmalloc(GR_SALT_LEN, GFP_KERNEL); |
26675 |
++ gr_system_sum = kmalloc(GR_SHA_LEN, GFP_KERNEL); |
26676 |
++ |
26677 |
++ if (!gr_usermode || !gr_system_salt || !gr_system_sum) { |
26678 |
++ panic("Unable to allocate grsecurity authentication structure"); |
26679 |
++ return; |
26680 |
++ } |
26681 |
++ |
26682 |
++#if !defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_SYSCTL_ON) |
26683 |
++#ifndef CONFIG_GRKERNSEC_SYSCTL |
26684 |
++ grsec_lock = 1; |
26685 |
++#endif |
26686 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL |
26687 |
++ grsec_enable_audit_textrel = 1; |
26688 |
++#endif |
26689 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP |
26690 |
++ grsec_enable_group = 1; |
26691 |
++ grsec_audit_gid = CONFIG_GRKERNSEC_AUDIT_GID; |
26692 |
++#endif |
26693 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR |
26694 |
++ grsec_enable_chdir = 1; |
26695 |
++#endif |
26696 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC |
26697 |
++ grsec_enable_audit_ipc = 1; |
26698 |
++#endif |
26699 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT |
26700 |
++ grsec_enable_mount = 1; |
26701 |
++#endif |
26702 |
++#ifdef CONFIG_GRKERNSEC_LINK |
26703 |
++ grsec_enable_link = 1; |
26704 |
++#endif |
26705 |
++#ifdef CONFIG_GRKERNSEC_DMESG |
26706 |
++ grsec_enable_dmesg = 1; |
26707 |
++#endif |
26708 |
++#ifdef CONFIG_GRKERNSEC_FIFO |
26709 |
++ grsec_enable_fifo = 1; |
26710 |
++#endif |
26711 |
++#ifdef CONFIG_GRKERNSEC_EXECVE |
26712 |
++ grsec_enable_execve = 1; |
26713 |
++#endif |
26714 |
++#ifdef CONFIG_GRKERNSEC_EXECLOG |
26715 |
++ grsec_enable_execlog = 1; |
26716 |
++#endif |
26717 |
++#ifdef CONFIG_GRKERNSEC_SIGNAL |
26718 |
++ grsec_enable_signal = 1; |
26719 |
++#endif |
26720 |
++#ifdef CONFIG_GRKERNSEC_FORKFAIL |
26721 |
++ grsec_enable_forkfail = 1; |
26722 |
++#endif |
26723 |
++#ifdef CONFIG_GRKERNSEC_TIME |
26724 |
++ grsec_enable_time = 1; |
26725 |
++#endif |
26726 |
++#ifdef CONFIG_GRKERNSEC_RESLOG |
26727 |
++ grsec_resource_logging = 1; |
26728 |
++#endif |
26729 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK |
26730 |
++ grsec_enable_chroot_findtask = 1; |
26731 |
++#endif |
26732 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX |
26733 |
++ grsec_enable_chroot_unix = 1; |
26734 |
++#endif |
26735 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT |
26736 |
++ grsec_enable_chroot_mount = 1; |
26737 |
++#endif |
26738 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR |
26739 |
++ grsec_enable_chroot_fchdir = 1; |
26740 |
++#endif |
26741 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT |
26742 |
++ grsec_enable_chroot_shmat = 1; |
26743 |
++#endif |
26744 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE |
26745 |
++ grsec_enable_chroot_double = 1; |
26746 |
++#endif |
26747 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT |
26748 |
++ grsec_enable_chroot_pivot = 1; |
26749 |
++#endif |
26750 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR |
26751 |
++ grsec_enable_chroot_chdir = 1; |
26752 |
++#endif |
26753 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD |
26754 |
++ grsec_enable_chroot_chmod = 1; |
26755 |
++#endif |
26756 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD |
26757 |
++ grsec_enable_chroot_mknod = 1; |
26758 |
++#endif |
26759 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE |
26760 |
++ grsec_enable_chroot_nice = 1; |
26761 |
++#endif |
26762 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG |
26763 |
++ grsec_enable_chroot_execlog = 1; |
26764 |
++#endif |
26765 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS |
26766 |
++ grsec_enable_chroot_caps = 1; |
26767 |
++#endif |
26768 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL |
26769 |
++ grsec_enable_chroot_sysctl = 1; |
26770 |
++#endif |
26771 |
++#ifdef CONFIG_GRKERNSEC_TPE |
26772 |
++ grsec_enable_tpe = 1; |
26773 |
++ grsec_tpe_gid = CONFIG_GRKERNSEC_TPE_GID; |
26774 |
++#ifdef CONFIG_GRKERNSEC_TPE_ALL |
26775 |
++ grsec_enable_tpe_all = 1; |
26776 |
++#endif |
26777 |
++#endif |
26778 |
++#ifdef CONFIG_GRKERNSEC_SOCKET_ALL |
26779 |
++ grsec_enable_socket_all = 1; |
26780 |
++ grsec_socket_all_gid = CONFIG_GRKERNSEC_SOCKET_ALL_GID; |
26781 |
++#endif |
26782 |
++#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT |
26783 |
++ grsec_enable_socket_client = 1; |
26784 |
++ grsec_socket_client_gid = CONFIG_GRKERNSEC_SOCKET_CLIENT_GID; |
26785 |
++#endif |
26786 |
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER |
26787 |
++ grsec_enable_socket_server = 1; |
26788 |
++ grsec_socket_server_gid = CONFIG_GRKERNSEC_SOCKET_SERVER_GID; |
26789 |
++#endif |
26790 |
++#endif |
26791 |
++ |
26792 |
++ return; |
26793 |
++} |
26794 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_ipc.c linux-2.6.28.8/grsecurity/grsec_ipc.c |
26795 |
+--- linux-2.6.28.8/grsecurity/grsec_ipc.c 1969-12-31 19:00:00.000000000 -0500 |
26796 |
++++ linux-2.6.28.8/grsecurity/grsec_ipc.c 2009-02-21 09:37:49.000000000 -0500 |
26797 |
+@@ -0,0 +1,81 @@ |
26798 |
++#include <linux/kernel.h> |
26799 |
++#include <linux/sched.h> |
26800 |
++#include <linux/types.h> |
26801 |
++#include <linux/ipc.h> |
26802 |
++#include <linux/grsecurity.h> |
26803 |
++#include <linux/grinternal.h> |
26804 |
++ |
26805 |
++void |
26806 |
++gr_log_msgget(const int ret, const int msgflg) |
26807 |
++{ |
26808 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC |
26809 |
++ if (((grsec_enable_group && in_group_p(grsec_audit_gid) && |
26810 |
++ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc && |
26811 |
++ !grsec_enable_group)) && (ret >= 0) |
26812 |
++ && (msgflg & IPC_CREAT)) |
26813 |
++ gr_log_noargs(GR_DO_AUDIT, GR_MSGQ_AUDIT_MSG); |
26814 |
++#endif |
26815 |
++ return; |
26816 |
++} |
26817 |
++ |
26818 |
++void |
26819 |
++gr_log_msgrm(const uid_t uid, const uid_t cuid) |
26820 |
++{ |
26821 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC |
26822 |
++ if ((grsec_enable_group && in_group_p(grsec_audit_gid) && |
26823 |
++ grsec_enable_audit_ipc) || |
26824 |
++ (grsec_enable_audit_ipc && !grsec_enable_group)) |
26825 |
++ gr_log_int_int(GR_DO_AUDIT, GR_MSGQR_AUDIT_MSG, uid, cuid); |
26826 |
++#endif |
26827 |
++ return; |
26828 |
++} |
26829 |
++ |
26830 |
++void |
26831 |
++gr_log_semget(const int err, const int semflg) |
26832 |
++{ |
26833 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC |
26834 |
++ if (((grsec_enable_group && in_group_p(grsec_audit_gid) && |
26835 |
++ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc && |
26836 |
++ !grsec_enable_group)) && (err >= 0) |
26837 |
++ && (semflg & IPC_CREAT)) |
26838 |
++ gr_log_noargs(GR_DO_AUDIT, GR_SEM_AUDIT_MSG); |
26839 |
++#endif |
26840 |
++ return; |
26841 |
++} |
26842 |
++ |
26843 |
++void |
26844 |
++gr_log_semrm(const uid_t uid, const uid_t cuid) |
26845 |
++{ |
26846 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC |
26847 |
++ if ((grsec_enable_group && in_group_p(grsec_audit_gid) && |
26848 |
++ grsec_enable_audit_ipc) || |
26849 |
++ (grsec_enable_audit_ipc && !grsec_enable_group)) |
26850 |
++ gr_log_int_int(GR_DO_AUDIT, GR_SEMR_AUDIT_MSG, uid, cuid); |
26851 |
++#endif |
26852 |
++ return; |
26853 |
++} |
26854 |
++ |
26855 |
++void |
26856 |
++gr_log_shmget(const int err, const int shmflg, const size_t size) |
26857 |
++{ |
26858 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC |
26859 |
++ if (((grsec_enable_group && in_group_p(grsec_audit_gid) && |
26860 |
++ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc && |
26861 |
++ !grsec_enable_group)) && (err >= 0) |
26862 |
++ && (shmflg & IPC_CREAT)) |
26863 |
++ gr_log_int(GR_DO_AUDIT, GR_SHM_AUDIT_MSG, size); |
26864 |
++#endif |
26865 |
++ return; |
26866 |
++} |
26867 |
++ |
26868 |
++void |
26869 |
++gr_log_shmrm(const uid_t uid, const uid_t cuid) |
26870 |
++{ |
26871 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC |
26872 |
++ if ((grsec_enable_group && in_group_p(grsec_audit_gid) && |
26873 |
++ grsec_enable_audit_ipc) || |
26874 |
++ (grsec_enable_audit_ipc && !grsec_enable_group)) |
26875 |
++ gr_log_int_int(GR_DO_AUDIT, GR_SHMR_AUDIT_MSG, uid, cuid); |
26876 |
++#endif |
26877 |
++ return; |
26878 |
++} |
26879 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_link.c linux-2.6.28.8/grsecurity/grsec_link.c |
26880 |
+--- linux-2.6.28.8/grsecurity/grsec_link.c 1969-12-31 19:00:00.000000000 -0500 |
26881 |
++++ linux-2.6.28.8/grsecurity/grsec_link.c 2009-02-21 09:37:49.000000000 -0500 |
26882 |
+@@ -0,0 +1,39 @@ |
26883 |
++#include <linux/kernel.h> |
26884 |
++#include <linux/sched.h> |
26885 |
++#include <linux/fs.h> |
26886 |
++#include <linux/file.h> |
26887 |
++#include <linux/grinternal.h> |
26888 |
++ |
26889 |
++int |
26890 |
++gr_handle_follow_link(const struct inode *parent, |
26891 |
++ const struct inode *inode, |
26892 |
++ const struct dentry *dentry, const struct vfsmount *mnt) |
26893 |
++{ |
26894 |
++#ifdef CONFIG_GRKERNSEC_LINK |
26895 |
++ if (grsec_enable_link && S_ISLNK(inode->i_mode) && |
26896 |
++ (parent->i_mode & S_ISVTX) && (parent->i_uid != inode->i_uid) && |
26897 |
++ (parent->i_mode & S_IWOTH) && (current->fsuid != inode->i_uid)) { |
26898 |
++ gr_log_fs_int2(GR_DONT_AUDIT, GR_SYMLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid); |
26899 |
++ return -EACCES; |
26900 |
++ } |
26901 |
++#endif |
26902 |
++ return 0; |
26903 |
++} |
26904 |
++ |
26905 |
++int |
26906 |
++gr_handle_hardlink(const struct dentry *dentry, |
26907 |
++ const struct vfsmount *mnt, |
26908 |
++ struct inode *inode, const int mode, const char *to) |
26909 |
++{ |
26910 |
++#ifdef CONFIG_GRKERNSEC_LINK |
26911 |
++ if (grsec_enable_link && current->fsuid != inode->i_uid && |
26912 |
++ (!S_ISREG(mode) || (mode & S_ISUID) || |
26913 |
++ ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) || |
26914 |
++ (generic_permission(inode, MAY_READ | MAY_WRITE, NULL))) && |
26915 |
++ !capable(CAP_FOWNER) && current->uid) { |
26916 |
++ gr_log_fs_int2_str(GR_DONT_AUDIT, GR_HARDLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid, to); |
26917 |
++ return -EPERM; |
26918 |
++ } |
26919 |
++#endif |
26920 |
++ return 0; |
26921 |
++} |
26922 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_log.c linux-2.6.28.8/grsecurity/grsec_log.c |
26923 |
+--- linux-2.6.28.8/grsecurity/grsec_log.c 1969-12-31 19:00:00.000000000 -0500 |
26924 |
++++ linux-2.6.28.8/grsecurity/grsec_log.c 2009-02-21 09:37:49.000000000 -0500 |
26925 |
+@@ -0,0 +1,269 @@ |
26926 |
++#include <linux/kernel.h> |
26927 |
++#include <linux/sched.h> |
26928 |
++#include <linux/file.h> |
26929 |
++#include <linux/tty.h> |
26930 |
++#include <linux/fs.h> |
26931 |
++#include <linux/grinternal.h> |
26932 |
++ |
26933 |
++#define BEGIN_LOCKS(x) \ |
26934 |
++ read_lock(&tasklist_lock); \ |
26935 |
++ read_lock(&grsec_exec_file_lock); \ |
26936 |
++ if (x != GR_DO_AUDIT) \ |
26937 |
++ spin_lock(&grsec_alert_lock); \ |
26938 |
++ else \ |
26939 |
++ spin_lock(&grsec_audit_lock) |
26940 |
++ |
26941 |
++#define END_LOCKS(x) \ |
26942 |
++ if (x != GR_DO_AUDIT) \ |
26943 |
++ spin_unlock(&grsec_alert_lock); \ |
26944 |
++ else \ |
26945 |
++ spin_unlock(&grsec_audit_lock); \ |
26946 |
++ read_unlock(&grsec_exec_file_lock); \ |
26947 |
++ read_unlock(&tasklist_lock); \ |
26948 |
++ if (x == GR_DONT_AUDIT) \ |
26949 |
++ gr_handle_alertkill(current) |
26950 |
++ |
26951 |
++enum { |
26952 |
++ FLOODING, |
26953 |
++ NO_FLOODING |
26954 |
++}; |
26955 |
++ |
26956 |
++extern char *gr_alert_log_fmt; |
26957 |
++extern char *gr_audit_log_fmt; |
26958 |
++extern char *gr_alert_log_buf; |
26959 |
++extern char *gr_audit_log_buf; |
26960 |
++ |
26961 |
++static int gr_log_start(int audit) |
26962 |
++{ |
26963 |
++ char *loglevel = (audit == GR_DO_AUDIT) ? KERN_INFO : KERN_ALERT; |
26964 |
++ char *fmt = (audit == GR_DO_AUDIT) ? gr_audit_log_fmt : gr_alert_log_fmt; |
26965 |
++ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf; |
26966 |
++ |
26967 |
++ if (audit == GR_DO_AUDIT) |
26968 |
++ goto set_fmt; |
26969 |
++ |
26970 |
++ if (!grsec_alert_wtime || jiffies - grsec_alert_wtime > CONFIG_GRKERNSEC_FLOODTIME * HZ) { |
26971 |
++ grsec_alert_wtime = jiffies; |
26972 |
++ grsec_alert_fyet = 0; |
26973 |
++ } else if ((jiffies - grsec_alert_wtime < CONFIG_GRKERNSEC_FLOODTIME * HZ) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) { |
26974 |
++ grsec_alert_fyet++; |
26975 |
++ } else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) { |
26976 |
++ grsec_alert_wtime = jiffies; |
26977 |
++ grsec_alert_fyet++; |
26978 |
++ printk(KERN_ALERT "grsec: more alerts, logging disabled for %d seconds\n", CONFIG_GRKERNSEC_FLOODTIME); |
26979 |
++ return FLOODING; |
26980 |
++ } else return FLOODING; |
26981 |
++ |
26982 |
++set_fmt: |
26983 |
++ memset(buf, 0, PAGE_SIZE); |
26984 |
++ if (current->signal->curr_ip && gr_acl_is_enabled()) { |
26985 |
++ sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: (%.64s:%c:%.950s) "); |
26986 |
++ snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip), current->role->rolename, gr_roletype_to_char(), current->acl->filename); |
26987 |
++ } else if (current->signal->curr_ip) { |
26988 |
++ sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: "); |
26989 |
++ snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip)); |
26990 |
++ } else if (gr_acl_is_enabled()) { |
26991 |
++ sprintf(fmt, "%s%s", loglevel, "grsec: (%.64s:%c:%.950s) "); |
26992 |
++ snprintf(buf, PAGE_SIZE - 1, fmt, current->role->rolename, gr_roletype_to_char(), current->acl->filename); |
26993 |
++ } else { |
26994 |
++ sprintf(fmt, "%s%s", loglevel, "grsec: "); |
26995 |
++ strcpy(buf, fmt); |
26996 |
++ } |
26997 |
++ |
26998 |
++ return NO_FLOODING; |
26999 |
++} |
27000 |
++ |
27001 |
++static void gr_log_middle(int audit, const char *msg, va_list ap) |
27002 |
++{ |
27003 |
++ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf; |
27004 |
++ unsigned int len = strlen(buf); |
27005 |
++ |
27006 |
++ vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap); |
27007 |
++ |
27008 |
++ return; |
27009 |
++} |
27010 |
++ |
27011 |
++static void gr_log_middle_varargs(int audit, const char *msg, ...) |
27012 |
++{ |
27013 |
++ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf; |
27014 |
++ unsigned int len = strlen(buf); |
27015 |
++ va_list ap; |
27016 |
++ |
27017 |
++ va_start(ap, msg); |
27018 |
++ vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap); |
27019 |
++ va_end(ap); |
27020 |
++ |
27021 |
++ return; |
27022 |
++} |
27023 |
++ |
27024 |
++static void gr_log_end(int audit) |
27025 |
++{ |
27026 |
++ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf; |
27027 |
++ unsigned int len = strlen(buf); |
27028 |
++ |
27029 |
++ snprintf(buf + len, PAGE_SIZE - len - 1, DEFAULTSECMSG, DEFAULTSECARGS(current)); |
27030 |
++ printk("%s\n", buf); |
27031 |
++ |
27032 |
++ return; |
27033 |
++} |
27034 |
++ |
27035 |
++void gr_log_varargs(int audit, const char *msg, int argtypes, ...) |
27036 |
++{ |
27037 |
++ int logtype; |
27038 |
++ char *result = (audit == GR_DO_AUDIT) ? "successful" : "denied"; |
27039 |
++ char *str1, *str2, *str3; |
27040 |
++ int num1, num2; |
27041 |
++ unsigned long ulong1, ulong2; |
27042 |
++ struct dentry *dentry; |
27043 |
++ struct vfsmount *mnt; |
27044 |
++ struct file *file; |
27045 |
++ struct task_struct *task; |
27046 |
++ va_list ap; |
27047 |
++ |
27048 |
++ BEGIN_LOCKS(audit); |
27049 |
++ logtype = gr_log_start(audit); |
27050 |
++ if (logtype == FLOODING) { |
27051 |
++ END_LOCKS(audit); |
27052 |
++ return; |
27053 |
++ } |
27054 |
++ va_start(ap, argtypes); |
27055 |
++ switch (argtypes) { |
27056 |
++ case GR_TTYSNIFF: |
27057 |
++ task = va_arg(ap, struct task_struct *); |
27058 |
++ gr_log_middle_varargs(audit, msg, NIPQUAD(task->signal->curr_ip), gr_task_fullpath0(task), task->comm, task->pid, gr_parent_task_fullpath0(task), task->parent->comm, task->parent->pid); |
27059 |
++ break; |
27060 |
++ case GR_SYSCTL_HIDDEN: |
27061 |
++ str1 = va_arg(ap, char *); |
27062 |
++ gr_log_middle_varargs(audit, msg, result, str1); |
27063 |
++ break; |
27064 |
++ case GR_RBAC: |
27065 |
++ dentry = va_arg(ap, struct dentry *); |
27066 |
++ mnt = va_arg(ap, struct vfsmount *); |
27067 |
++ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt)); |
27068 |
++ break; |
27069 |
++ case GR_RBAC_STR: |
27070 |
++ dentry = va_arg(ap, struct dentry *); |
27071 |
++ mnt = va_arg(ap, struct vfsmount *); |
27072 |
++ str1 = va_arg(ap, char *); |
27073 |
++ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1); |
27074 |
++ break; |
27075 |
++ case GR_STR_RBAC: |
27076 |
++ str1 = va_arg(ap, char *); |
27077 |
++ dentry = va_arg(ap, struct dentry *); |
27078 |
++ mnt = va_arg(ap, struct vfsmount *); |
27079 |
++ gr_log_middle_varargs(audit, msg, result, str1, gr_to_filename(dentry, mnt)); |
27080 |
++ break; |
27081 |
++ case GR_RBAC_MODE2: |
27082 |
++ dentry = va_arg(ap, struct dentry *); |
27083 |
++ mnt = va_arg(ap, struct vfsmount *); |
27084 |
++ str1 = va_arg(ap, char *); |
27085 |
++ str2 = va_arg(ap, char *); |
27086 |
++ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2); |
27087 |
++ break; |
27088 |
++ case GR_RBAC_MODE3: |
27089 |
++ dentry = va_arg(ap, struct dentry *); |
27090 |
++ mnt = va_arg(ap, struct vfsmount *); |
27091 |
++ str1 = va_arg(ap, char *); |
27092 |
++ str2 = va_arg(ap, char *); |
27093 |
++ str3 = va_arg(ap, char *); |
27094 |
++ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2, str3); |
27095 |
++ break; |
27096 |
++ case GR_FILENAME: |
27097 |
++ dentry = va_arg(ap, struct dentry *); |
27098 |
++ mnt = va_arg(ap, struct vfsmount *); |
27099 |
++ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt)); |
27100 |
++ break; |
27101 |
++ case GR_STR_FILENAME: |
27102 |
++ str1 = va_arg(ap, char *); |
27103 |
++ dentry = va_arg(ap, struct dentry *); |
27104 |
++ mnt = va_arg(ap, struct vfsmount *); |
27105 |
++ gr_log_middle_varargs(audit, msg, str1, gr_to_filename(dentry, mnt)); |
27106 |
++ break; |
27107 |
++ case GR_FILENAME_STR: |
27108 |
++ dentry = va_arg(ap, struct dentry *); |
27109 |
++ mnt = va_arg(ap, struct vfsmount *); |
27110 |
++ str1 = va_arg(ap, char *); |
27111 |
++ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), str1); |
27112 |
++ break; |
27113 |
++ case GR_FILENAME_TWO_INT: |
27114 |
++ dentry = va_arg(ap, struct dentry *); |
27115 |
++ mnt = va_arg(ap, struct vfsmount *); |
27116 |
++ num1 = va_arg(ap, int); |
27117 |
++ num2 = va_arg(ap, int); |
27118 |
++ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2); |
27119 |
++ break; |
27120 |
++ case GR_FILENAME_TWO_INT_STR: |
27121 |
++ dentry = va_arg(ap, struct dentry *); |
27122 |
++ mnt = va_arg(ap, struct vfsmount *); |
27123 |
++ num1 = va_arg(ap, int); |
27124 |
++ num2 = va_arg(ap, int); |
27125 |
++ str1 = va_arg(ap, char *); |
27126 |
++ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2, str1); |
27127 |
++ break; |
27128 |
++ case GR_TEXTREL: |
27129 |
++ file = va_arg(ap, struct file *); |
27130 |
++ ulong1 = va_arg(ap, unsigned long); |
27131 |
++ ulong2 = va_arg(ap, unsigned long); |
27132 |
++ gr_log_middle_varargs(audit, msg, file ? gr_to_filename(file->f_path.dentry, file->f_path.mnt) : "<anonymous mapping>", ulong1, ulong2); |
27133 |
++ break; |
27134 |
++ case GR_PTRACE: |
27135 |
++ task = va_arg(ap, struct task_struct *); |
27136 |
++ gr_log_middle_varargs(audit, msg, task->exec_file ? gr_to_filename(task->exec_file->f_path.dentry, task->exec_file->f_path.mnt) : "(none)", task->comm, task->pid); |
27137 |
++ break; |
27138 |
++ case GR_RESOURCE: |
27139 |
++ task = va_arg(ap, struct task_struct *); |
27140 |
++ ulong1 = va_arg(ap, unsigned long); |
27141 |
++ str1 = va_arg(ap, char *); |
27142 |
++ ulong2 = va_arg(ap, unsigned long); |
27143 |
++ gr_log_middle_varargs(audit, msg, ulong1, str1, ulong2, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid); |
27144 |
++ break; |
27145 |
++ case GR_CAP: |
27146 |
++ task = va_arg(ap, struct task_struct *); |
27147 |
++ str1 = va_arg(ap, char *); |
27148 |
++ gr_log_middle_varargs(audit, msg, str1, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid); |
27149 |
++ break; |
27150 |
++ case GR_SIG: |
27151 |
++ task = va_arg(ap, struct task_struct *); |
27152 |
++ num1 = va_arg(ap, int); |
27153 |
++ gr_log_middle_varargs(audit, msg, num1, gr_task_fullpath0(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath0(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid); |
27154 |
++ break; |
27155 |
++ case GR_CRASH1: |
27156 |
++ task = va_arg(ap, struct task_struct *); |
27157 |
++ ulong1 = va_arg(ap, unsigned long); |
27158 |
++ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid, task->uid, ulong1); |
27159 |
++ break; |
27160 |
++ case GR_CRASH2: |
27161 |
++ task = va_arg(ap, struct task_struct *); |
27162 |
++ ulong1 = va_arg(ap, unsigned long); |
27163 |
++ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, task->uid, task->euid, task->gid, task->egid, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid, ulong1); |
27164 |
++ break; |
27165 |
++ case GR_PSACCT: |
27166 |
++ { |
27167 |
++ unsigned int wday, cday; |
27168 |
++ __u8 whr, chr; |
27169 |
++ __u8 wmin, cmin; |
27170 |
++ __u8 wsec, csec; |
27171 |
++ char cur_tty[64] = { 0 }; |
27172 |
++ char parent_tty[64] = { 0 }; |
27173 |
++ |
27174 |
++ task = va_arg(ap, struct task_struct *); |
27175 |
++ wday = va_arg(ap, unsigned int); |
27176 |
++ cday = va_arg(ap, unsigned int); |
27177 |
++ whr = va_arg(ap, int); |
27178 |
++ chr = va_arg(ap, int); |
27179 |
++ wmin = va_arg(ap, int); |
27180 |
++ cmin = va_arg(ap, int); |
27181 |
++ wsec = va_arg(ap, int); |
27182 |
++ csec = va_arg(ap, int); |
27183 |
++ ulong1 = va_arg(ap, unsigned long); |
27184 |
++ |
27185 |
++ gr_log_middle_varargs(audit, msg, gr_task_fullpath(task), task->comm, task->pid, NIPQUAD(task->signal->curr_ip), tty_name(task->signal->tty, cur_tty), task->uid, task->euid, task->gid, task->egid, wday, whr, wmin, wsec, cday, chr, cmin, csec, (task->flags & PF_SIGNALED) ? "killed by signal" : "exited", ulong1, gr_parent_task_fullpath(task), task->parent->comm, task->parent->pid, NIPQUAD(task->parent->signal->curr_ip), tty_name(task->parent->signal->tty, parent_tty), task->parent->uid, task->parent->euid, task->parent->gid, task->parent->egid); |
27186 |
++ } |
27187 |
++ break; |
27188 |
++ default: |
27189 |
++ gr_log_middle(audit, msg, ap); |
27190 |
++ } |
27191 |
++ va_end(ap); |
27192 |
++ gr_log_end(audit); |
27193 |
++ END_LOCKS(audit); |
27194 |
++} |
27195 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_mem.c linux-2.6.28.8/grsecurity/grsec_mem.c |
27196 |
+--- linux-2.6.28.8/grsecurity/grsec_mem.c 1969-12-31 19:00:00.000000000 -0500 |
27197 |
++++ linux-2.6.28.8/grsecurity/grsec_mem.c 2009-02-21 09:37:49.000000000 -0500 |
27198 |
+@@ -0,0 +1,71 @@ |
27199 |
++#include <linux/kernel.h> |
27200 |
++#include <linux/sched.h> |
27201 |
++#include <linux/mm.h> |
27202 |
++#include <linux/mman.h> |
27203 |
++#include <linux/grinternal.h> |
27204 |
++ |
27205 |
++void |
27206 |
++gr_handle_ioperm(void) |
27207 |
++{ |
27208 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_IOPERM_MSG); |
27209 |
++ return; |
27210 |
++} |
27211 |
++ |
27212 |
++void |
27213 |
++gr_handle_iopl(void) |
27214 |
++{ |
27215 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_IOPL_MSG); |
27216 |
++ return; |
27217 |
++} |
27218 |
++ |
27219 |
++void |
27220 |
++gr_handle_mem_write(void) |
27221 |
++{ |
27222 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_WRITE_MSG); |
27223 |
++ return; |
27224 |
++} |
27225 |
++ |
27226 |
++void |
27227 |
++gr_handle_kmem_write(void) |
27228 |
++{ |
27229 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_KMEM_MSG); |
27230 |
++ return; |
27231 |
++} |
27232 |
++ |
27233 |
++void |
27234 |
++gr_handle_open_port(void) |
27235 |
++{ |
27236 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_PORT_OPEN_MSG); |
27237 |
++ return; |
27238 |
++} |
27239 |
++ |
27240 |
++int |
27241 |
++gr_handle_mem_mmap(const unsigned long offset, struct vm_area_struct *vma) |
27242 |
++{ |
27243 |
++ unsigned long start, end; |
27244 |
++ |
27245 |
++ start = offset; |
27246 |
++ end = start + vma->vm_end - vma->vm_start; |
27247 |
++ |
27248 |
++ if (start > end) { |
27249 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_MMAP_MSG); |
27250 |
++ return -EPERM; |
27251 |
++ } |
27252 |
++ |
27253 |
++ /* allowed ranges : ISA I/O BIOS */ |
27254 |
++ if ((start >= __pa(high_memory)) |
27255 |
++#ifdef CONFIG_X86 |
27256 |
++ || (start >= 0x000a0000 && end <= 0x00100000) |
27257 |
++ || (start >= 0x00000000 && end <= 0x00001000) |
27258 |
++#endif |
27259 |
++ ) |
27260 |
++ return 0; |
27261 |
++ |
27262 |
++ if (vma->vm_flags & VM_WRITE) { |
27263 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_MMAP_MSG); |
27264 |
++ return -EPERM; |
27265 |
++ } else |
27266 |
++ vma->vm_flags &= ~VM_MAYWRITE; |
27267 |
++ |
27268 |
++ return 0; |
27269 |
++} |
27270 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_mount.c linux-2.6.28.8/grsecurity/grsec_mount.c |
27271 |
+--- linux-2.6.28.8/grsecurity/grsec_mount.c 1969-12-31 19:00:00.000000000 -0500 |
27272 |
++++ linux-2.6.28.8/grsecurity/grsec_mount.c 2009-02-21 09:37:49.000000000 -0500 |
27273 |
+@@ -0,0 +1,34 @@ |
27274 |
++#include <linux/kernel.h> |
27275 |
++#include <linux/sched.h> |
27276 |
++#include <linux/grsecurity.h> |
27277 |
++#include <linux/grinternal.h> |
27278 |
++ |
27279 |
++void |
27280 |
++gr_log_remount(const char *devname, const int retval) |
27281 |
++{ |
27282 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT |
27283 |
++ if (grsec_enable_mount && (retval >= 0)) |
27284 |
++ gr_log_str(GR_DO_AUDIT, GR_REMOUNT_AUDIT_MSG, devname ? devname : "none"); |
27285 |
++#endif |
27286 |
++ return; |
27287 |
++} |
27288 |
++ |
27289 |
++void |
27290 |
++gr_log_unmount(const char *devname, const int retval) |
27291 |
++{ |
27292 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT |
27293 |
++ if (grsec_enable_mount && (retval >= 0)) |
27294 |
++ gr_log_str(GR_DO_AUDIT, GR_UNMOUNT_AUDIT_MSG, devname ? devname : "none"); |
27295 |
++#endif |
27296 |
++ return; |
27297 |
++} |
27298 |
++ |
27299 |
++void |
27300 |
++gr_log_mount(const char *from, const char *to, const int retval) |
27301 |
++{ |
27302 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT |
27303 |
++ if (grsec_enable_mount && (retval >= 0)) |
27304 |
++ gr_log_str_str(GR_DO_AUDIT, GR_MOUNT_AUDIT_MSG, from, to); |
27305 |
++#endif |
27306 |
++ return; |
27307 |
++} |
27308 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_sig.c linux-2.6.28.8/grsecurity/grsec_sig.c |
27309 |
+--- linux-2.6.28.8/grsecurity/grsec_sig.c 1969-12-31 19:00:00.000000000 -0500 |
27310 |
++++ linux-2.6.28.8/grsecurity/grsec_sig.c 2009-02-21 09:37:49.000000000 -0500 |
27311 |
+@@ -0,0 +1,58 @@ |
27312 |
++#include <linux/kernel.h> |
27313 |
++#include <linux/sched.h> |
27314 |
++#include <linux/delay.h> |
27315 |
++#include <linux/grsecurity.h> |
27316 |
++#include <linux/grinternal.h> |
27317 |
++ |
27318 |
++void |
27319 |
++gr_log_signal(const int sig, const struct task_struct *t) |
27320 |
++{ |
27321 |
++#ifdef CONFIG_GRKERNSEC_SIGNAL |
27322 |
++ if (grsec_enable_signal && ((sig == SIGSEGV) || (sig == SIGILL) || |
27323 |
++ (sig == SIGABRT) || (sig == SIGBUS))) { |
27324 |
++ if (t->pid == current->pid) { |
27325 |
++ gr_log_int(GR_DONT_AUDIT_GOOD, GR_UNISIGLOG_MSG, sig); |
27326 |
++ } else { |
27327 |
++ gr_log_sig(GR_DONT_AUDIT_GOOD, GR_DUALSIGLOG_MSG, t, sig); |
27328 |
++ } |
27329 |
++ } |
27330 |
++#endif |
27331 |
++ return; |
27332 |
++} |
27333 |
++ |
27334 |
++int |
27335 |
++gr_handle_signal(const struct task_struct *p, const int sig) |
27336 |
++{ |
27337 |
++#ifdef CONFIG_GRKERNSEC |
27338 |
++ if (current->pid > 1 && gr_check_protected_task(p)) { |
27339 |
++ gr_log_sig(GR_DONT_AUDIT, GR_SIG_ACL_MSG, p, sig); |
27340 |
++ return -EPERM; |
27341 |
++ } else if (gr_pid_is_chrooted((struct task_struct *)p)) { |
27342 |
++ return -EPERM; |
27343 |
++ } |
27344 |
++#endif |
27345 |
++ return 0; |
27346 |
++} |
27347 |
++ |
27348 |
++void gr_handle_brute_attach(struct task_struct *p) |
27349 |
++{ |
27350 |
++#ifdef CONFIG_GRKERNSEC_BRUTE |
27351 |
++ read_lock(&tasklist_lock); |
27352 |
++ read_lock(&grsec_exec_file_lock); |
27353 |
++ if (p->parent && p->parent->exec_file == p->exec_file) |
27354 |
++ p->parent->brute = 1; |
27355 |
++ read_unlock(&grsec_exec_file_lock); |
27356 |
++ read_unlock(&tasklist_lock); |
27357 |
++#endif |
27358 |
++ return; |
27359 |
++} |
27360 |
++ |
27361 |
++void gr_handle_brute_check(void) |
27362 |
++{ |
27363 |
++#ifdef CONFIG_GRKERNSEC_BRUTE |
27364 |
++ if (current->brute) |
27365 |
++ msleep(30 * 1000); |
27366 |
++#endif |
27367 |
++ return; |
27368 |
++} |
27369 |
++ |
27370 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_sock.c linux-2.6.28.8/grsecurity/grsec_sock.c |
27371 |
+--- linux-2.6.28.8/grsecurity/grsec_sock.c 1969-12-31 19:00:00.000000000 -0500 |
27372 |
++++ linux-2.6.28.8/grsecurity/grsec_sock.c 2009-02-21 09:37:49.000000000 -0500 |
27373 |
+@@ -0,0 +1,274 @@ |
27374 |
++#include <linux/kernel.h> |
27375 |
++#include <linux/module.h> |
27376 |
++#include <linux/sched.h> |
27377 |
++#include <linux/file.h> |
27378 |
++#include <linux/net.h> |
27379 |
++#include <linux/in.h> |
27380 |
++#include <linux/ip.h> |
27381 |
++#include <net/sock.h> |
27382 |
++#include <net/inet_sock.h> |
27383 |
++#include <linux/grsecurity.h> |
27384 |
++#include <linux/grinternal.h> |
27385 |
++#include <linux/gracl.h> |
27386 |
++ |
27387 |
++#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE) |
27388 |
++extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif); |
27389 |
++EXPORT_SYMBOL(udp_v4_lookup); |
27390 |
++#endif |
27391 |
++ |
27392 |
++kernel_cap_t gr_cap_rtnetlink(struct sock *sock); |
27393 |
++EXPORT_SYMBOL(gr_cap_rtnetlink); |
27394 |
++ |
27395 |
++extern int gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb); |
27396 |
++extern int gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr); |
27397 |
++ |
27398 |
++EXPORT_SYMBOL(gr_search_udp_recvmsg); |
27399 |
++EXPORT_SYMBOL(gr_search_udp_sendmsg); |
27400 |
++ |
27401 |
++#ifdef CONFIG_UNIX_MODULE |
27402 |
++EXPORT_SYMBOL(gr_acl_handle_unix); |
27403 |
++EXPORT_SYMBOL(gr_acl_handle_mknod); |
27404 |
++EXPORT_SYMBOL(gr_handle_chroot_unix); |
27405 |
++EXPORT_SYMBOL(gr_handle_create); |
27406 |
++#endif |
27407 |
++ |
27408 |
++#ifdef CONFIG_GRKERNSEC |
27409 |
++#define gr_conn_table_size 32749 |
27410 |
++struct conn_table_entry { |
27411 |
++ struct conn_table_entry *next; |
27412 |
++ struct signal_struct *sig; |
27413 |
++}; |
27414 |
++ |
27415 |
++struct conn_table_entry *gr_conn_table[gr_conn_table_size]; |
27416 |
++DEFINE_SPINLOCK(gr_conn_table_lock); |
27417 |
++ |
27418 |
++extern const char * gr_socktype_to_name(unsigned char type); |
27419 |
++extern const char * gr_proto_to_name(unsigned char proto); |
27420 |
++ |
27421 |
++static __inline__ int |
27422 |
++conn_hash(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, unsigned int size) |
27423 |
++{ |
27424 |
++ return ((daddr + saddr + (sport << 8) + (dport << 16)) % size); |
27425 |
++} |
27426 |
++ |
27427 |
++static __inline__ int |
27428 |
++conn_match(const struct signal_struct *sig, __u32 saddr, __u32 daddr, |
27429 |
++ __u16 sport, __u16 dport) |
27430 |
++{ |
27431 |
++ if (unlikely(sig->gr_saddr == saddr && sig->gr_daddr == daddr && |
27432 |
++ sig->gr_sport == sport && sig->gr_dport == dport)) |
27433 |
++ return 1; |
27434 |
++ else |
27435 |
++ return 0; |
27436 |
++} |
27437 |
++ |
27438 |
++static void gr_add_to_task_ip_table_nolock(struct signal_struct *sig, struct conn_table_entry *newent) |
27439 |
++{ |
27440 |
++ struct conn_table_entry **match; |
27441 |
++ unsigned int index; |
27442 |
++ |
27443 |
++ index = conn_hash(sig->gr_saddr, sig->gr_daddr, |
27444 |
++ sig->gr_sport, sig->gr_dport, |
27445 |
++ gr_conn_table_size); |
27446 |
++ |
27447 |
++ newent->sig = sig; |
27448 |
++ |
27449 |
++ match = &gr_conn_table[index]; |
27450 |
++ newent->next = *match; |
27451 |
++ *match = newent; |
27452 |
++ |
27453 |
++ return; |
27454 |
++} |
27455 |
++ |
27456 |
++static void gr_del_task_from_ip_table_nolock(struct signal_struct *sig) |
27457 |
++{ |
27458 |
++ struct conn_table_entry *match, *last = NULL; |
27459 |
++ unsigned int index; |
27460 |
++ |
27461 |
++ index = conn_hash(sig->gr_saddr, sig->gr_daddr, |
27462 |
++ sig->gr_sport, sig->gr_dport, |
27463 |
++ gr_conn_table_size); |
27464 |
++ |
27465 |
++ match = gr_conn_table[index]; |
27466 |
++ while (match && !conn_match(match->sig, |
27467 |
++ sig->gr_saddr, sig->gr_daddr, sig->gr_sport, |
27468 |
++ sig->gr_dport)) { |
27469 |
++ last = match; |
27470 |
++ match = match->next; |
27471 |
++ } |
27472 |
++ |
27473 |
++ if (match) { |
27474 |
++ if (last) |
27475 |
++ last->next = match->next; |
27476 |
++ else |
27477 |
++ gr_conn_table[index] = NULL; |
27478 |
++ kfree(match); |
27479 |
++ } |
27480 |
++ |
27481 |
++ return; |
27482 |
++} |
27483 |
++ |
27484 |
++static struct signal_struct * gr_lookup_task_ip_table(__u32 saddr, __u32 daddr, |
27485 |
++ __u16 sport, __u16 dport) |
27486 |
++{ |
27487 |
++ struct conn_table_entry *match; |
27488 |
++ unsigned int index; |
27489 |
++ |
27490 |
++ index = conn_hash(saddr, daddr, sport, dport, gr_conn_table_size); |
27491 |
++ |
27492 |
++ match = gr_conn_table[index]; |
27493 |
++ while (match && !conn_match(match->sig, saddr, daddr, sport, dport)) |
27494 |
++ match = match->next; |
27495 |
++ |
27496 |
++ if (match) |
27497 |
++ return match->sig; |
27498 |
++ else |
27499 |
++ return NULL; |
27500 |
++} |
27501 |
++ |
27502 |
++#endif |
27503 |
++ |
27504 |
++void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet) |
27505 |
++{ |
27506 |
++#ifdef CONFIG_GRKERNSEC |
27507 |
++ struct signal_struct *sig = task->signal; |
27508 |
++ struct conn_table_entry *newent; |
27509 |
++ |
27510 |
++ newent = kmalloc(sizeof(struct conn_table_entry), GFP_ATOMIC); |
27511 |
++ if (newent == NULL) |
27512 |
++ return; |
27513 |
++ /* no bh lock needed since we are called with bh disabled */ |
27514 |
++ spin_lock(&gr_conn_table_lock); |
27515 |
++ gr_del_task_from_ip_table_nolock(sig); |
27516 |
++ sig->gr_saddr = inet->rcv_saddr; |
27517 |
++ sig->gr_daddr = inet->daddr; |
27518 |
++ sig->gr_sport = inet->sport; |
27519 |
++ sig->gr_dport = inet->dport; |
27520 |
++ gr_add_to_task_ip_table_nolock(sig, newent); |
27521 |
++ spin_unlock(&gr_conn_table_lock); |
27522 |
++#endif |
27523 |
++ return; |
27524 |
++} |
27525 |
++ |
27526 |
++void gr_del_task_from_ip_table(struct task_struct *task) |
27527 |
++{ |
27528 |
++#ifdef CONFIG_GRKERNSEC |
27529 |
++ spin_lock_bh(&gr_conn_table_lock); |
27530 |
++ gr_del_task_from_ip_table_nolock(task->signal); |
27531 |
++ spin_unlock_bh(&gr_conn_table_lock); |
27532 |
++#endif |
27533 |
++ return; |
27534 |
++} |
27535 |
++ |
27536 |
++void |
27537 |
++gr_attach_curr_ip(const struct sock *sk) |
27538 |
++{ |
27539 |
++#ifdef CONFIG_GRKERNSEC |
27540 |
++ struct signal_struct *p, *set; |
27541 |
++ const struct inet_sock *inet = inet_sk(sk); |
27542 |
++ |
27543 |
++ if (unlikely(sk->sk_protocol != IPPROTO_TCP)) |
27544 |
++ return; |
27545 |
++ |
27546 |
++ set = current->signal; |
27547 |
++ |
27548 |
++ spin_lock_bh(&gr_conn_table_lock); |
27549 |
++ p = gr_lookup_task_ip_table(inet->daddr, inet->rcv_saddr, |
27550 |
++ inet->dport, inet->sport); |
27551 |
++ if (unlikely(p != NULL)) { |
27552 |
++ set->curr_ip = p->curr_ip; |
27553 |
++ set->used_accept = 1; |
27554 |
++ gr_del_task_from_ip_table_nolock(p); |
27555 |
++ spin_unlock_bh(&gr_conn_table_lock); |
27556 |
++ return; |
27557 |
++ } |
27558 |
++ spin_unlock_bh(&gr_conn_table_lock); |
27559 |
++ |
27560 |
++ set->curr_ip = inet->daddr; |
27561 |
++ set->used_accept = 1; |
27562 |
++#endif |
27563 |
++ return; |
27564 |
++} |
27565 |
++ |
27566 |
++int |
27567 |
++gr_handle_sock_all(const int family, const int type, const int protocol) |
27568 |
++{ |
27569 |
++#ifdef CONFIG_GRKERNSEC_SOCKET_ALL |
27570 |
++ if (grsec_enable_socket_all && in_group_p(grsec_socket_all_gid) && |
27571 |
++ (family != AF_UNIX) && (family != AF_LOCAL)) { |
27572 |
++ gr_log_int_str2(GR_DONT_AUDIT, GR_SOCK2_MSG, family, gr_socktype_to_name(type), gr_proto_to_name(protocol)); |
27573 |
++ return -EACCES; |
27574 |
++ } |
27575 |
++#endif |
27576 |
++ return 0; |
27577 |
++} |
27578 |
++ |
27579 |
++int |
27580 |
++gr_handle_sock_server(const struct sockaddr *sck) |
27581 |
++{ |
27582 |
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER |
27583 |
++ if (grsec_enable_socket_server && |
27584 |
++ in_group_p(grsec_socket_server_gid) && |
27585 |
++ sck && (sck->sa_family != AF_UNIX) && |
27586 |
++ (sck->sa_family != AF_LOCAL)) { |
27587 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG); |
27588 |
++ return -EACCES; |
27589 |
++ } |
27590 |
++#endif |
27591 |
++ return 0; |
27592 |
++} |
27593 |
++ |
27594 |
++int |
27595 |
++gr_handle_sock_server_other(const struct sock *sck) |
27596 |
++{ |
27597 |
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER |
27598 |
++ if (grsec_enable_socket_server && |
27599 |
++ in_group_p(grsec_socket_server_gid) && |
27600 |
++ sck && (sck->sk_family != AF_UNIX) && |
27601 |
++ (sck->sk_family != AF_LOCAL)) { |
27602 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG); |
27603 |
++ return -EACCES; |
27604 |
++ } |
27605 |
++#endif |
27606 |
++ return 0; |
27607 |
++} |
27608 |
++ |
27609 |
++int |
27610 |
++gr_handle_sock_client(const struct sockaddr *sck) |
27611 |
++{ |
27612 |
++#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT |
27613 |
++ if (grsec_enable_socket_client && in_group_p(grsec_socket_client_gid) && |
27614 |
++ sck && (sck->sa_family != AF_UNIX) && |
27615 |
++ (sck->sa_family != AF_LOCAL)) { |
27616 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_CONNECT_MSG); |
27617 |
++ return -EACCES; |
27618 |
++ } |
27619 |
++#endif |
27620 |
++ return 0; |
27621 |
++} |
27622 |
++ |
27623 |
++kernel_cap_t |
27624 |
++gr_cap_rtnetlink(struct sock *sock) |
27625 |
++{ |
27626 |
++#ifdef CONFIG_GRKERNSEC |
27627 |
++ if (!gr_acl_is_enabled()) |
27628 |
++ return current->cap_effective; |
27629 |
++ else if (sock->sk_protocol == NETLINK_ISCSI && |
27630 |
++ cap_raised(current->cap_effective, CAP_SYS_ADMIN) && |
27631 |
++ gr_task_is_capable(current, CAP_SYS_ADMIN)) |
27632 |
++ return current->cap_effective; |
27633 |
++ else if (sock->sk_protocol == NETLINK_AUDIT && |
27634 |
++ cap_raised(current->cap_effective, CAP_AUDIT_WRITE) && |
27635 |
++ gr_task_is_capable(current, CAP_AUDIT_WRITE) && |
27636 |
++ cap_raised(current->cap_effective, CAP_AUDIT_CONTROL) && |
27637 |
++ gr_task_is_capable(current, CAP_AUDIT_CONTROL)) |
27638 |
++ return current->cap_effective; |
27639 |
++ else if (cap_raised(current->cap_effective, CAP_NET_ADMIN) && |
27640 |
++ gr_task_is_capable(current, CAP_NET_ADMIN)) |
27641 |
++ return current->cap_effective; |
27642 |
++ else |
27643 |
++ return __cap_empty_set; |
27644 |
++#else |
27645 |
++ return current->cap_effective; |
27646 |
++#endif |
27647 |
++} |
27648 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_sysctl.c linux-2.6.28.8/grsecurity/grsec_sysctl.c |
27649 |
+--- linux-2.6.28.8/grsecurity/grsec_sysctl.c 1969-12-31 19:00:00.000000000 -0500 |
27650 |
++++ linux-2.6.28.8/grsecurity/grsec_sysctl.c 2009-02-21 09:37:49.000000000 -0500 |
27651 |
+@@ -0,0 +1,435 @@ |
27652 |
++#include <linux/kernel.h> |
27653 |
++#include <linux/sched.h> |
27654 |
++#include <linux/sysctl.h> |
27655 |
++#include <linux/grsecurity.h> |
27656 |
++#include <linux/grinternal.h> |
27657 |
++ |
27658 |
++#ifdef CONFIG_GRKERNSEC_MODSTOP |
27659 |
++int grsec_modstop; |
27660 |
++#endif |
27661 |
++ |
27662 |
++int |
27663 |
++gr_handle_sysctl_mod(const char *dirname, const char *name, const int op) |
27664 |
++{ |
27665 |
++#ifdef CONFIG_GRKERNSEC_SYSCTL |
27666 |
++ if (!strcmp(dirname, "grsecurity") && grsec_lock && (op & MAY_WRITE)) { |
27667 |
++ gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name); |
27668 |
++ return -EACCES; |
27669 |
++ } |
27670 |
++#endif |
27671 |
++#ifdef CONFIG_GRKERNSEC_MODSTOP |
27672 |
++ if (!strcmp(dirname, "grsecurity") && !strcmp(name, "disable_modules") && |
27673 |
++ grsec_modstop && (op & MAY_WRITE)) { |
27674 |
++ gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name); |
27675 |
++ return -EACCES; |
27676 |
++ } |
27677 |
++#endif |
27678 |
++ return 0; |
27679 |
++} |
27680 |
++ |
27681 |
++#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP) |
27682 |
++ctl_table grsecurity_table[] = { |
27683 |
++#ifdef CONFIG_GRKERNSEC_SYSCTL |
27684 |
++#ifdef CONFIG_GRKERNSEC_LINK |
27685 |
++ { |
27686 |
++ .ctl_name = CTL_UNNUMBERED, |
27687 |
++ .procname = "linking_restrictions", |
27688 |
++ .data = &grsec_enable_link, |
27689 |
++ .maxlen = sizeof(int), |
27690 |
++ .mode = 0600, |
27691 |
++ .proc_handler = &proc_dointvec, |
27692 |
++ }, |
27693 |
++#endif |
27694 |
++#ifdef CONFIG_GRKERNSEC_FIFO |
27695 |
++ { |
27696 |
++ .ctl_name = CTL_UNNUMBERED, |
27697 |
++ .procname = "fifo_restrictions", |
27698 |
++ .data = &grsec_enable_fifo, |
27699 |
++ .maxlen = sizeof(int), |
27700 |
++ .mode = 0600, |
27701 |
++ .proc_handler = &proc_dointvec, |
27702 |
++ }, |
27703 |
++#endif |
27704 |
++#ifdef CONFIG_GRKERNSEC_EXECVE |
27705 |
++ { |
27706 |
++ .ctl_name = CTL_UNNUMBERED, |
27707 |
++ .procname = "execve_limiting", |
27708 |
++ .data = &grsec_enable_execve, |
27709 |
++ .maxlen = sizeof(int), |
27710 |
++ .mode = 0600, |
27711 |
++ .proc_handler = &proc_dointvec, |
27712 |
++ }, |
27713 |
++#endif |
27714 |
++#ifdef CONFIG_GRKERNSEC_EXECLOG |
27715 |
++ { |
27716 |
++ .ctl_name = CTL_UNNUMBERED, |
27717 |
++ .procname = "exec_logging", |
27718 |
++ .data = &grsec_enable_execlog, |
27719 |
++ .maxlen = sizeof(int), |
27720 |
++ .mode = 0600, |
27721 |
++ .proc_handler = &proc_dointvec, |
27722 |
++ }, |
27723 |
++#endif |
27724 |
++#ifdef CONFIG_GRKERNSEC_SIGNAL |
27725 |
++ { |
27726 |
++ .ctl_name = CTL_UNNUMBERED, |
27727 |
++ .procname = "signal_logging", |
27728 |
++ .data = &grsec_enable_signal, |
27729 |
++ .maxlen = sizeof(int), |
27730 |
++ .mode = 0600, |
27731 |
++ .proc_handler = &proc_dointvec, |
27732 |
++ }, |
27733 |
++#endif |
27734 |
++#ifdef CONFIG_GRKERNSEC_FORKFAIL |
27735 |
++ { |
27736 |
++ .ctl_name = CTL_UNNUMBERED, |
27737 |
++ .procname = "forkfail_logging", |
27738 |
++ .data = &grsec_enable_forkfail, |
27739 |
++ .maxlen = sizeof(int), |
27740 |
++ .mode = 0600, |
27741 |
++ .proc_handler = &proc_dointvec, |
27742 |
++ }, |
27743 |
++#endif |
27744 |
++#ifdef CONFIG_GRKERNSEC_TIME |
27745 |
++ { |
27746 |
++ .ctl_name = CTL_UNNUMBERED, |
27747 |
++ .procname = "timechange_logging", |
27748 |
++ .data = &grsec_enable_time, |
27749 |
++ .maxlen = sizeof(int), |
27750 |
++ .mode = 0600, |
27751 |
++ .proc_handler = &proc_dointvec, |
27752 |
++ }, |
27753 |
++#endif |
27754 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT |
27755 |
++ { |
27756 |
++ .ctl_name = CTL_UNNUMBERED, |
27757 |
++ .procname = "chroot_deny_shmat", |
27758 |
++ .data = &grsec_enable_chroot_shmat, |
27759 |
++ .maxlen = sizeof(int), |
27760 |
++ .mode = 0600, |
27761 |
++ .proc_handler = &proc_dointvec, |
27762 |
++ }, |
27763 |
++#endif |
27764 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX |
27765 |
++ { |
27766 |
++ .ctl_name = CTL_UNNUMBERED, |
27767 |
++ .procname = "chroot_deny_unix", |
27768 |
++ .data = &grsec_enable_chroot_unix, |
27769 |
++ .maxlen = sizeof(int), |
27770 |
++ .mode = 0600, |
27771 |
++ .proc_handler = &proc_dointvec, |
27772 |
++ }, |
27773 |
++#endif |
27774 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT |
27775 |
++ { |
27776 |
++ .ctl_name = CTL_UNNUMBERED, |
27777 |
++ .procname = "chroot_deny_mount", |
27778 |
++ .data = &grsec_enable_chroot_mount, |
27779 |
++ .maxlen = sizeof(int), |
27780 |
++ .mode = 0600, |
27781 |
++ .proc_handler = &proc_dointvec, |
27782 |
++ }, |
27783 |
++#endif |
27784 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR |
27785 |
++ { |
27786 |
++ .ctl_name = CTL_UNNUMBERED, |
27787 |
++ .procname = "chroot_deny_fchdir", |
27788 |
++ .data = &grsec_enable_chroot_fchdir, |
27789 |
++ .maxlen = sizeof(int), |
27790 |
++ .mode = 0600, |
27791 |
++ .proc_handler = &proc_dointvec, |
27792 |
++ }, |
27793 |
++#endif |
27794 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE |
27795 |
++ { |
27796 |
++ .ctl_name = CTL_UNNUMBERED, |
27797 |
++ .procname = "chroot_deny_chroot", |
27798 |
++ .data = &grsec_enable_chroot_double, |
27799 |
++ .maxlen = sizeof(int), |
27800 |
++ .mode = 0600, |
27801 |
++ .proc_handler = &proc_dointvec, |
27802 |
++ }, |
27803 |
++#endif |
27804 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT |
27805 |
++ { |
27806 |
++ .ctl_name = CTL_UNNUMBERED, |
27807 |
++ .procname = "chroot_deny_pivot", |
27808 |
++ .data = &grsec_enable_chroot_pivot, |
27809 |
++ .maxlen = sizeof(int), |
27810 |
++ .mode = 0600, |
27811 |
++ .proc_handler = &proc_dointvec, |
27812 |
++ }, |
27813 |
++#endif |
27814 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR |
27815 |
++ { |
27816 |
++ .ctl_name = CTL_UNNUMBERED, |
27817 |
++ .procname = "chroot_enforce_chdir", |
27818 |
++ .data = &grsec_enable_chroot_chdir, |
27819 |
++ .maxlen = sizeof(int), |
27820 |
++ .mode = 0600, |
27821 |
++ .proc_handler = &proc_dointvec, |
27822 |
++ }, |
27823 |
++#endif |
27824 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD |
27825 |
++ { |
27826 |
++ .ctl_name = CTL_UNNUMBERED, |
27827 |
++ .procname = "chroot_deny_chmod", |
27828 |
++ .data = &grsec_enable_chroot_chmod, |
27829 |
++ .maxlen = sizeof(int), |
27830 |
++ .mode = 0600, |
27831 |
++ .proc_handler = &proc_dointvec, |
27832 |
++ }, |
27833 |
++#endif |
27834 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD |
27835 |
++ { |
27836 |
++ .ctl_name = CTL_UNNUMBERED, |
27837 |
++ .procname = "chroot_deny_mknod", |
27838 |
++ .data = &grsec_enable_chroot_mknod, |
27839 |
++ .maxlen = sizeof(int), |
27840 |
++ .mode = 0600, |
27841 |
++ .proc_handler = &proc_dointvec, |
27842 |
++ }, |
27843 |
++#endif |
27844 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_NICE |
27845 |
++ { |
27846 |
++ .ctl_name = CTL_UNNUMBERED, |
27847 |
++ .procname = "chroot_restrict_nice", |
27848 |
++ .data = &grsec_enable_chroot_nice, |
27849 |
++ .maxlen = sizeof(int), |
27850 |
++ .mode = 0600, |
27851 |
++ .proc_handler = &proc_dointvec, |
27852 |
++ }, |
27853 |
++#endif |
27854 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG |
27855 |
++ { |
27856 |
++ .ctl_name = CTL_UNNUMBERED, |
27857 |
++ .procname = "chroot_execlog", |
27858 |
++ .data = &grsec_enable_chroot_execlog, |
27859 |
++ .maxlen = sizeof(int), |
27860 |
++ .mode = 0600, |
27861 |
++ .proc_handler = &proc_dointvec, |
27862 |
++ }, |
27863 |
++#endif |
27864 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS |
27865 |
++ { |
27866 |
++ .ctl_name = CTL_UNNUMBERED, |
27867 |
++ .procname = "chroot_caps", |
27868 |
++ .data = &grsec_enable_chroot_caps, |
27869 |
++ .maxlen = sizeof(int), |
27870 |
++ .mode = 0600, |
27871 |
++ .proc_handler = &proc_dointvec, |
27872 |
++ }, |
27873 |
++#endif |
27874 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL |
27875 |
++ { |
27876 |
++ .ctl_name = CTL_UNNUMBERED, |
27877 |
++ .procname = "chroot_deny_sysctl", |
27878 |
++ .data = &grsec_enable_chroot_sysctl, |
27879 |
++ .maxlen = sizeof(int), |
27880 |
++ .mode = 0600, |
27881 |
++ .proc_handler = &proc_dointvec, |
27882 |
++ }, |
27883 |
++#endif |
27884 |
++#ifdef CONFIG_GRKERNSEC_TPE |
27885 |
++ { |
27886 |
++ .ctl_name = CTL_UNNUMBERED, |
27887 |
++ .procname = "tpe", |
27888 |
++ .data = &grsec_enable_tpe, |
27889 |
++ .maxlen = sizeof(int), |
27890 |
++ .mode = 0600, |
27891 |
++ .proc_handler = &proc_dointvec, |
27892 |
++ }, |
27893 |
++ { |
27894 |
++ .ctl_name = CTL_UNNUMBERED, |
27895 |
++ .procname = "tpe_gid", |
27896 |
++ .data = &grsec_tpe_gid, |
27897 |
++ .maxlen = sizeof(int), |
27898 |
++ .mode = 0600, |
27899 |
++ .proc_handler = &proc_dointvec, |
27900 |
++ }, |
27901 |
++#endif |
27902 |
++#ifdef CONFIG_GRKERNSEC_TPE_ALL |
27903 |
++ { |
27904 |
++ .ctl_name = CTL_UNNUMBERED, |
27905 |
++ .procname = "tpe_restrict_all", |
27906 |
++ .data = &grsec_enable_tpe_all, |
27907 |
++ .maxlen = sizeof(int), |
27908 |
++ .mode = 0600, |
27909 |
++ .proc_handler = &proc_dointvec, |
27910 |
++ }, |
27911 |
++#endif |
27912 |
++#ifdef CONFIG_GRKERNSEC_SOCKET_ALL |
27913 |
++ { |
27914 |
++ .ctl_name = CTL_UNNUMBERED, |
27915 |
++ .procname = "socket_all", |
27916 |
++ .data = &grsec_enable_socket_all, |
27917 |
++ .maxlen = sizeof(int), |
27918 |
++ .mode = 0600, |
27919 |
++ .proc_handler = &proc_dointvec, |
27920 |
++ }, |
27921 |
++ { |
27922 |
++ .ctl_name = CTL_UNNUMBERED, |
27923 |
++ .procname = "socket_all_gid", |
27924 |
++ .data = &grsec_socket_all_gid, |
27925 |
++ .maxlen = sizeof(int), |
27926 |
++ .mode = 0600, |
27927 |
++ .proc_handler = &proc_dointvec, |
27928 |
++ }, |
27929 |
++#endif |
27930 |
++#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT |
27931 |
++ { |
27932 |
++ .ctl_name = CTL_UNNUMBERED, |
27933 |
++ .procname = "socket_client", |
27934 |
++ .data = &grsec_enable_socket_client, |
27935 |
++ .maxlen = sizeof(int), |
27936 |
++ .mode = 0600, |
27937 |
++ .proc_handler = &proc_dointvec, |
27938 |
++ }, |
27939 |
++ { |
27940 |
++ .ctl_name = CTL_UNNUMBERED, |
27941 |
++ .procname = "socket_client_gid", |
27942 |
++ .data = &grsec_socket_client_gid, |
27943 |
++ .maxlen = sizeof(int), |
27944 |
++ .mode = 0600, |
27945 |
++ .proc_handler = &proc_dointvec, |
27946 |
++ }, |
27947 |
++#endif |
27948 |
++#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER |
27949 |
++ { |
27950 |
++ .ctl_name = CTL_UNNUMBERED, |
27951 |
++ .procname = "socket_server", |
27952 |
++ .data = &grsec_enable_socket_server, |
27953 |
++ .maxlen = sizeof(int), |
27954 |
++ .mode = 0600, |
27955 |
++ .proc_handler = &proc_dointvec, |
27956 |
++ }, |
27957 |
++ { |
27958 |
++ .ctl_name = CTL_UNNUMBERED, |
27959 |
++ .procname = "socket_server_gid", |
27960 |
++ .data = &grsec_socket_server_gid, |
27961 |
++ .maxlen = sizeof(int), |
27962 |
++ .mode = 0600, |
27963 |
++ .proc_handler = &proc_dointvec, |
27964 |
++ }, |
27965 |
++#endif |
27966 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP |
27967 |
++ { |
27968 |
++ .ctl_name = CTL_UNNUMBERED, |
27969 |
++ .procname = "audit_group", |
27970 |
++ .data = &grsec_enable_group, |
27971 |
++ .maxlen = sizeof(int), |
27972 |
++ .mode = 0600, |
27973 |
++ .proc_handler = &proc_dointvec, |
27974 |
++ }, |
27975 |
++ { |
27976 |
++ .ctl_name = CTL_UNNUMBERED, |
27977 |
++ .procname = "audit_gid", |
27978 |
++ .data = &grsec_audit_gid, |
27979 |
++ .maxlen = sizeof(int), |
27980 |
++ .mode = 0600, |
27981 |
++ .proc_handler = &proc_dointvec, |
27982 |
++ }, |
27983 |
++#endif |
27984 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR |
27985 |
++ { |
27986 |
++ .ctl_name = CTL_UNNUMBERED, |
27987 |
++ .procname = "audit_chdir", |
27988 |
++ .data = &grsec_enable_chdir, |
27989 |
++ .maxlen = sizeof(int), |
27990 |
++ .mode = 0600, |
27991 |
++ .proc_handler = &proc_dointvec, |
27992 |
++ }, |
27993 |
++#endif |
27994 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT |
27995 |
++ { |
27996 |
++ .ctl_name = CTL_UNNUMBERED, |
27997 |
++ .procname = "audit_mount", |
27998 |
++ .data = &grsec_enable_mount, |
27999 |
++ .maxlen = sizeof(int), |
28000 |
++ .mode = 0600, |
28001 |
++ .proc_handler = &proc_dointvec, |
28002 |
++ }, |
28003 |
++#endif |
28004 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_IPC |
28005 |
++ { |
28006 |
++ .ctl_name = CTL_UNNUMBERED, |
28007 |
++ .procname = "audit_ipc", |
28008 |
++ .data = &grsec_enable_audit_ipc, |
28009 |
++ .maxlen = sizeof(int), |
28010 |
++ .mode = 0600, |
28011 |
++ .proc_handler = &proc_dointvec, |
28012 |
++ }, |
28013 |
++#endif |
28014 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL |
28015 |
++ { |
28016 |
++ .ctl_name = CTL_UNNUMBERED, |
28017 |
++ .procname = "audit_textrel", |
28018 |
++ .data = &grsec_enable_audit_textrel, |
28019 |
++ .maxlen = sizeof(int), |
28020 |
++ .mode = 0600, |
28021 |
++ .proc_handler = &proc_dointvec, |
28022 |
++ }, |
28023 |
++#endif |
28024 |
++#ifdef CONFIG_GRKERNSEC_DMESG |
28025 |
++ { |
28026 |
++ .ctl_name = CTL_UNNUMBERED, |
28027 |
++ .procname = "dmesg", |
28028 |
++ .data = &grsec_enable_dmesg, |
28029 |
++ .maxlen = sizeof(int), |
28030 |
++ .mode = 0600, |
28031 |
++ .proc_handler = &proc_dointvec, |
28032 |
++ }, |
28033 |
++#endif |
28034 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK |
28035 |
++ { |
28036 |
++ .ctl_name = CTL_UNNUMBERED, |
28037 |
++ .procname = "chroot_findtask", |
28038 |
++ .data = &grsec_enable_chroot_findtask, |
28039 |
++ .maxlen = sizeof(int), |
28040 |
++ .mode = 0600, |
28041 |
++ .proc_handler = &proc_dointvec, |
28042 |
++ }, |
28043 |
++#endif |
28044 |
++#ifdef CONFIG_GRKERNSEC_RESLOG |
28045 |
++ { |
28046 |
++ .ctl_name = CTL_UNNUMBERED, |
28047 |
++ .procname = "resource_logging", |
28048 |
++ .data = &grsec_resource_logging, |
28049 |
++ .maxlen = sizeof(int), |
28050 |
++ .mode = 0600, |
28051 |
++ .proc_handler = &proc_dointvec, |
28052 |
++ }, |
28053 |
++#endif |
28054 |
++ { |
28055 |
++ .ctl_name = CTL_UNNUMBERED, |
28056 |
++ .procname = "grsec_lock", |
28057 |
++ .data = &grsec_lock, |
28058 |
++ .maxlen = sizeof(int), |
28059 |
++ .mode = 0600, |
28060 |
++ .proc_handler = &proc_dointvec, |
28061 |
++ }, |
28062 |
++#endif |
28063 |
++#ifdef CONFIG_GRKERNSEC_MODSTOP |
28064 |
++ { |
28065 |
++ .ctl_name = CTL_UNNUMBERED, |
28066 |
++ .procname = "disable_modules", |
28067 |
++ .data = &grsec_modstop, |
28068 |
++ .maxlen = sizeof(int), |
28069 |
++ .mode = 0600, |
28070 |
++ .proc_handler = &proc_dointvec, |
28071 |
++ }, |
28072 |
++#endif |
28073 |
++ { .ctl_name = 0 } |
28074 |
++}; |
28075 |
++#endif |
28076 |
++ |
28077 |
++int gr_check_modstop(void) |
28078 |
++{ |
28079 |
++#ifdef CONFIG_GRKERNSEC_MODSTOP |
28080 |
++ if (grsec_modstop == 1) { |
28081 |
++ gr_log_noargs(GR_DONT_AUDIT, GR_STOPMOD_MSG); |
28082 |
++ return 1; |
28083 |
++ } |
28084 |
++#endif |
28085 |
++ return 0; |
28086 |
++} |
28087 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_textrel.c linux-2.6.28.8/grsecurity/grsec_textrel.c |
28088 |
+--- linux-2.6.28.8/grsecurity/grsec_textrel.c 1969-12-31 19:00:00.000000000 -0500 |
28089 |
++++ linux-2.6.28.8/grsecurity/grsec_textrel.c 2009-02-21 09:37:49.000000000 -0500 |
28090 |
+@@ -0,0 +1,16 @@ |
28091 |
++#include <linux/kernel.h> |
28092 |
++#include <linux/sched.h> |
28093 |
++#include <linux/mm.h> |
28094 |
++#include <linux/file.h> |
28095 |
++#include <linux/grinternal.h> |
28096 |
++#include <linux/grsecurity.h> |
28097 |
++ |
28098 |
++void |
28099 |
++gr_log_textrel(struct vm_area_struct * vma) |
28100 |
++{ |
28101 |
++#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL |
28102 |
++ if (grsec_enable_audit_textrel) |
28103 |
++ gr_log_textrel_ulong_ulong(GR_DO_AUDIT, GR_TEXTREL_AUDIT_MSG, vma->vm_file, vma->vm_start, vma->vm_pgoff); |
28104 |
++#endif |
28105 |
++ return; |
28106 |
++} |
28107 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_time.c linux-2.6.28.8/grsecurity/grsec_time.c |
28108 |
+--- linux-2.6.28.8/grsecurity/grsec_time.c 1969-12-31 19:00:00.000000000 -0500 |
28109 |
++++ linux-2.6.28.8/grsecurity/grsec_time.c 2009-02-21 09:37:49.000000000 -0500 |
28110 |
+@@ -0,0 +1,13 @@ |
28111 |
++#include <linux/kernel.h> |
28112 |
++#include <linux/sched.h> |
28113 |
++#include <linux/grinternal.h> |
28114 |
++ |
28115 |
++void |
28116 |
++gr_log_timechange(void) |
28117 |
++{ |
28118 |
++#ifdef CONFIG_GRKERNSEC_TIME |
28119 |
++ if (grsec_enable_time) |
28120 |
++ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_TIME_MSG); |
28121 |
++#endif |
28122 |
++ return; |
28123 |
++} |
28124 |
+diff -urNp linux-2.6.28.8/grsecurity/grsec_tpe.c linux-2.6.28.8/grsecurity/grsec_tpe.c |
28125 |
+--- linux-2.6.28.8/grsecurity/grsec_tpe.c 1969-12-31 19:00:00.000000000 -0500 |
28126 |
++++ linux-2.6.28.8/grsecurity/grsec_tpe.c 2009-02-21 09:37:49.000000000 -0500 |
28127 |
+@@ -0,0 +1,37 @@ |
28128 |
++#include <linux/kernel.h> |
28129 |
++#include <linux/sched.h> |
28130 |
++#include <linux/file.h> |
28131 |
++#include <linux/fs.h> |
28132 |
++#include <linux/grinternal.h> |
28133 |
++ |
28134 |
++extern int gr_acl_tpe_check(void); |
28135 |
++ |
28136 |
++int |
28137 |
++gr_tpe_allow(const struct file *file) |
28138 |
++{ |
28139 |
++#ifdef CONFIG_GRKERNSEC |
28140 |
++ struct inode *inode = file->f_path.dentry->d_parent->d_inode; |
28141 |
++ |
28142 |
++ if (current->uid && ((grsec_enable_tpe && |
28143 |
++#ifdef CONFIG_GRKERNSEC_TPE_INVERT |
28144 |
++ !in_group_p(grsec_tpe_gid) |
28145 |
++#else |
28146 |
++ in_group_p(grsec_tpe_gid) |
28147 |
++#endif |
28148 |
++ ) || gr_acl_tpe_check()) && |
28149 |
++ (inode->i_uid || (!inode->i_uid && ((inode->i_mode & S_IWGRP) || |
28150 |
++ (inode->i_mode & S_IWOTH))))) { |
28151 |
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_path.dentry, file->f_path.mnt); |
28152 |
++ return 0; |
28153 |
++ } |
28154 |
++#ifdef CONFIG_GRKERNSEC_TPE_ALL |
28155 |
++ if (current->uid && grsec_enable_tpe && grsec_enable_tpe_all && |
28156 |
++ ((inode->i_uid && (inode->i_uid != current->uid)) || |
28157 |
++ (inode->i_mode & S_IWGRP) || (inode->i_mode & S_IWOTH))) { |
28158 |
++ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_path.dentry, file->f_path.mnt); |
28159 |
++ return 0; |
28160 |
++ } |
28161 |
++#endif |
28162 |
++#endif |
28163 |
++ return 1; |
28164 |
++} |
28165 |
+diff -urNp linux-2.6.28.8/grsecurity/grsum.c linux-2.6.28.8/grsecurity/grsum.c |
28166 |
+--- linux-2.6.28.8/grsecurity/grsum.c 1969-12-31 19:00:00.000000000 -0500 |
28167 |
++++ linux-2.6.28.8/grsecurity/grsum.c 2009-02-21 09:37:49.000000000 -0500 |
28168 |
+@@ -0,0 +1,59 @@ |
28169 |
++#include <linux/err.h> |
28170 |
++#include <linux/kernel.h> |
28171 |
++#include <linux/sched.h> |
28172 |
++#include <linux/mm.h> |
28173 |
++#include <linux/scatterlist.h> |
28174 |
++#include <linux/crypto.h> |
28175 |
++#include <linux/gracl.h> |
28176 |
++ |
28177 |
++ |
28178 |
++#if !defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE) || !defined(CONFIG_CRYPTO_SHA256) || defined(CONFIG_CRYPTO_SHA256_MODULE) |
28179 |
++#error "crypto and sha256 must be built into the kernel" |
28180 |
++#endif |
28181 |
++ |
28182 |
++int |
28183 |
++chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum) |
28184 |
++{ |
28185 |
++ char *p; |
28186 |
++ struct crypto_hash *tfm; |
28187 |
++ struct hash_desc desc; |
28188 |
++ struct scatterlist sg; |
28189 |
++ unsigned char temp_sum[GR_SHA_LEN]; |
28190 |
++ volatile int retval = 0; |
28191 |
++ volatile int dummy = 0; |
28192 |
++ unsigned int i; |
28193 |
++ |
28194 |
++ tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); |
28195 |
++ if (IS_ERR(tfm)) { |
28196 |
++ /* should never happen, since sha256 should be built in */ |
28197 |
++ return 1; |
28198 |
++ } |
28199 |
++ |
28200 |
++ desc.tfm = tfm; |
28201 |
++ desc.flags = 0; |
28202 |
++ |
28203 |
++ crypto_hash_init(&desc); |
28204 |
++ |
28205 |
++ p = salt; |
28206 |
++ sg_set_buf(&sg, p, GR_SALT_LEN); |
28207 |
++ crypto_hash_update(&desc, &sg, sg.length); |
28208 |
++ |
28209 |
++ p = entry->pw; |
28210 |
++ sg_set_buf(&sg, p, strlen(p)); |
28211 |
++ |
28212 |
++ crypto_hash_update(&desc, &sg, sg.length); |
28213 |
++ |
28214 |
++ crypto_hash_final(&desc, temp_sum); |
28215 |
++ |
28216 |
++ memset(entry->pw, 0, GR_PW_LEN); |
28217 |
++ |
28218 |
++ for (i = 0; i < GR_SHA_LEN; i++) |
28219 |
++ if (sum[i] != temp_sum[i]) |
28220 |
++ retval = 1; |
28221 |
++ else |
28222 |
++ dummy = 1; // waste a cycle |
28223 |
++ |
28224 |
++ crypto_free_hash(tfm); |
28225 |
++ |
28226 |
++ return retval; |
28227 |
++} |
28228 |
+diff -urNp linux-2.6.28.8/grsecurity/Kconfig linux-2.6.28.8/grsecurity/Kconfig |
28229 |
+--- linux-2.6.28.8/grsecurity/Kconfig 1969-12-31 19:00:00.000000000 -0500 |
28230 |
++++ linux-2.6.28.8/grsecurity/Kconfig 2009-03-07 14:50:21.000000000 -0500 |
28231 |
+@@ -0,0 +1,868 @@ |
28232 |
++# |
28233 |
++# grecurity configuration |
28234 |
++# |
28235 |
++ |
28236 |
++menu "Grsecurity" |
28237 |
++ |
28238 |
++config GRKERNSEC |
28239 |
++ bool "Grsecurity" |
28240 |
++ select CRYPTO |
28241 |
++ select CRYPTO_SHA256 |
28242 |
++ select SECURITY |
28243 |
++ select SECURITY_CAPABILITIES |
28244 |
++ help |
28245 |
++ If you say Y here, you will be able to configure many features |
28246 |
++ that will enhance the security of your system. It is highly |
28247 |
++ recommended that you say Y here and read through the help |
28248 |
++ for each option so that you fully understand the features and |
28249 |
++ can evaluate their usefulness for your machine. |
28250 |
++ |
28251 |
++choice |
28252 |
++ prompt "Security Level" |
28253 |
++ depends on GRKERNSEC |
28254 |
++ default GRKERNSEC_CUSTOM |
28255 |
++ |
28256 |
++config GRKERNSEC_LOW |
28257 |
++ bool "Low" |
28258 |
++ select GRKERNSEC_LINK |
28259 |
++ select GRKERNSEC_FIFO |
28260 |
++ select GRKERNSEC_EXECVE |
28261 |
++ select GRKERNSEC_RANDNET |
28262 |
++ select GRKERNSEC_DMESG |
28263 |
++ select GRKERNSEC_CHROOT |
28264 |
++ select GRKERNSEC_CHROOT_CHDIR |
28265 |
++ select GRKERNSEC_MODSTOP if (MODULES) |
28266 |
++ |
28267 |
++ help |
28268 |
++ If you choose this option, several of the grsecurity options will |
28269 |
++ be enabled that will give you greater protection against a number |
28270 |
++ of attacks, while assuring that none of your software will have any |
28271 |
++ conflicts with the additional security measures. If you run a lot |
28272 |
++ of unusual software, or you are having problems with the higher |
28273 |
++ security levels, you should say Y here. With this option, the |
28274 |
++ following features are enabled: |
28275 |
++ |
28276 |
++ - Linking restrictions |
28277 |
++ - FIFO restrictions |
28278 |
++ - Enforcing RLIMIT_NPROC on execve |
28279 |
++ - Restricted dmesg |
28280 |
++ - Enforced chdir("/") on chroot |
28281 |
++ - Runtime module disabling |
28282 |
++ |
28283 |
++config GRKERNSEC_MEDIUM |
28284 |
++ bool "Medium" |
28285 |
++ select PAX |
28286 |
++ select PAX_EI_PAX |
28287 |
++ select PAX_PT_PAX_FLAGS |
28288 |
++ select PAX_HAVE_ACL_FLAGS |
28289 |
++ select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR) |
28290 |
++ select GRKERNSEC_CHROOT |
28291 |
++ select GRKERNSEC_CHROOT_SYSCTL |
28292 |
++ select GRKERNSEC_LINK |
28293 |
++ select GRKERNSEC_FIFO |
28294 |
++ select GRKERNSEC_EXECVE |
28295 |
++ select GRKERNSEC_DMESG |
28296 |
++ select GRKERNSEC_RANDNET |
28297 |
++ select GRKERNSEC_FORKFAIL |
28298 |
++ select GRKERNSEC_TIME |
28299 |
++ select GRKERNSEC_SIGNAL |
28300 |
++ select GRKERNSEC_CHROOT |
28301 |
++ select GRKERNSEC_CHROOT_UNIX |
28302 |
++ select GRKERNSEC_CHROOT_MOUNT |
28303 |
++ select GRKERNSEC_CHROOT_PIVOT |
28304 |
++ select GRKERNSEC_CHROOT_DOUBLE |
28305 |
++ select GRKERNSEC_CHROOT_CHDIR |
28306 |
++ select GRKERNSEC_CHROOT_MKNOD |
28307 |
++ select GRKERNSEC_PROC |
28308 |
++ select GRKERNSEC_PROC_USERGROUP |
28309 |
++ select GRKERNSEC_MODSTOP if (MODULES) |
28310 |
++ select PAX_RANDUSTACK |
28311 |
++ select PAX_ASLR |
28312 |
++ select PAX_RANDMMAP |
28313 |
++ select PAX_REFCOUNT if (X86) |
28314 |
++ |
28315 |
++ help |
28316 |
++ If you say Y here, several features in addition to those included |
28317 |
++ in the low additional security level will be enabled. These |
28318 |
++ features provide even more security to your system, though in rare |
28319 |
++ cases they may be incompatible with very old or poorly written |
28320 |
++ software. If you enable this option, make sure that your auth |
28321 |
++ service (identd) is running as gid 1001. With this option, |
28322 |
++ the following features (in addition to those provided in the |
28323 |
++ low additional security level) will be enabled: |
28324 |
++ |
28325 |
++ - Failed fork logging |
28326 |
++ - Time change logging |
28327 |
++ - Signal logging |
28328 |
++ - Deny mounts in chroot |
28329 |
++ - Deny double chrooting |
28330 |
++ - Deny sysctl writes in chroot |
28331 |
++ - Deny mknod in chroot |
28332 |
++ - Deny access to abstract AF_UNIX sockets out of chroot |
28333 |
++ - Deny pivot_root in chroot |
28334 |
++ - Denied writes of /dev/kmem, /dev/mem, and /dev/port |
28335 |
++ - /proc restrictions with special GID set to 10 (usually wheel) |
28336 |
++ - Address Space Layout Randomization (ASLR) |
28337 |
++ - Prevent exploitation of most refcount overflows |
28338 |
++ |
28339 |
++config GRKERNSEC_HIGH |
28340 |
++ bool "High" |
28341 |
++ select GRKERNSEC_LINK |
28342 |
++ select GRKERNSEC_FIFO |
28343 |
++ select GRKERNSEC_EXECVE |
28344 |
++ select GRKERNSEC_DMESG |
28345 |
++ select GRKERNSEC_FORKFAIL |
28346 |
++ select GRKERNSEC_TIME |
28347 |
++ select GRKERNSEC_SIGNAL |
28348 |
++ select GRKERNSEC_CHROOT |
28349 |
++ select GRKERNSEC_CHROOT_SHMAT |
28350 |
++ select GRKERNSEC_CHROOT_UNIX |
28351 |
++ select GRKERNSEC_CHROOT_MOUNT |
28352 |
++ select GRKERNSEC_CHROOT_FCHDIR |
28353 |
++ select GRKERNSEC_CHROOT_PIVOT |
28354 |
++ select GRKERNSEC_CHROOT_DOUBLE |
28355 |
++ select GRKERNSEC_CHROOT_CHDIR |
28356 |
++ select GRKERNSEC_CHROOT_MKNOD |
28357 |
++ select GRKERNSEC_CHROOT_CAPS |
28358 |
++ select GRKERNSEC_CHROOT_SYSCTL |
28359 |
++ select GRKERNSEC_CHROOT_FINDTASK |
28360 |
++ select GRKERNSEC_PROC |
28361 |
++ select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR) |
28362 |
++ select GRKERNSEC_HIDESYM |
28363 |
++ select GRKERNSEC_BRUTE |
28364 |
++ select GRKERNSEC_PROC_USERGROUP |
28365 |
++ select GRKERNSEC_KMEM |
28366 |
++ select GRKERNSEC_RESLOG |
28367 |
++ select GRKERNSEC_RANDNET |
28368 |
++ select GRKERNSEC_PROC_ADD |
28369 |
++ select GRKERNSEC_CHROOT_CHMOD |
28370 |
++ select GRKERNSEC_CHROOT_NICE |
28371 |
++ select GRKERNSEC_AUDIT_MOUNT |
28372 |
++ select GRKERNSEC_MODSTOP if (MODULES) |
28373 |
++ select PAX |
28374 |
++ select PAX_RANDUSTACK |
28375 |
++ select PAX_ASLR |
28376 |
++ select PAX_RANDMMAP |
28377 |
++ select PAX_NOEXEC |
28378 |
++ select PAX_MPROTECT |
28379 |
++ select PAX_EI_PAX |
28380 |
++ select PAX_PT_PAX_FLAGS |
28381 |
++ select PAX_HAVE_ACL_FLAGS |
28382 |
++ select PAX_KERNEXEC if (X86 && !EFI && !COMPAT_VDSO && !PARAVIRT && (!X86_32 || X86_WP_WORKS_OK)) |
28383 |
++ select PAX_MEMORY_UDEREF if (!X86_64 && !COMPAT_VDSO) |
28384 |
++ select PAX_RANDKSTACK if (X86_TSC && !X86_64) |
28385 |
++ select PAX_SEGMEXEC if (X86 && !X86_64) |
28386 |
++ select PAX_PAGEEXEC if (!X86) |
28387 |
++ select PAX_EMUPLT if (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64) |
28388 |
++ select PAX_DLRESOLVE if (SPARC32 || SPARC64) |
28389 |
++ select PAX_SYSCALL if (PPC32) |
28390 |
++ select PAX_EMUTRAMP if (PARISC) |
28391 |
++ select PAX_EMUSIGRT if (PARISC) |
28392 |
++ select PAX_ETEXECRELOCS if (ALPHA || IA64 || PARISC) |
28393 |
++ select PAX_REFCOUNT if (X86) |
28394 |
++ help |
28395 |
++ If you say Y here, many of the features of grsecurity will be |
28396 |
++ enabled, which will protect you against many kinds of attacks |
28397 |
++ against your system. The heightened security comes at a cost |
28398 |
++ of an increased chance of incompatibilities with rare software |
28399 |
++ on your machine. Since this security level enables PaX, you should |
28400 |
++ view <http://pax.grsecurity.net> and read about the PaX |
28401 |
++ project. While you are there, download chpax and run it on |
28402 |
++ binaries that cause problems with PaX. Also remember that |
28403 |
++ since the /proc restrictions are enabled, you must run your |
28404 |
++ identd as gid 1001. This security level enables the following |
28405 |
++ features in addition to those listed in the low and medium |
28406 |
++ security levels: |
28407 |
++ |
28408 |
++ - Additional /proc restrictions |
28409 |
++ - Chmod restrictions in chroot |
28410 |
++ - No signals, ptrace, or viewing of processes outside of chroot |
28411 |
++ - Capability restrictions in chroot |
28412 |
++ - Deny fchdir out of chroot |
28413 |
++ - Priority restrictions in chroot |
28414 |
++ - Segmentation-based implementation of PaX |
28415 |
++ - Mprotect restrictions |
28416 |
++ - Removal of addresses from /proc/<pid>/[smaps|maps|stat] |
28417 |
++ - Kernel stack randomization |
28418 |
++ - Mount/unmount/remount logging |
28419 |
++ - Kernel symbol hiding |
28420 |
++ - Prevention of memory exhaustion-based exploits |
28421 |
++config GRKERNSEC_CUSTOM |
28422 |
++ bool "Custom" |
28423 |
++ help |
28424 |
++ If you say Y here, you will be able to configure every grsecurity |
28425 |
++ option, which allows you to enable many more features that aren't |
28426 |
++ covered in the basic security levels. These additional features |
28427 |
++ include TPE, socket restrictions, and the sysctl system for |
28428 |
++ grsecurity. It is advised that you read through the help for |
28429 |
++ each option to determine its usefulness in your situation. |
28430 |
++ |
28431 |
++endchoice |
28432 |
++ |
28433 |
++menu "Address Space Protection" |
28434 |
++depends on GRKERNSEC |
28435 |
++ |
28436 |
++config GRKERNSEC_KMEM |
28437 |
++ bool "Deny writing to /dev/kmem, /dev/mem, and /dev/port" |
28438 |
++ help |
28439 |
++ If you say Y here, /dev/kmem and /dev/mem won't be allowed to |
28440 |
++ be written to via mmap or otherwise to modify the running kernel. |
28441 |
++ /dev/port will also not be allowed to be opened. If you have module |
28442 |
++ support disabled, enabling this will close up four ways that are |
28443 |
++ currently used to insert malicious code into the running kernel. |
28444 |
++ Even with all these features enabled, we still highly recommend that |
28445 |
++ you use the RBAC system, as it is still possible for an attacker to |
28446 |
++ modify the running kernel through privileged I/O granted by ioperm/iopl. |
28447 |
++ If you are not using XFree86, you may be able to stop this additional |
28448 |
++ case by enabling the 'Disable privileged I/O' option. Though nothing |
28449 |
++ legitimately writes to /dev/kmem, XFree86 does need to write to /dev/mem, |
28450 |
++ but only to video memory, which is the only writing we allow in this |
28451 |
++ case. If /dev/kmem or /dev/mem are mmaped without PROT_WRITE, they will |
28452 |
++ not be allowed to mprotect it with PROT_WRITE later. |
28453 |
++ It is highly recommended that you say Y here if you meet all the |
28454 |
++ conditions above. |
28455 |
++ |
28456 |
++config GRKERNSEC_IO |
28457 |
++ bool "Disable privileged I/O" |
28458 |
++ depends on X86 |
28459 |
++ select RTC_CLASS |
28460 |
++ select RTC_INTF_DEV |
28461 |
++ help |
28462 |
++ If you say Y here, all ioperm and iopl calls will return an error. |
28463 |
++ Ioperm and iopl can be used to modify the running kernel. |
28464 |
++ Unfortunately, some programs need this access to operate properly, |
28465 |
++ the most notable of which are XFree86 and hwclock. hwclock can be |
28466 |
++ remedied by having RTC support in the kernel, so real-time |
28467 |
++ clock support is enabled if this option is enabled, to ensure |
28468 |
++ that hwclock operates correctly. XFree86 still will not |
28469 |
++ operate correctly with this option enabled, so DO NOT CHOOSE Y |
28470 |
++ IF YOU USE XFree86. If you use XFree86 and you still want to |
28471 |
++ protect your kernel against modification, use the RBAC system. |
28472 |
++ |
28473 |
++config GRKERNSEC_PROC_MEMMAP |
28474 |
++ bool "Remove addresses from /proc/<pid>/[smaps|maps|stat]" |
28475 |
++ depends on PAX_NOEXEC || PAX_ASLR |
28476 |
++ help |
28477 |
++ If you say Y here, the /proc/<pid>/maps and /proc/<pid>/stat files will |
28478 |
++ give no information about the addresses of its mappings if |
28479 |
++ PaX features that rely on random addresses are enabled on the task. |
28480 |
++ If you use PaX it is greatly recommended that you say Y here as it |
28481 |
++ closes up a hole that makes the full ASLR useless for suid |
28482 |
++ binaries. |
28483 |
++ |
28484 |
++config GRKERNSEC_BRUTE |
28485 |
++ bool "Deter exploit bruteforcing" |
28486 |
++ help |
28487 |
++ If you say Y here, attempts to bruteforce exploits against forking |
28488 |
++ daemons such as apache or sshd will be deterred. When a child of a |
28489 |
++ forking daemon is killed by PaX or crashes due to an illegal |
28490 |
++ instruction, the parent process will be delayed 30 seconds upon every |
28491 |
++ subsequent fork until the administrator is able to assess the |
28492 |
++ situation and restart the daemon. It is recommended that you also |
28493 |
++ enable signal logging in the auditing section so that logs are |
28494 |
++ generated when a process performs an illegal instruction. |
28495 |
++ |
28496 |
++config GRKERNSEC_MODSTOP |
28497 |
++ bool "Runtime module disabling" |
28498 |
++ depends on MODULES |
28499 |
++ help |
28500 |
++ If you say Y here, you will be able to disable the ability to (un)load |
28501 |
++ modules at runtime. This feature is useful if you need the ability |
28502 |
++ to load kernel modules at boot time, but do not want to allow an |
28503 |
++ attacker to load a rootkit kernel module into the system, or to remove |
28504 |
++ a loaded kernel module important to system functioning. You should |
28505 |
++ enable the /dev/mem protection feature as well, since rootkits can be |
28506 |
++ inserted into the kernel via other methods than kernel modules. Since |
28507 |
++ an untrusted module could still be loaded by modifying init scripts and |
28508 |
++ rebooting the system, it is also recommended that you enable the RBAC |
28509 |
++ system. If you enable this option, a sysctl option with name |
28510 |
++ "disable_modules" will be created. Setting this option to "1" disables |
28511 |
++ module loading. After this option is set, no further writes to it are |
28512 |
++ allowed until the system is rebooted. |
28513 |
++ |
28514 |
++config GRKERNSEC_HIDESYM |
28515 |
++ bool "Hide kernel symbols" |
28516 |
++ help |
28517 |
++ If you say Y here, getting information on loaded modules, and |
28518 |
++ displaying all kernel symbols through a syscall will be restricted |
28519 |
++ to users with CAP_SYS_MODULE. This option is only effective |
28520 |
++ provided the following conditions are met: |
28521 |
++ 1) The kernel using grsecurity is not precompiled by some distribution |
28522 |
++ 2) You are using the RBAC system and hiding other files such as your |
28523 |
++ kernel image and System.map |
28524 |
++ 3) You have the additional /proc restrictions enabled, which removes |
28525 |
++ /proc/kcore |
28526 |
++ If the above conditions are met, this option will aid to provide a |
28527 |
++ useful protection against local and remote kernel exploitation of |
28528 |
++ overflows and arbitrary read/write vulnerabilities. |
28529 |
++ |
28530 |
++endmenu |
28531 |
++menu "Role Based Access Control Options" |
28532 |
++depends on GRKERNSEC |
28533 |
++ |
28534 |
++config GRKERNSEC_ACL_HIDEKERN |
28535 |
++ bool "Hide kernel processes" |
28536 |
++ help |
28537 |
++ If you say Y here, all kernel threads will be hidden to all |
28538 |
++ processes but those whose subject has the "view hidden processes" |
28539 |
++ flag. |
28540 |
++ |
28541 |
++config GRKERNSEC_ACL_MAXTRIES |
28542 |
++ int "Maximum tries before password lockout" |
28543 |
++ default 3 |
28544 |
++ help |
28545 |
++ This option enforces the maximum number of times a user can attempt |
28546 |
++ to authorize themselves with the grsecurity RBAC system before being |
28547 |
++ denied the ability to attempt authorization again for a specified time. |
28548 |
++ The lower the number, the harder it will be to brute-force a password. |
28549 |
++ |
28550 |
++config GRKERNSEC_ACL_TIMEOUT |
28551 |
++ int "Time to wait after max password tries, in seconds" |
28552 |
++ default 30 |
28553 |
++ help |
28554 |
++ This option specifies the time the user must wait after attempting to |
28555 |
++ authorize to the RBAC system with the maximum number of invalid |
28556 |
++ passwords. The higher the number, the harder it will be to brute-force |
28557 |
++ a password. |
28558 |
++ |
28559 |
++endmenu |
28560 |
++menu "Filesystem Protections" |
28561 |
++depends on GRKERNSEC |
28562 |
++ |
28563 |
++config GRKERNSEC_PROC |
28564 |
++ bool "Proc restrictions" |
28565 |
++ help |
28566 |
++ If you say Y here, the permissions of the /proc filesystem |
28567 |
++ will be altered to enhance system security and privacy. You MUST |
28568 |
++ choose either a user only restriction or a user and group restriction. |
28569 |
++ Depending upon the option you choose, you can either restrict users to |
28570 |
++ see only the processes they themselves run, or choose a group that can |
28571 |
++ view all processes and files normally restricted to root if you choose |
28572 |
++ the "restrict to user only" option. NOTE: If you're running identd as |
28573 |
++ a non-root user, you will have to run it as the group you specify here. |
28574 |
++ |
28575 |
++config GRKERNSEC_PROC_USER |
28576 |
++ bool "Restrict /proc to user only" |
28577 |
++ depends on GRKERNSEC_PROC |
28578 |
++ help |
28579 |
++ If you say Y here, non-root users will only be able to view their own |
28580 |
++ processes, and restricts them from viewing network-related information, |
28581 |
++ and viewing kernel symbol and module information. |
28582 |
++ |
28583 |
++config GRKERNSEC_PROC_USERGROUP |
28584 |
++ bool "Allow special group" |
28585 |
++ depends on GRKERNSEC_PROC && !GRKERNSEC_PROC_USER |
28586 |
++ help |
28587 |
++ If you say Y here, you will be able to select a group that will be |
28588 |
++ able to view all processes, network-related information, and |
28589 |
++ kernel and symbol information. This option is useful if you want |
28590 |
++ to run identd as a non-root user. |
28591 |
++ |
28592 |
++config GRKERNSEC_PROC_GID |
28593 |
++ int "GID for special group" |
28594 |
++ depends on GRKERNSEC_PROC_USERGROUP |
28595 |
++ default 1001 |
28596 |
++ |
28597 |
++config GRKERNSEC_PROC_ADD |
28598 |
++ bool "Additional restrictions" |
28599 |
++ depends on GRKERNSEC_PROC_USER || GRKERNSEC_PROC_USERGROUP |
28600 |
++ help |
28601 |
++ If you say Y here, additional restrictions will be placed on |
28602 |
++ /proc that keep normal users from viewing device information and |
28603 |
++ slabinfo information that could be useful for exploits. |
28604 |
++ |
28605 |
++config GRKERNSEC_LINK |
28606 |
++ bool "Linking restrictions" |
28607 |
++ help |
28608 |
++ If you say Y here, /tmp race exploits will be prevented, since users |
28609 |
++ will no longer be able to follow symlinks owned by other users in |
28610 |
++ world-writable +t directories (i.e. /tmp), unless the owner of the |
28611 |
++ symlink is the owner of the directory. users will also not be |
28612 |
++ able to hardlink to files they do not own. If the sysctl option is |
28613 |
++ enabled, a sysctl option with name "linking_restrictions" is created. |
28614 |
++ |
28615 |
++config GRKERNSEC_FIFO |
28616 |
++ bool "FIFO restrictions" |
28617 |
++ help |
28618 |
++ If you say Y here, users will not be able to write to FIFOs they don't |
28619 |
++ own in world-writable +t directories (i.e. /tmp), unless the owner of |
28620 |
++ the FIFO is the same owner of the directory it's held in. If the sysctl |
28621 |
++ option is enabled, a sysctl option with name "fifo_restrictions" is |
28622 |
++ created. |
28623 |
++ |
28624 |
++config GRKERNSEC_CHROOT |
28625 |
++ bool "Chroot jail restrictions" |
28626 |
++ help |
28627 |
++ If you say Y here, you will be able to choose several options that will |
28628 |
++ make breaking out of a chrooted jail much more difficult. If you |
28629 |
++ encounter no software incompatibilities with the following options, it |
28630 |
++ is recommended that you enable each one. |
28631 |
++ |
28632 |
++config GRKERNSEC_CHROOT_MOUNT |
28633 |
++ bool "Deny mounts" |
28634 |
++ depends on GRKERNSEC_CHROOT |
28635 |
++ help |
28636 |
++ If you say Y here, processes inside a chroot will not be able to |
28637 |
++ mount or remount filesystems. If the sysctl option is enabled, a |
28638 |
++ sysctl option with name "chroot_deny_mount" is created. |
28639 |
++ |
28640 |
++config GRKERNSEC_CHROOT_DOUBLE |
28641 |
++ bool "Deny double-chroots" |
28642 |
++ depends on GRKERNSEC_CHROOT |
28643 |
++ help |
28644 |
++ If you say Y here, processes inside a chroot will not be able to chroot |
28645 |
++ again outside the chroot. This is a widely used method of breaking |
28646 |
++ out of a chroot jail and should not be allowed. If the sysctl |
28647 |
++ option is enabled, a sysctl option with name |
28648 |
++ "chroot_deny_chroot" is created. |
28649 |
++ |
28650 |
++config GRKERNSEC_CHROOT_PIVOT |
28651 |
++ bool "Deny pivot_root in chroot" |
28652 |
++ depends on GRKERNSEC_CHROOT |
28653 |
++ help |
28654 |
++ If you say Y here, processes inside a chroot will not be able to use |
28655 |
++ a function called pivot_root() that was introduced in Linux 2.3.41. It |
28656 |
++ works similar to chroot in that it changes the root filesystem. This |
28657 |
++ function could be misused in a chrooted process to attempt to break out |
28658 |
++ of the chroot, and therefore should not be allowed. If the sysctl |
28659 |
++ option is enabled, a sysctl option with name "chroot_deny_pivot" is |
28660 |
++ created. |
28661 |
++ |
28662 |
++config GRKERNSEC_CHROOT_CHDIR |
28663 |
++ bool "Enforce chdir(\"/\") on all chroots" |
28664 |
++ depends on GRKERNSEC_CHROOT |
28665 |
++ help |
28666 |
++ If you say Y here, the current working directory of all newly-chrooted |
28667 |
++ applications will be set to the the root directory of the chroot. |
28668 |
++ The man page on chroot(2) states: |
28669 |
++ Note that this call does not change the current working |
28670 |
++ directory, so that `.' can be outside the tree rooted at |
28671 |
++ `/'. In particular, the super-user can escape from a |
28672 |
++ `chroot jail' by doing `mkdir foo; chroot foo; cd ..'. |
28673 |
++ |
28674 |
++ It is recommended that you say Y here, since it's not known to break |
28675 |
++ any software. If the sysctl option is enabled, a sysctl option with |
28676 |
++ name "chroot_enforce_chdir" is created. |
28677 |
++ |
28678 |
++config GRKERNSEC_CHROOT_CHMOD |
28679 |
++ bool "Deny (f)chmod +s" |
28680 |
++ depends on GRKERNSEC_CHROOT |
28681 |
++ help |
28682 |
++ If you say Y here, processes inside a chroot will not be able to chmod |
28683 |
++ or fchmod files to make them have suid or sgid bits. This protects |
28684 |
++ against another published method of breaking a chroot. If the sysctl |
28685 |
++ option is enabled, a sysctl option with name "chroot_deny_chmod" is |
28686 |
++ created. |
28687 |
++ |
28688 |
++config GRKERNSEC_CHROOT_FCHDIR |
28689 |
++ bool "Deny fchdir out of chroot" |
28690 |
++ depends on GRKERNSEC_CHROOT |
28691 |
++ help |
28692 |
++ If you say Y here, a well-known method of breaking chroots by fchdir'ing |
28693 |
++ to a file descriptor of the chrooting process that points to a directory |
28694 |
++ outside the filesystem will be stopped. If the sysctl option |
28695 |
++ is enabled, a sysctl option with name "chroot_deny_fchdir" is created. |
28696 |
++ |
28697 |
++config GRKERNSEC_CHROOT_MKNOD |
28698 |
++ bool "Deny mknod" |
28699 |
++ depends on GRKERNSEC_CHROOT |
28700 |
++ help |
28701 |
++ If you say Y here, processes inside a chroot will not be allowed to |
28702 |
++ mknod. The problem with using mknod inside a chroot is that it |
28703 |
++ would allow an attacker to create a device entry that is the same |
28704 |
++ as one on the physical root of your system, which could range from |
28705 |
++ anything from the console device to a device for your harddrive (which |
28706 |
++ they could then use to wipe the drive or steal data). It is recommended |
28707 |
++ that you say Y here, unless you run into software incompatibilities. |
28708 |
++ If the sysctl option is enabled, a sysctl option with name |
28709 |
++ "chroot_deny_mknod" is created. |
28710 |
++ |
28711 |
++config GRKERNSEC_CHROOT_SHMAT |
28712 |
++ bool "Deny shmat() out of chroot" |
28713 |
++ depends on GRKERNSEC_CHROOT |
28714 |
++ help |
28715 |
++ If you say Y here, processes inside a chroot will not be able to attach |
28716 |
++ to shared memory segments that were created outside of the chroot jail. |
28717 |
++ It is recommended that you say Y here. If the sysctl option is enabled, |
28718 |
++ a sysctl option with name "chroot_deny_shmat" is created. |
28719 |
++ |
28720 |
++config GRKERNSEC_CHROOT_UNIX |
28721 |
++ bool "Deny access to abstract AF_UNIX sockets out of chroot" |
28722 |
++ depends on GRKERNSEC_CHROOT |
28723 |
++ help |
28724 |
++ If you say Y here, processes inside a chroot will not be able to |
28725 |
++ connect to abstract (meaning not belonging to a filesystem) Unix |
28726 |
++ domain sockets that were bound outside of a chroot. It is recommended |
28727 |
++ that you say Y here. If the sysctl option is enabled, a sysctl option |
28728 |
++ with name "chroot_deny_unix" is created. |
28729 |
++ |
28730 |
++config GRKERNSEC_CHROOT_FINDTASK |
28731 |
++ bool "Protect outside processes" |
28732 |
++ depends on GRKERNSEC_CHROOT |
28733 |
++ help |
28734 |
++ If you say Y here, processes inside a chroot will not be able to |
28735 |
++ kill, send signals with fcntl, ptrace, capget, getpgid, getsid, |
28736 |
++ or view any process outside of the chroot. If the sysctl |
28737 |
++ option is enabled, a sysctl option with name "chroot_findtask" is |
28738 |
++ created. |
28739 |
++ |
28740 |
++config GRKERNSEC_CHROOT_NICE |
28741 |
++ bool "Restrict priority changes" |
28742 |
++ depends on GRKERNSEC_CHROOT |
28743 |
++ help |
28744 |
++ If you say Y here, processes inside a chroot will not be able to raise |
28745 |
++ the priority of processes in the chroot, or alter the priority of |
28746 |
++ processes outside the chroot. This provides more security than simply |
28747 |
++ removing CAP_SYS_NICE from the process' capability set. If the |
28748 |
++ sysctl option is enabled, a sysctl option with name "chroot_restrict_nice" |
28749 |
++ is created. |
28750 |
++ |
28751 |
++config GRKERNSEC_CHROOT_SYSCTL |
28752 |
++ bool "Deny sysctl writes" |
28753 |
++ depends on GRKERNSEC_CHROOT |
28754 |
++ help |
28755 |
++ If you say Y here, an attacker in a chroot will not be able to |
28756 |
++ write to sysctl entries, either by sysctl(2) or through a /proc |
28757 |
++ interface. It is strongly recommended that you say Y here. If the |
28758 |
++ sysctl option is enabled, a sysctl option with name |
28759 |
++ "chroot_deny_sysctl" is created. |
28760 |
++ |
28761 |
++config GRKERNSEC_CHROOT_CAPS |
28762 |
++ bool "Capability restrictions" |
28763 |
++ depends on GRKERNSEC_CHROOT |
28764 |
++ help |
28765 |
++ If you say Y here, the capabilities on all root processes within a |
28766 |
++ chroot jail will be lowered to stop module insertion, raw i/o, |
28767 |
++ system and net admin tasks, rebooting the system, modifying immutable |
28768 |
++ files, modifying IPC owned by another, and changing the system time. |
28769 |
++ This is left an option because it can break some apps. Disable this |
28770 |
++ if your chrooted apps are having problems performing those kinds of |
28771 |
++ tasks. If the sysctl option is enabled, a sysctl option with |
28772 |
++ name "chroot_caps" is created. |
28773 |
++ |
28774 |
++endmenu |
28775 |
++menu "Kernel Auditing" |
28776 |
++depends on GRKERNSEC |
28777 |
++ |
28778 |
++config GRKERNSEC_AUDIT_GROUP |
28779 |
++ bool "Single group for auditing" |
28780 |
++ help |
28781 |
++ If you say Y here, the exec, chdir, (un)mount, and ipc logging features |
28782 |
++ will only operate on a group you specify. This option is recommended |
28783 |
++ if you only want to watch certain users instead of having a large |
28784 |
++ amount of logs from the entire system. If the sysctl option is enabled, |
28785 |
++ a sysctl option with name "audit_group" is created. |
28786 |
++ |
28787 |
++config GRKERNSEC_AUDIT_GID |
28788 |
++ int "GID for auditing" |
28789 |
++ depends on GRKERNSEC_AUDIT_GROUP |
28790 |
++ default 1007 |
28791 |
++ |
28792 |
++config GRKERNSEC_EXECLOG |
28793 |
++ bool "Exec logging" |
28794 |
++ help |
28795 |
++ If you say Y here, all execve() calls will be logged (since the |
28796 |
++ other exec*() calls are frontends to execve(), all execution |
28797 |
++ will be logged). Useful for shell-servers that like to keep track |
28798 |
++ of their users. If the sysctl option is enabled, a sysctl option with |
28799 |
++ name "exec_logging" is created. |
28800 |
++ WARNING: This option when enabled will produce a LOT of logs, especially |
28801 |
++ on an active system. |
28802 |
++ |
28803 |
++config GRKERNSEC_RESLOG |
28804 |
++ bool "Resource logging" |
28805 |
++ help |
28806 |
++ If you say Y here, all attempts to overstep resource limits will |
28807 |
++ be logged with the resource name, the requested size, and the current |
28808 |
++ limit. It is highly recommended that you say Y here. If the sysctl |
28809 |
++ option is enabled, a sysctl option with name "resource_logging" is |
28810 |
++ created. If the RBAC system is enabled, the sysctl value is ignored. |
28811 |
++ |
28812 |
++config GRKERNSEC_CHROOT_EXECLOG |
28813 |
++ bool "Log execs within chroot" |
28814 |
++ help |
28815 |
++ If you say Y here, all executions inside a chroot jail will be logged |
28816 |
++ to syslog. This can cause a large amount of logs if certain |
28817 |
++ applications (eg. djb's daemontools) are installed on the system, and |
28818 |
++ is therefore left as an option. If the sysctl option is enabled, a |
28819 |
++ sysctl option with name "chroot_execlog" is created. |
28820 |
++ |
28821 |
++config GRKERNSEC_AUDIT_CHDIR |
28822 |
++ bool "Chdir logging" |
28823 |
++ help |
28824 |
++ If you say Y here, all chdir() calls will be logged. If the sysctl |
28825 |
++ option is enabled, a sysctl option with name "audit_chdir" is created. |
28826 |
++ |
28827 |
++config GRKERNSEC_AUDIT_MOUNT |
28828 |
++ bool "(Un)Mount logging" |
28829 |
++ help |
28830 |
++ If you say Y here, all mounts and unmounts will be logged. If the |
28831 |
++ sysctl option is enabled, a sysctl option with name "audit_mount" is |
28832 |
++ created. |
28833 |
++ |
28834 |
++config GRKERNSEC_AUDIT_IPC |
28835 |
++ bool "IPC logging" |
28836 |
++ help |
28837 |
++ If you say Y here, creation and removal of message queues, semaphores, |
28838 |
++ and shared memory will be logged. If the sysctl option is enabled, a |
28839 |
++ sysctl option with name "audit_ipc" is created. |
28840 |
++ |
28841 |
++config GRKERNSEC_SIGNAL |
28842 |
++ bool "Signal logging" |
28843 |
++ help |
28844 |
++ If you say Y here, certain important signals will be logged, such as |
28845 |
++ SIGSEGV, which will as a result inform you of when a error in a program |
28846 |
++ occurred, which in some cases could mean a possible exploit attempt. |
28847 |
++ If the sysctl option is enabled, a sysctl option with name |
28848 |
++ "signal_logging" is created. |
28849 |
++ |
28850 |
++config GRKERNSEC_FORKFAIL |
28851 |
++ bool "Fork failure logging" |
28852 |
++ help |
28853 |
++ If you say Y here, all failed fork() attempts will be logged. |
28854 |
++ This could suggest a fork bomb, or someone attempting to overstep |
28855 |
++ their process limit. If the sysctl option is enabled, a sysctl option |
28856 |
++ with name "forkfail_logging" is created. |
28857 |
++ |
28858 |
++config GRKERNSEC_TIME |
28859 |
++ bool "Time change logging" |
28860 |
++ help |
28861 |
++ If you say Y here, any changes of the system clock will be logged. |
28862 |
++ If the sysctl option is enabled, a sysctl option with name |
28863 |
++ "timechange_logging" is created. |
28864 |
++ |
28865 |
++config GRKERNSEC_PROC_IPADDR |
28866 |
++ bool "/proc/<pid>/ipaddr support" |
28867 |
++ help |
28868 |
++ If you say Y here, a new entry will be added to each /proc/<pid> |
28869 |
++ directory that contains the IP address of the person using the task. |
28870 |
++ The IP is carried across local TCP and AF_UNIX stream sockets. |
28871 |
++ This information can be useful for IDS/IPSes to perform remote response |
28872 |
++ to a local attack. The entry is readable by only the owner of the |
28873 |
++ process (and root if he has CAP_DAC_OVERRIDE, which can be removed via |
28874 |
++ the RBAC system), and thus does not create privacy concerns. |
28875 |
++ |
28876 |
++config GRKERNSEC_AUDIT_TEXTREL |
28877 |
++ bool 'ELF text relocations logging (READ HELP)' |
28878 |
++ depends on PAX_MPROTECT |
28879 |
++ help |
28880 |
++ If you say Y here, text relocations will be logged with the filename |
28881 |
++ of the offending library or binary. The purpose of the feature is |
28882 |
++ to help Linux distribution developers get rid of libraries and |
28883 |
++ binaries that need text relocations which hinder the future progress |
28884 |
++ of PaX. Only Linux distribution developers should say Y here, and |
28885 |
++ never on a production machine, as this option creates an information |
28886 |
++ leak that could aid an attacker in defeating the randomization of |
28887 |
++ a single memory region. If the sysctl option is enabled, a sysctl |
28888 |
++ option with name "audit_textrel" is created. |
28889 |
++ |
28890 |
++endmenu |
28891 |
++ |
28892 |
++menu "Executable Protections" |
28893 |
++depends on GRKERNSEC |
28894 |
++ |
28895 |
++config GRKERNSEC_EXECVE |
28896 |
++ bool "Enforce RLIMIT_NPROC on execs" |
28897 |
++ help |
28898 |
++ If you say Y here, users with a resource limit on processes will |
28899 |
++ have the value checked during execve() calls. The current system |
28900 |
++ only checks the system limit during fork() calls. If the sysctl option |
28901 |
++ is enabled, a sysctl option with name "execve_limiting" is created. |
28902 |
++ |
28903 |
++config GRKERNSEC_DMESG |
28904 |
++ bool "Dmesg(8) restriction" |
28905 |
++ help |
28906 |
++ If you say Y here, non-root users will not be able to use dmesg(8) |
28907 |
++ to view up to the last 4kb of messages in the kernel's log buffer. |
28908 |
++ If the sysctl option is enabled, a sysctl option with name "dmesg" is |
28909 |
++ created. |
28910 |
++ |
28911 |
++config GRKERNSEC_TPE |
28912 |
++ bool "Trusted Path Execution (TPE)" |
28913 |
++ help |
28914 |
++ If you say Y here, you will be able to choose a gid to add to the |
28915 |
++ supplementary groups of users you want to mark as "untrusted." |
28916 |
++ These users will not be able to execute any files that are not in |
28917 |
++ root-owned directories writable only by root. If the sysctl option |
28918 |
++ is enabled, a sysctl option with name "tpe" is created. |
28919 |
++ |
28920 |
++config GRKERNSEC_TPE_ALL |
28921 |
++ bool "Partially restrict non-root users" |
28922 |
++ depends on GRKERNSEC_TPE |
28923 |
++ help |
28924 |
++ If you say Y here, All non-root users other than the ones in the |
28925 |
++ group specified in the main TPE option will only be allowed to |
28926 |
++ execute files in directories they own that are not group or |
28927 |
++ world-writable, or in directories owned by root and writable only by |
28928 |
++ root. If the sysctl option is enabled, a sysctl option with name |
28929 |
++ "tpe_restrict_all" is created. |
28930 |
++ |
28931 |
++config GRKERNSEC_TPE_INVERT |
28932 |
++ bool "Invert GID option" |
28933 |
++ depends on GRKERNSEC_TPE |
28934 |
++ help |
28935 |
++ If you say Y here, the group you specify in the TPE configuration will |
28936 |
++ decide what group TPE restrictions will be *disabled* for. This |
28937 |
++ option is useful if you want TPE restrictions to be applied to most |
28938 |
++ users on the system. |
28939 |
++ |
28940 |
++config GRKERNSEC_TPE_GID |
28941 |
++ int "GID for untrusted users" |
28942 |
++ depends on GRKERNSEC_TPE && !GRKERNSEC_TPE_INVERT |
28943 |
++ default 1005 |
28944 |
++ help |
28945 |
++ If you have selected the "Invert GID option" above, setting this |
28946 |
++ GID determines what group TPE restrictions will be *disabled* for. |
28947 |
++ If you have not selected the "Invert GID option" above, setting this |
28948 |
++ GID determines what group TPE restrictions will be *enabled* for. |
28949 |
++ If the sysctl option is enabled, a sysctl option with name "tpe_gid" |
28950 |
++ is created. |
28951 |
++ |
28952 |
++config GRKERNSEC_TPE_GID |
28953 |
++ int "GID for trusted users" |
28954 |
++ depends on GRKERNSEC_TPE && GRKERNSEC_TPE_INVERT |
28955 |
++ default 1005 |
28956 |
++ help |
28957 |
++ If you have selected the "Invert GID option" above, setting this |
28958 |
++ GID determines what group TPE restrictions will be *disabled* for. |
28959 |
++ If you have not selected the "Invert GID option" above, setting this |
28960 |
++ GID determines what group TPE restrictions will be *enabled* for. |
28961 |
++ If the sysctl option is enabled, a sysctl option with name "tpe_gid" |
28962 |
++ is created. |
28963 |
++ |
28964 |
++endmenu |
28965 |
++menu "Network Protections" |
28966 |
++depends on GRKERNSEC |
28967 |
++ |
28968 |
++config GRKERNSEC_RANDNET |
28969 |
++ bool "Larger entropy pools" |
28970 |
++ help |
28971 |
++ If you say Y here, the entropy pools used for many features of Linux |
28972 |
++ and grsecurity will be doubled in size. Since several grsecurity |
28973 |
++ features use additional randomness, it is recommended that you say Y |
28974 |
++ here. Saying Y here has a similar effect as modifying |
28975 |
++ /proc/sys/kernel/random/poolsize. |
28976 |
++ |
28977 |
++config GRKERNSEC_SOCKET |
28978 |
++ bool "Socket restrictions" |
28979 |
++ help |
28980 |
++ If you say Y here, you will be able to choose from several options. |
28981 |
++ If you assign a GID on your system and add it to the supplementary |
28982 |
++ groups of users you want to restrict socket access to, this patch |
28983 |
++ will perform up to three things, based on the option(s) you choose. |
28984 |
++ |
28985 |
++config GRKERNSEC_SOCKET_ALL |
28986 |
++ bool "Deny any sockets to group" |
28987 |
++ depends on GRKERNSEC_SOCKET |
28988 |
++ help |
28989 |
++ If you say Y here, you will be able to choose a GID of whose users will |
28990 |
++ be unable to connect to other hosts from your machine or run server |
28991 |
++ applications from your machine. If the sysctl option is enabled, a |
28992 |
++ sysctl option with name "socket_all" is created. |
28993 |
++ |
28994 |
++config GRKERNSEC_SOCKET_ALL_GID |
28995 |
++ int "GID to deny all sockets for" |
28996 |
++ depends on GRKERNSEC_SOCKET_ALL |
28997 |
++ default 1004 |
28998 |
++ help |
28999 |
++ Here you can choose the GID to disable socket access for. Remember to |
29000 |
++ add the users you want socket access disabled for to the GID |
29001 |
++ specified here. If the sysctl option is enabled, a sysctl option |
29002 |
++ with name "socket_all_gid" is created. |
29003 |
++ |
29004 |
++config GRKERNSEC_SOCKET_CLIENT |
29005 |
++ bool "Deny client sockets to group" |
29006 |
++ depends on GRKERNSEC_SOCKET |
29007 |
++ help |
29008 |
++ If you say Y here, you will be able to choose a GID of whose users will |
29009 |
++ be unable to connect to other hosts from your machine, but will be |
29010 |
++ able to run servers. If this option is enabled, all users in the group |
29011 |
++ you specify will have to use passive mode when initiating ftp transfers |
29012 |
++ from the shell on your machine. If the sysctl option is enabled, a |
29013 |
++ sysctl option with name "socket_client" is created. |
29014 |
++ |
29015 |
++config GRKERNSEC_SOCKET_CLIENT_GID |
29016 |
++ int "GID to deny client sockets for" |
29017 |
++ depends on GRKERNSEC_SOCKET_CLIENT |
29018 |
++ default 1003 |
29019 |
++ help |
29020 |
++ Here you can choose the GID to disable client socket access for. |
29021 |
++ Remember to add the users you want client socket access disabled for to |
29022 |
++ the GID specified here. If the sysctl option is enabled, a sysctl |
29023 |
++ option with name "socket_client_gid" is created. |
29024 |
++ |
29025 |
++config GRKERNSEC_SOCKET_SERVER |
29026 |
++ bool "Deny server sockets to group" |
29027 |
++ depends on GRKERNSEC_SOCKET |
29028 |
++ help |
29029 |
++ If you say Y here, you will be able to choose a GID of whose users will |
29030 |
++ be unable to run server applications from your machine. If the sysctl |
29031 |
++ option is enabled, a sysctl option with name "socket_server" is created. |
29032 |
++ |
29033 |
++config GRKERNSEC_SOCKET_SERVER_GID |
29034 |
++ int "GID to deny server sockets for" |
29035 |
++ depends on GRKERNSEC_SOCKET_SERVER |
29036 |
++ default 1002 |
29037 |
++ help |
29038 |
++ Here you can choose the GID to disable server socket access for. |
29039 |
++ Remember to add the users you want server socket access disabled for to |
29040 |
++ the GID specified here. If the sysctl option is enabled, a sysctl |
29041 |
++ option with name "socket_server_gid" is created. |
29042 |
++ |
29043 |
++endmenu |
29044 |
++menu "Sysctl support" |
29045 |
++depends on GRKERNSEC && SYSCTL |
29046 |
++ |
29047 |
++config GRKERNSEC_SYSCTL |
29048 |
++ bool "Sysctl support" |
29049 |
++ help |
29050 |
++ If you say Y here, you will be able to change the options that |
29051 |
++ grsecurity runs with at bootup, without having to recompile your |
29052 |
++ kernel. You can echo values to files in /proc/sys/kernel/grsecurity |
29053 |
++ to enable (1) or disable (0) various features. All the sysctl entries |
29054 |
++ are mutable until the "grsec_lock" entry is set to a non-zero value. |
29055 |
++ All features enabled in the kernel configuration are disabled at boot |
29056 |
++ if you do not say Y to the "Turn on features by default" option. |
29057 |
++ All options should be set at startup, and the grsec_lock entry should |
29058 |
++ be set to a non-zero value after all the options are set. |
29059 |
++ *THIS IS EXTREMELY IMPORTANT* |
29060 |
++ |
29061 |
++config GRKERNSEC_SYSCTL_ON |
29062 |
++ bool "Turn on features by default" |
29063 |
++ depends on GRKERNSEC_SYSCTL |
29064 |
++ help |
29065 |
++ If you say Y here, instead of having all features enabled in the |
29066 |
++ kernel configuration disabled at boot time, the features will be |
29067 |
++ enabled at boot time. It is recommended you say Y here unless |
29068 |
++ there is some reason you would want all sysctl-tunable features to |
29069 |
++ be disabled by default. As mentioned elsewhere, it is important |
29070 |
++ to enable the grsec_lock entry once you have finished modifying |
29071 |
++ the sysctl entries. |
29072 |
++ |
29073 |
++endmenu |
29074 |
++menu "Logging Options" |
29075 |
++depends on GRKERNSEC |
29076 |
++ |
29077 |
++config GRKERNSEC_FLOODTIME |
29078 |
++ int "Seconds in between log messages (minimum)" |
29079 |
++ default 10 |
29080 |
++ help |
29081 |
++ This option allows you to enforce the number of seconds between |
29082 |
++ grsecurity log messages. The default should be suitable for most |
29083 |
++ people, however, if you choose to change it, choose a value small enough |
29084 |
++ to allow informative logs to be produced, but large enough to |
29085 |
++ prevent flooding. |
29086 |
++ |
29087 |
++config GRKERNSEC_FLOODBURST |
29088 |
++ int "Number of messages in a burst (maximum)" |
29089 |
++ default 4 |
29090 |
++ help |
29091 |
++ This option allows you to choose the maximum number of messages allowed |
29092 |
++ within the flood time interval you chose in a separate option. The |
29093 |
++ default should be suitable for most people, however if you find that |
29094 |
++ many of your logs are being interpreted as flooding, you may want to |
29095 |
++ raise this value. |
29096 |
++ |
29097 |
++endmenu |
29098 |
++ |
29099 |
++endmenu |
29100 |
+diff -urNp linux-2.6.28.8/grsecurity/Makefile linux-2.6.28.8/grsecurity/Makefile |
29101 |
+--- linux-2.6.28.8/grsecurity/Makefile 1969-12-31 19:00:00.000000000 -0500 |
29102 |
++++ linux-2.6.28.8/grsecurity/Makefile 2009-02-21 09:37:49.000000000 -0500 |
29103 |
+@@ -0,0 +1,20 @@ |
29104 |
++# grsecurity's ACL system was originally written in 2001 by Michael Dalton |
29105 |
++# during 2001-2005 it has been completely redesigned by Brad Spengler |
29106 |
++# into an RBAC system |
29107 |
++# |
29108 |
++# All code in this directory and various hooks inserted throughout the kernel |
29109 |
++# are copyright Brad Spengler, and released under the GPL v2 or higher |
29110 |
++ |
29111 |
++obj-y = grsec_chdir.o grsec_chroot.o grsec_exec.o grsec_fifo.o grsec_fork.o \ |
29112 |
++ grsec_mount.o grsec_sig.o grsec_sock.o grsec_sysctl.o \ |
29113 |
++ grsec_time.o grsec_tpe.o grsec_ipc.o grsec_link.o grsec_textrel.o |
29114 |
++ |
29115 |
++obj-$(CONFIG_GRKERNSEC) += grsec_init.o grsum.o gracl.o gracl_ip.o gracl_segv.o \ |
29116 |
++ gracl_cap.o gracl_alloc.o gracl_shm.o grsec_mem.o gracl_fs.o \ |
29117 |
++ gracl_learn.o grsec_log.o |
29118 |
++obj-$(CONFIG_GRKERNSEC_RESLOG) += gracl_res.o |
29119 |
++ |
29120 |
++ifndef CONFIG_GRKERNSEC |
29121 |
++obj-y += grsec_disabled.o |
29122 |
++endif |
29123 |
++ |
29124 |
+diff -urNp linux-2.6.28.8/include/asm-frv/kmap_types.h linux-2.6.28.8/include/asm-frv/kmap_types.h |
29125 |
+--- linux-2.6.28.8/include/asm-frv/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
29126 |
++++ linux-2.6.28.8/include/asm-frv/kmap_types.h 2009-02-21 09:37:49.000000000 -0500 |
29127 |
+@@ -23,6 +23,7 @@ enum km_type { |
29128 |
+ KM_IRQ1, |
29129 |
+ KM_SOFTIRQ0, |
29130 |
+ KM_SOFTIRQ1, |
29131 |
++ KM_CLEARPAGE, |
29132 |
+ KM_TYPE_NR |
29133 |
+ }; |
29134 |
+ |
29135 |
+diff -urNp linux-2.6.28.8/include/asm-generic/futex.h linux-2.6.28.8/include/asm-generic/futex.h |
29136 |
+--- linux-2.6.28.8/include/asm-generic/futex.h 2009-02-06 16:47:45.000000000 -0500 |
29137 |
++++ linux-2.6.28.8/include/asm-generic/futex.h 2009-02-21 09:37:49.000000000 -0500 |
29138 |
+@@ -6,7 +6,7 @@ |
29139 |
+ #include <asm/errno.h> |
29140 |
+ |
29141 |
+ static inline int |
29142 |
+-futex_atomic_op_inuser (int encoded_op, int __user *uaddr) |
29143 |
++futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr) |
29144 |
+ { |
29145 |
+ int op = (encoded_op >> 28) & 7; |
29146 |
+ int cmp = (encoded_op >> 24) & 15; |
29147 |
+@@ -48,7 +48,7 @@ futex_atomic_op_inuser (int encoded_op, |
29148 |
+ } |
29149 |
+ |
29150 |
+ static inline int |
29151 |
+-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval) |
29152 |
++futex_atomic_cmpxchg_inatomic(u32 __user *uaddr, int oldval, int newval) |
29153 |
+ { |
29154 |
+ return -ENOSYS; |
29155 |
+ } |
29156 |
+diff -urNp linux-2.6.28.8/include/asm-generic/vmlinux.lds.h linux-2.6.28.8/include/asm-generic/vmlinux.lds.h |
29157 |
+--- linux-2.6.28.8/include/asm-generic/vmlinux.lds.h 2009-02-06 16:47:45.000000000 -0500 |
29158 |
++++ linux-2.6.28.8/include/asm-generic/vmlinux.lds.h 2009-02-21 09:37:49.000000000 -0500 |
29159 |
+@@ -69,6 +69,7 @@ |
29160 |
+ .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \ |
29161 |
+ VMLINUX_SYMBOL(__start_rodata) = .; \ |
29162 |
+ *(.rodata) *(.rodata.*) \ |
29163 |
++ *(.data.read_only) \ |
29164 |
+ *(__vermagic) /* Kernel version magic */ \ |
29165 |
+ *(__markers_strings) /* Markers: strings */ \ |
29166 |
+ *(__tracepoints_strings)/* Tracepoints: strings */ \ |
29167 |
+diff -urNp linux-2.6.28.8/include/asm-m32r/kmap_types.h linux-2.6.28.8/include/asm-m32r/kmap_types.h |
29168 |
+--- linux-2.6.28.8/include/asm-m32r/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
29169 |
++++ linux-2.6.28.8/include/asm-m32r/kmap_types.h 2009-02-21 09:37:49.000000000 -0500 |
29170 |
+@@ -21,7 +21,8 @@ D(9) KM_IRQ0, |
29171 |
+ D(10) KM_IRQ1, |
29172 |
+ D(11) KM_SOFTIRQ0, |
29173 |
+ D(12) KM_SOFTIRQ1, |
29174 |
+-D(13) KM_TYPE_NR |
29175 |
++D(13) KM_CLEARPAGE, |
29176 |
++D(14) KM_TYPE_NR |
29177 |
+ }; |
29178 |
+ |
29179 |
+ #undef D |
29180 |
+diff -urNp linux-2.6.28.8/include/asm-m68k/kmap_types.h linux-2.6.28.8/include/asm-m68k/kmap_types.h |
29181 |
+--- linux-2.6.28.8/include/asm-m68k/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
29182 |
++++ linux-2.6.28.8/include/asm-m68k/kmap_types.h 2009-02-21 09:37:49.000000000 -0500 |
29183 |
+@@ -15,6 +15,7 @@ enum km_type { |
29184 |
+ KM_IRQ1, |
29185 |
+ KM_SOFTIRQ0, |
29186 |
+ KM_SOFTIRQ1, |
29187 |
++ KM_CLEARPAGE, |
29188 |
+ KM_TYPE_NR |
29189 |
+ }; |
29190 |
+ |
29191 |
+diff -urNp linux-2.6.28.8/include/asm-mn10300/kmap_types.h linux-2.6.28.8/include/asm-mn10300/kmap_types.h |
29192 |
+--- linux-2.6.28.8/include/asm-mn10300/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
29193 |
++++ linux-2.6.28.8/include/asm-mn10300/kmap_types.h 2009-02-21 09:37:49.000000000 -0500 |
29194 |
+@@ -25,6 +25,7 @@ enum km_type { |
29195 |
+ KM_IRQ1, |
29196 |
+ KM_SOFTIRQ0, |
29197 |
+ KM_SOFTIRQ1, |
29198 |
++ KM_CLEARPAGE, |
29199 |
+ KM_TYPE_NR |
29200 |
+ }; |
29201 |
+ |
29202 |
+diff -urNp linux-2.6.28.8/include/asm-xtensa/kmap_types.h linux-2.6.28.8/include/asm-xtensa/kmap_types.h |
29203 |
+--- linux-2.6.28.8/include/asm-xtensa/kmap_types.h 2009-02-06 16:47:45.000000000 -0500 |
29204 |
++++ linux-2.6.28.8/include/asm-xtensa/kmap_types.h 2009-02-21 09:37:49.000000000 -0500 |
29205 |
+@@ -25,6 +25,7 @@ enum km_type { |
29206 |
+ KM_IRQ1, |
29207 |
+ KM_SOFTIRQ0, |
29208 |
+ KM_SOFTIRQ1, |
29209 |
++ KM_CLEARPAGE, |
29210 |
+ KM_TYPE_NR |
29211 |
+ }; |
29212 |
+ |
29213 |
+diff -urNp linux-2.6.28.8/include/drm/drm_pciids.h linux-2.6.28.8/include/drm/drm_pciids.h |
29214 |
+--- linux-2.6.28.8/include/drm/drm_pciids.h 2009-02-06 16:47:45.000000000 -0500 |
29215 |
++++ linux-2.6.28.8/include/drm/drm_pciids.h 2009-02-21 09:37:49.000000000 -0500 |
29216 |
+@@ -243,7 +243,7 @@ |
29217 |
+ {0x1002, 0x796d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \ |
29218 |
+ {0x1002, 0x796e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \ |
29219 |
+ {0x1002, 0x796f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_RS740|RADEON_IS_IGP|RADEON_NEW_MEMMAP|RADEON_IS_IGPGART}, \ |
29220 |
+- {0, 0, 0} |
29221 |
++ {0, 0, 0, 0, 0, 0} |
29222 |
+ |
29223 |
+ #define r128_PCI_IDS \ |
29224 |
+ {0x1002, 0x4c45, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29225 |
+@@ -283,14 +283,14 @@ |
29226 |
+ {0x1002, 0x5446, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29227 |
+ {0x1002, 0x544C, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29228 |
+ {0x1002, 0x5452, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29229 |
+- {0, 0, 0} |
29230 |
++ {0, 0, 0, 0, 0, 0} |
29231 |
+ |
29232 |
+ #define mga_PCI_IDS \ |
29233 |
+ {0x102b, 0x0520, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \ |
29234 |
+ {0x102b, 0x0521, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G200}, \ |
29235 |
+ {0x102b, 0x0525, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G400}, \ |
29236 |
+ {0x102b, 0x2527, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MGA_CARD_TYPE_G550}, \ |
29237 |
+- {0, 0, 0} |
29238 |
++ {0, 0, 0, 0, 0, 0} |
29239 |
+ |
29240 |
+ #define mach64_PCI_IDS \ |
29241 |
+ {0x1002, 0x4749, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29242 |
+@@ -313,7 +313,7 @@ |
29243 |
+ {0x1002, 0x4c53, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29244 |
+ {0x1002, 0x4c4d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29245 |
+ {0x1002, 0x4c4e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29246 |
+- {0, 0, 0} |
29247 |
++ {0, 0, 0, 0, 0, 0} |
29248 |
+ |
29249 |
+ #define sisdrv_PCI_IDS \ |
29250 |
+ {0x1039, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29251 |
+@@ -324,7 +324,7 @@ |
29252 |
+ {0x1039, 0x7300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29253 |
+ {0x18CA, 0x0040, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \ |
29254 |
+ {0x18CA, 0x0042, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_CHIP_315}, \ |
29255 |
+- {0, 0, 0} |
29256 |
++ {0, 0, 0, 0, 0, 0} |
29257 |
+ |
29258 |
+ #define tdfx_PCI_IDS \ |
29259 |
+ {0x121a, 0x0003, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29260 |
+@@ -333,7 +333,7 @@ |
29261 |
+ {0x121a, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29262 |
+ {0x121a, 0x0009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29263 |
+ {0x121a, 0x000b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29264 |
+- {0, 0, 0} |
29265 |
++ {0, 0, 0, 0, 0, 0} |
29266 |
+ |
29267 |
+ #define viadrv_PCI_IDS \ |
29268 |
+ {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29269 |
+@@ -345,25 +345,25 @@ |
29270 |
+ {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29271 |
+ {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \ |
29272 |
+ {0x1106, 0x3157, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \ |
29273 |
+- {0, 0, 0} |
29274 |
++ {0, 0, 0, 0, 0, 0} |
29275 |
+ |
29276 |
+ #define i810_PCI_IDS \ |
29277 |
+ {0x8086, 0x7121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29278 |
+ {0x8086, 0x7123, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29279 |
+ {0x8086, 0x7125, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29280 |
+ {0x8086, 0x1132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29281 |
+- {0, 0, 0} |
29282 |
++ {0, 0, 0, 0, 0, 0} |
29283 |
+ |
29284 |
+ #define i830_PCI_IDS \ |
29285 |
+ {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29286 |
+ {0x8086, 0x2562, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29287 |
+ {0x8086, 0x3582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29288 |
+ {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29289 |
+- {0, 0, 0} |
29290 |
++ {0, 0, 0, 0, 0, 0} |
29291 |
+ |
29292 |
+ #define gamma_PCI_IDS \ |
29293 |
+ {0x3d3d, 0x0008, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ |
29294 |
+- {0, 0, 0} |
29295 |
++ {0, 0, 0, 0, 0, 0} |
29296 |
+ |
29297 |
+ #define savage_PCI_IDS \ |
29298 |
+ {0x5333, 0x8a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_SAVAGE3D}, \ |
29299 |
+@@ -389,10 +389,10 @@ |
29300 |
+ {0x5333, 0x8d02, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_TWISTER}, \ |
29301 |
+ {0x5333, 0x8d03, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \ |
29302 |
+ {0x5333, 0x8d04, PCI_ANY_ID, PCI_ANY_ID, 0, 0, S3_PROSAVAGEDDR}, \ |
29303 |
+- {0, 0, 0} |
29304 |
++ {0, 0, 0, 0, 0, 0} |
29305 |
+ |
29306 |
+ #define ffb_PCI_IDS \ |
29307 |
+- {0, 0, 0} |
29308 |
++ {0, 0, 0, 0, 0, 0} |
29309 |
+ |
29310 |
+ #define i915_PCI_IDS \ |
29311 |
+ {0x8086, 0x3577, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ |
29312 |
+@@ -418,4 +418,4 @@ |
29313 |
+ {0x8086, 0x2e02, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ |
29314 |
+ {0x8086, 0x2e12, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ |
29315 |
+ {0x8086, 0x2e22, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, 0xffff00, 0}, \ |
29316 |
+- {0, 0, 0} |
29317 |
++ {0, 0, 0, 0, 0, 0} |
29318 |
+diff -urNp linux-2.6.28.8/include/linux/a.out.h linux-2.6.28.8/include/linux/a.out.h |
29319 |
+--- linux-2.6.28.8/include/linux/a.out.h 2009-02-06 16:47:45.000000000 -0500 |
29320 |
++++ linux-2.6.28.8/include/linux/a.out.h 2009-02-21 09:37:49.000000000 -0500 |
29321 |
+@@ -39,6 +39,14 @@ enum machine_type { |
29322 |
+ M_MIPS2 = 152 /* MIPS R6000/R4000 binary */ |
29323 |
+ }; |
29324 |
+ |
29325 |
++/* Constants for the N_FLAGS field */ |
29326 |
++#define F_PAX_PAGEEXEC 1 /* Paging based non-executable pages */ |
29327 |
++#define F_PAX_EMUTRAMP 2 /* Emulate trampolines */ |
29328 |
++#define F_PAX_MPROTECT 4 /* Restrict mprotect() */ |
29329 |
++#define F_PAX_RANDMMAP 8 /* Randomize mmap() base */ |
29330 |
++/*#define F_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */ |
29331 |
++#define F_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */ |
29332 |
++ |
29333 |
+ #if !defined (N_MAGIC) |
29334 |
+ #define N_MAGIC(exec) ((exec).a_info & 0xffff) |
29335 |
+ #endif |
29336 |
+diff -urNp linux-2.6.28.8/include/linux/binfmts.h linux-2.6.28.8/include/linux/binfmts.h |
29337 |
+--- linux-2.6.28.8/include/linux/binfmts.h 2009-02-06 16:47:45.000000000 -0500 |
29338 |
++++ linux-2.6.28.8/include/linux/binfmts.h 2009-02-21 09:37:49.000000000 -0500 |
29339 |
+@@ -74,6 +74,7 @@ struct linux_binfmt { |
29340 |
+ int (*load_binary)(struct linux_binprm *, struct pt_regs * regs); |
29341 |
+ int (*load_shlib)(struct file *); |
29342 |
+ int (*core_dump)(long signr, struct pt_regs *regs, struct file *file, unsigned long limit); |
29343 |
++ void (*handle_mprotect)(struct vm_area_struct *vma, unsigned long newflags); |
29344 |
+ unsigned long min_coredump; /* minimal dump size */ |
29345 |
+ int hasvdso; |
29346 |
+ }; |
29347 |
+diff -urNp linux-2.6.28.8/include/linux/cache.h linux-2.6.28.8/include/linux/cache.h |
29348 |
+--- linux-2.6.28.8/include/linux/cache.h 2009-02-06 16:47:45.000000000 -0500 |
29349 |
++++ linux-2.6.28.8/include/linux/cache.h 2009-02-21 09:37:49.000000000 -0500 |
29350 |
+@@ -16,6 +16,10 @@ |
29351 |
+ #define __read_mostly |
29352 |
+ #endif |
29353 |
+ |
29354 |
++#ifndef __read_only |
29355 |
++#define __read_only __read_mostly |
29356 |
++#endif |
29357 |
++ |
29358 |
+ #ifndef ____cacheline_aligned |
29359 |
+ #define ____cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES))) |
29360 |
+ #endif |
29361 |
+diff -urNp linux-2.6.28.8/include/linux/capability.h linux-2.6.28.8/include/linux/capability.h |
29362 |
+--- linux-2.6.28.8/include/linux/capability.h 2009-02-06 16:47:45.000000000 -0500 |
29363 |
++++ linux-2.6.28.8/include/linux/capability.h 2009-02-21 09:37:49.000000000 -0500 |
29364 |
+@@ -516,6 +516,7 @@ kernel_cap_t cap_set_effective(const ker |
29365 |
+ #define has_capability(t, cap) (security_capable((t), (cap)) == 0) |
29366 |
+ |
29367 |
+ extern int capable(int cap); |
29368 |
++int capable_nolog(int cap); |
29369 |
+ |
29370 |
+ #endif /* __KERNEL__ */ |
29371 |
+ |
29372 |
+diff -urNp linux-2.6.28.8/include/linux/cpumask.h linux-2.6.28.8/include/linux/cpumask.h |
29373 |
+--- linux-2.6.28.8/include/linux/cpumask.h 2009-02-06 16:47:45.000000000 -0500 |
29374 |
++++ linux-2.6.28.8/include/linux/cpumask.h 2009-02-21 09:37:49.000000000 -0500 |
29375 |
+@@ -142,7 +142,6 @@ |
29376 |
+ #include <linux/bitmap.h> |
29377 |
+ |
29378 |
+ typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t; |
29379 |
+-extern cpumask_t _unused_cpumask_arg_; |
29380 |
+ |
29381 |
+ #define cpu_set(cpu, dst) __cpu_set((cpu), &(dst)) |
29382 |
+ static inline void __cpu_set(int cpu, volatile cpumask_t *dstp) |
29383 |
+diff -urNp linux-2.6.28.8/include/linux/elf.h linux-2.6.28.8/include/linux/elf.h |
29384 |
+--- linux-2.6.28.8/include/linux/elf.h 2009-02-06 16:47:45.000000000 -0500 |
29385 |
++++ linux-2.6.28.8/include/linux/elf.h 2009-02-21 09:37:49.000000000 -0500 |
29386 |
+@@ -49,6 +49,17 @@ typedef __s64 Elf64_Sxword; |
29387 |
+ #define PT_GNU_EH_FRAME 0x6474e550 |
29388 |
+ |
29389 |
+ #define PT_GNU_STACK (PT_LOOS + 0x474e551) |
29390 |
++#define PT_GNU_RELRO (PT_LOOS + 0x474e552) |
29391 |
++ |
29392 |
++#define PT_PAX_FLAGS (PT_LOOS + 0x5041580) |
29393 |
++ |
29394 |
++/* Constants for the e_flags field */ |
29395 |
++#define EF_PAX_PAGEEXEC 1 /* Paging based non-executable pages */ |
29396 |
++#define EF_PAX_EMUTRAMP 2 /* Emulate trampolines */ |
29397 |
++#define EF_PAX_MPROTECT 4 /* Restrict mprotect() */ |
29398 |
++#define EF_PAX_RANDMMAP 8 /* Randomize mmap() base */ |
29399 |
++/*#define EF_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */ |
29400 |
++#define EF_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */ |
29401 |
+ |
29402 |
+ /* These constants define the different elf file types */ |
29403 |
+ #define ET_NONE 0 |
29404 |
+@@ -84,6 +95,8 @@ typedef __s64 Elf64_Sxword; |
29405 |
+ #define DT_DEBUG 21 |
29406 |
+ #define DT_TEXTREL 22 |
29407 |
+ #define DT_JMPREL 23 |
29408 |
++#define DT_FLAGS 30 |
29409 |
++ #define DF_TEXTREL 0x00000004 |
29410 |
+ #define DT_ENCODING 32 |
29411 |
+ #define OLD_DT_LOOS 0x60000000 |
29412 |
+ #define DT_LOOS 0x6000000d |
29413 |
+@@ -230,6 +243,19 @@ typedef struct elf64_hdr { |
29414 |
+ #define PF_W 0x2 |
29415 |
+ #define PF_X 0x1 |
29416 |
+ |
29417 |
++#define PF_PAGEEXEC (1U << 4) /* Enable PAGEEXEC */ |
29418 |
++#define PF_NOPAGEEXEC (1U << 5) /* Disable PAGEEXEC */ |
29419 |
++#define PF_SEGMEXEC (1U << 6) /* Enable SEGMEXEC */ |
29420 |
++#define PF_NOSEGMEXEC (1U << 7) /* Disable SEGMEXEC */ |
29421 |
++#define PF_MPROTECT (1U << 8) /* Enable MPROTECT */ |
29422 |
++#define PF_NOMPROTECT (1U << 9) /* Disable MPROTECT */ |
29423 |
++/*#define PF_RANDEXEC (1U << 10)*/ /* Enable RANDEXEC */ |
29424 |
++/*#define PF_NORANDEXEC (1U << 11)*/ /* Disable RANDEXEC */ |
29425 |
++#define PF_EMUTRAMP (1U << 12) /* Enable EMUTRAMP */ |
29426 |
++#define PF_NOEMUTRAMP (1U << 13) /* Disable EMUTRAMP */ |
29427 |
++#define PF_RANDMMAP (1U << 14) /* Enable RANDMMAP */ |
29428 |
++#define PF_NORANDMMAP (1U << 15) /* Disable RANDMMAP */ |
29429 |
++ |
29430 |
+ typedef struct elf32_phdr{ |
29431 |
+ Elf32_Word p_type; |
29432 |
+ Elf32_Off p_offset; |
29433 |
+@@ -322,6 +348,8 @@ typedef struct elf64_shdr { |
29434 |
+ #define EI_OSABI 7 |
29435 |
+ #define EI_PAD 8 |
29436 |
+ |
29437 |
++#define EI_PAX 14 |
29438 |
++ |
29439 |
+ #define ELFMAG0 0x7f /* EI_MAG */ |
29440 |
+ #define ELFMAG1 'E' |
29441 |
+ #define ELFMAG2 'L' |
29442 |
+@@ -384,6 +412,7 @@ extern Elf32_Dyn _DYNAMIC []; |
29443 |
+ #define elf_phdr elf32_phdr |
29444 |
+ #define elf_note elf32_note |
29445 |
+ #define elf_addr_t Elf32_Off |
29446 |
++#define elf_dyn Elf32_Dyn |
29447 |
+ |
29448 |
+ #else |
29449 |
+ |
29450 |
+@@ -392,6 +421,7 @@ extern Elf64_Dyn _DYNAMIC []; |
29451 |
+ #define elf_phdr elf64_phdr |
29452 |
+ #define elf_note elf64_note |
29453 |
+ #define elf_addr_t Elf64_Off |
29454 |
++#define elf_dyn Elf64_Dyn |
29455 |
+ |
29456 |
+ #endif |
29457 |
+ |
29458 |
+diff -urNp linux-2.6.28.8/include/linux/gracl.h linux-2.6.28.8/include/linux/gracl.h |
29459 |
+--- linux-2.6.28.8/include/linux/gracl.h 1969-12-31 19:00:00.000000000 -0500 |
29460 |
++++ linux-2.6.28.8/include/linux/gracl.h 2009-02-21 09:37:49.000000000 -0500 |
29461 |
+@@ -0,0 +1,318 @@ |
29462 |
++#ifndef GR_ACL_H |
29463 |
++#define GR_ACL_H |
29464 |
++ |
29465 |
++#include <linux/grdefs.h> |
29466 |
++#include <linux/resource.h> |
29467 |
++#include <linux/capability.h> |
29468 |
++#include <linux/dcache.h> |
29469 |
++#include <asm/resource.h> |
29470 |
++ |
29471 |
++/* Major status information */ |
29472 |
++ |
29473 |
++#define GR_VERSION "grsecurity 2.1.13" |
29474 |
++#define GRSECURITY_VERSION 0x2113 |
29475 |
++ |
29476 |
++enum { |
29477 |
++ GR_SHUTDOWN = 0, |
29478 |
++ GR_ENABLE = 1, |
29479 |
++ GR_SPROLE = 2, |
29480 |
++ GR_RELOAD = 3, |
29481 |
++ GR_SEGVMOD = 4, |
29482 |
++ GR_STATUS = 5, |
29483 |
++ GR_UNSPROLE = 6, |
29484 |
++ GR_PASSSET = 7, |
29485 |
++ GR_SPROLEPAM = 8, |
29486 |
++}; |
29487 |
++ |
29488 |
++/* Password setup definitions |
29489 |
++ * kernel/grhash.c */ |
29490 |
++enum { |
29491 |
++ GR_PW_LEN = 128, |
29492 |
++ GR_SALT_LEN = 16, |
29493 |
++ GR_SHA_LEN = 32, |
29494 |
++}; |
29495 |
++ |
29496 |
++enum { |
29497 |
++ GR_SPROLE_LEN = 64, |
29498 |
++}; |
29499 |
++ |
29500 |
++#define GR_NLIMITS (RLIMIT_LOCKS + 2) |
29501 |
++ |
29502 |
++/* Begin Data Structures */ |
29503 |
++ |
29504 |
++struct sprole_pw { |
29505 |
++ unsigned char *rolename; |
29506 |
++ unsigned char salt[GR_SALT_LEN]; |
29507 |
++ unsigned char sum[GR_SHA_LEN]; /* 256-bit SHA hash of the password */ |
29508 |
++}; |
29509 |
++ |
29510 |
++struct name_entry { |
29511 |
++ __u32 key; |
29512 |
++ ino_t inode; |
29513 |
++ dev_t device; |
29514 |
++ char *name; |
29515 |
++ __u16 len; |
29516 |
++ __u8 deleted; |
29517 |
++ struct name_entry *prev; |
29518 |
++ struct name_entry *next; |
29519 |
++}; |
29520 |
++ |
29521 |
++struct inodev_entry { |
29522 |
++ struct name_entry *nentry; |
29523 |
++ struct inodev_entry *prev; |
29524 |
++ struct inodev_entry *next; |
29525 |
++}; |
29526 |
++ |
29527 |
++struct acl_role_db { |
29528 |
++ struct acl_role_label **r_hash; |
29529 |
++ __u32 r_size; |
29530 |
++}; |
29531 |
++ |
29532 |
++struct inodev_db { |
29533 |
++ struct inodev_entry **i_hash; |
29534 |
++ __u32 i_size; |
29535 |
++}; |
29536 |
++ |
29537 |
++struct name_db { |
29538 |
++ struct name_entry **n_hash; |
29539 |
++ __u32 n_size; |
29540 |
++}; |
29541 |
++ |
29542 |
++struct crash_uid { |
29543 |
++ uid_t uid; |
29544 |
++ unsigned long expires; |
29545 |
++}; |
29546 |
++ |
29547 |
++struct gr_hash_struct { |
29548 |
++ void **table; |
29549 |
++ void **nametable; |
29550 |
++ void *first; |
29551 |
++ __u32 table_size; |
29552 |
++ __u32 used_size; |
29553 |
++ int type; |
29554 |
++}; |
29555 |
++ |
29556 |
++/* Userspace Grsecurity ACL data structures */ |
29557 |
++ |
29558 |
++struct acl_subject_label { |
29559 |
++ char *filename; |
29560 |
++ ino_t inode; |
29561 |
++ dev_t device; |
29562 |
++ __u32 mode; |
29563 |
++ kernel_cap_t cap_mask; |
29564 |
++ kernel_cap_t cap_lower; |
29565 |
++ |
29566 |
++ struct rlimit res[GR_NLIMITS]; |
29567 |
++ __u16 resmask; |
29568 |
++ |
29569 |
++ __u8 user_trans_type; |
29570 |
++ __u8 group_trans_type; |
29571 |
++ uid_t *user_transitions; |
29572 |
++ gid_t *group_transitions; |
29573 |
++ __u16 user_trans_num; |
29574 |
++ __u16 group_trans_num; |
29575 |
++ |
29576 |
++ __u32 ip_proto[8]; |
29577 |
++ __u32 ip_type; |
29578 |
++ struct acl_ip_label **ips; |
29579 |
++ __u32 ip_num; |
29580 |
++ __u32 inaddr_any_override; |
29581 |
++ |
29582 |
++ __u32 crashes; |
29583 |
++ unsigned long expires; |
29584 |
++ |
29585 |
++ struct acl_subject_label *parent_subject; |
29586 |
++ struct gr_hash_struct *hash; |
29587 |
++ struct acl_subject_label *prev; |
29588 |
++ struct acl_subject_label *next; |
29589 |
++ |
29590 |
++ struct acl_object_label **obj_hash; |
29591 |
++ __u32 obj_hash_size; |
29592 |
++ __u16 pax_flags; |
29593 |
++}; |
29594 |
++ |
29595 |
++struct role_allowed_ip { |
29596 |
++ __u32 addr; |
29597 |
++ __u32 netmask; |
29598 |
++ |
29599 |
++ struct role_allowed_ip *prev; |
29600 |
++ struct role_allowed_ip *next; |
29601 |
++}; |
29602 |
++ |
29603 |
++struct role_transition { |
29604 |
++ char *rolename; |
29605 |
++ |
29606 |
++ struct role_transition *prev; |
29607 |
++ struct role_transition *next; |
29608 |
++}; |
29609 |
++ |
29610 |
++struct acl_role_label { |
29611 |
++ char *rolename; |
29612 |
++ uid_t uidgid; |
29613 |
++ __u16 roletype; |
29614 |
++ |
29615 |
++ __u16 auth_attempts; |
29616 |
++ unsigned long expires; |
29617 |
++ |
29618 |
++ struct acl_subject_label *root_label; |
29619 |
++ struct gr_hash_struct *hash; |
29620 |
++ |
29621 |
++ struct acl_role_label *prev; |
29622 |
++ struct acl_role_label *next; |
29623 |
++ |
29624 |
++ struct role_transition *transitions; |
29625 |
++ struct role_allowed_ip *allowed_ips; |
29626 |
++ uid_t *domain_children; |
29627 |
++ __u16 domain_child_num; |
29628 |
++ |
29629 |
++ struct acl_subject_label **subj_hash; |
29630 |
++ __u32 subj_hash_size; |
29631 |
++}; |
29632 |
++ |
29633 |
++struct user_acl_role_db { |
29634 |
++ struct acl_role_label **r_table; |
29635 |
++ __u32 num_pointers; /* Number of allocations to track */ |
29636 |
++ __u32 num_roles; /* Number of roles */ |
29637 |
++ __u32 num_domain_children; /* Number of domain children */ |
29638 |
++ __u32 num_subjects; /* Number of subjects */ |
29639 |
++ __u32 num_objects; /* Number of objects */ |
29640 |
++}; |
29641 |
++ |
29642 |
++struct acl_object_label { |
29643 |
++ char *filename; |
29644 |
++ ino_t inode; |
29645 |
++ dev_t device; |
29646 |
++ __u32 mode; |
29647 |
++ |
29648 |
++ struct acl_subject_label *nested; |
29649 |
++ struct acl_object_label *globbed; |
29650 |
++ |
29651 |
++ /* next two structures not used */ |
29652 |
++ |
29653 |
++ struct acl_object_label *prev; |
29654 |
++ struct acl_object_label *next; |
29655 |
++}; |
29656 |
++ |
29657 |
++struct acl_ip_label { |
29658 |
++ char *iface; |
29659 |
++ __u32 addr; |
29660 |
++ __u32 netmask; |
29661 |
++ __u16 low, high; |
29662 |
++ __u8 mode; |
29663 |
++ __u32 type; |
29664 |
++ __u32 proto[8]; |
29665 |
++ |
29666 |
++ /* next two structures not used */ |
29667 |
++ |
29668 |
++ struct acl_ip_label *prev; |
29669 |
++ struct acl_ip_label *next; |
29670 |
++}; |
29671 |
++ |
29672 |
++struct gr_arg { |
29673 |
++ struct user_acl_role_db role_db; |
29674 |
++ unsigned char pw[GR_PW_LEN]; |
29675 |
++ unsigned char salt[GR_SALT_LEN]; |
29676 |
++ unsigned char sum[GR_SHA_LEN]; |
29677 |
++ unsigned char sp_role[GR_SPROLE_LEN]; |
29678 |
++ struct sprole_pw *sprole_pws; |
29679 |
++ dev_t segv_device; |
29680 |
++ ino_t segv_inode; |
29681 |
++ uid_t segv_uid; |
29682 |
++ __u16 num_sprole_pws; |
29683 |
++ __u16 mode; |
29684 |
++}; |
29685 |
++ |
29686 |
++struct gr_arg_wrapper { |
29687 |
++ struct gr_arg *arg; |
29688 |
++ __u32 version; |
29689 |
++ __u32 size; |
29690 |
++}; |
29691 |
++ |
29692 |
++struct subject_map { |
29693 |
++ struct acl_subject_label *user; |
29694 |
++ struct acl_subject_label *kernel; |
29695 |
++ struct subject_map *prev; |
29696 |
++ struct subject_map *next; |
29697 |
++}; |
29698 |
++ |
29699 |
++struct acl_subj_map_db { |
29700 |
++ struct subject_map **s_hash; |
29701 |
++ __u32 s_size; |
29702 |
++}; |
29703 |
++ |
29704 |
++/* End Data Structures Section */ |
29705 |
++ |
29706 |
++/* Hash functions generated by empirical testing by Brad Spengler |
29707 |
++ Makes good use of the low bits of the inode. Generally 0-1 times |
29708 |
++ in loop for successful match. 0-3 for unsuccessful match. |
29709 |
++ Shift/add algorithm with modulus of table size and an XOR*/ |
29710 |
++ |
29711 |
++static __inline__ unsigned int |
29712 |
++rhash(const uid_t uid, const __u16 type, const unsigned int sz) |
29713 |
++{ |
29714 |
++ return (((uid << type) + (uid ^ type)) % sz); |
29715 |
++} |
29716 |
++ |
29717 |
++ static __inline__ unsigned int |
29718 |
++shash(const struct acl_subject_label *userp, const unsigned int sz) |
29719 |
++{ |
29720 |
++ return ((const unsigned long)userp % sz); |
29721 |
++} |
29722 |
++ |
29723 |
++static __inline__ unsigned int |
29724 |
++fhash(const ino_t ino, const dev_t dev, const unsigned int sz) |
29725 |
++{ |
29726 |
++ return (((ino + dev) ^ ((ino << 13) + (ino << 23) + (dev << 9))) % sz); |
29727 |
++} |
29728 |
++ |
29729 |
++static __inline__ unsigned int |
29730 |
++nhash(const char *name, const __u16 len, const unsigned int sz) |
29731 |
++{ |
29732 |
++ return full_name_hash(name, len) % sz; |
29733 |
++} |
29734 |
++ |
29735 |
++#define FOR_EACH_ROLE_START(role,iter) \ |
29736 |
++ role = NULL; \ |
29737 |
++ iter = 0; \ |
29738 |
++ while (iter < acl_role_set.r_size) { \ |
29739 |
++ if (role == NULL) \ |
29740 |
++ role = acl_role_set.r_hash[iter]; \ |
29741 |
++ if (role == NULL) { \ |
29742 |
++ iter++; \ |
29743 |
++ continue; \ |
29744 |
++ } |
29745 |
++ |
29746 |
++#define FOR_EACH_ROLE_END(role,iter) \ |
29747 |
++ role = role->next; \ |
29748 |
++ if (role == NULL) \ |
29749 |
++ iter++; \ |
29750 |
++ } |
29751 |
++ |
29752 |
++#define FOR_EACH_SUBJECT_START(role,subj,iter) \ |
29753 |
++ subj = NULL; \ |
29754 |
++ iter = 0; \ |
29755 |
++ while (iter < role->subj_hash_size) { \ |
29756 |
++ if (subj == NULL) \ |
29757 |
++ subj = role->subj_hash[iter]; \ |
29758 |
++ if (subj == NULL) { \ |
29759 |
++ iter++; \ |
29760 |
++ continue; \ |
29761 |
++ } |
29762 |
++ |
29763 |
++#define FOR_EACH_SUBJECT_END(subj,iter) \ |
29764 |
++ subj = subj->next; \ |
29765 |
++ if (subj == NULL) \ |
29766 |
++ iter++; \ |
29767 |
++ } |
29768 |
++ |
29769 |
++ |
29770 |
++#define FOR_EACH_NESTED_SUBJECT_START(role,subj) \ |
29771 |
++ subj = role->hash->first; \ |
29772 |
++ while (subj != NULL) { |
29773 |
++ |
29774 |
++#define FOR_EACH_NESTED_SUBJECT_END(subj) \ |
29775 |
++ subj = subj->next; \ |
29776 |
++ } |
29777 |
++ |
29778 |
++#endif |
29779 |
++ |
29780 |
+diff -urNp linux-2.6.28.8/include/linux/gralloc.h linux-2.6.28.8/include/linux/gralloc.h |
29781 |
+--- linux-2.6.28.8/include/linux/gralloc.h 1969-12-31 19:00:00.000000000 -0500 |
29782 |
++++ linux-2.6.28.8/include/linux/gralloc.h 2009-02-21 09:37:49.000000000 -0500 |
29783 |
+@@ -0,0 +1,8 @@ |
29784 |
++#ifndef __GRALLOC_H |
29785 |
++#define __GRALLOC_H |
29786 |
++ |
29787 |
++void acl_free_all(void); |
29788 |
++int acl_alloc_stack_init(unsigned long size); |
29789 |
++void *acl_alloc(unsigned long len); |
29790 |
++ |
29791 |
++#endif |
29792 |
+diff -urNp linux-2.6.28.8/include/linux/grdefs.h linux-2.6.28.8/include/linux/grdefs.h |
29793 |
+--- linux-2.6.28.8/include/linux/grdefs.h 1969-12-31 19:00:00.000000000 -0500 |
29794 |
++++ linux-2.6.28.8/include/linux/grdefs.h 2009-02-21 09:37:49.000000000 -0500 |
29795 |
+@@ -0,0 +1,131 @@ |
29796 |
++#ifndef GRDEFS_H |
29797 |
++#define GRDEFS_H |
29798 |
++ |
29799 |
++/* Begin grsecurity status declarations */ |
29800 |
++ |
29801 |
++enum { |
29802 |
++ GR_READY = 0x01, |
29803 |
++ GR_STATUS_INIT = 0x00 // disabled state |
29804 |
++}; |
29805 |
++ |
29806 |
++/* Begin ACL declarations */ |
29807 |
++ |
29808 |
++/* Role flags */ |
29809 |
++ |
29810 |
++enum { |
29811 |
++ GR_ROLE_USER = 0x0001, |
29812 |
++ GR_ROLE_GROUP = 0x0002, |
29813 |
++ GR_ROLE_DEFAULT = 0x0004, |
29814 |
++ GR_ROLE_SPECIAL = 0x0008, |
29815 |
++ GR_ROLE_AUTH = 0x0010, |
29816 |
++ GR_ROLE_NOPW = 0x0020, |
29817 |
++ GR_ROLE_GOD = 0x0040, |
29818 |
++ GR_ROLE_LEARN = 0x0080, |
29819 |
++ GR_ROLE_TPE = 0x0100, |
29820 |
++ GR_ROLE_DOMAIN = 0x0200, |
29821 |
++ GR_ROLE_PAM = 0x0400 |
29822 |
++}; |
29823 |
++ |
29824 |
++/* ACL Subject and Object mode flags */ |
29825 |
++enum { |
29826 |
++ GR_DELETED = 0x80000000 |
29827 |
++}; |
29828 |
++ |
29829 |
++/* ACL Object-only mode flags */ |
29830 |
++enum { |
29831 |
++ GR_READ = 0x00000001, |
29832 |
++ GR_APPEND = 0x00000002, |
29833 |
++ GR_WRITE = 0x00000004, |
29834 |
++ GR_EXEC = 0x00000008, |
29835 |
++ GR_FIND = 0x00000010, |
29836 |
++ GR_INHERIT = 0x00000020, |
29837 |
++ GR_SETID = 0x00000040, |
29838 |
++ GR_CREATE = 0x00000080, |
29839 |
++ GR_DELETE = 0x00000100, |
29840 |
++ GR_LINK = 0x00000200, |
29841 |
++ GR_AUDIT_READ = 0x00000400, |
29842 |
++ GR_AUDIT_APPEND = 0x00000800, |
29843 |
++ GR_AUDIT_WRITE = 0x00001000, |
29844 |
++ GR_AUDIT_EXEC = 0x00002000, |
29845 |
++ GR_AUDIT_FIND = 0x00004000, |
29846 |
++ GR_AUDIT_INHERIT= 0x00008000, |
29847 |
++ GR_AUDIT_SETID = 0x00010000, |
29848 |
++ GR_AUDIT_CREATE = 0x00020000, |
29849 |
++ GR_AUDIT_DELETE = 0x00040000, |
29850 |
++ GR_AUDIT_LINK = 0x00080000, |
29851 |
++ GR_PTRACERD = 0x00100000, |
29852 |
++ GR_NOPTRACE = 0x00200000, |
29853 |
++ GR_SUPPRESS = 0x00400000, |
29854 |
++ GR_NOLEARN = 0x00800000 |
29855 |
++}; |
29856 |
++ |
29857 |
++#define GR_AUDITS (GR_AUDIT_READ | GR_AUDIT_WRITE | GR_AUDIT_APPEND | GR_AUDIT_EXEC | \ |
29858 |
++ GR_AUDIT_FIND | GR_AUDIT_INHERIT | GR_AUDIT_SETID | \ |
29859 |
++ GR_AUDIT_CREATE | GR_AUDIT_DELETE | GR_AUDIT_LINK) |
29860 |
++ |
29861 |
++/* ACL subject-only mode flags */ |
29862 |
++enum { |
29863 |
++ GR_KILL = 0x00000001, |
29864 |
++ GR_VIEW = 0x00000002, |
29865 |
++ GR_PROTECTED = 0x00000004, |
29866 |
++ GR_LEARN = 0x00000008, |
29867 |
++ GR_OVERRIDE = 0x00000010, |
29868 |
++ /* just a placeholder, this mode is only used in userspace */ |
29869 |
++ GR_DUMMY = 0x00000020, |
29870 |
++ GR_PROTSHM = 0x00000040, |
29871 |
++ GR_KILLPROC = 0x00000080, |
29872 |
++ GR_KILLIPPROC = 0x00000100, |
29873 |
++ /* just a placeholder, this mode is only used in userspace */ |
29874 |
++ GR_NOTROJAN = 0x00000200, |
29875 |
++ GR_PROTPROCFD = 0x00000400, |
29876 |
++ GR_PROCACCT = 0x00000800, |
29877 |
++ GR_RELAXPTRACE = 0x00001000, |
29878 |
++ GR_NESTED = 0x00002000, |
29879 |
++ GR_INHERITLEARN = 0x00004000, |
29880 |
++ GR_PROCFIND = 0x00008000, |
29881 |
++ GR_POVERRIDE = 0x00010000, |
29882 |
++ GR_KERNELAUTH = 0x00020000, |
29883 |
++}; |
29884 |
++ |
29885 |
++enum { |
29886 |
++ GR_PAX_ENABLE_SEGMEXEC = 0x0001, |
29887 |
++ GR_PAX_ENABLE_PAGEEXEC = 0x0002, |
29888 |
++ GR_PAX_ENABLE_MPROTECT = 0x0004, |
29889 |
++ GR_PAX_ENABLE_RANDMMAP = 0x0008, |
29890 |
++ GR_PAX_ENABLE_EMUTRAMP = 0x0010, |
29891 |
++ GR_PAX_DISABLE_SEGMEXEC = 0x0100, |
29892 |
++ GR_PAX_DISABLE_PAGEEXEC = 0x0200, |
29893 |
++ GR_PAX_DISABLE_MPROTECT = 0x0400, |
29894 |
++ GR_PAX_DISABLE_RANDMMAP = 0x0800, |
29895 |
++ GR_PAX_DISABLE_EMUTRAMP = 0x1000, |
29896 |
++}; |
29897 |
++ |
29898 |
++enum { |
29899 |
++ GR_ID_USER = 0x01, |
29900 |
++ GR_ID_GROUP = 0x02, |
29901 |
++}; |
29902 |
++ |
29903 |
++enum { |
29904 |
++ GR_ID_ALLOW = 0x01, |
29905 |
++ GR_ID_DENY = 0x02, |
29906 |
++}; |
29907 |
++ |
29908 |
++#define GR_CRASH_RES 11 |
29909 |
++#define GR_UIDTABLE_MAX 500 |
29910 |
++ |
29911 |
++/* begin resource learning section */ |
29912 |
++enum { |
29913 |
++ GR_RLIM_CPU_BUMP = 60, |
29914 |
++ GR_RLIM_FSIZE_BUMP = 50000, |
29915 |
++ GR_RLIM_DATA_BUMP = 10000, |
29916 |
++ GR_RLIM_STACK_BUMP = 1000, |
29917 |
++ GR_RLIM_CORE_BUMP = 10000, |
29918 |
++ GR_RLIM_RSS_BUMP = 500000, |
29919 |
++ GR_RLIM_NPROC_BUMP = 1, |
29920 |
++ GR_RLIM_NOFILE_BUMP = 5, |
29921 |
++ GR_RLIM_MEMLOCK_BUMP = 50000, |
29922 |
++ GR_RLIM_AS_BUMP = 500000, |
29923 |
++ GR_RLIM_LOCKS_BUMP = 2 |
29924 |
++}; |
29925 |
++ |
29926 |
++#endif |
29927 |
+diff -urNp linux-2.6.28.8/include/linux/grinternal.h linux-2.6.28.8/include/linux/grinternal.h |
29928 |
+--- linux-2.6.28.8/include/linux/grinternal.h 1969-12-31 19:00:00.000000000 -0500 |
29929 |
++++ linux-2.6.28.8/include/linux/grinternal.h 2009-02-21 09:37:49.000000000 -0500 |
29930 |
+@@ -0,0 +1,210 @@ |
29931 |
++#ifndef __GRINTERNAL_H |
29932 |
++#define __GRINTERNAL_H |
29933 |
++ |
29934 |
++#ifdef CONFIG_GRKERNSEC |
29935 |
++ |
29936 |
++#include <linux/fs.h> |
29937 |
++#include <linux/gracl.h> |
29938 |
++#include <linux/grdefs.h> |
29939 |
++#include <linux/grmsg.h> |
29940 |
++ |
29941 |
++void gr_add_learn_entry(const char *fmt, ...); |
29942 |
++__u32 gr_search_file(const struct dentry *dentry, const __u32 mode, |
29943 |
++ const struct vfsmount *mnt); |
29944 |
++__u32 gr_check_create(const struct dentry *new_dentry, |
29945 |
++ const struct dentry *parent, |
29946 |
++ const struct vfsmount *mnt, const __u32 mode); |
29947 |
++int gr_check_protected_task(const struct task_struct *task); |
29948 |
++__u32 to_gr_audit(const __u32 reqmode); |
29949 |
++int gr_set_acls(const int type); |
29950 |
++ |
29951 |
++int gr_acl_is_enabled(void); |
29952 |
++char gr_roletype_to_char(void); |
29953 |
++ |
29954 |
++void gr_handle_alertkill(struct task_struct *task); |
29955 |
++char *gr_to_filename(const struct dentry *dentry, |
29956 |
++ const struct vfsmount *mnt); |
29957 |
++char *gr_to_filename1(const struct dentry *dentry, |
29958 |
++ const struct vfsmount *mnt); |
29959 |
++char *gr_to_filename2(const struct dentry *dentry, |
29960 |
++ const struct vfsmount *mnt); |
29961 |
++char *gr_to_filename3(const struct dentry *dentry, |
29962 |
++ const struct vfsmount *mnt); |
29963 |
++ |
29964 |
++extern int grsec_enable_link; |
29965 |
++extern int grsec_enable_fifo; |
29966 |
++extern int grsec_enable_execve; |
29967 |
++extern int grsec_enable_shm; |
29968 |
++extern int grsec_enable_execlog; |
29969 |
++extern int grsec_enable_signal; |
29970 |
++extern int grsec_enable_forkfail; |
29971 |
++extern int grsec_enable_time; |
29972 |
++extern int grsec_enable_chroot_shmat; |
29973 |
++extern int grsec_enable_chroot_findtask; |
29974 |
++extern int grsec_enable_chroot_mount; |
29975 |
++extern int grsec_enable_chroot_double; |
29976 |
++extern int grsec_enable_chroot_pivot; |
29977 |
++extern int grsec_enable_chroot_chdir; |
29978 |
++extern int grsec_enable_chroot_chmod; |
29979 |
++extern int grsec_enable_chroot_mknod; |
29980 |
++extern int grsec_enable_chroot_fchdir; |
29981 |
++extern int grsec_enable_chroot_nice; |
29982 |
++extern int grsec_enable_chroot_execlog; |
29983 |
++extern int grsec_enable_chroot_caps; |
29984 |
++extern int grsec_enable_chroot_sysctl; |
29985 |
++extern int grsec_enable_chroot_unix; |
29986 |
++extern int grsec_enable_tpe; |
29987 |
++extern int grsec_tpe_gid; |
29988 |
++extern int grsec_enable_tpe_all; |
29989 |
++extern int grsec_enable_sidcaps; |
29990 |
++extern int grsec_enable_socket_all; |
29991 |
++extern int grsec_socket_all_gid; |
29992 |
++extern int grsec_enable_socket_client; |
29993 |
++extern int grsec_socket_client_gid; |
29994 |
++extern int grsec_enable_socket_server; |
29995 |
++extern int grsec_socket_server_gid; |
29996 |
++extern int grsec_audit_gid; |
29997 |
++extern int grsec_enable_group; |
29998 |
++extern int grsec_enable_audit_ipc; |
29999 |
++extern int grsec_enable_audit_textrel; |
30000 |
++extern int grsec_enable_mount; |
30001 |
++extern int grsec_enable_chdir; |
30002 |
++extern int grsec_resource_logging; |
30003 |
++extern int grsec_lock; |
30004 |
++ |
30005 |
++extern spinlock_t grsec_alert_lock; |
30006 |
++extern unsigned long grsec_alert_wtime; |
30007 |
++extern unsigned long grsec_alert_fyet; |
30008 |
++ |
30009 |
++extern spinlock_t grsec_audit_lock; |
30010 |
++ |
30011 |
++extern rwlock_t grsec_exec_file_lock; |
30012 |
++ |
30013 |
++#define gr_task_fullpath(tsk) (tsk->exec_file ? \ |
30014 |
++ gr_to_filename2(tsk->exec_file->f_path.dentry, \ |
30015 |
++ tsk->exec_file->f_vfsmnt) : "/") |
30016 |
++ |
30017 |
++#define gr_parent_task_fullpath(tsk) (tsk->parent->exec_file ? \ |
30018 |
++ gr_to_filename3(tsk->parent->exec_file->f_path.dentry, \ |
30019 |
++ tsk->parent->exec_file->f_vfsmnt) : "/") |
30020 |
++ |
30021 |
++#define gr_task_fullpath0(tsk) (tsk->exec_file ? \ |
30022 |
++ gr_to_filename(tsk->exec_file->f_path.dentry, \ |
30023 |
++ tsk->exec_file->f_vfsmnt) : "/") |
30024 |
++ |
30025 |
++#define gr_parent_task_fullpath0(tsk) (tsk->parent->exec_file ? \ |
30026 |
++ gr_to_filename1(tsk->parent->exec_file->f_path.dentry, \ |
30027 |
++ tsk->parent->exec_file->f_vfsmnt) : "/") |
30028 |
++ |
30029 |
++#define proc_is_chrooted(tsk_a) ((tsk_a->pid > 1) && (tsk_a->fs != NULL) && \ |
30030 |
++ ((tsk_a->fs->root.dentry->d_inode->i_sb->s_dev != \ |
30031 |
++ tsk_a->nsproxy->pid_ns->child_reaper->fs->root.dentry->d_inode->i_sb->s_dev) || \ |
30032 |
++ (tsk_a->fs->root.dentry->d_inode->i_ino != \ |
30033 |
++ tsk_a->nsproxy->pid_ns->child_reaper->fs->root.dentry->d_inode->i_ino))) |
30034 |
++ |
30035 |
++#define have_same_root(tsk_a,tsk_b) ((tsk_a->fs != NULL) && (tsk_b->fs != NULL) && \ |
30036 |
++ (tsk_a->fs->root.dentry->d_inode->i_sb->s_dev == \ |
30037 |
++ tsk_b->fs->root.dentry->d_inode->i_sb->s_dev) && \ |
30038 |
++ (tsk_a->fs->root.dentry->d_inode->i_ino == \ |
30039 |
++ tsk_b->fs->root.dentry->d_inode->i_ino)) |
30040 |
++ |
30041 |
++#define DEFAULTSECARGS(task) gr_task_fullpath(task), task->comm, \ |
30042 |
++ task->pid, task->uid, \ |
30043 |
++ task->euid, task->gid, task->egid, \ |
30044 |
++ gr_parent_task_fullpath(task), \ |
30045 |
++ task->parent->comm, task->parent->pid, \ |
30046 |
++ task->parent->uid, task->parent->euid, \ |
30047 |
++ task->parent->gid, task->parent->egid |
30048 |
++ |
30049 |
++#define GR_CHROOT_CAPS {{ \ |
30050 |
++ CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | CAP_TO_MASK(CAP_NET_ADMIN) | \ |
30051 |
++ CAP_TO_MASK(CAP_SYS_MODULE) | CAP_TO_MASK(CAP_SYS_RAWIO) | \ |
30052 |
++ CAP_TO_MASK(CAP_SYS_PACCT) | CAP_TO_MASK(CAP_SYS_ADMIN) | \ |
30053 |
++ CAP_TO_MASK(CAP_SYS_BOOT) | CAP_TO_MASK(CAP_SYS_TIME) | \ |
30054 |
++ CAP_TO_MASK(CAP_NET_RAW) | CAP_TO_MASK(CAP_SYS_TTY_CONFIG) | \ |
30055 |
++ CAP_TO_MASK(CAP_IPC_OWNER) , 0 }} |
30056 |
++ |
30057 |
++#define security_learn(normal_msg,args...) \ |
30058 |
++({ \ |
30059 |
++ read_lock(&grsec_exec_file_lock); \ |
30060 |
++ gr_add_learn_entry(normal_msg "\n", ## args); \ |
30061 |
++ read_unlock(&grsec_exec_file_lock); \ |
30062 |
++}) |
30063 |
++ |
30064 |
++enum { |
30065 |
++ GR_DO_AUDIT, |
30066 |
++ GR_DONT_AUDIT, |
30067 |
++ GR_DONT_AUDIT_GOOD |
30068 |
++}; |
30069 |
++ |
30070 |
++enum { |
30071 |
++ GR_TTYSNIFF, |
30072 |
++ GR_RBAC, |
30073 |
++ GR_RBAC_STR, |
30074 |
++ GR_STR_RBAC, |
30075 |
++ GR_RBAC_MODE2, |
30076 |
++ GR_RBAC_MODE3, |
30077 |
++ GR_FILENAME, |
30078 |
++ GR_SYSCTL_HIDDEN, |
30079 |
++ GR_NOARGS, |
30080 |
++ GR_ONE_INT, |
30081 |
++ GR_ONE_INT_TWO_STR, |
30082 |
++ GR_ONE_STR, |
30083 |
++ GR_STR_INT, |
30084 |
++ GR_TWO_INT, |
30085 |
++ GR_THREE_INT, |
30086 |
++ GR_FIVE_INT_TWO_STR, |
30087 |
++ GR_TWO_STR, |
30088 |
++ GR_THREE_STR, |
30089 |
++ GR_FOUR_STR, |
30090 |
++ GR_STR_FILENAME, |
30091 |
++ GR_FILENAME_STR, |
30092 |
++ GR_FILENAME_TWO_INT, |
30093 |
++ GR_FILENAME_TWO_INT_STR, |
30094 |
++ GR_TEXTREL, |
30095 |
++ GR_PTRACE, |
30096 |
++ GR_RESOURCE, |
30097 |
++ GR_CAP, |
30098 |
++ GR_SIG, |
30099 |
++ GR_CRASH1, |
30100 |
++ GR_CRASH2, |
30101 |
++ GR_PSACCT |
30102 |
++}; |
30103 |
++ |
30104 |
++#define gr_log_hidden_sysctl(audit, msg, str) gr_log_varargs(audit, msg, GR_SYSCTL_HIDDEN, str) |
30105 |
++#define gr_log_ttysniff(audit, msg, task) gr_log_varargs(audit, msg, GR_TTYSNIFF, task) |
30106 |
++#define gr_log_fs_rbac_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_RBAC, dentry, mnt) |
30107 |
++#define gr_log_fs_rbac_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_RBAC_STR, dentry, mnt, str) |
30108 |
++#define gr_log_fs_str_rbac(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_RBAC, str, dentry, mnt) |
30109 |
++#define gr_log_fs_rbac_mode2(audit, msg, dentry, mnt, str1, str2) gr_log_varargs(audit, msg, GR_RBAC_MODE2, dentry, mnt, str1, str2) |
30110 |
++#define gr_log_fs_rbac_mode3(audit, msg, dentry, mnt, str1, str2, str3) gr_log_varargs(audit, msg, GR_RBAC_MODE3, dentry, mnt, str1, str2, str3) |
30111 |
++#define gr_log_fs_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_FILENAME, dentry, mnt) |
30112 |
++#define gr_log_noargs(audit, msg) gr_log_varargs(audit, msg, GR_NOARGS) |
30113 |
++#define gr_log_int(audit, msg, num) gr_log_varargs(audit, msg, GR_ONE_INT, num) |
30114 |
++#define gr_log_int_str2(audit, msg, num, str1, str2) gr_log_varargs(audit, msg, GR_ONE_INT_TWO_STR, num, str1, str2) |
30115 |
++#define gr_log_str(audit, msg, str) gr_log_varargs(audit, msg, GR_ONE_STR, str) |
30116 |
++#define gr_log_str_int(audit, msg, str, num) gr_log_varargs(audit, msg, GR_STR_INT, str, num) |
30117 |
++#define gr_log_int_int(audit, msg, num1, num2) gr_log_varargs(audit, msg, GR_TWO_INT, num1, num2) |
30118 |
++#define gr_log_int3(audit, msg, num1, num2, num3) gr_log_varargs(audit, msg, GR_THREE_INT, num1, num2, num3) |
30119 |
++#define gr_log_int5_str2(audit, msg, num1, num2, str1, str2) gr_log_varargs(audit, msg, GR_FIVE_INT_TWO_STR, num1, num2, str1, str2) |
30120 |
++#define gr_log_str_str(audit, msg, str1, str2) gr_log_varargs(audit, msg, GR_TWO_STR, str1, str2) |
30121 |
++#define gr_log_str3(audit, msg, str1, str2, str3) gr_log_varargs(audit, msg, GR_THREE_STR, str1, str2, str3) |
30122 |
++#define gr_log_str4(audit, msg, str1, str2, str3, str4) gr_log_varargs(audit, msg, GR_FOUR_STR, str1, str2, str3, str4) |
30123 |
++#define gr_log_str_fs(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_FILENAME, str, dentry, mnt) |
30124 |
++#define gr_log_fs_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_FILENAME_STR, dentry, mnt, str) |
30125 |
++#define gr_log_fs_int2(audit, msg, dentry, mnt, num1, num2) gr_log_varargs(audit, msg, GR_FILENAME_TWO_INT, dentry, mnt, num1, num2) |
30126 |
++#define gr_log_fs_int2_str(audit, msg, dentry, mnt, num1, num2, str) gr_log_varargs(audit, msg, GR_FILENAME_TWO_INT_STR, dentry, mnt, num1, num2, str) |
30127 |
++#define gr_log_textrel_ulong_ulong(audit, msg, file, ulong1, ulong2) gr_log_varargs(audit, msg, GR_TEXTREL, file, ulong1, ulong2) |
30128 |
++#define gr_log_ptrace(audit, msg, task) gr_log_varargs(audit, msg, GR_PTRACE, task) |
30129 |
++#define gr_log_res_ulong2_str(audit, msg, task, ulong1, str, ulong2) gr_log_varargs(audit, msg, GR_RESOURCE, task, ulong1, str, ulong2) |
30130 |
++#define gr_log_cap(audit, msg, task, str) gr_log_varargs(audit, msg, GR_CAP, task, str) |
30131 |
++#define gr_log_sig(audit, msg, task, num) gr_log_varargs(audit, msg, GR_SIG, task, num) |
30132 |
++#define gr_log_crash1(audit, msg, task, ulong) gr_log_varargs(audit, msg, GR_CRASH1, task, ulong) |
30133 |
++#define gr_log_crash2(audit, msg, task, ulong1) gr_log_varargs(audit, msg, GR_CRASH2, task, ulong1) |
30134 |
++#define gr_log_procacct(audit, msg, task, num1, num2, num3, num4, num5, num6, num7, num8, num9) gr_log_varargs(audit, msg, GR_PSACCT, task, num1, num2, num3, num4, num5, num6, num7, num8, num9) |
30135 |
++ |
30136 |
++void gr_log_varargs(int audit, const char *msg, int argtypes, ...); |
30137 |
++ |
30138 |
++#endif |
30139 |
++ |
30140 |
++#endif |
30141 |
+diff -urNp linux-2.6.28.8/include/linux/grmsg.h linux-2.6.28.8/include/linux/grmsg.h |
30142 |
+--- linux-2.6.28.8/include/linux/grmsg.h 1969-12-31 19:00:00.000000000 -0500 |
30143 |
++++ linux-2.6.28.8/include/linux/grmsg.h 2009-02-21 09:37:49.000000000 -0500 |
30144 |
+@@ -0,0 +1,108 @@ |
30145 |
++#define DEFAULTSECMSG "%.256s[%.16s:%d] uid/euid:%u/%u gid/egid:%u/%u, parent %.256s[%.16s:%d] uid/euid:%u/%u gid/egid:%u/%u" |
30146 |
++#define GR_ACL_PROCACCT_MSG "%.256s[%.16s:%d] IP:%u.%u.%u.%u TTY:%.64s uid/euid:%u/%u gid/egid:%u/%u run time:[%ud %uh %um %us] cpu time:[%ud %uh %um %us] %s with exit code %ld, parent %.256s[%.16s:%d] IP:%u.%u.%u.%u TTY:%.64s uid/euid:%u/%u gid/egid:%u/%u" |
30147 |
++#define GR_PTRACE_ACL_MSG "denied ptrace of %.950s(%.16s:%d) by " |
30148 |
++#define GR_STOPMOD_MSG "denied modification of module state by " |
30149 |
++#define GR_IOPERM_MSG "denied use of ioperm() by " |
30150 |
++#define GR_IOPL_MSG "denied use of iopl() by " |
30151 |
++#define GR_SHMAT_ACL_MSG "denied attach of shared memory of UID %u, PID %d, ID %u by " |
30152 |
++#define GR_UNIX_CHROOT_MSG "denied connect() to abstract AF_UNIX socket outside of chroot by " |
30153 |
++#define GR_SHMAT_CHROOT_MSG "denied attach of shared memory outside of chroot by " |
30154 |
++#define GR_KMEM_MSG "denied write of /dev/kmem by " |
30155 |
++#define GR_PORT_OPEN_MSG "denied open of /dev/port by " |
30156 |
++#define GR_MEM_WRITE_MSG "denied write of /dev/mem by " |
30157 |
++#define GR_MEM_MMAP_MSG "denied mmap write of /dev/[k]mem by " |
30158 |
++#define GR_SYMLINK_MSG "not following symlink %.950s owned by %d.%d by " |
30159 |
++#define GR_LEARN_AUDIT_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%lu\t%lu\t%.4095s\t%lu\t%u.%u.%u.%u" |
30160 |
++#define GR_ID_LEARN_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%c\t%d\t%d\t%d\t%u.%u.%u.%u" |
30161 |
++#define GR_HIDDEN_ACL_MSG "%s access to hidden file %.950s by " |
30162 |
++#define GR_OPEN_ACL_MSG "%s open of %.950s for%s%s by " |
30163 |
++#define GR_CREATE_ACL_MSG "%s create of %.950s for%s%s by " |
30164 |
++#define GR_FIFO_MSG "denied writing FIFO %.950s of %d.%d by " |
30165 |
++#define GR_MKNOD_CHROOT_MSG "denied mknod of %.950s from chroot by " |
30166 |
++#define GR_MKNOD_ACL_MSG "%s mknod of %.950s by " |
30167 |
++#define GR_UNIXCONNECT_ACL_MSG "%s connect() to the unix domain socket %.950s by " |
30168 |
++#define GR_TTYSNIFF_ACL_MSG "terminal being sniffed by IP:%u.%u.%u.%u %.480s[%.16s:%d], parent %.480s[%.16s:%d] against " |
30169 |
++#define GR_MKDIR_ACL_MSG "%s mkdir of %.950s by " |
30170 |
++#define GR_RMDIR_ACL_MSG "%s rmdir of %.950s by " |
30171 |
++#define GR_UNLINK_ACL_MSG "%s unlink of %.950s by " |
30172 |
++#define GR_SYMLINK_ACL_MSG "%s symlink from %.480s to %.480s by " |
30173 |
++#define GR_HARDLINK_MSG "denied hardlink of %.930s (owned by %d.%d) to %.30s for " |
30174 |
++#define GR_LINK_ACL_MSG "%s link of %.480s to %.480s by " |
30175 |
++#define GR_INHERIT_ACL_MSG "successful inherit of %.480s's ACL for %.480s by " |
30176 |
++#define GR_RENAME_ACL_MSG "%s rename of %.480s to %.480s by " |
30177 |
++#define GR_PTRACE_EXEC_ACL_MSG "denied ptrace of %.950s by " |
30178 |
++#define GR_NPROC_MSG "denied overstep of process limit by " |
30179 |
++#define GR_EXEC_ACL_MSG "%s execution of %.950s by " |
30180 |
++#define GR_EXEC_TPE_MSG "denied untrusted exec of %.950s by " |
30181 |
++#define GR_SEGVSTART_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning uid %u from login for %lu seconds" |
30182 |
++#define GR_SEGVNOSUID_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning execution for %lu seconds" |
30183 |
++#define GR_MOUNT_CHROOT_MSG "denied mount of %.256s as %.930s from chroot by " |
30184 |
++#define GR_PIVOT_CHROOT_MSG "denied pivot_root from chroot by " |
30185 |
++#define GR_TRUNCATE_ACL_MSG "%s truncate of %.950s by " |
30186 |
++#define GR_ATIME_ACL_MSG "%s access time change of %.950s by " |
30187 |
++#define GR_ACCESS_ACL_MSG "%s access of %.950s for%s%s%s by " |
30188 |
++#define GR_CHROOT_CHROOT_MSG "denied double chroot to %.950s by " |
30189 |
++#define GR_FCHMOD_ACL_MSG "%s fchmod of %.950s by " |
30190 |
++#define GR_CHMOD_CHROOT_MSG "denied chmod +s of %.950s by " |
30191 |
++#define GR_CHMOD_ACL_MSG "%s chmod of %.950s by " |
30192 |
++#define GR_CHROOT_FCHDIR_MSG "denied fchdir outside of chroot to %.950s by " |
30193 |
++#define GR_CHOWN_ACL_MSG "%s chown of %.950s by " |
30194 |
++#define GR_WRITLIB_ACL_MSG "denied load of writable library %.950s by " |
30195 |
++#define GR_INITF_ACL_MSG "init_variables() failed %s by " |
30196 |
++#define GR_DISABLED_ACL_MSG "Error loading %s, trying to run kernel with acls disabled. To disable acls at startup use <kernel image name> gracl=off from your boot loader" |
30197 |
++#define GR_DEV_ACL_MSG "/dev/grsec: %d bytes sent %d required, being fed garbaged by " |
30198 |
++#define GR_SHUTS_ACL_MSG "shutdown auth success for " |
30199 |
++#define GR_SHUTF_ACL_MSG "shutdown auth failure for " |
30200 |
++#define GR_SHUTI_ACL_MSG "ignoring shutdown for disabled RBAC system for " |
30201 |
++#define GR_SEGVMODS_ACL_MSG "segvmod auth success for " |
30202 |
++#define GR_SEGVMODF_ACL_MSG "segvmod auth failure for " |
30203 |
++#define GR_SEGVMODI_ACL_MSG "ignoring segvmod for disabled RBAC system for " |
30204 |
++#define GR_ENABLE_ACL_MSG "%s RBAC system loaded by " |
30205 |
++#define GR_ENABLEF_ACL_MSG "unable to load %s for " |
30206 |
++#define GR_RELOADI_ACL_MSG "ignoring reload request for disabled RBAC system" |
30207 |
++#define GR_RELOAD_ACL_MSG "%s RBAC system reloaded by " |
30208 |
++#define GR_RELOADF_ACL_MSG "failed reload of %s for " |
30209 |
++#define GR_SPROLEI_ACL_MSG "ignoring change to special role for disabled RBAC system for " |
30210 |
++#define GR_SPROLES_ACL_MSG "successful change to special role %s (id %d) by " |
30211 |
++#define GR_SPROLEL_ACL_MSG "special role %s (id %d) exited by " |
30212 |
++#define GR_SPROLEF_ACL_MSG "special role %s failure for " |
30213 |
++#define GR_UNSPROLEI_ACL_MSG "ignoring unauth of special role for disabled RBAC system for " |
30214 |
++#define GR_UNSPROLES_ACL_MSG "successful unauth of special role %s (id %d) by " |
30215 |
++#define GR_UNSPROLEF_ACL_MSG "special role unauth of %s failure for " |
30216 |
++#define GR_INVMODE_ACL_MSG "invalid mode %d by " |
30217 |
++#define GR_PRIORITY_CHROOT_MSG "denied priority change of process (%.16s:%d) by " |
30218 |
++#define GR_FAILFORK_MSG "failed fork with errno %d by " |
30219 |
++#define GR_NICE_CHROOT_MSG "denied priority change by " |
30220 |
++#define GR_UNISIGLOG_MSG "signal %d sent to " |
30221 |
++#define GR_DUALSIGLOG_MSG "signal %d sent to " DEFAULTSECMSG " by " |
30222 |
++#define GR_SIG_ACL_MSG "denied send of signal %d to protected task " DEFAULTSECMSG " by " |
30223 |
++#define GR_SYSCTL_MSG "denied modification of grsecurity sysctl value : %.32s by " |
30224 |
++#define GR_SYSCTL_ACL_MSG "%s sysctl of %.950s for%s%s by " |
30225 |
++#define GR_TIME_MSG "time set by " |
30226 |
++#define GR_DEFACL_MSG "fatal: unable to find subject for (%.16s:%d), loaded by " |
30227 |
++#define GR_MMAP_ACL_MSG "%s executable mmap of %.950s by " |
30228 |
++#define GR_MPROTECT_ACL_MSG "%s executable mprotect of %.950s by " |
30229 |
++#define GR_SOCK_MSG "denied socket(%.16s,%.16s,%.16s) by " |
30230 |
++#define GR_SOCK2_MSG "denied socket(%d,%.16s,%.16s) by " |
30231 |
++#define GR_BIND_MSG "denied bind() by " |
30232 |
++#define GR_CONNECT_MSG "denied connect() by " |
30233 |
++#define GR_BIND_ACL_MSG "denied bind() to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by " |
30234 |
++#define GR_CONNECT_ACL_MSG "denied connect() to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by " |
30235 |
++#define GR_IP_LEARN_MSG "%s\t%u\t%u\t%u\t%.4095s\t%.4095s\t%u.%u.%u.%u\t%u\t%u\t%u\t%u\t%u.%u.%u.%u" |
30236 |
++#define GR_EXEC_CHROOT_MSG "exec of %.980s within chroot by process " |
30237 |
++#define GR_CAP_ACL_MSG "use of %s denied for " |
30238 |
++#define GR_USRCHANGE_ACL_MSG "change to uid %u denied for " |
30239 |
++#define GR_GRPCHANGE_ACL_MSG "change to gid %u denied for " |
30240 |
++#define GR_REMOUNT_AUDIT_MSG "remount of %.256s by " |
30241 |
++#define GR_UNMOUNT_AUDIT_MSG "unmount of %.256s by " |
30242 |
++#define GR_MOUNT_AUDIT_MSG "mount of %.256s to %.256s by " |
30243 |
++#define GR_CHDIR_AUDIT_MSG "chdir to %.980s by " |
30244 |
++#define GR_EXEC_AUDIT_MSG "exec of %.930s (%.128s) by " |
30245 |
++#define GR_MSGQ_AUDIT_MSG "message queue created by " |
30246 |
++#define GR_MSGQR_AUDIT_MSG "message queue of uid:%u euid:%u removed by " |
30247 |
++#define GR_SEM_AUDIT_MSG "semaphore created by " |
30248 |
++#define GR_SEMR_AUDIT_MSG "semaphore of uid:%u euid:%u removed by " |
30249 |
++#define GR_SHM_AUDIT_MSG "shared memory of size %d created by " |
30250 |
++#define GR_SHMR_AUDIT_MSG "shared memory of uid:%u euid:%u removed by " |
30251 |
++#define GR_RESOURCE_MSG "denied resource overstep by requesting %lu for %.16s against limit %lu for " |
30252 |
++#define GR_TEXTREL_AUDIT_MSG "text relocation in %s, VMA:0x%08lx 0x%08lx by " |
30253 |
+diff -urNp linux-2.6.28.8/include/linux/grsecurity.h linux-2.6.28.8/include/linux/grsecurity.h |
30254 |
+--- linux-2.6.28.8/include/linux/grsecurity.h 1969-12-31 19:00:00.000000000 -0500 |
30255 |
++++ linux-2.6.28.8/include/linux/grsecurity.h 2009-02-21 09:37:49.000000000 -0500 |
30256 |
+@@ -0,0 +1,200 @@ |
30257 |
++#ifndef GR_SECURITY_H |
30258 |
++#define GR_SECURITY_H |
30259 |
++#include <linux/fs.h> |
30260 |
++#include <linux/binfmts.h> |
30261 |
++#include <linux/gracl.h> |
30262 |
++ |
30263 |
++/* notify of brain-dead configs */ |
30264 |
++#if defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_PAGEEXEC) && !defined(CONFIG_PAX_SEGMEXEC) && !defined(CONFIG_PAX_KERNEXEC) |
30265 |
++#error "CONFIG_PAX_NOEXEC enabled, but PAGEEXEC, SEGMEXEC, and KERNEXEC are disabled." |
30266 |
++#endif |
30267 |
++#if defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_EI_PAX) && !defined(CONFIG_PAX_PT_PAX_FLAGS) |
30268 |
++#error "CONFIG_PAX_NOEXEC enabled, but neither CONFIG_PAX_EI_PAX nor CONFIG_PAX_PT_PAX_FLAGS are enabled." |
30269 |
++#endif |
30270 |
++#if defined(CONFIG_PAX_ASLR) && (defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)) && !defined(CONFIG_PAX_EI_PAX) && !defined(CONFIG_PAX_PT_PAX_FLAGS) |
30271 |
++#error "CONFIG_PAX_ASLR enabled, but neither CONFIG_PAX_EI_PAX nor CONFIG_PAX_PT_PAX_FLAGS are enabled." |
30272 |
++#endif |
30273 |
++#if defined(CONFIG_PAX_ASLR) && !defined(CONFIG_PAX_RANDKSTACK) && !defined(CONFIG_PAX_RANDUSTACK) && !defined(CONFIG_PAX_RANDMMAP) |
30274 |
++#error "CONFIG_PAX_ASLR enabled, but RANDKSTACK, RANDUSTACK, and RANDMMAP are disabled." |
30275 |
++#endif |
30276 |
++#if defined(CONFIG_PAX) && !defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_ASLR) |
30277 |
++#error "CONFIG_PAX enabled, but no PaX options are enabled." |
30278 |
++#endif |
30279 |
++ |
30280 |
++void gr_handle_brute_attach(struct task_struct *p); |
30281 |
++void gr_handle_brute_check(void); |
30282 |
++ |
30283 |
++char gr_roletype_to_char(void); |
30284 |
++ |
30285 |
++int gr_check_user_change(int real, int effective, int fs); |
30286 |
++int gr_check_group_change(int real, int effective, int fs); |
30287 |
++ |
30288 |
++void gr_del_task_from_ip_table(struct task_struct *p); |
30289 |
++ |
30290 |
++int gr_pid_is_chrooted(struct task_struct *p); |
30291 |
++int gr_handle_chroot_nice(void); |
30292 |
++int gr_handle_chroot_sysctl(const int op); |
30293 |
++int gr_handle_chroot_setpriority(struct task_struct *p, |
30294 |
++ const int niceval); |
30295 |
++int gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt); |
30296 |
++int gr_handle_chroot_chroot(const struct dentry *dentry, |
30297 |
++ const struct vfsmount *mnt); |
30298 |
++void gr_handle_chroot_caps(struct task_struct *task); |
30299 |
++void gr_handle_chroot_chdir(struct path *path); |
30300 |
++int gr_handle_chroot_chmod(const struct dentry *dentry, |
30301 |
++ const struct vfsmount *mnt, const int mode); |
30302 |
++int gr_handle_chroot_mknod(const struct dentry *dentry, |
30303 |
++ const struct vfsmount *mnt, const int mode); |
30304 |
++int gr_handle_chroot_mount(const struct dentry *dentry, |
30305 |
++ const struct vfsmount *mnt, |
30306 |
++ const char *dev_name); |
30307 |
++int gr_handle_chroot_pivot(void); |
30308 |
++int gr_handle_chroot_unix(const pid_t pid); |
30309 |
++ |
30310 |
++int gr_handle_rawio(const struct inode *inode); |
30311 |
++int gr_handle_nproc(void); |
30312 |
++ |
30313 |
++void gr_handle_ioperm(void); |
30314 |
++void gr_handle_iopl(void); |
30315 |
++ |
30316 |
++int gr_tpe_allow(const struct file *file); |
30317 |
++ |
30318 |
++int gr_random_pid(void); |
30319 |
++ |
30320 |
++void gr_log_forkfail(const int retval); |
30321 |
++void gr_log_timechange(void); |
30322 |
++void gr_log_signal(const int sig, const struct task_struct *t); |
30323 |
++void gr_log_chdir(const struct dentry *dentry, |
30324 |
++ const struct vfsmount *mnt); |
30325 |
++void gr_log_chroot_exec(const struct dentry *dentry, |
30326 |
++ const struct vfsmount *mnt); |
30327 |
++void gr_handle_exec_args(struct linux_binprm *bprm, char **argv); |
30328 |
++void gr_log_remount(const char *devname, const int retval); |
30329 |
++void gr_log_unmount(const char *devname, const int retval); |
30330 |
++void gr_log_mount(const char *from, const char *to, const int retval); |
30331 |
++void gr_log_msgget(const int ret, const int msgflg); |
30332 |
++void gr_log_msgrm(const uid_t uid, const uid_t cuid); |
30333 |
++void gr_log_semget(const int err, const int semflg); |
30334 |
++void gr_log_semrm(const uid_t uid, const uid_t cuid); |
30335 |
++void gr_log_shmget(const int err, const int shmflg, const size_t size); |
30336 |
++void gr_log_shmrm(const uid_t uid, const uid_t cuid); |
30337 |
++void gr_log_textrel(struct vm_area_struct *vma); |
30338 |
++ |
30339 |
++int gr_handle_follow_link(const struct inode *parent, |
30340 |
++ const struct inode *inode, |
30341 |
++ const struct dentry *dentry, |
30342 |
++ const struct vfsmount *mnt); |
30343 |
++int gr_handle_fifo(const struct dentry *dentry, |
30344 |
++ const struct vfsmount *mnt, |
30345 |
++ const struct dentry *dir, const int flag, |
30346 |
++ const int acc_mode); |
30347 |
++int gr_handle_hardlink(const struct dentry *dentry, |
30348 |
++ const struct vfsmount *mnt, |
30349 |
++ struct inode *inode, |
30350 |
++ const int mode, const char *to); |
30351 |
++ |
30352 |
++int gr_task_is_capable(struct task_struct *task, const int cap); |
30353 |
++int gr_is_capable_nolog(const int cap); |
30354 |
++void gr_learn_resource(const struct task_struct *task, const int limit, |
30355 |
++ const unsigned long wanted, const int gt); |
30356 |
++void gr_copy_label(struct task_struct *tsk); |
30357 |
++void gr_handle_crash(struct task_struct *task, const int sig); |
30358 |
++int gr_handle_signal(const struct task_struct *p, const int sig); |
30359 |
++int gr_check_crash_uid(const uid_t uid); |
30360 |
++int gr_check_protected_task(const struct task_struct *task); |
30361 |
++int gr_acl_handle_mmap(const struct file *file, |
30362 |
++ const unsigned long prot); |
30363 |
++int gr_acl_handle_mprotect(const struct file *file, |
30364 |
++ const unsigned long prot); |
30365 |
++int gr_check_hidden_task(const struct task_struct *tsk); |
30366 |
++__u32 gr_acl_handle_truncate(const struct dentry *dentry, |
30367 |
++ const struct vfsmount *mnt); |
30368 |
++__u32 gr_acl_handle_utime(const struct dentry *dentry, |
30369 |
++ const struct vfsmount *mnt); |
30370 |
++__u32 gr_acl_handle_access(const struct dentry *dentry, |
30371 |
++ const struct vfsmount *mnt, const int fmode); |
30372 |
++__u32 gr_acl_handle_fchmod(const struct dentry *dentry, |
30373 |
++ const struct vfsmount *mnt, mode_t mode); |
30374 |
++__u32 gr_acl_handle_chmod(const struct dentry *dentry, |
30375 |
++ const struct vfsmount *mnt, mode_t mode); |
30376 |
++__u32 gr_acl_handle_chown(const struct dentry *dentry, |
30377 |
++ const struct vfsmount *mnt); |
30378 |
++int gr_handle_ptrace(struct task_struct *task, const long request); |
30379 |
++int gr_handle_proc_ptrace(struct task_struct *task); |
30380 |
++__u32 gr_acl_handle_execve(const struct dentry *dentry, |
30381 |
++ const struct vfsmount *mnt); |
30382 |
++int gr_check_crash_exec(const struct file *filp); |
30383 |
++int gr_acl_is_enabled(void); |
30384 |
++void gr_set_kernel_label(struct task_struct *task); |
30385 |
++void gr_set_role_label(struct task_struct *task, const uid_t uid, |
30386 |
++ const gid_t gid); |
30387 |
++int gr_set_proc_label(const struct dentry *dentry, |
30388 |
++ const struct vfsmount *mnt); |
30389 |
++__u32 gr_acl_handle_hidden_file(const struct dentry *dentry, |
30390 |
++ const struct vfsmount *mnt); |
30391 |
++__u32 gr_acl_handle_open(const struct dentry *dentry, |
30392 |
++ const struct vfsmount *mnt, const int fmode); |
30393 |
++__u32 gr_acl_handle_creat(const struct dentry *dentry, |
30394 |
++ const struct dentry *p_dentry, |
30395 |
++ const struct vfsmount *p_mnt, const int fmode, |
30396 |
++ const int imode); |
30397 |
++void gr_handle_create(const struct dentry *dentry, |
30398 |
++ const struct vfsmount *mnt); |
30399 |
++__u32 gr_acl_handle_mknod(const struct dentry *new_dentry, |
30400 |
++ const struct dentry *parent_dentry, |
30401 |
++ const struct vfsmount *parent_mnt, |
30402 |
++ const int mode); |
30403 |
++__u32 gr_acl_handle_mkdir(const struct dentry *new_dentry, |
30404 |
++ const struct dentry *parent_dentry, |
30405 |
++ const struct vfsmount *parent_mnt); |
30406 |
++__u32 gr_acl_handle_rmdir(const struct dentry *dentry, |
30407 |
++ const struct vfsmount *mnt); |
30408 |
++void gr_handle_delete(const ino_t ino, const dev_t dev); |
30409 |
++__u32 gr_acl_handle_unlink(const struct dentry *dentry, |
30410 |
++ const struct vfsmount *mnt); |
30411 |
++__u32 gr_acl_handle_symlink(const struct dentry *new_dentry, |
30412 |
++ const struct dentry *parent_dentry, |
30413 |
++ const struct vfsmount *parent_mnt, |
30414 |
++ const char *from); |
30415 |
++__u32 gr_acl_handle_link(const struct dentry *new_dentry, |
30416 |
++ const struct dentry *parent_dentry, |
30417 |
++ const struct vfsmount *parent_mnt, |
30418 |
++ const struct dentry *old_dentry, |
30419 |
++ const struct vfsmount *old_mnt, const char *to); |
30420 |
++int gr_acl_handle_rename(struct dentry *new_dentry, |
30421 |
++ struct dentry *parent_dentry, |
30422 |
++ const struct vfsmount *parent_mnt, |
30423 |
++ struct dentry *old_dentry, |
30424 |
++ struct inode *old_parent_inode, |
30425 |
++ struct vfsmount *old_mnt, const char *newname); |
30426 |
++void gr_handle_rename(struct inode *old_dir, struct inode *new_dir, |
30427 |
++ struct dentry *old_dentry, |
30428 |
++ struct dentry *new_dentry, |
30429 |
++ struct vfsmount *mnt, const __u8 replace); |
30430 |
++__u32 gr_check_link(const struct dentry *new_dentry, |
30431 |
++ const struct dentry *parent_dentry, |
30432 |
++ const struct vfsmount *parent_mnt, |
30433 |
++ const struct dentry *old_dentry, |
30434 |
++ const struct vfsmount *old_mnt); |
30435 |
++int gr_acl_handle_filldir(const struct file *file, const char *name, |
30436 |
++ const unsigned int namelen, const ino_t ino); |
30437 |
++ |
30438 |
++__u32 gr_acl_handle_unix(const struct dentry *dentry, |
30439 |
++ const struct vfsmount *mnt); |
30440 |
++void gr_acl_handle_exit(void); |
30441 |
++void gr_acl_handle_psacct(struct task_struct *task, const long code); |
30442 |
++int gr_acl_handle_procpidmem(const struct task_struct *task); |
30443 |
++ |
30444 |
++#ifdef CONFIG_GRKERNSEC |
30445 |
++void gr_handle_mem_write(void); |
30446 |
++void gr_handle_kmem_write(void); |
30447 |
++void gr_handle_open_port(void); |
30448 |
++int gr_handle_mem_mmap(const unsigned long offset, |
30449 |
++ struct vm_area_struct *vma); |
30450 |
++ |
30451 |
++extern int grsec_enable_dmesg; |
30452 |
++extern int grsec_enable_randsrc; |
30453 |
++extern int grsec_enable_shm; |
30454 |
++#endif |
30455 |
++ |
30456 |
++#endif |
30457 |
+diff -urNp linux-2.6.28.8/include/linux/highmem.h linux-2.6.28.8/include/linux/highmem.h |
30458 |
+--- linux-2.6.28.8/include/linux/highmem.h 2009-02-06 16:47:45.000000000 -0500 |
30459 |
++++ linux-2.6.28.8/include/linux/highmem.h 2009-03-07 10:35:39.000000000 -0500 |
30460 |
+@@ -124,6 +124,18 @@ static inline void clear_highpage(struct |
30461 |
+ kunmap_atomic(kaddr, KM_USER0); |
30462 |
+ } |
30463 |
+ |
30464 |
++static inline void sanitize_highpage(struct page *page) |
30465 |
++{ |
30466 |
++ void *kaddr; |
30467 |
++ unsigned long flags; |
30468 |
++ |
30469 |
++ local_irq_save(flags); |
30470 |
++ kaddr = kmap_atomic(page, KM_CLEARPAGE); |
30471 |
++ clear_page(kaddr); |
30472 |
++ kunmap_atomic(kaddr, KM_CLEARPAGE); |
30473 |
++ local_irq_restore(flags); |
30474 |
++} |
30475 |
++ |
30476 |
+ static inline void zero_user_segments(struct page *page, |
30477 |
+ unsigned start1, unsigned end1, |
30478 |
+ unsigned start2, unsigned end2) |
30479 |
+diff -urNp linux-2.6.28.8/include/linux/jbd2.h linux-2.6.28.8/include/linux/jbd2.h |
30480 |
+--- linux-2.6.28.8/include/linux/jbd2.h 2009-03-07 10:24:49.000000000 -0500 |
30481 |
++++ linux-2.6.28.8/include/linux/jbd2.h 2009-03-07 10:29:51.000000000 -0500 |
30482 |
+@@ -66,7 +66,7 @@ extern u8 jbd2_journal_enable_debug; |
30483 |
+ } \ |
30484 |
+ } while (0) |
30485 |
+ #else |
30486 |
+-#define jbd_debug(f, a...) /**/ |
30487 |
++#define jbd_debug(f, a...) do {} while (0) |
30488 |
+ #endif |
30489 |
+ |
30490 |
+ static inline void *jbd2_alloc(size_t size, gfp_t flags) |
30491 |
+diff -urNp linux-2.6.28.8/include/linux/jbd.h linux-2.6.28.8/include/linux/jbd.h |
30492 |
+--- linux-2.6.28.8/include/linux/jbd.h 2009-02-06 16:47:45.000000000 -0500 |
30493 |
++++ linux-2.6.28.8/include/linux/jbd.h 2009-02-21 09:37:49.000000000 -0500 |
30494 |
+@@ -66,7 +66,7 @@ extern u8 journal_enable_debug; |
30495 |
+ } \ |
30496 |
+ } while (0) |
30497 |
+ #else |
30498 |
+-#define jbd_debug(f, a...) /**/ |
30499 |
++#define jbd_debug(f, a...) do {} while (0) |
30500 |
+ #endif |
30501 |
+ |
30502 |
+ static inline void *jbd_alloc(size_t size, gfp_t flags) |
30503 |
+diff -urNp linux-2.6.28.8/include/linux/kvm_host.h linux-2.6.28.8/include/linux/kvm_host.h |
30504 |
+--- linux-2.6.28.8/include/linux/kvm_host.h 2009-02-06 16:47:45.000000000 -0500 |
30505 |
++++ linux-2.6.28.8/include/linux/kvm_host.h 2009-02-21 09:37:49.000000000 -0500 |
30506 |
+@@ -150,7 +150,7 @@ void kvm_vcpu_uninit(struct kvm_vcpu *vc |
30507 |
+ void vcpu_load(struct kvm_vcpu *vcpu); |
30508 |
+ void vcpu_put(struct kvm_vcpu *vcpu); |
30509 |
+ |
30510 |
+-int kvm_init(void *opaque, unsigned int vcpu_size, |
30511 |
++int kvm_init(const void *opaque, unsigned int vcpu_size, |
30512 |
+ struct module *module); |
30513 |
+ void kvm_exit(void); |
30514 |
+ |
30515 |
+@@ -258,7 +258,7 @@ int kvm_arch_vcpu_ioctl_debug_guest(stru |
30516 |
+ struct kvm_debug_guest *dbg); |
30517 |
+ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run); |
30518 |
+ |
30519 |
+-int kvm_arch_init(void *opaque); |
30520 |
++int kvm_arch_init(const void *opaque); |
30521 |
+ void kvm_arch_exit(void); |
30522 |
+ |
30523 |
+ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu); |
30524 |
+diff -urNp linux-2.6.28.8/include/linux/libata.h linux-2.6.28.8/include/linux/libata.h |
30525 |
+--- linux-2.6.28.8/include/linux/libata.h 2009-02-06 16:47:45.000000000 -0500 |
30526 |
++++ linux-2.6.28.8/include/linux/libata.h 2009-02-21 09:37:49.000000000 -0500 |
30527 |
+@@ -64,11 +64,11 @@ |
30528 |
+ #ifdef ATA_VERBOSE_DEBUG |
30529 |
+ #define VPRINTK(fmt, args...) printk(KERN_ERR "%s: " fmt, __func__, ## args) |
30530 |
+ #else |
30531 |
+-#define VPRINTK(fmt, args...) |
30532 |
++#define VPRINTK(fmt, args...) do {} while (0) |
30533 |
+ #endif /* ATA_VERBOSE_DEBUG */ |
30534 |
+ #else |
30535 |
+-#define DPRINTK(fmt, args...) |
30536 |
+-#define VPRINTK(fmt, args...) |
30537 |
++#define DPRINTK(fmt, args...) do {} while (0) |
30538 |
++#define VPRINTK(fmt, args...) do {} while (0) |
30539 |
+ #endif /* ATA_DEBUG */ |
30540 |
+ |
30541 |
+ #define BPRINTK(fmt, args...) if (ap->flags & ATA_FLAG_DEBUGMSG) printk(KERN_ERR "%s: " fmt, __func__, ## args) |
30542 |
+diff -urNp linux-2.6.28.8/include/linux/mm.h linux-2.6.28.8/include/linux/mm.h |
30543 |
+--- linux-2.6.28.8/include/linux/mm.h 2009-03-07 10:24:49.000000000 -0500 |
30544 |
++++ linux-2.6.28.8/include/linux/mm.h 2009-03-07 10:29:51.000000000 -0500 |
30545 |
+@@ -39,6 +39,7 @@ extern unsigned long mmap_min_addr; |
30546 |
+ #include <asm/page.h> |
30547 |
+ #include <asm/pgtable.h> |
30548 |
+ #include <asm/processor.h> |
30549 |
++#include <asm/mman.h> |
30550 |
+ |
30551 |
+ #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n)) |
30552 |
+ |
30553 |
+@@ -115,6 +116,10 @@ extern unsigned int kobjsize(const void |
30554 |
+ #define VM_MIXEDMAP 0x10000000 /* Can contain "struct page" and pure PFN pages */ |
30555 |
+ #define VM_SAO 0x20000000 /* Strong Access Ordering (powerpc) */ |
30556 |
+ |
30557 |
++#ifdef CONFIG_PAX_PAGEEXEC |
30558 |
++#define VM_PAGEEXEC 0x40000000 /* vma->vm_page_prot needs special handling */ |
30559 |
++#endif |
30560 |
++ |
30561 |
+ #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ |
30562 |
+ #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS |
30563 |
+ #endif |
30564 |
+@@ -873,6 +878,8 @@ struct shrinker { |
30565 |
+ extern void register_shrinker(struct shrinker *); |
30566 |
+ extern void unregister_shrinker(struct shrinker *); |
30567 |
+ |
30568 |
++pgprot_t vm_get_page_prot(unsigned long vm_flags); |
30569 |
++ |
30570 |
+ int vma_wants_writenotify(struct vm_area_struct *vma); |
30571 |
+ |
30572 |
+ extern pte_t *get_locked_pte(struct mm_struct *mm, unsigned long addr, spinlock_t **ptl); |
30573 |
+@@ -1141,6 +1148,7 @@ out: |
30574 |
+ } |
30575 |
+ |
30576 |
+ extern int do_munmap(struct mm_struct *, unsigned long, size_t); |
30577 |
++extern int __do_munmap(struct mm_struct *, unsigned long, size_t); |
30578 |
+ |
30579 |
+ extern unsigned long do_brk(unsigned long, unsigned long); |
30580 |
+ |
30581 |
+@@ -1193,6 +1201,10 @@ extern struct vm_area_struct * find_vma( |
30582 |
+ extern struct vm_area_struct * find_vma_prev(struct mm_struct * mm, unsigned long addr, |
30583 |
+ struct vm_area_struct **pprev); |
30584 |
+ |
30585 |
++extern struct vm_area_struct *pax_find_mirror_vma(struct vm_area_struct *vma); |
30586 |
++extern void pax_mirror_vma(struct vm_area_struct *vma_m, struct vm_area_struct *vma); |
30587 |
++extern void pax_mirror_file_pte(struct vm_area_struct *vma, unsigned long address, struct page *page_m, spinlock_t *ptl); |
30588 |
++ |
30589 |
+ /* Look up the first VMA which intersects the interval start_addr..end_addr-1, |
30590 |
+ NULL if none. Assume start_addr < end_addr. */ |
30591 |
+ static inline struct vm_area_struct * find_vma_intersection(struct mm_struct * mm, unsigned long start_addr, unsigned long end_addr) |
30592 |
+@@ -1209,7 +1221,6 @@ static inline unsigned long vma_pages(st |
30593 |
+ return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; |
30594 |
+ } |
30595 |
+ |
30596 |
+-pgprot_t vm_get_page_prot(unsigned long vm_flags); |
30597 |
+ struct vm_area_struct *find_extend_vma(struct mm_struct *, unsigned long addr); |
30598 |
+ int remap_pfn_range(struct vm_area_struct *, unsigned long addr, |
30599 |
+ unsigned long pfn, unsigned long size, pgprot_t); |
30600 |
+@@ -1298,5 +1309,11 @@ int vmemmap_populate_basepages(struct pa |
30601 |
+ int vmemmap_populate(struct page *start_page, unsigned long pages, int node); |
30602 |
+ void vmemmap_populate_print_last(void); |
30603 |
+ |
30604 |
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT |
30605 |
++extern void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot); |
30606 |
++#else |
30607 |
++static inline void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot) {} |
30608 |
++#endif |
30609 |
++ |
30610 |
+ #endif /* __KERNEL__ */ |
30611 |
+ #endif /* _LINUX_MM_H */ |
30612 |
+diff -urNp linux-2.6.28.8/include/linux/mm_types.h linux-2.6.28.8/include/linux/mm_types.h |
30613 |
+--- linux-2.6.28.8/include/linux/mm_types.h 2009-02-06 16:47:45.000000000 -0500 |
30614 |
++++ linux-2.6.28.8/include/linux/mm_types.h 2009-02-21 09:37:49.000000000 -0500 |
30615 |
+@@ -157,6 +157,8 @@ struct vm_area_struct { |
30616 |
+ #ifdef CONFIG_NUMA |
30617 |
+ struct mempolicy *vm_policy; /* NUMA policy for the VMA */ |
30618 |
+ #endif |
30619 |
++ |
30620 |
++ struct vm_area_struct *vm_mirror;/* PaX: mirror vma or NULL */ |
30621 |
+ }; |
30622 |
+ |
30623 |
+ struct core_thread { |
30624 |
+@@ -256,6 +258,24 @@ struct mm_struct { |
30625 |
+ #ifdef CONFIG_MMU_NOTIFIER |
30626 |
+ struct mmu_notifier_mm *mmu_notifier_mm; |
30627 |
+ #endif |
30628 |
++ |
30629 |
++#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS) || defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) |
30630 |
++ unsigned long pax_flags; |
30631 |
++#endif |
30632 |
++ |
30633 |
++#ifdef CONFIG_PAX_DLRESOLVE |
30634 |
++ unsigned long call_dl_resolve; |
30635 |
++#endif |
30636 |
++ |
30637 |
++#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT) |
30638 |
++ unsigned long call_syscall; |
30639 |
++#endif |
30640 |
++ |
30641 |
++#ifdef CONFIG_PAX_ASLR |
30642 |
++ unsigned long delta_mmap; /* randomized offset */ |
30643 |
++ unsigned long delta_stack; /* randomized offset */ |
30644 |
++#endif |
30645 |
++ |
30646 |
+ }; |
30647 |
+ |
30648 |
+ #endif /* _LINUX_MM_TYPES_H */ |
30649 |
+diff -urNp linux-2.6.28.8/include/linux/module.h linux-2.6.28.8/include/linux/module.h |
30650 |
+--- linux-2.6.28.8/include/linux/module.h 2009-02-07 16:10:45.000000000 -0500 |
30651 |
++++ linux-2.6.28.8/include/linux/module.h 2009-02-21 09:37:49.000000000 -0500 |
30652 |
+@@ -283,16 +283,16 @@ struct module |
30653 |
+ int (*init)(void); |
30654 |
+ |
30655 |
+ /* If this is non-NULL, vfree after init() returns */ |
30656 |
+- void *module_init; |
30657 |
++ void *module_init_rx, *module_init_rw; |
30658 |
+ |
30659 |
+ /* Here is the actual code + data, vfree'd on unload. */ |
30660 |
+- void *module_core; |
30661 |
++ void *module_core_rx, *module_core_rw; |
30662 |
+ |
30663 |
+ /* Here are the sizes of the init and core sections */ |
30664 |
+- unsigned int init_size, core_size; |
30665 |
++ unsigned int init_size_rw, core_size_rw; |
30666 |
+ |
30667 |
+ /* The size of the executable code in each section. */ |
30668 |
+- unsigned int init_text_size, core_text_size; |
30669 |
++ unsigned int init_size_rx, core_size_rx; |
30670 |
+ |
30671 |
+ /* The handle returned from unwind_add_table. */ |
30672 |
+ void *unwind_info; |
30673 |
+diff -urNp linux-2.6.28.8/include/linux/moduleloader.h linux-2.6.28.8/include/linux/moduleloader.h |
30674 |
+--- linux-2.6.28.8/include/linux/moduleloader.h 2009-02-06 16:47:45.000000000 -0500 |
30675 |
++++ linux-2.6.28.8/include/linux/moduleloader.h 2009-02-21 09:37:49.000000000 -0500 |
30676 |
+@@ -17,9 +17,21 @@ int module_frob_arch_sections(Elf_Ehdr * |
30677 |
+ sections. Returns NULL on failure. */ |
30678 |
+ void *module_alloc(unsigned long size); |
30679 |
+ |
30680 |
++#ifdef CONFIG_PAX_KERNEXEC |
30681 |
++void *module_alloc_exec(unsigned long size); |
30682 |
++#else |
30683 |
++#define module_alloc_exec(x) module_alloc(x) |
30684 |
++#endif |
30685 |
++ |
30686 |
+ /* Free memory returned from module_alloc. */ |
30687 |
+ void module_free(struct module *mod, void *module_region); |
30688 |
+ |
30689 |
++#ifdef CONFIG_PAX_KERNEXEC |
30690 |
++void module_free_exec(struct module *mod, void *module_region); |
30691 |
++#else |
30692 |
++#define module_free_exec(x, y) module_free(x, y) |
30693 |
++#endif |
30694 |
++ |
30695 |
+ /* Apply the given relocation to the (simplified) ELF. Return -error |
30696 |
+ or 0. */ |
30697 |
+ int apply_relocate(Elf_Shdr *sechdrs, |
30698 |
+diff -urNp linux-2.6.28.8/include/linux/namei.h linux-2.6.28.8/include/linux/namei.h |
30699 |
+--- linux-2.6.28.8/include/linux/namei.h 2009-02-06 16:47:45.000000000 -0500 |
30700 |
++++ linux-2.6.28.8/include/linux/namei.h 2009-02-21 09:37:49.000000000 -0500 |
30701 |
+@@ -21,7 +21,7 @@ struct nameidata { |
30702 |
+ unsigned int flags; |
30703 |
+ int last_type; |
30704 |
+ unsigned depth; |
30705 |
+- char *saved_names[MAX_NESTED_LINKS + 1]; |
30706 |
++ const char *saved_names[MAX_NESTED_LINKS + 1]; |
30707 |
+ |
30708 |
+ /* Intent data */ |
30709 |
+ union { |
30710 |
+@@ -84,12 +84,12 @@ extern int follow_up(struct vfsmount **, |
30711 |
+ extern struct dentry *lock_rename(struct dentry *, struct dentry *); |
30712 |
+ extern void unlock_rename(struct dentry *, struct dentry *); |
30713 |
+ |
30714 |
+-static inline void nd_set_link(struct nameidata *nd, char *path) |
30715 |
++static inline void nd_set_link(struct nameidata *nd, const char *path) |
30716 |
+ { |
30717 |
+ nd->saved_names[nd->depth] = path; |
30718 |
+ } |
30719 |
+ |
30720 |
+-static inline char *nd_get_link(struct nameidata *nd) |
30721 |
++static inline const char *nd_get_link(struct nameidata *nd) |
30722 |
+ { |
30723 |
+ return nd->saved_names[nd->depth]; |
30724 |
+ } |
30725 |
+diff -urNp linux-2.6.28.8/include/linux/nodemask.h linux-2.6.28.8/include/linux/nodemask.h |
30726 |
+--- linux-2.6.28.8/include/linux/nodemask.h 2009-02-06 16:47:45.000000000 -0500 |
30727 |
++++ linux-2.6.28.8/include/linux/nodemask.h 2009-02-21 09:37:49.000000000 -0500 |
30728 |
+@@ -442,11 +442,11 @@ static inline int num_node_state(enum no |
30729 |
+ |
30730 |
+ #define any_online_node(mask) \ |
30731 |
+ ({ \ |
30732 |
+- int node; \ |
30733 |
+- for_each_node_mask(node, (mask)) \ |
30734 |
+- if (node_online(node)) \ |
30735 |
++ int __node; \ |
30736 |
++ for_each_node_mask(__node, (mask)) \ |
30737 |
++ if (node_online(__node)) \ |
30738 |
+ break; \ |
30739 |
+- node; \ |
30740 |
++ __node; \ |
30741 |
+ }) |
30742 |
+ |
30743 |
+ #define num_online_nodes() num_node_state(N_ONLINE) |
30744 |
+diff -urNp linux-2.6.28.8/include/linux/percpu.h linux-2.6.28.8/include/linux/percpu.h |
30745 |
+--- linux-2.6.28.8/include/linux/percpu.h 2009-02-06 16:47:45.000000000 -0500 |
30746 |
++++ linux-2.6.28.8/include/linux/percpu.h 2009-02-21 09:37:49.000000000 -0500 |
30747 |
+@@ -50,7 +50,7 @@ |
30748 |
+ #endif |
30749 |
+ |
30750 |
+ #define PERCPU_ENOUGH_ROOM \ |
30751 |
+- (__per_cpu_end - __per_cpu_start + PERCPU_MODULE_RESERVE) |
30752 |
++ ((unsigned long)(__per_cpu_end - __per_cpu_start + PERCPU_MODULE_RESERVE)) |
30753 |
+ #endif /* PERCPU_ENOUGH_ROOM */ |
30754 |
+ |
30755 |
+ /* |
30756 |
+diff -urNp linux-2.6.28.8/include/linux/poison.h linux-2.6.28.8/include/linux/poison.h |
30757 |
+--- linux-2.6.28.8/include/linux/poison.h 2009-02-06 16:47:45.000000000 -0500 |
30758 |
++++ linux-2.6.28.8/include/linux/poison.h 2009-02-21 09:37:49.000000000 -0500 |
30759 |
+@@ -7,8 +7,8 @@ |
30760 |
+ * under normal circumstances, used to verify that nobody uses |
30761 |
+ * non-initialized list entries. |
30762 |
+ */ |
30763 |
+-#define LIST_POISON1 ((void *) 0x00100100) |
30764 |
+-#define LIST_POISON2 ((void *) 0x00200200) |
30765 |
++#define LIST_POISON1 ((void *) 0xFF1001FFFF1001FFULL) |
30766 |
++#define LIST_POISON2 ((void *) 0xFF2002FFFF2002FFULL) |
30767 |
+ |
30768 |
+ /********** include/linux/timer.h **********/ |
30769 |
+ /* |
30770 |
+diff -urNp linux-2.6.28.8/include/linux/proc_fs.h linux-2.6.28.8/include/linux/proc_fs.h |
30771 |
+--- linux-2.6.28.8/include/linux/proc_fs.h 2009-02-06 16:47:45.000000000 -0500 |
30772 |
++++ linux-2.6.28.8/include/linux/proc_fs.h 2009-02-21 09:37:49.000000000 -0500 |
30773 |
+@@ -174,6 +174,19 @@ static inline struct proc_dir_entry *pro |
30774 |
+ return proc_create_data(name, mode, parent, proc_fops, NULL); |
30775 |
+ } |
30776 |
+ |
30777 |
++static inline struct proc_dir_entry *proc_create_grsec(const char *name, mode_t mode, |
30778 |
++ struct proc_dir_entry *parent, const struct file_operations *proc_fops) |
30779 |
++{ |
30780 |
++#ifdef CONFIG_GRKERNSEC_PROC_USER |
30781 |
++ return proc_create_data(name, S_IRUSR, parent, proc_fops, NULL); |
30782 |
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
30783 |
++ return proc_create_data(name, S_IRUSR | S_IRGRP, parent, proc_fops, NULL); |
30784 |
++#else |
30785 |
++ return proc_create_data(name, mode, parent, proc_fops, NULL); |
30786 |
++#endif |
30787 |
++} |
30788 |
++ |
30789 |
++ |
30790 |
+ static inline struct proc_dir_entry *create_proc_read_entry(const char *name, |
30791 |
+ mode_t mode, struct proc_dir_entry *base, |
30792 |
+ read_proc_t *read_proc, void * data) |
30793 |
+diff -urNp linux-2.6.28.8/include/linux/random.h linux-2.6.28.8/include/linux/random.h |
30794 |
+--- linux-2.6.28.8/include/linux/random.h 2009-02-06 16:47:45.000000000 -0500 |
30795 |
++++ linux-2.6.28.8/include/linux/random.h 2009-02-21 09:37:49.000000000 -0500 |
30796 |
+@@ -72,6 +72,11 @@ unsigned long randomize_range(unsigned l |
30797 |
+ u32 random32(void); |
30798 |
+ void srandom32(u32 seed); |
30799 |
+ |
30800 |
++static inline unsigned long pax_get_random_long(void) |
30801 |
++{ |
30802 |
++ return random32() + (sizeof(long) > 4 ? (unsigned long)random32() << 32 : 0); |
30803 |
++} |
30804 |
++ |
30805 |
+ #endif /* __KERNEL___ */ |
30806 |
+ |
30807 |
+ #endif /* _LINUX_RANDOM_H */ |
30808 |
+diff -urNp linux-2.6.28.8/include/linux/sched.h linux-2.6.28.8/include/linux/sched.h |
30809 |
+--- linux-2.6.28.8/include/linux/sched.h 2009-02-06 16:47:45.000000000 -0500 |
30810 |
++++ linux-2.6.28.8/include/linux/sched.h 2009-02-21 09:37:49.000000000 -0500 |
30811 |
+@@ -96,6 +96,7 @@ struct exec_domain; |
30812 |
+ struct futex_pi_state; |
30813 |
+ struct robust_list_head; |
30814 |
+ struct bio; |
30815 |
++struct linux_binprm; |
30816 |
+ |
30817 |
+ /* |
30818 |
+ * List of flags we want to share for kernel threads, |
30819 |
+@@ -588,6 +589,15 @@ struct signal_struct { |
30820 |
+ unsigned audit_tty; |
30821 |
+ struct tty_audit_buf *tty_audit_buf; |
30822 |
+ #endif |
30823 |
++ |
30824 |
++#ifdef CONFIG_GRKERNSEC |
30825 |
++ u32 curr_ip; |
30826 |
++ u32 gr_saddr; |
30827 |
++ u32 gr_daddr; |
30828 |
++ u16 gr_sport; |
30829 |
++ u16 gr_dport; |
30830 |
++ u8 used_accept:1; |
30831 |
++#endif |
30832 |
+ }; |
30833 |
+ |
30834 |
+ /* Context switch must be unlocked if interrupts are to be enabled */ |
30835 |
+@@ -1073,7 +1083,7 @@ struct sched_rt_entity { |
30836 |
+ |
30837 |
+ struct task_struct { |
30838 |
+ volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ |
30839 |
+- void *stack; |
30840 |
++ struct thread_info *stack; |
30841 |
+ atomic_t usage; |
30842 |
+ unsigned int flags; /* per process flags, defined below */ |
30843 |
+ unsigned int ptrace; |
30844 |
+@@ -1138,10 +1148,9 @@ struct task_struct { |
30845 |
+ pid_t pid; |
30846 |
+ pid_t tgid; |
30847 |
+ |
30848 |
+-#ifdef CONFIG_CC_STACKPROTECTOR |
30849 |
+ /* Canary value for the -fstack-protector gcc feature */ |
30850 |
+ unsigned long stack_canary; |
30851 |
+-#endif |
30852 |
++ |
30853 |
+ /* |
30854 |
+ * pointers to (original) parent process, youngest child, younger sibling, |
30855 |
+ * older sibling, respectively. (p->father can be replaced with |
30856 |
+@@ -1169,8 +1178,8 @@ struct task_struct { |
30857 |
+ struct list_head thread_group; |
30858 |
+ |
30859 |
+ struct completion *vfork_done; /* for vfork() */ |
30860 |
+- int __user *set_child_tid; /* CLONE_CHILD_SETTID */ |
30861 |
+- int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */ |
30862 |
++ pid_t __user *set_child_tid; /* CLONE_CHILD_SETTID */ |
30863 |
++ pid_t __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */ |
30864 |
+ |
30865 |
+ cputime_t utime, stime, utimescaled, stimescaled; |
30866 |
+ cputime_t gtime; |
30867 |
+@@ -1355,8 +1364,64 @@ struct task_struct { |
30868 |
+ unsigned long default_timer_slack_ns; |
30869 |
+ |
30870 |
+ struct list_head *scm_work_list; |
30871 |
++ |
30872 |
++#ifdef CONFIG_GRKERNSEC |
30873 |
++ /* grsecurity */ |
30874 |
++ struct acl_subject_label *acl; |
30875 |
++ struct acl_role_label *role; |
30876 |
++ struct file *exec_file; |
30877 |
++ u16 acl_role_id; |
30878 |
++ u8 acl_sp_role; |
30879 |
++ u8 is_writable; |
30880 |
++ u8 brute; |
30881 |
++#endif |
30882 |
++ |
30883 |
+ }; |
30884 |
+ |
30885 |
++#define MF_PAX_PAGEEXEC 0x01000000 /* Paging based non-executable pages */ |
30886 |
++#define MF_PAX_EMUTRAMP 0x02000000 /* Emulate trampolines */ |
30887 |
++#define MF_PAX_MPROTECT 0x04000000 /* Restrict mprotect() */ |
30888 |
++#define MF_PAX_RANDMMAP 0x08000000 /* Randomize mmap() base */ |
30889 |
++/*#define MF_PAX_RANDEXEC 0x10000000*/ /* Randomize ET_EXEC base */ |
30890 |
++#define MF_PAX_SEGMEXEC 0x20000000 /* Segmentation based non-executable pages */ |
30891 |
++ |
30892 |
++#ifdef CONFIG_PAX_SOFTMODE |
30893 |
++extern unsigned int pax_softmode; |
30894 |
++#endif |
30895 |
++ |
30896 |
++extern int pax_check_flags(unsigned long *); |
30897 |
++ |
30898 |
++/* if tsk != current then task_lock must be held on it */ |
30899 |
++#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) |
30900 |
++static inline unsigned long pax_get_flags(struct task_struct *tsk) |
30901 |
++{ |
30902 |
++ if (likely(tsk->mm)) |
30903 |
++ return tsk->mm->pax_flags; |
30904 |
++ else |
30905 |
++ return 0UL; |
30906 |
++} |
30907 |
++ |
30908 |
++/* if tsk != current then task_lock must be held on it */ |
30909 |
++static inline long pax_set_flags(struct task_struct *tsk, unsigned long flags) |
30910 |
++{ |
30911 |
++ if (likely(tsk->mm)) { |
30912 |
++ tsk->mm->pax_flags = flags; |
30913 |
++ return 0; |
30914 |
++ } |
30915 |
++ return -EINVAL; |
30916 |
++} |
30917 |
++#endif |
30918 |
++ |
30919 |
++#ifdef CONFIG_PAX_HAVE_ACL_FLAGS |
30920 |
++extern void pax_set_initial_flags(struct linux_binprm *bprm); |
30921 |
++#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS) |
30922 |
++extern void (*pax_set_initial_flags_func)(struct linux_binprm *bprm); |
30923 |
++#endif |
30924 |
++ |
30925 |
++void pax_report_fault(struct pt_regs *regs, void *pc, void *sp); |
30926 |
++void pax_report_insns(void *pc, void *sp); |
30927 |
++void pax_report_refcount_overflow(struct pt_regs *regs); |
30928 |
++ |
30929 |
+ /* |
30930 |
+ * Priority of a process goes from 0..MAX_PRIO-1, valid RT |
30931 |
+ * priority is 0..MAX_RT_PRIO-1, and SCHED_NORMAL/SCHED_BATCH |
30932 |
+@@ -1899,7 +1964,7 @@ extern void __cleanup_sighand(struct sig |
30933 |
+ extern void exit_itimers(struct signal_struct *); |
30934 |
+ extern void flush_itimer_signals(void); |
30935 |
+ |
30936 |
+-extern NORET_TYPE void do_group_exit(int); |
30937 |
++extern NORET_TYPE void do_group_exit(int) ATTRIB_NORET; |
30938 |
+ |
30939 |
+ extern void daemonize(const char *, ...); |
30940 |
+ extern int allow_signal(int); |
30941 |
+@@ -2002,8 +2067,8 @@ static inline void unlock_task_sighand(s |
30942 |
+ |
30943 |
+ #ifndef __HAVE_THREAD_FUNCTIONS |
30944 |
+ |
30945 |
+-#define task_thread_info(task) ((struct thread_info *)(task)->stack) |
30946 |
+-#define task_stack_page(task) ((task)->stack) |
30947 |
++#define task_thread_info(task) ((task)->stack) |
30948 |
++#define task_stack_page(task) ((void *)(task)->stack) |
30949 |
+ |
30950 |
+ static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) |
30951 |
+ { |
30952 |
+diff -urNp linux-2.6.28.8/include/linux/screen_info.h linux-2.6.28.8/include/linux/screen_info.h |
30953 |
+--- linux-2.6.28.8/include/linux/screen_info.h 2009-02-06 16:47:45.000000000 -0500 |
30954 |
++++ linux-2.6.28.8/include/linux/screen_info.h 2009-02-21 09:37:49.000000000 -0500 |
30955 |
+@@ -42,7 +42,8 @@ struct screen_info { |
30956 |
+ __u16 pages; /* 0x32 */ |
30957 |
+ __u16 vesa_attributes; /* 0x34 */ |
30958 |
+ __u32 capabilities; /* 0x36 */ |
30959 |
+- __u8 _reserved[6]; /* 0x3a */ |
30960 |
++ __u16 vesapm_size; /* 0x3a */ |
30961 |
++ __u8 _reserved[4]; /* 0x3c */ |
30962 |
+ } __attribute__((packed)); |
30963 |
+ |
30964 |
+ #define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */ |
30965 |
+diff -urNp linux-2.6.28.8/include/linux/security.h linux-2.6.28.8/include/linux/security.h |
30966 |
+--- linux-2.6.28.8/include/linux/security.h 2009-02-06 16:47:45.000000000 -0500 |
30967 |
++++ linux-2.6.28.8/include/linux/security.h 2009-02-21 09:37:49.000000000 -0500 |
30968 |
+@@ -32,6 +32,7 @@ |
30969 |
+ #include <linux/sched.h> |
30970 |
+ #include <linux/key.h> |
30971 |
+ #include <linux/xfrm.h> |
30972 |
++#include <linux/grsecurity.h> |
30973 |
+ #include <net/flow.h> |
30974 |
+ |
30975 |
+ /* Maximum number of letters for an LSM name string */ |
30976 |
+diff -urNp linux-2.6.28.8/include/linux/shm.h linux-2.6.28.8/include/linux/shm.h |
30977 |
+--- linux-2.6.28.8/include/linux/shm.h 2009-02-06 16:47:45.000000000 -0500 |
30978 |
++++ linux-2.6.28.8/include/linux/shm.h 2009-02-21 09:37:49.000000000 -0500 |
30979 |
+@@ -95,6 +95,10 @@ struct shmid_kernel /* private to the ke |
30980 |
+ pid_t shm_cprid; |
30981 |
+ pid_t shm_lprid; |
30982 |
+ struct user_struct *mlock_user; |
30983 |
++#ifdef CONFIG_GRKERNSEC |
30984 |
++ time_t shm_createtime; |
30985 |
++ pid_t shm_lapid; |
30986 |
++#endif |
30987 |
+ }; |
30988 |
+ |
30989 |
+ /* shm_mode upper byte flags */ |
30990 |
+diff -urNp linux-2.6.28.8/include/linux/slab.h linux-2.6.28.8/include/linux/slab.h |
30991 |
+--- linux-2.6.28.8/include/linux/slab.h 2009-02-06 16:47:45.000000000 -0500 |
30992 |
++++ linux-2.6.28.8/include/linux/slab.h 2009-02-21 09:37:49.000000000 -0500 |
30993 |
+@@ -73,10 +73,9 @@ |
30994 |
+ * ZERO_SIZE_PTR can be passed to kfree though in the same way that NULL can. |
30995 |
+ * Both make kfree a no-op. |
30996 |
+ */ |
30997 |
+-#define ZERO_SIZE_PTR ((void *)16) |
30998 |
++#define ZERO_SIZE_PTR ((void *)-1024L) |
30999 |
+ |
31000 |
+-#define ZERO_OR_NULL_PTR(x) ((unsigned long)(x) <= \ |
31001 |
+- (unsigned long)ZERO_SIZE_PTR) |
31002 |
++#define ZERO_OR_NULL_PTR(x) (!(x) || (x) == ZERO_SIZE_PTR) |
31003 |
+ |
31004 |
+ /* |
31005 |
+ * struct kmem_cache related prototypes |
31006 |
+diff -urNp linux-2.6.28.8/include/linux/sysctl.h linux-2.6.28.8/include/linux/sysctl.h |
31007 |
+--- linux-2.6.28.8/include/linux/sysctl.h 2009-02-06 16:47:45.000000000 -0500 |
31008 |
++++ linux-2.6.28.8/include/linux/sysctl.h 2009-02-21 09:37:49.000000000 -0500 |
31009 |
+@@ -165,7 +165,11 @@ enum |
31010 |
+ KERN_PANIC_ON_NMI=76, /* int: whether we will panic on an unrecovered */ |
31011 |
+ }; |
31012 |
+ |
31013 |
+- |
31014 |
++#ifdef CONFIG_PAX_SOFTMODE |
31015 |
++enum { |
31016 |
++ PAX_SOFTMODE=1 /* PaX: disable/enable soft mode */ |
31017 |
++}; |
31018 |
++#endif |
31019 |
+ |
31020 |
+ /* CTL_VM names: */ |
31021 |
+ enum |
31022 |
+diff -urNp linux-2.6.28.8/include/linux/thread_info.h linux-2.6.28.8/include/linux/thread_info.h |
31023 |
+--- linux-2.6.28.8/include/linux/thread_info.h 2009-02-06 16:47:45.000000000 -0500 |
31024 |
++++ linux-2.6.28.8/include/linux/thread_info.h 2009-02-21 09:37:49.000000000 -0500 |
31025 |
+@@ -23,7 +23,7 @@ struct restart_block { |
31026 |
+ }; |
31027 |
+ /* For futex_wait */ |
31028 |
+ struct { |
31029 |
+- u32 *uaddr; |
31030 |
++ u32 __user *uaddr; |
31031 |
+ u32 val; |
31032 |
+ u32 flags; |
31033 |
+ u32 bitset; |
31034 |
+diff -urNp linux-2.6.28.8/include/linux/uaccess.h linux-2.6.28.8/include/linux/uaccess.h |
31035 |
+--- linux-2.6.28.8/include/linux/uaccess.h 2009-02-06 16:47:45.000000000 -0500 |
31036 |
++++ linux-2.6.28.8/include/linux/uaccess.h 2009-02-21 09:37:49.000000000 -0500 |
31037 |
+@@ -76,11 +76,11 @@ static inline unsigned long __copy_from_ |
31038 |
+ long ret; \ |
31039 |
+ mm_segment_t old_fs = get_fs(); \ |
31040 |
+ \ |
31041 |
+- set_fs(KERNEL_DS); \ |
31042 |
+ pagefault_disable(); \ |
31043 |
++ set_fs(KERNEL_DS); \ |
31044 |
+ ret = __get_user(retval, (__force typeof(retval) __user *)(addr)); \ |
31045 |
+- pagefault_enable(); \ |
31046 |
+ set_fs(old_fs); \ |
31047 |
++ pagefault_enable(); \ |
31048 |
+ ret; \ |
31049 |
+ }) |
31050 |
+ |
31051 |
+diff -urNp linux-2.6.28.8/include/linux/vmalloc.h linux-2.6.28.8/include/linux/vmalloc.h |
31052 |
+--- linux-2.6.28.8/include/linux/vmalloc.h 2009-02-06 16:47:45.000000000 -0500 |
31053 |
++++ linux-2.6.28.8/include/linux/vmalloc.h 2009-02-21 09:37:49.000000000 -0500 |
31054 |
+@@ -13,6 +13,11 @@ struct vm_area_struct; /* vma defining |
31055 |
+ #define VM_MAP 0x00000004 /* vmap()ed pages */ |
31056 |
+ #define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */ |
31057 |
+ #define VM_VPAGES 0x00000010 /* buffer for pages was vmalloc'ed */ |
31058 |
++ |
31059 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) |
31060 |
++#define VM_KERNEXEC 0x00000020 /* allocate from executable kernel memory range */ |
31061 |
++#endif |
31062 |
++ |
31063 |
+ /* bits [20..32] reserved for arch specific ioremap internals */ |
31064 |
+ |
31065 |
+ /* |
31066 |
+diff -urNp linux-2.6.28.8/include/net/sctp/sctp.h linux-2.6.28.8/include/net/sctp/sctp.h |
31067 |
+--- linux-2.6.28.8/include/net/sctp/sctp.h 2009-02-06 16:47:45.000000000 -0500 |
31068 |
++++ linux-2.6.28.8/include/net/sctp/sctp.h 2009-02-21 09:37:49.000000000 -0500 |
31069 |
+@@ -309,8 +309,8 @@ extern int sctp_debug_flag; |
31070 |
+ |
31071 |
+ #else /* SCTP_DEBUG */ |
31072 |
+ |
31073 |
+-#define SCTP_DEBUG_PRINTK(whatever...) |
31074 |
+-#define SCTP_DEBUG_PRINTK_IPADDR(whatever...) |
31075 |
++#define SCTP_DEBUG_PRINTK(whatever...) do {} while (0) |
31076 |
++#define SCTP_DEBUG_PRINTK_IPADDR(whatever...) do {} while (0) |
31077 |
+ #define SCTP_ENABLE_DEBUG |
31078 |
+ #define SCTP_DISABLE_DEBUG |
31079 |
+ #define SCTP_ASSERT(expr, str, func) |
31080 |
+diff -urNp linux-2.6.28.8/include/sound/core.h linux-2.6.28.8/include/sound/core.h |
31081 |
+--- linux-2.6.28.8/include/sound/core.h 2009-02-06 16:47:45.000000000 -0500 |
31082 |
++++ linux-2.6.28.8/include/sound/core.h 2009-02-21 09:37:49.000000000 -0500 |
31083 |
+@@ -405,7 +405,7 @@ static inline int __snd_bug_on(void) |
31084 |
+ */ |
31085 |
+ #define snd_printdd(format, args...) snd_printk(format, ##args) |
31086 |
+ #else |
31087 |
+-#define snd_printdd(format, args...) /* nothing */ |
31088 |
++#define snd_printdd(format, args...) do {} while (0) |
31089 |
+ #endif |
31090 |
+ |
31091 |
+ |
31092 |
+diff -urNp linux-2.6.28.8/include/video/uvesafb.h linux-2.6.28.8/include/video/uvesafb.h |
31093 |
+--- linux-2.6.28.8/include/video/uvesafb.h 2009-02-06 16:47:45.000000000 -0500 |
31094 |
++++ linux-2.6.28.8/include/video/uvesafb.h 2009-02-21 09:37:49.000000000 -0500 |
31095 |
+@@ -175,6 +175,7 @@ struct uvesafb_par { |
31096 |
+ u8 ypan; /* 0 - nothing, 1 - ypan, 2 - ywrap */ |
31097 |
+ u8 pmi_setpal; /* PMI for palette changes */ |
31098 |
+ u16 *pmi_base; /* protected mode interface location */ |
31099 |
++ u8 *pmi_code; /* protected mode code location */ |
31100 |
+ void *pmi_start; |
31101 |
+ void *pmi_pal; |
31102 |
+ u8 *vbe_state_orig; /* |
31103 |
+diff -urNp linux-2.6.28.8/init/do_mounts.c linux-2.6.28.8/init/do_mounts.c |
31104 |
+--- linux-2.6.28.8/init/do_mounts.c 2009-02-06 16:47:45.000000000 -0500 |
31105 |
++++ linux-2.6.28.8/init/do_mounts.c 2009-02-21 09:37:49.000000000 -0500 |
31106 |
+@@ -214,11 +214,11 @@ static void __init get_fs_names(char *pa |
31107 |
+ |
31108 |
+ static int __init do_mount_root(char *name, char *fs, int flags, void *data) |
31109 |
+ { |
31110 |
+- int err = sys_mount(name, "/root", fs, flags, data); |
31111 |
++ int err = sys_mount((char __user *)name, (char __user *)"/root", (char __user *)fs, flags, (void __user *)data); |
31112 |
+ if (err) |
31113 |
+ return err; |
31114 |
+ |
31115 |
+- sys_chdir("/root"); |
31116 |
++ sys_chdir((char __user *)"/root"); |
31117 |
+ ROOT_DEV = current->fs->pwd.mnt->mnt_sb->s_dev; |
31118 |
+ printk("VFS: Mounted root (%s filesystem)%s.\n", |
31119 |
+ current->fs->pwd.mnt->mnt_sb->s_type->name, |
31120 |
+@@ -308,18 +308,18 @@ void __init change_floppy(char *fmt, ... |
31121 |
+ va_start(args, fmt); |
31122 |
+ vsprintf(buf, fmt, args); |
31123 |
+ va_end(args); |
31124 |
+- fd = sys_open("/dev/root", O_RDWR | O_NDELAY, 0); |
31125 |
++ fd = sys_open((char __user *)"/dev/root", O_RDWR | O_NDELAY, 0); |
31126 |
+ if (fd >= 0) { |
31127 |
+ sys_ioctl(fd, FDEJECT, 0); |
31128 |
+ sys_close(fd); |
31129 |
+ } |
31130 |
+ printk(KERN_NOTICE "VFS: Insert %s and press ENTER\n", buf); |
31131 |
+- fd = sys_open("/dev/console", O_RDWR, 0); |
31132 |
++ fd = sys_open((char __user *)"/dev/console", O_RDWR, 0); |
31133 |
+ if (fd >= 0) { |
31134 |
+ sys_ioctl(fd, TCGETS, (long)&termios); |
31135 |
+ termios.c_lflag &= ~ICANON; |
31136 |
+ sys_ioctl(fd, TCSETSF, (long)&termios); |
31137 |
+- sys_read(fd, &c, 1); |
31138 |
++ sys_read(fd, (char __user *)&c, 1); |
31139 |
+ termios.c_lflag |= ICANON; |
31140 |
+ sys_ioctl(fd, TCSETSF, (long)&termios); |
31141 |
+ sys_close(fd); |
31142 |
+@@ -406,7 +406,7 @@ void __init prepare_namespace(void) |
31143 |
+ |
31144 |
+ mount_root(); |
31145 |
+ out: |
31146 |
+- sys_mount(".", "/", NULL, MS_MOVE, NULL); |
31147 |
+- sys_chroot("."); |
31148 |
++ sys_mount((char __user *)".", (char __user *)"/", NULL, MS_MOVE, NULL); |
31149 |
++ sys_chroot((char __user *)"."); |
31150 |
+ } |
31151 |
+ |
31152 |
+diff -urNp linux-2.6.28.8/init/do_mounts.h linux-2.6.28.8/init/do_mounts.h |
31153 |
+--- linux-2.6.28.8/init/do_mounts.h 2009-02-06 16:47:45.000000000 -0500 |
31154 |
++++ linux-2.6.28.8/init/do_mounts.h 2009-02-21 09:37:49.000000000 -0500 |
31155 |
+@@ -14,15 +14,15 @@ extern int root_mountflags; |
31156 |
+ |
31157 |
+ static inline int create_dev(char *name, dev_t dev) |
31158 |
+ { |
31159 |
+- sys_unlink(name); |
31160 |
+- return sys_mknod(name, S_IFBLK|0600, new_encode_dev(dev)); |
31161 |
++ sys_unlink((char __user *)name); |
31162 |
++ return sys_mknod((char __user *)name, S_IFBLK|0600, new_encode_dev(dev)); |
31163 |
+ } |
31164 |
+ |
31165 |
+ #if BITS_PER_LONG == 32 |
31166 |
+ static inline u32 bstat(char *name) |
31167 |
+ { |
31168 |
+ struct stat64 stat; |
31169 |
+- if (sys_stat64(name, &stat) != 0) |
31170 |
++ if (sys_stat64((char __user *)name, (struct stat64 __user *)&stat) != 0) |
31171 |
+ return 0; |
31172 |
+ if (!S_ISBLK(stat.st_mode)) |
31173 |
+ return 0; |
31174 |
+diff -urNp linux-2.6.28.8/init/do_mounts_initrd.c linux-2.6.28.8/init/do_mounts_initrd.c |
31175 |
+--- linux-2.6.28.8/init/do_mounts_initrd.c 2009-02-06 16:47:45.000000000 -0500 |
31176 |
++++ linux-2.6.28.8/init/do_mounts_initrd.c 2009-02-21 09:37:49.000000000 -0500 |
31177 |
+@@ -32,7 +32,7 @@ static int __init do_linuxrc(void * shel |
31178 |
+ sys_close(old_fd);sys_close(root_fd); |
31179 |
+ sys_close(0);sys_close(1);sys_close(2); |
31180 |
+ sys_setsid(); |
31181 |
+- (void) sys_open("/dev/console",O_RDWR,0); |
31182 |
++ (void) sys_open((const char __user *)"/dev/console",O_RDWR,0); |
31183 |
+ (void) sys_dup(0); |
31184 |
+ (void) sys_dup(0); |
31185 |
+ return kernel_execve(shell, argv, envp_init); |
31186 |
+@@ -47,13 +47,13 @@ static void __init handle_initrd(void) |
31187 |
+ create_dev("/dev/root.old", Root_RAM0); |
31188 |
+ /* mount initrd on rootfs' /root */ |
31189 |
+ mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY); |
31190 |
+- sys_mkdir("/old", 0700); |
31191 |
+- root_fd = sys_open("/", 0, 0); |
31192 |
+- old_fd = sys_open("/old", 0, 0); |
31193 |
++ sys_mkdir((const char __user *)"/old", 0700); |
31194 |
++ root_fd = sys_open((const char __user *)"/", 0, 0); |
31195 |
++ old_fd = sys_open((const char __user *)"/old", 0, 0); |
31196 |
+ /* move initrd over / and chdir/chroot in initrd root */ |
31197 |
+- sys_chdir("/root"); |
31198 |
+- sys_mount(".", "/", NULL, MS_MOVE, NULL); |
31199 |
+- sys_chroot("."); |
31200 |
++ sys_chdir((const char __user *)"/root"); |
31201 |
++ sys_mount((char __user *)".", (char __user *)"/", NULL, MS_MOVE, NULL); |
31202 |
++ sys_chroot((const char __user *)"."); |
31203 |
+ |
31204 |
+ /* |
31205 |
+ * In case that a resume from disk is carried out by linuxrc or one of |
31206 |
+@@ -70,15 +70,15 @@ static void __init handle_initrd(void) |
31207 |
+ |
31208 |
+ /* move initrd to rootfs' /old */ |
31209 |
+ sys_fchdir(old_fd); |
31210 |
+- sys_mount("/", ".", NULL, MS_MOVE, NULL); |
31211 |
++ sys_mount((char __user *)"/", (char __user *)".", NULL, MS_MOVE, NULL); |
31212 |
+ /* switch root and cwd back to / of rootfs */ |
31213 |
+ sys_fchdir(root_fd); |
31214 |
+- sys_chroot("."); |
31215 |
++ sys_chroot((const char __user *)"."); |
31216 |
+ sys_close(old_fd); |
31217 |
+ sys_close(root_fd); |
31218 |
+ |
31219 |
+ if (new_decode_dev(real_root_dev) == Root_RAM0) { |
31220 |
+- sys_chdir("/old"); |
31221 |
++ sys_chdir((const char __user *)"/old"); |
31222 |
+ return; |
31223 |
+ } |
31224 |
+ |
31225 |
+@@ -86,17 +86,17 @@ static void __init handle_initrd(void) |
31226 |
+ mount_root(); |
31227 |
+ |
31228 |
+ printk(KERN_NOTICE "Trying to move old root to /initrd ... "); |
31229 |
+- error = sys_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL); |
31230 |
++ error = sys_mount((char __user *)"/old", (char __user *)"/root/initrd", NULL, MS_MOVE, NULL); |
31231 |
+ if (!error) |
31232 |
+ printk("okay\n"); |
31233 |
+ else { |
31234 |
+- int fd = sys_open("/dev/root.old", O_RDWR, 0); |
31235 |
++ int fd = sys_open((const char __user *)"/dev/root.old", O_RDWR, 0); |
31236 |
+ if (error == -ENOENT) |
31237 |
+ printk("/initrd does not exist. Ignored.\n"); |
31238 |
+ else |
31239 |
+ printk("failed\n"); |
31240 |
+ printk(KERN_NOTICE "Unmounting old root\n"); |
31241 |
+- sys_umount("/old", MNT_DETACH); |
31242 |
++ sys_umount((char __user *)"/old", MNT_DETACH); |
31243 |
+ printk(KERN_NOTICE "Trying to free ramdisk memory ... "); |
31244 |
+ if (fd < 0) { |
31245 |
+ error = fd; |
31246 |
+@@ -119,11 +119,11 @@ int __init initrd_load(void) |
31247 |
+ * mounted in the normal path. |
31248 |
+ */ |
31249 |
+ if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) { |
31250 |
+- sys_unlink("/initrd.image"); |
31251 |
++ sys_unlink((const char __user *)"/initrd.image"); |
31252 |
+ handle_initrd(); |
31253 |
+ return 1; |
31254 |
+ } |
31255 |
+ } |
31256 |
+- sys_unlink("/initrd.image"); |
31257 |
++ sys_unlink((const char __user *)"/initrd.image"); |
31258 |
+ return 0; |
31259 |
+ } |
31260 |
+diff -urNp linux-2.6.28.8/init/do_mounts_md.c linux-2.6.28.8/init/do_mounts_md.c |
31261 |
+--- linux-2.6.28.8/init/do_mounts_md.c 2009-02-06 16:47:45.000000000 -0500 |
31262 |
++++ linux-2.6.28.8/init/do_mounts_md.c 2009-02-21 09:37:49.000000000 -0500 |
31263 |
+@@ -171,7 +171,7 @@ static void __init md_setup_drive(void) |
31264 |
+ partitioned ? "_d" : "", minor, |
31265 |
+ md_setup_args[ent].device_names); |
31266 |
+ |
31267 |
+- fd = sys_open(name, 0, 0); |
31268 |
++ fd = sys_open((char __user *)name, 0, 0); |
31269 |
+ if (fd < 0) { |
31270 |
+ printk(KERN_ERR "md: open failed - cannot start " |
31271 |
+ "array %s\n", name); |
31272 |
+@@ -234,7 +234,7 @@ static void __init md_setup_drive(void) |
31273 |
+ * array without it |
31274 |
+ */ |
31275 |
+ sys_close(fd); |
31276 |
+- fd = sys_open(name, 0, 0); |
31277 |
++ fd = sys_open((char __user *)name, 0, 0); |
31278 |
+ sys_ioctl(fd, BLKRRPART, 0); |
31279 |
+ } |
31280 |
+ sys_close(fd); |
31281 |
+@@ -283,7 +283,7 @@ static void autodetect_raid(void) |
31282 |
+ printk(KERN_INFO "md: If you don't use raid, use raid=noautodetect\n"); |
31283 |
+ while (driver_probe_done() < 0) |
31284 |
+ msleep(100); |
31285 |
+- fd = sys_open("/dev/md0", 0, 0); |
31286 |
++ fd = sys_open((char __user *)"/dev/md0", 0, 0); |
31287 |
+ if (fd >= 0) { |
31288 |
+ sys_ioctl(fd, RAID_AUTORUN, raid_autopart); |
31289 |
+ sys_close(fd); |
31290 |
+diff -urNp linux-2.6.28.8/init/initramfs.c linux-2.6.28.8/init/initramfs.c |
31291 |
+--- linux-2.6.28.8/init/initramfs.c 2009-02-06 16:47:45.000000000 -0500 |
31292 |
++++ linux-2.6.28.8/init/initramfs.c 2009-02-21 09:37:49.000000000 -0500 |
31293 |
+@@ -276,7 +276,7 @@ static int __init maybe_link(void) |
31294 |
+ if (nlink >= 2) { |
31295 |
+ char *old = find_link(major, minor, ino, mode, collected); |
31296 |
+ if (old) |
31297 |
+- return (sys_link(old, collected) < 0) ? -1 : 1; |
31298 |
++ return (sys_link((char __user *)old, (char __user *)collected) < 0) ? -1 : 1; |
31299 |
+ } |
31300 |
+ return 0; |
31301 |
+ } |
31302 |
+@@ -285,11 +285,11 @@ static void __init clean_path(char *path |
31303 |
+ { |
31304 |
+ struct stat st; |
31305 |
+ |
31306 |
+- if (!sys_newlstat(path, &st) && (st.st_mode^mode) & S_IFMT) { |
31307 |
++ if (!sys_newlstat((char __user *)path, (struct stat __user *)&st) && (st.st_mode^mode) & S_IFMT) { |
31308 |
+ if (S_ISDIR(st.st_mode)) |
31309 |
+- sys_rmdir(path); |
31310 |
++ sys_rmdir((char __user *)path); |
31311 |
+ else |
31312 |
+- sys_unlink(path); |
31313 |
++ sys_unlink((char __user *)path); |
31314 |
+ } |
31315 |
+ } |
31316 |
+ |
31317 |
+@@ -312,7 +312,7 @@ static int __init do_name(void) |
31318 |
+ int openflags = O_WRONLY|O_CREAT; |
31319 |
+ if (ml != 1) |
31320 |
+ openflags |= O_TRUNC; |
31321 |
+- wfd = sys_open(collected, openflags, mode); |
31322 |
++ wfd = sys_open((char __user *)collected, openflags, mode); |
31323 |
+ |
31324 |
+ if (wfd >= 0) { |
31325 |
+ sys_fchown(wfd, uid, gid); |
31326 |
+@@ -322,16 +322,16 @@ static int __init do_name(void) |
31327 |
+ } |
31328 |
+ } |
31329 |
+ } else if (S_ISDIR(mode)) { |
31330 |
+- sys_mkdir(collected, mode); |
31331 |
+- sys_chown(collected, uid, gid); |
31332 |
+- sys_chmod(collected, mode); |
31333 |
++ sys_mkdir((char __user *)collected, mode); |
31334 |
++ sys_chown((char __user *)collected, uid, gid); |
31335 |
++ sys_chmod((char __user *)collected, mode); |
31336 |
+ dir_add(collected, mtime); |
31337 |
+ } else if (S_ISBLK(mode) || S_ISCHR(mode) || |
31338 |
+ S_ISFIFO(mode) || S_ISSOCK(mode)) { |
31339 |
+ if (maybe_link() == 0) { |
31340 |
+- sys_mknod(collected, mode, rdev); |
31341 |
+- sys_chown(collected, uid, gid); |
31342 |
+- sys_chmod(collected, mode); |
31343 |
++ sys_mknod((char __user *)collected, mode, rdev); |
31344 |
++ sys_chown((char __user *)collected, uid, gid); |
31345 |
++ sys_chmod((char __user *)collected, mode); |
31346 |
+ do_utime(collected, mtime); |
31347 |
+ } |
31348 |
+ } |
31349 |
+@@ -341,7 +341,7 @@ static int __init do_name(void) |
31350 |
+ static int __init do_copy(void) |
31351 |
+ { |
31352 |
+ if (count >= body_len) { |
31353 |
+- sys_write(wfd, victim, body_len); |
31354 |
++ sys_write(wfd, (char __user *)victim, body_len); |
31355 |
+ sys_close(wfd); |
31356 |
+ do_utime(vcollected, mtime); |
31357 |
+ kfree(vcollected); |
31358 |
+@@ -349,7 +349,7 @@ static int __init do_copy(void) |
31359 |
+ state = SkipIt; |
31360 |
+ return 0; |
31361 |
+ } else { |
31362 |
+- sys_write(wfd, victim, count); |
31363 |
++ sys_write(wfd, (char __user *)victim, count); |
31364 |
+ body_len -= count; |
31365 |
+ eat(count); |
31366 |
+ return 1; |
31367 |
+@@ -360,8 +360,8 @@ static int __init do_symlink(void) |
31368 |
+ { |
31369 |
+ collected[N_ALIGN(name_len) + body_len] = '\0'; |
31370 |
+ clean_path(collected, 0); |
31371 |
+- sys_symlink(collected + N_ALIGN(name_len), collected); |
31372 |
+- sys_lchown(collected, uid, gid); |
31373 |
++ sys_symlink((char __user *)collected + N_ALIGN(name_len), (char __user *)collected); |
31374 |
++ sys_lchown((char __user *)collected, uid, gid); |
31375 |
+ do_utime(collected, mtime); |
31376 |
+ state = SkipIt; |
31377 |
+ next_state = Reset; |
31378 |
+diff -urNp linux-2.6.28.8/init/Kconfig linux-2.6.28.8/init/Kconfig |
31379 |
+--- linux-2.6.28.8/init/Kconfig 2009-02-06 16:47:45.000000000 -0500 |
31380 |
++++ linux-2.6.28.8/init/Kconfig 2009-02-21 09:37:49.000000000 -0500 |
31381 |
+@@ -572,6 +572,7 @@ config SYSCTL_SYSCALL |
31382 |
+ config KALLSYMS |
31383 |
+ bool "Load all symbols for debugging/ksymoops" if EMBEDDED |
31384 |
+ default y |
31385 |
++ depends on !GRKERNSEC_HIDESYM |
31386 |
+ help |
31387 |
+ Say Y here to let the kernel print out symbolic crash information and |
31388 |
+ symbolic stack backtraces. This increases the size of the kernel |
31389 |
+@@ -822,9 +823,9 @@ config HAVE_GENERIC_DMA_COHERENT |
31390 |
+ |
31391 |
+ config SLABINFO |
31392 |
+ bool |
31393 |
+- depends on PROC_FS |
31394 |
++ depends on PROC_FS && !GRKERNSEC_PROC_ADD |
31395 |
+ depends on SLAB || SLUB_DEBUG |
31396 |
+- default y |
31397 |
++ default n |
31398 |
+ |
31399 |
+ config RT_MUTEXES |
31400 |
+ boolean |
31401 |
+diff -urNp linux-2.6.28.8/init/main.c linux-2.6.28.8/init/main.c |
31402 |
+--- linux-2.6.28.8/init/main.c 2009-02-06 16:47:45.000000000 -0500 |
31403 |
++++ linux-2.6.28.8/init/main.c 2009-02-21 09:37:49.000000000 -0500 |
31404 |
+@@ -104,6 +104,7 @@ static inline void mark_rodata_ro(void) |
31405 |
+ #ifdef CONFIG_TC |
31406 |
+ extern void tc_init(void); |
31407 |
+ #endif |
31408 |
++extern void grsecurity_init(void); |
31409 |
+ |
31410 |
+ enum system_states system_state; |
31411 |
+ EXPORT_SYMBOL(system_state); |
31412 |
+@@ -190,6 +191,40 @@ static int __init set_reset_devices(char |
31413 |
+ |
31414 |
+ __setup("reset_devices", set_reset_devices); |
31415 |
+ |
31416 |
++#if defined(CONFIG_PAX_MEMORY_UDEREF) && defined(CONFIG_X86_32) |
31417 |
++static int __init setup_pax_nouderef(char *str) |
31418 |
++{ |
31419 |
++ unsigned int cpu; |
31420 |
++ |
31421 |
++#ifdef CONFIG_PAX_KERNEXEC |
31422 |
++ unsigned long cr0; |
31423 |
++ |
31424 |
++ pax_open_kernel(cr0); |
31425 |
++#endif |
31426 |
++ |
31427 |
++ for (cpu = 0; cpu < NR_CPUS; cpu++) |
31428 |
++ get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_DS].b = 0x00cf9300; |
31429 |
++ |
31430 |
++#ifdef CONFIG_PAX_KERNEXEC |
31431 |
++ pax_close_kernel(cr0); |
31432 |
++#endif |
31433 |
++ |
31434 |
++ return 1; |
31435 |
++} |
31436 |
++__setup("pax_nouderef", setup_pax_nouderef); |
31437 |
++#endif |
31438 |
++ |
31439 |
++#ifdef CONFIG_PAX_SOFTMODE |
31440 |
++unsigned int pax_softmode; |
31441 |
++ |
31442 |
++static int __init setup_pax_softmode(char *str) |
31443 |
++{ |
31444 |
++ get_option(&str, &pax_softmode); |
31445 |
++ return 1; |
31446 |
++} |
31447 |
++__setup("pax_softmode=", setup_pax_softmode); |
31448 |
++#endif |
31449 |
++ |
31450 |
+ static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, }; |
31451 |
+ char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, }; |
31452 |
+ static const char *panic_later, *panic_param; |
31453 |
+@@ -388,7 +423,7 @@ static void __init setup_nr_cpu_ids(void |
31454 |
+ } |
31455 |
+ |
31456 |
+ #ifndef CONFIG_HAVE_SETUP_PER_CPU_AREA |
31457 |
+-unsigned long __per_cpu_offset[NR_CPUS] __read_mostly; |
31458 |
++unsigned long __per_cpu_offset[NR_CPUS] __read_only; |
31459 |
+ |
31460 |
+ EXPORT_SYMBOL(__per_cpu_offset); |
31461 |
+ |
31462 |
+@@ -704,6 +739,7 @@ int do_one_initcall(initcall_t fn) |
31463 |
+ { |
31464 |
+ int count = preempt_count(); |
31465 |
+ ktime_t delta; |
31466 |
++ const char *msg1 = "", *msg2 = ""; |
31467 |
+ char msgbuf[64]; |
31468 |
+ struct boot_trace it; |
31469 |
+ |
31470 |
+@@ -730,15 +766,15 @@ int do_one_initcall(initcall_t fn) |
31471 |
+ sprintf(msgbuf, "error code %d ", it.result); |
31472 |
+ |
31473 |
+ if (preempt_count() != count) { |
31474 |
+- strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf)); |
31475 |
++ msg1 = " preemption imbalance"; |
31476 |
+ preempt_count() = count; |
31477 |
+ } |
31478 |
+ if (irqs_disabled()) { |
31479 |
+- strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); |
31480 |
++ msg2 = " disabled interrupts"; |
31481 |
+ local_irq_enable(); |
31482 |
+ } |
31483 |
+- if (msgbuf[0]) { |
31484 |
+- printk("initcall %pF returned with %s\n", fn, msgbuf); |
31485 |
++ if (msgbuf[0] || *msg1 || *msg2) { |
31486 |
++ printk("initcall %pF returned with %s%s%s\n", fn, msgbuf, msg1, msg2); |
31487 |
+ } |
31488 |
+ |
31489 |
+ return it.result; |
31490 |
+@@ -877,6 +913,8 @@ static int __init kernel_init(void * unu |
31491 |
+ prepare_namespace(); |
31492 |
+ } |
31493 |
+ |
31494 |
++ grsecurity_init(); |
31495 |
++ |
31496 |
+ /* |
31497 |
+ * Ok, we have completed the initial bootup, and |
31498 |
+ * we're essentially up and running. Get rid of the |
31499 |
+diff -urNp linux-2.6.28.8/init/noinitramfs.c linux-2.6.28.8/init/noinitramfs.c |
31500 |
+--- linux-2.6.28.8/init/noinitramfs.c 2009-02-06 16:47:45.000000000 -0500 |
31501 |
++++ linux-2.6.28.8/init/noinitramfs.c 2009-02-21 09:37:49.000000000 -0500 |
31502 |
+@@ -29,7 +29,7 @@ static int __init default_rootfs(void) |
31503 |
+ { |
31504 |
+ int err; |
31505 |
+ |
31506 |
+- err = sys_mkdir("/dev", 0755); |
31507 |
++ err = sys_mkdir((const char __user *)"/dev", 0755); |
31508 |
+ if (err < 0) |
31509 |
+ goto out; |
31510 |
+ |
31511 |
+@@ -39,7 +39,7 @@ static int __init default_rootfs(void) |
31512 |
+ if (err < 0) |
31513 |
+ goto out; |
31514 |
+ |
31515 |
+- err = sys_mkdir("/root", 0700); |
31516 |
++ err = sys_mkdir((const char __user *)"/root", 0700); |
31517 |
+ if (err < 0) |
31518 |
+ goto out; |
31519 |
+ |
31520 |
+diff -urNp linux-2.6.28.8/ipc/ipc_sysctl.c linux-2.6.28.8/ipc/ipc_sysctl.c |
31521 |
+--- linux-2.6.28.8/ipc/ipc_sysctl.c 2009-02-06 16:47:45.000000000 -0500 |
31522 |
++++ linux-2.6.28.8/ipc/ipc_sysctl.c 2009-02-21 09:37:49.000000000 -0500 |
31523 |
+@@ -267,7 +267,7 @@ static struct ctl_table ipc_kern_table[] |
31524 |
+ .extra1 = &zero, |
31525 |
+ .extra2 = &one, |
31526 |
+ }, |
31527 |
+- {} |
31528 |
++ { 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } |
31529 |
+ }; |
31530 |
+ |
31531 |
+ static struct ctl_table ipc_root_table[] = { |
31532 |
+@@ -277,7 +277,7 @@ static struct ctl_table ipc_root_table[] |
31533 |
+ .mode = 0555, |
31534 |
+ .child = ipc_kern_table, |
31535 |
+ }, |
31536 |
+- {} |
31537 |
++ { 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } |
31538 |
+ }; |
31539 |
+ |
31540 |
+ static int __init ipc_sysctl_init(void) |
31541 |
+diff -urNp linux-2.6.28.8/ipc/msg.c linux-2.6.28.8/ipc/msg.c |
31542 |
+--- linux-2.6.28.8/ipc/msg.c 2009-02-06 16:47:45.000000000 -0500 |
31543 |
++++ linux-2.6.28.8/ipc/msg.c 2009-02-21 09:37:49.000000000 -0500 |
31544 |
+@@ -314,6 +314,7 @@ SYSCALL_DEFINE2(msgget, key_t, key, int, |
31545 |
+ struct ipc_namespace *ns; |
31546 |
+ struct ipc_ops msg_ops; |
31547 |
+ struct ipc_params msg_params; |
31548 |
++ long err; |
31549 |
+ |
31550 |
+ ns = current->nsproxy->ipc_ns; |
31551 |
+ |
31552 |
+@@ -324,7 +325,11 @@ SYSCALL_DEFINE2(msgget, key_t, key, int, |
31553 |
+ msg_params.key = key; |
31554 |
+ msg_params.flg = msgflg; |
31555 |
+ |
31556 |
+- return ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params); |
31557 |
++ err = ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params); |
31558 |
++ |
31559 |
++ gr_log_msgget(err, msgflg); |
31560 |
++ |
31561 |
++ return err; |
31562 |
+ } |
31563 |
+ |
31564 |
+ static inline unsigned long |
31565 |
+@@ -434,6 +439,7 @@ static int msgctl_down(struct ipc_namesp |
31566 |
+ |
31567 |
+ switch (cmd) { |
31568 |
+ case IPC_RMID: |
31569 |
++ gr_log_msgrm(ipcp->uid, ipcp->cuid); |
31570 |
+ freeque(ns, ipcp); |
31571 |
+ goto out_up; |
31572 |
+ case IPC_SET: |
31573 |
+diff -urNp linux-2.6.28.8/ipc/sem.c linux-2.6.28.8/ipc/sem.c |
31574 |
+--- linux-2.6.28.8/ipc/sem.c 2009-02-06 16:47:45.000000000 -0500 |
31575 |
++++ linux-2.6.28.8/ipc/sem.c 2009-02-21 09:37:49.000000000 -0500 |
31576 |
+@@ -313,6 +313,7 @@ SYSCALL_DEFINE3(semget, key_t, key, int, |
31577 |
+ struct ipc_namespace *ns; |
31578 |
+ struct ipc_ops sem_ops; |
31579 |
+ struct ipc_params sem_params; |
31580 |
++ long err; |
31581 |
+ |
31582 |
+ ns = current->nsproxy->ipc_ns; |
31583 |
+ |
31584 |
+@@ -327,7 +328,11 @@ SYSCALL_DEFINE3(semget, key_t, key, int, |
31585 |
+ sem_params.flg = semflg; |
31586 |
+ sem_params.u.nsems = nsems; |
31587 |
+ |
31588 |
+- return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params); |
31589 |
++ err = ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params); |
31590 |
++ |
31591 |
++ gr_log_semget(err, semflg); |
31592 |
++ |
31593 |
++ return err; |
31594 |
+ } |
31595 |
+ |
31596 |
+ /* |
31597 |
+@@ -870,6 +875,7 @@ static int semctl_down(struct ipc_namesp |
31598 |
+ |
31599 |
+ switch(cmd){ |
31600 |
+ case IPC_RMID: |
31601 |
++ gr_log_semrm(ipcp->uid, ipcp->cuid); |
31602 |
+ freeary(ns, ipcp); |
31603 |
+ goto out_up; |
31604 |
+ case IPC_SET: |
31605 |
+diff -urNp linux-2.6.28.8/ipc/shm.c linux-2.6.28.8/ipc/shm.c |
31606 |
+--- linux-2.6.28.8/ipc/shm.c 2009-02-07 16:10:45.000000000 -0500 |
31607 |
++++ linux-2.6.28.8/ipc/shm.c 2009-02-21 09:37:49.000000000 -0500 |
31608 |
+@@ -69,6 +69,14 @@ static void shm_destroy (struct ipc_name |
31609 |
+ static int sysvipc_shm_proc_show(struct seq_file *s, void *it); |
31610 |
+ #endif |
31611 |
+ |
31612 |
++#ifdef CONFIG_GRKERNSEC |
31613 |
++extern int gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid, |
31614 |
++ const time_t shm_createtime, const uid_t cuid, |
31615 |
++ const int shmid); |
31616 |
++extern int gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid, |
31617 |
++ const time_t shm_createtime); |
31618 |
++#endif |
31619 |
++ |
31620 |
+ void shm_init_ns(struct ipc_namespace *ns) |
31621 |
+ { |
31622 |
+ ns->shm_ctlmax = SHMMAX; |
31623 |
+@@ -87,6 +95,8 @@ static void do_shm_rmid(struct ipc_names |
31624 |
+ struct shmid_kernel *shp; |
31625 |
+ shp = container_of(ipcp, struct shmid_kernel, shm_perm); |
31626 |
+ |
31627 |
++ gr_log_shmrm(shp->shm_perm.uid, shp->shm_perm.cuid); |
31628 |
++ |
31629 |
+ if (shp->shm_nattch){ |
31630 |
+ shp->shm_perm.mode |= SHM_DEST; |
31631 |
+ /* Do not find it any more */ |
31632 |
+@@ -392,6 +402,14 @@ static int newseg(struct ipc_namespace * |
31633 |
+ shp->shm_lprid = 0; |
31634 |
+ shp->shm_atim = shp->shm_dtim = 0; |
31635 |
+ shp->shm_ctim = get_seconds(); |
31636 |
++#ifdef CONFIG_GRKERNSEC |
31637 |
++ { |
31638 |
++ struct timespec timeval; |
31639 |
++ do_posix_clock_monotonic_gettime(&timeval); |
31640 |
++ |
31641 |
++ shp->shm_createtime = timeval.tv_sec; |
31642 |
++ } |
31643 |
++#endif |
31644 |
+ shp->shm_segsz = size; |
31645 |
+ shp->shm_nattch = 0; |
31646 |
+ shp->shm_file = file; |
31647 |
+@@ -445,6 +463,7 @@ SYSCALL_DEFINE3(shmget, key_t, key, size |
31648 |
+ struct ipc_namespace *ns; |
31649 |
+ struct ipc_ops shm_ops; |
31650 |
+ struct ipc_params shm_params; |
31651 |
++ long err; |
31652 |
+ |
31653 |
+ ns = current->nsproxy->ipc_ns; |
31654 |
+ |
31655 |
+@@ -456,7 +475,11 @@ SYSCALL_DEFINE3(shmget, key_t, key, size |
31656 |
+ shm_params.flg = shmflg; |
31657 |
+ shm_params.u.size = size; |
31658 |
+ |
31659 |
+- return ipcget(ns, &shm_ids(ns), &shm_ops, &shm_params); |
31660 |
++ err = ipcget(ns, &shm_ids(ns), &shm_ops, &shm_params); |
31661 |
++ |
31662 |
++ gr_log_shmget(err, shmflg, size); |
31663 |
++ |
31664 |
++ return err; |
31665 |
+ } |
31666 |
+ |
31667 |
+ static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ds *in, int version) |
31668 |
+@@ -877,9 +900,21 @@ long do_shmat(int shmid, char __user *sh |
31669 |
+ if (err) |
31670 |
+ goto out_unlock; |
31671 |
+ |
31672 |
++#ifdef CONFIG_GRKERNSEC |
31673 |
++ if (!gr_handle_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime, |
31674 |
++ shp->shm_perm.cuid, shmid) || |
31675 |
++ !gr_chroot_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime)) { |
31676 |
++ err = -EACCES; |
31677 |
++ goto out_unlock; |
31678 |
++ } |
31679 |
++#endif |
31680 |
++ |
31681 |
+ path.dentry = dget(shp->shm_file->f_path.dentry); |
31682 |
+ path.mnt = shp->shm_file->f_path.mnt; |
31683 |
+ shp->shm_nattch++; |
31684 |
++#ifdef CONFIG_GRKERNSEC |
31685 |
++ shp->shm_lapid = current->pid; |
31686 |
++#endif |
31687 |
+ size = i_size_read(path.dentry->d_inode); |
31688 |
+ shm_unlock(shp); |
31689 |
+ |
31690 |
+diff -urNp linux-2.6.28.8/kernel/acct.c linux-2.6.28.8/kernel/acct.c |
31691 |
+--- linux-2.6.28.8/kernel/acct.c 2009-02-06 16:47:45.000000000 -0500 |
31692 |
++++ linux-2.6.28.8/kernel/acct.c 2009-02-21 09:37:49.000000000 -0500 |
31693 |
+@@ -573,7 +573,7 @@ static void do_acct_process(struct bsd_a |
31694 |
+ */ |
31695 |
+ flim = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; |
31696 |
+ current->signal->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; |
31697 |
+- file->f_op->write(file, (char *)&ac, |
31698 |
++ file->f_op->write(file, (char __user *)&ac, |
31699 |
+ sizeof(acct_t), &file->f_pos); |
31700 |
+ current->signal->rlim[RLIMIT_FSIZE].rlim_cur = flim; |
31701 |
+ set_fs(fs); |
31702 |
+diff -urNp linux-2.6.28.8/kernel/capability.c linux-2.6.28.8/kernel/capability.c |
31703 |
+--- linux-2.6.28.8/kernel/capability.c 2009-02-06 16:47:45.000000000 -0500 |
31704 |
++++ linux-2.6.28.8/kernel/capability.c 2009-02-21 09:37:49.000000000 -0500 |
31705 |
+@@ -498,10 +498,21 @@ SYSCALL_DEFINE2(capset, cap_user_header_ |
31706 |
+ */ |
31707 |
+ int capable(int cap) |
31708 |
+ { |
31709 |
+- if (has_capability(current, cap)) { |
31710 |
++ if (has_capability(current, cap) && gr_task_is_capable(current, cap)) { |
31711 |
+ current->flags |= PF_SUPERPRIV; |
31712 |
+ return 1; |
31713 |
+ } |
31714 |
+ return 0; |
31715 |
+ } |
31716 |
++ |
31717 |
++int capable_nolog(int cap) |
31718 |
++{ |
31719 |
++ if (has_capability(current, cap) && gr_is_capable_nolog(cap)) { |
31720 |
++ current->flags |= PF_SUPERPRIV; |
31721 |
++ return 1; |
31722 |
++ } |
31723 |
++ return 0; |
31724 |
++} |
31725 |
++ |
31726 |
+ EXPORT_SYMBOL(capable); |
31727 |
++EXPORT_SYMBOL(capable_nolog); |
31728 |
+diff -urNp linux-2.6.28.8/kernel/configs.c linux-2.6.28.8/kernel/configs.c |
31729 |
+--- linux-2.6.28.8/kernel/configs.c 2009-02-06 16:47:45.000000000 -0500 |
31730 |
++++ linux-2.6.28.8/kernel/configs.c 2009-02-21 09:37:49.000000000 -0500 |
31731 |
+@@ -73,8 +73,19 @@ static int __init ikconfig_init(void) |
31732 |
+ struct proc_dir_entry *entry; |
31733 |
+ |
31734 |
+ /* create the current config file */ |
31735 |
++#ifdef CONFIG_GRKERNSEC_PROC_ADD |
31736 |
++#ifdef CONFIG_GRKERNSEC_PROC_USER |
31737 |
++ entry = proc_create("config.gz", S_IFREG | S_IRUSR, NULL, |
31738 |
++ &ikconfig_file_ops); |
31739 |
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
31740 |
++ entry = proc_create("config.gz", S_IFREG | S_IRUSR | S_IRGRP, NULL, |
31741 |
++ &ikconfig_file_ops); |
31742 |
++#endif |
31743 |
++#else |
31744 |
+ entry = proc_create("config.gz", S_IFREG | S_IRUGO, NULL, |
31745 |
+ &ikconfig_file_ops); |
31746 |
++#endif |
31747 |
++ |
31748 |
+ if (!entry) |
31749 |
+ return -ENOMEM; |
31750 |
+ |
31751 |
+diff -urNp linux-2.6.28.8/kernel/cpu.c linux-2.6.28.8/kernel/cpu.c |
31752 |
+--- linux-2.6.28.8/kernel/cpu.c 2009-02-06 16:47:45.000000000 -0500 |
31753 |
++++ linux-2.6.28.8/kernel/cpu.c 2009-02-21 09:37:49.000000000 -0500 |
31754 |
+@@ -40,7 +40,7 @@ EXPORT_SYMBOL(cpu_possible_map); |
31755 |
+ /* Serializes the updates to cpu_online_map, cpu_present_map */ |
31756 |
+ static DEFINE_MUTEX(cpu_add_remove_lock); |
31757 |
+ |
31758 |
+-static __cpuinitdata RAW_NOTIFIER_HEAD(cpu_chain); |
31759 |
++static RAW_NOTIFIER_HEAD(cpu_chain); |
31760 |
+ |
31761 |
+ /* If set, cpu_up and cpu_down will return -EBUSY and do nothing. |
31762 |
+ * Should always be manipulated under cpu_add_remove_lock |
31763 |
+diff -urNp linux-2.6.28.8/kernel/exit.c linux-2.6.28.8/kernel/exit.c |
31764 |
+--- linux-2.6.28.8/kernel/exit.c 2009-02-06 16:47:45.000000000 -0500 |
31765 |
++++ linux-2.6.28.8/kernel/exit.c 2009-03-07 04:29:14.000000000 -0500 |
31766 |
+@@ -53,6 +53,10 @@ |
31767 |
+ #include <asm/pgtable.h> |
31768 |
+ #include <asm/mmu_context.h> |
31769 |
+ |
31770 |
++#ifdef CONFIG_GRKERNSEC |
31771 |
++extern rwlock_t grsec_exec_file_lock; |
31772 |
++#endif |
31773 |
++ |
31774 |
+ static void exit_mm(struct task_struct * tsk); |
31775 |
+ |
31776 |
+ static inline int task_detached(struct task_struct *p) |
31777 |
+@@ -163,6 +167,8 @@ void release_task(struct task_struct * p |
31778 |
+ struct task_struct *leader; |
31779 |
+ int zap_leader; |
31780 |
+ repeat: |
31781 |
++ gr_del_task_from_ip_table(p); |
31782 |
++ |
31783 |
+ tracehook_prepare_release_task(p); |
31784 |
+ atomic_dec(&p->user->processes); |
31785 |
+ proc_flush_task(p); |
31786 |
+@@ -326,11 +332,22 @@ static void reparent_to_kthreadd(void) |
31787 |
+ { |
31788 |
+ write_lock_irq(&tasklist_lock); |
31789 |
+ |
31790 |
++#ifdef CONFIG_GRKERNSEC |
31791 |
++ write_lock(&grsec_exec_file_lock); |
31792 |
++ if (current->exec_file) { |
31793 |
++ fput(current->exec_file); |
31794 |
++ current->exec_file = NULL; |
31795 |
++ } |
31796 |
++ write_unlock(&grsec_exec_file_lock); |
31797 |
++#endif |
31798 |
++ |
31799 |
+ ptrace_unlink(current); |
31800 |
+ /* Reparent to init */ |
31801 |
+ current->real_parent = current->parent = kthreadd_task; |
31802 |
+ list_move_tail(¤t->sibling, ¤t->real_parent->children); |
31803 |
+ |
31804 |
++ gr_set_kernel_label(current); |
31805 |
++ |
31806 |
+ /* Set the exit signal to SIGCHLD so we signal init on exit */ |
31807 |
+ current->exit_signal = SIGCHLD; |
31808 |
+ |
31809 |
+@@ -424,6 +441,17 @@ void daemonize(const char *name, ...) |
31810 |
+ vsnprintf(current->comm, sizeof(current->comm), name, args); |
31811 |
+ va_end(args); |
31812 |
+ |
31813 |
++#ifdef CONFIG_GRKERNSEC |
31814 |
++ write_lock(&grsec_exec_file_lock); |
31815 |
++ if (current->exec_file) { |
31816 |
++ fput(current->exec_file); |
31817 |
++ current->exec_file = NULL; |
31818 |
++ } |
31819 |
++ write_unlock(&grsec_exec_file_lock); |
31820 |
++#endif |
31821 |
++ |
31822 |
++ gr_set_kernel_label(current); |
31823 |
++ |
31824 |
+ /* |
31825 |
+ * If we were started as result of loading a module, close all of the |
31826 |
+ * user space pages. We don't need them, and if we didn't close them |
31827 |
+@@ -1066,6 +1094,9 @@ NORET_TYPE void do_exit(long code) |
31828 |
+ tsk->exit_code = code; |
31829 |
+ taskstats_exit(tsk, group_dead); |
31830 |
+ |
31831 |
++ gr_acl_handle_psacct(tsk, code); |
31832 |
++ gr_acl_handle_exit(); |
31833 |
++ |
31834 |
+ exit_mm(tsk); |
31835 |
+ |
31836 |
+ if (group_dead) |
31837 |
+@@ -1272,7 +1303,7 @@ static int wait_task_zombie(struct task_ |
31838 |
+ if (unlikely(options & WNOWAIT)) { |
31839 |
+ uid_t uid = p->uid; |
31840 |
+ int exit_code = p->exit_code; |
31841 |
+- int why, status; |
31842 |
++ int why; |
31843 |
+ |
31844 |
+ get_task_struct(p); |
31845 |
+ read_unlock(&tasklist_lock); |
31846 |
+diff -urNp linux-2.6.28.8/kernel/fork.c linux-2.6.28.8/kernel/fork.c |
31847 |
+--- linux-2.6.28.8/kernel/fork.c 2009-03-07 10:24:49.000000000 -0500 |
31848 |
++++ linux-2.6.28.8/kernel/fork.c 2009-03-07 10:29:51.000000000 -0500 |
31849 |
+@@ -236,7 +236,7 @@ static struct task_struct *dup_task_stru |
31850 |
+ setup_thread_stack(tsk, orig); |
31851 |
+ |
31852 |
+ #ifdef CONFIG_CC_STACKPROTECTOR |
31853 |
+- tsk->stack_canary = get_random_int(); |
31854 |
++ tsk->stack_canary = pax_get_random_long(); |
31855 |
+ #endif |
31856 |
+ |
31857 |
+ /* One for us, one for whoever does the "release_task()" (usually parent) */ |
31858 |
+@@ -273,8 +273,8 @@ static int dup_mmap(struct mm_struct *mm |
31859 |
+ mm->locked_vm = 0; |
31860 |
+ mm->mmap = NULL; |
31861 |
+ mm->mmap_cache = NULL; |
31862 |
+- mm->free_area_cache = oldmm->mmap_base; |
31863 |
+- mm->cached_hole_size = ~0UL; |
31864 |
++ mm->free_area_cache = oldmm->free_area_cache; |
31865 |
++ mm->cached_hole_size = oldmm->cached_hole_size; |
31866 |
+ mm->map_count = 0; |
31867 |
+ cpus_clear(mm->cpu_vm_mask); |
31868 |
+ mm->mm_rb = RB_ROOT; |
31869 |
+@@ -311,6 +311,7 @@ static int dup_mmap(struct mm_struct *mm |
31870 |
+ tmp->vm_flags &= ~VM_LOCKED; |
31871 |
+ tmp->vm_mm = mm; |
31872 |
+ tmp->vm_next = NULL; |
31873 |
++ tmp->vm_mirror = NULL; |
31874 |
+ anon_vma_link(tmp); |
31875 |
+ file = tmp->vm_file; |
31876 |
+ if (file) { |
31877 |
+@@ -358,6 +359,31 @@ static int dup_mmap(struct mm_struct *mm |
31878 |
+ if (retval) |
31879 |
+ goto out; |
31880 |
+ } |
31881 |
++ |
31882 |
++#ifdef CONFIG_PAX_SEGMEXEC |
31883 |
++ if (oldmm->pax_flags & MF_PAX_SEGMEXEC) { |
31884 |
++ struct vm_area_struct *mpnt_m; |
31885 |
++ |
31886 |
++ for (mpnt = oldmm->mmap, mpnt_m = mm->mmap; mpnt; mpnt = mpnt->vm_next, mpnt_m = mpnt_m->vm_next) { |
31887 |
++ BUG_ON(!mpnt_m || mpnt_m->vm_mirror || mpnt->vm_mm != oldmm || mpnt_m->vm_mm != mm); |
31888 |
++ |
31889 |
++ if (!mpnt->vm_mirror) |
31890 |
++ continue; |
31891 |
++ |
31892 |
++ if (mpnt->vm_end <= SEGMEXEC_TASK_SIZE) { |
31893 |
++ BUG_ON(mpnt->vm_mirror->vm_mirror != mpnt); |
31894 |
++ mpnt->vm_mirror = mpnt_m; |
31895 |
++ } else { |
31896 |
++ BUG_ON(mpnt->vm_mirror->vm_mirror == mpnt || mpnt->vm_mirror->vm_mirror->vm_mm != mm); |
31897 |
++ mpnt_m->vm_mirror = mpnt->vm_mirror->vm_mirror; |
31898 |
++ mpnt_m->vm_mirror->vm_mirror = mpnt_m; |
31899 |
++ mpnt->vm_mirror->vm_mirror = mpnt; |
31900 |
++ } |
31901 |
++ } |
31902 |
++ BUG_ON(mpnt_m); |
31903 |
++ } |
31904 |
++#endif |
31905 |
++ |
31906 |
+ /* a new mm has just been created */ |
31907 |
+ arch_dup_mmap(oldmm, mm); |
31908 |
+ retval = 0; |
31909 |
+@@ -527,9 +553,11 @@ void mm_release(struct task_struct *tsk, |
31910 |
+ #ifdef CONFIG_FUTEX |
31911 |
+ if (unlikely(tsk->robust_list)) |
31912 |
+ exit_robust_list(tsk); |
31913 |
++ tsk->robust_list = NULL; |
31914 |
+ #ifdef CONFIG_COMPAT |
31915 |
+ if (unlikely(tsk->compat_robust_list)) |
31916 |
+ compat_exit_robust_list(tsk); |
31917 |
++ tsk->compat_robust_list = NULL; |
31918 |
+ #endif |
31919 |
+ #endif |
31920 |
+ |
31921 |
+@@ -551,7 +579,7 @@ void mm_release(struct task_struct *tsk, |
31922 |
+ if (tsk->clear_child_tid |
31923 |
+ && !(tsk->flags & PF_SIGNALED) |
31924 |
+ && atomic_read(&mm->mm_users) > 1) { |
31925 |
+- u32 __user * tidptr = tsk->clear_child_tid; |
31926 |
++ pid_t __user * tidptr = tsk->clear_child_tid; |
31927 |
+ tsk->clear_child_tid = NULL; |
31928 |
+ |
31929 |
+ /* |
31930 |
+@@ -559,7 +587,7 @@ void mm_release(struct task_struct *tsk, |
31931 |
+ * not set up a proper pointer then tough luck. |
31932 |
+ */ |
31933 |
+ put_user(0, tidptr); |
31934 |
+- sys_futex(tidptr, FUTEX_WAKE, 1, NULL, NULL, 0); |
31935 |
++ sys_futex((u32 __user *)tidptr, FUTEX_WAKE, 1, NULL, NULL, 0); |
31936 |
+ } |
31937 |
+ } |
31938 |
+ |
31939 |
+@@ -984,6 +1012,9 @@ static struct task_struct *copy_process( |
31940 |
+ DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled); |
31941 |
+ #endif |
31942 |
+ retval = -EAGAIN; |
31943 |
++ |
31944 |
++ gr_learn_resource(p, RLIMIT_NPROC, atomic_read(&p->user->processes), 0); |
31945 |
++ |
31946 |
+ if (atomic_read(&p->user->processes) >= |
31947 |
+ p->signal->rlim[RLIMIT_NPROC].rlim_cur) { |
31948 |
+ if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && |
31949 |
+@@ -1147,6 +1178,8 @@ static struct task_struct *copy_process( |
31950 |
+ goto bad_fork_free_pid; |
31951 |
+ } |
31952 |
+ |
31953 |
++ gr_copy_label(p); |
31954 |
++ |
31955 |
+ p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; |
31956 |
+ /* |
31957 |
+ * Clear TID on mm_release()? |
31958 |
+@@ -1317,6 +1350,8 @@ bad_fork_cleanup_count: |
31959 |
+ bad_fork_free: |
31960 |
+ free_task(p); |
31961 |
+ fork_out: |
31962 |
++ gr_log_forkfail(retval); |
31963 |
++ |
31964 |
+ return ERR_PTR(retval); |
31965 |
+ } |
31966 |
+ |
31967 |
+@@ -1395,6 +1430,8 @@ long do_fork(unsigned long clone_flags, |
31968 |
+ if (clone_flags & CLONE_PARENT_SETTID) |
31969 |
+ put_user(nr, parent_tidptr); |
31970 |
+ |
31971 |
++ gr_handle_brute_check(); |
31972 |
++ |
31973 |
+ if (clone_flags & CLONE_VFORK) { |
31974 |
+ p->vfork_done = &vfork; |
31975 |
+ init_completion(&vfork); |
31976 |
+diff -urNp linux-2.6.28.8/kernel/futex.c linux-2.6.28.8/kernel/futex.c |
31977 |
+--- linux-2.6.28.8/kernel/futex.c 2009-02-06 16:47:45.000000000 -0500 |
31978 |
++++ linux-2.6.28.8/kernel/futex.c 2009-02-21 09:37:49.000000000 -0500 |
31979 |
+@@ -188,6 +188,11 @@ static int get_futex_key(u32 __user *uad |
31980 |
+ struct page *page; |
31981 |
+ int err; |
31982 |
+ |
31983 |
++#ifdef CONFIG_PAX_SEGMEXEC |
31984 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && address >= SEGMEXEC_TASK_SIZE) |
31985 |
++ return -EFAULT; |
31986 |
++#endif |
31987 |
++ |
31988 |
+ /* |
31989 |
+ * The futex address must be "naturally" aligned. |
31990 |
+ */ |
31991 |
+@@ -214,8 +219,8 @@ static int get_futex_key(u32 __user *uad |
31992 |
+ * The futex is hashed differently depending on whether |
31993 |
+ * it's in a shared or private mapping. So check vma first. |
31994 |
+ */ |
31995 |
+- vma = find_extend_vma(mm, address); |
31996 |
+- if (unlikely(!vma)) |
31997 |
++ vma = find_vma(mm, address); |
31998 |
++ if (unlikely(!vma || address < vma->vm_start)) |
31999 |
+ return -EFAULT; |
32000 |
+ |
32001 |
+ /* |
32002 |
+@@ -1348,7 +1353,7 @@ static int futex_wait(u32 __user *uaddr, |
32003 |
+ struct restart_block *restart; |
32004 |
+ restart = ¤t_thread_info()->restart_block; |
32005 |
+ restart->fn = futex_wait_restart; |
32006 |
+- restart->futex.uaddr = (u32 *)uaddr; |
32007 |
++ restart->futex.uaddr = uaddr; |
32008 |
+ restart->futex.val = val; |
32009 |
+ restart->futex.time = abs_time->tv64; |
32010 |
+ restart->futex.bitset = bitset; |
32011 |
+@@ -1908,7 +1913,7 @@ retry: |
32012 |
+ */ |
32013 |
+ static inline int fetch_robust_entry(struct robust_list __user **entry, |
32014 |
+ struct robust_list __user * __user *head, |
32015 |
+- int *pi) |
32016 |
++ unsigned int *pi) |
32017 |
+ { |
32018 |
+ unsigned long uentry; |
32019 |
+ |
32020 |
+diff -urNp linux-2.6.28.8/kernel/irq/handle.c linux-2.6.28.8/kernel/irq/handle.c |
32021 |
+--- linux-2.6.28.8/kernel/irq/handle.c 2009-02-06 16:47:45.000000000 -0500 |
32022 |
++++ linux-2.6.28.8/kernel/irq/handle.c 2009-02-21 09:37:49.000000000 -0500 |
32023 |
+@@ -57,7 +57,8 @@ struct irq_desc irq_desc[NR_IRQS] __cach |
32024 |
+ .depth = 1, |
32025 |
+ .lock = __SPIN_LOCK_UNLOCKED(irq_desc->lock), |
32026 |
+ #ifdef CONFIG_SMP |
32027 |
+- .affinity = CPU_MASK_ALL |
32028 |
++ .affinity = CPU_MASK_ALL, |
32029 |
++ .cpu = 0, |
32030 |
+ #endif |
32031 |
+ } |
32032 |
+ }; |
32033 |
+diff -urNp linux-2.6.28.8/kernel/kallsyms.c linux-2.6.28.8/kernel/kallsyms.c |
32034 |
+--- linux-2.6.28.8/kernel/kallsyms.c 2009-02-06 16:47:45.000000000 -0500 |
32035 |
++++ linux-2.6.28.8/kernel/kallsyms.c 2009-02-21 09:37:49.000000000 -0500 |
32036 |
+@@ -62,6 +62,18 @@ static inline int is_kernel_text(unsigne |
32037 |
+ |
32038 |
+ static inline int is_kernel(unsigned long addr) |
32039 |
+ { |
32040 |
++ |
32041 |
++#if defined(CONFIG_PAX_KERNEXEC) && defined(CONFIG_MODULES) |
32042 |
++ if ((unsigned long)MODULES_VADDR <= ktla_ktva(addr) && |
32043 |
++ ktla_ktva(addr) < (unsigned long)MODULES_END) |
32044 |
++ return 0; |
32045 |
++#endif |
32046 |
++ |
32047 |
++#ifdef CONFIG_X86_32 |
32048 |
++ if (is_kernel_inittext(addr)) |
32049 |
++ return 1; |
32050 |
++#endif |
32051 |
++ |
32052 |
+ if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end) |
32053 |
+ return 1; |
32054 |
+ return in_gate_area_no_task(addr); |
32055 |
+@@ -372,7 +384,6 @@ static unsigned long get_ksymbol_core(st |
32056 |
+ |
32057 |
+ static void reset_iter(struct kallsym_iter *iter, loff_t new_pos) |
32058 |
+ { |
32059 |
+- iter->name[0] = '\0'; |
32060 |
+ iter->nameoff = get_symbol_offset(new_pos); |
32061 |
+ iter->pos = new_pos; |
32062 |
+ } |
32063 |
+@@ -456,7 +467,7 @@ static int kallsyms_open(struct inode *i |
32064 |
+ struct kallsym_iter *iter; |
32065 |
+ int ret; |
32066 |
+ |
32067 |
+- iter = kmalloc(sizeof(*iter), GFP_KERNEL); |
32068 |
++ iter = kzalloc(sizeof(*iter), GFP_KERNEL); |
32069 |
+ if (!iter) |
32070 |
+ return -ENOMEM; |
32071 |
+ reset_iter(iter, 0); |
32072 |
+@@ -478,7 +489,15 @@ static const struct file_operations kall |
32073 |
+ |
32074 |
+ static int __init kallsyms_init(void) |
32075 |
+ { |
32076 |
++#ifdef CONFIG_GRKERNSEC_PROC_ADD |
32077 |
++#ifdef CONFIG_GRKERNSEC_PROC_USER |
32078 |
++ proc_create("kallsyms", S_IFREG | S_IRUSR, NULL, &kallsyms_operations); |
32079 |
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
32080 |
++ proc_create("kallsyms", S_IFREG | S_IRUSR | S_IRGRP, NULL, &kallsyms_operations); |
32081 |
++#endif |
32082 |
++#else |
32083 |
+ proc_create("kallsyms", 0444, NULL, &kallsyms_operations); |
32084 |
++#endif |
32085 |
+ return 0; |
32086 |
+ } |
32087 |
+ __initcall(kallsyms_init); |
32088 |
+diff -urNp linux-2.6.28.8/kernel/kmod.c linux-2.6.28.8/kernel/kmod.c |
32089 |
+--- linux-2.6.28.8/kernel/kmod.c 2009-02-06 16:47:45.000000000 -0500 |
32090 |
++++ linux-2.6.28.8/kernel/kmod.c 2009-02-21 09:37:49.000000000 -0500 |
32091 |
+@@ -108,7 +108,7 @@ int request_module(const char *fmt, ...) |
32092 |
+ return -ENOMEM; |
32093 |
+ } |
32094 |
+ |
32095 |
+- ret = call_usermodehelper(modprobe_path, argv, envp, 1); |
32096 |
++ ret = call_usermodehelper(modprobe_path, argv, envp, UMH_WAIT_PROC); |
32097 |
+ atomic_dec(&kmod_concurrent); |
32098 |
+ return ret; |
32099 |
+ } |
32100 |
+diff -urNp linux-2.6.28.8/kernel/kprobes.c linux-2.6.28.8/kernel/kprobes.c |
32101 |
+--- linux-2.6.28.8/kernel/kprobes.c 2009-02-06 16:47:45.000000000 -0500 |
32102 |
++++ linux-2.6.28.8/kernel/kprobes.c 2009-02-21 09:37:49.000000000 -0500 |
32103 |
+@@ -182,7 +182,7 @@ kprobe_opcode_t __kprobes *get_insn_slot |
32104 |
+ * kernel image and loaded module images reside. This is required |
32105 |
+ * so x86_64 can correctly handle the %rip-relative fixups. |
32106 |
+ */ |
32107 |
+- kip->insns = module_alloc(PAGE_SIZE); |
32108 |
++ kip->insns = module_alloc_exec(PAGE_SIZE); |
32109 |
+ if (!kip->insns) { |
32110 |
+ kfree(kip); |
32111 |
+ return NULL; |
32112 |
+@@ -214,7 +214,7 @@ static int __kprobes collect_one_slot(st |
32113 |
+ hlist_add_head(&kip->hlist, |
32114 |
+ &kprobe_insn_pages); |
32115 |
+ } else { |
32116 |
+- module_free(NULL, kip->insns); |
32117 |
++ module_free_exec(NULL, kip->insns); |
32118 |
+ kfree(kip); |
32119 |
+ } |
32120 |
+ return 1; |
32121 |
+diff -urNp linux-2.6.28.8/kernel/lockdep.c linux-2.6.28.8/kernel/lockdep.c |
32122 |
+--- linux-2.6.28.8/kernel/lockdep.c 2009-02-06 16:47:45.000000000 -0500 |
32123 |
++++ linux-2.6.28.8/kernel/lockdep.c 2009-02-21 09:37:49.000000000 -0500 |
32124 |
+@@ -627,6 +627,10 @@ static int static_obj(void *obj) |
32125 |
+ int i; |
32126 |
+ #endif |
32127 |
+ |
32128 |
++#ifdef CONFIG_PAX_KERNEXEC |
32129 |
++ start = (unsigned long )&_data; |
32130 |
++#endif |
32131 |
++ |
32132 |
+ /* |
32133 |
+ * static variable? |
32134 |
+ */ |
32135 |
+@@ -638,9 +642,12 @@ static int static_obj(void *obj) |
32136 |
+ * percpu var? |
32137 |
+ */ |
32138 |
+ for_each_possible_cpu(i) { |
32139 |
++#ifdef CONFIG_X86_32 |
32140 |
++ start = per_cpu_offset(i); |
32141 |
++#else |
32142 |
+ start = (unsigned long) &__per_cpu_start + per_cpu_offset(i); |
32143 |
+- end = (unsigned long) &__per_cpu_start + PERCPU_ENOUGH_ROOM |
32144 |
+- + per_cpu_offset(i); |
32145 |
++#endif |
32146 |
++ end = start + PERCPU_ENOUGH_ROOM; |
32147 |
+ |
32148 |
+ if ((addr >= start) && (addr < end)) |
32149 |
+ return 1; |
32150 |
+diff -urNp linux-2.6.28.8/kernel/module.c linux-2.6.28.8/kernel/module.c |
32151 |
+--- linux-2.6.28.8/kernel/module.c 2009-02-06 16:47:45.000000000 -0500 |
32152 |
++++ linux-2.6.28.8/kernel/module.c 2009-02-21 09:37:50.000000000 -0500 |
32153 |
+@@ -47,6 +47,11 @@ |
32154 |
+ #include <linux/rculist.h> |
32155 |
+ #include <asm/uaccess.h> |
32156 |
+ #include <asm/cacheflush.h> |
32157 |
++ |
32158 |
++#ifdef CONFIG_PAX_KERNEXEC |
32159 |
++#include <asm/desc.h> |
32160 |
++#endif |
32161 |
++ |
32162 |
+ #include <linux/license.h> |
32163 |
+ #include <asm/sections.h> |
32164 |
+ #include <linux/tracepoint.h> |
32165 |
+@@ -76,7 +81,10 @@ static DECLARE_WAIT_QUEUE_HEAD(module_wq |
32166 |
+ static BLOCKING_NOTIFIER_HEAD(module_notify_list); |
32167 |
+ |
32168 |
+ /* Bounds of module allocation, for speeding __module_text_address */ |
32169 |
+-static unsigned long module_addr_min = -1UL, module_addr_max = 0; |
32170 |
++static unsigned long module_addr_min_rw = -1UL, module_addr_max_rw = 0; |
32171 |
++static unsigned long module_addr_min_rx = -1UL, module_addr_max_rx = 0; |
32172 |
++ |
32173 |
++extern int gr_check_modstop(void); |
32174 |
+ |
32175 |
+ int register_module_notifier(struct notifier_block * nb) |
32176 |
+ { |
32177 |
+@@ -245,7 +253,7 @@ static bool each_symbol(bool (*fn)(const |
32178 |
+ return true; |
32179 |
+ |
32180 |
+ list_for_each_entry_rcu(mod, &modules, list) { |
32181 |
+- struct symsearch arr[] = { |
32182 |
++ struct symsearch modarr[] = { |
32183 |
+ { mod->syms, mod->syms + mod->num_syms, mod->crcs, |
32184 |
+ NOT_GPL_ONLY, false }, |
32185 |
+ { mod->gpl_syms, mod->gpl_syms + mod->num_gpl_syms, |
32186 |
+@@ -267,7 +275,7 @@ static bool each_symbol(bool (*fn)(const |
32187 |
+ #endif |
32188 |
+ }; |
32189 |
+ |
32190 |
+- if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data)) |
32191 |
++ if (each_symbol_in_section(modarr, ARRAY_SIZE(modarr), mod, fn, data)) |
32192 |
+ return true; |
32193 |
+ } |
32194 |
+ return false; |
32195 |
+@@ -403,6 +411,8 @@ static inline unsigned int block_size(in |
32196 |
+ return val; |
32197 |
+ } |
32198 |
+ |
32199 |
++EXPORT_SYMBOL(__per_cpu_start); |
32200 |
++ |
32201 |
+ static void *percpu_modalloc(unsigned long size, unsigned long align, |
32202 |
+ const char *name) |
32203 |
+ { |
32204 |
+@@ -410,7 +420,7 @@ static void *percpu_modalloc(unsigned lo |
32205 |
+ unsigned int i; |
32206 |
+ void *ptr; |
32207 |
+ |
32208 |
+- if (align > PAGE_SIZE) { |
32209 |
++ if (align-1 >= PAGE_SIZE) { |
32210 |
+ printk(KERN_WARNING "%s: per-cpu alignment %li > %li\n", |
32211 |
+ name, align, PAGE_SIZE); |
32212 |
+ align = PAGE_SIZE; |
32213 |
+@@ -492,7 +502,11 @@ static void percpu_modcopy(void *pcpudes |
32214 |
+ int cpu; |
32215 |
+ |
32216 |
+ for_each_possible_cpu(cpu) |
32217 |
++#ifdef CONFIG_X86_32 |
32218 |
++ memcpy(pcpudest + __per_cpu_offset[cpu], from, size); |
32219 |
++#else |
32220 |
+ memcpy(pcpudest + per_cpu_offset(cpu), from, size); |
32221 |
++#endif |
32222 |
+ } |
32223 |
+ |
32224 |
+ static int percpu_modinit(void) |
32225 |
+@@ -750,6 +764,9 @@ SYSCALL_DEFINE2(delete_module, const cha |
32226 |
+ char name[MODULE_NAME_LEN]; |
32227 |
+ int ret, forced = 0; |
32228 |
+ |
32229 |
++ if (gr_check_modstop()) |
32230 |
++ return -EPERM; |
32231 |
++ |
32232 |
+ if (!capable(CAP_SYS_MODULE)) |
32233 |
+ return -EPERM; |
32234 |
+ |
32235 |
+@@ -1448,19 +1465,22 @@ static void free_module(struct module *m |
32236 |
+ module_unload_free(mod); |
32237 |
+ |
32238 |
+ /* release any pointers to mcount in this module */ |
32239 |
+- ftrace_release(mod->module_core, mod->core_size); |
32240 |
++ ftrace_release(mod->module_core_rx, mod->core_size_rx); |
32241 |
+ |
32242 |
+ /* This may be NULL, but that's OK */ |
32243 |
+- module_free(mod, mod->module_init); |
32244 |
++ module_free(mod, mod->module_init_rw); |
32245 |
++ module_free_exec(mod, mod->module_init_rx); |
32246 |
+ kfree(mod->args); |
32247 |
+ if (mod->percpu) |
32248 |
+ percpu_modfree(mod->percpu); |
32249 |
+ |
32250 |
+ /* Free lock-classes: */ |
32251 |
+- lockdep_free_key_range(mod->module_core, mod->core_size); |
32252 |
++ lockdep_free_key_range(mod->module_core_rx, mod->core_size_rx); |
32253 |
++ lockdep_free_key_range(mod->module_core_rw, mod->core_size_rw); |
32254 |
+ |
32255 |
+ /* Finally, free the core (containing the module structure) */ |
32256 |
+- module_free(mod, mod->module_core); |
32257 |
++ module_free_exec(mod, mod->module_core_rx); |
32258 |
++ module_free(mod, mod->module_core_rw); |
32259 |
+ } |
32260 |
+ |
32261 |
+ void *__symbol_get(const char *symbol) |
32262 |
+@@ -1526,10 +1546,14 @@ static int simplify_symbols(Elf_Shdr *se |
32263 |
+ struct module *mod) |
32264 |
+ { |
32265 |
+ Elf_Sym *sym = (void *)sechdrs[symindex].sh_addr; |
32266 |
+- unsigned long secbase; |
32267 |
++ unsigned long secbase, symbol; |
32268 |
+ unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym); |
32269 |
+ int ret = 0; |
32270 |
+ |
32271 |
++#ifdef CONFIG_PAX_KERNEXEC |
32272 |
++ unsigned long cr0; |
32273 |
++#endif |
32274 |
++ |
32275 |
+ for (i = 1; i < n; i++) { |
32276 |
+ switch (sym[i].st_shndx) { |
32277 |
+ case SHN_COMMON: |
32278 |
+@@ -1548,10 +1572,19 @@ static int simplify_symbols(Elf_Shdr *se |
32279 |
+ break; |
32280 |
+ |
32281 |
+ case SHN_UNDEF: |
32282 |
+- sym[i].st_value |
32283 |
+- = resolve_symbol(sechdrs, versindex, |
32284 |
++ symbol = resolve_symbol(sechdrs, versindex, |
32285 |
+ strtab + sym[i].st_name, mod); |
32286 |
+ |
32287 |
++#ifdef CONFIG_PAX_KERNEXEC |
32288 |
++ pax_open_kernel(cr0); |
32289 |
++#endif |
32290 |
++ |
32291 |
++ sym[i].st_value = symbol; |
32292 |
++ |
32293 |
++#ifdef CONFIG_PAX_KERNEXEC |
32294 |
++ pax_close_kernel(cr0); |
32295 |
++#endif |
32296 |
++ |
32297 |
+ /* Ok if resolved. */ |
32298 |
+ if (!IS_ERR_VALUE(sym[i].st_value)) |
32299 |
+ break; |
32300 |
+@@ -1566,11 +1599,27 @@ static int simplify_symbols(Elf_Shdr *se |
32301 |
+ |
32302 |
+ default: |
32303 |
+ /* Divert to percpu allocation if a percpu var. */ |
32304 |
+- if (sym[i].st_shndx == pcpuindex) |
32305 |
++ if (sym[i].st_shndx == pcpuindex) { |
32306 |
++ |
32307 |
++#if defined(CONFIG_X86_32) && defined(CONFIG_SMP) |
32308 |
++ secbase = (unsigned long)mod->percpu - (unsigned long)__per_cpu_start; |
32309 |
++#else |
32310 |
+ secbase = (unsigned long)mod->percpu; |
32311 |
+- else |
32312 |
++#endif |
32313 |
++ |
32314 |
++ } else |
32315 |
+ secbase = sechdrs[sym[i].st_shndx].sh_addr; |
32316 |
++ |
32317 |
++#ifdef CONFIG_PAX_KERNEXEC |
32318 |
++ pax_open_kernel(cr0); |
32319 |
++#endif |
32320 |
++ |
32321 |
+ sym[i].st_value += secbase; |
32322 |
++ |
32323 |
++#ifdef CONFIG_PAX_KERNEXEC |
32324 |
++ pax_close_kernel(cr0); |
32325 |
++#endif |
32326 |
++ |
32327 |
+ break; |
32328 |
+ } |
32329 |
+ } |
32330 |
+@@ -1622,11 +1671,12 @@ static void layout_sections(struct modul |
32331 |
+ || strncmp(secstrings + s->sh_name, |
32332 |
+ ".init", 5) == 0) |
32333 |
+ continue; |
32334 |
+- s->sh_entsize = get_offset(&mod->core_size, s); |
32335 |
++ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC)) |
32336 |
++ s->sh_entsize = get_offset(&mod->core_size_rw, s); |
32337 |
++ else |
32338 |
++ s->sh_entsize = get_offset(&mod->core_size_rx, s); |
32339 |
+ DEBUGP("\t%s\n", secstrings + s->sh_name); |
32340 |
+ } |
32341 |
+- if (m == 0) |
32342 |
+- mod->core_text_size = mod->core_size; |
32343 |
+ } |
32344 |
+ |
32345 |
+ DEBUGP("Init section allocation order:\n"); |
32346 |
+@@ -1640,12 +1690,13 @@ static void layout_sections(struct modul |
32347 |
+ || strncmp(secstrings + s->sh_name, |
32348 |
+ ".init", 5) != 0) |
32349 |
+ continue; |
32350 |
+- s->sh_entsize = (get_offset(&mod->init_size, s) |
32351 |
+- | INIT_OFFSET_MASK); |
32352 |
++ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC)) |
32353 |
++ s->sh_entsize = get_offset(&mod->init_size_rw, s); |
32354 |
++ else |
32355 |
++ s->sh_entsize = get_offset(&mod->init_size_rx, s); |
32356 |
++ s->sh_entsize |= INIT_OFFSET_MASK; |
32357 |
+ DEBUGP("\t%s\n", secstrings + s->sh_name); |
32358 |
+ } |
32359 |
+- if (m == 0) |
32360 |
+- mod->init_text_size = mod->init_size; |
32361 |
+ } |
32362 |
+ } |
32363 |
+ |
32364 |
+@@ -1785,14 +1836,31 @@ static void add_kallsyms(struct module * |
32365 |
+ { |
32366 |
+ unsigned int i; |
32367 |
+ |
32368 |
++#ifdef CONFIG_PAX_KERNEXEC |
32369 |
++ unsigned long cr0; |
32370 |
++#endif |
32371 |
++ |
32372 |
+ mod->symtab = (void *)sechdrs[symindex].sh_addr; |
32373 |
+ mod->num_symtab = sechdrs[symindex].sh_size / sizeof(Elf_Sym); |
32374 |
+ mod->strtab = (void *)sechdrs[strindex].sh_addr; |
32375 |
+ |
32376 |
+ /* Set types up while we still have access to sections. */ |
32377 |
+- for (i = 0; i < mod->num_symtab; i++) |
32378 |
+- mod->symtab[i].st_info |
32379 |
+- = elf_type(&mod->symtab[i], sechdrs, secstrings, mod); |
32380 |
++ |
32381 |
++ for (i = 0; i < mod->num_symtab; i++) { |
32382 |
++ char type = elf_type(&mod->symtab[i], sechdrs, secstrings, mod); |
32383 |
++ |
32384 |
++#ifdef CONFIG_PAX_KERNEXEC |
32385 |
++ pax_open_kernel(cr0); |
32386 |
++#endif |
32387 |
++ |
32388 |
++ mod->symtab[i].st_info = type; |
32389 |
++ |
32390 |
++#ifdef CONFIG_PAX_KERNEXEC |
32391 |
++ pax_close_kernel(cr0); |
32392 |
++#endif |
32393 |
++ |
32394 |
++ } |
32395 |
++ |
32396 |
+ } |
32397 |
+ #else |
32398 |
+ static inline void add_kallsyms(struct module *mod, |
32399 |
+@@ -1819,16 +1887,30 @@ static void dynamic_printk_setup(struct |
32400 |
+ #endif /* CONFIG_DYNAMIC_PRINTK_DEBUG */ |
32401 |
+ } |
32402 |
+ |
32403 |
+-static void *module_alloc_update_bounds(unsigned long size) |
32404 |
++static void *module_alloc_update_bounds_rw(unsigned long size) |
32405 |
+ { |
32406 |
+ void *ret = module_alloc(size); |
32407 |
+ |
32408 |
+ if (ret) { |
32409 |
+ /* Update module bounds. */ |
32410 |
+- if ((unsigned long)ret < module_addr_min) |
32411 |
+- module_addr_min = (unsigned long)ret; |
32412 |
+- if ((unsigned long)ret + size > module_addr_max) |
32413 |
+- module_addr_max = (unsigned long)ret + size; |
32414 |
++ if ((unsigned long)ret < module_addr_min_rw) |
32415 |
++ module_addr_min_rw = (unsigned long)ret; |
32416 |
++ if ((unsigned long)ret + size > module_addr_max_rw) |
32417 |
++ module_addr_max_rw = (unsigned long)ret + size; |
32418 |
++ } |
32419 |
++ return ret; |
32420 |
++} |
32421 |
++ |
32422 |
++static void *module_alloc_update_bounds_rx(unsigned long size) |
32423 |
++{ |
32424 |
++ void *ret = module_alloc_exec(size); |
32425 |
++ |
32426 |
++ if (ret) { |
32427 |
++ /* Update module bounds. */ |
32428 |
++ if ((unsigned long)ret < module_addr_min_rx) |
32429 |
++ module_addr_min_rx = (unsigned long)ret; |
32430 |
++ if ((unsigned long)ret + size > module_addr_max_rx) |
32431 |
++ module_addr_max_rx = (unsigned long)ret + size; |
32432 |
+ } |
32433 |
+ return ret; |
32434 |
+ } |
32435 |
+@@ -1856,6 +1938,10 @@ static noinline struct module *load_modu |
32436 |
+ unsigned long *mseg; |
32437 |
+ mm_segment_t old_fs; |
32438 |
+ |
32439 |
++#ifdef CONFIG_PAX_KERNEXEC |
32440 |
++ unsigned long cr0; |
32441 |
++#endif |
32442 |
++ |
32443 |
+ DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n", |
32444 |
+ umod, len, uargs); |
32445 |
+ if (len < sizeof(*hdr)) |
32446 |
+@@ -2010,22 +2096,57 @@ static noinline struct module *load_modu |
32447 |
+ layout_sections(mod, hdr, sechdrs, secstrings); |
32448 |
+ |
32449 |
+ /* Do the allocs. */ |
32450 |
+- ptr = module_alloc_update_bounds(mod->core_size); |
32451 |
++ ptr = module_alloc_update_bounds_rw(mod->core_size_rw); |
32452 |
+ if (!ptr) { |
32453 |
+ err = -ENOMEM; |
32454 |
+ goto free_percpu; |
32455 |
+ } |
32456 |
+- memset(ptr, 0, mod->core_size); |
32457 |
+- mod->module_core = ptr; |
32458 |
++ memset(ptr, 0, mod->core_size_rw); |
32459 |
++ mod->module_core_rw = ptr; |
32460 |
+ |
32461 |
+- ptr = module_alloc_update_bounds(mod->init_size); |
32462 |
+- if (!ptr && mod->init_size) { |
32463 |
++ ptr = module_alloc_update_bounds_rw(mod->init_size_rw); |
32464 |
++ if (!ptr && mod->init_size_rw) { |
32465 |
+ err = -ENOMEM; |
32466 |
+- goto free_core; |
32467 |
++ goto free_core_rw; |
32468 |
+ } |
32469 |
+- memset(ptr, 0, mod->init_size); |
32470 |
+- mod->module_init = ptr; |
32471 |
++ memset(ptr, 0, mod->init_size_rw); |
32472 |
++ mod->module_init_rw = ptr; |
32473 |
++ |
32474 |
++ ptr = module_alloc_update_bounds_rx(mod->core_size_rx); |
32475 |
++ if (!ptr) { |
32476 |
++ err = -ENOMEM; |
32477 |
++ goto free_init_rw; |
32478 |
++ } |
32479 |
++ |
32480 |
++#ifdef CONFIG_PAX_KERNEXEC |
32481 |
++ pax_open_kernel(cr0); |
32482 |
++#endif |
32483 |
+ |
32484 |
++ memset(ptr, 0, mod->core_size_rx); |
32485 |
++ |
32486 |
++#ifdef CONFIG_PAX_KERNEXEC |
32487 |
++ pax_close_kernel(cr0); |
32488 |
++#endif |
32489 |
++ |
32490 |
++ mod->module_core_rx = ptr; |
32491 |
++ |
32492 |
++ ptr = module_alloc_update_bounds_rx(mod->init_size_rx); |
32493 |
++ if (!ptr && mod->init_size_rx) { |
32494 |
++ err = -ENOMEM; |
32495 |
++ goto free_core_rx; |
32496 |
++ } |
32497 |
++ |
32498 |
++#ifdef CONFIG_PAX_KERNEXEC |
32499 |
++ pax_open_kernel(cr0); |
32500 |
++#endif |
32501 |
++ |
32502 |
++ memset(ptr, 0, mod->init_size_rx); |
32503 |
++ |
32504 |
++#ifdef CONFIG_PAX_KERNEXEC |
32505 |
++ pax_close_kernel(cr0); |
32506 |
++#endif |
32507 |
++ |
32508 |
++ mod->module_init_rx = ptr; |
32509 |
+ /* Transfer each section which specifies SHF_ALLOC */ |
32510 |
+ DEBUGP("final section addresses:\n"); |
32511 |
+ for (i = 0; i < hdr->e_shnum; i++) { |
32512 |
+@@ -2034,17 +2155,41 @@ static noinline struct module *load_modu |
32513 |
+ if (!(sechdrs[i].sh_flags & SHF_ALLOC)) |
32514 |
+ continue; |
32515 |
+ |
32516 |
+- if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK) |
32517 |
+- dest = mod->module_init |
32518 |
+- + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK); |
32519 |
+- else |
32520 |
+- dest = mod->module_core + sechdrs[i].sh_entsize; |
32521 |
++ if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK) { |
32522 |
++ if ((sechdrs[i].sh_flags & SHF_WRITE) || !(sechdrs[i].sh_flags & SHF_ALLOC)) |
32523 |
++ dest = mod->module_init_rw |
32524 |
++ + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK); |
32525 |
++ else |
32526 |
++ dest = mod->module_init_rx |
32527 |
++ + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK); |
32528 |
++ } else { |
32529 |
++ if ((sechdrs[i].sh_flags & SHF_WRITE) || !(sechdrs[i].sh_flags & SHF_ALLOC)) |
32530 |
++ dest = mod->module_core_rw + sechdrs[i].sh_entsize; |
32531 |
++ else |
32532 |
++ dest = mod->module_core_rx + sechdrs[i].sh_entsize; |
32533 |
++ } |
32534 |
++ |
32535 |
++ if (sechdrs[i].sh_type != SHT_NOBITS) { |
32536 |
+ |
32537 |
+- if (sechdrs[i].sh_type != SHT_NOBITS) |
32538 |
+- memcpy(dest, (void *)sechdrs[i].sh_addr, |
32539 |
+- sechdrs[i].sh_size); |
32540 |
++#ifdef CONFIG_PAX_KERNEXEC |
32541 |
++ if (!(sechdrs[i].sh_flags & SHF_WRITE) && (sechdrs[i].sh_flags & SHF_ALLOC)) { |
32542 |
++ pax_open_kernel(cr0); |
32543 |
++ memcpy(dest, (void *)sechdrs[i].sh_addr, sechdrs[i].sh_size); |
32544 |
++ pax_close_kernel(cr0); |
32545 |
++ } else |
32546 |
++#endif |
32547 |
++ |
32548 |
++ memcpy(dest, (void *)sechdrs[i].sh_addr, sechdrs[i].sh_size); |
32549 |
++ } |
32550 |
+ /* Update sh_addr to point to copy in image. */ |
32551 |
+- sechdrs[i].sh_addr = (unsigned long)dest; |
32552 |
++ |
32553 |
++#ifdef CONFIG_PAX_KERNEXEC |
32554 |
++ if (sechdrs[i].sh_flags & SHF_EXECINSTR) |
32555 |
++ sechdrs[i].sh_addr = ktva_ktla((unsigned long)dest); |
32556 |
++ else |
32557 |
++#endif |
32558 |
++ |
32559 |
++ sechdrs[i].sh_addr = (unsigned long)dest; |
32560 |
+ DEBUGP("\t0x%lx %s\n", sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name); |
32561 |
+ } |
32562 |
+ /* Module has been moved. */ |
32563 |
+@@ -2144,8 +2289,8 @@ static noinline struct module *load_modu |
32564 |
+ |
32565 |
+ /* Now do relocations. */ |
32566 |
+ for (i = 1; i < hdr->e_shnum; i++) { |
32567 |
+- const char *strtab = (char *)sechdrs[strindex].sh_addr; |
32568 |
+ unsigned int info = sechdrs[i].sh_info; |
32569 |
++ strtab = (char *)sechdrs[strindex].sh_addr; |
32570 |
+ |
32571 |
+ /* Not a valid relocation section? */ |
32572 |
+ if (info >= hdr->e_shnum) |
32573 |
+@@ -2216,12 +2361,12 @@ static noinline struct module *load_modu |
32574 |
+ * Do it before processing of module parameters, so the module |
32575 |
+ * can provide parameter accessor functions of its own. |
32576 |
+ */ |
32577 |
+- if (mod->module_init) |
32578 |
+- flush_icache_range((unsigned long)mod->module_init, |
32579 |
+- (unsigned long)mod->module_init |
32580 |
+- + mod->init_size); |
32581 |
+- flush_icache_range((unsigned long)mod->module_core, |
32582 |
+- (unsigned long)mod->module_core + mod->core_size); |
32583 |
++ if (mod->module_init_rx) |
32584 |
++ flush_icache_range((unsigned long)mod->module_init_rx, |
32585 |
++ (unsigned long)mod->module_init_rx |
32586 |
++ + mod->init_size_rx); |
32587 |
++ flush_icache_range((unsigned long)mod->module_core_rx, |
32588 |
++ (unsigned long)mod->module_core_rx + mod->core_size_rx); |
32589 |
+ |
32590 |
+ set_fs(old_fs); |
32591 |
+ |
32592 |
+@@ -2266,12 +2411,16 @@ static noinline struct module *load_modu |
32593 |
+ cleanup: |
32594 |
+ kobject_del(&mod->mkobj.kobj); |
32595 |
+ kobject_put(&mod->mkobj.kobj); |
32596 |
+- ftrace_release(mod->module_core, mod->core_size); |
32597 |
++ ftrace_release(mod->module_core_rx, mod->core_size_rx); |
32598 |
+ free_unload: |
32599 |
+ module_unload_free(mod); |
32600 |
+- module_free(mod, mod->module_init); |
32601 |
+- free_core: |
32602 |
+- module_free(mod, mod->module_core); |
32603 |
++ module_free_exec(mod, mod->module_init_rx); |
32604 |
++ free_core_rx: |
32605 |
++ module_free_exec(mod, mod->module_core_rx); |
32606 |
++ free_init_rw: |
32607 |
++ module_free(mod, mod->module_init_rw); |
32608 |
++ free_core_rw: |
32609 |
++ module_free(mod, mod->module_core_rw); |
32610 |
+ free_percpu: |
32611 |
+ if (percpu) |
32612 |
+ percpu_modfree(percpu); |
32613 |
+@@ -2294,6 +2443,9 @@ SYSCALL_DEFINE3(init_module, void __user |
32614 |
+ struct module *mod; |
32615 |
+ int ret = 0; |
32616 |
+ |
32617 |
++ if (gr_check_modstop()) |
32618 |
++ return -EPERM; |
32619 |
++ |
32620 |
+ /* Must have permission */ |
32621 |
+ if (!capable(CAP_SYS_MODULE)) |
32622 |
+ return -EPERM; |
32623 |
+@@ -2349,10 +2501,12 @@ SYSCALL_DEFINE3(init_module, void __user |
32624 |
+ /* Drop initial reference. */ |
32625 |
+ module_put(mod); |
32626 |
+ unwind_remove_table(mod->unwind_info, 1); |
32627 |
+- module_free(mod, mod->module_init); |
32628 |
+- mod->module_init = NULL; |
32629 |
+- mod->init_size = 0; |
32630 |
+- mod->init_text_size = 0; |
32631 |
++ module_free(mod, mod->module_init_rw); |
32632 |
++ module_free_exec(mod, mod->module_init_rx); |
32633 |
++ mod->module_init_rw = NULL; |
32634 |
++ mod->module_init_rx = NULL; |
32635 |
++ mod->init_size_rw = 0; |
32636 |
++ mod->init_size_rx = 0; |
32637 |
+ mutex_unlock(&module_mutex); |
32638 |
+ |
32639 |
+ return 0; |
32640 |
+@@ -2360,6 +2514,13 @@ SYSCALL_DEFINE3(init_module, void __user |
32641 |
+ |
32642 |
+ static inline int within(unsigned long addr, void *start, unsigned long size) |
32643 |
+ { |
32644 |
++ |
32645 |
++#ifdef CONFIG_PAX_KERNEXEC |
32646 |
++ if (ktla_ktva(addr) >= (unsigned long)start && |
32647 |
++ ktla_ktva(addr) < (unsigned long)start + size) |
32648 |
++ return 1; |
32649 |
++#endif |
32650 |
++ |
32651 |
+ return ((void *)addr >= start && (void *)addr < start + size); |
32652 |
+ } |
32653 |
+ |
32654 |
+@@ -2383,10 +2544,14 @@ static const char *get_ksymbol(struct mo |
32655 |
+ unsigned long nextval; |
32656 |
+ |
32657 |
+ /* At worse, next value is at end of module */ |
32658 |
+- if (within(addr, mod->module_init, mod->init_size)) |
32659 |
+- nextval = (unsigned long)mod->module_init+mod->init_text_size; |
32660 |
++ if (within(addr, mod->module_init_rx, mod->init_size_rx)) |
32661 |
++ nextval = (unsigned long)mod->module_init_rx+mod->init_size_rx; |
32662 |
++ else if (within(addr, mod->module_init_rw, mod->init_size_rw)) |
32663 |
++ nextval = (unsigned long)mod->module_init_rw+mod->init_size_rw; |
32664 |
++ else if (within(addr, mod->module_core_rx, mod->core_size_rx)) |
32665 |
++ nextval = (unsigned long)mod->module_core_rx+mod->core_size_rx; |
32666 |
+ else |
32667 |
+- nextval = (unsigned long)mod->module_core+mod->core_text_size; |
32668 |
++ nextval = (unsigned long)mod->module_core_rw+mod->core_size_rw; |
32669 |
+ |
32670 |
+ /* Scan for closest preceeding symbol, and next symbol. (ELF |
32671 |
+ starts real symbols at 1). */ |
32672 |
+@@ -2431,8 +2596,10 @@ const char *module_address_lookup(unsign |
32673 |
+ |
32674 |
+ preempt_disable(); |
32675 |
+ list_for_each_entry_rcu(mod, &modules, list) { |
32676 |
+- if (within(addr, mod->module_init, mod->init_size) |
32677 |
+- || within(addr, mod->module_core, mod->core_size)) { |
32678 |
++ if (within(addr, mod->module_init_rx, mod->init_size_rx) || |
32679 |
++ within(addr, mod->module_init_rw, mod->init_size_rw) || |
32680 |
++ within(addr, mod->module_core_rx, mod->core_size_rx) || |
32681 |
++ within(addr, mod->module_core_rw, mod->core_size_rw)) { |
32682 |
+ if (modname) |
32683 |
+ *modname = mod->name; |
32684 |
+ ret = get_ksymbol(mod, addr, size, offset); |
32685 |
+@@ -2454,8 +2621,10 @@ int lookup_module_symbol_name(unsigned l |
32686 |
+ |
32687 |
+ preempt_disable(); |
32688 |
+ list_for_each_entry_rcu(mod, &modules, list) { |
32689 |
+- if (within(addr, mod->module_init, mod->init_size) || |
32690 |
+- within(addr, mod->module_core, mod->core_size)) { |
32691 |
++ if (within(addr, mod->module_init_rx, mod->init_size_rx) || |
32692 |
++ within(addr, mod->module_init_rw, mod->init_size_rw) || |
32693 |
++ within(addr, mod->module_core_rx, mod->core_size_rx) || |
32694 |
++ within(addr, mod->module_core_rw, mod->core_size_rw)) { |
32695 |
+ const char *sym; |
32696 |
+ |
32697 |
+ sym = get_ksymbol(mod, addr, NULL, NULL); |
32698 |
+@@ -2478,8 +2647,10 @@ int lookup_module_symbol_attrs(unsigned |
32699 |
+ |
32700 |
+ preempt_disable(); |
32701 |
+ list_for_each_entry_rcu(mod, &modules, list) { |
32702 |
+- if (within(addr, mod->module_init, mod->init_size) || |
32703 |
+- within(addr, mod->module_core, mod->core_size)) { |
32704 |
++ if (within(addr, mod->module_init_rx, mod->init_size_rx) || |
32705 |
++ within(addr, mod->module_init_rw, mod->init_size_rw) || |
32706 |
++ within(addr, mod->module_core_rx, mod->core_size_rx) || |
32707 |
++ within(addr, mod->module_core_rw, mod->core_size_rw)) { |
32708 |
+ const char *sym; |
32709 |
+ |
32710 |
+ sym = get_ksymbol(mod, addr, size, offset); |
32711 |
+@@ -2613,7 +2784,7 @@ static int m_show(struct seq_file *m, vo |
32712 |
+ char buf[8]; |
32713 |
+ |
32714 |
+ seq_printf(m, "%s %u", |
32715 |
+- mod->name, mod->init_size + mod->core_size); |
32716 |
++ mod->name, mod->init_size_rx + mod->init_size_rw + mod->core_size_rx + mod->core_size_rw); |
32717 |
+ print_unload_info(m, mod); |
32718 |
+ |
32719 |
+ /* Informative for users. */ |
32720 |
+@@ -2622,7 +2793,7 @@ static int m_show(struct seq_file *m, vo |
32721 |
+ mod->state == MODULE_STATE_COMING ? "Loading": |
32722 |
+ "Live"); |
32723 |
+ /* Used by oprofile and other similar tools. */ |
32724 |
+- seq_printf(m, " 0x%p", mod->module_core); |
32725 |
++ seq_printf(m, " 0x%p 0x%p", mod->module_core_rx, mod->module_core_rw); |
32726 |
+ |
32727 |
+ /* Taints info */ |
32728 |
+ if (mod->taints) |
32729 |
+@@ -2698,8 +2869,8 @@ int is_module_address(unsigned long addr |
32730 |
+ preempt_disable(); |
32731 |
+ |
32732 |
+ list_for_each_entry_rcu(mod, &modules, list) { |
32733 |
+- if (within(addr, mod->module_core, mod->core_size)) { |
32734 |
+- preempt_enable(); |
32735 |
++ if (within(addr, mod->module_core_rx, mod->core_size_rx) || |
32736 |
++ within(addr, mod->module_core_rw, mod->core_size_rw)) { |
32737 |
+ return 1; |
32738 |
+ } |
32739 |
+ } |
32740 |
+@@ -2715,12 +2886,16 @@ struct module *__module_text_address(uns |
32741 |
+ { |
32742 |
+ struct module *mod; |
32743 |
+ |
32744 |
+- if (addr < module_addr_min || addr > module_addr_max) |
32745 |
++#ifdef CONFIG_X86_32 |
32746 |
++ addr = ktla_ktva(addr); |
32747 |
++#endif |
32748 |
++ |
32749 |
++ if (addr < module_addr_min_rx || addr > module_addr_max_rx) |
32750 |
+ return NULL; |
32751 |
+ |
32752 |
+ list_for_each_entry_rcu(mod, &modules, list) |
32753 |
+- if (within(addr, mod->module_init, mod->init_text_size) |
32754 |
+- || within(addr, mod->module_core, mod->core_text_size)) |
32755 |
++ if (within(addr, mod->module_init_rx, mod->init_size_rx) |
32756 |
++ || within(addr, mod->module_core_rx, mod->core_size_rx)) |
32757 |
+ return mod; |
32758 |
+ return NULL; |
32759 |
+ } |
32760 |
+diff -urNp linux-2.6.28.8/kernel/mutex.c linux-2.6.28.8/kernel/mutex.c |
32761 |
+--- linux-2.6.28.8/kernel/mutex.c 2009-02-06 16:47:45.000000000 -0500 |
32762 |
++++ linux-2.6.28.8/kernel/mutex.c 2009-02-21 09:37:50.000000000 -0500 |
32763 |
+@@ -83,7 +83,7 @@ __mutex_lock_slowpath(atomic_t *lock_cou |
32764 |
+ * |
32765 |
+ * This function is similar to (but not equivalent to) down(). |
32766 |
+ */ |
32767 |
+-void inline __sched mutex_lock(struct mutex *lock) |
32768 |
++inline void __sched mutex_lock(struct mutex *lock) |
32769 |
+ { |
32770 |
+ might_sleep(); |
32771 |
+ /* |
32772 |
+diff -urNp linux-2.6.28.8/kernel/panic.c linux-2.6.28.8/kernel/panic.c |
32773 |
+--- linux-2.6.28.8/kernel/panic.c 2009-02-06 16:47:45.000000000 -0500 |
32774 |
++++ linux-2.6.28.8/kernel/panic.c 2009-02-21 09:37:50.000000000 -0500 |
32775 |
+@@ -367,6 +367,8 @@ EXPORT_SYMBOL(warn_slowpath); |
32776 |
+ */ |
32777 |
+ void __stack_chk_fail(void) |
32778 |
+ { |
32779 |
++ print_symbol("stack corrupted in: %s\n", (unsigned long)__builtin_return_address(0)); |
32780 |
++ dump_stack(); |
32781 |
+ panic("stack-protector: Kernel stack is corrupted"); |
32782 |
+ } |
32783 |
+ EXPORT_SYMBOL(__stack_chk_fail); |
32784 |
+diff -urNp linux-2.6.28.8/kernel/pid.c linux-2.6.28.8/kernel/pid.c |
32785 |
+--- linux-2.6.28.8/kernel/pid.c 2009-02-06 16:47:45.000000000 -0500 |
32786 |
++++ linux-2.6.28.8/kernel/pid.c 2009-02-21 09:37:50.000000000 -0500 |
32787 |
+@@ -33,6 +33,7 @@ |
32788 |
+ #include <linux/rculist.h> |
32789 |
+ #include <linux/bootmem.h> |
32790 |
+ #include <linux/hash.h> |
32791 |
++#include <linux/security.h> |
32792 |
+ #include <linux/pid_namespace.h> |
32793 |
+ #include <linux/init_task.h> |
32794 |
+ #include <linux/syscalls.h> |
32795 |
+@@ -45,7 +46,7 @@ struct pid init_struct_pid = INIT_STRUCT |
32796 |
+ |
32797 |
+ int pid_max = PID_MAX_DEFAULT; |
32798 |
+ |
32799 |
+-#define RESERVED_PIDS 300 |
32800 |
++#define RESERVED_PIDS 500 |
32801 |
+ |
32802 |
+ int pid_max_min = RESERVED_PIDS + 1; |
32803 |
+ int pid_max_max = PID_MAX_LIMIT; |
32804 |
+@@ -381,7 +382,14 @@ EXPORT_SYMBOL(pid_task); |
32805 |
+ struct task_struct *find_task_by_pid_type_ns(int type, int nr, |
32806 |
+ struct pid_namespace *ns) |
32807 |
+ { |
32808 |
+- return pid_task(find_pid_ns(nr, ns), type); |
32809 |
++ struct task_struct *task; |
32810 |
++ |
32811 |
++ task = pid_task(find_pid_ns(nr, ns), type); |
32812 |
++ |
32813 |
++ if (gr_pid_is_chrooted(task)) |
32814 |
++ return NULL; |
32815 |
++ |
32816 |
++ return task; |
32817 |
+ } |
32818 |
+ |
32819 |
+ EXPORT_SYMBOL(find_task_by_pid_type_ns); |
32820 |
+diff -urNp linux-2.6.28.8/kernel/posix-cpu-timers.c linux-2.6.28.8/kernel/posix-cpu-timers.c |
32821 |
+--- linux-2.6.28.8/kernel/posix-cpu-timers.c 2009-02-06 16:47:45.000000000 -0500 |
32822 |
++++ linux-2.6.28.8/kernel/posix-cpu-timers.c 2009-02-21 09:37:50.000000000 -0500 |
32823 |
+@@ -6,6 +6,7 @@ |
32824 |
+ #include <linux/posix-timers.h> |
32825 |
+ #include <linux/errno.h> |
32826 |
+ #include <linux/math64.h> |
32827 |
++#include <linux/security.h> |
32828 |
+ #include <asm/uaccess.h> |
32829 |
+ #include <linux/kernel_stat.h> |
32830 |
+ |
32831 |
+@@ -1157,6 +1158,7 @@ static void check_process_timers(struct |
32832 |
+ __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk); |
32833 |
+ return; |
32834 |
+ } |
32835 |
++ gr_learn_resource(tsk, RLIMIT_CPU, psecs, 1); |
32836 |
+ if (psecs >= sig->rlim[RLIMIT_CPU].rlim_cur) { |
32837 |
+ /* |
32838 |
+ * At the soft limit, send a SIGXCPU every second. |
32839 |
+@@ -1381,17 +1383,17 @@ void run_posix_cpu_timers(struct task_st |
32840 |
+ * timer call will interfere. |
32841 |
+ */ |
32842 |
+ list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) { |
32843 |
+- int firing; |
32844 |
++ int __firing; |
32845 |
+ spin_lock(&timer->it_lock); |
32846 |
+ list_del_init(&timer->it.cpu.entry); |
32847 |
+- firing = timer->it.cpu.firing; |
32848 |
++ __firing = timer->it.cpu.firing; |
32849 |
+ timer->it.cpu.firing = 0; |
32850 |
+ /* |
32851 |
+ * The firing flag is -1 if we collided with a reset |
32852 |
+ * of the timer, which already reported this |
32853 |
+ * almost-firing as an overrun. So don't generate an event. |
32854 |
+ */ |
32855 |
+- if (likely(firing >= 0)) { |
32856 |
++ if (likely(__firing >= 0)) { |
32857 |
+ cpu_timer_fire(timer); |
32858 |
+ } |
32859 |
+ spin_unlock(&timer->it_lock); |
32860 |
+diff -urNp linux-2.6.28.8/kernel/power/poweroff.c linux-2.6.28.8/kernel/power/poweroff.c |
32861 |
+--- linux-2.6.28.8/kernel/power/poweroff.c 2009-02-06 16:47:45.000000000 -0500 |
32862 |
++++ linux-2.6.28.8/kernel/power/poweroff.c 2009-02-21 09:37:50.000000000 -0500 |
32863 |
+@@ -37,7 +37,7 @@ static struct sysrq_key_op sysrq_powerof |
32864 |
+ .enable_mask = SYSRQ_ENABLE_BOOT, |
32865 |
+ }; |
32866 |
+ |
32867 |
+-static int pm_sysrq_init(void) |
32868 |
++static int __init pm_sysrq_init(void) |
32869 |
+ { |
32870 |
+ register_sysrq_key('o', &sysrq_poweroff_op); |
32871 |
+ return 0; |
32872 |
+diff -urNp linux-2.6.28.8/kernel/printk.c linux-2.6.28.8/kernel/printk.c |
32873 |
+--- linux-2.6.28.8/kernel/printk.c 2009-02-06 16:47:45.000000000 -0500 |
32874 |
++++ linux-2.6.28.8/kernel/printk.c 2009-02-21 09:37:50.000000000 -0500 |
32875 |
+@@ -254,6 +254,11 @@ int do_syslog(int type, char __user *buf |
32876 |
+ char c; |
32877 |
+ int error = 0; |
32878 |
+ |
32879 |
++#ifdef CONFIG_GRKERNSEC_DMESG |
32880 |
++ if (grsec_enable_dmesg && !capable(CAP_SYS_ADMIN)) |
32881 |
++ return -EPERM; |
32882 |
++#endif |
32883 |
++ |
32884 |
+ error = security_syslog(type); |
32885 |
+ if (error) |
32886 |
+ return error; |
32887 |
+diff -urNp linux-2.6.28.8/kernel/ptrace.c linux-2.6.28.8/kernel/ptrace.c |
32888 |
+--- linux-2.6.28.8/kernel/ptrace.c 2009-02-06 16:47:45.000000000 -0500 |
32889 |
++++ linux-2.6.28.8/kernel/ptrace.c 2009-02-21 09:37:50.000000000 -0500 |
32890 |
+@@ -132,12 +132,12 @@ int __ptrace_may_access(struct task_stru |
32891 |
+ (current->uid != task->uid) || |
32892 |
+ (current->gid != task->egid) || |
32893 |
+ (current->gid != task->sgid) || |
32894 |
+- (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) |
32895 |
++ (current->gid != task->gid)) && !capable_nolog(CAP_SYS_PTRACE)) |
32896 |
+ return -EPERM; |
32897 |
+ smp_rmb(); |
32898 |
+ if (task->mm) |
32899 |
+ dumpable = get_dumpable(task->mm); |
32900 |
+- if (!dumpable && !capable(CAP_SYS_PTRACE)) |
32901 |
++ if (!dumpable && !capable_nolog(CAP_SYS_PTRACE)) |
32902 |
+ return -EPERM; |
32903 |
+ |
32904 |
+ return security_ptrace_may_access(task, mode); |
32905 |
+@@ -193,7 +193,7 @@ repeat: |
32906 |
+ |
32907 |
+ /* Go */ |
32908 |
+ task->ptrace |= PT_PTRACED; |
32909 |
+- if (capable(CAP_SYS_PTRACE)) |
32910 |
++ if (capable_nolog(CAP_SYS_PTRACE)) |
32911 |
+ task->ptrace |= PT_PTRACE_CAP; |
32912 |
+ |
32913 |
+ __ptrace_link(task, current); |
32914 |
+@@ -582,6 +582,11 @@ SYSCALL_DEFINE4(ptrace, long, request, l |
32915 |
+ if (ret < 0) |
32916 |
+ goto out_put_task_struct; |
32917 |
+ |
32918 |
++ if (gr_handle_ptrace(child, request)) { |
32919 |
++ ret = -EPERM; |
32920 |
++ goto out_put_task_struct; |
32921 |
++ } |
32922 |
++ |
32923 |
+ ret = arch_ptrace(child, request, addr, data); |
32924 |
+ if (ret < 0) |
32925 |
+ goto out_put_task_struct; |
32926 |
+diff -urNp linux-2.6.28.8/kernel/relay.c linux-2.6.28.8/kernel/relay.c |
32927 |
+--- linux-2.6.28.8/kernel/relay.c 2009-02-06 16:47:45.000000000 -0500 |
32928 |
++++ linux-2.6.28.8/kernel/relay.c 2009-02-21 09:37:50.000000000 -0500 |
32929 |
+@@ -1292,7 +1292,7 @@ static int subbuf_splice_actor(struct fi |
32930 |
+ return 0; |
32931 |
+ |
32932 |
+ ret = *nonpad_ret = splice_to_pipe(pipe, &spd); |
32933 |
+- if (ret < 0 || ret < total_len) |
32934 |
++ if ((int)ret < 0 || ret < total_len) |
32935 |
+ return ret; |
32936 |
+ |
32937 |
+ if (read_start + ret == nonpad_end) |
32938 |
+diff -urNp linux-2.6.28.8/kernel/resource.c linux-2.6.28.8/kernel/resource.c |
32939 |
+--- linux-2.6.28.8/kernel/resource.c 2009-02-06 16:47:45.000000000 -0500 |
32940 |
++++ linux-2.6.28.8/kernel/resource.c 2009-02-21 09:37:50.000000000 -0500 |
32941 |
+@@ -132,8 +132,18 @@ static const struct file_operations proc |
32942 |
+ |
32943 |
+ static int __init ioresources_init(void) |
32944 |
+ { |
32945 |
++#ifdef CONFIG_GRKERNSEC_PROC_ADD |
32946 |
++#ifdef CONFIG_GRKERNSEC_PROC_USER |
32947 |
++ proc_create("ioports", S_IRUSR, NULL, &proc_ioports_operations); |
32948 |
++ proc_create("iomem", S_IRUSR, NULL, &proc_iomem_operations); |
32949 |
++#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP) |
32950 |
++ proc_create("ioports", S_IRUSR | S_IRGRP, NULL, &proc_ioports_operations); |
32951 |
++ proc_create("iomem", S_IRUSR | S_IRGRP, NULL, &proc_iomem_operations); |
32952 |
++#endif |
32953 |
++#else |
32954 |
+ proc_create("ioports", 0, NULL, &proc_ioports_operations); |
32955 |
+ proc_create("iomem", 0, NULL, &proc_iomem_operations); |
32956 |
++#endif |
32957 |
+ return 0; |
32958 |
+ } |
32959 |
+ __initcall(ioresources_init); |
32960 |
+diff -urNp linux-2.6.28.8/kernel/sched.c linux-2.6.28.8/kernel/sched.c |
32961 |
+--- linux-2.6.28.8/kernel/sched.c 2009-02-07 16:10:45.000000000 -0500 |
32962 |
++++ linux-2.6.28.8/kernel/sched.c 2009-02-21 09:37:50.000000000 -0500 |
32963 |
+@@ -5045,7 +5045,8 @@ SYSCALL_DEFINE1(nice, int, increment) |
32964 |
+ if (nice > 19) |
32965 |
+ nice = 19; |
32966 |
+ |
32967 |
+- if (increment < 0 && !can_nice(current, nice)) |
32968 |
++ if (increment < 0 && (!can_nice(current, nice) || |
32969 |
++ gr_handle_chroot_nice())) |
32970 |
+ return -EPERM; |
32971 |
+ |
32972 |
+ retval = security_task_setnice(current, nice); |
32973 |
+@@ -6310,7 +6311,7 @@ static struct ctl_table sd_ctl_dir[] = { |
32974 |
+ .procname = "sched_domain", |
32975 |
+ .mode = 0555, |
32976 |
+ }, |
32977 |
+- {0, }, |
32978 |
++ { 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } |
32979 |
+ }; |
32980 |
+ |
32981 |
+ static struct ctl_table sd_ctl_root[] = { |
32982 |
+@@ -6320,7 +6321,7 @@ static struct ctl_table sd_ctl_root[] = |
32983 |
+ .mode = 0555, |
32984 |
+ .child = sd_ctl_dir, |
32985 |
+ }, |
32986 |
+- {0, }, |
32987 |
++ { 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } |
32988 |
+ }; |
32989 |
+ |
32990 |
+ static struct ctl_table *sd_alloc_ctl_entry(int n) |
32991 |
+diff -urNp linux-2.6.28.8/kernel/signal.c linux-2.6.28.8/kernel/signal.c |
32992 |
+--- linux-2.6.28.8/kernel/signal.c 2009-02-06 16:47:45.000000000 -0500 |
32993 |
++++ linux-2.6.28.8/kernel/signal.c 2009-03-07 14:17:22.000000000 -0500 |
32994 |
+@@ -596,6 +596,9 @@ static int check_kill_permission(int sig |
32995 |
+ } |
32996 |
+ } |
32997 |
+ |
32998 |
++ if (gr_handle_signal(t, sig)) |
32999 |
++ return -EPERM; |
33000 |
++ |
33001 |
+ return security_task_kill(t, info, sig, 0); |
33002 |
+ } |
33003 |
+ |
33004 |
+@@ -887,8 +890,8 @@ static void print_fatal_signal(struct pt |
33005 |
+ for (i = 0; i < 16; i++) { |
33006 |
+ unsigned char insn; |
33007 |
+ |
33008 |
+- __get_user(insn, (unsigned char *)(regs->ip + i)); |
33009 |
+- printk("%02x ", insn); |
33010 |
++ if (!get_user(insn, (unsigned char __user *)(regs->ip + i))) |
33011 |
++ printk("%02x ", insn); |
33012 |
+ } |
33013 |
+ } |
33014 |
+ #endif |
33015 |
+@@ -911,7 +914,7 @@ __group_send_sig_info(int sig, struct si |
33016 |
+ return send_signal(sig, info, p, 1); |
33017 |
+ } |
33018 |
+ |
33019 |
+-static int |
33020 |
++int |
33021 |
+ specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) |
33022 |
+ { |
33023 |
+ return send_signal(sig, info, t, 0); |
33024 |
+@@ -951,6 +954,9 @@ force_sig_info(int sig, struct siginfo * |
33025 |
+ ret = specific_send_sig_info(sig, info, t); |
33026 |
+ spin_unlock_irqrestore(&t->sighand->siglock, flags); |
33027 |
+ |
33028 |
++ gr_log_signal(sig, t); |
33029 |
++ gr_handle_crash(t, sig); |
33030 |
++ |
33031 |
+ return ret; |
33032 |
+ } |
33033 |
+ |
33034 |
+@@ -1021,6 +1027,8 @@ int group_send_sig_info(int sig, struct |
33035 |
+ ret = __group_send_sig_info(sig, info, p); |
33036 |
+ unlock_task_sighand(p, &flags); |
33037 |
+ } |
33038 |
++ if (!ret) |
33039 |
++ gr_log_signal(sig, p); |
33040 |
+ } |
33041 |
+ |
33042 |
+ return ret; |
33043 |
+diff -urNp linux-2.6.28.8/kernel/softirq.c linux-2.6.28.8/kernel/softirq.c |
33044 |
+--- linux-2.6.28.8/kernel/softirq.c 2009-02-06 16:47:45.000000000 -0500 |
33045 |
++++ linux-2.6.28.8/kernel/softirq.c 2009-02-21 09:37:50.000000000 -0500 |
33046 |
+@@ -463,9 +463,9 @@ void tasklet_kill(struct tasklet_struct |
33047 |
+ printk("Attempt to kill tasklet from interrupt\n"); |
33048 |
+ |
33049 |
+ while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) { |
33050 |
+- do |
33051 |
++ do { |
33052 |
+ yield(); |
33053 |
+- while (test_bit(TASKLET_STATE_SCHED, &t->state)); |
33054 |
++ } while (test_bit(TASKLET_STATE_SCHED, &t->state)); |
33055 |
+ } |
33056 |
+ tasklet_unlock_wait(t); |
33057 |
+ clear_bit(TASKLET_STATE_SCHED, &t->state); |
33058 |
+diff -urNp linux-2.6.28.8/kernel/sys.c linux-2.6.28.8/kernel/sys.c |
33059 |
+--- linux-2.6.28.8/kernel/sys.c 2009-02-07 16:10:45.000000000 -0500 |
33060 |
++++ linux-2.6.28.8/kernel/sys.c 2009-02-21 09:37:50.000000000 -0500 |
33061 |
+@@ -125,6 +125,12 @@ static int set_one_prio(struct task_stru |
33062 |
+ error = -EACCES; |
33063 |
+ goto out; |
33064 |
+ } |
33065 |
++ |
33066 |
++ if (gr_handle_chroot_setpriority(p, niceval)) { |
33067 |
++ error = -EACCES; |
33068 |
++ goto out; |
33069 |
++ } |
33070 |
++ |
33071 |
+ no_nice = security_task_setnice(p, niceval); |
33072 |
+ if (no_nice) { |
33073 |
+ error = no_nice; |
33074 |
+@@ -181,10 +187,10 @@ SYSCALL_DEFINE3(setpriority, int, which, |
33075 |
+ if ((who != current->uid) && !(user = find_user(who))) |
33076 |
+ goto out_unlock; /* No processes for this user */ |
33077 |
+ |
33078 |
+- do_each_thread(g, p) |
33079 |
++ do_each_thread(g, p) { |
33080 |
+ if (p->uid == who) |
33081 |
+ error = set_one_prio(p, niceval, error); |
33082 |
+- while_each_thread(g, p); |
33083 |
++ } while_each_thread(g, p); |
33084 |
+ if (who != current->uid) |
33085 |
+ free_uid(user); /* For find_user() */ |
33086 |
+ break; |
33087 |
+@@ -243,13 +249,13 @@ SYSCALL_DEFINE2(getpriority, int, which, |
33088 |
+ if ((who != current->uid) && !(user = find_user(who))) |
33089 |
+ goto out_unlock; /* No processes for this user */ |
33090 |
+ |
33091 |
+- do_each_thread(g, p) |
33092 |
++ do_each_thread(g, p) { |
33093 |
+ if (p->uid == who) { |
33094 |
+ niceval = 20 - task_nice(p); |
33095 |
+ if (niceval > retval) |
33096 |
+ retval = niceval; |
33097 |
+ } |
33098 |
+- while_each_thread(g, p); |
33099 |
++ } while_each_thread(g, p); |
33100 |
+ if (who != current->uid) |
33101 |
+ free_uid(user); /* for find_user() */ |
33102 |
+ break; |
33103 |
+@@ -500,6 +506,10 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, g |
33104 |
+ else |
33105 |
+ return -EPERM; |
33106 |
+ } |
33107 |
++ |
33108 |
++ if (gr_check_group_change(new_rgid, new_egid, -1)) |
33109 |
++ return -EPERM; |
33110 |
++ |
33111 |
+ if (new_egid != old_egid) { |
33112 |
+ set_dumpable(current->mm, suid_dumpable); |
33113 |
+ smp_wmb(); |
33114 |
+@@ -507,6 +517,9 @@ SYSCALL_DEFINE2(setregid, gid_t, rgid, g |
33115 |
+ if (rgid != (gid_t) -1 || |
33116 |
+ (egid != (gid_t) -1 && egid != old_rgid)) |
33117 |
+ current->sgid = new_egid; |
33118 |
++ |
33119 |
++ gr_set_role_label(current, current->uid, new_rgid); |
33120 |
++ |
33121 |
+ current->fsgid = new_egid; |
33122 |
+ current->egid = new_egid; |
33123 |
+ current->gid = new_rgid; |
33124 |
+@@ -529,11 +542,17 @@ SYSCALL_DEFINE1(setgid, gid_t, gid) |
33125 |
+ if (retval) |
33126 |
+ return retval; |
33127 |
+ |
33128 |
++ if (gr_check_group_change(gid, gid, gid)) |
33129 |
++ return -EPERM; |
33130 |
++ |
33131 |
+ if (capable(CAP_SETGID)) { |
33132 |
+ if (old_egid != gid) { |
33133 |
+ set_dumpable(current->mm, suid_dumpable); |
33134 |
+ smp_wmb(); |
33135 |
+ } |
33136 |
++ |
33137 |
++ gr_set_role_label(current, current->uid, gid); |
33138 |
++ |
33139 |
+ current->gid = current->egid = current->sgid = current->fsgid = gid; |
33140 |
+ } else if ((gid == current->gid) || (gid == current->sgid)) { |
33141 |
+ if (old_egid != gid) { |
33142 |
+@@ -571,6 +590,9 @@ static int set_user(uid_t new_ruid, int |
33143 |
+ set_dumpable(current->mm, suid_dumpable); |
33144 |
+ smp_wmb(); |
33145 |
+ } |
33146 |
++ |
33147 |
++ gr_set_role_label(current, new_ruid, current->gid); |
33148 |
++ |
33149 |
+ current->uid = new_ruid; |
33150 |
+ return 0; |
33151 |
+ } |
33152 |
+@@ -620,6 +642,9 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, u |
33153 |
+ return -EPERM; |
33154 |
+ } |
33155 |
+ |
33156 |
++ if (gr_check_user_change(new_ruid, new_euid, -1)) |
33157 |
++ return -EPERM; |
33158 |
++ |
33159 |
+ if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0) |
33160 |
+ return -EAGAIN; |
33161 |
+ |
33162 |
+@@ -666,6 +691,12 @@ SYSCALL_DEFINE1(setuid, uid_t, uid) |
33163 |
+ old_suid = current->suid; |
33164 |
+ new_suid = old_suid; |
33165 |
+ |
33166 |
++ if (gr_check_crash_uid(uid)) |
33167 |
++ return -EPERM; |
33168 |
++ |
33169 |
++ if (gr_check_user_change(uid, uid, uid)) |
33170 |
++ return -EPERM; |
33171 |
++ |
33172 |
+ if (capable(CAP_SETUID)) { |
33173 |
+ if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) |
33174 |
+ return -EAGAIN; |
33175 |
+@@ -713,6 +744,10 @@ SYSCALL_DEFINE3(setresuid, uid_t, ruid, |
33176 |
+ (suid != current->euid) && (suid != current->suid)) |
33177 |
+ return -EPERM; |
33178 |
+ } |
33179 |
++ |
33180 |
++ if (gr_check_user_change(ruid, euid, -1)) |
33181 |
++ return -EPERM; |
33182 |
++ |
33183 |
+ if (ruid != (uid_t) -1) { |
33184 |
+ if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0) |
33185 |
+ return -EAGAIN; |
33186 |
+@@ -767,6 +802,10 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, |
33187 |
+ (sgid != current->egid) && (sgid != current->sgid)) |
33188 |
+ return -EPERM; |
33189 |
+ } |
33190 |
++ |
33191 |
++ if (gr_check_group_change(rgid, egid, -1)) |
33192 |
++ return -EPERM; |
33193 |
++ |
33194 |
+ if (egid != (gid_t) -1) { |
33195 |
+ if (egid != current->egid) { |
33196 |
+ set_dumpable(current->mm, suid_dumpable); |
33197 |
+@@ -775,8 +814,10 @@ SYSCALL_DEFINE3(setresgid, gid_t, rgid, |
33198 |
+ current->egid = egid; |
33199 |
+ } |
33200 |
+ current->fsgid = current->egid; |
33201 |
+- if (rgid != (gid_t) -1) |
33202 |
++ if (rgid != (gid_t) -1) { |
33203 |
++ gr_set_role_label(current, current->uid, rgid); |
33204 |
+ current->gid = rgid; |
33205 |
++ } |
33206 |
+ if (sgid != (gid_t) -1) |
33207 |
+ current->sgid = sgid; |
33208 |
+ |
33209 |
+@@ -811,6 +852,9 @@ SYSCALL_DEFINE1(setfsuid, uid_t, uid) |
33210 |
+ if (security_task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS)) |
33211 |
+ return old_fsuid; |
33212 |
+ |
33213 |
++ if (gr_check_user_change(-1, -1, uid)) |
33214 |
++ return old_fsuid; |
33215 |
++ |
33216 |
+ if (uid == current->uid || uid == current->euid || |
33217 |
+ uid == current->suid || uid == current->fsuid || |
33218 |
+ capable(CAP_SETUID)) { |
33219 |
+@@ -843,6 +887,9 @@ SYSCALL_DEFINE1(setfsgid, gid_t, gid) |
33220 |
+ if (gid == current->gid || gid == current->egid || |
33221 |
+ gid == current->sgid || gid == current->fsgid || |
33222 |
+ capable(CAP_SETGID)) { |
33223 |
++ if (gr_check_group_change(-1, -1, gid)) |
33224 |
++ return old_fsgid; |
33225 |
++ |
33226 |
+ if (gid != old_fsgid) { |
33227 |
+ set_dumpable(current->mm, suid_dumpable); |
33228 |
+ smp_wmb(); |
33229 |
+@@ -914,7 +961,10 @@ SYSCALL_DEFINE2(setpgid, pid_t, pid, pid |
33230 |
+ write_lock_irq(&tasklist_lock); |
33231 |
+ |
33232 |
+ err = -ESRCH; |
33233 |
+- p = find_task_by_vpid(pid); |
33234 |
++ /* grsec: replaced find_task_by_vpid with equivalent call which |
33235 |
++ lacks the chroot restriction |
33236 |
++ */ |
33237 |
++ p = pid_task(find_pid_ns(pid, current->nsproxy->pid_ns), PIDTYPE_PID); |
33238 |
+ if (!p) |
33239 |
+ goto out; |
33240 |
+ |
33241 |
+@@ -1640,7 +1690,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsi |
33242 |
+ error = get_dumpable(current->mm); |
33243 |
+ break; |
33244 |
+ case PR_SET_DUMPABLE: |
33245 |
+- if (arg2 < 0 || arg2 > 1) { |
33246 |
++ if (arg2 > 1) { |
33247 |
+ error = -EINVAL; |
33248 |
+ break; |
33249 |
+ } |
33250 |
+diff -urNp linux-2.6.28.8/kernel/sysctl.c linux-2.6.28.8/kernel/sysctl.c |
33251 |
+--- linux-2.6.28.8/kernel/sysctl.c 2009-02-06 16:47:45.000000000 -0500 |
33252 |
++++ linux-2.6.28.8/kernel/sysctl.c 2009-03-07 04:29:14.000000000 -0500 |
33253 |
+@@ -61,6 +61,13 @@ |
33254 |
+ static int deprecated_sysctl_warning(struct __sysctl_args *args); |
33255 |
+ |
33256 |
+ #if defined(CONFIG_SYSCTL) |
33257 |
++#include <linux/grsecurity.h> |
33258 |
++#include <linux/grinternal.h> |
33259 |
++ |
33260 |
++extern __u32 gr_handle_sysctl(const ctl_table *table, const int op); |
33261 |
++extern int gr_handle_sysctl_mod(const char *dirname, const char *name, |
33262 |
++ const int op); |
33263 |
++extern int gr_handle_chroot_sysctl(const int op); |
33264 |
+ |
33265 |
+ /* External variables not in a header file. */ |
33266 |
+ extern int C_A_D; |
33267 |
+@@ -152,6 +159,7 @@ static int proc_do_cad_pid(struct ctl_ta |
33268 |
+ static int proc_taint(struct ctl_table *table, int write, struct file *filp, |
33269 |
+ void __user *buffer, size_t *lenp, loff_t *ppos); |
33270 |
+ #endif |
33271 |
++extern ctl_table grsecurity_table[]; |
33272 |
+ |
33273 |
+ static struct ctl_table root_table[]; |
33274 |
+ static struct ctl_table_root sysctl_table_root; |
33275 |
+@@ -184,6 +192,21 @@ extern struct ctl_table epoll_table[]; |
33276 |
+ int sysctl_legacy_va_layout; |
33277 |
+ #endif |
33278 |
+ |
33279 |
++#ifdef CONFIG_PAX_SOFTMODE |
33280 |
++static ctl_table pax_table[] = { |
33281 |
++ { |
33282 |
++ .ctl_name = CTL_UNNUMBERED, |
33283 |
++ .procname = "softmode", |
33284 |
++ .data = &pax_softmode, |
33285 |
++ .maxlen = sizeof(unsigned int), |
33286 |
++ .mode = 0600, |
33287 |
++ .proc_handler = &proc_dointvec, |
33288 |
++ }, |
33289 |
++ |
33290 |
++ { .ctl_name = 0 } |
33291 |
++}; |
33292 |
++#endif |
33293 |
++ |
33294 |
+ extern int prove_locking; |
33295 |
+ extern int lock_stat; |
33296 |
+ |
33297 |
+@@ -856,6 +879,25 @@ static struct ctl_table kern_table[] = { |
33298 |
+ .proc_handler = &scan_unevictable_handler, |
33299 |
+ }, |
33300 |
+ #endif |
33301 |
++ |
33302 |
++#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP) |
33303 |
++ { |
33304 |
++ .ctl_name = CTL_UNNUMBERED, |
33305 |
++ .procname = "grsecurity", |
33306 |
++ .mode = 0500, |
33307 |
++ .child = grsecurity_table, |
33308 |
++ }, |
33309 |
++#endif |
33310 |
++ |
33311 |
++#ifdef CONFIG_PAX_SOFTMODE |
33312 |
++ { |
33313 |
++ .ctl_name = CTL_UNNUMBERED, |
33314 |
++ .procname = "pax", |
33315 |
++ .mode = 0500, |
33316 |
++ .child = pax_table, |
33317 |
++ }, |
33318 |
++#endif |
33319 |
++ |
33320 |
+ /* |
33321 |
+ * NOTE: do not add new entries to this table unless you have read |
33322 |
+ * Documentation/sysctl/ctl_unnumbered.txt |
33323 |
+@@ -1562,6 +1604,8 @@ static int do_sysctl_strategy(struct ctl |
33324 |
+ return 0; |
33325 |
+ } |
33326 |
+ |
33327 |
++static int sysctl_perm_nochk(struct ctl_table_root *root, struct ctl_table *table, int op); |
33328 |
++ |
33329 |
+ static int parse_table(int __user *name, int nlen, |
33330 |
+ void __user *oldval, size_t __user *oldlenp, |
33331 |
+ void __user *newval, size_t newlen, |
33332 |
+@@ -1580,7 +1624,7 @@ repeat: |
33333 |
+ if (n == table->ctl_name) { |
33334 |
+ int error; |
33335 |
+ if (table->child) { |
33336 |
+- if (sysctl_perm(root, table, MAY_EXEC)) |
33337 |
++ if (sysctl_perm_nochk(root, table, MAY_EXEC)) |
33338 |
+ return -EPERM; |
33339 |
+ name++; |
33340 |
+ nlen--; |
33341 |
+@@ -1665,6 +1709,33 @@ int sysctl_perm(struct ctl_table_root *r |
33342 |
+ int error; |
33343 |
+ int mode; |
33344 |
+ |
33345 |
++ if (table->parent != NULL && table->parent->procname != NULL && |
33346 |
++ table->procname != NULL && |
33347 |
++ gr_handle_sysctl_mod(table->parent->procname, table->procname, op)) |
33348 |
++ return -EACCES; |
33349 |
++ if (gr_handle_chroot_sysctl(op)) |
33350 |
++ return -EACCES; |
33351 |
++ error = gr_handle_sysctl(table, op); |
33352 |
++ if (error) |
33353 |
++ return error; |
33354 |
++ |
33355 |
++ error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC)); |
33356 |
++ if (error) |
33357 |
++ return error; |
33358 |
++ |
33359 |
++ if (root->permissions) |
33360 |
++ mode = root->permissions(root, current->nsproxy, table); |
33361 |
++ else |
33362 |
++ mode = table->mode; |
33363 |
++ |
33364 |
++ return test_perm(mode, op); |
33365 |
++} |
33366 |
++ |
33367 |
++int sysctl_perm_nochk(struct ctl_table_root *root, struct ctl_table *table, int op) |
33368 |
++{ |
33369 |
++ int error; |
33370 |
++ int mode; |
33371 |
++ |
33372 |
+ error = security_sysctl(table, op & (MAY_READ | MAY_WRITE | MAY_EXEC)); |
33373 |
+ if (error) |
33374 |
+ return error; |
33375 |
+diff -urNp linux-2.6.28.8/kernel/time/tick-broadcast.c linux-2.6.28.8/kernel/time/tick-broadcast.c |
33376 |
+--- linux-2.6.28.8/kernel/time/tick-broadcast.c 2009-02-06 16:47:45.000000000 -0500 |
33377 |
++++ linux-2.6.28.8/kernel/time/tick-broadcast.c 2009-02-21 09:37:50.000000000 -0500 |
33378 |
+@@ -114,7 +114,7 @@ int tick_device_uses_broadcast(struct cl |
33379 |
+ * then clear the broadcast bit. |
33380 |
+ */ |
33381 |
+ if (!(dev->features & CLOCK_EVT_FEAT_C3STOP)) { |
33382 |
+- int cpu = smp_processor_id(); |
33383 |
++ cpu = smp_processor_id(); |
33384 |
+ |
33385 |
+ cpu_clear(cpu, tick_broadcast_mask); |
33386 |
+ tick_broadcast_clear_oneshot(cpu); |
33387 |
+diff -urNp linux-2.6.28.8/kernel/time.c linux-2.6.28.8/kernel/time.c |
33388 |
+--- linux-2.6.28.8/kernel/time.c 2009-02-06 16:47:45.000000000 -0500 |
33389 |
++++ linux-2.6.28.8/kernel/time.c 2009-02-21 09:37:50.000000000 -0500 |
33390 |
+@@ -92,6 +92,9 @@ SYSCALL_DEFINE1(stime, time_t __user *, |
33391 |
+ return err; |
33392 |
+ |
33393 |
+ do_settimeofday(&tv); |
33394 |
++ |
33395 |
++ gr_log_timechange(); |
33396 |
++ |
33397 |
+ return 0; |
33398 |
+ } |
33399 |
+ |
33400 |
+@@ -200,6 +203,8 @@ SYSCALL_DEFINE2(settimeofday, struct tim |
33401 |
+ return -EFAULT; |
33402 |
+ } |
33403 |
+ |
33404 |
++ gr_log_timechange(); |
33405 |
++ |
33406 |
+ return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL); |
33407 |
+ } |
33408 |
+ |
33409 |
+@@ -238,7 +243,7 @@ EXPORT_SYMBOL(current_fs_time); |
33410 |
+ * Avoid unnecessary multiplications/divisions in the |
33411 |
+ * two most common HZ cases: |
33412 |
+ */ |
33413 |
+-unsigned int inline jiffies_to_msecs(const unsigned long j) |
33414 |
++inline unsigned int jiffies_to_msecs(const unsigned long j) |
33415 |
+ { |
33416 |
+ #if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) |
33417 |
+ return (MSEC_PER_SEC / HZ) * j; |
33418 |
+@@ -254,7 +259,7 @@ unsigned int inline jiffies_to_msecs(con |
33419 |
+ } |
33420 |
+ EXPORT_SYMBOL(jiffies_to_msecs); |
33421 |
+ |
33422 |
+-unsigned int inline jiffies_to_usecs(const unsigned long j) |
33423 |
++inline unsigned int jiffies_to_usecs(const unsigned long j) |
33424 |
+ { |
33425 |
+ #if HZ <= USEC_PER_SEC && !(USEC_PER_SEC % HZ) |
33426 |
+ return (USEC_PER_SEC / HZ) * j; |
33427 |
+diff -urNp linux-2.6.28.8/kernel/utsname_sysctl.c linux-2.6.28.8/kernel/utsname_sysctl.c |
33428 |
+--- linux-2.6.28.8/kernel/utsname_sysctl.c 2009-02-06 16:47:45.000000000 -0500 |
33429 |
++++ linux-2.6.28.8/kernel/utsname_sysctl.c 2009-02-21 09:37:50.000000000 -0500 |
33430 |
+@@ -123,7 +123,7 @@ static struct ctl_table uts_kern_table[] |
33431 |
+ .proc_handler = proc_do_uts_string, |
33432 |
+ .strategy = sysctl_uts_string, |
33433 |
+ }, |
33434 |
+- {} |
33435 |
++ { 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } |
33436 |
+ }; |
33437 |
+ |
33438 |
+ static struct ctl_table uts_root_table[] = { |
33439 |
+@@ -133,7 +133,7 @@ static struct ctl_table uts_root_table[] |
33440 |
+ .mode = 0555, |
33441 |
+ .child = uts_kern_table, |
33442 |
+ }, |
33443 |
+- {} |
33444 |
++ { 0, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL, NULL, NULL } |
33445 |
+ }; |
33446 |
+ |
33447 |
+ static int __init utsname_sysctl_init(void) |
33448 |
+diff -urNp linux-2.6.28.8/lib/radix-tree.c linux-2.6.28.8/lib/radix-tree.c |
33449 |
+--- linux-2.6.28.8/lib/radix-tree.c 2009-02-06 16:47:45.000000000 -0500 |
33450 |
++++ linux-2.6.28.8/lib/radix-tree.c 2009-02-21 09:37:50.000000000 -0500 |
33451 |
+@@ -81,7 +81,7 @@ struct radix_tree_preload { |
33452 |
+ int nr; |
33453 |
+ struct radix_tree_node *nodes[RADIX_TREE_MAX_PATH]; |
33454 |
+ }; |
33455 |
+-DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, }; |
33456 |
++DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads); |
33457 |
+ |
33458 |
+ static inline gfp_t root_gfp_mask(struct radix_tree_root *root) |
33459 |
+ { |
33460 |
+diff -urNp linux-2.6.28.8/localversion-grsec linux-2.6.28.8/localversion-grsec |
33461 |
+--- linux-2.6.28.8/localversion-grsec 1969-12-31 19:00:00.000000000 -0500 |
33462 |
++++ linux-2.6.28.8/localversion-grsec 2009-02-21 09:37:50.000000000 -0500 |
33463 |
+@@ -0,0 +1 @@ |
33464 |
++-grsec |
33465 |
+diff -urNp linux-2.6.28.8/Makefile linux-2.6.28.8/Makefile |
33466 |
+--- linux-2.6.28.8/Makefile 2009-03-07 10:24:49.000000000 -0500 |
33467 |
++++ linux-2.6.28.8/Makefile 2009-03-07 10:29:51.000000000 -0500 |
33468 |
+@@ -221,7 +221,7 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" |
33469 |
+ |
33470 |
+ HOSTCC = gcc |
33471 |
+ HOSTCXX = g++ |
33472 |
+-HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer |
33473 |
++HOSTCFLAGS = -Wall -W -Wno-unused -Wno-sign-compare -Wstrict-prototypes -O2 -fomit-frame-pointer |
33474 |
+ HOSTCXXFLAGS = -O2 |
33475 |
+ |
33476 |
+ # Decide whether to build built-in, modular, or both. |
33477 |
+@@ -619,7 +619,7 @@ export mod_strip_cmd |
33478 |
+ |
33479 |
+ |
33480 |
+ ifeq ($(KBUILD_EXTMOD),) |
33481 |
+-core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ |
33482 |
++core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/ |
33483 |
+ |
33484 |
+ vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ |
33485 |
+ $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ |
33486 |
+diff -urNp linux-2.6.28.8/mm/filemap.c linux-2.6.28.8/mm/filemap.c |
33487 |
+--- linux-2.6.28.8/mm/filemap.c 2009-02-06 16:47:45.000000000 -0500 |
33488 |
++++ linux-2.6.28.8/mm/filemap.c 2009-02-21 09:37:50.000000000 -0500 |
33489 |
+@@ -1609,7 +1609,7 @@ int generic_file_mmap(struct file * file |
33490 |
+ struct address_space *mapping = file->f_mapping; |
33491 |
+ |
33492 |
+ if (!mapping->a_ops->readpage) |
33493 |
+- return -ENOEXEC; |
33494 |
++ return -ENODEV; |
33495 |
+ file_accessed(file); |
33496 |
+ vma->vm_ops = &generic_file_vm_ops; |
33497 |
+ vma->vm_flags |= VM_CAN_NONLINEAR; |
33498 |
+@@ -1970,6 +1970,7 @@ inline int generic_write_checks(struct f |
33499 |
+ *pos = i_size_read(inode); |
33500 |
+ |
33501 |
+ if (limit != RLIM_INFINITY) { |
33502 |
++ gr_learn_resource(current, RLIMIT_FSIZE,*pos, 0); |
33503 |
+ if (*pos >= limit) { |
33504 |
+ send_sig(SIGXFSZ, current, 0); |
33505 |
+ return -EFBIG; |
33506 |
+diff -urNp linux-2.6.28.8/mm/fremap.c linux-2.6.28.8/mm/fremap.c |
33507 |
+--- linux-2.6.28.8/mm/fremap.c 2009-02-06 16:47:45.000000000 -0500 |
33508 |
++++ linux-2.6.28.8/mm/fremap.c 2009-02-21 09:37:50.000000000 -0500 |
33509 |
+@@ -153,6 +153,13 @@ SYSCALL_DEFINE5(remap_file_pages, unsign |
33510 |
+ retry: |
33511 |
+ vma = find_vma(mm, start); |
33512 |
+ |
33513 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33514 |
++ if (vma && (mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_flags & VM_MAYEXEC)) { |
33515 |
++ up_read(&mm->mmap_sem); |
33516 |
++ return err; |
33517 |
++ } |
33518 |
++#endif |
33519 |
++ |
33520 |
+ /* |
33521 |
+ * Make sure the vma is shared, that it supports prefaulting, |
33522 |
+ * and that the remapped range is valid and fully within |
33523 |
+diff -urNp linux-2.6.28.8/mm/hugetlb.c linux-2.6.28.8/mm/hugetlb.c |
33524 |
+--- linux-2.6.28.8/mm/hugetlb.c 2009-02-06 16:47:45.000000000 -0500 |
33525 |
++++ linux-2.6.28.8/mm/hugetlb.c 2009-02-21 09:37:50.000000000 -0500 |
33526 |
+@@ -1832,6 +1832,26 @@ static int unmap_ref_private(struct mm_s |
33527 |
+ return 1; |
33528 |
+ } |
33529 |
+ |
33530 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33531 |
++static void pax_mirror_huge_pte(struct vm_area_struct *vma, unsigned long address, struct page *page_m) |
33532 |
++{ |
33533 |
++ struct mm_struct *mm = vma->vm_mm; |
33534 |
++ struct vm_area_struct *vma_m; |
33535 |
++ unsigned long address_m; |
33536 |
++ pte_t *ptep_m; |
33537 |
++ |
33538 |
++ vma_m = pax_find_mirror_vma(vma); |
33539 |
++ if (!vma_m) |
33540 |
++ return; |
33541 |
++ |
33542 |
++ BUG_ON(address >= SEGMEXEC_TASK_SIZE); |
33543 |
++ address_m = address + SEGMEXEC_TASK_SIZE; |
33544 |
++ ptep_m = huge_pte_offset(mm, address_m & HPAGE_MASK); |
33545 |
++ get_page(page_m); |
33546 |
++ set_huge_pte_at(mm, address_m, ptep_m, make_huge_pte(vma_m, page_m, 0)); |
33547 |
++} |
33548 |
++#endif |
33549 |
++ |
33550 |
+ static int hugetlb_cow(struct mm_struct *mm, struct vm_area_struct *vma, |
33551 |
+ unsigned long address, pte_t *ptep, pte_t pte, |
33552 |
+ struct page *pagecache_page) |
33553 |
+@@ -1903,6 +1923,11 @@ retry_avoidcopy: |
33554 |
+ huge_ptep_clear_flush(vma, address, ptep); |
33555 |
+ set_huge_pte_at(mm, address, ptep, |
33556 |
+ make_huge_pte(vma, new_page, 1)); |
33557 |
++ |
33558 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33559 |
++ pax_mirror_huge_pte(vma, address, new_page); |
33560 |
++#endif |
33561 |
++ |
33562 |
+ /* Make the old page be freed below */ |
33563 |
+ new_page = old_page; |
33564 |
+ } |
33565 |
+@@ -2012,6 +2037,10 @@ retry: |
33566 |
+ && (vma->vm_flags & VM_SHARED))); |
33567 |
+ set_huge_pte_at(mm, address, ptep, new_pte); |
33568 |
+ |
33569 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33570 |
++ pax_mirror_huge_pte(vma, address, page); |
33571 |
++#endif |
33572 |
++ |
33573 |
+ if (write_access && !(vma->vm_flags & VM_SHARED)) { |
33574 |
+ /* Optimization, do the COW without a second fault */ |
33575 |
+ ret = hugetlb_cow(mm, vma, address, ptep, new_pte, page); |
33576 |
+@@ -2040,6 +2069,28 @@ int hugetlb_fault(struct mm_struct *mm, |
33577 |
+ static DEFINE_MUTEX(hugetlb_instantiation_mutex); |
33578 |
+ struct hstate *h = hstate_vma(vma); |
33579 |
+ |
33580 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33581 |
++ struct vm_area_struct *vma_m; |
33582 |
++ |
33583 |
++ vma_m = pax_find_mirror_vma(vma); |
33584 |
++ if (vma_m) { |
33585 |
++ unsigned long address_m; |
33586 |
++ |
33587 |
++ if (vma->vm_start > vma_m->vm_start) { |
33588 |
++ address_m = address; |
33589 |
++ address -= SEGMEXEC_TASK_SIZE; |
33590 |
++ vma = vma_m; |
33591 |
++ h = hstate_vma(vma); |
33592 |
++ } else |
33593 |
++ address_m = address + SEGMEXEC_TASK_SIZE; |
33594 |
++ |
33595 |
++ if (!huge_pte_alloc(mm, address_m, huge_page_size(h))) |
33596 |
++ return VM_FAULT_OOM; |
33597 |
++ address_m &= HPAGE_MASK; |
33598 |
++ unmap_hugepage_range(vma, address_m, address_m + HPAGE_SIZE, NULL); |
33599 |
++ } |
33600 |
++#endif |
33601 |
++ |
33602 |
+ ptep = huge_pte_alloc(mm, address, huge_page_size(h)); |
33603 |
+ if (!ptep) |
33604 |
+ return VM_FAULT_OOM; |
33605 |
+diff -urNp linux-2.6.28.8/mm/madvise.c linux-2.6.28.8/mm/madvise.c |
33606 |
+--- linux-2.6.28.8/mm/madvise.c 2009-02-06 16:47:45.000000000 -0500 |
33607 |
++++ linux-2.6.28.8/mm/madvise.c 2009-02-21 09:37:50.000000000 -0500 |
33608 |
+@@ -43,6 +43,10 @@ static long madvise_behavior(struct vm_a |
33609 |
+ pgoff_t pgoff; |
33610 |
+ int new_flags = vma->vm_flags; |
33611 |
+ |
33612 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33613 |
++ struct vm_area_struct *vma_m; |
33614 |
++#endif |
33615 |
++ |
33616 |
+ switch (behavior) { |
33617 |
+ case MADV_NORMAL: |
33618 |
+ new_flags = new_flags & ~VM_RAND_READ & ~VM_SEQ_READ; |
33619 |
+@@ -92,6 +96,13 @@ success: |
33620 |
+ /* |
33621 |
+ * vm_flags is protected by the mmap_sem held in write mode. |
33622 |
+ */ |
33623 |
++ |
33624 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33625 |
++ vma_m = pax_find_mirror_vma(vma); |
33626 |
++ if (vma_m) |
33627 |
++ vma_m->vm_flags = new_flags & ~(VM_WRITE | VM_MAYWRITE | VM_ACCOUNT); |
33628 |
++#endif |
33629 |
++ |
33630 |
+ vma->vm_flags = new_flags; |
33631 |
+ |
33632 |
+ out: |
33633 |
+@@ -236,6 +247,17 @@ madvise_vma(struct vm_area_struct *vma, |
33634 |
+ |
33635 |
+ case MADV_DONTNEED: |
33636 |
+ error = madvise_dontneed(vma, prev, start, end); |
33637 |
++ |
33638 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33639 |
++ if (!error) { |
33640 |
++ struct vm_area_struct *vma_m, *prev_m; |
33641 |
++ |
33642 |
++ vma_m = pax_find_mirror_vma(vma); |
33643 |
++ if (vma_m) |
33644 |
++ error = madvise_dontneed(vma_m, &prev_m, start + SEGMEXEC_TASK_SIZE, end + SEGMEXEC_TASK_SIZE); |
33645 |
++ } |
33646 |
++#endif |
33647 |
++ |
33648 |
+ break; |
33649 |
+ |
33650 |
+ default: |
33651 |
+@@ -308,6 +330,16 @@ SYSCALL_DEFINE3(madvise, unsigned long, |
33652 |
+ if (end < start) |
33653 |
+ goto out; |
33654 |
+ |
33655 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33656 |
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) { |
33657 |
++ if (end > SEGMEXEC_TASK_SIZE) |
33658 |
++ goto out; |
33659 |
++ } else |
33660 |
++#endif |
33661 |
++ |
33662 |
++ if (end > TASK_SIZE) |
33663 |
++ goto out; |
33664 |
++ |
33665 |
+ error = 0; |
33666 |
+ if (end == start) |
33667 |
+ goto out; |
33668 |
+diff -urNp linux-2.6.28.8/mm/memory.c linux-2.6.28.8/mm/memory.c |
33669 |
+--- linux-2.6.28.8/mm/memory.c 2009-02-07 16:10:45.000000000 -0500 |
33670 |
++++ linux-2.6.28.8/mm/memory.c 2009-02-21 09:37:50.000000000 -0500 |
33671 |
+@@ -47,6 +47,7 @@ |
33672 |
+ #include <linux/pagemap.h> |
33673 |
+ #include <linux/rmap.h> |
33674 |
+ #include <linux/module.h> |
33675 |
++#include <linux/security.h> |
33676 |
+ #include <linux/delayacct.h> |
33677 |
+ #include <linux/init.h> |
33678 |
+ #include <linux/writeback.h> |
33679 |
+@@ -1151,11 +1152,11 @@ int __get_user_pages(struct task_struct |
33680 |
+ vm_flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE); |
33681 |
+ i = 0; |
33682 |
+ |
33683 |
+- do { |
33684 |
++ while (len) { |
33685 |
+ struct vm_area_struct *vma; |
33686 |
+ unsigned int foll_flags; |
33687 |
+ |
33688 |
+- vma = find_extend_vma(mm, start); |
33689 |
++ vma = find_vma(mm, start); |
33690 |
+ if (!vma && in_gate_area(tsk, start)) { |
33691 |
+ unsigned long pg = start & PAGE_MASK; |
33692 |
+ struct vm_area_struct *gate_vma = get_gate_vma(tsk); |
33693 |
+@@ -1197,7 +1198,7 @@ int __get_user_pages(struct task_struct |
33694 |
+ continue; |
33695 |
+ } |
33696 |
+ |
33697 |
+- if (!vma || |
33698 |
++ if (!vma || start < vma->vm_start || |
33699 |
+ (vma->vm_flags & (VM_IO | VM_PFNMAP)) || |
33700 |
+ (!ignore && !(vm_flags & vma->vm_flags))) |
33701 |
+ return i ? : -EFAULT; |
33702 |
+@@ -1271,7 +1272,7 @@ int __get_user_pages(struct task_struct |
33703 |
+ start += PAGE_SIZE; |
33704 |
+ len--; |
33705 |
+ } while (len && start < vma->vm_end); |
33706 |
+- } while (len); |
33707 |
++ } |
33708 |
+ return i; |
33709 |
+ } |
33710 |
+ |
33711 |
+@@ -1760,6 +1761,186 @@ static inline void cow_user_page(struct |
33712 |
+ copy_user_highpage(dst, src, va, vma); |
33713 |
+ } |
33714 |
+ |
33715 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33716 |
++static void pax_unmap_mirror_pte(struct vm_area_struct *vma, unsigned long address, pmd_t *pmd) |
33717 |
++{ |
33718 |
++ struct mm_struct *mm = vma->vm_mm; |
33719 |
++ spinlock_t *ptl; |
33720 |
++ pte_t *pte, entry; |
33721 |
++ |
33722 |
++ pte = pte_offset_map_lock(mm, pmd, address, &ptl); |
33723 |
++ entry = *pte; |
33724 |
++ if (!pte_present(entry)) { |
33725 |
++ if (!pte_none(entry)) { |
33726 |
++ BUG_ON(pte_file(entry)); |
33727 |
++ free_swap_and_cache(pte_to_swp_entry(entry)); |
33728 |
++ pte_clear_not_present_full(mm, address, pte, 0); |
33729 |
++ } |
33730 |
++ } else { |
33731 |
++ struct page *page; |
33732 |
++ |
33733 |
++ flush_cache_page(vma, address, pte_pfn(entry)); |
33734 |
++ entry = ptep_clear_flush(vma, address, pte); |
33735 |
++ BUG_ON(pte_dirty(entry)); |
33736 |
++ page = vm_normal_page(vma, address, entry); |
33737 |
++ if (page) { |
33738 |
++ update_hiwater_rss(mm); |
33739 |
++ if (PageAnon(page)) |
33740 |
++ dec_mm_counter(mm, anon_rss); |
33741 |
++ else |
33742 |
++ dec_mm_counter(mm, file_rss); |
33743 |
++ page_remove_rmap(page, vma); |
33744 |
++ page_cache_release(page); |
33745 |
++ } |
33746 |
++ } |
33747 |
++ pte_unmap_unlock(pte, ptl); |
33748 |
++} |
33749 |
++ |
33750 |
++/* PaX: if vma is mirrored, synchronize the mirror's PTE |
33751 |
++ * |
33752 |
++ * the ptl of the lower mapped page is held on entry and is not released on exit |
33753 |
++ * or inside to ensure atomic changes to the PTE states (swapout, mremap, munmap, etc) |
33754 |
++ */ |
33755 |
++static void pax_mirror_anon_pte(struct vm_area_struct *vma, unsigned long address, struct page *page_m, spinlock_t *ptl) |
33756 |
++{ |
33757 |
++ struct mm_struct *mm = vma->vm_mm; |
33758 |
++ unsigned long address_m; |
33759 |
++ spinlock_t *ptl_m; |
33760 |
++ struct vm_area_struct *vma_m; |
33761 |
++ pmd_t *pmd_m; |
33762 |
++ pte_t *pte_m, entry_m; |
33763 |
++ |
33764 |
++ BUG_ON(!page_m || !PageAnon(page_m)); |
33765 |
++ |
33766 |
++ vma_m = pax_find_mirror_vma(vma); |
33767 |
++ if (!vma_m) |
33768 |
++ return; |
33769 |
++ |
33770 |
++ BUG_ON(!PageLocked(page_m)); |
33771 |
++ BUG_ON(address >= SEGMEXEC_TASK_SIZE); |
33772 |
++ address_m = address + SEGMEXEC_TASK_SIZE; |
33773 |
++ pmd_m = pmd_offset(pud_offset(pgd_offset(mm, address_m), address_m), address_m); |
33774 |
++ pte_m = pte_offset_map_nested(pmd_m, address_m); |
33775 |
++ ptl_m = pte_lockptr(mm, pmd_m); |
33776 |
++ if (ptl != ptl_m) { |
33777 |
++ spin_lock_nested(ptl_m, SINGLE_DEPTH_NESTING); |
33778 |
++ if (!pte_none(*pte_m)) |
33779 |
++ goto out; |
33780 |
++ } |
33781 |
++ |
33782 |
++ entry_m = pfn_pte(page_to_pfn(page_m), vma_m->vm_page_prot); |
33783 |
++ page_cache_get(page_m); |
33784 |
++ page_add_anon_rmap(page_m, vma_m, address_m); |
33785 |
++ inc_mm_counter(mm, anon_rss); |
33786 |
++ set_pte_at(mm, address_m, pte_m, entry_m); |
33787 |
++ update_mmu_cache(vma_m, address_m, entry_m); |
33788 |
++out: |
33789 |
++ if (ptl != ptl_m) |
33790 |
++ spin_unlock(ptl_m); |
33791 |
++ pte_unmap_nested(pte_m); |
33792 |
++ unlock_page(page_m); |
33793 |
++} |
33794 |
++ |
33795 |
++void pax_mirror_file_pte(struct vm_area_struct *vma, unsigned long address, struct page *page_m, spinlock_t *ptl) |
33796 |
++{ |
33797 |
++ struct mm_struct *mm = vma->vm_mm; |
33798 |
++ unsigned long address_m; |
33799 |
++ spinlock_t *ptl_m; |
33800 |
++ struct vm_area_struct *vma_m; |
33801 |
++ pmd_t *pmd_m; |
33802 |
++ pte_t *pte_m, entry_m; |
33803 |
++ |
33804 |
++ BUG_ON(!page_m || PageAnon(page_m)); |
33805 |
++ |
33806 |
++ vma_m = pax_find_mirror_vma(vma); |
33807 |
++ if (!vma_m) |
33808 |
++ return; |
33809 |
++ |
33810 |
++ BUG_ON(address >= SEGMEXEC_TASK_SIZE); |
33811 |
++ address_m = address + SEGMEXEC_TASK_SIZE; |
33812 |
++ pmd_m = pmd_offset(pud_offset(pgd_offset(mm, address_m), address_m), address_m); |
33813 |
++ pte_m = pte_offset_map_nested(pmd_m, address_m); |
33814 |
++ ptl_m = pte_lockptr(mm, pmd_m); |
33815 |
++ if (ptl != ptl_m) { |
33816 |
++ spin_lock_nested(ptl_m, SINGLE_DEPTH_NESTING); |
33817 |
++ if (!pte_none(*pte_m)) |
33818 |
++ goto out; |
33819 |
++ } |
33820 |
++ |
33821 |
++ entry_m = pfn_pte(page_to_pfn(page_m), vma_m->vm_page_prot); |
33822 |
++ page_cache_get(page_m); |
33823 |
++ page_add_file_rmap(page_m); |
33824 |
++ inc_mm_counter(mm, file_rss); |
33825 |
++ set_pte_at(mm, address_m, pte_m, entry_m); |
33826 |
++ update_mmu_cache(vma_m, address_m, entry_m); |
33827 |
++out: |
33828 |
++ if (ptl != ptl_m) |
33829 |
++ spin_unlock(ptl_m); |
33830 |
++ pte_unmap_nested(pte_m); |
33831 |
++} |
33832 |
++ |
33833 |
++static void pax_mirror_pfn_pte(struct vm_area_struct *vma, unsigned long address, unsigned long pfn_m, spinlock_t *ptl) |
33834 |
++{ |
33835 |
++ struct mm_struct *mm = vma->vm_mm; |
33836 |
++ unsigned long address_m; |
33837 |
++ spinlock_t *ptl_m; |
33838 |
++ struct vm_area_struct *vma_m; |
33839 |
++ pmd_t *pmd_m; |
33840 |
++ pte_t *pte_m, entry_m; |
33841 |
++ |
33842 |
++ vma_m = pax_find_mirror_vma(vma); |
33843 |
++ if (!vma_m) |
33844 |
++ return; |
33845 |
++ |
33846 |
++ BUG_ON(address >= SEGMEXEC_TASK_SIZE); |
33847 |
++ address_m = address + SEGMEXEC_TASK_SIZE; |
33848 |
++ pmd_m = pmd_offset(pud_offset(pgd_offset(mm, address_m), address_m), address_m); |
33849 |
++ pte_m = pte_offset_map_nested(pmd_m, address_m); |
33850 |
++ ptl_m = pte_lockptr(mm, pmd_m); |
33851 |
++ if (ptl != ptl_m) { |
33852 |
++ spin_lock_nested(ptl_m, SINGLE_DEPTH_NESTING); |
33853 |
++ if (!pte_none(*pte_m)) |
33854 |
++ goto out; |
33855 |
++ } |
33856 |
++ |
33857 |
++ entry_m = pfn_pte(pfn_m, vma_m->vm_page_prot); |
33858 |
++ set_pte_at(mm, address_m, pte_m, entry_m); |
33859 |
++out: |
33860 |
++ if (ptl != ptl_m) |
33861 |
++ spin_unlock(ptl_m); |
33862 |
++ pte_unmap_nested(pte_m); |
33863 |
++} |
33864 |
++ |
33865 |
++static void pax_mirror_pte(struct vm_area_struct *vma, unsigned long address, pte_t *pte, pmd_t *pmd, spinlock_t *ptl) |
33866 |
++{ |
33867 |
++ struct page *page_m; |
33868 |
++ pte_t entry; |
33869 |
++ |
33870 |
++ if (!(vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC)) |
33871 |
++ goto out; |
33872 |
++ |
33873 |
++ entry = *pte; |
33874 |
++ page_m = vm_normal_page(vma, address, entry); |
33875 |
++ if (!page_m) |
33876 |
++ pax_mirror_pfn_pte(vma, address, pte_pfn(entry), ptl); |
33877 |
++ else if (PageAnon(page_m)) { |
33878 |
++ if (pax_find_mirror_vma(vma)) { |
33879 |
++ pte_unmap_unlock(pte, ptl); |
33880 |
++ lock_page(page_m); |
33881 |
++ pte = pte_offset_map_lock(vma->vm_mm, pmd, address, &ptl); |
33882 |
++ if (pte_same(entry, *pte)) |
33883 |
++ pax_mirror_anon_pte(vma, address, page_m, ptl); |
33884 |
++ else |
33885 |
++ unlock_page(page_m); |
33886 |
++ } |
33887 |
++ } else |
33888 |
++ pax_mirror_file_pte(vma, address, page_m, ptl); |
33889 |
++ |
33890 |
++out: |
33891 |
++ pte_unmap_unlock(pte, ptl); |
33892 |
++} |
33893 |
++#endif |
33894 |
++ |
33895 |
+ /* |
33896 |
+ * This routine handles present pages, when users try to write |
33897 |
+ * to a shared page. It is done by copying the page to a new address |
33898 |
+@@ -1897,6 +2078,12 @@ gotten: |
33899 |
+ */ |
33900 |
+ page_table = pte_offset_map_lock(mm, pmd, address, &ptl); |
33901 |
+ if (likely(pte_same(*page_table, orig_pte))) { |
33902 |
++ |
33903 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33904 |
++ if (pax_find_mirror_vma(vma)) |
33905 |
++ BUG_ON(!trylock_page(new_page)); |
33906 |
++#endif |
33907 |
++ |
33908 |
+ if (old_page) { |
33909 |
+ if (!PageAnon(old_page)) { |
33910 |
+ dec_mm_counter(mm, file_rss); |
33911 |
+@@ -1947,6 +2134,10 @@ gotten: |
33912 |
+ page_remove_rmap(old_page, vma); |
33913 |
+ } |
33914 |
+ |
33915 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33916 |
++ pax_mirror_anon_pte(vma, address, new_page, ptl); |
33917 |
++#endif |
33918 |
++ |
33919 |
+ /* Free the old page.. */ |
33920 |
+ new_page = old_page; |
33921 |
+ ret |= VM_FAULT_WRITE; |
33922 |
+@@ -2206,6 +2397,7 @@ int vmtruncate(struct inode * inode, lof |
33923 |
+ unsigned long limit; |
33924 |
+ |
33925 |
+ limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur; |
33926 |
++ gr_learn_resource(current, RLIMIT_FSIZE, offset, 1); |
33927 |
+ if (limit != RLIM_INFINITY && offset > limit) |
33928 |
+ goto out_sig; |
33929 |
+ if (offset > inode->i_sb->s_maxbytes) |
33930 |
+@@ -2357,6 +2549,11 @@ static int do_swap_page(struct mm_struct |
33931 |
+ swap_free(entry); |
33932 |
+ if (vm_swap_full() || (vma->vm_flags & VM_LOCKED) || PageMlocked(page)) |
33933 |
+ remove_exclusive_swap_page(page); |
33934 |
++ |
33935 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33936 |
++ if (write_access || !pax_find_mirror_vma(vma)) |
33937 |
++#endif |
33938 |
++ |
33939 |
+ unlock_page(page); |
33940 |
+ |
33941 |
+ if (write_access) { |
33942 |
+@@ -2368,6 +2565,11 @@ static int do_swap_page(struct mm_struct |
33943 |
+ |
33944 |
+ /* No need to invalidate - it was non-present before */ |
33945 |
+ update_mmu_cache(vma, address, pte); |
33946 |
++ |
33947 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33948 |
++ pax_mirror_anon_pte(vma, address, page, ptl); |
33949 |
++#endif |
33950 |
++ |
33951 |
+ unlock: |
33952 |
+ pte_unmap_unlock(page_table, ptl); |
33953 |
+ out: |
33954 |
+@@ -2412,6 +2614,12 @@ static int do_anonymous_page(struct mm_s |
33955 |
+ page_table = pte_offset_map_lock(mm, pmd, address, &ptl); |
33956 |
+ if (!pte_none(*page_table)) |
33957 |
+ goto release; |
33958 |
++ |
33959 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33960 |
++ if (pax_find_mirror_vma(vma)) |
33961 |
++ BUG_ON(!trylock_page(page)); |
33962 |
++#endif |
33963 |
++ |
33964 |
+ inc_mm_counter(mm, anon_rss); |
33965 |
+ SetPageSwapBacked(page); |
33966 |
+ lru_cache_add_active_or_unevictable(page, vma); |
33967 |
+@@ -2420,6 +2628,11 @@ static int do_anonymous_page(struct mm_s |
33968 |
+ |
33969 |
+ /* No need to invalidate - it was non-present before */ |
33970 |
+ update_mmu_cache(vma, address, entry); |
33971 |
++ |
33972 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33973 |
++ pax_mirror_anon_pte(vma, address, page, ptl); |
33974 |
++#endif |
33975 |
++ |
33976 |
+ unlock: |
33977 |
+ pte_unmap_unlock(page_table, ptl); |
33978 |
+ return 0; |
33979 |
+@@ -2556,6 +2769,12 @@ static int __do_fault(struct mm_struct * |
33980 |
+ */ |
33981 |
+ /* Only go through if we didn't race with anybody else... */ |
33982 |
+ if (likely(pte_same(*page_table, orig_pte))) { |
33983 |
++ |
33984 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33985 |
++ if (anon && pax_find_mirror_vma(vma)) |
33986 |
++ BUG_ON(!trylock_page(page)); |
33987 |
++#endif |
33988 |
++ |
33989 |
+ flush_icache_page(vma, page); |
33990 |
+ entry = mk_pte(page, vma->vm_page_prot); |
33991 |
+ if (flags & FAULT_FLAG_WRITE) |
33992 |
+@@ -2578,6 +2797,14 @@ static int __do_fault(struct mm_struct * |
33993 |
+ |
33994 |
+ /* no need to invalidate: a not-present page won't be cached */ |
33995 |
+ update_mmu_cache(vma, address, entry); |
33996 |
++ |
33997 |
++#ifdef CONFIG_PAX_SEGMEXEC |
33998 |
++ if (anon) |
33999 |
++ pax_mirror_anon_pte(vma, address, page, ptl); |
34000 |
++ else |
34001 |
++ pax_mirror_file_pte(vma, address, page, ptl); |
34002 |
++#endif |
34003 |
++ |
34004 |
+ } else { |
34005 |
+ if (charged) |
34006 |
+ mem_cgroup_uncharge_page(page); |
34007 |
+@@ -2711,6 +2938,12 @@ static inline int handle_pte_fault(struc |
34008 |
+ if (write_access) |
34009 |
+ flush_tlb_page(vma, address); |
34010 |
+ } |
34011 |
++ |
34012 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34013 |
++ pax_mirror_pte(vma, address, pte, pmd, ptl); |
34014 |
++ return 0; |
34015 |
++#endif |
34016 |
++ |
34017 |
+ unlock: |
34018 |
+ pte_unmap_unlock(pte, ptl); |
34019 |
+ return 0; |
34020 |
+@@ -2727,6 +2960,10 @@ int handle_mm_fault(struct mm_struct *mm |
34021 |
+ pmd_t *pmd; |
34022 |
+ pte_t *pte; |
34023 |
+ |
34024 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34025 |
++ struct vm_area_struct *vma_m; |
34026 |
++#endif |
34027 |
++ |
34028 |
+ __set_current_state(TASK_RUNNING); |
34029 |
+ |
34030 |
+ count_vm_event(PGFAULT); |
34031 |
+@@ -2734,6 +2971,34 @@ int handle_mm_fault(struct mm_struct *mm |
34032 |
+ if (unlikely(is_vm_hugetlb_page(vma))) |
34033 |
+ return hugetlb_fault(mm, vma, address, write_access); |
34034 |
+ |
34035 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34036 |
++ vma_m = pax_find_mirror_vma(vma); |
34037 |
++ if (vma_m) { |
34038 |
++ unsigned long address_m; |
34039 |
++ pgd_t *pgd_m; |
34040 |
++ pud_t *pud_m; |
34041 |
++ pmd_t *pmd_m; |
34042 |
++ |
34043 |
++ if (vma->vm_start > vma_m->vm_start) { |
34044 |
++ address_m = address; |
34045 |
++ address -= SEGMEXEC_TASK_SIZE; |
34046 |
++ vma = vma_m; |
34047 |
++ } else |
34048 |
++ address_m = address + SEGMEXEC_TASK_SIZE; |
34049 |
++ |
34050 |
++ pgd_m = pgd_offset(mm, address_m); |
34051 |
++ pud_m = pud_alloc(mm, pgd_m, address_m); |
34052 |
++ if (!pud_m) |
34053 |
++ return VM_FAULT_OOM; |
34054 |
++ pmd_m = pmd_alloc(mm, pud_m, address_m); |
34055 |
++ if (!pmd_m) |
34056 |
++ return VM_FAULT_OOM; |
34057 |
++ if (!pmd_present(*pmd_m) && __pte_alloc(mm, pmd_m, address_m)) |
34058 |
++ return VM_FAULT_OOM; |
34059 |
++ pax_unmap_mirror_pte(vma_m, address_m, pmd_m); |
34060 |
++ } |
34061 |
++#endif |
34062 |
++ |
34063 |
+ pgd = pgd_offset(mm, address); |
34064 |
+ pud = pud_alloc(mm, pgd, address); |
34065 |
+ if (!pud) |
34066 |
+@@ -2831,7 +3096,7 @@ static int __init gate_vma_init(void) |
34067 |
+ gate_vma.vm_start = FIXADDR_USER_START; |
34068 |
+ gate_vma.vm_end = FIXADDR_USER_END; |
34069 |
+ gate_vma.vm_flags = VM_READ | VM_MAYREAD | VM_EXEC | VM_MAYEXEC; |
34070 |
+- gate_vma.vm_page_prot = __P101; |
34071 |
++ gate_vma.vm_page_prot = vm_get_page_prot(gate_vma.vm_flags); |
34072 |
+ /* |
34073 |
+ * Make sure the vDSO gets into every core dump. |
34074 |
+ * Dumping its contents makes post-mortem fully interpretable later |
34075 |
+diff -urNp linux-2.6.28.8/mm/mempolicy.c linux-2.6.28.8/mm/mempolicy.c |
34076 |
+--- linux-2.6.28.8/mm/mempolicy.c 2009-02-06 16:47:45.000000000 -0500 |
34077 |
++++ linux-2.6.28.8/mm/mempolicy.c 2009-02-21 09:37:50.000000000 -0500 |
34078 |
+@@ -551,6 +551,10 @@ static int mbind_range(struct vm_area_st |
34079 |
+ struct vm_area_struct *next; |
34080 |
+ int err; |
34081 |
+ |
34082 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34083 |
++ struct vm_area_struct *vma_m; |
34084 |
++#endif |
34085 |
++ |
34086 |
+ err = 0; |
34087 |
+ for (; vma && vma->vm_start < end; vma = next) { |
34088 |
+ next = vma->vm_next; |
34089 |
+@@ -562,6 +566,16 @@ static int mbind_range(struct vm_area_st |
34090 |
+ err = policy_vma(vma, new); |
34091 |
+ if (err) |
34092 |
+ break; |
34093 |
++ |
34094 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34095 |
++ vma_m = pax_find_mirror_vma(vma); |
34096 |
++ if (vma_m) { |
34097 |
++ err = policy_vma(vma_m, new); |
34098 |
++ if (err) |
34099 |
++ break; |
34100 |
++ } |
34101 |
++#endif |
34102 |
++ |
34103 |
+ } |
34104 |
+ return err; |
34105 |
+ } |
34106 |
+@@ -954,6 +968,17 @@ static long do_mbind(unsigned long start |
34107 |
+ |
34108 |
+ if (end < start) |
34109 |
+ return -EINVAL; |
34110 |
++ |
34111 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34112 |
++ if (mm->pax_flags & MF_PAX_SEGMEXEC) { |
34113 |
++ if (end > SEGMEXEC_TASK_SIZE) |
34114 |
++ return -EINVAL; |
34115 |
++ } else |
34116 |
++#endif |
34117 |
++ |
34118 |
++ if (end > TASK_SIZE) |
34119 |
++ return -EINVAL; |
34120 |
++ |
34121 |
+ if (end == start) |
34122 |
+ return 0; |
34123 |
+ |
34124 |
+diff -urNp linux-2.6.28.8/mm/migrate.c linux-2.6.28.8/mm/migrate.c |
34125 |
+--- linux-2.6.28.8/mm/migrate.c 2009-02-06 16:47:45.000000000 -0500 |
34126 |
++++ linux-2.6.28.8/mm/migrate.c 2009-02-21 09:37:50.000000000 -0500 |
34127 |
+@@ -1139,7 +1139,7 @@ int migrate_vmas(struct mm_struct *mm, c |
34128 |
+ struct vm_area_struct *vma; |
34129 |
+ int err = 0; |
34130 |
+ |
34131 |
+- for(vma = mm->mmap; vma->vm_next && !err; vma = vma->vm_next) { |
34132 |
++ for(vma = mm->mmap; vma && !err; vma = vma->vm_next) { |
34133 |
+ if (vma->vm_ops && vma->vm_ops->migrate) { |
34134 |
+ err = vma->vm_ops->migrate(vma, to, from, flags); |
34135 |
+ if (err) |
34136 |
+diff -urNp linux-2.6.28.8/mm/mlock.c linux-2.6.28.8/mm/mlock.c |
34137 |
+--- linux-2.6.28.8/mm/mlock.c 2009-02-07 16:10:45.000000000 -0500 |
34138 |
++++ linux-2.6.28.8/mm/mlock.c 2009-02-21 09:37:50.000000000 -0500 |
34139 |
+@@ -13,6 +13,7 @@ |
34140 |
+ #include <linux/pagemap.h> |
34141 |
+ #include <linux/mempolicy.h> |
34142 |
+ #include <linux/syscalls.h> |
34143 |
++#include <linux/security.h> |
34144 |
+ #include <linux/sched.h> |
34145 |
+ #include <linux/module.h> |
34146 |
+ #include <linux/rmap.h> |
34147 |
+@@ -452,6 +453,17 @@ static int do_mlock(unsigned long start, |
34148 |
+ return -EINVAL; |
34149 |
+ if (end == start) |
34150 |
+ return 0; |
34151 |
++ |
34152 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34153 |
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) { |
34154 |
++ if (end > SEGMEXEC_TASK_SIZE) |
34155 |
++ return -EINVAL; |
34156 |
++ } else |
34157 |
++#endif |
34158 |
++ |
34159 |
++ if (end > TASK_SIZE) |
34160 |
++ return -EINVAL; |
34161 |
++ |
34162 |
+ vma = find_vma_prev(current->mm, start, &prev); |
34163 |
+ if (!vma || vma->vm_start > start) |
34164 |
+ return -ENOMEM; |
34165 |
+@@ -511,6 +523,7 @@ SYSCALL_DEFINE2(mlock, unsigned long, st |
34166 |
+ lock_limit >>= PAGE_SHIFT; |
34167 |
+ |
34168 |
+ /* check against resource limits */ |
34169 |
++ gr_learn_resource(current, RLIMIT_MEMLOCK, (current->mm->locked_vm << PAGE_SHIFT) + len, 1); |
34170 |
+ if ((locked <= lock_limit) || capable(CAP_IPC_LOCK)) |
34171 |
+ error = do_mlock(start, len, 1); |
34172 |
+ up_write(¤t->mm->mmap_sem); |
34173 |
+@@ -532,10 +545,10 @@ SYSCALL_DEFINE2(munlock, unsigned long, |
34174 |
+ static int do_mlockall(int flags) |
34175 |
+ { |
34176 |
+ struct vm_area_struct * vma, * prev = NULL; |
34177 |
+- unsigned int def_flags = 0; |
34178 |
++ unsigned int def_flags = current->mm->def_flags & ~VM_LOCKED; |
34179 |
+ |
34180 |
+ if (flags & MCL_FUTURE) |
34181 |
+- def_flags = VM_LOCKED; |
34182 |
++ def_flags |= VM_LOCKED; |
34183 |
+ current->mm->def_flags = def_flags; |
34184 |
+ if (flags == MCL_FUTURE) |
34185 |
+ goto out; |
34186 |
+@@ -543,6 +556,12 @@ static int do_mlockall(int flags) |
34187 |
+ for (vma = current->mm->mmap; vma ; vma = prev->vm_next) { |
34188 |
+ unsigned int newflags; |
34189 |
+ |
34190 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34191 |
++ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_start >= SEGMEXEC_TASK_SIZE)) |
34192 |
++ break; |
34193 |
++#endif |
34194 |
++ |
34195 |
++ BUG_ON(vma->vm_end > TASK_SIZE); |
34196 |
+ newflags = vma->vm_flags | VM_LOCKED; |
34197 |
+ if (!(flags & MCL_CURRENT)) |
34198 |
+ newflags &= ~VM_LOCKED; |
34199 |
+@@ -574,6 +593,7 @@ SYSCALL_DEFINE1(mlockall, int, flags) |
34200 |
+ lock_limit >>= PAGE_SHIFT; |
34201 |
+ |
34202 |
+ ret = -ENOMEM; |
34203 |
++ gr_learn_resource(current, RLIMIT_MEMLOCK, current->mm->total_vm, 1); |
34204 |
+ if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) || |
34205 |
+ capable(CAP_IPC_LOCK)) |
34206 |
+ ret = do_mlockall(flags); |
34207 |
+diff -urNp linux-2.6.28.8/mm/mmap.c linux-2.6.28.8/mm/mmap.c |
34208 |
+--- linux-2.6.28.8/mm/mmap.c 2009-02-08 00:54:27.000000000 -0500 |
34209 |
++++ linux-2.6.28.8/mm/mmap.c 2009-02-21 09:37:50.000000000 -0500 |
34210 |
+@@ -43,6 +43,16 @@ |
34211 |
+ #define arch_rebalance_pgtables(addr, len) (addr) |
34212 |
+ #endif |
34213 |
+ |
34214 |
++static inline void verify_mm_writelocked(struct mm_struct *mm) |
34215 |
++{ |
34216 |
++#if defined(CONFIG_DEBUG_VM) || defined(CONFIG_PAX) |
34217 |
++ if (unlikely(down_read_trylock(&mm->mmap_sem))) { |
34218 |
++ up_read(&mm->mmap_sem); |
34219 |
++ BUG(); |
34220 |
++ } |
34221 |
++#endif |
34222 |
++} |
34223 |
++ |
34224 |
+ static void unmap_region(struct mm_struct *mm, |
34225 |
+ struct vm_area_struct *vma, struct vm_area_struct *prev, |
34226 |
+ unsigned long start, unsigned long end); |
34227 |
+@@ -68,16 +78,25 @@ static void unmap_region(struct mm_struc |
34228 |
+ * x: (no) no x: (no) yes x: (no) yes x: (yes) yes |
34229 |
+ * |
34230 |
+ */ |
34231 |
+-pgprot_t protection_map[16] = { |
34232 |
++pgprot_t protection_map[16] __read_only = { |
34233 |
+ __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111, |
34234 |
+ __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111 |
34235 |
+ }; |
34236 |
+ |
34237 |
+ pgprot_t vm_get_page_prot(unsigned long vm_flags) |
34238 |
+ { |
34239 |
+- return __pgprot(pgprot_val(protection_map[vm_flags & |
34240 |
++ pgprot_t prot = __pgprot(pgprot_val(protection_map[vm_flags & |
34241 |
+ (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)]) | |
34242 |
+ pgprot_val(arch_vm_get_page_prot(vm_flags))); |
34243 |
++ |
34244 |
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32) |
34245 |
++ if (!nx_enabled && |
34246 |
++ (vm_flags & (VM_PAGEEXEC | VM_EXEC)) == VM_PAGEEXEC && |
34247 |
++ (vm_flags & (VM_READ | VM_WRITE))) |
34248 |
++ prot = __pgprot(pte_val(pte_exprotect(__pte(pgprot_val(prot))))); |
34249 |
++#endif |
34250 |
++ |
34251 |
++ return prot; |
34252 |
+ } |
34253 |
+ EXPORT_SYMBOL(vm_get_page_prot); |
34254 |
+ |
34255 |
+@@ -233,6 +252,7 @@ static struct vm_area_struct *remove_vma |
34256 |
+ struct vm_area_struct *next = vma->vm_next; |
34257 |
+ |
34258 |
+ might_sleep(); |
34259 |
++ BUG_ON(vma->vm_mirror); |
34260 |
+ if (vma->vm_ops && vma->vm_ops->close) |
34261 |
+ vma->vm_ops->close(vma); |
34262 |
+ if (vma->vm_file) { |
34263 |
+@@ -269,6 +289,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) |
34264 |
+ * not page aligned -Ram Gupta |
34265 |
+ */ |
34266 |
+ rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; |
34267 |
++ gr_learn_resource(current, RLIMIT_DATA, (brk - mm->start_brk) + (mm->end_data - mm->start_data), 1); |
34268 |
+ if (rlim < RLIM_INFINITY && (brk - mm->start_brk) + |
34269 |
+ (mm->end_data - mm->start_data) > rlim) |
34270 |
+ goto out; |
34271 |
+@@ -696,6 +717,12 @@ static int |
34272 |
+ can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags, |
34273 |
+ struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff) |
34274 |
+ { |
34275 |
++ |
34276 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34277 |
++ if ((vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) && vma->vm_start == SEGMEXEC_TASK_SIZE) |
34278 |
++ return 0; |
34279 |
++#endif |
34280 |
++ |
34281 |
+ if (is_mergeable_vma(vma, file, vm_flags) && |
34282 |
+ is_mergeable_anon_vma(anon_vma, vma->anon_vma)) { |
34283 |
+ if (vma->vm_pgoff == vm_pgoff) |
34284 |
+@@ -715,6 +742,12 @@ static int |
34285 |
+ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags, |
34286 |
+ struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff) |
34287 |
+ { |
34288 |
++ |
34289 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34290 |
++ if ((vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) && vma->vm_end == SEGMEXEC_TASK_SIZE) |
34291 |
++ return 0; |
34292 |
++#endif |
34293 |
++ |
34294 |
+ if (is_mergeable_vma(vma, file, vm_flags) && |
34295 |
+ is_mergeable_anon_vma(anon_vma, vma->anon_vma)) { |
34296 |
+ pgoff_t vm_pglen; |
34297 |
+@@ -757,12 +790,19 @@ can_vma_merge_after(struct vm_area_struc |
34298 |
+ struct vm_area_struct *vma_merge(struct mm_struct *mm, |
34299 |
+ struct vm_area_struct *prev, unsigned long addr, |
34300 |
+ unsigned long end, unsigned long vm_flags, |
34301 |
+- struct anon_vma *anon_vma, struct file *file, |
34302 |
++ struct anon_vma *anon_vma, struct file *file, |
34303 |
+ pgoff_t pgoff, struct mempolicy *policy) |
34304 |
+ { |
34305 |
+ pgoff_t pglen = (end - addr) >> PAGE_SHIFT; |
34306 |
+ struct vm_area_struct *area, *next; |
34307 |
+ |
34308 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34309 |
++ unsigned long addr_m = addr + SEGMEXEC_TASK_SIZE, end_m = end + SEGMEXEC_TASK_SIZE; |
34310 |
++ struct vm_area_struct *area_m = NULL, *next_m = NULL, *prev_m = NULL; |
34311 |
++ |
34312 |
++ BUG_ON((mm->pax_flags & MF_PAX_SEGMEXEC) && SEGMEXEC_TASK_SIZE < end); |
34313 |
++#endif |
34314 |
++ |
34315 |
+ /* |
34316 |
+ * We later require that vma->vm_flags == vm_flags, |
34317 |
+ * so this tests vma->vm_flags & VM_SPECIAL, too. |
34318 |
+@@ -778,6 +818,15 @@ struct vm_area_struct *vma_merge(struct |
34319 |
+ if (next && next->vm_end == end) /* cases 6, 7, 8 */ |
34320 |
+ next = next->vm_next; |
34321 |
+ |
34322 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34323 |
++ if (prev) |
34324 |
++ prev_m = pax_find_mirror_vma(prev); |
34325 |
++ if (area) |
34326 |
++ area_m = pax_find_mirror_vma(area); |
34327 |
++ if (next) |
34328 |
++ next_m = pax_find_mirror_vma(next); |
34329 |
++#endif |
34330 |
++ |
34331 |
+ /* |
34332 |
+ * Can it merge with the predecessor? |
34333 |
+ */ |
34334 |
+@@ -797,9 +846,24 @@ struct vm_area_struct *vma_merge(struct |
34335 |
+ /* cases 1, 6 */ |
34336 |
+ vma_adjust(prev, prev->vm_start, |
34337 |
+ next->vm_end, prev->vm_pgoff, NULL); |
34338 |
+- } else /* cases 2, 5, 7 */ |
34339 |
++ |
34340 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34341 |
++ if (prev_m) |
34342 |
++ vma_adjust(prev_m, prev_m->vm_start, |
34343 |
++ next_m->vm_end, prev_m->vm_pgoff, NULL); |
34344 |
++#endif |
34345 |
++ |
34346 |
++ } else { /* cases 2, 5, 7 */ |
34347 |
+ vma_adjust(prev, prev->vm_start, |
34348 |
+ end, prev->vm_pgoff, NULL); |
34349 |
++ |
34350 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34351 |
++ if (prev_m) |
34352 |
++ vma_adjust(prev_m, prev_m->vm_start, |
34353 |
++ end_m, prev_m->vm_pgoff, NULL); |
34354 |
++#endif |
34355 |
++ |
34356 |
++ } |
34357 |
+ return prev; |
34358 |
+ } |
34359 |
+ |
34360 |
+@@ -810,12 +874,27 @@ struct vm_area_struct *vma_merge(struct |
34361 |
+ mpol_equal(policy, vma_policy(next)) && |
34362 |
+ can_vma_merge_before(next, vm_flags, |
34363 |
+ anon_vma, file, pgoff+pglen)) { |
34364 |
+- if (prev && addr < prev->vm_end) /* case 4 */ |
34365 |
++ if (prev && addr < prev->vm_end) { /* case 4 */ |
34366 |
+ vma_adjust(prev, prev->vm_start, |
34367 |
+ addr, prev->vm_pgoff, NULL); |
34368 |
+- else /* cases 3, 8 */ |
34369 |
++ |
34370 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34371 |
++ if (prev_m) |
34372 |
++ vma_adjust(prev_m, prev_m->vm_start, |
34373 |
++ addr_m, prev_m->vm_pgoff, NULL); |
34374 |
++#endif |
34375 |
++ |
34376 |
++ } else { /* cases 3, 8 */ |
34377 |
+ vma_adjust(area, addr, next->vm_end, |
34378 |
+ next->vm_pgoff - pglen, NULL); |
34379 |
++ |
34380 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34381 |
++ if (area_m) |
34382 |
++ vma_adjust(area_m, addr_m, next_m->vm_end, |
34383 |
++ next_m->vm_pgoff - pglen, NULL); |
34384 |
++#endif |
34385 |
++ |
34386 |
++ } |
34387 |
+ return area; |
34388 |
+ } |
34389 |
+ |
34390 |
+@@ -890,14 +969,11 @@ none: |
34391 |
+ void vm_stat_account(struct mm_struct *mm, unsigned long flags, |
34392 |
+ struct file *file, long pages) |
34393 |
+ { |
34394 |
+- const unsigned long stack_flags |
34395 |
+- = VM_STACK_FLAGS & (VM_GROWSUP|VM_GROWSDOWN); |
34396 |
+- |
34397 |
+ if (file) { |
34398 |
+ mm->shared_vm += pages; |
34399 |
+ if ((flags & (VM_EXEC|VM_WRITE)) == VM_EXEC) |
34400 |
+ mm->exec_vm += pages; |
34401 |
+- } else if (flags & stack_flags) |
34402 |
++ } else if (flags & (VM_GROWSUP|VM_GROWSDOWN)) |
34403 |
+ mm->stack_vm += pages; |
34404 |
+ if (flags & (VM_RESERVED|VM_IO)) |
34405 |
+ mm->reserved_vm += pages; |
34406 |
+@@ -925,7 +1001,7 @@ unsigned long do_mmap_pgoff(struct file |
34407 |
+ * (the exception is when the underlying filesystem is noexec |
34408 |
+ * mounted, in which case we dont add PROT_EXEC.) |
34409 |
+ */ |
34410 |
+- if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC)) |
34411 |
++ if ((prot & (PROT_READ | PROT_WRITE)) && (current->personality & READ_IMPLIES_EXEC)) |
34412 |
+ if (!(file && (file->f_path.mnt->mnt_flags & MNT_NOEXEC))) |
34413 |
+ prot |= PROT_EXEC; |
34414 |
+ |
34415 |
+@@ -935,15 +1011,15 @@ unsigned long do_mmap_pgoff(struct file |
34416 |
+ if (!(flags & MAP_FIXED)) |
34417 |
+ addr = round_hint_to_min(addr); |
34418 |
+ |
34419 |
+- error = arch_mmap_check(addr, len, flags); |
34420 |
+- if (error) |
34421 |
+- return error; |
34422 |
+- |
34423 |
+ /* Careful about overflows.. */ |
34424 |
+ len = PAGE_ALIGN(len); |
34425 |
+ if (!len || len > TASK_SIZE) |
34426 |
+ return -ENOMEM; |
34427 |
+ |
34428 |
++ error = arch_mmap_check(addr, len, flags); |
34429 |
++ if (error) |
34430 |
++ return error; |
34431 |
++ |
34432 |
+ /* offset overflow? */ |
34433 |
+ if ((pgoff + (len >> PAGE_SHIFT)) < pgoff) |
34434 |
+ return -EOVERFLOW; |
34435 |
+@@ -955,7 +1031,7 @@ unsigned long do_mmap_pgoff(struct file |
34436 |
+ /* Obtain the address to map to. we verify (or select) it and ensure |
34437 |
+ * that it represents a valid section of the address space. |
34438 |
+ */ |
34439 |
+- addr = get_unmapped_area(file, addr, len, pgoff, flags); |
34440 |
++ addr = get_unmapped_area(file, addr, len, pgoff, flags | ((prot & PROT_EXEC) ? MAP_EXECUTABLE : 0)); |
34441 |
+ if (addr & ~PAGE_MASK) |
34442 |
+ return addr; |
34443 |
+ |
34444 |
+@@ -966,6 +1042,26 @@ unsigned long do_mmap_pgoff(struct file |
34445 |
+ vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) | |
34446 |
+ mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; |
34447 |
+ |
34448 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
34449 |
++ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { |
34450 |
++ |
34451 |
++#ifdef CONFIG_PAX_MPROTECT |
34452 |
++ if (mm->pax_flags & MF_PAX_MPROTECT) { |
34453 |
++ if ((prot & (PROT_WRITE | PROT_EXEC)) != PROT_EXEC) |
34454 |
++ vm_flags &= ~(VM_EXEC | VM_MAYEXEC); |
34455 |
++ else |
34456 |
++ vm_flags &= ~(VM_WRITE | VM_MAYWRITE); |
34457 |
++ } |
34458 |
++#endif |
34459 |
++ |
34460 |
++ } |
34461 |
++#endif |
34462 |
++ |
34463 |
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32) |
34464 |
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && file) |
34465 |
++ vm_flags &= ~VM_PAGEEXEC; |
34466 |
++#endif |
34467 |
++ |
34468 |
+ if (flags & MAP_LOCKED) { |
34469 |
+ if (!can_do_mlock()) |
34470 |
+ return -EPERM; |
34471 |
+@@ -979,6 +1075,7 @@ unsigned long do_mmap_pgoff(struct file |
34472 |
+ locked += mm->locked_vm; |
34473 |
+ lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; |
34474 |
+ lock_limit >>= PAGE_SHIFT; |
34475 |
++ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1); |
34476 |
+ if (locked > lock_limit && !capable(CAP_IPC_LOCK)) |
34477 |
+ return -EAGAIN; |
34478 |
+ } |
34479 |
+@@ -1051,6 +1148,9 @@ unsigned long do_mmap_pgoff(struct file |
34480 |
+ if (error) |
34481 |
+ return error; |
34482 |
+ |
34483 |
++ if (!gr_acl_handle_mmap(file, prot)) |
34484 |
++ return -EACCES; |
34485 |
++ |
34486 |
+ return mmap_region(file, addr, len, flags, vm_flags, pgoff, |
34487 |
+ accountable); |
34488 |
+ } |
34489 |
+@@ -1064,10 +1164,10 @@ EXPORT_SYMBOL(do_mmap_pgoff); |
34490 |
+ */ |
34491 |
+ int vma_wants_writenotify(struct vm_area_struct *vma) |
34492 |
+ { |
34493 |
+- unsigned int vm_flags = vma->vm_flags; |
34494 |
++ unsigned long vm_flags = vma->vm_flags; |
34495 |
+ |
34496 |
+ /* If it was private or non-writable, the write bit is already clear */ |
34497 |
+- if ((vm_flags & (VM_WRITE|VM_SHARED)) != ((VM_WRITE|VM_SHARED))) |
34498 |
++ if ((vm_flags & (VM_WRITE|VM_SHARED)) != (VM_WRITE|VM_SHARED)) |
34499 |
+ return 0; |
34500 |
+ |
34501 |
+ /* The backer wishes to know when pages are first written to? */ |
34502 |
+@@ -1102,14 +1202,24 @@ unsigned long mmap_region(struct file *f |
34503 |
+ unsigned long charged = 0; |
34504 |
+ struct inode *inode = file ? file->f_path.dentry->d_inode : NULL; |
34505 |
+ |
34506 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34507 |
++ struct vm_area_struct *vma_m = NULL; |
34508 |
++#endif |
34509 |
++ |
34510 |
++ /* |
34511 |
++ * mm->mmap_sem is required to protect against another thread |
34512 |
++ * changing the mappings in case we sleep. |
34513 |
++ */ |
34514 |
++ verify_mm_writelocked(mm); |
34515 |
++ |
34516 |
+ /* Clear old maps */ |
34517 |
+ error = -ENOMEM; |
34518 |
+-munmap_back: |
34519 |
+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); |
34520 |
+ if (vma && vma->vm_start < addr + len) { |
34521 |
+ if (do_munmap(mm, addr, len)) |
34522 |
+ return -ENOMEM; |
34523 |
+- goto munmap_back; |
34524 |
++ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); |
34525 |
++ BUG_ON(vma && vma->vm_start < addr + len); |
34526 |
+ } |
34527 |
+ |
34528 |
+ /* Check against address space limit. */ |
34529 |
+@@ -1158,6 +1268,16 @@ munmap_back: |
34530 |
+ goto unacct_error; |
34531 |
+ } |
34532 |
+ |
34533 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34534 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (vm_flags & VM_EXEC)) { |
34535 |
++ vma_m = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
34536 |
++ if (!vma_m) { |
34537 |
++ error = -ENOMEM; |
34538 |
++ goto free_vma; |
34539 |
++ } |
34540 |
++ } |
34541 |
++#endif |
34542 |
++ |
34543 |
+ vma->vm_mm = mm; |
34544 |
+ vma->vm_start = addr; |
34545 |
+ vma->vm_end = addr + len; |
34546 |
+@@ -1180,6 +1300,19 @@ munmap_back: |
34547 |
+ error = file->f_op->mmap(file, vma); |
34548 |
+ if (error) |
34549 |
+ goto unmap_and_free_vma; |
34550 |
++ |
34551 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34552 |
++ if (vma_m && (vm_flags & VM_EXECUTABLE)) |
34553 |
++ added_exe_file_vma(mm); |
34554 |
++#endif |
34555 |
++ |
34556 |
++#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32) |
34557 |
++ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && !(vma->vm_flags & VM_SPECIAL)) { |
34558 |
++ vma->vm_flags |= VM_PAGEEXEC; |
34559 |
++ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
34560 |
++ } |
34561 |
++#endif |
34562 |
++ |
34563 |
+ if (vm_flags & VM_EXECUTABLE) |
34564 |
+ added_exe_file_vma(mm); |
34565 |
+ } else if (vm_flags & VM_SHARED) { |
34566 |
+@@ -1215,13 +1348,30 @@ munmap_back: |
34567 |
+ if (merged_vma) { |
34568 |
+ mpol_put(vma_policy(vma)); |
34569 |
+ kmem_cache_free(vm_area_cachep, vma); |
34570 |
++ vma = NULL; |
34571 |
+ fput(file); |
34572 |
++ |
34573 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34574 |
++ if (vma_m) { |
34575 |
++ kmem_cache_free(vm_area_cachep, vma_m); |
34576 |
++ |
34577 |
++ if (vm_flags & VM_EXECUTABLE) |
34578 |
++ removed_exe_file_vma(mm); |
34579 |
++ } |
34580 |
++#endif |
34581 |
++ |
34582 |
+ if (vm_flags & VM_EXECUTABLE) |
34583 |
+ removed_exe_file_vma(mm); |
34584 |
+ vma = merged_vma; |
34585 |
+ } else { |
34586 |
+ vma_link(mm, vma, prev, rb_link, rb_parent); |
34587 |
+ file = vma->vm_file; |
34588 |
++ |
34589 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34590 |
++ if (vma_m) |
34591 |
++ pax_mirror_vma(vma_m, vma); |
34592 |
++#endif |
34593 |
++ |
34594 |
+ } |
34595 |
+ |
34596 |
+ /* Once vma denies write, undo our temporary denial count */ |
34597 |
+@@ -1230,6 +1380,7 @@ munmap_back: |
34598 |
+ out: |
34599 |
+ mm->total_vm += len >> PAGE_SHIFT; |
34600 |
+ vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT); |
34601 |
++ track_exec_limit(mm, addr, addr + len, vm_flags); |
34602 |
+ if (vm_flags & VM_LOCKED) { |
34603 |
+ /* |
34604 |
+ * makes pages present; downgrades, drops, reacquires mmap_sem |
34605 |
+@@ -1252,6 +1403,12 @@ unmap_and_free_vma: |
34606 |
+ unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); |
34607 |
+ charged = 0; |
34608 |
+ free_vma: |
34609 |
++ |
34610 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34611 |
++ if (vma_m) |
34612 |
++ kmem_cache_free(vm_area_cachep, vma_m); |
34613 |
++#endif |
34614 |
++ |
34615 |
+ kmem_cache_free(vm_area_cachep, vma); |
34616 |
+ unacct_error: |
34617 |
+ if (charged) |
34618 |
+@@ -1285,6 +1442,10 @@ arch_get_unmapped_area(struct file *filp |
34619 |
+ if (flags & MAP_FIXED) |
34620 |
+ return addr; |
34621 |
+ |
34622 |
++#ifdef CONFIG_PAX_RANDMMAP |
34623 |
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) |
34624 |
++#endif |
34625 |
++ |
34626 |
+ if (addr) { |
34627 |
+ addr = PAGE_ALIGN(addr); |
34628 |
+ vma = find_vma(mm, addr); |
34629 |
+@@ -1293,10 +1454,10 @@ arch_get_unmapped_area(struct file *filp |
34630 |
+ return addr; |
34631 |
+ } |
34632 |
+ if (len > mm->cached_hole_size) { |
34633 |
+- start_addr = addr = mm->free_area_cache; |
34634 |
++ start_addr = addr = mm->free_area_cache; |
34635 |
+ } else { |
34636 |
+- start_addr = addr = TASK_UNMAPPED_BASE; |
34637 |
+- mm->cached_hole_size = 0; |
34638 |
++ start_addr = addr = mm->mmap_base; |
34639 |
++ mm->cached_hole_size = 0; |
34640 |
+ } |
34641 |
+ |
34642 |
+ full_search: |
34643 |
+@@ -1307,9 +1468,8 @@ full_search: |
34644 |
+ * Start a new search - just in case we missed |
34645 |
+ * some holes. |
34646 |
+ */ |
34647 |
+- if (start_addr != TASK_UNMAPPED_BASE) { |
34648 |
+- addr = TASK_UNMAPPED_BASE; |
34649 |
+- start_addr = addr; |
34650 |
++ if (start_addr != mm->mmap_base) { |
34651 |
++ start_addr = addr = mm->mmap_base; |
34652 |
+ mm->cached_hole_size = 0; |
34653 |
+ goto full_search; |
34654 |
+ } |
34655 |
+@@ -1331,10 +1491,16 @@ full_search: |
34656 |
+ |
34657 |
+ void arch_unmap_area(struct mm_struct *mm, unsigned long addr) |
34658 |
+ { |
34659 |
++ |
34660 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34661 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && SEGMEXEC_TASK_SIZE <= addr) |
34662 |
++ return; |
34663 |
++#endif |
34664 |
++ |
34665 |
+ /* |
34666 |
+ * Is this a new hole at the lowest possible address? |
34667 |
+ */ |
34668 |
+- if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache) { |
34669 |
++ if (addr >= mm->mmap_base && addr < mm->free_area_cache) { |
34670 |
+ mm->free_area_cache = addr; |
34671 |
+ mm->cached_hole_size = ~0UL; |
34672 |
+ } |
34673 |
+@@ -1352,7 +1518,7 @@ arch_get_unmapped_area_topdown(struct fi |
34674 |
+ { |
34675 |
+ struct vm_area_struct *vma; |
34676 |
+ struct mm_struct *mm = current->mm; |
34677 |
+- unsigned long addr = addr0; |
34678 |
++ unsigned long base = mm->mmap_base, addr = addr0; |
34679 |
+ |
34680 |
+ /* requested length too big for entire address space */ |
34681 |
+ if (len > TASK_SIZE) |
34682 |
+@@ -1361,6 +1527,10 @@ arch_get_unmapped_area_topdown(struct fi |
34683 |
+ if (flags & MAP_FIXED) |
34684 |
+ return addr; |
34685 |
+ |
34686 |
++#ifdef CONFIG_PAX_RANDMMAP |
34687 |
++ if (!(mm->pax_flags & MF_PAX_RANDMMAP)) |
34688 |
++#endif |
34689 |
++ |
34690 |
+ /* requesting a specific address */ |
34691 |
+ if (addr) { |
34692 |
+ addr = PAGE_ALIGN(addr); |
34693 |
+@@ -1418,13 +1588,21 @@ bottomup: |
34694 |
+ * can happen with large stack limits and large mmap() |
34695 |
+ * allocations. |
34696 |
+ */ |
34697 |
++ mm->mmap_base = TASK_UNMAPPED_BASE; |
34698 |
++ |
34699 |
++#ifdef CONFIG_PAX_RANDMMAP |
34700 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
34701 |
++ mm->mmap_base += mm->delta_mmap; |
34702 |
++#endif |
34703 |
++ |
34704 |
++ mm->free_area_cache = mm->mmap_base; |
34705 |
+ mm->cached_hole_size = ~0UL; |
34706 |
+- mm->free_area_cache = TASK_UNMAPPED_BASE; |
34707 |
+ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags); |
34708 |
+ /* |
34709 |
+ * Restore the topdown base: |
34710 |
+ */ |
34711 |
+- mm->free_area_cache = mm->mmap_base; |
34712 |
++ mm->mmap_base = base; |
34713 |
++ mm->free_area_cache = base; |
34714 |
+ mm->cached_hole_size = ~0UL; |
34715 |
+ |
34716 |
+ return addr; |
34717 |
+@@ -1433,6 +1611,12 @@ bottomup: |
34718 |
+ |
34719 |
+ void arch_unmap_area_topdown(struct mm_struct *mm, unsigned long addr) |
34720 |
+ { |
34721 |
++ |
34722 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34723 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && SEGMEXEC_TASK_SIZE <= addr) |
34724 |
++ return; |
34725 |
++#endif |
34726 |
++ |
34727 |
+ /* |
34728 |
+ * Is this a new hole at the highest possible address? |
34729 |
+ */ |
34730 |
+@@ -1440,8 +1624,10 @@ void arch_unmap_area_topdown(struct mm_s |
34731 |
+ mm->free_area_cache = addr; |
34732 |
+ |
34733 |
+ /* dont allow allocations above current base */ |
34734 |
+- if (mm->free_area_cache > mm->mmap_base) |
34735 |
++ if (mm->free_area_cache > mm->mmap_base) { |
34736 |
+ mm->free_area_cache = mm->mmap_base; |
34737 |
++ mm->cached_hole_size = ~0UL; |
34738 |
++ } |
34739 |
+ } |
34740 |
+ |
34741 |
+ unsigned long |
34742 |
+@@ -1541,6 +1727,27 @@ out: |
34743 |
+ return prev ? prev->vm_next : vma; |
34744 |
+ } |
34745 |
+ |
34746 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34747 |
++struct vm_area_struct *pax_find_mirror_vma(struct vm_area_struct *vma) |
34748 |
++{ |
34749 |
++ struct vm_area_struct *vma_m; |
34750 |
++ |
34751 |
++ BUG_ON(!vma || vma->vm_start >= vma->vm_end); |
34752 |
++ if (!(vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) || !(vma->vm_flags & VM_EXEC)) { |
34753 |
++ BUG_ON(vma->vm_mirror); |
34754 |
++ return NULL; |
34755 |
++ } |
34756 |
++ BUG_ON(vma->vm_start < SEGMEXEC_TASK_SIZE && SEGMEXEC_TASK_SIZE < vma->vm_end); |
34757 |
++ vma_m = vma->vm_mirror; |
34758 |
++ BUG_ON(!vma_m || vma_m->vm_mirror != vma); |
34759 |
++ BUG_ON(vma->vm_file != vma_m->vm_file); |
34760 |
++ BUG_ON(vma->vm_end - vma->vm_start != vma_m->vm_end - vma_m->vm_start); |
34761 |
++ BUG_ON(vma->vm_pgoff != vma_m->vm_pgoff || vma->anon_vma != vma_m->anon_vma); |
34762 |
++ BUG_ON((vma->vm_flags ^ vma_m->vm_flags) & ~(VM_WRITE | VM_MAYWRITE | VM_ACCOUNT | VM_LOCKED)); |
34763 |
++ return vma_m; |
34764 |
++} |
34765 |
++#endif |
34766 |
++ |
34767 |
+ /* |
34768 |
+ * Verify that the stack growth is acceptable and |
34769 |
+ * update accounting. This is shared with both the |
34770 |
+@@ -1557,6 +1764,7 @@ static int acct_stack_growth(struct vm_a |
34771 |
+ return -ENOMEM; |
34772 |
+ |
34773 |
+ /* Stack limit test */ |
34774 |
++ gr_learn_resource(current, RLIMIT_STACK, size, 1); |
34775 |
+ if (size > rlim[RLIMIT_STACK].rlim_cur) |
34776 |
+ return -ENOMEM; |
34777 |
+ |
34778 |
+@@ -1566,6 +1774,7 @@ static int acct_stack_growth(struct vm_a |
34779 |
+ unsigned long limit; |
34780 |
+ locked = mm->locked_vm + grow; |
34781 |
+ limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT; |
34782 |
++ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1); |
34783 |
+ if (locked > limit && !capable(CAP_IPC_LOCK)) |
34784 |
+ return -ENOMEM; |
34785 |
+ } |
34786 |
+@@ -1580,7 +1789,7 @@ static int acct_stack_growth(struct vm_a |
34787 |
+ * Overcommit.. This must be the final test, as it will |
34788 |
+ * update security statistics. |
34789 |
+ */ |
34790 |
+- if (security_vm_enough_memory(grow)) |
34791 |
++ if (security_vm_enough_memory_mm(mm, grow)) |
34792 |
+ return -ENOMEM; |
34793 |
+ |
34794 |
+ /* Ok, everything looks good - let it rip */ |
34795 |
+@@ -1601,35 +1810,40 @@ static |
34796 |
+ #endif |
34797 |
+ int expand_upwards(struct vm_area_struct *vma, unsigned long address) |
34798 |
+ { |
34799 |
+- int error; |
34800 |
++ int error, locknext; |
34801 |
+ |
34802 |
+ if (!(vma->vm_flags & VM_GROWSUP)) |
34803 |
+ return -EFAULT; |
34804 |
+ |
34805 |
++ /* Also guard against wrapping around to address 0. */ |
34806 |
++ if (address < PAGE_ALIGN(address+1)) |
34807 |
++ address = PAGE_ALIGN(address+1); |
34808 |
++ else |
34809 |
++ return -ENOMEM; |
34810 |
++ |
34811 |
+ /* |
34812 |
+ * We must make sure the anon_vma is allocated |
34813 |
+ * so that the anon_vma locking is not a noop. |
34814 |
+ */ |
34815 |
+ if (unlikely(anon_vma_prepare(vma))) |
34816 |
+ return -ENOMEM; |
34817 |
++ locknext = vma->vm_next && (vma->vm_next->vm_flags & VM_GROWSDOWN); |
34818 |
++ if (locknext && unlikely(anon_vma_prepare(vma->vm_next))) |
34819 |
++ return -ENOMEM; |
34820 |
+ anon_vma_lock(vma); |
34821 |
++ if (locknext) |
34822 |
++ anon_vma_lock(vma->vm_next); |
34823 |
+ |
34824 |
+ /* |
34825 |
+ * vma->vm_start/vm_end cannot change under us because the caller |
34826 |
+ * is required to hold the mmap_sem in read mode. We need the |
34827 |
+- * anon_vma lock to serialize against concurrent expand_stacks. |
34828 |
+- * Also guard against wrapping around to address 0. |
34829 |
++ * anon_vma locks to serialize against concurrent expand_stacks |
34830 |
++ * and expand_upwards. |
34831 |
+ */ |
34832 |
+- if (address < PAGE_ALIGN(address+4)) |
34833 |
+- address = PAGE_ALIGN(address+4); |
34834 |
+- else { |
34835 |
+- anon_vma_unlock(vma); |
34836 |
+- return -ENOMEM; |
34837 |
+- } |
34838 |
+ error = 0; |
34839 |
+ |
34840 |
+ /* Somebody else might have raced and expanded it already */ |
34841 |
+- if (address > vma->vm_end) { |
34842 |
++ if (address > vma->vm_end && (!locknext || vma->vm_next->vm_start >= address)) { |
34843 |
+ unsigned long size, grow; |
34844 |
+ |
34845 |
+ size = address - vma->vm_start; |
34846 |
+@@ -1639,6 +1853,8 @@ int expand_upwards(struct vm_area_struct |
34847 |
+ if (!error) |
34848 |
+ vma->vm_end = address; |
34849 |
+ } |
34850 |
++ if (locknext) |
34851 |
++ anon_vma_unlock(vma->vm_next); |
34852 |
+ anon_vma_unlock(vma); |
34853 |
+ return error; |
34854 |
+ } |
34855 |
+@@ -1650,7 +1866,8 @@ int expand_upwards(struct vm_area_struct |
34856 |
+ static int expand_downwards(struct vm_area_struct *vma, |
34857 |
+ unsigned long address) |
34858 |
+ { |
34859 |
+- int error; |
34860 |
++ int error, lockprev = 0; |
34861 |
++ struct vm_area_struct *prev = NULL; |
34862 |
+ |
34863 |
+ /* |
34864 |
+ * We must make sure the anon_vma is allocated |
34865 |
+@@ -1664,6 +1881,15 @@ static int expand_downwards(struct vm_ar |
34866 |
+ if (error) |
34867 |
+ return error; |
34868 |
+ |
34869 |
++#if defined(CONFIG_STACK_GROWSUP) || defined(CONFIG_IA64) |
34870 |
++ find_vma_prev(vma->vm_mm, address, &prev); |
34871 |
++ lockprev = prev && (prev->vm_flags & VM_GROWSUP); |
34872 |
++#endif |
34873 |
++ if (lockprev && unlikely(anon_vma_prepare(prev))) |
34874 |
++ return -ENOMEM; |
34875 |
++ if (lockprev) |
34876 |
++ anon_vma_lock(prev); |
34877 |
++ |
34878 |
+ anon_vma_lock(vma); |
34879 |
+ |
34880 |
+ /* |
34881 |
+@@ -1673,9 +1899,15 @@ static int expand_downwards(struct vm_ar |
34882 |
+ */ |
34883 |
+ |
34884 |
+ /* Somebody else might have raced and expanded it already */ |
34885 |
+- if (address < vma->vm_start) { |
34886 |
++ if (address < vma->vm_start && (!lockprev || prev->vm_end <= address)) { |
34887 |
+ unsigned long size, grow; |
34888 |
+ |
34889 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34890 |
++ struct vm_area_struct *vma_m; |
34891 |
++ |
34892 |
++ vma_m = pax_find_mirror_vma(vma); |
34893 |
++#endif |
34894 |
++ |
34895 |
+ size = vma->vm_end - address; |
34896 |
+ grow = (vma->vm_start - address) >> PAGE_SHIFT; |
34897 |
+ |
34898 |
+@@ -1683,9 +1915,20 @@ static int expand_downwards(struct vm_ar |
34899 |
+ if (!error) { |
34900 |
+ vma->vm_start = address; |
34901 |
+ vma->vm_pgoff -= grow; |
34902 |
++ track_exec_limit(vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_flags); |
34903 |
++ |
34904 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34905 |
++ if (vma_m) { |
34906 |
++ vma_m->vm_start -= grow << PAGE_SHIFT; |
34907 |
++ vma_m->vm_pgoff -= grow; |
34908 |
++ } |
34909 |
++#endif |
34910 |
++ |
34911 |
+ } |
34912 |
+ } |
34913 |
+ anon_vma_unlock(vma); |
34914 |
++ if (lockprev) |
34915 |
++ anon_vma_unlock(prev); |
34916 |
+ return error; |
34917 |
+ } |
34918 |
+ |
34919 |
+@@ -1761,6 +2004,13 @@ static void remove_vma_list(struct mm_st |
34920 |
+ do { |
34921 |
+ long nrpages = vma_pages(vma); |
34922 |
+ |
34923 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34924 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_start >= SEGMEXEC_TASK_SIZE)) { |
34925 |
++ vma = remove_vma(vma); |
34926 |
++ continue; |
34927 |
++ } |
34928 |
++#endif |
34929 |
++ |
34930 |
+ mm->total_vm -= nrpages; |
34931 |
+ vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages); |
34932 |
+ vma = remove_vma(vma); |
34933 |
+@@ -1805,6 +2055,16 @@ detach_vmas_to_be_unmapped(struct mm_str |
34934 |
+ |
34935 |
+ insertion_point = (prev ? &prev->vm_next : &mm->mmap); |
34936 |
+ do { |
34937 |
++ |
34938 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34939 |
++ if (vma->vm_mirror) { |
34940 |
++ BUG_ON(!vma->vm_mirror->vm_mirror || vma->vm_mirror->vm_mirror != vma); |
34941 |
++ vma->vm_mirror->vm_mirror = NULL; |
34942 |
++ vma->vm_mirror->vm_flags &= ~VM_EXEC; |
34943 |
++ vma->vm_mirror = NULL; |
34944 |
++ } |
34945 |
++#endif |
34946 |
++ |
34947 |
+ rb_erase(&vma->vm_rb, &mm->mm_rb); |
34948 |
+ mm->map_count--; |
34949 |
+ tail_vma = vma; |
34950 |
+@@ -1824,6 +2084,108 @@ detach_vmas_to_be_unmapped(struct mm_str |
34951 |
+ * Split a vma into two pieces at address 'addr', a new vma is allocated |
34952 |
+ * either for the first part or the tail. |
34953 |
+ */ |
34954 |
++ |
34955 |
++#ifdef CONFIG_PAX_SEGMEXEC |
34956 |
++int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, |
34957 |
++ unsigned long addr, int new_below) |
34958 |
++{ |
34959 |
++ struct mempolicy *pol; |
34960 |
++ struct vm_area_struct *new, *vma_m, *new_m = NULL; |
34961 |
++ unsigned long addr_m = addr + SEGMEXEC_TASK_SIZE; |
34962 |
++ |
34963 |
++ if (is_vm_hugetlb_page(vma) && (addr & ~HPAGE_MASK)) |
34964 |
++ return -EINVAL; |
34965 |
++ |
34966 |
++ vma_m = pax_find_mirror_vma(vma); |
34967 |
++ if (vma_m) { |
34968 |
++ BUG_ON(vma->vm_end > SEGMEXEC_TASK_SIZE); |
34969 |
++ if (mm->map_count >= sysctl_max_map_count-1) |
34970 |
++ return -ENOMEM; |
34971 |
++ } else if (mm->map_count >= sysctl_max_map_count) |
34972 |
++ return -ENOMEM; |
34973 |
++ |
34974 |
++ new = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); |
34975 |
++ if (!new) |
34976 |
++ return -ENOMEM; |
34977 |
++ |
34978 |
++ if (vma_m) { |
34979 |
++ new_m = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); |
34980 |
++ if (!new_m) { |
34981 |
++ kmem_cache_free(vm_area_cachep, new); |
34982 |
++ return -ENOMEM; |
34983 |
++ } |
34984 |
++ } |
34985 |
++ |
34986 |
++ /* most fields are the same, copy all, and then fixup */ |
34987 |
++ *new = *vma; |
34988 |
++ |
34989 |
++ if (new_below) |
34990 |
++ new->vm_end = addr; |
34991 |
++ else { |
34992 |
++ new->vm_start = addr; |
34993 |
++ new->vm_pgoff += ((addr - vma->vm_start) >> PAGE_SHIFT); |
34994 |
++ } |
34995 |
++ |
34996 |
++ if (vma_m) { |
34997 |
++ *new_m = *vma_m; |
34998 |
++ new_m->vm_mirror = new; |
34999 |
++ new->vm_mirror = new_m; |
35000 |
++ |
35001 |
++ if (new_below) |
35002 |
++ new_m->vm_end = addr_m; |
35003 |
++ else { |
35004 |
++ new_m->vm_start = addr_m; |
35005 |
++ new_m->vm_pgoff += ((addr_m - vma_m->vm_start) >> PAGE_SHIFT); |
35006 |
++ } |
35007 |
++ } |
35008 |
++ |
35009 |
++ pol = mpol_dup(vma_policy(vma)); |
35010 |
++ if (IS_ERR(pol)) { |
35011 |
++ if (new_m) |
35012 |
++ kmem_cache_free(vm_area_cachep, new_m); |
35013 |
++ kmem_cache_free(vm_area_cachep, new); |
35014 |
++ return PTR_ERR(pol); |
35015 |
++ } |
35016 |
++ vma_set_policy(new, pol); |
35017 |
++ |
35018 |
++ if (new->vm_file) { |
35019 |
++ get_file(new->vm_file); |
35020 |
++ if (vma->vm_flags & VM_EXECUTABLE) |
35021 |
++ added_exe_file_vma(mm); |
35022 |
++ } |
35023 |
++ |
35024 |
++ if (new->vm_ops && new->vm_ops->open) |
35025 |
++ new->vm_ops->open(new); |
35026 |
++ |
35027 |
++ if (new_below) |
35028 |
++ vma_adjust(vma, addr, vma->vm_end, vma->vm_pgoff + |
35029 |
++ ((addr - new->vm_start) >> PAGE_SHIFT), new); |
35030 |
++ else |
35031 |
++ vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new); |
35032 |
++ |
35033 |
++ if (vma_m) { |
35034 |
++ mpol_get(pol); |
35035 |
++ vma_set_policy(new_m, pol); |
35036 |
++ |
35037 |
++ if (new_m->vm_file) { |
35038 |
++ get_file(new_m->vm_file); |
35039 |
++ if (vma_m->vm_flags & VM_EXECUTABLE) |
35040 |
++ added_exe_file_vma(mm); |
35041 |
++ } |
35042 |
++ |
35043 |
++ if (new_m->vm_ops && new_m->vm_ops->open) |
35044 |
++ new_m->vm_ops->open(new_m); |
35045 |
++ |
35046 |
++ if (new_below) |
35047 |
++ vma_adjust(vma_m, addr_m, vma_m->vm_end, vma_m->vm_pgoff + |
35048 |
++ ((addr_m - new_m->vm_start) >> PAGE_SHIFT), new_m); |
35049 |
++ else |
35050 |
++ vma_adjust(vma_m, vma_m->vm_start, addr_m, vma_m->vm_pgoff, new_m); |
35051 |
++ } |
35052 |
++ |
35053 |
++ return 0; |
35054 |
++} |
35055 |
++#else |
35056 |
+ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma, |
35057 |
+ unsigned long addr, int new_below) |
35058 |
+ { |
35059 |
+@@ -1875,17 +2237,37 @@ int split_vma(struct mm_struct * mm, str |
35060 |
+ |
35061 |
+ return 0; |
35062 |
+ } |
35063 |
++#endif |
35064 |
+ |
35065 |
+ /* Munmap is split into 2 main parts -- this part which finds |
35066 |
+ * what needs doing, and the areas themselves, which do the |
35067 |
+ * work. This now handles partial unmappings. |
35068 |
+ * Jeremy Fitzhardinge <jeremy@××××.org> |
35069 |
+ */ |
35070 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35071 |
+ int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) |
35072 |
+ { |
35073 |
++ int ret = __do_munmap(mm, start, len); |
35074 |
++ if (ret || !(mm->pax_flags & MF_PAX_SEGMEXEC)) |
35075 |
++ return ret; |
35076 |
++ |
35077 |
++ return __do_munmap(mm, start + SEGMEXEC_TASK_SIZE, len); |
35078 |
++} |
35079 |
++ |
35080 |
++int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len) |
35081 |
++#else |
35082 |
++int do_munmap(struct mm_struct *mm, unsigned long start, size_t len) |
35083 |
++#endif |
35084 |
++{ |
35085 |
+ unsigned long end; |
35086 |
+ struct vm_area_struct *vma, *prev, *last; |
35087 |
+ |
35088 |
++ /* |
35089 |
++ * mm->mmap_sem is required to protect against another thread |
35090 |
++ * changing the mappings in case we sleep. |
35091 |
++ */ |
35092 |
++ verify_mm_writelocked(mm); |
35093 |
++ |
35094 |
+ if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE-start) |
35095 |
+ return -EINVAL; |
35096 |
+ |
35097 |
+@@ -1949,6 +2331,8 @@ int do_munmap(struct mm_struct *mm, unsi |
35098 |
+ /* Fix up all other VM information */ |
35099 |
+ remove_vma_list(mm, vma); |
35100 |
+ |
35101 |
++ track_exec_limit(mm, start, end, 0UL); |
35102 |
++ |
35103 |
+ return 0; |
35104 |
+ } |
35105 |
+ |
35106 |
+@@ -1961,22 +2345,18 @@ SYSCALL_DEFINE2(munmap, unsigned long, a |
35107 |
+ |
35108 |
+ profile_munmap(addr); |
35109 |
+ |
35110 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35111 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && |
35112 |
++ (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len)) |
35113 |
++ return -EINVAL; |
35114 |
++#endif |
35115 |
++ |
35116 |
+ down_write(&mm->mmap_sem); |
35117 |
+ ret = do_munmap(mm, addr, len); |
35118 |
+ up_write(&mm->mmap_sem); |
35119 |
+ return ret; |
35120 |
+ } |
35121 |
+ |
35122 |
+-static inline void verify_mm_writelocked(struct mm_struct *mm) |
35123 |
+-{ |
35124 |
+-#ifdef CONFIG_DEBUG_VM |
35125 |
+- if (unlikely(down_read_trylock(&mm->mmap_sem))) { |
35126 |
+- WARN_ON(1); |
35127 |
+- up_read(&mm->mmap_sem); |
35128 |
+- } |
35129 |
+-#endif |
35130 |
+-} |
35131 |
+- |
35132 |
+ /* |
35133 |
+ * this is really a simplified "do_mmap". it only handles |
35134 |
+ * anonymous maps. eventually we may be able to do some |
35135 |
+@@ -1990,6 +2370,11 @@ unsigned long do_brk(unsigned long addr, |
35136 |
+ struct rb_node ** rb_link, * rb_parent; |
35137 |
+ pgoff_t pgoff = addr >> PAGE_SHIFT; |
35138 |
+ int error; |
35139 |
++ unsigned long charged; |
35140 |
++ |
35141 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35142 |
++ struct vm_area_struct *vma_m = NULL; |
35143 |
++#endif |
35144 |
+ |
35145 |
+ len = PAGE_ALIGN(len); |
35146 |
+ if (!len) |
35147 |
+@@ -2007,19 +2392,34 @@ unsigned long do_brk(unsigned long addr, |
35148 |
+ |
35149 |
+ flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; |
35150 |
+ |
35151 |
++#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) |
35152 |
++ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) { |
35153 |
++ flags &= ~VM_EXEC; |
35154 |
++ |
35155 |
++#ifdef CONFIG_PAX_MPROTECT |
35156 |
++ if (mm->pax_flags & MF_PAX_MPROTECT) |
35157 |
++ flags &= ~VM_MAYEXEC; |
35158 |
++#endif |
35159 |
++ |
35160 |
++ } |
35161 |
++#endif |
35162 |
++ |
35163 |
+ error = arch_mmap_check(addr, len, flags); |
35164 |
+ if (error) |
35165 |
+ return error; |
35166 |
+ |
35167 |
++ charged = len >> PAGE_SHIFT; |
35168 |
++ |
35169 |
+ /* |
35170 |
+ * mlock MCL_FUTURE? |
35171 |
+ */ |
35172 |
+ if (mm->def_flags & VM_LOCKED) { |
35173 |
+ unsigned long locked, lock_limit; |
35174 |
+- locked = len >> PAGE_SHIFT; |
35175 |
++ locked = charged; |
35176 |
+ locked += mm->locked_vm; |
35177 |
+ lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur; |
35178 |
+ lock_limit >>= PAGE_SHIFT; |
35179 |
++ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1); |
35180 |
+ if (locked > lock_limit && !capable(CAP_IPC_LOCK)) |
35181 |
+ return -EAGAIN; |
35182 |
+ } |
35183 |
+@@ -2033,22 +2433,22 @@ unsigned long do_brk(unsigned long addr, |
35184 |
+ /* |
35185 |
+ * Clear old maps. this also does some error checking for us |
35186 |
+ */ |
35187 |
+- munmap_back: |
35188 |
+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); |
35189 |
+ if (vma && vma->vm_start < addr + len) { |
35190 |
+ if (do_munmap(mm, addr, len)) |
35191 |
+ return -ENOMEM; |
35192 |
+- goto munmap_back; |
35193 |
++ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); |
35194 |
++ BUG_ON(vma && vma->vm_start < addr + len); |
35195 |
+ } |
35196 |
+ |
35197 |
+ /* Check against address space limits *after* clearing old maps... */ |
35198 |
+- if (!may_expand_vm(mm, len >> PAGE_SHIFT)) |
35199 |
++ if (!may_expand_vm(mm, charged)) |
35200 |
+ return -ENOMEM; |
35201 |
+ |
35202 |
+ if (mm->map_count > sysctl_max_map_count) |
35203 |
+ return -ENOMEM; |
35204 |
+ |
35205 |
+- if (security_vm_enough_memory(len >> PAGE_SHIFT)) |
35206 |
++ if (security_vm_enough_memory(charged)) |
35207 |
+ return -ENOMEM; |
35208 |
+ |
35209 |
+ /* Can we just expand an old private anonymous mapping? */ |
35210 |
+@@ -2062,10 +2462,21 @@ unsigned long do_brk(unsigned long addr, |
35211 |
+ */ |
35212 |
+ vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
35213 |
+ if (!vma) { |
35214 |
+- vm_unacct_memory(len >> PAGE_SHIFT); |
35215 |
++ vm_unacct_memory(charged); |
35216 |
+ return -ENOMEM; |
35217 |
+ } |
35218 |
+ |
35219 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35220 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (flags & VM_EXEC)) { |
35221 |
++ vma_m = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
35222 |
++ if (!vma_m) { |
35223 |
++ kmem_cache_free(vm_area_cachep, vma); |
35224 |
++ vm_unacct_memory(charged); |
35225 |
++ return -ENOMEM; |
35226 |
++ } |
35227 |
++ } |
35228 |
++#endif |
35229 |
++ |
35230 |
+ vma->vm_mm = mm; |
35231 |
+ vma->vm_start = addr; |
35232 |
+ vma->vm_end = addr + len; |
35233 |
+@@ -2074,11 +2485,12 @@ unsigned long do_brk(unsigned long addr, |
35234 |
+ vma->vm_page_prot = vm_get_page_prot(flags); |
35235 |
+ vma_link(mm, vma, prev, rb_link, rb_parent); |
35236 |
+ out: |
35237 |
+- mm->total_vm += len >> PAGE_SHIFT; |
35238 |
++ mm->total_vm += charged; |
35239 |
+ if (flags & VM_LOCKED) { |
35240 |
+ if (!mlock_vma_pages_range(vma, addr, addr + len)) |
35241 |
+- mm->locked_vm += (len >> PAGE_SHIFT); |
35242 |
++ mm->locked_vm += charged; |
35243 |
+ } |
35244 |
++ track_exec_limit(mm, addr, addr + len, flags); |
35245 |
+ return addr; |
35246 |
+ } |
35247 |
+ |
35248 |
+@@ -2124,8 +2536,10 @@ void exit_mmap(struct mm_struct *mm) |
35249 |
+ * Walk the list again, actually closing and freeing it, |
35250 |
+ * with preemption enabled, without holding any MM locks. |
35251 |
+ */ |
35252 |
+- while (vma) |
35253 |
++ while (vma) { |
35254 |
++ vma->vm_mirror = NULL; |
35255 |
+ vma = remove_vma(vma); |
35256 |
++ } |
35257 |
+ |
35258 |
+ BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT); |
35259 |
+ } |
35260 |
+@@ -2139,6 +2553,10 @@ int insert_vm_struct(struct mm_struct * |
35261 |
+ struct vm_area_struct * __vma, * prev; |
35262 |
+ struct rb_node ** rb_link, * rb_parent; |
35263 |
+ |
35264 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35265 |
++ struct vm_area_struct *vma_m = NULL; |
35266 |
++#endif |
35267 |
++ |
35268 |
+ /* |
35269 |
+ * The vm_pgoff of a purely anonymous vma should be irrelevant |
35270 |
+ * until its first write fault, when page's anon_vma and index |
35271 |
+@@ -2161,7 +2579,22 @@ int insert_vm_struct(struct mm_struct * |
35272 |
+ if ((vma->vm_flags & VM_ACCOUNT) && |
35273 |
+ security_vm_enough_memory_mm(mm, vma_pages(vma))) |
35274 |
+ return -ENOMEM; |
35275 |
++ |
35276 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35277 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (vma->vm_flags & VM_EXEC)) { |
35278 |
++ vma_m = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
35279 |
++ if (!vma_m) |
35280 |
++ return -ENOMEM; |
35281 |
++ } |
35282 |
++#endif |
35283 |
++ |
35284 |
+ vma_link(mm, vma, prev, rb_link, rb_parent); |
35285 |
++ |
35286 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35287 |
++ if (vma_m) |
35288 |
++ pax_mirror_vma(vma_m, vma); |
35289 |
++#endif |
35290 |
++ |
35291 |
+ return 0; |
35292 |
+ } |
35293 |
+ |
35294 |
+@@ -2179,6 +2612,8 @@ struct vm_area_struct *copy_vma(struct v |
35295 |
+ struct rb_node **rb_link, *rb_parent; |
35296 |
+ struct mempolicy *pol; |
35297 |
+ |
35298 |
++ BUG_ON(vma->vm_mirror); |
35299 |
++ |
35300 |
+ /* |
35301 |
+ * If anonymous vma has not yet been faulted, update new pgoff |
35302 |
+ * to match new location, to increase its chance of merging. |
35303 |
+@@ -2222,6 +2657,35 @@ struct vm_area_struct *copy_vma(struct v |
35304 |
+ return new_vma; |
35305 |
+ } |
35306 |
+ |
35307 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35308 |
++void pax_mirror_vma(struct vm_area_struct *vma_m, struct vm_area_struct *vma) |
35309 |
++{ |
35310 |
++ struct vm_area_struct *prev_m; |
35311 |
++ struct rb_node **rb_link_m, *rb_parent_m; |
35312 |
++ struct mempolicy *pol_m; |
35313 |
++ |
35314 |
++ BUG_ON(!(vma->vm_mm->pax_flags & MF_PAX_SEGMEXEC) || !(vma->vm_flags & VM_EXEC)); |
35315 |
++ BUG_ON(vma->vm_mirror || vma_m->vm_mirror); |
35316 |
++ BUG_ON(!mpol_equal(vma_policy(vma), vma_policy(vma_m))); |
35317 |
++ *vma_m = *vma; |
35318 |
++ pol_m = vma_policy(vma_m); |
35319 |
++ mpol_get(pol_m); |
35320 |
++ vma_set_policy(vma_m, pol_m); |
35321 |
++ vma_m->vm_start += SEGMEXEC_TASK_SIZE; |
35322 |
++ vma_m->vm_end += SEGMEXEC_TASK_SIZE; |
35323 |
++ vma_m->vm_flags &= ~(VM_WRITE | VM_MAYWRITE | VM_ACCOUNT | VM_LOCKED); |
35324 |
++ vma_m->vm_page_prot = vm_get_page_prot(vma_m->vm_flags); |
35325 |
++ if (vma_m->vm_file) |
35326 |
++ get_file(vma_m->vm_file); |
35327 |
++ if (vma_m->vm_ops && vma_m->vm_ops->open) |
35328 |
++ vma_m->vm_ops->open(vma_m); |
35329 |
++ find_vma_prepare(vma->vm_mm, vma_m->vm_start, &prev_m, &rb_link_m, &rb_parent_m); |
35330 |
++ vma_link(vma->vm_mm, vma_m, prev_m, rb_link_m, rb_parent_m); |
35331 |
++ vma_m->vm_mirror = vma; |
35332 |
++ vma->vm_mirror = vma_m; |
35333 |
++} |
35334 |
++#endif |
35335 |
++ |
35336 |
+ /* |
35337 |
+ * Return true if the calling process may expand its vm space by the passed |
35338 |
+ * number of pages |
35339 |
+@@ -2232,7 +2696,7 @@ int may_expand_vm(struct mm_struct *mm, |
35340 |
+ unsigned long lim; |
35341 |
+ |
35342 |
+ lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT; |
35343 |
+- |
35344 |
++ gr_learn_resource(current, RLIMIT_AS, (cur + npages) << PAGE_SHIFT, 1); |
35345 |
+ if (cur + npages > lim) |
35346 |
+ return 0; |
35347 |
+ return 1; |
35348 |
+@@ -2301,6 +2765,15 @@ int install_special_mapping(struct mm_st |
35349 |
+ vma->vm_start = addr; |
35350 |
+ vma->vm_end = addr + len; |
35351 |
+ |
35352 |
++#ifdef CONFIG_PAX_MPROTECT |
35353 |
++ if (mm->pax_flags & MF_PAX_MPROTECT) { |
35354 |
++ if ((vm_flags & (VM_WRITE | VM_EXEC)) != VM_EXEC) |
35355 |
++ vm_flags &= ~(VM_EXEC | VM_MAYEXEC); |
35356 |
++ else |
35357 |
++ vm_flags &= ~(VM_WRITE | VM_MAYWRITE); |
35358 |
++ } |
35359 |
++#endif |
35360 |
++ |
35361 |
+ vma->vm_flags = vm_flags | mm->def_flags | VM_DONTEXPAND; |
35362 |
+ vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); |
35363 |
+ |
35364 |
+diff -urNp linux-2.6.28.8/mm/mprotect.c linux-2.6.28.8/mm/mprotect.c |
35365 |
+--- linux-2.6.28.8/mm/mprotect.c 2009-02-06 16:47:45.000000000 -0500 |
35366 |
++++ linux-2.6.28.8/mm/mprotect.c 2009-02-21 09:37:50.000000000 -0500 |
35367 |
+@@ -22,10 +22,16 @@ |
35368 |
+ #include <linux/swap.h> |
35369 |
+ #include <linux/swapops.h> |
35370 |
+ #include <linux/mmu_notifier.h> |
35371 |
++ |
35372 |
++#ifdef CONFIG_PAX_MPROTECT |
35373 |
++#include <linux/elf.h> |
35374 |
++#endif |
35375 |
++ |
35376 |
+ #include <asm/uaccess.h> |
35377 |
+ #include <asm/pgtable.h> |
35378 |
+ #include <asm/cacheflush.h> |
35379 |
+ #include <asm/tlbflush.h> |
35380 |
++#include <asm/mmu_context.h> |
35381 |
+ |
35382 |
+ #ifndef pgprot_modify |
35383 |
+ static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) |
35384 |
+@@ -133,6 +139,48 @@ static void change_protection(struct vm_ |
35385 |
+ flush_tlb_range(vma, start, end); |
35386 |
+ } |
35387 |
+ |
35388 |
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT |
35389 |
++/* called while holding the mmap semaphor for writing except stack expansion */ |
35390 |
++void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot) |
35391 |
++{ |
35392 |
++ unsigned long oldlimit, newlimit = 0UL; |
35393 |
++ |
35394 |
++ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || nx_enabled) |
35395 |
++ return; |
35396 |
++ |
35397 |
++ spin_lock(&mm->page_table_lock); |
35398 |
++ oldlimit = mm->context.user_cs_limit; |
35399 |
++ if ((prot & VM_EXEC) && oldlimit < end) |
35400 |
++ /* USER_CS limit moved up */ |
35401 |
++ newlimit = end; |
35402 |
++ else if (!(prot & VM_EXEC) && start < oldlimit && oldlimit <= end) |
35403 |
++ /* USER_CS limit moved down */ |
35404 |
++ newlimit = start; |
35405 |
++ |
35406 |
++ if (newlimit) { |
35407 |
++ mm->context.user_cs_limit = newlimit; |
35408 |
++ |
35409 |
++#ifdef CONFIG_SMP |
35410 |
++ wmb(); |
35411 |
++ cpus_clear(mm->context.cpu_user_cs_mask); |
35412 |
++ cpu_set(smp_processor_id(), mm->context.cpu_user_cs_mask); |
35413 |
++#endif |
35414 |
++ |
35415 |
++ set_user_cs(mm->context.user_cs_base, mm->context.user_cs_limit, smp_processor_id()); |
35416 |
++ } |
35417 |
++ spin_unlock(&mm->page_table_lock); |
35418 |
++ if (newlimit == end) { |
35419 |
++ struct vm_area_struct *vma = find_vma(mm, oldlimit); |
35420 |
++ |
35421 |
++ for (; vma && vma->vm_start < end; vma = vma->vm_next) |
35422 |
++ if (is_vm_hugetlb_page(vma)) |
35423 |
++ hugetlb_change_protection(vma, vma->vm_start, vma->vm_end, vma->vm_page_prot); |
35424 |
++ else |
35425 |
++ change_protection(vma, vma->vm_start, vma->vm_end, vma->vm_page_prot, vma_wants_writenotify(vma)); |
35426 |
++ } |
35427 |
++} |
35428 |
++#endif |
35429 |
++ |
35430 |
+ int |
35431 |
+ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, |
35432 |
+ unsigned long start, unsigned long end, unsigned long newflags) |
35433 |
+@@ -145,6 +193,14 @@ mprotect_fixup(struct vm_area_struct *vm |
35434 |
+ int error; |
35435 |
+ int dirty_accountable = 0; |
35436 |
+ |
35437 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35438 |
++ struct vm_area_struct *vma_m = NULL; |
35439 |
++ unsigned long start_m, end_m; |
35440 |
++ |
35441 |
++ start_m = start + SEGMEXEC_TASK_SIZE; |
35442 |
++ end_m = end + SEGMEXEC_TASK_SIZE; |
35443 |
++#endif |
35444 |
++ |
35445 |
+ if (newflags == oldflags) { |
35446 |
+ *pprev = vma; |
35447 |
+ return 0; |
35448 |
+@@ -165,6 +221,38 @@ mprotect_fixup(struct vm_area_struct *vm |
35449 |
+ } |
35450 |
+ } |
35451 |
+ |
35452 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35453 |
++ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && ((oldflags ^ newflags) & VM_EXEC)) { |
35454 |
++ if (start != vma->vm_start) { |
35455 |
++ error = split_vma(mm, vma, start, 1); |
35456 |
++ if (error) |
35457 |
++ goto fail; |
35458 |
++ BUG_ON(!*pprev || (*pprev)->vm_next == vma); |
35459 |
++ *pprev = (*pprev)->vm_next; |
35460 |
++ } |
35461 |
++ |
35462 |
++ if (end != vma->vm_end) { |
35463 |
++ error = split_vma(mm, vma, end, 0); |
35464 |
++ if (error) |
35465 |
++ goto fail; |
35466 |
++ } |
35467 |
++ |
35468 |
++ if (pax_find_mirror_vma(vma)) { |
35469 |
++ error = __do_munmap(mm, start_m, end_m - start_m); |
35470 |
++ if (error) |
35471 |
++ goto fail; |
35472 |
++ } else { |
35473 |
++ vma_m = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); |
35474 |
++ if (!vma_m) { |
35475 |
++ error = -ENOMEM; |
35476 |
++ goto fail; |
35477 |
++ } |
35478 |
++ vma->vm_flags = newflags; |
35479 |
++ pax_mirror_vma(vma_m, vma); |
35480 |
++ } |
35481 |
++ } |
35482 |
++#endif |
35483 |
++ |
35484 |
+ /* |
35485 |
+ * First try to merge with previous and/or next vma. |
35486 |
+ */ |
35487 |
+@@ -196,8 +284,14 @@ success: |
35488 |
+ * held in write mode. |
35489 |
+ */ |
35490 |
+ vma->vm_flags = newflags; |
35491 |
++ |
35492 |
++#ifdef CONFIG_PAX_MPROTECT |
35493 |
++ if (current->binfmt && current->binfmt->handle_mprotect) |
35494 |
++ current->binfmt->handle_mprotect(vma, newflags); |
35495 |
++#endif |
35496 |
++ |
35497 |
+ vma->vm_page_prot = pgprot_modify(vma->vm_page_prot, |
35498 |
+- vm_get_page_prot(newflags)); |
35499 |
++ vm_get_page_prot(vma->vm_flags)); |
35500 |
+ |
35501 |
+ if (vma_wants_writenotify(vma)) { |
35502 |
+ vma->vm_page_prot = vm_get_page_prot(newflags & ~VM_SHARED); |
35503 |
+@@ -238,6 +332,17 @@ SYSCALL_DEFINE3(mprotect, unsigned long, |
35504 |
+ end = start + len; |
35505 |
+ if (end <= start) |
35506 |
+ return -ENOMEM; |
35507 |
++ |
35508 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35509 |
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) { |
35510 |
++ if (end > SEGMEXEC_TASK_SIZE) |
35511 |
++ return -EINVAL; |
35512 |
++ } else |
35513 |
++#endif |
35514 |
++ |
35515 |
++ if (end > TASK_SIZE) |
35516 |
++ return -EINVAL; |
35517 |
++ |
35518 |
+ if (!arch_validate_prot(prot)) |
35519 |
+ return -EINVAL; |
35520 |
+ |
35521 |
+@@ -245,7 +350,7 @@ SYSCALL_DEFINE3(mprotect, unsigned long, |
35522 |
+ /* |
35523 |
+ * Does the application expect PROT_READ to imply PROT_EXEC: |
35524 |
+ */ |
35525 |
+- if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC)) |
35526 |
++ if ((prot & (PROT_READ | PROT_WRITE)) && (current->personality & READ_IMPLIES_EXEC)) |
35527 |
+ prot |= PROT_EXEC; |
35528 |
+ |
35529 |
+ vm_flags = calc_vm_prot_bits(prot); |
35530 |
+@@ -277,6 +382,16 @@ SYSCALL_DEFINE3(mprotect, unsigned long, |
35531 |
+ if (start > vma->vm_start) |
35532 |
+ prev = vma; |
35533 |
+ |
35534 |
++ if (!gr_acl_handle_mprotect(vma->vm_file, prot)) { |
35535 |
++ error = -EACCES; |
35536 |
++ goto out; |
35537 |
++ } |
35538 |
++ |
35539 |
++#ifdef CONFIG_PAX_MPROTECT |
35540 |
++ if (current->binfmt && current->binfmt->handle_mprotect) |
35541 |
++ current->binfmt->handle_mprotect(vma, vm_flags); |
35542 |
++#endif |
35543 |
++ |
35544 |
+ for (nstart = start ; ; ) { |
35545 |
+ unsigned long newflags; |
35546 |
+ |
35547 |
+@@ -300,6 +415,9 @@ SYSCALL_DEFINE3(mprotect, unsigned long, |
35548 |
+ error = mprotect_fixup(vma, &prev, nstart, tmp, newflags); |
35549 |
+ if (error) |
35550 |
+ goto out; |
35551 |
++ |
35552 |
++ track_exec_limit(current->mm, nstart, tmp, vm_flags); |
35553 |
++ |
35554 |
+ nstart = tmp; |
35555 |
+ |
35556 |
+ if (nstart < prev->vm_end) |
35557 |
+diff -urNp linux-2.6.28.8/mm/mremap.c linux-2.6.28.8/mm/mremap.c |
35558 |
+--- linux-2.6.28.8/mm/mremap.c 2009-02-06 16:47:45.000000000 -0500 |
35559 |
++++ linux-2.6.28.8/mm/mremap.c 2009-02-21 09:37:50.000000000 -0500 |
35560 |
+@@ -113,6 +113,12 @@ static void move_ptes(struct vm_area_str |
35561 |
+ continue; |
35562 |
+ pte = ptep_clear_flush(vma, old_addr, old_pte); |
35563 |
+ pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr); |
35564 |
++ |
35565 |
++#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT |
35566 |
++ if (!nx_enabled && (new_vma->vm_flags & (VM_PAGEEXEC | VM_EXEC)) == VM_PAGEEXEC) |
35567 |
++ pte = pte_exprotect(pte); |
35568 |
++#endif |
35569 |
++ |
35570 |
+ set_pte_at(mm, new_addr, new_pte, pte); |
35571 |
+ } |
35572 |
+ |
35573 |
+@@ -262,6 +268,7 @@ unsigned long do_mremap(unsigned long ad |
35574 |
+ struct vm_area_struct *vma; |
35575 |
+ unsigned long ret = -EINVAL; |
35576 |
+ unsigned long charged = 0; |
35577 |
++ unsigned long pax_task_size = TASK_SIZE; |
35578 |
+ |
35579 |
+ if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE)) |
35580 |
+ goto out; |
35581 |
+@@ -280,6 +287,15 @@ unsigned long do_mremap(unsigned long ad |
35582 |
+ if (!new_len) |
35583 |
+ goto out; |
35584 |
+ |
35585 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35586 |
++ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) |
35587 |
++ pax_task_size = SEGMEXEC_TASK_SIZE; |
35588 |
++#endif |
35589 |
++ |
35590 |
++ if (new_len > pax_task_size || addr > pax_task_size-new_len || |
35591 |
++ old_len > pax_task_size || addr > pax_task_size-old_len) |
35592 |
++ goto out; |
35593 |
++ |
35594 |
+ /* new_addr is only valid if MREMAP_FIXED is specified */ |
35595 |
+ if (flags & MREMAP_FIXED) { |
35596 |
+ if (new_addr & ~PAGE_MASK) |
35597 |
+@@ -287,16 +303,13 @@ unsigned long do_mremap(unsigned long ad |
35598 |
+ if (!(flags & MREMAP_MAYMOVE)) |
35599 |
+ goto out; |
35600 |
+ |
35601 |
+- if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len) |
35602 |
++ if (new_addr > pax_task_size - new_len) |
35603 |
+ goto out; |
35604 |
+ |
35605 |
+ /* Check if the location we're moving into overlaps the |
35606 |
+ * old location at all, and fail if it does. |
35607 |
+ */ |
35608 |
+- if ((new_addr <= addr) && (new_addr+new_len) > addr) |
35609 |
+- goto out; |
35610 |
+- |
35611 |
+- if ((addr <= new_addr) && (addr+old_len) > new_addr) |
35612 |
++ if (addr + old_len > new_addr && new_addr + new_len > addr) |
35613 |
+ goto out; |
35614 |
+ |
35615 |
+ ret = security_file_mmap(NULL, 0, 0, 0, new_addr, 1); |
35616 |
+@@ -334,6 +347,14 @@ unsigned long do_mremap(unsigned long ad |
35617 |
+ ret = -EINVAL; |
35618 |
+ goto out; |
35619 |
+ } |
35620 |
++ |
35621 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35622 |
++ if (pax_find_mirror_vma(vma)) { |
35623 |
++ ret = -EINVAL; |
35624 |
++ goto out; |
35625 |
++ } |
35626 |
++#endif |
35627 |
++ |
35628 |
+ /* We can't remap across vm area boundaries */ |
35629 |
+ if (old_len > vma->vm_end - addr) |
35630 |
+ goto out; |
35631 |
+@@ -367,7 +388,7 @@ unsigned long do_mremap(unsigned long ad |
35632 |
+ if (old_len == vma->vm_end - addr && |
35633 |
+ !((flags & MREMAP_FIXED) && (addr != new_addr)) && |
35634 |
+ (old_len != new_len || !(flags & MREMAP_MAYMOVE))) { |
35635 |
+- unsigned long max_addr = TASK_SIZE; |
35636 |
++ unsigned long max_addr = pax_task_size; |
35637 |
+ if (vma->vm_next) |
35638 |
+ max_addr = vma->vm_next->vm_start; |
35639 |
+ /* can we just expand the current mapping? */ |
35640 |
+@@ -385,6 +406,7 @@ unsigned long do_mremap(unsigned long ad |
35641 |
+ addr + new_len); |
35642 |
+ } |
35643 |
+ ret = addr; |
35644 |
++ track_exec_limit(vma->vm_mm, vma->vm_start, addr + new_len, vma->vm_flags); |
35645 |
+ goto out; |
35646 |
+ } |
35647 |
+ } |
35648 |
+@@ -395,8 +417,8 @@ unsigned long do_mremap(unsigned long ad |
35649 |
+ */ |
35650 |
+ ret = -ENOMEM; |
35651 |
+ if (flags & MREMAP_MAYMOVE) { |
35652 |
++ unsigned long map_flags = 0; |
35653 |
+ if (!(flags & MREMAP_FIXED)) { |
35654 |
+- unsigned long map_flags = 0; |
35655 |
+ if (vma->vm_flags & VM_MAYSHARE) |
35656 |
+ map_flags |= MAP_SHARED; |
35657 |
+ |
35658 |
+@@ -411,7 +433,12 @@ unsigned long do_mremap(unsigned long ad |
35659 |
+ if (ret) |
35660 |
+ goto out; |
35661 |
+ } |
35662 |
++ map_flags = vma->vm_flags; |
35663 |
+ ret = move_vma(vma, addr, old_len, new_len, new_addr); |
35664 |
++ if (!(ret & ~PAGE_MASK)) { |
35665 |
++ track_exec_limit(current->mm, addr, addr + old_len, 0UL); |
35666 |
++ track_exec_limit(current->mm, new_addr, new_addr + new_len, map_flags); |
35667 |
++ } |
35668 |
+ } |
35669 |
+ out: |
35670 |
+ if (ret & ~PAGE_MASK) |
35671 |
+diff -urNp linux-2.6.28.8/mm/nommu.c linux-2.6.28.8/mm/nommu.c |
35672 |
+--- linux-2.6.28.8/mm/nommu.c 2009-02-06 16:47:45.000000000 -0500 |
35673 |
++++ linux-2.6.28.8/mm/nommu.c 2009-02-21 09:37:50.000000000 -0500 |
35674 |
+@@ -459,15 +459,6 @@ struct vm_area_struct *find_vma(struct m |
35675 |
+ } |
35676 |
+ EXPORT_SYMBOL(find_vma); |
35677 |
+ |
35678 |
+-/* |
35679 |
+- * find a VMA |
35680 |
+- * - we don't extend stack VMAs under NOMMU conditions |
35681 |
+- */ |
35682 |
+-struct vm_area_struct *find_extend_vma(struct mm_struct *mm, unsigned long addr) |
35683 |
+-{ |
35684 |
+- return find_vma(mm, addr); |
35685 |
+-} |
35686 |
+- |
35687 |
+ int expand_stack(struct vm_area_struct *vma, unsigned long address) |
35688 |
+ { |
35689 |
+ return -ENOMEM; |
35690 |
+diff -urNp linux-2.6.28.8/mm/page_alloc.c linux-2.6.28.8/mm/page_alloc.c |
35691 |
+--- linux-2.6.28.8/mm/page_alloc.c 2009-03-07 10:24:49.000000000 -0500 |
35692 |
++++ linux-2.6.28.8/mm/page_alloc.c 2009-03-07 10:29:51.000000000 -0500 |
35693 |
+@@ -525,6 +525,10 @@ static void __free_pages_ok(struct page |
35694 |
+ int i; |
35695 |
+ int reserved = 0; |
35696 |
+ |
35697 |
++#ifdef CONFIG_PAX_MEMORY_SANITIZE |
35698 |
++ unsigned long index = 1UL << order; |
35699 |
++#endif |
35700 |
++ |
35701 |
+ for (i = 0 ; i < (1 << order) ; ++i) |
35702 |
+ reserved += free_pages_check(page + i); |
35703 |
+ if (reserved) |
35704 |
+@@ -535,6 +539,12 @@ static void __free_pages_ok(struct page |
35705 |
+ debug_check_no_obj_freed(page_address(page), |
35706 |
+ PAGE_SIZE << order); |
35707 |
+ } |
35708 |
++ |
35709 |
++#ifdef CONFIG_PAX_MEMORY_SANITIZE |
35710 |
++ for (; index; --index) |
35711 |
++ sanitize_highpage(page + index - 1); |
35712 |
++#endif |
35713 |
++ |
35714 |
+ arch_free_page(page, order); |
35715 |
+ kernel_map_pages(page, 1 << order, 0); |
35716 |
+ |
35717 |
+@@ -635,8 +645,10 @@ static int prep_new_page(struct page *pa |
35718 |
+ arch_alloc_page(page, order); |
35719 |
+ kernel_map_pages(page, 1 << order, 1); |
35720 |
+ |
35721 |
++#ifndef CONFIG_PAX_MEMORY_SANITIZE |
35722 |
+ if (gfp_flags & __GFP_ZERO) |
35723 |
+ prep_zero_page(page, order, gfp_flags); |
35724 |
++#endif |
35725 |
+ |
35726 |
+ if (order && (gfp_flags & __GFP_COMP)) |
35727 |
+ prep_compound_page(page, order); |
35728 |
+@@ -997,6 +1009,11 @@ static void free_hot_cold_page(struct pa |
35729 |
+ debug_check_no_locks_freed(page_address(page), PAGE_SIZE); |
35730 |
+ debug_check_no_obj_freed(page_address(page), PAGE_SIZE); |
35731 |
+ } |
35732 |
++ |
35733 |
++#ifdef CONFIG_PAX_MEMORY_SANITIZE |
35734 |
++ sanitize_highpage(page); |
35735 |
++#endif |
35736 |
++ |
35737 |
+ arch_free_page(page, 0); |
35738 |
+ kernel_map_pages(page, 1, 0); |
35739 |
+ |
35740 |
+diff -urNp linux-2.6.28.8/mm/rmap.c linux-2.6.28.8/mm/rmap.c |
35741 |
+--- linux-2.6.28.8/mm/rmap.c 2009-02-06 16:47:45.000000000 -0500 |
35742 |
++++ linux-2.6.28.8/mm/rmap.c 2009-02-21 09:37:50.000000000 -0500 |
35743 |
+@@ -103,6 +103,10 @@ int anon_vma_prepare(struct vm_area_stru |
35744 |
+ struct mm_struct *mm = vma->vm_mm; |
35745 |
+ struct anon_vma *allocated; |
35746 |
+ |
35747 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35748 |
++ struct vm_area_struct *vma_m; |
35749 |
++#endif |
35750 |
++ |
35751 |
+ anon_vma = find_mergeable_anon_vma(vma); |
35752 |
+ allocated = NULL; |
35753 |
+ if (!anon_vma) { |
35754 |
+@@ -116,6 +120,15 @@ int anon_vma_prepare(struct vm_area_stru |
35755 |
+ /* page_table_lock to protect against threads */ |
35756 |
+ spin_lock(&mm->page_table_lock); |
35757 |
+ if (likely(!vma->anon_vma)) { |
35758 |
++ |
35759 |
++#ifdef CONFIG_PAX_SEGMEXEC |
35760 |
++ vma_m = pax_find_mirror_vma(vma); |
35761 |
++ if (vma_m) { |
35762 |
++ vma_m->anon_vma = anon_vma; |
35763 |
++ __anon_vma_link(vma_m); |
35764 |
++ } |
35765 |
++#endif |
35766 |
++ |
35767 |
+ vma->anon_vma = anon_vma; |
35768 |
+ list_add_tail(&vma->anon_vma_node, &anon_vma->head); |
35769 |
+ allocated = NULL; |
35770 |
+diff -urNp linux-2.6.28.8/mm/shmem.c linux-2.6.28.8/mm/shmem.c |
35771 |
+--- linux-2.6.28.8/mm/shmem.c 2009-02-06 16:47:45.000000000 -0500 |
35772 |
++++ linux-2.6.28.8/mm/shmem.c 2009-02-21 09:37:50.000000000 -0500 |
35773 |
+@@ -2486,7 +2486,7 @@ static struct file_system_type tmpfs_fs_ |
35774 |
+ .get_sb = shmem_get_sb, |
35775 |
+ .kill_sb = kill_litter_super, |
35776 |
+ }; |
35777 |
+-static struct vfsmount *shm_mnt; |
35778 |
++struct vfsmount *shm_mnt; |
35779 |
+ |
35780 |
+ static int __init init_tmpfs(void) |
35781 |
+ { |
35782 |
+diff -urNp linux-2.6.28.8/mm/slab.c linux-2.6.28.8/mm/slab.c |
35783 |
+--- linux-2.6.28.8/mm/slab.c 2009-02-06 16:47:45.000000000 -0500 |
35784 |
++++ linux-2.6.28.8/mm/slab.c 2009-02-21 09:37:50.000000000 -0500 |
35785 |
+@@ -305,7 +305,7 @@ struct kmem_list3 { |
35786 |
+ * Need this for bootstrapping a per node allocator. |
35787 |
+ */ |
35788 |
+ #define NUM_INIT_LISTS (3 * MAX_NUMNODES) |
35789 |
+-struct kmem_list3 __initdata initkmem_list3[NUM_INIT_LISTS]; |
35790 |
++struct kmem_list3 initkmem_list3[NUM_INIT_LISTS]; |
35791 |
+ #define CACHE_CACHE 0 |
35792 |
+ #define SIZE_AC MAX_NUMNODES |
35793 |
+ #define SIZE_L3 (2 * MAX_NUMNODES) |
35794 |
+@@ -654,14 +654,14 @@ struct cache_names { |
35795 |
+ static struct cache_names __initdata cache_names[] = { |
35796 |
+ #define CACHE(x) { .name = "size-" #x, .name_dma = "size-" #x "(DMA)" }, |
35797 |
+ #include <linux/kmalloc_sizes.h> |
35798 |
+- {NULL,} |
35799 |
++ {NULL, NULL} |
35800 |
+ #undef CACHE |
35801 |
+ }; |
35802 |
+ |
35803 |
+ static struct arraycache_init initarray_cache __initdata = |
35804 |
+- { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} }; |
35805 |
++ { {0, BOOT_CPUCACHE_ENTRIES, 1, 0}, {NULL} }; |
35806 |
+ static struct arraycache_init initarray_generic = |
35807 |
+- { {0, BOOT_CPUCACHE_ENTRIES, 1, 0} }; |
35808 |
++ { {0, BOOT_CPUCACHE_ENTRIES, 1, 0}, {NULL} }; |
35809 |
+ |
35810 |
+ /* internal cache of cache description objs */ |
35811 |
+ static struct kmem_cache cache_cache = { |
35812 |
+@@ -2997,7 +2997,7 @@ retry: |
35813 |
+ * there must be at least one object available for |
35814 |
+ * allocation. |
35815 |
+ */ |
35816 |
+- BUG_ON(slabp->inuse < 0 || slabp->inuse >= cachep->num); |
35817 |
++ BUG_ON(slabp->inuse >= cachep->num); |
35818 |
+ |
35819 |
+ while (slabp->inuse < cachep->num && batchcount--) { |
35820 |
+ STATS_INC_ALLOCED(cachep); |
35821 |
+@@ -4491,10 +4491,12 @@ static const struct file_operations proc |
35822 |
+ |
35823 |
+ static int __init slab_proc_init(void) |
35824 |
+ { |
35825 |
++#if !defined(CONFIG_GRKERNSEC_PROC_ADD) |
35826 |
+ proc_create("slabinfo",S_IWUSR|S_IRUGO,NULL,&proc_slabinfo_operations); |
35827 |
+ #ifdef CONFIG_DEBUG_SLAB_LEAK |
35828 |
+ proc_create("slab_allocators", 0, NULL, &proc_slabstats_operations); |
35829 |
+ #endif |
35830 |
++#endif |
35831 |
+ return 0; |
35832 |
+ } |
35833 |
+ module_init(slab_proc_init); |
35834 |
+diff -urNp linux-2.6.28.8/mm/slub.c linux-2.6.28.8/mm/slub.c |
35835 |
+--- linux-2.6.28.8/mm/slub.c 2009-02-06 16:47:45.000000000 -0500 |
35836 |
++++ linux-2.6.28.8/mm/slub.c 2009-02-21 09:37:50.000000000 -0500 |
35837 |
+@@ -4508,7 +4508,9 @@ static const struct file_operations proc |
35838 |
+ |
35839 |
+ static int __init slab_proc_init(void) |
35840 |
+ { |
35841 |
++#if !defined(CONFIG_GRKERNSEC_PROC_ADD) |
35842 |
+ proc_create("slabinfo",S_IWUSR|S_IRUGO,NULL,&proc_slabinfo_operations); |
35843 |
++#endif |
35844 |
+ return 0; |
35845 |
+ } |
35846 |
+ module_init(slab_proc_init); |
35847 |
+diff -urNp linux-2.6.28.8/mm/tiny-shmem.c linux-2.6.28.8/mm/tiny-shmem.c |
35848 |
+--- linux-2.6.28.8/mm/tiny-shmem.c 2009-02-06 16:47:45.000000000 -0500 |
35849 |
++++ linux-2.6.28.8/mm/tiny-shmem.c 2009-02-21 09:37:50.000000000 -0500 |
35850 |
+@@ -26,7 +26,7 @@ static struct file_system_type tmpfs_fs_ |
35851 |
+ .kill_sb = kill_litter_super, |
35852 |
+ }; |
35853 |
+ |
35854 |
+-static struct vfsmount *shm_mnt; |
35855 |
++struct vfsmount *shm_mnt; |
35856 |
+ |
35857 |
+ static int __init init_tmpfs(void) |
35858 |
+ { |
35859 |
+diff -urNp linux-2.6.28.8/mm/util.c linux-2.6.28.8/mm/util.c |
35860 |
+--- linux-2.6.28.8/mm/util.c 2009-02-06 16:47:45.000000000 -0500 |
35861 |
++++ linux-2.6.28.8/mm/util.c 2009-02-21 09:37:50.000000000 -0500 |
35862 |
+@@ -167,6 +167,12 @@ EXPORT_SYMBOL(strndup_user); |
35863 |
+ void arch_pick_mmap_layout(struct mm_struct *mm) |
35864 |
+ { |
35865 |
+ mm->mmap_base = TASK_UNMAPPED_BASE; |
35866 |
++ |
35867 |
++#ifdef CONFIG_PAX_RANDMMAP |
35868 |
++ if (mm->pax_flags & MF_PAX_RANDMMAP) |
35869 |
++ mm->mmap_base += mm->delta_mmap; |
35870 |
++#endif |
35871 |
++ |
35872 |
+ mm->get_unmapped_area = arch_get_unmapped_area; |
35873 |
+ mm->unmap_area = arch_unmap_area; |
35874 |
+ } |
35875 |
+diff -urNp linux-2.6.28.8/mm/vmalloc.c linux-2.6.28.8/mm/vmalloc.c |
35876 |
+--- linux-2.6.28.8/mm/vmalloc.c 2009-03-07 10:24:49.000000000 -0500 |
35877 |
++++ linux-2.6.28.8/mm/vmalloc.c 2009-03-07 10:29:51.000000000 -0500 |
35878 |
+@@ -90,6 +90,11 @@ static int vmap_pte_range(pmd_t *pmd, un |
35879 |
+ unsigned long end, pgprot_t prot, struct page **pages, int *nr) |
35880 |
+ { |
35881 |
+ pte_t *pte; |
35882 |
++ int ret = -ENOMEM; |
35883 |
++ |
35884 |
++#ifdef CONFIG_PAX_KERNEXEC |
35885 |
++ unsigned long cr0; |
35886 |
++#endif |
35887 |
+ |
35888 |
+ /* |
35889 |
+ * nr is a running index into the array which helps higher level |
35890 |
+@@ -99,17 +104,33 @@ static int vmap_pte_range(pmd_t *pmd, un |
35891 |
+ pte = pte_alloc_kernel(pmd, addr); |
35892 |
+ if (!pte) |
35893 |
+ return -ENOMEM; |
35894 |
++ |
35895 |
++#ifdef CONFIG_PAX_KERNEXEC |
35896 |
++ pax_open_kernel(cr0); |
35897 |
++#endif |
35898 |
++ |
35899 |
+ do { |
35900 |
+ struct page *page = pages[*nr]; |
35901 |
+ |
35902 |
+- if (WARN_ON(!pte_none(*pte))) |
35903 |
+- return -EBUSY; |
35904 |
+- if (WARN_ON(!page)) |
35905 |
+- return -ENOMEM; |
35906 |
++ if (WARN_ON(!pte_none(*pte))) { |
35907 |
++ ret = -EBUSY; |
35908 |
++ goto out; |
35909 |
++ } |
35910 |
++ if (WARN_ON(!page)) { |
35911 |
++ ret = -ENOMEM; |
35912 |
++ goto out; |
35913 |
++ } |
35914 |
+ set_pte_at(&init_mm, addr, pte, mk_pte(page, prot)); |
35915 |
+ (*nr)++; |
35916 |
+ } while (pte++, addr += PAGE_SIZE, addr != end); |
35917 |
+- return 0; |
35918 |
++ ret = 0; |
35919 |
++out: |
35920 |
++ |
35921 |
++#ifdef CONFIG_PAX_KERNEXEC |
35922 |
++ pax_close_kernel(cr0); |
35923 |
++#endif |
35924 |
++ |
35925 |
++ return ret; |
35926 |
+ } |
35927 |
+ |
35928 |
+ static int vmap_pmd_range(pud_t *pud, unsigned long addr, |
35929 |
+@@ -1033,6 +1054,16 @@ static struct vm_struct *__get_vm_area_n |
35930 |
+ unsigned long align = 1; |
35931 |
+ |
35932 |
+ BUG_ON(in_interrupt()); |
35933 |
++ |
35934 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) |
35935 |
++ if (flags & VM_KERNEXEC) { |
35936 |
++ if (start != VMALLOC_START || end != VMALLOC_END) |
35937 |
++ return NULL; |
35938 |
++ start = (unsigned long)MODULES_VADDR; |
35939 |
++ end = (unsigned long)MODULES_END; |
35940 |
++ } |
35941 |
++#endif |
35942 |
++ |
35943 |
+ if (flags & VM_IOREMAP) { |
35944 |
+ int bit = fls(size); |
35945 |
+ |
35946 |
+@@ -1256,6 +1287,11 @@ void *vmap(struct page **pages, unsigned |
35947 |
+ if (count > num_physpages) |
35948 |
+ return NULL; |
35949 |
+ |
35950 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) |
35951 |
++ if (!(pgprot_val(prot) & _PAGE_NX)) |
35952 |
++ flags |= VM_KERNEXEC; |
35953 |
++#endif |
35954 |
++ |
35955 |
+ area = get_vm_area_caller((count << PAGE_SHIFT), flags, |
35956 |
+ __builtin_return_address(0)); |
35957 |
+ if (!area) |
35958 |
+@@ -1352,6 +1388,13 @@ static void *__vmalloc_node(unsigned lon |
35959 |
+ if (!size || (size >> PAGE_SHIFT) > num_physpages) |
35960 |
+ return NULL; |
35961 |
+ |
35962 |
++#if defined(CONFIG_MODULES) && defined(CONFIG_X86_32) && defined(CONFIG_PAX_KERNEXEC) |
35963 |
++ if (!(pgprot_val(prot) & _PAGE_NX)) |
35964 |
++ area = __get_vm_area_node(size, VM_ALLOC | VM_KERNEXEC, VMALLOC_START, VMALLOC_END, |
35965 |
++ node, gfp_mask, caller); |
35966 |
++ else |
35967 |
++#endif |
35968 |
++ |
35969 |
+ area = __get_vm_area_node(size, VM_ALLOC, VMALLOC_START, VMALLOC_END, |
35970 |
+ node, gfp_mask, caller); |
35971 |
+ |
35972 |
+@@ -1441,7 +1484,7 @@ EXPORT_SYMBOL(vmalloc_node); |
35973 |
+ |
35974 |
+ void *vmalloc_exec(unsigned long size) |
35975 |
+ { |
35976 |
+- return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC); |
35977 |
++ return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL_EXEC); |
35978 |
+ } |
35979 |
+ |
35980 |
+ #if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32) |
35981 |
+diff -urNp linux-2.6.28.8/net/bridge/br_stp_if.c linux-2.6.28.8/net/bridge/br_stp_if.c |
35982 |
+--- linux-2.6.28.8/net/bridge/br_stp_if.c 2009-02-06 16:47:45.000000000 -0500 |
35983 |
++++ linux-2.6.28.8/net/bridge/br_stp_if.c 2009-02-21 09:37:50.000000000 -0500 |
35984 |
+@@ -146,7 +146,7 @@ static void br_stp_stop(struct net_bridg |
35985 |
+ char *envp[] = { NULL }; |
35986 |
+ |
35987 |
+ if (br->stp_enabled == BR_USER_STP) { |
35988 |
+- r = call_usermodehelper(BR_STP_PROG, argv, envp, 1); |
35989 |
++ r = call_usermodehelper(BR_STP_PROG, argv, envp, UMH_WAIT_PROC); |
35990 |
+ printk(KERN_INFO "%s: userspace STP stopped, return code %d\n", |
35991 |
+ br->dev->name, r); |
35992 |
+ |
35993 |
+diff -urNp linux-2.6.28.8/net/core/flow.c linux-2.6.28.8/net/core/flow.c |
35994 |
+--- linux-2.6.28.8/net/core/flow.c 2009-02-06 16:47:45.000000000 -0500 |
35995 |
++++ linux-2.6.28.8/net/core/flow.c 2009-02-21 09:37:50.000000000 -0500 |
35996 |
+@@ -39,7 +39,7 @@ atomic_t flow_cache_genid = ATOMIC_INIT( |
35997 |
+ |
35998 |
+ static u32 flow_hash_shift; |
35999 |
+ #define flow_hash_size (1 << flow_hash_shift) |
36000 |
+-static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables) = { NULL }; |
36001 |
++static DEFINE_PER_CPU(struct flow_cache_entry **, flow_tables); |
36002 |
+ |
36003 |
+ #define flow_table(cpu) (per_cpu(flow_tables, cpu)) |
36004 |
+ |
36005 |
+@@ -52,7 +52,7 @@ struct flow_percpu_info { |
36006 |
+ u32 hash_rnd; |
36007 |
+ int count; |
36008 |
+ }; |
36009 |
+-static DEFINE_PER_CPU(struct flow_percpu_info, flow_hash_info) = { 0 }; |
36010 |
++static DEFINE_PER_CPU(struct flow_percpu_info, flow_hash_info); |
36011 |
+ |
36012 |
+ #define flow_hash_rnd_recalc(cpu) \ |
36013 |
+ (per_cpu(flow_hash_info, cpu).hash_rnd_recalc) |
36014 |
+@@ -69,7 +69,7 @@ struct flow_flush_info { |
36015 |
+ atomic_t cpuleft; |
36016 |
+ struct completion completion; |
36017 |
+ }; |
36018 |
+-static DEFINE_PER_CPU(struct tasklet_struct, flow_flush_tasklets) = { NULL }; |
36019 |
++static DEFINE_PER_CPU(struct tasklet_struct, flow_flush_tasklets); |
36020 |
+ |
36021 |
+ #define flow_flush_tasklet(cpu) (&per_cpu(flow_flush_tasklets, cpu)) |
36022 |
+ |
36023 |
+diff -urNp linux-2.6.28.8/net/dccp/ccids/ccid3.c linux-2.6.28.8/net/dccp/ccids/ccid3.c |
36024 |
+--- linux-2.6.28.8/net/dccp/ccids/ccid3.c 2009-02-06 16:47:45.000000000 -0500 |
36025 |
++++ linux-2.6.28.8/net/dccp/ccids/ccid3.c 2009-02-21 09:37:50.000000000 -0500 |
36026 |
+@@ -43,7 +43,7 @@ |
36027 |
+ static int ccid3_debug; |
36028 |
+ #define ccid3_pr_debug(format, a...) DCCP_PR_DEBUG(ccid3_debug, format, ##a) |
36029 |
+ #else |
36030 |
+-#define ccid3_pr_debug(format, a...) |
36031 |
++#define ccid3_pr_debug(format, a...) do {} while (0) |
36032 |
+ #endif |
36033 |
+ |
36034 |
+ /* |
36035 |
+diff -urNp linux-2.6.28.8/net/dccp/dccp.h linux-2.6.28.8/net/dccp/dccp.h |
36036 |
+--- linux-2.6.28.8/net/dccp/dccp.h 2009-02-06 16:47:45.000000000 -0500 |
36037 |
++++ linux-2.6.28.8/net/dccp/dccp.h 2009-02-21 09:37:50.000000000 -0500 |
36038 |
+@@ -43,8 +43,8 @@ extern int dccp_debug; |
36039 |
+ #define dccp_pr_debug(format, a...) DCCP_PR_DEBUG(dccp_debug, format, ##a) |
36040 |
+ #define dccp_pr_debug_cat(format, a...) DCCP_PRINTK(dccp_debug, format, ##a) |
36041 |
+ #else |
36042 |
+-#define dccp_pr_debug(format, a...) |
36043 |
+-#define dccp_pr_debug_cat(format, a...) |
36044 |
++#define dccp_pr_debug(format, a...) do {} while (0) |
36045 |
++#define dccp_pr_debug_cat(format, a...) do {} while (0) |
36046 |
+ #endif |
36047 |
+ |
36048 |
+ extern struct inet_hashinfo dccp_hashinfo; |
36049 |
+diff -urNp linux-2.6.28.8/net/ipv4/inet_connection_sock.c linux-2.6.28.8/net/ipv4/inet_connection_sock.c |
36050 |
+--- linux-2.6.28.8/net/ipv4/inet_connection_sock.c 2009-02-06 16:47:45.000000000 -0500 |
36051 |
++++ linux-2.6.28.8/net/ipv4/inet_connection_sock.c 2009-02-21 09:37:50.000000000 -0500 |
36052 |
+@@ -15,6 +15,7 @@ |
36053 |
+ |
36054 |
+ #include <linux/module.h> |
36055 |
+ #include <linux/jhash.h> |
36056 |
++#include <linux/security.h> |
36057 |
+ |
36058 |
+ #include <net/inet_connection_sock.h> |
36059 |
+ #include <net/inet_hashtables.h> |
36060 |
+diff -urNp linux-2.6.28.8/net/ipv4/inet_hashtables.c linux-2.6.28.8/net/ipv4/inet_hashtables.c |
36061 |
+--- linux-2.6.28.8/net/ipv4/inet_hashtables.c 2009-02-06 16:47:45.000000000 -0500 |
36062 |
++++ linux-2.6.28.8/net/ipv4/inet_hashtables.c 2009-02-21 09:37:50.000000000 -0500 |
36063 |
+@@ -18,11 +18,14 @@ |
36064 |
+ #include <linux/sched.h> |
36065 |
+ #include <linux/slab.h> |
36066 |
+ #include <linux/wait.h> |
36067 |
++#include <linux/security.h> |
36068 |
+ |
36069 |
+ #include <net/inet_connection_sock.h> |
36070 |
+ #include <net/inet_hashtables.h> |
36071 |
+ #include <net/ip.h> |
36072 |
+ |
36073 |
++extern void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet); |
36074 |
++ |
36075 |
+ /* |
36076 |
+ * Allocate and initialize a new local port bind bucket. |
36077 |
+ * The bindhash mutex for snum's hash chain must be held here. |
36078 |
+@@ -487,6 +490,8 @@ ok: |
36079 |
+ } |
36080 |
+ spin_unlock(&head->lock); |
36081 |
+ |
36082 |
++ gr_update_task_in_ip_table(current, inet_sk(sk)); |
36083 |
++ |
36084 |
+ if (tw) { |
36085 |
+ inet_twsk_deschedule(tw, death_row); |
36086 |
+ inet_twsk_put(tw); |
36087 |
+diff -urNp linux-2.6.28.8/net/ipv4/netfilter/ipt_stealth.c linux-2.6.28.8/net/ipv4/netfilter/ipt_stealth.c |
36088 |
+--- linux-2.6.28.8/net/ipv4/netfilter/ipt_stealth.c 1969-12-31 19:00:00.000000000 -0500 |
36089 |
++++ linux-2.6.28.8/net/ipv4/netfilter/ipt_stealth.c 2009-02-21 09:37:50.000000000 -0500 |
36090 |
+@@ -0,0 +1,114 @@ |
36091 |
++/* Kernel module to add stealth support. |
36092 |
++ * |
36093 |
++ * Copyright (C) 2002-2006 Brad Spengler <spender@××××××××××.net> |
36094 |
++ * |
36095 |
++ */ |
36096 |
++ |
36097 |
++#include <linux/kernel.h> |
36098 |
++#include <linux/module.h> |
36099 |
++#include <linux/skbuff.h> |
36100 |
++#include <linux/net.h> |
36101 |
++#include <linux/sched.h> |
36102 |
++#include <linux/inet.h> |
36103 |
++#include <linux/stddef.h> |
36104 |
++ |
36105 |
++#include <net/ip.h> |
36106 |
++#include <net/sock.h> |
36107 |
++#include <net/tcp.h> |
36108 |
++#include <net/udp.h> |
36109 |
++#include <net/route.h> |
36110 |
++#include <net/inet_common.h> |
36111 |
++ |
36112 |
++#include <linux/netfilter_ipv4/ip_tables.h> |
36113 |
++ |
36114 |
++MODULE_LICENSE("GPL"); |
36115 |
++ |
36116 |
++extern struct sock *udp_v4_lookup(struct net *net, u32 saddr, u16 sport, u32 daddr, u16 dport, int dif); |
36117 |
++ |
36118 |
++static bool |
36119 |
++match(const struct sk_buff *skb, |
36120 |
++ const struct net_device *in, |
36121 |
++ const struct net_device *out, |
36122 |
++ const struct xt_match *match, |
36123 |
++ const void *matchinfo, |
36124 |
++ int offset, |
36125 |
++ unsigned int protoff, |
36126 |
++ bool *hotdrop) |
36127 |
++{ |
36128 |
++ struct iphdr *ip = ip_hdr(skb); |
36129 |
++ struct tcphdr th; |
36130 |
++ struct udphdr uh; |
36131 |
++ struct sock *sk = NULL; |
36132 |
++ |
36133 |
++ if (!ip || offset) return false; |
36134 |
++ |
36135 |
++ switch(ip->protocol) { |
36136 |
++ case IPPROTO_TCP: |
36137 |
++ if (skb_copy_bits(skb, (ip_hdr(skb))->ihl*4, &th, sizeof(th)) < 0) { |
36138 |
++ *hotdrop = true; |
36139 |
++ return false; |
36140 |
++ } |
36141 |
++ if (!(th.syn && !th.ack)) return false; |
36142 |
++ sk = inet_lookup_listener(dev_net(skb->dev), &tcp_hashinfo, ip->daddr, th.dest, inet_iif(skb)); |
36143 |
++ break; |
36144 |
++ case IPPROTO_UDP: |
36145 |
++ if (skb_copy_bits(skb, (ip_hdr(skb))->ihl*4, &uh, sizeof(uh)) < 0) { |
36146 |
++ *hotdrop = true; |
36147 |
++ return false; |
36148 |
++ } |
36149 |
++ sk = udp_v4_lookup(dev_net(skb->dev), ip->saddr, uh.source, ip->daddr, uh.dest, skb->dev->ifindex); |
36150 |
++ break; |
36151 |
++ default: |
36152 |
++ return false; |
36153 |
++ } |
36154 |
++ |
36155 |
++ if(!sk) // port is being listened on, match this |
36156 |
++ return true; |
36157 |
++ else { |
36158 |
++ sock_put(sk); |
36159 |
++ return false; |
36160 |
++ } |
36161 |
++} |
36162 |
++ |
36163 |
++/* Called when user tries to insert an entry of this type. */ |
36164 |
++static bool |
36165 |
++checkentry(const char *tablename, |
36166 |
++ const void *nip, |
36167 |
++ const struct xt_match *match, |
36168 |
++ void *matchinfo, |
36169 |
++ unsigned int hook_mask) |
36170 |
++{ |
36171 |
++ const struct ipt_ip *ip = (const struct ipt_ip *)nip; |
36172 |
++ |
36173 |
++ if(((ip->proto == IPPROTO_TCP && !(ip->invflags & IPT_INV_PROTO)) || |
36174 |
++ ((ip->proto == IPPROTO_UDP) && !(ip->invflags & IPT_INV_PROTO))) |
36175 |
++ && (hook_mask & (1 << NF_INET_LOCAL_IN))) |
36176 |
++ return true; |
36177 |
++ |
36178 |
++ printk("stealth: Only works on TCP and UDP for the INPUT chain.\n"); |
36179 |
++ |
36180 |
++ return false; |
36181 |
++} |
36182 |
++ |
36183 |
++ |
36184 |
++static struct xt_match stealth_match __read_mostly = { |
36185 |
++ .name = "stealth", |
36186 |
++ .family = AF_INET, |
36187 |
++ .match = match, |
36188 |
++ .checkentry = checkentry, |
36189 |
++ .destroy = NULL, |
36190 |
++ .me = THIS_MODULE |
36191 |
++}; |
36192 |
++ |
36193 |
++static int __init init(void) |
36194 |
++{ |
36195 |
++ return xt_register_match(&stealth_match); |
36196 |
++} |
36197 |
++ |
36198 |
++static void __exit fini(void) |
36199 |
++{ |
36200 |
++ xt_unregister_match(&stealth_match); |
36201 |
++} |
36202 |
++ |
36203 |
++module_init(init); |
36204 |
++module_exit(fini); |
36205 |
+diff -urNp linux-2.6.28.8/net/ipv4/netfilter/Kconfig linux-2.6.28.8/net/ipv4/netfilter/Kconfig |
36206 |
+--- linux-2.6.28.8/net/ipv4/netfilter/Kconfig 2009-02-06 16:47:45.000000000 -0500 |
36207 |
++++ linux-2.6.28.8/net/ipv4/netfilter/Kconfig 2009-03-07 04:29:14.000000000 -0500 |
36208 |
+@@ -101,6 +101,21 @@ config IP_NF_MATCH_TTL |
36209 |
+ |
36210 |
+ To compile it as a module, choose M here. If unsure, say N. |
36211 |
+ |
36212 |
++config IP_NF_MATCH_STEALTH |
36213 |
++ tristate "stealth match support" |
36214 |
++ depends on IP_NF_IPTABLES |
36215 |
++ help |
36216 |
++ Enabling this option will drop all syn packets coming to unserved tcp |
36217 |
++ ports as well as all packets coming to unserved udp ports. If you |
36218 |
++ are using your system to route any type of packets (ie. via NAT) |
36219 |
++ you should put this module at the end of your ruleset, since it will |
36220 |
++ drop packets that aren't going to ports that are listening on your |
36221 |
++ machine itself, it doesn't take into account that the packet might be |
36222 |
++ destined for someone on your internal network if you're using NAT for |
36223 |
++ instance. |
36224 |
++ |
36225 |
++ To compile it as a module, choose M here. If unsure, say N. |
36226 |
++ |
36227 |
+ # `filter', generic and specific targets |
36228 |
+ config IP_NF_FILTER |
36229 |
+ tristate "Packet filtering" |
36230 |
+diff -urNp linux-2.6.28.8/net/ipv4/netfilter/Makefile linux-2.6.28.8/net/ipv4/netfilter/Makefile |
36231 |
+--- linux-2.6.28.8/net/ipv4/netfilter/Makefile 2009-02-06 16:47:45.000000000 -0500 |
36232 |
++++ linux-2.6.28.8/net/ipv4/netfilter/Makefile 2009-02-21 09:37:50.000000000 -0500 |
36233 |
+@@ -61,6 +61,7 @@ obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += |
36234 |
+ obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o |
36235 |
+ obj-$(CONFIG_IP_NF_TARGET_REDIRECT) += ipt_REDIRECT.o |
36236 |
+ obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o |
36237 |
++obj-$(CONFIG_IP_NF_MATCH_STEALTH) += ipt_stealth.o |
36238 |
+ obj-$(CONFIG_IP_NF_TARGET_TTL) += ipt_TTL.o |
36239 |
+ obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o |
36240 |
+ |
36241 |
+diff -urNp linux-2.6.28.8/net/ipv4/tcp_ipv4.c linux-2.6.28.8/net/ipv4/tcp_ipv4.c |
36242 |
+--- linux-2.6.28.8/net/ipv4/tcp_ipv4.c 2009-02-06 16:47:45.000000000 -0500 |
36243 |
++++ linux-2.6.28.8/net/ipv4/tcp_ipv4.c 2009-02-21 09:37:50.000000000 -0500 |
36244 |
+@@ -55,6 +55,7 @@ |
36245 |
+ #include <linux/fcntl.h> |
36246 |
+ #include <linux/module.h> |
36247 |
+ #include <linux/random.h> |
36248 |
++#include <linux/security.h> |
36249 |
+ #include <linux/cache.h> |
36250 |
+ #include <linux/jhash.h> |
36251 |
+ #include <linux/init.h> |
36252 |
+diff -urNp linux-2.6.28.8/net/ipv4/udp.c linux-2.6.28.8/net/ipv4/udp.c |
36253 |
+--- linux-2.6.28.8/net/ipv4/udp.c 2009-02-08 00:54:28.000000000 -0500 |
36254 |
++++ linux-2.6.28.8/net/ipv4/udp.c 2009-02-21 09:37:50.000000000 -0500 |
36255 |
+@@ -84,6 +84,7 @@ |
36256 |
+ #include <linux/types.h> |
36257 |
+ #include <linux/fcntl.h> |
36258 |
+ #include <linux/module.h> |
36259 |
++#include <linux/security.h> |
36260 |
+ #include <linux/socket.h> |
36261 |
+ #include <linux/sockios.h> |
36262 |
+ #include <linux/igmp.h> |
36263 |
+@@ -104,6 +105,9 @@ |
36264 |
+ #include <net/xfrm.h> |
36265 |
+ #include "udp_impl.h" |
36266 |
+ |
36267 |
++extern int gr_search_udp_recvmsg(struct sock *sk, const struct sk_buff *skb); |
36268 |
++extern int gr_search_udp_sendmsg(struct sock *sk, struct sockaddr_in *addr); |
36269 |
++ |
36270 |
+ /* |
36271 |
+ * Snmp MIB for the UDP layer |
36272 |
+ */ |
36273 |
+@@ -284,6 +288,13 @@ struct sock *udp4_lib_lookup(struct net |
36274 |
+ } |
36275 |
+ EXPORT_SYMBOL_GPL(udp4_lib_lookup); |
36276 |
+ |
36277 |
++struct sock *udp_v4_lookup(struct net *net, __be32 saddr, __be16 sport, |
36278 |
++ __be32 daddr, __be16 dport, int dif) |
36279 |
++{ |
36280 |
++ return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, udp_hash); |
36281 |
++} |
36282 |
++ |
36283 |
++ |
36284 |
+ static inline struct sock *udp_v4_mcast_next(struct net *net, struct sock *sk, |
36285 |
+ __be16 loc_port, __be32 loc_addr, |
36286 |
+ __be16 rmt_port, __be32 rmt_addr, |
36287 |
+@@ -574,9 +585,18 @@ int udp_sendmsg(struct kiocb *iocb, stru |
36288 |
+ dport = usin->sin_port; |
36289 |
+ if (dport == 0) |
36290 |
+ return -EINVAL; |
36291 |
++ |
36292 |
++ err = gr_search_udp_sendmsg(sk, usin); |
36293 |
++ if (err) |
36294 |
++ return err; |
36295 |
+ } else { |
36296 |
+ if (sk->sk_state != TCP_ESTABLISHED) |
36297 |
+ return -EDESTADDRREQ; |
36298 |
++ |
36299 |
++ err = gr_search_udp_sendmsg(sk, NULL); |
36300 |
++ if (err) |
36301 |
++ return err; |
36302 |
++ |
36303 |
+ daddr = inet->daddr; |
36304 |
+ dport = inet->dport; |
36305 |
+ /* Open fast path for connected socket. |
36306 |
+@@ -842,6 +862,10 @@ try_again: |
36307 |
+ if (!skb) |
36308 |
+ goto out; |
36309 |
+ |
36310 |
++ err = gr_search_udp_recvmsg(sk, skb); |
36311 |
++ if (err) |
36312 |
++ goto out_free; |
36313 |
++ |
36314 |
+ ulen = skb->len - sizeof(struct udphdr); |
36315 |
+ copied = len; |
36316 |
+ if (copied > ulen) |
36317 |
+diff -urNp linux-2.6.28.8/net/ipv6/exthdrs.c linux-2.6.28.8/net/ipv6/exthdrs.c |
36318 |
+--- linux-2.6.28.8/net/ipv6/exthdrs.c 2009-02-06 16:47:45.000000000 -0500 |
36319 |
++++ linux-2.6.28.8/net/ipv6/exthdrs.c 2009-02-21 09:37:50.000000000 -0500 |
36320 |
+@@ -630,7 +630,7 @@ static struct tlvtype_proc tlvprochopopt |
36321 |
+ .type = IPV6_TLV_JUMBO, |
36322 |
+ .func = ipv6_hop_jumbo, |
36323 |
+ }, |
36324 |
+- { -1, } |
36325 |
++ { -1, NULL } |
36326 |
+ }; |
36327 |
+ |
36328 |
+ int ipv6_parse_hopopts(struct sk_buff *skb) |
36329 |
+diff -urNp linux-2.6.28.8/net/ipv6/raw.c linux-2.6.28.8/net/ipv6/raw.c |
36330 |
+--- linux-2.6.28.8/net/ipv6/raw.c 2009-02-06 16:47:45.000000000 -0500 |
36331 |
++++ linux-2.6.28.8/net/ipv6/raw.c 2009-02-21 09:37:50.000000000 -0500 |
36332 |
+@@ -600,7 +600,7 @@ out: |
36333 |
+ return err; |
36334 |
+ } |
36335 |
+ |
36336 |
+-static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, |
36337 |
++static int rawv6_send_hdrinc(struct sock *sk, void *from, unsigned int length, |
36338 |
+ struct flowi *fl, struct rt6_info *rt, |
36339 |
+ unsigned int flags) |
36340 |
+ { |
36341 |
+diff -urNp linux-2.6.28.8/net/irda/ircomm/ircomm_tty.c linux-2.6.28.8/net/irda/ircomm/ircomm_tty.c |
36342 |
+--- linux-2.6.28.8/net/irda/ircomm/ircomm_tty.c 2009-02-06 16:47:45.000000000 -0500 |
36343 |
++++ linux-2.6.28.8/net/irda/ircomm/ircomm_tty.c 2009-02-21 09:37:50.000000000 -0500 |
36344 |
+@@ -371,7 +371,7 @@ static int ircomm_tty_open(struct tty_st |
36345 |
+ IRDA_DEBUG(2, "%s()\n", __func__ ); |
36346 |
+ |
36347 |
+ line = tty->index; |
36348 |
+- if ((line < 0) || (line >= IRCOMM_TTY_PORTS)) { |
36349 |
++ if (line >= IRCOMM_TTY_PORTS) { |
36350 |
+ return -ENODEV; |
36351 |
+ } |
36352 |
+ |
36353 |
+diff -urNp linux-2.6.28.8/net/sctp/socket.c linux-2.6.28.8/net/sctp/socket.c |
36354 |
+--- linux-2.6.28.8/net/sctp/socket.c 2009-02-06 16:47:45.000000000 -0500 |
36355 |
++++ linux-2.6.28.8/net/sctp/socket.c 2009-02-21 09:37:50.000000000 -0500 |
36356 |
+@@ -1434,7 +1434,7 @@ SCTP_STATIC int sctp_sendmsg(struct kioc |
36357 |
+ struct sctp_sndrcvinfo *sinfo; |
36358 |
+ struct sctp_initmsg *sinit; |
36359 |
+ sctp_assoc_t associd = 0; |
36360 |
+- sctp_cmsgs_t cmsgs = { NULL }; |
36361 |
++ sctp_cmsgs_t cmsgs = { NULL, NULL }; |
36362 |
+ int err; |
36363 |
+ sctp_scope_t scope; |
36364 |
+ long timeo; |
36365 |
+@@ -5616,7 +5616,6 @@ pp_found: |
36366 |
+ */ |
36367 |
+ int reuse = sk->sk_reuse; |
36368 |
+ struct sock *sk2; |
36369 |
+- struct hlist_node *node; |
36370 |
+ |
36371 |
+ SCTP_DEBUG_PRINTK("sctp_get_port() found a possible match\n"); |
36372 |
+ if (pp->fastreuse && sk->sk_reuse && |
36373 |
+diff -urNp linux-2.6.28.8/net/socket.c linux-2.6.28.8/net/socket.c |
36374 |
+--- linux-2.6.28.8/net/socket.c 2009-02-06 16:47:45.000000000 -0500 |
36375 |
++++ linux-2.6.28.8/net/socket.c 2009-03-07 04:29:14.000000000 -0500 |
36376 |
+@@ -87,6 +87,7 @@ |
36377 |
+ #include <linux/audit.h> |
36378 |
+ #include <linux/wireless.h> |
36379 |
+ #include <linux/nsproxy.h> |
36380 |
++#include <linux/in.h> |
36381 |
+ |
36382 |
+ #include <asm/uaccess.h> |
36383 |
+ #include <asm/unistd.h> |
36384 |
+@@ -97,6 +98,21 @@ |
36385 |
+ #include <net/sock.h> |
36386 |
+ #include <linux/netfilter.h> |
36387 |
+ |
36388 |
++extern void gr_attach_curr_ip(const struct sock *sk); |
36389 |
++extern int gr_handle_sock_all(const int family, const int type, |
36390 |
++ const int protocol); |
36391 |
++extern int gr_handle_sock_server(const struct sockaddr *sck); |
36392 |
++extern int gr_handle_sock_server_other(const struct socket *sck); |
36393 |
++extern int gr_handle_sock_client(const struct sockaddr *sck); |
36394 |
++extern int gr_search_connect(struct socket * sock, |
36395 |
++ struct sockaddr_in * addr); |
36396 |
++extern int gr_search_bind(struct socket * sock, |
36397 |
++ struct sockaddr_in * addr); |
36398 |
++extern int gr_search_listen(struct socket * sock); |
36399 |
++extern int gr_search_accept(struct socket * sock); |
36400 |
++extern int gr_search_socket(const int domain, const int type, |
36401 |
++ const int protocol); |
36402 |
++ |
36403 |
+ static int sock_no_open(struct inode *irrelevant, struct file *dontcare); |
36404 |
+ static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, |
36405 |
+ unsigned long nr_segs, loff_t pos); |
36406 |
+@@ -300,7 +316,7 @@ static int sockfs_get_sb(struct file_sys |
36407 |
+ mnt); |
36408 |
+ } |
36409 |
+ |
36410 |
+-static struct vfsmount *sock_mnt __read_mostly; |
36411 |
++struct vfsmount *sock_mnt __read_mostly; |
36412 |
+ |
36413 |
+ static struct file_system_type sock_fs_type = { |
36414 |
+ .name = "sockfs", |
36415 |
+@@ -1235,6 +1251,16 @@ SYSCALL_DEFINE3(socket, int, family, int |
36416 |
+ if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) |
36417 |
+ flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK; |
36418 |
+ |
36419 |
++ if(!gr_search_socket(family, type, protocol)) { |
36420 |
++ retval = -EACCES; |
36421 |
++ goto out; |
36422 |
++ } |
36423 |
++ |
36424 |
++ if (gr_handle_sock_all(family, type, protocol)) { |
36425 |
++ retval = -EACCES; |
36426 |
++ goto out; |
36427 |
++ } |
36428 |
++ |
36429 |
+ retval = sock_create(family, type, protocol, &sock); |
36430 |
+ if (retval < 0) |
36431 |
+ goto out; |
36432 |
+@@ -1374,6 +1400,14 @@ SYSCALL_DEFINE3(bind, int, fd, struct so |
36433 |
+ if (sock) { |
36434 |
+ err = move_addr_to_kernel(umyaddr, addrlen, (struct sockaddr *)&address); |
36435 |
+ if (err >= 0) { |
36436 |
++ if (gr_handle_sock_server((struct sockaddr *)&address)) { |
36437 |
++ err = -EACCES; |
36438 |
++ goto error; |
36439 |
++ } |
36440 |
++ err = gr_search_bind(sock, (struct sockaddr_in *)&address); |
36441 |
++ if (err) |
36442 |
++ goto error; |
36443 |
++ |
36444 |
+ err = security_socket_bind(sock, |
36445 |
+ (struct sockaddr *)&address, |
36446 |
+ addrlen); |
36447 |
+@@ -1382,6 +1416,7 @@ SYSCALL_DEFINE3(bind, int, fd, struct so |
36448 |
+ (struct sockaddr *) |
36449 |
+ &address, addrlen); |
36450 |
+ } |
36451 |
++error: |
36452 |
+ fput_light(sock->file, fput_needed); |
36453 |
+ } |
36454 |
+ return err; |
36455 |
+@@ -1405,10 +1440,20 @@ SYSCALL_DEFINE2(listen, int, fd, int, ba |
36456 |
+ if ((unsigned)backlog > somaxconn) |
36457 |
+ backlog = somaxconn; |
36458 |
+ |
36459 |
++ if (gr_handle_sock_server_other(sock)) { |
36460 |
++ err = -EPERM; |
36461 |
++ goto error; |
36462 |
++ } |
36463 |
++ |
36464 |
++ err = gr_search_listen(sock); |
36465 |
++ if (err) |
36466 |
++ goto error; |
36467 |
++ |
36468 |
+ err = security_socket_listen(sock, backlog); |
36469 |
+ if (!err) |
36470 |
+ err = sock->ops->listen(sock, backlog); |
36471 |
+ |
36472 |
++error: |
36473 |
+ fput_light(sock->file, fput_needed); |
36474 |
+ } |
36475 |
+ return err; |
36476 |
+@@ -1451,6 +1496,18 @@ SYSCALL_DEFINE4(accept4, int, fd, struct |
36477 |
+ newsock->type = sock->type; |
36478 |
+ newsock->ops = sock->ops; |
36479 |
+ |
36480 |
++ if (gr_handle_sock_server_other(sock)) { |
36481 |
++ err = -EPERM; |
36482 |
++ sock_release(newsock); |
36483 |
++ goto out_put; |
36484 |
++ } |
36485 |
++ |
36486 |
++ err = gr_search_accept(sock); |
36487 |
++ if (err) { |
36488 |
++ sock_release(newsock); |
36489 |
++ goto out_put; |
36490 |
++ } |
36491 |
++ |
36492 |
+ /* |
36493 |
+ * We don't need try_module_get here, as the listening socket (sock) |
36494 |
+ * has the protocol module (sock->ops->owner) held. |
36495 |
+@@ -1494,6 +1551,7 @@ SYSCALL_DEFINE4(accept4, int, fd, struct |
36496 |
+ err = newfd; |
36497 |
+ |
36498 |
+ security_socket_post_accept(sock, newsock); |
36499 |
++ gr_attach_curr_ip(newsock->sk); |
36500 |
+ |
36501 |
+ out_put: |
36502 |
+ fput_light(sock->file, fput_needed); |
36503 |
+@@ -1532,6 +1590,7 @@ SYSCALL_DEFINE3(connect, int, fd, struct |
36504 |
+ int, addrlen) |
36505 |
+ { |
36506 |
+ struct socket *sock; |
36507 |
++ struct sockaddr *sck; |
36508 |
+ struct sockaddr_storage address; |
36509 |
+ int err, fput_needed; |
36510 |
+ |
36511 |
+@@ -1542,6 +1601,17 @@ SYSCALL_DEFINE3(connect, int, fd, struct |
36512 |
+ if (err < 0) |
36513 |
+ goto out_put; |
36514 |
+ |
36515 |
++ sck = (struct sockaddr *)&address; |
36516 |
++ |
36517 |
++ if (gr_handle_sock_client(sck)) { |
36518 |
++ err = -EACCES; |
36519 |
++ goto out_put; |
36520 |
++ } |
36521 |
++ |
36522 |
++ err = gr_search_connect(sock, (struct sockaddr_in *)sck); |
36523 |
++ if (err) |
36524 |
++ goto out_put; |
36525 |
++ |
36526 |
+ err = |
36527 |
+ security_socket_connect(sock, (struct sockaddr *)&address, addrlen); |
36528 |
+ if (err) |
36529 |
+diff -urNp linux-2.6.28.8/net/unix/af_unix.c linux-2.6.28.8/net/unix/af_unix.c |
36530 |
+--- linux-2.6.28.8/net/unix/af_unix.c 2009-02-06 16:47:45.000000000 -0500 |
36531 |
++++ linux-2.6.28.8/net/unix/af_unix.c 2009-02-21 09:37:50.000000000 -0500 |
36532 |
+@@ -727,6 +727,12 @@ static struct sock *unix_find_other(stru |
36533 |
+ err = -ECONNREFUSED; |
36534 |
+ if (!S_ISSOCK(inode->i_mode)) |
36535 |
+ goto put_fail; |
36536 |
++ |
36537 |
++ if (!gr_acl_handle_unix(path.dentry, path.mnt)) { |
36538 |
++ err = -EACCES; |
36539 |
++ goto put_fail; |
36540 |
++ } |
36541 |
++ |
36542 |
+ u = unix_find_socket_byinode(net, inode); |
36543 |
+ if (!u) |
36544 |
+ goto put_fail; |
36545 |
+@@ -747,6 +753,13 @@ static struct sock *unix_find_other(stru |
36546 |
+ if (u) { |
36547 |
+ struct dentry *dentry; |
36548 |
+ dentry = unix_sk(u)->dentry; |
36549 |
++ |
36550 |
++ if (!gr_handle_chroot_unix(u->sk_peercred.pid)) { |
36551 |
++ err = -EPERM; |
36552 |
++ sock_put(u); |
36553 |
++ goto fail; |
36554 |
++ } |
36555 |
++ |
36556 |
+ if (dentry) |
36557 |
+ touch_atime(unix_sk(u)->mnt, dentry); |
36558 |
+ } else |
36559 |
+@@ -829,10 +842,20 @@ static int unix_bind(struct socket *sock |
36560 |
+ err = mnt_want_write(nd.path.mnt); |
36561 |
+ if (err) |
36562 |
+ goto out_mknod_dput; |
36563 |
++ |
36564 |
++ if (!gr_acl_handle_mknod(dentry, nd.path.dentry, nd.path.mnt, mode)) { |
36565 |
++ err = -EACCES; |
36566 |
++ mnt_drop_write(nd.path.mnt); |
36567 |
++ goto out_mknod_dput; |
36568 |
++ } |
36569 |
++ |
36570 |
+ err = vfs_mknod(nd.path.dentry->d_inode, dentry, mode, 0); |
36571 |
+ mnt_drop_write(nd.path.mnt); |
36572 |
+ if (err) |
36573 |
+ goto out_mknod_dput; |
36574 |
++ |
36575 |
++ gr_handle_create(dentry, nd.path.mnt); |
36576 |
++ |
36577 |
+ mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
36578 |
+ dput(nd.path.dentry); |
36579 |
+ nd.path.dentry = dentry; |
36580 |
+@@ -850,6 +873,10 @@ static int unix_bind(struct socket *sock |
36581 |
+ goto out_unlock; |
36582 |
+ } |
36583 |
+ |
36584 |
++#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX |
36585 |
++ sk->sk_peercred.pid = current->pid; |
36586 |
++#endif |
36587 |
++ |
36588 |
+ list = &unix_socket_table[addr->hash]; |
36589 |
+ } else { |
36590 |
+ list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; |
36591 |
+diff -urNp linux-2.6.28.8/scripts/pnmtologo.c linux-2.6.28.8/scripts/pnmtologo.c |
36592 |
+--- linux-2.6.28.8/scripts/pnmtologo.c 2009-02-06 16:47:45.000000000 -0500 |
36593 |
++++ linux-2.6.28.8/scripts/pnmtologo.c 2009-02-21 09:37:50.000000000 -0500 |
36594 |
+@@ -237,14 +237,14 @@ static void write_header(void) |
36595 |
+ fprintf(out, " * Linux logo %s\n", logoname); |
36596 |
+ fputs(" */\n\n", out); |
36597 |
+ fputs("#include <linux/linux_logo.h>\n\n", out); |
36598 |
+- fprintf(out, "static unsigned char %s_data[] __initdata = {\n", |
36599 |
++ fprintf(out, "static unsigned char %s_data[] = {\n", |
36600 |
+ logoname); |
36601 |
+ } |
36602 |
+ |
36603 |
+ static void write_footer(void) |
36604 |
+ { |
36605 |
+ fputs("\n};\n\n", out); |
36606 |
+- fprintf(out, "struct linux_logo %s __initdata = {\n", logoname); |
36607 |
++ fprintf(out, "struct linux_logo %s = {\n", logoname); |
36608 |
+ fprintf(out, " .type\t= %s,\n", logo_types[logo_type]); |
36609 |
+ fprintf(out, " .width\t= %d,\n", logo_width); |
36610 |
+ fprintf(out, " .height\t= %d,\n", logo_height); |
36611 |
+@@ -374,7 +374,7 @@ static void write_logo_clut224(void) |
36612 |
+ fputs("\n};\n\n", out); |
36613 |
+ |
36614 |
+ /* write logo clut */ |
36615 |
+- fprintf(out, "static unsigned char %s_clut[] __initdata = {\n", |
36616 |
++ fprintf(out, "static unsigned char %s_clut[] = {\n", |
36617 |
+ logoname); |
36618 |
+ write_hex_cnt = 0; |
36619 |
+ for (i = 0; i < logo_clutsize; i++) { |
36620 |
+diff -urNp linux-2.6.28.8/security/commoncap.c linux-2.6.28.8/security/commoncap.c |
36621 |
+--- linux-2.6.28.8/security/commoncap.c 2009-02-06 16:47:45.000000000 -0500 |
36622 |
++++ linux-2.6.28.8/security/commoncap.c 2009-03-07 04:29:14.000000000 -0500 |
36623 |
+@@ -27,9 +27,11 @@ |
36624 |
+ #include <linux/prctl.h> |
36625 |
+ #include <linux/securebits.h> |
36626 |
+ |
36627 |
++extern kernel_cap_t gr_cap_rtnetlink(struct sock *sk); |
36628 |
++ |
36629 |
+ int cap_netlink_send(struct sock *sk, struct sk_buff *skb) |
36630 |
+ { |
36631 |
+- NETLINK_CB(skb).eff_cap = current->cap_effective; |
36632 |
++ NETLINK_CB(skb).eff_cap = gr_cap_rtnetlink(sk); |
36633 |
+ return 0; |
36634 |
+ } |
36635 |
+ |
36636 |
+@@ -56,6 +58,14 @@ int cap_capable (struct task_struct *tsk |
36637 |
+ return -EPERM; |
36638 |
+ } |
36639 |
+ |
36640 |
++int cap_capable_nolog (struct task_struct *tsk, int cap) |
36641 |
++{ |
36642 |
++ /* tsk = current for all callers */ |
36643 |
++ if (cap_raised(tsk->cap_effective, cap) && gr_is_capable_nolog(cap)) |
36644 |
++ return 0; |
36645 |
++ return -EPERM; |
36646 |
++} |
36647 |
++ |
36648 |
+ int cap_settime(struct timespec *ts, struct timezone *tz) |
36649 |
+ { |
36650 |
+ if (!capable(CAP_SYS_TIME)) |
36651 |
+@@ -379,8 +389,11 @@ void cap_bprm_apply_creds (struct linux_ |
36652 |
+ } |
36653 |
+ } |
36654 |
+ |
36655 |
+- current->suid = current->euid = current->fsuid = bprm->e_uid; |
36656 |
+- current->sgid = current->egid = current->fsgid = bprm->e_gid; |
36657 |
++ if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid)) |
36658 |
++ current->suid = current->euid = current->fsuid = bprm->e_uid; |
36659 |
++ |
36660 |
++ if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid)) |
36661 |
++ current->sgid = current->egid = current->fsgid = bprm->e_gid; |
36662 |
+ |
36663 |
+ /* For init, we want to retain the capabilities set |
36664 |
+ * in the init_task struct. Thus we skip the usual |
36665 |
+@@ -393,6 +406,8 @@ void cap_bprm_apply_creds (struct linux_ |
36666 |
+ cap_clear(current->cap_effective); |
36667 |
+ } |
36668 |
+ |
36669 |
++ gr_handle_chroot_caps(current); |
36670 |
++ |
36671 |
+ /* AUD: Audit candidate if current->cap_effective is set */ |
36672 |
+ |
36673 |
+ current->securebits &= ~issecure_mask(SECURE_KEEP_CAPS); |
36674 |
+@@ -705,7 +720,7 @@ int cap_vm_enough_memory(struct mm_struc |
36675 |
+ { |
36676 |
+ int cap_sys_admin = 0; |
36677 |
+ |
36678 |
+- if (cap_capable(current, CAP_SYS_ADMIN) == 0) |
36679 |
++ if (cap_capable_nolog(current, CAP_SYS_ADMIN) == 0) |
36680 |
+ cap_sys_admin = 1; |
36681 |
+ return __vm_enough_memory(mm, pages, cap_sys_admin); |
36682 |
+ } |
36683 |
+diff -urNp linux-2.6.28.8/security/Kconfig linux-2.6.28.8/security/Kconfig |
36684 |
+--- linux-2.6.28.8/security/Kconfig 2009-02-06 16:47:45.000000000 -0500 |
36685 |
++++ linux-2.6.28.8/security/Kconfig 2009-02-21 09:37:50.000000000 -0500 |
36686 |
+@@ -4,6 +4,447 @@ |
36687 |
+ |
36688 |
+ menu "Security options" |
36689 |
+ |
36690 |
++source grsecurity/Kconfig |
36691 |
++ |
36692 |
++menu "PaX" |
36693 |
++ |
36694 |
++config PAX |
36695 |
++ bool "Enable various PaX features" |
36696 |
++ depends on GRKERNSEC && (ALPHA || ARM || AVR32 || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || PPC64 || SPARC32 || SPARC64 || X86) |
36697 |
++ help |
36698 |
++ This allows you to enable various PaX features. PaX adds |
36699 |
++ intrusion prevention mechanisms to the kernel that reduce |
36700 |
++ the risks posed by exploitable memory corruption bugs. |
36701 |
++ |
36702 |
++menu "PaX Control" |
36703 |
++ depends on PAX |
36704 |
++ |
36705 |
++config PAX_SOFTMODE |
36706 |
++ bool 'Support soft mode' |
36707 |
++ help |
36708 |
++ Enabling this option will allow you to run PaX in soft mode, that |
36709 |
++ is, PaX features will not be enforced by default, only on executables |
36710 |
++ marked explicitly. You must also enable PT_PAX_FLAGS support as it |
36711 |
++ is the only way to mark executables for soft mode use. |
36712 |
++ |
36713 |
++ Soft mode can be activated by using the "pax_softmode=1" kernel command |
36714 |
++ line option on boot. Furthermore you can control various PaX features |
36715 |
++ at runtime via the entries in /proc/sys/kernel/pax. |
36716 |
++ |
36717 |
++config PAX_EI_PAX |
36718 |
++ bool 'Use legacy ELF header marking' |
36719 |
++ help |
36720 |
++ Enabling this option will allow you to control PaX features on |
36721 |
++ a per executable basis via the 'chpax' utility available at |
36722 |
++ http://pax.grsecurity.net/. The control flags will be read from |
36723 |
++ an otherwise reserved part of the ELF header. This marking has |
36724 |
++ numerous drawbacks (no support for soft-mode, toolchain does not |
36725 |
++ know about the non-standard use of the ELF header) therefore it |
36726 |
++ has been deprecated in favour of PT_PAX_FLAGS support. |
36727 |
++ |
36728 |
++ If you have applications not marked by the PT_PAX_FLAGS ELF |
36729 |
++ program header then you MUST enable this option otherwise they |
36730 |
++ will not get any protection. |
36731 |
++ |
36732 |
++ Note that if you enable PT_PAX_FLAGS marking support as well, |
36733 |
++ the PT_PAX_FLAG marks will override the legacy EI_PAX marks. |
36734 |
++ |
36735 |
++config PAX_PT_PAX_FLAGS |
36736 |
++ bool 'Use ELF program header marking' |
36737 |
++ help |
36738 |
++ Enabling this option will allow you to control PaX features on |
36739 |
++ a per executable basis via the 'paxctl' utility available at |
36740 |
++ http://pax.grsecurity.net/. The control flags will be read from |
36741 |
++ a PaX specific ELF program header (PT_PAX_FLAGS). This marking |
36742 |
++ has the benefits of supporting both soft mode and being fully |
36743 |
++ integrated into the toolchain (the binutils patch is available |
36744 |
++ from http://pax.grsecurity.net). |
36745 |
++ |
36746 |
++ If you have applications not marked by the PT_PAX_FLAGS ELF |
36747 |
++ program header then you MUST enable the EI_PAX marking support |
36748 |
++ otherwise they will not get any protection. |
36749 |
++ |
36750 |
++ Note that if you enable the legacy EI_PAX marking support as well, |
36751 |
++ the EI_PAX marks will be overridden by the PT_PAX_FLAGS marks. |
36752 |
++ |
36753 |
++choice |
36754 |
++ prompt 'MAC system integration' |
36755 |
++ default PAX_HAVE_ACL_FLAGS |
36756 |
++ help |
36757 |
++ Mandatory Access Control systems have the option of controlling |
36758 |
++ PaX flags on a per executable basis, choose the method supported |
36759 |
++ by your particular system. |
36760 |
++ |
36761 |
++ - "none": if your MAC system does not interact with PaX, |
36762 |
++ - "direct": if your MAC system defines pax_set_initial_flags() itself, |
36763 |
++ - "hook": if your MAC system uses the pax_set_initial_flags_func callback. |
36764 |
++ |
36765 |
++ NOTE: this option is for developers/integrators only. |
36766 |
++ |
36767 |
++ config PAX_NO_ACL_FLAGS |
36768 |
++ bool 'none' |
36769 |
++ |
36770 |
++ config PAX_HAVE_ACL_FLAGS |
36771 |
++ bool 'direct' |
36772 |
++ |
36773 |
++ config PAX_HOOK_ACL_FLAGS |
36774 |
++ bool 'hook' |
36775 |
++endchoice |
36776 |
++ |
36777 |
++endmenu |
36778 |
++ |
36779 |
++menu "Non-executable pages" |
36780 |
++ depends on PAX |
36781 |
++ |
36782 |
++config PAX_NOEXEC |
36783 |
++ bool "Enforce non-executable pages" |
36784 |
++ depends on (PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS) && (ALPHA || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || PPC64 || SPARC32 || SPARC64 || X86) |
36785 |
++ help |
36786 |
++ By design some architectures do not allow for protecting memory |
36787 |
++ pages against execution or even if they do, Linux does not make |
36788 |
++ use of this feature. In practice this means that if a page is |
36789 |
++ readable (such as the stack or heap) it is also executable. |
36790 |
++ |
36791 |
++ There is a well known exploit technique that makes use of this |
36792 |
++ fact and a common programming mistake where an attacker can |
36793 |
++ introduce code of his choice somewhere in the attacked program's |
36794 |
++ memory (typically the stack or the heap) and then execute it. |
36795 |
++ |
36796 |
++ If the attacked program was running with different (typically |
36797 |
++ higher) privileges than that of the attacker, then he can elevate |
36798 |
++ his own privilege level (e.g. get a root shell, write to files for |
36799 |
++ which he does not have write access to, etc). |
36800 |
++ |
36801 |
++ Enabling this option will let you choose from various features |
36802 |
++ that prevent the injection and execution of 'foreign' code in |
36803 |
++ a program. |
36804 |
++ |
36805 |
++ This will also break programs that rely on the old behaviour and |
36806 |
++ expect that dynamically allocated memory via the malloc() family |
36807 |
++ of functions is executable (which it is not). Notable examples |
36808 |
++ are the XFree86 4.x server, the java runtime and wine. |
36809 |
++ |
36810 |
++config PAX_PAGEEXEC |
36811 |
++ bool "Paging based non-executable pages" |
36812 |
++ depends on !COMPAT_VDSO && PAX_NOEXEC && (!X86_32 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MCORE2 || MPENTIUM4 || MPSC || MK7 || MK8 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MVIAC3_2 || MVIAC7) |
36813 |
++ help |
36814 |
++ This implementation is based on the paging feature of the CPU. |
36815 |
++ On i386 without hardware non-executable bit support there is a |
36816 |
++ variable but usually low performance impact, however on Intel's |
36817 |
++ P4 core based CPUs it is very high so you should not enable this |
36818 |
++ for kernels meant to be used on such CPUs. |
36819 |
++ |
36820 |
++ On alpha, avr32, ia64, parisc, sparc, sparc64, x86_64 and i386 |
36821 |
++ with hardware non-executable bit support there is no performance |
36822 |
++ impact, on ppc the impact is negligible. |
36823 |
++ |
36824 |
++ Note that several architectures require various emulations due to |
36825 |
++ badly designed userland ABIs, this will cause a performance impact |
36826 |
++ but will disappear as soon as userland is fixed (e.g., ppc users |
36827 |
++ can make use of the secure-plt feature found in binutils). |
36828 |
++ |
36829 |
++config PAX_SEGMEXEC |
36830 |
++ bool "Segmentation based non-executable pages" |
36831 |
++ depends on !COMPAT_VDSO && PAX_NOEXEC && X86_32 |
36832 |
++ help |
36833 |
++ This implementation is based on the segmentation feature of the |
36834 |
++ CPU and has a very small performance impact, however applications |
36835 |
++ will be limited to a 1.5 GB address space instead of the normal |
36836 |
++ 3 GB. |
36837 |
++ |
36838 |
++config PAX_EMUTRAMP |
36839 |
++ bool "Emulate trampolines" if (PAX_PAGEEXEC || PAX_SEGMEXEC) && (PARISC || PPC32 || X86) |
36840 |
++ default y if PARISC || PPC32 |
36841 |
++ help |
36842 |
++ There are some programs and libraries that for one reason or |
36843 |
++ another attempt to execute special small code snippets from |
36844 |
++ non-executable memory pages. Most notable examples are the |
36845 |
++ signal handler return code generated by the kernel itself and |
36846 |
++ the GCC trampolines. |
36847 |
++ |
36848 |
++ If you enabled CONFIG_PAX_PAGEEXEC or CONFIG_PAX_SEGMEXEC then |
36849 |
++ such programs will no longer work under your kernel. |
36850 |
++ |
36851 |
++ As a remedy you can say Y here and use the 'chpax' or 'paxctl' |
36852 |
++ utilities to enable trampoline emulation for the affected programs |
36853 |
++ yet still have the protection provided by the non-executable pages. |
36854 |
++ |
36855 |
++ On parisc and ppc you MUST enable this option and EMUSIGRT as |
36856 |
++ well, otherwise your system will not even boot. |
36857 |
++ |
36858 |
++ Alternatively you can say N here and use the 'chpax' or 'paxctl' |
36859 |
++ utilities to disable CONFIG_PAX_PAGEEXEC and CONFIG_PAX_SEGMEXEC |
36860 |
++ for the affected files. |
36861 |
++ |
36862 |
++ NOTE: enabling this feature *may* open up a loophole in the |
36863 |
++ protection provided by non-executable pages that an attacker |
36864 |
++ could abuse. Therefore the best solution is to not have any |
36865 |
++ files on your system that would require this option. This can |
36866 |
++ be achieved by not using libc5 (which relies on the kernel |
36867 |
++ signal handler return code) and not using or rewriting programs |
36868 |
++ that make use of the nested function implementation of GCC. |
36869 |
++ Skilled users can just fix GCC itself so that it implements |
36870 |
++ nested function calls in a way that does not interfere with PaX. |
36871 |
++ |
36872 |
++config PAX_EMUSIGRT |
36873 |
++ bool "Automatically emulate sigreturn trampolines" |
36874 |
++ depends on PAX_EMUTRAMP && (PARISC || PPC32) |
36875 |
++ default y |
36876 |
++ help |
36877 |
++ Enabling this option will have the kernel automatically detect |
36878 |
++ and emulate signal return trampolines executing on the stack |
36879 |
++ that would otherwise lead to task termination. |
36880 |
++ |
36881 |
++ This solution is intended as a temporary one for users with |
36882 |
++ legacy versions of libc (libc5, glibc 2.0, uClibc before 0.9.17, |
36883 |
++ Modula-3 runtime, etc) or executables linked to such, basically |
36884 |
++ everything that does not specify its own SA_RESTORER function in |
36885 |
++ normal executable memory like glibc 2.1+ does. |
36886 |
++ |
36887 |
++ On parisc and ppc you MUST enable this option, otherwise your |
36888 |
++ system will not even boot. |
36889 |
++ |
36890 |
++ NOTE: this feature cannot be disabled on a per executable basis |
36891 |
++ and since it *does* open up a loophole in the protection provided |
36892 |
++ by non-executable pages, the best solution is to not have any |
36893 |
++ files on your system that would require this option. |
36894 |
++ |
36895 |
++config PAX_MPROTECT |
36896 |
++ bool "Restrict mprotect()" |
36897 |
++ depends on (PAX_PAGEEXEC || PAX_SEGMEXEC) && !PPC64 |
36898 |
++ help |
36899 |
++ Enabling this option will prevent programs from |
36900 |
++ - changing the executable status of memory pages that were |
36901 |
++ not originally created as executable, |
36902 |
++ - making read-only executable pages writable again, |
36903 |
++ - creating executable pages from anonymous memory. |
36904 |
++ |
36905 |
++ You should say Y here to complete the protection provided by |
36906 |
++ the enforcement of non-executable pages. |
36907 |
++ |
36908 |
++ NOTE: you can use the 'chpax' or 'paxctl' utilities to control |
36909 |
++ this feature on a per file basis. |
36910 |
++ |
36911 |
++config PAX_NOELFRELOCS |
36912 |
++ bool "Disallow ELF text relocations" |
36913 |
++ depends on PAX_MPROTECT && !PAX_ETEXECRELOCS && (IA64 || X86) |
36914 |
++ help |
36915 |
++ Non-executable pages and mprotect() restrictions are effective |
36916 |
++ in preventing the introduction of new executable code into an |
36917 |
++ attacked task's address space. There remain only two venues |
36918 |
++ for this kind of attack: if the attacker can execute already |
36919 |
++ existing code in the attacked task then he can either have it |
36920 |
++ create and mmap() a file containing his code or have it mmap() |
36921 |
++ an already existing ELF library that does not have position |
36922 |
++ independent code in it and use mprotect() on it to make it |
36923 |
++ writable and copy his code there. While protecting against |
36924 |
++ the former approach is beyond PaX, the latter can be prevented |
36925 |
++ by having only PIC ELF libraries on one's system (which do not |
36926 |
++ need to relocate their code). If you are sure this is your case, |
36927 |
++ then enable this option otherwise be careful as you may not even |
36928 |
++ be able to boot or log on your system (for example, some PAM |
36929 |
++ modules are erroneously compiled as non-PIC by default). |
36930 |
++ |
36931 |
++ NOTE: if you are using dynamic ELF executables (as suggested |
36932 |
++ when using ASLR) then you must have made sure that you linked |
36933 |
++ your files using the PIC version of crt1 (the et_dyn.tar.gz package |
36934 |
++ referenced there has already been updated to support this). |
36935 |
++ |
36936 |
++config PAX_ETEXECRELOCS |
36937 |
++ bool "Allow ELF ET_EXEC text relocations" |
36938 |
++ depends on PAX_MPROTECT && (ALPHA || IA64 || PARISC) |
36939 |
++ default y |
36940 |
++ help |
36941 |
++ On some architectures there are incorrectly created applications |
36942 |
++ that require text relocations and would not work without enabling |
36943 |
++ this option. If you are an alpha, ia64 or parisc user, you should |
36944 |
++ enable this option and disable it once you have made sure that |
36945 |
++ none of your applications need it. |
36946 |
++ |
36947 |
++config PAX_EMUPLT |
36948 |
++ bool "Automatically emulate ELF PLT" |
36949 |
++ depends on PAX_MPROTECT && (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64) |
36950 |
++ default y |
36951 |
++ help |
36952 |
++ Enabling this option will have the kernel automatically detect |
36953 |
++ and emulate the Procedure Linkage Table entries in ELF files. |
36954 |
++ On some architectures such entries are in writable memory, and |
36955 |
++ become non-executable leading to task termination. Therefore |
36956 |
++ it is mandatory that you enable this option on alpha, parisc, |
36957 |
++ ppc (if secure-plt is not used throughout in userland), sparc |
36958 |
++ and sparc64, otherwise your system would not even boot. |
36959 |
++ |
36960 |
++ NOTE: this feature *does* open up a loophole in the protection |
36961 |
++ provided by the non-executable pages, therefore the proper |
36962 |
++ solution is to modify the toolchain to produce a PLT that does |
36963 |
++ not need to be writable. |
36964 |
++ |
36965 |
++config PAX_DLRESOLVE |
36966 |
++ bool |
36967 |
++ depends on PAX_EMUPLT && (SPARC32 || SPARC64) |
36968 |
++ default y |
36969 |
++ |
36970 |
++config PAX_SYSCALL |
36971 |
++ bool |
36972 |
++ depends on PAX_PAGEEXEC && PPC32 |
36973 |
++ default y |
36974 |
++ |
36975 |
++config PAX_KERNEXEC |
36976 |
++ bool "Enforce non-executable kernel pages" |
36977 |
++ depends on PAX_NOEXEC && X86 && !EFI && !COMPAT_VDSO && (!X86_32 || X86_WP_WORKS_OK) && !PARAVIRT |
36978 |
++ help |
36979 |
++ This is the kernel land equivalent of PAGEEXEC and MPROTECT, |
36980 |
++ that is, enabling this option will make it harder to inject |
36981 |
++ and execute 'foreign' code in kernel memory itself. |
36982 |
++ |
36983 |
++endmenu |
36984 |
++ |
36985 |
++menu "Address Space Layout Randomization" |
36986 |
++ depends on PAX |
36987 |
++ |
36988 |
++config PAX_ASLR |
36989 |
++ bool "Address Space Layout Randomization" |
36990 |
++ depends on PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS |
36991 |
++ help |
36992 |
++ Many if not most exploit techniques rely on the knowledge of |
36993 |
++ certain addresses in the attacked program. The following options |
36994 |
++ will allow the kernel to apply a certain amount of randomization |
36995 |
++ to specific parts of the program thereby forcing an attacker to |
36996 |
++ guess them in most cases. Any failed guess will most likely crash |
36997 |
++ the attacked program which allows the kernel to detect such attempts |
36998 |
++ and react on them. PaX itself provides no reaction mechanisms, |
36999 |
++ instead it is strongly encouraged that you make use of Nergal's |
37000 |
++ segvguard (ftp://ftp.pl.openwall.com/misc/segvguard/) or grsecurity's |
37001 |
++ (http://www.grsecurity.net/) built-in crash detection features or |
37002 |
++ develop one yourself. |
37003 |
++ |
37004 |
++ By saying Y here you can choose to randomize the following areas: |
37005 |
++ - top of the task's kernel stack |
37006 |
++ - top of the task's userland stack |
37007 |
++ - base address for mmap() requests that do not specify one |
37008 |
++ (this includes all libraries) |
37009 |
++ - base address of the main executable |
37010 |
++ |
37011 |
++ It is strongly recommended to say Y here as address space layout |
37012 |
++ randomization has negligible impact on performance yet it provides |
37013 |
++ a very effective protection. |
37014 |
++ |
37015 |
++ NOTE: you can use the 'chpax' or 'paxctl' utilities to control |
37016 |
++ this feature on a per file basis. |
37017 |
++ |
37018 |
++config PAX_RANDKSTACK |
37019 |
++ bool "Randomize kernel stack base" |
37020 |
++ depends on PAX_ASLR && X86_TSC && X86_32 |
37021 |
++ help |
37022 |
++ By saying Y here the kernel will randomize every task's kernel |
37023 |
++ stack on every system call. This will not only force an attacker |
37024 |
++ to guess it but also prevent him from making use of possible |
37025 |
++ leaked information about it. |
37026 |
++ |
37027 |
++ Since the kernel stack is a rather scarce resource, randomization |
37028 |
++ may cause unexpected stack overflows, therefore you should very |
37029 |
++ carefully test your system. Note that once enabled in the kernel |
37030 |
++ configuration, this feature cannot be disabled on a per file basis. |
37031 |
++ |
37032 |
++config PAX_RANDUSTACK |
37033 |
++ bool "Randomize user stack base" |
37034 |
++ depends on PAX_ASLR |
37035 |
++ help |
37036 |
++ By saying Y here the kernel will randomize every task's userland |
37037 |
++ stack. The randomization is done in two steps where the second |
37038 |
++ one may apply a big amount of shift to the top of the stack and |
37039 |
++ cause problems for programs that want to use lots of memory (more |
37040 |
++ than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is). |
37041 |
++ For this reason the second step can be controlled by 'chpax' or |
37042 |
++ 'paxctl' on a per file basis. |
37043 |
++ |
37044 |
++config PAX_RANDMMAP |
37045 |
++ bool "Randomize mmap() base" |
37046 |
++ depends on PAX_ASLR |
37047 |
++ help |
37048 |
++ By saying Y here the kernel will use a randomized base address for |
37049 |
++ mmap() requests that do not specify one themselves. As a result |
37050 |
++ all dynamically loaded libraries will appear at random addresses |
37051 |
++ and therefore be harder to exploit by a technique where an attacker |
37052 |
++ attempts to execute library code for his purposes (e.g. spawn a |
37053 |
++ shell from an exploited program that is running at an elevated |
37054 |
++ privilege level). |
37055 |
++ |
37056 |
++ Furthermore, if a program is relinked as a dynamic ELF file, its |
37057 |
++ base address will be randomized as well, completing the full |
37058 |
++ randomization of the address space layout. Attacking such programs |
37059 |
++ becomes a guess game. You can find an example of doing this at |
37060 |
++ http://pax.grsecurity.net/et_dyn.tar.gz and practical samples at |
37061 |
++ http://www.grsecurity.net/grsec-gcc-specs.tar.gz . |
37062 |
++ |
37063 |
++ NOTE: you can use the 'chpax' or 'paxctl' utilities to control this |
37064 |
++ feature on a per file basis. |
37065 |
++ |
37066 |
++endmenu |
37067 |
++ |
37068 |
++menu "Miscellaneous hardening features" |
37069 |
++ |
37070 |
++config PAX_MEMORY_SANITIZE |
37071 |
++ bool "Sanitize all freed memory" |
37072 |
++ help |
37073 |
++ By saying Y here the kernel will erase memory pages as soon as they |
37074 |
++ are freed. This in turn reduces the lifetime of data stored in the |
37075 |
++ pages, making it less likely that sensitive information such as |
37076 |
++ passwords, cryptographic secrets, etc stay in memory for too long. |
37077 |
++ |
37078 |
++ This is especially useful for programs whose runtime is short, long |
37079 |
++ lived processes and the kernel itself benefit from this as long as |
37080 |
++ they operate on whole memory pages and ensure timely freeing of pages |
37081 |
++ that may hold sensitive information. |
37082 |
++ |
37083 |
++ The tradeoff is performance impact, on a single CPU system kernel |
37084 |
++ compilation sees a 3% slowdown, other systems and workloads may vary |
37085 |
++ and you are advised to test this feature on your expected workload |
37086 |
++ before deploying it. |
37087 |
++ |
37088 |
++ Note that this feature does not protect data stored in live pages, |
37089 |
++ e.g., process memory swapped to disk may stay there for a long time. |
37090 |
++ |
37091 |
++config PAX_MEMORY_UDEREF |
37092 |
++ bool "Prevent invalid userland pointer dereference" |
37093 |
++ depends on X86_32 && !COMPAT_VDSO && !UML_X86 |
37094 |
++ help |
37095 |
++ By saying Y here the kernel will be prevented from dereferencing |
37096 |
++ userland pointers in contexts where the kernel expects only kernel |
37097 |
++ pointers. This is both a useful runtime debugging feature and a |
37098 |
++ security measure that prevents exploiting a class of kernel bugs. |
37099 |
++ |
37100 |
++ The tradeoff is that some virtualization solutions may experience |
37101 |
++ a huge slowdown and therefore you should not enable this feature |
37102 |
++ for kernels meant to run in such environments. Whether a given VM |
37103 |
++ solution is affected or not is best determined by simply trying it |
37104 |
++ out, the performance impact will be obvious right on boot as this |
37105 |
++ mechanism engages from very early on. A good rule of thumb is that |
37106 |
++ VMs running on CPUs without hardware virtualization support (i.e., |
37107 |
++ the majority of IA-32 CPUs) will likely experience the slowdown. |
37108 |
++ |
37109 |
++config PAX_REFCOUNT |
37110 |
++ bool "Prevent various kernel object reference counter overflows" |
37111 |
++ depends on X86 |
37112 |
++ help |
37113 |
++ By saying Y here the kernel will detect and prevent overflowing |
37114 |
++ various (but not all) kinds of object reference counters. Such |
37115 |
++ overflows can normally occur due to bugs only and are often, if |
37116 |
++ not always, exploitable. |
37117 |
++ |
37118 |
++ The tradeoff is that data structures protected by an overflowed |
37119 |
++ refcount will never be freed and therefore will leak memory. Note |
37120 |
++ that this leak also happens even without this protection but in |
37121 |
++ that case the overflow can eventually trigger the freeing of the |
37122 |
++ data structure while it is still being used elsewhere, resulting |
37123 |
++ in the exploitable situation that this feature prevents. |
37124 |
++ |
37125 |
++ Since this has a negligible performance impact, you should enable |
37126 |
++ this feature. |
37127 |
++endmenu |
37128 |
++ |
37129 |
++endmenu |
37130 |
++ |
37131 |
+ config KEYS |
37132 |
+ bool "Enable access key retention support" |
37133 |
+ help |
37134 |
+diff -urNp linux-2.6.28.8/sound/core/oss/pcm_oss.c linux-2.6.28.8/sound/core/oss/pcm_oss.c |
37135 |
+--- linux-2.6.28.8/sound/core/oss/pcm_oss.c 2009-02-06 16:47:45.000000000 -0500 |
37136 |
++++ linux-2.6.28.8/sound/core/oss/pcm_oss.c 2009-02-21 09:37:50.000000000 -0500 |
37137 |
+@@ -2929,8 +2929,8 @@ static void snd_pcm_oss_proc_done(struct |
37138 |
+ } |
37139 |
+ } |
37140 |
+ #else /* !CONFIG_SND_VERBOSE_PROCFS */ |
37141 |
+-#define snd_pcm_oss_proc_init(pcm) |
37142 |
+-#define snd_pcm_oss_proc_done(pcm) |
37143 |
++#define snd_pcm_oss_proc_init(pcm) do {} while (0) |
37144 |
++#define snd_pcm_oss_proc_done(pcm) do {} while (0) |
37145 |
+ #endif /* CONFIG_SND_VERBOSE_PROCFS */ |
37146 |
+ |
37147 |
+ /* |
37148 |
+diff -urNp linux-2.6.28.8/sound/core/seq/seq_lock.h linux-2.6.28.8/sound/core/seq/seq_lock.h |
37149 |
+--- linux-2.6.28.8/sound/core/seq/seq_lock.h 2009-02-06 16:47:45.000000000 -0500 |
37150 |
++++ linux-2.6.28.8/sound/core/seq/seq_lock.h 2009-02-21 09:37:50.000000000 -0500 |
37151 |
+@@ -23,10 +23,10 @@ void snd_use_lock_sync_helper(snd_use_lo |
37152 |
+ #else /* SMP || CONFIG_SND_DEBUG */ |
37153 |
+ |
37154 |
+ typedef spinlock_t snd_use_lock_t; /* dummy */ |
37155 |
+-#define snd_use_lock_init(lockp) /**/ |
37156 |
+-#define snd_use_lock_use(lockp) /**/ |
37157 |
+-#define snd_use_lock_free(lockp) /**/ |
37158 |
+-#define snd_use_lock_sync(lockp) /**/ |
37159 |
++#define snd_use_lock_init(lockp) do {} while (0) |
37160 |
++#define snd_use_lock_use(lockp) do {} while (0) |
37161 |
++#define snd_use_lock_free(lockp) do {} while (0) |
37162 |
++#define snd_use_lock_sync(lockp) do {} while (0) |
37163 |
+ |
37164 |
+ #endif /* SMP || CONFIG_SND_DEBUG */ |
37165 |
+ |
37166 |
+diff -urNp linux-2.6.28.8/sound/pci/ac97/ac97_patch.c linux-2.6.28.8/sound/pci/ac97/ac97_patch.c |
37167 |
+--- linux-2.6.28.8/sound/pci/ac97/ac97_patch.c 2009-02-06 16:47:45.000000000 -0500 |
37168 |
++++ linux-2.6.28.8/sound/pci/ac97/ac97_patch.c 2009-02-21 09:37:50.000000000 -0500 |
37169 |
+@@ -1498,7 +1498,7 @@ static const struct snd_ac97_res_table a |
37170 |
+ { AC97_VIDEO, 0x9f1f }, |
37171 |
+ { AC97_AUX, 0x9f1f }, |
37172 |
+ { AC97_PCM, 0x9f1f }, |
37173 |
+- { } /* terminator */ |
37174 |
++ { 0, 0 } /* terminator */ |
37175 |
+ }; |
37176 |
+ |
37177 |
+ static int patch_ad1819(struct snd_ac97 * ac97) |
37178 |
+@@ -3870,7 +3870,7 @@ static struct snd_ac97_res_table lm4550_ |
37179 |
+ { AC97_AUX, 0x1f1f }, |
37180 |
+ { AC97_PCM, 0x1f1f }, |
37181 |
+ { AC97_REC_GAIN, 0x0f0f }, |
37182 |
+- { } /* terminator */ |
37183 |
++ { 0, 0 } /* terminator */ |
37184 |
+ }; |
37185 |
+ |
37186 |
+ static int patch_lm4550(struct snd_ac97 *ac97) |
37187 |
+diff -urNp linux-2.6.28.8/sound/pci/ens1370.c linux-2.6.28.8/sound/pci/ens1370.c |
37188 |
+--- linux-2.6.28.8/sound/pci/ens1370.c 2009-02-06 16:47:45.000000000 -0500 |
37189 |
++++ linux-2.6.28.8/sound/pci/ens1370.c 2009-02-21 09:37:50.000000000 -0500 |
37190 |
+@@ -452,7 +452,7 @@ static struct pci_device_id snd_audiopci |
37191 |
+ { 0x1274, 0x5880, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ES1373 - CT5880 */ |
37192 |
+ { 0x1102, 0x8938, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* Ectiva EV1938 */ |
37193 |
+ #endif |
37194 |
+- { 0, } |
37195 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
37196 |
+ }; |
37197 |
+ |
37198 |
+ MODULE_DEVICE_TABLE(pci, snd_audiopci_ids); |
37199 |
+diff -urNp linux-2.6.28.8/sound/pci/intel8x0.c linux-2.6.28.8/sound/pci/intel8x0.c |
37200 |
+--- linux-2.6.28.8/sound/pci/intel8x0.c 2009-02-06 16:47:45.000000000 -0500 |
37201 |
++++ linux-2.6.28.8/sound/pci/intel8x0.c 2009-02-21 09:37:50.000000000 -0500 |
37202 |
+@@ -443,7 +443,7 @@ static struct pci_device_id snd_intel8x0 |
37203 |
+ { 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD8111 */ |
37204 |
+ { 0x1022, 0x7445, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD768 */ |
37205 |
+ { 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI }, /* Ali5455 */ |
37206 |
+- { 0, } |
37207 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
37208 |
+ }; |
37209 |
+ |
37210 |
+ MODULE_DEVICE_TABLE(pci, snd_intel8x0_ids); |
37211 |
+@@ -2088,7 +2088,7 @@ static struct ac97_quirk ac97_quirks[] _ |
37212 |
+ .type = AC97_TUNE_HP_ONLY |
37213 |
+ }, |
37214 |
+ #endif |
37215 |
+- { } /* terminator */ |
37216 |
++ { 0, 0, 0, 0, NULL, 0 } /* terminator */ |
37217 |
+ }; |
37218 |
+ |
37219 |
+ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock, |
37220 |
+diff -urNp linux-2.6.28.8/sound/pci/intel8x0m.c linux-2.6.28.8/sound/pci/intel8x0m.c |
37221 |
+--- linux-2.6.28.8/sound/pci/intel8x0m.c 2009-02-06 16:47:45.000000000 -0500 |
37222 |
++++ linux-2.6.28.8/sound/pci/intel8x0m.c 2009-02-21 09:37:50.000000000 -0500 |
37223 |
+@@ -239,7 +239,7 @@ static struct pci_device_id snd_intel8x0 |
37224 |
+ { 0x1022, 0x746d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_INTEL }, /* AMD8111 */ |
37225 |
+ { 0x10b9, 0x5455, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALI }, /* Ali5455 */ |
37226 |
+ #endif |
37227 |
+- { 0, } |
37228 |
++ { 0, 0, 0, 0, 0, 0, 0 } |
37229 |
+ }; |
37230 |
+ |
37231 |
+ MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids); |
37232 |
+@@ -1258,7 +1258,7 @@ static struct shortname_table { |
37233 |
+ { 0x5455, "ALi M5455" }, |
37234 |
+ { 0x746d, "AMD AMD8111" }, |
37235 |
+ #endif |
37236 |
+- { 0 }, |
37237 |
++ { 0, NULL }, |
37238 |
+ }; |
37239 |
+ |
37240 |
+ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci, |
37241 |
+diff -urNp linux-2.6.28.8/virt/kvm/kvm_main.c linux-2.6.28.8/virt/kvm/kvm_main.c |
37242 |
+--- linux-2.6.28.8/virt/kvm/kvm_main.c 2009-02-06 16:47:45.000000000 -0500 |
37243 |
++++ linux-2.6.28.8/virt/kvm/kvm_main.c 2009-02-21 09:37:50.000000000 -0500 |
37244 |
+@@ -1765,6 +1765,9 @@ static struct miscdevice kvm_dev = { |
37245 |
+ KVM_MINOR, |
37246 |
+ "kvm", |
37247 |
+ &kvm_chardev_ops, |
37248 |
++ {NULL, NULL}, |
37249 |
++ NULL, |
37250 |
++ NULL |
37251 |
+ }; |
37252 |
+ |
37253 |
+ static void hardware_enable(void *junk) |
37254 |
+@@ -1996,7 +1999,7 @@ static void kvm_sched_out(struct preempt |
37255 |
+ kvm_arch_vcpu_put(vcpu); |
37256 |
+ } |
37257 |
+ |
37258 |
+-int kvm_init(void *opaque, unsigned int vcpu_size, |
37259 |
++int kvm_init(const void *opaque, unsigned int vcpu_size, |
37260 |
+ struct module *module) |
37261 |
+ { |
37262 |
+ int r; |
37263 |
|
37264 |
Added: hardened/2.6/tags/2.6.28-7/4421_grsec-remove-localversion-grsec.patch |
37265 |
=================================================================== |
37266 |
--- hardened/2.6/tags/2.6.28-7/4421_grsec-remove-localversion-grsec.patch (rev 0) |
37267 |
+++ hardened/2.6/tags/2.6.28-7/4421_grsec-remove-localversion-grsec.patch 2009-03-21 10:58:14 UTC (rev 1529) |
37268 |
@@ -0,0 +1,9 @@ |
37269 |
+From: Kerin Millar <kerframil@×××××.com> |
37270 |
+ |
37271 |
+Remove grsecurity's localversion-grsec file as it is inconsistent with |
37272 |
+Gentoo's kernel practices and naming scheme. |
37273 |
+ |
37274 |
+--- a/localversion-grsec 2008-02-24 14:26:59.000000000 +0000 |
37275 |
++++ b/localversion-grsec 1970-01-01 01:00:00.000000000 +0100 |
37276 |
+@@ -1 +0,0 @@ |
37277 |
+--grsec |
37278 |
|
37279 |
Added: hardened/2.6/tags/2.6.28-7/4422_grsec-mute-warnings.patch |
37280 |
=================================================================== |
37281 |
--- hardened/2.6/tags/2.6.28-7/4422_grsec-mute-warnings.patch (rev 0) |
37282 |
+++ hardened/2.6/tags/2.6.28-7/4422_grsec-mute-warnings.patch 2009-03-21 10:58:14 UTC (rev 1529) |
37283 |
@@ -0,0 +1,28 @@ |
37284 |
+From: Gordon Malm <gengor@g.o> |
37285 |
+ |
37286 |
+Updated patch for kernel series 2.6.24. |
37287 |
+ |
37288 |
+The credits/description from the original version of this patch remain accurate |
37289 |
+and are included below. |
37290 |
+ |
37291 |
+--- |
37292 |
+From: Alexander Gabert <gaberta@××××××××.de> |
37293 |
+ |
37294 |
+This patch removes the warnings introduced by grsec patch 2.1.9 and later. |
37295 |
+It removes the -W options added by the patch and restores the original |
37296 |
+warning flags of vanilla kernel versions. |
37297 |
+ |
37298 |
+Acked-by: Christian Heim <phreak@g.o> |
37299 |
+--- |
37300 |
+ |
37301 |
+--- a/Makefile |
37302 |
++++ b/Makefile |
37303 |
+@@ -214,7 +214,7 @@ |
37304 |
+ |
37305 |
+ HOSTCC = gcc |
37306 |
+ HOSTCXX = g++ |
37307 |
+-HOSTCFLAGS = -Wall -W -Wno-unused -Wno-sign-compare -Wstrict-prototypes -O2 -fomit-frame-pointer |
37308 |
++HOSTCFLAGS = -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer |
37309 |
+ HOSTCXXFLAGS = -O2 |
37310 |
+ |
37311 |
+ # Decide whether to build built-in, modular, or both. |
37312 |
|
37313 |
Added: hardened/2.6/tags/2.6.28-7/4425_grsec-pax-without-grsec.patch |
37314 |
=================================================================== |
37315 |
--- hardened/2.6/tags/2.6.28-7/4425_grsec-pax-without-grsec.patch (rev 0) |
37316 |
+++ hardened/2.6/tags/2.6.28-7/4425_grsec-pax-without-grsec.patch 2009-03-21 10:58:14 UTC (rev 1529) |
37317 |
@@ -0,0 +1,60 @@ |
37318 |
+From: Gordon Malm <gengor@g.o> |
37319 |
+ |
37320 |
+Allow PaX options to be selected without first selecting CONFIG_GRKERNSEC. |
37321 |
+ |
37322 |
+This patch has been updated to keep current with newer kernel versions. |
37323 |
+The original version of this patch contained no credits/description. |
37324 |
+ |
37325 |
+--- a/arch/x86/mm/fault.c |
37326 |
++++ b/arch/x86/mm/fault.c |
37327 |
+@@ -431,10 +431,12 @@ static void show_fault_oops(struct pt_re |
37328 |
+ if (init_mm.start_code <= address && address < init_mm.end_code) |
37329 |
+ #endif |
37330 |
+ { |
37331 |
++#ifdef CONFIG_GRKERNSEC |
37332 |
+ if (current->signal->curr_ip) |
37333 |
+ printk(KERN_ERR "PAX: From %u.%u.%u.%u: %s:%d, uid/euid: %u/%u, attempted to modify kernel code\n", |
37334 |
+ NIPQUAD(current->signal->curr_ip), current->comm, task_pid_nr(current), current->uid, current->euid); |
37335 |
+ else |
37336 |
++#endif |
37337 |
+ printk(KERN_ERR "PAX: %s:%d, uid/euid: %u/%u, attempted to modify kernel code\n", |
37338 |
+ current->comm, task_pid_nr(current), current->uid, current->euid); |
37339 |
+ } |
37340 |
+--- a/fs/exec.c |
37341 |
++++ b/fs/exec.c |
37342 |
+@@ -1693,9 +1693,11 @@ void pax_report_fault(struct pt_regs *re |
37343 |
+ } |
37344 |
+ up_read(&mm->mmap_sem); |
37345 |
+ } |
37346 |
++#ifdef CONFIG_GRKERNSEC |
37347 |
+ if (tsk->signal->curr_ip) |
37348 |
+ printk(KERN_ERR "PAX: From %u.%u.%u.%u: execution attempt in: %s, %08lx-%08lx %08lx\n", NIPQUAD(tsk->signal->curr_ip), path_fault, start, end, offset); |
37349 |
+ else |
37350 |
++#endif |
37351 |
+ printk(KERN_ERR "PAX: execution attempt in: %s, %08lx-%08lx %08lx\n", path_fault, start, end, offset); |
37352 |
+ printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, " |
37353 |
+ "PC: %p, SP: %p\n", path_exec, tsk->comm, task_pid_nr(tsk), |
37354 |
+@@ -1710,10 +1712,12 @@ void pax_report_fault(struct pt_regs *re |
37355 |
+ #ifdef CONFIG_PAX_REFCOUNT |
37356 |
+ void pax_report_refcount_overflow(struct pt_regs *regs) |
37357 |
+ { |
37358 |
++#ifdef CONFIG_GRKERNSEC |
37359 |
+ if (current->signal->curr_ip) |
37360 |
+ printk(KERN_ERR "PAX: From %u.%u.%u.%u: refcount overflow detected in: %s:%d, uid/euid: %u/%u\n", |
37361 |
+ NIPQUAD(current->signal->curr_ip), current->comm, task_pid_nr(current), current->uid, current->euid); |
37362 |
+ else |
37363 |
++#endif |
37364 |
+ printk(KERN_ERR "PAX: refcount overflow detected in: %s:%d, uid/euid: %u/%u\n", |
37365 |
+ current->comm, task_pid_nr(current), current->uid, current->euid); |
37366 |
+ print_symbol(KERN_ERR "PAX: refcount overflow occured at: %s\n", instruction_pointer(regs)); |
37367 |
+--- a/security/Kconfig |
37368 |
++++ b/security/Kconfig |
37369 |
+@@ -10,7 +10,7 @@ menu "PaX" |
37370 |
+ |
37371 |
+ config PAX |
37372 |
+ bool "Enable various PaX features" |
37373 |
+- depends on GRKERNSEC && (ALPHA || ARM || AVR32 || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || PPC64 || SPARC32 || SPARC64 || X86) |
37374 |
++ depends on (ALPHA || ARM || AVR32 || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || PPC64 || SPARC32 || SPARC64 || X86) |
37375 |
+ help |
37376 |
+ This allows you to enable various PaX features. PaX adds |
37377 |
+ intrusion prevention mechanisms to the kernel that reduce |
37378 |
|
37379 |
Added: hardened/2.6/tags/2.6.28-7/4430_grsec-kconfig-default-gids.patch |
37380 |
=================================================================== |
37381 |
--- hardened/2.6/tags/2.6.28-7/4430_grsec-kconfig-default-gids.patch (rev 0) |
37382 |
+++ hardened/2.6/tags/2.6.28-7/4430_grsec-kconfig-default-gids.patch 2009-03-21 10:58:14 UTC (rev 1529) |
37383 |
@@ -0,0 +1,76 @@ |
37384 |
+From: Kerin Millar <kerframil@×××××.com> |
37385 |
+ |
37386 |
+grsecurity contains a number of options which allow certain protections |
37387 |
+to be applied to or exempted from members of a given group. However, the |
37388 |
+default GIDs specified in the upstream patch are entirely arbitrary and |
37389 |
+there is no telling which (if any) groups the GIDs will correlate with |
37390 |
+on an end-user's system. Because some users don't pay a great deal of |
37391 |
+attention to the finer points of kernel configuration, it is probably |
37392 |
+wise to specify some reasonable defaults so as to stop careless users |
37393 |
+from shooting themselves in the foot. |
37394 |
+ |
37395 |
+--- a/grsecurity/Kconfig |
37396 |
++++ b/grsecurity/Kconfig |
37397 |
+@@ -352,7 +564,7 @@ |
37398 |
+ config GRKERNSEC_PROC_GID |
37399 |
+ int "GID for special group" |
37400 |
+ depends on GRKERNSEC_PROC_USERGROUP |
37401 |
+- default 1001 |
37402 |
++ default 10 |
37403 |
+ |
37404 |
+ config GRKERNSEC_PROC_ADD |
37405 |
+ bool "Additional restrictions" |
37406 |
+@@ -547,7 +759,7 @@ |
37407 |
+ config GRKERNSEC_AUDIT_GID |
37408 |
+ int "GID for auditing" |
37409 |
+ depends on GRKERNSEC_AUDIT_GROUP |
37410 |
+- default 1007 |
37411 |
++ default 100 |
37412 |
+ |
37413 |
+ config GRKERNSEC_EXECLOG |
37414 |
+ bool "Exec logging" |
37415 |
+@@ -700,7 +912,7 @@ |
37416 |
+ config GRKERNSEC_TPE_GID |
37417 |
+ int "GID for untrusted users" |
37418 |
+ depends on GRKERNSEC_TPE && !GRKERNSEC_TPE_INVERT |
37419 |
+- default 1005 |
37420 |
++ default 100 |
37421 |
+ help |
37422 |
+ If you have selected the "Invert GID option" above, setting this |
37423 |
+ GID determines what group TPE restrictions will be *disabled* for. |
37424 |
+@@ -712,7 +924,7 @@ |
37425 |
+ config GRKERNSEC_TPE_GID |
37426 |
+ int "GID for trusted users" |
37427 |
+ depends on GRKERNSEC_TPE && GRKERNSEC_TPE_INVERT |
37428 |
+- default 1005 |
37429 |
++ default 10 |
37430 |
+ help |
37431 |
+ If you have selected the "Invert GID option" above, setting this |
37432 |
+ GID determines what group TPE restrictions will be *disabled* for. |
37433 |
+@@ -754,7 +966,7 @@ |
37434 |
+ config GRKERNSEC_SOCKET_ALL_GID |
37435 |
+ int "GID to deny all sockets for" |
37436 |
+ depends on GRKERNSEC_SOCKET_ALL |
37437 |
+- default 1004 |
37438 |
++ default 65534 |
37439 |
+ help |
37440 |
+ Here you can choose the GID to disable socket access for. Remember to |
37441 |
+ add the users you want socket access disabled for to the GID |
37442 |
+@@ -775,7 +987,7 @@ |
37443 |
+ config GRKERNSEC_SOCKET_CLIENT_GID |
37444 |
+ int "GID to deny client sockets for" |
37445 |
+ depends on GRKERNSEC_SOCKET_CLIENT |
37446 |
+- default 1003 |
37447 |
++ default 65534 |
37448 |
+ help |
37449 |
+ Here you can choose the GID to disable client socket access for. |
37450 |
+ Remember to add the users you want client socket access disabled for to |
37451 |
+@@ -793,7 +1005,7 @@ |
37452 |
+ config GRKERNSEC_SOCKET_SERVER_GID |
37453 |
+ int "GID to deny server sockets for" |
37454 |
+ depends on GRKERNSEC_SOCKET_SERVER |
37455 |
+- default 1002 |
37456 |
++ default 65534 |
37457 |
+ help |
37458 |
+ Here you can choose the GID to disable server socket access for. |
37459 |
+ Remember to add the users you want server socket access disabled for to |
37460 |
|
37461 |
Added: hardened/2.6/tags/2.6.28-7/4435_grsec-kconfig-gentoo.patch |
37462 |
=================================================================== |
37463 |
--- hardened/2.6/tags/2.6.28-7/4435_grsec-kconfig-gentoo.patch (rev 0) |
37464 |
+++ hardened/2.6/tags/2.6.28-7/4435_grsec-kconfig-gentoo.patch 2009-03-21 10:58:14 UTC (rev 1529) |
37465 |
@@ -0,0 +1,243 @@ |
37466 |
+From: Gordon Malm <gengor@g.o> |
37467 |
+From: Kerin Millar <kerframil@×××××.com> |
37468 |
+ |
37469 |
+Add Hardened Gentoo [server/workstation] predefined grsecurity |
37470 |
+levels. They're designed to provide a comparitively high level of |
37471 |
+security while remaining generally suitable for as great a majority |
37472 |
+of the userbase as possible (particularly new users). |
37473 |
+ |
37474 |
+Make Hardened Gentoo [workstation] predefined grsecurity level the |
37475 |
+default. The Hardened Gentoo [server] level is more restrictive |
37476 |
+and conflicts with some software and thus would be less suitable. |
37477 |
+ |
37478 |
+The original version of this patch was conceived and created by: |
37479 |
+Ned Ludd <solar@g.o> |
37480 |
+ |
37481 |
+--- a/grsecurity/Kconfig |
37482 |
++++ b/grsecurity/Kconfig |
37483 |
+@@ -20,7 +20,7 @@ config GRKERNSEC |
37484 |
+ choice |
37485 |
+ prompt "Security Level" |
37486 |
+ depends on GRKERNSEC |
37487 |
+- default GRKERNSEC_CUSTOM |
37488 |
++ default GRKERNSEC_HARDENED_WORKSTATION |
37489 |
+ |
37490 |
+ config GRKERNSEC_LOW |
37491 |
+ bool "Low" |
37492 |
+@@ -183,6 +183,216 @@ config GRKERNSEC_HIGH |
37493 |
+ - Mount/unmount/remount logging |
37494 |
+ - Kernel symbol hiding |
37495 |
+ - Prevention of memory exhaustion-based exploits |
37496 |
++ |
37497 |
++config GRKERNSEC_HARDENED_SERVER |
37498 |
++ bool "Hardened Gentoo [server]" |
37499 |
++ select GRKERNSEC_AUDIT_MOUNT |
37500 |
++ select GRKERNSEC_BRUTE |
37501 |
++ select GRKERNSEC_CHROOT |
37502 |
++ select GRKERNSEC_CHROOT_CAPS |
37503 |
++ select GRKERNSEC_CHROOT_CHDIR |
37504 |
++ select GRKERNSEC_CHROOT_CHMOD |
37505 |
++ select GRKERNSEC_CHROOT_DOUBLE |
37506 |
++ select GRKERNSEC_CHROOT_FCHDIR |
37507 |
++ select GRKERNSEC_CHROOT_FINDTASK |
37508 |
++ select GRKERNSEC_CHROOT_MKNOD |
37509 |
++ select GRKERNSEC_CHROOT_MOUNT |
37510 |
++ select GRKERNSEC_CHROOT_NICE |
37511 |
++ select GRKERNSEC_CHROOT_PIVOT |
37512 |
++ select GRKERNSEC_CHROOT_SHMAT |
37513 |
++ select GRKERNSEC_CHROOT_SYSCTL |
37514 |
++ select GRKERNSEC_CHROOT_UNIX |
37515 |
++ select GRKERNSEC_DMESG |
37516 |
++ select GRKERNSEC_EXECVE |
37517 |
++ select GRKERNSEC_FIFO |
37518 |
++ select GRKERNSEC_FORKFAIL |
37519 |
++ select GRKERNSEC_HIDESYM |
37520 |
++ select GRKERNSEC_IO if (X86) |
37521 |
++ select GRKERNSEC_KMEM |
37522 |
++ select GRKERNSEC_LINK |
37523 |
++ select GRKERNSEC_MODSTOP if (MODULES) |
37524 |
++ select GRKERNSEC_PROC |
37525 |
++ select GRKERNSEC_PROC_ADD |
37526 |
++ select GRKERNSEC_PROC_IPADDR |
37527 |
++ select GRKERNSEC_PROC_MEMMAP |
37528 |
++ select GRKERNSEC_PROC_USERGROUP |
37529 |
++ select GRKERNSEC_RANDNET |
37530 |
++ select GRKERNSEC_RESLOG |
37531 |
++ select GRKERNSEC_SIGNAL |
37532 |
++# select GRKERNSEC_SOCKET |
37533 |
++# select GRKERNSEC_SOCKET_SERVER |
37534 |
++ select GRKERNSEC_SYSCTL |
37535 |
++ select GRKERNSEC_SYSCTL_ON |
37536 |
++ select GRKERNSEC_TIME |
37537 |
++ select PAX |
37538 |
++ select PAX_ASLR |
37539 |
++ select PAX_DLRESOLVE if (SPARC32 || SPARC64) |
37540 |
++ select PAX_EI_PAX |
37541 |
++ select PAX_EMUPLT if (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64) |
37542 |
++ select PAX_EMUSIGRT if (PARISC || PPC32) |
37543 |
++ select PAX_EMUTRAMP if (PARISC || PPC32) |
37544 |
++ select PAX_ETEXECRELOCS if (ALPHA || IA64 || PARISC) |
37545 |
++ select PAX_KERNEXEC if (X86 && !EFI && !COMPAT_VDSO && !PARAVIRT && (!X86_32 || X86_WP_WORKS_OK)) |
37546 |
++ select PAX_MEMORY_SANITIZE |
37547 |
++ select PAX_MEMORY_UDEREF if (X86_32 && !COMPAT_VDSO && !UML_X86) |
37548 |
++ select PAX_MPROTECT if (!PPC64) |
37549 |
++ select PAX_HAVE_ACL_FLAGS |
37550 |
++ select PAX_NOELFRELOCS if (X86) |
37551 |
++ select PAX_NOEXEC |
37552 |
++ select PAX_PAGEEXEC |
37553 |
++ select PAX_PT_PAX_FLAGS |
37554 |
++ select PAX_RANDKSTACK if (X86_32 && X86_TSC) |
37555 |
++ select PAX_RANDMMAP |
37556 |
++ select PAX_RANDUSTACK |
37557 |
++ select PAX_REFCOUNT if (X86) |
37558 |
++ select PAX_SEGMEXEC if (X86_32) |
37559 |
++ select PAX_SYSCALL if (PPC32) |
37560 |
++ help |
37561 |
++ If you say Y here, a configuration will be used that is endorsed by |
37562 |
++ the Hardened Gentoo project. Therefore, many of the protections |
37563 |
++ made available by grsecurity and PaX will be enabled. |
37564 |
++ |
37565 |
++ Hardened Gentoo's pre-defined security levels are designed to provide |
37566 |
++ a high level of security while minimizing incompatibilities with the |
37567 |
++ majority of available software. For further information, please |
37568 |
++ view <http://www.grsecurity.net> and <http://pax.grsecurity.net> as |
37569 |
++ well as the Hardened Gentoo Primer at |
37570 |
++ <http://www.gentoo.org/proj/en/hardened/primer.xml>. |
37571 |
++ |
37572 |
++ This Hardened Gentoo [server] level is identical to the |
37573 |
++ Hardened Gentoo [workstation] level, but with the GRKERNSEC_IO, |
37574 |
++ PAX_KERNEXEC and PAX_NOELFRELOCS security features enabled. |
37575 |
++ Accordingly, this is the preferred security level if the system will |
37576 |
++ not be utilizing software incompatible with the aforementioned |
37577 |
++ grsecurity/PaX features. |
37578 |
++ |
37579 |
++ You may wish to emerge paxctl, a utility which allows you to toggle |
37580 |
++ PaX features on problematic binaries on an individual basis. Note that |
37581 |
++ this only works for ELF binaries that contain a PT_PAX_FLAGS header. |
37582 |
++ Translated, this means that if you wish to toggle PaX features on |
37583 |
++ binaries provided by applications that are distributed only in binary |
37584 |
++ format (rather than being built locally from sources), you will need to |
37585 |
++ run paxctl -C on the binaries beforehand so as to inject the missing |
37586 |
++ headers. |
37587 |
++ |
37588 |
++ When this level is selected, some options cannot be changed. However, |
37589 |
++ you may opt to fully customize the options that are selected by |
37590 |
++ choosing "Custom" in the Security Level menu. You may find it helpful |
37591 |
++ to inherit the options selected by the "Hardened Gentoo [server]" |
37592 |
++ security level as a starting point for further configuration. To |
37593 |
++ accomplish this, select this security level then exit the menuconfig |
37594 |
++ interface, saving changes when prompted. Then, run make menuconfig |
37595 |
++ again and select the "Custom" level. |
37596 |
++ |
37597 |
++ Note that this security level probably should not be used if the |
37598 |
++ target system is a 32bit x86 virtualized guest. If you intend to run |
37599 |
++ the kernel in a 32bit x86 virtualized guest you will likely need to |
37600 |
++ disable the PAX_MEMORY_UDEREF option in order to avoid an unacceptable |
37601 |
++ impact on performance. |
37602 |
++ |
37603 |
++config GRKERNSEC_HARDENED_WORKSTATION |
37604 |
++ bool "Hardened Gentoo [workstation]" |
37605 |
++ select GRKERNSEC_AUDIT_MOUNT |
37606 |
++ select GRKERNSEC_BRUTE |
37607 |
++ select GRKERNSEC_CHROOT |
37608 |
++ select GRKERNSEC_CHROOT_CAPS |
37609 |
++ select GRKERNSEC_CHROOT_CHDIR |
37610 |
++ select GRKERNSEC_CHROOT_CHMOD |
37611 |
++ select GRKERNSEC_CHROOT_DOUBLE |
37612 |
++ select GRKERNSEC_CHROOT_FCHDIR |
37613 |
++ select GRKERNSEC_CHROOT_FINDTASK |
37614 |
++ select GRKERNSEC_CHROOT_MKNOD |
37615 |
++ select GRKERNSEC_CHROOT_MOUNT |
37616 |
++ select GRKERNSEC_CHROOT_NICE |
37617 |
++ select GRKERNSEC_CHROOT_PIVOT |
37618 |
++ select GRKERNSEC_CHROOT_SHMAT |
37619 |
++ select GRKERNSEC_CHROOT_SYSCTL |
37620 |
++ select GRKERNSEC_CHROOT_UNIX |
37621 |
++ select GRKERNSEC_DMESG |
37622 |
++ select GRKERNSEC_EXECVE |
37623 |
++ select GRKERNSEC_FIFO |
37624 |
++ select GRKERNSEC_FORKFAIL |
37625 |
++ select GRKERNSEC_HIDESYM |
37626 |
++ select GRKERNSEC_KMEM |
37627 |
++ select GRKERNSEC_LINK |
37628 |
++ select GRKERNSEC_MODSTOP if (MODULES) |
37629 |
++ select GRKERNSEC_PROC |
37630 |
++ select GRKERNSEC_PROC_ADD |
37631 |
++ select GRKERNSEC_PROC_IPADDR |
37632 |
++ select GRKERNSEC_PROC_MEMMAP |
37633 |
++ select GRKERNSEC_PROC_USERGROUP |
37634 |
++ select GRKERNSEC_RANDNET |
37635 |
++ select GRKERNSEC_RESLOG |
37636 |
++ select GRKERNSEC_SIGNAL |
37637 |
++# select GRKERNSEC_SOCKET |
37638 |
++# select GRKERNSEC_SOCKET_SERVER |
37639 |
++ select GRKERNSEC_SYSCTL |
37640 |
++ select GRKERNSEC_SYSCTL_ON |
37641 |
++ select GRKERNSEC_TIME |
37642 |
++ select PAX |
37643 |
++ select PAX_ASLR |
37644 |
++ select PAX_DLRESOLVE if (SPARC32 || SPARC64) |
37645 |
++ select PAX_EI_PAX |
37646 |
++ select PAX_EMUPLT if (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64) |
37647 |
++ select PAX_EMUSIGRT if (PARISC || PPC32) |
37648 |
++ select PAX_EMUTRAMP if (PARISC || PPC32) |
37649 |
++ select PAX_ETEXECRELOCS if (ALPHA || IA64 || PARISC) |
37650 |
++ select PAX_MEMORY_SANITIZE |
37651 |
++ select PAX_MEMORY_UDEREF if (X86_32 && !COMPAT_VDSO && !UML_X86) |
37652 |
++ select PAX_MPROTECT if (!PPC64) |
37653 |
++ select PAX_HAVE_ACL_FLAGS |
37654 |
++ select PAX_NOEXEC |
37655 |
++ select PAX_PAGEEXEC |
37656 |
++ select PAX_PT_PAX_FLAGS |
37657 |
++ select PAX_RANDKSTACK if (X86_32 && X86_TSC) |
37658 |
++ select PAX_RANDMMAP |
37659 |
++ select PAX_RANDUSTACK |
37660 |
++ select PAX_REFCOUNT if (X86) |
37661 |
++ select PAX_SEGMEXEC if (X86_32) |
37662 |
++ select PAX_SYSCALL if (PPC32) |
37663 |
++ help |
37664 |
++ If you say Y here, a configuration will be used that is endorsed by |
37665 |
++ the Hardened Gentoo project. Therefore, many of the protections |
37666 |
++ made available by grsecurity and PaX will be enabled. |
37667 |
++ |
37668 |
++ Hardened Gentoo's pre-defined security levels are designed to provide |
37669 |
++ a high level of security while minimizing incompatibilities with the |
37670 |
++ majority of available software. For further information, please |
37671 |
++ view <http://www.grsecurity.net> and <http://pax.grsecurity.net> as |
37672 |
++ well as the Hardened Gentoo Primer at |
37673 |
++ <http://www.gentoo.org/proj/en/hardened/primer.xml>. |
37674 |
++ |
37675 |
++ This Hardened Gentoo [workstation] level is designed for machines |
37676 |
++ which are intended to run software not compatible with the |
37677 |
++ GRKERNSEC_IO, PAX_KERNEXEC and PAX_NOELFRELOCS features of grsecurity. |
37678 |
++ Accordingly, this security level is suitable for use with the X server |
37679 |
++ "Xorg" and/or any system that will act as host OS to the virtualization |
37680 |
++ softwares vmware-server or virtualbox. |
37681 |
++ |
37682 |
++ You may wish to emerge paxctl, a utility which allows you to toggle |
37683 |
++ PaX features on problematic binaries on an individual basis. Note that |
37684 |
++ this only works for ELF binaries that contain a PT_PAX_FLAGS header. |
37685 |
++ Translated, this means that if you wish to toggle PaX features on |
37686 |
++ binaries provided by applications that are distributed only in binary |
37687 |
++ format (rather than being built locally from sources), you will need to |
37688 |
++ run paxctl -C on the binaries beforehand so as to inject the missing |
37689 |
++ headers. |
37690 |
++ |
37691 |
++ When this level is selected, some options cannot be changed. However, |
37692 |
++ you may opt to fully customize the options that are selected by |
37693 |
++ choosing "Custom" in the Security Level menu. You may find it helpful |
37694 |
++ to inherit the options selected by the "Hardened Gentoo [workstation]" |
37695 |
++ security level as a starting point for further configuration. To |
37696 |
++ accomplish this, select this security level then exit the menuconfig |
37697 |
++ interface, saving changes when prompted. Then, run make menuconfig |
37698 |
++ again and select the "Custom" level. |
37699 |
++ |
37700 |
++ Note that this security level probably should not be used if the |
37701 |
++ target system is a 32bit x86 virtualized guest. If you intend to run |
37702 |
++ the kernel in a 32bit x86 virtualized guest you will likely need to |
37703 |
++ disable the PAX_MEMORY_UDEREF option in order to avoid an unacceptable |
37704 |
++ impact on performance. |
37705 |
++ |
37706 |
+ config GRKERNSEC_CUSTOM |
37707 |
+ bool "Custom" |
37708 |
+ help |
37709 |
|
37710 |
Added: hardened/2.6/tags/2.6.28-7/4440_selinux-avc_audit-log-curr_ip.patch |
37711 |
=================================================================== |
37712 |
--- hardened/2.6/tags/2.6.28-7/4440_selinux-avc_audit-log-curr_ip.patch (rev 0) |
37713 |
+++ hardened/2.6/tags/2.6.28-7/4440_selinux-avc_audit-log-curr_ip.patch 2009-03-21 10:58:14 UTC (rev 1529) |
37714 |
@@ -0,0 +1,65 @@ |
37715 |
+From: Gordon Malm <gengor@g.o> |
37716 |
+ |
37717 |
+This is a reworked version of the original |
37718 |
+*_selinux-avc_audit-log-curr_ip.patch carried in earlier releases of |
37719 |
+hardened-sources. |
37720 |
+ |
37721 |
+Dropping the patch, or simply fixing the #ifdef of the original patch |
37722 |
+could break automated logging setups so this route was necessary. |
37723 |
+ |
37724 |
+Suggestions for improving the help text are welcome. |
37725 |
+ |
37726 |
+The original patch's description is still accurate and included below. |
37727 |
+ |
37728 |
+--- |
37729 |
+Provides support for a new field ipaddr within the SELinux |
37730 |
+AVC audit log, relying in task_struct->curr_ip (ipv4 only) |
37731 |
+provided by grSecurity patch to be applied before. |
37732 |
+ |
37733 |
+Signed-off-by: Lorenzo Hernandez Garcia-Hierro <lorenzo@×××.org> |
37734 |
+--- |
37735 |
+ |
37736 |
+--- a/grsecurity/Kconfig |
37737 |
++++ b/grsecurity/Kconfig |
37738 |
+@@ -1044,6 +1044,27 @@ endmenu |
37739 |
+ menu "Logging Options" |
37740 |
+ depends on GRKERNSEC |
37741 |
+ |
37742 |
++config GRKERNSEC_SELINUX_AVC_LOG_IPADDR |
37743 |
++ def_bool n |
37744 |
++ prompt "Add source IP address to SELinux AVC log messages" |
37745 |
++ depends on GRKERNSEC && SECURITY_SELINUX |
37746 |
++ help |
37747 |
++ If you say Y here, a new field "ipaddr=" will be added to many SELinux |
37748 |
++ AVC log messages. The value of this field in any given message |
37749 |
++ represents the source IP address of the remote machine/user that created |
37750 |
++ the offending process. |
37751 |
++ |
37752 |
++ This information is sourced from task_struct->curr_ip provided by |
37753 |
++ grsecurity's GRKERNSEC top-level configuration option. One limitation |
37754 |
++ is that only IPv4 is supported. |
37755 |
++ |
37756 |
++ In many instances SELinux AVC log messages already log a superior level |
37757 |
++ of information that also includes source port and destination ip/port. |
37758 |
++ Additionally, SELinux's AVC log code supports IPv6. |
37759 |
++ |
37760 |
++ However, grsecurity's task_struct->curr_ip will sometimes (often?) |
37761 |
++ provide the offender's IP address where stock SELinux logging fails to. |
37762 |
++ |
37763 |
+ config GRKERNSEC_FLOODTIME |
37764 |
+ int "Seconds in between log messages (minimum)" |
37765 |
+ default 10 |
37766 |
+--- a/security/selinux/avc.c |
37767 |
++++ b/security/selinux/avc.c |
37768 |
+@@ -202,6 +202,11 @@ static void avc_dump_query(struct audit_ |
37769 |
+ char *scontext; |
37770 |
+ u32 scontext_len; |
37771 |
+ |
37772 |
++#ifdef CONFIG_GRKERNSEC_SELINUX_AVC_LOG_IPADDR |
37773 |
++ if (current->signal->curr_ip) |
37774 |
++ audit_log_format(ab, "ipaddr=%u.%u.%u.%u ", NIPQUAD(current->signal->curr_ip)); |
37775 |
++#endif |
37776 |
++ |
37777 |
+ rc = security_sid_to_context(ssid, &scontext, &scontext_len); |
37778 |
+ if (rc) |
37779 |
+ audit_log_format(ab, "ssid=%d", ssid); |
37780 |
|
37781 |
Added: hardened/2.6/tags/2.6.28-7/4445_disable-compat_vdso.patch |
37782 |
=================================================================== |
37783 |
--- hardened/2.6/tags/2.6.28-7/4445_disable-compat_vdso.patch (rev 0) |
37784 |
+++ hardened/2.6/tags/2.6.28-7/4445_disable-compat_vdso.patch 2009-03-21 10:58:14 UTC (rev 1529) |
37785 |
@@ -0,0 +1,74 @@ |
37786 |
+From: Gordon Malm <gengor@g.o> |
37787 |
+From: Kerin Millar <kerframil@×××××.com> |
37788 |
+ |
37789 |
+COMPAT_VDSO is inappropriate for any modern Hardened Gentoo system. It |
37790 |
+conflicts with various parts of PaX, crashing the system if enabled |
37791 |
+while PaX's NOEXEC or UDEREF features are active. Moreover, it prevents |
37792 |
+a number of important PaX options from appearing in the configuration |
37793 |
+menu, including all PaX NOEXEC implementations. Unfortunately, the |
37794 |
+reason for the disappearance of these PaX configuration options is |
37795 |
+often far from obvious to inexperienced users. |
37796 |
+ |
37797 |
+Therefore, we disable the COMPAT_VDSO menu entry entirely. However, |
37798 |
+COMPAT_VDSO operation can still be enabled via bootparam and sysctl |
37799 |
+interfaces. Consequently, we must also disable the ability to select |
37800 |
+COMPAT_VDSO operation at boot or runtime. Here we patch the kernel so |
37801 |
+that selecting COMPAT_VDSO operation at boot/runtime has no effect if |
37802 |
+conflicting PaX options are enabled, leaving VDSO_ENABLED operation |
37803 |
+intact. |
37804 |
+ |
37805 |
+Closes bug: http://bugs.gentoo.org/show_bug.cgi?id=210138 |
37806 |
+ |
37807 |
+--- a/arch/x86/Kconfig |
37808 |
++++ b/arch/x86/Kconfig |
37809 |
+@@ -1215,16 +1215,7 @@ config HOTPLUG_CPU |
37810 |
+ |
37811 |
+ config COMPAT_VDSO |
37812 |
+ def_bool n |
37813 |
+- prompt "Compat VDSO support" |
37814 |
+ depends on (X86_32 || IA32_EMULATION) && !PAX_NOEXEC |
37815 |
+- help |
37816 |
+- Map the 32-bit VDSO to the predictable old-style address too. |
37817 |
+- ---help--- |
37818 |
+- Say N here if you are running a sufficiently recent glibc |
37819 |
+- version (2.3.3 or later), to remove the high-mapped |
37820 |
+- VDSO mapping and to exclusively use the randomized VDSO. |
37821 |
+- |
37822 |
+- If unsure, say Y. |
37823 |
+ |
37824 |
+ endmenu |
37825 |
+ |
37826 |
+--- a/arch/x86/vdso/vdso32-setup.c |
37827 |
++++ b/arch/x86/vdso/vdso32-setup.c |
37828 |
+@@ -333,17 +333,21 @@ int arch_setup_additional_pages(struct l |
37829 |
+ |
37830 |
+ map_compat_vdso(compat); |
37831 |
+ |
37832 |
++#if !defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_MEMORY_UDEREF) |
37833 |
+ if (compat) |
37834 |
+ addr = VDSO_HIGH_BASE; |
37835 |
+ else { |
37836 |
++#endif |
37837 |
+ addr = get_unmapped_area(NULL, 0, PAGE_SIZE, 0, MAP_EXECUTABLE); |
37838 |
+ if (IS_ERR_VALUE(addr)) { |
37839 |
+ ret = addr; |
37840 |
+ goto up_fail; |
37841 |
+ } |
37842 |
++#if !defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_MEMORY_UDEREF) |
37843 |
+ } |
37844 |
+ |
37845 |
+ if (compat_uses_vma || !compat) { |
37846 |
++#endif |
37847 |
+ /* |
37848 |
+ * MAYWRITE to allow gdb to COW and set breakpoints |
37849 |
+ * |
37850 |
+@@ -361,7 +365,9 @@ int arch_setup_additional_pages(struct l |
37851 |
+ |
37852 |
+ if (ret) |
37853 |
+ goto up_fail; |
37854 |
++#if !defined(CONFIG_PAX_NOEXEC) && !defined(CONFIG_PAX_MEMORY_UDEREF) |
37855 |
+ } |
37856 |
++#endif |
37857 |
+ |
37858 |
+ current->mm->context.vdso = addr; |
37859 |
+ current_thread_info()->sysenter_return = |
37860 |
|
37861 |
Added: hardened/2.6/tags/2.6.28-7/4450_grsec-grkernsec_io-select-rtc-cmos.patch |
37862 |
=================================================================== |
37863 |
--- hardened/2.6/tags/2.6.28-7/4450_grsec-grkernsec_io-select-rtc-cmos.patch (rev 0) |
37864 |
+++ hardened/2.6/tags/2.6.28-7/4450_grsec-grkernsec_io-select-rtc-cmos.patch 2009-03-21 10:58:14 UTC (rev 1529) |
37865 |
@@ -0,0 +1,14 @@ |
37866 |
+From: Gordon Malm <gengor@g.o> |
37867 |
+ |
37868 |
+Build rtc-cmos driver into the kernel when GRKERNSEC_IO is enabled. |
37869 |
+ |
37870 |
+--- a/grsecurity/Kconfig |
37871 |
++++ b/grsecurity/Kconfig |
37872 |
+@@ -437,6 +437,7 @@ config GRKERNSEC_IO |
37873 |
+ depends on X86 |
37874 |
+ select RTC_CLASS |
37875 |
+ select RTC_INTF_DEV |
37876 |
++ select RTC_DRV_CMOS |
37877 |
+ help |
37878 |
+ If you say Y here, all ioperm and iopl calls will return an error. |
37879 |
+ Ioperm and iopl can be used to modify the running kernel. |