]> git.pld-linux.org Git - packages/kernel.git/blame - grsecurity-2.1.9-2.6.17.11.patch
- added LED devices support
[packages/kernel.git] / grsecurity-2.1.9-2.6.17.11.patch
CommitLineData
379b62f8 1diff -urNp linux-2.6.17.11/arch/alpha/kernel/module.c linux-2.6.17.11/arch/alpha/kernel/module.c
2--- linux-2.6.17.11/arch/alpha/kernel/module.c 2006-08-07 00:18:54.000000000 -0400
3+++ linux-2.6.17.11/arch/alpha/kernel/module.c 2006-08-12 08:17:55.000000000 -0400
4@@ -177,7 +177,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs,
5
6 /* The small sections were sorted to the end of the segment.
7 The following should definitely cover them. */
8- gp = (u64)me->module_core + me->core_size - 0x8000;
9+ gp = (u64)me->module_core_rw + me->core_size_rw - 0x8000;
10 got = sechdrs[me->arch.gotsecindex].sh_addr;
11
12 for (i = 0; i < n; i++) {
13diff -urNp linux-2.6.17.11/arch/alpha/kernel/osf_sys.c linux-2.6.17.11/arch/alpha/kernel/osf_sys.c
14--- linux-2.6.17.11/arch/alpha/kernel/osf_sys.c 2006-08-07 00:18:54.000000000 -0400
15+++ linux-2.6.17.11/arch/alpha/kernel/osf_sys.c 2006-08-12 08:17:55.000000000 -0400
16@@ -1273,6 +1273,10 @@ arch_get_unmapped_area(struct file *filp
17 merely specific addresses, but regions of memory -- perhaps
18 this feature should be incorporated into all ports? */
19
20+#ifdef CONFIG_PAX_RANDMMAP
21+ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
22+#endif
23+
24 if (addr) {
25 addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
26 if (addr != (unsigned long) -ENOMEM)
27@@ -1280,8 +1284,8 @@ arch_get_unmapped_area(struct file *filp
28 }
29
30 /* Next, try allocating at TASK_UNMAPPED_BASE. */
31- addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE),
32- len, limit);
33+ addr = arch_get_unmapped_area_1 (PAGE_ALIGN(current->mm->mmap_base), len, limit);
34+
35 if (addr != (unsigned long) -ENOMEM)
36 return addr;
37
38diff -urNp linux-2.6.17.11/arch/alpha/kernel/ptrace.c linux-2.6.17.11/arch/alpha/kernel/ptrace.c
39--- linux-2.6.17.11/arch/alpha/kernel/ptrace.c 2006-08-07 00:18:54.000000000 -0400
40+++ linux-2.6.17.11/arch/alpha/kernel/ptrace.c 2006-08-12 08:17:55.000000000 -0400
41@@ -15,6 +15,7 @@
42 #include <linux/security.h>
43 #include <linux/signal.h>
44 #include <linux/vs_pid.h>
45+#include <linux/grsecurity.h>
46
47 #include <asm/uaccess.h>
48 #include <asm/pgtable.h>
49@@ -283,6 +284,9 @@ do_sys_ptrace(long request, long pid, lo
50 goto out_notsk;
51 }
52
53+ if (gr_handle_ptrace(child, request))
54+ goto out;
55+
56 if (request == PTRACE_ATTACH) {
57 ret = ptrace_attach(child);
58 goto out;
59diff -urNp linux-2.6.17.11/arch/alpha/mm/fault.c linux-2.6.17.11/arch/alpha/mm/fault.c
60--- linux-2.6.17.11/arch/alpha/mm/fault.c 2006-08-07 00:18:54.000000000 -0400
61+++ linux-2.6.17.11/arch/alpha/mm/fault.c 2006-08-12 08:17:55.000000000 -0400
62@@ -25,6 +25,7 @@
63 #include <linux/smp_lock.h>
64 #include <linux/interrupt.h>
65 #include <linux/module.h>
66+#include <linux/binfmts.h>
67
68 #include <asm/system.h>
69 #include <asm/uaccess.h>
70@@ -56,6 +57,124 @@ __load_new_mm_context(struct mm_struct *
71 __reload_thread(pcb);
72 }
73
74+#ifdef CONFIG_PAX_PAGEEXEC
75+/*
76+ * PaX: decide what to do with offenders (regs->pc = fault address)
77+ *
78+ * returns 1 when task should be killed
79+ * 2 when patched PLT trampoline was detected
80+ * 3 when unpatched PLT trampoline was detected
81+ */
82+static int pax_handle_fetch_fault(struct pt_regs *regs)
83+{
84+
85+#ifdef CONFIG_PAX_EMUPLT
86+ int err;
87+
88+ do { /* PaX: patched PLT emulation #1 */
89+ unsigned int ldah, ldq, jmp;
90+
91+ err = get_user(ldah, (unsigned int *)regs->pc);
92+ err |= get_user(ldq, (unsigned int *)(regs->pc+4));
93+ err |= get_user(jmp, (unsigned int *)(regs->pc+8));
94+
95+ if (err)
96+ break;
97+
98+ if ((ldah & 0xFFFF0000U) == 0x277B0000U &&
99+ (ldq & 0xFFFF0000U) == 0xA77B0000U &&
100+ jmp == 0x6BFB0000U)
101+ {
102+ unsigned long r27, addr;
103+ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
104+ unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL;
105+
106+ addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
107+ err = get_user(r27, (unsigned long*)addr);
108+ if (err)
109+ break;
110+
111+ regs->r27 = r27;
112+ regs->pc = r27;
113+ return 2;
114+ }
115+ } while (0);
116+
117+ do { /* PaX: patched PLT emulation #2 */
118+ unsigned int ldah, lda, br;
119+
120+ err = get_user(ldah, (unsigned int *)regs->pc);
121+ err |= get_user(lda, (unsigned int *)(regs->pc+4));
122+ err |= get_user(br, (unsigned int *)(regs->pc+8));
123+
124+ if (err)
125+ break;
126+
127+ if ((ldah & 0xFFFF0000U)== 0x277B0000U &&
128+ (lda & 0xFFFF0000U) == 0xA77B0000U &&
129+ (br & 0xFFE00000U) == 0xC3E00000U)
130+ {
131+ unsigned long addr = br | 0xFFFFFFFFFFE00000UL;
132+ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
133+ unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL;
134+
135+ regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
136+ regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
137+ return 2;
138+ }
139+ } while (0);
140+
141+ do { /* PaX: unpatched PLT emulation */
142+ unsigned int br;
143+
144+ err = get_user(br, (unsigned int *)regs->pc);
145+
146+ if (!err && (br & 0xFFE00000U) == 0xC3800000U) {
147+ unsigned int br2, ldq, nop, jmp;
148+ unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver;
149+
150+ addr = regs->pc + 4 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
151+ err = get_user(br2, (unsigned int *)addr);
152+ err |= get_user(ldq, (unsigned int *)(addr+4));
153+ err |= get_user(nop, (unsigned int *)(addr+8));
154+ err |= get_user(jmp, (unsigned int *)(addr+12));
155+ err |= get_user(resolver, (unsigned long *)(addr+16));
156+
157+ if (err)
158+ break;
159+
160+ if (br2 == 0xC3600000U &&
161+ ldq == 0xA77B000CU &&
162+ nop == 0x47FF041FU &&
163+ jmp == 0x6B7B0000U)
164+ {
165+ regs->r28 = regs->pc+4;
166+ regs->r27 = addr+16;
167+ regs->pc = resolver;
168+ return 3;
169+ }
170+ }
171+ } while (0);
172+#endif
173+
174+ return 1;
175+}
176+
177+void pax_report_insns(void *pc, void *sp)
178+{
179+ unsigned long i;
180+
181+ printk(KERN_ERR "PAX: bytes at PC: ");
182+ for (i = 0; i < 5; i++) {
183+ unsigned int c;
184+ if (get_user(c, (unsigned int*)pc+i))
185+ printk("???????? ");
186+ else
187+ printk("%08x ", c);
188+ }
189+ printk("\n");
190+}
191+#endif
192
193 /*
194 * This routine handles page faults. It determines the address,
195@@ -133,8 +252,29 @@ do_page_fault(unsigned long address, uns
196 good_area:
197 si_code = SEGV_ACCERR;
198 if (cause < 0) {
199- if (!(vma->vm_flags & VM_EXEC))
200+ if (!(vma->vm_flags & VM_EXEC)) {
201+
202+#ifdef CONFIG_PAX_PAGEEXEC
203+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->pc)
204+ goto bad_area;
205+
206+ up_read(&mm->mmap_sem);
207+ switch(pax_handle_fetch_fault(regs)) {
208+
209+#ifdef CONFIG_PAX_EMUPLT
210+ case 2:
211+ case 3:
212+ return;
213+#endif
214+
215+ }
216+ pax_report_fault(regs, (void*)regs->pc, (void*)rdusp());
217+ do_exit(SIGKILL);
218+#else
219 goto bad_area;
220+#endif
221+
222+ }
223 } else if (!cause) {
224 /* Allow reads even for write-only mappings */
225 if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
226diff -urNp linux-2.6.17.11/arch/arm/mm/mmap.c linux-2.6.17.11/arch/arm/mm/mmap.c
227--- linux-2.6.17.11/arch/arm/mm/mmap.c 2006-08-07 00:18:54.000000000 -0400
228+++ linux-2.6.17.11/arch/arm/mm/mmap.c 2006-08-12 08:17:55.000000000 -0400
229@@ -62,6 +62,10 @@ arch_get_unmapped_area(struct file *filp
230 if (len > TASK_SIZE)
231 return -ENOMEM;
232
233+#ifdef CONFIG_PAX_RANDMMAP
234+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
235+#endif
236+
237 if (addr) {
238 if (do_align)
239 addr = COLOUR_ALIGN(addr, pgoff);
240@@ -76,7 +80,7 @@ arch_get_unmapped_area(struct file *filp
241 if (len > mm->cached_hole_size) {
242 start_addr = addr = mm->free_area_cache;
243 } else {
244- start_addr = addr = TASK_UNMAPPED_BASE;
245+ start_addr = addr = mm->mmap_base;
246 mm->cached_hole_size = 0;
247 }
248
249@@ -93,8 +97,8 @@ full_search:
250 * Start a new search - just in case we missed
251 * some holes.
252 */
253- if (start_addr != TASK_UNMAPPED_BASE) {
254- start_addr = addr = TASK_UNMAPPED_BASE;
255+ if (start_addr != mm->mmap_base) {
256+ start_addr = addr = mm->mmap_base;
257 mm->cached_hole_size = 0;
258 goto full_search;
259 }
260diff -urNp linux-2.6.17.11/arch/i386/boot/compressed/head.S linux-2.6.17.11/arch/i386/boot/compressed/head.S
261--- linux-2.6.17.11/arch/i386/boot/compressed/head.S 2006-08-07 00:18:54.000000000 -0400
262+++ linux-2.6.17.11/arch/i386/boot/compressed/head.S 2006-08-12 08:17:55.000000000 -0400
263@@ -39,11 +39,13 @@ startup_32:
264 movl %eax,%gs
265
266 lss stack_start,%esp
267+ movl 0x000000,%ecx
268 xorl %eax,%eax
269 1: incl %eax # check that A20 really IS enabled
270 movl %eax,0x000000 # loop forever if it isn't
271 cmpl %eax,0x100000
272 je 1b
273+ movl %ecx,0x000000
274
275 /*
276 * Initialize eflags. Some BIOS's leave bits like NT set. This would
277diff -urNp linux-2.6.17.11/arch/i386/Kconfig linux-2.6.17.11/arch/i386/Kconfig
278--- linux-2.6.17.11/arch/i386/Kconfig 2006-08-07 00:18:54.000000000 -0400
279+++ linux-2.6.17.11/arch/i386/Kconfig 2006-08-12 08:17:55.000000000 -0400
280@@ -948,7 +948,7 @@ config PCI
281 choice
282 prompt "PCI access mode"
283 depends on PCI && !X86_VISWS
284- default PCI_GOANY
285+ default PCI_GODIRECT
286 ---help---
287 On PCI systems, the BIOS can be used to detect the PCI devices and
288 determine their configuration. However, some old PCI motherboards
289@@ -980,7 +980,7 @@ endchoice
290
291 config PCI_BIOS
292 bool
293- depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
294+ depends on !X86_VISWS && PCI && PCI_GOBIOS
295 default y
296
297 config PCI_DIRECT
298diff -urNp linux-2.6.17.11/arch/i386/Kconfig.cpu linux-2.6.17.11/arch/i386/Kconfig.cpu
299--- linux-2.6.17.11/arch/i386/Kconfig.cpu 2006-08-07 00:18:54.000000000 -0400
300+++ linux-2.6.17.11/arch/i386/Kconfig.cpu 2006-08-12 08:17:55.000000000 -0400
301@@ -251,7 +251,7 @@ config X86_PPRO_FENCE
302
303 config X86_F00F_BUG
304 bool
305- depends on M586MMX || M586TSC || M586 || M486 || M386
306+ depends on (M586MMX || M586TSC || M586 || M486 || M386) && !PAX_KERNEXEC
307 default y
308
309 config X86_WP_WORKS_OK
310@@ -281,7 +281,7 @@ config X86_CMPXCHG64
311
312 config X86_ALIGNMENT_16
313 bool
314- depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
315+ depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
316 default y
317
318 config X86_GOOD_APIC
319diff -urNp linux-2.6.17.11/arch/i386/Kconfig.debug linux-2.6.17.11/arch/i386/Kconfig.debug
320--- linux-2.6.17.11/arch/i386/Kconfig.debug 2006-08-07 00:18:54.000000000 -0400
321+++ linux-2.6.17.11/arch/i386/Kconfig.debug 2006-08-12 08:17:55.000000000 -0400
322@@ -53,7 +53,7 @@ config DEBUG_PAGEALLOC
323
324 config DEBUG_RODATA
325 bool "Write protect kernel read-only data structures"
326- depends on DEBUG_KERNEL
327+ depends on DEBUG_KERNEL && 0
328 help
329 Mark the kernel read-only data as write-protected in the pagetables,
330 in order to catch accidental (and incorrect) writes to such const
331diff -urNp linux-2.6.17.11/arch/i386/kernel/acpi/sleep.c linux-2.6.17.11/arch/i386/kernel/acpi/sleep.c
332--- linux-2.6.17.11/arch/i386/kernel/acpi/sleep.c 2006-08-07 00:18:54.000000000 -0400
333+++ linux-2.6.17.11/arch/i386/kernel/acpi/sleep.c 2006-08-12 08:17:55.000000000 -0400
334@@ -10,6 +10,7 @@
335 #include <linux/dmi.h>
336 #include <asm/smp.h>
337 #include <asm/tlbflush.h>
338+#include <asm/desc.h>
339
340 /* address in low memory of the wakeup routine. */
341 unsigned long acpi_wakeup_address = 0;
342@@ -24,11 +25,22 @@ static void init_low_mapping(pgd_t * pgd
343 {
344 int pgd_ofs = 0;
345
346+#ifdef CONFIG_PAX_KERNEXEC
347+ unsigned long cr0;
348+
349+ pax_open_kernel(cr0);
350+#endif
351+
352 while ((pgd_ofs < pgd_limit)
353 && (pgd_ofs + USER_PTRS_PER_PGD < PTRS_PER_PGD)) {
354 set_pgd(pgd, *(pgd + USER_PTRS_PER_PGD));
355 pgd_ofs++, pgd++;
356 }
357+
358+#ifdef CONFIG_PAX_KERNEXEC
359+ pax_close_kernel(cr0);
360+#endif
361+
362 flush_tlb_all();
363 }
364
365@@ -55,7 +67,18 @@ int acpi_save_state_mem(void)
366 */
367 void acpi_restore_state_mem(void)
368 {
369+#ifdef CONFIG_PAX_KERNEXEC
370+ unsigned long cr0;
371+
372+ pax_open_kernel(cr0);
373+#endif
374+
375 zap_low_mappings();
376+
377+#ifdef CONFIG_PAX_KERNEXEC
378+ pax_close_kernel(cr0);
379+#endif
380+
381 }
382
383 /**
384diff -urNp linux-2.6.17.11/arch/i386/kernel/alternative.c linux-2.6.17.11/arch/i386/kernel/alternative.c
385--- linux-2.6.17.11/arch/i386/kernel/alternative.c 2006-08-07 00:18:54.000000000 -0400
386+++ linux-2.6.17.11/arch/i386/kernel/alternative.c 2006-08-12 08:17:55.000000000 -0400
387@@ -3,6 +3,7 @@
388 #include <linux/list.h>
389 #include <asm/alternative.h>
390 #include <asm/sections.h>
391+#include <asm/desc.h>
392
393 #define DEBUG 0
394 #if DEBUG
395@@ -101,71 +102,128 @@ void apply_alternatives(struct alt_instr
396 struct alt_instr *a;
397 int diff, i, k;
398
399+#ifdef CONFIG_PAX_KERNEXEC
400+ unsigned long cr0;
401+
402+ pax_open_kernel(cr0);
403+#endif
404+
405 DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
406 for (a = start; a < end; a++) {
407 BUG_ON(a->replacementlen > a->instrlen);
408 if (!boot_cpu_has(a->cpuid))
409 continue;
410- memcpy(a->instr, a->replacement, a->replacementlen);
411+ memcpy(a->instr + __KERNEL_TEXT_OFFSET, a->replacement, a->replacementlen);
412 diff = a->instrlen - a->replacementlen;
413 /* Pad the rest with nops */
414 for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
415 k = diff;
416 if (k > ASM_NOP_MAX)
417 k = ASM_NOP_MAX;
418- memcpy(a->instr + i, noptable[k], k);
419+ memcpy(a->instr + i + __KERNEL_TEXT_OFFSET, noptable[k], k);
420 }
421 }
422+
423+#ifdef CONFIG_PAX_KERNEXEC
424+ pax_close_kernel(cr0);
425+#endif
426+
427 }
428
429 static void alternatives_smp_save(struct alt_instr *start, struct alt_instr *end)
430 {
431 struct alt_instr *a;
432
433+#ifdef CONFIG_PAX_KERNEXEC
434+ unsigned long cr0;
435+
436+ pax_open_kernel(cr0);
437+#endif
438+
439 DPRINTK("%s: alt table %p-%p\n", __FUNCTION__, start, end);
440 for (a = start; a < end; a++) {
441 memcpy(a->replacement + a->replacementlen,
442- a->instr,
443+ a->instr + __KERNEL_TEXT_OFFSET,
444 a->instrlen);
445 }
446+
447+#ifdef CONFIG_PAX_KERNEXEC
448+ pax_close_kernel(cr0);
449+#endif
450+
451 }
452
453 static void alternatives_smp_apply(struct alt_instr *start, struct alt_instr *end)
454 {
455 struct alt_instr *a;
456
457+#ifdef CONFIG_PAX_KERNEXEC
458+ unsigned long cr0;
459+
460+ pax_open_kernel(cr0);
461+#endif
462+
463 for (a = start; a < end; a++) {
464- memcpy(a->instr,
465+ memcpy(a->instr + __KERNEL_TEXT_OFFSET,
466 a->replacement + a->replacementlen,
467 a->instrlen);
468 }
469+
470+#ifdef CONFIG_PAX_KERNEXEC
471+ pax_close_kernel(cr0);
472+#endif
473+
474 }
475
476 static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
477 {
478- u8 **ptr;
479+ u8 *ptr;
480+
481+#ifdef CONFIG_PAX_KERNEXEC
482+ unsigned long cr0;
483
484- for (ptr = start; ptr < end; ptr++) {
485- if (*ptr < text)
486+ pax_open_kernel(cr0);
487+#endif
488+
489+ for (; start < end; start++) {
490+ ptr = *start + __KERNEL_TEXT_OFFSET;
491+ if (ptr < text)
492 continue;
493- if (*ptr > text_end)
494+ if (ptr > text_end)
495 continue;
496- **ptr = 0xf0; /* lock prefix */
497+ *ptr = 0xf0; /* lock prefix */
498 };
499+
500+#ifdef CONFIG_PAX_KERNEXEC
501+ pax_close_kernel(cr0);
502+#endif
503+
504 }
505
506 static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end)
507 {
508 unsigned char **noptable = find_nop_table();
509- u8 **ptr;
510+ u8 *ptr;
511+
512+#ifdef CONFIG_PAX_KERNEXEC
513+ unsigned long cr0;
514+
515+ pax_open_kernel(cr0);
516+#endif
517
518- for (ptr = start; ptr < end; ptr++) {
519- if (*ptr < text)
520+ for (; start < end; start++) {
521+ ptr = *start + __KERNEL_TEXT_OFFSET;
522+ if (ptr < text)
523 continue;
524- if (*ptr > text_end)
525+ if (ptr > text_end)
526 continue;
527- **ptr = noptable[1][0];
528+ *ptr = noptable[1][0];
529 };
530+
531+#ifdef CONFIG_PAX_KERNEXEC
532+ pax_close_kernel(cr0);
533+#endif
534+
535 }
536
537 struct smp_alt_module {
538diff -urNp linux-2.6.17.11/arch/i386/kernel/apic.c linux-2.6.17.11/arch/i386/kernel/apic.c
539--- linux-2.6.17.11/arch/i386/kernel/apic.c 2006-08-07 00:18:54.000000000 -0400
540+++ linux-2.6.17.11/arch/i386/kernel/apic.c 2006-08-12 08:17:55.000000000 -0400
541@@ -1176,7 +1176,7 @@ inline void smp_local_timer_interrupt(st
542 {
543 profile_tick(CPU_PROFILING, regs);
544 #ifdef CONFIG_SMP
545- update_process_times(user_mode_vm(regs));
546+ update_process_times(user_mode(regs));
547 #endif
548
549 /*
550diff -urNp linux-2.6.17.11/arch/i386/kernel/apm.c linux-2.6.17.11/arch/i386/kernel/apm.c
551--- linux-2.6.17.11/arch/i386/kernel/apm.c 2006-08-07 00:18:54.000000000 -0400
552+++ linux-2.6.17.11/arch/i386/kernel/apm.c 2006-08-12 08:17:55.000000000 -0400
553@@ -235,7 +235,7 @@
554 #include "io_ports.h"
555
556 extern unsigned long get_cmos_time(void);
557-extern void machine_real_restart(unsigned char *, int);
558+extern void machine_real_restart(const unsigned char *, unsigned int);
559
560 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
561 extern int (*console_blank_hook)(int);
562@@ -589,9 +589,18 @@ static u8 apm_bios_call(u32 func, u32 eb
563 struct desc_struct save_desc_40;
564 struct desc_struct *gdt;
565
566+#ifdef CONFIG_PAX_KERNEXEC
567+ unsigned long cr0;
568+#endif
569+
570 cpus = apm_save_cpus();
571
572 cpu = get_cpu();
573+
574+#ifdef CONFIG_PAX_KERNEXEC
575+ pax_open_kernel(cr0);
576+#endif
577+
578 gdt = get_cpu_gdt_table(cpu);
579 save_desc_40 = gdt[0x40 / 8];
580 gdt[0x40 / 8] = bad_bios_desc;
581@@ -603,6 +612,11 @@ static u8 apm_bios_call(u32 func, u32 eb
582 APM_DO_RESTORE_SEGS;
583 local_irq_restore(flags);
584 gdt[0x40 / 8] = save_desc_40;
585+
586+#ifdef CONFIG_PAX_KERNEXEC
587+ pax_close_kernel(cr0);
588+#endif
589+
590 put_cpu();
591 apm_restore_cpus(cpus);
592
593@@ -633,9 +647,18 @@ static u8 apm_bios_call_simple(u32 func,
594 struct desc_struct save_desc_40;
595 struct desc_struct *gdt;
596
597+#ifdef CONFIG_PAX_KERNEXEC
598+ unsigned long cr0;
599+#endif
600+
601 cpus = apm_save_cpus();
602
603 cpu = get_cpu();
604+
605+#ifdef CONFIG_PAX_KERNEXEC
606+ pax_open_kernel(cr0);
607+#endif
608+
609 gdt = get_cpu_gdt_table(cpu);
610 save_desc_40 = gdt[0x40 / 8];
611 gdt[0x40 / 8] = bad_bios_desc;
612@@ -647,6 +670,11 @@ static u8 apm_bios_call_simple(u32 func,
613 APM_DO_RESTORE_SEGS;
614 local_irq_restore(flags);
615 gdt[0x40 / 8] = save_desc_40;
616+
617+#ifdef CONFIG_PAX_KERNEXEC
618+ pax_close_kernel(cr0);
619+#endif
620+
621 put_cpu();
622 apm_restore_cpus(cpus);
623 return error;
624@@ -910,7 +938,7 @@ recalc:
625
626 static void apm_power_off(void)
627 {
628- unsigned char po_bios_call[] = {
629+ const unsigned char po_bios_call[] = {
630 0xb8, 0x00, 0x10, /* movw $0x1000,ax */
631 0x8e, 0xd0, /* movw ax,ss */
632 0xbc, 0x00, 0xf0, /* movw $0xf000,sp */
633diff -urNp linux-2.6.17.11/arch/i386/kernel/asm-offsets.c linux-2.6.17.11/arch/i386/kernel/asm-offsets.c
634--- linux-2.6.17.11/arch/i386/kernel/asm-offsets.c 2006-08-07 00:18:54.000000000 -0400
635+++ linux-2.6.17.11/arch/i386/kernel/asm-offsets.c 2006-08-12 08:17:55.000000000 -0400
636@@ -68,5 +68,6 @@ void foo(void)
637 sizeof(struct tss_struct));
638
639 DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
640+ DEFINE(PTRS_PER_PTE_asm, PTRS_PER_PTE);
641 DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL));
642 }
643diff -urNp linux-2.6.17.11/arch/i386/kernel/cpu/common.c linux-2.6.17.11/arch/i386/kernel/cpu/common.c
644--- linux-2.6.17.11/arch/i386/kernel/cpu/common.c 2006-08-07 00:18:54.000000000 -0400
645+++ linux-2.6.17.11/arch/i386/kernel/cpu/common.c 2006-08-12 08:17:55.000000000 -0400
646@@ -4,7 +4,6 @@
647 #include <linux/smp.h>
648 #include <linux/module.h>
649 #include <linux/percpu.h>
650-#include <linux/bootmem.h>
651 #include <asm/semaphore.h>
652 #include <asm/processor.h>
653 #include <asm/i387.h>
654@@ -19,16 +18,18 @@
655
656 #include "cpu.h"
657
658-DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
659-EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
660-
661 DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
662 EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
663
664 static int cachesize_override __cpuinitdata = -1;
665 static int disable_x86_fxsr __cpuinitdata;
666 static int disable_x86_serial_nr __cpuinitdata = 1;
667+
668+#ifdef CONFIG_PAX_NOVSYSCALL
669+static int disable_x86_sep __cpuinitdata = 1;
670+#else
671 static int disable_x86_sep __cpuinitdata;
672+#endif
673
674 struct cpu_dev * cpu_devs[X86_VENDOR_NUM] = {};
675
676@@ -590,11 +591,10 @@ void __init early_cpu_init(void)
677 void __cpuinit cpu_init(void)
678 {
679 int cpu = smp_processor_id();
680- struct tss_struct * t = &per_cpu(init_tss, cpu);
681+ struct tss_struct * t = init_tss + cpu;
682 struct thread_struct *thread = &current->thread;
683- struct desc_struct *gdt;
684+ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
685 __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
686- struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
687
688 if (cpu_test_and_set(cpu, cpu_initialized)) {
689 printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
690@@ -612,29 +612,11 @@ void __cpuinit cpu_init(void)
691 }
692
693 /*
694- * This is a horrible hack to allocate the GDT. The problem
695- * is that cpu_init() is called really early for the boot CPU
696- * (and hence needs bootmem) but much later for the secondary
697- * CPUs, when bootmem will have gone away
698- */
699- if (NODE_DATA(0)->bdata->node_bootmem_map) {
700- gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
701- /* alloc_bootmem_pages panics on failure, so no check */
702- memset(gdt, 0, PAGE_SIZE);
703- } else {
704- gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
705- if (unlikely(!gdt)) {
706- printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
707- for (;;)
708- local_irq_enable();
709- }
710- }
711-
712- /*
713 * Initialize the per-CPU GDT with the boot GDT,
714 * and set up the GDT descriptor:
715 */
716- memcpy(gdt, cpu_gdt_table, GDT_SIZE);
717+ if (cpu)
718+ memcpy(gdt, cpu_gdt_table, GDT_SIZE);
719
720 /* Set up GDT entry for 16bit stack */
721 *(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |=
722@@ -642,10 +624,10 @@ void __cpuinit cpu_init(void)
723 ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
724 (CPU_16BIT_STACK_SIZE - 1);
725
726- cpu_gdt_descr->size = GDT_SIZE - 1;
727- cpu_gdt_descr->address = (unsigned long)gdt;
728+ cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
729+ cpu_gdt_descr[cpu].address = (unsigned long)gdt;
730
731- load_gdt(cpu_gdt_descr);
732+ load_gdt(&cpu_gdt_descr[cpu]);
733 load_idt(&idt_descr);
734
735 /*
736@@ -660,7 +642,7 @@ void __cpuinit cpu_init(void)
737 load_esp0(t, thread);
738 set_tss_desc(cpu,t);
739 load_TR_desc();
740- load_LDT(&init_mm.context);
741+ _load_LDT(&init_mm.context);
742
743 #ifdef CONFIG_DOUBLEFAULT
744 /* Set up doublefault TSS pointer in the GDT */
745@@ -668,7 +650,7 @@ void __cpuinit cpu_init(void)
746 #endif
747
748 /* Clear %fs and %gs. */
749- asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
750+ asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r"(0));
751
752 /* Clear all 6 debug registers: */
753 set_debugreg(0, 0);
754diff -urNp linux-2.6.17.11/arch/i386/kernel/crash.c linux-2.6.17.11/arch/i386/kernel/crash.c
755--- linux-2.6.17.11/arch/i386/kernel/crash.c 2006-08-07 00:18:54.000000000 -0400
756+++ linux-2.6.17.11/arch/i386/kernel/crash.c 2006-08-12 08:17:55.000000000 -0400
757@@ -105,7 +105,7 @@ static int crash_nmi_callback(struct pt_
758 return 1;
759 local_irq_disable();
760
761- if (!user_mode_vm(regs)) {
762+ if (!user_mode(regs)) {
763 crash_fixup_ss_esp(&fixed_regs, regs);
764 regs = &fixed_regs;
765 }
766diff -urNp linux-2.6.17.11/arch/i386/kernel/doublefault.c linux-2.6.17.11/arch/i386/kernel/doublefault.c
767--- linux-2.6.17.11/arch/i386/kernel/doublefault.c 2006-08-07 00:18:54.000000000 -0400
768+++ linux-2.6.17.11/arch/i386/kernel/doublefault.c 2006-08-12 08:17:55.000000000 -0400
769@@ -11,7 +11,7 @@
770
771 #define DOUBLEFAULT_STACKSIZE (1024)
772 static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE];
773-#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE)
774+#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE-2)
775
776 #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000)
777
778@@ -56,10 +56,10 @@ struct tss_struct doublefault_tss __cach
779 .eip = (unsigned long) doublefault_fn,
780 .eflags = X86_EFLAGS_SF | 0x2, /* 0x2 bit is always set */
781 .esp = STACK_START,
782- .es = __USER_DS,
783+ .es = __KERNEL_DS,
784 .cs = __KERNEL_CS,
785 .ss = __KERNEL_DS,
786- .ds = __USER_DS,
787+ .ds = __KERNEL_DS,
788
789 .__cr3 = __pa(swapper_pg_dir)
790 };
791diff -urNp linux-2.6.17.11/arch/i386/kernel/efi.c linux-2.6.17.11/arch/i386/kernel/efi.c
792--- linux-2.6.17.11/arch/i386/kernel/efi.c 2006-08-07 00:18:54.000000000 -0400
793+++ linux-2.6.17.11/arch/i386/kernel/efi.c 2006-08-12 08:17:55.000000000 -0400
794@@ -64,82 +64,43 @@ extern void * boot_ioremap(unsigned long
795
796 static unsigned long efi_rt_eflags;
797 static DEFINE_SPINLOCK(efi_rt_lock);
798-static pgd_t efi_bak_pg_dir_pointer[2];
799+static pgd_t __initdata efi_bak_pg_dir_pointer[KERNEL_PGD_PTRS] __attribute__ ((aligned (4096)));
800
801-static void efi_call_phys_prelog(void)
802+static void __init efi_call_phys_prelog(void)
803 {
804- unsigned long cr4;
805- unsigned long temp;
806- struct Xgt_desc_struct *cpu_gdt_descr;
807-
808 spin_lock(&efi_rt_lock);
809 local_irq_save(efi_rt_eflags);
810
811- cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
812-
813- /*
814- * If I don't have PSE, I should just duplicate two entries in page
815- * directory. If I have PSE, I just need to duplicate one entry in
816- * page directory.
817- */
818- cr4 = read_cr4();
819-
820- if (cr4 & X86_CR4_PSE) {
821- efi_bak_pg_dir_pointer[0].pgd =
822- swapper_pg_dir[pgd_index(0)].pgd;
823- swapper_pg_dir[0].pgd =
824- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
825- } else {
826- efi_bak_pg_dir_pointer[0].pgd =
827- swapper_pg_dir[pgd_index(0)].pgd;
828- efi_bak_pg_dir_pointer[1].pgd =
829- swapper_pg_dir[pgd_index(0x400000)].pgd;
830- swapper_pg_dir[pgd_index(0)].pgd =
831- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
832- temp = PAGE_OFFSET + 0x400000;
833- swapper_pg_dir[pgd_index(0x400000)].pgd =
834- swapper_pg_dir[pgd_index(temp)].pgd;
835- }
836+ clone_pgd_range(efi_bak_pg_dir_pointer, swapper_pg_dir, KERNEL_PGD_PTRS);
837+ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
838+ USER_PGD_PTRS >= KERNEL_PGD_PTRS ? KERNEL_PGD_PTRS : USER_PGD_PTRS);
839
840 /*
841 * After the lock is released, the original page table is restored.
842 */
843- local_flush_tlb();
844+ __flush_tlb_all();
845
846- cpu_gdt_descr->address = __pa(cpu_gdt_descr->address);
847- load_gdt(cpu_gdt_descr);
848+ cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
849+ load_gdt((struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0]));
850 }
851
852-static void efi_call_phys_epilog(void)
853+static void __init efi_call_phys_epilog(void)
854 {
855- unsigned long cr4;
856- struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
857-
858- cpu_gdt_descr->address = (unsigned long)__va(cpu_gdt_descr->address);
859- load_gdt(cpu_gdt_descr);
860+ cpu_gdt_descr[0].address = (unsigned long) __va(cpu_gdt_descr[0].address);
861+ load_gdt(&cpu_gdt_descr[0]);
862
863- cr4 = read_cr4();
864-
865- if (cr4 & X86_CR4_PSE) {
866- swapper_pg_dir[pgd_index(0)].pgd =
867- efi_bak_pg_dir_pointer[0].pgd;
868- } else {
869- swapper_pg_dir[pgd_index(0)].pgd =
870- efi_bak_pg_dir_pointer[0].pgd;
871- swapper_pg_dir[pgd_index(0x400000)].pgd =
872- efi_bak_pg_dir_pointer[1].pgd;
873- }
874+ clone_pgd_range(swapper_pg_dir, efi_bak_pg_dir_pointer, KERNEL_PGD_PTRS);
875
876 /*
877 * After the lock is released, the original page table is restored.
878 */
879- local_flush_tlb();
880+ __flush_tlb_all();
881
882 local_irq_restore(efi_rt_eflags);
883 spin_unlock(&efi_rt_lock);
884 }
885
886-static efi_status_t
887+static efi_status_t __init
888 phys_efi_set_virtual_address_map(unsigned long memory_map_size,
889 unsigned long descriptor_size,
890 u32 descriptor_version,
891@@ -155,7 +116,7 @@ phys_efi_set_virtual_address_map(unsigne
892 return status;
893 }
894
895-static efi_status_t
896+static efi_status_t __init
897 phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
898 {
899 efi_status_t status;
900diff -urNp linux-2.6.17.11/arch/i386/kernel/efi_stub.S linux-2.6.17.11/arch/i386/kernel/efi_stub.S
901--- linux-2.6.17.11/arch/i386/kernel/efi_stub.S 2006-08-07 00:18:54.000000000 -0400
902+++ linux-2.6.17.11/arch/i386/kernel/efi_stub.S 2006-08-12 08:17:55.000000000 -0400
903@@ -7,6 +7,7 @@
904
905 #include <linux/config.h>
906 #include <linux/linkage.h>
907+#include <linux/init.h>
908 #include <asm/page.h>
909 #include <asm/pgtable.h>
910
911@@ -22,7 +23,7 @@
912 * service functions will comply with gcc calling convention, too.
913 */
914
915-.text
916+__INIT
917 ENTRY(efi_call_phys)
918 /*
919 * 0. The function can only be called in Linux kernel. So CS has been
920@@ -38,9 +39,7 @@ ENTRY(efi_call_phys)
921 * The mapping of lower virtual memory has been created in prelog and
922 * epilog.
923 */
924- movl $1f, %edx
925- subl $__PAGE_OFFSET, %edx
926- jmp *%edx
927+ jmp 1f-__PAGE_OFFSET
928 1:
929
930 /*
931@@ -49,14 +48,8 @@ ENTRY(efi_call_phys)
932 * parameter 2, ..., param n. To make things easy, we save the return
933 * address of efi_call_phys in a global variable.
934 */
935- popl %edx
936- movl %edx, saved_return_addr
937- /* get the function pointer into ECX*/
938- popl %ecx
939- movl %ecx, efi_rt_function_ptr
940- movl $2f, %edx
941- subl $__PAGE_OFFSET, %edx
942- pushl %edx
943+ popl (saved_return_addr)
944+ popl (efi_rt_function_ptr)
945
946 /*
947 * 3. Clear PG bit in %CR0.
948@@ -75,9 +68,8 @@ ENTRY(efi_call_phys)
949 /*
950 * 5. Call the physical function.
951 */
952- jmp *%ecx
953+ call *(efi_rt_function_ptr-__PAGE_OFFSET)
954
955-2:
956 /*
957 * 6. After EFI runtime service returns, control will return to
958 * following instruction. We'd better readjust stack pointer first.
959@@ -87,37 +79,29 @@ ENTRY(efi_call_phys)
960 /*
961 * 7. Restore PG bit
962 */
963- movl %cr0, %edx
964- orl $0x80000000, %edx
965- movl %edx, %cr0
966- jmp 1f
967-1:
968 /*
969 * 8. Now restore the virtual mode from flat mode by
970 * adding EIP with PAGE_OFFSET.
971 */
972- movl $1f, %edx
973- jmp *%edx
974+ movl %cr0, %edx
975+ orl $0x80000000, %edx
976+ movl %edx, %cr0
977+ jmp 1f+__PAGE_OFFSET
978 1:
979
980 /*
981 * 9. Balance the stack. And because EAX contain the return value,
982 * we'd better not clobber it.
983 */
984- leal efi_rt_function_ptr, %edx
985- movl (%edx), %ecx
986- pushl %ecx
987+ pushl (efi_rt_function_ptr)
988
989 /*
990- * 10. Push the saved return address onto the stack and return.
991+ * 10. Return to the saved return address.
992 */
993- leal saved_return_addr, %edx
994- movl (%edx), %ecx
995- pushl %ecx
996- ret
997+ jmpl *(saved_return_addr)
998 .previous
999
1000-.data
1001+__INITDATA
1002 saved_return_addr:
1003 .long 0
1004 efi_rt_function_ptr:
1005diff -urNp linux-2.6.17.11/arch/i386/kernel/entry.S linux-2.6.17.11/arch/i386/kernel/entry.S
1006--- linux-2.6.17.11/arch/i386/kernel/entry.S 2006-08-07 00:18:54.000000000 -0400
1007+++ linux-2.6.17.11/arch/i386/kernel/entry.S 2006-08-12 08:17:55.000000000 -0400
1008@@ -82,7 +82,7 @@ VM_MASK = 0x00020000
1009 #define resume_kernel restore_nocheck
1010 #endif
1011
1012-#define SAVE_ALL \
1013+#define __SAVE_ALL(_DS) \
1014 cld; \
1015 pushl %es; \
1016 pushl %ds; \
1017@@ -93,10 +93,24 @@ VM_MASK = 0x00020000
1018 pushl %edx; \
1019 pushl %ecx; \
1020 pushl %ebx; \
1021- movl $(__USER_DS), %edx; \
1022+ movl $(_DS), %edx; \
1023 movl %edx, %ds; \
1024 movl %edx, %es;
1025
1026+#ifdef CONFIG_PAX_KERNEXEC
1027+#define SAVE_ALL \
1028+ __SAVE_ALL(__KERNEL_DS) \
1029+ movl %cr0, %edx; \
1030+ movl %edx, %esi; \
1031+ orl $0x10000, %edx; \
1032+ xorl %edx, %esi; \
1033+ movl %edx, %cr0;
1034+#elif defined(CONFIG_PAX_NOVSYSCALL)
1035+#define SAVE_ALL __SAVE_ALL(__KERNEL_DS)
1036+#else
1037+#define SAVE_ALL __SAVE_ALL(__USER_DS)
1038+#endif
1039+
1040 #define RESTORE_INT_REGS \
1041 popl %ebx; \
1042 popl %ecx; \
1043@@ -146,7 +160,19 @@ ret_from_intr:
1044 movl EFLAGS(%esp), %eax # mix EFLAGS and CS
1045 movb CS(%esp), %al
1046 testl $(VM_MASK | 3), %eax
1047+
1048+#ifdef CONFIG_PAX_KERNEXEC
1049+ jnz resume_userspace
1050+
1051+ movl %cr0, %edx
1052+ xorl %esi, %edx
1053+ movl %edx, %cr0
1054+ jmp resume_kernel
1055+#else
1056 jz resume_kernel
1057+#endif
1058+
1059+
1060 ENTRY(resume_userspace)
1061 cli # make sure we don't miss an interrupt
1062 # setting need_resched or sigpending
1063@@ -190,9 +216,17 @@ sysenter_past_esp:
1064 * Load the potential sixth argument from user stack.
1065 * Careful about security.
1066 */
1067+
1068+#ifdef CONFIG_PAX_MEMORY_UDEREF
1069+ pushl $(__USER_DS)
1070+ pop %ds
1071+1: movl %ds:(%ebp),%ebp
1072+#else
1073 cmpl $__PAGE_OFFSET-3,%ebp
1074 jae syscall_fault
1075 1: movl (%ebp),%ebp
1076+#endif
1077+
1078 .section __ex_table,"a"
1079 .align 4
1080 .long 1b,syscall_fault
1081@@ -213,13 +247,33 @@ sysenter_past_esp:
1082 movl TI_flags(%ebp), %ecx
1083 testw $_TIF_ALLWORK_MASK, %cx
1084 jne syscall_exit_work
1085+
1086+#ifdef CONFIG_PAX_RANDKSTACK
1087+ pushl %eax
1088+ call pax_randomize_kstack
1089+ popl %eax
1090+#endif
1091+
1092 /* if something modifies registers it must also disable sysexit */
1093 movl EIP(%esp), %edx
1094 movl OLDESP(%esp), %ecx
1095+1: mov DS(%esp), %ds
1096+2: mov ES(%esp), %es
1097 xorl %ebp,%ebp
1098 sti
1099 sysexit
1100
1101+.section .fixup,"ax"
1102+3: movl $0,DS(%esp)
1103+ jmp 1b
1104+4: movl $0,ES(%esp)
1105+ jmp 2b
1106+.previous
1107+.section __ex_table,"a"
1108+ .align 4
1109+ .long 1b,3b
1110+ .long 2b,4b
1111+.previous
1112
1113 # system call handler stub
1114 ENTRY(system_call)
1115@@ -247,6 +301,10 @@ syscall_exit:
1116 testw $_TIF_ALLWORK_MASK, %cx # current->work
1117 jne syscall_exit_work
1118
1119+#ifdef CONFIG_PAX_RANDKSTACK
1120+ call pax_randomize_kstack
1121+#endif
1122+
1123 restore_all:
1124 movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
1125 # Warning: OLDSS(%esp) contains the wrong/random values if we
1126@@ -402,7 +460,7 @@ syscall_badsys:
1127 * Build the entry stubs and pointer table with
1128 * some assembler magic.
1129 */
1130-.data
1131+.section .rodata,"a",@progbits
1132 ENTRY(interrupt)
1133 .text
1134
1135@@ -412,7 +470,7 @@ ENTRY(irq_entries_start)
1136 ALIGN
1137 1: pushl $vector-256
1138 jmp common_interrupt
1139-.data
1140+.section .rodata,"a",@progbits
1141 .long 1b
1142 .text
1143 vector=vector+1
1144@@ -459,10 +517,19 @@ error_code:
1145 movl ORIG_EAX(%esp), %edx # get the error code
1146 movl %eax, ORIG_EAX(%esp)
1147 movl %ecx, ES(%esp)
1148- movl $(__USER_DS), %ecx
1149+ movl $(__KERNEL_DS), %ecx
1150 movl %ecx, %ds
1151 movl %ecx, %es
1152 movl %esp,%eax # pt_regs pointer
1153+
1154+#ifdef CONFIG_PAX_KERNEXEC
1155+ movl %cr0, %ecx
1156+ movl %ecx, %esi
1157+ orl $0x10000, %ecx
1158+ xorl %ecx, %esi
1159+ movl %ecx, %cr0
1160+#endif
1161+
1162 call *%edi
1163 jmp ret_from_exception
1164
1165@@ -558,6 +625,13 @@ nmi_stack_correct:
1166 xorl %edx,%edx # zero error code
1167 movl %esp,%eax # pt_regs pointer
1168 call do_nmi
1169+
1170+#ifdef CONFIG_PAX_KERNEXEC
1171+ movl %cr0, %edx
1172+ xorl %esi, %edx
1173+ movl %edx, %cr0
1174+#endif
1175+
1176 jmp restore_all
1177
1178 nmi_stack_fixup:
1179@@ -588,6 +662,13 @@ nmi_16bit_stack:
1180 FIXUP_ESPFIX_STACK # %eax == %esp
1181 xorl %edx,%edx # zero error code
1182 call do_nmi
1183+
1184+#ifdef CONFIG_PAX_KERNEXEC
1185+ movl %cr0, %edx
1186+ xorl %esi, %edx
1187+ movl %edx, %cr0
1188+#endif
1189+
1190 RESTORE_REGS
1191 lss 12+4(%esp), %esp # back to 16bit stack
1192 1: iret
1193@@ -663,7 +744,6 @@ ENTRY(spurious_interrupt_bug)
1194 pushl $do_spurious_interrupt_bug
1195 jmp error_code
1196
1197-.section .rodata,"a"
1198 #include "syscall_table.S"
1199
1200 syscall_table_size=(.-sys_call_table)
1201diff -urNp linux-2.6.17.11/arch/i386/kernel/head.S linux-2.6.17.11/arch/i386/kernel/head.S
1202--- linux-2.6.17.11/arch/i386/kernel/head.S 2006-08-07 00:18:54.000000000 -0400
1203+++ linux-2.6.17.11/arch/i386/kernel/head.S 2006-08-12 08:17:55.000000000 -0400
1204@@ -46,6 +46,16 @@
1205 */
1206 #define INIT_MAP_BEYOND_END (128*1024)
1207
1208+#ifdef CONFIG_PAX_KERNEXEC
1209+/* PaX: fill first page in .text with int3 to catch NULL derefs in kernel mode */
1210+.fill 4096,1,0xcc
1211+#endif
1212+
1213+/*
1214+ * Real beginning of normal "text" segment
1215+ */
1216+ENTRY(stext)
1217+ENTRY(_stext)
1218
1219 /*
1220 * 32-bit kernel entrypoint; only used by the boot CPU. On entry,
1221@@ -67,6 +77,26 @@ ENTRY(startup_32)
1222 movl %eax,%fs
1223 movl %eax,%gs
1224
1225+#ifdef CONFIG_PAX_MEMORY_UDEREF
1226+ movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c09700),%eax
1227+ movl %eax,(cpu_gdt_table - __PAGE_OFFSET + GDT_ENTRY_KERNEL_DS * 8 + 4)
1228+ movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c0f300),%eax
1229+ movl %eax,(cpu_gdt_table - __PAGE_OFFSET + GDT_ENTRY_DEFAULT_USER_DS * 8 + 4)
1230+#endif
1231+
1232+#ifdef CONFIG_PAX_KERNEXEC
1233+ movl $ __KERNEL_TEXT_OFFSET,%eax
1234+ movw %ax,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 2)
1235+ rorl $16,%eax
1236+ movb %al,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 4)
1237+ movb %ah,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 7)
1238+
1239+ movb %al,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 4)
1240+ movb %ah,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 7)
1241+ rorl $16,%eax
1242+ movw %ax,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 2)
1243+#endif
1244+
1245 /*
1246 * Clear BSS first so that there are no surprises...
1247 * No need to cld as DF is already clear from cld above...
1248@@ -114,24 +144,42 @@ ENTRY(startup_32)
1249 * Warning: don't use %esi or the stack in this code. However, %esp
1250 * can be used as a GPR if you really need it...
1251 */
1252-page_pde_offset = (__PAGE_OFFSET >> 20);
1253-
1254+#ifdef CONFIG_X86_PAE
1255+page_pde_offset = ((__PAGE_OFFSET >> 21) * (4096 / PTRS_PER_PTE_asm));
1256+#else
1257+page_pde_offset = ((__PAGE_OFFSET >> 22) * (4096 / PTRS_PER_PTE_asm));
1258+#endif
1259 movl $(pg0 - __PAGE_OFFSET), %edi
1260+#ifdef CONFIG_X86_PAE
1261+ movl $(swapper_pm_dir - __PAGE_OFFSET), %edx
1262+#else
1263 movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
1264- movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */
1265+#endif
1266+ movl $0x063, %eax /* 0x063 = DIRTY+ACCESSED+PRESENT+RW */
1267 10:
1268- leal 0x007(%edi),%ecx /* Create PDE entry */
1269+ leal 0x063(%edi),%ecx /* Create PDE entry */
1270 movl %ecx,(%edx) /* Store identity PDE entry */
1271 movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */
1272+#ifdef CONFIG_X86_PAE
1273+ movl $0,4(%edx)
1274+ movl $0,page_pde_offset+4(%edx)
1275+ addl $8,%edx
1276+ movl $512, %ecx
1277+#else
1278 addl $4,%edx
1279 movl $1024, %ecx
1280+#endif
1281 11:
1282 stosl
1283+#ifdef CONFIG_X86_PAE
1284+ movl $0,(%edi)
1285+ addl $4,%edi
1286+#endif
1287 addl $0x1000,%eax
1288 loop 11b
1289 /* End condition: we must map up to and including INIT_MAP_BEYOND_END */
1290- /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */
1291- leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp
1292+ /* bytes beyond the end of our own page tables; the +0x063 is the attribute bits */
1293+ leal (INIT_MAP_BEYOND_END+0x063)(%edi),%ebp
1294 cmpl %ebp,%eax
1295 jb 10b
1296 movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
1297@@ -154,6 +202,11 @@ ENTRY(startup_32_smp)
1298 movl %eax,%fs
1299 movl %eax,%gs
1300
1301+ /* This is a secondary processor (AP) */
1302+ xorl %ebx,%ebx
1303+ incl %ebx
1304+#endif /* CONFIG_SMP */
1305+
1306 /*
1307 * New page tables may be in 4Mbyte page mode and may
1308 * be using the global pages.
1309@@ -169,26 +222,27 @@ ENTRY(startup_32_smp)
1310 * not yet offset PAGE_OFFSET..
1311 */
1312 #define cr4_bits mmu_cr4_features-__PAGE_OFFSET
1313+3:
1314 movl cr4_bits,%edx
1315 andl %edx,%edx
1316- jz 6f
1317+ jz 5f
1318 movl %cr4,%eax # Turn on paging options (PSE,PAE,..)
1319 orl %edx,%eax
1320 movl %eax,%cr4
1321
1322- btl $5, %eax # check if PAE is enabled
1323- jnc 6f
1324+#ifdef CONFIG_X86_PAE
1325+ movl %ebx,%edi
1326
1327 /* Check if extended functions are implemented */
1328 movl $0x80000000, %eax
1329 cpuid
1330 cmpl $0x80000000, %eax
1331- jbe 6f
1332+ jbe 4f
1333 mov $0x80000001, %eax
1334 cpuid
1335 /* Execute Disable bit supported? */
1336 btl $20, %edx
1337- jnc 6f
1338+ jnc 4f
1339
1340 /* Setup EFER (Extended Feature Enable Register) */
1341 movl $0xc0000080, %ecx
1342@@ -197,14 +251,12 @@ ENTRY(startup_32_smp)
1343 btsl $11, %eax
1344 /* Make changes effective */
1345 wrmsr
1346+ btsl $63,__supported_pte_mask-__PAGE_OFFSET
1347
1348-6:
1349- /* This is a secondary processor (AP) */
1350- xorl %ebx,%ebx
1351- incl %ebx
1352-
1353-3:
1354-#endif /* CONFIG_SMP */
1355+4:
1356+ movl %edi,%ebx
1357+#endif
1358+5:
1359
1360 /*
1361 * Enable paging
1362@@ -229,9 +281,7 @@ ENTRY(startup_32_smp)
1363
1364 #ifdef CONFIG_SMP
1365 andl %ebx,%ebx
1366- jz 1f /* Initial CPU cleans BSS */
1367- jmp checkCPUtype
1368-1:
1369+ jnz checkCPUtype /* Initial CPU cleans BSS */
1370 #endif /* CONFIG_SMP */
1371
1372 /*
1373@@ -308,8 +358,6 @@ is386: movl $2,%ecx # set MP
1374 ljmp $(__KERNEL_CS),$1f
1375 1: movl $(__KERNEL_DS),%eax # reload all the segment registers
1376 movl %eax,%ss # after changing gdt.
1377-
1378- movl $(__USER_DS),%eax # DS/ES contains default USER segment
1379 movl %eax,%ds
1380 movl %eax,%es
1381
1382@@ -378,13 +426,35 @@ rp_sidt:
1383 addl $8,%edi
1384 dec %ecx
1385 jne rp_sidt
1386+
1387+ lea ignore_int_error_code,%edx
1388+ movw %dx,%ax /* selector = 0x0010 = cs */
1389+ movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
1390+
1391+ lea idt_table,%edi
1392+ movl %eax,8*8(%edi)
1393+ movl %edx,8*8+4(%edi)
1394+ movl %eax,10*8(%edi)
1395+ movl %edx,10*8+4(%edi)
1396+ movl %eax,11*8(%edi)
1397+ movl %edx,11*8+4(%edi)
1398+ movl %eax,12*8(%edi)
1399+ movl %edx,12*8+4(%edi)
1400+ movl %eax,13*8(%edi)
1401+ movl %edx,13*8+4(%edi)
1402+ movl %eax,14*8(%edi)
1403+ movl %edx,14*8+4(%edi)
1404+ movl %eax,17*8(%edi)
1405+ movl %edx,17*8+4(%edi)
1406 ret
1407
1408 /* This is the default interrupt "handler" :-) */
1409 ALIGN
1410+ignore_int_error_code:
1411+ addl $4,%esp
1412 ignore_int:
1413- cld
1414 #ifdef CONFIG_PRINTK
1415+ cld
1416 pushl %eax
1417 pushl %ecx
1418 pushl %edx
1419@@ -393,17 +463,16 @@ ignore_int:
1420 movl $(__KERNEL_DS),%eax
1421 movl %eax,%ds
1422 movl %eax,%es
1423- pushl 16(%esp)
1424- pushl 24(%esp)
1425- pushl 32(%esp)
1426- pushl 40(%esp)
1427+ pushl 28(%esp)
1428+ pushl 28(%esp)
1429+ pushl 28(%esp)
1430 pushl $int_msg
1431 #ifdef CONFIG_EARLY_PRINTK
1432 call early_printk
1433 #else
1434 call printk
1435 #endif
1436- addl $(5*4),%esp
1437+ addl $(4*4),%esp
1438 popl %ds
1439 popl %es
1440 popl %edx
1441@@ -412,32 +481,50 @@ ignore_int:
1442 #endif
1443 iret
1444
1445-/*
1446- * Real beginning of normal "text" segment
1447- */
1448-ENTRY(stext)
1449-ENTRY(_stext)
1450-
1451-/*
1452- * BSS section
1453- */
1454-.section ".bss.page_aligned","w"
1455+.section .swapper_pg_dir,"a",@progbits
1456 ENTRY(swapper_pg_dir)
1457+#ifdef CONFIG_X86_PAE
1458+ .long swapper_pm_dir-__PAGE_OFFSET+1
1459+ .long 0
1460+ .long swapper_pm_dir+512*8-__PAGE_OFFSET+1
1461+ .long 0
1462+ .long swapper_pm_dir+512*16-__PAGE_OFFSET+1
1463+ .long 0
1464+ .long swapper_pm_dir+512*24-__PAGE_OFFSET+1
1465+ .long 0
1466+#else
1467 .fill 1024,4,0
1468+#endif
1469+
1470+#ifdef CONFIG_X86_PAE
1471+.section .swapper_pm_dir,"a",@progbits
1472+ENTRY(swapper_pm_dir)
1473+ .fill 512,8,0
1474+ .fill 512,8,0
1475+ .fill 512,8,0
1476+ .fill 512,8,0
1477+#endif
1478+
1479+.section .empty_zero_page,"a",@progbits
1480 ENTRY(empty_zero_page)
1481 .fill 4096,1,0
1482
1483 /*
1484- * This starts the data section.
1485- */
1486-.data
1487+ * The IDT has to be page-aligned to simplify the Pentium
1488+ * F0 0F bug workaround.. We have a special link segment
1489+ * for this.
1490+ */
1491+.section .idt,"a",@progbits
1492+ENTRY(idt_table)
1493+ .fill 256,8,0
1494+
1495+.section .rodata,"a",@progbits
1496+ready: .byte 0
1497
1498 ENTRY(stack_start)
1499- .long init_thread_union+THREAD_SIZE
1500+ .long init_thread_union+THREAD_SIZE-8
1501 .long __BOOT_DS
1502
1503-ready: .byte 0
1504-
1505 int_msg:
1506 .asciz "Unknown interrupt or fault at EIP %p %p %p\n"
1507
1508@@ -465,10 +552,12 @@ idt_descr:
1509
1510 # boot GDT descriptor (later on used by CPU#0):
1511 .word 0 # 32 bit align gdt_desc.address
1512-cpu_gdt_descr:
1513+ENTRY(cpu_gdt_descr)
1514 .word GDT_ENTRIES*8-1
1515 .long cpu_gdt_table
1516
1517+ .fill NR_CPUS*8-6,1,0 # space for the other GDT descriptors
1518+
1519 /*
1520 * The boot_gdt_table must mirror the equivalent in setup.S and is
1521 * used only for booting.
1522@@ -476,13 +565,13 @@ cpu_gdt_descr:
1523 .align L1_CACHE_BYTES
1524 ENTRY(boot_gdt_table)
1525 .fill GDT_ENTRY_BOOT_CS,8,0
1526- .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */
1527- .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */
1528+ .quad 0x00cf9b000000ffff /* kernel 4GB code at 0x00000000 */
1529+ .quad 0x00cf93000000ffff /* kernel 4GB data at 0x00000000 */
1530
1531 /*
1532 * The Global Descriptor Table contains 28 quadwords, per-CPU.
1533 */
1534- .align L1_CACHE_BYTES
1535+ .align PAGE_SIZE_asm
1536 ENTRY(cpu_gdt_table)
1537 .quad 0x0000000000000000 /* NULL descriptor */
1538 .quad 0x0000000000000000 /* 0x0b reserved */
1539@@ -497,10 +586,10 @@ ENTRY(cpu_gdt_table)
1540 .quad 0x0000000000000000 /* 0x53 reserved */
1541 .quad 0x0000000000000000 /* 0x5b reserved */
1542
1543- .quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */
1544- .quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */
1545- .quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */
1546- .quad 0x00cff2000000ffff /* 0x7b user 4GB data at 0x00000000 */
1547+ .quad 0x00cf9b000000ffff /* 0x60 kernel 4GB code at 0x00000000 */
1548+ .quad 0x00cf93000000ffff /* 0x68 kernel 4GB data at 0x00000000 */
1549+ .quad 0x00cffb000000ffff /* 0x73 user 4GB code at 0x00000000 */
1550+ .quad 0x00cff3000000ffff /* 0x7b user 4GB data at 0x00000000 */
1551
1552 .quad 0x0000000000000000 /* 0x80 TSS descriptor */
1553 .quad 0x0000000000000000 /* 0x88 LDT descriptor */
1554@@ -510,24 +599,30 @@ ENTRY(cpu_gdt_table)
1555 * They code segments and data segments have fixed 64k limits,
1556 * the transfer segment sizes are set at run time.
1557 */
1558- .quad 0x00409a000000ffff /* 0x90 32-bit code */
1559- .quad 0x00009a000000ffff /* 0x98 16-bit code */
1560- .quad 0x000092000000ffff /* 0xa0 16-bit data */
1561- .quad 0x0000920000000000 /* 0xa8 16-bit data */
1562- .quad 0x0000920000000000 /* 0xb0 16-bit data */
1563+ .quad 0x00409b000000ffff /* 0x90 32-bit code */
1564+ .quad 0x00009b000000ffff /* 0x98 16-bit code */
1565+ .quad 0x000093000000ffff /* 0xa0 16-bit data */
1566+ .quad 0x0000930000000000 /* 0xa8 16-bit data */
1567+ .quad 0x0000930000000000 /* 0xb0 16-bit data */
1568
1569 /*
1570 * The APM segments have byte granularity and their bases
1571 * are set at run time. All have 64k limits.
1572 */
1573- .quad 0x00409a000000ffff /* 0xb8 APM CS code */
1574- .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */
1575- .quad 0x004092000000ffff /* 0xc8 APM DS data */
1576+ .quad 0x00409b000000ffff /* 0xb8 APM CS code */
1577+ .quad 0x00009b000000ffff /* 0xc0 APM CS 16 code (16 bit) */
1578+ .quad 0x004093000000ffff /* 0xc8 APM DS data */
1579
1580- .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */
1581+ .quad 0x0000930000000000 /* 0xd0 - ESPFIX 16-bit SS */
1582 .quad 0x0000000000000000 /* 0xd8 - unused */
1583 .quad 0x0000000000000000 /* 0xe0 - unused */
1584 .quad 0x0000000000000000 /* 0xe8 - unused */
1585 .quad 0x0000000000000000 /* 0xf0 - unused */
1586 .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */
1587
1588+ /* Be sure this is zeroed to avoid false validations in Xen */
1589+ .fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0
1590+
1591+#ifdef CONFIG_SMP
1592+ .fill (NR_CPUS-1) * (PAGE_SIZE_asm / 8),8,0 /* other CPU's GDT */
1593+#endif
1594diff -urNp linux-2.6.17.11/arch/i386/kernel/i386_ksyms.c linux-2.6.17.11/arch/i386/kernel/i386_ksyms.c
1595--- linux-2.6.17.11/arch/i386/kernel/i386_ksyms.c 2006-08-07 00:18:54.000000000 -0400
1596+++ linux-2.6.17.11/arch/i386/kernel/i386_ksyms.c 2006-08-12 08:17:55.000000000 -0400
1597@@ -3,12 +3,16 @@
1598 #include <asm/checksum.h>
1599 #include <asm/desc.h>
1600
1601+EXPORT_SYMBOL_GPL(cpu_gdt_table);
1602+
1603 EXPORT_SYMBOL(__down_failed);
1604 EXPORT_SYMBOL(__down_failed_interruptible);
1605 EXPORT_SYMBOL(__down_failed_trylock);
1606 EXPORT_SYMBOL(__up_wakeup);
1607 /* Networking helper routines. */
1608 EXPORT_SYMBOL(csum_partial_copy_generic);
1609+EXPORT_SYMBOL(csum_partial_copy_generic_to_user);
1610+EXPORT_SYMBOL(csum_partial_copy_generic_from_user);
1611
1612 EXPORT_SYMBOL(__get_user_1);
1613 EXPORT_SYMBOL(__get_user_2);
1614diff -urNp linux-2.6.17.11/arch/i386/kernel/init_task.c linux-2.6.17.11/arch/i386/kernel/init_task.c
1615--- linux-2.6.17.11/arch/i386/kernel/init_task.c 2006-08-07 00:18:54.000000000 -0400
1616+++ linux-2.6.17.11/arch/i386/kernel/init_task.c 2006-08-12 08:17:55.000000000 -0400
1617@@ -42,5 +42,5 @@ EXPORT_SYMBOL(init_task);
1618 * per-CPU TSS segments. Threads are completely 'soft' on Linux,
1619 * no more per-task TSS's.
1620 */
1621-DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS;
1622+struct tss_struct init_tss[NR_CPUS] ____cacheline_internodealigned_in_smp = { [0 ... NR_CPUS-1] = INIT_TSS };
1623
1624diff -urNp linux-2.6.17.11/arch/i386/kernel/ioport.c linux-2.6.17.11/arch/i386/kernel/ioport.c
1625--- linux-2.6.17.11/arch/i386/kernel/ioport.c 2006-08-07 00:18:54.000000000 -0400
1626+++ linux-2.6.17.11/arch/i386/kernel/ioport.c 2006-08-12 08:17:55.000000000 -0400
1627@@ -16,6 +16,7 @@
1628 #include <linux/stddef.h>
1629 #include <linux/slab.h>
1630 #include <linux/thread_info.h>
1631+#include <linux/grsecurity.h>
1632
1633 /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
1634 static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
1635@@ -64,9 +65,16 @@ asmlinkage long sys_ioperm(unsigned long
1636
1637 if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
1638 return -EINVAL;
1639+#ifdef CONFIG_GRKERNSEC_IO
1640+ if (turn_on) {
1641+ gr_handle_ioperm();
1642+#else
1643 if (turn_on && !capable(CAP_SYS_RAWIO))
1644+#endif
1645 return -EPERM;
1646-
1647+#ifdef CONFIG_GRKERNSEC_IO
1648+ }
1649+#endif
1650 /*
1651 * If it's the first ioperm() call in this thread's lifetime, set the
1652 * IO bitmap up. ioperm() is much less timing critical than clone(),
1653@@ -88,7 +96,7 @@ asmlinkage long sys_ioperm(unsigned long
1654 * because the ->io_bitmap_max value must match the bitmap
1655 * contents:
1656 */
1657- tss = &per_cpu(init_tss, get_cpu());
1658+ tss = init_tss + get_cpu();
1659
1660 set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
1661
1662@@ -142,8 +150,13 @@ asmlinkage long sys_iopl(unsigned long u
1663 return -EINVAL;
1664 /* Trying to gain more privileges? */
1665 if (level > old) {
1666+#ifdef CONFIG_GRKERNSEC_IO
1667+ gr_handle_iopl();
1668+ return -EPERM;
1669+#else
1670 if (!capable(CAP_SYS_RAWIO))
1671 return -EPERM;
1672+#endif
1673 }
1674 t->iopl = level << 12;
1675 regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl;
1676diff -urNp linux-2.6.17.11/arch/i386/kernel/irq.c linux-2.6.17.11/arch/i386/kernel/irq.c
1677--- linux-2.6.17.11/arch/i386/kernel/irq.c 2006-08-07 00:18:54.000000000 -0400
1678+++ linux-2.6.17.11/arch/i386/kernel/irq.c 2006-08-12 08:17:55.000000000 -0400
1679@@ -91,7 +91,7 @@ fastcall unsigned int do_IRQ(struct pt_r
1680 int arg1, arg2, ebx;
1681
1682 /* build the stack frame on the IRQ stack */
1683- isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
1684+ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)) - 2;
1685 irqctx->tinfo.task = curctx->tinfo.task;
1686 irqctx->tinfo.previous_esp = current_stack_pointer;
1687
1688@@ -119,10 +119,10 @@ fastcall unsigned int do_IRQ(struct pt_r
1689 * gcc's 3.0 and earlier don't handle that correctly.
1690 */
1691 static char softirq_stack[NR_CPUS * THREAD_SIZE]
1692- __attribute__((__aligned__(THREAD_SIZE)));
1693+ __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
1694
1695 static char hardirq_stack[NR_CPUS * THREAD_SIZE]
1696- __attribute__((__aligned__(THREAD_SIZE)));
1697+ __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
1698
1699 /*
1700 * allocate per-cpu stacks for hardirq and for softirq processing
1701@@ -182,7 +182,7 @@ asmlinkage void do_softirq(void)
1702 irqctx->tinfo.previous_esp = current_stack_pointer;
1703
1704 /* build the stack frame on the softirq stack */
1705- isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
1706+ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)) - 2;
1707
1708 asm volatile(
1709 " xchgl %%ebx,%%esp \n"
1710diff -urNp linux-2.6.17.11/arch/i386/kernel/ldt.c linux-2.6.17.11/arch/i386/kernel/ldt.c
1711--- linux-2.6.17.11/arch/i386/kernel/ldt.c 2006-08-07 00:18:54.000000000 -0400
1712+++ linux-2.6.17.11/arch/i386/kernel/ldt.c 2006-08-12 08:17:55.000000000 -0400
1713@@ -103,6 +103,19 @@ int init_new_context(struct task_struct
1714 retval = copy_ldt(&mm->context, &old_mm->context);
1715 up(&old_mm->context.sem);
1716 }
1717+
1718+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
1719+ if (!mm->context.user_cs_limit) {
1720+ mm->context.user_cs_base = 0UL;
1721+ mm->context.user_cs_limit = ~0UL;
1722+
1723+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
1724+ cpus_clear(mm->context.cpu_user_cs_mask);
1725+#endif
1726+
1727+ }
1728+#endif
1729+
1730 return retval;
1731 }
1732
1733@@ -160,7 +173,7 @@ static int read_default_ldt(void __user
1734 {
1735 int err;
1736 unsigned long size;
1737- void *address;
1738+ const void *address;
1739
1740 err = 0;
1741 address = &default_ldt[0];
1742@@ -215,6 +228,13 @@ static int write_ldt(void __user * ptr,
1743 }
1744 }
1745
1746+#ifdef CONFIG_PAX_SEGMEXEC
1747+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (ldt_info.contents & MODIFY_LDT_CONTENTS_CODE)) {
1748+ error = -EINVAL;
1749+ goto out_unlock;
1750+ }
1751+#endif
1752+
1753 entry_1 = LDT_entry_a(&ldt_info);
1754 entry_2 = LDT_entry_b(&ldt_info);
1755 if (oldmode)
1756diff -urNp linux-2.6.17.11/arch/i386/kernel/module.c linux-2.6.17.11/arch/i386/kernel/module.c
1757--- linux-2.6.17.11/arch/i386/kernel/module.c 2006-08-07 00:18:54.000000000 -0400
1758+++ linux-2.6.17.11/arch/i386/kernel/module.c 2006-08-12 08:17:55.000000000 -0400
1759@@ -21,6 +21,7 @@
1760 #include <linux/fs.h>
1761 #include <linux/string.h>
1762 #include <linux/kernel.h>
1763+#include <asm/desc.h>
1764
1765 #if 0
1766 #define DEBUGP printk
1767@@ -32,9 +33,30 @@ void *module_alloc(unsigned long size)
1768 {
1769 if (size == 0)
1770 return NULL;
1771+
1772+#ifdef CONFIG_PAX_KERNEXEC
1773+ return vmalloc(size);
1774+#else
1775 return vmalloc_exec(size);
1776+#endif
1777+
1778 }
1779
1780+#ifdef CONFIG_PAX_KERNEXEC
1781+void *module_alloc_exec(unsigned long size)
1782+{
1783+ struct vm_struct *area;
1784+
1785+ if (size == 0)
1786+ return NULL;
1787+
1788+ area = __get_vm_area(size, 0, (unsigned long)&MODULES_VADDR, (unsigned long)&MODULES_END);
1789+ if (area)
1790+ return area->addr;
1791+
1792+ return NULL;
1793+}
1794+#endif
1795
1796 /* Free memory returned from module_alloc */
1797 void module_free(struct module *mod, void *module_region)
1798@@ -44,6 +66,45 @@ void module_free(struct module *mod, voi
1799 table entries. */
1800 }
1801
1802+#ifdef CONFIG_PAX_KERNEXEC
1803+void module_free_exec(struct module *mod, void *module_region)
1804+{
1805+ struct vm_struct **p, *tmp;
1806+
1807+ if (!module_region)
1808+ return;
1809+
1810+ if ((PAGE_SIZE-1) & (unsigned long)module_region) {
1811+ printk(KERN_ERR "Trying to module_free_exec() bad address (%p)\n", module_region);
1812+ WARN_ON(1);
1813+ return;
1814+ }
1815+
1816+ write_lock(&vmlist_lock);
1817+ for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next)
1818+ if (tmp->addr == module_region)
1819+ break;
1820+
1821+ if (tmp) {
1822+ unsigned long cr0;
1823+
1824+ pax_open_kernel(cr0);
1825+ memset(tmp->addr, 0xCC, tmp->size);
1826+ pax_close_kernel(cr0);
1827+
1828+ *p = tmp->next;
1829+ kfree(tmp);
1830+ }
1831+ write_unlock(&vmlist_lock);
1832+
1833+ if (!tmp) {
1834+ printk(KERN_ERR "Trying to module_free_exec() nonexistent vm area (%p)\n",
1835+ module_region);
1836+ WARN_ON(1);
1837+ }
1838+}
1839+#endif
1840+
1841 /* We don't need anything special. */
1842 int module_frob_arch_sections(Elf_Ehdr *hdr,
1843 Elf_Shdr *sechdrs,
1844@@ -62,14 +123,16 @@ int apply_relocate(Elf32_Shdr *sechdrs,
1845 unsigned int i;
1846 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
1847 Elf32_Sym *sym;
1848- uint32_t *location;
1849+ uint32_t *plocation, location;
1850
1851 DEBUGP("Applying relocate section %u to %u\n", relsec,
1852 sechdrs[relsec].sh_info);
1853 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
1854 /* This is where to make the change */
1855- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
1856- + rel[i].r_offset;
1857+ plocation = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset;
1858+ location = (uint32_t)plocation;
1859+ if (sechdrs[sechdrs[relsec].sh_info].sh_flags & SHF_EXECINSTR)
1860+ plocation = (void *)plocation + __KERNEL_TEXT_OFFSET;
1861 /* This is the symbol it is referring to. Note that all
1862 undefined symbols have been resolved. */
1863 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
1864@@ -78,11 +141,11 @@ int apply_relocate(Elf32_Shdr *sechdrs,
1865 switch (ELF32_R_TYPE(rel[i].r_info)) {
1866 case R_386_32:
1867 /* We add the value into the location given */
1868- *location += sym->st_value;
1869+ *plocation += sym->st_value;
1870 break;
1871 case R_386_PC32:
1872 /* Add the value, subtract its postition */
1873- *location += sym->st_value - (uint32_t)location;
1874+ *plocation += sym->st_value - location;
1875 break;
1876 default:
1877 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
1878diff -urNp linux-2.6.17.11/arch/i386/kernel/process.c linux-2.6.17.11/arch/i386/kernel/process.c
1879--- linux-2.6.17.11/arch/i386/kernel/process.c 2006-08-07 00:18:54.000000000 -0400
1880+++ linux-2.6.17.11/arch/i386/kernel/process.c 2006-08-12 08:17:55.000000000 -0400
1881@@ -69,7 +69,7 @@ EXPORT_SYMBOL(boot_option_idle_override)
1882 */
1883 unsigned long thread_saved_pc(struct task_struct *tsk)
1884 {
1885- return ((unsigned long *)tsk->thread.esp)[3];
1886+ return tsk->thread.eip;
1887 }
1888
1889 /*
1890@@ -294,7 +294,7 @@ void show_regs(struct pt_regs * regs)
1891 printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id());
1892 print_symbol("EIP is at %s\n", regs->eip);
1893
1894- if (user_mode_vm(regs))
1895+ if (user_mode(regs))
1896 printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
1897 printk(" EFLAGS: %08lx %s (%s %.*s)\n",
1898 regs->eflags, print_tainted(), system_utsname.release,
1899@@ -343,8 +343,8 @@ int kernel_thread(int (*fn)(void *), voi
1900 regs.ebx = (unsigned long) fn;
1901 regs.edx = (unsigned long) arg;
1902
1903- regs.xds = __USER_DS;
1904- regs.xes = __USER_DS;
1905+ regs.xds = __KERNEL_DS;
1906+ regs.xes = __KERNEL_DS;
1907 regs.orig_eax = -1;
1908 regs.eip = (unsigned long) kernel_thread_helper;
1909 regs.xcs = __KERNEL_CS;
1910@@ -366,7 +366,7 @@ void exit_thread(void)
1911 /* The process may have allocated an io port bitmap... nuke it. */
1912 if (unlikely(NULL != t->io_bitmap_ptr)) {
1913 int cpu = get_cpu();
1914- struct tss_struct *tss = &per_cpu(init_tss, cpu);
1915+ struct tss_struct *tss = init_tss + cpu;
1916
1917 kfree(t->io_bitmap_ptr);
1918 t->io_bitmap_ptr = NULL;
1919@@ -386,6 +386,9 @@ void flush_thread(void)
1920 {
1921 struct task_struct *tsk = current;
1922
1923+ __asm__("mov %0,%%fs\n"
1924+ "mov %0,%%gs\n"
1925+ : : "r" (0) : "memory");
1926 memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
1927 memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
1928 /*
1929@@ -418,7 +421,7 @@ int copy_thread(int nr, unsigned long cl
1930 struct task_struct *tsk;
1931 int err;
1932
1933- childregs = task_pt_regs(p);
1934+ childregs = task_stack_page(p) + THREAD_SIZE - sizeof(struct pt_regs) - 8;
1935 *childregs = *regs;
1936 childregs->eax = 0;
1937 childregs->esp = esp;
1938@@ -461,6 +464,11 @@ int copy_thread(int nr, unsigned long cl
1939 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
1940 goto out;
1941
1942+#ifdef CONFIG_PAX_SEGMEXEC
1943+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
1944+ goto out;
1945+#endif
1946+
1947 desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
1948 desc->a = LDT_entry_a(&info);
1949 desc->b = LDT_entry_b(&info);
1950@@ -625,7 +633,11 @@ struct task_struct fastcall * __switch_t
1951 struct thread_struct *prev = &prev_p->thread,
1952 *next = &next_p->thread;
1953 int cpu = smp_processor_id();
1954- struct tss_struct *tss = &per_cpu(init_tss, cpu);
1955+ struct tss_struct *tss = init_tss + cpu;
1956+
1957+#ifdef CONFIG_PAX_KERNEXEC
1958+ unsigned long cr0;
1959+#endif
1960
1961 /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
1962
1963@@ -648,11 +660,23 @@ struct task_struct fastcall * __switch_t
1964 savesegment(fs, prev->fs);
1965 savesegment(gs, prev->gs);
1966
1967+#ifdef CONFIG_PAX_KERNEXEC
1968+ pax_open_kernel(cr0);
1969+#endif
1970+
1971+#ifdef CONFIG_PAX_MEMORY_UDEREF
1972+ __set_fs(get_fs(), cpu);
1973+#endif
1974+
1975 /*
1976 * Load the per-thread Thread-Local Storage descriptor.
1977 */
1978 load_TLS(next, cpu);
1979
1980+#ifdef CONFIG_PAX_KERNEXEC
1981+ pax_close_kernel(cr0);
1982+#endif
1983+
1984 /*
1985 * Restore %fs and %gs if needed.
1986 *
1987@@ -806,8 +830,18 @@ asmlinkage int sys_set_thread_area(struc
1988 struct desc_struct *desc;
1989 int cpu, idx;
1990
1991+#ifdef CONFIG_PAX_KERNEXEC
1992+ unsigned long cr0;
1993+#endif
1994+
1995 if (copy_from_user(&info, u_info, sizeof(info)))
1996 return -EFAULT;
1997+
1998+#ifdef CONFIG_PAX_SEGMEXEC
1999+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
2000+ return -EINVAL;
2001+#endif
2002+
2003 idx = info.entry_number;
2004
2005 /*
2006@@ -839,8 +873,17 @@ asmlinkage int sys_set_thread_area(struc
2007 desc->a = LDT_entry_a(&info);
2008 desc->b = LDT_entry_b(&info);
2009 }
2010+
2011+#ifdef CONFIG_PAX_KERNEXEC
2012+ pax_open_kernel(cr0);
2013+#endif
2014+
2015 load_TLS(t, cpu);
2016
2017+#ifdef CONFIG_PAX_KERNEXEC
2018+ pax_close_kernel(cr0);
2019+#endif
2020+
2021 put_cpu();
2022
2023 return 0;
2024@@ -896,9 +939,27 @@ asmlinkage int sys_get_thread_area(struc
2025 return 0;
2026 }
2027
2028-unsigned long arch_align_stack(unsigned long sp)
2029+#ifdef CONFIG_PAX_RANDKSTACK
2030+asmlinkage void pax_randomize_kstack(void)
2031 {
2032- if (randomize_va_space)
2033- sp -= get_random_int() % 8192;
2034- return sp & ~0xf;
2035+ struct tss_struct *tss = init_tss + smp_processor_id();
2036+ unsigned long time;
2037+
2038+ if (!randomize_va_space)
2039+ return;
2040+
2041+ rdtscl(time);
2042+
2043+ /* P4 seems to return a 0 LSB, ignore it */
2044+#ifdef CONFIG_MPENTIUM4
2045+ time &= 0x1EUL;
2046+ time <<= 2;
2047+#else
2048+ time &= 0xFUL;
2049+ time <<= 3;
2050+#endif
2051+
2052+ tss->esp0 ^= time;
2053+ current->thread.esp0 = tss->esp0;
2054 }
2055+#endif
2056diff -urNp linux-2.6.17.11/arch/i386/kernel/ptrace.c linux-2.6.17.11/arch/i386/kernel/ptrace.c
2057--- linux-2.6.17.11/arch/i386/kernel/ptrace.c 2006-08-07 00:18:54.000000000 -0400
2058+++ linux-2.6.17.11/arch/i386/kernel/ptrace.c 2006-08-12 08:17:55.000000000 -0400
2059@@ -17,6 +17,7 @@
2060 #include <linux/audit.h>
2061 #include <linux/seccomp.h>
2062 #include <linux/signal.h>
2063+#include <linux/grsecurity.h>
2064
2065 #include <asm/uaccess.h>
2066 #include <asm/pgtable.h>
2067@@ -342,6 +343,11 @@ ptrace_set_thread_area(struct task_struc
2068 if (copy_from_user(&info, user_desc, sizeof(info)))
2069 return -EFAULT;
2070
2071+#ifdef CONFIG_PAX_SEGMEXEC
2072+ if ((child->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
2073+ return -EINVAL;
2074+#endif
2075+
2076 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
2077 return -EINVAL;
2078
2079@@ -432,6 +438,17 @@ long arch_ptrace(struct task_struct *chi
2080 if(addr == (long) &dummy->u_debugreg[5]) break;
2081 if(addr < (long) &dummy->u_debugreg[4] &&
2082 ((unsigned long) data) >= TASK_SIZE-3) break;
2083+
2084+#ifdef CONFIG_GRKERNSEC
2085+ if(addr >= (long) &dummy->u_debugreg[0] &&
2086+ addr <= (long) &dummy->u_debugreg[3]){
2087+ long reg = (addr - (long) &dummy->u_debugreg[0]) >> 2;
2088+ long type = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 4*reg)) & 3;
2089+ long align = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 2 + 4*reg)) & 3;
2090+ if((type & 1) && (data & align))
2091+ break;
2092+ }
2093+#endif
2094
2095 /* Sanity-check data. Take one half-byte at once with
2096 * check = (val >> (16 + 4*i)) & 0xf. It contains the
2097@@ -645,7 +662,7 @@ void send_sigtrap(struct task_struct *ts
2098 info.si_code = TRAP_BRKPT;
2099
2100 /* User-mode eip? */
2101- info.si_addr = user_mode_vm(regs) ? (void __user *) regs->eip : NULL;
2102+ info.si_addr = user_mode(regs) ? (void __user *) regs->eip : NULL;
2103
2104 /* Send us the fakey SIGTRAP */
2105 force_sig_info(SIGTRAP, &info, tsk);
2106diff -urNp linux-2.6.17.11/arch/i386/kernel/reboot.c linux-2.6.17.11/arch/i386/kernel/reboot.c
2107--- linux-2.6.17.11/arch/i386/kernel/reboot.c 2006-08-07 00:18:54.000000000 -0400
2108+++ linux-2.6.17.11/arch/i386/kernel/reboot.c 2006-08-12 08:17:55.000000000 -0400
2109@@ -25,7 +25,7 @@
2110 void (*pm_power_off)(void);
2111 EXPORT_SYMBOL(pm_power_off);
2112
2113-static int reboot_mode;
2114+static unsigned short reboot_mode;
2115 static int reboot_thru_bios;
2116
2117 #ifdef CONFIG_SMP
2118@@ -138,18 +138,18 @@ core_initcall(reboot_init);
2119 doesn't work with at least one type of 486 motherboard. It is easy
2120 to stop this code working; hence the copious comments. */
2121
2122-static unsigned long long
2123+static const unsigned long long
2124 real_mode_gdt_entries [3] =
2125 {
2126 0x0000000000000000ULL, /* Null descriptor */
2127- 0x00009a000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */
2128- 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
2129+ 0x00009b000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */
2130+ 0x000093000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
2131 };
2132
2133 static struct
2134 {
2135 unsigned short size __attribute__ ((packed));
2136- unsigned long long * base __attribute__ ((packed));
2137+ const unsigned long long * base __attribute__ ((packed));
2138 }
2139 real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries },
2140 real_mode_idt = { 0x3ff, NULL },
2141@@ -175,7 +175,7 @@ no_idt = { 0, NULL };
2142 More could be done here to set up the registers as if a CPU reset had
2143 occurred; hopefully real BIOSs don't assume much. */
2144
2145-static unsigned char real_mode_switch [] =
2146+static const unsigned char real_mode_switch [] =
2147 {
2148 0x66, 0x0f, 0x20, 0xc0, /* movl %cr0,%eax */
2149 0x66, 0x83, 0xe0, 0x11, /* andl $0x00000011,%eax */
2150@@ -189,7 +189,7 @@ static unsigned char real_mode_switch []
2151 0x24, 0x10, /* f: andb $0x10,al */
2152 0x66, 0x0f, 0x22, 0xc0 /* movl %eax,%cr0 */
2153 };
2154-static unsigned char jump_to_bios [] =
2155+static const unsigned char jump_to_bios [] =
2156 {
2157 0xea, 0x00, 0x00, 0xff, 0xff /* ljmp $0xffff,$0x0000 */
2158 };
2159@@ -199,10 +199,14 @@ static unsigned char jump_to_bios [] =
2160 * specified by the code and length parameters.
2161 * We assume that length will aways be less that 100!
2162 */
2163-void machine_real_restart(unsigned char *code, int length)
2164+void machine_real_restart(const unsigned char *code, unsigned int length)
2165 {
2166 unsigned long flags;
2167
2168+#ifdef CONFIG_PAX_KERNEXEC
2169+ unsigned long cr0;
2170+#endif
2171+
2172 local_irq_disable();
2173
2174 /* Write zero to CMOS register number 0x0f, which the BIOS POST
2175@@ -223,8 +227,16 @@ void machine_real_restart(unsigned char
2176 from the kernel segment. This assumes the kernel segment starts at
2177 virtual address PAGE_OFFSET. */
2178
2179- memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
2180- sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
2181+#ifdef CONFIG_PAX_KERNEXEC
2182+ pax_open_kernel(cr0);
2183+#endif
2184+
2185+ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
2186+ USER_PGD_PTRS >= KERNEL_PGD_PTRS ? KERNEL_PGD_PTRS : USER_PGD_PTRS);
2187+
2188+#ifdef CONFIG_PAX_KERNEXEC
2189+ pax_close_kernel(cr0);
2190+#endif
2191
2192 /*
2193 * Use `swapper_pg_dir' as our page directory.
2194@@ -237,7 +249,7 @@ void machine_real_restart(unsigned char
2195 REBOOT.COM programs, and the previous reset routine did this
2196 too. */
2197
2198- *((unsigned short *)0x472) = reboot_mode;
2199+ __put_user(reboot_mode, (unsigned short __user *)0x472);
2200
2201 /* For the switch to real mode, copy some code to low memory. It has
2202 to be in the first 64k because it is running in 16-bit mode, and it
2203@@ -245,9 +257,9 @@ void machine_real_restart(unsigned char
2204 off paging. Copy it near the end of the first page, out of the way
2205 of BIOS variables. */
2206
2207- memcpy ((void *) (0x1000 - sizeof (real_mode_switch) - 100),
2208+ flags = __copy_to_user ((void __user *) (0x1000 - sizeof (real_mode_switch) - 100),
2209 real_mode_switch, sizeof (real_mode_switch));
2210- memcpy ((void *) (0x1000 - 100), code, length);
2211+ flags = __copy_to_user ((void __user *) (0x1000 - 100), code, length);
2212
2213 /* Set up the IDT for real mode. */
2214
2215@@ -329,7 +341,7 @@ void machine_emergency_restart(void)
2216 __asm__ __volatile__("int3");
2217 }
2218 /* rebooting needs to touch the page at absolute addr 0 */
2219- *((unsigned short *)__va(0x472)) = reboot_mode;
2220+ __put_user(reboot_mode, (unsigned short __user *)0x472);
2221 for (;;) {
2222 mach_reboot_fixups(); /* for board specific fixups */
2223 mach_reboot();
2224diff -urNp linux-2.6.17.11/arch/i386/kernel/setup.c linux-2.6.17.11/arch/i386/kernel/setup.c
2225--- linux-2.6.17.11/arch/i386/kernel/setup.c 2006-08-07 00:18:54.000000000 -0400
2226+++ linux-2.6.17.11/arch/i386/kernel/setup.c 2006-08-12 08:17:55.000000000 -0400
2227@@ -88,7 +88,11 @@ struct cpuinfo_x86 new_cpu_data __initda
2228 struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
2229 EXPORT_SYMBOL(boot_cpu_data);
2230
2231+#ifdef CONFIG_X86_PAE
2232+unsigned long mmu_cr4_features = X86_CR4_PAE;
2233+#else
2234 unsigned long mmu_cr4_features;
2235+#endif
2236
2237 #ifdef CONFIG_ACPI
2238 int acpi_disabled = 0;
2239@@ -1493,14 +1497,14 @@ void __init setup_arch(char **cmdline_p)
2240
2241 if (!MOUNT_ROOT_RDONLY)
2242 root_mountflags &= ~MS_RDONLY;
2243- init_mm.start_code = (unsigned long) _text;
2244- init_mm.end_code = (unsigned long) _etext;
2245+ init_mm.start_code = (unsigned long) _text + __KERNEL_TEXT_OFFSET;
2246+ init_mm.end_code = (unsigned long) _etext + __KERNEL_TEXT_OFFSET;
2247 init_mm.end_data = (unsigned long) _edata;
2248 init_mm.brk = init_pg_tables_end + PAGE_OFFSET;
2249
2250- code_resource.start = virt_to_phys(_text);
2251- code_resource.end = virt_to_phys(_etext)-1;
2252- data_resource.start = virt_to_phys(_etext);
2253+ code_resource.start = virt_to_phys(_text + __KERNEL_TEXT_OFFSET);
2254+ code_resource.end = virt_to_phys(_etext + __KERNEL_TEXT_OFFSET)-1;
2255+ data_resource.start = virt_to_phys(_data);
2256 data_resource.end = virt_to_phys(_edata)-1;
2257
2258 parse_cmdline_early(cmdline_p);
2259diff -urNp linux-2.6.17.11/arch/i386/kernel/signal.c linux-2.6.17.11/arch/i386/kernel/signal.c
2260--- linux-2.6.17.11/arch/i386/kernel/signal.c 2006-08-07 00:18:54.000000000 -0400
2261+++ linux-2.6.17.11/arch/i386/kernel/signal.c 2006-08-12 08:17:55.000000000 -0400
2262@@ -351,7 +351,17 @@ static int setup_frame(int sig, struct k
2263 goto give_sigsegv;
2264 }
2265
2266+#ifdef CONFIG_PAX_NOVSYSCALL
2267+ restorer = frame->retcode;
2268+#else
2269 restorer = &__kernel_sigreturn;
2270+
2271+#ifdef CONFIG_PAX_SEGMEXEC
2272+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
2273+ restorer -= SEGMEXEC_TASK_SIZE;
2274+#endif
2275+#endif
2276+
2277 if (ka->sa.sa_flags & SA_RESTORER)
2278 restorer = ka->sa.sa_restorer;
2279
2280@@ -447,7 +457,18 @@ static int setup_rt_frame(int sig, struc
2281 goto give_sigsegv;
2282
2283 /* Set up to return from userspace. */
2284+
2285+#ifdef CONFIG_PAX_NOVSYSCALL
2286+ restorer = frame->retcode;
2287+#else
2288 restorer = &__kernel_rt_sigreturn;
2289+
2290+#ifdef CONFIG_PAX_SEGMEXEC
2291+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
2292+ restorer -= SEGMEXEC_TASK_SIZE;
2293+#endif
2294+#endif
2295+
2296 if (ka->sa.sa_flags & SA_RESTORER)
2297 restorer = ka->sa.sa_restorer;
2298 err |= __put_user(restorer, &frame->pretcode);
2299@@ -580,7 +601,7 @@ static void fastcall do_signal(struct pt
2300 * before reaching here, so testing against kernel
2301 * CS suffices.
2302 */
2303- if (!user_mode(regs))
2304+ if (!user_mode_novm(regs))
2305 return;
2306
2307 if (test_thread_flag(TIF_RESTORE_SIGMASK))
2308diff -urNp linux-2.6.17.11/arch/i386/kernel/smpboot.c linux-2.6.17.11/arch/i386/kernel/smpboot.c
2309--- linux-2.6.17.11/arch/i386/kernel/smpboot.c 2006-08-07 00:18:54.000000000 -0400
2310+++ linux-2.6.17.11/arch/i386/kernel/smpboot.c 2006-08-12 08:17:55.000000000 -0400
2311@@ -1069,7 +1069,7 @@ static int __cpuinit __smp_prepare_cpu(i
2312
2313 /* init low mem mapping */
2314 clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
2315- KERNEL_PGD_PTRS);
2316+ USER_PGD_PTRS >= KERNEL_PGD_PTRS ? KERNEL_PGD_PTRS : USER_PGD_PTRS);
2317 flush_tlb_all();
2318 schedule_work(&task);
2319 wait_for_completion(&done);
2320diff -urNp linux-2.6.17.11/arch/i386/kernel/syscall_table.S linux-2.6.17.11/arch/i386/kernel/syscall_table.S
2321--- linux-2.6.17.11/arch/i386/kernel/syscall_table.S 2006-08-07 00:18:54.000000000 -0400
2322+++ linux-2.6.17.11/arch/i386/kernel/syscall_table.S 2006-08-12 08:17:55.000000000 -0400
2323@@ -1,3 +1,4 @@
2324+.section .rodata,"a",@progbits
2325 ENTRY(sys_call_table)
2326 .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
2327 .long sys_exit
2328diff -urNp linux-2.6.17.11/arch/i386/kernel/sysenter.c linux-2.6.17.11/arch/i386/kernel/sysenter.c
2329--- linux-2.6.17.11/arch/i386/kernel/sysenter.c 2006-08-07 00:18:54.000000000 -0400
2330+++ linux-2.6.17.11/arch/i386/kernel/sysenter.c 2006-08-12 08:17:55.000000000 -0400
2331@@ -24,7 +24,7 @@ extern asmlinkage void sysenter_entry(vo
2332 void enable_sep_cpu(void)
2333 {
2334 int cpu = get_cpu();
2335- struct tss_struct *tss = &per_cpu(init_tss, cpu);
2336+ struct tss_struct *tss = init_tss + cpu;
2337
2338 if (!boot_cpu_has(X86_FEATURE_SEP)) {
2339 put_cpu();
2340@@ -48,6 +48,7 @@ extern const char vsyscall_sysenter_star
2341
2342 int __init sysenter_setup(void)
2343 {
2344+#ifndef CONFIG_PAX_NOVSYSCALL
2345 void *page = (void *)get_zeroed_page(GFP_ATOMIC);
2346
2347 __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
2348@@ -62,6 +63,7 @@ int __init sysenter_setup(void)
2349 memcpy(page,
2350 &vsyscall_sysenter_start,
2351 &vsyscall_sysenter_end - &vsyscall_sysenter_start);
2352+#endif
2353
2354 return 0;
2355 }
2356diff -urNp linux-2.6.17.11/arch/i386/kernel/sys_i386.c linux-2.6.17.11/arch/i386/kernel/sys_i386.c
2357--- linux-2.6.17.11/arch/i386/kernel/sys_i386.c 2006-08-07 00:18:54.000000000 -0400
2358+++ linux-2.6.17.11/arch/i386/kernel/sys_i386.c 2006-08-12 08:17:55.000000000 -0400
2359@@ -99,6 +99,191 @@ out:
2360 return err;
2361 }
2362
2363+unsigned long
2364+arch_get_unmapped_area(struct file *filp, unsigned long addr,
2365+ unsigned long len, unsigned long pgoff, unsigned long flags)
2366+{
2367+ struct mm_struct *mm = current->mm;
2368+ struct vm_area_struct *vma;
2369+ unsigned long start_addr, task_size = TASK_SIZE;
2370+
2371+#ifdef CONFIG_PAX_SEGMEXEC
2372+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
2373+ task_size = SEGMEXEC_TASK_SIZE;
2374+#endif
2375+
2376+ if (len > task_size)
2377+ return -ENOMEM;
2378+
2379+#ifdef CONFIG_PAX_RANDMMAP
2380+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
2381+#endif
2382+
2383+ if (addr) {
2384+ addr = PAGE_ALIGN(addr);
2385+ vma = find_vma(mm, addr);
2386+ if (task_size - len >= addr &&
2387+ (!vma || addr + len <= vma->vm_start))
2388+ return addr;
2389+ }
2390+ if (len > mm->cached_hole_size) {
2391+ start_addr = addr = mm->free_area_cache;
2392+ } else {
2393+ start_addr = addr = mm->mmap_base;
2394+ mm->cached_hole_size = 0;
2395+ }
2396+
2397+#ifdef CONFIG_PAX_PAGEEXEC
2398+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE) && start_addr >= mm->mmap_base) {
2399+ start_addr = 0x00110000UL;
2400+
2401+#ifdef CONFIG_PAX_RANDMMAP
2402+ if (mm->pax_flags & MF_PAX_RANDMMAP)
2403+ start_addr += mm->delta_mmap & 0x03FFF000UL;
2404+#endif
2405+
2406+ if (mm->start_brk <= start_addr && start_addr < mm->mmap_base)
2407+ start_addr = addr = mm->mmap_base;
2408+ else
2409+ addr = start_addr;
2410+ }
2411+#endif
2412+
2413+full_search:
2414+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
2415+ /* At this point: (!vma || addr < vma->vm_end). */
2416+ if (task_size - len < addr) {
2417+ /*
2418+ * Start a new search - just in case we missed
2419+ * some holes.
2420+ */
2421+ if (start_addr != mm->mmap_base) {
2422+ start_addr = addr = mm->mmap_base;
2423+ mm->cached_hole_size = 0;
2424+ goto full_search;
2425+ }
2426+ return -ENOMEM;
2427+ }
2428+ if (!vma || addr + len <= vma->vm_start) {
2429+ /*
2430+ * Remember the place where we stopped the search:
2431+ */
2432+ mm->free_area_cache = addr + len;
2433+ return addr;
2434+ }
2435+ if (addr + mm->cached_hole_size < vma->vm_start)
2436+ mm->cached_hole_size = vma->vm_start - addr;
2437+ addr = vma->vm_end;
2438+ if (mm->start_brk <= addr && addr < mm->mmap_base) {
2439+ start_addr = addr = mm->mmap_base;
2440+ goto full_search;
2441+ }
2442+ }
2443+}
2444+
2445+unsigned long
2446+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
2447+ const unsigned long len, const unsigned long pgoff,
2448+ const unsigned long flags)
2449+{
2450+ struct vm_area_struct *vma;
2451+ struct mm_struct *mm = current->mm;
2452+ unsigned long base = mm->mmap_base, addr = addr0, task_size = TASK_SIZE;
2453+
2454+#ifdef CONFIG_PAX_SEGMEXEC
2455+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
2456+ task_size = SEGMEXEC_TASK_SIZE;
2457+#endif
2458+
2459+ /* requested length too big for entire address space */
2460+ if (len > task_size)
2461+ return -ENOMEM;
2462+
2463+#ifdef CONFIG_PAX_PAGEEXEC
2464+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE))
2465+ goto bottomup;
2466+#endif
2467+
2468+#ifdef CONFIG_PAX_RANDMMAP
2469+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
2470+#endif
2471+
2472+ /* requesting a specific address */
2473+ if (addr) {
2474+ addr = PAGE_ALIGN(addr);
2475+ vma = find_vma(mm, addr);
2476+ if (task_size - len >= addr &&
2477+ (!vma || addr + len <= vma->vm_start))
2478+ return addr;
2479+ }
2480+
2481+ /* check if free_area_cache is useful for us */
2482+ if (len <= mm->cached_hole_size) {
2483+ mm->cached_hole_size = 0;
2484+ mm->free_area_cache = mm->mmap_base;
2485+ }
2486+
2487+ /* either no address requested or can't fit in requested address hole */
2488+ addr = mm->free_area_cache;
2489+
2490+ /* make sure it can fit in the remaining address space */
2491+ if (addr > len) {
2492+ vma = find_vma(mm, addr-len);
2493+ if (!vma || addr <= vma->vm_start)
2494+ /* remember the address as a hint for next time */
2495+ return (mm->free_area_cache = addr-len);
2496+ }
2497+
2498+ if (mm->mmap_base < len)
2499+ goto bottomup;
2500+
2501+ addr = mm->mmap_base-len;
2502+
2503+ do {
2504+ /*
2505+ * Lookup failure means no vma is above this address,
2506+ * else if new region fits below vma->vm_start,
2507+ * return with success:
2508+ */
2509+ vma = find_vma(mm, addr);
2510+ if (!vma || addr+len <= vma->vm_start)
2511+ /* remember the address as a hint for next time */
2512+ return (mm->free_area_cache = addr);
2513+
2514+ /* remember the largest hole we saw so far */
2515+ if (addr + mm->cached_hole_size < vma->vm_start)
2516+ mm->cached_hole_size = vma->vm_start - addr;
2517+
2518+ /* try just below the current vma->vm_start */
2519+ addr = vma->vm_start-len;
2520+ } while (len < vma->vm_start);
2521+
2522+bottomup:
2523+ /*
2524+ * A failed mmap() very likely causes application failure,
2525+ * so fall back to the bottom-up function here. This scenario
2526+ * can happen with large stack limits and large mmap()
2527+ * allocations.
2528+ */
2529+ mm->mmap_base = TASK_UNMAPPED_BASE;
2530+
2531+#ifdef CONFIG_PAX_RANDMMAP
2532+ if (mm->pax_flags & MF_PAX_RANDMMAP)
2533+ mm->mmap_base += mm->delta_mmap;
2534+#endif
2535+
2536+ mm->free_area_cache = mm->mmap_base;
2537+ mm->cached_hole_size = ~0UL;
2538+ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
2539+ /*
2540+ * Restore the topdown base:
2541+ */
2542+ mm->mmap_base = base;
2543+ mm->free_area_cache = base;
2544+ mm->cached_hole_size = ~0UL;
2545+
2546+ return addr;
2547+}
2548
2549 struct sel_arg_struct {
2550 unsigned long n;
2551diff -urNp linux-2.6.17.11/arch/i386/kernel/traps.c linux-2.6.17.11/arch/i386/kernel/traps.c
2552--- linux-2.6.17.11/arch/i386/kernel/traps.c 2006-08-07 00:18:54.000000000 -0400
2553+++ linux-2.6.17.11/arch/i386/kernel/traps.c 2006-08-12 08:17:55.000000000 -0400
2554@@ -28,6 +28,7 @@
2555 #include <linux/utsname.h>
2556 #include <linux/kprobes.h>
2557 #include <linux/kexec.h>
2558+#include <linux/binfmts.h>
2559
2560 #ifdef CONFIG_EISA
2561 #include <linux/ioport.h>
2562@@ -58,18 +59,13 @@
2563
2564 asmlinkage int system_call(void);
2565
2566-struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
2567+const struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
2568 { 0, 0 }, { 0, 0 } };
2569
2570 /* Do we ignore FPU interrupts ? */
2571 char ignore_fpu_irq = 0;
2572
2573-/*
2574- * The IDT has to be page-aligned to simplify the Pentium
2575- * F0 0F bug workaround.. We have a special link segment
2576- * for this.
2577- */
2578-struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
2579+extern struct desc_struct idt_table[256];
2580
2581 asmlinkage void divide_error(void);
2582 asmlinkage void debug(void);
2583@@ -144,18 +140,22 @@ static inline unsigned long print_contex
2584 {
2585 unsigned long addr;
2586 int printed = 0; /* nr of entries already printed on current line */
2587+ int i = kstack_depth_to_print;
2588
2589 #ifdef CONFIG_FRAME_POINTER
2590 while (valid_stack_ptr(tinfo, (void *)ebp)) {
2591 addr = *(unsigned long *)(ebp + 4);
2592 printed = print_addr_and_symbol(addr, log_lvl, printed);
2593 ebp = *(unsigned long *)ebp;
2594+ --i;
2595 }
2596 #else
2597 while (valid_stack_ptr(tinfo, stack)) {
2598 addr = *stack++;
2599- if (__kernel_text_address(addr))
2600+ if (__kernel_text_address(addr + __KERNEL_TEXT_OFFSET)) {
2601 printed = print_addr_and_symbol(addr, log_lvl, printed);
2602+ --i;
2603+ }
2604 }
2605 #endif
2606 if (printed)
2607@@ -249,7 +249,7 @@ void show_registers(struct pt_regs *regs
2608
2609 esp = (unsigned long) (&regs->esp);
2610 savesegment(ss, ss);
2611- if (user_mode_vm(regs)) {
2612+ if (user_mode(regs)) {
2613 in_kernel = 0;
2614 esp = regs->esp;
2615 ss = regs->xss & 0xffff;
2616@@ -276,13 +276,15 @@ void show_registers(struct pt_regs *regs
2617 */
2618 if (in_kernel) {
2619 u8 __user *eip;
2620+ mm_segment_t old_fs = get_fs();
2621
2622 printk("\n" KERN_EMERG "Stack: ");
2623 show_stack_log_lvl(NULL, (unsigned long *)esp, KERN_EMERG);
2624
2625 printk(KERN_EMERG "Code: ");
2626
2627- eip = (u8 __user *)regs->eip - 43;
2628+ set_fs(KERNEL_DS);
2629+ eip = (u8 __user *)regs->eip - 43 + __KERNEL_TEXT_OFFSET;
2630 for (i = 0; i < 64; i++, eip++) {
2631 unsigned char c;
2632
2633@@ -290,11 +292,12 @@ void show_registers(struct pt_regs *regs
2634 printk(" Bad EIP value.");
2635 break;
2636 }
2637- if (eip == (u8 __user *)regs->eip)
2638+ if (eip == (u8 __user *)regs->eip + __KERNEL_TEXT_OFFSET)
2639 printk("<%02x> ", c);
2640 else
2641 printk("%02x ", c);
2642 }
2643+ set_fs(old_fs);
2644 }
2645 printk("\n");
2646 }
2647@@ -306,29 +309,34 @@ static void handle_BUG(struct pt_regs *r
2648 char *file;
2649 char c;
2650 unsigned long eip;
2651+ mm_segment_t old_fs = get_fs();
2652
2653- eip = regs->eip;
2654+ eip = regs->eip + __KERNEL_TEXT_OFFSET;
2655
2656+ set_fs(KERNEL_DS);
2657 if (eip < PAGE_OFFSET)
2658 goto no_bug;
2659 if (__get_user(ud2, (unsigned short __user *)eip))
2660 goto no_bug;
2661 if (ud2 != 0x0b0f)
2662 goto no_bug;
2663- if (__get_user(line, (unsigned short __user *)(eip + 2)))
2664+ if (__get_user(line, (unsigned short __user *)(eip + 3)))
2665 goto bug;
2666- if (__get_user(file, (char * __user *)(eip + 4)) ||
2667- (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
2668+ if (__get_user(file, (char * __user *)(eip + 8)) || file < _text + __KERNEL_TEXT_OFFSET)
2669+ goto bug;
2670+ if (__get_user(c, file))
2671 file = "<bad filename>";
2672
2673 printk(KERN_EMERG "------------[ cut here ]------------\n");
2674 printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
2675
2676 no_bug:
2677+ set_fs(old_fs);
2678 return;
2679
2680 /* Here we know it was a BUG but file-n-line is unavailable */
2681 bug:
2682+ set_fs(old_fs);
2683 printk(KERN_EMERG "Kernel BUG\n");
2684 }
2685
2686@@ -430,7 +438,7 @@ void die(const char * str, struct pt_reg
2687
2688 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
2689 {
2690- if (!user_mode_vm(regs))
2691+ if (!user_mode(regs))
2692 die(str, regs, err);
2693 }
2694
2695@@ -448,7 +456,7 @@ static void __kprobes do_trap(int trapnr
2696 goto trap_signal;
2697 }
2698
2699- if (!user_mode(regs))
2700+ if (!user_mode_novm(regs))
2701 goto kernel_trap;
2702
2703 trap_signal: {
2704@@ -536,7 +544,7 @@ fastcall void __kprobes do_general_prote
2705 long error_code)
2706 {
2707 int cpu = get_cpu();
2708- struct tss_struct *tss = &per_cpu(init_tss, cpu);
2709+ struct tss_struct *tss = &init_tss[cpu];
2710 struct thread_struct *thread = &current->thread;
2711
2712 /*
2713@@ -572,9 +580,25 @@ fastcall void __kprobes do_general_prote
2714 if (regs->eflags & VM_MASK)
2715 goto gp_in_vm86;
2716
2717- if (!user_mode(regs))
2718+ if (!user_mode_novm(regs))
2719 goto gp_in_kernel;
2720
2721+#ifdef CONFIG_PAX_PAGEEXEC
2722+ if (current->mm && (current->mm->pax_flags & MF_PAX_PAGEEXEC)) {
2723+ struct mm_struct *mm = current->mm;
2724+ unsigned long limit;
2725+
2726+ down_write(&mm->mmap_sem);
2727+ limit = mm->context.user_cs_limit;
2728+ if (limit < TASK_SIZE) {
2729+ track_exec_limit(mm, limit, TASK_SIZE, PROT_EXEC);
2730+ up_write(&mm->mmap_sem);
2731+ return;
2732+ }
2733+ up_write(&mm->mmap_sem);
2734+ }
2735+#endif
2736+
2737 current->thread.error_code = error_code;
2738 current->thread.trap_no = 13;
2739 force_sig(SIGSEGV, current);
2740@@ -590,6 +614,13 @@ gp_in_kernel:
2741 if (notify_die(DIE_GPF, "general protection fault", regs,
2742 error_code, 13, SIGSEGV) == NOTIFY_STOP)
2743 return;
2744+
2745+#ifdef CONFIG_PAX_KERNEXEC
2746+ if ((regs->xcs & 0xFFFF) == __KERNEL_CS)
2747+ die("PAX: suspicious general protection fault", regs, error_code);
2748+ else
2749+#endif
2750+
2751 die("general protection fault", regs, error_code);
2752 }
2753 }
2754@@ -663,7 +694,7 @@ void die_nmi (struct pt_regs *regs, cons
2755 /* If we are in kernel we are probably nested up pretty bad
2756 * and might aswell get out now while we still can.
2757 */
2758- if (!user_mode_vm(regs)) {
2759+ if (!user_mode(regs)) {
2760 current->thread.trap_no = 2;
2761 crash_kexec(regs);
2762 }
2763@@ -816,7 +847,7 @@ fastcall void __kprobes do_debug(struct
2764 * check for kernel mode by just checking the CPL
2765 * of CS.
2766 */
2767- if (!user_mode(regs))
2768+ if (!user_mode_novm(regs))
2769 goto clear_TF_reenable;
2770 }
2771
2772@@ -1106,7 +1137,19 @@ do { \
2773 */
2774 void set_intr_gate(unsigned int n, void *addr)
2775 {
2776+
2777+#ifdef CONFIG_PAX_KERNEXEC
2778+ unsigned long cr0;
2779+
2780+ pax_open_kernel(cr0);
2781+#endif
2782+
2783 _set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
2784+
2785+#ifdef CONFIG_PAX_KERNEXEC
2786+ pax_close_kernel(cr0);
2787+#endif
2788+
2789 }
2790
2791 /*
2792diff -urNp linux-2.6.17.11/arch/i386/kernel/vm86.c linux-2.6.17.11/arch/i386/kernel/vm86.c
2793--- linux-2.6.17.11/arch/i386/kernel/vm86.c 2006-08-07 00:18:54.000000000 -0400
2794+++ linux-2.6.17.11/arch/i386/kernel/vm86.c 2006-08-12 08:17:55.000000000 -0400
2795@@ -123,7 +123,7 @@ struct pt_regs * fastcall save_v86_state
2796 do_exit(SIGSEGV);
2797 }
2798
2799- tss = &per_cpu(init_tss, get_cpu());
2800+ tss = init_tss + get_cpu();
2801 current->thread.esp0 = current->thread.saved_esp0;
2802 current->thread.sysenter_cs = __KERNEL_CS;
2803 load_esp0(tss, &current->thread);
2804@@ -297,7 +297,7 @@ static void do_sys_vm86(struct kernel_vm
2805 savesegment(fs, tsk->thread.saved_fs);
2806 savesegment(gs, tsk->thread.saved_gs);
2807
2808- tss = &per_cpu(init_tss, get_cpu());
2809+ tss = init_tss + get_cpu();
2810 tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
2811 if (cpu_has_sep)
2812 tsk->thread.sysenter_cs = 0;
2813diff -urNp linux-2.6.17.11/arch/i386/kernel/vmlinux.lds.S linux-2.6.17.11/arch/i386/kernel/vmlinux.lds.S
2814--- linux-2.6.17.11/arch/i386/kernel/vmlinux.lds.S 2006-08-07 00:18:54.000000000 -0400
2815+++ linux-2.6.17.11/arch/i386/kernel/vmlinux.lds.S 2006-08-12 08:17:55.000000000 -0400
2816@@ -4,10 +4,19 @@
2817
2818 #define LOAD_OFFSET __PAGE_OFFSET
2819
2820+#include <linux/config.h>
2821+
2822 #include <asm-generic/vmlinux.lds.h>
2823 #include <asm/thread_info.h>
2824 #include <asm/page.h>
2825 #include <asm/cache.h>
2826+#include <asm/segment.h>
2827+
2828+#ifdef CONFIG_X86_PAE
2829+#define PMD_SHIFT 21
2830+#else
2831+#define PMD_SHIFT 22
2832+#endif
2833
2834 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
2835 OUTPUT_ARCH(i386)
2836@@ -16,59 +25,14 @@ jiffies = jiffies_64;
2837 SECTIONS
2838 {
2839 . = __KERNEL_START;
2840- phys_startup_32 = startup_32 - LOAD_OFFSET;
2841- /* read-only */
2842- _text = .; /* Text and read-only data */
2843- .text : AT(ADDR(.text) - LOAD_OFFSET) {
2844- *(.text)
2845- SCHED_TEXT
2846- LOCK_TEXT
2847- KPROBES_TEXT
2848- *(.fixup)
2849- *(.gnu.warning)
2850- } = 0x9090
2851-
2852- _etext = .; /* End of text section */
2853-
2854- . = ALIGN(16); /* Exception table */
2855- __start___ex_table = .;
2856- __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
2857- __stop___ex_table = .;
2858-
2859- RODATA
2860+ phys_startup_32 = startup_32 - LOAD_OFFSET + __KERNEL_TEXT_OFFSET;
2861
2862- /* writeable */
2863- .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
2864- *(.data)
2865- CONSTRUCTORS
2866+ .text.startup : AT(ADDR(.text.startup) - LOAD_OFFSET) {
2867+ BYTE(0xEA) /* jmp far */
2868+ LONG(phys_startup_32)
2869+ SHORT(__BOOT_CS)
2870 }
2871
2872- . = ALIGN(4096);
2873- __nosave_begin = .;
2874- .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
2875- . = ALIGN(4096);
2876- __nosave_end = .;
2877-
2878- . = ALIGN(4096);
2879- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
2880- *(.data.idt)
2881- }
2882-
2883- . = ALIGN(32);
2884- .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
2885- *(.data.cacheline_aligned)
2886- }
2887-
2888- /* rarely changed data like cpu maps */
2889- . = ALIGN(32);
2890- .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
2891- _edata = .; /* End of data section */
2892-
2893- . = ALIGN(THREAD_SIZE); /* init_task */
2894- .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
2895- *(.data.init_task)
2896- }
2897-
2898 /* might get freed after init */
2899 . = ALIGN(4096);
2900 __smp_alt_begin = .;
2901@@ -92,11 +56,6 @@ SECTIONS
2902 /* will be freed after init */
2903 . = ALIGN(4096); /* Init code and data */
2904 __init_begin = .;
2905- .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
2906- _sinittext = .;
2907- *(.init.text)
2908- _einittext = .;
2909- }
2910 .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
2911 . = ALIGN(16);
2912 __setup_start = .;
2913@@ -128,9 +87,7 @@ SECTIONS
2914 .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
2915 *(.altinstr_replacement)
2916 }
2917- /* .exit.text is discard at runtime, not link time, to deal with references
2918- from .altinstructions and .eh_frame */
2919- .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
2920+
2921 .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
2922 . = ALIGN(4096);
2923 __initramfs_start = .;
2924@@ -140,10 +97,108 @@ SECTIONS
2925 __per_cpu_start = .;
2926 .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
2927 __per_cpu_end = .;
2928+
2929+ /* read-only */
2930+
2931 . = ALIGN(4096);
2932- __init_end = .;
2933+ .init.text (. - __KERNEL_TEXT_OFFSET) : AT(ADDR(.init.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
2934+ _sinittext = .;
2935+ *(.init.text)
2936+ _einittext = .;
2937+ }
2938+
2939+ /* .exit.text is discard at runtime, not link time, to deal with references
2940+ from .altinstructions and .eh_frame */
2941+ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { *(.exit.text) }
2942+
2943+#ifdef CONFIG_PAX_KERNEXEC
2944+ .text.align : AT(ADDR(.text.align) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
2945+ . = ALIGN(__KERNEL_TEXT_OFFSET - LOAD_OFFSET) - 1;
2946+ BYTE(0)
2947+ }
2948+#else
2949+ . = ALIGN(4096);
2950+#endif
2951+
2952+ __init_end = . + __KERNEL_TEXT_OFFSET;
2953 /* freed after init ends here */
2954-
2955+
2956+ _text = .; /* Text and read-only data */
2957+ .text : AT(ADDR(.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
2958+ *(.text)
2959+ SCHED_TEXT
2960+ LOCK_TEXT
2961+ KPROBES_TEXT
2962+ *(.fixup)
2963+ *(.gnu.warning)
2964+ } = 0x9090
2965+
2966+ _etext = .; /* End of text section */
2967+ . += __KERNEL_TEXT_OFFSET;
2968+ . = ALIGN(16); /* Exception table */
2969+ __start___ex_table = .;
2970+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
2971+ __stop___ex_table = .;
2972+
2973+ . = ALIGN(4096);
2974+ .rodata.page_aligned : AT(ADDR(.rodata.page_aligned) - LOAD_OFFSET) {
2975+ *(.empty_zero_page)
2976+
2977+#ifdef CONFIG_X86_PAE
2978+ *(.swapper_pm_dir)
2979+#endif
2980+
2981+ *(.swapper_pg_dir)
2982+ *(.idt)
2983+ }
2984+
2985+ RODATA
2986+
2987+#ifdef CONFIG_PAX_KERNEXEC
2988+ . = ALIGN(4096);
2989+ MODULES_VADDR = .;
2990+
2991+ .module.text : AT(ADDR(.module.text) - LOAD_OFFSET) {
2992+ . += (4 * 1024 * 1024);
2993+ . = ALIGN(1 << PMD_SHIFT) - 1;
2994+ BYTE(0)
2995+ }
2996+
2997+ MODULES_END = .;
2998+#else
2999+ . = ALIGN(32);
3000+#endif
3001+
3002+ /* writeable */
3003+ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
3004+ _data = .;
3005+ *(.data)
3006+ CONSTRUCTORS
3007+ }
3008+
3009+ . = ALIGN(4096);
3010+ __nosave_begin = .;
3011+ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
3012+ . = ALIGN(4096);
3013+ __nosave_end = .;
3014+
3015+ . = ALIGN(32);
3016+ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
3017+ *(.data.cacheline_aligned)
3018+ }
3019+
3020+ /* rarely changed data like cpu maps */
3021+ . = ALIGN(32);
3022+ .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
3023+
3024+ . = ALIGN(THREAD_SIZE); /* init_task */
3025+ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
3026+ *(.data.init_task)
3027+ }
3028+
3029+ _edata = .; /* End of data section */
3030+
3031+ . = ALIGN(4096);
3032 __bss_start = .; /* BSS */
3033 .bss.page_aligned : AT(ADDR(.bss.page_aligned) - LOAD_OFFSET) {
3034 *(.bss.page_aligned)
3035diff -urNp linux-2.6.17.11/arch/i386/lib/checksum.S linux-2.6.17.11/arch/i386/lib/checksum.S
3036--- linux-2.6.17.11/arch/i386/lib/checksum.S 2006-08-07 00:18:54.000000000 -0400
3037+++ linux-2.6.17.11/arch/i386/lib/checksum.S 2006-08-12 08:17:55.000000000 -0400
3038@@ -27,7 +27,8 @@
3039
3040 #include <linux/config.h>
3041 #include <asm/errno.h>
3042-
3043+#include <asm/segment.h>
3044+
3045 /*
3046 * computes a partial checksum, e.g. for TCP/UDP fragments
3047 */
3048@@ -281,12 +282,23 @@ unsigned int csum_partial_copy_generic (
3049
3050 .align 4
3051 .globl csum_partial_copy_generic
3052-
3053+.globl csum_partial_copy_generic_to_user
3054+.globl csum_partial_copy_generic_from_user
3055+
3056 #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
3057
3058 #define ARGBASE 16
3059 #define FP 12
3060-
3061+
3062+csum_partial_copy_generic_to_user:
3063+ pushl $(__USER_DS)
3064+ popl %es
3065+ jmp csum_partial_copy_generic
3066+
3067+csum_partial_copy_generic_from_user:
3068+ pushl $(__USER_DS)
3069+ popl %ds
3070+
3071 csum_partial_copy_generic:
3072 subl $4,%esp
3073 pushl %edi
3074@@ -305,7 +317,7 @@ csum_partial_copy_generic:
3075 jmp 4f
3076 SRC(1: movw (%esi), %bx )
3077 addl $2, %esi
3078-DST( movw %bx, (%edi) )
3079+DST( movw %bx, %es:(%edi) )
3080 addl $2, %edi
3081 addw %bx, %ax
3082 adcl $0, %eax
3083@@ -317,30 +329,30 @@ DST( movw %bx, (%edi) )
3084 SRC(1: movl (%esi), %ebx )
3085 SRC( movl 4(%esi), %edx )
3086 adcl %ebx, %eax
3087-DST( movl %ebx, (%edi) )
3088+DST( movl %ebx, %es:(%edi) )
3089 adcl %edx, %eax
3090-DST( movl %edx, 4(%edi) )
3091+DST( movl %edx, %es:4(%edi) )
3092
3093 SRC( movl 8(%esi), %ebx )
3094 SRC( movl 12(%esi), %edx )
3095 adcl %ebx, %eax
3096-DST( movl %ebx, 8(%edi) )
3097+DST( movl %ebx, %es:8(%edi) )
3098 adcl %edx, %eax
3099-DST( movl %edx, 12(%edi) )
3100+DST( movl %edx, %es:12(%edi) )
3101
3102 SRC( movl 16(%esi), %ebx )
3103 SRC( movl 20(%esi), %edx )
3104 adcl %ebx, %eax
3105-DST( movl %ebx, 16(%edi) )
3106+DST( movl %ebx, %es:16(%edi) )
3107 adcl %edx, %eax
3108-DST( movl %edx, 20(%edi) )
3109+DST( movl %edx, %es:20(%edi) )
3110
3111 SRC( movl 24(%esi), %ebx )
3112 SRC( movl 28(%esi), %edx )
3113 adcl %ebx, %eax
3114-DST( movl %ebx, 24(%edi) )
3115+DST( movl %ebx, %es:24(%edi) )
3116 adcl %edx, %eax
3117-DST( movl %edx, 28(%edi) )
3118+DST( movl %edx, %es:28(%edi) )
3119
3120 lea 32(%esi), %esi
3121 lea 32(%edi), %edi
3122@@ -354,7 +366,7 @@ DST( movl %edx, 28(%edi) )
3123 shrl $2, %edx # This clears CF
3124 SRC(3: movl (%esi), %ebx )
3125 adcl %ebx, %eax
3126-DST( movl %ebx, (%edi) )
3127+DST( movl %ebx, %es:(%edi) )
3128 lea 4(%esi), %esi
3129 lea 4(%edi), %edi
3130 dec %edx
3131@@ -366,12 +378,12 @@ DST( movl %ebx, (%edi) )
3132 jb 5f
3133 SRC( movw (%esi), %cx )
3134 leal 2(%esi), %esi
3135-DST( movw %cx, (%edi) )
3136+DST( movw %cx, %es:(%edi) )
3137 leal 2(%edi), %edi
3138 je 6f
3139 shll $16,%ecx
3140 SRC(5: movb (%esi), %cl )
3141-DST( movb %cl, (%edi) )
3142+DST( movb %cl, %es:(%edi) )
3143 6: addl %ecx, %eax
3144 adcl $0, %eax
3145 7:
3146@@ -382,7 +394,7 @@ DST( movb %cl, (%edi) )
3147
3148 6001:
3149 movl ARGBASE+20(%esp), %ebx # src_err_ptr
3150- movl $-EFAULT, (%ebx)
3151+ movl $-EFAULT, %ss:(%ebx)
3152
3153 # zero the complete destination - computing the rest
3154 # is too much work
3155@@ -395,11 +407,15 @@ DST( movb %cl, (%edi) )
3156
3157 6002:
3158 movl ARGBASE+24(%esp), %ebx # dst_err_ptr
3159- movl $-EFAULT,(%ebx)
3160+ movl $-EFAULT,%ss:(%ebx)
3161 jmp 5000b
3162
3163 .previous
3164
3165+ pushl %ss
3166+ popl %ds
3167+ pushl %ss
3168+ popl %es
3169 popl %ebx
3170 popl %esi
3171 popl %edi
3172@@ -411,17 +427,28 @@ DST( movb %cl, (%edi) )
3173 /* Version for PentiumII/PPro */
3174
3175 #define ROUND1(x) \
3176+ nop; nop; nop; \
3177 SRC(movl x(%esi), %ebx ) ; \
3178 addl %ebx, %eax ; \
3179- DST(movl %ebx, x(%edi) ) ;
3180+ DST(movl %ebx, %es:x(%edi));
3181
3182 #define ROUND(x) \
3183+ nop; nop; nop; \
3184 SRC(movl x(%esi), %ebx ) ; \
3185 adcl %ebx, %eax ; \
3186- DST(movl %ebx, x(%edi) ) ;
3187+ DST(movl %ebx, %es:x(%edi));
3188
3189 #define ARGBASE 12
3190-
3191+
3192+csum_partial_copy_generic_to_user:
3193+ pushl $(__USER_DS)
3194+ popl %es
3195+ jmp csum_partial_copy_generic
3196+
3197+csum_partial_copy_generic_from_user:
3198+ pushl $(__USER_DS)
3199+ popl %ds
3200+
3201 csum_partial_copy_generic:
3202 pushl %ebx
3203 pushl %edi
3204@@ -440,7 +467,7 @@ csum_partial_copy_generic:
3205 subl %ebx, %edi
3206 lea -1(%esi),%edx
3207 andl $-32,%edx
3208- lea 3f(%ebx,%ebx), %ebx
3209+ lea 3f(%ebx,%ebx,2), %ebx
3210 testl %esi, %esi
3211 jmp *%ebx
3212 1: addl $64,%esi
3213@@ -461,19 +488,19 @@ csum_partial_copy_generic:
3214 jb 5f
3215 SRC( movw (%esi), %dx )
3216 leal 2(%esi), %esi
3217-DST( movw %dx, (%edi) )
3218+DST( movw %dx, %es:(%edi) )
3219 leal 2(%edi), %edi
3220 je 6f
3221 shll $16,%edx
3222 5:
3223 SRC( movb (%esi), %dl )
3224-DST( movb %dl, (%edi) )
3225+DST( movb %dl, %es:(%edi) )
3226 6: addl %edx, %eax
3227 adcl $0, %eax
3228 7:
3229 .section .fixup, "ax"
3230 6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr
3231- movl $-EFAULT, (%ebx)
3232+ movl $-EFAULT, %ss:(%ebx)
3233 # zero the complete destination (computing the rest is too much work)
3234 movl ARGBASE+8(%esp),%edi # dst
3235 movl ARGBASE+12(%esp),%ecx # len
3236@@ -481,10 +508,14 @@ DST( movb %dl, (%edi) )
3237 rep; stosb
3238 jmp 7b
3239 6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr
3240- movl $-EFAULT, (%ebx)
3241+ movl $-EFAULT, %ss:(%ebx)
3242 jmp 7b
3243 .previous
3244
3245+ pushl %ss
3246+ popl %ds
3247+ pushl %ss
3248+ popl %es
3249 popl %esi
3250 popl %edi
3251 popl %ebx
3252diff -urNp linux-2.6.17.11/arch/i386/lib/getuser.S linux-2.6.17.11/arch/i386/lib/getuser.S
3253--- linux-2.6.17.11/arch/i386/lib/getuser.S 2006-08-07 00:18:54.000000000 -0400
3254+++ linux-2.6.17.11/arch/i386/lib/getuser.S 2006-08-12 08:17:55.000000000 -0400
3255@@ -9,6 +9,7 @@
3256 * return value.
3257 */
3258 #include <asm/thread_info.h>
3259+#include <asm/segment.h>
3260
3261
3262 /*
3263@@ -30,8 +31,12 @@ __get_user_1:
3264 GET_THREAD_INFO(%edx)
3265 cmpl TI_addr_limit(%edx),%eax
3266 jae bad_get_user
3267+ pushl $(__USER_DS)
3268+ popl %ds
3269 1: movzbl (%eax),%edx
3270 xorl %eax,%eax
3271+ pushl %ss
3272+ pop %ds
3273 ret
3274
3275 .align 4
3276@@ -42,7 +47,11 @@ __get_user_2:
3277 GET_THREAD_INFO(%edx)
3278 cmpl TI_addr_limit(%edx),%eax
3279 jae bad_get_user
3280+ pushl $(__USER_DS)
3281+ popl %ds
3282 2: movzwl -1(%eax),%edx
3283+ pushl %ss
3284+ pop %ds
3285 xorl %eax,%eax
3286 ret
3287
3288@@ -54,11 +63,17 @@ __get_user_4:
3289 GET_THREAD_INFO(%edx)
3290 cmpl TI_addr_limit(%edx),%eax
3291 jae bad_get_user
3292+ pushl $(__USER_DS)
3293+ popl %ds
3294 3: movl -3(%eax),%edx
3295+ pushl %ss
3296+ pop %ds
3297 xorl %eax,%eax
3298 ret
3299
3300 bad_get_user:
3301+ pushl %ss
3302+ pop %ds
3303 xorl %edx,%edx
3304 movl $-14,%eax
3305 ret
3306diff -urNp linux-2.6.17.11/arch/i386/lib/mmx.c linux-2.6.17.11/arch/i386/lib/mmx.c
3307--- linux-2.6.17.11/arch/i386/lib/mmx.c 2006-08-07 00:18:54.000000000 -0400
3308+++ linux-2.6.17.11/arch/i386/lib/mmx.c 2006-08-12 08:17:55.000000000 -0400
3309@@ -48,14 +48,30 @@ void *_mmx_memcpy(void *to, const void *
3310 " prefetch 256(%0)\n"
3311 "2: \n"
3312 ".section .fixup, \"ax\"\n"
3313- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3314+ "3: \n"
3315+
3316+#ifdef CONFIG_PAX_KERNEXEC
3317+ " cli\n"
3318+ " movl %%cr0, %%eax\n"
3319+ " andl $0xFFFEFFFF, %%eax\n"
3320+ " movl %%eax, %%cr0\n"
3321+#endif
3322+
3323+ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3324+
3325+#ifdef CONFIG_PAX_KERNEXEC
3326+ " orl $0x00010000, %%eax\n"
3327+ " movl %%eax, %%cr0\n"
3328+ " sti\n"
3329+#endif
3330+
3331 " jmp 2b\n"
3332 ".previous\n"
3333 ".section __ex_table,\"a\"\n"
3334 " .align 4\n"
3335 " .long 1b, 3b\n"
3336 ".previous"
3337- : : "r" (from) );
3338+ : : "r" (from) : "ax");
3339
3340
3341 for(; i>5; i--)
3342@@ -79,14 +95,30 @@ void *_mmx_memcpy(void *to, const void *
3343 " movq %%mm2, 48(%1)\n"
3344 " movq %%mm3, 56(%1)\n"
3345 ".section .fixup, \"ax\"\n"
3346- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3347+ "3:\n"
3348+
3349+#ifdef CONFIG_PAX_KERNEXEC
3350+ " cli\n"
3351+ " movl %%cr0, %%eax\n"
3352+ " andl $0xFFFEFFFF, %%eax\n"
3353+ " movl %%eax, %%cr0\n"
3354+#endif
3355+
3356+ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3357+
3358+#ifdef CONFIG_PAX_KERNEXEC
3359+ " orl $0x00010000, %%eax\n"
3360+ " movl %%eax, %%cr0\n"
3361+ " sti\n"
3362+#endif
3363+
3364 " jmp 2b\n"
3365 ".previous\n"
3366 ".section __ex_table,\"a\"\n"
3367 " .align 4\n"
3368 " .long 1b, 3b\n"
3369 ".previous"
3370- : : "r" (from), "r" (to) : "memory");
3371+ : : "r" (from), "r" (to) : "memory", "ax");
3372 from+=64;
3373 to+=64;
3374 }
3375@@ -179,14 +211,30 @@ static void fast_copy_page(void *to, voi
3376 " prefetch 256(%0)\n"
3377 "2: \n"
3378 ".section .fixup, \"ax\"\n"
3379- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3380+ "3: \n"
3381+
3382+#ifdef CONFIG_PAX_KERNEXEC
3383+ " cli\n"
3384+ " movl %%cr0, %%eax\n"
3385+ " andl $0xFFFEFFFF, %%eax\n"
3386+ " movl %%eax, %%cr0\n"
3387+#endif
3388+
3389+ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3390+
3391+#ifdef CONFIG_PAX_KERNEXEC
3392+ " orl $0x00010000, %%eax\n"
3393+ " movl %%eax, %%cr0\n"
3394+ " sti\n"
3395+#endif
3396+
3397 " jmp 2b\n"
3398 ".previous\n"
3399 ".section __ex_table,\"a\"\n"
3400 " .align 4\n"
3401 " .long 1b, 3b\n"
3402 ".previous"
3403- : : "r" (from) );
3404+ : : "r" (from) : "ax");
3405
3406 for(i=0; i<(4096-320)/64; i++)
3407 {
3408@@ -209,14 +257,30 @@ static void fast_copy_page(void *to, voi
3409 " movq 56(%0), %%mm7\n"
3410 " movntq %%mm7, 56(%1)\n"
3411 ".section .fixup, \"ax\"\n"
3412- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3413+ "3:\n"
3414+
3415+#ifdef CONFIG_PAX_KERNEXEC
3416+ " cli\n"
3417+ " movl %%cr0, %%eax\n"
3418+ " andl $0xFFFEFFFF, %%eax\n"
3419+ " movl %%eax, %%cr0\n"
3420+#endif
3421+
3422+ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3423+
3424+#ifdef CONFIG_PAX_KERNEXEC
3425+ " orl $0x00010000, %%eax\n"
3426+ " movl %%eax, %%cr0\n"
3427+ " sti\n"
3428+#endif
3429+
3430 " jmp 2b\n"
3431 ".previous\n"
3432 ".section __ex_table,\"a\"\n"
3433 " .align 4\n"
3434 " .long 1b, 3b\n"
3435 ".previous"
3436- : : "r" (from), "r" (to) : "memory");
3437+ : : "r" (from), "r" (to) : "memory", "ax");
3438 from+=64;
3439 to+=64;
3440 }
3441@@ -309,14 +373,30 @@ static void fast_copy_page(void *to, voi
3442 " prefetch 256(%0)\n"
3443 "2: \n"
3444 ".section .fixup, \"ax\"\n"
3445- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3446+ "3: \n"
3447+
3448+#ifdef CONFIG_PAX_KERNEXEC
3449+ " cli\n"
3450+ " movl %%cr0, %%eax\n"
3451+ " andl $0xFFFEFFFF, %%eax\n"
3452+ " movl %%eax, %%cr0\n"
3453+#endif
3454+
3455+ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3456+
3457+#ifdef CONFIG_PAX_KERNEXEC
3458+ " orl $0x00010000, %%eax\n"
3459+ " movl %%eax, %%cr0\n"
3460+ " sti\n"
3461+#endif
3462+
3463 " jmp 2b\n"
3464 ".previous\n"
3465 ".section __ex_table,\"a\"\n"
3466 " .align 4\n"
3467 " .long 1b, 3b\n"
3468 ".previous"
3469- : : "r" (from) );
3470+ : : "r" (from) : "ax");
3471
3472 for(i=0; i<4096/64; i++)
3473 {
3474@@ -339,14 +419,30 @@ static void fast_copy_page(void *to, voi
3475 " movq %%mm2, 48(%1)\n"
3476 " movq %%mm3, 56(%1)\n"
3477 ".section .fixup, \"ax\"\n"
3478- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3479+ "3:\n"
3480+
3481+#ifdef CONFIG_PAX_KERNEXEC
3482+ " cli\n"
3483+ " movl %%cr0, %%eax\n"
3484+ " andl $0xFFFEFFFF, %%eax\n"
3485+ " movl %%eax, %%cr0\n"
3486+#endif
3487+
3488+ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3489+
3490+#ifdef CONFIG_PAX_KERNEXEC
3491+ " orl $0x00010000, %%eax\n"
3492+ " movl %%eax, %%cr0\n"
3493+ " sti\n"
3494+#endif
3495+
3496 " jmp 2b\n"
3497 ".previous\n"
3498 ".section __ex_table,\"a\"\n"
3499 " .align 4\n"
3500 " .long 1b, 3b\n"
3501 ".previous"
3502- : : "r" (from), "r" (to) : "memory");
3503+ : : "r" (from), "r" (to) : "memory", "ax");
3504 from+=64;
3505 to+=64;
3506 }
3507diff -urNp linux-2.6.17.11/arch/i386/lib/putuser.S linux-2.6.17.11/arch/i386/lib/putuser.S
3508--- linux-2.6.17.11/arch/i386/lib/putuser.S 2006-08-07 00:18:54.000000000 -0400
3509+++ linux-2.6.17.11/arch/i386/lib/putuser.S 2006-08-12 08:17:55.000000000 -0400
3510@@ -9,6 +9,7 @@
3511 * return value.
3512 */
3513 #include <asm/thread_info.h>
3514+#include <asm/segment.h>
3515
3516
3517 /*
3518@@ -33,7 +34,11 @@ __put_user_1:
3519 ENTER
3520 cmpl TI_addr_limit(%ebx),%ecx
3521 jae bad_put_user
3522+ pushl $(__USER_DS)
3523+ popl %ds
3524 1: movb %al,(%ecx)
3525+ pushl %ss
3526+ popl %ds
3527 xorl %eax,%eax
3528 EXIT
3529
3530@@ -45,7 +50,11 @@ __put_user_2:
3531 subl $1,%ebx
3532 cmpl %ebx,%ecx
3533 jae bad_put_user
3534+ pushl $(__USER_DS)
3535+ popl %ds
3536 2: movw %ax,(%ecx)
3537+ pushl %ss
3538+ popl %ds
3539 xorl %eax,%eax
3540 EXIT
3541
3542@@ -57,7 +66,11 @@ __put_user_4:
3543 subl $3,%ebx
3544 cmpl %ebx,%ecx
3545 jae bad_put_user
3546+ pushl $(__USER_DS)
3547+ popl %ds
3548 3: movl %eax,(%ecx)
3549+ pushl %ss
3550+ popl %ds
3551 xorl %eax,%eax
3552 EXIT
3553
3554@@ -69,12 +82,18 @@ __put_user_8:
3555 subl $7,%ebx
3556 cmpl %ebx,%ecx
3557 jae bad_put_user
3558+ pushl $(__USER_DS)
3559+ popl %ds
3560 4: movl %eax,(%ecx)
3561 5: movl %edx,4(%ecx)
3562+ pushl %ss
3563+ popl %ds
3564 xorl %eax,%eax
3565 EXIT
3566
3567 bad_put_user:
3568+ pushl %ss
3569+ popl %ds
3570 movl $-14,%eax
3571 EXIT
3572
3573diff -urNp linux-2.6.17.11/arch/i386/lib/usercopy.c linux-2.6.17.11/arch/i386/lib/usercopy.c
3574--- linux-2.6.17.11/arch/i386/lib/usercopy.c 2006-08-07 00:18:54.000000000 -0400
3575+++ linux-2.6.17.11/arch/i386/lib/usercopy.c 2006-08-12 08:17:55.000000000 -0400
3576@@ -33,6 +33,7 @@ do { \
3577 int __d0, __d1, __d2; \
3578 might_sleep(); \
3579 __asm__ __volatile__( \
3580+ " movw %w10,%%ds\n" \
3581 " testl %1,%1\n" \
3582 " jz 2f\n" \
3583 "0: lodsb\n" \
3584@@ -43,6 +44,8 @@ do { \
3585 " jnz 0b\n" \
3586 "1: subl %1,%0\n" \
3587 "2:\n" \
3588+ " pushl %%ss\n" \
3589+ " popl %%ds\n" \
3590 ".section .fixup,\"ax\"\n" \
3591 "3: movl %5,%0\n" \
3592 " jmp 2b\n" \
3593@@ -53,7 +56,8 @@ do { \
3594 ".previous" \
3595 : "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \
3596 "=&D" (__d2) \
3597- : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
3598+ : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst),\
3599+ "r"(__USER_DS) \
3600 : "memory"); \
3601 } while (0)
3602
3603@@ -123,10 +127,13 @@ do { \
3604 int __d0; \
3605 might_sleep(); \
3606 __asm__ __volatile__( \
3607+ " movw %w6,%%es\n" \
3608 "0: rep; stosl\n" \
3609 " movl %2,%0\n" \
3610 "1: rep; stosb\n" \
3611 "2:\n" \
3612+ " pushl %%ss\n" \
3613+ " popl %%es\n" \
3614 ".section .fixup,\"ax\"\n" \
3615 "3: lea 0(%2,%0,4),%0\n" \
3616 " jmp 2b\n" \
3617@@ -137,7 +144,8 @@ do { \
3618 " .long 1b,2b\n" \
3619 ".previous" \
3620 : "=&c"(size), "=&D" (__d0) \
3621- : "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0)); \
3622+ : "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0), \
3623+ "r"(__USER_DS)); \
3624 } while (0)
3625
3626 /**
3627@@ -198,14 +206,17 @@ long strnlen_user(const char __user *s,
3628 might_sleep();
3629
3630 __asm__ __volatile__(
3631+ " movw %w8,%%es\n"
3632 " testl %0, %0\n"
3633 " jz 3f\n"
3634- " andl %0,%%ecx\n"
3635+ " movl %0,%%ecx\n"
3636 "0: repne; scasb\n"
3637 " setne %%al\n"
3638 " subl %%ecx,%0\n"
3639 " addl %0,%%eax\n"
3640 "1:\n"
3641+ " pushl %%ss\n"
3642+ " popl %%es\n"
3643 ".section .fixup,\"ax\"\n"
3644 "2: xorl %%eax,%%eax\n"
3645 " jmp 1b\n"
3646@@ -217,7 +228,7 @@ long strnlen_user(const char __user *s,
3647 " .long 0b,2b\n"
3648 ".previous"
3649 :"=r" (n), "=D" (s), "=a" (res), "=c" (tmp)
3650- :"0" (n), "1" (s), "2" (0), "3" (mask)
3651+ :"0" (n), "1" (s), "2" (0), "3" (mask), "r" (__USER_DS)
3652 :"cc");
3653 return res & mask;
3654 }
3655@@ -229,6 +240,7 @@ __copy_user_intel(void __user *to, const
3656 {
3657 int d0, d1;
3658 __asm__ __volatile__(
3659+ " movw %w6, %%es\n"
3660 " .align 2,0x90\n"
3661 "1: movl 32(%4), %%eax\n"
3662 " cmpl $67, %0\n"
3663@@ -237,36 +249,36 @@ __copy_user_intel(void __user *to, const
3664 " .align 2,0x90\n"
3665 "3: movl 0(%4), %%eax\n"
3666 "4: movl 4(%4), %%edx\n"
3667- "5: movl %%eax, 0(%3)\n"
3668- "6: movl %%edx, 4(%3)\n"
3669+ "5: movl %%eax, %%es:0(%3)\n"
3670+ "6: movl %%edx, %%es:4(%3)\n"
3671 "7: movl 8(%4), %%eax\n"
3672 "8: movl 12(%4),%%edx\n"
3673- "9: movl %%eax, 8(%3)\n"
3674- "10: movl %%edx, 12(%3)\n"
3675+ "9: movl %%eax, %%es:8(%3)\n"
3676+ "10: movl %%edx, %%es:12(%3)\n"
3677 "11: movl 16(%4), %%eax\n"
3678 "12: movl 20(%4), %%edx\n"
3679- "13: movl %%eax, 16(%3)\n"
3680- "14: movl %%edx, 20(%3)\n"
3681+ "13: movl %%eax, %%es:16(%3)\n"
3682+ "14: movl %%edx, %%es:20(%3)\n"
3683 "15: movl 24(%4), %%eax\n"
3684 "16: movl 28(%4), %%edx\n"
3685- "17: movl %%eax, 24(%3)\n"
3686- "18: movl %%edx, 28(%3)\n"
3687+ "17: movl %%eax, %%es:24(%3)\n"
3688+ "18: movl %%edx, %%es:28(%3)\n"
3689 "19: movl 32(%4), %%eax\n"
3690 "20: movl 36(%4), %%edx\n"
3691- "21: movl %%eax, 32(%3)\n"
3692- "22: movl %%edx, 36(%3)\n"
3693+ "21: movl %%eax, %%es:32(%3)\n"
3694+ "22: movl %%edx, %%es:36(%3)\n"
3695 "23: movl 40(%4), %%eax\n"
3696 "24: movl 44(%4), %%edx\n"
3697- "25: movl %%eax, 40(%3)\n"
3698- "26: movl %%edx, 44(%3)\n"
3699+ "25: movl %%eax, %%es:40(%3)\n"
3700+ "26: movl %%edx, %%es:44(%3)\n"
3701 "27: movl 48(%4), %%eax\n"
3702 "28: movl 52(%4), %%edx\n"
3703- "29: movl %%eax, 48(%3)\n"
3704- "30: movl %%edx, 52(%3)\n"
3705+ "29: movl %%eax, %%es:48(%3)\n"
3706+ "30: movl %%edx, %%es:52(%3)\n"
3707 "31: movl 56(%4), %%eax\n"
3708 "32: movl 60(%4), %%edx\n"
3709- "33: movl %%eax, 56(%3)\n"
3710- "34: movl %%edx, 60(%3)\n"
3711+ "33: movl %%eax, %%es:56(%3)\n"
3712+ "34: movl %%edx, %%es:60(%3)\n"
3713 " addl $-64, %0\n"
3714 " addl $64, %4\n"
3715 " addl $64, %3\n"
3716@@ -280,6 +292,8 @@ __copy_user_intel(void __user *to, const
3717 "36: movl %%eax, %0\n"
3718 "37: rep; movsb\n"
3719 "100:\n"
3720+ " pushl %%ss\n"
3721+ " popl %%es\n"
3722 ".section .fixup,\"ax\"\n"
3723 "101: lea 0(%%eax,%0,4),%0\n"
3724 " jmp 100b\n"
3725@@ -326,7 +340,7 @@ __copy_user_intel(void __user *to, const
3726 " .long 99b,101b\n"
3727 ".previous"
3728 : "=&c"(size), "=&D" (d0), "=&S" (d1)
3729- : "1"(to), "2"(from), "0"(size)
3730+ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS)
3731 : "eax", "edx", "memory");
3732 return size;
3733 }
3734@@ -336,6 +350,7 @@ __copy_user_zeroing_intel(void *to, cons
3735 {
3736 int d0, d1;
3737 __asm__ __volatile__(
3738+ " movw %w6, %%ds\n"
3739 " .align 2,0x90\n"
3740 "0: movl 32(%4), %%eax\n"
3741 " cmpl $67, %0\n"
3742@@ -344,36 +359,36 @@ __copy_user_zeroing_intel(void *to, cons
3743 " .align 2,0x90\n"
3744 "2: movl 0(%4), %%eax\n"
3745 "21: movl 4(%4), %%edx\n"
3746- " movl %%eax, 0(%3)\n"
3747- " movl %%edx, 4(%3)\n"
3748+ " movl %%eax, %%es:0(%3)\n"
3749+ " movl %%edx, %%es:4(%3)\n"
3750 "3: movl 8(%4), %%eax\n"
3751 "31: movl 12(%4),%%edx\n"
3752- " movl %%eax, 8(%3)\n"
3753- " movl %%edx, 12(%3)\n"
3754+ " movl %%eax, %%es:8(%3)\n"
3755+ " movl %%edx, %%es:12(%3)\n"
3756 "4: movl 16(%4), %%eax\n"
3757 "41: movl 20(%4), %%edx\n"
3758- " movl %%eax, 16(%3)\n"
3759- " movl %%edx, 20(%3)\n"
3760+ " movl %%eax, %%es:16(%3)\n"
3761+ " movl %%edx, %%es:20(%3)\n"
3762 "10: movl 24(%4), %%eax\n"
3763 "51: movl 28(%4), %%edx\n"
3764- " movl %%eax, 24(%3)\n"
3765- " movl %%edx, 28(%3)\n"
3766+ " movl %%eax, %%es:24(%3)\n"
3767+ " movl %%edx, %%es:28(%3)\n"
3768 "11: movl 32(%4), %%eax\n"
3769 "61: movl 36(%4), %%edx\n"
3770- " movl %%eax, 32(%3)\n"
3771- " movl %%edx, 36(%3)\n"
3772+ " movl %%eax, %%es:32(%3)\n"
3773+ " movl %%edx, %%es:36(%3)\n"
3774 "12: movl 40(%4), %%eax\n"
3775 "71: movl 44(%4), %%edx\n"
3776- " movl %%eax, 40(%3)\n"
3777- " movl %%edx, 44(%3)\n"
3778+ " movl %%eax, %%es:40(%3)\n"
3779+ " movl %%edx, %%es:44(%3)\n"
3780 "13: movl 48(%4), %%eax\n"
3781 "81: movl 52(%4), %%edx\n"
3782- " movl %%eax, 48(%3)\n"
3783- " movl %%edx, 52(%3)\n"
3784+ " movl %%eax, %%es:48(%3)\n"
3785+ " movl %%edx, %%es:52(%3)\n"
3786 "14: movl 56(%4), %%eax\n"
3787 "91: movl 60(%4), %%edx\n"
3788- " movl %%eax, 56(%3)\n"
3789- " movl %%edx, 60(%3)\n"
3790+ " movl %%eax, %%es:56(%3)\n"
3791+ " movl %%edx, %%es:60(%3)\n"
3792 " addl $-64, %0\n"
3793 " addl $64, %4\n"
3794 " addl $64, %3\n"
3795@@ -387,6 +402,8 @@ __copy_user_zeroing_intel(void *to, cons
3796 " movl %%eax,%0\n"
3797 "7: rep; movsb\n"
3798 "8:\n"
3799+ " pushl %%ss\n"
3800+ " popl %%ds\n"
3801 ".section .fixup,\"ax\"\n"
3802 "9: lea 0(%%eax,%0,4),%0\n"
3803 "16: pushl %0\n"
3804@@ -421,7 +438,7 @@ __copy_user_zeroing_intel(void *to, cons
3805 " .long 7b,16b\n"
3806 ".previous"
3807 : "=&c"(size), "=&D" (d0), "=&S" (d1)
3808- : "1"(to), "2"(from), "0"(size)
3809+ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS)
3810 : "eax", "edx", "memory");
3811 return size;
3812 }
3813@@ -441,6 +458,7 @@ __copy_user_intel(void __user *to, const
3814 do { \
3815 int __d0, __d1, __d2; \
3816 __asm__ __volatile__( \
3817+ " movw %w8,%%es\n" \
3818 " cmp $7,%0\n" \
3819 " jbe 1f\n" \
3820 " movl %1,%0\n" \
3821@@ -456,6 +474,8 @@ do { \
3822 " movl %3,%0\n" \
3823 "1: rep; movsb\n" \
3824 "2:\n" \
3825+ " pushl %%ss\n" \
3826+ " popl %%es\n" \
3827 ".section .fixup,\"ax\"\n" \
3828 "5: addl %3,%0\n" \
3829 " jmp 2b\n" \
3830@@ -469,7 +489,7 @@ do { \
3831 " .long 1b,2b\n" \
3832 ".previous" \
3833 : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \
3834- : "3"(size), "0"(size), "1"(to), "2"(from) \
3835+ : "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS)\
3836 : "memory"); \
3837 } while (0)
3838
3839@@ -477,6 +497,7 @@ do { \
3840 do { \
3841 int __d0, __d1, __d2; \
3842 __asm__ __volatile__( \
3843+ " movw %w8,%%ds\n" \
3844 " cmp $7,%0\n" \
3845 " jbe 1f\n" \
3846 " movl %1,%0\n" \
3847@@ -492,6 +513,8 @@ do { \
3848 " movl %3,%0\n" \
3849 "1: rep; movsb\n" \
3850 "2:\n" \
3851+ " pushl %%ss\n" \
3852+ " popl %%ds\n" \
3853 ".section .fixup,\"ax\"\n" \
3854 "5: addl %3,%0\n" \
3855 " jmp 6f\n" \
3856@@ -511,7 +534,7 @@ do { \
3857 " .long 1b,6b\n" \
3858 ".previous" \
3859 : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \
3860- : "3"(size), "0"(size), "1"(to), "2"(from) \
3861+ : "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS)\
3862 : "memory"); \
3863 } while (0)
3864
3865@@ -640,3 +663,45 @@ copy_from_user(void *to, const void __us
3866 return n;
3867 }
3868 EXPORT_SYMBOL(copy_from_user);
3869+
3870+#ifdef CONFIG_PAX_MEMORY_UDEREF
3871+void __set_fs(mm_segment_t x, int cpu)
3872+{
3873+ unsigned long limit = x.seg;
3874+
3875+ current_thread_info()->addr_limit = x;
3876+ if (likely(limit)) {
3877+ limit -= 1UL;
3878+ limit >>= 12;
3879+ }
3880+
3881+ get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_DS].a = (limit & 0xFFFFUL);
3882+ get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_DS].b = (limit & 0xF0000UL) | 0xC0F300UL;
3883+}
3884+
3885+void set_fs(mm_segment_t x)
3886+{
3887+ int cpu = get_cpu();
3888+
3889+#ifdef CONFIG_PAX_KERNEXEC
3890+ unsigned long cr0;
3891+
3892+ pax_open_kernel(cr0);
3893+#endif
3894+
3895+ __set_fs(x, cpu);
3896+
3897+#ifdef CONFIG_PAX_KERNEXEC
3898+ pax_close_kernel(cr0);
3899+#endif
3900+
3901+ put_cpu_no_resched();
3902+}
3903+#else
3904+void set_fs(mm_segment_t x)
3905+{
3906+ current_thread_info()->addr_limit = x;
3907+}
3908+#endif
3909+
3910+EXPORT_SYMBOL(set_fs);
3911diff -urNp linux-2.6.17.11/arch/i386/mach-voyager/voyager_smp.c linux-2.6.17.11/arch/i386/mach-voyager/voyager_smp.c
3912--- linux-2.6.17.11/arch/i386/mach-voyager/voyager_smp.c 2006-08-07 00:18:54.000000000 -0400
3913+++ linux-2.6.17.11/arch/i386/mach-voyager/voyager_smp.c 2006-08-12 08:17:55.000000000 -0400
3914@@ -1295,7 +1295,7 @@ smp_local_timer_interrupt(struct pt_regs
3915 per_cpu(prof_counter, cpu);
3916 }
3917
3918- update_process_times(user_mode_vm(regs));
3919+ update_process_times(user_mode(regs));
3920 }
3921
3922 if( ((1<<cpu) & voyager_extended_vic_processors) == 0)
3923diff -urNp linux-2.6.17.11/arch/i386/mm/boot_ioremap.c linux-2.6.17.11/arch/i386/mm/boot_ioremap.c
3924--- linux-2.6.17.11/arch/i386/mm/boot_ioremap.c 2006-08-07 00:18:54.000000000 -0400
3925+++ linux-2.6.17.11/arch/i386/mm/boot_ioremap.c 2006-08-12 08:17:55.000000000 -0400
3926@@ -8,53 +8,37 @@
3927 */
3928
3929
3930-/*
3931- * We need to use the 2-level pagetable functions, but CONFIG_X86_PAE
3932- * keeps that from happenning. If anyone has a better way, I'm listening.
3933- *
3934- * boot_pte_t is defined only if this all works correctly
3935- */
3936-
3937 #include <linux/config.h>
3938-#undef CONFIG_X86_PAE
3939 #include <asm/page.h>
3940 #include <asm/pgtable.h>
3941 #include <asm/tlbflush.h>
3942 #include <linux/init.h>
3943 #include <linux/stddef.h>
3944
3945-/*
3946- * I'm cheating here. It is known that the two boot PTE pages are
3947- * allocated next to each other. I'm pretending that they're just
3948- * one big array.
3949- */
3950-
3951-#define BOOT_PTE_PTRS (PTRS_PER_PTE*2)
3952-#define boot_pte_index(address) \
3953- (((address) >> PAGE_SHIFT) & (BOOT_PTE_PTRS - 1))
3954-
3955-static inline boot_pte_t* boot_vaddr_to_pte(void *address)
3956-{
3957- boot_pte_t* boot_pg = (boot_pte_t*)pg0;
3958- return &boot_pg[boot_pte_index((unsigned long)address)];
3959-}
3960
3961 /*
3962 * This is only for a caller who is clever enough to page-align
3963 * phys_addr and virtual_source, and who also has a preference
3964 * about which virtual address from which to steal ptes
3965 */
3966-static void __boot_ioremap(unsigned long phys_addr, unsigned long nrpages,
3967- void* virtual_source)
3968+static void __init __boot_ioremap(unsigned long phys_addr, unsigned int nrpages,
3969+ char* virtual_source)
3970 {
3971- boot_pte_t* pte;
3972- int i;
3973- char *vaddr = virtual_source;
3974+ pgd_t *pgd;
3975+ pud_t *pud;
3976+ pmd_t *pmd;
3977+ pte_t* pte;
3978+ unsigned int i;
3979+ unsigned long vaddr = (unsigned long)virtual_source;
3980+
3981+ pgd = pgd_offset_k(vaddr);
3982+ pud = pud_offset(pgd, vaddr);
3983+ pmd = pmd_offset(pud, vaddr);
3984+ pte = pte_offset_kernel(pmd, vaddr);
3985
3986- pte = boot_vaddr_to_pte(virtual_source);
3987 for (i=0; i < nrpages; i++, phys_addr += PAGE_SIZE, pte++) {
3988 set_pte(pte, pfn_pte(phys_addr>>PAGE_SHIFT, PAGE_KERNEL));
3989- __flush_tlb_one(&vaddr[i*PAGE_SIZE]);
3990+ __flush_tlb_one(&virtual_source[i*PAGE_SIZE]);
3991 }
3992 }
3993
3994diff -urNp linux-2.6.17.11/arch/i386/mm/extable.c linux-2.6.17.11/arch/i386/mm/extable.c
3995--- linux-2.6.17.11/arch/i386/mm/extable.c 2006-08-07 00:18:54.000000000 -0400
3996+++ linux-2.6.17.11/arch/i386/mm/extable.c 2006-08-12 08:17:55.000000000 -0400
3997@@ -12,7 +12,7 @@ int fixup_exception(struct pt_regs *regs
3998 const struct exception_table_entry *fixup;
3999
4000 #ifdef CONFIG_PNPBIOS
4001- if (unlikely((regs->xcs & ~15) == (GDT_ENTRY_PNPBIOS_BASE << 3)))
4002+ if (unlikely(!(regs->eflags & VM_MASK) && ((regs->xcs & 0xFFFCU) == PNP_CS32 || (regs->xcs & 0xFFFCU) == PNP_CS16)))
4003 {
4004 extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
4005 extern u32 pnp_bios_is_utter_crap;
4006diff -urNp linux-2.6.17.11/arch/i386/mm/fault.c linux-2.6.17.11/arch/i386/mm/fault.c
4007--- linux-2.6.17.11/arch/i386/mm/fault.c 2006-08-07 00:18:54.000000000 -0400
4008+++ linux-2.6.17.11/arch/i386/mm/fault.c 2006-08-12 08:17:55.000000000 -0400
4009@@ -22,6 +22,9 @@
4010 #include <linux/highmem.h>
4011 #include <linux/module.h>
4012 #include <linux/kprobes.h>
4013+#include <linux/unistd.h>
4014+#include <linux/compiler.h>
4015+#include <linux/binfmts.h>
4016
4017 #include <asm/system.h>
4018 #include <asm/uaccess.h>
4019@@ -82,11 +85,13 @@ static inline unsigned long get_segment_
4020
4021 /* Unlikely, but must come before segment checks. */
4022 if (unlikely((regs->eflags & VM_MASK) != 0))
4023- return eip + (seg << 4);
4024+ return (eip & 0xFFFF) + (seg << 4);
4025
4026 /* By far the most common cases. */
4027- if (likely(seg == __USER_CS || seg == __KERNEL_CS))
4028+ if (likely(seg == __USER_CS))
4029 return eip;
4030+ if (likely(seg == __KERNEL_CS))
4031+ return eip + __KERNEL_TEXT_OFFSET;
4032
4033 /* Check the segment exists, is within the current LDT/GDT size,
4034 that kernel/user (ring 0..3) has the appropriate privilege,
4035@@ -214,6 +219,30 @@ static noinline void force_sig_info_faul
4036
4037 fastcall void do_invalid_op(struct pt_regs *, unsigned long);
4038
4039+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
4040+static int pax_handle_fetch_fault(struct pt_regs *regs);
4041+#endif
4042+
4043+#ifdef CONFIG_PAX_PAGEEXEC
4044+static inline pmd_t * pax_get_pmd(struct mm_struct *mm, unsigned long address)
4045+{
4046+ pgd_t *pgd;
4047+ pud_t *pud;
4048+ pmd_t *pmd;
4049+
4050+ pgd = pgd_offset(mm, address);
4051+ if (!pgd_present(*pgd))
4052+ return NULL;
4053+ pud = pud_offset(pgd, address);
4054+ if (!pud_present(*pud))
4055+ return NULL;
4056+ pmd = pmd_offset(pud, address);
4057+ if (!pmd_present(*pmd))
4058+ return NULL;
4059+ return pmd;
4060+}
4061+#endif
4062+
4063 static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
4064 {
4065 unsigned index = pgd_index(address);
4066@@ -295,13 +324,20 @@ fastcall void __kprobes do_page_fault(st
4067 struct mm_struct *mm;
4068 struct vm_area_struct * vma;
4069 unsigned long address;
4070- unsigned long page;
4071 int write, si_code;
4072
4073+#ifdef CONFIG_PAX_PAGEEXEC
4074+ pmd_t *pmd;
4075+ pte_t *pte;
4076+ spinlock_t *ptl;
4077+ unsigned char pte_mask;
4078+#endif
4079+
4080 /* get the address */
4081 address = read_cr2();
4082
4083 tsk = current;
4084+ mm = tsk->mm;
4085
4086 si_code = SEGV_MAPERR;
4087
4088@@ -340,14 +376,12 @@ fastcall void __kprobes do_page_fault(st
4089 if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
4090 local_irq_enable();
4091
4092- mm = tsk->mm;
4093-
4094 /*
4095 * If we're in an interrupt, have no user context or are running in an
4096 * atomic region then we must not take the fault..
4097 */
4098 if (in_atomic() || !mm)
4099- goto bad_area_nosemaphore;
4100+ goto bad_area_nopax;
4101
4102 /* When running in the kernel we expect faults to occur only to
4103 * addresses in user space. All other faults represent errors in the
4104@@ -367,10 +401,101 @@ fastcall void __kprobes do_page_fault(st
4105 if (!down_read_trylock(&mm->mmap_sem)) {
4106 if ((error_code & 4) == 0 &&
4107 !search_exception_tables(regs->eip))
4108- goto bad_area_nosemaphore;
4109+ goto bad_area_nopax;
4110 down_read(&mm->mmap_sem);
4111 }
4112
4113+#ifdef CONFIG_PAX_PAGEEXEC
4114+ if (unlikely((error_code & 5) != 5 ||
4115+ (regs->eflags & X86_EFLAGS_VM) ||
4116+ !(mm->pax_flags & MF_PAX_PAGEEXEC)))
4117+ goto not_pax_fault;
4118+
4119+ /* PaX: it's our fault, let's handle it if we can */
4120+
4121+ /* PaX: take a look at read faults before acquiring any locks */
4122+ if (unlikely(!(error_code & 2) && (regs->eip == address))) {
4123+ /* instruction fetch attempt from a protected page in user mode */
4124+ up_read(&mm->mmap_sem);
4125+ switch (pax_handle_fetch_fault(regs)) {
4126+
4127+#ifdef CONFIG_PAX_EMUTRAMP
4128+ case 2:
4129+ return;
4130+#endif
4131+
4132+ }
4133+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
4134+ do_exit(SIGKILL);
4135+ }
4136+
4137+ pmd = pax_get_pmd(mm, address);
4138+ if (unlikely(!pmd))
4139+ goto not_pax_fault;
4140+
4141+ pte = pte_offset_map_lock(mm, pmd, address, &ptl);
4142+ if (unlikely(!(pte_val(*pte) & _PAGE_PRESENT) || pte_user(*pte))) {
4143+ pte_unmap_unlock(pte, ptl);
4144+ goto not_pax_fault;
4145+ }
4146+
4147+ if (unlikely((error_code & 2) && !pte_write(*pte))) {
4148+ /* write attempt to a protected page in user mode */
4149+ pte_unmap_unlock(pte, ptl);
4150+ goto not_pax_fault;
4151+ }
4152+
4153+#ifdef CONFIG_SMP
4154+ if (likely(address > get_limit(regs->xcs) && cpu_isset(smp_processor_id(), mm->context.cpu_user_cs_mask)))
4155+#else
4156+ if (likely(address > get_limit(regs->xcs)))
4157+#endif
4158+ {
4159+ set_pte(pte, pte_mkread(*pte));
4160+ __flush_tlb_one(address);
4161+ pte_unmap_unlock(pte, ptl);
4162+ up_read(&mm->mmap_sem);
4163+ return;
4164+ }
4165+
4166+ pte_mask = _PAGE_ACCESSED | _PAGE_USER | ((error_code & 2) << (_PAGE_BIT_DIRTY-1));
4167+
4168+ /*
4169+ * PaX: fill DTLB with user rights and retry
4170+ */
4171+ __asm__ __volatile__ (
4172+ "movw %w4,%%ds\n"
4173+ "orb %2,%%ss:(%1)\n"
4174+#if defined(CONFIG_M586) || defined(CONFIG_M586TSC)
4175+/*
4176+ * PaX: let this uncommented 'invlpg' remind us on the behaviour of Intel's
4177+ * (and AMD's) TLBs. namely, they do not cache PTEs that would raise *any*
4178+ * page fault when examined during a TLB load attempt. this is true not only
4179+ * for PTEs holding a non-present entry but also present entries that will
4180+ * raise a page fault (such as those set up by PaX, or the copy-on-write
4181+ * mechanism). in effect it means that we do *not* need to flush the TLBs
4182+ * for our target pages since their PTEs are simply not in the TLBs at all.
4183+
4184+ * the best thing in omitting it is that we gain around 15-20% speed in the
4185+ * fast path of the page fault handler and can get rid of tracing since we
4186+ * can no longer flush unintended entries.
4187+ */
4188+ "invlpg (%0)\n"
4189+#endif
4190+ "testb $0,(%0)\n"
4191+ "xorb %3,%%ss:(%1)\n"
4192+ "pushl %%ss\n"
4193+ "popl %%ds\n"
4194+ :
4195+ : "q" (address), "r" (pte), "q" (pte_mask), "i" (_PAGE_USER), "r" (__USER_DS)
4196+ : "memory", "cc");
4197+ pte_unmap_unlock(pte, ptl);
4198+ up_read(&mm->mmap_sem);
4199+ return;
4200+
4201+not_pax_fault:
4202+#endif
4203+
4204 vma = find_vma(mm, address);
4205 if (!vma)
4206 goto bad_area;
4207@@ -456,6 +581,37 @@ bad_area:
4208 up_read(&mm->mmap_sem);
4209
4210 bad_area_nosemaphore:
4211+
4212+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
4213+ if (mm && (error_code & 4) && !(regs->eflags & X86_EFLAGS_VM)) {
4214+
4215+#ifdef CONFIG_PAX_PAGEEXEC
4216+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && !(error_code & 3) && (regs->eip == address)) {
4217+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
4218+ do_exit(SIGKILL);
4219+ }
4220+#endif
4221+
4222+#ifdef CONFIG_PAX_SEGMEXEC
4223+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && !(error_code & 3) && (regs->eip + SEGMEXEC_TASK_SIZE == address)) {
4224+
4225+ switch (pax_handle_fetch_fault(regs)) {
4226+
4227+#ifdef CONFIG_PAX_EMUTRAMP
4228+ case 2:
4229+ return;
4230+#endif
4231+
4232+ }
4233+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
4234+ do_exit(SIGKILL);
4235+ }
4236+#endif
4237+
4238+ }
4239+#endif
4240+
4241+bad_area_nopax:
4242 /* User mode accesses just cause a SIGSEGV */
4243 if (error_code & 4) {
4244 /*
4245@@ -523,6 +679,21 @@ no_context:
4246 if (address < PAGE_SIZE)
4247 printk(KERN_ALERT "BUG: unable to handle kernel NULL "
4248 "pointer dereference");
4249+
4250+#ifdef CONFIG_PAX_KERNEXEC
4251+#ifdef CONFIG_MODULES
4252+ else if (init_mm.start_code <= address && address < (unsigned long)MODULES_END)
4253+#else
4254+ else if (init_mm.start_code <= address && address < init_mm.end_code)
4255+#endif
4256+ if (tsk->signal->curr_ip)
4257+ printk(KERN_ERR "PAX: From %u.%u.%u.%u: %s:%d, uid/euid: %u/%u, attempted to modify kernel code",
4258+ NIPQUAD(tsk->signal->curr_ip), tsk->comm, tsk->pid, tsk->uid, tsk->euid);
4259+ else
4260+ printk(KERN_ERR "PAX: %s:%d, uid/euid: %u/%u, attempted to modify kernel code",
4261+ tsk->comm, tsk->pid, tsk->uid, tsk->euid);
4262+#endif
4263+
4264 else
4265 printk(KERN_ALERT "BUG: unable to handle kernel paging"
4266 " request");
4267@@ -530,24 +701,34 @@ no_context:
4268 printk(KERN_ALERT " printing eip:\n");
4269 printk("%08lx\n", regs->eip);
4270 }
4271- page = read_cr3();
4272- page = ((unsigned long *) __va(page))[address >> 22];
4273- if (oops_may_print())
4274- printk(KERN_ALERT "*pde = %08lx\n", page);
4275- /*
4276- * We must not directly access the pte in the highpte
4277- * case, the page table might be allocated in highmem.
4278- * And lets rather not kmap-atomic the pte, just in case
4279- * it's allocated already.
4280- */
4281+
4282+ if (oops_may_print()) {
4283+ unsigned long index = pgd_index(address);
4284+ pgd_t *pgd;
4285+ pud_t *pud;
4286+ pmd_t *pmd;
4287+ pte_t *pte;
4288+
4289+ pgd = index + (pgd_t *)__va(read_cr3());
4290+ printk(KERN_ALERT "*pgd = %*llx\n", sizeof(*pgd), (unsigned long long)pgd_val(*pgd));
4291+ if (pgd_present(*pgd)) {
4292+ pud = pud_offset(pgd, address);
4293+ pmd = pmd_offset(pud, address);
4294+ printk(KERN_ALERT "*pmd = %*llx\n", sizeof(*pmd), (unsigned long long)pmd_val(*pmd));
4295+ /*
4296+ * We must not directly access the pte in the highpte
4297+ * case, the page table might be allocated in highmem.
4298+ * And lets rather not kmap-atomic the pte, just in case
4299+ * it's allocated already.
4300+ */
4301 #ifndef CONFIG_HIGHPTE
4302- if ((page & 1) && oops_may_print()) {
4303- page &= PAGE_MASK;
4304- address &= 0x003ff000;
4305- page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
4306- printk(KERN_ALERT "*pte = %08lx\n", page);
4307- }
4308+ if (pmd_present(*pmd) && !pmd_large(*pmd)) {
4309+ pte = pte_offset_kernel(pmd, address);
4310+ printk(KERN_ALERT "*pte = %*llx\n", sizeof(*pte), (unsigned long long)pte_val(*pte));
4311+ }
4312 #endif
4313+ }
4314+ }
4315 tsk->thread.cr2 = address;
4316 tsk->thread.trap_no = 14;
4317 tsk->thread.error_code = error_code;
4318@@ -624,3 +805,105 @@ void vmalloc_sync_all(void)
4319 }
4320 }
4321 #endif
4322+
4323+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
4324+/*
4325+ * PaX: decide what to do with offenders (regs->eip = fault address)
4326+ *
4327+ * returns 1 when task should be killed
4328+ * 2 when gcc trampoline was detected
4329+ */
4330+static int pax_handle_fetch_fault(struct pt_regs *regs)
4331+{
4332+
4333+#ifdef CONFIG_PAX_EMUTRAMP
4334+ static const unsigned char trans[8] = {6, 1, 2, 0, 13, 5, 3, 4};
4335+ int err;
4336+#endif
4337+
4338+ if (regs->eflags & X86_EFLAGS_VM)
4339+ return 1;
4340+
4341+#ifdef CONFIG_PAX_EMUTRAMP
4342+ if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
4343+ return 1;
4344+
4345+ do { /* PaX: gcc trampoline emulation #1 */
4346+ unsigned char mov1, mov2;
4347+ unsigned short jmp;
4348+ unsigned long addr1, addr2;
4349+
4350+ err = get_user(mov1, (unsigned char __user *)regs->eip);
4351+ err |= get_user(addr1, (unsigned long __user *)(regs->eip + 1));
4352+ err |= get_user(mov2, (unsigned char __user *)(regs->eip + 5));
4353+ err |= get_user(addr2, (unsigned long __user *)(regs->eip + 6));
4354+ err |= get_user(jmp, (unsigned short __user *)(regs->eip + 10));
4355+
4356+ if (err)
4357+ break;
4358+
4359+ if ((mov1 & 0xF8) == 0xB8 &&
4360+ (mov2 & 0xF8) == 0xB8 &&
4361+ (mov1 & 0x07) != (mov2 & 0x07) &&
4362+ (jmp & 0xF8FF) == 0xE0FF &&
4363+ (mov2 & 0x07) == ((jmp>>8) & 0x07))
4364+ {
4365+ ((unsigned long *)regs)[trans[mov1 & 0x07]] = addr1;
4366+ ((unsigned long *)regs)[trans[mov2 & 0x07]] = addr2;
4367+ regs->eip = addr2;
4368+ return 2;
4369+ }
4370+ } while (0);
4371+
4372+ do { /* PaX: gcc trampoline emulation #2 */
4373+ unsigned char mov, jmp;
4374+ unsigned long addr1, addr2;
4375+
4376+ err = get_user(mov, (unsigned char __user *)regs->eip);
4377+ err |= get_user(addr1, (unsigned long __user *)(regs->eip + 1));
4378+ err |= get_user(jmp, (unsigned char __user *)(regs->eip + 5));
4379+ err |= get_user(addr2, (unsigned long __user *)(regs->eip + 6));
4380+
4381+ if (err)
4382+ break;
4383+
4384+ if ((mov & 0xF8) == 0xB8 &&
4385+ jmp == 0xE9)
4386+ {
4387+ ((unsigned long *)regs)[trans[mov & 0x07]] = addr1;
4388+ regs->eip += addr2 + 10;
4389+ return 2;
4390+ }
4391+ } while (0);
4392+#endif
4393+
4394+ return 1; /* PaX in action */
4395+}
4396+#endif
4397+
4398+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
4399+void pax_report_insns(void *pc, void *sp)
4400+{
4401+ long i;
4402+
4403+ printk(KERN_ERR "PAX: bytes at PC: ");
4404+ for (i = 0; i < 20; i++) {
4405+ unsigned char c;
4406+ if (get_user(c, (unsigned char __user *)pc+i))
4407+ printk("?? ");
4408+ else
4409+ printk("%02x ", c);
4410+ }
4411+ printk("\n");
4412+
4413+ printk(KERN_ERR "PAX: bytes at SP-4: ");
4414+ for (i = -1; i < 20; i++) {
4415+ unsigned long c;
4416+ if (get_user(c, (unsigned long __user *)sp+i))
4417+ printk("???????? ");
4418+ else
4419+ printk("%08lx ", c);
4420+ }
4421+ printk("\n");
4422+}
4423+#endif
4424diff -urNp linux-2.6.17.11/arch/i386/mm/hugetlbpage.c linux-2.6.17.11/arch/i386/mm/hugetlbpage.c
4425--- linux-2.6.17.11/arch/i386/mm/hugetlbpage.c 2006-08-07 00:18:54.000000000 -0400
4426+++ linux-2.6.17.11/arch/i386/mm/hugetlbpage.c 2006-08-12 08:17:55.000000000 -0400
4427@@ -121,7 +121,12 @@ static unsigned long hugetlb_get_unmappe
4428 {
4429 struct mm_struct *mm = current->mm;
4430 struct vm_area_struct *vma;
4431- unsigned long start_addr;
4432+ unsigned long start_addr, task_size = TASK_SIZE;
4433+
4434+#ifdef CONFIG_PAX_SEGMEXEC
4435+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
4436+ task_size = SEGMEXEC_TASK_SIZE;
4437+#endif
4438
4439 if (len > mm->cached_hole_size) {
4440 start_addr = mm->free_area_cache;
4441@@ -135,7 +140,7 @@ full_search:
4442
4443 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
4444 /* At this point: (!vma || addr < vma->vm_end). */
4445- if (TASK_SIZE - len < addr) {
4446+ if (task_size - len < addr) {
4447 /*
4448 * Start a new search - just in case we missed
4449 * some holes.
4450@@ -163,9 +168,8 @@ static unsigned long hugetlb_get_unmappe
4451 {
4452 struct mm_struct *mm = current->mm;
4453 struct vm_area_struct *vma, *prev_vma;
4454- unsigned long base = mm->mmap_base, addr = addr0;
4455+ unsigned long base = mm->mmap_base, addr;
4456 unsigned long largest_hole = mm->cached_hole_size;
4457- int first_time = 1;
4458
4459 /* don't allow allocations above current base */
4460 if (mm->free_area_cache > base)
4461@@ -175,7 +179,7 @@ static unsigned long hugetlb_get_unmappe
4462 largest_hole = 0;
4463 mm->free_area_cache = base;
4464 }
4465-try_again:
4466+
4467 /* make sure it can fit in the remaining address space */
4468 if (mm->free_area_cache < len)
4469 goto fail;
4470@@ -217,16 +221,6 @@ try_again:
4471
4472 fail:
4473 /*
4474- * if hint left us with no space for the requested
4475- * mapping then try again:
4476- */
4477- if (first_time) {
4478- mm->free_area_cache = base;
4479- largest_hole = 0;
4480- first_time = 0;
4481- goto try_again;
4482- }
4483- /*
4484 * A failed mmap() very likely causes application failure,
4485 * so fall back to the bottom-up function here. This scenario
4486 * can happen with large stack limits and large mmap()
4487@@ -252,16 +246,23 @@ hugetlb_get_unmapped_area(struct file *f
4488 {
4489 struct mm_struct *mm = current->mm;
4490 struct vm_area_struct *vma;
4491+ unsigned long task_size = TASK_SIZE;
4492
4493 if (len & ~HPAGE_MASK)
4494 return -EINVAL;
4495- if (len > TASK_SIZE)
4496+
4497+#ifdef CONFIG_PAX_SEGMEXEC
4498+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
4499+ task_size = SEGMEXEC_TASK_SIZE;
4500+#endif
4501+
4502+ if (len > task_size || addr > task_size - len)
4503 return -ENOMEM;
4504
4505 if (addr) {
4506 addr = ALIGN(addr, HPAGE_SIZE);
4507 vma = find_vma(mm, addr);
4508- if (TASK_SIZE - len >= addr &&
4509+ if (task_size - len >= addr &&
4510 (!vma || addr + len <= vma->vm_start))
4511 return addr;
4512 }
4513diff -urNp linux-2.6.17.11/arch/i386/mm/init.c linux-2.6.17.11/arch/i386/mm/init.c
4514--- linux-2.6.17.11/arch/i386/mm/init.c 2006-08-07 00:18:54.000000000 -0400
4515+++ linux-2.6.17.11/arch/i386/mm/init.c 2006-08-12 08:17:55.000000000 -0400
4516@@ -41,6 +41,7 @@
4517 #include <asm/tlb.h>
4518 #include <asm/tlbflush.h>
4519 #include <asm/sections.h>
4520+#include <asm/desc.h>
4521
4522 unsigned int __VMALLOC_RESERVE = 128 << 20;
4523
4524@@ -50,30 +51,6 @@ unsigned long highstart_pfn, highend_pfn
4525 static int noinline do_test_wp_bit(void);
4526
4527 /*
4528- * Creates a middle page table and puts a pointer to it in the
4529- * given global directory entry. This only returns the gd entry
4530- * in non-PAE compilation mode, since the middle layer is folded.
4531- */
4532-static pmd_t * __init one_md_table_init(pgd_t *pgd)
4533-{
4534- pud_t *pud;
4535- pmd_t *pmd_table;
4536-
4537-#ifdef CONFIG_X86_PAE
4538- pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
4539- set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
4540- pud = pud_offset(pgd, 0);
4541- if (pmd_table != pmd_offset(pud, 0))
4542- BUG();
4543-#else
4544- pud = pud_offset(pgd, 0);
4545- pmd_table = pmd_offset(pud, 0);
4546-#endif
4547-
4548- return pmd_table;
4549-}
4550-
4551-/*
4552 * Create a page table and place a pointer to it in a middle page
4553 * directory entry.
4554 */
4555@@ -81,7 +58,11 @@ static pte_t * __init one_page_table_ini
4556 {
4557 if (pmd_none(*pmd)) {
4558 pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
4559+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
4560+ set_pmd(pmd, __pmd(__pa(page_table) | _KERNPG_TABLE));
4561+#else
4562 set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
4563+#endif
4564 if (page_table != pte_offset_kernel(pmd, 0))
4565 BUG();
4566
4567@@ -116,8 +97,6 @@ static void __init page_table_range_init
4568 pgd = pgd_base + pgd_idx;
4569
4570 for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
4571- if (pgd_none(*pgd))
4572- one_md_table_init(pgd);
4573 pud = pud_offset(pgd, vaddr);
4574 pmd = pmd_offset(pud, vaddr);
4575 for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
4576@@ -130,11 +109,22 @@ static void __init page_table_range_init
4577 }
4578 }
4579
4580-static inline int is_kernel_text(unsigned long addr)
4581+static inline int is_kernel_text(unsigned long start, unsigned long end)
4582 {
4583- if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end)
4584- return 1;
4585- return 0;
4586+ unsigned long etext;
4587+
4588+#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
4589+ etext = (unsigned long)&MODULES_END - __KERNEL_TEXT_OFFSET;
4590+#else
4591+ etext = (unsigned long)&_etext;
4592+#endif
4593+
4594+ if ((start > etext + __KERNEL_TEXT_OFFSET ||
4595+ end <= (unsigned long)_stext + __KERNEL_TEXT_OFFSET) &&
4596+ (start > (unsigned long)_einittext + __KERNEL_TEXT_OFFSET ||
4597+ end <= (unsigned long)_sinittext + __KERNEL_TEXT_OFFSET))
4598+ return 0;
4599+ return 1;
4600 }
4601
4602 /*
4603@@ -146,26 +136,24 @@ static void __init kernel_physical_mappi
4604 {
4605 unsigned long pfn;
4606 pgd_t *pgd;
4607+ pud_t *pud;
4608 pmd_t *pmd;
4609 pte_t *pte;
4610- int pgd_idx, pmd_idx, pte_ofs;
4611+ unsigned int pgd_idx, pmd_idx, pte_ofs;
4612
4613 pgd_idx = pgd_index(PAGE_OFFSET);
4614 pgd = pgd_base + pgd_idx;
4615 pfn = 0;
4616
4617- for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
4618- pmd = one_md_table_init(pgd);
4619- if (pfn >= max_low_pfn)
4620- continue;
4621+ for (; pgd_idx < PTRS_PER_PGD && pfn < max_low_pfn; pgd++, pgd_idx++) {
4622+ pud = pud_offset(pgd, 0);
4623+ pmd = pmd_offset(pud, 0);
4624 for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
4625- unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;
4626+ unsigned long address = pfn * PAGE_SIZE + PAGE_OFFSET;
4627
4628 /* Map with big pages if possible, otherwise create normal page tables. */
4629 if (cpu_has_pse) {
4630- unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
4631-
4632- if (is_kernel_text(address) || is_kernel_text(address2))
4633+ if (is_kernel_text(address, address + PMD_SIZE))
4634 set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
4635 else
4636 set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
4637@@ -174,7 +162,7 @@ static void __init kernel_physical_mappi
4638 pte = one_page_table_init(pmd);
4639
4640 for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++) {
4641- if (is_kernel_text(address))
4642+ if (is_kernel_text(address, address + PAGE_SIZE))
4643 set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
4644 else
4645 set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
4646@@ -341,13 +329,6 @@ static void __init pagetable_init (void)
4647 unsigned long vaddr;
4648 pgd_t *pgd_base = swapper_pg_dir;
4649
4650-#ifdef CONFIG_X86_PAE
4651- int i;
4652- /* Init entries of the first-level page table to the zero page */
4653- for (i = 0; i < PTRS_PER_PGD; i++)
4654- set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
4655-#endif
4656-
4657 /* Enable PSE if available */
4658 if (cpu_has_pse) {
4659 set_in_cr4(X86_CR4_PSE);
4660@@ -371,17 +352,6 @@ static void __init pagetable_init (void)
4661 page_table_range_init(vaddr, 0, pgd_base);
4662
4663 permanent_kmaps_init(pgd_base);
4664-
4665-#ifdef CONFIG_X86_PAE
4666- /*
4667- * Add low memory identity-mappings - SMP needs it when
4668- * starting up on an AP from real-mode. In the non-PAE
4669- * case we already have these mappings through head.S.
4670- * All user-space mappings are explicitly cleared after
4671- * SMP startup.
4672- */
4673- set_pgd(&pgd_base[0], pgd_base[USER_PTRS_PER_PGD]);
4674-#endif
4675 }
4676
4677 #ifdef CONFIG_SOFTWARE_SUSPEND
4678@@ -423,7 +393,6 @@ void zap_low_mappings (void)
4679 flush_tlb_all();
4680 }
4681
4682-static int disable_nx __initdata = 0;
4683 u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
4684
4685 /*
4686@@ -437,11 +406,9 @@ u64 __supported_pte_mask __read_mostly =
4687 void __init noexec_setup(const char *str)
4688 {
4689 if (!strncmp(str, "on",2) && cpu_has_nx) {
4690- __supported_pte_mask |= _PAGE_NX;
4691- disable_nx = 0;
4692+ nx_enabled = 1;
4693 } else if (!strncmp(str,"off",3)) {
4694- disable_nx = 1;
4695- __supported_pte_mask &= ~_PAGE_NX;
4696+ nx_enabled = 0;
4697 }
4698 }
4699
4700@@ -450,17 +417,13 @@ int nx_enabled = 0;
4701
4702 static void __init set_nx(void)
4703 {
4704- unsigned int v[4], l, h;
4705+ if (!nx_enabled && cpu_has_nx) {
4706+ unsigned l, h;
4707
4708- if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
4709- cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
4710- if ((v[3] & (1 << 20)) && !disable_nx) {
4711- rdmsr(MSR_EFER, l, h);
4712- l |= EFER_NX;
4713- wrmsr(MSR_EFER, l, h);
4714- nx_enabled = 1;
4715- __supported_pte_mask |= _PAGE_NX;
4716- }
4717+ __supported_pte_mask &= ~_PAGE_NX;
4718+ rdmsr(MSR_EFER, l, h);
4719+ l &= ~EFER_NX;
4720+ wrmsr(MSR_EFER, l, h);
4721 }
4722 }
4723
4724@@ -512,14 +475,6 @@ void __init paging_init(void)
4725
4726 load_cr3(swapper_pg_dir);
4727
4728-#ifdef CONFIG_X86_PAE
4729- /*
4730- * We will bail out later - printk doesn't work right now so
4731- * the user would just see a hanging kernel.
4732- */
4733- if (cpu_has_pae)
4734- set_in_cr4(X86_CR4_PAE);
4735-#endif
4736 __flush_tlb_all();
4737
4738 kmap_init();
4739@@ -611,7 +566,7 @@ void __init mem_init(void)
4740 set_highmem_pages_init(bad_ppro);
4741
4742 codesize = (unsigned long) &_etext - (unsigned long) &_text;
4743- datasize = (unsigned long) &_edata - (unsigned long) &_etext;
4744+ datasize = (unsigned long) &_edata - (unsigned long) &_data;
4745 initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
4746
4747 kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
4748@@ -628,10 +583,6 @@ void __init mem_init(void)
4749 (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
4750 );
4751
4752-#ifdef CONFIG_X86_PAE
4753- if (!cpu_has_pae)
4754- panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
4755-#endif
4756 if (boot_cpu_data.wp_works_ok < 0)
4757 test_wp_bit();
4758
4759@@ -761,6 +712,37 @@ void free_init_pages(char *what, unsigne
4760
4761 void free_initmem(void)
4762 {
4763+
4764+#ifdef CONFIG_PAX_KERNEXEC
4765+ /* PaX: limit KERNEL_CS to actual size */
4766+ unsigned long addr, limit;
4767+ int cpu;
4768+ pgd_t *pgd;
4769+ pud_t *pud;
4770+ pmd_t *pmd;
4771+
4772+#ifdef CONFIG_MODULES
4773+ limit = (unsigned long)&MODULES_END - __KERNEL_TEXT_OFFSET;
4774+#else
4775+ limit = (unsigned long)&_etext;
4776+#endif
4777+ limit = (limit - 1UL) >> PAGE_SHIFT;
4778+
4779+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
4780+ get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].a = (get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].a & 0xFFFF0000UL) | (limit & 0x0FFFFUL);
4781+ get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].b = (get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].b & 0xFFF0FFFFUL) | (limit & 0xF0000UL);
4782+ }
4783+
4784+ /* PaX: make KERNEL_CS read-only */
4785+ for (addr = __KERNEL_TEXT_OFFSET; addr < (unsigned long)&_data; addr += PMD_SIZE) {
4786+ pgd = pgd_offset_k(addr);
4787+ pud = pud_offset(pgd, addr);
4788+ pmd = pmd_offset(pud, addr);
4789+ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW));
4790+ }
4791+ flush_tlb_all();
4792+#endif
4793+
4794 free_init_pages("unused kernel memory",
4795 (unsigned long)(&__init_begin),
4796 (unsigned long)(&__init_end));
4797diff -urNp linux-2.6.17.11/arch/i386/mm/mmap.c linux-2.6.17.11/arch/i386/mm/mmap.c
4798--- linux-2.6.17.11/arch/i386/mm/mmap.c 2006-08-07 00:18:54.000000000 -0400
4799+++ linux-2.6.17.11/arch/i386/mm/mmap.c 2006-08-12 08:17:55.000000000 -0400
4800@@ -34,12 +34,18 @@
4801 * Leave an at least ~128 MB hole.
4802 */
4803 #define MIN_GAP (128*1024*1024)
4804-#define MAX_GAP (TASK_SIZE/6*5)
4805+#define MAX_GAP (task_size/6*5)
4806
4807 static inline unsigned long mmap_base(struct mm_struct *mm)
4808 {
4809 unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
4810 unsigned long random_factor = 0;
4811+ unsigned long task_size = TASK_SIZE;
4812+
4813+#ifdef CONFIG_PAX_SEGMEXEC
4814+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
4815+ task_size = SEGMEXEC_TASK_SIZE;
4816+#endif
4817
4818 if (current->flags & PF_RANDOMIZE)
4819 random_factor = get_random_int() % (1024*1024);
4820@@ -49,7 +55,7 @@ static inline unsigned long mmap_base(st
4821 else if (gap > MAX_GAP)
4822 gap = MAX_GAP;
4823
4824- return PAGE_ALIGN(TASK_SIZE - gap - random_factor);
4825+ return PAGE_ALIGN(task_size - gap - random_factor);
4826 }
4827
4828 /*
4829@@ -66,10 +72,22 @@ void arch_pick_mmap_layout(struct mm_str
4830 (current->personality & ADDR_COMPAT_LAYOUT) ||
4831 current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
4832 mm->mmap_base = TASK_UNMAPPED_BASE;
4833+
4834+#ifdef CONFIG_PAX_RANDMMAP
4835+ if (mm->pax_flags & MF_PAX_RANDMMAP)
4836+ mm->mmap_base += mm->delta_mmap;
4837+#endif
4838+
4839 mm->get_unmapped_area = arch_get_unmapped_area;
4840 mm->unmap_area = arch_unmap_area;
4841 } else {
4842 mm->mmap_base = mmap_base(mm);
4843+
4844+#ifdef CONFIG_PAX_RANDMMAP
4845+ if (mm->pax_flags & MF_PAX_RANDMMAP)
4846+ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
4847+#endif
4848+
4849 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
4850 mm->unmap_area = arch_unmap_area_topdown;
4851 }
4852diff -urNp linux-2.6.17.11/arch/i386/mm/pageattr.c linux-2.6.17.11/arch/i386/mm/pageattr.c
4853--- linux-2.6.17.11/arch/i386/mm/pageattr.c 2006-08-07 00:18:54.000000000 -0400
4854+++ linux-2.6.17.11/arch/i386/mm/pageattr.c 2006-08-12 08:17:55.000000000 -0400
4855@@ -14,6 +14,7 @@
4856 #include <asm/tlbflush.h>
4857 #include <asm/pgalloc.h>
4858 #include <asm/sections.h>
4859+#include <asm/desc.h>
4860
4861 static DEFINE_SPINLOCK(cpa_lock);
4862 static struct list_head df_list = LIST_HEAD_INIT(df_list);
4863@@ -84,7 +85,18 @@ static void set_pmd_pte(pte_t *kpte, uns
4864 struct page *page;
4865 unsigned long flags;
4866
4867+#ifdef CONFIG_PAX_KERNEXEC
4868+ unsigned long cr0;
4869+
4870+ pax_open_kernel(cr0);
4871+#endif
4872+
4873 set_pte_atomic(kpte, pte); /* change init_mm */
4874+
4875+#ifdef CONFIG_PAX_KERNEXEC
4876+ pax_close_kernel(cr0);
4877+#endif
4878+
4879 if (PTRS_PER_PMD > 1)
4880 return;
4881
4882@@ -111,7 +123,7 @@ static inline void revert_page(struct pa
4883 pte_t *linear;
4884
4885 ref_prot =
4886- ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
4887+ ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext + __KERNEL_TEXT_OFFSET)
4888 ? PAGE_KERNEL_LARGE_EXEC : PAGE_KERNEL_LARGE;
4889
4890 linear = (pte_t *)
4891@@ -143,7 +155,7 @@ __change_page_attr(struct page *page, pg
4892 struct page *split;
4893
4894 ref_prot =
4895- ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
4896+ ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext + __KERNEL_TEXT_OFFSET)
4897 ? PAGE_KERNEL_EXEC : PAGE_KERNEL;
4898 split = split_large_page(address, prot, ref_prot);
4899 if (!split)
4900diff -urNp linux-2.6.17.11/arch/i386/oprofile/backtrace.c linux-2.6.17.11/arch/i386/oprofile/backtrace.c
4901--- linux-2.6.17.11/arch/i386/oprofile/backtrace.c 2006-08-07 00:18:54.000000000 -0400
4902+++ linux-2.6.17.11/arch/i386/oprofile/backtrace.c 2006-08-12 08:17:55.000000000 -0400
4903@@ -116,7 +116,7 @@ x86_backtrace(struct pt_regs * const reg
4904 head = (struct frame_head *)regs->ebp;
4905 #endif
4906
4907- if (!user_mode_vm(regs)) {
4908+ if (!user_mode(regs)) {
4909 while (depth-- && valid_kernel_stack(head, regs))
4910 head = dump_kernel_backtrace(head);
4911 return;
4912diff -urNp linux-2.6.17.11/arch/i386/power/cpu.c linux-2.6.17.11/arch/i386/power/cpu.c
4913--- linux-2.6.17.11/arch/i386/power/cpu.c 2006-08-07 00:18:54.000000000 -0400
4914+++ linux-2.6.17.11/arch/i386/power/cpu.c 2006-08-12 08:17:55.000000000 -0400
4915@@ -62,7 +62,7 @@ static void do_fpu_end(void)
4916 static void fix_processor_context(void)
4917 {
4918 int cpu = smp_processor_id();
4919- struct tss_struct * t = &per_cpu(init_tss, cpu);
4920+ struct tss_struct * t = init_tss + cpu;
4921
4922 set_tss_desc(cpu,t); /* This just modifies memory; should not be necessary. But... This is necessary, because 386 hardware has concept of busy TSS or some similar stupidity. */
4923
4924diff -urNp linux-2.6.17.11/arch/ia64/ia32/binfmt_elf32.c linux-2.6.17.11/arch/ia64/ia32/binfmt_elf32.c
4925--- linux-2.6.17.11/arch/ia64/ia32/binfmt_elf32.c 2006-08-07 00:18:54.000000000 -0400
4926+++ linux-2.6.17.11/arch/ia64/ia32/binfmt_elf32.c 2006-08-12 08:17:55.000000000 -0400
4927@@ -46,6 +46,17 @@ randomize_stack_top(unsigned long stack_
4928
4929 #define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack))
4930
4931+#ifdef CONFIG_PAX_ASLR
4932+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
4933+
4934+#define PAX_DELTA_MMAP_LSB(tsk) IA32_PAGE_SHIFT
4935+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - IA32_PAGE_SHIFT)
4936+#define PAX_DELTA_EXEC_LSB(tsk) IA32_PAGE_SHIFT
4937+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - IA32_PAGE_SHIFT)
4938+#define PAX_DELTA_STACK_LSB(tsk) IA32_PAGE_SHIFT
4939+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - IA32_PAGE_SHIFT)
4940+#endif
4941+
4942 /* Ugly but avoids duplication */
4943 #include "../../../fs/binfmt_elf.c"
4944
4945diff -urNp linux-2.6.17.11/arch/ia64/ia32/ia32priv.h linux-2.6.17.11/arch/ia64/ia32/ia32priv.h
4946--- linux-2.6.17.11/arch/ia64/ia32/ia32priv.h 2006-08-07 00:18:54.000000000 -0400
4947+++ linux-2.6.17.11/arch/ia64/ia32/ia32priv.h 2006-08-12 08:17:55.000000000 -0400
4948@@ -305,7 +305,14 @@ struct old_linux32_dirent {
4949 #define ELF_DATA ELFDATA2LSB
4950 #define ELF_ARCH EM_386
4951
4952-#define IA32_STACK_TOP IA32_PAGE_OFFSET
4953+#ifdef CONFIG_PAX_RANDUSTACK
4954+#define __IA32_DELTA_STACK (current->mm->delta_stack)
4955+#else
4956+#define __IA32_DELTA_STACK 0UL
4957+#endif
4958+
4959+#define IA32_STACK_TOP (IA32_PAGE_OFFSET - __IA32_DELTA_STACK)
4960+
4961 #define IA32_GATE_OFFSET IA32_PAGE_OFFSET
4962 #define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE
4963
4964diff -urNp linux-2.6.17.11/arch/ia64/kernel/module.c linux-2.6.17.11/arch/ia64/kernel/module.c
4965--- linux-2.6.17.11/arch/ia64/kernel/module.c 2006-08-07 00:18:54.000000000 -0400
4966+++ linux-2.6.17.11/arch/ia64/kernel/module.c 2006-08-12 08:17:55.000000000 -0400
4967@@ -322,7 +322,7 @@ module_alloc (unsigned long size)
4968 void
4969 module_free (struct module *mod, void *module_region)
4970 {
4971- if (mod->arch.init_unw_table && module_region == mod->module_init) {
4972+ if (mod->arch.init_unw_table && module_region == mod->module_init_rx) {
4973 unw_remove_unwind_table(mod->arch.init_unw_table);
4974 mod->arch.init_unw_table = NULL;
4975 }
4976@@ -500,15 +500,39 @@ module_frob_arch_sections (Elf_Ehdr *ehd
4977 }
4978
4979 static inline int
4980+in_init_rx (const struct module *mod, uint64_t addr)
4981+{
4982+ return addr - (uint64_t) mod->module_init_rx < mod->init_size_rx;
4983+}
4984+
4985+static inline int
4986+in_init_rw (const struct module *mod, uint64_t addr)
4987+{
4988+ return addr - (uint64_t) mod->module_init_rw < mod->init_size_rw;
4989+}
4990+
4991+static inline int
4992 in_init (const struct module *mod, uint64_t addr)
4993 {
4994- return addr - (uint64_t) mod->module_init < mod->init_size;
4995+ return in_init_rx(mod, value) || in_init_rw(mod, value);
4996+}
4997+
4998+static inline int
4999+in_core_rx (const struct module *mod, uint64_t addr)
5000+{
5001+ return addr - (uint64_t) mod->module_core_rx < mod->core_size_rx;
5002+}
5003+
5004+static inline int
5005+in_core_rw (const struct module *mod, uint64_t addr)
5006+{
5007+ return addr - (uint64_t) mod->module_core_rw < mod->core_size_rw;
5008 }
5009
5010 static inline int
5011 in_core (const struct module *mod, uint64_t addr)
5012 {
5013- return addr - (uint64_t) mod->module_core < mod->core_size;
5014+ return in_core_rx(mod, value) || in_core_rw(mod, value);
5015 }
5016
5017 static inline int
5018@@ -692,7 +716,14 @@ do_reloc (struct module *mod, uint8_t r_
5019 break;
5020
5021 case RV_BDREL:
5022- val -= (uint64_t) (in_init(mod, val) ? mod->module_init : mod->module_core);
5023+ if (in_init_rx(mod, val))
5024+ val -= (uint64_t) mod->module_init_rx;
5025+ else if (in_init_rw(mod, val))
5026+ val -= (uint64_t) mod->module_init_rw;
5027+ else if (in_core_rx(mod, val))
5028+ val -= (uint64_t) mod->module_core_rx;
5029+ else if (in_core_rw(mod, val))
5030+ val -= (uint64_t) mod->module_core_rw;
5031 break;
5032
5033 case RV_LTV:
5034@@ -826,15 +857,15 @@ apply_relocate_add (Elf64_Shdr *sechdrs,
5035 * addresses have been selected...
5036 */
5037 uint64_t gp;
5038- if (mod->core_size > MAX_LTOFF)
5039+ if (mod->core_size_rx + mod->core_size_rw > MAX_LTOFF)
5040 /*
5041 * This takes advantage of fact that SHF_ARCH_SMALL gets allocated
5042 * at the end of the module.
5043 */
5044- gp = mod->core_size - MAX_LTOFF / 2;
5045+ gp = mod->core_size_rx + mod->core_size_rw - MAX_LTOFF / 2;
5046 else
5047- gp = mod->core_size / 2;
5048- gp = (uint64_t) mod->module_core + ((gp + 7) & -8);
5049+ gp = (mod->core_size_rx + mod->core_size_rw) / 2;
5050+ gp = (uint64_t) mod->module_core_rx + ((gp + 7) & -8);
5051 mod->arch.gp = gp;
5052 DEBUGP("%s: placing gp at 0x%lx\n", __FUNCTION__, gp);
5053 }
5054diff -urNp linux-2.6.17.11/arch/ia64/kernel/ptrace.c linux-2.6.17.11/arch/ia64/kernel/ptrace.c
5055--- linux-2.6.17.11/arch/ia64/kernel/ptrace.c 2006-08-07 00:18:54.000000000 -0400
5056+++ linux-2.6.17.11/arch/ia64/kernel/ptrace.c 2006-08-12 08:17:55.000000000 -0400
5057@@ -18,6 +18,7 @@
5058 #include <linux/audit.h>
5059 #include <linux/signal.h>
5060 #include <linux/vs_pid.h>
5061+#include <linux/grsecurity.h>
5062
5063 #include <asm/pgtable.h>
5064 #include <asm/processor.h>
5065@@ -1447,6 +1448,9 @@ sys_ptrace (long request, pid_t pid, uns
5066 if (pid == 1) /* no messing around with init! */
5067 goto out_tsk;
5068
5069+ if (gr_handle_ptrace(child, request))
5070+ goto out_tsk;
5071+
5072 if (request == PTRACE_ATTACH) {
5073 ret = ptrace_attach(child);
5074 goto out_tsk;
5075diff -urNp linux-2.6.17.11/arch/ia64/kernel/sys_ia64.c linux-2.6.17.11/arch/ia64/kernel/sys_ia64.c
5076--- linux-2.6.17.11/arch/ia64/kernel/sys_ia64.c 2006-08-23 19:30:00.000000000 -0400
5077+++ linux-2.6.17.11/arch/ia64/kernel/sys_ia64.c 2006-08-23 19:30:12.000000000 -0400
5078@@ -38,6 +38,13 @@ arch_get_unmapped_area (struct file *fil
5079 if (REGION_NUMBER(addr) == RGN_HPAGE)
5080 addr = 0;
5081 #endif
5082+
5083+#ifdef CONFIG_PAX_RANDMMAP
5084+ if ((mm->pax_flags & MF_PAX_RANDMMAP) && addr && filp)
5085+ addr = mm->free_area_cache;
5086+ else
5087+#endif
5088+
5089 if (!addr)
5090 addr = mm->free_area_cache;
5091
5092@@ -56,9 +63,9 @@ arch_get_unmapped_area (struct file *fil
5093 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
5094 /* At this point: (!vma || addr < vma->vm_end). */
5095 if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) {
5096- if (start_addr != TASK_UNMAPPED_BASE) {
5097+ if (start_addr != mm->mmap_base) {
5098 /* Start a new search --- just in case we missed some holes. */
5099- addr = TASK_UNMAPPED_BASE;
5100+ addr = mm->mmap_base;
5101 goto full_search;
5102 }
5103 return -ENOMEM;
5104diff -urNp linux-2.6.17.11/arch/ia64/mm/fault.c linux-2.6.17.11/arch/ia64/mm/fault.c
5105--- linux-2.6.17.11/arch/ia64/mm/fault.c 2006-08-07 00:18:54.000000000 -0400
5106+++ linux-2.6.17.11/arch/ia64/mm/fault.c 2006-08-12 08:17:55.000000000 -0400
5107@@ -10,6 +10,7 @@
5108 #include <linux/smp_lock.h>
5109 #include <linux/interrupt.h>
5110 #include <linux/kprobes.h>
5111+#include <linux/binfmts.h>
5112
5113 #include <asm/pgtable.h>
5114 #include <asm/processor.h>
5115@@ -51,6 +52,23 @@ mapped_kernel_page_is_present (unsigned
5116 return pte_present(pte);
5117 }
5118
5119+#ifdef CONFIG_PAX_PAGEEXEC
5120+void pax_report_insns(void *pc, void *sp)
5121+{
5122+ unsigned long i;
5123+
5124+ printk(KERN_ERR "PAX: bytes at PC: ");
5125+ for (i = 0; i < 8; i++) {
5126+ unsigned int c;
5127+ if (get_user(c, (unsigned int*)pc+i))
5128+ printk("???????? ");
5129+ else
5130+ printk("%08x ", c);
5131+ }
5132+ printk("\n");
5133+}
5134+#endif
5135+
5136 void __kprobes
5137 ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
5138 {
5139@@ -116,9 +134,23 @@ ia64_do_page_fault (unsigned long addres
5140 | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)
5141 | (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_BIT));
5142
5143- if ((vma->vm_flags & mask) != mask)
5144+ if ((vma->vm_flags & mask) != mask) {
5145+
5146+#ifdef CONFIG_PAX_PAGEEXEC
5147+ if (!(vma->vm_flags & VM_EXEC) && (mask & VM_EXEC)) {
5148+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->cr_iip)
5149+ goto bad_area;
5150+
5151+ up_read(&mm->mmap_sem);
5152+ pax_report_fault(regs, (void*)regs->cr_iip, (void*)regs->r12);
5153+ do_exit(SIGKILL);
5154+ }
5155+#endif
5156+
5157 goto bad_area;
5158
5159+ }
5160+
5161 survive:
5162 /*
5163 * If for any reason at all we couldn't handle the fault, make
5164diff -urNp linux-2.6.17.11/arch/ia64/mm/init.c linux-2.6.17.11/arch/ia64/mm/init.c
5165--- linux-2.6.17.11/arch/ia64/mm/init.c 2006-08-07 00:18:54.000000000 -0400
5166+++ linux-2.6.17.11/arch/ia64/mm/init.c 2006-08-12 08:17:55.000000000 -0400
5167@@ -20,8 +20,8 @@
5168 #include <linux/swap.h>
5169 #include <linux/proc_fs.h>
5170 #include <linux/bitops.h>
5171+#include <linux/a.out.h>
5172
5173-#include <asm/a.out.h>
5174 #include <asm/dma.h>
5175 #include <asm/ia32.h>
5176 #include <asm/io.h>
5177diff -urNp linux-2.6.17.11/arch/mips/kernel/binfmt_elfn32.c linux-2.6.17.11/arch/mips/kernel/binfmt_elfn32.c
5178--- linux-2.6.17.11/arch/mips/kernel/binfmt_elfn32.c 2006-08-07 00:18:54.000000000 -0400
5179+++ linux-2.6.17.11/arch/mips/kernel/binfmt_elfn32.c 2006-08-12 08:17:55.000000000 -0400
5180@@ -50,6 +50,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
5181 #undef ELF_ET_DYN_BASE
5182 #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
5183
5184+#ifdef CONFIG_PAX_ASLR
5185+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
5186+
5187+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
5188+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5189+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
5190+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5191+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
5192+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5193+#endif
5194+
5195 #include <asm/processor.h>
5196 #include <linux/module.h>
5197 #include <linux/elfcore.h>
5198diff -urNp linux-2.6.17.11/arch/mips/kernel/binfmt_elfo32.c linux-2.6.17.11/arch/mips/kernel/binfmt_elfo32.c
5199--- linux-2.6.17.11/arch/mips/kernel/binfmt_elfo32.c 2006-08-07 00:18:54.000000000 -0400
5200+++ linux-2.6.17.11/arch/mips/kernel/binfmt_elfo32.c 2006-08-12 08:17:55.000000000 -0400
5201@@ -52,6 +52,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
5202 #undef ELF_ET_DYN_BASE
5203 #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
5204
5205+#ifdef CONFIG_PAX_ASLR
5206+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
5207+
5208+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
5209+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5210+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
5211+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5212+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
5213+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5214+#endif
5215+
5216 #include <asm/processor.h>
5217 #include <linux/module.h>
5218 #include <linux/elfcore.h>
5219diff -urNp linux-2.6.17.11/arch/mips/kernel/syscall.c linux-2.6.17.11/arch/mips/kernel/syscall.c
5220--- linux-2.6.17.11/arch/mips/kernel/syscall.c 2006-08-07 00:18:54.000000000 -0400
5221+++ linux-2.6.17.11/arch/mips/kernel/syscall.c 2006-08-12 08:17:55.000000000 -0400
5222@@ -89,6 +89,11 @@ unsigned long arch_get_unmapped_area(str
5223 do_color_align = 0;
5224 if (filp || (flags & MAP_SHARED))
5225 do_color_align = 1;
5226+
5227+#ifdef CONFIG_PAX_RANDMMAP
5228+ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
5229+#endif
5230+
5231 if (addr) {
5232 if (do_color_align)
5233 addr = COLOUR_ALIGN(addr, pgoff);
5234@@ -99,7 +104,7 @@ unsigned long arch_get_unmapped_area(str
5235 (!vmm || addr + len <= vmm->vm_start))
5236 return addr;
5237 }
5238- addr = TASK_UNMAPPED_BASE;
5239+ addr = current->mm->mmap_base;
5240 if (do_color_align)
5241 addr = COLOUR_ALIGN(addr, pgoff);
5242 else
5243diff -urNp linux-2.6.17.11/arch/mips/mm/fault.c linux-2.6.17.11/arch/mips/mm/fault.c
5244--- linux-2.6.17.11/arch/mips/mm/fault.c 2006-08-07 00:18:54.000000000 -0400
5245+++ linux-2.6.17.11/arch/mips/mm/fault.c 2006-08-12 08:17:55.000000000 -0400
5246@@ -27,6 +27,23 @@
5247 #include <asm/ptrace.h>
5248 #include <asm/highmem.h> /* For VMALLOC_END */
5249
5250+#ifdef CONFIG_PAX_PAGEEXEC
5251+void pax_report_insns(void *pc)
5252+{
5253+ unsigned long i;
5254+
5255+ printk(KERN_ERR "PAX: bytes at PC: ");
5256+ for (i = 0; i < 5; i++) {
5257+ unsigned int c;
5258+ if (get_user(c, (unsigned int*)pc+i))
5259+ printk("???????? ");
5260+ else
5261+ printk("%08x ", c);
5262+ }
5263+ printk("\n");
5264+}
5265+#endif
5266+
5267 /*
5268 * This routine handles page faults. It determines the address,
5269 * and the problem, and then passes it off to one of the appropriate
5270diff -urNp linux-2.6.17.11/arch/parisc/kernel/module.c linux-2.6.17.11/arch/parisc/kernel/module.c
5271--- linux-2.6.17.11/arch/parisc/kernel/module.c 2006-08-07 00:18:54.000000000 -0400
5272+++ linux-2.6.17.11/arch/parisc/kernel/module.c 2006-08-12 08:17:55.000000000 -0400
5273@@ -72,16 +72,38 @@
5274
5275 /* three functions to determine where in the module core
5276 * or init pieces the location is */
5277+static inline int is_init_rx(struct module *me, void *loc)
5278+{
5279+ return (loc >= me->module_init_rx &&
5280+ loc < (me->module_init_rx + me->init_size_rx));
5281+}
5282+
5283+static inline int is_init_rw(struct module *me, void *loc)
5284+{
5285+ return (loc >= me->module_init_rw &&
5286+ loc < (me->module_init_rw + me->init_size_rw));
5287+}
5288+
5289 static inline int is_init(struct module *me, void *loc)
5290 {
5291- return (loc >= me->module_init &&
5292- loc <= (me->module_init + me->init_size));
5293+ return is_init_rx(me, loc) || is_init_rw(me, loc);
5294+}
5295+
5296+static inline int is_core_rx(struct module *me, void *loc)
5297+{
5298+ return (loc >= me->module_core_rx &&
5299+ loc < (me->module_core_rx + me->core_size_rx));
5300+}
5301+
5302+static inline int is_core_rw(struct module *me, void *loc)
5303+{
5304+ return (loc >= me->module_core_rw &&
5305+ loc < (me->module_core_rw + me->core_size_rw));
5306 }
5307
5308 static inline int is_core(struct module *me, void *loc)
5309 {
5310- return (loc >= me->module_core &&
5311- loc <= (me->module_core + me->core_size));
5312+ return is_core_rx(me, loc) || is_core_rw(me, loc);
5313 }
5314
5315 static inline int is_local(struct module *me, void *loc)
5316@@ -289,21 +311,21 @@ int module_frob_arch_sections(CONST Elf_
5317 }
5318
5319 /* align things a bit */
5320- me->core_size = ALIGN(me->core_size, 16);
5321- me->arch.got_offset = me->core_size;
5322- me->core_size += gots * sizeof(struct got_entry);
5323-
5324- me->core_size = ALIGN(me->core_size, 16);
5325- me->arch.fdesc_offset = me->core_size;
5326- me->core_size += fdescs * sizeof(Elf_Fdesc);
5327-
5328- me->core_size = ALIGN(me->core_size, 16);
5329- me->arch.stub_offset = me->core_size;
5330- me->core_size += stubs * sizeof(struct stub_entry);
5331-
5332- me->init_size = ALIGN(me->init_size, 16);
5333- me->arch.init_stub_offset = me->init_size;
5334- me->init_size += init_stubs * sizeof(struct stub_entry);
5335+ me->core_size_rw = ALIGN(me->core_size_rw, 16);
5336+ me->arch.got_offset = me->core_size_rw;
5337+ me->core_size_rw += gots * sizeof(struct got_entry);
5338+
5339+ me->core_size_rw = ALIGN(me->core_size_rw, 16);
5340+ me->arch.fdesc_offset = me->core_size_rw;
5341+ me->core_size_rw += fdescs * sizeof(Elf_Fdesc);
5342+
5343+ me->core_size_rx = ALIGN(me->core_size_rx, 16);
5344+ me->arch.stub_offset = me->core_size_rx;
5345+ me->core_size_rx += stubs * sizeof(struct stub_entry);
5346+
5347+ me->init_size_rx = ALIGN(me->init_size_rx, 16);
5348+ me->arch.init_stub_offset = me->init_size_rx;
5349+ me->init_size_rx += init_stubs * sizeof(struct stub_entry);
5350
5351 me->arch.got_max = gots;
5352 me->arch.fdesc_max = fdescs;
5353@@ -323,7 +345,7 @@ static Elf64_Word get_got(struct module
5354
5355 BUG_ON(value == 0);
5356
5357- got = me->module_core + me->arch.got_offset;
5358+ got = me->module_core_rw + me->arch.got_offset;
5359 for (i = 0; got[i].addr; i++)
5360 if (got[i].addr == value)
5361 goto out;
5362@@ -341,7 +363,7 @@ static Elf64_Word get_got(struct module
5363 #ifdef __LP64__
5364 static Elf_Addr get_fdesc(struct module *me, unsigned long value)
5365 {
5366- Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
5367+ Elf_Fdesc *fdesc = me->module_core_rw + me->arch.fdesc_offset;
5368
5369 if (!value) {
5370 printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
5371@@ -359,7 +381,7 @@ static Elf_Addr get_fdesc(struct module
5372
5373 /* Create new one */
5374 fdesc->addr = value;
5375- fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset;
5376+ fdesc->gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset;
5377 return (Elf_Addr)fdesc;
5378 }
5379 #endif /* __LP64__ */
5380@@ -373,12 +395,12 @@ static Elf_Addr get_stub(struct module *
5381 if(init_section) {
5382 i = me->arch.init_stub_count++;
5383 BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
5384- stub = me->module_init + me->arch.init_stub_offset +
5385+ stub = me->module_init_rx + me->arch.init_stub_offset +
5386 i * sizeof(struct stub_entry);
5387 } else {
5388 i = me->arch.stub_count++;
5389 BUG_ON(me->arch.stub_count > me->arch.stub_max);
5390- stub = me->module_core + me->arch.stub_offset +
5391+ stub = me->module_core_rx + me->arch.stub_offset +
5392 i * sizeof(struct stub_entry);
5393 }
5394
5395@@ -721,7 +743,7 @@ register_unwind_table(struct module *me,
5396
5397 table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr;
5398 end = table + sechdrs[me->arch.unwind_section].sh_size;
5399- gp = (Elf_Addr)me->module_core + me->arch.got_offset;
5400+ gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset;
5401
5402 DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
5403 me->arch.unwind_section, table, end, gp);
5404diff -urNp linux-2.6.17.11/arch/parisc/kernel/ptrace.c linux-2.6.17.11/arch/parisc/kernel/ptrace.c
5405--- linux-2.6.17.11/arch/parisc/kernel/ptrace.c 2006-08-07 00:18:54.000000000 -0400
5406+++ linux-2.6.17.11/arch/parisc/kernel/ptrace.c 2006-08-12 08:17:55.000000000 -0400
5407@@ -18,6 +18,7 @@
5408 #include <linux/security.h>
5409 #include <linux/compat.h>
5410 #include <linux/signal.h>
5411+#include <linux/grsecurity.h>
5412
5413 #include <asm/uaccess.h>
5414 #include <asm/pgtable.h>
5415diff -urNp linux-2.6.17.11/arch/parisc/kernel/sys_parisc.c linux-2.6.17.11/arch/parisc/kernel/sys_parisc.c
5416--- linux-2.6.17.11/arch/parisc/kernel/sys_parisc.c 2006-08-07 00:18:54.000000000 -0400
5417+++ linux-2.6.17.11/arch/parisc/kernel/sys_parisc.c 2006-08-12 08:17:55.000000000 -0400
5418@@ -105,7 +105,7 @@ unsigned long arch_get_unmapped_area(str
5419 if (len > TASK_SIZE)
5420 return -ENOMEM;
5421 if (!addr)
5422- addr = TASK_UNMAPPED_BASE;
5423+ addr = current->mm->mmap_base;
5424
5425 if (filp) {
5426 addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
5427diff -urNp linux-2.6.17.11/arch/parisc/kernel/traps.c linux-2.6.17.11/arch/parisc/kernel/traps.c
5428--- linux-2.6.17.11/arch/parisc/kernel/traps.c 2006-08-07 00:18:54.000000000 -0400
5429+++ linux-2.6.17.11/arch/parisc/kernel/traps.c 2006-08-12 08:17:55.000000000 -0400
5430@@ -711,9 +711,7 @@ void handle_interruption(int code, struc
5431
5432 down_read(&current->mm->mmap_sem);
5433 vma = find_vma(current->mm,regs->iaoq[0]);
5434- if (vma && (regs->iaoq[0] >= vma->vm_start)
5435- && (vma->vm_flags & VM_EXEC)) {
5436-
5437+ if (vma && (regs->iaoq[0] >= vma->vm_start)) {
5438 fault_address = regs->iaoq[0];
5439 fault_space = regs->iasq[0];
5440
5441diff -urNp linux-2.6.17.11/arch/parisc/mm/fault.c linux-2.6.17.11/arch/parisc/mm/fault.c
5442--- linux-2.6.17.11/arch/parisc/mm/fault.c 2006-08-07 00:18:54.000000000 -0400
5443+++ linux-2.6.17.11/arch/parisc/mm/fault.c 2006-08-12 08:17:55.000000000 -0400
5444@@ -16,6 +16,8 @@
5445 #include <linux/sched.h>
5446 #include <linux/interrupt.h>
5447 #include <linux/module.h>
5448+#include <linux/unistd.h>
5449+#include <linux/binfmts.h>
5450
5451 #include <asm/uaccess.h>
5452 #include <asm/traps.h>
5453@@ -57,7 +59,7 @@ DEFINE_PER_CPU(struct exception_data, ex
5454 static unsigned long
5455 parisc_acctyp(unsigned long code, unsigned int inst)
5456 {
5457- if (code == 6 || code == 16)
5458+ if (code == 6 || code == 7 || code == 16)
5459 return VM_EXEC;
5460
5461 switch (inst & 0xf0000000) {
5462@@ -143,6 +145,116 @@ parisc_acctyp(unsigned long code, unsign
5463 }
5464 #endif
5465
5466+#ifdef CONFIG_PAX_PAGEEXEC
5467+/*
5468+ * PaX: decide what to do with offenders (instruction_pointer(regs) = fault address)
5469+ *
5470+ * returns 1 when task should be killed
5471+ * 2 when rt_sigreturn trampoline was detected
5472+ * 3 when unpatched PLT trampoline was detected
5473+ */
5474+static int pax_handle_fetch_fault(struct pt_regs *regs)
5475+{
5476+
5477+#ifdef CONFIG_PAX_EMUPLT
5478+ int err;
5479+
5480+ do { /* PaX: unpatched PLT emulation */
5481+ unsigned int bl, depwi;
5482+
5483+ err = get_user(bl, (unsigned int*)instruction_pointer(regs));
5484+ err |= get_user(depwi, (unsigned int*)(instruction_pointer(regs)+4));
5485+
5486+ if (err)
5487+ break;
5488+
5489+ if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) {
5490+ unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12;
5491+
5492+ err = get_user(ldw, (unsigned int*)addr);
5493+ err |= get_user(bv, (unsigned int*)(addr+4));
5494+ err |= get_user(ldw2, (unsigned int*)(addr+8));
5495+
5496+ if (err)
5497+ break;
5498+
5499+ if (ldw == 0x0E801096U &&
5500+ bv == 0xEAC0C000U &&
5501+ ldw2 == 0x0E881095U)
5502+ {
5503+ unsigned int resolver, map;
5504+
5505+ err = get_user(resolver, (unsigned int*)(instruction_pointer(regs)+8));
5506+ err |= get_user(map, (unsigned int*)(instruction_pointer(regs)+12));
5507+ if (err)
5508+ break;
5509+
5510+ regs->gr[20] = instruction_pointer(regs)+8;
5511+ regs->gr[21] = map;
5512+ regs->gr[22] = resolver;
5513+ regs->iaoq[0] = resolver | 3UL;
5514+ regs->iaoq[1] = regs->iaoq[0] + 4;
5515+ return 3;
5516+ }
5517+ }
5518+ } while (0);
5519+#endif
5520+
5521+#ifdef CONFIG_PAX_EMUTRAMP
5522+
5523+#ifndef CONFIG_PAX_EMUSIGRT
5524+ if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
5525+ return 1;
5526+#endif
5527+
5528+ do { /* PaX: rt_sigreturn emulation */
5529+ unsigned int ldi1, ldi2, bel, nop;
5530+
5531+ err = get_user(ldi1, (unsigned int *)instruction_pointer(regs));
5532+ err |= get_user(ldi2, (unsigned int *)(instruction_pointer(regs)+4));
5533+ err |= get_user(bel, (unsigned int *)(instruction_pointer(regs)+8));
5534+ err |= get_user(nop, (unsigned int *)(instruction_pointer(regs)+12));
5535+
5536+ if (err)
5537+ break;
5538+
5539+ if ((ldi1 == 0x34190000U || ldi1 == 0x34190002U) &&
5540+ ldi2 == 0x3414015AU &&
5541+ bel == 0xE4008200U &&
5542+ nop == 0x08000240U)
5543+ {
5544+ regs->gr[25] = (ldi1 & 2) >> 1;
5545+ regs->gr[20] = __NR_rt_sigreturn;
5546+ regs->gr[31] = regs->iaoq[1] + 16;
5547+ regs->sr[0] = regs->iasq[1];
5548+ regs->iaoq[0] = 0x100UL;
5549+ regs->iaoq[1] = regs->iaoq[0] + 4;
5550+ regs->iasq[0] = regs->sr[2];
5551+ regs->iasq[1] = regs->sr[2];
5552+ return 2;
5553+ }
5554+ } while (0);
5555+#endif
5556+
5557+ return 1;
5558+}
5559+
5560+void pax_report_insns(void *pc, void *sp)
5561+{
5562+ unsigned long i;
5563+
5564+ printk(KERN_ERR "PAX: bytes at PC: ");
5565+ for (i = 0; i < 5; i++) {
5566+ unsigned int c;
5567+ if (get_user(c, (unsigned int*)pc+i))
5568+ printk("???????? ");
5569+ else
5570+ printk("%08x ", c);
5571+ }
5572+ printk("\n");
5573+}
5574+#endif
5575+
5576 void do_page_fault(struct pt_regs *regs, unsigned long code,
5577 unsigned long address)
5578 {
5579@@ -168,8 +280,33 @@ good_area:
5580
5581 acc_type = parisc_acctyp(code,regs->iir);
5582
5583- if ((vma->vm_flags & acc_type) != acc_type)
5584+ if ((vma->vm_flags & acc_type) != acc_type) {
5585+
5586+#ifdef CONFIG_PAX_PAGEEXEC
5587+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (acc_type & VM_EXEC) &&
5588+ (address & ~3UL) == instruction_pointer(regs))
5589+ {
5590+ up_read(&mm->mmap_sem);
5591+ switch(pax_handle_fetch_fault(regs)) {
5592+
5593+#ifdef CONFIG_PAX_EMUPLT
5594+ case 3:
5595+ return;
5596+#endif
5597+
5598+#ifdef CONFIG_PAX_EMUTRAMP
5599+ case 2:
5600+ return;
5601+#endif
5602+
5603+ }
5604+ pax_report_fault(regs, (void*)instruction_pointer(regs), (void*)regs->gr[30]);
5605+ do_exit(SIGKILL);
5606+ }
5607+#endif
5608+
5609 goto bad_area;
5610+ }
5611
5612 /*
5613 * If for any reason at all we couldn't handle the fault, make
5614diff -urNp linux-2.6.17.11/arch/powerpc/kernel/module_32.c linux-2.6.17.11/arch/powerpc/kernel/module_32.c
5615--- linux-2.6.17.11/arch/powerpc/kernel/module_32.c 2006-08-07 00:18:54.000000000 -0400
5616+++ linux-2.6.17.11/arch/powerpc/kernel/module_32.c 2006-08-12 08:17:55.000000000 -0400
5617@@ -123,7 +123,7 @@ int module_frob_arch_sections(Elf32_Ehdr
5618 me->arch.core_plt_section = i;
5619 }
5620 if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
5621- printk("Module doesn't contain .plt or .init.plt sections.\n");
5622+ printk("Module %s doesn't contain .plt or .init.plt sections.\n", me->name);
5623 return -ENOEXEC;
5624 }
5625
5626@@ -164,11 +164,16 @@ static uint32_t do_plt_call(void *locati
5627
5628 DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location);
5629 /* Init, or core PLT? */
5630- if (location >= mod->module_core
5631- && location < mod->module_core + mod->core_size)
5632+ if ((location >= mod->module_core_rx && location < mod->module_core_rx + mod->core_size_rx) ||
5633+ (location >= mod->module_core_rw && location < mod->module_core_rw + mod->core_size_rw))
5634 entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
5635- else
5636+ else if ((location >= mod->module_init_rx && location < mod->module_init_rx + mod->init_size_rx) ||
5637+ (location >= mod->module_init_rw && location < mod->module_init_rw + mod->init_size_rw))
5638 entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
5639+ else {
5640+ printk(KERN_ERR "%s: invalid R_PPC_REL24 entry found\n", mod->name);
5641+ return ~0UL;
5642+ }
5643
5644 /* Find this entry, or if that fails, the next avail. entry */
5645 while (entry->jump[0]) {
5646diff -urNp linux-2.6.17.11/arch/powerpc/mm/fault.c linux-2.6.17.11/arch/powerpc/mm/fault.c
5647--- linux-2.6.17.11/arch/powerpc/mm/fault.c 2006-08-07 00:18:54.000000000 -0400
5648+++ linux-2.6.17.11/arch/powerpc/mm/fault.c 2006-08-12 08:17:55.000000000 -0400
5649@@ -29,6 +29,7 @@
5650 #include <linux/highmem.h>
5651 #include <linux/module.h>
5652 #include <linux/kprobes.h>
5653+#include <linux/binfmts.h>
5654
5655 #include <asm/page.h>
5656 #include <asm/pgtable.h>
5657@@ -103,6 +104,38 @@ static void do_dabr(struct pt_regs *regs
5658 }
5659 #endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
5660
5661+#ifdef CONFIG_PAX_PAGEEXEC
5662+/*
5663+ * PaX: decide what to do with offenders (regs->nip = fault address)
5664+ *
5665+ * returns 1 when task should be killed
5666+ */
5667+static int pax_handle_fetch_fault(struct pt_regs *regs)
5668+{
5669+
5670+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT)
5671+ int err;
5672+#endif
5673+
5674+ return 1;
5675+}
5676+
5677+void pax_report_insns(void *pc, void *sp)
5678+{
5679+ unsigned long i;
5680+
5681+ printk(KERN_ERR "PAX: bytes at PC: ");
5682+ for (i = 0; i < 5; i++) {
5683+ unsigned int c;
5684+ if (get_user(c, (unsigned int*)pc+i))
5685+ printk("???????? ");
5686+ else
5687+ printk("%08x ", c);
5688+ }
5689+ printk("\n");
5690+}
5691+#endif
5692+
5693 /*
5694 * For 600- and 800-family processors, the error_code parameter is DSISR
5695 * for a data fault, SRR1 for an instruction fault. For 400-family processors
5696@@ -335,6 +368,19 @@ bad_area:
5697 bad_area_nosemaphore:
5698 /* User mode accesses cause a SIGSEGV */
5699 if (user_mode(regs)) {
5700+
5701+#ifdef CONFIG_PAX_PAGEEXEC
5702+ if (mm->pax_flags & MF_PAX_PAGEEXEC) {
5703+ if (is_exec && (error_code & DSISR_PROTFAULT)) {
5704+ switch (pax_handle_fetch_fault(regs)) {
5705+ }
5706+
5707+ pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]);
5708+ do_exit(SIGKILL);
5709+ }
5710+ }
5711+#endif
5712+
5713 _exception(SIGSEGV, regs, code, address);
5714 return 0;
5715 }
5716diff -urNp linux-2.6.17.11/arch/powerpc/mm/mmap.c linux-2.6.17.11/arch/powerpc/mm/mmap.c
5717--- linux-2.6.17.11/arch/powerpc/mm/mmap.c 2006-08-07 00:18:54.000000000 -0400
5718+++ linux-2.6.17.11/arch/powerpc/mm/mmap.c 2006-08-12 08:17:55.000000000 -0400
5719@@ -74,10 +74,22 @@ void arch_pick_mmap_layout(struct mm_str
5720 */
5721 if (mmap_is_legacy()) {
5722 mm->mmap_base = TASK_UNMAPPED_BASE;
5723+
5724+#ifdef CONFIG_PAX_RANDMMAP
5725+ if (mm->pax_flags & MF_PAX_RANDMMAP)
5726+ mm->mmap_base += mm->delta_mmap;
5727+#endif
5728+
5729 mm->get_unmapped_area = arch_get_unmapped_area;
5730 mm->unmap_area = arch_unmap_area;
5731 } else {
5732 mm->mmap_base = mmap_base();
5733+
5734+#ifdef CONFIG_PAX_RANDMMAP
5735+ if (mm->pax_flags & MF_PAX_RANDMMAP)
5736+ mm->mmap_base -= mm->delta_mmap;
5737+#endif
5738+
5739 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
5740 mm->unmap_area = arch_unmap_area_topdown;
5741 }
5742diff -urNp linux-2.6.17.11/arch/ppc/mm/fault.c linux-2.6.17.11/arch/ppc/mm/fault.c
5743--- linux-2.6.17.11/arch/ppc/mm/fault.c 2006-08-07 00:18:54.000000000 -0400
5744+++ linux-2.6.17.11/arch/ppc/mm/fault.c 2006-08-12 08:17:55.000000000 -0400
5745@@ -26,6 +26,11 @@
5746 #include <linux/interrupt.h>
5747 #include <linux/highmem.h>
5748 #include <linux/module.h>
5749+#include <linux/slab.h>
5750+#include <linux/pagemap.h>
5751+#include <linux/compiler.h>
5752+#include <linux/binfmts.h>
5753+#include <linux/unistd.h>
5754
5755 #include <asm/page.h>
5756 #include <asm/pgtable.h>
5757@@ -49,6 +54,364 @@ unsigned long pte_misses; /* updated by
5758 unsigned long pte_errors; /* updated by do_page_fault() */
5759 unsigned int probingmem;
5760
5761+#ifdef CONFIG_PAX_EMUSIGRT
5762+void pax_syscall_close(struct vm_area_struct * vma)
5763+{
5764+ vma->vm_mm->call_syscall = 0UL;
5765+}
5766+
5767+static struct page* pax_syscall_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
5768+{
5769+ struct page* page;
5770+ unsigned int *kaddr;
5771+
5772+ page = alloc_page(GFP_HIGHUSER);
5773+ if (!page)
5774+ return NOPAGE_OOM;
5775+
5776+ kaddr = kmap(page);
5777+ memset(kaddr, 0, PAGE_SIZE);
5778+ kaddr[0] = 0x44000002U; /* sc */
5779+ __flush_dcache_icache(kaddr);
5780+ kunmap(page);
5781+ if (type)
5782+ *type = VM_FAULT_MAJOR;
5783+ return page;
5784+}
5785+
5786+static struct vm_operations_struct pax_vm_ops = {
5787+ .close = pax_syscall_close,
5788+ .nopage = pax_syscall_nopage,
5789+};
5790+
5791+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
5792+{
5793+ int ret;
5794+
5795+ memset(vma, 0, sizeof(*vma));
5796+ vma->vm_mm = current->mm;
5797+ vma->vm_start = addr;
5798+ vma->vm_end = addr + PAGE_SIZE;
5799+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
5800+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
5801+ vma->vm_ops = &pax_vm_ops;
5802+
5803+ ret = insert_vm_struct(current->mm, vma);
5804+ if (ret)
5805+ return ret;
5806+
5807+ ++current->mm->total_vm;
5808+ return 0;
5809+}
5810+#endif
5811+
5812+#ifdef CONFIG_PAX_PAGEEXEC
5813+/*
5814+ * PaX: decide what to do with offenders (regs->nip = fault address)
5815+ *
5816+ * returns 1 when task should be killed
5817+ * 2 when patched GOT trampoline was detected
5818+ * 3 when patched PLT trampoline was detected
5819+ * 4 when unpatched PLT trampoline was detected
5820+ * 5 when sigreturn trampoline was detected
5821+ * 7 when rt_sigreturn trampoline was detected
5822+ */
5823+static int pax_handle_fetch_fault(struct pt_regs *regs)
5824+{
5825+
5826+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT)
5827+ int err;
5828+#endif
5829+
5830+#ifdef CONFIG_PAX_EMUPLT
5831+ do { /* PaX: patched GOT emulation */
5832+ unsigned int blrl;
5833+
5834+ err = get_user(blrl, (unsigned int*)regs->nip);
5835+
5836+ if (!err && blrl == 0x4E800021U) {
5837+ unsigned long temp = regs->nip;
5838+
5839+ regs->nip = regs->link & 0xFFFFFFFCUL;
5840+ regs->link = temp + 4UL;
5841+ return 2;
5842+ }
5843+ } while (0);
5844+
5845+ do { /* PaX: patched PLT emulation #1 */
5846+ unsigned int b;
5847+
5848+ err = get_user(b, (unsigned int *)regs->nip);
5849+
5850+ if (!err && (b & 0xFC000003U) == 0x48000000U) {
5851+ regs->nip += (((b | 0xFC000000UL) ^ 0x02000000UL) + 0x02000000UL);
5852+ return 3;
5853+ }
5854+ } while (0);
5855+
5856+ do { /* PaX: unpatched PLT emulation #1 */
5857+ unsigned int li, b;
5858+
5859+ err = get_user(li, (unsigned int *)regs->nip);
5860+ err |= get_user(b, (unsigned int *)(regs->nip+4));
5861+
5862+ if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) {
5863+ unsigned int rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr;
5864+ unsigned long addr = b | 0xFC000000UL;
5865+
5866+ addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL);
5867+ err = get_user(rlwinm, (unsigned int*)addr);
5868+ err |= get_user(add, (unsigned int*)(addr+4));
5869+ err |= get_user(li2, (unsigned int*)(addr+8));
5870+ err |= get_user(addis2, (unsigned int*)(addr+12));
5871+ err |= get_user(mtctr, (unsigned int*)(addr+16));
5872+ err |= get_user(li3, (unsigned int*)(addr+20));
5873+ err |= get_user(addis3, (unsigned int*)(addr+24));
5874+ err |= get_user(bctr, (unsigned int*)(addr+28));
5875+
5876+ if (err)
5877+ break;
5878+
5879+ if (rlwinm == 0x556C083CU &&
5880+ add == 0x7D6C5A14U &&
5881+ (li2 & 0xFFFF0000U) == 0x39800000U &&
5882+ (addis2 & 0xFFFF0000U) == 0x3D8C0000U &&
5883+ mtctr == 0x7D8903A6U &&
5884+ (li3 & 0xFFFF0000U) == 0x39800000U &&
5885+ (addis3 & 0xFFFF0000U) == 0x3D8C0000U &&
5886+ bctr == 0x4E800420U)
5887+ {
5888+ regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5889+ regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5890+ regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16;
5891+ regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5892+ regs->ctr += (addis2 & 0xFFFFU) << 16;
5893+ regs->nip = regs->ctr;
5894+ return 4;
5895+ }
5896+ }
5897+ } while (0);
5898+
5899+#if 0
5900+ do { /* PaX: unpatched PLT emulation #2 */
5901+ unsigned int lis, lwzu, b, bctr;
5902+
5903+ err = get_user(lis, (unsigned int *)regs->nip);
5904+ err |= get_user(lwzu, (unsigned int *)(regs->nip+4));
5905+ err |= get_user(b, (unsigned int *)(regs->nip+8));
5906+ err |= get_user(bctr, (unsigned int *)(regs->nip+12));
5907+
5908+ if (err)
5909+ break;
5910+
5911+ if ((lis & 0xFFFF0000U) == 0x39600000U &&
5912+ (lwzu & 0xU) == 0xU &&
5913+ (b & 0xFC000003U) == 0x48000000U &&
5914+ bctr == 0x4E800420U)
5915+ {
5916+ unsigned int addis, addi, rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr;
5917+ unsigned long addr = b | 0xFC000000UL;
5918+
5919+ addr = regs->nip + 12 + ((addr ^ 0x02000000UL) + 0x02000000UL);
5920+ err = get_user(addis, (unsigned int*)addr);
5921+ err |= get_user(addi, (unsigned int*)(addr+4));
5922+ err |= get_user(rlwinm, (unsigned int*)(addr+8));
5923+ err |= get_user(add, (unsigned int*)(addr+12));
5924+ err |= get_user(li2, (unsigned int*)(addr+16));
5925+ err |= get_user(addis2, (unsigned int*)(addr+20));
5926+ err |= get_user(mtctr, (unsigned int*)(addr+24));
5927+ err |= get_user(li3, (unsigned int*)(addr+28));
5928+ err |= get_user(addis3, (unsigned int*)(addr+32));
5929+ err |= get_user(bctr, (unsigned int*)(addr+36));
5930+
5931+ if (err)
5932+ break;
5933+
5934+ if ((addis & 0xFFFF0000U) == 0x3D6B0000U &&
5935+ (addi & 0xFFFF0000U) == 0x396B0000U &&
5936+ rlwinm == 0x556C083CU &&
5937+ add == 0x7D6C5A14U &&
5938+ (li2 & 0xFFFF0000U) == 0x39800000U &&
5939+ (addis2 & 0xFFFF0000U) == 0x3D8C0000U &&
5940+ mtctr == 0x7D8903A6U &&
5941+ (li3 & 0xFFFF0000U) == 0x39800000U &&
5942+ (addis3 & 0xFFFF0000U) == 0x3D8C0000U &&
5943+ bctr == 0x4E800420U)
5944+ {
5945+ regs->gpr[PT_R11] =
5946+ regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5947+ regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5948+ regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16;
5949+ regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5950+ regs->ctr += (addis2 & 0xFFFFU) << 16;
5951+ regs->nip = regs->ctr;
5952+ return 4;
5953+ }
5954+ }
5955+ } while (0);
5956+#endif
5957+
5958+ do { /* PaX: unpatched PLT emulation #3 */
5959+ unsigned int li, b;
5960+
5961+ err = get_user(li, (unsigned int *)regs->nip);
5962+ err |= get_user(b, (unsigned int *)(regs->nip+4));
5963+
5964+ if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) {
5965+ unsigned int addis, lwz, mtctr, bctr;
5966+ unsigned long addr = b | 0xFC000000UL;
5967+
5968+ addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL);
5969+ err = get_user(addis, (unsigned int*)addr);
5970+ err |= get_user(lwz, (unsigned int*)(addr+4));
5971+ err |= get_user(mtctr, (unsigned int*)(addr+8));
5972+ err |= get_user(bctr, (unsigned int*)(addr+12));
5973+
5974+ if (err)
5975+ break;
5976+
5977+ if ((addis & 0xFFFF0000U) == 0x3D6B0000U &&
5978+ (lwz & 0xFFFF0000U) == 0x816B0000U &&
5979+ mtctr == 0x7D6903A6U &&
5980+ bctr == 0x4E800420U)
5981+ {
5982+ unsigned int r11;
5983+
5984+ addr = (addis << 16) + (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5985+ addr += (((lwz | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5986+
5987+ err = get_user(r11, (unsigned int*)addr);
5988+ if (err)
5989+ break;
5990+
5991+ regs->gpr[PT_R11] = r11;
5992+ regs->ctr = r11;
5993+ regs->nip = r11;
5994+ return 4;
5995+ }
5996+ }
5997+ } while (0);
5998+#endif
5999+
6000+#ifdef CONFIG_PAX_EMUSIGRT
6001+ do { /* PaX: sigreturn emulation */
6002+ unsigned int li, sc;
6003+
6004+ err = get_user(li, (unsigned int *)regs->nip);
6005+ err |= get_user(sc, (unsigned int *)(regs->nip+4));
6006+
6007+ if (!err && li == 0x38000000U + __NR_sigreturn && sc == 0x44000002U) {
6008+ struct vm_area_struct *vma;
6009+ unsigned long call_syscall;
6010+
6011+ down_read(&current->mm->mmap_sem);
6012+ call_syscall = current->mm->call_syscall;
6013+ up_read(&current->mm->mmap_sem);
6014+ if (likely(call_syscall))
6015+ goto emulate;
6016+
6017+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
6018+
6019+ down_write(&current->mm->mmap_sem);
6020+ if (current->mm->call_syscall) {
6021+ call_syscall = current->mm->call_syscall;
6022+ up_write(&current->mm->mmap_sem);
6023+ if (vma) kmem_cache_free(vm_area_cachep, vma);
6024+ goto emulate;
6025+ }
6026+
6027+ call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
6028+ if (!vma || (call_syscall & ~PAGE_MASK)) {
6029+ up_write(&current->mm->mmap_sem);
6030+ if (vma) kmem_cache_free(vm_area_cachep, vma);
6031+ return 1;
6032+ }
6033+
6034+ if (pax_insert_vma(vma, call_syscall)) {
6035+ up_write(&current->mm->mmap_sem);
6036+ kmem_cache_free(vm_area_cachep, vma);
6037+ return 1;
6038+ }
6039+
6040+ current->mm->call_syscall = call_syscall;
6041+ up_write(&current->mm->mmap_sem);
6042+
6043+emulate:
6044+ regs->gpr[PT_R0] = __NR_sigreturn;
6045+ regs->nip = call_syscall;
6046+ return 5;
6047+ }
6048+ } while (0);
6049+
6050+ do { /* PaX: rt_sigreturn emulation */
6051+ unsigned int li, sc;
6052+
6053+ err = get_user(li, (unsigned int *)regs->nip);
6054+ err |= get_user(sc, (unsigned int *)(regs->nip+4));
6055+
6056+ if (!err && li == 0x38000000U + __NR_rt_sigreturn && sc == 0x44000002U) {
6057+ struct vm_area_struct *vma;
6058+ unsigned int call_syscall;
6059+
6060+ down_read(&current->mm->mmap_sem);
6061+ call_syscall = current->mm->call_syscall;
6062+ up_read(&current->mm->mmap_sem);
6063+ if (likely(call_syscall))
6064+ goto rt_emulate;
6065+
6066+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
6067+
6068+ down_write(&current->mm->mmap_sem);
6069+ if (current->mm->call_syscall) {
6070+ call_syscall = current->mm->call_syscall;
6071+ up_write(&current->mm->mmap_sem);
6072+ if (vma) kmem_cache_free(vm_area_cachep, vma);
6073+ goto rt_emulate;
6074+ }
6075+
6076+ call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
6077+ if (!vma || (call_syscall & ~PAGE_MASK)) {
6078+ up_write(&current->mm->mmap_sem);
6079+ if (vma) kmem_cache_free(vm_area_cachep, vma);
6080+ return 1;
6081+ }
6082+
6083+ if (pax_insert_vma(vma, call_syscall)) {
6084+ up_write(&current->mm->mmap_sem);
6085+ kmem_cache_free(vm_area_cachep, vma);
6086+ return 1;
6087+ }
6088+
6089+ current->mm->call_syscall = call_syscall;
6090+ up_write(&current->mm->mmap_sem);
6091+
6092+rt_emulate:
6093+ regs->gpr[PT_R0] = __NR_rt_sigreturn;
6094+ regs->nip = call_syscall;
6095+ return 6;
6096+ }
6097+ } while (0);
6098+#endif
6099+
6100+ return 1;
6101+}
6102+
6103+void pax_report_insns(void *pc, void *sp)
6104+{
6105+ unsigned long i;
6106+
6107+ printk(KERN_ERR "PAX: bytes at PC: ");
6108+ for (i = 0; i < 5; i++) {
6109+ unsigned int c;
6110+ if (get_user(c, (unsigned int*)pc+i))
6111+ printk("???????? ");
6112+ else
6113+ printk("%08x ", c);
6114+ }
6115+ printk("\n");
6116+}
6117+#endif
6118+
6119 /*
6120 * Check whether the instruction at regs->nip is a store using
6121 * an update addressing form which will update r1.
6122@@ -109,7 +472,7 @@ int do_page_fault(struct pt_regs *regs,
6123 * indicate errors in DSISR but can validly be set in SRR1.
6124 */
6125 if (TRAP(regs) == 0x400)
6126- error_code &= 0x48200000;
6127+ error_code &= 0x58200000;
6128 else
6129 is_write = error_code & 0x02000000;
6130 #endif /* CONFIG_4xx || CONFIG_BOOKE */
6131@@ -204,15 +567,14 @@ good_area:
6132 pte_t *ptep;
6133 pmd_t *pmdp;
6134
6135-#if 0
6136+#if 1
6137 /* It would be nice to actually enforce the VM execute
6138 permission on CPUs which can do so, but far too
6139 much stuff in userspace doesn't get the permissions
6140 right, so we let any page be executed for now. */
6141 if (! (vma->vm_flags & VM_EXEC))
6142 goto bad_area;
6143-#endif
6144-
6145+#else
6146 /* Since 4xx/Book-E supports per-page execute permission,
6147 * we lazily flush dcache to icache. */
6148 ptep = NULL;
6149@@ -235,6 +597,7 @@ good_area:
6150 pte_unmap_unlock(ptep, ptl);
6151 }
6152 #endif
6153+#endif
6154 /* a read */
6155 } else {
6156 /* protection fault */
6157@@ -280,6 +643,33 @@ bad_area:
6158
6159 /* User mode accesses cause a SIGSEGV */
6160 if (user_mode(regs)) {
6161+
6162+#ifdef CONFIG_PAX_PAGEEXEC
6163+ if (mm->pax_flags & MF_PAX_PAGEEXEC) {
6164+ if ((TRAP(regs) == 0x400) && (regs->nip == address)) {
6165+ switch (pax_handle_fetch_fault(regs)) {
6166+
6167+#ifdef CONFIG_PAX_EMUPLT
6168+ case 2:
6169+ case 3:
6170+ case 4:
6171+ return 0;
6172+#endif
6173+
6174+#ifdef CONFIG_PAX_EMUSIGRT
6175+ case 5:
6176+ case 6:
6177+ return 0;
6178+#endif
6179+
6180+ }
6181+
6182+ pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]);
6183+ do_exit(SIGKILL);
6184+ }
6185+ }
6186+#endif
6187+
6188 _exception(SIGSEGV, regs, code, address);
6189 return 0;
6190 }
6191diff -urNp linux-2.6.17.11/arch/s390/kernel/module.c linux-2.6.17.11/arch/s390/kernel/module.c
6192--- linux-2.6.17.11/arch/s390/kernel/module.c 2006-08-07 00:18:54.000000000 -0400
6193+++ linux-2.6.17.11/arch/s390/kernel/module.c 2006-08-12 08:17:55.000000000 -0400
6194@@ -164,11 +164,11 @@ module_frob_arch_sections(Elf_Ehdr *hdr,
6195
6196 /* Increase core size by size of got & plt and set start
6197 offsets for got and plt. */
6198- me->core_size = ALIGN(me->core_size, 4);
6199- me->arch.got_offset = me->core_size;
6200- me->core_size += me->arch.got_size;
6201- me->arch.plt_offset = me->core_size;
6202- me->core_size += me->arch.plt_size;
6203+ me->core_size_rw = ALIGN(me->core_size_rw, 4);
6204+ me->arch.got_offset = me->core_size_rw;
6205+ me->core_size_rw += me->arch.got_size;
6206+ me->arch.plt_offset = me->core_size_rx;
6207+ me->core_size_rx += me->arch.plt_size;
6208 return 0;
6209 }
6210
6211@@ -254,7 +254,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6212 if (info->got_initialized == 0) {
6213 Elf_Addr *gotent;
6214
6215- gotent = me->module_core + me->arch.got_offset +
6216+ gotent = me->module_core_rw + me->arch.got_offset +
6217 info->got_offset;
6218 *gotent = val;
6219 info->got_initialized = 1;
6220@@ -278,7 +278,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6221 else if (r_type == R_390_GOTENT ||
6222 r_type == R_390_GOTPLTENT)
6223 *(unsigned int *) loc =
6224- (val + (Elf_Addr) me->module_core - loc) >> 1;
6225+ (val + (Elf_Addr) me->module_core_rw - loc) >> 1;
6226 else if (r_type == R_390_GOT64 ||
6227 r_type == R_390_GOTPLT64)
6228 *(unsigned long *) loc = val;
6229@@ -292,7 +292,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6230 case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */
6231 if (info->plt_initialized == 0) {
6232 unsigned int *ip;
6233- ip = me->module_core + me->arch.plt_offset +
6234+ ip = me->module_core_rx + me->arch.plt_offset +
6235 info->plt_offset;
6236 #ifndef CONFIG_64BIT
6237 ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */
6238@@ -314,7 +314,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6239 val = me->arch.plt_offset - me->arch.got_offset +
6240 info->plt_offset + rela->r_addend;
6241 else
6242- val = (Elf_Addr) me->module_core +
6243+ val = (Elf_Addr) me->module_core_rx +
6244 me->arch.plt_offset + info->plt_offset +
6245 rela->r_addend - loc;
6246 if (r_type == R_390_PLT16DBL)
6247@@ -334,7 +334,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6248 case R_390_GOTOFF32: /* 32 bit offset to GOT. */
6249 case R_390_GOTOFF64: /* 64 bit offset to GOT. */
6250 val = val + rela->r_addend -
6251- ((Elf_Addr) me->module_core + me->arch.got_offset);
6252+ ((Elf_Addr) me->module_core_rw + me->arch.got_offset);
6253 if (r_type == R_390_GOTOFF16)
6254 *(unsigned short *) loc = val;
6255 else if (r_type == R_390_GOTOFF32)
6256@@ -344,7 +344,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6257 break;
6258 case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */
6259 case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */
6260- val = (Elf_Addr) me->module_core + me->arch.got_offset +
6261+ val = (Elf_Addr) me->module_core_rw + me->arch.got_offset +
6262 rela->r_addend - loc;
6263 if (r_type == R_390_GOTPC)
6264 *(unsigned int *) loc = val;
6265diff -urNp linux-2.6.17.11/arch/sparc/kernel/ptrace.c linux-2.6.17.11/arch/sparc/kernel/ptrace.c
6266--- linux-2.6.17.11/arch/sparc/kernel/ptrace.c 2006-08-07 00:18:54.000000000 -0400
6267+++ linux-2.6.17.11/arch/sparc/kernel/ptrace.c 2006-08-12 08:17:55.000000000 -0400
6268@@ -19,6 +19,7 @@
6269 #include <linux/security.h>
6270 #include <linux/signal.h>
6271 #include <linux/vs_pid.h>
6272+#include <linux/grsecurity.h>
6273
6274 #include <asm/pgtable.h>
6275 #include <asm/system.h>
6276@@ -300,6 +301,11 @@ asmlinkage void do_ptrace(struct pt_regs
6277 goto out;
6278 }
6279
6280+ if (gr_handle_ptrace(child, request)) {
6281+ pt_error_return(regs, EPERM);
6282+ goto out_tsk;
6283+ }
6284+
6285 if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
6286 || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
6287 if (ptrace_attach(child)) {
6288diff -urNp linux-2.6.17.11/arch/sparc/kernel/sys_sparc.c linux-2.6.17.11/arch/sparc/kernel/sys_sparc.c
6289--- linux-2.6.17.11/arch/sparc/kernel/sys_sparc.c 2006-08-23 19:30:00.000000000 -0400
6290+++ linux-2.6.17.11/arch/sparc/kernel/sys_sparc.c 2006-08-23 19:30:12.000000000 -0400
6291@@ -56,7 +56,7 @@ unsigned long arch_get_unmapped_area(str
6292 if (ARCH_SUN4C_SUN4 && len > 0x20000000)
6293 return -ENOMEM;
6294 if (!addr)
6295- addr = TASK_UNMAPPED_BASE;
6296+ addr = current->mm->mmap_base;
6297
6298 if (flags & MAP_SHARED)
6299 addr = COLOUR_ALIGN(addr);
6300diff -urNp linux-2.6.17.11/arch/sparc/Makefile linux-2.6.17.11/arch/sparc/Makefile
6301--- linux-2.6.17.11/arch/sparc/Makefile 2006-08-07 00:18:54.000000000 -0400
6302+++ linux-2.6.17.11/arch/sparc/Makefile 2006-08-12 08:17:55.000000000 -0400
6303@@ -34,7 +34,7 @@ libs-y += arch/sparc/prom/ arch/sparc/li
6304 # Renaming is done to avoid confusing pattern matching rules in 2.5.45 (multy-)
6305 INIT_Y := $(patsubst %/, %/built-in.o, $(init-y))
6306 CORE_Y := $(core-y)
6307-CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
6308+CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
6309 CORE_Y := $(patsubst %/, %/built-in.o, $(CORE_Y))
6310 DRIVERS_Y := $(patsubst %/, %/built-in.o, $(drivers-y))
6311 NET_Y := $(patsubst %/, %/built-in.o, $(net-y))
6312diff -urNp linux-2.6.17.11/arch/sparc/mm/fault.c linux-2.6.17.11/arch/sparc/mm/fault.c
6313--- linux-2.6.17.11/arch/sparc/mm/fault.c 2006-08-07 00:18:54.000000000 -0400
6314+++ linux-2.6.17.11/arch/sparc/mm/fault.c 2006-08-12 08:17:55.000000000 -0400
6315@@ -21,6 +21,10 @@
6316 #include <linux/smp_lock.h>
6317 #include <linux/interrupt.h>
6318 #include <linux/module.h>
6319+#include <linux/slab.h>
6320+#include <linux/pagemap.h>
6321+#include <linux/compiler.h>
6322+#include <linux/binfmts.h>
6323
6324 #include <asm/system.h>
6325 #include <asm/page.h>
6326@@ -217,6 +221,252 @@ static unsigned long compute_si_addr(str
6327 return safe_compute_effective_address(regs, insn);
6328 }
6329
6330+#ifdef CONFIG_PAX_PAGEEXEC
6331+void pax_emuplt_close(struct vm_area_struct * vma)
6332+{
6333+ vma->vm_mm->call_dl_resolve = 0UL;
6334+}
6335+
6336+static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
6337+{
6338+ struct page* page;
6339+ unsigned int *kaddr;
6340+
6341+ page = alloc_page(GFP_HIGHUSER);
6342+ if (!page)
6343+ return NOPAGE_OOM;
6344+
6345+ kaddr = kmap(page);
6346+ memset(kaddr, 0, PAGE_SIZE);
6347+ kaddr[0] = 0x9DE3BFA8U; /* save */
6348+ flush_dcache_page(page);
6349+ kunmap(page);
6350+ if (type)
6351+ *type = VM_FAULT_MAJOR;
6352+
6353+ return page;
6354+}
6355+
6356+static struct vm_operations_struct pax_vm_ops = {
6357+ .close = pax_emuplt_close,
6358+ .nopage = pax_emuplt_nopage,
6359+};
6360+
6361+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
6362+{
6363+ int ret;
6364+
6365+ memset(vma, 0, sizeof(*vma));
6366+ vma->vm_mm = current->mm;
6367+ vma->vm_start = addr;
6368+ vma->vm_end = addr + PAGE_SIZE;
6369+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
6370+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
6371+ vma->vm_ops = &pax_vm_ops;
6372+
6373+ ret = insert_vm_struct(current->mm, vma);
6374+ if (ret)
6375+ return ret;
6376+
6377+ ++current->mm->total_vm;
6378+ return 0;
6379+}
6380+
6381+/*
6382+ * PaX: decide what to do with offenders (regs->pc = fault address)
6383+ *
6384+ * returns 1 when task should be killed
6385+ * 2 when patched PLT trampoline was detected
6386+ * 3 when unpatched PLT trampoline was detected
6387+ */
6388+static int pax_handle_fetch_fault(struct pt_regs *regs)
6389+{
6390+
6391+#ifdef CONFIG_PAX_EMUPLT
6392+ int err;
6393+
6394+ do { /* PaX: patched PLT emulation #1 */
6395+ unsigned int sethi1, sethi2, jmpl;
6396+
6397+ err = get_user(sethi1, (unsigned int*)regs->pc);
6398+ err |= get_user(sethi2, (unsigned int*)(regs->pc+4));
6399+ err |= get_user(jmpl, (unsigned int*)(regs->pc+8));
6400+
6401+ if (err)
6402+ break;
6403+
6404+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
6405+ (sethi2 & 0xFFC00000U) == 0x03000000U &&
6406+ (jmpl & 0xFFFFE000U) == 0x81C06000U)
6407+ {
6408+ unsigned int addr;
6409+
6410+ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
6411+ addr = regs->u_regs[UREG_G1];
6412+ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
6413+ regs->pc = addr;
6414+ regs->npc = addr+4;
6415+ return 2;
6416+ }
6417+ } while (0);
6418+
6419+ { /* PaX: patched PLT emulation #2 */
6420+ unsigned int ba;
6421+
6422+ err = get_user(ba, (unsigned int*)regs->pc);
6423+
6424+ if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
6425+ unsigned int addr;
6426+
6427+ addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
6428+ regs->pc = addr;
6429+ regs->npc = addr+4;
6430+ return 2;
6431+ }
6432+ }
6433+
6434+ do { /* PaX: patched PLT emulation #3 */
6435+ unsigned int sethi, jmpl, nop;
6436+
6437+ err = get_user(sethi, (unsigned int*)regs->pc);
6438+ err |= get_user(jmpl, (unsigned int*)(regs->pc+4));
6439+ err |= get_user(nop, (unsigned int*)(regs->pc+8));
6440+
6441+ if (err)
6442+ break;
6443+
6444+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
6445+ (jmpl & 0xFFFFE000U) == 0x81C06000U &&
6446+ nop == 0x01000000U)
6447+ {
6448+ unsigned int addr;
6449+
6450+ addr = (sethi & 0x003FFFFFU) << 10;
6451+ regs->u_regs[UREG_G1] = addr;
6452+ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
6453+ regs->pc = addr;
6454+ regs->npc = addr+4;
6455+ return 2;
6456+ }
6457+ } while (0);
6458+
6459+ do { /* PaX: unpatched PLT emulation step 1 */
6460+ unsigned int sethi, ba, nop;
6461+
6462+ err = get_user(sethi, (unsigned int*)regs->pc);
6463+ err |= get_user(ba, (unsigned int*)(regs->pc+4));
6464+ err |= get_user(nop, (unsigned int*)(regs->pc+8));
6465+
6466+ if (err)
6467+ break;
6468+
6469+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
6470+ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
6471+ nop == 0x01000000U)
6472+ {
6473+ unsigned int addr, save, call;
6474+
6475+ if ((ba & 0xFFC00000U) == 0x30800000U)
6476+ addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
6477+ else
6478+ addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2);
6479+
6480+ err = get_user(save, (unsigned int*)addr);
6481+ err |= get_user(call, (unsigned int*)(addr+4));
6482+ err |= get_user(nop, (unsigned int*)(addr+8));
6483+ if (err)
6484+ break;
6485+
6486+ if (save == 0x9DE3BFA8U &&
6487+ (call & 0xC0000000U) == 0x40000000U &&
6488+ nop == 0x01000000U)
6489+ {
6490+ struct vm_area_struct *vma;
6491+ unsigned long call_dl_resolve;
6492+
6493+ down_read(&current->mm->mmap_sem);
6494+ call_dl_resolve = current->mm->call_dl_resolve;
6495+ up_read(&current->mm->mmap_sem);
6496+ if (likely(call_dl_resolve))
6497+ goto emulate;
6498+
6499+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
6500+
6501+ down_write(&current->mm->mmap_sem);
6502+ if (current->mm->call_dl_resolve) {
6503+ call_dl_resolve = current->mm->call_dl_resolve;
6504+ up_write(&current->mm->mmap_sem);
6505+ if (vma) kmem_cache_free(vm_area_cachep, vma);
6506+ goto emulate;
6507+ }
6508+
6509+ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
6510+ if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
6511+ up_write(&current->mm->mmap_sem);
6512+ if (vma) kmem_cache_free(vm_area_cachep, vma);
6513+ return 1;
6514+ }
6515+
6516+ if (pax_insert_vma(vma, call_dl_resolve)) {
6517+ up_write(&current->mm->mmap_sem);
6518+ kmem_cache_free(vm_area_cachep, vma);
6519+ return 1;
6520+ }
6521+
6522+ current->mm->call_dl_resolve = call_dl_resolve;
6523+ up_write(&current->mm->mmap_sem);
6524+
6525+emulate:
6526+ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
6527+ regs->pc = call_dl_resolve;
6528+ regs->npc = addr+4;
6529+ return 3;
6530+ }
6531+ }
6532+ } while (0);
6533+
6534+ do { /* PaX: unpatched PLT emulation step 2 */
6535+ unsigned int save, call, nop;
6536+
6537+ err = get_user(save, (unsigned int*)(regs->pc-4));
6538+ err |= get_user(call, (unsigned int*)regs->pc);
6539+ err |= get_user(nop, (unsigned int*)(regs->pc+4));
6540+ if (err)
6541+ break;
6542+
6543+ if (save == 0x9DE3BFA8U &&
6544+ (call & 0xC0000000U) == 0x40000000U &&
6545+ nop == 0x01000000U)
6546+ {
6547+ unsigned int dl_resolve = regs->pc + ((((call | 0xC0000000U) ^ 0x20000000U) + 0x20000000U) << 2);
6548+
6549+ regs->u_regs[UREG_RETPC] = regs->pc;
6550+ regs->pc = dl_resolve;
6551+ regs->npc = dl_resolve+4;
6552+ return 3;
6553+ }
6554+ } while (0);
6555+#endif
6556+
6557+ return 1;
6558+}
6559+
6560+void pax_report_insns(void *pc, void *sp)
6561+{
6562+ unsigned long i;
6563+
6564+ printk(KERN_ERR "PAX: bytes at PC: ");
6565+ for (i = 0; i < 5; i++) {
6566+ unsigned int c;
6567+ if (get_user(c, (unsigned int*)pc+i))
6568+ printk("???????? ");
6569+ else
6570+ printk("%08x ", c);
6571+ }
6572+ printk("\n");
6573+}
6574+#endif
6575+
6576 asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
6577 unsigned long address)
6578 {
6579@@ -280,6 +530,24 @@ good_area:
6580 if(!(vma->vm_flags & VM_WRITE))
6581 goto bad_area;
6582 } else {
6583+
6584+#ifdef CONFIG_PAX_PAGEEXEC
6585+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && text_fault && !(vma->vm_flags & VM_EXEC)) {
6586+ up_read(&mm->mmap_sem);
6587+ switch (pax_handle_fetch_fault(regs)) {
6588+
6589+#ifdef CONFIG_PAX_EMUPLT
6590+ case 2:
6591+ case 3:
6592+ return;
6593+#endif
6594+
6595+ }
6596+ pax_report_fault(regs, (void*)regs->pc, (void*)regs->u_regs[UREG_FP]);
6597+ do_exit(SIGKILL);
6598+ }
6599+#endif
6600+
6601 /* Allow reads even for write-only mappings */
6602 if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
6603 goto bad_area;
6604diff -urNp linux-2.6.17.11/arch/sparc/mm/init.c linux-2.6.17.11/arch/sparc/mm/init.c
6605--- linux-2.6.17.11/arch/sparc/mm/init.c 2006-08-07 00:18:54.000000000 -0400
6606+++ linux-2.6.17.11/arch/sparc/mm/init.c 2006-08-12 08:17:55.000000000 -0400
6607@@ -333,17 +333,17 @@ void __init paging_init(void)
6608
6609 /* Initialize the protection map with non-constant, MMU dependent values. */
6610 protection_map[0] = PAGE_NONE;
6611- protection_map[1] = PAGE_READONLY;
6612- protection_map[2] = PAGE_COPY;
6613- protection_map[3] = PAGE_COPY;
6614+ protection_map[1] = PAGE_READONLY_NOEXEC;
6615+ protection_map[2] = PAGE_COPY_NOEXEC;
6616+ protection_map[3] = PAGE_COPY_NOEXEC;
6617 protection_map[4] = PAGE_READONLY;
6618 protection_map[5] = PAGE_READONLY;
6619 protection_map[6] = PAGE_COPY;
6620 protection_map[7] = PAGE_COPY;
6621 protection_map[8] = PAGE_NONE;
6622- protection_map[9] = PAGE_READONLY;
6623- protection_map[10] = PAGE_SHARED;
6624- protection_map[11] = PAGE_SHARED;
6625+ protection_map[9] = PAGE_READONLY_NOEXEC;
6626+ protection_map[10] = PAGE_SHARED_NOEXEC;
6627+ protection_map[11] = PAGE_SHARED_NOEXEC;
6628 protection_map[12] = PAGE_READONLY;
6629 protection_map[13] = PAGE_READONLY;
6630 protection_map[14] = PAGE_SHARED;
6631diff -urNp linux-2.6.17.11/arch/sparc/mm/srmmu.c linux-2.6.17.11/arch/sparc/mm/srmmu.c
6632--- linux-2.6.17.11/arch/sparc/mm/srmmu.c 2006-08-07 00:18:54.000000000 -0400
6633+++ linux-2.6.17.11/arch/sparc/mm/srmmu.c 2006-08-12 08:17:55.000000000 -0400
6634@@ -2161,6 +2161,13 @@ void __init ld_mmu_srmmu(void)
6635 BTFIXUPSET_INT(page_shared, pgprot_val(SRMMU_PAGE_SHARED));
6636 BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY));
6637 BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY));
6638+
6639+#ifdef CONFIG_PAX_PAGEEXEC
6640+ BTFIXUPSET_INT(page_shared_noexec, pgprot_val(SRMMU_PAGE_SHARED_NOEXEC));
6641+ BTFIXUPSET_INT(page_copy_noexec, pgprot_val(SRMMU_PAGE_COPY_NOEXEC));
6642+ BTFIXUPSET_INT(page_readonly_noexec, pgprot_val(SRMMU_PAGE_RDONLY_NOEXEC));
6643+#endif
6644+
6645 BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL));
6646 page_kernel = pgprot_val(SRMMU_PAGE_KERNEL);
6647
6648diff -urNp linux-2.6.17.11/arch/sparc64/kernel/ptrace.c linux-2.6.17.11/arch/sparc64/kernel/ptrace.c
6649--- linux-2.6.17.11/arch/sparc64/kernel/ptrace.c 2006-08-07 00:18:54.000000000 -0400
6650+++ linux-2.6.17.11/arch/sparc64/kernel/ptrace.c 2006-08-12 08:17:55.000000000 -0400
6651@@ -22,6 +22,7 @@
6652 #include <linux/audit.h>
6653 #include <linux/signal.h>
6654 #include <linux/vs_pid.h>
6655+#include <linux/grsecurity.h>
6656
6657 #include <asm/asi.h>
6658 #include <asm/pgtable.h>
6659@@ -213,6 +214,11 @@ asmlinkage void do_ptrace(struct pt_regs
6660 goto out;
6661 }
6662
6663+ if (gr_handle_ptrace(child, (long)request)) {
6664+ pt_error_return(regs, EPERM);
6665+ goto out_tsk;
6666+ }
6667+
6668 if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
6669 || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
6670 if (ptrace_attach(child)) {
6671diff -urNp linux-2.6.17.11/arch/sparc64/kernel/sys_sparc.c linux-2.6.17.11/arch/sparc64/kernel/sys_sparc.c
6672--- linux-2.6.17.11/arch/sparc64/kernel/sys_sparc.c 2006-08-23 19:30:00.000000000 -0400
6673+++ linux-2.6.17.11/arch/sparc64/kernel/sys_sparc.c 2006-08-23 19:30:12.000000000 -0400
6674@@ -140,6 +140,10 @@ unsigned long arch_get_unmapped_area(str
6675 if (filp || (flags & MAP_SHARED))
6676 do_color_align = 1;
6677
6678+#ifdef CONFIG_PAX_RANDMMAP
6679+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
6680+#endif
6681+
6682 if (addr) {
6683 if (do_color_align)
6684 addr = COLOUR_ALIGN(addr, pgoff);
6685@@ -153,9 +157,9 @@ unsigned long arch_get_unmapped_area(str
6686 }
6687
6688 if (len > mm->cached_hole_size) {
6689- start_addr = addr = mm->free_area_cache;
6690+ start_addr = addr = mm->free_area_cache;
6691 } else {
6692- start_addr = addr = TASK_UNMAPPED_BASE;
6693+ start_addr = addr = mm->mmap_base;
6694 mm->cached_hole_size = 0;
6695 }
6696
6697@@ -175,8 +179,8 @@ full_search:
6698 vma = find_vma(mm, VA_EXCLUDE_END);
6699 }
6700 if (unlikely(task_size < addr)) {
6701- if (start_addr != TASK_UNMAPPED_BASE) {
6702- start_addr = addr = TASK_UNMAPPED_BASE;
6703+ if (start_addr != mm->mmap_base) {
6704+ start_addr = addr = mm->mmap_base;
6705 mm->cached_hole_size = 0;
6706 goto full_search;
6707 }
6708@@ -379,6 +383,12 @@ void arch_pick_mmap_layout(struct mm_str
6709 current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY ||
6710 sysctl_legacy_va_layout) {
6711 mm->mmap_base = TASK_UNMAPPED_BASE + random_factor;
6712+
6713+#ifdef CONFIG_PAX_RANDMMAP
6714+ if (mm->pax_flags & MF_PAX_RANDMMAP)
6715+ mm->mmap_base += mm->delta_mmap;
6716+#endif
6717+
6718 mm->get_unmapped_area = arch_get_unmapped_area;
6719 mm->unmap_area = arch_unmap_area;
6720 } else {
6721@@ -393,6 +403,12 @@ void arch_pick_mmap_layout(struct mm_str
6722 gap = (task_size / 6 * 5);
6723
6724 mm->mmap_base = PAGE_ALIGN(task_size - gap - random_factor);
6725+
6726+#ifdef CONFIG_PAX_RANDMMAP
6727+ if (mm->pax_flags & MF_PAX_RANDMMAP)
6728+ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
6729+#endif
6730+
6731 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
6732 mm->unmap_area = arch_unmap_area_topdown;
6733 }
6734diff -urNp linux-2.6.17.11/arch/sparc64/mm/fault.c linux-2.6.17.11/arch/sparc64/mm/fault.c
6735--- linux-2.6.17.11/arch/sparc64/mm/fault.c 2006-08-07 00:18:54.000000000 -0400
6736+++ linux-2.6.17.11/arch/sparc64/mm/fault.c 2006-08-12 08:17:55.000000000 -0400
6737@@ -19,6 +19,10 @@
6738 #include <linux/init.h>
6739 #include <linux/interrupt.h>
6740 #include <linux/kprobes.h>
6741+#include <linux/slab.h>
6742+#include <linux/pagemap.h>
6743+#include <linux/compiler.h>
6744+#include <linux/binfmts.h>
6745
6746 #include <asm/page.h>
6747 #include <asm/pgtable.h>
6748@@ -253,6 +257,369 @@ cannot_handle:
6749 unhandled_fault (address, current, regs);
6750 }
6751
6752+#ifdef CONFIG_PAX_PAGEEXEC
6753+#ifdef CONFIG_PAX_EMUPLT
6754+static void pax_emuplt_close(struct vm_area_struct * vma)
6755+{
6756+ vma->vm_mm->call_dl_resolve = 0UL;
6757+}
6758+
6759+static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
6760+{
6761+ struct page* page;
6762+ unsigned int *kaddr;
6763+
6764+ page = alloc_page(GFP_HIGHUSER);
6765+ if (!page)
6766+ return NOPAGE_OOM;
6767+
6768+ kaddr = kmap(page);
6769+ memset(kaddr, 0, PAGE_SIZE);
6770+ kaddr[0] = 0x9DE3BFA8U; /* save */
6771+ flush_dcache_page(page);
6772+ kunmap(page);
6773+ if (type)
6774+ *type = VM_FAULT_MAJOR;
6775+ return page;
6776+}
6777+
6778+static struct vm_operations_struct pax_vm_ops = {
6779+ .close = pax_emuplt_close,
6780+ .nopage = pax_emuplt_nopage,
6781+};
6782+
6783+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
6784+{
6785+ int ret;
6786+
6787+ memset(vma, 0, sizeof(*vma));
6788+ vma->vm_mm = current->mm;
6789+ vma->vm_start = addr;
6790+ vma->vm_end = addr + PAGE_SIZE;
6791+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
6792+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
6793+ vma->vm_ops = &pax_vm_ops;
6794+
6795+ ret = insert_vm_struct(current->mm, vma);
6796+ if (ret)
6797+ return ret;
6798+
6799+ ++current->mm->total_vm;
6800+ return 0;
6801+}
6802+#endif
6803+
6804+/*
6805+ * PaX: decide what to do with offenders (regs->tpc = fault address)
6806+ *
6807+ * returns 1 when task should be killed
6808+ * 2 when patched PLT trampoline was detected
6809+ * 3 when unpatched PLT trampoline was detected
6810+ */
6811+static int pax_handle_fetch_fault(struct pt_regs *regs)
6812+{
6813+
6814+#ifdef CONFIG_PAX_EMUPLT
6815+ int err;
6816+
6817+ do { /* PaX: patched PLT emulation #1 */
6818+ unsigned int sethi1, sethi2, jmpl;
6819+
6820+ err = get_user(sethi1, (unsigned int*)regs->tpc);
6821+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
6822+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+8));
6823+
6824+ if (err)
6825+ break;
6826+
6827+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
6828+ (sethi2 & 0xFFC00000U) == 0x03000000U &&
6829+ (jmpl & 0xFFFFE000U) == 0x81C06000U)
6830+ {
6831+ unsigned long addr;
6832+
6833+ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
6834+ addr = regs->u_regs[UREG_G1];
6835+ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
6836+ regs->tpc = addr;
6837+ regs->tnpc = addr+4;
6838+ return 2;
6839+ }
6840+ } while (0);
6841+
6842+ { /* PaX: patched PLT emulation #2 */
6843+ unsigned int ba;
6844+
6845+ err = get_user(ba, (unsigned int*)regs->tpc);
6846+
6847+ if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
6848+ unsigned long addr;
6849+
6850+ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
6851+ regs->tpc = addr;
6852+ regs->tnpc = addr+4;
6853+ return 2;
6854+ }
6855+ }
6856+
6857+ do { /* PaX: patched PLT emulation #3 */
6858+ unsigned int sethi, jmpl, nop;
6859+
6860+ err = get_user(sethi, (unsigned int*)regs->tpc);
6861+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+4));
6862+ err |= get_user(nop, (unsigned int*)(regs->tpc+8));
6863+
6864+ if (err)
6865+ break;
6866+
6867+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
6868+ (jmpl & 0xFFFFE000U) == 0x81C06000U &&
6869+ nop == 0x01000000U)
6870+ {
6871+ unsigned long addr;
6872+
6873+ addr = (sethi & 0x003FFFFFU) << 10;
6874+ regs->u_regs[UREG_G1] = addr;
6875+ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
6876+ regs->tpc = addr;
6877+ regs->tnpc = addr+4;
6878+ return 2;
6879+ }
6880+ } while (0);
6881+
6882+ do { /* PaX: patched PLT emulation #4 */
6883+ unsigned int mov1, call, mov2;
6884+
6885+ err = get_user(mov1, (unsigned int*)regs->tpc);
6886+ err |= get_user(call, (unsigned int*)(regs->tpc+4));
6887+ err |= get_user(mov2, (unsigned int*)(regs->tpc+8));
6888+
6889+ if (err)
6890+ break;
6891+
6892+ if (mov1 == 0x8210000FU &&
6893+ (call & 0xC0000000U) == 0x40000000U &&
6894+ mov2 == 0x9E100001U)
6895+ {
6896+ unsigned long addr;
6897+
6898+ regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC];
6899+ addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
6900+ regs->tpc = addr;
6901+ regs->tnpc = addr+4;
6902+ return 2;
6903+ }
6904+ } while (0);
6905+
6906+ do { /* PaX: patched PLT emulation #5 */
6907+ unsigned int sethi1, sethi2, or1, or2, sllx, jmpl, nop;
6908+
6909+ err = get_user(sethi1, (unsigned int*)regs->tpc);
6910+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
6911+ err |= get_user(or1, (unsigned int*)(regs->tpc+8));
6912+ err |= get_user(or2, (unsigned int*)(regs->tpc+12));
6913+ err |= get_user(sllx, (unsigned int*)(regs->tpc+16));
6914+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+20));
6915+ err |= get_user(nop, (unsigned int*)(regs->tpc+24));
6916+
6917+ if (err)
6918+ break;
6919+
6920+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
6921+ (sethi2 & 0xFFC00000U) == 0x0B000000U &&
6922+ (or1 & 0xFFFFE000U) == 0x82106000U &&
6923+ (or2 & 0xFFFFE000U) == 0x8A116000U &&
6924+ sllx == 0x83287020 &&
6925+ jmpl == 0x81C04005U &&
6926+ nop == 0x01000000U)
6927+ {
6928+ unsigned long addr;
6929+
6930+ regs->u_regs[UREG_G1] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU);
6931+ regs->u_regs[UREG_G1] <<= 32;
6932+ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU);
6933+ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
6934+ regs->tpc = addr;
6935+ regs->tnpc = addr+4;
6936+ return 2;
6937+ }
6938+ } while (0);
6939+
6940+ do { /* PaX: patched PLT emulation #6 */
6941+ unsigned int sethi1, sethi2, sllx, or, jmpl, nop;
6942+
6943+ err = get_user(sethi1, (unsigned int*)regs->tpc);
6944+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
6945+ err |= get_user(sllx, (unsigned int*)(regs->tpc+8));
6946+ err |= get_user(or, (unsigned int*)(regs->tpc+12));
6947+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+16));
6948+ err |= get_user(nop, (unsigned int*)(regs->tpc+20));
6949+
6950+ if (err)
6951+ break;
6952+
6953+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
6954+ (sethi2 & 0xFFC00000U) == 0x0B000000U &&
6955+ sllx == 0x83287020 &&
6956+ (or & 0xFFFFE000U) == 0x8A116000U &&
6957+ jmpl == 0x81C04005U &&
6958+ nop == 0x01000000U)
6959+ {
6960+ unsigned long addr;
6961+
6962+ regs->u_regs[UREG_G1] = (sethi1 & 0x003FFFFFU) << 10;
6963+ regs->u_regs[UREG_G1] <<= 32;
6964+ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or & 0x3FFU);
6965+ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
6966+ regs->tpc = addr;
6967+ regs->tnpc = addr+4;
6968+ return 2;
6969+ }
6970+ } while (0);
6971+
6972+ do { /* PaX: patched PLT emulation #7 */
6973+ unsigned int sethi, ba, nop;
6974+
6975+ err = get_user(sethi, (unsigned int*)regs->tpc);
6976+ err |= get_user(ba, (unsigned int*)(regs->tpc+4));
6977+ err |= get_user(nop, (unsigned int*)(regs->tpc+8));
6978+
6979+ if (err)
6980+ break;
6981+
6982+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
6983+ (ba & 0xFFF00000U) == 0x30600000U &&
6984+ nop == 0x01000000U)
6985+ {
6986+ unsigned long addr;
6987+
6988+ addr = (sethi & 0x003FFFFFU) << 10;
6989+ regs->u_regs[UREG_G1] = addr;
6990+ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
6991+ regs->tpc = addr;
6992+ regs->tnpc = addr+4;
6993+ return 2;
6994+ }
6995+ } while (0);
6996+
6997+ do { /* PaX: unpatched PLT emulation step 1 */
6998+ unsigned int sethi, ba, nop;
6999+
7000+ err = get_user(sethi, (unsigned int*)regs->tpc);
7001+ err |= get_user(ba, (unsigned int*)(regs->tpc+4));
7002+ err |= get_user(nop, (unsigned int*)(regs->tpc+8));
7003+
7004+ if (err)
7005+ break;
7006+
7007+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
7008+ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
7009+ nop == 0x01000000U)
7010+ {
7011+ unsigned long addr;
7012+ unsigned int save, call;
7013+
7014+ if ((ba & 0xFFC00000U) == 0x30800000U)
7015+ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
7016+ else
7017+ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
7018+
7019+ err = get_user(save, (unsigned int*)addr);
7020+ err |= get_user(call, (unsigned int*)(addr+4));
7021+ err |= get_user(nop, (unsigned int*)(addr+8));
7022+ if (err)
7023+ break;
7024+
7025+ if (save == 0x9DE3BFA8U &&
7026+ (call & 0xC0000000U) == 0x40000000U &&
7027+ nop == 0x01000000U)
7028+ {
7029+ struct vm_area_struct *vma;
7030+ unsigned long call_dl_resolve;
7031+
7032+ down_read(&current->mm->mmap_sem);
7033+ call_dl_resolve = current->mm->call_dl_resolve;
7034+ up_read(&current->mm->mmap_sem);
7035+ if (likely(call_dl_resolve))
7036+ goto emulate;
7037+
7038+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
7039+
7040+ down_write(&current->mm->mmap_sem);
7041+ if (current->mm->call_dl_resolve) {
7042+ call_dl_resolve = current->mm->call_dl_resolve;
7043+ up_write(&current->mm->mmap_sem);
7044+ if (vma) kmem_cache_free(vm_area_cachep, vma);
7045+ goto emulate;
7046+ }
7047+
7048+ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
7049+ if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
7050+ up_write(&current->mm->mmap_sem);
7051+ if (vma) kmem_cache_free(vm_area_cachep, vma);
7052+ return 1;
7053+ }
7054+
7055+ if (pax_insert_vma(vma, call_dl_resolve)) {
7056+ up_write(&current->mm->mmap_sem);
7057+ kmem_cache_free(vm_area_cachep, vma);
7058+ return 1;
7059+ }
7060+
7061+ current->mm->call_dl_resolve = call_dl_resolve;
7062+ up_write(&current->mm->mmap_sem);
7063+
7064+emulate:
7065+ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
7066+ regs->tpc = call_dl_resolve;
7067+ regs->tnpc = addr+4;
7068+ return 3;
7069+ }
7070+ }
7071+ } while (0);
7072+
7073+ do { /* PaX: unpatched PLT emulation step 2 */
7074+ unsigned int save, call, nop;
7075+
7076+ err = get_user(save, (unsigned int*)(regs->tpc-4));
7077+ err |= get_user(call, (unsigned int*)regs->tpc);
7078+ err |= get_user(nop, (unsigned int*)(regs->tpc+4));
7079+ if (err)
7080+ break;
7081+
7082+ if (save == 0x9DE3BFA8U &&
7083+ (call & 0xC0000000U) == 0x40000000U &&
7084+ nop == 0x01000000U)
7085+ {
7086+ unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
7087+
7088+ regs->u_regs[UREG_RETPC] = regs->tpc;
7089+ regs->tpc = dl_resolve;
7090+ regs->tnpc = dl_resolve+4;
7091+ return 3;
7092+ }
7093+ } while (0);
7094+#endif
7095+
7096+ return 1;
7097+}
7098+
7099+void pax_report_insns(void *pc, void *sp)
7100+{
7101+ unsigned long i;
7102+
7103+ printk(KERN_ERR "PAX: bytes at PC: ");
7104+ for (i = 0; i < 5; i++) {
7105+ unsigned int c;
7106+ if (get_user(c, (unsigned int*)pc+i))
7107+ printk("???????? ");
7108+ else
7109+ printk("%08x ", c);
7110+ }
7111+ printk("\n");
7112+}
7113+#endif
7114+
7115 asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
7116 {
7117 struct mm_struct *mm = current->mm;
7118@@ -295,8 +662,10 @@ asmlinkage void __kprobes do_sparc64_fau
7119 goto intr_or_no_mm;
7120
7121 if (test_thread_flag(TIF_32BIT)) {
7122- if (!(regs->tstate & TSTATE_PRIV))
7123+ if (!(regs->tstate & TSTATE_PRIV)) {
7124 regs->tpc &= 0xffffffff;
7125+ regs->tnpc &= 0xffffffff;
7126+ }
7127 address &= 0xffffffff;
7128 }
7129
7130@@ -313,6 +682,29 @@ asmlinkage void __kprobes do_sparc64_fau
7131 if (!vma)
7132 goto bad_area;
7133
7134+#ifdef CONFIG_PAX_PAGEEXEC
7135+ /* PaX: detect ITLB misses on non-exec pages */
7136+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && vma->vm_start <= address &&
7137+ !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB))
7138+ {
7139+ if (address != regs->tpc)
7140+ goto good_area;
7141+
7142+ up_read(&mm->mmap_sem);
7143+ switch (pax_handle_fetch_fault(regs)) {
7144+
7145+#ifdef CONFIG_PAX_EMUPLT
7146+ case 2:
7147+ case 3:
7148+ return;
7149+#endif
7150+
7151+ }
7152+ pax_report_fault(regs, (void*)regs->tpc, (void*)(regs->u_regs[UREG_FP] + STACK_BIAS));
7153+ do_exit(SIGKILL);
7154+ }
7155+#endif
7156+
7157 /* Pure DTLB misses do not tell us whether the fault causing
7158 * load/store/atomic was a write or not, it only says that there
7159 * was no match. So in such a case we (carefully) read the
7160diff -urNp linux-2.6.17.11/arch/v850/kernel/module.c linux-2.6.17.11/arch/v850/kernel/module.c
7161--- linux-2.6.17.11/arch/v850/kernel/module.c 2006-08-07 00:18:54.000000000 -0400
7162+++ linux-2.6.17.11/arch/v850/kernel/module.c 2006-08-12 08:17:55.000000000 -0400
7163@@ -150,8 +150,8 @@ static uint32_t do_plt_call (void *locat
7164 tramp[1] = ((val >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
7165
7166 /* Init, or core PLT? */
7167- if (location >= mod->module_core
7168- && location < mod->module_core + mod->core_size)
7169+ if (location >= mod->module_core_rx
7170+ && location < mod->module_core_rx + mod->core_size_rx)
7171 entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
7172 else
7173 entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
7174diff -urNp linux-2.6.17.11/arch/x86_64/boot/compressed/head.S linux-2.6.17.11/arch/x86_64/boot/compressed/head.S
7175--- linux-2.6.17.11/arch/x86_64/boot/compressed/head.S 2006-08-07 00:18:54.000000000 -0400
7176+++ linux-2.6.17.11/arch/x86_64/boot/compressed/head.S 2006-08-12 08:17:55.000000000 -0400
7177@@ -41,11 +41,13 @@ startup_32:
7178 movl %eax,%gs
7179
7180 lss stack_start,%esp
7181+ movl 0x000000,%ecx
7182 xorl %eax,%eax
7183 1: incl %eax # check that A20 really IS enabled
7184 movl %eax,0x000000 # loop forever if it isn't
7185 cmpl %eax,0x100000
7186 je 1b
7187+ movl %ecx,0x000000
7188
7189 /*
7190 * Initialize eflags. Some BIOS's leave bits like NT set. This would
7191diff -urNp linux-2.6.17.11/arch/x86_64/ia32/ia32_binfmt.c linux-2.6.17.11/arch/x86_64/ia32/ia32_binfmt.c
7192--- linux-2.6.17.11/arch/x86_64/ia32/ia32_binfmt.c 2006-08-07 00:18:54.000000000 -0400
7193+++ linux-2.6.17.11/arch/x86_64/ia32/ia32_binfmt.c 2006-08-12 08:17:55.000000000 -0400
7194@@ -186,6 +186,17 @@ struct elf_prpsinfo
7195 //#include <asm/ia32.h>
7196 #include <linux/elf.h>
7197
7198+#ifdef CONFIG_PAX_ASLR
7199+#define PAX_ELF_ET_DYN_BASE(tsk) 0x08048000UL
7200+
7201+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
7202+#define PAX_DELTA_MMAP_LEN(tsk) 16
7203+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
7204+#define PAX_DELTA_EXEC_LEN(tsk) 16
7205+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
7206+#define PAX_DELTA_STACK_LEN(tsk) 16
7207+#endif
7208+
7209 typedef struct user_i387_ia32_struct elf_fpregset_t;
7210 typedef struct user32_fxsr_struct elf_fpxregset_t;
7211
7212diff -urNp linux-2.6.17.11/arch/x86_64/ia32/mmap32.c linux-2.6.17.11/arch/x86_64/ia32/mmap32.c
7213--- linux-2.6.17.11/arch/x86_64/ia32/mmap32.c 2006-08-07 00:18:54.000000000 -0400
7214+++ linux-2.6.17.11/arch/x86_64/ia32/mmap32.c 2006-08-12 08:17:55.000000000 -0400
7215@@ -68,10 +68,22 @@ void ia32_pick_mmap_layout(struct mm_str
7216 (current->personality & ADDR_COMPAT_LAYOUT) ||
7217 current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
7218 mm->mmap_base = TASK_UNMAPPED_BASE;
7219+
7220+#ifdef CONFIG_PAX_RANDMMAP
7221+ if (mm->pax_flags & MF_PAX_RANDMMAP)
7222+ mm->mmap_base += mm->delta_mmap;
7223+#endif
7224+
7225 mm->get_unmapped_area = arch_get_unmapped_area;
7226 mm->unmap_area = arch_unmap_area;
7227 } else {
7228 mm->mmap_base = mmap_base(mm);
7229+
7230+#ifdef CONFIG_PAX_RANDMMAP
7231+ if (mm->pax_flags & MF_PAX_RANDMMAP)
7232+ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
7233+#endif
7234+
7235 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
7236 mm->unmap_area = arch_unmap_area_topdown;
7237 }
7238diff -urNp linux-2.6.17.11/arch/x86_64/kernel/process.c linux-2.6.17.11/arch/x86_64/kernel/process.c
7239--- linux-2.6.17.11/arch/x86_64/kernel/process.c 2006-08-07 00:18:54.000000000 -0400
7240+++ linux-2.6.17.11/arch/x86_64/kernel/process.c 2006-08-12 08:17:55.000000000 -0400
7241@@ -830,9 +830,3 @@ int dump_task_regs(struct task_struct *t
7242 return 1;
7243 }
7244
7245-unsigned long arch_align_stack(unsigned long sp)
7246-{
7247- if (randomize_va_space)
7248- sp -= get_random_int() % 8192;
7249- return sp & ~0xf;
7250-}
7251diff -urNp linux-2.6.17.11/arch/x86_64/kernel/ptrace.c linux-2.6.17.11/arch/x86_64/kernel/ptrace.c
7252--- linux-2.6.17.11/arch/x86_64/kernel/ptrace.c 2006-08-07 00:18:54.000000000 -0400
7253+++ linux-2.6.17.11/arch/x86_64/kernel/ptrace.c 2006-08-12 08:17:55.000000000 -0400
7254@@ -19,6 +19,7 @@
7255 #include <linux/audit.h>
7256 #include <linux/seccomp.h>
7257 #include <linux/signal.h>
7258+#include <linux/grsecurity.h>
7259
7260 #include <asm/uaccess.h>
7261 #include <asm/pgtable.h>
7262diff -urNp linux-2.6.17.11/arch/x86_64/kernel/setup64.c linux-2.6.17.11/arch/x86_64/kernel/setup64.c
7263--- linux-2.6.17.11/arch/x86_64/kernel/setup64.c 2006-08-07 00:18:54.000000000 -0400
7264+++ linux-2.6.17.11/arch/x86_64/kernel/setup64.c 2006-08-12 08:17:55.000000000 -0400
7265@@ -38,7 +38,6 @@ struct desc_ptr idt_descr = { 256 * 16 -
7266 char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
7267
7268 unsigned long __supported_pte_mask __read_mostly = ~0UL;
7269-static int do_not_nx __cpuinitdata = 0;
7270
7271 /* noexec=on|off
7272 Control non executable mappings for 64bit processes.
7273@@ -50,16 +49,14 @@ int __init nonx_setup(char *str)
7274 {
7275 if (!strncmp(str, "on", 2)) {
7276 __supported_pte_mask |= _PAGE_NX;
7277- do_not_nx = 0;
7278 } else if (!strncmp(str, "off", 3)) {
7279- do_not_nx = 1;
7280 __supported_pte_mask &= ~_PAGE_NX;
7281 }
7282 return 1;
7283 }
7284 __setup("noexec=", nonx_setup); /* parsed early actually */
7285
7286-int force_personality32 = 0;
7287+int force_personality32;
7288
7289 /* noexec32=on|off
7290 Control non executable heap for 32bit processes.
7291@@ -173,7 +170,7 @@ void __cpuinit check_efer(void)
7292 unsigned long efer;
7293
7294 rdmsrl(MSR_EFER, efer);
7295- if (!(efer & EFER_NX) || do_not_nx) {
7296+ if (!(efer & EFER_NX)) {
7297 __supported_pte_mask &= ~_PAGE_NX;
7298 }
7299 }
7300diff -urNp linux-2.6.17.11/arch/x86_64/kernel/sys_x86_64.c linux-2.6.17.11/arch/x86_64/kernel/sys_x86_64.c
7301--- linux-2.6.17.11/arch/x86_64/kernel/sys_x86_64.c 2006-08-07 00:18:54.000000000 -0400
7302+++ linux-2.6.17.11/arch/x86_64/kernel/sys_x86_64.c 2006-08-12 08:17:55.000000000 -0400
7303@@ -65,8 +65,8 @@ out:
7304 return error;
7305 }
7306
7307-static void find_start_end(unsigned long flags, unsigned long *begin,
7308- unsigned long *end)
7309+static void find_start_end(struct mm_struct *mm, unsigned long flags,
7310+ unsigned long *begin, unsigned long *end)
7311 {
7312 if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
7313 /* This is usually used needed to map code in small
7314@@ -79,7 +79,7 @@ static void find_start_end(unsigned long
7315 *begin = 0x40000000;
7316 *end = 0x80000000;
7317 } else {
7318- *begin = TASK_UNMAPPED_BASE;
7319+ *begin = mm->mmap_base;
7320 *end = TASK_SIZE;
7321 }
7322 }
7323@@ -93,11 +93,15 @@ arch_get_unmapped_area(struct file *filp
7324 unsigned long start_addr;
7325 unsigned long begin, end;
7326
7327- find_start_end(flags, &begin, &end);
7328+ find_start_end(mm, flags, &begin, &end);
7329
7330 if (len > end)
7331 return -ENOMEM;
7332
7333+#ifdef CONFIG_PAX_RANDMMAP
7334+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
7335+#endif
7336+
7337 if (addr) {
7338 addr = PAGE_ALIGN(addr);
7339 vma = find_vma(mm, addr);
7340diff -urNp linux-2.6.17.11/arch/x86_64/mm/fault.c linux-2.6.17.11/arch/x86_64/mm/fault.c
7341--- linux-2.6.17.11/arch/x86_64/mm/fault.c 2006-08-07 00:18:54.000000000 -0400
7342+++ linux-2.6.17.11/arch/x86_64/mm/fault.c 2006-08-12 08:17:55.000000000 -0400
7343@@ -24,6 +24,7 @@
7344 #include <linux/compiler.h>
7345 #include <linux/module.h>
7346 #include <linux/kprobes.h>
7347+#include <linux/binfmts.h>
7348
7349 #include <asm/system.h>
7350 #include <asm/uaccess.h>
7351@@ -294,6 +295,33 @@ static int vmalloc_fault(unsigned long a
7352 return 0;
7353 }
7354
7355+#ifdef CONFIG_PAX_PAGEEXEC
7356+void pax_report_insns(void *pc, void *sp)
7357+{
7358+ long i;
7359+
7360+ printk(KERN_ERR "PAX: bytes at PC: ");
7361+ for (i = 0; i < 20; i++) {
7362+ unsigned char c;
7363+ if (get_user(c, (unsigned char __user *)pc+i))
7364+ printk("?? ");
7365+ else
7366+ printk("%02x ", c);
7367+ }
7368+ printk("\n");
7369+
7370+ printk(KERN_ERR "PAX: bytes at SP-8: ");
7371+ for (i = -1; i < 10; i++) {
7372+ unsigned long c;
7373+ if (get_user(c, (unsigned long __user *)sp+i))
7374+ printk("???????????????? ");
7375+ else
7376+ printk("%016lx ", c);
7377+ }
7378+ printk("\n");
7379+}
7380+#endif
7381+
7382 int page_fault_trace = 0;
7383 int exception_trace = 1;
7384
7385@@ -423,6 +451,8 @@ asmlinkage void __kprobes do_page_fault(
7386 good_area:
7387 info.si_code = SEGV_ACCERR;
7388 write = 0;
7389+ if ((error_code & PF_INSTR) && !(vma->vm_flags & VM_EXEC))
7390+ goto bad_area;
7391 switch (error_code & (PF_PROT|PF_WRITE)) {
7392 default: /* 3: write, present */
7393 /* fall through */
7394@@ -489,7 +519,14 @@ bad_area_nosemaphore:
7395 tsk->comm, tsk->pid, address, regs->rip,
7396 regs->rsp, error_code);
7397 }
7398-
7399+
7400+#ifdef CONFIG_PAX_PAGEEXEC
7401+ if (mm && (mm->pax_flags & MF_PAX_PAGEEXEC) && (error_code & 16)) {
7402+ pax_report_fault(regs, (void*)regs->rip, (void*)regs->rsp);
7403+ do_exit(SIGKILL);
7404+ }
7405+#endif
7406+
7407 tsk->thread.cr2 = address;
7408 /* Kernel addresses are always protection faults */
7409 tsk->thread.error_code = error_code | (address >= TASK_SIZE);
7410diff -urNp linux-2.6.17.11/arch/x86_64/mm/mmap.c linux-2.6.17.11/arch/x86_64/mm/mmap.c
7411--- linux-2.6.17.11/arch/x86_64/mm/mmap.c 2006-08-07 00:18:54.000000000 -0400
7412+++ linux-2.6.17.11/arch/x86_64/mm/mmap.c 2006-08-12 08:17:55.000000000 -0400
7413@@ -24,6 +24,12 @@ void arch_pick_mmap_layout(struct mm_str
7414 unsigned rnd = get_random_int() & 0xfffffff;
7415 mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT;
7416 }
7417+
7418+#ifdef CONFIG_PAX_RANDMMAP
7419+ if (mm->pax_flags & MF_PAX_RANDMMAP)
7420+ mm->mmap_base += mm->delta_mmap;
7421+#endif
7422+
7423 mm->get_unmapped_area = arch_get_unmapped_area;
7424 mm->unmap_area = arch_unmap_area;
7425 }
7426diff -urNp linux-2.6.17.11/Documentation/dontdiff linux-2.6.17.11/Documentation/dontdiff
7427--- linux-2.6.17.11/Documentation/dontdiff 2006-08-07 00:18:54.000000000 -0400
7428+++ linux-2.6.17.11/Documentation/dontdiff 2006-08-12 08:17:55.000000000 -0400
7429@@ -55,7 +55,7 @@ aic7*seq.h*
7430 aicasm
7431 aicdb.h*
7432 asm
7433-asm-offsets.*
7434+asm-offsets.h
7435 asm_offsets.*
7436 autoconf.h*
7437 bbootsect
7438diff -urNp linux-2.6.17.11/drivers/char/agp/frontend.c linux-2.6.17.11/drivers/char/agp/frontend.c
7439--- linux-2.6.17.11/drivers/char/agp/frontend.c 2006-08-07 00:18:54.000000000 -0400
7440+++ linux-2.6.17.11/drivers/char/agp/frontend.c 2006-08-12 08:17:55.000000000 -0400
7441@@ -841,7 +841,7 @@ static int agpioc_reserve_wrap(struct ag
7442 if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
7443 return -EFAULT;
7444
7445- if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
7446+ if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment_priv))
7447 return -EFAULT;
7448
7449 client = agp_find_client_by_pid(reserve.pid);
7450diff -urNp linux-2.6.17.11/drivers/char/keyboard.c linux-2.6.17.11/drivers/char/keyboard.c
7451--- linux-2.6.17.11/drivers/char/keyboard.c 2006-08-07 00:18:54.000000000 -0400
7452+++ linux-2.6.17.11/drivers/char/keyboard.c 2006-08-12 08:17:55.000000000 -0400
7453@@ -618,6 +618,16 @@ static void k_spec(struct vc_data *vc, u
7454 kbd->kbdmode == VC_MEDIUMRAW) &&
7455 value != KVAL(K_SAK))
7456 return; /* SAK is allowed even in raw mode */
7457+
7458+#if defined(CONFIG_GRKERNSEC_PROC) || defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
7459+ {
7460+ void *func = fn_handler[value];
7461+ if (func == fn_show_state || func == fn_show_ptregs ||
7462+ func == fn_show_mem)
7463+ return;
7464+ }
7465+#endif
7466+
7467 fn_handler[value](vc, regs);
7468 }
7469
7470diff -urNp linux-2.6.17.11/drivers/char/mem.c linux-2.6.17.11/drivers/char/mem.c
7471--- linux-2.6.17.11/drivers/char/mem.c 2006-08-07 00:18:54.000000000 -0400
7472+++ linux-2.6.17.11/drivers/char/mem.c 2006-08-12 08:17:55.000000000 -0400
7473@@ -28,6 +28,7 @@
7474 #include <linux/backing-dev.h>
7475 #include <linux/bootmem.h>
7476 #include <linux/pipe_fs_i.h>
7477+#include <linux/grsecurity.h>
7478
7479 #include <asm/uaccess.h>
7480 #include <asm/io.h>
7481@@ -36,6 +37,10 @@
7482 # include <linux/efi.h>
7483 #endif
7484
7485+#ifdef CONFIG_GRKERNSEC
7486+extern struct file_operations grsec_fops;
7487+#endif
7488+
7489 /*
7490 * Architectures vary in how they handle caching for addresses
7491 * outside of main memory.
7492@@ -175,6 +180,11 @@ static ssize_t write_mem(struct file * f
7493 if (!valid_phys_addr_range(p, count))
7494 return -EFAULT;
7495
7496+#ifdef CONFIG_GRKERNSEC_KMEM
7497+ gr_handle_mem_write();
7498+ return -EPERM;
7499+#endif
7500+
7501 written = 0;
7502
7503 #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
7504@@ -251,6 +261,11 @@ static int mmap_mem(struct file * file,
7505 size,
7506 vma->vm_page_prot);
7507
7508+#ifdef CONFIG_GRKERNSEC_KMEM
7509+ if (gr_handle_mem_mmap(vma->vm_pgoff << PAGE_SHIFT, vma))
7510+ return -EPERM;
7511+#endif
7512+
7513 /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
7514 if (remap_pfn_range(vma,
7515 vma->vm_start,
7516@@ -478,6 +493,11 @@ static ssize_t write_kmem(struct file *
7517 ssize_t written;
7518 char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
7519
7520+#ifdef CONFIG_GRKERNSEC_KMEM
7521+ gr_handle_kmem_write();
7522+ return -EPERM;
7523+#endif
7524+
7525 if (p < (unsigned long) high_memory) {
7526
7527 wrote = count;
7528@@ -618,7 +638,23 @@ static inline size_t read_zero_pagealign
7529 count = size;
7530
7531 zap_page_range(vma, addr, count, NULL);
7532- zeromap_page_range(vma, addr, count, PAGE_COPY);
7533+ zeromap_page_range(vma, addr, count, vma->vm_page_prot);
7534+
7535+#ifdef CONFIG_PAX_SEGMEXEC
7536+ if (vma->vm_flags & VM_MIRROR) {
7537+ unsigned long addr_m;
7538+ struct vm_area_struct * vma_m;
7539+
7540+ addr_m = vma->vm_start + vma->vm_mirror;
7541+ vma_m = find_vma(mm, addr_m);
7542+ if (vma_m && vma_m->vm_start == addr_m && (vma_m->vm_flags & VM_MIRROR)) {
7543+ addr_m = addr + vma->vm_mirror;
7544+ zap_page_range(vma_m, addr_m, count, NULL);
7545+ } else
7546+ printk(KERN_ERR "PAX: VMMIRROR: read_zero bug, %08lx, %08lx\n",
7547+ addr, vma->vm_start);
7548+ }
7549+#endif
7550
7551 size -= count;
7552 buf += count;
7553@@ -767,6 +803,16 @@ static loff_t memory_lseek(struct file *
7554
7555 static int open_port(struct inode * inode, struct file * filp)
7556 {
7557+#ifdef CONFIG_GRKERNSEC_KMEM
7558+ gr_handle_open_port();
7559+ return -EPERM;
7560+#endif
7561+
7562+ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
7563+}
7564+
7565+static int open_mem(struct inode * inode, struct file * filp)
7566+{
7567 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
7568 }
7569
7570@@ -774,7 +820,6 @@ static int open_port(struct inode * inod
7571 #define full_lseek null_lseek
7572 #define write_zero write_null
7573 #define read_full read_zero
7574-#define open_mem open_port
7575 #define open_kmem open_mem
7576 #define open_oldmem open_mem
7577
7578@@ -897,6 +942,11 @@ static int memory_open(struct inode * in
7579 filp->f_op = &oldmem_fops;
7580 break;
7581 #endif
7582+#ifdef CONFIG_GRKERNSEC
7583+ case 13:
7584+ filp->f_op = &grsec_fops;
7585+ break;
7586+#endif
7587 default:
7588 return -ENXIO;
7589 }
7590@@ -929,6 +979,9 @@ static const struct {
7591 #ifdef CONFIG_CRASH_DUMP
7592 {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
7593 #endif
7594+#ifdef CONFIG_GRKERNSEC
7595+ {13,"grsec", S_IRUSR | S_IWUGO, &grsec_fops},
7596+#endif
7597 };
7598
7599 static struct class *mem_class;
7600diff -urNp linux-2.6.17.11/drivers/char/random.c linux-2.6.17.11/drivers/char/random.c
7601--- linux-2.6.17.11/drivers/char/random.c 2006-08-07 00:18:54.000000000 -0400
7602+++ linux-2.6.17.11/drivers/char/random.c 2006-08-12 08:17:55.000000000 -0400
7603@@ -249,8 +249,13 @@
7604 /*
7605 * Configuration information
7606 */
7607+#ifdef CONFIG_GRKERNSEC_RANDNET
7608+#define INPUT_POOL_WORDS 512
7609+#define OUTPUT_POOL_WORDS 128
7610+#else
7611 #define INPUT_POOL_WORDS 128
7612 #define OUTPUT_POOL_WORDS 32
7613+#endif
7614 #define SEC_XFER_SIZE 512
7615
7616 /*
7617@@ -287,10 +292,17 @@ static struct poolinfo {
7618 int poolwords;
7619 int tap1, tap2, tap3, tap4, tap5;
7620 } poolinfo_table[] = {
7621+#ifdef CONFIG_GRKERNSEC_RANDNET
7622+ /* x^512 + x^411 + x^308 + x^208 +x^104 + x + 1 -- 225 */
7623+ { 512, 411, 308, 208, 104, 1 },
7624+ /* x^128 + x^103 + x^76 + x^51 + x^25 + x + 1 -- 105 */
7625+ { 128, 103, 76, 51, 25, 1 },
7626+#else
7627 /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
7628 { 128, 103, 76, 51, 25, 1 },
7629 /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
7630 { 32, 26, 20, 14, 7, 1 },
7631+#endif
7632 #if 0
7633 /* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */
7634 { 2048, 1638, 1231, 819, 411, 1 },
7635@@ -1658,3 +1670,25 @@ randomize_range(unsigned long start, uns
7636 return 0;
7637 return PAGE_ALIGN(get_random_int() % range + start);
7638 }
7639+
7640+#if defined(CONFIG_PAX_ASLR) || defined(CONFIG_GRKERNSEC)
7641+unsigned long pax_get_random_long(void)
7642+{
7643+ static time_t rekey_time;
7644+ static __u32 secret[12];
7645+ time_t t;
7646+
7647+ /*
7648+ * Pick a random secret every REKEY_INTERVAL seconds.
7649+ */
7650+ t = get_seconds();
7651+ if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) {
7652+ rekey_time = t;
7653+ get_random_bytes(secret, sizeof(secret));
7654+ }
7655+
7656+ secret[1] = half_md4_transform(secret+8, secret);
7657+ secret[0] = half_md4_transform(secret+8, secret);
7658+ return *(unsigned long *)secret;
7659+}
7660+#endif
7661diff -urNp linux-2.6.17.11/drivers/char/vt_ioctl.c linux-2.6.17.11/drivers/char/vt_ioctl.c
7662--- linux-2.6.17.11/drivers/char/vt_ioctl.c 2006-08-07 00:18:54.000000000 -0400
7663+++ linux-2.6.17.11/drivers/char/vt_ioctl.c 2006-08-12 08:17:55.000000000 -0400
7664@@ -96,6 +96,12 @@ do_kdsk_ioctl(int cmd, struct kbentry __
7665 case KDSKBENT:
7666 if (!perm)
7667 return -EPERM;
7668+
7669+#ifdef CONFIG_GRKERNSEC
7670+ if (!capable(CAP_SYS_TTY_CONFIG))
7671+ return -EPERM;
7672+#endif
7673+
7674 if (!i && v == K_NOSUCHMAP) {
7675 /* disallocate map */
7676 key_map = key_maps[s];
7677@@ -236,6 +242,13 @@ do_kdgkb_ioctl(int cmd, struct kbsentry
7678 goto reterr;
7679 }
7680
7681+#ifdef CONFIG_GRKERNSEC
7682+ if (!capable(CAP_SYS_TTY_CONFIG)) {
7683+ ret = -EPERM;
7684+ goto reterr;
7685+ }
7686+#endif
7687+
7688 q = func_table[i];
7689 first_free = funcbufptr + (funcbufsize - funcbufleft);
7690 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
7691diff -urNp linux-2.6.17.11/drivers/ieee1394/hosts.c linux-2.6.17.11/drivers/ieee1394/hosts.c
7692--- linux-2.6.17.11/drivers/ieee1394/hosts.c 2006-08-07 00:18:54.000000000 -0400
7693+++ linux-2.6.17.11/drivers/ieee1394/hosts.c 2006-08-12 08:17:55.000000000 -0400
7694@@ -75,6 +75,7 @@ static int dummy_isoctl(struct hpsb_iso
7695 }
7696
7697 static struct hpsb_host_driver dummy_driver = {
7698+ .name = "dummy",
7699 .transmit_packet = dummy_transmit_packet,
7700 .devctl = dummy_devctl,
7701 .isoctl = dummy_isoctl
7702diff -urNp linux-2.6.17.11/drivers/ieee1394/ohci1394.c linux-2.6.17.11/drivers/ieee1394/ohci1394.c
7703--- linux-2.6.17.11/drivers/ieee1394/ohci1394.c 2006-08-23 19:30:00.000000000 -0400
7704+++ linux-2.6.17.11/drivers/ieee1394/ohci1394.c 2006-08-23 19:30:12.000000000 -0400
7705@@ -162,9 +162,9 @@ printk(level "%s: " fmt "\n" , OHCI1394_
7706 printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
7707
7708 /* Module Parameters */
7709-static int phys_dma = 1;
7710+static int phys_dma = 0;
7711 module_param(phys_dma, int, 0644);
7712-MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1).");
7713+MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 0).");
7714
7715 static void dma_trm_tasklet(unsigned long data);
7716 static void dma_trm_reset(struct dma_trm_ctx *d);
7717diff -urNp linux-2.6.17.11/drivers/mtd/devices/doc2001.c linux-2.6.17.11/drivers/mtd/devices/doc2001.c
7718--- linux-2.6.17.11/drivers/mtd/devices/doc2001.c 2006-08-07 00:18:54.000000000 -0400
7719+++ linux-2.6.17.11/drivers/mtd/devices/doc2001.c 2006-08-12 08:17:55.000000000 -0400
7720@@ -423,6 +423,8 @@ static int doc_read_ecc (struct mtd_info
7721 /* Don't allow read past end of device */
7722 if (from >= this->totlen)
7723 return -EINVAL;
7724+ if (!len)
7725+ return -EINVAL;
7726
7727 /* Don't allow a single read to cross a 512-byte block boundary */
7728 if (from + len > ((from | 0x1ff) + 1))
7729diff -urNp linux-2.6.17.11/drivers/net/pcnet32.c linux-2.6.17.11/drivers/net/pcnet32.c
7730--- linux-2.6.17.11/drivers/net/pcnet32.c 2006-08-07 00:18:54.000000000 -0400
7731+++ linux-2.6.17.11/drivers/net/pcnet32.c 2006-08-12 08:17:55.000000000 -0400
7732@@ -81,7 +81,7 @@ static int cards_found;
7733 /*
7734 * VLB I/O addresses
7735 */
7736-static unsigned int pcnet32_portlist[] __initdata =
7737+static unsigned int pcnet32_portlist[] __devinitdata =
7738 { 0x300, 0x320, 0x340, 0x360, 0 };
7739
7740 static int pcnet32_debug = 0;
7741diff -urNp linux-2.6.17.11/drivers/pci/proc.c linux-2.6.17.11/drivers/pci/proc.c
7742--- linux-2.6.17.11/drivers/pci/proc.c 2006-08-07 00:18:54.000000000 -0400
7743+++ linux-2.6.17.11/drivers/pci/proc.c 2006-08-12 08:17:55.000000000 -0400
7744@@ -473,7 +473,15 @@ static int __init pci_proc_init(void)
7745 {
7746 struct proc_dir_entry *entry;
7747 struct pci_dev *dev = NULL;
7748+#ifdef CONFIG_GRKERNSEC_PROC_ADD
7749+#ifdef CONFIG_GRKERNSEC_PROC_USER
7750+ proc_bus_pci_dir = proc_mkdir_mode("pci", S_IRUSR | S_IXUSR, proc_bus);
7751+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
7752+ proc_bus_pci_dir = proc_mkdir_mode("pci", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, proc_bus);
7753+#endif
7754+#else
7755 proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
7756+#endif
7757 entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
7758 if (entry)
7759 entry->proc_fops = &proc_bus_pci_dev_operations;
7760diff -urNp linux-2.6.17.11/drivers/pnp/pnpbios/bioscalls.c linux-2.6.17.11/drivers/pnp/pnpbios/bioscalls.c
7761--- linux-2.6.17.11/drivers/pnp/pnpbios/bioscalls.c 2006-08-07 00:18:54.000000000 -0400
7762+++ linux-2.6.17.11/drivers/pnp/pnpbios/bioscalls.c 2006-08-12 08:17:55.000000000 -0400
7763@@ -65,7 +65,7 @@ set_base(gdt[(selname) >> 3], (u32)(addr
7764 set_limit(gdt[(selname) >> 3], size); \
7765 } while(0)
7766
7767-static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
7768+static struct desc_struct bad_bios_desc = { 0, 0x00409300 };
7769
7770 /*
7771 * At some point we want to use this stack frame pointer to unwind
7772@@ -93,6 +93,10 @@ static inline u16 call_pnp_bios(u16 func
7773 struct desc_struct save_desc_40;
7774 int cpu;
7775
7776+#ifdef CONFIG_PAX_KERNEXEC
7777+ unsigned long cr0;
7778+#endif
7779+
7780 /*
7781 * PnP BIOSes are generally not terribly re-entrant.
7782 * Also, don't rely on them to save everything correctly.
7783@@ -107,6 +111,10 @@ static inline u16 call_pnp_bios(u16 func
7784 /* On some boxes IRQ's during PnP BIOS calls are deadly. */
7785 spin_lock_irqsave(&pnp_bios_lock, flags);
7786
7787+#ifdef CONFIG_PAX_KERNEXEC
7788+ pax_open_kernel(cr0);
7789+#endif
7790+
7791 /* The lock prevents us bouncing CPU here */
7792 if (ts1_size)
7793 Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
7794@@ -142,9 +150,14 @@ static inline u16 call_pnp_bios(u16 func
7795 "i" (0)
7796 : "memory"
7797 );
7798- spin_unlock_irqrestore(&pnp_bios_lock, flags);
7799
7800 get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40;
7801+
7802+#ifdef CONFIG_PAX_KERNEXEC
7803+ pax_close_kernel(cr0);
7804+#endif
7805+
7806+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
7807 put_cpu();
7808
7809 /* If we get here and this is set then the PnP BIOS faulted on us. */
7810diff -urNp linux-2.6.17.11/drivers/video/i810/i810_main.c linux-2.6.17.11/drivers/video/i810/i810_main.c
7811--- linux-2.6.17.11/drivers/video/i810/i810_main.c 2006-08-07 00:18:54.000000000 -0400
7812+++ linux-2.6.17.11/drivers/video/i810/i810_main.c 2006-08-12 08:17:55.000000000 -0400
7813@@ -1508,7 +1508,7 @@ static int i810fb_cursor(struct fb_info
7814 int size = ((cursor->image.width + 7) >> 3) *
7815 cursor->image.height;
7816 int i;
7817- u8 *data = kmalloc(64 * 8, GFP_ATOMIC);
7818+ u8 *data = kmalloc(64 * 8, GFP_KERNEL);
7819
7820 if (data == NULL)
7821 return -ENOMEM;
7822diff -urNp linux-2.6.17.11/drivers/video/vesafb.c linux-2.6.17.11/drivers/video/vesafb.c
7823--- linux-2.6.17.11/drivers/video/vesafb.c 2006-08-07 00:18:54.000000000 -0400
7824+++ linux-2.6.17.11/drivers/video/vesafb.c 2006-08-12 08:17:55.000000000 -0400
7825@@ -259,7 +259,7 @@ static int __init vesafb_probe(struct pl
7826 size_remap = size_total;
7827 vesafb_fix.smem_len = size_remap;
7828
7829-#ifndef __i386__
7830+#if !defined(__i386__) || defined(CONFIG_PAX_KERNEXEC)
7831 screen_info.vesapm_seg = 0;
7832 #endif
7833
7834diff -urNp linux-2.6.17.11/fs/binfmt_aout.c linux-2.6.17.11/fs/binfmt_aout.c
7835--- linux-2.6.17.11/fs/binfmt_aout.c 2006-08-07 00:18:54.000000000 -0400
7836+++ linux-2.6.17.11/fs/binfmt_aout.c 2006-08-12 08:17:55.000000000 -0400
7837@@ -24,6 +24,7 @@
7838 #include <linux/personality.h>
7839 #include <linux/init.h>
7840 #include <linux/vs_memory.h>
7841+#include <linux/grsecurity.h>
7842
7843 #include <asm/system.h>
7844 #include <asm/uaccess.h>
7845@@ -123,10 +124,12 @@ static int aout_core_dump(long signr, st
7846 /* If the size of the dump file exceeds the rlimit, then see what would happen
7847 if we wrote the stack, but not the data area. */
7848 #ifdef __sparc__
7849+ gr_learn_resource(current, RLIMIT_CORE, dump.u_dsize+dump.u_ssize, 1);
7850 if ((dump.u_dsize+dump.u_ssize) >
7851 current->signal->rlim[RLIMIT_CORE].rlim_cur)
7852 dump.u_dsize = 0;
7853 #else
7854+ gr_learn_resource(current, RLIMIT_CORE, (dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE, 1);
7855 if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
7856 current->signal->rlim[RLIMIT_CORE].rlim_cur)
7857 dump.u_dsize = 0;
7858@@ -134,10 +137,12 @@ static int aout_core_dump(long signr, st
7859
7860 /* Make sure we have enough room to write the stack and data areas. */
7861 #ifdef __sparc__
7862+ gr_learn_resource(current, RLIMIT_CORE, dump.u_ssize, 1);
7863 if ((dump.u_ssize) >
7864 current->signal->rlim[RLIMIT_CORE].rlim_cur)
7865 dump.u_ssize = 0;
7866 #else
7867+ gr_learn_resource(current, RLIMIT_CORE, (dump.u_ssize+1) * PAGE_SIZE, 1);
7868 if ((dump.u_ssize+1) * PAGE_SIZE >
7869 current->signal->rlim[RLIMIT_CORE].rlim_cur)
7870 dump.u_ssize = 0;
7871@@ -287,6 +292,8 @@ static int load_aout_binary(struct linux
7872 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
7873 if (rlim >= RLIM_INFINITY)
7874 rlim = ~0;
7875+
7876+ gr_learn_resource(current, RLIMIT_DATA, ex.a_data + ex.a_bss, 1);
7877 if (ex.a_data + ex.a_bss > rlim)
7878 return -ENOMEM;
7879
7880@@ -319,6 +326,28 @@ static int load_aout_binary(struct linux
7881 current->mm->mmap = NULL;
7882 compute_creds(bprm);
7883 current->flags &= ~PF_FORKNOEXEC;
7884+
7885+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
7886+ current->mm->pax_flags = 0UL;
7887+#endif
7888+
7889+#ifdef CONFIG_PAX_PAGEEXEC
7890+ if (!(N_FLAGS(ex) & F_PAX_PAGEEXEC)) {
7891+ current->mm->pax_flags |= MF_PAX_PAGEEXEC;
7892+
7893+#ifdef CONFIG_PAX_EMUTRAMP
7894+ if (N_FLAGS(ex) & F_PAX_EMUTRAMP)
7895+ current->mm->pax_flags |= MF_PAX_EMUTRAMP;
7896+#endif
7897+
7898+#ifdef CONFIG_PAX_MPROTECT
7899+ if (!(N_FLAGS(ex) & F_PAX_MPROTECT))
7900+ current->mm->pax_flags |= MF_PAX_MPROTECT;
7901+#endif
7902+
7903+ }
7904+#endif
7905+
7906 #ifdef __sparc__
7907 if (N_MAGIC(ex) == NMAGIC) {
7908 loff_t pos = fd_offset;
7909@@ -414,7 +443,7 @@ static int load_aout_binary(struct linux
7910
7911 down_write(&current->mm->mmap_sem);
7912 error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
7913- PROT_READ | PROT_WRITE | PROT_EXEC,
7914+ PROT_READ | PROT_WRITE,
7915 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
7916 fd_offset + ex.a_text);
7917 up_write(&current->mm->mmap_sem);
7918diff -urNp linux-2.6.17.11/fs/binfmt_elf.c linux-2.6.17.11/fs/binfmt_elf.c
7919--- linux-2.6.17.11/fs/binfmt_elf.c 2006-08-07 00:18:54.000000000 -0400
7920+++ linux-2.6.17.11/fs/binfmt_elf.c 2006-08-12 08:17:55.000000000 -0400
7921@@ -38,11 +38,16 @@
7922 #include <linux/random.h>
7923 #include <linux/vs_memory.h>
7924 #include <linux/vs_cvirt.h>
7925+#include <linux/grsecurity.h>
7926
7927 #include <asm/uaccess.h>
7928 #include <asm/param.h>
7929 #include <asm/page.h>
7930
7931+#ifdef CONFIG_PAX_SEGMEXEC
7932+#include <asm/desc.h>
7933+#endif
7934+
7935 #include <linux/elf.h>
7936
7937 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
7938@@ -90,6 +95,8 @@ static struct linux_binfmt elf_format =
7939
7940 static int set_brk(unsigned long start, unsigned long end)
7941 {
7942+ unsigned long e = end;
7943+
7944 start = ELF_PAGEALIGN(start);
7945 end = ELF_PAGEALIGN(end);
7946 if (end > start) {
7947@@ -100,7 +107,7 @@ static int set_brk(unsigned long start,
7948 if (BAD_ADDR(addr))
7949 return addr;
7950 }
7951- current->mm->start_brk = current->mm->brk = end;
7952+ current->mm->start_brk = current->mm->brk = e;
7953 return 0;
7954 }
7955
7956@@ -316,10 +323,9 @@ static unsigned long load_elf_interp(str
7957 {
7958 struct elf_phdr *elf_phdata;
7959 struct elf_phdr *eppnt;
7960- unsigned long load_addr = 0;
7961- int load_addr_set = 0;
7962+ unsigned long load_addr = 0, min_addr, max_addr, task_size = TASK_SIZE;
7963 unsigned long last_bss = 0, elf_bss = 0;
7964- unsigned long error = ~0UL;
7965+ unsigned long error = -EINVAL;
7966 int retval, i, size;
7967
7968 /* First of all, some simple consistency checks */
7969@@ -358,59 +364,80 @@ static unsigned long load_elf_interp(str
7970 goto out_close;
7971 }
7972
7973+#ifdef CONFIG_PAX_SEGMEXEC
7974+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
7975+ task_size = SEGMEXEC_TASK_SIZE;
7976+#endif
7977+
7978 eppnt = elf_phdata;
7979+ min_addr = task_size;
7980+ max_addr = 0;
7981+ error = -ENOMEM;
7982+
7983 for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
7984- if (eppnt->p_type == PT_LOAD) {
7985- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
7986- int elf_prot = 0;
7987- unsigned long vaddr = 0;
7988- unsigned long k, map_addr;
7989-
7990- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
7991- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
7992- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
7993- vaddr = eppnt->p_vaddr;
7994- if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
7995- elf_type |= MAP_FIXED;
7996-
7997- map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
7998- error = map_addr;
7999- if (BAD_ADDR(map_addr))
8000- goto out_close;
8001-
8002- if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
8003- load_addr = map_addr - ELF_PAGESTART(vaddr);
8004- load_addr_set = 1;
8005- }
8006-
8007- /*
8008- * Check to see if the section's size will overflow the
8009- * allowed task size. Note that p_filesz must always be
8010- * <= p_memsize so it is only necessary to check p_memsz.
8011- */
8012- k = load_addr + eppnt->p_vaddr;
8013- if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz ||
8014- eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) {
8015- error = -ENOMEM;
8016+ if (eppnt->p_type != PT_LOAD)
8017+ continue;
8018+
8019+ /*
8020+ * Check to see if the section's size will overflow the
8021+ * allowed task size. Note that p_filesz must always be
8022+ * <= p_memsize so it is only necessary to check p_memsz.
8023+ */
8024+ if (eppnt->p_filesz > eppnt->p_memsz || eppnt->p_vaddr >= eppnt->p_vaddr + eppnt->p_memsz)
8025+ goto out_close;
8026+
8027+ if (min_addr > ELF_PAGESTART(eppnt->p_vaddr))
8028+ min_addr = ELF_PAGESTART(eppnt->p_vaddr);
8029+ if (max_addr < ELF_PAGEALIGN(eppnt->p_vaddr + eppnt->p_memsz))
8030+ max_addr = ELF_PAGEALIGN(eppnt->p_vaddr + eppnt->p_memsz);
8031+ }
8032+ if (min_addr >= max_addr)
8033 goto out_close;
8034- }
8035
8036- /*
8037- * Find the end of the file mapping for this phdr, and keep
8038- * track of the largest address we see for this.
8039- */
8040- k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
8041- if (k > elf_bss)
8042- elf_bss = k;
8043-
8044- /*
8045- * Do the same thing for the memory mapping - between
8046- * elf_bss and last_bss is the bss section.
8047- */
8048- k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
8049- if (k > last_bss)
8050- last_bss = k;
8051- }
8052+ eppnt = elf_phdata;
8053+ for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
8054+ int elf_type = MAP_PRIVATE | MAP_DENYWRITE | MAP_FIXED;
8055+ int elf_prot = 0;
8056+ unsigned long vaddr;
8057+ unsigned long k, map_addr;
8058+
8059+ if (eppnt->p_type != PT_LOAD)
8060+ continue;
8061+
8062+ if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
8063+ if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
8064+ if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
8065+ vaddr = eppnt->p_vaddr;
8066+
8067+ if (!load_addr && interp_elf_ex->e_type == ET_DYN) {
8068+ load_addr = get_unmapped_area(interpreter, 0, max_addr - min_addr, 0, MAP_PRIVATE | MAP_EXECUTABLE);
8069+
8070+ if (load_addr > task_size)
8071+ goto out_close;
8072+
8073+ load_addr -= min_addr;
8074+ }
8075+
8076+ map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
8077+ error = map_addr;
8078+ if (BAD_ADDR(map_addr))
8079+ goto out_close;
8080+
8081+ /*
8082+ * Find the end of the file mapping for this phdr, and keep
8083+ * track of the largest address we see for this.
8084+ */
8085+ k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
8086+ if (k > elf_bss)
8087+ elf_bss = k;
8088+
8089+ /*
8090+ * Do the same thing for the memory mapping - between
8091+ * elf_bss and last_bss is the bss section.
8092+ */
8093+ k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
8094+ if (k > last_bss)
8095+ last_bss = k;
8096 }
8097
8098 /*
8099@@ -447,7 +474,7 @@ out:
8100 static unsigned long load_aout_interp(struct exec * interp_ex,
8101 struct file * interpreter)
8102 {
8103- unsigned long text_data, elf_entry = ~0UL;
8104+ unsigned long text_data, elf_entry = -EINVAL;
8105 char __user * addr;
8106 loff_t offset;
8107
8108@@ -491,6 +518,180 @@ out:
8109 return elf_entry;
8110 }
8111
8112+#if (defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)) && defined(CONFIG_PAX_SOFTMODE)
8113+static unsigned long pax_parse_softmode(const struct elf_phdr * const elf_phdata)
8114+{
8115+ unsigned long pax_flags = 0UL;
8116+
8117+#ifdef CONFIG_PAX_PAGEEXEC
8118+ if (elf_phdata->p_flags & PF_PAGEEXEC)
8119+ pax_flags |= MF_PAX_PAGEEXEC;
8120+#endif
8121+
8122+#ifdef CONFIG_PAX_SEGMEXEC
8123+ if (elf_phdata->p_flags & PF_SEGMEXEC)
8124+ pax_flags |= MF_PAX_SEGMEXEC;
8125+#endif
8126+
8127+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
8128+ if (pax_flags & MF_PAX_PAGEEXEC)
8129+ pax_flags &= ~MF_PAX_SEGMEXEC;
8130+#endif
8131+
8132+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
8133+ if (pax_flags & MF_PAX_SEGMEXEC)
8134+ pax_flags &= ~MF_PAX_PAGEEXEC;
8135+#endif
8136+
8137+#ifdef CONFIG_PAX_EMUTRAMP
8138+ if (elf_phdata->p_flags & PF_EMUTRAMP)
8139+ pax_flags |= MF_PAX_EMUTRAMP;
8140+#endif
8141+
8142+#ifdef CONFIG_PAX_MPROTECT
8143+ if (elf_phdata->p_flags & PF_MPROTECT)
8144+ pax_flags |= MF_PAX_MPROTECT;
8145+#endif
8146+
8147+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
8148+ if (randomize_va_space && (elf_phdata->p_flags & PF_RANDMMAP))
8149+ pax_flags |= MF_PAX_RANDMMAP;
8150+#endif
8151+
8152+ return pax_flags;
8153+}
8154+#endif
8155+
8156+#ifdef CONFIG_PAX_PT_PAX_FLAGS
8157+static unsigned long pax_parse_hardmode(const struct elf_phdr * const elf_phdata)
8158+{
8159+ unsigned long pax_flags = 0UL;
8160+
8161+#ifdef CONFIG_PAX_PAGEEXEC
8162+ if (!(elf_phdata->p_flags & PF_NOPAGEEXEC))
8163+ pax_flags |= MF_PAX_PAGEEXEC;
8164+#endif
8165+
8166+#ifdef CONFIG_PAX_SEGMEXEC
8167+ if (!(elf_phdata->p_flags & PF_NOSEGMEXEC))
8168+ pax_flags |= MF_PAX_SEGMEXEC;
8169+#endif
8170+
8171+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
8172+ if (pax_flags & MF_PAX_PAGEEXEC)
8173+ pax_flags &= ~MF_PAX_SEGMEXEC;
8174+#endif
8175+
8176+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
8177+ if (pax_flags & MF_PAX_SEGMEXEC)
8178+ pax_flags &= ~MF_PAX_PAGEEXEC;
8179+#endif
8180+
8181+#ifdef CONFIG_PAX_EMUTRAMP
8182+ if (!(elf_phdata->p_flags & PF_NOEMUTRAMP))
8183+ pax_flags |= MF_PAX_EMUTRAMP;
8184+#endif
8185+
8186+#ifdef CONFIG_PAX_MPROTECT
8187+ if (!(elf_phdata->p_flags & PF_NOMPROTECT))
8188+ pax_flags |= MF_PAX_MPROTECT;
8189+#endif
8190+
8191+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
8192+ if (randomize_va_space && !(elf_phdata->p_flags & PF_NORANDMMAP))
8193+ pax_flags |= MF_PAX_RANDMMAP;
8194+#endif
8195+
8196+ return pax_flags;
8197+}
8198+#endif
8199+
8200+#ifdef CONFIG_PAX_EI_PAX
8201+static unsigned long pax_parse_ei_pax(const struct elfhdr * const elf_ex)
8202+{
8203+ unsigned long pax_flags = 0UL;
8204+
8205+#ifdef CONFIG_PAX_PAGEEXEC
8206+ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_PAGEEXEC))
8207+ pax_flags |= MF_PAX_PAGEEXEC;
8208+#endif
8209+
8210+#ifdef CONFIG_PAX_SEGMEXEC
8211+ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_SEGMEXEC))
8212+ pax_flags |= MF_PAX_SEGMEXEC;
8213+#endif
8214+
8215+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
8216+ if (pax_flags & MF_PAX_PAGEEXEC)
8217+ pax_flags &= ~MF_PAX_SEGMEXEC;
8218+#endif
8219+
8220+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
8221+ if (pax_flags & MF_PAX_SEGMEXEC)
8222+ pax_flags &= ~MF_PAX_PAGEEXEC;
8223+#endif
8224+
8225+#ifdef CONFIG_PAX_EMUTRAMP
8226+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && (elf_ex->e_ident[EI_PAX] & EF_PAX_EMUTRAMP))
8227+ pax_flags |= MF_PAX_EMUTRAMP;
8228+#endif
8229+
8230+#ifdef CONFIG_PAX_MPROTECT
8231+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && !(elf_ex->e_ident[EI_PAX] & EF_PAX_MPROTECT))
8232+ pax_flags |= MF_PAX_MPROTECT;
8233+#endif
8234+
8235+#ifdef CONFIG_PAX_ASLR
8236+ if (randomize_va_space && !(elf_ex->e_ident[EI_PAX] & EF_PAX_RANDMMAP))
8237+ pax_flags |= MF_PAX_RANDMMAP;
8238+#endif
8239+
8240+ return pax_flags;
8241+}
8242+#endif
8243+
8244+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)
8245+static long pax_parse_elf_flags(const struct elfhdr * const elf_ex, const struct elf_phdr * const elf_phdata)
8246+{
8247+ unsigned long pax_flags = 0UL;
8248+
8249+#ifdef CONFIG_PAX_PT_PAX_FLAGS
8250+ unsigned long i;
8251+#endif
8252+
8253+#ifdef CONFIG_PAX_EI_PAX
8254+ pax_flags = pax_parse_ei_pax(elf_ex);
8255+#endif
8256+
8257+#ifdef CONFIG_PAX_PT_PAX_FLAGS
8258+ for (i = 0UL; i < elf_ex->e_phnum; i++)
8259+ if (elf_phdata[i].p_type == PT_PAX_FLAGS) {
8260+ if (((elf_phdata[i].p_flags & PF_PAGEEXEC) && (elf_phdata[i].p_flags & PF_NOPAGEEXEC)) ||
8261+ ((elf_phdata[i].p_flags & PF_SEGMEXEC) && (elf_phdata[i].p_flags & PF_NOSEGMEXEC)) ||
8262+ ((elf_phdata[i].p_flags & PF_EMUTRAMP) && (elf_phdata[i].p_flags & PF_NOEMUTRAMP)) ||
8263+ ((elf_phdata[i].p_flags & PF_MPROTECT) && (elf_phdata[i].p_flags & PF_NOMPROTECT)) ||
8264+ ((elf_phdata[i].p_flags & PF_RANDMMAP) && (elf_phdata[i].p_flags & PF_NORANDMMAP)))
8265+ return -EINVAL;
8266+
8267+#ifdef CONFIG_PAX_SOFTMODE
8268+ if (pax_softmode)
8269+ pax_flags = pax_parse_softmode(&elf_phdata[i]);
8270+ else
8271+#endif
8272+
8273+ pax_flags = pax_parse_hardmode(&elf_phdata[i]);
8274+ break;
8275+ }
8276+#endif
8277+
8278+ if (0 > pax_check_flags(&pax_flags))
8279+ return -EINVAL;
8280+
8281+ current->mm->pax_flags = pax_flags;
8282+ return 0;
8283+}
8284+#endif
8285+
8286 /*
8287 * These are the functions used to load ELF style executables and shared
8288 * libraries. There is no binary dependent code anywhere else.
8289@@ -527,7 +728,7 @@ static int load_elf_binary(struct linux_
8290 char * elf_interpreter = NULL;
8291 unsigned int interpreter_type = INTERPRETER_NONE;
8292 unsigned char ibcs2_interpreter = 0;
8293- unsigned long error;
8294+ unsigned long error = 0;
8295 struct elf_phdr * elf_ppnt, *elf_phdata;
8296 unsigned long elf_bss, elf_brk;
8297 int elf_exec_fileno;
8298@@ -545,6 +746,7 @@ static int load_elf_binary(struct linux_
8299 struct elfhdr interp_elf_ex;
8300 struct exec interp_ex;
8301 } *loc;
8302+ unsigned long task_size = TASK_SIZE;
8303
8304 loc = kmalloc(sizeof(*loc), GFP_KERNEL);
8305 if (!loc) {
8306@@ -770,14 +972,88 @@ static int load_elf_binary(struct linux_
8307 current->mm->end_code = 0;
8308 current->mm->mmap = NULL;
8309 current->flags &= ~PF_FORKNOEXEC;
8310+
8311+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
8312+ current->mm->pax_flags = 0UL;
8313+#endif
8314+
8315+#ifdef CONFIG_PAX_DLRESOLVE
8316+ current->mm->call_dl_resolve = 0UL;
8317+#endif
8318+
8319+#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
8320+ current->mm->call_syscall = 0UL;
8321+#endif
8322+
8323+#ifdef CONFIG_PAX_ASLR
8324+ current->mm->delta_mmap = 0UL;
8325+ current->mm->delta_exec = 0UL;
8326+ current->mm->delta_stack = 0UL;
8327+#endif
8328+
8329 current->mm->def_flags = def_flags;
8330
8331+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)
8332+ if (0 > pax_parse_elf_flags(&loc->elf_ex, elf_phdata)) {
8333+ send_sig(SIGKILL, current, 0);
8334+ goto out_free_dentry;
8335+ }
8336+#endif
8337+
8338+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
8339+ pax_set_initial_flags(bprm);
8340+#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
8341+ if (pax_set_initial_flags_func)
8342+ (pax_set_initial_flags_func)(bprm);
8343+#endif
8344+
8345+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
8346+ if (current->mm->pax_flags & MF_PAX_PAGEEXEC)
8347+ current->mm->context.user_cs_limit = PAGE_SIZE;
8348+#endif
8349+
8350+#ifdef CONFIG_PAX_SEGMEXEC
8351+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
8352+ int cpu = get_cpu();
8353+
8354+ current->mm->context.user_cs_base = SEGMEXEC_TASK_SIZE;
8355+ current->mm->context.user_cs_limit = -SEGMEXEC_TASK_SIZE;
8356+ set_user_cs(current->mm, cpu);
8357+ put_cpu();
8358+ task_size = SEGMEXEC_TASK_SIZE;
8359+ }
8360+#endif
8361+
8362+#ifdef CONFIG_PAX_ASLR
8363+ if (current->mm->pax_flags & MF_PAX_RANDMMAP) {
8364+#define pax_delta_mask(delta, lsb, len) (((delta) & ((1UL << (len)) - 1)) << (lsb))
8365+
8366+ current->mm->delta_mmap = pax_delta_mask(pax_get_random_long(), PAX_DELTA_MMAP_LSB(current), PAX_DELTA_MMAP_LEN(current));
8367+ current->mm->delta_exec = pax_delta_mask(pax_get_random_long(), PAX_DELTA_EXEC_LSB(current), PAX_DELTA_EXEC_LEN(current));
8368+ current->mm->delta_stack = pax_delta_mask(pax_get_random_long(), PAX_DELTA_STACK_LSB(current), PAX_DELTA_STACK_LEN(current));
8369+ }
8370+#endif
8371+
8372+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
8373+ if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
8374+ executable_stack = EXSTACK_DEFAULT;
8375+#endif
8376+
8377 /* Do this immediately, since STACK_TOP as used in setup_arg_pages
8378 may depend on the personality. */
8379 SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
8380+
8381+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
8382+ if (!(current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)))
8383+#endif
8384+
8385 if (elf_read_implies_exec(loc->elf_ex, executable_stack))
8386 current->personality |= READ_IMPLIES_EXEC;
8387
8388+#ifdef CONFIG_PAX_ASLR
8389+ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP))
8390+#endif
8391+
8392 if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
8393 current->flags |= PF_RANDOMIZE;
8394 arch_pick_mmap_layout(current->mm);
8395@@ -849,6 +1125,15 @@ static int load_elf_binary(struct linux_
8396 base, as well as whatever program they might try to exec. This
8397 is because the brk will follow the loader, and is not movable. */
8398 load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
8399+
8400+#ifdef CONFIG_PAX_RANDMMAP
8401+ /* PaX: randomize base address at the default exe base if requested */
8402+ if (current->mm->pax_flags & MF_PAX_RANDMMAP) {
8403+ load_bias = ELF_PAGESTART(PAX_ELF_ET_DYN_BASE(current) - vaddr + current->mm->delta_exec);
8404+ elf_flags |= MAP_FIXED;
8405+ }
8406+#endif
8407+
8408 }
8409
8410 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
8411@@ -876,9 +1161,9 @@ static int load_elf_binary(struct linux_
8412 * allowed task size. Note that p_filesz must always be
8413 * <= p_memsz so it is only necessary to check p_memsz.
8414 */
8415- if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
8416- elf_ppnt->p_memsz > TASK_SIZE ||
8417- TASK_SIZE - elf_ppnt->p_memsz < k) {
8418+ if (k > task_size || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
8419+ elf_ppnt->p_memsz > task_size ||
8420+ task_size - elf_ppnt->p_memsz < k) {
8421 /* set_brk can never work. Avoid overflows. */
8422 send_sig(SIGKILL, current, 0);
8423 goto out_free_dentry;
8424@@ -905,6 +1190,12 @@ static int load_elf_binary(struct linux_
8425 start_data += load_bias;
8426 end_data += load_bias;
8427
8428+#ifdef CONFIG_PAX_RANDMMAP
8429+ if (current->mm->pax_flags & MF_PAX_RANDMMAP)
8430+ elf_brk += PAGE_SIZE + pax_delta_mask(pax_get_random_long(), 4, PAGE_SHIFT);
8431+#undef pax_delta_mask
8432+#endif
8433+
8434 /* Calling set_brk effectively mmaps the pages that we need
8435 * for the bss and break sections. We must do this before
8436 * mapping in the interpreter, to make sure it doesn't wind
8437@@ -933,7 +1224,7 @@ static int load_elf_binary(struct linux_
8438 printk(KERN_ERR "Unable to load interpreter %.128s\n",
8439 elf_interpreter);
8440 force_sig(SIGSEGV, current);
8441- retval = -ENOEXEC; /* Nobody gets to see this, but.. */
8442+ retval = elf_entry; /* Nobody gets to see this, but.. */
8443 goto out_free_dentry;
8444 }
8445 reloc_func_desc = interp_load_addr;
8446@@ -1157,7 +1448,7 @@ static int dump_seek(struct file *file,
8447 *
8448 * I think we should skip something. But I am not sure how. H.J.
8449 */
8450-static int maydump(struct vm_area_struct *vma)
8451+static int maydump(struct vm_area_struct *vma, long signr)
8452 {
8453 /* Do not dump I/O mapped devices or special mappings */
8454 if (vma->vm_flags & (VM_IO | VM_RESERVED))
8455@@ -1168,7 +1459,7 @@ static int maydump(struct vm_area_struct
8456 return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
8457
8458 /* If it hasn't been written to, don't write it out */
8459- if (!vma->anon_vma)
8460+ if (signr != SIGKILL && !vma->anon_vma)
8461 return 0;
8462
8463 return 1;
8464@@ -1222,8 +1513,11 @@ static int writenote(struct memelfnote *
8465 #undef DUMP_SEEK
8466
8467 #define DUMP_WRITE(addr, nr) \
8468+ do { \
8469+ gr_learn_resource(current, RLIMIT_CORE, size + (nr), 1); \
8470 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
8471- goto end_coredump;
8472+ goto end_coredump; \
8473+ } while (0);
8474 #define DUMP_SEEK(off) \
8475 if (!dump_seek(file, (off))) \
8476 goto end_coredump;
8477@@ -1573,7 +1867,7 @@ static int elf_core_dump(long signr, str
8478 phdr.p_offset = offset;
8479 phdr.p_vaddr = vma->vm_start;
8480 phdr.p_paddr = 0;
8481- phdr.p_filesz = maydump(vma) ? sz : 0;
8482+ phdr.p_filesz = maydump(vma, signr) ? sz : 0;
8483 phdr.p_memsz = sz;
8484 offset += phdr.p_filesz;
8485 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
8486@@ -1606,7 +1900,7 @@ static int elf_core_dump(long signr, str
8487 for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
8488 unsigned long addr;
8489
8490- if (!maydump(vma))
8491+ if (!maydump(vma, signr))
8492 continue;
8493
8494 for (addr = vma->vm_start;
8495@@ -1625,6 +1919,7 @@ static int elf_core_dump(long signr, str
8496 void *kaddr;
8497 flush_cache_page(vma, addr, page_to_pfn(page));
8498 kaddr = kmap(page);
8499+ gr_learn_resource(current, RLIMIT_CORE, size + PAGE_SIZE, 1);
8500 if ((size += PAGE_SIZE) > limit ||
8501 !dump_write(file, kaddr,
8502 PAGE_SIZE)) {
8503diff -urNp linux-2.6.17.11/fs/binfmt_flat.c linux-2.6.17.11/fs/binfmt_flat.c
8504--- linux-2.6.17.11/fs/binfmt_flat.c 2006-08-07 00:18:54.000000000 -0400
8505+++ linux-2.6.17.11/fs/binfmt_flat.c 2006-08-12 08:17:55.000000000 -0400
8506@@ -552,7 +552,9 @@ static int load_flat_file(struct linux_b
8507 realdatastart = (unsigned long) -ENOMEM;
8508 printk("Unable to allocate RAM for process data, errno %d\n",
8509 (int)-datapos);
8510+ down_write(&current->mm->mmap_sem);
8511 do_munmap(current->mm, textpos, text_len);
8512+ up_write(&current->mm->mmap_sem);
8513 ret = realdatastart;
8514 goto err;
8515 }
8516@@ -574,8 +576,10 @@ static int load_flat_file(struct linux_b
8517 }
8518 if (result >= (unsigned long)-4096) {
8519 printk("Unable to read data+bss, errno %d\n", (int)-result);
8520+ down_write(&current->mm->mmap_sem);
8521 do_munmap(current->mm, textpos, text_len);
8522 do_munmap(current->mm, realdatastart, data_len + extra);
8523+ up_write(&current->mm->mmap_sem);
8524 ret = result;
8525 goto err;
8526 }
8527@@ -639,8 +643,10 @@ static int load_flat_file(struct linux_b
8528 }
8529 if (result >= (unsigned long)-4096) {
8530 printk("Unable to read code+data+bss, errno %d\n",(int)-result);
8531+ down_write(&current->mm->mmap_sem);
8532 do_munmap(current->mm, textpos, text_len + data_len + extra +
8533 MAX_SHARED_LIBS * sizeof(unsigned long));
8534+ up_write(&current->mm->mmap_sem);
8535 ret = result;
8536 goto err;
8537 }
8538diff -urNp linux-2.6.17.11/fs/binfmt_misc.c linux-2.6.17.11/fs/binfmt_misc.c
8539--- linux-2.6.17.11/fs/binfmt_misc.c 2006-08-07 00:18:54.000000000 -0400
8540+++ linux-2.6.17.11/fs/binfmt_misc.c 2006-08-12 08:17:55.000000000 -0400
8541@@ -112,9 +112,11 @@ static int load_misc_binary(struct linux
8542 struct files_struct *files = NULL;
8543
8544 retval = -ENOEXEC;
8545- if (!enabled)
8546+ if (!enabled || bprm->misc)
8547 goto _ret;
8548
8549+ bprm->misc++;
8550+
8551 /* to keep locking time low, we copy the interpreter string */
8552 read_lock(&entries_lock);
8553 fmt = check_file(bprm);
8554diff -urNp linux-2.6.17.11/fs/buffer.c linux-2.6.17.11/fs/buffer.c
8555--- linux-2.6.17.11/fs/buffer.c 2006-08-07 00:18:54.000000000 -0400
8556+++ linux-2.6.17.11/fs/buffer.c 2006-08-12 08:17:55.000000000 -0400
8557@@ -42,6 +42,7 @@
8558 #include <linux/bitops.h>
8559 #include <linux/mpage.h>
8560 #include <linux/bit_spinlock.h>
8561+#include <linux/grsecurity.h>
8562
8563 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
8564 static void invalidate_bh_lrus(void);
8565@@ -2167,6 +2168,7 @@ static int __generic_cont_expand(struct
8566
8567 err = -EFBIG;
8568 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
8569+ gr_learn_resource(current, RLIMIT_FSIZE, (unsigned long) size, 1);
8570 if (limit != RLIM_INFINITY && size > (loff_t)limit) {
8571 send_sig(SIGXFSZ, current, 0);
8572 goto out;
8573diff -urNp linux-2.6.17.11/fs/compat.c linux-2.6.17.11/fs/compat.c
8574--- linux-2.6.17.11/fs/compat.c 2006-08-07 00:18:54.000000000 -0400
8575+++ linux-2.6.17.11/fs/compat.c 2006-08-12 08:17:55.000000000 -0400
8576@@ -46,6 +46,7 @@
8577 #include <linux/rwsem.h>
8578 #include <linux/acct.h>
8579 #include <linux/mm.h>
8580+#include <linux/grsecurity.h>
8581
8582 #include <net/sock.h> /* siocdevprivate_ioctl */
8583
8584@@ -1498,6 +1499,11 @@ int compat_do_execve(char * filename,
8585 struct file *file;
8586 int retval;
8587 int i;
8588+#ifdef CONFIG_GRKERNSEC
8589+ struct file *old_exec_file;
8590+ struct acl_subject_label *old_acl;
8591+ struct rlimit old_rlim[RLIM_NLIMITS];
8592+#endif
8593
8594 retval = -ENOMEM;
8595 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
8596@@ -1515,6 +1521,15 @@ int compat_do_execve(char * filename,
8597 bprm->file = file;
8598 bprm->filename = filename;
8599 bprm->interp = filename;
8600+
8601+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->user->processes), 1);
8602+ retval = -EAGAIN;
8603+ if (gr_handle_nproc())
8604+ goto out_file;
8605+ retval = -EACCES;
8606+ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt))
8607+ goto out_file;
8608+
8609 bprm->mm = mm_alloc();
8610 retval = -ENOMEM;
8611 if (!bprm->mm)
8612@@ -1553,10 +1568,39 @@ int compat_do_execve(char * filename,
8613 if (retval < 0)
8614 goto out;
8615
8616+ if (!gr_tpe_allow(file)) {
8617+ retval = -EACCES;
8618+ goto out;
8619+ }
8620+
8621+ if (gr_check_crash_exec(file)) {
8622+ retval = -EACCES;
8623+ goto out;
8624+ }
8625+
8626+ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
8627+
8628+ gr_handle_exec_args(bprm, (char __user * __user *)argv);
8629+
8630+#ifdef CONFIG_GRKERNSEC
8631+ old_acl = current->acl;
8632+ memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim));
8633+ old_exec_file = current->exec_file;
8634+ get_file(file);
8635+ current->exec_file = file;
8636+#endif
8637+
8638+ gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
8639+
8640 retval = search_binary_handler(bprm, regs);
8641 if (retval >= 0) {
8642 free_arg_pages(bprm);
8643
8644+#ifdef CONFIG_GRKERNSEC
8645+ if (old_exec_file)
8646+ fput(old_exec_file);
8647+#endif
8648+
8649 /* execve success */
8650 security_bprm_free(bprm);
8651 acct_update_integrals(current);
8652@@ -1564,6 +1608,13 @@ int compat_do_execve(char * filename,
8653 return retval;
8654 }
8655
8656+#ifdef CONFIG_GRKERNSEC
8657+ current->acl = old_acl;
8658+ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim));
8659+ fput(current->exec_file);
8660+ current->exec_file = old_exec_file;
8661+#endif
8662+
8663 out:
8664 /* Something went wrong, return the inode and free the argument pages*/
8665 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
8666diff -urNp linux-2.6.17.11/fs/dcache.c linux-2.6.17.11/fs/dcache.c
8667--- linux-2.6.17.11/fs/dcache.c 2006-08-07 00:18:54.000000000 -0400
8668+++ linux-2.6.17.11/fs/dcache.c 2006-08-12 08:17:55.000000000 -0400
8669@@ -1389,7 +1389,7 @@ already_unhashed:
8670 *
8671 * "buflen" should be positive. Caller holds the dcache_lock.
8672 */
8673-static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
8674+char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
8675 struct dentry *root, struct vfsmount *rootmnt,
8676 char *buffer, int buflen)
8677 {
8678diff -urNp linux-2.6.17.11/fs/exec.c linux-2.6.17.11/fs/exec.c
8679--- linux-2.6.17.11/fs/exec.c 2006-08-07 00:18:54.000000000 -0400
8680+++ linux-2.6.17.11/fs/exec.c 2006-08-12 08:17:55.000000000 -0400
8681@@ -49,6 +49,8 @@
8682 #include <linux/cn_proc.h>
8683 #include <linux/vs_cvirt.h>
8684 #include <linux/vs_memory.h>
8685+#include <linux/random.h>
8686+#include <linux/grsecurity.h>
8687
8688 #include <asm/uaccess.h>
8689 #include <asm/mmu_context.h>
8690@@ -67,6 +69,15 @@ EXPORT_SYMBOL(suid_dumpable);
8691 static struct linux_binfmt *formats;
8692 static DEFINE_RWLOCK(binfmt_lock);
8693
8694+#ifdef CONFIG_PAX_SOFTMODE
8695+unsigned int pax_softmode;
8696+#endif
8697+
8698+#ifdef CONFIG_PAX_HOOK_ACL_FLAGS
8699+void (*pax_set_initial_flags_func)(struct linux_binprm * bprm);
8700+EXPORT_SYMBOL(pax_set_initial_flags_func);
8701+#endif
8702+
8703 int register_binfmt(struct linux_binfmt * fmt)
8704 {
8705 struct linux_binfmt ** tmp = &formats;
8706@@ -312,6 +323,10 @@ void install_arg_page(struct vm_area_str
8707 if (unlikely(anon_vma_prepare(vma)))
8708 goto out;
8709
8710+#ifdef CONFIG_PAX_SEGMEXEC
8711+ if (page_count(page) == 1)
8712+#endif
8713+
8714 flush_dcache_page(page);
8715 pte = get_locked_pte(mm, address, &ptl);
8716 if (!pte)
8717@@ -321,9 +336,21 @@ void install_arg_page(struct vm_area_str
8718 goto out;
8719 }
8720 inc_mm_counter(mm, anon_rss);
8721+
8722+#ifdef CONFIG_PAX_SEGMEXEC
8723+ if (page_count(page) == 1)
8724+#endif
8725+
8726 lru_cache_add_active(page);
8727 set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte(
8728 page, vma->vm_page_prot))));
8729+
8730+#ifdef CONFIG_PAX_SEGMEXEC
8731+ if (page_count(page) != 1)
8732+ page_add_anon_rmap(page, vma, address);
8733+ else
8734+#endif
8735+
8736 page_add_new_anon_rmap(page, vma, address);
8737 pte_unmap_unlock(pte, ptl);
8738
8739@@ -346,6 +373,10 @@ int setup_arg_pages(struct linux_binprm
8740 int i, ret;
8741 long arg_size;
8742
8743+#ifdef CONFIG_PAX_SEGMEXEC
8744+ struct vm_area_struct *mpnt_m = NULL;
8745+#endif
8746+
8747 #ifdef CONFIG_STACK_GROWSUP
8748 /* Move the argument and environment strings to the bottom of the
8749 * stack space.
8750@@ -404,11 +435,19 @@ int setup_arg_pages(struct linux_binprm
8751 bprm->loader += stack_base;
8752 bprm->exec += stack_base;
8753
8754- mpnt = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
8755+ mpnt = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
8756 if (!mpnt)
8757 return -ENOMEM;
8758
8759- memset(mpnt, 0, sizeof(*mpnt));
8760+#ifdef CONFIG_PAX_SEGMEXEC
8761+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (VM_STACK_FLAGS & VM_MAYEXEC)) {
8762+ mpnt_m = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL);
8763+ if (!mpnt_m) {
8764+ kmem_cache_free(vm_area_cachep, mpnt);
8765+ return -ENOMEM;
8766+ }
8767+ }
8768+#endif
8769
8770 down_write(&mm->mmap_sem);
8771 {
8772@@ -430,13 +469,50 @@ int setup_arg_pages(struct linux_binprm
8773 else
8774 mpnt->vm_flags = VM_STACK_FLAGS;
8775 mpnt->vm_flags |= mm->def_flags;
8776- mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
8777+
8778+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32)
8779+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC))
8780+ mpnt->vm_page_prot = protection_map[(mpnt->vm_flags | VM_EXEC) & (VM_READ|VM_WRITE|VM_EXEC)];
8781+ else
8782+#endif
8783+
8784+ mpnt->vm_page_prot = protection_map[mpnt->vm_flags & (VM_READ|VM_WRITE|VM_EXEC)];
8785 if ((ret = insert_vm_struct(mm, mpnt))) {
8786 up_write(&mm->mmap_sem);
8787 kmem_cache_free(vm_area_cachep, mpnt);
8788+
8789+#ifdef CONFIG_PAX_SEGMEXEC
8790+ if (mpnt_m)
8791+ kmem_cache_free(vm_area_cachep, mpnt_m);
8792+#endif
8793+
8794 return ret;
8795 }
8796 mm->stack_vm = mm->total_vm = vma_pages(mpnt);
8797+
8798+#ifdef CONFIG_PAX_SEGMEXEC
8799+ if (mpnt_m) {
8800+ *mpnt_m = *mpnt;
8801+ if (!(mpnt->vm_flags & VM_EXEC)) {
8802+ mpnt_m->vm_flags &= ~(VM_READ | VM_WRITE | VM_EXEC);
8803+ mpnt_m->vm_page_prot = PAGE_NONE;
8804+ }
8805+ mpnt_m->vm_start += SEGMEXEC_TASK_SIZE;
8806+ mpnt_m->vm_end += SEGMEXEC_TASK_SIZE;
8807+ if ((ret = insert_vm_struct(mm, mpnt_m))) {
8808+ up_write(&mm->mmap_sem);
8809+ kmem_cache_free(vm_area_cachep, mpnt_m);
8810+ return ret;
8811+ }
8812+ mpnt_m->vm_flags |= VM_MIRROR;
8813+ mpnt->vm_flags |= VM_MIRROR;
8814+ mpnt_m->vm_mirror = mpnt->vm_start - mpnt_m->vm_start;
8815+ mpnt->vm_mirror = mpnt_m->vm_start - mpnt->vm_start;
8816+ mpnt_m->vm_pgoff = mpnt->vm_pgoff;
8817+ mm->total_vm += vma_pages(mpnt_m);
8818+ }
8819+#endif
8820+
8821 }
8822
8823 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
8824@@ -444,6 +520,14 @@ int setup_arg_pages(struct linux_binprm
8825 if (page) {
8826 bprm->page[i] = NULL;
8827 install_arg_page(mpnt, page, stack_base);
8828+
8829+#ifdef CONFIG_PAX_SEGMEXEC
8830+ if (mpnt_m) {
8831+ page_cache_get(page);
8832+ install_arg_page(mpnt_m, page, stack_base + SEGMEXEC_TASK_SIZE);
8833+ }
8834+#endif
8835+
8836 }
8837 stack_base += PAGE_SIZE;
8838 }
8839@@ -1147,6 +1231,11 @@ int do_execve(char * filename,
8840 struct file *file;
8841 int retval;
8842 int i;
8843+#ifdef CONFIG_GRKERNSEC
8844+ struct file *old_exec_file;
8845+ struct acl_subject_label *old_acl;
8846+ struct rlimit old_rlim[RLIM_NLIMITS];
8847+#endif
8848
8849 retval = -ENOMEM;
8850 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
8851@@ -1158,10 +1247,29 @@ int do_execve(char * filename,
8852 if (IS_ERR(file))
8853 goto out_kfree;
8854
8855+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->user->processes), 1);
8856+
8857+ if (gr_handle_nproc()) {
8858+ allow_write_access(file);
8859+ fput(file);
8860+ return -EAGAIN;
8861+ }
8862+
8863+ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) {
8864+ allow_write_access(file);
8865+ fput(file);
8866+ return -EACCES;
8867+ }
8868+
8869 sched_exec();
8870
8871 bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
8872
8873+#ifdef CONFIG_PAX_RANDUSTACK
8874+ if (randomize_va_space)
8875+ bprm->p -= (pax_get_random_long() & ~(sizeof(void *)-1)) & ~PAGE_MASK;
8876+#endif
8877+
8878 bprm->file = file;
8879 bprm->filename = filename;
8880 bprm->interp = filename;
8881@@ -1203,8 +1311,38 @@ int do_execve(char * filename,
8882 if (retval < 0)
8883 goto out;
8884
8885+ if (!gr_tpe_allow(file)) {
8886+ retval = -EACCES;
8887+ goto out;
8888+ }
8889+
8890+ if (gr_check_crash_exec(file)) {
8891+ retval = -EACCES;
8892+ goto out;
8893+ }
8894+
8895+ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
8896+
8897+ gr_handle_exec_args(bprm, argv);
8898+
8899+#ifdef CONFIG_GRKERNSEC
8900+ old_acl = current->acl;
8901+ memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim));
8902+ old_exec_file = current->exec_file;
8903+ get_file(file);
8904+ current->exec_file = file;
8905+#endif
8906+
8907+ retval = gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
8908+ if (retval < 0)
8909+ goto out_fail;
8910+
8911 retval = search_binary_handler(bprm,regs);
8912 if (retval >= 0) {
8913+#ifdef CONFIG_GRKERNSEC
8914+ if (old_exec_file)
8915+ fput(old_exec_file);
8916+#endif
8917 free_arg_pages(bprm);
8918
8919 /* execve success */
8920@@ -1214,6 +1352,14 @@ int do_execve(char * filename,
8921 return retval;
8922 }
8923
8924+out_fail:
8925+#ifdef CONFIG_GRKERNSEC
8926+ current->acl = old_acl;
8927+ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim));
8928+ fput(current->exec_file);
8929+ current->exec_file = old_exec_file;
8930+#endif
8931+
8932 out:
8933 /* Something went wrong, return the inode and free the argument pages*/
8934 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
8935@@ -1374,6 +1520,114 @@ static void format_corename(char *corena
8936 *out_ptr = 0;
8937 }
8938
8939+int pax_check_flags(unsigned long * flags)
8940+{
8941+ int retval = 0;
8942+
8943+#if !defined(__i386__) || !defined(CONFIG_PAX_SEGMEXEC)
8944+ if (*flags & MF_PAX_SEGMEXEC)
8945+ {
8946+ *flags &= ~MF_PAX_SEGMEXEC;
8947+ retval = -EINVAL;
8948+ }
8949+#endif
8950+
8951+ if ((*flags & MF_PAX_PAGEEXEC)
8952+
8953+#ifdef CONFIG_PAX_PAGEEXEC
8954+ && (*flags & MF_PAX_SEGMEXEC)
8955+#endif
8956+
8957+ )
8958+ {
8959+ *flags &= ~MF_PAX_PAGEEXEC;
8960+ retval = -EINVAL;
8961+ }
8962+
8963+ if ((*flags & MF_PAX_MPROTECT)
8964+
8965+#ifdef CONFIG_PAX_MPROTECT
8966+ && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
8967+#endif
8968+
8969+ )
8970+ {
8971+ *flags &= ~MF_PAX_MPROTECT;
8972+ retval = -EINVAL;
8973+ }
8974+
8975+ if ((*flags & MF_PAX_EMUTRAMP)
8976+
8977+#ifdef CONFIG_PAX_EMUTRAMP
8978+ && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
8979+#endif
8980+
8981+ )
8982+ {
8983+ *flags &= ~MF_PAX_EMUTRAMP;
8984+ retval = -EINVAL;
8985+ }
8986+
8987+ return retval;
8988+}
8989+
8990+EXPORT_SYMBOL(pax_check_flags);
8991+
8992+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
8993+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp)
8994+{
8995+ struct task_struct *tsk = current;
8996+ struct mm_struct *mm = current->mm;
8997+ char* buffer_exec = (char*)__get_free_page(GFP_ATOMIC);
8998+ char* buffer_fault = (char*)__get_free_page(GFP_ATOMIC);
8999+ char* path_exec=NULL;
9000+ char* path_fault=NULL;
9001+ unsigned long start=0UL, end=0UL, offset=0UL;
9002+
9003+ if (buffer_exec && buffer_fault) {
9004+ struct vm_area_struct* vma, * vma_exec=NULL, * vma_fault=NULL;
9005+
9006+ down_read(&mm->mmap_sem);
9007+ vma = mm->mmap;
9008+ while (vma && (!vma_exec || !vma_fault)) {
9009+ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
9010+ vma_exec = vma;
9011+ if (vma->vm_start <= (unsigned long)pc && (unsigned long)pc < vma->vm_end)
9012+ vma_fault = vma;
9013+ vma = vma->vm_next;
9014+ }
9015+ if (vma_exec) {
9016+ path_exec = d_path(vma_exec->vm_file->f_dentry, vma_exec->vm_file->f_vfsmnt, buffer_exec, PAGE_SIZE);
9017+ if (IS_ERR(path_exec))
9018+ path_exec = "<path too long>";
9019+ }
9020+ if (vma_fault) {
9021+ start = vma_fault->vm_start;
9022+ end = vma_fault->vm_end;
9023+ offset = vma_fault->vm_pgoff << PAGE_SHIFT;
9024+ if (vma_fault->vm_file) {
9025+ path_fault = d_path(vma_fault->vm_file->f_dentry, vma_fault->vm_file->f_vfsmnt, buffer_fault, PAGE_SIZE);
9026+ if (IS_ERR(path_fault))
9027+ path_fault = "<path too long>";
9028+ } else
9029+ path_fault = "<anonymous mapping>";
9030+ }
9031+ up_read(&mm->mmap_sem);
9032+ }
9033+ if (tsk->signal->curr_ip)
9034+ 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);
9035+ else
9036+ printk(KERN_ERR "PAX: execution attempt in: %s, %08lx-%08lx %08lx\n", path_fault, start, end, offset);
9037+ printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, "
9038+ "PC: %p, SP: %p\n", path_exec, tsk->comm, tsk->pid,
9039+ tsk->uid, tsk->euid, pc, sp);
9040+ free_page((unsigned long)buffer_exec);
9041+ free_page((unsigned long)buffer_fault);
9042+ pax_report_insns(pc, sp);
9043+ do_coredump(SIGKILL, SIGKILL, regs);
9044+}
9045+#endif
9046+
9047 static void zap_threads (struct mm_struct *mm)
9048 {
9049 struct task_struct *g, *p;
9050@@ -1491,6 +1745,10 @@ int do_coredump(long signr, int exit_cod
9051 */
9052 clear_thread_flag(TIF_SIGPENDING);
9053
9054+ if (signr == SIGKILL || signr == SIGILL)
9055+ gr_handle_brute_attach(current);
9056+
9057+ gr_learn_resource(current, RLIMIT_CORE, binfmt->min_coredump, 1);
9058 if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
9059 goto fail_unlock;
9060
9061diff -urNp linux-2.6.17.11/fs/fcntl.c linux-2.6.17.11/fs/fcntl.c
9062--- linux-2.6.17.11/fs/fcntl.c 2006-08-07 00:18:54.000000000 -0400
9063+++ linux-2.6.17.11/fs/fcntl.c 2006-08-12 08:17:55.000000000 -0400
9064@@ -18,6 +18,7 @@
9065 #include <linux/signal.h>
9066 #include <linux/rcupdate.h>
9067 #include <linux/vs_limit.h>
9068+#include <linux/grsecurity.h>
9069
9070 #include <asm/poll.h>
9071 #include <asm/siginfo.h>
9072@@ -63,6 +64,7 @@ static int locate_fd(struct files_struct
9073 struct fdtable *fdt;
9074
9075 error = -EINVAL;
9076+ gr_learn_resource(current, RLIMIT_NOFILE, orig_start, 0);
9077 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
9078 goto out;
9079
9080@@ -83,6 +85,7 @@ repeat:
9081 }
9082
9083 error = -EMFILE;
9084+ gr_learn_resource(current, RLIMIT_NOFILE, newfd, 0);
9085 if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
9086 goto out;
9087
9088@@ -141,6 +144,8 @@ asmlinkage long sys_dup2(unsigned int ol
9089 struct files_struct * files = current->files;
9090 struct fdtable *fdt;
9091
9092+ gr_learn_resource(current, RLIMIT_NOFILE, newfd, 0);
9093+
9094 spin_lock(&files->file_lock);
9095 if (!(file = fcheck(oldfd)))
9096 goto out_unlock;
9097@@ -427,7 +432,8 @@ static inline int sigio_perm(struct task
9098 return (((fown->euid == 0) ||
9099 (fown->euid == p->suid) || (fown->euid == p->uid) ||
9100 (fown->uid == p->suid) || (fown->uid == p->uid)) &&
9101- !security_file_send_sigiotask(p, fown, sig));
9102+ !security_file_send_sigiotask(p, fown, sig) &&
9103+ !gr_check_protected_task(p) && !gr_pid_is_chrooted(p));
9104 }
9105
9106 static void send_sigio_to_task(struct task_struct *p,
9107diff -urNp linux-2.6.17.11/fs/Kconfig linux-2.6.17.11/fs/Kconfig
9108--- linux-2.6.17.11/fs/Kconfig 2006-08-07 00:18:54.000000000 -0400
9109+++ linux-2.6.17.11/fs/Kconfig 2006-08-12 08:17:55.000000000 -0400
9110@@ -794,7 +794,7 @@ config PROC_FS
9111
9112 config PROC_KCORE
9113 bool "/proc/kcore support" if !ARM
9114- depends on PROC_FS && MMU
9115+ depends on PROC_FS && MMU && !GRKERNSEC_PROC_ADD
9116
9117 config PROC_VMCORE
9118 bool "/proc/vmcore support (EXPERIMENTAL)"
9119diff -urNp linux-2.6.17.11/fs/namei.c linux-2.6.17.11/fs/namei.c
9120--- linux-2.6.17.11/fs/namei.c 2006-08-07 00:18:54.000000000 -0400
9121+++ linux-2.6.17.11/fs/namei.c 2006-08-12 08:17:55.000000000 -0400
9122@@ -32,6 +32,7 @@
9123 #include <linux/vserver/inode.h>
9124 #include <linux/vs_tag.h>
9125 #include <linux/vserver/debug.h>
9126+#include <linux/grsecurity.h>
9127 #include <asm/namei.h>
9128 #include <asm/uaccess.h>
9129
9130@@ -611,6 +612,13 @@ static inline int do_follow_link(struct
9131 err = security_inode_follow_link(path->dentry, nd);
9132 if (err)
9133 goto loop;
9134+
9135+ if (gr_handle_follow_link(path->dentry->d_parent->d_inode,
9136+ path->dentry->d_inode, path->dentry, nd->mnt)) {
9137+ err = -EACCES;
9138+ goto loop;
9139+ }
9140+
9141 current->link_count++;
9142 current->total_link_count++;
9143 nd->depth++;
9144@@ -954,11 +962,18 @@ return_reval:
9145 break;
9146 }
9147 return_base:
9148+ if (!gr_acl_handle_hidden_file(nd->dentry, nd->mnt)) {
9149+ path_release(nd);
9150+ return -ENOENT;
9151+ }
9152 return 0;
9153 out_dput:
9154 dput_path(&next, nd);
9155 break;
9156 }
9157+ if (!gr_acl_handle_hidden_file(nd->dentry, nd->mnt))
9158+ err = -ENOENT;
9159+
9160 path_release(nd);
9161 return_err:
9162 return err;
9163@@ -1601,6 +1616,17 @@ int open_namei(int dfd, const char *path
9164 nd, flag);
9165 if (error)
9166 return error;
9167+
9168+ if (gr_handle_rawio(nd->dentry->d_inode)) {
9169+ error = -EPERM;
9170+ goto exit;
9171+ }
9172+
9173+ if (!gr_acl_handle_open(nd->dentry, nd->mnt, flag)) {
9174+ error = -EACCES;
9175+ goto exit;
9176+ }
9177+
9178 goto ok;
9179 }
9180
9181@@ -1641,9 +1667,16 @@ do_last:
9182
9183 /* Negative dentry, just create the file */
9184 if (!path.dentry->d_inode) {
9185+ if (!gr_acl_handle_creat(path.dentry, nd->dentry, nd->mnt, flag, mode)) {
9186+ error = -EACCES;
9187+ mutex_unlock(&dir->d_inode->i_mutex);
9188+ goto exit_dput;
9189+ }
9190 if (!IS_POSIXACL(dir->d_inode))
9191 mode &= ~current->fs->umask;
9192 error = vfs_create(dir->d_inode, path.dentry, mode, nd);
9193+ if (!error)
9194+ gr_handle_create(path.dentry, nd->mnt);
9195 mutex_unlock(&dir->d_inode->i_mutex);
9196 dput(nd->dentry);
9197 nd->dentry = path.dentry;
9198@@ -1658,6 +1691,23 @@ do_last:
9199 /*
9200 * It already exists.
9201 */
9202+
9203+ if (gr_handle_rawio(path.dentry->d_inode)) {
9204+ mutex_unlock(&dir->d_inode->i_mutex);
9205+ error = -EPERM;
9206+ goto exit_dput;
9207+ }
9208+ if (!gr_acl_handle_open(path.dentry, nd->mnt, flag)) {
9209+ mutex_unlock(&dir->d_inode->i_mutex);
9210+ error = -EACCES;
9211+ goto exit_dput;
9212+ }
9213+ if (gr_handle_fifo(path.dentry, nd->mnt, dir, flag, acc_mode)) {
9214+ mutex_unlock(&dir->d_inode->i_mutex);
9215+ error = -EACCES;
9216+ goto exit_dput;
9217+ }
9218+
9219 mutex_unlock(&dir->d_inode->i_mutex);
9220
9221 error = -EEXIST;
9222@@ -1711,6 +1761,13 @@ do_link:
9223 error = security_inode_follow_link(path.dentry, nd);
9224 if (error)
9225 goto exit_dput;
9226+
9227+ if (gr_handle_follow_link(path.dentry->d_parent->d_inode, path.dentry->d_inode,
9228+ path.dentry, nd->mnt)) {
9229+ error = -EACCES;
9230+ goto exit_dput;
9231+ }
9232+
9233 error = __do_follow_link(&path, nd);
9234 if (error) {
9235 /* Does someone understand code flow here? Or it is only
9236@@ -1837,6 +1894,22 @@ asmlinkage long sys_mknodat(int dfd, con
9237 if (!IS_POSIXACL(nd.dentry->d_inode))
9238 mode &= ~current->fs->umask;
9239 if (!IS_ERR(dentry)) {
9240+ if (gr_handle_chroot_mknod(dentry, nd.mnt, mode)) {
9241+ error = -EPERM;
9242+ dput(dentry);
9243+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
9244+ path_release(&nd);
9245+ goto out;
9246+ }
9247+
9248+ if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) {
9249+ error = -EACCES;
9250+ dput(dentry);
9251+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
9252+ path_release(&nd);
9253+ goto out;
9254+ }
9255+
9256 switch (mode & S_IFMT) {
9257 case 0: case S_IFREG:
9258 error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
9259@@ -1854,6 +1927,10 @@ asmlinkage long sys_mknodat(int dfd, con
9260 default:
9261 error = -EINVAL;
9262 }
9263+
9264+ if (!error)
9265+ gr_handle_create(dentry, nd.mnt);
9266+
9267 dput(dentry);
9268 }
9269 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9270@@ -1908,9 +1985,19 @@ asmlinkage long sys_mkdirat(int dfd, con
9271 dentry = lookup_create(&nd, 1);
9272 error = PTR_ERR(dentry);
9273 if (!IS_ERR(dentry)) {
9274+ error = 0;
9275 if (!IS_POSIXACL(nd.dentry->d_inode))
9276 mode &= ~current->fs->umask;
9277- error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
9278+
9279+ if (!gr_acl_handle_mkdir(dentry, nd.dentry, nd.mnt))
9280+ error = -EACCES;
9281+
9282+ if (!error)
9283+ error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
9284+
9285+ if (!error)
9286+ gr_handle_create(dentry, nd.mnt);
9287+
9288 dput(dentry);
9289 }
9290 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9291@@ -1994,6 +2081,8 @@ static long do_rmdir(int dfd, const char
9292 char * name;
9293 struct dentry *dentry;
9294 struct nameidata nd;
9295+ ino_t saved_ino = 0;
9296+ dev_t saved_dev = 0;
9297
9298 name = getname(pathname);
9299 if(IS_ERR(name))
9300@@ -2018,7 +2107,21 @@ static long do_rmdir(int dfd, const char
9301 dentry = lookup_hash(&nd);
9302 error = PTR_ERR(dentry);
9303 if (!IS_ERR(dentry)) {
9304- error = vfs_rmdir(nd.dentry->d_inode, dentry);
9305+ error = 0;
9306+ if (dentry->d_inode) {
9307+ if (dentry->d_inode->i_nlink <= 1) {
9308+ saved_ino = dentry->d_inode->i_ino;
9309+ saved_dev = dentry->d_inode->i_sb->s_dev;
9310+ }
9311+
9312+ if (!gr_acl_handle_rmdir(dentry, nd.mnt))
9313+ error = -EACCES;
9314+ }
9315+
9316+ if (!error)
9317+ error = vfs_rmdir(nd.dentry->d_inode, dentry);
9318+ if (!error && (saved_dev || saved_ino))
9319+ gr_handle_delete(saved_ino, saved_dev);
9320 dput(dentry);
9321 }
9322 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9323@@ -2077,6 +2180,8 @@ static long do_unlinkat(int dfd, const c
9324 struct dentry *dentry;
9325 struct nameidata nd;
9326 struct inode *inode = NULL;
9327+ ino_t saved_ino = 0;
9328+ dev_t saved_dev = 0;
9329
9330 name = getname(pathname);
9331 if(IS_ERR(name))
9332@@ -2092,13 +2197,26 @@ static long do_unlinkat(int dfd, const c
9333 dentry = lookup_hash(&nd);
9334 error = PTR_ERR(dentry);
9335 if (!IS_ERR(dentry)) {
9336+ error = 0;
9337 /* Why not before? Because we want correct error value */
9338 if (nd.last.name[nd.last.len])
9339 goto slashes;
9340 inode = dentry->d_inode;
9341- if (inode)
9342+ if (inode) {
9343+ if (inode->i_nlink <= 1) {
9344+ saved_ino = inode->i_ino;
9345+ saved_dev = inode->i_sb->s_dev;
9346+ }
9347+
9348+ if (!gr_acl_handle_unlink(dentry, nd.mnt))
9349+ error = -EACCES;
9350+
9351 atomic_inc(&inode->i_count);
9352- error = vfs_unlink(nd.dentry->d_inode, dentry);
9353+ }
9354+ if (!error)
9355+ error = vfs_unlink(nd.dentry->d_inode, dentry);
9356+ if (!error && (saved_ino || saved_dev))
9357+ gr_handle_delete(saved_ino, saved_dev);
9358 exit2:
9359 dput(dentry);
9360 }
9361@@ -2176,7 +2294,15 @@ asmlinkage long sys_symlinkat(const char
9362 dentry = lookup_create(&nd, 0);
9363 error = PTR_ERR(dentry);
9364 if (!IS_ERR(dentry)) {
9365- error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
9366+ error = 0;
9367+ if (!gr_acl_handle_symlink(dentry, nd.dentry, nd.mnt, from))
9368+ error = -EACCES;
9369+
9370+ if (!error)
9371+ error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
9372+
9373+ if (!error)
9374+ gr_handle_create(dentry, nd.mnt);
9375 dput(dentry);
9376 }
9377 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9378@@ -2268,7 +2394,20 @@ asmlinkage long sys_linkat(int olddfd, c
9379 new_dentry = lookup_create(&nd, 0);
9380 error = PTR_ERR(new_dentry);
9381 if (!IS_ERR(new_dentry)) {
9382- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
9383+ error = 0;
9384+ if (gr_handle_hardlink(old_nd.dentry, old_nd.mnt,
9385+ old_nd.dentry->d_inode,
9386+ old_nd.dentry->d_inode->i_mode, to))
9387+ error = -EPERM;
9388+ if (!gr_acl_handle_link(new_dentry, nd.dentry, nd.mnt,
9389+ old_nd.dentry, old_nd.mnt, to))
9390+ error = -EACCES;
9391+ if (!error)
9392+ error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
9393+
9394+ if (!error)
9395+ gr_handle_create(new_dentry, nd.mnt);
9396+
9397 dput(new_dentry);
9398 }
9399 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9400@@ -2494,8 +2633,16 @@ static int do_rename(int olddfd, const c
9401 if (new_dentry == trap)
9402 goto exit5;
9403
9404- error = vfs_rename(old_dir->d_inode, old_dentry,
9405+ error = gr_acl_handle_rename(new_dentry, newnd.dentry, newnd.mnt,
9406+ old_dentry, old_dir->d_inode, oldnd.mnt,
9407+ newname);
9408+
9409+ if (!error)
9410+ error = vfs_rename(old_dir->d_inode, old_dentry,
9411 new_dir->d_inode, new_dentry);
9412+ if (!error)
9413+ gr_handle_rename(old_dir->d_inode, newnd.dentry->d_inode, old_dentry,
9414+ new_dentry, oldnd.mnt, new_dentry->d_inode ? 1 : 0);
9415 exit5:
9416 dput(new_dentry);
9417 exit4:
9418diff -urNp linux-2.6.17.11/fs/namespace.c linux-2.6.17.11/fs/namespace.c
9419--- linux-2.6.17.11/fs/namespace.c 2006-08-07 00:18:54.000000000 -0400
9420+++ linux-2.6.17.11/fs/namespace.c 2006-08-12 08:17:55.000000000 -0400
9421@@ -23,6 +23,8 @@
9422 #include <linux/mount.h>
9423 #include <linux/vserver/namespace.h>
9424 #include <linux/vserver/tag.h>
9425+#include <linux/sched.h>
9426+#include <linux/grsecurity.h>
9427 #include <asm/uaccess.h>
9428 #include <asm/unistd.h>
9429 #include "pnode.h"
9430@@ -600,6 +602,8 @@ static int do_umount(struct vfsmount *mn
9431 DQUOT_OFF(sb);
9432 retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
9433 unlock_kernel();
9434+
9435+ gr_log_remount(mnt->mnt_devname, retval);
9436 }
9437 up_write(&sb->s_umount);
9438 return retval;
9439@@ -620,6 +624,9 @@ static int do_umount(struct vfsmount *mn
9440 security_sb_umount_busy(mnt);
9441 up_write(&namespace_sem);
9442 release_mounts(&umount_list);
9443+
9444+ gr_log_unmount(mnt->mnt_devname, retval);
9445+
9446 return retval;
9447 }
9448
9449@@ -1346,6 +1353,11 @@ long do_mount(char *dev_name, char *dir_
9450 if (retval)
9451 goto dput_out;
9452
9453+ if (gr_handle_chroot_mount(nd.dentry, nd.mnt, dev_name)) {
9454+ retval = -EPERM;
9455+ goto dput_out;
9456+ }
9457+
9458 if (flags & MS_REMOUNT)
9459 retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
9460 data_page);
9461@@ -1360,6 +1372,9 @@ long do_mount(char *dev_name, char *dir_
9462 dev_name, data_page);
9463 dput_out:
9464 path_release(&nd);
9465+
9466+ gr_log_mount(dev_name, dir_name, retval);
9467+
9468 return retval;
9469 }
9470
9471@@ -1612,6 +1627,9 @@ asmlinkage long sys_pivot_root(const cha
9472 if (!capable(CAP_SYS_ADMIN))
9473 return -EPERM;
9474
9475+ if (gr_handle_chroot_pivot())
9476+ return -EPERM;
9477+
9478 lock_kernel();
9479
9480 error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
9481diff -urNp linux-2.6.17.11/fs/open.c linux-2.6.17.11/fs/open.c
9482--- linux-2.6.17.11/fs/open.c 2006-08-07 00:18:54.000000000 -0400
9483+++ linux-2.6.17.11/fs/open.c 2006-08-12 08:17:55.000000000 -0400
9484@@ -28,6 +28,7 @@
9485 #include <linux/vserver/vs_limit.h.h>
9486 #include <linux/vserver/vs_dlimit.h>
9487 #include <linux/tag.h>
9488+#include <linux/grsecurity.h>
9489
9490 #include <asm/unistd.h>
9491
9492@@ -207,6 +208,9 @@ int do_truncate(struct dentry *dentry, l
9493 if (length < 0)
9494 return -EINVAL;
9495
9496+ if (filp && !gr_acl_handle_truncate(dentry, filp->f_vfsmnt))
9497+ return -EACCES;
9498+
9499 newattrs.ia_size = length;
9500 newattrs.ia_valid = ATTR_SIZE | time_attrs;
9501 if (filp) {
9502@@ -407,6 +411,12 @@ asmlinkage long sys_utime(char __user *
9503 (error = vfs_permission(&nd, MAY_WRITE)) != 0)
9504 goto dput_and_out;
9505 }
9506+
9507+ if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) {
9508+ error = -EACCES;
9509+ goto dput_and_out;
9510+ }
9511+
9512 mutex_lock(&inode->i_mutex);
9513 error = notify_change(nd.dentry, &newattrs);
9514 mutex_unlock(&inode->i_mutex);
9515@@ -460,6 +470,12 @@ long do_utimes(int dfd, char __user *fil
9516 (error = vfs_permission(&nd, MAY_WRITE)) != 0)
9517 goto dput_and_out;
9518 }
9519+
9520+ if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) {
9521+ error = -EACCES;
9522+ goto dput_and_out;
9523+ }
9524+
9525 mutex_lock(&inode->i_mutex);
9526 error = notify_change(nd.dentry, &newattrs);
9527 mutex_unlock(&inode->i_mutex);
9528@@ -526,6 +542,10 @@ asmlinkage long sys_faccessat(int dfd, c
9529 if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
9530 && !special_file(nd.dentry->d_inode->i_mode))
9531 res = -EROFS;
9532+
9533+ if (!res && !gr_acl_handle_access(nd.dentry, nd.mnt, mode))
9534+ res = -EACCES;
9535+
9536 path_release(&nd);
9537 }
9538
9539@@ -554,6 +574,8 @@ asmlinkage long sys_chdir(const char __u
9540 if (error)
9541 goto dput_and_out;
9542
9543+ gr_log_chdir(nd.dentry, nd.mnt);
9544+
9545 set_fs_pwd(current->fs, nd.mnt, nd.dentry);
9546
9547 dput_and_out:
9548@@ -584,6 +606,13 @@ asmlinkage long sys_fchdir(unsigned int
9549 goto out_putf;
9550
9551 error = file_permission(file, MAY_EXEC);
9552+
9553+ if (!error && !gr_chroot_fchdir(dentry, mnt))
9554+ error = -EPERM;
9555+
9556+ if (!error)
9557+ gr_log_chdir(dentry, mnt);
9558+
9559 if (!error)
9560 set_fs_pwd(current->fs, mnt, dentry);
9561 out_putf:
9562@@ -609,8 +638,16 @@ asmlinkage long sys_chroot(const char __
9563 if (!capable(CAP_SYS_CHROOT))
9564 goto dput_and_out;
9565
9566+ if (gr_handle_chroot_chroot(nd.dentry, nd.mnt))
9567+ goto dput_and_out;
9568+
9569 set_fs_root(current->fs, nd.mnt, nd.dentry);
9570 set_fs_altroot();
9571+
9572+ gr_handle_chroot_caps(current);
9573+
9574+ gr_handle_chroot_chdir(nd.dentry, nd.mnt);
9575+
9576 error = 0;
9577 dput_and_out:
9578 path_release(&nd);
9579@@ -641,9 +678,22 @@ asmlinkage long sys_fchmod(unsigned int
9580 err = -EPERM;
9581 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
9582 goto out_putf;
9583+
9584+ if (!gr_acl_handle_fchmod(dentry, file->f_vfsmnt, mode)) {
9585+ err = -EACCES;
9586+ goto out_putf;
9587+ }
9588+
9589 mutex_lock(&inode->i_mutex);
9590 if (mode == (mode_t) -1)
9591 mode = inode->i_mode;
9592+
9593+ if (gr_handle_chroot_chmod(dentry, file->f_vfsmnt, mode)) {
9594+ err = -EPERM;
9595+ mutex_unlock(&inode->i_mutex);
9596+ goto out_putf;
9597+ }
9598+
9599 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
9600 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
9601 err = notify_change(dentry, &newattrs);
9602@@ -676,9 +726,21 @@ asmlinkage long sys_fchmodat(int dfd, co
9603 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
9604 goto dput_and_out;
9605
9606+ if (!gr_acl_handle_chmod(nd.dentry, nd.mnt, mode)) {
9607+ error = -EACCES;
9608+ goto dput_and_out;
9609+ };
9610+
9611 mutex_lock(&inode->i_mutex);
9612 if (mode == (mode_t) -1)
9613 mode = inode->i_mode;
9614+
9615+ if (gr_handle_chroot_chmod(nd.dentry, nd.mnt, mode)) {
9616+ error = -EACCES;
9617+ mutex_unlock(&inode->i_mutex);
9618+ goto dput_and_out;
9619+ }
9620+
9621 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
9622 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
9623 error = notify_change(nd.dentry, &newattrs);
9624@@ -695,7 +757,7 @@ asmlinkage long sys_chmod(const char __u
9625 return sys_fchmodat(AT_FDCWD, filename, mode);
9626 }
9627
9628-static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
9629+static int chown_common(struct dentry * dentry, uid_t user, gid_t group, struct vfsmount *mnt)
9630 {
9631 struct inode * inode;
9632 int error;
9633@@ -712,6 +774,12 @@ static int chown_common(struct dentry *
9634 error = -EPERM;
9635 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
9636 goto out;
9637+
9638+ if (!gr_acl_handle_chown(dentry, mnt)) {
9639+ error = -EACCES;
9640+ goto out;
9641+ }
9642+
9643 newattrs.ia_valid = ATTR_CTIME;
9644 if (user != (uid_t) -1) {
9645 newattrs.ia_valid |= ATTR_UID;
9646@@ -737,7 +805,7 @@ asmlinkage long sys_chown(const char __u
9647
9648 error = user_path_walk(filename, &nd);
9649 if (!error) {
9650- error = chown_common(nd.dentry, user, group);
9651+ error = chown_common(nd.dentry, user, group, nd.mnt);
9652 path_release(&nd);
9653 }
9654 return error;
9655@@ -756,7 +824,7 @@ asmlinkage long sys_fchownat(int dfd, co
9656 follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
9657 error = __user_walk_fd(dfd, filename, follow, &nd);
9658 if (!error) {
9659- error = chown_common(nd.dentry, user, group);
9660+ error = chown_common(nd.dentry, user, group, nd.mnt);
9661 path_release(&nd);
9662 }
9663 out:
9664@@ -770,7 +838,7 @@ asmlinkage long sys_lchown(const char __
9665
9666 error = user_path_walk_link(filename, &nd);
9667 if (!error) {
9668- error = chown_common(nd.dentry, user, group);
9669+ error = chown_common(nd.dentry, user, group, nd.mnt);
9670 path_release(&nd);
9671 }
9672 return error;
9673@@ -787,7 +855,7 @@ asmlinkage long sys_fchown(unsigned int
9674 struct dentry * dentry;
9675 dentry = file->f_dentry;
9676 audit_inode(NULL, dentry->d_inode, 0);
9677- error = chown_common(dentry, user, group);
9678+ error = chown_common(dentry, user, group, file->f_vfsmnt);
9679 fput(file);
9680 }
9681 return error;
9682@@ -995,6 +1063,7 @@ repeat:
9683 * N.B. For clone tasks sharing a files structure, this test
9684 * will limit the total number of files that can be opened.
9685 */
9686+ gr_learn_resource(current, RLIMIT_NOFILE, fd, 0);
9687 if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
9688 goto out;
9689
9690diff -urNp linux-2.6.17.11/fs/pipe.c linux-2.6.17.11/fs/pipe.c
9691--- linux-2.6.17.11/fs/pipe.c 2006-08-07 00:18:54.000000000 -0400
9692+++ linux-2.6.17.11/fs/pipe.c 2006-08-12 08:17:55.000000000 -0400
9693@@ -842,7 +842,7 @@ void free_pipe_info(struct inode *inode)
9694 inode->i_pipe = NULL;
9695 }
9696
9697-static struct vfsmount *pipe_mnt __read_mostly;
9698+struct vfsmount *pipe_mnt __read_mostly;
9699 static int pipefs_delete_dentry(struct dentry *dentry)
9700 {
9701 return 1;
9702diff -urNp linux-2.6.17.11/fs/proc/array.c linux-2.6.17.11/fs/proc/array.c
9703--- linux-2.6.17.11/fs/proc/array.c 2006-08-07 00:18:54.000000000 -0400
9704+++ linux-2.6.17.11/fs/proc/array.c 2006-08-12 08:17:55.000000000 -0400
9705@@ -293,6 +293,21 @@ static inline char *task_cap(struct task
9706 cap_t(p->cap_effective));
9707 }
9708
9709+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
9710+static inline char *task_pax(struct task_struct *p, char *buffer)
9711+{
9712+ if (p->mm)
9713+ return buffer + sprintf(buffer, "PaX:\t%c%c%c%c%c\n",
9714+ p->mm->pax_flags & MF_PAX_PAGEEXEC ? 'P' : 'p',
9715+ p->mm->pax_flags & MF_PAX_EMUTRAMP ? 'E' : 'e',
9716+ p->mm->pax_flags & MF_PAX_MPROTECT ? 'M' : 'm',
9717+ p->mm->pax_flags & MF_PAX_RANDMMAP ? 'R' : 'r',
9718+ p->mm->pax_flags & MF_PAX_SEGMEXEC ? 'S' : 's');
9719+ else
9720+ return buffer + sprintf(buffer, "PaX:\t-----\n");
9721+}
9722+#endif
9723+
9724 int proc_pid_status(struct task_struct *task, char * buffer)
9725 {
9726 char * orig = buffer;
9727@@ -311,9 +326,20 @@ int proc_pid_status(struct task_struct *
9728 #if defined(CONFIG_S390)
9729 buffer = task_show_regs(task, buffer);
9730 #endif
9731+
9732+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
9733+ buffer = task_pax(task, buffer);
9734+#endif
9735+
9736 return buffer - orig;
9737 }
9738
9739+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
9740+#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
9741+ (_mm->pax_flags & MF_PAX_RANDMMAP || \
9742+ _mm->pax_flags & MF_PAX_SEGMEXEC))
9743+#endif
9744+
9745 static int do_task_stat(struct task_struct *task, char * buffer, int whole)
9746 {
9747 unsigned long vsize, eip, esp, wchan = ~0UL;
9748@@ -398,6 +424,19 @@ static int do_task_stat(struct task_stru
9749 stime = task->stime;
9750 }
9751
9752+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
9753+ if (PAX_RAND_FLAGS(mm)) {
9754+ eip = 0;
9755+ esp = 0;
9756+ wchan = 0;
9757+ }
9758+#endif
9759+#ifdef CONFIG_GRKERNSEC_HIDESYM
9760+ wchan = 0;
9761+ eip =0;
9762+ esp =0;
9763+#endif
9764+
9765 /* scale priority and nice values from timeslices to -20..20 */
9766 /* to make it look like a "normal" Unix priority/nice value */
9767 priority = task_prio(task);
9768@@ -437,9 +476,15 @@ static int do_task_stat(struct task_stru
9769 vsize,
9770 mm ? get_mm_rss(mm) : 0,
9771 rsslim,
9772+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
9773+ PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->start_code : 0),
9774+ PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->end_code : 0),
9775+ PAX_RAND_FLAGS(mm) ? 0 : (mm ? mm->start_stack : 0),
9776+#else
9777 mm ? mm->start_code : 0,
9778 mm ? mm->end_code : 0,
9779 mm ? mm->start_stack : 0,
9780+#endif
9781 esp,
9782 eip,
9783 /* The signal information here is obsolete.
9784@@ -485,3 +530,14 @@ int proc_pid_statm(struct task_struct *t
9785 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
9786 size, resident, shared, text, lib, data, 0);
9787 }
9788+
9789+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
9790+int proc_pid_ipaddr(struct task_struct *task, char * buffer)
9791+{
9792+ int len;
9793+
9794+ len = sprintf(buffer, "%u.%u.%u.%u\n", NIPQUAD(task->signal->curr_ip));
9795+ return len;
9796+}
9797+#endif
9798+
9799diff -urNp linux-2.6.17.11/fs/proc/base.c linux-2.6.17.11/fs/proc/base.c
9800--- linux-2.6.17.11/fs/proc/base.c 2006-08-07 00:18:54.000000000 -0400
9801+++ linux-2.6.17.11/fs/proc/base.c 2006-08-12 08:17:55.000000000 -0400
9802@@ -72,6 +72,7 @@
9803 #include <linux/cpuset.h>
9804 #include <linux/audit.h>
9805 #include <linux/poll.h>
9806+#include <linux/grsecurity.h>
9807 #include "internal.h"
9808
9809 /*
9810@@ -125,6 +126,9 @@ enum pid_directory_inos {
9811 #ifdef CONFIG_AUDITSYSCALL
9812 PROC_TGID_LOGINUID,
9813 #endif
9814+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
9815+ PROC_TGID_IPADDR,
9816+#endif
9817 PROC_TGID_OOM_SCORE,
9818 PROC_TGID_OOM_ADJUST,
9819 PROC_TID_INO,
9820@@ -204,6 +208,9 @@ static struct pid_entry tgid_base_stuff[
9821 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
9822 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
9823 E(PROC_TGID_MOUNTSTATS, "mountstats", S_IFREG|S_IRUSR),
9824+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
9825+ E(PROC_TGID_IPADDR, "ipaddr", S_IFREG|S_IRUSR),
9826+#endif
9827 #ifdef CONFIG_MMU
9828 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
9829 #endif
9830@@ -410,7 +417,7 @@ static int proc_task_root_link(struct in
9831 (task->parent == current && \
9832 (task->ptrace & PT_PTRACED) && \
9833 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
9834- security_ptrace(current,task) == 0))
9835+ security_ptrace(current,task) == 0 && !gr_handle_proc_ptrace(task)))
9836
9837 static int proc_pid_environ(struct task_struct *task, char * buffer)
9838 {
9839@@ -591,9 +598,25 @@ static int proc_check_root(struct inode
9840
9841 static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
9842 {
9843+ int ret = -EACCES;
9844+ struct task_struct *task;
9845+
9846 if (generic_permission(inode, mask, NULL) != 0)
9847- return -EACCES;
9848- return proc_check_root(inode);
9849+ goto out;
9850+
9851+ ret = proc_check_root(inode);
9852+ if (ret)
9853+ goto out;
9854+
9855+ task = proc_task(inode);
9856+
9857+ if (!task)
9858+ goto out;
9859+
9860+ ret = gr_acl_handle_procpidmem(task);
9861+
9862+out:
9863+ return ret;
9864 }
9865
9866 static int proc_setattr(struct dentry *dentry, struct iattr *attr)
9867@@ -1396,6 +1419,9 @@ static struct inode *proc_pid_make_inode
9868 inode->i_uid = task->euid;
9869 inode->i_gid = task->egid;
9870 }
9871+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
9872+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
9873+#endif
9874 security_task_to_inode(task, inode);
9875
9876 out:
9877@@ -1424,7 +1450,9 @@ static int pid_revalidate(struct dentry
9878 if (pid_alive(task)) {
9879 if (proc_type(inode) == PROC_TGID_INO || proc_type(inode) == PROC_TID_INO || task_dumpable(task)) {
9880 inode->i_uid = task->euid;
9881+#ifndef CONFIG_GRKERNSEC_PROC_USERGROUP
9882 inode->i_gid = task->egid;
9883+#endif
9884 } else {
9885 inode->i_uid = 0;
9886 inode->i_gid = 0;
9887@@ -1756,6 +1784,12 @@ static struct dentry *proc_pident_lookup
9888 inode->i_fop = &proc_info_file_operations;
9889 ei->op.proc_read = proc_pid_status;
9890 break;
9891+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
9892+ case PROC_TGID_IPADDR:
9893+ inode->i_fop = &proc_info_file_operations;
9894+ ei->op.proc_read = proc_pid_ipaddr;
9895+ break;
9896+#endif
9897 case PROC_TID_STAT:
9898 inode->i_fop = &proc_info_file_operations;
9899 ei->op.proc_read = proc_tid_stat;
9900@@ -2069,6 +2103,22 @@ struct dentry *proc_pid_lookup(struct in
9901 if (!task)
9902 goto out;
9903
9904+ if (gr_check_hidden_task(task)) {
9905+ put_task_struct(task);
9906+ goto out;
9907+ }
9908+
9909+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9910+ if (current->uid && (task->uid != current->uid)
9911+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
9912+ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)
9913+#endif
9914+ ) {
9915+ put_task_struct(task);
9916+ goto out;
9917+ }
9918+#endif
9919+
9920 inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
9921
9922
9923@@ -2076,7 +2126,15 @@ struct dentry *proc_pid_lookup(struct in
9924 put_task_struct(task);
9925 goto out;
9926 }
9927+
9928+#ifdef CONFIG_GRKERNSEC_PROC_USER
9929+ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR;
9930+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9931+ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP;
9932+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
9933+#else
9934 inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
9935+#endif
9936 inode->i_op = &proc_tgid_base_inode_operations;
9937 inode->i_fop = &proc_tgid_base_operations;
9938 inode->i_flags|=S_IMMUTABLE;
9939@@ -2168,6 +2226,9 @@ out:
9940 static int get_tgid_list(int index, unsigned long version, unsigned int *tgids)
9941 {
9942 struct task_struct *p;
9943+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9944+ struct task_struct *tmp = current;
9945+#endif
9946 int nr_tgids = 0;
9947
9948 index--;
9949@@ -2188,6 +2249,18 @@ static int get_tgid_list(int index, unsi
9950 int tgid = p->pid;
9951 if (!pid_alive(p))
9952 continue;
9953+ if (gr_pid_is_chrooted(p))
9954+ continue;
9955+ if (gr_check_hidden_task(p))
9956+ continue;
9957+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9958+ if (tmp->uid && (p->uid != tmp->uid)
9959+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
9960+ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)
9961+#endif
9962+ )
9963+ continue;
9964+#endif
9965 if (--index >= 0)
9966 continue;
9967 tgids[nr_tgids] = tgid;
9968diff -urNp linux-2.6.17.11/fs/proc/inode.c linux-2.6.17.11/fs/proc/inode.c
9969--- linux-2.6.17.11/fs/proc/inode.c 2006-08-07 00:18:54.000000000 -0400
9970+++ linux-2.6.17.11/fs/proc/inode.c 2006-08-12 08:17:55.000000000 -0400
9971@@ -169,7 +169,11 @@ struct inode *proc_get_inode(struct supe
9972 if (de->mode) {
9973 inode->i_mode = de->mode;
9974 inode->i_uid = de->uid;
9975+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
9976+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
9977+#else
9978 inode->i_gid = de->gid;
9979+#endif
9980 }
9981 if (de->size)
9982 inode->i_size = de->size;
9983diff -urNp linux-2.6.17.11/fs/proc/internal.h linux-2.6.17.11/fs/proc/internal.h
9984--- linux-2.6.17.11/fs/proc/internal.h 2006-08-07 00:18:54.000000000 -0400
9985+++ linux-2.6.17.11/fs/proc/internal.h 2006-08-12 08:17:55.000000000 -0400
9986@@ -36,6 +36,9 @@ extern int proc_tid_stat(struct task_str
9987 extern int proc_tgid_stat(struct task_struct *, char *);
9988 extern int proc_pid_status(struct task_struct *, char *);
9989 extern int proc_pid_statm(struct task_struct *, char *);
9990+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
9991+extern int proc_pid_ipaddr(struct task_struct*,char*);
9992+#endif
9993
9994 void free_proc_entry(struct proc_dir_entry *de);
9995
9996diff -urNp linux-2.6.17.11/fs/proc/proc_misc.c linux-2.6.17.11/fs/proc/proc_misc.c
9997--- linux-2.6.17.11/fs/proc/proc_misc.c 2006-08-07 00:18:54.000000000 -0400
9998+++ linux-2.6.17.11/fs/proc/proc_misc.c 2006-08-12 08:17:55.000000000 -0400
9999@@ -651,6 +651,8 @@ void create_seq_entry(char *name, mode_t
10000 void __init proc_misc_init(void)
10001 {
10002 struct proc_dir_entry *entry;
10003+ int gr_mode = 0;
10004+
10005 static struct {
10006 char *name;
10007 int (*read_proc)(char*,char**,off_t,int,int*,void*);
10008@@ -666,7 +668,9 @@ void __init proc_misc_init(void)
10009 {"stram", stram_read_proc},
10010 #endif
10011 {"filesystems", filesystems_read_proc},
10012+#ifndef CONFIG_GRKERNSEC_PROC_ADD
10013 {"cmdline", cmdline_read_proc},
10014+#endif
10015 {"locks", locks_read_proc},
10016 {"execdomains", execdomains_read_proc},
10017 {NULL,}
10018@@ -674,19 +678,36 @@ void __init proc_misc_init(void)
10019 for (p = simple_ones; p->name; p++)
10020 create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
10021
10022+#ifdef CONFIG_GRKERNSEC_PROC_USER
10023+ gr_mode = S_IRUSR;
10024+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
10025+ gr_mode = S_IRUSR | S_IRGRP;
10026+#endif
10027+#ifdef CONFIG_GRKERNSEC_PROC_ADD
10028+ create_proc_read_entry("cmdline", gr_mode, NULL, &cmdline_read_proc, NULL);
10029+#endif
10030+
10031 proc_symlink("mounts", NULL, "self/mounts");
10032
10033 /* And now for trickier ones */
10034 entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
10035 if (entry)
10036 entry->proc_fops = &proc_kmsg_operations;
10037+#ifdef CONFIG_GRKERNSEC_PROC_ADD
10038+ create_seq_entry("devices", gr_mode, &proc_devinfo_operations);
10039+#else
10040 create_seq_entry("devices", 0, &proc_devinfo_operations);
10041+#endif
10042 create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
10043 create_seq_entry("partitions", 0, &proc_partitions_operations);
10044 create_seq_entry("stat", 0, &proc_stat_operations);
10045 create_seq_entry("interrupts", 0, &proc_interrupts_operations);
10046 #ifdef CONFIG_SLAB
10047+#ifdef CONFIG_GRKERNSEC_PROC_ADD
10048+ create_seq_entry("slabinfo",S_IWUSR|gr_mode,&proc_slabinfo_operations);
10049+#else
10050 create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
10051+#endif
10052 #ifdef CONFIG_DEBUG_SLAB_LEAK
10053 create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations);
10054 #endif
10055@@ -701,7 +722,7 @@ void __init proc_misc_init(void)
10056 #ifdef CONFIG_SCHEDSTATS
10057 create_seq_entry("schedstat", 0, &proc_schedstat_operations);
10058 #endif
10059-#ifdef CONFIG_PROC_KCORE
10060+#if defined(CONFIG_PROC_KCORE) && !defined(CONFIG_GRKERNSEC_PROC_ADD)
10061 proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
10062 if (proc_root_kcore) {
10063 proc_root_kcore->proc_fops = &proc_kcore_operations;
10064diff -urNp linux-2.6.17.11/fs/proc/root.c linux-2.6.17.11/fs/proc/root.c
10065--- linux-2.6.17.11/fs/proc/root.c 2006-08-07 00:18:54.000000000 -0400
10066+++ linux-2.6.17.11/fs/proc/root.c 2006-08-12 08:17:55.000000000 -0400
10067@@ -53,7 +53,13 @@ void __init proc_root_init(void)
10068 return;
10069 }
10070 proc_misc_init();
10071+#ifdef CONFIG_GRKERNSEC_PROC_USER
10072+ proc_net = proc_mkdir_mode("net", S_IRUSR | S_IXUSR, NULL);
10073+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
10074+ proc_net = proc_mkdir_mode("net", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL);
10075+#else
10076 proc_net = proc_mkdir("net", NULL);
10077+#endif
10078 proc_net_stat = proc_mkdir("net/stat", NULL);
10079
10080 #ifdef CONFIG_SYSVIPC
10081@@ -77,7 +83,15 @@ void __init proc_root_init(void)
10082 #ifdef CONFIG_PROC_DEVICETREE
10083 proc_device_tree_init();
10084 #endif
10085+#ifdef CONFIG_GRKERNSEC_PROC_ADD
10086+#ifdef CONFIG_GRKERNSEC_PROC_USER
10087+ proc_bus = proc_mkdir_mode("bus", S_IRUSR | S_IXUSR, NULL);
10088+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
10089+ proc_bus = proc_mkdir_mode("bus", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL);
10090+#endif
10091+#else
10092 proc_bus = proc_mkdir("bus", NULL);
10093+#endif
10094 }
10095
10096 static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
10097diff -urNp linux-2.6.17.11/fs/proc/task_mmu.c linux-2.6.17.11/fs/proc/task_mmu.c
10098--- linux-2.6.17.11/fs/proc/task_mmu.c 2006-08-07 00:18:54.000000000 -0400
10099+++ linux-2.6.17.11/fs/proc/task_mmu.c 2006-08-12 08:17:55.000000000 -0400
10100@@ -43,15 +43,27 @@ char *task_mem(struct mm_struct *mm, cha
10101 "VmStk:\t%8lu kB\n"
10102 "VmExe:\t%8lu kB\n"
10103 "VmLib:\t%8lu kB\n"
10104- "VmPTE:\t%8lu kB\n",
10105- hiwater_vm << (PAGE_SHIFT-10),
10106+ "VmPTE:\t%8lu kB\n"
10107+
10108+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
10109+ "CsBase:\t%8lx\nCsLim:\t%8lx\n"
10110+#endif
10111+
10112+ ,hiwater_vm << (PAGE_SHIFT-10),
10113 (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
10114 mm->locked_vm << (PAGE_SHIFT-10),
10115 hiwater_rss << (PAGE_SHIFT-10),
10116 total_rss << (PAGE_SHIFT-10),
10117 data << (PAGE_SHIFT-10),
10118 mm->stack_vm << (PAGE_SHIFT-10), text, lib,
10119- (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
10120+ (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10
10121+
10122+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
10123+ , mm->context.user_cs_base, mm->context.user_cs_limit
10124+#endif
10125+
10126+ );
10127+
10128 return buffer;
10129 }
10130
10131@@ -118,6 +130,12 @@ struct mem_size_stats
10132 unsigned long private_dirty;
10133 };
10134
10135+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
10136+#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
10137+ (_mm->pax_flags & MF_PAX_RANDMMAP || \
10138+ _mm->pax_flags & MF_PAX_SEGMEXEC))
10139+#endif
10140+
10141 static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
10142 {
10143 struct task_struct *task = m->private;
10144@@ -136,13 +154,30 @@ static int show_map_internal(struct seq_
10145 }
10146
10147 seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
10148+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
10149+ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_start,
10150+ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_end,
10151+#else
10152 vma->vm_start,
10153 vma->vm_end,
10154+#endif
10155+
10156+#if 0
10157+ flags & VM_MAYREAD ? flags & VM_READ ? 'R' : '+' : flags & VM_READ ? 'r' : '-',
10158+ flags & VM_MAYWRITE ? flags & VM_WRITE ? 'W' : '+' : flags & VM_WRITE ? 'w' : '-',
10159+ flags & VM_MAYEXEC ? flags & VM_EXEC ? 'X' : '+' : flags & VM_EXEC ? 'x' : '-',
10160+#else
10161 flags & VM_READ ? 'r' : '-',
10162 flags & VM_WRITE ? 'w' : '-',
10163 flags & VM_EXEC ? 'x' : '-',
10164+#endif
10165+
10166 flags & VM_MAYSHARE ? 's' : 'p',
10167+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
10168+ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_pgoff << PAGE_SHIFT,
10169+#else
10170 vma->vm_pgoff << PAGE_SHIFT,
10171+#endif
10172 MAJOR(dev), MINOR(dev), ino, &len);
10173
10174 /*
10175@@ -154,13 +189,13 @@ static int show_map_internal(struct seq_
10176 seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
10177 } else {
10178 if (mm) {
10179- if (vma->vm_start <= mm->start_brk &&
10180- vma->vm_end >= mm->brk) {
10181+ if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
10182 pad_len_spaces(m, len);
10183 seq_puts(m, "[heap]");
10184 } else {
10185- if (vma->vm_start <= mm->start_stack &&
10186- vma->vm_end >= mm->start_stack) {
10187+ if ((vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP)) ||
10188+ (vma->vm_start <= mm->start_stack &&
10189+ vma->vm_end >= mm->start_stack)) {
10190
10191 pad_len_spaces(m, len);
10192 seq_puts(m, "[stack]");
10193@@ -173,7 +208,25 @@ static int show_map_internal(struct seq_
10194 }
10195 seq_putc(m, '\n');
10196
10197- if (mss)
10198+
10199+ if (mss) {
10200+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
10201+ if (PAX_RAND_FLAGS(mm))
10202+ seq_printf(m,
10203+ "Size: %8lu kB\n"
10204+ "Rss: %8lu kB\n"
10205+ "Shared_Clean: %8lu kB\n"
10206+ "Shared_Dirty: %8lu kB\n"
10207+ "Private_Clean: %8lu kB\n"
10208+ "Private_Dirty: %8lu kB\n",
10209+ 0UL,
10210+ 0UL,
10211+ 0UL,
10212+ 0UL,
10213+ 0UL,
10214+ 0UL);
10215+ else
10216+#endif
10217 seq_printf(m,
10218 "Size: %8lu kB\n"
10219 "Rss: %8lu kB\n"
10220@@ -187,6 +240,7 @@ static int show_map_internal(struct seq_
10221 mss->shared_dirty >> 10,
10222 mss->private_clean >> 10,
10223 mss->private_dirty >> 10);
10224+ }
10225
10226 if (m->count < m->size) /* vma is copied successfully */
10227 m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
10228diff -urNp linux-2.6.17.11/fs/readdir.c linux-2.6.17.11/fs/readdir.c
10229--- linux-2.6.17.11/fs/readdir.c 2006-08-07 00:18:54.000000000 -0400
10230+++ linux-2.6.17.11/fs/readdir.c 2006-08-12 08:17:55.000000000 -0400
10231@@ -16,6 +16,8 @@
10232 #include <linux/security.h>
10233 #include <linux/syscalls.h>
10234 #include <linux/unistd.h>
10235+#include <linux/namei.h>
10236+#include <linux/grsecurity.h>
10237
10238 #include <asm/uaccess.h>
10239
10240@@ -65,6 +67,7 @@ struct old_linux_dirent {
10241
10242 struct readdir_callback {
10243 struct old_linux_dirent __user * dirent;
10244+ struct file * file;
10245 int result;
10246 };
10247
10248@@ -76,6 +79,10 @@ static int fillonedir(void * __buf, cons
10249
10250 if (buf->result)
10251 return -EINVAL;
10252+
10253+ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
10254+ return 0;
10255+
10256 buf->result++;
10257 dirent = buf->dirent;
10258 if (!access_ok(VERIFY_WRITE, dirent,
10259@@ -107,6 +114,7 @@ asmlinkage long old_readdir(unsigned int
10260
10261 buf.result = 0;
10262 buf.dirent = dirent;
10263+ buf.file = file;
10264
10265 error = vfs_readdir(file, fillonedir, &buf);
10266 if (error >= 0)
10267@@ -133,6 +141,7 @@ struct linux_dirent {
10268 struct getdents_callback {
10269 struct linux_dirent __user * current_dir;
10270 struct linux_dirent __user * previous;
10271+ struct file * file;
10272 int count;
10273 int error;
10274 };
10275@@ -147,6 +156,10 @@ static int filldir(void * __buf, const c
10276 buf->error = -EINVAL; /* only used if we fail.. */
10277 if (reclen > buf->count)
10278 return -EINVAL;
10279+
10280+ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
10281+ return 0;
10282+
10283 dirent = buf->previous;
10284 if (dirent) {
10285 if (__put_user(offset, &dirent->d_off))
10286@@ -191,6 +204,7 @@ asmlinkage long sys_getdents(unsigned in
10287
10288 buf.current_dir = dirent;
10289 buf.previous = NULL;
10290+ buf.file = file;
10291 buf.count = count;
10292 buf.error = 0;
10293
10294@@ -217,6 +231,7 @@ out:
10295 struct getdents_callback64 {
10296 struct linux_dirent64 __user * current_dir;
10297 struct linux_dirent64 __user * previous;
10298+ struct file * file;
10299 int count;
10300 int error;
10301 };
10302@@ -231,6 +246,10 @@ static int filldir64(void * __buf, const
10303 buf->error = -EINVAL; /* only used if we fail.. */
10304 if (reclen > buf->count)
10305 return -EINVAL;
10306+
10307+ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
10308+ return 0;
10309+
10310 dirent = buf->previous;
10311 if (dirent) {
10312 if (__put_user(offset, &dirent->d_off))
10313@@ -277,6 +296,7 @@ asmlinkage long sys_getdents64(unsigned
10314
10315 buf.current_dir = dirent;
10316 buf.previous = NULL;
10317+ buf.file = file;
10318 buf.count = count;
10319 buf.error = 0;
10320
10321diff -urNp linux-2.6.17.11/fs/xfs/linux-2.6/xfs_file.c linux-2.6.17.11/fs/xfs/linux-2.6/xfs_file.c
10322--- linux-2.6.17.11/fs/xfs/linux-2.6/xfs_file.c 2006-08-07 00:18:54.000000000 -0400
10323+++ linux-2.6.17.11/fs/xfs/linux-2.6/xfs_file.c 2006-08-12 08:17:55.000000000 -0400
10324@@ -461,6 +461,11 @@ xfs_file_mmap(
10325 vattr_t vattr;
10326 int error;
10327
10328+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32)
10329+ if ((vma->vm_mm->pax_flags & MF_PAX_PAGEEXEC) && !(vma->vm_flags & VM_EXEC))
10330+ vma->vm_page_prot = __pgprot(pte_val(pte_exprotect(__pte(pgprot_val(vma->vm_page_prot)))));
10331+#endif
10332+
10333 vma->vm_ops = &xfs_file_vm_ops;
10334
10335 #ifdef CONFIG_XFS_DMAPI
10336diff -urNp linux-2.6.17.11/grsecurity/gracl_alloc.c linux-2.6.17.11/grsecurity/gracl_alloc.c
10337--- linux-2.6.17.11/grsecurity/gracl_alloc.c 1969-12-31 19:00:00.000000000 -0500
10338+++ linux-2.6.17.11/grsecurity/gracl_alloc.c 2006-08-12 08:17:55.000000000 -0400
10339@@ -0,0 +1,91 @@
10340+#include <linux/kernel.h>
10341+#include <linux/mm.h>
10342+#include <linux/slab.h>
10343+#include <linux/vmalloc.h>
10344+#include <linux/gracl.h>
10345+#include <linux/grsecurity.h>
10346+
10347+static unsigned long alloc_stack_next = 1;
10348+static unsigned long alloc_stack_size = 1;
10349+static void **alloc_stack;
10350+
10351+static __inline__ int
10352+alloc_pop(void)
10353+{
10354+ if (alloc_stack_next == 1)
10355+ return 0;
10356+
10357+ kfree(alloc_stack[alloc_stack_next - 2]);
10358+
10359+ alloc_stack_next--;
10360+
10361+ return 1;
10362+}
10363+
10364+static __inline__ void
10365+alloc_push(void *buf)
10366+{
10367+ if (alloc_stack_next >= alloc_stack_size)
10368+ BUG();
10369+
10370+ alloc_stack[alloc_stack_next - 1] = buf;
10371+
10372+ alloc_stack_next++;
10373+
10374+ return;
10375+}
10376+
10377+void *
10378+acl_alloc(unsigned long len)
10379+{
10380+ void *ret;
10381+
10382+ if (len > PAGE_SIZE)
10383+ BUG();
10384+
10385+ ret = kmalloc(len, GFP_KERNEL);
10386+
10387+ if (ret)
10388+ alloc_push(ret);
10389+
10390+ return ret;
10391+}
10392+
10393+void
10394+acl_free_all(void)
10395+{
10396+ if (gr_acl_is_enabled() || !alloc_stack)
10397+ return;
10398+
10399+ while (alloc_pop()) ;
10400+
10401+ if (alloc_stack) {
10402+ if ((alloc_stack_size * sizeof (void *)) <= PAGE_SIZE)
10403+ kfree(alloc_stack);
10404+ else
10405+ vfree(alloc_stack);
10406+ }
10407+
10408+ alloc_stack = NULL;
10409+ alloc_stack_size = 1;
10410+ alloc_stack_next = 1;
10411+
10412+ return;
10413+}
10414+
10415+int
10416+acl_alloc_stack_init(unsigned long size)
10417+{
10418+ if ((size * sizeof (void *)) <= PAGE_SIZE)
10419+ alloc_stack =
10420+ (void **) kmalloc(size * sizeof (void *), GFP_KERNEL);
10421+ else
10422+ alloc_stack = (void **) vmalloc(size * sizeof (void *));
10423+
10424+ alloc_stack_size = size;
10425+
10426+ if (!alloc_stack)
10427+ return 0;
10428+ else
10429+ return 1;
10430+}
10431diff -urNp linux-2.6.17.11/grsecurity/gracl.c linux-2.6.17.11/grsecurity/gracl.c
10432--- linux-2.6.17.11/grsecurity/gracl.c 1969-12-31 19:00:00.000000000 -0500
10433+++ linux-2.6.17.11/grsecurity/gracl.c 2006-08-12 08:17:55.000000000 -0400
10434@@ -0,0 +1,3547 @@
10435+#include <linux/kernel.h>
10436+#include <linux/module.h>
10437+#include <linux/sched.h>
10438+#include <linux/mm.h>
10439+#include <linux/file.h>
10440+#include <linux/fs.h>
10441+#include <linux/namei.h>
10442+#include <linux/mount.h>
10443+#include <linux/tty.h>
10444+#include <linux/proc_fs.h>
10445+#include <linux/smp_lock.h>
10446+#include <linux/slab.h>
10447+#include <linux/vmalloc.h>
10448+#include <linux/types.h>
10449+#include <linux/capability.h>
10450+#include <linux/sysctl.h>
10451+#include <linux/netdevice.h>
10452+#include <linux/ptrace.h>
10453+#include <linux/gracl.h>
10454+#include <linux/gralloc.h>
10455+#include <linux/grsecurity.h>
10456+#include <linux/grinternal.h>
10457+#include <linux/percpu.h>
10458+
10459+#include <asm/uaccess.h>
10460+#include <asm/errno.h>
10461+#include <asm/mman.h>
10462+
10463+static struct acl_role_db acl_role_set;
10464+static struct name_db name_set;
10465+static struct inodev_db inodev_set;
10466+
10467+/* for keeping track of userspace pointers used for subjects, so we
10468+ can share references in the kernel as well
10469+*/
10470+
10471+static struct dentry *real_root;
10472+static struct vfsmount *real_root_mnt;
10473+
10474+static struct acl_subj_map_db subj_map_set;
10475+
10476+static struct acl_role_label *default_role;
10477+
10478+static u16 acl_sp_role_value;
10479+
10480+extern char *gr_shared_page[4];
10481+static DECLARE_MUTEX(gr_dev_sem);
10482+rwlock_t gr_inode_lock = RW_LOCK_UNLOCKED;
10483+
10484+struct gr_arg *gr_usermode;
10485+
10486+static unsigned int gr_status = GR_STATUS_INIT;
10487+
10488+extern int chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum);
10489+extern void gr_clear_learn_entries(void);
10490+
10491+#ifdef CONFIG_GRKERNSEC_RESLOG
10492+extern void gr_log_resource(const struct task_struct *task,
10493+ const int res, const unsigned long wanted, const int gt);
10494+#endif
10495+
10496+extern char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
10497+ struct dentry *root, struct vfsmount *rootmnt,
10498+ char *buffer, int buflen);
10499+
10500+unsigned char *gr_system_salt;
10501+unsigned char *gr_system_sum;
10502+
10503+static struct sprole_pw **acl_special_roles = NULL;
10504+static __u16 num_sprole_pws = 0;
10505+
10506+static struct acl_role_label *kernel_role = NULL;
10507+
10508+static unsigned int gr_auth_attempts = 0;
10509+static unsigned long gr_auth_expires = 0UL;
10510+
10511+extern struct vfsmount *sock_mnt;
10512+extern struct vfsmount *pipe_mnt;
10513+extern struct vfsmount *shm_mnt;
10514+static struct acl_object_label *fakefs_obj;
10515+
10516+extern int gr_init_uidset(void);
10517+extern void gr_free_uidset(void);
10518+extern void gr_remove_uid(uid_t uid);
10519+extern int gr_find_uid(uid_t uid);
10520+
10521+__inline__ int
10522+gr_acl_is_enabled(void)
10523+{
10524+ return (gr_status & GR_READY);
10525+}
10526+
10527+char gr_roletype_to_char(void)
10528+{
10529+ switch (current->role->roletype &
10530+ (GR_ROLE_DEFAULT | GR_ROLE_USER | GR_ROLE_GROUP |
10531+ GR_ROLE_SPECIAL)) {
10532+ case GR_ROLE_DEFAULT:
10533+ return 'D';
10534+ case GR_ROLE_USER:
10535+ return 'U';
10536+ case GR_ROLE_GROUP:
10537+ return 'G';
10538+ case GR_ROLE_SPECIAL:
10539+ return 'S';
10540+ }
10541+
10542+ return 'X';
10543+}
10544+
10545+__inline__ int
10546+gr_acl_tpe_check(void)
10547+{
10548+ if (unlikely(!(gr_status & GR_READY)))
10549+ return 0;
10550+ if (current->role->roletype & GR_ROLE_TPE)
10551+ return 1;
10552+ else
10553+ return 0;
10554+}
10555+
10556+int
10557+gr_handle_rawio(const struct inode *inode)
10558+{
10559+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
10560+ if (inode && S_ISBLK(inode->i_mode) &&
10561+ grsec_enable_chroot_caps && proc_is_chrooted(current) &&
10562+ !capable(CAP_SYS_RAWIO))
10563+ return 1;
10564+#endif
10565+ return 0;
10566+}
10567+
10568+static int
10569+gr_streq(const char *a, const char *b, const unsigned int lena, const unsigned int lenb)
10570+{
10571+ int i;
10572+ unsigned long *l1;
10573+ unsigned long *l2;
10574+ unsigned char *c1;
10575+ unsigned char *c2;
10576+ int num_longs;
10577+
10578+ if (likely(lena != lenb))
10579+ return 0;
10580+
10581+ l1 = (unsigned long *)a;
10582+ l2 = (unsigned long *)b;
10583+
10584+ num_longs = lena / sizeof(unsigned long);
10585+
10586+ for (i = num_longs; i--; l1++, l2++) {
10587+ if (unlikely(*l1 != *l2))
10588+ return 0;
10589+ }
10590+
10591+ c1 = (unsigned char *) l1;
10592+ c2 = (unsigned char *) l2;
10593+
10594+ i = lena - (num_longs * sizeof(unsigned long));
10595+
10596+ for (; i--; c1++, c2++) {
10597+ if (unlikely(*c1 != *c2))
10598+ return 0;
10599+ }
10600+
10601+ return 1;
10602+}
10603+
10604+static char *
10605+gen_full_path(struct dentry *dentry, struct vfsmount *vfsmnt,
10606+ struct dentry *root, struct vfsmount *rootmnt, char *buf, int buflen)
10607+{
10608+ char *end = buf + buflen;
10609+ char *retval;
10610+ int namelen = 0;
10611+
10612+ *--end = '\0';
10613+
10614+ retval = end - 1;
10615+ *retval = '/';
10616+
10617+ if (dentry == root && vfsmnt == rootmnt)
10618+ return retval;
10619+ if (dentry != vfsmnt->mnt_root && !IS_ROOT(dentry)) {
10620+ namelen = strlen(dentry->d_name.name);
10621+ buflen -= namelen;
10622+ if (buflen < 2)
10623+ goto err;
10624+ if (dentry->d_parent != root || vfsmnt != rootmnt)
10625+ buflen--;
10626+ }
10627+
10628+ retval = __d_path(dentry->d_parent, vfsmnt, root, rootmnt, buf, buflen);
10629+ if (unlikely(IS_ERR(retval)))
10630+err:
10631+ retval = strcpy(buf, "<path too long>");
10632+ else if (namelen != 0) {
10633+ end = buf + buflen - 1; // accounts for null termination
10634+ if (dentry->d_parent != root || vfsmnt != rootmnt)
10635+ *end++ = '/'; // accounted for above with buflen--
10636+ memcpy(end, dentry->d_name.name, namelen);
10637+ }
10638+
10639+ return retval;
10640+}
10641+
10642+static char *
10643+__d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
10644+ char *buf, int buflen)
10645+{
10646+ char *res;
10647+
10648+ /* we can use real_root, real_root_mnt, because this is only called
10649+ by the RBAC system */
10650+ res = gen_full_path((struct dentry *)dentry, (struct vfsmount *)vfsmnt, real_root, real_root_mnt, buf, buflen);
10651+
10652+ return res;
10653+}
10654+
10655+static char *
10656+d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
10657+ char *buf, int buflen)
10658+{
10659+ char *res;
10660+ struct dentry *root;
10661+ struct vfsmount *rootmnt;
10662+
10663+ /* we can't use real_root, real_root_mnt, because they belong only to the RBAC system */
10664+ read_lock(&child_reaper->fs->lock);
10665+ root = dget(child_reaper->fs->root);
10666+ rootmnt = mntget(child_reaper->fs->rootmnt);
10667+ read_unlock(&child_reaper->fs->lock);
10668+
10669+ spin_lock(&dcache_lock);
10670+ res = gen_full_path((struct dentry *)dentry, (struct vfsmount *)vfsmnt, root, rootmnt, buf, buflen);
10671+ spin_unlock(&dcache_lock);
10672+
10673+ dput(root);
10674+ mntput(rootmnt);
10675+ return res;
10676+}
10677+
10678+static char *
10679+gr_to_filename_rbac(const struct dentry *dentry, const struct vfsmount *mnt)
10680+{
10681+ char *ret;
10682+ spin_lock(&dcache_lock);
10683+ ret = __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()),
10684+ PAGE_SIZE);
10685+ spin_unlock(&dcache_lock);
10686+ return ret;
10687+}
10688+
10689+char *
10690+gr_to_filename_nolock(const struct dentry *dentry, const struct vfsmount *mnt)
10691+{
10692+ return __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()),
10693+ PAGE_SIZE);
10694+}
10695+
10696+char *
10697+gr_to_filename(const struct dentry *dentry, const struct vfsmount *mnt)
10698+{
10699+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()),
10700+ PAGE_SIZE);
10701+}
10702+
10703+char *
10704+gr_to_filename1(const struct dentry *dentry, const struct vfsmount *mnt)
10705+{
10706+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[1], smp_processor_id()),
10707+ PAGE_SIZE);
10708+}
10709+
10710+char *
10711+gr_to_filename2(const struct dentry *dentry, const struct vfsmount *mnt)
10712+{
10713+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[2], smp_processor_id()),
10714+ PAGE_SIZE);
10715+}
10716+
10717+char *
10718+gr_to_filename3(const struct dentry *dentry, const struct vfsmount *mnt)
10719+{
10720+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[3], smp_processor_id()),
10721+ PAGE_SIZE);
10722+}
10723+
10724+__inline__ __u32
10725+to_gr_audit(const __u32 reqmode)
10726+{
10727+ /* masks off auditable permission flags, then shifts them to create
10728+ auditing flags, and adds the special case of append auditing if
10729+ we're requesting write */
10730+ return (((reqmode & GR_AUDIT_READ) << 10) | ((reqmode & GR_WRITE) ? GR_AUDIT_APPEND : 0));
10731+}
10732+
10733+struct acl_subject_label *
10734+lookup_subject_map(const struct acl_subject_label *userp)
10735+{
10736+ unsigned int index = shash(userp, subj_map_set.s_size);
10737+ struct subject_map *match;
10738+
10739+ match = subj_map_set.s_hash[index];
10740+
10741+ while (match && match->user != userp)
10742+ match = match->next;
10743+
10744+ if (match != NULL)
10745+ return match->kernel;
10746+ else
10747+ return NULL;
10748+}
10749+
10750+static void
10751+insert_subj_map_entry(struct subject_map *subjmap)
10752+{
10753+ unsigned int index = shash(subjmap->user, subj_map_set.s_size);
10754+ struct subject_map **curr;
10755+
10756+ subjmap->prev = NULL;
10757+
10758+ curr = &subj_map_set.s_hash[index];
10759+ if (*curr != NULL)
10760+ (*curr)->prev = subjmap;
10761+
10762+ subjmap->next = *curr;
10763+ *curr = subjmap;
10764+
10765+ return;
10766+}
10767+
10768+static struct acl_role_label *
10769+lookup_acl_role_label(const struct task_struct *task, const uid_t uid,
10770+ const gid_t gid)
10771+{
10772+ unsigned int index = rhash(uid, GR_ROLE_USER, acl_role_set.r_size);
10773+ struct acl_role_label *match;
10774+ struct role_allowed_ip *ipp;
10775+ unsigned int x;
10776+
10777+ match = acl_role_set.r_hash[index];
10778+
10779+ while (match) {
10780+ if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_USER)) == (GR_ROLE_DOMAIN | GR_ROLE_USER)) {
10781+ for (x = 0; x < match->domain_child_num; x++) {
10782+ if (match->domain_children[x] == uid)
10783+ goto found;
10784+ }
10785+ } else if (match->uidgid == uid && match->roletype & GR_ROLE_USER)
10786+ break;
10787+ match = match->next;
10788+ }
10789+found:
10790+ if (match == NULL) {
10791+ try_group:
10792+ index = rhash(gid, GR_ROLE_GROUP, acl_role_set.r_size);
10793+ match = acl_role_set.r_hash[index];
10794+
10795+ while (match) {
10796+ if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) == (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) {
10797+ for (x = 0; x < match->domain_child_num; x++) {
10798+ if (match->domain_children[x] == gid)
10799+ goto found2;
10800+ }
10801+ } else if (match->uidgid == gid && match->roletype & GR_ROLE_GROUP)
10802+ break;
10803+ match = match->next;
10804+ }
10805+found2:
10806+ if (match == NULL)
10807+ match = default_role;
10808+ if (match->allowed_ips == NULL)
10809+ return match;
10810+ else {
10811+ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
10812+ if (likely
10813+ ((ntohl(task->signal->curr_ip) & ipp->netmask) ==
10814+ (ntohl(ipp->addr) & ipp->netmask)))
10815+ return match;
10816+ }
10817+ match = default_role;
10818+ }
10819+ } else if (match->allowed_ips == NULL) {
10820+ return match;
10821+ } else {
10822+ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
10823+ if (likely
10824+ ((ntohl(task->signal->curr_ip) & ipp->netmask) ==
10825+ (ntohl(ipp->addr) & ipp->netmask)))
10826+ return match;
10827+ }
10828+ goto try_group;
10829+ }
10830+
10831+ return match;
10832+}
10833+
10834+struct acl_subject_label *
10835+lookup_acl_subj_label(const ino_t ino, const dev_t dev,
10836+ const struct acl_role_label *role)
10837+{
10838+ unsigned int index = fhash(ino, dev, role->subj_hash_size);
10839+ struct acl_subject_label *match;
10840+
10841+ match = role->subj_hash[index];
10842+
10843+ while (match && (match->inode != ino || match->device != dev ||
10844+ (match->mode & GR_DELETED))) {
10845+ match = match->next;
10846+ }
10847+
10848+ if (match && !(match->mode & GR_DELETED))
10849+ return match;
10850+ else
10851+ return NULL;
10852+}
10853+
10854+static struct acl_object_label *
10855+lookup_acl_obj_label(const ino_t ino, const dev_t dev,
10856+ const struct acl_subject_label *subj)
10857+{
10858+ unsigned int index = fhash(ino, dev, subj->obj_hash_size);
10859+ struct acl_object_label *match;
10860+
10861+ match = subj->obj_hash[index];
10862+
10863+ while (match && (match->inode != ino || match->device != dev ||
10864+ (match->mode & GR_DELETED))) {
10865+ match = match->next;
10866+ }
10867+
10868+ if (match && !(match->mode & GR_DELETED))
10869+ return match;
10870+ else
10871+ return NULL;
10872+}
10873+
10874+static struct acl_object_label *
10875+lookup_acl_obj_label_create(const ino_t ino, const dev_t dev,
10876+ const struct acl_subject_label *subj)
10877+{
10878+ unsigned int index = fhash(ino, dev, subj->obj_hash_size);
10879+ struct acl_object_label *match;
10880+
10881+ match = subj->obj_hash[index];
10882+
10883+ while (match && (match->inode != ino || match->device != dev ||
10884+ !(match->mode & GR_DELETED))) {
10885+ match = match->next;
10886+ }
10887+
10888+ if (match && (match->mode & GR_DELETED))
10889+ return match;
10890+
10891+ match = subj->obj_hash[index];
10892+
10893+ while (match && (match->inode != ino || match->device != dev ||
10894+ (match->mode & GR_DELETED))) {
10895+ match = match->next;
10896+ }
10897+
10898+ if (match && !(match->mode & GR_DELETED))
10899+ return match;
10900+ else
10901+ return NULL;
10902+}
10903+
10904+static struct name_entry *
10905+lookup_name_entry(const char *name)
10906+{
10907+ unsigned int len = strlen(name);
10908+ unsigned int key = full_name_hash(name, len);
10909+ unsigned int index = key % name_set.n_size;
10910+ struct name_entry *match;
10911+
10912+ match = name_set.n_hash[index];
10913+
10914+ while (match && (match->key != key || !gr_streq(match->name, name, match->len, len)))
10915+ match = match->next;
10916+
10917+ return match;
10918+}
10919+
10920+static struct inodev_entry *
10921+lookup_inodev_entry(const ino_t ino, const dev_t dev)
10922+{
10923+ unsigned int index = fhash(ino, dev, inodev_set.i_size);
10924+ struct inodev_entry *match;
10925+
10926+ match = inodev_set.i_hash[index];
10927+
10928+ while (match && (match->nentry->inode != ino || match->nentry->device != dev))
10929+ match = match->next;
10930+
10931+ return match;
10932+}
10933+
10934+static void
10935+insert_inodev_entry(struct inodev_entry *entry)
10936+{
10937+ unsigned int index = fhash(entry->nentry->inode, entry->nentry->device,
10938+ inodev_set.i_size);
10939+ struct inodev_entry **curr;
10940+
10941+ entry->prev = NULL;
10942+
10943+ curr = &inodev_set.i_hash[index];
10944+ if (*curr != NULL)
10945+ (*curr)->prev = entry;
10946+
10947+ entry->next = *curr;
10948+ *curr = entry;
10949+
10950+ return;
10951+}
10952+
10953+static void
10954+__insert_acl_role_label(struct acl_role_label *role, uid_t uidgid)
10955+{
10956+ unsigned int index =
10957+ rhash(uidgid, role->roletype & (GR_ROLE_USER | GR_ROLE_GROUP), acl_role_set.r_size);
10958+ struct acl_role_label **curr;
10959+
10960+ role->prev = NULL;
10961+
10962+ curr = &acl_role_set.r_hash[index];
10963+ if (*curr != NULL)
10964+ (*curr)->prev = role;
10965+
10966+ role->next = *curr;
10967+ *curr = role;
10968+
10969+ return;
10970+}
10971+
10972+static void
10973+insert_acl_role_label(struct acl_role_label *role)
10974+{
10975+ int i;
10976+
10977+ if (role->roletype & GR_ROLE_DOMAIN) {
10978+ for (i = 0; i < role->domain_child_num; i++)
10979+ __insert_acl_role_label(role, role->domain_children[i]);
10980+ } else
10981+ __insert_acl_role_label(role, role->uidgid);
10982+}
10983+
10984+static int
10985+insert_name_entry(char *name, const ino_t inode, const dev_t device)
10986+{
10987+ struct name_entry **curr, *nentry;
10988+ struct inodev_entry *ientry;
10989+ unsigned int len = strlen(name);
10990+ unsigned int key = full_name_hash(name, len);
10991+ unsigned int index = key % name_set.n_size;
10992+
10993+ curr = &name_set.n_hash[index];
10994+
10995+ while (*curr && ((*curr)->key != key || !gr_streq((*curr)->name, name, (*curr)->len, len)))
10996+ curr = &((*curr)->next);
10997+
10998+ if (*curr != NULL)
10999+ return 1;
11000+
11001+ nentry = acl_alloc(sizeof (struct name_entry));
11002+ if (nentry == NULL)
11003+ return 0;
11004+ ientry = acl_alloc(sizeof (struct inodev_entry));
11005+ if (ientry == NULL)
11006+ return 0;
11007+ ientry->nentry = nentry;
11008+
11009+ nentry->key = key;
11010+ nentry->name = name;
11011+ nentry->inode = inode;
11012+ nentry->device = device;
11013+ nentry->len = len;
11014+
11015+ nentry->prev = NULL;
11016+ curr = &name_set.n_hash[index];
11017+ if (*curr != NULL)
11018+ (*curr)->prev = nentry;
11019+ nentry->next = *curr;
11020+ *curr = nentry;
11021+
11022+ /* insert us into the table searchable by inode/dev */
11023+ insert_inodev_entry(ientry);
11024+
11025+ return 1;
11026+}
11027+
11028+static void
11029+insert_acl_obj_label(struct acl_object_label *obj,
11030+ struct acl_subject_label *subj)
11031+{
11032+ unsigned int index =
11033+ fhash(obj->inode, obj->device, subj->obj_hash_size);
11034+ struct acl_object_label **curr;
11035+
11036+
11037+ obj->prev = NULL;
11038+
11039+ curr = &subj->obj_hash[index];
11040+ if (*curr != NULL)
11041+ (*curr)->prev = obj;
11042+
11043+ obj->next = *curr;
11044+ *curr = obj;
11045+
11046+ return;
11047+}
11048+
11049+static void
11050+insert_acl_subj_label(struct acl_subject_label *obj,
11051+ struct acl_role_label *role)
11052+{
11053+ unsigned int index = fhash(obj->inode, obj->device, role->subj_hash_size);
11054+ struct acl_subject_label **curr;
11055+
11056+ obj->prev = NULL;
11057+
11058+ curr = &role->subj_hash[index];
11059+ if (*curr != NULL)
11060+ (*curr)->prev = obj;
11061+
11062+ obj->next = *curr;
11063+ *curr = obj;
11064+
11065+ return;
11066+}
11067+
11068+/* allocating chained hash tables, so optimal size is where lambda ~ 1 */
11069+
11070+static void *
11071+create_table(__u32 * len, int elementsize)
11072+{
11073+ unsigned int table_sizes[] = {
11074+ 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381,
11075+ 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
11076+ 4194301, 8388593, 16777213, 33554393, 67108859, 134217689,
11077+ 268435399, 536870909, 1073741789, 2147483647
11078+ };
11079+ void *newtable = NULL;
11080+ unsigned int pwr = 0;
11081+
11082+ while ((pwr < ((sizeof (table_sizes) / sizeof (table_sizes[0])) - 1)) &&
11083+ table_sizes[pwr] <= *len)
11084+ pwr++;
11085+
11086+ if (table_sizes[pwr] <= *len)
11087+ return newtable;
11088+
11089+ if ((table_sizes[pwr] * elementsize) <= PAGE_SIZE)
11090+ newtable =
11091+ kmalloc(table_sizes[pwr] * elementsize, GFP_KERNEL);
11092+ else
11093+ newtable = vmalloc(table_sizes[pwr] * elementsize);
11094+
11095+ *len = table_sizes[pwr];
11096+
11097+ return newtable;
11098+}
11099+
11100+static int
11101+init_variables(const struct gr_arg *arg)
11102+{
11103+ unsigned int stacksize;
11104+
11105+ subj_map_set.s_size = arg->role_db.num_subjects;
11106+ acl_role_set.r_size = arg->role_db.num_roles + arg->role_db.num_domain_children;
11107+ name_set.n_size = arg->role_db.num_objects;
11108+ inodev_set.i_size = arg->role_db.num_objects;
11109+
11110+ if (!subj_map_set.s_size || !acl_role_set.r_size ||
11111+ !name_set.n_size || !inodev_set.i_size)
11112+ return 1;
11113+
11114+ if (!gr_init_uidset())
11115+ return 1;
11116+
11117+ /* set up the stack that holds allocation info */
11118+
11119+ stacksize = arg->role_db.num_pointers + 5;
11120+
11121+ if (!acl_alloc_stack_init(stacksize))
11122+ return 1;
11123+
11124+ /* grab reference for the real root dentry and vfsmount */
11125+ read_lock(&child_reaper->fs->lock);
11126+ real_root_mnt = mntget(child_reaper->fs->rootmnt);
11127+ real_root = dget(child_reaper->fs->root);
11128+ read_unlock(&child_reaper->fs->lock);
11129+
11130+ fakefs_obj = acl_alloc(sizeof(struct acl_object_label));
11131+ if (fakefs_obj == NULL)
11132+ return 1;
11133+ fakefs_obj->mode = GR_FIND | GR_READ | GR_WRITE | GR_EXEC;
11134+
11135+ subj_map_set.s_hash =
11136+ (struct subject_map **) create_table(&subj_map_set.s_size, sizeof(void *));
11137+ acl_role_set.r_hash =
11138+ (struct acl_role_label **) create_table(&acl_role_set.r_size, sizeof(void *));
11139+ name_set.n_hash = (struct name_entry **) create_table(&name_set.n_size, sizeof(void *));
11140+ inodev_set.i_hash =
11141+ (struct inodev_entry **) create_table(&inodev_set.i_size, sizeof(void *));
11142+
11143+ if (!subj_map_set.s_hash || !acl_role_set.r_hash ||
11144+ !name_set.n_hash || !inodev_set.i_hash)
11145+ return 1;
11146+
11147+ memset(subj_map_set.s_hash, 0,
11148+ sizeof(struct subject_map *) * subj_map_set.s_size);
11149+ memset(acl_role_set.r_hash, 0,
11150+ sizeof (struct acl_role_label *) * acl_role_set.r_size);
11151+ memset(name_set.n_hash, 0,
11152+ sizeof (struct name_entry *) * name_set.n_size);
11153+ memset(inodev_set.i_hash, 0,
11154+ sizeof (struct inodev_entry *) * inodev_set.i_size);
11155+
11156+ return 0;
11157+}
11158+
11159+/* free information not needed after startup
11160+ currently contains user->kernel pointer mappings for subjects
11161+*/
11162+
11163+static void
11164+free_init_variables(void)
11165+{
11166+ __u32 i;
11167+
11168+ if (subj_map_set.s_hash) {
11169+ for (i = 0; i < subj_map_set.s_size; i++) {
11170+ if (subj_map_set.s_hash[i]) {
11171+ kfree(subj_map_set.s_hash[i]);
11172+ subj_map_set.s_hash[i] = NULL;
11173+ }
11174+ }
11175+
11176+ if ((subj_map_set.s_size * sizeof (struct subject_map *)) <=
11177+ PAGE_SIZE)
11178+ kfree(subj_map_set.s_hash);
11179+ else
11180+ vfree(subj_map_set.s_hash);
11181+ }
11182+
11183+ return;
11184+}
11185+
11186+static void
11187+free_variables(void)
11188+{
11189+ struct acl_subject_label *s;
11190+ struct acl_role_label *r;
11191+ struct task_struct *task, *task2;
11192+ unsigned int i, x;
11193+
11194+ gr_clear_learn_entries();
11195+
11196+ read_lock(&tasklist_lock);
11197+ do_each_thread(task2, task) {
11198+ task->acl_sp_role = 0;
11199+ task->acl_role_id = 0;
11200+ task->acl = NULL;
11201+ task->role = NULL;
11202+ } while_each_thread(task2, task);
11203+ read_unlock(&tasklist_lock);
11204+
11205+ /* release the reference to the real root dentry and vfsmount */
11206+ if (real_root)
11207+ dput(real_root);
11208+ real_root = NULL;
11209+ if (real_root_mnt)
11210+ mntput(real_root_mnt);
11211+ real_root_mnt = NULL;
11212+
11213+ /* free all object hash tables */
11214+
11215+ FOR_EACH_ROLE_START(r, i)
11216+ if (r->subj_hash == NULL)
11217+ break;
11218+ FOR_EACH_SUBJECT_START(r, s, x)
11219+ if (s->obj_hash == NULL)
11220+ break;
11221+ if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE)
11222+ kfree(s->obj_hash);
11223+ else
11224+ vfree(s->obj_hash);
11225+ FOR_EACH_SUBJECT_END(s, x)
11226+ FOR_EACH_NESTED_SUBJECT_START(r, s)
11227+ if (s->obj_hash == NULL)
11228+ break;
11229+ if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE)
11230+ kfree(s->obj_hash);
11231+ else
11232+ vfree(s->obj_hash);
11233+ FOR_EACH_NESTED_SUBJECT_END(s)
11234+ if ((r->subj_hash_size * sizeof (struct acl_subject_label *)) <= PAGE_SIZE)
11235+ kfree(r->subj_hash);
11236+ else
11237+ vfree(r->subj_hash);
11238+ r->subj_hash = NULL;
11239+ FOR_EACH_ROLE_END(r,i)
11240+
11241+ acl_free_all();
11242+
11243+ if (acl_role_set.r_hash) {
11244+ if ((acl_role_set.r_size * sizeof (struct acl_role_label *)) <=
11245+ PAGE_SIZE)
11246+ kfree(acl_role_set.r_hash);
11247+ else
11248+ vfree(acl_role_set.r_hash);
11249+ }
11250+ if (name_set.n_hash) {
11251+ if ((name_set.n_size * sizeof (struct name_entry *)) <=
11252+ PAGE_SIZE)
11253+ kfree(name_set.n_hash);
11254+ else
11255+ vfree(name_set.n_hash);
11256+ }
11257+
11258+ if (inodev_set.i_hash) {
11259+ if ((inodev_set.i_size * sizeof (struct inodev_entry *)) <=
11260+ PAGE_SIZE)
11261+ kfree(inodev_set.i_hash);
11262+ else
11263+ vfree(inodev_set.i_hash);
11264+ }
11265+
11266+ gr_free_uidset();
11267+
11268+ memset(&name_set, 0, sizeof (struct name_db));
11269+ memset(&inodev_set, 0, sizeof (struct inodev_db));
11270+ memset(&acl_role_set, 0, sizeof (struct acl_role_db));
11271+ memset(&subj_map_set, 0, sizeof (struct acl_subj_map_db));
11272+
11273+ default_role = NULL;
11274+
11275+ return;
11276+}
11277+
11278+static __u32
11279+count_user_objs(struct acl_object_label *userp)
11280+{
11281+ struct acl_object_label o_tmp;
11282+ __u32 num = 0;
11283+
11284+ while (userp) {
11285+ if (copy_from_user(&o_tmp, userp,
11286+ sizeof (struct acl_object_label)))
11287+ break;
11288+
11289+ userp = o_tmp.prev;
11290+ num++;
11291+ }
11292+
11293+ return num;
11294+}
11295+
11296+static struct acl_subject_label *
11297+do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role);
11298+
11299+static int
11300+copy_user_glob(struct acl_object_label *obj)
11301+{
11302+ struct acl_object_label *g_tmp, **guser;
11303+ unsigned int len;
11304+ char *tmp;
11305+
11306+ if (obj->globbed == NULL)
11307+ return 0;
11308+
11309+ guser = &obj->globbed;
11310+ while (*guser) {
11311+ g_tmp = (struct acl_object_label *)
11312+ acl_alloc(sizeof (struct acl_object_label));
11313+ if (g_tmp == NULL)
11314+ return -ENOMEM;
11315+
11316+ if (copy_from_user(g_tmp, *guser,
11317+ sizeof (struct acl_object_label)))
11318+ return -EFAULT;
11319+
11320+ len = strnlen_user(g_tmp->filename, PATH_MAX);
11321+
11322+ if (!len || len >= PATH_MAX)
11323+ return -EINVAL;
11324+
11325+ if ((tmp = (char *) acl_alloc(len)) == NULL)
11326+ return -ENOMEM;
11327+
11328+ if (copy_from_user(tmp, g_tmp->filename, len))
11329+ return -EFAULT;
11330+
11331+ g_tmp->filename = tmp;
11332+
11333+ *guser = g_tmp;
11334+ guser = &(g_tmp->next);
11335+ }
11336+
11337+ return 0;
11338+}
11339+
11340+static int
11341+copy_user_objs(struct acl_object_label *userp, struct acl_subject_label *subj,
11342+ struct acl_role_label *role)
11343+{
11344+ struct acl_object_label *o_tmp;
11345+ unsigned int len;
11346+ int ret;
11347+ char *tmp;
11348+
11349+ while (userp) {
11350+ if ((o_tmp = (struct acl_object_label *)
11351+ acl_alloc(sizeof (struct acl_object_label))) == NULL)
11352+ return -ENOMEM;
11353+
11354+ if (copy_from_user(o_tmp, userp,
11355+ sizeof (struct acl_object_label)))
11356+ return -EFAULT;
11357+
11358+ userp = o_tmp->prev;
11359+
11360+ len = strnlen_user(o_tmp->filename, PATH_MAX);
11361+
11362+ if (!len || len >= PATH_MAX)
11363+ return -EINVAL;
11364+
11365+ if ((tmp = (char *) acl_alloc(len)) == NULL)
11366+ return -ENOMEM;
11367+
11368+ if (copy_from_user(tmp, o_tmp->filename, len))
11369+ return -EFAULT;
11370+
11371+ o_tmp->filename = tmp;
11372+
11373+ insert_acl_obj_label(o_tmp, subj);
11374+ if (!insert_name_entry(o_tmp->filename, o_tmp->inode,
11375+ o_tmp->device))
11376+ return -ENOMEM;
11377+
11378+ ret = copy_user_glob(o_tmp);
11379+ if (ret)
11380+ return ret;
11381+
11382+ if (o_tmp->nested) {
11383+ o_tmp->nested = do_copy_user_subj(o_tmp->nested, role);
11384+ if (IS_ERR(o_tmp->nested))
11385+ return PTR_ERR(o_tmp->nested);
11386+
11387+ /* insert into nested subject list */
11388+ o_tmp->nested->next = role->hash->first;
11389+ role->hash->first = o_tmp->nested;
11390+ }
11391+ }
11392+
11393+ return 0;
11394+}
11395+
11396+static __u32
11397+count_user_subjs(struct acl_subject_label *userp)
11398+{
11399+ struct acl_subject_label s_tmp;
11400+ __u32 num = 0;
11401+
11402+ while (userp) {
11403+ if (copy_from_user(&s_tmp, userp,
11404+ sizeof (struct acl_subject_label)))
11405+ break;
11406+
11407+ userp = s_tmp.prev;
11408+ /* do not count nested subjects against this count, since
11409+ they are not included in the hash table, but are
11410+ attached to objects. We have already counted
11411+ the subjects in userspace for the allocation
11412+ stack
11413+ */
11414+ if (!(s_tmp.mode & GR_NESTED))
11415+ num++;
11416+ }
11417+
11418+ return num;
11419+}
11420+
11421+static int
11422+copy_user_allowedips(struct acl_role_label *rolep)
11423+{
11424+ struct role_allowed_ip *ruserip, *rtmp = NULL, *rlast;
11425+
11426+ ruserip = rolep->allowed_ips;
11427+
11428+ while (ruserip) {
11429+ rlast = rtmp;
11430+
11431+ if ((rtmp = (struct role_allowed_ip *)
11432+ acl_alloc(sizeof (struct role_allowed_ip))) == NULL)
11433+ return -ENOMEM;
11434+
11435+ if (copy_from_user(rtmp, ruserip,
11436+ sizeof (struct role_allowed_ip)))
11437+ return -EFAULT;
11438+
11439+ ruserip = rtmp->prev;
11440+
11441+ if (!rlast) {
11442+ rtmp->prev = NULL;
11443+ rolep->allowed_ips = rtmp;
11444+ } else {
11445+ rlast->next = rtmp;
11446+ rtmp->prev = rlast;
11447+ }
11448+
11449+ if (!ruserip)
11450+ rtmp->next = NULL;
11451+ }
11452+
11453+ return 0;
11454+}
11455+
11456+static int
11457+copy_user_transitions(struct acl_role_label *rolep)
11458+{
11459+ struct role_transition *rusertp, *rtmp = NULL, *rlast;
11460+
11461+ unsigned int len;
11462+ char *tmp;
11463+
11464+ rusertp = rolep->transitions;
11465+
11466+ while (rusertp) {
11467+ rlast = rtmp;
11468+
11469+ if ((rtmp = (struct role_transition *)
11470+ acl_alloc(sizeof (struct role_transition))) == NULL)
11471+ return -ENOMEM;
11472+
11473+ if (copy_from_user(rtmp, rusertp,
11474+ sizeof (struct role_transition)))
11475+ return -EFAULT;
11476+
11477+ rusertp = rtmp->prev;
11478+
11479+ len = strnlen_user(rtmp->rolename, GR_SPROLE_LEN);
11480+
11481+ if (!len || len >= GR_SPROLE_LEN)
11482+ return -EINVAL;
11483+
11484+ if ((tmp = (char *) acl_alloc(len)) == NULL)
11485+ return -ENOMEM;
11486+
11487+ if (copy_from_user(tmp, rtmp->rolename, len))
11488+ return -EFAULT;
11489+
11490+ rtmp->rolename = tmp;
11491+
11492+ if (!rlast) {
11493+ rtmp->prev = NULL;
11494+ rolep->transitions = rtmp;
11495+ } else {
11496+ rlast->next = rtmp;
11497+ rtmp->prev = rlast;
11498+ }
11499+
11500+ if (!rusertp)
11501+ rtmp->next = NULL;
11502+ }
11503+
11504+ return 0;
11505+}
11506+
11507+static struct acl_subject_label *
11508+do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role)
11509+{
11510+ struct acl_subject_label *s_tmp = NULL, *s_tmp2;
11511+ unsigned int len;
11512+ char *tmp;
11513+ __u32 num_objs;
11514+ struct acl_ip_label **i_tmp, *i_utmp2;
11515+ struct gr_hash_struct ghash;
11516+ struct subject_map *subjmap;
11517+ unsigned int i_num;
11518+ int err;
11519+
11520+ s_tmp = lookup_subject_map(userp);
11521+
11522+ /* we've already copied this subject into the kernel, just return
11523+ the reference to it, and don't copy it over again
11524+ */
11525+ if (s_tmp)
11526+ return(s_tmp);
11527+
11528+ if ((s_tmp = (struct acl_subject_label *)
11529+ acl_alloc(sizeof (struct acl_subject_label))) == NULL)
11530+ return ERR_PTR(-ENOMEM);
11531+
11532+ subjmap = (struct subject_map *)kmalloc(sizeof (struct subject_map), GFP_KERNEL);
11533+ if (subjmap == NULL)
11534+ return ERR_PTR(-ENOMEM);
11535+
11536+ subjmap->user = userp;
11537+ subjmap->kernel = s_tmp;
11538+ insert_subj_map_entry(subjmap);
11539+
11540+ if (copy_from_user(s_tmp, userp,
11541+ sizeof (struct acl_subject_label)))
11542+ return ERR_PTR(-EFAULT);
11543+
11544+ len = strnlen_user(s_tmp->filename, PATH_MAX);
11545+
11546+ if (!len || len >= PATH_MAX)
11547+ return ERR_PTR(-EINVAL);
11548+
11549+ if ((tmp = (char *) acl_alloc(len)) == NULL)
11550+ return ERR_PTR(-ENOMEM);
11551+
11552+ if (copy_from_user(tmp, s_tmp->filename, len))
11553+ return ERR_PTR(-EFAULT);
11554+
11555+ s_tmp->filename = tmp;
11556+
11557+ if (!strcmp(s_tmp->filename, "/"))
11558+ role->root_label = s_tmp;
11559+
11560+ if (copy_from_user(&ghash, s_tmp->hash, sizeof(struct gr_hash_struct)))
11561+ return ERR_PTR(-EFAULT);
11562+
11563+ /* copy user and group transition tables */
11564+
11565+ if (s_tmp->user_trans_num) {
11566+ uid_t *uidlist;
11567+
11568+ uidlist = (uid_t *)acl_alloc(s_tmp->user_trans_num * sizeof(uid_t));
11569+ if (uidlist == NULL)
11570+ return ERR_PTR(-ENOMEM);
11571+ if (copy_from_user(uidlist, s_tmp->user_transitions, s_tmp->user_trans_num * sizeof(uid_t)))
11572+ return ERR_PTR(-EFAULT);
11573+
11574+ s_tmp->user_transitions = uidlist;
11575+ }
11576+
11577+ if (s_tmp->group_trans_num) {
11578+ gid_t *gidlist;
11579+
11580+ gidlist = (gid_t *)acl_alloc(s_tmp->group_trans_num * sizeof(gid_t));
11581+ if (gidlist == NULL)
11582+ return ERR_PTR(-ENOMEM);
11583+ if (copy_from_user(gidlist, s_tmp->group_transitions, s_tmp->group_trans_num * sizeof(gid_t)))
11584+ return ERR_PTR(-EFAULT);
11585+
11586+ s_tmp->group_transitions = gidlist;
11587+ }
11588+
11589+ /* set up object hash table */
11590+ num_objs = count_user_objs(ghash.first);
11591+
11592+ s_tmp->obj_hash_size = num_objs;
11593+ s_tmp->obj_hash =
11594+ (struct acl_object_label **)
11595+ create_table(&(s_tmp->obj_hash_size), sizeof(void *));
11596+
11597+ if (!s_tmp->obj_hash)
11598+ return ERR_PTR(-ENOMEM);
11599+
11600+ memset(s_tmp->obj_hash, 0,
11601+ s_tmp->obj_hash_size *
11602+ sizeof (struct acl_object_label *));
11603+
11604+ /* add in objects */
11605+ err = copy_user_objs(ghash.first, s_tmp, role);
11606+
11607+ if (err)
11608+ return ERR_PTR(err);
11609+
11610+ /* set pointer for parent subject */
11611+ if (s_tmp->parent_subject) {
11612+ s_tmp2 = do_copy_user_subj(s_tmp->parent_subject, role);
11613+
11614+ if (IS_ERR(s_tmp2))
11615+ return s_tmp2;
11616+
11617+ s_tmp->parent_subject = s_tmp2;
11618+ }
11619+
11620+ /* add in ip acls */
11621+
11622+ if (!s_tmp->ip_num) {
11623+ s_tmp->ips = NULL;
11624+ goto insert;
11625+ }
11626+
11627+ i_tmp =
11628+ (struct acl_ip_label **) acl_alloc(s_tmp->ip_num *
11629+ sizeof (struct
11630+ acl_ip_label *));
11631+
11632+ if (!i_tmp)
11633+ return ERR_PTR(-ENOMEM);
11634+
11635+ for (i_num = 0; i_num < s_tmp->ip_num; i_num++) {
11636+ *(i_tmp + i_num) =
11637+ (struct acl_ip_label *)
11638+ acl_alloc(sizeof (struct acl_ip_label));
11639+ if (!*(i_tmp + i_num))
11640+ return ERR_PTR(-ENOMEM);
11641+
11642+ if (copy_from_user
11643+ (&i_utmp2, s_tmp->ips + i_num,
11644+ sizeof (struct acl_ip_label *)))
11645+ return ERR_PTR(-EFAULT);
11646+
11647+ if (copy_from_user
11648+ (*(i_tmp + i_num), i_utmp2,
11649+ sizeof (struct acl_ip_label)))
11650+ return ERR_PTR(-EFAULT);
11651+
11652+ if ((*(i_tmp + i_num))->iface == NULL)
11653+ continue;
11654+
11655+ len = strnlen_user((*(i_tmp + i_num))->iface, IFNAMSIZ);
11656+ if (!len || len >= IFNAMSIZ)
11657+ return ERR_PTR(-EINVAL);
11658+ tmp = acl_alloc(len);
11659+ if (tmp == NULL)
11660+ return ERR_PTR(-ENOMEM);
11661+ if (copy_from_user(tmp, (*(i_tmp + i_num))->iface, len))
11662+ return ERR_PTR(-EFAULT);
11663+ (*(i_tmp + i_num))->iface = tmp;
11664+ }
11665+
11666+ s_tmp->ips = i_tmp;
11667+
11668+insert:
11669+ if (!insert_name_entry(s_tmp->filename, s_tmp->inode,
11670+ s_tmp->device))
11671+ return ERR_PTR(-ENOMEM);
11672+
11673+ return s_tmp;
11674+}
11675+
11676+static int
11677+copy_user_subjs(struct acl_subject_label *userp, struct acl_role_label *role)
11678+{
11679+ struct acl_subject_label s_pre;
11680+ struct acl_subject_label * ret;
11681+ int err;
11682+
11683+ while (userp) {
11684+ if (copy_from_user(&s_pre, userp,
11685+ sizeof (struct acl_subject_label)))
11686+ return -EFAULT;
11687+
11688+ /* do not add nested subjects here, add
11689+ while parsing objects
11690+ */
11691+
11692+ if (s_pre.mode & GR_NESTED) {
11693+ userp = s_pre.prev;
11694+ continue;
11695+ }
11696+
11697+ ret = do_copy_user_subj(userp, role);
11698+
11699+ err = PTR_ERR(ret);
11700+ if (IS_ERR(ret))
11701+ return err;
11702+
11703+ insert_acl_subj_label(ret, role);
11704+
11705+ userp = s_pre.prev;
11706+ }
11707+
11708+ return 0;
11709+}
11710+
11711+static int
11712+copy_user_acl(struct gr_arg *arg)
11713+{
11714+ struct acl_role_label *r_tmp = NULL, **r_utmp, *r_utmp2;
11715+ struct sprole_pw *sptmp;
11716+ struct gr_hash_struct *ghash;
11717+ uid_t *domainlist;
11718+ unsigned int r_num;
11719+ unsigned int len;
11720+ char *tmp;
11721+ int err = 0;
11722+ __u16 i;
11723+ __u32 num_subjs;
11724+
11725+ /* we need a default and kernel role */
11726+ if (arg->role_db.num_roles < 2)
11727+ return -EINVAL;
11728+
11729+ /* copy special role authentication info from userspace */
11730+
11731+ num_sprole_pws = arg->num_sprole_pws;
11732+ acl_special_roles = (struct sprole_pw **) acl_alloc(num_sprole_pws * sizeof(struct sprole_pw *));
11733+
11734+ if (!acl_special_roles) {
11735+ err = -ENOMEM;
11736+ goto cleanup;
11737+ }
11738+
11739+ for (i = 0; i < num_sprole_pws; i++) {
11740+ sptmp = (struct sprole_pw *) acl_alloc(sizeof(struct sprole_pw));
11741+ if (!sptmp) {
11742+ err = -ENOMEM;
11743+ goto cleanup;
11744+ }
11745+ if (copy_from_user(sptmp, arg->sprole_pws + i,
11746+ sizeof (struct sprole_pw))) {
11747+ err = -EFAULT;
11748+ goto cleanup;
11749+ }
11750+
11751+ len =
11752+ strnlen_user(sptmp->rolename, GR_SPROLE_LEN);
11753+
11754+ if (!len || len >= GR_SPROLE_LEN) {
11755+ err = -EINVAL;
11756+ goto cleanup;
11757+ }
11758+
11759+ if ((tmp = (char *) acl_alloc(len)) == NULL) {
11760+ err = -ENOMEM;
11761+ goto cleanup;
11762+ }
11763+
11764+ if (copy_from_user(tmp, sptmp->rolename, len)) {
11765+ err = -EFAULT;
11766+ goto cleanup;
11767+ }
11768+
11769+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
11770+ printk(KERN_ALERT "Copying special role %s\n", tmp);
11771+#endif
11772+ sptmp->rolename = tmp;
11773+ acl_special_roles[i] = sptmp;
11774+ }
11775+
11776+ r_utmp = (struct acl_role_label **) arg->role_db.r_table;
11777+
11778+ for (r_num = 0; r_num < arg->role_db.num_roles; r_num++) {
11779+ r_tmp = acl_alloc(sizeof (struct acl_role_label));
11780+
11781+ if (!r_tmp) {
11782+ err = -ENOMEM;
11783+ goto cleanup;
11784+ }
11785+
11786+ if (copy_from_user(&r_utmp2, r_utmp + r_num,
11787+ sizeof (struct acl_role_label *))) {
11788+ err = -EFAULT;
11789+ goto cleanup;
11790+ }
11791+
11792+ if (copy_from_user(r_tmp, r_utmp2,
11793+ sizeof (struct acl_role_label))) {
11794+ err = -EFAULT;
11795+ goto cleanup;
11796+ }
11797+
11798+ len = strnlen_user(r_tmp->rolename, GR_SPROLE_LEN);
11799+
11800+ if (!len || len >= PATH_MAX) {
11801+ err = -EINVAL;
11802+ goto cleanup;
11803+ }
11804+
11805+ if ((tmp = (char *) acl_alloc(len)) == NULL) {
11806+ err = -ENOMEM;
11807+ goto cleanup;
11808+ }
11809+ if (copy_from_user(tmp, r_tmp->rolename, len)) {
11810+ err = -EFAULT;
11811+ goto cleanup;
11812+ }
11813+ r_tmp->rolename = tmp;
11814+
11815+ if (!strcmp(r_tmp->rolename, "default")
11816+ && (r_tmp->roletype & GR_ROLE_DEFAULT)) {
11817+ default_role = r_tmp;
11818+ } else if (!strcmp(r_tmp->rolename, ":::kernel:::")) {
11819+ kernel_role = r_tmp;
11820+ }
11821+
11822+ if ((ghash = (struct gr_hash_struct *) acl_alloc(sizeof(struct gr_hash_struct))) == NULL) {
11823+ err = -ENOMEM;
11824+ goto cleanup;
11825+ }
11826+ if (copy_from_user(ghash, r_tmp->hash, sizeof(struct gr_hash_struct))) {
11827+ err = -EFAULT;
11828+ goto cleanup;
11829+ }
11830+
11831+ r_tmp->hash = ghash;
11832+
11833+ num_subjs = count_user_subjs(r_tmp->hash->first);
11834+
11835+ r_tmp->subj_hash_size = num_subjs;
11836+ r_tmp->subj_hash =
11837+ (struct acl_subject_label **)
11838+ create_table(&(r_tmp->subj_hash_size), sizeof(void *));
11839+
11840+ if (!r_tmp->subj_hash) {
11841+ err = -ENOMEM;
11842+ goto cleanup;
11843+ }
11844+
11845+ err = copy_user_allowedips(r_tmp);
11846+ if (err)
11847+ goto cleanup;
11848+
11849+ /* copy domain info */
11850+ if (r_tmp->domain_children != NULL) {
11851+ domainlist = acl_alloc(r_tmp->domain_child_num * sizeof(uid_t));
11852+ if (domainlist == NULL) {
11853+ err = -ENOMEM;
11854+ goto cleanup;
11855+ }
11856+ if (copy_from_user(domainlist, r_tmp->domain_children, r_tmp->domain_child_num * sizeof(uid_t))) {
11857+ err = -EFAULT;
11858+ goto cleanup;
11859+ }
11860+ r_tmp->domain_children = domainlist;
11861+ }
11862+
11863+ err = copy_user_transitions(r_tmp);
11864+ if (err)
11865+ goto cleanup;
11866+
11867+ memset(r_tmp->subj_hash, 0,
11868+ r_tmp->subj_hash_size *
11869+ sizeof (struct acl_subject_label *));
11870+
11871+ err = copy_user_subjs(r_tmp->hash->first, r_tmp);
11872+
11873+ if (err)
11874+ goto cleanup;
11875+
11876+ /* set nested subject list to null */
11877+ r_tmp->hash->first = NULL;
11878+
11879+ insert_acl_role_label(r_tmp);
11880+ }
11881+
11882+ goto return_err;
11883+ cleanup:
11884+ free_variables();
11885+ return_err:
11886+ return err;
11887+
11888+}
11889+
11890+static int
11891+gracl_init(struct gr_arg *args)
11892+{
11893+ int error = 0;
11894+
11895+ memcpy(gr_system_salt, args->salt, GR_SALT_LEN);
11896+ memcpy(gr_system_sum, args->sum, GR_SHA_LEN);
11897+
11898+ if (init_variables(args)) {
11899+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_INITF_ACL_MSG, GR_VERSION);
11900+ error = -ENOMEM;
11901+ free_variables();
11902+ goto out;
11903+ }
11904+
11905+ error = copy_user_acl(args);
11906+ free_init_variables();
11907+ if (error) {
11908+ free_variables();
11909+ goto out;
11910+ }
11911+
11912+ if ((error = gr_set_acls(0))) {
11913+ free_variables();
11914+ goto out;
11915+ }
11916+
11917+ gr_status |= GR_READY;
11918+ out:
11919+ return error;
11920+}
11921+
11922+/* derived from glibc fnmatch() 0: match, 1: no match*/
11923+
11924+static int
11925+glob_match(const char *p, const char *n)
11926+{
11927+ char c;
11928+
11929+ while ((c = *p++) != '\0') {
11930+ switch (c) {
11931+ case '?':
11932+ if (*n == '\0')
11933+ return 1;
11934+ else if (*n == '/')
11935+ return 1;
11936+ break;
11937+ case '\\':
11938+ if (*n != c)
11939+ return 1;
11940+ break;
11941+ case '*':
11942+ for (c = *p++; c == '?' || c == '*'; c = *p++) {
11943+ if (*n == '/')
11944+ return 1;
11945+ else if (c == '?') {
11946+ if (*n == '\0')
11947+ return 1;
11948+ else
11949+ ++n;
11950+ }
11951+ }
11952+ if (c == '\0') {
11953+ return 0;
11954+ } else {
11955+ const char *endp;
11956+
11957+ if ((endp = strchr(n, '/')) == NULL)
11958+ endp = n + strlen(n);
11959+
11960+ if (c == '[') {
11961+ for (--p; n < endp; ++n)
11962+ if (!glob_match(p, n))
11963+ return 0;
11964+ } else if (c == '/') {
11965+ while (*n != '\0' && *n != '/')
11966+ ++n;
11967+ if (*n == '/' && !glob_match(p, n + 1))
11968+ return 0;
11969+ } else {
11970+ for (--p; n < endp; ++n)
11971+ if (*n == c && !glob_match(p, n))
11972+ return 0;
11973+ }
11974+
11975+ return 1;
11976+ }
11977+ case '[':
11978+ {
11979+ int not;
11980+ char cold;
11981+
11982+ if (*n == '\0' || *n == '/')
11983+ return 1;
11984+
11985+ not = (*p == '!' || *p == '^');
11986+ if (not)
11987+ ++p;
11988+
11989+ c = *p++;
11990+ for (;;) {
11991+ unsigned char fn = (unsigned char)*n;
11992+
11993+ if (c == '\0')
11994+ return 1;
11995+ else {
11996+ if (c == fn)
11997+ goto matched;
11998+ cold = c;
11999+ c = *p++;
12000+
12001+ if (c == '-' && *p != ']') {
12002+ unsigned char cend = *p++;
12003+
12004+ if (cend == '\0')
12005+ return 1;
12006+
12007+ if (cold <= fn && fn <= cend)
12008+ goto matched;
12009+
12010+ c = *p++;
12011+ }
12012+ }
12013+
12014+ if (c == ']')
12015+ break;
12016+ }
12017+ if (!not)
12018+ return 1;
12019+ break;
12020+ matched:
12021+ while (c != ']') {
12022+ if (c == '\0')
12023+ return 1;
12024+
12025+ c = *p++;
12026+ }
12027+ if (not)
12028+ return 1;
12029+ }
12030+ break;
12031+ default:
12032+ if (c != *n)
12033+ return 1;
12034+ }
12035+
12036+ ++n;
12037+ }
12038+
12039+ if (*n == '\0')
12040+ return 0;
12041+
12042+ if (*n == '/')
12043+ return 0;
12044+
12045+ return 1;
12046+}
12047+
12048+static struct acl_object_label *
12049+chk_glob_label(struct acl_object_label *globbed,
12050+ struct dentry *dentry, struct vfsmount *mnt, char **path)
12051+{
12052+ struct acl_object_label *tmp;
12053+
12054+ if (*path == NULL)
12055+ *path = gr_to_filename_nolock(dentry, mnt);
12056+
12057+ tmp = globbed;
12058+
12059+ while (tmp) {
12060+ if (!glob_match(tmp->filename, *path))
12061+ return tmp;
12062+ tmp = tmp->next;
12063+ }
12064+
12065+ return NULL;
12066+}
12067+
12068+static struct acl_object_label *
12069+__full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
12070+ const ino_t curr_ino, const dev_t curr_dev,
12071+ const struct acl_subject_label *subj, char **path)
12072+{
12073+ struct acl_subject_label *tmpsubj;
12074+ struct acl_object_label *retval;
12075+ struct acl_object_label *retval2;
12076+
12077+ tmpsubj = (struct acl_subject_label *) subj;
12078+ read_lock(&gr_inode_lock);
12079+ do {
12080+ retval = lookup_acl_obj_label(curr_ino, curr_dev, tmpsubj);
12081+ if (retval) {
12082+ if (retval->globbed) {
12083+ retval2 = chk_glob_label(retval->globbed, (struct dentry *)orig_dentry,
12084+ (struct vfsmount *)orig_mnt, path);
12085+ if (retval2)
12086+ retval = retval2;
12087+ }
12088+ break;
12089+ }
12090+ } while ((tmpsubj = tmpsubj->parent_subject));
12091+ read_unlock(&gr_inode_lock);
12092+
12093+ return retval;
12094+}
12095+
12096+static __inline__ struct acl_object_label *
12097+full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
12098+ const struct dentry *curr_dentry,
12099+ const struct acl_subject_label *subj, char **path)
12100+{
12101+ return __full_lookup(orig_dentry, orig_mnt,
12102+ curr_dentry->d_inode->i_ino,
12103+ curr_dentry->d_inode->i_sb->s_dev, subj, path);
12104+}
12105+
12106+static struct acl_object_label *
12107+__chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
12108+ const struct acl_subject_label *subj, char *path)
12109+{
12110+ struct dentry *dentry = (struct dentry *) l_dentry;
12111+ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
12112+ struct acl_object_label *retval;
12113+
12114+ spin_lock(&dcache_lock);
12115+
12116+ if (unlikely(mnt == shm_mnt || mnt == pipe_mnt || mnt == sock_mnt)) {
12117+ retval = fakefs_obj;
12118+ goto out;
12119+ }
12120+
12121+ for (;;) {
12122+ if (dentry == real_root && mnt == real_root_mnt)
12123+ break;
12124+
12125+ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) {
12126+ if (mnt->mnt_parent == mnt)
12127+ break;
12128+
12129+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
12130+ if (retval != NULL)
12131+ goto out;
12132+
12133+ dentry = mnt->mnt_mountpoint;
12134+ mnt = mnt->mnt_parent;
12135+ continue;
12136+ }
12137+
12138+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
12139+ if (retval != NULL)
12140+ goto out;
12141+
12142+ dentry = dentry->d_parent;
12143+ }
12144+
12145+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
12146+
12147+ if (retval == NULL)
12148+ retval = full_lookup(l_dentry, l_mnt, real_root, subj, &path);
12149+out:
12150+ spin_unlock(&dcache_lock);
12151+ return retval;
12152+}
12153+
12154+static __inline__ struct acl_object_label *
12155+chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
12156+ const struct acl_subject_label *subj)
12157+{
12158+ char *path = NULL;
12159+ return __chk_obj_label(l_dentry, l_mnt, subj, path);
12160+}
12161+
12162+static __inline__ struct acl_object_label *
12163+chk_obj_create_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
12164+ const struct acl_subject_label *subj, char *path)
12165+{
12166+ return __chk_obj_label(l_dentry, l_mnt, subj, path);
12167+}
12168+
12169+static struct acl_subject_label *
12170+chk_subj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
12171+ const struct acl_role_label *role)
12172+{
12173+ struct dentry *dentry = (struct dentry *) l_dentry;
12174+ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
12175+ struct acl_subject_label *retval;
12176+
12177+ spin_lock(&dcache_lock);
12178+
12179+ for (;;) {
12180+ if (dentry == real_root && mnt == real_root_mnt)
12181+ break;
12182+ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) {
12183+ if (mnt->mnt_parent == mnt)
12184+ break;
12185+
12186+ read_lock(&gr_inode_lock);
12187+ retval =
12188+ lookup_acl_subj_label(dentry->d_inode->i_ino,
12189+ dentry->d_inode->i_sb->s_dev, role);
12190+ read_unlock(&gr_inode_lock);
12191+ if (retval != NULL)
12192+ goto out;
12193+
12194+ dentry = mnt->mnt_mountpoint;
12195+ mnt = mnt->mnt_parent;
12196+ continue;
12197+ }
12198+
12199+ read_lock(&gr_inode_lock);
12200+ retval = lookup_acl_subj_label(dentry->d_inode->i_ino,
12201+ dentry->d_inode->i_sb->s_dev, role);
12202+ read_unlock(&gr_inode_lock);
12203+ if (retval != NULL)
12204+ goto out;
12205+
12206+ dentry = dentry->d_parent;
12207+ }
12208+
12209+ read_lock(&gr_inode_lock);
12210+ retval = lookup_acl_subj_label(dentry->d_inode->i_ino,
12211+ dentry->d_inode->i_sb->s_dev, role);
12212+ read_unlock(&gr_inode_lock);
12213+
12214+ if (unlikely(retval == NULL)) {
12215+ read_lock(&gr_inode_lock);
12216+ retval = lookup_acl_subj_label(real_root->d_inode->i_ino,
12217+ real_root->d_inode->i_sb->s_dev, role);
12218+ read_unlock(&gr_inode_lock);
12219+ }
12220+out:
12221+ spin_unlock(&dcache_lock);
12222+
12223+ return retval;
12224+}
12225+
12226+static void
12227+gr_log_learn(const struct task_struct *task, const struct dentry *dentry, const struct vfsmount *mnt, const __u32 mode)
12228+{
12229+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, task->role->roletype,
12230+ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_dentry,
12231+ task->exec_file->f_vfsmnt) : task->acl->filename, task->acl->filename,
12232+ 1, 1, gr_to_filename(dentry, mnt), (unsigned long) mode, NIPQUAD(task->signal->curr_ip));
12233+
12234+ return;
12235+}
12236+
12237+static void
12238+gr_log_learn_id_change(const struct task_struct *task, const char type, const unsigned int real,
12239+ const unsigned int effective, const unsigned int fs)
12240+{
12241+ security_learn(GR_ID_LEARN_MSG, task->role->rolename, task->role->roletype,
12242+ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_dentry,
12243+ task->exec_file->f_vfsmnt) : task->acl->filename, task->acl->filename,
12244+ type, real, effective, fs, NIPQUAD(task->signal->curr_ip));
12245+
12246+ return;
12247+}
12248+
12249+__u32
12250+gr_check_link(const struct dentry * new_dentry,
12251+ const struct dentry * parent_dentry,
12252+ const struct vfsmount * parent_mnt,
12253+ const struct dentry * old_dentry, const struct vfsmount * old_mnt)
12254+{
12255+ struct acl_object_label *obj;
12256+ __u32 oldmode, newmode;
12257+ __u32 needmode;
12258+
12259+ if (unlikely(!(gr_status & GR_READY)))
12260+ return (GR_CREATE | GR_LINK);
12261+
12262+ obj = chk_obj_label(old_dentry, old_mnt, current->acl);
12263+ oldmode = obj->mode;
12264+
12265+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
12266+ oldmode |= (GR_CREATE | GR_LINK);
12267+
12268+ needmode = GR_CREATE | GR_AUDIT_CREATE | GR_SUPPRESS;
12269+ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID))
12270+ needmode |= GR_SETID | GR_AUDIT_SETID;
12271+
12272+ newmode =
12273+ gr_check_create(new_dentry, parent_dentry, parent_mnt,
12274+ oldmode | needmode);
12275+
12276+ needmode = newmode & (GR_FIND | GR_APPEND | GR_WRITE | GR_EXEC |
12277+ GR_SETID | GR_READ | GR_FIND | GR_DELETE |
12278+ GR_INHERIT | GR_AUDIT_INHERIT);
12279+
12280+ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID) && !(newmode & GR_SETID))
12281+ goto bad;
12282+
12283+ if ((oldmode & needmode) != needmode)
12284+ goto bad;
12285+
12286+ needmode = oldmode & (GR_NOPTRACE | GR_PTRACERD | GR_INHERIT | GR_AUDITS);
12287+ if ((newmode & needmode) != needmode)
12288+ goto bad;
12289+
12290+ if ((newmode & (GR_CREATE | GR_LINK)) == (GR_CREATE | GR_LINK))
12291+ return newmode;
12292+bad:
12293+ needmode = oldmode;
12294+ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID))
12295+ needmode |= GR_SETID;
12296+
12297+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) {
12298+ gr_log_learn(current, old_dentry, old_mnt, needmode);
12299+ return (GR_CREATE | GR_LINK);
12300+ } else if (newmode & GR_SUPPRESS)
12301+ return GR_SUPPRESS;
12302+ else
12303+ return 0;
12304+}
12305+
12306+__u32
12307+gr_search_file(const struct dentry * dentry, const __u32 mode,
12308+ const struct vfsmount * mnt)
12309+{
12310+ __u32 retval = mode;
12311+ struct acl_subject_label *curracl;
12312+ struct acl_object_label *currobj;
12313+
12314+ if (unlikely(!(gr_status & GR_READY)))
12315+ return (mode & ~GR_AUDITS);
12316+
12317+ curracl = current->acl;
12318+
12319+ currobj = chk_obj_label(dentry, mnt, curracl);
12320+ retval = currobj->mode & mode;
12321+
12322+ if (unlikely
12323+ ((curracl->mode & (GR_LEARN | GR_INHERITLEARN)) && !(mode & GR_NOPTRACE)
12324+ && (retval != (mode & ~(GR_AUDITS | GR_SUPPRESS))))) {
12325+ __u32 new_mode = mode;
12326+
12327+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
12328+
12329+ retval = new_mode;
12330+
12331+ if (new_mode & GR_EXEC && curracl->mode & GR_INHERITLEARN)
12332+ new_mode |= GR_INHERIT;
12333+
12334+ if (!(mode & GR_NOLEARN))
12335+ gr_log_learn(current, dentry, mnt, new_mode);
12336+ }
12337+
12338+ return retval;
12339+}
12340+
12341+__u32
12342+gr_check_create(const struct dentry * new_dentry, const struct dentry * parent,
12343+ const struct vfsmount * mnt, const __u32 mode)
12344+{
12345+ struct name_entry *match;
12346+ struct acl_object_label *matchpo;
12347+ struct acl_subject_label *curracl;
12348+ char *path;
12349+ __u32 retval;
12350+
12351+ if (unlikely(!(gr_status & GR_READY)))
12352+ return (mode & ~GR_AUDITS);
12353+
12354+ preempt_disable();
12355+ path = gr_to_filename_rbac(new_dentry, mnt);
12356+ match = lookup_name_entry(path);
12357+
12358+ if (!match)
12359+ goto check_parent;
12360+
12361+ curracl = current->acl;
12362+
12363+ read_lock(&gr_inode_lock);
12364+ matchpo = lookup_acl_obj_label_create(match->inode, match->device, curracl);
12365+ read_unlock(&gr_inode_lock);
12366+
12367+ if (matchpo) {
12368+ if ((matchpo->mode & mode) !=
12369+ (mode & ~(GR_AUDITS | GR_SUPPRESS))
12370+ && curracl->mode & (GR_LEARN | GR_INHERITLEARN)) {
12371+ __u32 new_mode = mode;
12372+
12373+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
12374+
12375+ gr_log_learn(current, new_dentry, mnt, new_mode);
12376+
12377+ preempt_enable();
12378+ return new_mode;
12379+ }
12380+ preempt_enable();
12381+ return (matchpo->mode & mode);
12382+ }
12383+
12384+ check_parent:
12385+ curracl = current->acl;
12386+
12387+ matchpo = chk_obj_create_label(parent, mnt, curracl, path);
12388+ retval = matchpo->mode & mode;
12389+
12390+ if ((retval != (mode & ~(GR_AUDITS | GR_SUPPRESS)))
12391+ && (curracl->mode & (GR_LEARN | GR_INHERITLEARN))) {
12392+ __u32 new_mode = mode;
12393+
12394+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
12395+
12396+ gr_log_learn(current, new_dentry, mnt, new_mode);
12397+ preempt_enable();
12398+ return new_mode;
12399+ }
12400+
12401+ preempt_enable();
12402+ return retval;
12403+}
12404+
12405+int
12406+gr_check_hidden_task(const struct task_struct *task)
12407+{
12408+ if (unlikely(!(gr_status & GR_READY)))
12409+ return 0;
12410+
12411+ if (!(task->acl->mode & GR_PROCFIND) && !(current->acl->mode & GR_VIEW))
12412+ return 1;
12413+
12414+ return 0;
12415+}
12416+
12417+int
12418+gr_check_protected_task(const struct task_struct *task)
12419+{
12420+ if (unlikely(!(gr_status & GR_READY) || !task))
12421+ return 0;
12422+
12423+ if ((task->acl->mode & GR_PROTECTED) && !(current->acl->mode & GR_KILL) &&
12424+ task->acl != current->acl)
12425+ return 1;
12426+
12427+ return 0;
12428+}
12429+
12430+void
12431+gr_copy_label(struct task_struct *tsk)
12432+{
12433+ tsk->signal->used_accept = 0;
12434+ tsk->acl_sp_role = 0;
12435+ tsk->acl_role_id = current->acl_role_id;
12436+ tsk->acl = current->acl;
12437+ tsk->role = current->role;
12438+ tsk->signal->curr_ip = current->signal->curr_ip;
12439+ if (current->exec_file)
12440+ get_file(current->exec_file);
12441+ tsk->exec_file = current->exec_file;
12442+ tsk->is_writable = current->is_writable;
12443+ if (unlikely(current->signal->used_accept))
12444+ current->signal->curr_ip = 0;
12445+
12446+ return;
12447+}
12448+
12449+static void
12450+gr_set_proc_res(struct task_struct *task)
12451+{
12452+ struct acl_subject_label *proc;
12453+ unsigned short i;
12454+
12455+ proc = task->acl;
12456+
12457+ if (proc->mode & (GR_LEARN | GR_INHERITLEARN))
12458+ return;
12459+
12460+ for (i = 0; i < (GR_NLIMITS - 1); i++) {
12461+ if (!(proc->resmask & (1 << i)))
12462+ continue;
12463+
12464+ task->signal->rlim[i].rlim_cur = proc->res[i].rlim_cur;
12465+ task->signal->rlim[i].rlim_max = proc->res[i].rlim_max;
12466+ }
12467+
12468+ return;
12469+}
12470+
12471+int
12472+gr_check_user_change(int real, int effective, int fs)
12473+{
12474+ unsigned int i;
12475+ __u16 num;
12476+ uid_t *uidlist;
12477+ int curuid;
12478+ int realok = 0;
12479+ int effectiveok = 0;
12480+ int fsok = 0;
12481+
12482+ if (unlikely(!(gr_status & GR_READY)))
12483+ return 0;
12484+
12485+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
12486+ gr_log_learn_id_change(current, 'u', real, effective, fs);
12487+
12488+ num = current->acl->user_trans_num;
12489+ uidlist = current->acl->user_transitions;
12490+
12491+ if (uidlist == NULL)
12492+ return 0;
12493+
12494+ if (real == -1)
12495+ realok = 1;
12496+ if (effective == -1)
12497+ effectiveok = 1;
12498+ if (fs == -1)
12499+ fsok = 1;
12500+
12501+ if (current->acl->user_trans_type & GR_ID_ALLOW) {
12502+ for (i = 0; i < num; i++) {
12503+ curuid = (int)uidlist[i];
12504+ if (real == curuid)
12505+ realok = 1;
12506+ if (effective == curuid)
12507+ effectiveok = 1;
12508+ if (fs == curuid)
12509+ fsok = 1;
12510+ }
12511+ } else if (current->acl->user_trans_type & GR_ID_DENY) {
12512+ for (i = 0; i < num; i++) {
12513+ curuid = (int)uidlist[i];
12514+ if (real == curuid)
12515+ break;
12516+ if (effective == curuid)
12517+ break;
12518+ if (fs == curuid)
12519+ break;
12520+ }
12521+ /* not in deny list */
12522+ if (i == num) {
12523+ realok = 1;
12524+ effectiveok = 1;
12525+ fsok = 1;
12526+ }
12527+ }
12528+
12529+ if (realok && effectiveok && fsok)
12530+ return 0;
12531+ else {
12532+ gr_log_int(GR_DONT_AUDIT, GR_USRCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real);
12533+ return 1;
12534+ }
12535+}
12536+
12537+int
12538+gr_check_group_change(int real, int effective, int fs)
12539+{
12540+ unsigned int i;
12541+ __u16 num;
12542+ gid_t *gidlist;
12543+ int curgid;
12544+ int realok = 0;
12545+ int effectiveok = 0;
12546+ int fsok = 0;
12547+
12548+ if (unlikely(!(gr_status & GR_READY)))
12549+ return 0;
12550+
12551+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
12552+ gr_log_learn_id_change(current, 'g', real, effective, fs);
12553+
12554+ num = current->acl->group_trans_num;
12555+ gidlist = current->acl->group_transitions;
12556+
12557+ if (gidlist == NULL)
12558+ return 0;
12559+
12560+ if (real == -1)
12561+ realok = 1;
12562+ if (effective == -1)
12563+ effectiveok = 1;
12564+ if (fs == -1)
12565+ fsok = 1;
12566+
12567+ if (current->acl->group_trans_type & GR_ID_ALLOW) {
12568+ for (i = 0; i < num; i++) {
12569+ curgid = (int)gidlist[i];
12570+ if (real == curgid)
12571+ realok = 1;
12572+ if (effective == curgid)
12573+ effectiveok = 1;
12574+ if (fs == curgid)
12575+ fsok = 1;
12576+ }
12577+ } else if (current->acl->group_trans_type & GR_ID_DENY) {
12578+ for (i = 0; i < num; i++) {
12579+ curgid = (int)gidlist[i];
12580+ if (real == curgid)
12581+ break;
12582+ if (effective == curgid)
12583+ break;
12584+ if (fs == curgid)
12585+ break;
12586+ }
12587+ /* not in deny list */
12588+ if (i == num) {
12589+ realok = 1;
12590+ effectiveok = 1;
12591+ fsok = 1;
12592+ }
12593+ }
12594+
12595+ if (realok && effectiveok && fsok)
12596+ return 0;
12597+ else {
12598+ gr_log_int(GR_DONT_AUDIT, GR_GRPCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real);
12599+ return 1;
12600+ }
12601+}
12602+
12603+void
12604+gr_set_role_label(struct task_struct *task, const uid_t uid, const uid_t gid)
12605+{
12606+ struct acl_role_label *role = task->role;
12607+ struct acl_subject_label *subj = NULL;
12608+ struct acl_object_label *obj;
12609+ struct file *filp;
12610+
12611+ if (unlikely(!(gr_status & GR_READY)))
12612+ return;
12613+
12614+ filp = task->exec_file;
12615+
12616+ /* kernel process, we'll give them the kernel role */
12617+ if (unlikely(!filp)) {
12618+ task->role = kernel_role;
12619+ task->acl = kernel_role->root_label;
12620+ return;
12621+ } else if (!task->role || !(task->role->roletype & GR_ROLE_SPECIAL))
12622+ role = lookup_acl_role_label(task, uid, gid);
12623+
12624+ /* perform subject lookup in possibly new role
12625+ we can use this result below in the case where role == task->role
12626+ */
12627+ subj = chk_subj_label(filp->f_dentry, filp->f_vfsmnt, role);
12628+
12629+ /* if we changed uid/gid, but result in the same role
12630+ and are using inheritance, don't lose the inherited subject
12631+ if current subject is other than what normal lookup
12632+ would result in, we arrived via inheritance, don't
12633+ lose subject
12634+ */
12635+ if (role != task->role || (!(task->acl->mode & GR_INHERITLEARN) &&
12636+ (subj == task->acl)))
12637+ task->acl = subj;
12638+
12639+ task->role = role;
12640+
12641+ task->is_writable = 0;
12642+
12643+ /* ignore additional mmap checks for processes that are writable
12644+ by the default ACL */
12645+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
12646+ if (unlikely(obj->mode & GR_WRITE))
12647+ task->is_writable = 1;
12648+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label);
12649+ if (unlikely(obj->mode & GR_WRITE))
12650+ task->is_writable = 1;
12651+
12652+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
12653+ printk(KERN_ALERT "Set role label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
12654+#endif
12655+
12656+ gr_set_proc_res(task);
12657+
12658+ return;
12659+}
12660+
12661+int
12662+gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
12663+{
12664+ struct task_struct *task = current;
12665+ struct acl_subject_label *newacl;
12666+ struct acl_object_label *obj;
12667+ __u32 retmode;
12668+
12669+ if (unlikely(!(gr_status & GR_READY)))
12670+ return 0;
12671+
12672+ newacl = chk_subj_label(dentry, mnt, task->role);
12673+
12674+ task_lock(task);
12675+ if (((task->ptrace & PT_PTRACED) && !(task->acl->mode &
12676+ GR_POVERRIDE) && (task->acl != newacl) &&
12677+ !(task->role->roletype & GR_ROLE_GOD) &&
12678+ !gr_search_file(dentry, GR_PTRACERD, mnt) &&
12679+ !(task->acl->mode & (GR_LEARN | GR_INHERITLEARN))) ||
12680+ (atomic_read(&task->fs->count) > 1 ||
12681+ atomic_read(&task->files->count) > 1 ||
12682+ atomic_read(&task->sighand->count) > 1)) {
12683+ task_unlock(task);
12684+ gr_log_fs_generic(GR_DONT_AUDIT, GR_PTRACE_EXEC_ACL_MSG, dentry, mnt);
12685+ return -EACCES;
12686+ }
12687+ task_unlock(task);
12688+
12689+ obj = chk_obj_label(dentry, mnt, task->acl);
12690+ retmode = obj->mode & (GR_INHERIT | GR_AUDIT_INHERIT);
12691+
12692+ if (!(task->acl->mode & GR_INHERITLEARN) &&
12693+ ((newacl->mode & GR_LEARN) || !(retmode & GR_INHERIT))) {
12694+ if (obj->nested)
12695+ task->acl = obj->nested;
12696+ else
12697+ task->acl = newacl;
12698+ } else if (retmode & GR_INHERIT && retmode & GR_AUDIT_INHERIT)
12699+ gr_log_str_fs(GR_DO_AUDIT, GR_INHERIT_ACL_MSG, task->acl->filename, dentry, mnt);
12700+
12701+ task->is_writable = 0;
12702+
12703+ /* ignore additional mmap checks for processes that are writable
12704+ by the default ACL */
12705+ obj = chk_obj_label(dentry, mnt, default_role->root_label);
12706+ if (unlikely(obj->mode & GR_WRITE))
12707+ task->is_writable = 1;
12708+ obj = chk_obj_label(dentry, mnt, task->role->root_label);
12709+ if (unlikely(obj->mode & GR_WRITE))
12710+ task->is_writable = 1;
12711+
12712+ gr_set_proc_res(task);
12713+
12714+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
12715+ printk(KERN_ALERT "Set subject label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
12716+#endif
12717+ return 0;
12718+}
12719+
12720+static void
12721+do_handle_delete(const ino_t ino, const dev_t dev)
12722+{
12723+ struct acl_object_label *matchpo;
12724+ struct acl_subject_label *matchps;
12725+ struct acl_subject_label *subj;
12726+ struct acl_role_label *role;
12727+ unsigned int i, x;
12728+
12729+ FOR_EACH_ROLE_START(role, i)
12730+ FOR_EACH_SUBJECT_START(role, subj, x)
12731+ if ((matchpo = lookup_acl_obj_label(ino, dev, subj)) != NULL)
12732+ matchpo->mode |= GR_DELETED;
12733+ FOR_EACH_SUBJECT_END(subj,x)
12734+ FOR_EACH_NESTED_SUBJECT_START(role, subj)
12735+ if (subj->inode == ino && subj->device == dev)
12736+ subj->mode |= GR_DELETED;
12737+ FOR_EACH_NESTED_SUBJECT_END(subj)
12738+ if ((matchps = lookup_acl_subj_label(ino, dev, role)) != NULL)
12739+ matchps->mode |= GR_DELETED;
12740+ FOR_EACH_ROLE_END(role,i)
12741+
12742+ return;
12743+}
12744+
12745+void
12746+gr_handle_delete(const ino_t ino, const dev_t dev)
12747+{
12748+ if (unlikely(!(gr_status & GR_READY)))
12749+ return;
12750+
12751+ write_lock(&gr_inode_lock);
12752+ if (unlikely((unsigned long)lookup_inodev_entry(ino, dev)))
12753+ do_handle_delete(ino, dev);
12754+ write_unlock(&gr_inode_lock);
12755+
12756+ return;
12757+}
12758+
12759+static void
12760+update_acl_obj_label(const ino_t oldinode, const dev_t olddevice,
12761+ const ino_t newinode, const dev_t newdevice,
12762+ struct acl_subject_label *subj)
12763+{
12764+ unsigned int index = fhash(oldinode, olddevice, subj->obj_hash_size);
12765+ struct acl_object_label *match;
12766+
12767+ match = subj->obj_hash[index];
12768+
12769+ while (match && (match->inode != oldinode ||
12770+ match->device != olddevice ||
12771+ !(match->mode & GR_DELETED)))
12772+ match = match->next;
12773+
12774+ if (match && (match->inode == oldinode)
12775+ && (match->device == olddevice)
12776+ && (match->mode & GR_DELETED)) {
12777+ if (match->prev == NULL) {
12778+ subj->obj_hash[index] = match->next;
12779+ if (match->next != NULL)
12780+ match->next->prev = NULL;
12781+ } else {
12782+ match->prev->next = match->next;
12783+ if (match->next != NULL)
12784+ match->next->prev = match->prev;
12785+ }
12786+ match->prev = NULL;
12787+ match->next = NULL;
12788+ match->inode = newinode;
12789+ match->device = newdevice;
12790+ match->mode &= ~GR_DELETED;
12791+
12792+ insert_acl_obj_label(match, subj);
12793+ }
12794+
12795+ return;
12796+}
12797+
12798+static void
12799+update_acl_subj_label(const ino_t oldinode, const dev_t olddevice,
12800+ const ino_t newinode, const dev_t newdevice,
12801+ struct acl_role_label *role)
12802+{
12803+ unsigned int index = fhash(oldinode, olddevice, role->subj_hash_size);
12804+ struct acl_subject_label *match;
12805+
12806+ match = role->subj_hash[index];
12807+
12808+ while (match && (match->inode != oldinode ||
12809+ match->device != olddevice ||
12810+ !(match->mode & GR_DELETED)))
12811+ match = match->next;
12812+
12813+ if (match && (match->inode == oldinode)
12814+ && (match->device == olddevice)
12815+ && (match->mode & GR_DELETED)) {
12816+ if (match->prev == NULL) {
12817+ role->subj_hash[index] = match->next;
12818+ if (match->next != NULL)
12819+ match->next->prev = NULL;
12820+ } else {
12821+ match->prev->next = match->next;
12822+ if (match->next != NULL)
12823+ match->next->prev = match->prev;
12824+ }
12825+ match->prev = NULL;
12826+ match->next = NULL;
12827+ match->inode = newinode;
12828+ match->device = newdevice;
12829+ match->mode &= ~GR_DELETED;
12830+
12831+ insert_acl_subj_label(match, role);
12832+ }
12833+
12834+ return;
12835+}
12836+
12837+static void
12838+update_inodev_entry(const ino_t oldinode, const dev_t olddevice,
12839+ const ino_t newinode, const dev_t newdevice)
12840+{
12841+ unsigned int index = fhash(oldinode, olddevice, inodev_set.i_size);
12842+ struct inodev_entry *match;
12843+
12844+ match = inodev_set.i_hash[index];
12845+
12846+ while (match && (match->nentry->inode != oldinode ||
12847+ match->nentry->device != olddevice))
12848+ match = match->next;
12849+
12850+ if (match && (match->nentry->inode == oldinode)
12851+ && (match->nentry->device == olddevice)) {
12852+ if (match->prev == NULL) {
12853+ inodev_set.i_hash[index] = match->next;
12854+ if (match->next != NULL)
12855+ match->next->prev = NULL;
12856+ } else {
12857+ match->prev->next = match->next;
12858+ if (match->next != NULL)
12859+ match->next->prev = match->prev;
12860+ }
12861+ match->prev = NULL;
12862+ match->next = NULL;
12863+ match->nentry->inode = newinode;
12864+ match->nentry->device = newdevice;
12865+
12866+ insert_inodev_entry(match);
12867+ }
12868+
12869+ return;
12870+}
12871+
12872+static void
12873+do_handle_create(const struct name_entry *matchn, const struct dentry *dentry,
12874+ const struct vfsmount *mnt)
12875+{
12876+ struct acl_subject_label *subj;
12877+ struct acl_role_label *role;
12878+ unsigned int i, x;
12879+
12880+ FOR_EACH_ROLE_START(role, i)
12881+ update_acl_subj_label(matchn->inode, matchn->device,
12882+ dentry->d_inode->i_ino,
12883+ dentry->d_inode->i_sb->s_dev, role);
12884+
12885+ FOR_EACH_NESTED_SUBJECT_START(role, subj)
12886+ if ((subj->inode == dentry->d_inode->i_ino) &&
12887+ (subj->device == dentry->d_inode->i_sb->s_dev)) {
12888+ subj->inode = dentry->d_inode->i_ino;
12889+ subj->device = dentry->d_inode->i_sb->s_dev;
12890+ }
12891+ FOR_EACH_NESTED_SUBJECT_END(subj)
12892+ FOR_EACH_SUBJECT_START(role, subj, x)
12893+ update_acl_obj_label(matchn->inode, matchn->device,
12894+ dentry->d_inode->i_ino,
12895+ dentry->d_inode->i_sb->s_dev, subj);
12896+ FOR_EACH_SUBJECT_END(subj,x)
12897+ FOR_EACH_ROLE_END(role,i)
12898+
12899+ update_inodev_entry(matchn->inode, matchn->device,
12900+ dentry->d_inode->i_ino, dentry->d_inode->i_sb->s_dev);
12901+
12902+ return;
12903+}
12904+
12905+void
12906+gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
12907+{
12908+ struct name_entry *matchn;
12909+
12910+ if (unlikely(!(gr_status & GR_READY)))
12911+ return;
12912+
12913+ preempt_disable();
12914+ matchn = lookup_name_entry(gr_to_filename_rbac(dentry, mnt));
12915+
12916+ if (unlikely((unsigned long)matchn)) {
12917+ write_lock(&gr_inode_lock);
12918+ do_handle_create(matchn, dentry, mnt);
12919+ write_unlock(&gr_inode_lock);
12920+ }
12921+ preempt_enable();
12922+
12923+ return;
12924+}
12925+
12926+void
12927+gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
12928+ struct dentry *old_dentry,
12929+ struct dentry *new_dentry,
12930+ struct vfsmount *mnt, const __u8 replace)
12931+{
12932+ struct name_entry *matchn;
12933+
12934+ if (unlikely(!(gr_status & GR_READY)))
12935+ return;
12936+
12937+ preempt_disable();
12938+ matchn = lookup_name_entry(gr_to_filename_rbac(new_dentry, mnt));
12939+
12940+ /* we wouldn't have to check d_inode if it weren't for
12941+ NFS silly-renaming
12942+ */
12943+
12944+ write_lock(&gr_inode_lock);
12945+ if (unlikely(replace && new_dentry->d_inode)) {
12946+ if (unlikely(lookup_inodev_entry(new_dentry->d_inode->i_ino,
12947+ new_dentry->d_inode->i_sb->s_dev) &&
12948+ (old_dentry->d_inode->i_nlink <= 1)))
12949+ do_handle_delete(new_dentry->d_inode->i_ino,
12950+ new_dentry->d_inode->i_sb->s_dev);
12951+ }
12952+
12953+ if (unlikely(lookup_inodev_entry(old_dentry->d_inode->i_ino,
12954+ old_dentry->d_inode->i_sb->s_dev) &&
12955+ (old_dentry->d_inode->i_nlink <= 1)))
12956+ do_handle_delete(old_dentry->d_inode->i_ino,
12957+ old_dentry->d_inode->i_sb->s_dev);
12958+
12959+ if (unlikely((unsigned long)matchn))
12960+ do_handle_create(matchn, old_dentry, mnt);
12961+
12962+ write_unlock(&gr_inode_lock);
12963+ preempt_enable();
12964+
12965+ return;
12966+}
12967+
12968+static int
12969+lookup_special_role_auth(__u16 mode, const char *rolename, unsigned char **salt,
12970+ unsigned char **sum)
12971+{
12972+ struct acl_role_label *r;
12973+ struct role_allowed_ip *ipp;
12974+ struct role_transition *trans;
12975+ unsigned int i;
12976+ int found = 0;
12977+
12978+ /* check transition table */
12979+
12980+ for (trans = current->role->transitions; trans; trans = trans->next) {
12981+ if (!strcmp(rolename, trans->rolename)) {
12982+ found = 1;
12983+ break;
12984+ }
12985+ }
12986+
12987+ if (!found)
12988+ return 0;
12989+
12990+ /* handle special roles that do not require authentication
12991+ and check ip */
12992+
12993+ FOR_EACH_ROLE_START(r, i)
12994+ if (!strcmp(rolename, r->rolename) &&
12995+ (r->roletype & GR_ROLE_SPECIAL)) {
12996+ found = 0;
12997+ if (r->allowed_ips != NULL) {
12998+ for (ipp = r->allowed_ips; ipp; ipp = ipp->next) {
12999+ if ((ntohl(current->signal->curr_ip) & ipp->netmask) ==
13000+ (ntohl(ipp->addr) & ipp->netmask))
13001+ found = 1;
13002+ }
13003+ } else
13004+ found = 2;
13005+ if (!found)
13006+ return 0;
13007+
13008+ if (((mode == SPROLE) && (r->roletype & GR_ROLE_NOPW)) ||
13009+ ((mode == SPROLEPAM) && (r->roletype & GR_ROLE_PAM))) {
13010+ *salt = NULL;
13011+ *sum = NULL;
13012+ return 1;
13013+ }
13014+ }
13015+ FOR_EACH_ROLE_END(r,i)
13016+
13017+ for (i = 0; i < num_sprole_pws; i++) {
13018+ if (!strcmp(rolename, acl_special_roles[i]->rolename)) {
13019+ *salt = acl_special_roles[i]->salt;
13020+ *sum = acl_special_roles[i]->sum;
13021+ return 1;
13022+ }
13023+ }
13024+
13025+ return 0;
13026+}
13027+
13028+static void
13029+assign_special_role(char *rolename)
13030+{
13031+ struct acl_object_label *obj;
13032+ struct acl_role_label *r;
13033+ struct acl_role_label *assigned = NULL;
13034+ struct task_struct *tsk;
13035+ struct file *filp;
13036+ unsigned int i;
13037+
13038+ FOR_EACH_ROLE_START(r, i)
13039+ if (!strcmp(rolename, r->rolename) &&
13040+ (r->roletype & GR_ROLE_SPECIAL))
13041+ assigned = r;
13042+ FOR_EACH_ROLE_END(r,i)
13043+
13044+ if (!assigned)
13045+ return;
13046+
13047+ read_lock(&tasklist_lock);
13048+ read_lock(&grsec_exec_file_lock);
13049+
13050+ tsk = current->parent;
13051+ if (tsk == NULL)
13052+ goto out_unlock;
13053+
13054+ filp = tsk->exec_file;
13055+ if (filp == NULL)
13056+ goto out_unlock;
13057+
13058+ tsk->is_writable = 0;
13059+
13060+ tsk->acl_sp_role = 1;
13061+ tsk->acl_role_id = ++acl_sp_role_value;
13062+ tsk->role = assigned;
13063+ tsk->acl = chk_subj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role);
13064+
13065+ /* ignore additional mmap checks for processes that are writable
13066+ by the default ACL */
13067+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
13068+ if (unlikely(obj->mode & GR_WRITE))
13069+ tsk->is_writable = 1;
13070+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role->root_label);
13071+ if (unlikely(obj->mode & GR_WRITE))
13072+ tsk->is_writable = 1;
13073+
13074+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
13075+ printk(KERN_ALERT "Assigning special role:%s subject:%s to process (%s:%d)\n", tsk->role->rolename, tsk->acl->filename, tsk->comm, tsk->pid);
13076+#endif
13077+
13078+out_unlock:
13079+ read_unlock(&grsec_exec_file_lock);
13080+ read_unlock(&tasklist_lock);
13081+ return;
13082+}
13083+
13084+int gr_check_secure_terminal(struct task_struct *task)
13085+{
13086+ struct task_struct *p, *p2, *p3;
13087+ struct files_struct *files;
13088+ struct fdtable *fdt;
13089+ struct file *our_file = NULL, *file;
13090+ int i;
13091+
13092+ if (task->signal->tty == NULL)
13093+ return 1;
13094+
13095+ files = get_files_struct(task);
13096+ if (files != NULL) {
13097+ rcu_read_lock();
13098+ fdt = files_fdtable(files);
13099+ for (i=0; i < fdt->max_fds; i++) {
13100+ file = fcheck_files(files, i);
13101+ if (file && (our_file == NULL) && (file->private_data == task->signal->tty)) {
13102+ get_file(file);
13103+ our_file = file;
13104+ }
13105+ }
13106+ rcu_read_unlock();
13107+ put_files_struct(files);
13108+ }
13109+
13110+ if (our_file == NULL)
13111+ return 1;
13112+
13113+ read_lock(&tasklist_lock);
13114+ do_each_thread(p2, p) {
13115+ files = get_files_struct(p);
13116+ if (files == NULL ||
13117+ (p->signal && p->signal->tty == task->signal->tty)) {
13118+ if (files != NULL)
13119+ put_files_struct(files);
13120+ continue;
13121+ }
13122+ rcu_read_lock();
13123+ fdt = files_fdtable(files);
13124+ for (i=0; i < fdt->max_fds; i++) {
13125+ file = fcheck_files(files, i);
13126+ if (file && S_ISCHR(file->f_dentry->d_inode->i_mode) &&
13127+ file->f_dentry->d_inode->i_rdev == our_file->f_dentry->d_inode->i_rdev) {
13128+ p3 = task;
13129+ while (p3->pid > 0) {
13130+ if (p3 == p)
13131+ break;
13132+ p3 = p3->parent;
13133+ }
13134+ if (p3 == p)
13135+ break;
13136+ gr_log_ttysniff(GR_DONT_AUDIT_GOOD, GR_TTYSNIFF_ACL_MSG, p);
13137+ gr_handle_alertkill(p);
13138+ rcu_read_unlock();
13139+ put_files_struct(files);
13140+ read_unlock(&tasklist_lock);
13141+ fput(our_file);
13142+ return 0;
13143+ }
13144+ }
13145+ rcu_read_unlock();
13146+ put_files_struct(files);
13147+ } while_each_thread(p2, p);
13148+ read_unlock(&tasklist_lock);
13149+
13150+ fput(our_file);
13151+ return 1;
13152+}
13153+
13154+ssize_t
13155+write_grsec_handler(struct file *file, const char * buf, size_t count, loff_t *ppos)
13156+{
13157+ struct gr_arg_wrapper uwrap;
13158+ unsigned char *sprole_salt;
13159+ unsigned char *sprole_sum;
13160+ int error = sizeof (struct gr_arg_wrapper);
13161+ int error2 = 0;
13162+
13163+ down(&gr_dev_sem);
13164+
13165+ if ((gr_status & GR_READY) && !(current->acl->mode & GR_KERNELAUTH)) {
13166+ error = -EPERM;
13167+ goto out;
13168+ }
13169+
13170+ if (count != sizeof (struct gr_arg_wrapper)) {
13171+ gr_log_int_int(GR_DONT_AUDIT_GOOD, GR_DEV_ACL_MSG, (int)count, (int)sizeof(struct gr_arg_wrapper));
13172+ error = -EINVAL;
13173+ goto out;
13174+ }
13175+
13176+
13177+ if (gr_auth_expires && time_after_eq(get_seconds(), gr_auth_expires)) {
13178+ gr_auth_expires = 0;
13179+ gr_auth_attempts = 0;
13180+ }
13181+
13182+ if (copy_from_user(&uwrap, buf, sizeof (struct gr_arg_wrapper))) {
13183+ error = -EFAULT;
13184+ goto out;
13185+ }
13186+
13187+ if ((uwrap.version != GRSECURITY_VERSION) || (uwrap.size != sizeof(struct gr_arg))) {
13188+ error = -EINVAL;
13189+ goto out;
13190+ }
13191+
13192+ if (copy_from_user(gr_usermode, uwrap.arg, sizeof (struct gr_arg))) {
13193+ error = -EFAULT;
13194+ goto out;
13195+ }
13196+
13197+ if (gr_usermode->mode != SPROLE && gr_usermode->mode != SPROLEPAM &&
13198+ gr_auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES &&
13199+ time_after(gr_auth_expires, get_seconds())) {
13200+ error = -EBUSY;
13201+ goto out;
13202+ }
13203+
13204+ /* if non-root trying to do anything other than use a special role,
13205+ do not attempt authentication, do not count towards authentication
13206+ locking
13207+ */
13208+
13209+ if (gr_usermode->mode != SPROLE && gr_usermode->mode != STATUS &&
13210+ gr_usermode->mode != UNSPROLE && gr_usermode->mode != SPROLEPAM &&
13211+ current->uid) {
13212+ error = -EPERM;
13213+ goto out;
13214+ }
13215+
13216+ /* ensure pw and special role name are null terminated */
13217+
13218+ gr_usermode->pw[GR_PW_LEN - 1] = '\0';
13219+ gr_usermode->sp_role[GR_SPROLE_LEN - 1] = '\0';
13220+
13221+ /* Okay.
13222+ * We have our enough of the argument structure..(we have yet
13223+ * to copy_from_user the tables themselves) . Copy the tables
13224+ * only if we need them, i.e. for loading operations. */
13225+
13226+ switch (gr_usermode->mode) {
13227+ case STATUS:
13228+ if (gr_status & GR_READY) {
13229+ error = 1;
13230+ if (!gr_check_secure_terminal(current))
13231+ error = 3;
13232+ } else
13233+ error = 2;
13234+ goto out;
13235+ case SHUTDOWN:
13236+ if ((gr_status & GR_READY)
13237+ && !(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
13238+ gr_status &= ~GR_READY;
13239+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTS_ACL_MSG);
13240+ free_variables();
13241+ memset(gr_usermode, 0, sizeof (struct gr_arg));
13242+ memset(gr_system_salt, 0, GR_SALT_LEN);
13243+ memset(gr_system_sum, 0, GR_SHA_LEN);
13244+ } else if (gr_status & GR_READY) {
13245+ gr_log_noargs(GR_DONT_AUDIT, GR_SHUTF_ACL_MSG);
13246+ error = -EPERM;
13247+ } else {
13248+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTI_ACL_MSG);
13249+ error = -EAGAIN;
13250+ }
13251+ break;
13252+ case ENABLE:
13253+ if (!(gr_status & GR_READY) && !(error2 = gracl_init(gr_usermode)))
13254+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_ENABLE_ACL_MSG, GR_VERSION);
13255+ else {
13256+ if (gr_status & GR_READY)
13257+ error = -EAGAIN;
13258+ else
13259+ error = error2;
13260+ gr_log_str(GR_DONT_AUDIT, GR_ENABLEF_ACL_MSG, GR_VERSION);
13261+ }
13262+ break;
13263+ case RELOAD:
13264+ if (!(gr_status & GR_READY)) {
13265+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOADI_ACL_MSG, GR_VERSION);
13266+ error = -EAGAIN;
13267+ } else if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
13268+ lock_kernel();
13269+ gr_status &= ~GR_READY;
13270+ free_variables();
13271+ if (!(error2 = gracl_init(gr_usermode))) {
13272+ unlock_kernel();
13273+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOAD_ACL_MSG, GR_VERSION);
13274+ } else {
13275+ unlock_kernel();
13276+ error = error2;
13277+ gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION);
13278+ }
13279+ } else {
13280+ gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION);
13281+ error = -EPERM;
13282+ }
13283+ break;
13284+ case SEGVMOD:
13285+ if (unlikely(!(gr_status & GR_READY))) {
13286+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODI_ACL_MSG);
13287+ error = -EAGAIN;
13288+ break;
13289+ }
13290+
13291+ if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
13292+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODS_ACL_MSG);
13293+ if (gr_usermode->segv_device && gr_usermode->segv_inode) {
13294+ struct acl_subject_label *segvacl;
13295+ segvacl =
13296+ lookup_acl_subj_label(gr_usermode->segv_inode,
13297+ gr_usermode->segv_device,
13298+ current->role);
13299+ if (segvacl) {
13300+ segvacl->crashes = 0;
13301+ segvacl->expires = 0;
13302+ }
13303+ } else if (gr_find_uid(gr_usermode->segv_uid) >= 0) {
13304+ gr_remove_uid(gr_usermode->segv_uid);
13305+ }
13306+ } else {
13307+ gr_log_noargs(GR_DONT_AUDIT, GR_SEGVMODF_ACL_MSG);
13308+ error = -EPERM;
13309+ }
13310+ break;
13311+ case SPROLE:
13312+ case SPROLEPAM:
13313+ if (unlikely(!(gr_status & GR_READY))) {
13314+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SPROLEI_ACL_MSG);
13315+ error = -EAGAIN;
13316+ break;
13317+ }
13318+
13319+ if (current->role->expires && time_after_eq(get_seconds(), current->role->expires)) {
13320+ current->role->expires = 0;
13321+ current->role->auth_attempts = 0;
13322+ }
13323+
13324+ if (current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES &&
13325+ time_after(current->role->expires, get_seconds())) {
13326+ error = -EBUSY;
13327+ goto out;
13328+ }
13329+
13330+ if (lookup_special_role_auth
13331+ (gr_usermode->mode, gr_usermode->sp_role, &sprole_salt, &sprole_sum)
13332+ && ((!sprole_salt && !sprole_sum)
13333+ || !(chkpw(gr_usermode, sprole_salt, sprole_sum)))) {
13334+ char *p = "";
13335+ assign_special_role(gr_usermode->sp_role);
13336+ read_lock(&tasklist_lock);
13337+ if (current->parent)
13338+ p = current->parent->role->rolename;
13339+ read_unlock(&tasklist_lock);
13340+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLES_ACL_MSG,
13341+ p, acl_sp_role_value);
13342+ } else {
13343+ gr_log_str(GR_DONT_AUDIT, GR_SPROLEF_ACL_MSG, gr_usermode->sp_role);
13344+ error = -EPERM;
13345+ if(!(current->role->auth_attempts++))
13346+ current->role->expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT;
13347+
13348+ goto out;
13349+ }
13350+ break;
13351+ case UNSPROLE:
13352+ if (unlikely(!(gr_status & GR_READY))) {
13353+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_UNSPROLEI_ACL_MSG);
13354+ error = -EAGAIN;
13355+ break;
13356+ }
13357+
13358+ if (current->role->roletype & GR_ROLE_SPECIAL) {
13359+ char *p = "";
13360+ int i = 0;
13361+
13362+ read_lock(&tasklist_lock);
13363+ if (current->parent) {
13364+ p = current->parent->role->rolename;
13365+ i = current->parent->acl_role_id;
13366+ }
13367+ read_unlock(&tasklist_lock);
13368+
13369+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_UNSPROLES_ACL_MSG, p, i);
13370+ gr_set_acls(1);
13371+ } else {
13372+ gr_log_str(GR_DONT_AUDIT, GR_UNSPROLEF_ACL_MSG, current->role->rolename);
13373+ error = -EPERM;
13374+ goto out;
13375+ }
13376+ break;
13377+ default:
13378+ gr_log_int(GR_DONT_AUDIT, GR_INVMODE_ACL_MSG, gr_usermode->mode);
13379+ error = -EINVAL;
13380+ break;
13381+ }
13382+
13383+ if (error != -EPERM)
13384+ goto out;
13385+
13386+ if(!(gr_auth_attempts++))
13387+ gr_auth_expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT;
13388+
13389+ out:
13390+ up(&gr_dev_sem);
13391+ return error;
13392+}
13393+
13394+int
13395+gr_set_acls(const int type)
13396+{
13397+ struct acl_object_label *obj;
13398+ struct task_struct *task, *task2;
13399+ struct file *filp;
13400+ struct acl_role_label *role = current->role;
13401+ __u16 acl_role_id = current->acl_role_id;
13402+
13403+ read_lock(&tasklist_lock);
13404+ read_lock(&grsec_exec_file_lock);
13405+ do_each_thread(task2, task) {
13406+ /* check to see if we're called from the exit handler,
13407+ if so, only replace ACLs that have inherited the admin
13408+ ACL */
13409+
13410+ if (type && (task->role != role ||
13411+ task->acl_role_id != acl_role_id))
13412+ continue;
13413+
13414+ task->acl_role_id = 0;
13415+ task->acl_sp_role = 0;
13416+
13417+ if ((filp = task->exec_file)) {
13418+ task->role = lookup_acl_role_label(task, task->uid, task->gid);
13419+
13420+ task->acl =
13421+ chk_subj_label(filp->f_dentry, filp->f_vfsmnt,
13422+ task->role);
13423+ if (task->acl) {
13424+ struct acl_subject_label *curr;
13425+ curr = task->acl;
13426+
13427+ task->is_writable = 0;
13428+ /* ignore additional mmap checks for processes that are writable
13429+ by the default ACL */
13430+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
13431+ if (unlikely(obj->mode & GR_WRITE))
13432+ task->is_writable = 1;
13433+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label);
13434+ if (unlikely(obj->mode & GR_WRITE))
13435+ task->is_writable = 1;
13436+
13437+ gr_set_proc_res(task);
13438+
13439+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
13440+ printk(KERN_ALERT "gr_set_acls for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
13441+#endif
13442+ } else {
13443+ read_unlock(&grsec_exec_file_lock);
13444+ read_unlock(&tasklist_lock);
13445+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_DEFACL_MSG, task->comm, task->pid);
13446+ return 1;
13447+ }
13448+ } else {
13449+ // it's a kernel process
13450+ task->role = kernel_role;
13451+ task->acl = kernel_role->root_label;
13452+#ifdef CONFIG_GRKERNSEC_ACL_HIDEKERN
13453+ task->acl->mode &= ~GR_PROCFIND;
13454+#endif
13455+ }
13456+ } while_each_thread(task2, task);
13457+ read_unlock(&grsec_exec_file_lock);
13458+ read_unlock(&tasklist_lock);
13459+ return 0;
13460+}
13461+
13462+void
13463+gr_learn_resource(const struct task_struct *task,
13464+ const int res, const unsigned long wanted, const int gt)
13465+{
13466+ struct acl_subject_label *acl;
13467+
13468+ if (unlikely((gr_status & GR_READY) &&
13469+ task->acl && (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))))
13470+ goto skip_reslog;
13471+
13472+#ifdef CONFIG_GRKERNSEC_RESLOG
13473+ gr_log_resource(task, res, wanted, gt);
13474+#endif
13475+ skip_reslog:
13476+
13477+ if (unlikely(!(gr_status & GR_READY) || !wanted))
13478+ return;
13479+
13480+ acl = task->acl;
13481+
13482+ if (likely(!acl || !(acl->mode & (GR_LEARN | GR_INHERITLEARN)) ||
13483+ !(acl->resmask & (1 << (unsigned short) res))))
13484+ return;
13485+
13486+ if (wanted >= acl->res[res].rlim_cur) {
13487+ unsigned long res_add;
13488+
13489+ res_add = wanted;
13490+ switch (res) {
13491+ case RLIMIT_CPU:
13492+ res_add += GR_RLIM_CPU_BUMP;
13493+ break;
13494+ case RLIMIT_FSIZE:
13495+ res_add += GR_RLIM_FSIZE_BUMP;
13496+ break;
13497+ case RLIMIT_DATA:
13498+ res_add += GR_RLIM_DATA_BUMP;
13499+ break;
13500+ case RLIMIT_STACK:
13501+ res_add += GR_RLIM_STACK_BUMP;
13502+ break;
13503+ case RLIMIT_CORE:
13504+ res_add += GR_RLIM_CORE_BUMP;
13505+ break;
13506+ case RLIMIT_RSS:
13507+ res_add += GR_RLIM_RSS_BUMP;
13508+ break;
13509+ case RLIMIT_NPROC:
13510+ res_add += GR_RLIM_NPROC_BUMP;
13511+ break;
13512+ case RLIMIT_NOFILE:
13513+ res_add += GR_RLIM_NOFILE_BUMP;
13514+ break;
13515+ case RLIMIT_MEMLOCK:
13516+ res_add += GR_RLIM_MEMLOCK_BUMP;
13517+ break;
13518+ case RLIMIT_AS:
13519+ res_add += GR_RLIM_AS_BUMP;
13520+ break;
13521+ case RLIMIT_LOCKS:
13522+ res_add += GR_RLIM_LOCKS_BUMP;
13523+ break;
13524+ }
13525+
13526+ acl->res[res].rlim_cur = res_add;
13527+
13528+ if (wanted > acl->res[res].rlim_max)
13529+ acl->res[res].rlim_max = res_add;
13530+
13531+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
13532+ task->role->roletype, acl->filename,
13533+ acl->res[res].rlim_cur, acl->res[res].rlim_max,
13534+ "", (unsigned long) res);
13535+ }
13536+
13537+ return;
13538+}
13539+
13540+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
13541+void
13542+pax_set_initial_flags(struct linux_binprm *bprm)
13543+{
13544+ struct task_struct *task = current;
13545+ struct acl_subject_label *proc;
13546+ unsigned long flags;
13547+
13548+ if (unlikely(!(gr_status & GR_READY)))
13549+ return;
13550+
13551+ flags = pax_get_flags(task);
13552+
13553+ proc = task->acl;
13554+
13555+ if (proc->pax_flags & GR_PAX_DISABLE_PAGEEXEC)
13556+ flags &= ~MF_PAX_PAGEEXEC;
13557+ if (proc->pax_flags & GR_PAX_DISABLE_SEGMEXEC)
13558+ flags &= ~MF_PAX_SEGMEXEC;
13559+ if (proc->pax_flags & GR_PAX_DISABLE_RANDMMAP)
13560+ flags &= ~MF_PAX_RANDMMAP;
13561+ if (proc->pax_flags & GR_PAX_DISABLE_EMUTRAMP)
13562+ flags &= ~MF_PAX_EMUTRAMP;
13563+ if (proc->pax_flags & GR_PAX_DISABLE_MPROTECT)
13564+ flags &= ~MF_PAX_MPROTECT;
13565+
13566+ if (proc->pax_flags & GR_PAX_ENABLE_PAGEEXEC)
13567+ flags |= MF_PAX_PAGEEXEC;
13568+ if (proc->pax_flags & GR_PAX_ENABLE_SEGMEXEC)
13569+ flags |= MF_PAX_SEGMEXEC;
13570+ if (proc->pax_flags & GR_PAX_ENABLE_RANDMMAP)
13571+ flags |= MF_PAX_RANDMMAP;
13572+ if (proc->pax_flags & GR_PAX_ENABLE_EMUTRAMP)
13573+ flags |= MF_PAX_EMUTRAMP;
13574+ if (proc->pax_flags & GR_PAX_ENABLE_MPROTECT)
13575+ flags |= MF_PAX_MPROTECT;
13576+
13577+ pax_set_flags(task, flags);
13578+
13579+ return;
13580+}
13581+#endif
13582+
13583+#ifdef CONFIG_SYSCTL
13584+extern struct proc_dir_entry *proc_sys_root;
13585+
13586+/* the following function is called under the BKL */
13587+
13588+__u32
13589+gr_handle_sysctl(const struct ctl_table *table, const void *oldval,
13590+ const void *newval)
13591+{
13592+ struct proc_dir_entry *tmp;
13593+ struct nameidata nd;
13594+ const char *proc_sys = "/proc/sys";
13595+ char *path;
13596+ struct acl_object_label *obj;
13597+ unsigned short len = 0, pos = 0, depth = 0, i;
13598+ __u32 err = 0;
13599+ __u32 mode = 0;
13600+
13601+ if (unlikely(!(gr_status & GR_READY)))
13602+ return 1;
13603+
13604+ path = per_cpu_ptr(gr_shared_page[0], smp_processor_id());
13605+
13606+ if (oldval)
13607+ mode |= GR_READ;
13608+ if (newval)
13609+ mode |= GR_WRITE;
13610+
13611+ /* convert the requested sysctl entry into a pathname */
13612+
13613+ for (tmp = table->de; tmp != proc_sys_root; tmp = tmp->parent) {
13614+ len += strlen(tmp->name);
13615+ len++;
13616+ depth++;
13617+ }
13618+
13619+ if ((len + depth + strlen(proc_sys) + 1) > PAGE_SIZE)
13620+ return 0; /* deny */
13621+
13622+ memset(path, 0, PAGE_SIZE);
13623+
13624+ memcpy(path, proc_sys, strlen(proc_sys));
13625+
13626+ pos += strlen(proc_sys);
13627+
13628+ for (; depth > 0; depth--) {
13629+ path[pos] = '/';
13630+ pos++;
13631+ for (i = 1, tmp = table->de; tmp != proc_sys_root;
13632+ tmp = tmp->parent) {
13633+ if (depth == i) {
13634+ memcpy(path + pos, tmp->name,
13635+ strlen(tmp->name));
13636+ pos += strlen(tmp->name);
13637+ }
13638+ i++;
13639+ }
13640+ }
13641+
13642+ err = path_lookup(path, LOOKUP_FOLLOW, &nd);
13643+
13644+ if (err)
13645+ goto out;
13646+
13647+ obj = chk_obj_label(nd.dentry, nd.mnt, current->acl);
13648+ err = obj->mode & (mode | to_gr_audit(mode) | GR_SUPPRESS);
13649+
13650+ if (unlikely((current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) &&
13651+ ((err & mode) != mode))) {
13652+ __u32 new_mode = mode;
13653+
13654+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
13655+
13656+ err = new_mode;
13657+ gr_log_learn(current, nd.dentry, nd.mnt, new_mode);
13658+ } else if ((err & mode) != mode && !(err & GR_SUPPRESS)) {
13659+ gr_log_str4(GR_DONT_AUDIT, GR_SYSCTL_ACL_MSG, "denied",
13660+ path, (mode & GR_READ) ? " reading" : "",
13661+ (mode & GR_WRITE) ? " writing" : "");
13662+ err = 0;
13663+ } else if ((err & mode) != mode) {
13664+ err = 0;
13665+ } else if (((err & mode) == mode) && (err & GR_AUDITS)) {
13666+ gr_log_str4(GR_DO_AUDIT, GR_SYSCTL_ACL_MSG, "successful",
13667+ path, (mode & GR_READ) ? " reading" : "",
13668+ (mode & GR_WRITE) ? " writing" : "");
13669+ }
13670+
13671+ path_release(&nd);
13672+
13673+ out:
13674+ return err;
13675+}
13676+#endif
13677+
13678+int
13679+gr_handle_proc_ptrace(struct task_struct *task)
13680+{
13681+ struct file *filp;
13682+ struct task_struct *tmp = task;
13683+ struct task_struct *curtemp = current;
13684+ __u32 retmode;
13685+
13686+ if (unlikely(!(gr_status & GR_READY)))
13687+ return 0;
13688+
13689+ read_lock(&tasklist_lock);
13690+ read_lock(&grsec_exec_file_lock);
13691+ filp = task->exec_file;
13692+
13693+ while (tmp->pid > 0) {
13694+ if (tmp == curtemp)
13695+ break;
13696+ tmp = tmp->parent;
13697+ }
13698+
13699+ if (!filp || (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE))) {
13700+ read_unlock(&grsec_exec_file_lock);
13701+ read_unlock(&tasklist_lock);
13702+ return 1;
13703+ }
13704+
13705+ retmode = gr_search_file(filp->f_dentry, GR_NOPTRACE, filp->f_vfsmnt);
13706+ read_unlock(&grsec_exec_file_lock);
13707+ read_unlock(&tasklist_lock);
13708+
13709+ if (retmode & GR_NOPTRACE)
13710+ return 1;
13711+
13712+ if (!(current->acl->mode & GR_POVERRIDE) && !(current->role->roletype & GR_ROLE_GOD)
13713+ && (current->acl != task->acl || (current->acl != current->role->root_label
13714+ && current->pid != task->pid)))
13715+ return 1;
13716+
13717+ return 0;
13718+}
13719+
13720+int
13721+gr_handle_ptrace(struct task_struct *task, const long request)
13722+{
13723+ struct task_struct *tmp = task;
13724+ struct task_struct *curtemp = current;
13725+ __u32 retmode;
13726+
13727+ if (unlikely(!(gr_status & GR_READY)))
13728+ return 0;
13729+
13730+ read_lock(&tasklist_lock);
13731+ while (tmp->pid > 0) {
13732+ if (tmp == curtemp)
13733+ break;
13734+ tmp = tmp->parent;
13735+ }
13736+
13737+ if (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE)) {
13738+ read_unlock(&tasklist_lock);
13739+ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
13740+ return 1;
13741+ }
13742+ read_unlock(&tasklist_lock);
13743+
13744+ read_lock(&grsec_exec_file_lock);
13745+ if (unlikely(!task->exec_file)) {
13746+ read_unlock(&grsec_exec_file_lock);
13747+ return 0;
13748+ }
13749+
13750+ retmode = gr_search_file(task->exec_file->f_dentry, GR_PTRACERD | GR_NOPTRACE, task->exec_file->f_vfsmnt);
13751+ read_unlock(&grsec_exec_file_lock);
13752+
13753+ if (retmode & GR_NOPTRACE) {
13754+ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
13755+ return 1;
13756+ }
13757+
13758+ if (retmode & GR_PTRACERD) {
13759+ switch (request) {
13760+ case PTRACE_POKETEXT:
13761+ case PTRACE_POKEDATA:
13762+ case PTRACE_POKEUSR:
13763+#if !defined(CONFIG_PPC32) && !defined(CONFIG_PPC64) && !defined(CONFIG_PARISC) && !defined(CONFIG_ALPHA) && !defined(CONFIG_IA64)
13764+ case PTRACE_SETREGS:
13765+ case PTRACE_SETFPREGS:
13766+#endif
13767+#ifdef CONFIG_X86
13768+ case PTRACE_SETFPXREGS:
13769+#endif
13770+#ifdef CONFIG_ALTIVEC
13771+ case PTRACE_SETVRREGS:
13772+#endif
13773+ return 1;
13774+ default:
13775+ return 0;
13776+ }
13777+ } else if (!(current->acl->mode & GR_POVERRIDE) &&
13778+ !(current->role->roletype & GR_ROLE_GOD) &&
13779+ (current->acl != task->acl)) {
13780+ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
13781+ return 1;
13782+ }
13783+
13784+ return 0;
13785+}
13786+
13787+static int is_writable_mmap(const struct file *filp)
13788+{
13789+ struct task_struct *task = current;
13790+ struct acl_object_label *obj, *obj2;
13791+
13792+ if (gr_status & GR_READY && !(task->acl->mode & GR_OVERRIDE) &&
13793+ !task->is_writable && S_ISREG(filp->f_dentry->d_inode->i_mode)) {
13794+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
13795+ obj2 = chk_obj_label(filp->f_dentry, filp->f_vfsmnt,
13796+ task->role->root_label);
13797+ if (unlikely((obj->mode & GR_WRITE) || (obj2->mode & GR_WRITE))) {
13798+ gr_log_fs_generic(GR_DONT_AUDIT, GR_WRITLIB_ACL_MSG, filp->f_dentry, filp->f_vfsmnt);
13799+ return 1;
13800+ }
13801+ }
13802+ return 0;
13803+}
13804+
13805+int
13806+gr_acl_handle_mmap(const struct file *file, const unsigned long prot)
13807+{
13808+ __u32 mode;
13809+
13810+ if (unlikely(!file || !(prot & PROT_EXEC)))
13811+ return 1;
13812+
13813+ if (is_writable_mmap(file))
13814+ return 0;
13815+
13816+ mode =
13817+ gr_search_file(file->f_dentry,
13818+ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
13819+ file->f_vfsmnt);
13820+
13821+ if (!gr_tpe_allow(file))
13822+ return 0;
13823+
13824+ if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) {
13825+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MMAP_ACL_MSG, file->f_dentry, file->f_vfsmnt);
13826+ return 0;
13827+ } else if (unlikely(!(mode & GR_EXEC))) {
13828+ return 0;
13829+ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
13830+ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MMAP_ACL_MSG, file->f_dentry, file->f_vfsmnt);
13831+ return 1;
13832+ }
13833+
13834+ return 1;
13835+}
13836+
13837+int
13838+gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
13839+{
13840+ __u32 mode;
13841+
13842+ if (unlikely(!file || !(prot & PROT_EXEC)))
13843+ return 1;
13844+
13845+ if (is_writable_mmap(file))
13846+ return 0;
13847+
13848+ mode =
13849+ gr_search_file(file->f_dentry,
13850+ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
13851+ file->f_vfsmnt);
13852+
13853+ if (!gr_tpe_allow(file))
13854+ return 0;
13855+
13856+ if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) {
13857+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MPROTECT_ACL_MSG, file->f_dentry, file->f_vfsmnt);
13858+ return 0;
13859+ } else if (unlikely(!(mode & GR_EXEC))) {
13860+ return 0;
13861+ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
13862+ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MPROTECT_ACL_MSG, file->f_dentry, file->f_vfsmnt);
13863+ return 1;
13864+ }
13865+
13866+ return 1;
13867+}
13868+
13869+void
13870+gr_acl_handle_psacct(struct task_struct *task, const long code)
13871+{
13872+ unsigned long runtime;
13873+ unsigned long cputime;
13874+ unsigned int wday, cday;
13875+ __u8 whr, chr;
13876+ __u8 wmin, cmin;
13877+ __u8 wsec, csec;
13878+
13879+ if (unlikely(!(gr_status & GR_READY) || !task->acl ||
13880+ !(task->acl->mode & GR_PROCACCT)))
13881+ return;
13882+
13883+ runtime = xtime.tv_sec - task->start_time.tv_sec;
13884+ wday = runtime / (3600 * 24);
13885+ runtime -= wday * (3600 * 24);
13886+ whr = runtime / 3600;
13887+ runtime -= whr * 3600;
13888+ wmin = runtime / 60;
13889+ runtime -= wmin * 60;
13890+ wsec = runtime;
13891+
13892+ cputime = (task->utime + task->stime) / HZ;
13893+ cday = cputime / (3600 * 24);
13894+ cputime -= cday * (3600 * 24);
13895+ chr = cputime / 3600;
13896+ cputime -= chr * 3600;
13897+ cmin = cputime / 60;
13898+ cputime -= cmin * 60;
13899+ csec = cputime;
13900+
13901+ gr_log_procacct(GR_DO_AUDIT, GR_ACL_PROCACCT_MSG, task, wday, whr, wmin, wsec, cday, chr, cmin, csec, code);
13902+
13903+ return;
13904+}
13905+
13906+void gr_set_kernel_label(struct task_struct *task)
13907+{
13908+ if (gr_status & GR_READY) {
13909+ task->role = kernel_role;
13910+ task->acl = kernel_role->root_label;
13911+ }
13912+ return;
13913+}
13914+
13915+int gr_acl_handle_filldir(const struct file *file, const char *name, const unsigned int namelen, const ino_t ino)
13916+{
13917+ struct task_struct *task = current;
13918+ struct dentry *dentry = file->f_dentry;
13919+ struct vfsmount *mnt = file->f_vfsmnt;
13920+ struct acl_object_label *obj, *tmp;
13921+ struct acl_subject_label *subj;
13922+ unsigned int bufsize;
13923+ int is_not_root;
13924+ char *path;
13925+
13926+ if (unlikely(!(gr_status & GR_READY)))
13927+ return 1;
13928+
13929+ if (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))
13930+ return 1;
13931+
13932+ subj = task->acl;
13933+ do {
13934+ obj = lookup_acl_obj_label(ino, dentry->d_inode->i_sb->s_dev, subj);
13935+ if (obj != NULL)
13936+ return (obj->mode & GR_FIND) ? 1 : 0;
13937+ } while ((subj = subj->parent_subject));
13938+
13939+ obj = chk_obj_label(dentry, mnt, task->acl);
13940+ if (obj->globbed == NULL)
13941+ return (obj->mode & GR_FIND) ? 1 : 0;
13942+
13943+ is_not_root = ((obj->filename[0] == '/') &&
13944+ (obj->filename[1] == '\0')) ? 0 : 1;
13945+ bufsize = PAGE_SIZE - namelen - is_not_root;
13946+
13947+ /* check bufsize > PAGE_SIZE || bufsize == 0 */
13948+ if (unlikely((bufsize - 1) > (PAGE_SIZE - 1)))
13949+ return 1;
13950+
13951+ preempt_disable();
13952+ path = d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()),
13953+ bufsize);
13954+
13955+ bufsize = strlen(path);
13956+
13957+ /* if base is "/", don't append an additional slash */
13958+ if (is_not_root)
13959+ *(path + bufsize) = '/';
13960+ memcpy(path + bufsize + is_not_root, name, namelen);
13961+ *(path + bufsize + namelen + is_not_root) = '\0';
13962+
13963+ tmp = obj->globbed;
13964+ while (tmp) {
13965+ if (!glob_match(tmp->filename, path)) {
13966+ preempt_enable();
13967+ return (tmp->mode & GR_FIND) ? 1 : 0;
13968+ }
13969+ tmp = tmp->next;
13970+ }
13971+ preempt_enable();
13972+ return (obj->mode & GR_FIND) ? 1 : 0;
13973+}
13974+
13975+EXPORT_SYMBOL(gr_learn_resource);
13976+EXPORT_SYMBOL(gr_set_kernel_label);
13977+#ifdef CONFIG_SECURITY
13978+EXPORT_SYMBOL(gr_check_user_change);
13979+EXPORT_SYMBOL(gr_check_group_change);
13980+#endif
13981+
13982diff -urNp linux-2.6.17.11/grsecurity/gracl_cap.c linux-2.6.17.11/grsecurity/gracl_cap.c
13983--- linux-2.6.17.11/grsecurity/gracl_cap.c 1969-12-31 19:00:00.000000000 -0500
13984+++ linux-2.6.17.11/grsecurity/gracl_cap.c 2006-08-12 08:17:55.000000000 -0400
13985@@ -0,0 +1,110 @@
13986+#include <linux/kernel.h>
13987+#include <linux/module.h>
13988+#include <linux/sched.h>
13989+#include <linux/capability.h>
13990+#include <linux/gracl.h>
13991+#include <linux/grsecurity.h>
13992+#include <linux/grinternal.h>
13993+
13994+static const char *captab_log[] = {
13995+ "CAP_CHOWN",
13996+ "CAP_DAC_OVERRIDE",
13997+ "CAP_DAC_READ_SEARCH",
13998+ "CAP_FOWNER",
13999+ "CAP_FSETID",
14000+ "CAP_KILL",
14001+ "CAP_SETGID",
14002+ "CAP_SETUID",
14003+ "CAP_SETPCAP",
14004+ "CAP_LINUX_IMMUTABLE",
14005+ "CAP_NET_BIND_SERVICE",
14006+ "CAP_NET_BROADCAST",
14007+ "CAP_NET_ADMIN",
14008+ "CAP_NET_RAW",
14009+ "CAP_IPC_LOCK",
14010+ "CAP_IPC_OWNER",
14011+ "CAP_SYS_MODULE",
14012+ "CAP_SYS_RAWIO",
14013+ "CAP_SYS_CHROOT",
14014+ "CAP_SYS_PTRACE",
14015+ "CAP_SYS_PACCT",
14016+ "CAP_SYS_ADMIN",
14017+ "CAP_SYS_BOOT",
14018+ "CAP_SYS_NICE",
14019+ "CAP_SYS_RESOURCE",
14020+ "CAP_SYS_TIME",
14021+ "CAP_SYS_TTY_CONFIG",
14022+ "CAP_MKNOD",
14023+ "CAP_LEASE"
14024+};
14025+
14026+EXPORT_SYMBOL(gr_task_is_capable);
14027+
14028+int
14029+gr_task_is_capable(struct task_struct *task, const int cap)
14030+{
14031+ struct acl_subject_label *curracl;
14032+ __u32 cap_drop = 0, cap_mask = 0;
14033+
14034+ if (!gr_acl_is_enabled())
14035+ return 1;
14036+
14037+ curracl = task->acl;
14038+
14039+ cap_drop = curracl->cap_lower;
14040+ cap_mask = curracl->cap_mask;
14041+
14042+ while ((curracl = curracl->parent_subject)) {
14043+ if (!(cap_mask & (1 << cap)) && (curracl->cap_mask & (1 << cap)))
14044+ cap_drop |= curracl->cap_lower & (1 << cap);
14045+ cap_mask |= curracl->cap_mask;
14046+ }
14047+
14048+ if (!cap_raised(cap_drop, cap))
14049+ return 1;
14050+
14051+ curracl = task->acl;
14052+
14053+ if ((curracl->mode & (GR_LEARN | GR_INHERITLEARN))
14054+ && cap_raised(task->cap_effective, cap)) {
14055+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
14056+ task->role->roletype, task->uid,
14057+ task->gid, task->exec_file ?
14058+ gr_to_filename(task->exec_file->f_dentry,
14059+ task->exec_file->f_vfsmnt) : curracl->filename,
14060+ curracl->filename, 0UL,
14061+ 0UL, "", (unsigned long) cap, NIPQUAD(task->signal->curr_ip));
14062+ return 1;
14063+ }
14064+
14065+ if ((cap >= 0) && (cap < (sizeof(captab_log)/sizeof(captab_log[0]))) && cap_raised(task->cap_effective, cap))
14066+ gr_log_cap(GR_DONT_AUDIT, GR_CAP_ACL_MSG, task, captab_log[cap]);
14067+
14068+ return 0;
14069+}
14070+
14071+int
14072+gr_is_capable_nolog(const int cap)
14073+{
14074+ struct acl_subject_label *curracl;
14075+ __u32 cap_drop = 0, cap_mask = 0;
14076+
14077+ if (!gr_acl_is_enabled())
14078+ return 1;
14079+
14080+ curracl = current->acl;
14081+
14082+ cap_drop = curracl->cap_lower;
14083+ cap_mask = curracl->cap_mask;
14084+
14085+ while ((curracl = curracl->parent_subject)) {
14086+ cap_drop |= curracl->cap_lower & (cap_mask & ~curracl->cap_mask);
14087+ cap_mask |= curracl->cap_mask;
14088+ }
14089+
14090+ if (!cap_raised(cap_drop, cap))
14091+ return 1;
14092+
14093+ return 0;
14094+}
14095+
14096diff -urNp linux-2.6.17.11/grsecurity/gracl_fs.c linux-2.6.17.11/grsecurity/gracl_fs.c
14097--- linux-2.6.17.11/grsecurity/gracl_fs.c 1969-12-31 19:00:00.000000000 -0500
14098+++ linux-2.6.17.11/grsecurity/gracl_fs.c 2006-08-12 08:17:55.000000000 -0400
14099@@ -0,0 +1,423 @@
14100+#include <linux/kernel.h>
14101+#include <linux/sched.h>
14102+#include <linux/types.h>
14103+#include <linux/fs.h>
14104+#include <linux/file.h>
14105+#include <linux/stat.h>
14106+#include <linux/grsecurity.h>
14107+#include <linux/grinternal.h>
14108+#include <linux/gracl.h>
14109+
14110+__u32
14111+gr_acl_handle_hidden_file(const struct dentry * dentry,
14112+ const struct vfsmount * mnt)
14113+{
14114+ __u32 mode;
14115+
14116+ if (unlikely(!dentry->d_inode))
14117+ return GR_FIND;
14118+
14119+ mode =
14120+ gr_search_file(dentry, GR_FIND | GR_AUDIT_FIND | GR_SUPPRESS, mnt);
14121+
14122+ if (unlikely(mode & GR_FIND && mode & GR_AUDIT_FIND)) {
14123+ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt);
14124+ return mode;
14125+ } else if (unlikely(!(mode & GR_FIND) && !(mode & GR_SUPPRESS))) {
14126+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt);
14127+ return 0;
14128+ } else if (unlikely(!(mode & GR_FIND)))
14129+ return 0;
14130+
14131+ return GR_FIND;
14132+}
14133+
14134+__u32
14135+gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
14136+ const int fmode)
14137+{
14138+ __u32 reqmode = GR_FIND;
14139+ __u32 mode;
14140+
14141+ if (unlikely(!dentry->d_inode))
14142+ return reqmode;
14143+
14144+ if (unlikely(fmode & O_APPEND))
14145+ reqmode |= GR_APPEND;
14146+ else if (unlikely(fmode & FMODE_WRITE))
14147+ reqmode |= GR_WRITE;
14148+ if (likely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
14149+ reqmode |= GR_READ;
14150+
14151+ mode =
14152+ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
14153+ mnt);
14154+
14155+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
14156+ gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt,
14157+ reqmode & GR_READ ? " reading" : "",
14158+ reqmode & GR_WRITE ? " writing" : reqmode &
14159+ GR_APPEND ? " appending" : "");
14160+ return reqmode;
14161+ } else
14162+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
14163+ {
14164+ gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt,
14165+ reqmode & GR_READ ? " reading" : "",
14166+ reqmode & GR_WRITE ? " writing" : reqmode &
14167+ GR_APPEND ? " appending" : "");
14168+ return 0;
14169+ } else if (unlikely((mode & reqmode) != reqmode))
14170+ return 0;
14171+
14172+ return reqmode;
14173+}
14174+
14175+__u32
14176+gr_acl_handle_creat(const struct dentry * dentry,
14177+ const struct dentry * p_dentry,
14178+ const struct vfsmount * p_mnt, const int fmode,
14179+ const int imode)
14180+{
14181+ __u32 reqmode = GR_WRITE | GR_CREATE;
14182+ __u32 mode;
14183+
14184+ if (unlikely(fmode & O_APPEND))
14185+ reqmode |= GR_APPEND;
14186+ if (unlikely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
14187+ reqmode |= GR_READ;
14188+ if (unlikely((fmode & O_CREAT) && (imode & (S_ISUID | S_ISGID))))
14189+ reqmode |= GR_SETID;
14190+
14191+ mode =
14192+ gr_check_create(dentry, p_dentry, p_mnt,
14193+ reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
14194+
14195+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
14196+ gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt,
14197+ reqmode & GR_READ ? " reading" : "",
14198+ reqmode & GR_WRITE ? " writing" : reqmode &
14199+ GR_APPEND ? " appending" : "");
14200+ return reqmode;
14201+ } else
14202+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
14203+ {
14204+ gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt,
14205+ reqmode & GR_READ ? " reading" : "",
14206+ reqmode & GR_WRITE ? " writing" : reqmode &
14207+ GR_APPEND ? " appending" : "");
14208+ return 0;
14209+ } else if (unlikely((mode & reqmode) != reqmode))
14210+ return 0;
14211+
14212+ return reqmode;
14213+}
14214+
14215+__u32
14216+gr_acl_handle_access(const struct dentry * dentry, const struct vfsmount * mnt,
14217+ const int fmode)
14218+{
14219+ __u32 mode, reqmode = GR_FIND;
14220+
14221+ if ((fmode & S_IXOTH) && !S_ISDIR(dentry->d_inode->i_mode))
14222+ reqmode |= GR_EXEC;
14223+ if (fmode & S_IWOTH)
14224+ reqmode |= GR_WRITE;
14225+ if (fmode & S_IROTH)
14226+ reqmode |= GR_READ;
14227+
14228+ mode =
14229+ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
14230+ mnt);
14231+
14232+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
14233+ gr_log_fs_rbac_mode3(GR_DO_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt,
14234+ reqmode & GR_READ ? " reading" : "",
14235+ reqmode & GR_WRITE ? " writing" : "",
14236+ reqmode & GR_EXEC ? " executing" : "");
14237+ return reqmode;
14238+ } else
14239+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
14240+ {
14241+ gr_log_fs_rbac_mode3(GR_DONT_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt,
14242+ reqmode & GR_READ ? " reading" : "",
14243+ reqmode & GR_WRITE ? " writing" : "",
14244+ reqmode & GR_EXEC ? " executing" : "");
14245+ return 0;
14246+ } else if (unlikely((mode & reqmode) != reqmode))
14247+ return 0;
14248+
14249+ return reqmode;
14250+}
14251+
14252+static __u32 generic_fs_handler(const struct dentry *dentry, const struct vfsmount *mnt, __u32 reqmode, const char *fmt)
14253+{
14254+ __u32 mode;
14255+
14256+ mode = gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, mnt);
14257+
14258+ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) {
14259+ gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, dentry, mnt);
14260+ return mode;
14261+ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) {
14262+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, dentry, mnt);
14263+ return 0;
14264+ } else if (unlikely((mode & (reqmode)) != (reqmode)))
14265+ return 0;
14266+
14267+ return (reqmode);
14268+}
14269+
14270+__u32
14271+gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
14272+{
14273+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_RMDIR_ACL_MSG);
14274+}
14275+
14276+__u32
14277+gr_acl_handle_unlink(const struct dentry *dentry, const struct vfsmount *mnt)
14278+{
14279+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_UNLINK_ACL_MSG);
14280+}
14281+
14282+__u32
14283+gr_acl_handle_truncate(const struct dentry *dentry, const struct vfsmount *mnt)
14284+{
14285+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_TRUNCATE_ACL_MSG);
14286+}
14287+
14288+__u32
14289+gr_acl_handle_utime(const struct dentry *dentry, const struct vfsmount *mnt)
14290+{
14291+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_ATIME_ACL_MSG);
14292+}
14293+
14294+__u32
14295+gr_acl_handle_fchmod(const struct dentry *dentry, const struct vfsmount *mnt,
14296+ mode_t mode)
14297+{
14298+ if (unlikely(dentry->d_inode && S_ISSOCK(dentry->d_inode->i_mode)))
14299+ return 1;
14300+
14301+ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
14302+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
14303+ GR_FCHMOD_ACL_MSG);
14304+ } else {
14305+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_FCHMOD_ACL_MSG);
14306+ }
14307+}
14308+
14309+__u32
14310+gr_acl_handle_chmod(const struct dentry *dentry, const struct vfsmount *mnt,
14311+ mode_t mode)
14312+{
14313+ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
14314+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
14315+ GR_CHMOD_ACL_MSG);
14316+ } else {
14317+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHMOD_ACL_MSG);
14318+ }
14319+}
14320+
14321+__u32
14322+gr_acl_handle_chown(const struct dentry *dentry, const struct vfsmount *mnt)
14323+{
14324+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHOWN_ACL_MSG);
14325+}
14326+
14327+__u32
14328+gr_acl_handle_execve(const struct dentry *dentry, const struct vfsmount *mnt)
14329+{
14330+ return generic_fs_handler(dentry, mnt, GR_EXEC, GR_EXEC_ACL_MSG);
14331+}
14332+
14333+__u32
14334+gr_acl_handle_unix(const struct dentry *dentry, const struct vfsmount *mnt)
14335+{
14336+ return generic_fs_handler(dentry, mnt, GR_READ | GR_WRITE,
14337+ GR_UNIXCONNECT_ACL_MSG);
14338+}
14339+
14340+/* hardlinks require at minimum create permission,
14341+ any additional privilege required is based on the
14342+ privilege of the file being linked to
14343+*/
14344+__u32
14345+gr_acl_handle_link(const struct dentry * new_dentry,
14346+ const struct dentry * parent_dentry,
14347+ const struct vfsmount * parent_mnt,
14348+ const struct dentry * old_dentry,
14349+ const struct vfsmount * old_mnt, const char *to)
14350+{
14351+ __u32 mode;
14352+ __u32 needmode = GR_CREATE | GR_LINK;
14353+ __u32 needaudit = GR_AUDIT_CREATE | GR_AUDIT_LINK;
14354+
14355+ mode =
14356+ gr_check_link(new_dentry, parent_dentry, parent_mnt, old_dentry,
14357+ old_mnt);
14358+
14359+ if (unlikely(((mode & needmode) == needmode) && (mode & needaudit))) {
14360+ gr_log_fs_rbac_str(GR_DO_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to);
14361+ return mode;
14362+ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
14363+ gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to);
14364+ return 0;
14365+ } else if (unlikely((mode & needmode) != needmode))
14366+ return 0;
14367+
14368+ return 1;
14369+}
14370+
14371+__u32
14372+gr_acl_handle_symlink(const struct dentry * new_dentry,
14373+ const struct dentry * parent_dentry,
14374+ const struct vfsmount * parent_mnt, const char *from)
14375+{
14376+ __u32 needmode = GR_WRITE | GR_CREATE;
14377+ __u32 mode;
14378+
14379+ mode =
14380+ gr_check_create(new_dentry, parent_dentry, parent_mnt,
14381+ GR_CREATE | GR_AUDIT_CREATE |
14382+ GR_WRITE | GR_AUDIT_WRITE | GR_SUPPRESS);
14383+
14384+ if (unlikely(mode & GR_WRITE && mode & GR_AUDITS)) {
14385+ gr_log_fs_str_rbac(GR_DO_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt);
14386+ return mode;
14387+ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
14388+ gr_log_fs_str_rbac(GR_DONT_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt);
14389+ return 0;
14390+ } else if (unlikely((mode & needmode) != needmode))
14391+ return 0;
14392+
14393+ return (GR_WRITE | GR_CREATE);
14394+}
14395+
14396+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)
14397+{
14398+ __u32 mode;
14399+
14400+ mode = gr_check_create(new_dentry, parent_dentry, parent_mnt, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
14401+
14402+ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) {
14403+ gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, new_dentry, parent_mnt);
14404+ return mode;
14405+ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) {
14406+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, new_dentry, parent_mnt);
14407+ return 0;
14408+ } else if (unlikely((mode & (reqmode)) != (reqmode)))
14409+ return 0;
14410+
14411+ return (reqmode);
14412+}
14413+
14414+__u32
14415+gr_acl_handle_mknod(const struct dentry * new_dentry,
14416+ const struct dentry * parent_dentry,
14417+ const struct vfsmount * parent_mnt,
14418+ const int mode)
14419+{
14420+ __u32 reqmode = GR_WRITE | GR_CREATE;
14421+ if (unlikely(mode & (S_ISUID | S_ISGID)))
14422+ reqmode |= GR_SETID;
14423+
14424+ return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
14425+ reqmode, GR_MKNOD_ACL_MSG);
14426+}
14427+
14428+__u32
14429+gr_acl_handle_mkdir(const struct dentry *new_dentry,
14430+ const struct dentry *parent_dentry,
14431+ const struct vfsmount *parent_mnt)
14432+{
14433+ return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
14434+ GR_WRITE | GR_CREATE, GR_MKDIR_ACL_MSG);
14435+}
14436+
14437+#define RENAME_CHECK_SUCCESS(old, new) \
14438+ (((old & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)) && \
14439+ ((new & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)))
14440+
14441+int
14442+gr_acl_handle_rename(struct dentry *new_dentry,
14443+ struct dentry *parent_dentry,
14444+ const struct vfsmount *parent_mnt,
14445+ struct dentry *old_dentry,
14446+ struct inode *old_parent_inode,
14447+ struct vfsmount *old_mnt, const char *newname)
14448+{
14449+ __u32 comp1, comp2;
14450+ int error = 0;
14451+
14452+ if (unlikely(!gr_acl_is_enabled()))
14453+ return 0;
14454+
14455+ if (!new_dentry->d_inode) {
14456+ comp1 = gr_check_create(new_dentry, parent_dentry, parent_mnt,
14457+ GR_READ | GR_WRITE | GR_CREATE | GR_AUDIT_READ |
14458+ GR_AUDIT_WRITE | GR_AUDIT_CREATE | GR_SUPPRESS);
14459+ comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE |
14460+ GR_DELETE | GR_AUDIT_DELETE |
14461+ GR_AUDIT_READ | GR_AUDIT_WRITE |
14462+ GR_SUPPRESS, old_mnt);
14463+ } else {
14464+ comp1 = gr_search_file(new_dentry, GR_READ | GR_WRITE |
14465+ GR_CREATE | GR_DELETE |
14466+ GR_AUDIT_CREATE | GR_AUDIT_DELETE |
14467+ GR_AUDIT_READ | GR_AUDIT_WRITE |
14468+ GR_SUPPRESS, parent_mnt);
14469+ comp2 =
14470+ gr_search_file(old_dentry,
14471+ GR_READ | GR_WRITE | GR_AUDIT_READ |
14472+ GR_DELETE | GR_AUDIT_DELETE |
14473+ GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt);
14474+ }
14475+
14476+ if (RENAME_CHECK_SUCCESS(comp1, comp2) &&
14477+ ((comp1 & GR_AUDITS) || (comp2 & GR_AUDITS)))
14478+ gr_log_fs_rbac_str(GR_DO_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname);
14479+ else if (!RENAME_CHECK_SUCCESS(comp1, comp2) && !(comp1 & GR_SUPPRESS)
14480+ && !(comp2 & GR_SUPPRESS)) {
14481+ gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname);
14482+ error = -EACCES;
14483+ } else if (unlikely(!RENAME_CHECK_SUCCESS(comp1, comp2)))
14484+ error = -EACCES;
14485+
14486+ return error;
14487+}
14488+
14489+void
14490+gr_acl_handle_exit(void)
14491+{
14492+ u16 id;
14493+ char *rolename;
14494+ struct file *exec_file;
14495+
14496+ if (unlikely(current->acl_sp_role && gr_acl_is_enabled())) {
14497+ id = current->acl_role_id;
14498+ rolename = current->role->rolename;
14499+ gr_set_acls(1);
14500+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLEL_ACL_MSG, rolename, id);
14501+ }
14502+
14503+ write_lock(&grsec_exec_file_lock);
14504+ exec_file = current->exec_file;
14505+ current->exec_file = NULL;
14506+ write_unlock(&grsec_exec_file_lock);
14507+
14508+ if (exec_file)
14509+ fput(exec_file);
14510+}
14511+
14512+int
14513+gr_acl_handle_procpidmem(const struct task_struct *task)
14514+{
14515+ if (unlikely(!gr_acl_is_enabled()))
14516+ return 0;
14517+
14518+ if (task->acl->mode & GR_PROTPROCFD)
14519+ return -EACCES;
14520+
14521+ return 0;
14522+}
14523diff -urNp linux-2.6.17.11/grsecurity/gracl_ip.c linux-2.6.17.11/grsecurity/gracl_ip.c
14524--- linux-2.6.17.11/grsecurity/gracl_ip.c 1969-12-31 19:00:00.000000000 -0500
14525+++ linux-2.6.17.11/grsecurity/gracl_ip.c 2006-08-12 08:17:55.000000000 -0400
14526@@ -0,0 +1,313 @@
14527+#include <linux/kernel.h>
14528+#include <asm/uaccess.h>
14529+#include <asm/errno.h>
14530+#include <net/sock.h>
14531+#include <linux/file.h>
14532+#include <linux/fs.h>
14533+#include <linux/net.h>
14534+#include <linux/in.h>
14535+#include <linux/skbuff.h>
14536+#include <linux/ip.h>
14537+#include <linux/udp.h>
14538+#include <linux/smp_lock.h>
14539+#include <linux/types.h>
14540+#include <linux/sched.h>
14541+#include <linux/netdevice.h>
14542+#include <linux/inetdevice.h>
14543+#include <linux/gracl.h>
14544+#include <linux/grsecurity.h>
14545+#include <linux/grinternal.h>
14546+
14547+#define GR_BIND 0x01
14548+#define GR_CONNECT 0x02
14549+#define GR_INVERT 0x04
14550+
14551+static const char * gr_protocols[256] = {
14552+ "ip", "icmp", "igmp", "ggp", "ipencap", "st", "tcp", "cbt",
14553+ "egp", "igp", "bbn-rcc", "nvp", "pup", "argus", "emcon", "xnet",
14554+ "chaos", "udp", "mux", "dcn", "hmp", "prm", "xns-idp", "trunk-1",
14555+ "trunk-2", "leaf-1", "leaf-2", "rdp", "irtp", "iso-tp4", "netblt", "mfe-nsp",
14556+ "merit-inp", "sep", "3pc", "idpr", "xtp", "ddp", "idpr-cmtp", "tp++",
14557+ "il", "ipv6", "sdrp", "ipv6-route", "ipv6-frag", "idrp", "rsvp", "gre",
14558+ "mhrp", "bna", "ipv6-crypt", "ipv6-auth", "i-nlsp", "swipe", "narp", "mobile",
14559+ "tlsp", "skip", "ipv6-icmp", "ipv6-nonxt", "ipv6-opts", "unknown:61", "cftp", "unknown:63",
14560+ "sat-expak", "kryptolan", "rvd", "ippc", "unknown:68", "sat-mon", "visa", "ipcv",
14561+ "cpnx", "cphb", "wsn", "pvp", "br-sat-mon", "sun-nd", "wb-mon", "wb-expak",
14562+ "iso-ip", "vmtp", "secure-vmtp", "vines", "ttp", "nfsnet-igp", "dgp", "tcf",
14563+ "eigrp", "ospf", "sprite-rpc", "larp", "mtp", "ax.25", "ipip", "micp",
14564+ "scc-sp", "etherip", "encap", "unknown:99", "gmtp", "ifmp", "pnni", "pim",
14565+ "aris", "scps", "qnx", "a/n", "ipcomp", "snp", "compaq-peer", "ipx-in-ip",
14566+ "vrrp", "pgm", "unknown:114", "l2tp", "ddx", "iatp", "stp", "srp",
14567+ "uti", "smp", "sm", "ptp", "isis", "fire", "crtp", "crdup",
14568+ "sscopmce", "iplt", "sps", "pipe", "sctp", "fc", "unkown:134", "unknown:135",
14569+ "unknown:136", "unknown:137", "unknown:138", "unknown:139", "unknown:140", "unknown:141", "unknown:142", "unknown:143",
14570+ "unknown:144", "unknown:145", "unknown:146", "unknown:147", "unknown:148", "unknown:149", "unknown:150", "unknown:151",
14571+ "unknown:152", "unknown:153", "unknown:154", "unknown:155", "unknown:156", "unknown:157", "unknown:158", "unknown:159",
14572+ "unknown:160", "unknown:161", "unknown:162", "unknown:163", "unknown:164", "unknown:165", "unknown:166", "unknown:167",
14573+ "unknown:168", "unknown:169", "unknown:170", "unknown:171", "unknown:172", "unknown:173", "unknown:174", "unknown:175",
14574+ "unknown:176", "unknown:177", "unknown:178", "unknown:179", "unknown:180", "unknown:181", "unknown:182", "unknown:183",
14575+ "unknown:184", "unknown:185", "unknown:186", "unknown:187", "unknown:188", "unknown:189", "unknown:190", "unknown:191",
14576+ "unknown:192", "unknown:193", "unknown:194", "unknown:195", "unknown:196", "unknown:197", "unknown:198", "unknown:199",
14577+ "unknown:200", "unknown:201", "unknown:202", "unknown:203", "unknown:204", "unknown:205", "unknown:206", "unknown:207",
14578+ "unknown:208", "unknown:209", "unknown:210", "unknown:211", "unknown:212", "unknown:213", "unknown:214", "unknown:215",
14579+ "unknown:216", "unknown:217", "unknown:218", "unknown:219", "unknown:220", "unknown:221", "unknown:222", "unknown:223",
14580+ "unknown:224", "unknown:225", "unknown:226", "unknown:227", "unknown:228", "unknown:229", "unknown:230", "unknown:231",
14581+ "unknown:232", "unknown:233", "unknown:234", "unknown:235", "unknown:236", "unknown:237", "unknown:238", "unknown:239",
14582+ "unknown:240", "unknown:241", "unknown:242", "unknown:243", "unknown:244", "unknown:245", "unknown:246", "unknown:247",
14583+ "unknown:248", "unknown:249", "unknown:250", "unknown:251", "unknown:252", "unknown:253", "unknown:254", "unknown:255",
14584+ };
14585+
14586+static const char * gr_socktypes[11] = {
14587+ "unknown:0", "stream", "dgram", "raw", "rdm", "seqpacket", "unknown:6",
14588+ "unknown:7", "unknown:8", "unknown:9", "packet"
14589+ };
14590+
14591+const char *
14592+gr_proto_to_name(unsigned char proto)
14593+{
14594+ return gr_protocols[proto];
14595+}
14596+
14597+const char *
14598+gr_socktype_to_name(unsigned char type)
14599+{
14600+ return gr_socktypes[type];
14601+}
14602+
14603+int
14604+gr_search_socket(const int domain, const int type, const int protocol)
14605+{
14606+ struct acl_subject_label *curr;
14607+
14608+ if (unlikely(!gr_acl_is_enabled()))
14609+ goto exit;
14610+
14611+ if ((domain < 0) || (type < 0) || (protocol < 0) || (domain != PF_INET)
14612+ || (domain >= NPROTO) || (type >= SOCK_MAX) || (protocol > 255))
14613+ goto exit; // let the kernel handle it
14614+
14615+ curr = current->acl;
14616+
14617+ if (!curr->ips)
14618+ goto exit;
14619+
14620+ if ((curr->ip_type & (1 << type)) &&
14621+ (curr->ip_proto[protocol / 32] & (1 << (protocol % 32))))
14622+ goto exit;
14623+
14624+ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
14625+ /* we don't place acls on raw sockets , and sometimes
14626+ dgram/ip sockets are opened for ioctl and not
14627+ bind/connect, so we'll fake a bind learn log */
14628+ if (type == SOCK_RAW || type == SOCK_PACKET) {
14629+ __u32 fakeip = 0;
14630+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
14631+ current->role->roletype, current->uid,
14632+ current->gid, current->exec_file ?
14633+ gr_to_filename(current->exec_file->f_dentry,
14634+ current->exec_file->f_vfsmnt) :
14635+ curr->filename, curr->filename,
14636+ NIPQUAD(fakeip), 0, type,
14637+ protocol, GR_CONNECT,
14638+NIPQUAD(current->signal->curr_ip));
14639+ } else if ((type == SOCK_DGRAM) && (protocol == IPPROTO_IP)) {
14640+ __u32 fakeip = 0;
14641+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
14642+ current->role->roletype, current->uid,
14643+ current->gid, current->exec_file ?
14644+ gr_to_filename(current->exec_file->f_dentry,
14645+ current->exec_file->f_vfsmnt) :
14646+ curr->filename, curr->filename,
14647+ NIPQUAD(fakeip), 0, type,
14648+ protocol, GR_BIND, NIPQUAD(current->signal->curr_ip));
14649+ }
14650+ /* we'll log when they use connect or bind */
14651+ goto exit;
14652+ }
14653+
14654+ gr_log_str3(GR_DONT_AUDIT, GR_SOCK_MSG, "inet",
14655+ gr_socktype_to_name(type), gr_proto_to_name(protocol));
14656+
14657+ return 0;
14658+ exit:
14659+ return 1;
14660+}
14661+
14662+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)
14663+{
14664+ if ((ip->mode & mode) &&
14665+ (ip_port >= ip->low) &&
14666+ (ip_port <= ip->high) &&
14667+ ((ntohl(ip_addr) & our_netmask) ==
14668+ (ntohl(our_addr) & our_netmask))
14669+ && (ip->proto[protocol / 32] & (1 << (protocol % 32)))
14670+ && (ip->type & (1 << type))) {
14671+ if (ip->mode & GR_INVERT)
14672+ return 2; // specifically denied
14673+ else
14674+ return 1; // allowed
14675+ }
14676+
14677+ return 0; // not specifically allowed, may continue parsing
14678+}
14679+
14680+static int
14681+gr_search_connectbind(const int mode, const struct sock *sk,
14682+ const struct sockaddr_in *addr, const int type)
14683+{
14684+ char iface[IFNAMSIZ] = {0};
14685+ struct acl_subject_label *curr;
14686+ struct acl_ip_label *ip;
14687+ struct net_device *dev;
14688+ struct in_device *idev;
14689+ unsigned long i;
14690+ int ret;
14691+ __u32 ip_addr = 0;
14692+ __u32 our_addr;
14693+ __u32 our_netmask;
14694+ char *p;
14695+ __u16 ip_port = 0;
14696+
14697+ if (unlikely(!gr_acl_is_enabled() || sk->sk_family != PF_INET))
14698+ return 1;
14699+
14700+ curr = current->acl;
14701+
14702+ if (!curr->ips)
14703+ return 1;
14704+
14705+ ip_addr = addr->sin_addr.s_addr;
14706+ ip_port = ntohs(addr->sin_port);
14707+
14708+ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
14709+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
14710+ current->role->roletype, current->uid,
14711+ current->gid, current->exec_file ?
14712+ gr_to_filename(current->exec_file->f_dentry,
14713+ current->exec_file->f_vfsmnt) :
14714+ curr->filename, curr->filename,
14715+ NIPQUAD(ip_addr), ip_port, type,
14716+ sk->sk_protocol, mode, NIPQUAD(current->signal->curr_ip));
14717+ return 1;
14718+ }
14719+
14720+ for (i = 0; i < curr->ip_num; i++) {
14721+ ip = *(curr->ips + i);
14722+ if (ip->iface != NULL) {
14723+ strncpy(iface, ip->iface, IFNAMSIZ - 1);
14724+ p = strchr(iface, ':');
14725+ if (p != NULL)
14726+ *p = '\0';
14727+ dev = dev_get_by_name(iface);
14728+ if (dev == NULL)
14729+ continue;
14730+ idev = in_dev_get(dev);
14731+ if (idev == NULL) {
14732+ dev_put(dev);
14733+ continue;
14734+ }
14735+ rcu_read_lock();
14736+ for_ifa(idev) {
14737+ if (!strcmp(ip->iface, ifa->ifa_label)) {
14738+ our_addr = ifa->ifa_address;
14739+ our_netmask = 0xffffffff;
14740+ ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask);
14741+ if (ret == 1) {
14742+ rcu_read_unlock();
14743+ in_dev_put(idev);
14744+ dev_put(dev);
14745+ return 1;
14746+ } else if (ret == 2) {
14747+ rcu_read_unlock();
14748+ in_dev_put(idev);
14749+ dev_put(dev);
14750+ goto denied;
14751+ }
14752+ }
14753+ } endfor_ifa(idev);
14754+ rcu_read_unlock();
14755+ in_dev_put(idev);
14756+ dev_put(dev);
14757+ } else {
14758+ our_addr = ip->addr;
14759+ our_netmask = ip->netmask;
14760+ ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask);
14761+ if (ret == 1)
14762+ return 1;
14763+ else if (ret == 2)
14764+ goto denied;
14765+ }
14766+ }
14767+
14768+denied:
14769+ if (mode == GR_BIND)
14770+ 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));
14771+ else if (mode == GR_CONNECT)
14772+ 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));
14773+
14774+ return 0;
14775+}
14776+
14777+int
14778+gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
14779+{
14780+ return gr_search_connectbind(GR_CONNECT, sock->sk, addr, sock->type);
14781+}
14782+
14783+int
14784+gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
14785+{
14786+ return gr_search_connectbind(GR_BIND, sock->sk, addr, sock->type);
14787+}
14788+
14789+int gr_search_listen(const struct socket *sock)
14790+{
14791+ struct sock *sk = sock->sk;
14792+ struct sockaddr_in addr;
14793+
14794+ addr.sin_addr.s_addr = inet_sk(sk)->saddr;
14795+ addr.sin_port = inet_sk(sk)->sport;
14796+
14797+ return gr_search_connectbind(GR_BIND, sock->sk, &addr, sock->type);
14798+}
14799+
14800+int gr_search_accept(const struct socket *sock)
14801+{
14802+ struct sock *sk = sock->sk;
14803+ struct sockaddr_in addr;
14804+
14805+ addr.sin_addr.s_addr = inet_sk(sk)->saddr;
14806+ addr.sin_port = inet_sk(sk)->sport;
14807+
14808+ return gr_search_connectbind(GR_BIND, sock->sk, &addr, sock->type);
14809+}
14810+
14811+int
14812+gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
14813+{
14814+ if (addr)
14815+ return gr_search_connectbind(GR_CONNECT, sk, addr, SOCK_DGRAM);
14816+ else {
14817+ struct sockaddr_in sin;
14818+ const struct inet_sock *inet = inet_sk(sk);
14819+
14820+ sin.sin_addr.s_addr = inet->daddr;
14821+ sin.sin_port = inet->dport;
14822+
14823+ return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM);
14824+ }
14825+}
14826+
14827+int
14828+gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
14829+{
14830+ struct sockaddr_in sin;
14831+
14832+ if (unlikely(skb->len < sizeof (struct udphdr)))
14833+ return 1; // skip this packet
14834+
14835+ sin.sin_addr.s_addr = skb->nh.iph->saddr;
14836+ sin.sin_port = skb->h.uh->source;
14837+
14838+ return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM);
14839+}
14840diff -urNp linux-2.6.17.11/grsecurity/gracl_learn.c linux-2.6.17.11/grsecurity/gracl_learn.c
14841--- linux-2.6.17.11/grsecurity/gracl_learn.c 1969-12-31 19:00:00.000000000 -0500
14842+++ linux-2.6.17.11/grsecurity/gracl_learn.c 2006-08-12 08:17:55.000000000 -0400
14843@@ -0,0 +1,204 @@
14844+#include <linux/kernel.h>
14845+#include <linux/mm.h>
14846+#include <linux/sched.h>
14847+#include <linux/poll.h>
14848+#include <linux/smp_lock.h>
14849+#include <linux/string.h>
14850+#include <linux/file.h>
14851+#include <linux/types.h>
14852+#include <linux/vmalloc.h>
14853+#include <linux/grinternal.h>
14854+
14855+extern ssize_t write_grsec_handler(struct file * file, const char __user * buf,
14856+ size_t count, loff_t *ppos);
14857+extern int gr_acl_is_enabled(void);
14858+
14859+static DECLARE_WAIT_QUEUE_HEAD(learn_wait);
14860+static int gr_learn_attached;
14861+
14862+/* use a 512k buffer */
14863+#define LEARN_BUFFER_SIZE (512 * 1024)
14864+
14865+static spinlock_t gr_learn_lock = SPIN_LOCK_UNLOCKED;
14866+static DECLARE_MUTEX(gr_learn_user_sem);
14867+
14868+/* we need to maintain two buffers, so that the kernel context of grlearn
14869+ uses a semaphore around the userspace copying, and the other kernel contexts
14870+ use a spinlock when copying into the buffer, since they cannot sleep
14871+*/
14872+static char *learn_buffer;
14873+static char *learn_buffer_user;
14874+static int learn_buffer_len;
14875+static int learn_buffer_user_len;
14876+
14877+static ssize_t
14878+read_learn(struct file *file, char __user * buf, size_t count, loff_t * ppos)
14879+{
14880+ DECLARE_WAITQUEUE(wait, current);
14881+ ssize_t retval = 0;
14882+
14883+ add_wait_queue(&learn_wait, &wait);
14884+ set_current_state(TASK_INTERRUPTIBLE);
14885+ do {
14886+ down(&gr_learn_user_sem);
14887+ spin_lock(&gr_learn_lock);
14888+ if (learn_buffer_len)
14889+ break;
14890+ spin_unlock(&gr_learn_lock);
14891+ up(&gr_learn_user_sem);
14892+ if (file->f_flags & O_NONBLOCK) {
14893+ retval = -EAGAIN;
14894+ goto out;
14895+ }
14896+ if (signal_pending(current)) {
14897+ retval = -ERESTARTSYS;
14898+ goto out;
14899+ }
14900+
14901+ schedule();
14902+ } while (1);
14903+
14904+ memcpy(learn_buffer_user, learn_buffer, learn_buffer_len);
14905+ learn_buffer_user_len = learn_buffer_len;
14906+ retval = learn_buffer_len;
14907+ learn_buffer_len = 0;
14908+
14909+ spin_unlock(&gr_learn_lock);
14910+
14911+ if (copy_to_user(buf, learn_buffer_user, learn_buffer_user_len))
14912+ retval = -EFAULT;
14913+
14914+ up(&gr_learn_user_sem);
14915+out:
14916+ set_current_state(TASK_RUNNING);
14917+ remove_wait_queue(&learn_wait, &wait);
14918+ return retval;
14919+}
14920+
14921+static unsigned int
14922+poll_learn(struct file * file, poll_table * wait)
14923+{
14924+ poll_wait(file, &learn_wait, wait);
14925+
14926+ if (learn_buffer_len)
14927+ return (POLLIN | POLLRDNORM);
14928+
14929+ return 0;
14930+}
14931+
14932+void
14933+gr_clear_learn_entries(void)
14934+{
14935+ char *tmp;
14936+
14937+ down(&gr_learn_user_sem);
14938+ if (learn_buffer != NULL) {
14939+ spin_lock(&gr_learn_lock);
14940+ tmp = learn_buffer;
14941+ learn_buffer = NULL;
14942+ spin_unlock(&gr_learn_lock);
14943+ vfree(learn_buffer);
14944+ }
14945+ if (learn_buffer_user != NULL) {
14946+ vfree(learn_buffer_user);
14947+ learn_buffer_user = NULL;
14948+ }
14949+ learn_buffer_len = 0;
14950+ up(&gr_learn_user_sem);
14951+
14952+ return;
14953+}
14954+
14955+void
14956+gr_add_learn_entry(const char *fmt, ...)
14957+{
14958+ va_list args;
14959+ unsigned int len;
14960+
14961+ if (!gr_learn_attached)
14962+ return;
14963+
14964+ spin_lock(&gr_learn_lock);
14965+
14966+ /* leave a gap at the end so we know when it's "full" but don't have to
14967+ compute the exact length of the string we're trying to append
14968+ */
14969+ if (learn_buffer_len > LEARN_BUFFER_SIZE - 16384) {
14970+ spin_unlock(&gr_learn_lock);
14971+ wake_up_interruptible(&learn_wait);
14972+ return;
14973+ }
14974+ if (learn_buffer == NULL) {
14975+ spin_unlock(&gr_learn_lock);
14976+ return;
14977+ }
14978+
14979+ va_start(args, fmt);
14980+ len = vsnprintf(learn_buffer + learn_buffer_len, LEARN_BUFFER_SIZE - learn_buffer_len, fmt, args);
14981+ va_end(args);
14982+
14983+ learn_buffer_len += len + 1;
14984+
14985+ spin_unlock(&gr_learn_lock);
14986+ wake_up_interruptible(&learn_wait);
14987+
14988+ return;
14989+}
14990+
14991+static int
14992+open_learn(struct inode *inode, struct file *file)
14993+{
14994+ if (file->f_mode & FMODE_READ && gr_learn_attached)
14995+ return -EBUSY;
14996+ if (file->f_mode & FMODE_READ) {
14997+ down(&gr_learn_user_sem);
14998+ if (learn_buffer == NULL)
14999+ learn_buffer = vmalloc(LEARN_BUFFER_SIZE);
15000+ if (learn_buffer_user == NULL)
15001+ learn_buffer_user = vmalloc(LEARN_BUFFER_SIZE);
15002+ if (learn_buffer == NULL)
15003+ return -ENOMEM;
15004+ if (learn_buffer_user == NULL)
15005+ return -ENOMEM;
15006+ learn_buffer_len = 0;
15007+ learn_buffer_user_len = 0;
15008+ gr_learn_attached = 1;
15009+ up(&gr_learn_user_sem);
15010+ }
15011+ return 0;
15012+}
15013+
15014+static int
15015+close_learn(struct inode *inode, struct file *file)
15016+{
15017+ char *tmp;
15018+
15019+ if (file->f_mode & FMODE_READ) {
15020+ down(&gr_learn_user_sem);
15021+ if (learn_buffer != NULL) {
15022+ spin_lock(&gr_learn_lock);
15023+ tmp = learn_buffer;
15024+ learn_buffer = NULL;
15025+ spin_unlock(&gr_learn_lock);
15026+ vfree(tmp);
15027+ }
15028+ if (learn_buffer_user != NULL) {
15029+ vfree(learn_buffer_user);
15030+ learn_buffer_user = NULL;
15031+ }
15032+ learn_buffer_len = 0;
15033+ learn_buffer_user_len = 0;
15034+ gr_learn_attached = 0;
15035+ up(&gr_learn_user_sem);
15036+ }
15037+
15038+ return 0;
15039+}
15040+
15041+struct file_operations grsec_fops = {
15042+ .read = read_learn,
15043+ .write = write_grsec_handler,
15044+ .open = open_learn,
15045+ .release = close_learn,
15046+ .poll = poll_learn,
15047+};
15048diff -urNp linux-2.6.17.11/grsecurity/gracl_res.c linux-2.6.17.11/grsecurity/gracl_res.c
15049--- linux-2.6.17.11/grsecurity/gracl_res.c 1969-12-31 19:00:00.000000000 -0500
15050+++ linux-2.6.17.11/grsecurity/gracl_res.c 2006-08-12 08:17:55.000000000 -0400
15051@@ -0,0 +1,45 @@
15052+#include <linux/kernel.h>
15053+#include <linux/sched.h>
15054+#include <linux/gracl.h>
15055+#include <linux/grinternal.h>
15056+
15057+static const char *restab_log[] = {
15058+ [RLIMIT_CPU] = "RLIMIT_CPU",
15059+ [RLIMIT_FSIZE] = "RLIMIT_FSIZE",
15060+ [RLIMIT_DATA] = "RLIMIT_DATA",
15061+ [RLIMIT_STACK] = "RLIMIT_STACK",
15062+ [RLIMIT_CORE] = "RLIMIT_CORE",
15063+ [RLIMIT_RSS] = "RLIMIT_RSS",
15064+ [RLIMIT_NPROC] = "RLIMIT_NPROC",
15065+ [RLIMIT_NOFILE] = "RLIMIT_NOFILE",
15066+ [RLIMIT_MEMLOCK] = "RLIMIT_MEMLOCK",
15067+ [RLIMIT_AS] = "RLIMIT_AS",
15068+ [RLIMIT_LOCKS] = "RLIMIT_LOCKS",
15069+ [RLIMIT_LOCKS + 1] = "RLIMIT_CRASH"
15070+};
15071+
15072+void
15073+gr_log_resource(const struct task_struct *task,
15074+ const int res, const unsigned long wanted, const int gt)
15075+{
15076+ if (res == RLIMIT_NPROC &&
15077+ (cap_raised(task->cap_effective, CAP_SYS_ADMIN) ||
15078+ cap_raised(task->cap_effective, CAP_SYS_RESOURCE)))
15079+ return;
15080+ else if (res == RLIMIT_MEMLOCK &&
15081+ cap_raised(task->cap_effective, CAP_IPC_LOCK))
15082+ return;
15083+
15084+ if (!gr_acl_is_enabled() && !grsec_resource_logging)
15085+ return;
15086+
15087+ preempt_disable();
15088+
15089+ if (unlikely(((gt && wanted > task->signal->rlim[res].rlim_cur) ||
15090+ (!gt && wanted >= task->signal->rlim[res].rlim_cur)) &&
15091+ task->signal->rlim[res].rlim_cur != RLIM_INFINITY))
15092+ gr_log_res_ulong2_str(GR_DONT_AUDIT, GR_RESOURCE_MSG, task, wanted, restab_log[res], task->signal->rlim[res].rlim_cur);
15093+ preempt_enable_no_resched();
15094+
15095+ return;
15096+}
15097diff -urNp linux-2.6.17.11/grsecurity/gracl_segv.c linux-2.6.17.11/grsecurity/gracl_segv.c
15098--- linux-2.6.17.11/grsecurity/gracl_segv.c 1969-12-31 19:00:00.000000000 -0500
15099+++ linux-2.6.17.11/grsecurity/gracl_segv.c 2006-08-12 08:17:55.000000000 -0400
15100@@ -0,0 +1,295 @@
15101+#include <linux/kernel.h>
15102+#include <linux/mm.h>
15103+#include <asm/uaccess.h>
15104+#include <asm/errno.h>
15105+#include <asm/mman.h>
15106+#include <net/sock.h>
15107+#include <linux/file.h>
15108+#include <linux/fs.h>
15109+#include <linux/net.h>
15110+#include <linux/in.h>
15111+#include <linux/smp_lock.h>
15112+#include <linux/slab.h>
15113+#include <linux/types.h>
15114+#include <linux/sched.h>
15115+#include <linux/timer.h>
15116+#include <linux/gracl.h>
15117+#include <linux/grsecurity.h>
15118+#include <linux/grinternal.h>
15119+
15120+static struct crash_uid *uid_set;
15121+static unsigned short uid_used;
15122+static spinlock_t gr_uid_lock = SPIN_LOCK_UNLOCKED;
15123+extern rwlock_t gr_inode_lock;
15124+extern struct acl_subject_label *
15125+ lookup_acl_subj_label(const ino_t inode, const dev_t dev,
15126+ struct acl_role_label *role);
15127+extern int specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t);
15128+
15129+int
15130+gr_init_uidset(void)
15131+{
15132+ uid_set =
15133+ kmalloc(GR_UIDTABLE_MAX * sizeof (struct crash_uid), GFP_KERNEL);
15134+ uid_used = 0;
15135+
15136+ return uid_set ? 1 : 0;
15137+}
15138+
15139+void
15140+gr_free_uidset(void)
15141+{
15142+ if (uid_set)
15143+ kfree(uid_set);
15144+
15145+ return;
15146+}
15147+
15148+int
15149+gr_find_uid(const uid_t uid)
15150+{
15151+ struct crash_uid *tmp = uid_set;
15152+ uid_t buid;
15153+ int low = 0, high = uid_used - 1, mid;
15154+
15155+ while (high >= low) {
15156+ mid = (low + high) >> 1;
15157+ buid = tmp[mid].uid;
15158+ if (buid == uid)
15159+ return mid;
15160+ if (buid > uid)
15161+ high = mid - 1;
15162+ if (buid < uid)
15163+ low = mid + 1;
15164+ }
15165+
15166+ return -1;
15167+}
15168+
15169+static __inline__ void
15170+gr_insertsort(void)
15171+{
15172+ unsigned short i, j;
15173+ struct crash_uid index;
15174+
15175+ for (i = 1; i < uid_used; i++) {
15176+ index = uid_set[i];
15177+ j = i;
15178+ while ((j > 0) && uid_set[j - 1].uid > index.uid) {
15179+ uid_set[j] = uid_set[j - 1];
15180+ j--;
15181+ }
15182+ uid_set[j] = index;
15183+ }
15184+
15185+ return;
15186+}
15187+
15188+static __inline__ void
15189+gr_insert_uid(const uid_t uid, const unsigned long expires)
15190+{
15191+ int loc;
15192+
15193+ if (uid_used == GR_UIDTABLE_MAX)
15194+ return;
15195+
15196+ loc = gr_find_uid(uid);
15197+
15198+ if (loc >= 0) {
15199+ uid_set[loc].expires = expires;
15200+ return;
15201+ }
15202+
15203+ uid_set[uid_used].uid = uid;
15204+ uid_set[uid_used].expires = expires;
15205+ uid_used++;
15206+
15207+ gr_insertsort();
15208+
15209+ return;
15210+}
15211+
15212+void
15213+gr_remove_uid(const unsigned short loc)
15214+{
15215+ unsigned short i;
15216+
15217+ for (i = loc + 1; i < uid_used; i++)
15218+ uid_set[i - 1] = uid_set[i];
15219+
15220+ uid_used--;
15221+
15222+ return;
15223+}
15224+
15225+int
15226+gr_check_crash_uid(const uid_t uid)
15227+{
15228+ int loc;
15229+ int ret = 0;
15230+
15231+ if (unlikely(!gr_acl_is_enabled()))
15232+ return 0;
15233+
15234+ spin_lock(&gr_uid_lock);
15235+ loc = gr_find_uid(uid);
15236+
15237+ if (loc < 0)
15238+ goto out_unlock;
15239+
15240+ if (time_before_eq(uid_set[loc].expires, get_seconds()))
15241+ gr_remove_uid(loc);
15242+ else
15243+ ret = 1;
15244+
15245+out_unlock:
15246+ spin_unlock(&gr_uid_lock);
15247+ return ret;
15248+}
15249+
15250+static __inline__ int
15251+proc_is_setxid(const struct task_struct *task)
15252+{
15253+ if (task->uid != task->euid || task->uid != task->suid ||
15254+ task->uid != task->fsuid)
15255+ return 1;
15256+ if (task->gid != task->egid || task->gid != task->sgid ||
15257+ task->gid != task->fsgid)
15258+ return 1;
15259+
15260+ return 0;
15261+}
15262+static __inline__ int
15263+gr_fake_force_sig(int sig, struct task_struct *t)
15264+{
15265+ unsigned long int flags;
15266+ int ret;
15267+
15268+ spin_lock_irqsave(&t->sighand->siglock, flags);
15269+ if (sigismember(&t->blocked, sig) || t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) {
15270+ t->sighand->action[sig-1].sa.sa_handler = SIG_DFL;
15271+ sigdelset(&t->blocked, sig);
15272+ recalc_sigpending_tsk(t);
15273+ }
15274+ ret = specific_send_sig_info(sig, (void*)1L, t);
15275+ spin_unlock_irqrestore(&t->sighand->siglock, flags);
15276+
15277+ return ret;
15278+}
15279+
15280+void
15281+gr_handle_crash(struct task_struct *task, const int sig)
15282+{
15283+ struct acl_subject_label *curr;
15284+ struct acl_subject_label *curr2;
15285+ struct task_struct *tsk, *tsk2;
15286+
15287+ if (sig != SIGSEGV && sig != SIGKILL && sig != SIGBUS && sig != SIGILL)
15288+ return;
15289+
15290+ if (unlikely(!gr_acl_is_enabled()))
15291+ return;
15292+
15293+ curr = task->acl;
15294+
15295+ if (!(curr->resmask & (1 << GR_CRASH_RES)))
15296+ return;
15297+
15298+ if (time_before_eq(curr->expires, get_seconds())) {
15299+ curr->expires = 0;
15300+ curr->crashes = 0;
15301+ }
15302+
15303+ curr->crashes++;
15304+
15305+ if (!curr->expires)
15306+ curr->expires = get_seconds() + curr->res[GR_CRASH_RES].rlim_max;
15307+
15308+ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
15309+ time_after(curr->expires, get_seconds())) {
15310+ if (task->uid && proc_is_setxid(task)) {
15311+ gr_log_crash1(GR_DONT_AUDIT, GR_SEGVSTART_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
15312+ spin_lock(&gr_uid_lock);
15313+ gr_insert_uid(task->uid, curr->expires);
15314+ spin_unlock(&gr_uid_lock);
15315+ curr->expires = 0;
15316+ curr->crashes = 0;
15317+ read_lock(&tasklist_lock);
15318+ do_each_thread(tsk2, tsk) {
15319+ if (tsk != task && tsk->uid == task->uid)
15320+ gr_fake_force_sig(SIGKILL, tsk);
15321+ } while_each_thread(tsk2, tsk);
15322+ read_unlock(&tasklist_lock);
15323+ } else {
15324+ gr_log_crash2(GR_DONT_AUDIT, GR_SEGVNOSUID_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
15325+ read_lock(&tasklist_lock);
15326+ do_each_thread(tsk2, tsk) {
15327+ if (likely(tsk != task)) {
15328+ curr2 = tsk->acl;
15329+
15330+ if (curr2->device == curr->device &&
15331+ curr2->inode == curr->inode)
15332+ gr_fake_force_sig(SIGKILL, tsk);
15333+ }
15334+ } while_each_thread(tsk2, tsk);
15335+ read_unlock(&tasklist_lock);
15336+ }
15337+ }
15338+
15339+ return;
15340+}
15341+
15342+int
15343+gr_check_crash_exec(const struct file *filp)
15344+{
15345+ struct acl_subject_label *curr;
15346+
15347+ if (unlikely(!gr_acl_is_enabled()))
15348+ return 0;
15349+
15350+ read_lock(&gr_inode_lock);
15351+ curr = lookup_acl_subj_label(filp->f_dentry->d_inode->i_ino,
15352+ filp->f_dentry->d_inode->i_sb->s_dev,
15353+ current->role);
15354+ read_unlock(&gr_inode_lock);
15355+
15356+ if (!curr || !(curr->resmask & (1 << GR_CRASH_RES)) ||
15357+ (!curr->crashes && !curr->expires))
15358+ return 0;
15359+
15360+ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
15361+ time_after(curr->expires, get_seconds()))
15362+ return 1;
15363+ else if (time_before_eq(curr->expires, get_seconds())) {
15364+ curr->crashes = 0;
15365+ curr->expires = 0;
15366+ }
15367+
15368+ return 0;
15369+}
15370+
15371+void
15372+gr_handle_alertkill(struct task_struct *task)
15373+{
15374+ struct acl_subject_label *curracl;
15375+ __u32 curr_ip;
15376+ struct task_struct *p, *p2;
15377+
15378+ if (unlikely(!gr_acl_is_enabled()))
15379+ return;
15380+
15381+ curracl = task->acl;
15382+ curr_ip = task->signal->curr_ip;
15383+
15384+ if ((curracl->mode & GR_KILLIPPROC) && curr_ip) {
15385+ read_lock(&tasklist_lock);
15386+ do_each_thread(p2, p) {
15387+ if (p->signal->curr_ip == curr_ip)
15388+ gr_fake_force_sig(SIGKILL, p);
15389+ } while_each_thread(p2, p);
15390+ read_unlock(&tasklist_lock);
15391+ } else if (curracl->mode & GR_KILLPROC)
15392+ gr_fake_force_sig(SIGKILL, task);
15393+
15394+ return;
15395+}
15396diff -urNp linux-2.6.17.11/grsecurity/gracl_shm.c linux-2.6.17.11/grsecurity/gracl_shm.c
15397--- linux-2.6.17.11/grsecurity/gracl_shm.c 1969-12-31 19:00:00.000000000 -0500
15398+++ linux-2.6.17.11/grsecurity/gracl_shm.c 2006-08-12 08:17:55.000000000 -0400
15399@@ -0,0 +1,33 @@
15400+#include <linux/kernel.h>
15401+#include <linux/mm.h>
15402+#include <linux/sched.h>
15403+#include <linux/file.h>
15404+#include <linux/ipc.h>
15405+#include <linux/gracl.h>
15406+#include <linux/grsecurity.h>
15407+#include <linux/grinternal.h>
15408+
15409+int
15410+gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
15411+ const time_t shm_createtime, const uid_t cuid, const int shmid)
15412+{
15413+ struct task_struct *task;
15414+
15415+ if (!gr_acl_is_enabled())
15416+ return 1;
15417+
15418+ task = find_task_by_pid(shm_cprid);
15419+
15420+ if (unlikely(!task))
15421+ task = find_task_by_pid(shm_lapid);
15422+
15423+ if (unlikely(task && (time_before((unsigned long)task->start_time.tv_sec, (unsigned long)shm_createtime) ||
15424+ (task->pid == shm_lapid)) &&
15425+ (task->acl->mode & GR_PROTSHM) &&
15426+ (task->acl != current->acl))) {
15427+ gr_log_int3(GR_DONT_AUDIT, GR_SHMAT_ACL_MSG, cuid, shm_cprid, shmid);
15428+ return 0;
15429+ }
15430+
15431+ return 1;
15432+}
15433diff -urNp linux-2.6.17.11/grsecurity/grsec_chdir.c linux-2.6.17.11/grsecurity/grsec_chdir.c
15434--- linux-2.6.17.11/grsecurity/grsec_chdir.c 1969-12-31 19:00:00.000000000 -0500
15435+++ linux-2.6.17.11/grsecurity/grsec_chdir.c 2006-08-12 08:17:55.000000000 -0400
15436@@ -0,0 +1,19 @@
15437+#include <linux/kernel.h>
15438+#include <linux/sched.h>
15439+#include <linux/fs.h>
15440+#include <linux/file.h>
15441+#include <linux/grsecurity.h>
15442+#include <linux/grinternal.h>
15443+
15444+void
15445+gr_log_chdir(const struct dentry *dentry, const struct vfsmount *mnt)
15446+{
15447+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
15448+ if ((grsec_enable_chdir && grsec_enable_group &&
15449+ in_group_p(grsec_audit_gid)) || (grsec_enable_chdir &&
15450+ !grsec_enable_group)) {
15451+ gr_log_fs_generic(GR_DO_AUDIT, GR_CHDIR_AUDIT_MSG, dentry, mnt);
15452+ }
15453+#endif
15454+ return;
15455+}
15456diff -urNp linux-2.6.17.11/grsecurity/grsec_chroot.c linux-2.6.17.11/grsecurity/grsec_chroot.c
15457--- linux-2.6.17.11/grsecurity/grsec_chroot.c 1969-12-31 19:00:00.000000000 -0500
15458+++ linux-2.6.17.11/grsecurity/grsec_chroot.c 2006-08-12 08:17:55.000000000 -0400
15459@@ -0,0 +1,332 @@
15460+#include <linux/kernel.h>
15461+#include <linux/module.h>
15462+#include <linux/sched.h>
15463+#include <linux/file.h>
15464+#include <linux/fs.h>
15465+#include <linux/mount.h>
15466+#include <linux/types.h>
15467+#include <linux/grinternal.h>
15468+
15469+int
15470+gr_handle_chroot_unix(const pid_t pid)
15471+{
15472+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
15473+ struct pid *spid = NULL;
15474+
15475+ if (unlikely(!grsec_enable_chroot_unix))
15476+ return 1;
15477+
15478+ if (likely(!proc_is_chrooted(current)))
15479+ return 1;
15480+
15481+ read_lock(&tasklist_lock);
15482+
15483+ spid = find_pid(pid);
15484+ if (spid) {
15485+ struct task_struct *p;
15486+ p = pid_task(spid, PIDTYPE_PID);
15487+ task_lock(p);
15488+ if (unlikely(!have_same_root(current, p))) {
15489+ task_unlock(p);
15490+ read_unlock(&tasklist_lock);
15491+ gr_log_noargs(GR_DONT_AUDIT, GR_UNIX_CHROOT_MSG);
15492+ return 0;
15493+ }
15494+ task_unlock(p);
15495+ }
15496+ read_unlock(&tasklist_lock);
15497+#endif
15498+ return 1;
15499+}
15500+
15501+int
15502+gr_handle_chroot_nice(void)
15503+{
15504+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
15505+ if (grsec_enable_chroot_nice && proc_is_chrooted(current)) {
15506+ gr_log_noargs(GR_DONT_AUDIT, GR_NICE_CHROOT_MSG);
15507+ return -EPERM;
15508+ }
15509+#endif
15510+ return 0;
15511+}
15512+
15513+int
15514+gr_handle_chroot_setpriority(struct task_struct *p, const int niceval)
15515+{
15516+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
15517+ if (grsec_enable_chroot_nice && (niceval < task_nice(p))
15518+ && proc_is_chrooted(current)) {
15519+ gr_log_str_int(GR_DONT_AUDIT, GR_PRIORITY_CHROOT_MSG, p->comm, p->pid);
15520+ return -EACCES;
15521+ }
15522+#endif
15523+ return 0;
15524+}
15525+
15526+int
15527+gr_handle_chroot_rawio(const struct inode *inode)
15528+{
15529+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
15530+ if (grsec_enable_chroot_caps && proc_is_chrooted(current) &&
15531+ inode && S_ISBLK(inode->i_mode) && !capable(CAP_SYS_RAWIO))
15532+ return 1;
15533+#endif
15534+ return 0;
15535+}
15536+
15537+int
15538+gr_pid_is_chrooted(struct task_struct *p)
15539+{
15540+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
15541+ if (!grsec_enable_chroot_findtask || !proc_is_chrooted(current) || !p)
15542+ return 0;
15543+
15544+ task_lock(p);
15545+ if ((p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) ||
15546+ !have_same_root(current, p)) {
15547+ task_unlock(p);
15548+ return 1;
15549+ }
15550+ task_unlock(p);
15551+#endif
15552+ return 0;
15553+}
15554+
15555+EXPORT_SYMBOL(gr_pid_is_chrooted);
15556+
15557+#if defined(CONFIG_GRKERNSEC_CHROOT_DOUBLE) || defined(CONFIG_GRKERNSEC_CHROOT_FCHDIR)
15558+int gr_is_outside_chroot(const struct dentry *u_dentry, const struct vfsmount *u_mnt)
15559+{
15560+ struct dentry *dentry = (struct dentry *)u_dentry;
15561+ struct vfsmount *mnt = (struct vfsmount *)u_mnt;
15562+ struct dentry *realroot;
15563+ struct vfsmount *realrootmnt;
15564+ struct dentry *currentroot;
15565+ struct vfsmount *currentmnt;
15566+ int ret = 1;
15567+
15568+ read_lock(&child_reaper->fs->lock);
15569+ realrootmnt = mntget(child_reaper->fs->rootmnt);
15570+ realroot = dget(child_reaper->fs->root);
15571+ read_unlock(&child_reaper->fs->lock);
15572+
15573+ read_lock(&current->fs->lock);
15574+ currentmnt = mntget(current->fs->rootmnt);
15575+ currentroot = dget(current->fs->root);
15576+ read_unlock(&current->fs->lock);
15577+
15578+ spin_lock(&dcache_lock);
15579+ for (;;) {
15580+ if (unlikely((dentry == realroot && mnt == realrootmnt)
15581+ || (dentry == currentroot && mnt == currentmnt)))
15582+ break;
15583+ if (unlikely(dentry == mnt->mnt_root || IS_ROOT(dentry))) {
15584+ if (mnt->mnt_parent == mnt)
15585+ break;
15586+ dentry = mnt->mnt_mountpoint;
15587+ mnt = mnt->mnt_parent;
15588+ continue;
15589+ }
15590+ dentry = dentry->d_parent;
15591+ }
15592+ spin_unlock(&dcache_lock);
15593+
15594+ dput(currentroot);
15595+ mntput(currentmnt);
15596+
15597+ /* access is outside of chroot */
15598+ if (dentry == realroot && mnt == realrootmnt)
15599+ ret = 0;
15600+
15601+ dput(realroot);
15602+ mntput(realrootmnt);
15603+ return ret;
15604+}
15605+#endif
15606+
15607+int
15608+gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt)
15609+{
15610+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
15611+ if (!grsec_enable_chroot_fchdir)
15612+ return 1;
15613+
15614+ if (!proc_is_chrooted(current))
15615+ return 1;
15616+ else if (!gr_is_outside_chroot(u_dentry, u_mnt)) {
15617+ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_FCHDIR_MSG, u_dentry, u_mnt);
15618+ return 0;
15619+ }
15620+#endif
15621+ return 1;
15622+}
15623+
15624+int
15625+gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
15626+ const time_t shm_createtime)
15627+{
15628+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
15629+ struct pid *pid = NULL;
15630+ time_t starttime;
15631+
15632+ if (unlikely(!grsec_enable_chroot_shmat))
15633+ return 1;
15634+
15635+ if (likely(!proc_is_chrooted(current)))
15636+ return 1;
15637+
15638+ read_lock(&tasklist_lock);
15639+
15640+ pid = find_pid(shm_cprid);
15641+ if (pid) {
15642+ struct task_struct *p;
15643+ p = pid_task(pid, PIDTYPE_PID);
15644+ task_lock(p);
15645+ starttime = p->start_time.tv_sec;
15646+ if (unlikely(!have_same_root(current, p) &&
15647+ time_before((unsigned long)starttime, (unsigned long)shm_createtime))) {
15648+ task_unlock(p);
15649+ read_unlock(&tasklist_lock);
15650+ gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG);
15651+ return 0;
15652+ }
15653+ task_unlock(p);
15654+ } else {
15655+ pid = find_pid(shm_lapid);
15656+ if (pid) {
15657+ struct task_struct *p;
15658+ p = pid_task(pid, PIDTYPE_PID);
15659+ task_lock(p);
15660+ if (unlikely(!have_same_root(current, p))) {
15661+ task_unlock(p);
15662+ read_unlock(&tasklist_lock);
15663+ gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG);
15664+ return 0;
15665+ }
15666+ task_unlock(p);
15667+ }
15668+ }
15669+
15670+ read_unlock(&tasklist_lock);
15671+#endif
15672+ return 1;
15673+}
15674+
15675+void
15676+gr_log_chroot_exec(const struct dentry *dentry, const struct vfsmount *mnt)
15677+{
15678+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
15679+ if (grsec_enable_chroot_execlog && proc_is_chrooted(current))
15680+ gr_log_fs_generic(GR_DO_AUDIT, GR_EXEC_CHROOT_MSG, dentry, mnt);
15681+#endif
15682+ return;
15683+}
15684+
15685+int
15686+gr_handle_chroot_mknod(const struct dentry *dentry,
15687+ const struct vfsmount *mnt, const int mode)
15688+{
15689+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
15690+ if (grsec_enable_chroot_mknod && !S_ISFIFO(mode) && !S_ISREG(mode) &&
15691+ proc_is_chrooted(current)) {
15692+ gr_log_fs_generic(GR_DONT_AUDIT, GR_MKNOD_CHROOT_MSG, dentry, mnt);
15693+ return -EPERM;
15694+ }
15695+#endif
15696+ return 0;
15697+}
15698+
15699+int
15700+gr_handle_chroot_mount(const struct dentry *dentry,
15701+ const struct vfsmount *mnt, const char *dev_name)
15702+{
15703+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
15704+ if (grsec_enable_chroot_mount && proc_is_chrooted(current)) {
15705+ gr_log_str_fs(GR_DONT_AUDIT, GR_MOUNT_CHROOT_MSG, dev_name, dentry, mnt);
15706+ return -EPERM;
15707+ }
15708+#endif
15709+ return 0;
15710+}
15711+
15712+int
15713+gr_handle_chroot_pivot(void)
15714+{
15715+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
15716+ if (grsec_enable_chroot_pivot && proc_is_chrooted(current)) {
15717+ gr_log_noargs(GR_DONT_AUDIT, GR_PIVOT_CHROOT_MSG);
15718+ return -EPERM;
15719+ }
15720+#endif
15721+ return 0;
15722+}
15723+
15724+int
15725+gr_handle_chroot_chroot(const struct dentry *dentry, const struct vfsmount *mnt)
15726+{
15727+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
15728+ if (grsec_enable_chroot_double && proc_is_chrooted(current) &&
15729+ !gr_is_outside_chroot(dentry, mnt)) {
15730+ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_CHROOT_MSG, dentry, mnt);
15731+ return -EPERM;
15732+ }
15733+#endif
15734+ return 0;
15735+}
15736+
15737+void
15738+gr_handle_chroot_caps(struct task_struct *task)
15739+{
15740+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
15741+ if (grsec_enable_chroot_caps && proc_is_chrooted(task)) {
15742+ task->cap_permitted =
15743+ cap_drop(task->cap_permitted, GR_CHROOT_CAPS);
15744+ task->cap_inheritable =
15745+ cap_drop(task->cap_inheritable, GR_CHROOT_CAPS);
15746+ task->cap_effective =
15747+ cap_drop(task->cap_effective, GR_CHROOT_CAPS);
15748+ }
15749+#endif
15750+ return;
15751+}
15752+
15753+int
15754+gr_handle_chroot_sysctl(const int op)
15755+{
15756+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
15757+ if (grsec_enable_chroot_sysctl && proc_is_chrooted(current)
15758+ && (op & 002))
15759+ return -EACCES;
15760+#endif
15761+ return 0;
15762+}
15763+
15764+void
15765+gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt)
15766+{
15767+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
15768+ if (grsec_enable_chroot_chdir)
15769+ set_fs_pwd(current->fs, mnt, dentry);
15770+#endif
15771+ return;
15772+}
15773+
15774+int
15775+gr_handle_chroot_chmod(const struct dentry *dentry,
15776+ const struct vfsmount *mnt, const int mode)
15777+{
15778+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
15779+ if (grsec_enable_chroot_chmod &&
15780+ ((mode & S_ISUID) || ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) &&
15781+ proc_is_chrooted(current)) {
15782+ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHMOD_CHROOT_MSG, dentry, mnt);
15783+ return -EPERM;
15784+ }
15785+#endif
15786+ return 0;
15787+}
15788+
15789+#ifdef CONFIG_SECURITY
15790+EXPORT_SYMBOL(gr_handle_chroot_caps);
15791+#endif
15792diff -urNp linux-2.6.17.11/grsecurity/grsec_disabled.c linux-2.6.17.11/grsecurity/grsec_disabled.c
15793--- linux-2.6.17.11/grsecurity/grsec_disabled.c 1969-12-31 19:00:00.000000000 -0500
15794+++ linux-2.6.17.11/grsecurity/grsec_disabled.c 2006-08-12 08:17:55.000000000 -0400
15795@@ -0,0 +1,418 @@
15796+#include <linux/kernel.h>
15797+#include <linux/module.h>
15798+#include <linux/config.h>
15799+#include <linux/sched.h>
15800+#include <linux/file.h>
15801+#include <linux/fs.h>
15802+#include <linux/kdev_t.h>
15803+#include <linux/net.h>
15804+#include <linux/in.h>
15805+#include <linux/ip.h>
15806+#include <linux/skbuff.h>
15807+#include <linux/sysctl.h>
15808+
15809+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
15810+void
15811+pax_set_initial_flags(struct linux_binprm *bprm)
15812+{
15813+ return;
15814+}
15815+#endif
15816+
15817+#ifdef CONFIG_SYSCTL
15818+__u32
15819+gr_handle_sysctl(const struct ctl_table * table, __u32 mode)
15820+{
15821+ return mode;
15822+}
15823+#endif
15824+
15825+int
15826+gr_acl_is_enabled(void)
15827+{
15828+ return 0;
15829+}
15830+
15831+int
15832+gr_handle_rawio(const struct inode *inode)
15833+{
15834+ return 0;
15835+}
15836+
15837+void
15838+gr_acl_handle_psacct(struct task_struct *task, const long code)
15839+{
15840+ return;
15841+}
15842+
15843+int
15844+gr_handle_ptrace(struct task_struct *task, const long request)
15845+{
15846+ return 0;
15847+}
15848+
15849+int
15850+gr_handle_proc_ptrace(struct task_struct *task)
15851+{
15852+ return 0;
15853+}
15854+
15855+void
15856+gr_learn_resource(const struct task_struct *task,
15857+ const int res, const unsigned long wanted, const int gt)
15858+{
15859+ return;
15860+}
15861+
15862+int
15863+gr_set_acls(const int type)
15864+{
15865+ return 0;
15866+}
15867+
15868+int
15869+gr_check_hidden_task(const struct task_struct *tsk)
15870+{
15871+ return 0;
15872+}
15873+
15874+int
15875+gr_check_protected_task(const struct task_struct *task)
15876+{
15877+ return 0;
15878+}
15879+
15880+void
15881+gr_copy_label(struct task_struct *tsk)
15882+{
15883+ return;
15884+}
15885+
15886+void
15887+gr_set_pax_flags(struct task_struct *task)
15888+{
15889+ return;
15890+}
15891+
15892+int
15893+gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
15894+{
15895+ return 0;
15896+}
15897+
15898+void
15899+gr_handle_delete(const ino_t ino, const dev_t dev)
15900+{
15901+ return;
15902+}
15903+
15904+void
15905+gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
15906+{
15907+ return;
15908+}
15909+
15910+void
15911+gr_handle_crash(struct task_struct *task, const int sig)
15912+{
15913+ return;
15914+}
15915+
15916+int
15917+gr_check_crash_exec(const struct file *filp)
15918+{
15919+ return 0;
15920+}
15921+
15922+int
15923+gr_check_crash_uid(const uid_t uid)
15924+{
15925+ return 0;
15926+}
15927+
15928+void
15929+gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
15930+ struct dentry *old_dentry,
15931+ struct dentry *new_dentry,
15932+ struct vfsmount *mnt, const __u8 replace)
15933+{
15934+ return;
15935+}
15936+
15937+int
15938+gr_search_socket(const int family, const int type, const int protocol)
15939+{
15940+ return 1;
15941+}
15942+
15943+int
15944+gr_search_connectbind(const int mode, const struct socket *sock,
15945+ const struct sockaddr_in *addr)
15946+{
15947+ return 1;
15948+}
15949+
15950+int
15951+gr_task_is_capable(struct task_struct *task, const int cap)
15952+{
15953+ return 1;
15954+}
15955+
15956+int
15957+gr_is_capable_nolog(const int cap)
15958+{
15959+ return 1;
15960+}
15961+
15962+void
15963+gr_handle_alertkill(struct task_struct *task)
15964+{
15965+ return;
15966+}
15967+
15968+__u32
15969+gr_acl_handle_execve(const struct dentry * dentry, const struct vfsmount * mnt)
15970+{
15971+ return 1;
15972+}
15973+
15974+__u32
15975+gr_acl_handle_hidden_file(const struct dentry * dentry,
15976+ const struct vfsmount * mnt)
15977+{
15978+ return 1;
15979+}
15980+
15981+__u32
15982+gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
15983+ const int fmode)
15984+{
15985+ return 1;
15986+}
15987+
15988+__u32
15989+gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
15990+{
15991+ return 1;
15992+}
15993+
15994+__u32
15995+gr_acl_handle_unlink(const struct dentry * dentry, const struct vfsmount * mnt)
15996+{
15997+ return 1;
15998+}
15999+
16000+int
16001+gr_acl_handle_mmap(const struct file *file, const unsigned long prot,
16002+ unsigned int *vm_flags)
16003+{
16004+ return 1;
16005+}
16006+
16007+__u32
16008+gr_acl_handle_truncate(const struct dentry * dentry,
16009+ const struct vfsmount * mnt)
16010+{
16011+ return 1;
16012+}
16013+
16014+__u32
16015+gr_acl_handle_utime(const struct dentry * dentry, const struct vfsmount * mnt)
16016+{
16017+ return 1;
16018+}
16019+
16020+__u32
16021+gr_acl_handle_access(const struct dentry * dentry,
16022+ const struct vfsmount * mnt, const int fmode)
16023+{
16024+ return 1;
16025+}
16026+
16027+__u32
16028+gr_acl_handle_fchmod(const struct dentry * dentry, const struct vfsmount * mnt,
16029+ mode_t mode)
16030+{
16031+ return 1;
16032+}
16033+
16034+__u32
16035+gr_acl_handle_chmod(const struct dentry * dentry, const struct vfsmount * mnt,
16036+ mode_t mode)
16037+{
16038+ return 1;
16039+}
16040+
16041+__u32
16042+gr_acl_handle_chown(const struct dentry * dentry, const struct vfsmount * mnt)
16043+{
16044+ return 1;
16045+}
16046+
16047+void
16048+grsecurity_init(void)
16049+{
16050+ return;
16051+}
16052+
16053+__u32
16054+gr_acl_handle_mknod(const struct dentry * new_dentry,
16055+ const struct dentry * parent_dentry,
16056+ const struct vfsmount * parent_mnt,
16057+ const int mode)
16058+{
16059+ return 1;
16060+}
16061+
16062+__u32
16063+gr_acl_handle_mkdir(const struct dentry * new_dentry,
16064+ const struct dentry * parent_dentry,
16065+ const struct vfsmount * parent_mnt)
16066+{
16067+ return 1;
16068+}
16069+
16070+__u32
16071+gr_acl_handle_symlink(const struct dentry * new_dentry,
16072+ const struct dentry * parent_dentry,
16073+ const struct vfsmount * parent_mnt, const char *from)
16074+{
16075+ return 1;
16076+}
16077+
16078+__u32
16079+gr_acl_handle_link(const struct dentry * new_dentry,
16080+ const struct dentry * parent_dentry,
16081+ const struct vfsmount * parent_mnt,
16082+ const struct dentry * old_dentry,
16083+ const struct vfsmount * old_mnt, const char *to)
16084+{
16085+ return 1;
16086+}
16087+
16088+int
16089+gr_acl_handle_rename(const struct dentry *new_dentry,
16090+ const struct dentry *parent_dentry,
16091+ const struct vfsmount *parent_mnt,
16092+ const struct dentry *old_dentry,
16093+ const struct inode *old_parent_inode,
16094+ const struct vfsmount *old_mnt, const char *newname)
16095+{
16096+ return 0;
16097+}
16098+
16099+int
16100+gr_acl_handle_filldir(const struct file *file, const char *name,
16101+ const int namelen, const ino_t ino)
16102+{
16103+ return 1;
16104+}
16105+
16106+int
16107+gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
16108+ const time_t shm_createtime, const uid_t cuid, const int shmid)
16109+{
16110+ return 1;
16111+}
16112+
16113+int
16114+gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
16115+{
16116+ return 1;
16117+}
16118+
16119+int
16120+gr_search_accept(const struct socket *sock)
16121+{
16122+ return 1;
16123+}
16124+
16125+int
16126+gr_search_listen(const struct socket *sock)
16127+{
16128+ return 1;
16129+}
16130+
16131+int
16132+gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
16133+{
16134+ return 1;
16135+}
16136+
16137+__u32
16138+gr_acl_handle_unix(const struct dentry * dentry, const struct vfsmount * mnt)
16139+{
16140+ return 1;
16141+}
16142+
16143+__u32
16144+gr_acl_handle_creat(const struct dentry * dentry,
16145+ const struct dentry * p_dentry,
16146+ const struct vfsmount * p_mnt, const int fmode,
16147+ const int imode)
16148+{
16149+ return 1;
16150+}
16151+
16152+void
16153+gr_acl_handle_exit(void)
16154+{
16155+ return;
16156+}
16157+
16158+int
16159+gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
16160+{
16161+ return 1;
16162+}
16163+
16164+void
16165+gr_set_role_label(const uid_t uid, const gid_t gid)
16166+{
16167+ return;
16168+}
16169+
16170+int
16171+gr_acl_handle_procpidmem(const struct task_struct *task)
16172+{
16173+ return 0;
16174+}
16175+
16176+int
16177+gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
16178+{
16179+ return 1;
16180+}
16181+
16182+int
16183+gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
16184+{
16185+ return 1;
16186+}
16187+
16188+void
16189+gr_set_kernel_label(struct task_struct *task)
16190+{
16191+ return;
16192+}
16193+
16194+int
16195+gr_check_user_change(int real, int effective, int fs)
16196+{
16197+ return 0;
16198+}
16199+
16200+int
16201+gr_check_group_change(int real, int effective, int fs)
16202+{
16203+ return 0;
16204+}
16205+
16206+
16207+EXPORT_SYMBOL(gr_task_is_capable);
16208+EXPORT_SYMBOL(gr_learn_resource);
16209+EXPORT_SYMBOL(gr_set_kernel_label);
16210+#ifdef CONFIG_SECURITY
16211+EXPORT_SYMBOL(gr_check_user_change);
16212+EXPORT_SYMBOL(gr_check_group_change);
16213+#endif
16214diff -urNp linux-2.6.17.11/grsecurity/grsec_exec.c linux-2.6.17.11/grsecurity/grsec_exec.c
16215--- linux-2.6.17.11/grsecurity/grsec_exec.c 1969-12-31 19:00:00.000000000 -0500
16216+++ linux-2.6.17.11/grsecurity/grsec_exec.c 2006-08-12 08:17:55.000000000 -0400
16217@@ -0,0 +1,88 @@
16218+#include <linux/kernel.h>
16219+#include <linux/sched.h>
16220+#include <linux/file.h>
16221+#include <linux/binfmts.h>
16222+#include <linux/smp_lock.h>
16223+#include <linux/fs.h>
16224+#include <linux/types.h>
16225+#include <linux/grdefs.h>
16226+#include <linux/grinternal.h>
16227+#include <linux/capability.h>
16228+
16229+#include <asm/uaccess.h>
16230+
16231+#ifdef CONFIG_GRKERNSEC_EXECLOG
16232+static char gr_exec_arg_buf[132];
16233+static DECLARE_MUTEX(gr_exec_arg_sem);
16234+#endif
16235+
16236+int
16237+gr_handle_nproc(void)
16238+{
16239+#ifdef CONFIG_GRKERNSEC_EXECVE
16240+ if (grsec_enable_execve && current->user &&
16241+ (atomic_read(&current->user->processes) >
16242+ current->signal->rlim[RLIMIT_NPROC].rlim_cur) &&
16243+ !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) {
16244+ gr_log_noargs(GR_DONT_AUDIT, GR_NPROC_MSG);
16245+ return -EAGAIN;
16246+ }
16247+#endif
16248+ return 0;
16249+}
16250+
16251+void
16252+gr_handle_exec_args(struct linux_binprm *bprm, const char __user *__user *argv)
16253+{
16254+#ifdef CONFIG_GRKERNSEC_EXECLOG
16255+ char *grarg = gr_exec_arg_buf;
16256+ unsigned int i, x, execlen = 0;
16257+ char c;
16258+
16259+ if (!((grsec_enable_execlog && grsec_enable_group &&
16260+ in_group_p(grsec_audit_gid))
16261+ || (grsec_enable_execlog && !grsec_enable_group)))
16262+ return;
16263+
16264+ down(&gr_exec_arg_sem);
16265+ memset(grarg, 0, sizeof(gr_exec_arg_buf));
16266+
16267+ if (unlikely(argv == NULL))
16268+ goto log;
16269+
16270+ for (i = 0; i < bprm->argc && execlen < 128; i++) {
16271+ const char __user *p;
16272+ unsigned int len;
16273+
16274+ if (copy_from_user(&p, argv + i, sizeof(p)))
16275+ goto log;
16276+ if (!p)
16277+ goto log;
16278+ len = strnlen_user(p, 128 - execlen);
16279+ if (len > 128 - execlen)
16280+ len = 128 - execlen;
16281+ else if (len > 0)
16282+ len--;
16283+ if (copy_from_user(grarg + execlen, p, len))
16284+ goto log;
16285+
16286+ /* rewrite unprintable characters */
16287+ for (x = 0; x < len; x++) {
16288+ c = *(grarg + execlen + x);
16289+ if (c < 32 || c > 126)
16290+ *(grarg + execlen + x) = ' ';
16291+ }
16292+
16293+ execlen += len;
16294+ *(grarg + execlen) = ' ';
16295+ *(grarg + execlen + 1) = '\0';
16296+ execlen++;
16297+ }
16298+
16299+ log:
16300+ gr_log_fs_str(GR_DO_AUDIT, GR_EXEC_AUDIT_MSG, bprm->file->f_dentry,
16301+ bprm->file->f_vfsmnt, grarg);
16302+ up(&gr_exec_arg_sem);
16303+#endif
16304+ return;
16305+}
16306diff -urNp linux-2.6.17.11/grsecurity/grsec_fifo.c linux-2.6.17.11/grsecurity/grsec_fifo.c
16307--- linux-2.6.17.11/grsecurity/grsec_fifo.c 1969-12-31 19:00:00.000000000 -0500
16308+++ linux-2.6.17.11/grsecurity/grsec_fifo.c 2006-08-12 08:17:55.000000000 -0400
16309@@ -0,0 +1,22 @@
16310+#include <linux/kernel.h>
16311+#include <linux/sched.h>
16312+#include <linux/fs.h>
16313+#include <linux/file.h>
16314+#include <linux/grinternal.h>
16315+
16316+int
16317+gr_handle_fifo(const struct dentry *dentry, const struct vfsmount *mnt,
16318+ const struct dentry *dir, const int flag, const int acc_mode)
16319+{
16320+#ifdef CONFIG_GRKERNSEC_FIFO
16321+ if (grsec_enable_fifo && S_ISFIFO(dentry->d_inode->i_mode) &&
16322+ !(flag & O_EXCL) && (dir->d_inode->i_mode & S_ISVTX) &&
16323+ (dentry->d_inode->i_uid != dir->d_inode->i_uid) &&
16324+ (current->fsuid != dentry->d_inode->i_uid)) {
16325+ if (!generic_permission(dentry->d_inode, acc_mode, NULL))
16326+ gr_log_fs_int2(GR_DONT_AUDIT, GR_FIFO_MSG, dentry, mnt, dentry->d_inode->i_uid, dentry->d_inode->i_gid);
16327+ return -EACCES;
16328+ }
16329+#endif
16330+ return 0;
16331+}
16332diff -urNp linux-2.6.17.11/grsecurity/grsec_fork.c linux-2.6.17.11/grsecurity/grsec_fork.c
16333--- linux-2.6.17.11/grsecurity/grsec_fork.c 1969-12-31 19:00:00.000000000 -0500
16334+++ linux-2.6.17.11/grsecurity/grsec_fork.c 2006-08-12 08:17:55.000000000 -0400
16335@@ -0,0 +1,15 @@
16336+#include <linux/kernel.h>
16337+#include <linux/sched.h>
16338+#include <linux/grsecurity.h>
16339+#include <linux/grinternal.h>
16340+#include <linux/errno.h>
16341+
16342+void
16343+gr_log_forkfail(const int retval)
16344+{
16345+#ifdef CONFIG_GRKERNSEC_FORKFAIL
16346+ if (grsec_enable_forkfail && retval != -ERESTARTNOINTR)
16347+ gr_log_int(GR_DONT_AUDIT, GR_FAILFORK_MSG, retval);
16348+#endif
16349+ return;
16350+}
16351diff -urNp linux-2.6.17.11/grsecurity/grsec_init.c linux-2.6.17.11/grsecurity/grsec_init.c
16352--- linux-2.6.17.11/grsecurity/grsec_init.c 1969-12-31 19:00:00.000000000 -0500
16353+++ linux-2.6.17.11/grsecurity/grsec_init.c 2006-08-12 08:17:55.000000000 -0400
16354@@ -0,0 +1,236 @@
16355+#include <linux/kernel.h>
16356+#include <linux/sched.h>
16357+#include <linux/mm.h>
16358+#include <linux/smp_lock.h>
16359+#include <linux/gracl.h>
16360+#include <linux/slab.h>
16361+#include <linux/vmalloc.h>
16362+#include <linux/percpu.h>
16363+
16364+int grsec_enable_shm;
16365+int grsec_enable_link;
16366+int grsec_enable_dmesg;
16367+int grsec_enable_fifo;
16368+int grsec_enable_execve;
16369+int grsec_enable_execlog;
16370+int grsec_enable_signal;
16371+int grsec_enable_forkfail;
16372+int grsec_enable_time;
16373+int grsec_enable_audit_textrel;
16374+int grsec_enable_group;
16375+int grsec_audit_gid;
16376+int grsec_enable_chdir;
16377+int grsec_enable_audit_ipc;
16378+int grsec_enable_mount;
16379+int grsec_enable_chroot_findtask;
16380+int grsec_enable_chroot_mount;
16381+int grsec_enable_chroot_shmat;
16382+int grsec_enable_chroot_fchdir;
16383+int grsec_enable_chroot_double;
16384+int grsec_enable_chroot_pivot;
16385+int grsec_enable_chroot_chdir;
16386+int grsec_enable_chroot_chmod;
16387+int grsec_enable_chroot_mknod;
16388+int grsec_enable_chroot_nice;
16389+int grsec_enable_chroot_execlog;
16390+int grsec_enable_chroot_caps;
16391+int grsec_enable_chroot_sysctl;
16392+int grsec_enable_chroot_unix;
16393+int grsec_enable_tpe;
16394+int grsec_tpe_gid;
16395+int grsec_enable_tpe_all;
16396+int grsec_enable_randpid;
16397+int grsec_enable_socket_all;
16398+int grsec_socket_all_gid;
16399+int grsec_enable_socket_client;
16400+int grsec_socket_client_gid;
16401+int grsec_enable_socket_server;
16402+int grsec_socket_server_gid;
16403+int grsec_resource_logging;
16404+int grsec_lock;
16405+
16406+spinlock_t grsec_alert_lock = SPIN_LOCK_UNLOCKED;
16407+unsigned long grsec_alert_wtime = 0;
16408+unsigned long grsec_alert_fyet = 0;
16409+
16410+spinlock_t grsec_audit_lock = SPIN_LOCK_UNLOCKED;
16411+
16412+rwlock_t grsec_exec_file_lock = RW_LOCK_UNLOCKED;
16413+
16414+char *gr_shared_page[4];
16415+
16416+char *gr_alert_log_fmt;
16417+char *gr_audit_log_fmt;
16418+char *gr_alert_log_buf;
16419+char *gr_audit_log_buf;
16420+
16421+extern struct gr_arg *gr_usermode;
16422+extern unsigned char *gr_system_salt;
16423+extern unsigned char *gr_system_sum;
16424+
16425+void
16426+grsecurity_init(void)
16427+{
16428+ int j;
16429+ /* create the per-cpu shared pages */
16430+
16431+ preempt_disable();
16432+ for (j = 0; j < 4; j++) {
16433+ gr_shared_page[j] = (char *)__alloc_percpu(PAGE_SIZE);
16434+ if (gr_shared_page[j] == NULL) {
16435+ panic("Unable to allocate grsecurity shared page");
16436+ return;
16437+ }
16438+ }
16439+ preempt_enable();
16440+
16441+ /* allocate log buffers */
16442+ gr_alert_log_fmt = kmalloc(512, GFP_KERNEL);
16443+ if (!gr_alert_log_fmt) {
16444+ panic("Unable to allocate grsecurity alert log format buffer");
16445+ return;
16446+ }
16447+ gr_audit_log_fmt = kmalloc(512, GFP_KERNEL);
16448+ if (!gr_audit_log_fmt) {
16449+ panic("Unable to allocate grsecurity audit log format buffer");
16450+ return;
16451+ }
16452+ gr_alert_log_buf = (char *) get_zeroed_page(GFP_KERNEL);
16453+ if (!gr_alert_log_buf) {
16454+ panic("Unable to allocate grsecurity alert log buffer");
16455+ return;
16456+ }
16457+ gr_audit_log_buf = (char *) get_zeroed_page(GFP_KERNEL);
16458+ if (!gr_audit_log_buf) {
16459+ panic("Unable to allocate grsecurity audit log buffer");
16460+ return;
16461+ }
16462+
16463+ /* allocate memory for authentication structure */
16464+ gr_usermode = kmalloc(sizeof(struct gr_arg), GFP_KERNEL);
16465+ gr_system_salt = kmalloc(GR_SALT_LEN, GFP_KERNEL);
16466+ gr_system_sum = kmalloc(GR_SHA_LEN, GFP_KERNEL);
16467+
16468+ if (!gr_usermode || !gr_system_salt || !gr_system_sum) {
16469+ panic("Unable to allocate grsecurity authentication structure");
16470+ return;
16471+ }
16472+
16473+#if !defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_SYSCTL_ON)
16474+#ifndef CONFIG_GRKERNSEC_SYSCTL
16475+ grsec_lock = 1;
16476+#endif
16477+#ifdef CONFIG_GRKERNSEC_SHM
16478+ grsec_enable_shm = 1;
16479+#endif
16480+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
16481+ grsec_enable_audit_textrel = 1;
16482+#endif
16483+#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
16484+ grsec_enable_group = 1;
16485+ grsec_audit_gid = CONFIG_GRKERNSEC_AUDIT_GID;
16486+#endif
16487+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
16488+ grsec_enable_chdir = 1;
16489+#endif
16490+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
16491+ grsec_enable_audit_ipc = 1;
16492+#endif
16493+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
16494+ grsec_enable_mount = 1;
16495+#endif
16496+#ifdef CONFIG_GRKERNSEC_LINK
16497+ grsec_enable_link = 1;
16498+#endif
16499+#ifdef CONFIG_GRKERNSEC_DMESG
16500+ grsec_enable_dmesg = 1;
16501+#endif
16502+#ifdef CONFIG_GRKERNSEC_FIFO
16503+ grsec_enable_fifo = 1;
16504+#endif
16505+#ifdef CONFIG_GRKERNSEC_EXECVE
16506+ grsec_enable_execve = 1;
16507+#endif
16508+#ifdef CONFIG_GRKERNSEC_EXECLOG
16509+ grsec_enable_execlog = 1;
16510+#endif
16511+#ifdef CONFIG_GRKERNSEC_SIGNAL
16512+ grsec_enable_signal = 1;
16513+#endif
16514+#ifdef CONFIG_GRKERNSEC_FORKFAIL
16515+ grsec_enable_forkfail = 1;
16516+#endif
16517+#ifdef CONFIG_GRKERNSEC_TIME
16518+ grsec_enable_time = 1;
16519+#endif
16520+#ifdef CONFIG_GRKERNSEC_RESLOG
16521+ grsec_resource_logging = 1;
16522+#endif
16523+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
16524+ grsec_enable_chroot_findtask = 1;
16525+#endif
16526+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
16527+ grsec_enable_chroot_unix = 1;
16528+#endif
16529+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
16530+ grsec_enable_chroot_mount = 1;
16531+#endif
16532+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
16533+ grsec_enable_chroot_fchdir = 1;
16534+#endif
16535+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
16536+ grsec_enable_chroot_shmat = 1;
16537+#endif
16538+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
16539+ grsec_enable_chroot_double = 1;
16540+#endif
16541+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
16542+ grsec_enable_chroot_pivot = 1;
16543+#endif
16544+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
16545+ grsec_enable_chroot_chdir = 1;
16546+#endif
16547+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
16548+ grsec_enable_chroot_chmod = 1;
16549+#endif
16550+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
16551+ grsec_enable_chroot_mknod = 1;
16552+#endif
16553+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
16554+ grsec_enable_chroot_nice = 1;
16555+#endif
16556+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
16557+ grsec_enable_chroot_execlog = 1;
16558+#endif
16559+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
16560+ grsec_enable_chroot_caps = 1;
16561+#endif
16562+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
16563+ grsec_enable_chroot_sysctl = 1;
16564+#endif
16565+#ifdef CONFIG_GRKERNSEC_TPE
16566+ grsec_enable_tpe = 1;
16567+ grsec_tpe_gid = CONFIG_GRKERNSEC_TPE_GID;
16568+#ifdef CONFIG_GRKERNSEC_TPE_ALL
16569+ grsec_enable_tpe_all = 1;
16570+#endif
16571+#endif
16572+#ifdef CONFIG_GRKERNSEC_RANDPID
16573+ grsec_enable_randpid = 1;
16574+#endif
16575+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
16576+ grsec_enable_socket_all = 1;
16577+ grsec_socket_all_gid = CONFIG_GRKERNSEC_SOCKET_ALL_GID;
16578+#endif
16579+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
16580+ grsec_enable_socket_client = 1;
16581+ grsec_socket_client_gid = CONFIG_GRKERNSEC_SOCKET_CLIENT_GID;
16582+#endif
16583+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
16584+ grsec_enable_socket_server = 1;
16585+ grsec_socket_server_gid = CONFIG_GRKERNSEC_SOCKET_SERVER_GID;
16586+#endif
16587+#endif
16588+
16589+ return;
16590+}
16591diff -urNp linux-2.6.17.11/grsecurity/grsec_ipc.c linux-2.6.17.11/grsecurity/grsec_ipc.c
16592--- linux-2.6.17.11/grsecurity/grsec_ipc.c 1969-12-31 19:00:00.000000000 -0500
16593+++ linux-2.6.17.11/grsecurity/grsec_ipc.c 2006-08-12 08:17:55.000000000 -0400
16594@@ -0,0 +1,81 @@
16595+#include <linux/kernel.h>
16596+#include <linux/sched.h>
16597+#include <linux/types.h>
16598+#include <linux/ipc.h>
16599+#include <linux/grsecurity.h>
16600+#include <linux/grinternal.h>
16601+
16602+void
16603+gr_log_msgget(const int ret, const int msgflg)
16604+{
16605+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
16606+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
16607+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
16608+ !grsec_enable_group)) && (ret >= 0)
16609+ && (msgflg & IPC_CREAT))
16610+ gr_log_noargs(GR_DO_AUDIT, GR_MSGQ_AUDIT_MSG);
16611+#endif
16612+ return;
16613+}
16614+
16615+void
16616+gr_log_msgrm(const uid_t uid, const uid_t cuid)
16617+{
16618+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
16619+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
16620+ grsec_enable_audit_ipc) ||
16621+ (grsec_enable_audit_ipc && !grsec_enable_group))
16622+ gr_log_int_int(GR_DO_AUDIT, GR_MSGQR_AUDIT_MSG, uid, cuid);
16623+#endif
16624+ return;
16625+}
16626+
16627+void
16628+gr_log_semget(const int err, const int semflg)
16629+{
16630+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
16631+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
16632+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
16633+ !grsec_enable_group)) && (err >= 0)
16634+ && (semflg & IPC_CREAT))
16635+ gr_log_noargs(GR_DO_AUDIT, GR_SEM_AUDIT_MSG);
16636+#endif
16637+ return;
16638+}
16639+
16640+void
16641+gr_log_semrm(const uid_t uid, const uid_t cuid)
16642+{
16643+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
16644+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
16645+ grsec_enable_audit_ipc) ||
16646+ (grsec_enable_audit_ipc && !grsec_enable_group))
16647+ gr_log_int_int(GR_DO_AUDIT, GR_SEMR_AUDIT_MSG, uid, cuid);
16648+#endif
16649+ return;
16650+}
16651+
16652+void
16653+gr_log_shmget(const int err, const int shmflg, const size_t size)
16654+{
16655+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
16656+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
16657+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
16658+ !grsec_enable_group)) && (err >= 0)
16659+ && (shmflg & IPC_CREAT))
16660+ gr_log_int(GR_DO_AUDIT, GR_SHM_AUDIT_MSG, size);
16661+#endif
16662+ return;
16663+}
16664+
16665+void
16666+gr_log_shmrm(const uid_t uid, const uid_t cuid)
16667+{
16668+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
16669+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
16670+ grsec_enable_audit_ipc) ||
16671+ (grsec_enable_audit_ipc && !grsec_enable_group))
16672+ gr_log_int_int(GR_DO_AUDIT, GR_SHMR_AUDIT_MSG, uid, cuid);
16673+#endif
16674+ return;
16675+}
16676diff -urNp linux-2.6.17.11/grsecurity/grsec_link.c linux-2.6.17.11/grsecurity/grsec_link.c
16677--- linux-2.6.17.11/grsecurity/grsec_link.c 1969-12-31 19:00:00.000000000 -0500
16678+++ linux-2.6.17.11/grsecurity/grsec_link.c 2006-08-12 08:17:55.000000000 -0400
16679@@ -0,0 +1,39 @@
16680+#include <linux/kernel.h>
16681+#include <linux/sched.h>
16682+#include <linux/fs.h>
16683+#include <linux/file.h>
16684+#include <linux/grinternal.h>
16685+
16686+int
16687+gr_handle_follow_link(const struct inode *parent,
16688+ const struct inode *inode,
16689+ const struct dentry *dentry, const struct vfsmount *mnt)
16690+{
16691+#ifdef CONFIG_GRKERNSEC_LINK
16692+ if (grsec_enable_link && S_ISLNK(inode->i_mode) &&
16693+ (parent->i_mode & S_ISVTX) && (parent->i_uid != inode->i_uid) &&
16694+ (parent->i_mode & S_IWOTH) && (current->fsuid != inode->i_uid)) {
16695+ gr_log_fs_int2(GR_DONT_AUDIT, GR_SYMLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid);
16696+ return -EACCES;
16697+ }
16698+#endif
16699+ return 0;
16700+}
16701+
16702+int
16703+gr_handle_hardlink(const struct dentry *dentry,
16704+ const struct vfsmount *mnt,
16705+ struct inode *inode, const int mode, const char *to)
16706+{
16707+#ifdef CONFIG_GRKERNSEC_LINK
16708+ if (grsec_enable_link && current->fsuid != inode->i_uid &&
16709+ (!S_ISREG(mode) || (mode & S_ISUID) ||
16710+ ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) ||
16711+ (generic_permission(inode, MAY_READ | MAY_WRITE, NULL))) &&
16712+ !capable(CAP_FOWNER) && current->uid) {
16713+ gr_log_fs_int2_str(GR_DONT_AUDIT, GR_HARDLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid, to);
16714+ return -EPERM;
16715+ }
16716+#endif
16717+ return 0;
16718+}
16719diff -urNp linux-2.6.17.11/grsecurity/grsec_log.c linux-2.6.17.11/grsecurity/grsec_log.c
16720--- linux-2.6.17.11/grsecurity/grsec_log.c 1969-12-31 19:00:00.000000000 -0500
16721+++ linux-2.6.17.11/grsecurity/grsec_log.c 2006-08-12 08:17:55.000000000 -0400
16722@@ -0,0 +1,265 @@
16723+#include <linux/kernel.h>
16724+#include <linux/sched.h>
16725+#include <linux/file.h>
16726+#include <linux/tty.h>
16727+#include <linux/fs.h>
16728+#include <linux/grinternal.h>
16729+
16730+#define BEGIN_LOCKS(x) \
16731+ read_lock(&tasklist_lock); \
16732+ read_lock(&grsec_exec_file_lock); \
16733+ if (x != GR_DO_AUDIT) \
16734+ spin_lock(&grsec_alert_lock); \
16735+ else \
16736+ spin_lock(&grsec_audit_lock)
16737+
16738+#define END_LOCKS(x) \
16739+ if (x != GR_DO_AUDIT) \
16740+ spin_unlock(&grsec_alert_lock); \
16741+ else \
16742+ spin_unlock(&grsec_audit_lock); \
16743+ read_unlock(&grsec_exec_file_lock); \
16744+ read_unlock(&tasklist_lock); \
16745+ if (x == GR_DONT_AUDIT) \
16746+ gr_handle_alertkill(current)
16747+
16748+enum {
16749+ FLOODING,
16750+ NO_FLOODING
16751+};
16752+
16753+extern char *gr_alert_log_fmt;
16754+extern char *gr_audit_log_fmt;
16755+extern char *gr_alert_log_buf;
16756+extern char *gr_audit_log_buf;
16757+
16758+static int gr_log_start(int audit)
16759+{
16760+ char *loglevel = (audit == GR_DO_AUDIT) ? KERN_INFO : KERN_ALERT;
16761+ char *fmt = (audit == GR_DO_AUDIT) ? gr_audit_log_fmt : gr_alert_log_fmt;
16762+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
16763+
16764+ if (audit == GR_DO_AUDIT)
16765+ goto set_fmt;
16766+
16767+ if (!grsec_alert_wtime || jiffies - grsec_alert_wtime > CONFIG_GRKERNSEC_FLOODTIME * HZ) {
16768+ grsec_alert_wtime = jiffies;
16769+ grsec_alert_fyet = 0;
16770+ } else if ((jiffies - grsec_alert_wtime < CONFIG_GRKERNSEC_FLOODTIME * HZ) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) {
16771+ grsec_alert_fyet++;
16772+ } else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) {
16773+ grsec_alert_wtime = jiffies;
16774+ grsec_alert_fyet++;
16775+ printk(KERN_ALERT "grsec: more alerts, logging disabled for %d seconds\n", CONFIG_GRKERNSEC_FLOODTIME);
16776+ return FLOODING;
16777+ } else return FLOODING;
16778+
16779+set_fmt:
16780+ memset(buf, 0, PAGE_SIZE);
16781+ if (current->signal->curr_ip && gr_acl_is_enabled()) {
16782+ sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: (%.64s:%c:%.950s) ");
16783+ snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip), current->role->rolename, gr_roletype_to_char(), current->acl->filename);
16784+ } else if (current->signal->curr_ip) {
16785+ sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: ");
16786+ snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip));
16787+ } else if (gr_acl_is_enabled()) {
16788+ sprintf(fmt, "%s%s", loglevel, "grsec: (%.64s:%c:%.950s) ");
16789+ snprintf(buf, PAGE_SIZE - 1, fmt, current->role->rolename, gr_roletype_to_char(), current->acl->filename);
16790+ } else {
16791+ sprintf(fmt, "%s%s", loglevel, "grsec: ");
16792+ strcpy(buf, fmt);
16793+ }
16794+
16795+ return NO_FLOODING;
16796+}
16797+
16798+static void gr_log_middle(int audit, const char *msg, va_list ap)
16799+{
16800+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
16801+ unsigned int len = strlen(buf);
16802+
16803+ vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap);
16804+
16805+ return;
16806+}
16807+
16808+static void gr_log_middle_varargs(int audit, const char *msg, ...)
16809+{
16810+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
16811+ unsigned int len = strlen(buf);
16812+ va_list ap;
16813+
16814+ va_start(ap, msg);
16815+ vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap);
16816+ va_end(ap);
16817+
16818+ return;
16819+}
16820+
16821+static void gr_log_end(int audit)
16822+{
16823+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
16824+ unsigned int len = strlen(buf);
16825+
16826+ snprintf(buf + len, PAGE_SIZE - len - 1, DEFAULTSECMSG, DEFAULTSECARGS(current));
16827+ printk("%s\n", buf);
16828+
16829+ return;
16830+}
16831+
16832+void gr_log_varargs(int audit, const char *msg, int argtypes, ...)
16833+{
16834+ int logtype;
16835+ char *result = (audit == GR_DO_AUDIT) ? "successful" : "denied";
16836+ char *str1, *str2, *str3;
16837+ int num1, num2;
16838+ unsigned long ulong1, ulong2;
16839+ struct dentry *dentry;
16840+ struct vfsmount *mnt;
16841+ struct file *file;
16842+ struct task_struct *task;
16843+ va_list ap;
16844+
16845+ BEGIN_LOCKS(audit);
16846+ logtype = gr_log_start(audit);
16847+ if (logtype == FLOODING) {
16848+ END_LOCKS(audit);
16849+ return;
16850+ }
16851+ va_start(ap, argtypes);
16852+ switch (argtypes) {
16853+ case GR_TTYSNIFF:
16854+ task = va_arg(ap, struct task_struct *);
16855+ 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);
16856+ break;
16857+ case GR_RBAC:
16858+ dentry = va_arg(ap, struct dentry *);
16859+ mnt = va_arg(ap, struct vfsmount *);
16860+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt));
16861+ break;
16862+ case GR_RBAC_STR:
16863+ dentry = va_arg(ap, struct dentry *);
16864+ mnt = va_arg(ap, struct vfsmount *);
16865+ str1 = va_arg(ap, char *);
16866+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1);
16867+ break;
16868+ case GR_STR_RBAC:
16869+ str1 = va_arg(ap, char *);
16870+ dentry = va_arg(ap, struct dentry *);
16871+ mnt = va_arg(ap, struct vfsmount *);
16872+ gr_log_middle_varargs(audit, msg, result, str1, gr_to_filename(dentry, mnt));
16873+ break;
16874+ case GR_RBAC_MODE2:
16875+ dentry = va_arg(ap, struct dentry *);
16876+ mnt = va_arg(ap, struct vfsmount *);
16877+ str1 = va_arg(ap, char *);
16878+ str2 = va_arg(ap, char *);
16879+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2);
16880+ break;
16881+ case GR_RBAC_MODE3:
16882+ dentry = va_arg(ap, struct dentry *);
16883+ mnt = va_arg(ap, struct vfsmount *);
16884+ str1 = va_arg(ap, char *);
16885+ str2 = va_arg(ap, char *);
16886+ str3 = va_arg(ap, char *);
16887+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2, str3);
16888+ break;
16889+ case GR_FILENAME:
16890+ dentry = va_arg(ap, struct dentry *);
16891+ mnt = va_arg(ap, struct vfsmount *);
16892+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt));
16893+ break;
16894+ case GR_STR_FILENAME:
16895+ str1 = va_arg(ap, char *);
16896+ dentry = va_arg(ap, struct dentry *);
16897+ mnt = va_arg(ap, struct vfsmount *);
16898+ gr_log_middle_varargs(audit, msg, str1, gr_to_filename(dentry, mnt));
16899+ break;
16900+ case GR_FILENAME_STR:
16901+ dentry = va_arg(ap, struct dentry *);
16902+ mnt = va_arg(ap, struct vfsmount *);
16903+ str1 = va_arg(ap, char *);
16904+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), str1);
16905+ break;
16906+ case GR_FILENAME_TWO_INT:
16907+ dentry = va_arg(ap, struct dentry *);
16908+ mnt = va_arg(ap, struct vfsmount *);
16909+ num1 = va_arg(ap, int);
16910+ num2 = va_arg(ap, int);
16911+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2);
16912+ break;
16913+ case GR_FILENAME_TWO_INT_STR:
16914+ dentry = va_arg(ap, struct dentry *);
16915+ mnt = va_arg(ap, struct vfsmount *);
16916+ num1 = va_arg(ap, int);
16917+ num2 = va_arg(ap, int);
16918+ str1 = va_arg(ap, char *);
16919+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2, str1);
16920+ break;
16921+ case GR_TEXTREL:
16922+ file = va_arg(ap, struct file *);
16923+ ulong1 = va_arg(ap, unsigned long);
16924+ ulong2 = va_arg(ap, unsigned long);
16925+ gr_log_middle_varargs(audit, msg, file ? gr_to_filename(file->f_dentry, file->f_vfsmnt) : "<anonymous mapping>", ulong1, ulong2);
16926+ break;
16927+ case GR_PTRACE:
16928+ task = va_arg(ap, struct task_struct *);
16929+ gr_log_middle_varargs(audit, msg, task->exec_file ? gr_to_filename(task->exec_file->f_dentry, task->exec_file->f_vfsmnt) : "(none)", task->comm, task->pid);
16930+ break;
16931+ case GR_RESOURCE:
16932+ task = va_arg(ap, struct task_struct *);
16933+ ulong1 = va_arg(ap, unsigned long);
16934+ str1 = va_arg(ap, char *);
16935+ ulong2 = va_arg(ap, unsigned long);
16936+ 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);
16937+ break;
16938+ case GR_CAP:
16939+ task = va_arg(ap, struct task_struct *);
16940+ str1 = va_arg(ap, char *);
16941+ 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);
16942+ break;
16943+ case GR_SIG:
16944+ task = va_arg(ap, struct task_struct *);
16945+ num1 = va_arg(ap, int);
16946+ 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);
16947+ break;
16948+ case GR_CRASH1:
16949+ task = va_arg(ap, struct task_struct *);
16950+ ulong1 = va_arg(ap, unsigned long);
16951+ 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);
16952+ break;
16953+ case GR_CRASH2:
16954+ task = va_arg(ap, struct task_struct *);
16955+ ulong1 = va_arg(ap, unsigned long);
16956+ 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);
16957+ break;
16958+ case GR_PSACCT:
16959+ {
16960+ unsigned int wday, cday;
16961+ __u8 whr, chr;
16962+ __u8 wmin, cmin;
16963+ __u8 wsec, csec;
16964+ char cur_tty[64] = { 0 };
16965+ char parent_tty[64] = { 0 };
16966+
16967+ task = va_arg(ap, struct task_struct *);
16968+ wday = va_arg(ap, unsigned int);
16969+ cday = va_arg(ap, unsigned int);
16970+ whr = va_arg(ap, int);
16971+ chr = va_arg(ap, int);
16972+ wmin = va_arg(ap, int);
16973+ cmin = va_arg(ap, int);
16974+ wsec = va_arg(ap, int);
16975+ csec = va_arg(ap, int);
16976+ ulong1 = va_arg(ap, unsigned long);
16977+
16978+ 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);
16979+ }
16980+ break;
16981+ default:
16982+ gr_log_middle(audit, msg, ap);
16983+ }
16984+ va_end(ap);
16985+ gr_log_end(audit);
16986+ END_LOCKS(audit);
16987+}
16988diff -urNp linux-2.6.17.11/grsecurity/grsec_mem.c linux-2.6.17.11/grsecurity/grsec_mem.c
16989--- linux-2.6.17.11/grsecurity/grsec_mem.c 1969-12-31 19:00:00.000000000 -0500
16990+++ linux-2.6.17.11/grsecurity/grsec_mem.c 2006-08-12 08:17:55.000000000 -0400
16991@@ -0,0 +1,71 @@
16992+#include <linux/kernel.h>
16993+#include <linux/sched.h>
16994+#include <linux/mm.h>
16995+#include <linux/mman.h>
16996+#include <linux/grinternal.h>
16997+
16998+void
16999+gr_handle_ioperm(void)
17000+{
17001+ gr_log_noargs(GR_DONT_AUDIT, GR_IOPERM_MSG);
17002+ return;
17003+}
17004+
17005+void
17006+gr_handle_iopl(void)
17007+{
17008+ gr_log_noargs(GR_DONT_AUDIT, GR_IOPL_MSG);
17009+ return;
17010+}
17011+
17012+void
17013+gr_handle_mem_write(void)
17014+{
17015+ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_WRITE_MSG);
17016+ return;
17017+}
17018+
17019+void
17020+gr_handle_kmem_write(void)
17021+{
17022+ gr_log_noargs(GR_DONT_AUDIT, GR_KMEM_MSG);
17023+ return;
17024+}
17025+
17026+void
17027+gr_handle_open_port(void)
17028+{
17029+ gr_log_noargs(GR_DONT_AUDIT, GR_PORT_OPEN_MSG);
17030+ return;
17031+}
17032+
17033+int
17034+gr_handle_mem_mmap(const unsigned long offset, struct vm_area_struct *vma)
17035+{
17036+ unsigned long start, end;
17037+
17038+ start = offset;
17039+ end = start + vma->vm_end - vma->vm_start;
17040+
17041+ if (start > end) {
17042+ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_MMAP_MSG);
17043+ return -EPERM;
17044+ }
17045+
17046+ /* allowed ranges : ISA I/O BIOS */
17047+ if ((start >= __pa(high_memory))
17048+#ifdef CONFIG_X86
17049+ || (start >= 0x000a0000 && end <= 0x00100000)
17050+ || (start >= 0x00000000 && end <= 0x00001000)
17051+#endif
17052+ )
17053+ return 0;
17054+
17055+ if (vma->vm_flags & VM_WRITE) {
17056+ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_MMAP_MSG);
17057+ return -EPERM;
17058+ } else
17059+ vma->vm_flags &= ~VM_MAYWRITE;
17060+
17061+ return 0;
17062+}
17063diff -urNp linux-2.6.17.11/grsecurity/grsec_mount.c linux-2.6.17.11/grsecurity/grsec_mount.c
17064--- linux-2.6.17.11/grsecurity/grsec_mount.c 1969-12-31 19:00:00.000000000 -0500
17065+++ linux-2.6.17.11/grsecurity/grsec_mount.c 2006-08-12 08:17:55.000000000 -0400
17066@@ -0,0 +1,34 @@
17067+#include <linux/kernel.h>
17068+#include <linux/sched.h>
17069+#include <linux/grsecurity.h>
17070+#include <linux/grinternal.h>
17071+
17072+void
17073+gr_log_remount(const char *devname, const int retval)
17074+{
17075+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
17076+ if (grsec_enable_mount && (retval >= 0))
17077+ gr_log_str(GR_DO_AUDIT, GR_REMOUNT_AUDIT_MSG, devname ? devname : "none");
17078+#endif
17079+ return;
17080+}
17081+
17082+void
17083+gr_log_unmount(const char *devname, const int retval)
17084+{
17085+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
17086+ if (grsec_enable_mount && (retval >= 0))
17087+ gr_log_str(GR_DO_AUDIT, GR_UNMOUNT_AUDIT_MSG, devname ? devname : "none");
17088+#endif
17089+ return;
17090+}
17091+
17092+void
17093+gr_log_mount(const char *from, const char *to, const int retval)
17094+{
17095+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
17096+ if (grsec_enable_mount && (retval >= 0))
17097+ gr_log_str_str(GR_DO_AUDIT, GR_MOUNT_AUDIT_MSG, from, to);
17098+#endif
17099+ return;
17100+}
17101diff -urNp linux-2.6.17.11/grsecurity/grsec_rand.c linux-2.6.17.11/grsecurity/grsec_rand.c
17102--- linux-2.6.17.11/grsecurity/grsec_rand.c 1969-12-31 19:00:00.000000000 -0500
17103+++ linux-2.6.17.11/grsecurity/grsec_rand.c 2006-08-12 08:17:55.000000000 -0400
17104@@ -0,0 +1,26 @@
17105+#include <linux/kernel.h>
17106+#include <linux/sched.h>
17107+#include <linux/smp_lock.h>
17108+#include <linux/grsecurity.h>
17109+#include <linux/grinternal.h>
17110+
17111+extern int pid_max;
17112+
17113+int
17114+gr_random_pid(void)
17115+{
17116+#ifdef CONFIG_GRKERNSEC_RANDPID
17117+ int pid;
17118+
17119+ if (grsec_enable_randpid && current->fs->root) {
17120+ /* return a pid in the range 1 ... pid_max - 1
17121+ optimize this so we don't have to do a real division
17122+ */
17123+ pid = 1 + (get_random_long() % pid_max);
17124+ if (pid == pid_max)
17125+ pid = pid_max - 1;
17126+ return pid;
17127+ }
17128+#endif
17129+ return 0;
17130+}
17131diff -urNp linux-2.6.17.11/grsecurity/grsec_sig.c linux-2.6.17.11/grsecurity/grsec_sig.c
17132--- linux-2.6.17.11/grsecurity/grsec_sig.c 1969-12-31 19:00:00.000000000 -0500
17133+++ linux-2.6.17.11/grsecurity/grsec_sig.c 2006-08-12 08:17:55.000000000 -0400
17134@@ -0,0 +1,59 @@
17135+#include <linux/kernel.h>
17136+#include <linux/sched.h>
17137+#include <linux/grsecurity.h>
17138+#include <linux/grinternal.h>
17139+
17140+void
17141+gr_log_signal(const int sig, const struct task_struct *t)
17142+{
17143+#ifdef CONFIG_GRKERNSEC_SIGNAL
17144+ if (grsec_enable_signal && ((sig == SIGSEGV) || (sig == SIGILL) ||
17145+ (sig == SIGABRT) || (sig == SIGBUS))) {
17146+ if (t->pid == current->pid) {
17147+ gr_log_int(GR_DONT_AUDIT_GOOD, GR_UNISIGLOG_MSG, sig);
17148+ } else {
17149+ gr_log_sig(GR_DONT_AUDIT_GOOD, GR_DUALSIGLOG_MSG, t, sig);
17150+ }
17151+ }
17152+#endif
17153+ return;
17154+}
17155+
17156+int
17157+gr_handle_signal(const struct task_struct *p, const int sig)
17158+{
17159+#ifdef CONFIG_GRKERNSEC
17160+ if (current->pid > 1 && gr_check_protected_task(p)) {
17161+ gr_log_sig(GR_DONT_AUDIT, GR_SIG_ACL_MSG, p, sig);
17162+ return -EPERM;
17163+ } else if (gr_pid_is_chrooted((struct task_struct *)p)) {
17164+ return -EPERM;
17165+ }
17166+#endif
17167+ return 0;
17168+}
17169+
17170+void gr_handle_brute_attach(struct task_struct *p)
17171+{
17172+#ifdef CONFIG_GRKERNSEC_BRUTE
17173+ read_lock(&tasklist_lock);
17174+ read_lock(&grsec_exec_file_lock);
17175+ if (p->parent && p->parent->exec_file == p->exec_file)
17176+ p->parent->brute = 1;
17177+ read_unlock(&grsec_exec_file_lock);
17178+ read_unlock(&tasklist_lock);
17179+#endif
17180+ return;
17181+}
17182+
17183+void gr_handle_brute_check(void)
17184+{
17185+#ifdef CONFIG_GRKERNSEC_BRUTE
17186+ if (current->brute) {
17187+ set_current_state(TASK_UNINTERRUPTIBLE);
17188+ schedule_timeout(30 * HZ);
17189+ }
17190+#endif
17191+ return;
17192+}
17193+
17194diff -urNp linux-2.6.17.11/grsecurity/grsec_sock.c linux-2.6.17.11/grsecurity/grsec_sock.c
17195--- linux-2.6.17.11/grsecurity/grsec_sock.c 1969-12-31 19:00:00.000000000 -0500
17196+++ linux-2.6.17.11/grsecurity/grsec_sock.c 2006-08-12 08:17:55.000000000 -0400
17197@@ -0,0 +1,263 @@
17198+#include <linux/kernel.h>
17199+#include <linux/module.h>
17200+#include <linux/sched.h>
17201+#include <linux/file.h>
17202+#include <linux/net.h>
17203+#include <linux/in.h>
17204+#include <linux/ip.h>
17205+#include <net/sock.h>
17206+#include <net/inet_sock.h>
17207+#include <linux/grsecurity.h>
17208+#include <linux/grinternal.h>
17209+#include <linux/gracl.h>
17210+
17211+#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE)
17212+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
17213+EXPORT_SYMBOL(udp_v4_lookup);
17214+#endif
17215+
17216+EXPORT_SYMBOL(gr_cap_rtnetlink);
17217+
17218+extern int gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb);
17219+extern int gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr);
17220+
17221+EXPORT_SYMBOL(gr_search_udp_recvmsg);
17222+EXPORT_SYMBOL(gr_search_udp_sendmsg);
17223+
17224+#ifdef CONFIG_UNIX_MODULE
17225+EXPORT_SYMBOL(gr_acl_handle_unix);
17226+EXPORT_SYMBOL(gr_acl_handle_mknod);
17227+EXPORT_SYMBOL(gr_handle_chroot_unix);
17228+EXPORT_SYMBOL(gr_handle_create);
17229+#endif
17230+
17231+#ifdef CONFIG_GRKERNSEC
17232+#define gr_conn_table_size 32749
17233+struct conn_table_entry {
17234+ struct conn_table_entry *next;
17235+ struct signal_struct *sig;
17236+};
17237+
17238+struct conn_table_entry *gr_conn_table[gr_conn_table_size];
17239+spinlock_t gr_conn_table_lock = SPIN_LOCK_UNLOCKED;
17240+
17241+extern const char * gr_socktype_to_name(unsigned char type);
17242+extern const char * gr_proto_to_name(unsigned char proto);
17243+
17244+static __inline__ int
17245+conn_hash(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, unsigned int size)
17246+{
17247+ return ((daddr + saddr + (sport << 8) + (dport << 16)) % size);
17248+}
17249+
17250+static __inline__ int
17251+conn_match(const struct signal_struct *sig, __u32 saddr, __u32 daddr,
17252+ __u16 sport, __u16 dport)
17253+{
17254+ if (unlikely(sig->gr_saddr == saddr && sig->gr_daddr == daddr &&
17255+ sig->gr_sport == sport && sig->gr_dport == dport))
17256+ return 1;
17257+ else
17258+ return 0;
17259+}
17260+
17261+static void gr_add_to_task_ip_table_nolock(struct signal_struct *sig, struct conn_table_entry *newent)
17262+{
17263+ struct conn_table_entry **match;
17264+ unsigned int index;
17265+
17266+ index = conn_hash(sig->gr_saddr, sig->gr_daddr,
17267+ sig->gr_sport, sig->gr_dport,
17268+ gr_conn_table_size);
17269+
17270+ newent->sig = sig;
17271+
17272+ match = &gr_conn_table[index];
17273+ newent->next = *match;
17274+ *match = newent;
17275+
17276+ return;
17277+}
17278+
17279+static void gr_del_task_from_ip_table_nolock(struct signal_struct *sig)
17280+{
17281+ struct conn_table_entry *match, *last = NULL;
17282+ unsigned int index;
17283+
17284+ index = conn_hash(sig->gr_saddr, sig->gr_daddr,
17285+ sig->gr_sport, sig->gr_dport,
17286+ gr_conn_table_size);
17287+
17288+ match = gr_conn_table[index];
17289+ while (match && !conn_match(match->sig,
17290+ sig->gr_saddr, sig->gr_daddr, sig->gr_sport,
17291+ sig->gr_dport)) {
17292+ last = match;
17293+ match = match->next;
17294+ }
17295+
17296+ if (match) {
17297+ if (last)
17298+ last->next = match->next;
17299+ else
17300+ gr_conn_table[index] = NULL;
17301+ kfree(match);
17302+ }
17303+
17304+ return;
17305+}
17306+
17307+static struct signal_struct * gr_lookup_task_ip_table(__u32 saddr, __u32 daddr,
17308+ __u16 sport, __u16 dport)
17309+{
17310+ struct conn_table_entry *match;
17311+ unsigned int index;
17312+
17313+ index = conn_hash(saddr, daddr, sport, dport, gr_conn_table_size);
17314+
17315+ match = gr_conn_table[index];
17316+ while (match && !conn_match(match->sig, saddr, daddr, sport, dport))
17317+ match = match->next;
17318+
17319+ if (match)
17320+ return match->sig;
17321+ else
17322+ return NULL;
17323+}
17324+
17325+#endif
17326+
17327+void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet)
17328+{
17329+#ifdef CONFIG_GRKERNSEC
17330+ struct signal_struct *sig = task->signal;
17331+ struct conn_table_entry *newent;
17332+
17333+ newent = kmalloc(sizeof(struct conn_table_entry), GFP_ATOMIC);
17334+ if (newent == NULL)
17335+ return;
17336+ /* no bh lock needed since we are called with bh disabled */
17337+ spin_lock(&gr_conn_table_lock);
17338+ gr_del_task_from_ip_table_nolock(sig);
17339+ sig->gr_saddr = inet->rcv_saddr;
17340+ sig->gr_daddr = inet->daddr;
17341+ sig->gr_sport = inet->sport;
17342+ sig->gr_dport = inet->dport;
17343+ gr_add_to_task_ip_table_nolock(sig, newent);
17344+ spin_unlock(&gr_conn_table_lock);
17345+#endif
17346+ return;
17347+}
17348+
17349+void gr_del_task_from_ip_table(struct task_struct *task)
17350+{
17351+#ifdef CONFIG_GRKERNSEC
17352+ spin_lock(&gr_conn_table_lock);
17353+ gr_del_task_from_ip_table_nolock(task->signal);
17354+ spin_unlock(&gr_conn_table_lock);
17355+#endif
17356+ return;
17357+}
17358+
17359+void
17360+gr_attach_curr_ip(const struct sock *sk)
17361+{
17362+#ifdef CONFIG_GRKERNSEC
17363+ struct signal_struct *p, *set;
17364+ const struct inet_sock *inet = inet_sk(sk);
17365+
17366+ if (unlikely(sk->sk_protocol != IPPROTO_TCP))
17367+ return;
17368+
17369+ set = current->signal;
17370+
17371+ spin_lock_bh(&gr_conn_table_lock);
17372+ p = gr_lookup_task_ip_table(inet->daddr, inet->rcv_saddr,
17373+ inet->dport, inet->sport);
17374+ if (unlikely(p != NULL)) {
17375+ set->curr_ip = p->curr_ip;
17376+ set->used_accept = 1;
17377+ gr_del_task_from_ip_table_nolock(p);
17378+ spin_unlock_bh(&gr_conn_table_lock);
17379+ return;
17380+ }
17381+ spin_unlock_bh(&gr_conn_table_lock);
17382+
17383+ set->curr_ip = inet->daddr;
17384+ set->used_accept = 1;
17385+#endif
17386+ return;
17387+}
17388+
17389+int
17390+gr_handle_sock_all(const int family, const int type, const int protocol)
17391+{
17392+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
17393+ if (grsec_enable_socket_all && in_group_p(grsec_socket_all_gid) &&
17394+ (family != AF_UNIX) && (family != AF_LOCAL)) {
17395+ gr_log_int_str2(GR_DONT_AUDIT, GR_SOCK2_MSG, family, gr_socktype_to_name(type), gr_proto_to_name(protocol));
17396+ return -EACCES;
17397+ }
17398+#endif
17399+ return 0;
17400+}
17401+
17402+int
17403+gr_handle_sock_server(const struct sockaddr *sck)
17404+{
17405+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
17406+ if (grsec_enable_socket_server &&
17407+ in_group_p(grsec_socket_server_gid) &&
17408+ sck && (sck->sa_family != AF_UNIX) &&
17409+ (sck->sa_family != AF_LOCAL)) {
17410+ gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
17411+ return -EACCES;
17412+ }
17413+#endif
17414+ return 0;
17415+}
17416+
17417+int
17418+gr_handle_sock_server_other(const struct sock *sck)
17419+{
17420+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
17421+ if (grsec_enable_socket_server &&
17422+ in_group_p(grsec_socket_server_gid) &&
17423+ sck && (sck->sk_family != AF_UNIX) &&
17424+ (sck->sk_family != AF_LOCAL)) {
17425+ gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
17426+ return -EACCES;
17427+ }
17428+#endif
17429+ return 0;
17430+}
17431+
17432+int
17433+gr_handle_sock_client(const struct sockaddr *sck)
17434+{
17435+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
17436+ if (grsec_enable_socket_client && in_group_p(grsec_socket_client_gid) &&
17437+ sck && (sck->sa_family != AF_UNIX) &&
17438+ (sck->sa_family != AF_LOCAL)) {
17439+ gr_log_noargs(GR_DONT_AUDIT, GR_CONNECT_MSG);
17440+ return -EACCES;
17441+ }
17442+#endif
17443+ return 0;
17444+}
17445+
17446+__u32
17447+gr_cap_rtnetlink(void)
17448+{
17449+#ifdef CONFIG_GRKERNSEC
17450+ if (!gr_acl_is_enabled())
17451+ return current->cap_effective;
17452+ else if (cap_raised(current->cap_effective, CAP_NET_ADMIN) &&
17453+ gr_task_is_capable(current, CAP_NET_ADMIN))
17454+ return current->cap_effective;
17455+ else
17456+ return 0;
17457+#else
17458+ return current->cap_effective;
17459+#endif
17460+}
17461diff -urNp linux-2.6.17.11/grsecurity/grsec_sysctl.c linux-2.6.17.11/grsecurity/grsec_sysctl.c
17462--- linux-2.6.17.11/grsecurity/grsec_sysctl.c 1969-12-31 19:00:00.000000000 -0500
17463+++ linux-2.6.17.11/grsecurity/grsec_sysctl.c 2006-08-12 08:17:55.000000000 -0400
17464@@ -0,0 +1,466 @@
17465+#include <linux/kernel.h>
17466+#include <linux/sched.h>
17467+#include <linux/sysctl.h>
17468+#include <linux/grsecurity.h>
17469+#include <linux/grinternal.h>
17470+
17471+#ifdef CONFIG_GRKERNSEC_MODSTOP
17472+int grsec_modstop;
17473+#endif
17474+
17475+int
17476+gr_handle_sysctl_mod(const char *dirname, const char *name, const int op)
17477+{
17478+#ifdef CONFIG_GRKERNSEC_SYSCTL
17479+ if (!strcmp(dirname, "grsecurity") && grsec_lock && (op & 002)) {
17480+ gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name);
17481+ return -EACCES;
17482+ }
17483+#endif
17484+#ifdef CONFIG_GRKERNSEC_MODSTOP
17485+ if (!strcmp(dirname, "grsecurity") && !strcmp(name, "disable_modules") &&
17486+ grsec_modstop && (op & 002)) {
17487+ gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name);
17488+ return -EACCES;
17489+ }
17490+#endif
17491+ return 0;
17492+}
17493+
17494+#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP)
17495+enum {GS_LINK=1, GS_FIFO, GS_EXECVE, GS_EXECLOG, GS_SIGNAL,
17496+GS_FORKFAIL, GS_TIME, GS_CHROOT_SHMAT, GS_CHROOT_UNIX, GS_CHROOT_MNT,
17497+GS_CHROOT_FCHDIR, GS_CHROOT_DBL, GS_CHROOT_PVT, GS_CHROOT_CD, GS_CHROOT_CM,
17498+GS_CHROOT_MK, GS_CHROOT_NI, GS_CHROOT_EXECLOG, GS_CHROOT_CAPS,
17499+GS_CHROOT_SYSCTL, GS_TPE, GS_TPE_GID, GS_TPE_ALL, GS_SIDCAPS,
17500+GS_RANDPID, GS_SOCKET_ALL, GS_SOCKET_ALL_GID, GS_SOCKET_CLIENT,
17501+GS_SOCKET_CLIENT_GID, GS_SOCKET_SERVER, GS_SOCKET_SERVER_GID,
17502+GS_GROUP, GS_GID, GS_ACHDIR, GS_AMOUNT, GS_AIPC, GS_DMSG,
17503+GS_TEXTREL, GS_FINDTASK, GS_SHM, GS_LOCK, GS_MODSTOP, GS_RESLOG};
17504+
17505+
17506+ctl_table grsecurity_table[] = {
17507+#ifdef CONFIG_GRKERNSEC_SYSCTL
17508+#ifdef CONFIG_GRKERNSEC_LINK
17509+ {
17510+ .ctl_name = GS_LINK,
17511+ .procname = "linking_restrictions",
17512+ .data = &grsec_enable_link,
17513+ .maxlen = sizeof(int),
17514+ .mode = 0600,
17515+ .proc_handler = &proc_dointvec,
17516+ },
17517+#endif
17518+#ifdef CONFIG_GRKERNSEC_FIFO
17519+ {
17520+ .ctl_name = GS_FIFO,
17521+ .procname = "fifo_restrictions",
17522+ .data = &grsec_enable_fifo,
17523+ .maxlen = sizeof(int),
17524+ .mode = 0600,
17525+ .proc_handler = &proc_dointvec,
17526+ },
17527+#endif
17528+#ifdef CONFIG_GRKERNSEC_EXECVE
17529+ {
17530+ .ctl_name = GS_EXECVE,
17531+ .procname = "execve_limiting",
17532+ .data = &grsec_enable_execve,
17533+ .maxlen = sizeof(int),
17534+ .mode = 0600,
17535+ .proc_handler = &proc_dointvec,
17536+ },
17537+#endif
17538+#ifdef CONFIG_GRKERNSEC_EXECLOG
17539+ {
17540+ .ctl_name = GS_EXECLOG,
17541+ .procname = "exec_logging",
17542+ .data = &grsec_enable_execlog,
17543+ .maxlen = sizeof(int),
17544+ .mode = 0600,
17545+ .proc_handler = &proc_dointvec,
17546+ },
17547+#endif
17548+#ifdef CONFIG_GRKERNSEC_SIGNAL
17549+ {
17550+ .ctl_name = GS_SIGNAL,
17551+ .procname = "signal_logging",
17552+ .data = &grsec_enable_signal,
17553+ .maxlen = sizeof(int),
17554+ .mode = 0600,
17555+ .proc_handler = &proc_dointvec,
17556+ },
17557+#endif
17558+#ifdef CONFIG_GRKERNSEC_FORKFAIL
17559+ {
17560+ .ctl_name = GS_FORKFAIL,
17561+ .procname = "forkfail_logging",
17562+ .data = &grsec_enable_forkfail,
17563+ .maxlen = sizeof(int),
17564+ .mode = 0600,
17565+ .proc_handler = &proc_dointvec,
17566+ },
17567+#endif
17568+#ifdef CONFIG_GRKERNSEC_TIME
17569+ {
17570+ .ctl_name = GS_TIME,
17571+ .procname = "timechange_logging",
17572+ .data = &grsec_enable_time,
17573+ .maxlen = sizeof(int),
17574+ .mode = 0600,
17575+ .proc_handler = &proc_dointvec,
17576+ },
17577+#endif
17578+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
17579+ {
17580+ .ctl_name = GS_CHROOT_SHMAT,
17581+ .procname = "chroot_deny_shmat",
17582+ .data = &grsec_enable_chroot_shmat,
17583+ .maxlen = sizeof(int),
17584+ .mode = 0600,
17585+ .proc_handler = &proc_dointvec,
17586+ },
17587+#endif
17588+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
17589+ {
17590+ .ctl_name = GS_CHROOT_UNIX,
17591+ .procname = "chroot_deny_unix",
17592+ .data = &grsec_enable_chroot_unix,
17593+ .maxlen = sizeof(int),
17594+ .mode = 0600,
17595+ .proc_handler = &proc_dointvec,
17596+ },
17597+#endif
17598+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
17599+ {
17600+ .ctl_name = GS_CHROOT_MNT,
17601+ .procname = "chroot_deny_mount",
17602+ .data = &grsec_enable_chroot_mount,
17603+ .maxlen = sizeof(int),
17604+ .mode = 0600,
17605+ .proc_handler = &proc_dointvec,
17606+ },
17607+#endif
17608+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
17609+ {
17610+ .ctl_name = GS_CHROOT_FCHDIR,
17611+ .procname = "chroot_deny_fchdir",
17612+ .data = &grsec_enable_chroot_fchdir,
17613+ .maxlen = sizeof(int),
17614+ .mode = 0600,
17615+ .proc_handler = &proc_dointvec,
17616+ },
17617+#endif
17618+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
17619+ {
17620+ .ctl_name = GS_CHROOT_DBL,
17621+ .procname = "chroot_deny_chroot",
17622+ .data = &grsec_enable_chroot_double,
17623+ .maxlen = sizeof(int),
17624+ .mode = 0600,
17625+ .proc_handler = &proc_dointvec,
17626+ },
17627+#endif
17628+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
17629+ {
17630+ .ctl_name = GS_CHROOT_PVT,
17631+ .procname = "chroot_deny_pivot",
17632+ .data = &grsec_enable_chroot_pivot,
17633+ .maxlen = sizeof(int),
17634+ .mode = 0600,
17635+ .proc_handler = &proc_dointvec,
17636+ },
17637+#endif
17638+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
17639+ {
17640+ .ctl_name = GS_CHROOT_CD,
17641+ .procname = "chroot_enforce_chdir",
17642+ .data = &grsec_enable_chroot_chdir,
17643+ .maxlen = sizeof(int),
17644+ .mode = 0600,
17645+ .proc_handler = &proc_dointvec,
17646+ },
17647+#endif
17648+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
17649+ {
17650+ .ctl_name = GS_CHROOT_CM,
17651+ .procname = "chroot_deny_chmod",
17652+ .data = &grsec_enable_chroot_chmod,
17653+ .maxlen = sizeof(int),
17654+ .mode = 0600,
17655+ .proc_handler = &proc_dointvec,
17656+ },
17657+#endif
17658+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
17659+ {
17660+ .ctl_name = GS_CHROOT_MK,
17661+ .procname = "chroot_deny_mknod",
17662+ .data = &grsec_enable_chroot_mknod,
17663+ .maxlen = sizeof(int),
17664+ .mode = 0600,
17665+ .proc_handler = &proc_dointvec,
17666+ },
17667+#endif
17668+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
17669+ {
17670+ .ctl_name = GS_CHROOT_NI,
17671+ .procname = "chroot_restrict_nice",
17672+ .data = &grsec_enable_chroot_nice,
17673+ .maxlen = sizeof(int),
17674+ .mode = 0600,
17675+ .proc_handler = &proc_dointvec,
17676+ },
17677+#endif
17678+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
17679+ {
17680+ .ctl_name = GS_CHROOT_EXECLOG,
17681+ .procname = "chroot_execlog",
17682+ .data = &grsec_enable_chroot_execlog,
17683+ .maxlen = sizeof(int),
17684+ .mode = 0600,
17685+ .proc_handler = &proc_dointvec,
17686+ },
17687+#endif
17688+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
17689+ {
17690+ .ctl_name = GS_CHROOT_CAPS,
17691+ .procname = "chroot_caps",
17692+ .data = &grsec_enable_chroot_caps,
17693+ .maxlen = sizeof(int),
17694+ .mode = 0600,
17695+ .proc_handler = &proc_dointvec,
17696+ },
17697+#endif
17698+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
17699+ {
17700+ .ctl_name = GS_CHROOT_SYSCTL,
17701+ .procname = "chroot_deny_sysctl",
17702+ .data = &grsec_enable_chroot_sysctl,
17703+ .maxlen = sizeof(int),
17704+ .mode = 0600,
17705+ .proc_handler = &proc_dointvec,
17706+ },
17707+#endif
17708+#ifdef CONFIG_GRKERNSEC_TPE
17709+ {
17710+ .ctl_name = GS_TPE,
17711+ .procname = "tpe",
17712+ .data = &grsec_enable_tpe,
17713+ .maxlen = sizeof(int),
17714+ .mode = 0600,
17715+ .proc_handler = &proc_dointvec,
17716+ },
17717+ {
17718+ .ctl_name = GS_TPE_GID,
17719+ .procname = "tpe_gid",
17720+ .data = &grsec_tpe_gid,
17721+ .maxlen = sizeof(int),
17722+ .mode = 0600,
17723+ .proc_handler = &proc_dointvec,
17724+ },
17725+#endif
17726+#ifdef CONFIG_GRKERNSEC_TPE_ALL
17727+ {
17728+ .ctl_name = GS_TPE_ALL,
17729+ .procname = "tpe_restrict_all",
17730+ .data = &grsec_enable_tpe_all,
17731+ .maxlen = sizeof(int),
17732+ .mode = 0600,
17733+ .proc_handler = &proc_dointvec,
17734+ },
17735+#endif
17736+#ifdef CONFIG_GRKERNSEC_RANDPID
17737+ {
17738+ .ctl_name = GS_RANDPID,
17739+ .procname = "rand_pids",
17740+ .data = &grsec_enable_randpid,
17741+ .maxlen = sizeof(int),
17742+ .mode = 0600,
17743+ .proc_handler = &proc_dointvec,
17744+ },
17745+#endif
17746+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
17747+ {
17748+ .ctl_name = GS_SOCKET_ALL,
17749+ .procname = "socket_all",
17750+ .data = &grsec_enable_socket_all,
17751+ .maxlen = sizeof(int),
17752+ .mode = 0600,
17753+ .proc_handler = &proc_dointvec,
17754+ },
17755+ {
17756+ .ctl_name = GS_SOCKET_ALL_GID,
17757+ .procname = "socket_all_gid",
17758+ .data = &grsec_socket_all_gid,
17759+ .maxlen = sizeof(int),
17760+ .mode = 0600,
17761+ .proc_handler = &proc_dointvec,
17762+ },
17763+#endif
17764+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
17765+ {
17766+ .ctl_name = GS_SOCKET_CLIENT,
17767+ .procname = "socket_client",
17768+ .data = &grsec_enable_socket_client,
17769+ .maxlen = sizeof(int),
17770+ .mode = 0600,
17771+ .proc_handler = &proc_dointvec,
17772+ },
17773+ {
17774+ .ctl_name = GS_SOCKET_CLIENT_GID,
17775+ .procname = "socket_client_gid",
17776+ .data = &grsec_socket_client_gid,
17777+ .maxlen = sizeof(int),
17778+ .mode = 0600,
17779+ .proc_handler = &proc_dointvec,
17780+ },
17781+#endif
17782+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
17783+ {
17784+ .ctl_name = GS_SOCKET_SERVER,
17785+ .procname = "socket_server",
17786+ .data = &grsec_enable_socket_server,
17787+ .maxlen = sizeof(int),
17788+ .mode = 0600,
17789+ .proc_handler = &proc_dointvec,
17790+ },
17791+ {
17792+ .ctl_name = GS_SOCKET_SERVER_GID,
17793+ .procname = "socket_server_gid",
17794+ .data = &grsec_socket_server_gid,
17795+ .maxlen = sizeof(int),
17796+ .mode = 0600,
17797+ .proc_handler = &proc_dointvec,
17798+ },
17799+#endif
17800+#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
17801+ {
17802+ .ctl_name = GS_GROUP,
17803+ .procname = "audit_group",
17804+ .data = &grsec_enable_group,
17805+ .maxlen = sizeof(int),
17806+ .mode = 0600,
17807+ .proc_handler = &proc_dointvec,
17808+ },
17809+ {
17810+ .ctl_name = GS_GID,
17811+ .procname = "audit_gid",
17812+ .data = &grsec_audit_gid,
17813+ .maxlen = sizeof(int),
17814+ .mode = 0600,
17815+ .proc_handler = &proc_dointvec,
17816+ },
17817+#endif
17818+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
17819+ {
17820+ .ctl_name = GS_ACHDIR,
17821+ .procname = "audit_chdir",
17822+ .data = &grsec_enable_chdir,
17823+ .maxlen = sizeof(int),
17824+ .mode = 0600,
17825+ .proc_handler = &proc_dointvec,
17826+ },
17827+#endif
17828+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
17829+ {
17830+ .ctl_name = GS_AMOUNT,
17831+ .procname = "audit_mount",
17832+ .data = &grsec_enable_mount,
17833+ .maxlen = sizeof(int),
17834+ .mode = 0600,
17835+ .proc_handler = &proc_dointvec,
17836+ },
17837+#endif
17838+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
17839+ {
17840+ .ctl_name = GS_AIPC,
17841+ .procname = "audit_ipc",
17842+ .data = &grsec_enable_audit_ipc,
17843+ .maxlen = sizeof(int),
17844+ .mode = 0600,
17845+ .proc_handler = &proc_dointvec,
17846+ },
17847+#endif
17848+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
17849+ {
17850+ .ctl_name = GS_TEXTREL,
17851+ .procname = "audit_textrel",
17852+ .data = &grsec_enable_audit_textrel,
17853+ .maxlen = sizeof(int),
17854+ .mode = 0600,
17855+ .proc_handler = &proc_dointvec,
17856+ },
17857+#endif
17858+#ifdef CONFIG_GRKERNSEC_DMESG
17859+ {
17860+ .ctl_name = GS_DMSG,
17861+ .procname = "dmesg",
17862+ .data = &grsec_enable_dmesg,
17863+ .maxlen = sizeof(int),
17864+ .mode = 0600,
17865+ .proc_handler = &proc_dointvec,
17866+ },
17867+#endif
17868+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
17869+ {
17870+ .ctl_name = GS_FINDTASK,
17871+ .procname = "chroot_findtask",
17872+ .data = &grsec_enable_chroot_findtask,
17873+ .maxlen = sizeof(int),
17874+ .mode = 0600,
17875+ .proc_handler = &proc_dointvec,
17876+ },
17877+#endif
17878+#ifdef CONFIG_GRKERNSEC_SHM
17879+ {
17880+ .ctl_name = GS_SHM,
17881+ .procname = "destroy_unused_shm",
17882+ .data = &grsec_enable_shm,
17883+ .maxlen = sizeof(int),
17884+ .mode = 0600,
17885+ .proc_handler = &proc_dointvec,
17886+ },
17887+#endif
17888+#ifdef CONFIG_GRKERNSEC_RESLOG
17889+ {
17890+ .ctl_name = GS_RESLOG,
17891+ .procname = "resource_logging",
17892+ .data = &grsec_resource_logging,
17893+ .maxlen = sizeof(int),
17894+ .mode = 0600,
17895+ .proc_handler = &proc_dointvec,
17896+ },
17897+#endif
17898+ {
17899+ .ctl_name = GS_LOCK,
17900+ .procname = "grsec_lock",
17901+ .data = &grsec_lock,
17902+ .maxlen = sizeof(int),
17903+ .mode = 0600,
17904+ .proc_handler = &proc_dointvec,
17905+ },
17906+#endif
17907+#ifdef CONFIG_GRKERNSEC_MODSTOP
17908+ {
17909+ .ctl_name = GS_MODSTOP,
17910+ .procname = "disable_modules",
17911+ .data = &grsec_modstop,
17912+ .maxlen = sizeof(int),
17913+ .mode = 0600,
17914+ .proc_handler = &proc_dointvec,
17915+ },
17916+#endif
17917+ { .ctl_name = 0 }
17918+};
17919+#endif
17920+
17921+int gr_check_modstop(void)
17922+{
17923+#ifdef CONFIG_GRKERNSEC_MODSTOP
17924+ if (grsec_modstop == 1) {
17925+ gr_log_noargs(GR_DONT_AUDIT, GR_STOPMOD_MSG);
17926+ return 1;
17927+ }
17928+#endif
17929+ return 0;
17930+}
17931diff -urNp linux-2.6.17.11/grsecurity/grsec_textrel.c linux-2.6.17.11/grsecurity/grsec_textrel.c
17932--- linux-2.6.17.11/grsecurity/grsec_textrel.c 1969-12-31 19:00:00.000000000 -0500
17933+++ linux-2.6.17.11/grsecurity/grsec_textrel.c 2006-08-12 08:17:55.000000000 -0400
17934@@ -0,0 +1,16 @@
17935+#include <linux/kernel.h>
17936+#include <linux/sched.h>
17937+#include <linux/mm.h>
17938+#include <linux/file.h>
17939+#include <linux/grinternal.h>
17940+#include <linux/grsecurity.h>
17941+
17942+void
17943+gr_log_textrel(struct vm_area_struct * vma)
17944+{
17945+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
17946+ if (grsec_enable_audit_textrel)
17947+ gr_log_textrel_ulong_ulong(GR_DO_AUDIT, GR_TEXTREL_AUDIT_MSG, vma->vm_file, vma->vm_start, vma->vm_pgoff);
17948+#endif
17949+ return;
17950+}
17951diff -urNp linux-2.6.17.11/grsecurity/grsec_time.c linux-2.6.17.11/grsecurity/grsec_time.c
17952--- linux-2.6.17.11/grsecurity/grsec_time.c 1969-12-31 19:00:00.000000000 -0500
17953+++ linux-2.6.17.11/grsecurity/grsec_time.c 2006-08-12 08:17:55.000000000 -0400
17954@@ -0,0 +1,13 @@
17955+#include <linux/kernel.h>
17956+#include <linux/sched.h>
17957+#include <linux/grinternal.h>
17958+
17959+void
17960+gr_log_timechange(void)
17961+{
17962+#ifdef CONFIG_GRKERNSEC_TIME
17963+ if (grsec_enable_time)
17964+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_TIME_MSG);
17965+#endif
17966+ return;
17967+}
17968diff -urNp linux-2.6.17.11/grsecurity/grsec_tpe.c linux-2.6.17.11/grsecurity/grsec_tpe.c
17969--- linux-2.6.17.11/grsecurity/grsec_tpe.c 1969-12-31 19:00:00.000000000 -0500
17970+++ linux-2.6.17.11/grsecurity/grsec_tpe.c 2006-08-12 08:17:55.000000000 -0400
17971@@ -0,0 +1,37 @@
17972+#include <linux/kernel.h>
17973+#include <linux/sched.h>
17974+#include <linux/file.h>
17975+#include <linux/fs.h>
17976+#include <linux/grinternal.h>
17977+
17978+extern int gr_acl_tpe_check(void);
17979+
17980+int
17981+gr_tpe_allow(const struct file *file)
17982+{
17983+#ifdef CONFIG_GRKERNSEC
17984+ struct inode *inode = file->f_dentry->d_parent->d_inode;
17985+
17986+ if (current->uid && ((grsec_enable_tpe &&
17987+#ifdef CONFIG_GRKERNSEC_TPE_INVERT
17988+ !in_group_p(grsec_tpe_gid)
17989+#else
17990+ in_group_p(grsec_tpe_gid)
17991+#endif
17992+ ) || gr_acl_tpe_check()) &&
17993+ (inode->i_uid || (!inode->i_uid && ((inode->i_mode & S_IWGRP) ||
17994+ (inode->i_mode & S_IWOTH))))) {
17995+ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_dentry, file->f_vfsmnt);
17996+ return 0;
17997+ }
17998+#ifdef CONFIG_GRKERNSEC_TPE_ALL
17999+ if (current->uid && grsec_enable_tpe && grsec_enable_tpe_all &&
18000+ ((inode->i_uid && (inode->i_uid != current->uid)) ||
18001+ (inode->i_mode & S_IWGRP) || (inode->i_mode & S_IWOTH))) {
18002+ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_dentry, file->f_vfsmnt);
18003+ return 0;
18004+ }
18005+#endif
18006+#endif
18007+ return 1;
18008+}
18009diff -urNp linux-2.6.17.11/grsecurity/grsum.c linux-2.6.17.11/grsecurity/grsum.c
18010--- linux-2.6.17.11/grsecurity/grsum.c 1969-12-31 19:00:00.000000000 -0500
18011+++ linux-2.6.17.11/grsecurity/grsum.c 2006-08-12 08:17:55.000000000 -0400
18012@@ -0,0 +1,59 @@
18013+#include <linux/kernel.h>
18014+#include <linux/sched.h>
18015+#include <linux/mm.h>
18016+#include <asm/scatterlist.h>
18017+#include <linux/crypto.h>
18018+#include <linux/gracl.h>
18019+
18020+
18021+#if !defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE) || !defined(CONFIG_CRYPTO_SHA256) || defined(CONFIG_CRYPTO_SHA256_MODULE)
18022+#error "crypto and sha256 must be built into the kernel"
18023+#endif
18024+
18025+int
18026+chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum)
18027+{
18028+ char *p;
18029+ struct crypto_tfm *tfm;
18030+ unsigned char temp_sum[GR_SHA_LEN];
18031+ struct scatterlist sg[2];
18032+ volatile int retval = 0;
18033+ volatile int dummy = 0;
18034+ unsigned int i;
18035+
18036+ tfm = crypto_alloc_tfm("sha256", 0);
18037+ if (tfm == NULL) {
18038+ /* should never happen, since sha256 should be built in */
18039+ return 1;
18040+ }
18041+
18042+ crypto_digest_init(tfm);
18043+
18044+ p = salt;
18045+ sg[0].page = virt_to_page(p);
18046+ sg[0].offset = ((long) p & ~PAGE_MASK);
18047+ sg[0].length = GR_SALT_LEN;
18048+
18049+ crypto_digest_update(tfm, sg, 1);
18050+
18051+ p = entry->pw;
18052+ sg[0].page = virt_to_page(p);
18053+ sg[0].offset = ((long) p & ~PAGE_MASK);
18054+ sg[0].length = strlen(entry->pw);
18055+
18056+ crypto_digest_update(tfm, sg, 1);
18057+
18058+ crypto_digest_final(tfm, temp_sum);
18059+
18060+ memset(entry->pw, 0, GR_PW_LEN);
18061+
18062+ for (i = 0; i < GR_SHA_LEN; i++)
18063+ if (sum[i] != temp_sum[i])
18064+ retval = 1;
18065+ else
18066+ dummy = 1; // waste a cycle
18067+
18068+ crypto_free_tfm(tfm);
18069+
18070+ return retval;
18071+}
18072diff -urNp linux-2.6.17.11/grsecurity/Kconfig linux-2.6.17.11/grsecurity/Kconfig
18073--- linux-2.6.17.11/grsecurity/Kconfig 1969-12-31 19:00:00.000000000 -0500
18074+++ linux-2.6.17.11/grsecurity/Kconfig 2006-08-12 08:17:55.000000000 -0400
18075@@ -0,0 +1,890 @@
18076+#
18077+# grecurity configuration
18078+#
18079+
18080+menu "Grsecurity"
18081+
18082+config GRKERNSEC
18083+ bool "Grsecurity"
18084+ select CRYPTO
18085+ select CRYPTO_SHA256
18086+ help
18087+ If you say Y here, you will be able to configure many features
18088+ that will enhance the security of your system. It is highly
18089+ recommended that you say Y here and read through the help
18090+ for each option so that you fully understand the features and
18091+ can evaluate their usefulness for your machine.
18092+
18093+choice
18094+ prompt "Security Level"
18095+ depends GRKERNSEC
18096+ default GRKERNSEC_CUSTOM
18097+
18098+config GRKERNSEC_LOW
18099+ bool "Low"
18100+ select GRKERNSEC_LINK
18101+ select GRKERNSEC_FIFO
18102+ select GRKERNSEC_RANDPID
18103+ select GRKERNSEC_EXECVE
18104+ select GRKERNSEC_RANDNET
18105+ select GRKERNSEC_DMESG
18106+ select GRKERNSEC_CHROOT_CHDIR
18107+ select GRKERNSEC_MODSTOP if (MODULES)
18108+
18109+ help
18110+ If you choose this option, several of the grsecurity options will
18111+ be enabled that will give you greater protection against a number
18112+ of attacks, while assuring that none of your software will have any
18113+ conflicts with the additional security measures. If you run a lot
18114+ of unusual software, or you are having problems with the higher
18115+ security levels, you should say Y here. With this option, the
18116+ following features are enabled:
18117+
18118+ - Linking restrictions
18119+ - FIFO restrictions
18120+ - Randomized PIDs
18121+ - Enforcing RLIMIT_NPROC on execve
18122+ - Restricted dmesg
18123+ - Enforced chdir("/") on chroot
18124+ - Runtime module disabling
18125+
18126+config GRKERNSEC_MEDIUM
18127+ bool "Medium"
18128+ select PAX
18129+ select PAX_EI_PAX
18130+ select PAX_PT_PAX_FLAGS
18131+ select PAX_HAVE_ACL_FLAGS
18132+ select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR)
18133+ select GRKERNSEC_CHROOT_SYSCTL
18134+ select GRKERNSEC_LINK
18135+ select GRKERNSEC_FIFO
18136+ select GRKERNSEC_RANDPID
18137+ select GRKERNSEC_EXECVE
18138+ select GRKERNSEC_DMESG
18139+ select GRKERNSEC_RANDNET
18140+ select GRKERNSEC_FORKFAIL
18141+ select GRKERNSEC_TIME
18142+ select GRKERNSEC_SIGNAL
18143+ select GRKERNSEC_CHROOT
18144+ select GRKERNSEC_CHROOT_UNIX
18145+ select GRKERNSEC_CHROOT_MOUNT
18146+ select GRKERNSEC_CHROOT_PIVOT
18147+ select GRKERNSEC_CHROOT_DOUBLE
18148+ select GRKERNSEC_CHROOT_CHDIR
18149+ select GRKERNSEC_CHROOT_MKNOD
18150+ select GRKERNSEC_PROC
18151+ select GRKERNSEC_PROC_USERGROUP
18152+ select GRKERNSEC_MODSTOP if (MODULES)
18153+ select PAX_RANDUSTACK
18154+ select PAX_ASLR
18155+ select PAX_RANDMMAP
18156+ select PAX_NOVSYSCALL if (X86 && !X86_64)
18157+
18158+ help
18159+ If you say Y here, several features in addition to those included
18160+ in the low additional security level will be enabled. These
18161+ features provide even more security to your system, though in rare
18162+ cases they may be incompatible with very old or poorly written
18163+ software. If you enable this option, make sure that your auth
18164+ service (identd) is running as gid 1001. With this option,
18165+ the following features (in addition to those provided in the
18166+ low additional security level) will be enabled:
18167+
18168+ - Randomized TCP source ports
18169+ - Failed fork logging
18170+ - Time change logging
18171+ - Signal logging
18172+ - Deny mounts in chroot
18173+ - Deny double chrooting
18174+ - Deny sysctl writes in chroot
18175+ - Deny mknod in chroot
18176+ - Deny access to abstract AF_UNIX sockets out of chroot
18177+ - Deny pivot_root in chroot
18178+ - Denied writes of /dev/kmem, /dev/mem, and /dev/port
18179+ - /proc restrictions with special GID set to 10 (usually wheel)
18180+ - Address Space Layout Randomization (ASLR)
18181+
18182+config GRKERNSEC_HIGH
18183+ bool "High"
18184+ select GRKERNSEC_LINK
18185+ select GRKERNSEC_FIFO
18186+ select GRKERNSEC_RANDPID
18187+ select GRKERNSEC_EXECVE
18188+ select GRKERNSEC_DMESG
18189+ select GRKERNSEC_FORKFAIL
18190+ select GRKERNSEC_TIME
18191+ select GRKERNSEC_SIGNAL
18192+ select GRKERNSEC_CHROOT_SHMAT
18193+ select GRKERNSEC_CHROOT_UNIX
18194+ select GRKERNSEC_CHROOT_MOUNT
18195+ select GRKERNSEC_CHROOT_FCHDIR
18196+ select GRKERNSEC_CHROOT_PIVOT
18197+ select GRKERNSEC_CHROOT_DOUBLE
18198+ select GRKERNSEC_CHROOT_CHDIR
18199+ select GRKERNSEC_CHROOT_MKNOD
18200+ select GRKERNSEC_CHROOT_CAPS
18201+ select GRKERNSEC_CHROOT_SYSCTL
18202+ select GRKERNSEC_CHROOT_FINDTASK
18203+ select GRKERNSEC_PROC
18204+ select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR)
18205+ select GRKERNSEC_HIDESYM
18206+ select GRKERNSEC_BRUTE
18207+ select GRKERNSEC_SHM if (SYSVIPC)
18208+ select GRKERNSEC_PROC_USERGROUP
18209+ select GRKERNSEC_KMEM
18210+ select GRKERNSEC_RESLOG
18211+ select GRKERNSEC_RANDNET
18212+ select GRKERNSEC_PROC_ADD
18213+ select GRKERNSEC_CHROOT_CHMOD
18214+ select GRKERNSEC_CHROOT_NICE
18215+ select GRKERNSEC_AUDIT_MOUNT
18216+ select GRKERNSEC_MODSTOP if (MODULES)
18217+ select PAX
18218+ select PAX_RANDUSTACK
18219+ select PAX_ASLR
18220+ select PAX_RANDMMAP
18221+ select PAX_NOEXEC
18222+ select PAX_MPROTECT
18223+ select PAX_EI_PAX
18224+ select PAX_PT_PAX_FLAGS
18225+ select PAX_HAVE_ACL_FLAGS
18226+ select PAX_KERNEXEC if (!X86_64 && !MODULES && !HOTPLUG_PCI_COMPAQ_NVRAM && !PCI_BIOS)
18227+ select PAX_RANDKSTACK if (X86_TSC && !X86_64)
18228+ select PAX_SEGMEXEC if (X86 && !X86_64)
18229+ select PAX_PAGEEXEC if (!X86)
18230+ select PAX_EMUPLT if (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64)
18231+ select PAX_DLRESOLVE if (SPARC32 || SPARC64)
18232+ select PAX_SYSCALL if (PPC32)
18233+ select PAX_EMUTRAMP if (PARISC)
18234+ select PAX_EMUSIGRT if (PARISC)
18235+ select PAX_NOVSYSCALL if (X86 && !X86_64)
18236+ select PAX_ETEXECRELOCS if (ALPHA || IA64 || PARISC)
18237+ help
18238+ If you say Y here, many of the features of grsecurity will be
18239+ enabled, which will protect you against many kinds of attacks
18240+ against your system. The heightened security comes at a cost
18241+ of an increased chance of incompatibilities with rare software
18242+ on your machine. Since this security level enables PaX, you should
18243+ view <http://pax.grsecurity.net> and read about the PaX
18244+ project. While you are there, download chpax and run it on
18245+ binaries that cause problems with PaX. Also remember that
18246+ since the /proc restrictions are enabled, you must run your
18247+ identd as gid 1001. This security level enables the following
18248+ features in addition to those listed in the low and medium
18249+ security levels:
18250+
18251+ - Additional /proc restrictions
18252+ - Chmod restrictions in chroot
18253+ - No signals, ptrace, or viewing of processes outside of chroot
18254+ - Capability restrictions in chroot
18255+ - Deny fchdir out of chroot
18256+ - Priority restrictions in chroot
18257+ - Segmentation-based implementation of PaX
18258+ - Mprotect restrictions
18259+ - Removal of addresses from /proc/<pid>/[smaps|maps|stat]
18260+ - Kernel stack randomization
18261+ - Mount/unmount/remount logging
18262+ - Kernel symbol hiding
18263+ - Destroy unused shared memory
18264+ - Prevention of memory exhaustion-based exploits
18265+config GRKERNSEC_CUSTOM
18266+ bool "Custom"
18267+ help
18268+ If you say Y here, you will be able to configure every grsecurity
18269+ option, which allows you to enable many more features that aren't
18270+ covered in the basic security levels. These additional features
18271+ include TPE, socket restrictions, and the sysctl system for
18272+ grsecurity. It is advised that you read through the help for
18273+ each option to determine its usefulness in your situation.
18274+
18275+endchoice
18276+
18277+menu "Address Space Protection"
18278+depends on GRKERNSEC
18279+
18280+config GRKERNSEC_KMEM
18281+ bool "Deny writing to /dev/kmem, /dev/mem, and /dev/port"
18282+ help
18283+ If you say Y here, /dev/kmem and /dev/mem won't be allowed to
18284+ be written to via mmap or otherwise to modify the running kernel.
18285+ /dev/port will also not be allowed to be opened. If you have module
18286+ support disabled, enabling this will close up four ways that are
18287+ currently used to insert malicious code into the running kernel.
18288+ Even with all these features enabled, we still highly recommend that
18289+ you use the RBAC system, as it is still possible for an attacker to
18290+ modify the running kernel through privileged I/O granted by ioperm/iopl.
18291+ If you are not using XFree86, you may be able to stop this additional
18292+ case by enabling the 'Disable privileged I/O' option. Though nothing
18293+ legitimately writes to /dev/kmem, XFree86 does need to write to /dev/mem,
18294+ but only to video memory, which is the only writing we allow in this
18295+ case. If /dev/kmem or /dev/mem are mmaped without PROT_WRITE, they will
18296+ not be allowed to mprotect it with PROT_WRITE later.
18297+ It is highly recommended that you say Y here if you meet all the
18298+ conditions above.
18299+
18300+config GRKERNSEC_IO
18301+ bool "Disable privileged I/O"
18302+ depends on X86
18303+ select RTC
18304+ help
18305+ If you say Y here, all ioperm and iopl calls will return an error.
18306+ Ioperm and iopl can be used to modify the running kernel.
18307+ Unfortunately, some programs need this access to operate properly,
18308+ the most notable of which are XFree86 and hwclock. hwclock can be
18309+ remedied by having RTC support in the kernel, so CONFIG_RTC is
18310+ enabled if this option is enabled, to ensure that hwclock operates
18311+ correctly. XFree86 still will not operate correctly with this option
18312+ enabled, so DO NOT CHOOSE Y IF YOU USE XFree86. If you use XFree86
18313+ and you still want to protect your kernel against modification,
18314+ use the RBAC system.
18315+
18316+config GRKERNSEC_PROC_MEMMAP
18317+ bool "Remove addresses from /proc/<pid>/[smaps|maps|stat]"
18318+ depends on PAX_NOEXEC || PAX_ASLR
18319+ help
18320+ If you say Y here, the /proc/<pid>/maps and /proc/<pid>/stat files will
18321+ give no information about the addresses of its mappings if
18322+ PaX features that rely on random addresses are enabled on the task.
18323+ If you use PaX it is greatly recommended that you say Y here as it
18324+ closes up a hole that makes the full ASLR useless for suid
18325+ binaries.
18326+
18327+config GRKERNSEC_BRUTE
18328+ bool "Deter exploit bruteforcing"
18329+ help
18330+ If you say Y here, attempts to bruteforce exploits against forking
18331+ daemons such as apache or sshd will be deterred. When a child of a
18332+ forking daemon is killed by PaX or crashes due to an illegal
18333+ instruction, the parent process will be delayed 30 seconds upon every
18334+ subsequent fork until the administrator is able to assess the
18335+ situation and restart the daemon. It is recommended that you also
18336+ enable signal logging in the auditing section so that logs are
18337+ generated when a process performs an illegal instruction.
18338+
18339+config GRKERNSEC_MODSTOP
18340+ bool "Runtime module disabling"
18341+ depends on MODULES
18342+ help
18343+ If you say Y here, you will be able to disable the ability to (un)load
18344+ modules at runtime. This feature is useful if you need the ability
18345+ to load kernel modules at boot time, but do not want to allow an
18346+ attacker to load a rootkit kernel module into the system, or to remove
18347+ a loaded kernel module important to system functioning. You should
18348+ enable the /dev/mem protection feature as well, since rootkits can be
18349+ inserted into the kernel via other methods than kernel modules. Since
18350+ an untrusted module could still be loaded by modifying init scripts and
18351+ rebooting the system, it is also recommended that you enable the RBAC
18352+ system. If you enable this option, a sysctl option with name
18353+ "disable_modules" will be created. Setting this option to "1" disables
18354+ module loading. After this option is set, no further writes to it are
18355+ allowed until the system is rebooted.
18356+
18357+config GRKERNSEC_HIDESYM
18358+ bool "Hide kernel symbols"
18359+ help
18360+ If you say Y here, getting information on loaded modules, and
18361+ displaying all kernel symbols through a syscall will be restricted
18362+ to users with CAP_SYS_MODULE. This option is only effective
18363+ provided the following conditions are met:
18364+ 1) The kernel using grsecurity is not precompiled by some distribution
18365+ 2) You are using the RBAC system and hiding other files such as your
18366+ kernel image and System.map
18367+ 3) You have the additional /proc restrictions enabled, which removes
18368+ /proc/kcore
18369+ If the above conditions are met, this option will aid to provide a
18370+ useful protection against local and remote kernel exploitation of
18371+ overflows and arbitrary read/write vulnerabilities.
18372+
18373+endmenu
18374+menu "Role Based Access Control Options"
18375+depends on GRKERNSEC
18376+
18377+config GRKERNSEC_ACL_HIDEKERN
18378+ bool "Hide kernel processes"
18379+ help
18380+ If you say Y here, all kernel threads will be hidden to all
18381+ processes but those whose subject has the "view hidden processes"
18382+ flag.
18383+
18384+config GRKERNSEC_ACL_MAXTRIES
18385+ int "Maximum tries before password lockout"
18386+ default 3
18387+ help
18388+ This option enforces the maximum number of times a user can attempt
18389+ to authorize themselves with the grsecurity RBAC system before being
18390+ denied the ability to attempt authorization again for a specified time.
18391+ The lower the number, the harder it will be to brute-force a password.
18392+
18393+config GRKERNSEC_ACL_TIMEOUT
18394+ int "Time to wait after max password tries, in seconds"
18395+ default 30
18396+ help
18397+ This option specifies the time the user must wait after attempting to
18398+ authorize to the RBAC system with the maximum number of invalid
18399+ passwords. The higher the number, the harder it will be to brute-force
18400+ a password.
18401+
18402+endmenu
18403+menu "Filesystem Protections"
18404+depends on GRKERNSEC
18405+
18406+config GRKERNSEC_PROC
18407+ bool "Proc restrictions"
18408+ help
18409+ If you say Y here, the permissions of the /proc filesystem
18410+ will be altered to enhance system security and privacy. You MUST
18411+ choose either a user only restriction or a user and group restriction.
18412+ Depending upon the option you choose, you can either restrict users to
18413+ see only the processes they themselves run, or choose a group that can
18414+ view all processes and files normally restricted to root if you choose
18415+ the "restrict to user only" option. NOTE: If you're running identd as
18416+ a non-root user, you will have to run it as the group you specify here.
18417+
18418+config GRKERNSEC_PROC_USER
18419+ bool "Restrict /proc to user only"
18420+ depends on GRKERNSEC_PROC
18421+ help
18422+ If you say Y here, non-root users will only be able to view their own
18423+ processes, and restricts them from viewing network-related information,
18424+ and viewing kernel symbol and module information.
18425+
18426+config GRKERNSEC_PROC_USERGROUP
18427+ bool "Allow special group"
18428+ depends on GRKERNSEC_PROC && !GRKERNSEC_PROC_USER
18429+ help
18430+ If you say Y here, you will be able to select a group that will be
18431+ able to view all processes, network-related information, and
18432+ kernel and symbol information. This option is useful if you want
18433+ to run identd as a non-root user.
18434+
18435+config GRKERNSEC_PROC_GID
18436+ int "GID for special group"
18437+ depends on GRKERNSEC_PROC_USERGROUP
18438+ default 1001
18439+
18440+config GRKERNSEC_PROC_ADD
18441+ bool "Additional restrictions"
18442+ depends on GRKERNSEC_PROC_USER || GRKERNSEC_PROC_USERGROUP
18443+ help
18444+ If you say Y here, additional restrictions will be placed on
18445+ /proc that keep normal users from viewing device information and
18446+ slabinfo information that could be useful for exploits.
18447+
18448+config GRKERNSEC_LINK
18449+ bool "Linking restrictions"
18450+ help
18451+ If you say Y here, /tmp race exploits will be prevented, since users
18452+ will no longer be able to follow symlinks owned by other users in
18453+ world-writable +t directories (i.e. /tmp), unless the owner of the
18454+ symlink is the owner of the directory. users will also not be
18455+ able to hardlink to files they do not own. If the sysctl option is
18456+ enabled, a sysctl option with name "linking_restrictions" is created.
18457+
18458+config GRKERNSEC_FIFO
18459+ bool "FIFO restrictions"
18460+ help
18461+ If you say Y here, users will not be able to write to FIFOs they don't
18462+ own in world-writable +t directories (i.e. /tmp), unless the owner of
18463+ the FIFO is the same owner of the directory it's held in. If the sysctl
18464+ option is enabled, a sysctl option with name "fifo_restrictions" is
18465+ created.
18466+
18467+config GRKERNSEC_CHROOT
18468+ bool "Chroot jail restrictions"
18469+ help
18470+ If you say Y here, you will be able to choose several options that will
18471+ make breaking out of a chrooted jail much more difficult. If you
18472+ encounter no software incompatibilities with the following options, it
18473+ is recommended that you enable each one.
18474+
18475+config GRKERNSEC_CHROOT_MOUNT
18476+ bool "Deny mounts"
18477+ depends on GRKERNSEC_CHROOT
18478+ help
18479+ If you say Y here, processes inside a chroot will not be able to
18480+ mount or remount filesystems. If the sysctl option is enabled, a
18481+ sysctl option with name "chroot_deny_mount" is created.
18482+
18483+config GRKERNSEC_CHROOT_DOUBLE
18484+ bool "Deny double-chroots"
18485+ depends on GRKERNSEC_CHROOT
18486+ help
18487+ If you say Y here, processes inside a chroot will not be able to chroot
18488+ again outside the chroot. This is a widely used method of breaking
18489+ out of a chroot jail and should not be allowed. If the sysctl
18490+ option is enabled, a sysctl option with name
18491+ "chroot_deny_chroot" is created.
18492+
18493+config GRKERNSEC_CHROOT_PIVOT
18494+ bool "Deny pivot_root in chroot"
18495+ depends on GRKERNSEC_CHROOT
18496+ help
18497+ If you say Y here, processes inside a chroot will not be able to use
18498+ a function called pivot_root() that was introduced in Linux 2.3.41. It
18499+ works similar to chroot in that it changes the root filesystem. This
18500+ function could be misused in a chrooted process to attempt to break out
18501+ of the chroot, and therefore should not be allowed. If the sysctl
18502+ option is enabled, a sysctl option with name "chroot_deny_pivot" is
18503+ created.
18504+
18505+config GRKERNSEC_CHROOT_CHDIR
18506+ bool "Enforce chdir(\"/\") on all chroots"
18507+ depends on GRKERNSEC_CHROOT
18508+ help
18509+ If you say Y here, the current working directory of all newly-chrooted
18510+ applications will be set to the the root directory of the chroot.
18511+ The man page on chroot(2) states:
18512+ Note that this call does not change the current working
18513+ directory, so that `.' can be outside the tree rooted at
18514+ `/'. In particular, the super-user can escape from a
18515+ `chroot jail' by doing `mkdir foo; chroot foo; cd ..'.
18516+
18517+ It is recommended that you say Y here, since it's not known to break
18518+ any software. If the sysctl option is enabled, a sysctl option with
18519+ name "chroot_enforce_chdir" is created.
18520+
18521+config GRKERNSEC_CHROOT_CHMOD
18522+ bool "Deny (f)chmod +s"
18523+ depends on GRKERNSEC_CHROOT
18524+ help
18525+ If you say Y here, processes inside a chroot will not be able to chmod
18526+ or fchmod files to make them have suid or sgid bits. This protects
18527+ against another published method of breaking a chroot. If the sysctl
18528+ option is enabled, a sysctl option with name "chroot_deny_chmod" is
18529+ created.
18530+
18531+config GRKERNSEC_CHROOT_FCHDIR
18532+ bool "Deny fchdir out of chroot"
18533+ depends on GRKERNSEC_CHROOT
18534+ help
18535+ If you say Y here, a well-known method of breaking chroots by fchdir'ing
18536+ to a file descriptor of the chrooting process that points to a directory
18537+ outside the filesystem will be stopped. If the sysctl option
18538+ is enabled, a sysctl option with name "chroot_deny_fchdir" is created.
18539+
18540+config GRKERNSEC_CHROOT_MKNOD
18541+ bool "Deny mknod"
18542+ depends on GRKERNSEC_CHROOT
18543+ help
18544+ If you say Y here, processes inside a chroot will not be allowed to
18545+ mknod. The problem with using mknod inside a chroot is that it
18546+ would allow an attacker to create a device entry that is the same
18547+ as one on the physical root of your system, which could range from
18548+ anything from the console device to a device for your harddrive (which
18549+ they could then use to wipe the drive or steal data). It is recommended
18550+ that you say Y here, unless you run into software incompatibilities.
18551+ If the sysctl option is enabled, a sysctl option with name
18552+ "chroot_deny_mknod" is created.
18553+
18554+config GRKERNSEC_CHROOT_SHMAT
18555+ bool "Deny shmat() out of chroot"
18556+ depends on GRKERNSEC_CHROOT
18557+ help
18558+ If you say Y here, processes inside a chroot will not be able to attach
18559+ to shared memory segments that were created outside of the chroot jail.
18560+ It is recommended that you say Y here. If the sysctl option is enabled,
18561+ a sysctl option with name "chroot_deny_shmat" is created.
18562+
18563+config GRKERNSEC_CHROOT_UNIX
18564+ bool "Deny access to abstract AF_UNIX sockets out of chroot"
18565+ depends on GRKERNSEC_CHROOT
18566+ help
18567+ If you say Y here, processes inside a chroot will not be able to
18568+ connect to abstract (meaning not belonging to a filesystem) Unix
18569+ domain sockets that were bound outside of a chroot. It is recommended
18570+ that you say Y here. If the sysctl option is enabled, a sysctl option
18571+ with name "chroot_deny_unix" is created.
18572+
18573+config GRKERNSEC_CHROOT_FINDTASK
18574+ bool "Protect outside processes"
18575+ depends on GRKERNSEC_CHROOT
18576+ help
18577+ If you say Y here, processes inside a chroot will not be able to
18578+ kill, send signals with fcntl, ptrace, capget, setpgid, getpgid,
18579+ getsid, or view any process outside of the chroot. If the sysctl
18580+ option is enabled, a sysctl option with name "chroot_findtask" is
18581+ created.
18582+
18583+config GRKERNSEC_CHROOT_NICE
18584+ bool "Restrict priority changes"
18585+ depends on GRKERNSEC_CHROOT
18586+ help
18587+ If you say Y here, processes inside a chroot will not be able to raise
18588+ the priority of processes in the chroot, or alter the priority of
18589+ processes outside the chroot. This provides more security than simply
18590+ removing CAP_SYS_NICE from the process' capability set. If the
18591+ sysctl option is enabled, a sysctl option with name "chroot_restrict_nice"
18592+ is created.
18593+
18594+config GRKERNSEC_CHROOT_SYSCTL
18595+ bool "Deny sysctl writes"
18596+ depends on GRKERNSEC_CHROOT
18597+ help
18598+ If you say Y here, an attacker in a chroot will not be able to
18599+ write to sysctl entries, either by sysctl(2) or through a /proc
18600+ interface. It is strongly recommended that you say Y here. If the
18601+ sysctl option is enabled, a sysctl option with name
18602+ "chroot_deny_sysctl" is created.
18603+
18604+config GRKERNSEC_CHROOT_CAPS
18605+ bool "Capability restrictions"
18606+ depends on GRKERNSEC_CHROOT
18607+ help
18608+ If you say Y here, the capabilities on all root processes within a
18609+ chroot jail will be lowered to stop module insertion, raw i/o,
18610+ system and net admin tasks, rebooting the system, modifying immutable
18611+ files, modifying IPC owned by another, and changing the system time.
18612+ This is left an option because it can break some apps. Disable this
18613+ if your chrooted apps are having problems performing those kinds of
18614+ tasks. If the sysctl option is enabled, a sysctl option with
18615+ name "chroot_caps" is created.
18616+
18617+endmenu
18618+menu "Kernel Auditing"
18619+depends on GRKERNSEC
18620+
18621+config GRKERNSEC_AUDIT_GROUP
18622+ bool "Single group for auditing"
18623+ help
18624+ If you say Y here, the exec, chdir, (un)mount, and ipc logging features
18625+ will only operate on a group you specify. This option is recommended
18626+ if you only want to watch certain users instead of having a large
18627+ amount of logs from the entire system. If the sysctl option is enabled,
18628+ a sysctl option with name "audit_group" is created.
18629+
18630+config GRKERNSEC_AUDIT_GID
18631+ int "GID for auditing"
18632+ depends on GRKERNSEC_AUDIT_GROUP
18633+ default 1007
18634+
18635+config GRKERNSEC_EXECLOG
18636+ bool "Exec logging"
18637+ help
18638+ If you say Y here, all execve() calls will be logged (since the
18639+ other exec*() calls are frontends to execve(), all execution
18640+ will be logged). Useful for shell-servers that like to keep track
18641+ of their users. If the sysctl option is enabled, a sysctl option with
18642+ name "exec_logging" is created.
18643+ WARNING: This option when enabled will produce a LOT of logs, especially
18644+ on an active system.
18645+
18646+config GRKERNSEC_RESLOG
18647+ bool "Resource logging"
18648+ help
18649+ If you say Y here, all attempts to overstep resource limits will
18650+ be logged with the resource name, the requested size, and the current
18651+ limit. It is highly recommended that you say Y here. If the sysctl
18652+ option is enabled, a sysctl option with name "resource_logging" is
18653+ created. If the RBAC system is enabled, the sysctl value is ignored.
18654+
18655+config GRKERNSEC_CHROOT_EXECLOG
18656+ bool "Log execs within chroot"
18657+ help
18658+ If you say Y here, all executions inside a chroot jail will be logged
18659+ to syslog. This can cause a large amount of logs if certain
18660+ applications (eg. djb's daemontools) are installed on the system, and
18661+ is therefore left as an option. If the sysctl option is enabled, a
18662+ sysctl option with name "chroot_execlog" is created.
18663+
18664+config GRKERNSEC_AUDIT_CHDIR
18665+ bool "Chdir logging"
18666+ help
18667+ If you say Y here, all chdir() calls will be logged. If the sysctl
18668+ option is enabled, a sysctl option with name "audit_chdir" is created.
18669+
18670+config GRKERNSEC_AUDIT_MOUNT
18671+ bool "(Un)Mount logging"
18672+ help
18673+ If you say Y here, all mounts and unmounts will be logged. If the
18674+ sysctl option is enabled, a sysctl option with name "audit_mount" is
18675+ created.
18676+
18677+config GRKERNSEC_AUDIT_IPC
18678+ bool "IPC logging"
18679+ help
18680+ If you say Y here, creation and removal of message queues, semaphores,
18681+ and shared memory will be logged. If the sysctl option is enabled, a
18682+ sysctl option with name "audit_ipc" is created.
18683+
18684+config GRKERNSEC_SIGNAL
18685+ bool "Signal logging"
18686+ help
18687+ If you say Y here, certain important signals will be logged, such as
18688+ SIGSEGV, which will as a result inform you of when a error in a program
18689+ occurred, which in some cases could mean a possible exploit attempt.
18690+ If the sysctl option is enabled, a sysctl option with name
18691+ "signal_logging" is created.
18692+
18693+config GRKERNSEC_FORKFAIL
18694+ bool "Fork failure logging"
18695+ help
18696+ If you say Y here, all failed fork() attempts will be logged.
18697+ This could suggest a fork bomb, or someone attempting to overstep
18698+ their process limit. If the sysctl option is enabled, a sysctl option
18699+ with name "forkfail_logging" is created.
18700+
18701+config GRKERNSEC_TIME
18702+ bool "Time change logging"
18703+ help
18704+ If you say Y here, any changes of the system clock will be logged.
18705+ If the sysctl option is enabled, a sysctl option with name
18706+ "timechange_logging" is created.
18707+
18708+config GRKERNSEC_PROC_IPADDR
18709+ bool "/proc/<pid>/ipaddr support"
18710+ help
18711+ If you say Y here, a new entry will be added to each /proc/<pid>
18712+ directory that contains the IP address of the person using the task.
18713+ The IP is carried across local TCP and AF_UNIX stream sockets.
18714+ This information can be useful for IDS/IPSes to perform remote response
18715+ to a local attack. The entry is readable by only the owner of the
18716+ process (and root if he has CAP_DAC_OVERRIDE, which can be removed via
18717+ the RBAC system), and thus does not create privacy concerns.
18718+
18719+config GRKERNSEC_AUDIT_TEXTREL
18720+ bool 'ELF text relocations logging (READ HELP)'
18721+ depends on PAX_MPROTECT
18722+ help
18723+ If you say Y here, text relocations will be logged with the filename
18724+ of the offending library or binary. The purpose of the feature is
18725+ to help Linux distribution developers get rid of libraries and
18726+ binaries that need text relocations which hinder the future progress
18727+ of PaX. Only Linux distribution developers should say Y here, and
18728+ never on a production machine, as this option creates an information
18729+ leak that could aid an attacker in defeating the randomization of
18730+ a single memory region. If the sysctl option is enabled, a sysctl
18731+ option with name "audit_textrel" is created.
18732+
18733+endmenu
18734+
18735+menu "Executable Protections"
18736+depends on GRKERNSEC
18737+
18738+config GRKERNSEC_EXECVE
18739+ bool "Enforce RLIMIT_NPROC on execs"
18740+ help
18741+ If you say Y here, users with a resource limit on processes will
18742+ have the value checked during execve() calls. The current system
18743+ only checks the system limit during fork() calls. If the sysctl option
18744+ is enabled, a sysctl option with name "execve_limiting" is created.
18745+
18746+config GRKERNSEC_SHM
18747+ bool "Destroy unused shared memory"
18748+ depends on SYSVIPC
18749+ help
18750+ If you say Y here, shared memory will be destroyed when no one is
18751+ attached to it. Otherwise, resources involved with the shared
18752+ memory can be used up and not be associated with any process (as the
18753+ shared memory still exists, and the creating process has exited). If
18754+ the sysctl option is enabled, a sysctl option with name
18755+ "destroy_unused_shm" is created.
18756+
18757+config GRKERNSEC_DMESG
18758+ bool "Dmesg(8) restriction"
18759+ help
18760+ If you say Y here, non-root users will not be able to use dmesg(8)
18761+ to view up to the last 4kb of messages in the kernel's log buffer.
18762+ If the sysctl option is enabled, a sysctl option with name "dmesg" is
18763+ created.
18764+
18765+config GRKERNSEC_RANDPID
18766+ bool "Randomized PIDs"
18767+ help
18768+ If you say Y here, all PIDs created on the system will be
18769+ pseudo-randomly generated. This is extremely effective along
18770+ with the /proc restrictions to disallow an attacker from guessing
18771+ pids of daemons, etc. PIDs are also used in some cases as part
18772+ of a naming system for temporary files, so this option would keep
18773+ those filenames from being predicted as well. We also use code
18774+ to make sure that PID numbers aren't reused too soon. If the sysctl
18775+ option is enabled, a sysctl option with name "rand_pids" is created.
18776+
18777+config GRKERNSEC_TPE
18778+ bool "Trusted Path Execution (TPE)"
18779+ help
18780+ If you say Y here, you will be able to choose a gid to add to the
18781+ supplementary groups of users you want to mark as "untrusted."
18782+ These users will not be able to execute any files that are not in
18783+ root-owned directories writable only by root. If the sysctl option
18784+ is enabled, a sysctl option with name "tpe" is created.
18785+
18786+config GRKERNSEC_TPE_ALL
18787+ bool "Partially restrict non-root users"
18788+ depends on GRKERNSEC_TPE
18789+ help
18790+ If you say Y here, All non-root users other than the ones in the
18791+ group specified in the main TPE option will only be allowed to
18792+ execute files in directories they own that are not group or
18793+ world-writable, or in directories owned by root and writable only by
18794+ root. If the sysctl option is enabled, a sysctl option with name
18795+ "tpe_restrict_all" is created.
18796+
18797+config GRKERNSEC_TPE_INVERT
18798+ bool "Invert GID option"
18799+ depends on GRKERNSEC_TPE
18800+ help
18801+ If you say Y here, the group you specify in the TPE configuration will
18802+ decide what group TPE restrictions will be *disabled* for. This
18803+ option is useful if you want TPE restrictions to be applied to most
18804+ users on the system.
18805+
18806+config GRKERNSEC_TPE_GID
18807+ int "GID for untrusted users"
18808+ depends on GRKERNSEC_TPE && !GRKERNSEC_TPE_INVERT
18809+ default 1005
18810+ help
18811+ If you have selected the "Invert GID option" above, setting this
18812+ GID determines what group TPE restrictions will be *disabled* for.
18813+ If you have not selected the "Invert GID option" above, setting this
18814+ GID determines what group TPE restrictions will be *enabled* for.
18815+ If the sysctl option is enabled, a sysctl option with name "tpe_gid"
18816+ is created.
18817+
18818+config GRKERNSEC_TPE_GID
18819+ int "GID for trusted users"
18820+ depends on GRKERNSEC_TPE && GRKERNSEC_TPE_INVERT
18821+ default 1005
18822+ help
18823+ If you have selected the "Invert GID option" above, setting this
18824+ GID determines what group TPE restrictions will be *disabled* for.
18825+ If you have not selected the "Invert GID option" above, setting this
18826+ GID determines what group TPE restrictions will be *enabled* for.
18827+ If the sysctl option is enabled, a sysctl option with name "tpe_gid"
18828+ is created.
18829+
18830+endmenu
18831+menu "Network Protections"
18832+depends on GRKERNSEC
18833+
18834+config GRKERNSEC_RANDNET
18835+ bool "Larger entropy pools"
18836+ help
18837+ If you say Y here, the entropy pools used for many features of Linux
18838+ and grsecurity will be doubled in size. Since several grsecurity
18839+ features use additional randomness, it is recommended that you say Y
18840+ here. Saying Y here has a similar effect as modifying
18841+ /proc/sys/kernel/random/poolsize.
18842+
18843+config GRKERNSEC_SOCKET
18844+ bool "Socket restrictions"
18845+ help
18846+ If you say Y here, you will be able to choose from several options.
18847+ If you assign a GID on your system and add it to the supplementary
18848+ groups of users you want to restrict socket access to, this patch
18849+ will perform up to three things, based on the option(s) you choose.
18850+
18851+config GRKERNSEC_SOCKET_ALL
18852+ bool "Deny any sockets to group"
18853+ depends on GRKERNSEC_SOCKET
18854+ help
18855+ If you say Y here, you will be able to choose a GID of whose users will
18856+ be unable to connect to other hosts from your machine or run server
18857+ applications from your machine. If the sysctl option is enabled, a
18858+ sysctl option with name "socket_all" is created.
18859+
18860+config GRKERNSEC_SOCKET_ALL_GID
18861+ int "GID to deny all sockets for"
18862+ depends on GRKERNSEC_SOCKET_ALL
18863+ default 1004
18864+ help
18865+ Here you can choose the GID to disable socket access for. Remember to
18866+ add the users you want socket access disabled for to the GID
18867+ specified here. If the sysctl option is enabled, a sysctl option
18868+ with name "socket_all_gid" is created.
18869+
18870+config GRKERNSEC_SOCKET_CLIENT
18871+ bool "Deny client sockets to group"
18872+ depends on GRKERNSEC_SOCKET
18873+ help
18874+ If you say Y here, you will be able to choose a GID of whose users will
18875+ be unable to connect to other hosts from your machine, but will be
18876+ able to run servers. If this option is enabled, all users in the group
18877+ you specify will have to use passive mode when initiating ftp transfers
18878+ from the shell on your machine. If the sysctl option is enabled, a
18879+ sysctl option with name "socket_client" is created.
18880+
18881+config GRKERNSEC_SOCKET_CLIENT_GID
18882+ int "GID to deny client sockets for"
18883+ depends on GRKERNSEC_SOCKET_CLIENT
18884+ default 1003
18885+ help
18886+ Here you can choose the GID to disable client socket access for.
18887+ Remember to add the users you want client socket access disabled for to
18888+ the GID specified here. If the sysctl option is enabled, a sysctl
18889+ option with name "socket_client_gid" is created.
18890+
18891+config GRKERNSEC_SOCKET_SERVER
18892+ bool "Deny server sockets to group"
18893+ depends on GRKERNSEC_SOCKET
18894+ help
18895+ If you say Y here, you will be able to choose a GID of whose users will
18896+ be unable to run server applications from your machine. If the sysctl
18897+ option is enabled, a sysctl option with name "socket_server" is created.
18898+
18899+config GRKERNSEC_SOCKET_SERVER_GID
18900+ int "GID to deny server sockets for"
18901+ depends on GRKERNSEC_SOCKET_SERVER
18902+ default 1002
18903+ help
18904+ Here you can choose the GID to disable server socket access for.
18905+ Remember to add the users you want server socket access disabled for to
18906+ the GID specified here. If the sysctl option is enabled, a sysctl
18907+ option with name "socket_server_gid" is created.
18908+
18909+endmenu
18910+menu "Sysctl support"
18911+depends on GRKERNSEC && SYSCTL
18912+
18913+config GRKERNSEC_SYSCTL
18914+ bool "Sysctl support"
18915+ help
18916+ If you say Y here, you will be able to change the options that
18917+ grsecurity runs with at bootup, without having to recompile your
18918+ kernel. You can echo values to files in /proc/sys/kernel/grsecurity
18919+ to enable (1) or disable (0) various features. All the sysctl entries
18920+ are mutable until the "grsec_lock" entry is set to a non-zero value.
18921+ All features enabled in the kernel configuration are disabled at boot
18922+ if you do not say Y to the "Turn on features by default" option.
18923+ All options should be set at startup, and the grsec_lock entry should
18924+ be set to a non-zero value after all the options are set.
18925+ *THIS IS EXTREMELY IMPORTANT*
18926+
18927+config GRKERNSEC_SYSCTL_ON
18928+ bool "Turn on features by default"
18929+ depends on GRKERNSEC_SYSCTL
18930+ help
18931+ If you say Y here, instead of having all features enabled in the
18932+ kernel configuration disabled at boot time, the features will be
18933+ enabled at boot time. It is recommended you say Y here unless
18934+ there is some reason you would want all sysctl-tunable features to
18935+ be disabled by default. As mentioned elsewhere, it is important
18936+ to enable the grsec_lock entry once you have finished modifying
18937+ the sysctl entries.
18938+
18939+endmenu
18940+menu "Logging Options"
18941+depends on GRKERNSEC
18942+
18943+config GRKERNSEC_FLOODTIME
18944+ int "Seconds in between log messages (minimum)"
18945+ default 10
18946+ help
18947+ This option allows you to enforce the number of seconds between
18948+ grsecurity log messages. The default should be suitable for most
18949+ people, however, if you choose to change it, choose a value small enough
18950+ to allow informative logs to be produced, but large enough to
18951+ prevent flooding.
18952+
18953+config GRKERNSEC_FLOODBURST
18954+ int "Number of messages in a burst (maximum)"
18955+ default 4
18956+ help
18957+ This option allows you to choose the maximum number of messages allowed
18958+ within the flood time interval you chose in a separate option. The
18959+ default should be suitable for most people, however if you find that
18960+ many of your logs are being interpreted as flooding, you may want to
18961+ raise this value.
18962+
18963+endmenu
18964+
18965+endmenu
18966diff -urNp linux-2.6.17.11/grsecurity/Makefile linux-2.6.17.11/grsecurity/Makefile
18967--- linux-2.6.17.11/grsecurity/Makefile 1969-12-31 19:00:00.000000000 -0500
18968+++ linux-2.6.17.11/grsecurity/Makefile 2006-08-12 08:17:55.000000000 -0400
18969@@ -0,0 +1,20 @@
18970+# grsecurity's ACL system was originally written in 2001 by Michael Dalton
18971+# during 2001-2005 it has been completely redesigned by Brad Spengler
18972+# into an RBAC system
18973+#
18974+# All code in this directory and various hooks inserted throughout the kernel
18975+# are copyright Brad Spengler, and released under the GPL v2 or higher
18976+
18977+obj-y = grsec_chdir.o grsec_chroot.o grsec_exec.o grsec_fifo.o grsec_fork.o \
18978+ grsec_mount.o grsec_rand.o grsec_sig.o grsec_sock.o grsec_sysctl.o \
18979+ grsec_time.o grsec_tpe.o grsec_ipc.o grsec_link.o grsec_textrel.o
18980+
18981+obj-$(CONFIG_GRKERNSEC) += grsec_init.o grsum.o gracl.o gracl_ip.o gracl_segv.o \
18982+ gracl_cap.o gracl_alloc.o gracl_shm.o grsec_mem.o gracl_fs.o \
18983+ gracl_learn.o grsec_log.o
18984+obj-$(CONFIG_GRKERNSEC_RESLOG) += gracl_res.o
18985+
18986+ifndef CONFIG_GRKERNSEC
18987+obj-y += grsec_disabled.o
18988+endif
18989+
18990diff -urNp linux-2.6.17.11/include/asm-alpha/a.out.h linux-2.6.17.11/include/asm-alpha/a.out.h
18991--- linux-2.6.17.11/include/asm-alpha/a.out.h 2006-08-07 00:18:54.000000000 -0400
18992+++ linux-2.6.17.11/include/asm-alpha/a.out.h 2006-08-12 08:17:55.000000000 -0400
18993@@ -98,7 +98,7 @@ struct exec
18994 set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000L \
18995 ? ADDR_LIMIT_32BIT : 0) | PER_OSF4))
18996
18997-#define STACK_TOP \
18998+#define __STACK_TOP \
18999 (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL)
19000
19001 #endif
19002diff -urNp linux-2.6.17.11/include/asm-alpha/elf.h linux-2.6.17.11/include/asm-alpha/elf.h
19003--- linux-2.6.17.11/include/asm-alpha/elf.h 2006-08-07 00:18:54.000000000 -0400
19004+++ linux-2.6.17.11/include/asm-alpha/elf.h 2006-08-12 08:17:55.000000000 -0400
19005@@ -91,6 +91,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
19006
19007 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
19008
19009+#ifdef CONFIG_PAX_ASLR
19010+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 0x10000 : 0x120000000UL)
19011+
19012+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
19013+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28)
19014+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
19015+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28)
19016+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
19017+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 19)
19018+#endif
19019+
19020 /* $0 is set by ld.so to a pointer to a function which might be
19021 registered using atexit. This provides a mean for the dynamic
19022 linker to call DT_FINI functions for shared libraries that have
19023diff -urNp linux-2.6.17.11/include/asm-alpha/kmap_types.h linux-2.6.17.11/include/asm-alpha/kmap_types.h
19024--- linux-2.6.17.11/include/asm-alpha/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
19025+++ linux-2.6.17.11/include/asm-alpha/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
19026@@ -25,7 +25,8 @@ D(9) KM_IRQ0,
19027 D(10) KM_IRQ1,
19028 D(11) KM_SOFTIRQ0,
19029 D(12) KM_SOFTIRQ1,
19030-D(13) KM_TYPE_NR
19031+D(13) KM_CLEARPAGE,
19032+D(14) KM_TYPE_NR
19033 };
19034
19035 #undef D
19036diff -urNp linux-2.6.17.11/include/asm-alpha/page.h linux-2.6.17.11/include/asm-alpha/page.h
19037--- linux-2.6.17.11/include/asm-alpha/page.h 2006-08-07 00:18:54.000000000 -0400
19038+++ linux-2.6.17.11/include/asm-alpha/page.h 2006-08-12 08:17:55.000000000 -0400
19039@@ -93,6 +93,16 @@ typedef unsigned long pgprot_t;
19040
19041 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
19042 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
19043+
19044+#ifdef CONFIG_PAX_PAGEEXEC
19045+#ifdef CONFIG_PAX_MPROTECT
19046+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
19047+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
19048+#else
19049+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
19050+#endif
19051+#endif
19052+
19053 #endif /* __KERNEL__ */
19054
19055 #include <asm-generic/memory_model.h>
19056diff -urNp linux-2.6.17.11/include/asm-alpha/pgtable.h linux-2.6.17.11/include/asm-alpha/pgtable.h
19057--- linux-2.6.17.11/include/asm-alpha/pgtable.h 2006-08-07 00:18:54.000000000 -0400
19058+++ linux-2.6.17.11/include/asm-alpha/pgtable.h 2006-08-12 08:17:55.000000000 -0400
19059@@ -102,6 +102,17 @@ struct vm_area_struct;
19060 #define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS)
19061 #define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
19062 #define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
19063+
19064+#ifdef CONFIG_PAX_PAGEEXEC
19065+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOE)
19066+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE)
19067+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE)
19068+#else
19069+# define PAGE_SHARED_NOEXEC PAGE_SHARED
19070+# define PAGE_COPY_NOEXEC PAGE_COPY
19071+# define PAGE_READONLY_NOEXEC PAGE_READONLY
19072+#endif
19073+
19074 #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
19075
19076 #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
19077diff -urNp linux-2.6.17.11/include/asm-arm/a.out.h linux-2.6.17.11/include/asm-arm/a.out.h
19078--- linux-2.6.17.11/include/asm-arm/a.out.h 2006-08-07 00:18:54.000000000 -0400
19079+++ linux-2.6.17.11/include/asm-arm/a.out.h 2006-08-12 08:17:55.000000000 -0400
19080@@ -28,7 +28,7 @@ struct exec
19081 #define M_ARM 103
19082
19083 #ifdef __KERNEL__
19084-#define STACK_TOP ((current->personality == PER_LINUX_32BIT) ? \
19085+#define __STACK_TOP ((current->personality == PER_LINUX_32BIT) ? \
19086 TASK_SIZE : TASK_SIZE_26)
19087 #endif
19088
19089diff -urNp linux-2.6.17.11/include/asm-arm/elf.h linux-2.6.17.11/include/asm-arm/elf.h
19090--- linux-2.6.17.11/include/asm-arm/elf.h 2006-08-07 00:18:54.000000000 -0400
19091+++ linux-2.6.17.11/include/asm-arm/elf.h 2006-08-12 08:17:55.000000000 -0400
19092@@ -56,6 +56,17 @@ typedef struct user_fp elf_fpregset_t;
19093
19094 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
19095
19096+#ifdef CONFIG_PAX_ASLR
19097+#define PAX_ELF_ET_DYN_BASE(tsk) 0x00008000UL
19098+
19099+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
19100+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
19101+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
19102+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
19103+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
19104+#define PAX_DELTA_STACK_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
19105+#endif
19106+
19107 /* When the program starts, a1 contains a pointer to a function to be
19108 registered with atexit, as per the SVR4 ABI. A value of 0 means we
19109 have no such handler. */
19110diff -urNp linux-2.6.17.11/include/asm-arm/kmap_types.h linux-2.6.17.11/include/asm-arm/kmap_types.h
19111--- linux-2.6.17.11/include/asm-arm/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
19112+++ linux-2.6.17.11/include/asm-arm/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
19113@@ -18,6 +18,7 @@ enum km_type {
19114 KM_IRQ1,
19115 KM_SOFTIRQ0,
19116 KM_SOFTIRQ1,
19117+ KM_CLEARPAGE,
19118 KM_TYPE_NR
19119 };
19120
19121diff -urNp linux-2.6.17.11/include/asm-arm26/kmap_types.h linux-2.6.17.11/include/asm-arm26/kmap_types.h
19122--- linux-2.6.17.11/include/asm-arm26/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
19123+++ linux-2.6.17.11/include/asm-arm26/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
19124@@ -6,7 +6,8 @@
19125 */
19126 enum km_type {
19127 KM_IRQ0,
19128- KM_USER1
19129+ KM_USER1,
19130+ KM_CLEARPAGE
19131 };
19132
19133 #endif
19134diff -urNp linux-2.6.17.11/include/asm-cris/kmap_types.h linux-2.6.17.11/include/asm-cris/kmap_types.h
19135--- linux-2.6.17.11/include/asm-cris/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
19136+++ linux-2.6.17.11/include/asm-cris/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
19137@@ -19,6 +19,7 @@ enum km_type {
19138 KM_IRQ1,
19139 KM_SOFTIRQ0,
19140 KM_SOFTIRQ1,
19141+ KM_CLEARPAGE,
19142 KM_TYPE_NR
19143 };
19144
19145diff -urNp linux-2.6.17.11/include/asm-frv/kmap_types.h linux-2.6.17.11/include/asm-frv/kmap_types.h
19146--- linux-2.6.17.11/include/asm-frv/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
19147+++ linux-2.6.17.11/include/asm-frv/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
19148@@ -23,6 +23,7 @@ enum km_type {
19149 KM_IRQ1,
19150 KM_SOFTIRQ0,
19151 KM_SOFTIRQ1,
19152+ KM_CLEARPAGE,
19153 KM_TYPE_NR
19154 };
19155
19156diff -urNp linux-2.6.17.11/include/asm-h8300/kmap_types.h linux-2.6.17.11/include/asm-h8300/kmap_types.h
19157--- linux-2.6.17.11/include/asm-h8300/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
19158+++ linux-2.6.17.11/include/asm-h8300/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
19159@@ -15,6 +15,7 @@ enum km_type {
19160 KM_IRQ1,
19161 KM_SOFTIRQ0,
19162 KM_SOFTIRQ1,
19163+ KM_CLEARPAGE,
19164 KM_TYPE_NR
19165 };
19166
19167diff -urNp linux-2.6.17.11/include/asm-i386/alternative.h linux-2.6.17.11/include/asm-i386/alternative.h
19168--- linux-2.6.17.11/include/asm-i386/alternative.h 2006-08-07 00:18:54.000000000 -0400
19169+++ linux-2.6.17.11/include/asm-i386/alternative.h 2006-08-12 08:17:55.000000000 -0400
19170@@ -47,7 +47,7 @@ extern void alternatives_smp_switch(int
19171 " .byte 662b-661b\n" /* sourcelen */ \
19172 " .byte 664f-663f\n" /* replacementlen */ \
19173 ".previous\n" \
19174- ".section .altinstr_replacement,\"ax\"\n" \
19175+ ".section .altinstr_replacement,\"a\"\n" \
19176 "663:\n\t" newinstr "\n664:\n" /* replacement */\
19177 ".previous" :: "i" (feature) : "memory")
19178
19179@@ -71,7 +71,7 @@ extern void alternatives_smp_switch(int
19180 " .byte 662b-661b\n" /* sourcelen */ \
19181 " .byte 664f-663f\n" /* replacementlen */ \
19182 ".previous\n" \
19183- ".section .altinstr_replacement,\"ax\"\n" \
19184+ ".section .altinstr_replacement,\"a\"\n" \
19185 "663:\n\t" newinstr "\n664:\n" /* replacement */\
19186 ".previous" :: "i" (feature), ##input)
19187
19188@@ -110,7 +110,7 @@ extern void alternatives_smp_switch(int
19189 " .byte 662b-661b\n" /* sourcelen */ \
19190 " .byte 664f-663f\n" /* replacementlen */ \
19191 ".previous\n" \
19192- ".section .smp_altinstr_replacement,\"awx\"\n" \
19193+ ".section .smp_altinstr_replacement,\"aw\"\n" \
19194 "663:\n\t" upinstr "\n" /* replacement */ \
19195 "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \
19196 ".previous" : args)
19197diff -urNp linux-2.6.17.11/include/asm-i386/a.out.h linux-2.6.17.11/include/asm-i386/a.out.h
19198--- linux-2.6.17.11/include/asm-i386/a.out.h 2006-08-07 00:18:54.000000000 -0400
19199+++ linux-2.6.17.11/include/asm-i386/a.out.h 2006-08-12 08:17:55.000000000 -0400
19200@@ -19,7 +19,11 @@ struct exec
19201
19202 #ifdef __KERNEL__
19203
19204-#define STACK_TOP TASK_SIZE
19205+#ifdef CONFIG_PAX_SEGMEXEC
19206+#define __STACK_TOP ((current->mm->pax_flags & MF_PAX_SEGMEXEC)?TASK_SIZE/2:TASK_SIZE)
19207+#else
19208+#define __STACK_TOP TASK_SIZE
19209+#endif
19210
19211 #endif
19212
19213diff -urNp linux-2.6.17.11/include/asm-i386/auxvec.h linux-2.6.17.11/include/asm-i386/auxvec.h
19214--- linux-2.6.17.11/include/asm-i386/auxvec.h 2006-08-07 00:18:54.000000000 -0400
19215+++ linux-2.6.17.11/include/asm-i386/auxvec.h 2006-08-12 08:17:55.000000000 -0400
19216@@ -5,7 +5,9 @@
19217 * Architecture-neutral AT_ values in 0-17, leave some room
19218 * for more of them, start the x86-specific ones at 32.
19219 */
19220+#ifndef CONFIG_PAX_NOVSYSCALL
19221 #define AT_SYSINFO 32
19222 #define AT_SYSINFO_EHDR 33
19223+#endif
19224
19225 #endif
19226diff -urNp linux-2.6.17.11/include/asm-i386/bug.h linux-2.6.17.11/include/asm-i386/bug.h
19227--- linux-2.6.17.11/include/asm-i386/bug.h 2006-08-07 00:18:54.000000000 -0400
19228+++ linux-2.6.17.11/include/asm-i386/bug.h 2006-08-12 08:17:55.000000000 -0400
19229@@ -12,10 +12,10 @@
19230 #ifdef CONFIG_BUG
19231 #define HAVE_ARCH_BUG
19232 #ifdef CONFIG_DEBUG_BUGVERBOSE
19233-#define BUG() \
19234- __asm__ __volatile__( "ud2\n" \
19235- "\t.word %c0\n" \
19236- "\t.long %c1\n" \
19237+#define BUG() \
19238+ __asm__ __volatile__( "ud2\n\t" \
19239+ "testl %c0, %%eax\n\t" \
19240+ "testl %c1, %%eax\n\t" \
19241 : : "i" (__LINE__), "i" (__FILE__))
19242 #else
19243 #define BUG() __asm__ __volatile__("ud2\n")
19244diff -urNp linux-2.6.17.11/include/asm-i386/checksum.h linux-2.6.17.11/include/asm-i386/checksum.h
19245--- linux-2.6.17.11/include/asm-i386/checksum.h 2006-08-07 00:18:54.000000000 -0400
19246+++ linux-2.6.17.11/include/asm-i386/checksum.h 2006-08-12 08:17:55.000000000 -0400
19247@@ -30,6 +30,12 @@ asmlinkage unsigned int csum_partial(con
19248 asmlinkage unsigned int csum_partial_copy_generic(const unsigned char *src, unsigned char *dst,
19249 int len, int sum, int *src_err_ptr, int *dst_err_ptr);
19250
19251+asmlinkage unsigned int csum_partial_copy_generic_to_user(const unsigned char *src, unsigned char *dst,
19252+ int len, int sum, int *src_err_ptr, int *dst_err_ptr);
19253+
19254+asmlinkage unsigned int csum_partial_copy_generic_from_user(const unsigned char *src, unsigned char *dst,
19255+ int len, int sum, int *src_err_ptr, int *dst_err_ptr);
19256+
19257 /*
19258 * Note: when you get a NULL pointer exception here this means someone
19259 * passed in an incorrect kernel address to one of these functions.
19260@@ -49,7 +55,7 @@ unsigned int csum_partial_copy_from_user
19261 int len, int sum, int *err_ptr)
19262 {
19263 might_sleep();
19264- return csum_partial_copy_generic((__force unsigned char *)src, dst,
19265+ return csum_partial_copy_generic_from_user((__force unsigned char *)src, dst,
19266 len, sum, err_ptr, NULL);
19267 }
19268
19269@@ -183,7 +189,7 @@ static __inline__ unsigned int csum_and_
19270 {
19271 might_sleep();
19272 if (access_ok(VERIFY_WRITE, dst, len))
19273- return csum_partial_copy_generic(src, (__force unsigned char *)dst, len, sum, NULL, err_ptr);
19274+ return csum_partial_copy_generic_to_user(src, (__force unsigned char *)dst, len, sum, NULL, err_ptr);
19275
19276 if (len)
19277 *err_ptr = -EFAULT;
19278diff -urNp linux-2.6.17.11/include/asm-i386/desc.h linux-2.6.17.11/include/asm-i386/desc.h
19279--- linux-2.6.17.11/include/asm-i386/desc.h 2006-08-07 00:18:54.000000000 -0400
19280+++ linux-2.6.17.11/include/asm-i386/desc.h 2006-08-12 08:17:55.000000000 -0400
19281@@ -10,11 +10,13 @@
19282
19283 #include <linux/preempt.h>
19284 #include <linux/smp.h>
19285-#include <linux/percpu.h>
19286+#include <linux/sched.h>
19287
19288 #include <asm/mmu.h>
19289+#include <asm/pgtable.h>
19290+#include <asm/tlbflush.h>
19291
19292-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
19293+extern struct desc_struct cpu_gdt_table[NR_CPUS][PAGE_SIZE / sizeof(struct desc_struct)];
19294
19295 DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
19296
19297@@ -24,13 +26,53 @@ struct Xgt_desc_struct {
19298 unsigned short pad;
19299 } __attribute__ ((packed));
19300
19301-extern struct Xgt_desc_struct idt_descr;
19302-DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
19303-
19304+extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
19305
19306 static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
19307 {
19308- return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
19309+ return cpu_gdt_table[cpu];
19310+}
19311+
19312+#define pax_open_kernel(cr0) \
19313+do { \
19314+ typecheck(unsigned long,cr0); \
19315+ preempt_disable(); \
19316+ cr0 = read_cr0(); \
19317+ write_cr0(cr0 & ~0x10000UL); \
19318+} while(0)
19319+
19320+#define pax_close_kernel(cr0) \
19321+do { \
19322+ typecheck(unsigned long,cr0); \
19323+ write_cr0(cr0); \
19324+ preempt_enable_no_resched(); \
19325+} while(0)
19326+
19327+static inline void set_user_cs(struct mm_struct *mm, int cpu)
19328+{
19329+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
19330+ unsigned long base = mm->context.user_cs_base;
19331+ unsigned long limit = mm->context.user_cs_limit;
19332+
19333+#ifdef CONFIG_PAX_KERNEXEC
19334+ unsigned long cr0;
19335+
19336+ pax_open_kernel(cr0);
19337+#endif
19338+
19339+ if (likely(limit)) {
19340+ limit -= 1UL;
19341+ limit >>= 12;
19342+ }
19343+
19344+ get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS].a = (limit & 0xFFFFUL) | (base << 16);
19345+ get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS].b = (limit & 0xF0000UL) | 0xC0FB00UL | (base & 0xFF000000UL) | ((base >> 16) & 0xFFUL);
19346+
19347+#ifdef CONFIG_PAX_KERNEXEC
19348+ pax_close_kernel(cr0);
19349+#endif
19350+
19351+#endif
19352 }
19353
19354 #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
19355@@ -50,7 +92,7 @@ static inline struct desc_struct *get_cp
19356 * This is the ldt that every process will get unless we need
19357 * something other than this.
19358 */
19359-extern struct desc_struct default_ldt[];
19360+extern const struct desc_struct default_ldt[];
19361 extern void set_intr_gate(unsigned int irq, void * addr);
19362
19363 #define _set_tssldt_desc(n,addr,limit,type) \
19364@@ -64,7 +106,7 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\
19365 "rorl $16,%1" \
19366 : "=m"(*(n)) : "q" (addr), "r"(n), "ir"(limit), "i"(type))
19367
19368-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
19369+static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
19370 {
19371 _set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr,
19372 offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
19373@@ -72,11 +114,28 @@ static inline void __set_tss_desc(unsign
19374
19375 #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
19376
19377-static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
19378+static inline void __set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size)
19379 {
19380 _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
19381 }
19382
19383+static inline void set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size)
19384+{
19385+
19386+#ifdef CONFIG_PAX_KERNEXEC
19387+ unsigned long cr0;
19388+
19389+ pax_open_kernel(cr0);
19390+#endif
19391+
19392+ _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
19393+
19394+#ifdef CONFIG_PAX_KERNEXEC
19395+ pax_close_kernel(cr0);
19396+#endif
19397+
19398+}
19399+
19400 #define LDT_entry_a(info) \
19401 ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
19402
19403@@ -90,7 +149,7 @@ static inline void set_ldt_desc(unsigned
19404 ((info)->seg_32bit << 22) | \
19405 ((info)->limit_in_pages << 23) | \
19406 ((info)->useable << 20) | \
19407- 0x7000)
19408+ 0x7100)
19409
19410 #define LDT_empty(info) (\
19411 (info)->base_addr == 0 && \
19412@@ -134,7 +193,7 @@ static inline void clear_LDT(void)
19413 */
19414 static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
19415 {
19416- void *segments = pc->ldt;
19417+ const void *segments = pc->ldt;
19418 int count = pc->size;
19419
19420 if (likely(!count)) {
19421@@ -162,6 +221,22 @@ static inline unsigned long get_desc_bas
19422 return base;
19423 }
19424
19425+static inline void _load_LDT(mm_context_t *pc)
19426+{
19427+ int cpu = get_cpu();
19428+ const void *segments = pc->ldt;
19429+ int count = pc->size;
19430+
19431+ if (likely(!count)) {
19432+ segments = &default_ldt[0];
19433+ count = 5;
19434+ }
19435+
19436+ __set_ldt_desc(cpu, segments, count);
19437+ load_LDT_desc();
19438+ put_cpu();
19439+}
19440+
19441 #endif /* !__ASSEMBLY__ */
19442
19443 #endif
19444diff -urNp linux-2.6.17.11/include/asm-i386/elf.h linux-2.6.17.11/include/asm-i386/elf.h
19445--- linux-2.6.17.11/include/asm-i386/elf.h 2006-08-07 00:18:54.000000000 -0400
19446+++ linux-2.6.17.11/include/asm-i386/elf.h 2006-08-12 08:17:55.000000000 -0400
19447@@ -71,7 +71,22 @@ typedef struct user_fxsr_struct elf_fpxr
19448 the loader. We need to make sure that it is out of the way of the program
19449 that it will "exec", and that there is sufficient room for the brk. */
19450
19451+#ifdef CONFIG_PAX_SEGMEXEC
19452+#define ELF_ET_DYN_BASE ((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3*2 : TASK_SIZE/3*2)
19453+#else
19454 #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
19455+#endif
19456+
19457+#ifdef CONFIG_PAX_ASLR
19458+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000000UL
19459+
19460+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
19461+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
19462+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
19463+#define PAX_DELTA_EXEC_LEN(tsk) 15
19464+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
19465+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
19466+#endif
19467
19468 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
19469 now struct_user_regs, they are different) */
19470@@ -131,7 +146,14 @@ extern int dump_task_extended_fpu (struc
19471
19472 #define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
19473 #define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
19474+
19475+#ifndef CONFIG_PAX_NOVSYSCALL
19476+#ifdef CONFIG_PAX_SEGMEXEC
19477+#define VSYSCALL_ENTRY ((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? (unsigned long) &__kernel_vsyscall - SEGMEXEC_TASK_SIZE : (unsigned long) &__kernel_vsyscall)
19478+#else
19479 #define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall)
19480+#endif
19481+
19482 extern void __kernel_vsyscall;
19483
19484 #define ARCH_DLINFO \
19485@@ -187,3 +209,5 @@ do { \
19486 #endif
19487
19488 #endif
19489+
19490+#endif
19491diff -urNp linux-2.6.17.11/include/asm-i386/i387.h linux-2.6.17.11/include/asm-i386/i387.h
19492--- linux-2.6.17.11/include/asm-i386/i387.h 2006-08-07 00:18:54.000000000 -0400
19493+++ linux-2.6.17.11/include/asm-i386/i387.h 2006-08-12 08:17:55.000000000 -0400
19494@@ -40,13 +40,8 @@ extern void kernel_fpu_begin(void);
19495 #define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
19496
19497 /* We need a safe address that is cheap to find and that is already
19498- in L1 during context switch. The best choices are unfortunately
19499- different for UP and SMP */
19500-#ifdef CONFIG_SMP
19501-#define safe_address (__per_cpu_offset[0])
19502-#else
19503-#define safe_address (kstat_cpu(0).cpustat.user)
19504-#endif
19505+ in L1 during context switch. */
19506+#define safe_address (init_tss[smp_processor_id()].esp0)
19507
19508 /*
19509 * These must be called with preempt disabled
19510diff -urNp linux-2.6.17.11/include/asm-i386/kmap_types.h linux-2.6.17.11/include/asm-i386/kmap_types.h
19511--- linux-2.6.17.11/include/asm-i386/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
19512+++ linux-2.6.17.11/include/asm-i386/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
19513@@ -23,7 +23,8 @@ D(9) KM_IRQ0,
19514 D(10) KM_IRQ1,
19515 D(11) KM_SOFTIRQ0,
19516 D(12) KM_SOFTIRQ1,
19517-D(13) KM_TYPE_NR
19518+D(13) KM_CLEARPAGE,
19519+D(14) KM_TYPE_NR
19520 };
19521
19522 #undef D
19523diff -urNp linux-2.6.17.11/include/asm-i386/mach-default/apm.h linux-2.6.17.11/include/asm-i386/mach-default/apm.h
19524--- linux-2.6.17.11/include/asm-i386/mach-default/apm.h 2006-08-07 00:18:54.000000000 -0400
19525+++ linux-2.6.17.11/include/asm-i386/mach-default/apm.h 2006-08-12 08:17:55.000000000 -0400
19526@@ -36,7 +36,7 @@ static inline void apm_bios_call_asm(u32
19527 __asm__ __volatile__(APM_DO_ZERO_SEGS
19528 "pushl %%edi\n\t"
19529 "pushl %%ebp\n\t"
19530- "lcall *%%cs:apm_bios_entry\n\t"
19531+ "lcall *%%ss:apm_bios_entry\n\t"
19532 "setc %%al\n\t"
19533 "popl %%ebp\n\t"
19534 "popl %%edi\n\t"
19535@@ -60,7 +60,7 @@ static inline u8 apm_bios_call_simple_as
19536 __asm__ __volatile__(APM_DO_ZERO_SEGS
19537 "pushl %%edi\n\t"
19538 "pushl %%ebp\n\t"
19539- "lcall *%%cs:apm_bios_entry\n\t"
19540+ "lcall *%%ss:apm_bios_entry\n\t"
19541 "setc %%bl\n\t"
19542 "popl %%ebp\n\t"
19543 "popl %%edi\n\t"
19544diff -urNp linux-2.6.17.11/include/asm-i386/mach-default/do_timer.h linux-2.6.17.11/include/asm-i386/mach-default/do_timer.h
19545--- linux-2.6.17.11/include/asm-i386/mach-default/do_timer.h 2006-08-07 00:18:54.000000000 -0400
19546+++ linux-2.6.17.11/include/asm-i386/mach-default/do_timer.h 2006-08-12 08:17:55.000000000 -0400
19547@@ -18,7 +18,7 @@ static inline void do_timer_interrupt_ho
19548 {
19549 do_timer(regs);
19550 #ifndef CONFIG_SMP
19551- update_process_times(user_mode_vm(regs));
19552+ update_process_times(user_mode(regs));
19553 #endif
19554 /*
19555 * In the SMP case we use the local APIC timer interrupt to do the
19556diff -urNp linux-2.6.17.11/include/asm-i386/mach-visws/do_timer.h linux-2.6.17.11/include/asm-i386/mach-visws/do_timer.h
19557--- linux-2.6.17.11/include/asm-i386/mach-visws/do_timer.h 2006-08-07 00:18:54.000000000 -0400
19558+++ linux-2.6.17.11/include/asm-i386/mach-visws/do_timer.h 2006-08-12 08:17:55.000000000 -0400
19559@@ -11,7 +11,7 @@ static inline void do_timer_interrupt_ho
19560
19561 do_timer(regs);
19562 #ifndef CONFIG_SMP
19563- update_process_times(user_mode_vm(regs));
19564+ update_process_times(user_mode(regs));
19565 #endif
19566 /*
19567 * In the SMP case we use the local APIC timer interrupt to do the
19568diff -urNp linux-2.6.17.11/include/asm-i386/mach-voyager/do_timer.h linux-2.6.17.11/include/asm-i386/mach-voyager/do_timer.h
19569--- linux-2.6.17.11/include/asm-i386/mach-voyager/do_timer.h 2006-08-07 00:18:54.000000000 -0400
19570+++ linux-2.6.17.11/include/asm-i386/mach-voyager/do_timer.h 2006-08-12 08:17:55.000000000 -0400
19571@@ -5,7 +5,7 @@ static inline void do_timer_interrupt_ho
19572 {
19573 do_timer(regs);
19574 #ifndef CONFIG_SMP
19575- update_process_times(user_mode_vm(regs));
19576+ update_process_times(user_mode(regs));
19577 #endif
19578
19579 voyager_timer_interrupt(regs);
19580diff -urNp linux-2.6.17.11/include/asm-i386/mman.h linux-2.6.17.11/include/asm-i386/mman.h
19581--- linux-2.6.17.11/include/asm-i386/mman.h 2006-08-07 00:18:54.000000000 -0400
19582+++ linux-2.6.17.11/include/asm-i386/mman.h 2006-08-12 08:17:55.000000000 -0400
19583@@ -11,6 +11,10 @@
19584 #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
19585 #define MAP_NONBLOCK 0x10000 /* do not block on IO */
19586
19587+#ifdef CONFIG_PAX_SEGMEXEC
19588+#define MAP_MIRROR 0x20000
19589+#endif
19590+
19591 #define MCL_CURRENT 1 /* lock all current mappings */
19592 #define MCL_FUTURE 2 /* lock all future mappings */
19593
19594diff -urNp linux-2.6.17.11/include/asm-i386/mmu_context.h linux-2.6.17.11/include/asm-i386/mmu_context.h
19595--- linux-2.6.17.11/include/asm-i386/mmu_context.h 2006-08-07 00:18:54.000000000 -0400
19596+++ linux-2.6.17.11/include/asm-i386/mmu_context.h 2006-08-12 08:17:55.000000000 -0400
19597@@ -46,6 +46,18 @@ static inline void switch_mm(struct mm_s
19598 */
19599 if (unlikely(prev->context.ldt != next->context.ldt))
19600 load_LDT_nolock(&next->context, cpu);
19601+
19602+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
19603+ cpu_clear(cpu, prev->context.cpu_user_cs_mask);
19604+ cpu_set(cpu, next->context.cpu_user_cs_mask);
19605+#endif
19606+
19607+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
19608+ if (prev->context.user_cs_base != next->context.user_cs_base ||
19609+ prev->context.user_cs_limit != next->context.user_cs_limit)
19610+#endif
19611+
19612+ set_user_cs(next, cpu);
19613 }
19614 #ifdef CONFIG_SMP
19615 else {
19616@@ -58,6 +70,12 @@ static inline void switch_mm(struct mm_s
19617 */
19618 load_cr3(next->pgd);
19619 load_LDT_nolock(&next->context, cpu);
19620+
19621+#ifdef CONFIG_PAX_PAGEEXEC
19622+ cpu_set(cpu, next->context.cpu_user_cs_mask);
19623+#endif
19624+
19625+ set_user_cs(next, cpu);
19626 }
19627 }
19628 #endif
19629diff -urNp linux-2.6.17.11/include/asm-i386/mmu.h linux-2.6.17.11/include/asm-i386/mmu.h
19630--- linux-2.6.17.11/include/asm-i386/mmu.h 2006-08-07 00:18:54.000000000 -0400
19631+++ linux-2.6.17.11/include/asm-i386/mmu.h 2006-08-12 08:17:55.000000000 -0400
19632@@ -12,6 +12,17 @@ typedef struct {
19633 int size;
19634 struct semaphore sem;
19635 void *ldt;
19636+
19637+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
19638+ unsigned long user_cs_base;
19639+ unsigned long user_cs_limit;
19640+
19641+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
19642+ cpumask_t cpu_user_cs_mask;
19643+#endif
19644+
19645+#endif
19646+
19647 } mm_context_t;
19648
19649 #endif
19650diff -urNp linux-2.6.17.11/include/asm-i386/module.h linux-2.6.17.11/include/asm-i386/module.h
19651--- linux-2.6.17.11/include/asm-i386/module.h 2006-08-07 00:18:54.000000000 -0400
19652+++ linux-2.6.17.11/include/asm-i386/module.h 2006-08-12 08:17:55.000000000 -0400
19653@@ -72,6 +72,12 @@ struct mod_arch_specific
19654 #define MODULE_STACKSIZE ""
19655 #endif
19656
19657-#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE
19658+#ifdef CONFIG_GRKERNSEC
19659+#define MODULE_GRSEC "GRSECURITY "
19660+#else
19661+#define MODULE_GRSEC ""
19662+#endif
19663+
19664+#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE MODULE_GRSEC
19665
19666 #endif /* _ASM_I386_MODULE_H */
19667diff -urNp linux-2.6.17.11/include/asm-i386/page.h linux-2.6.17.11/include/asm-i386/page.h
19668--- linux-2.6.17.11/include/asm-i386/page.h 2006-08-07 00:18:54.000000000 -0400
19669+++ linux-2.6.17.11/include/asm-i386/page.h 2006-08-12 08:17:55.000000000 -0400
19670@@ -52,13 +52,14 @@ typedef struct { unsigned long long pgpr
19671 #define pmd_val(x) ((x).pmd)
19672 #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
19673 #define __pmd(x) ((pmd_t) { (x) } )
19674+#define __pte(x) ({ pte_t __pte = {(x), (x) >> 32}; __pte;})
19675 #define HPAGE_SHIFT 21
19676 #else
19677 typedef struct { unsigned long pte_low; } pte_t;
19678 typedef struct { unsigned long pgd; } pgd_t;
19679 typedef struct { unsigned long pgprot; } pgprot_t;
19680-#define boot_pte_t pte_t /* or would you rather have a typedef */
19681 #define pte_val(x) ((x).pte_low)
19682+#define __pte(x) ((pte_t) { (x) } )
19683 #define HPAGE_SHIFT 22
19684 #endif
19685 #define PTE_MASK PAGE_MASK
19686@@ -73,7 +74,6 @@ typedef struct { unsigned long pgprot; }
19687 #define pgd_val(x) ((x).pgd)
19688 #define pgprot_val(x) ((x).pgprot)
19689
19690-#define __pte(x) ((pte_t) { (x) } )
19691 #define __pgd(x) ((pgd_t) { (x) } )
19692 #define __pgprot(x) ((pgprot_t) { (x) } )
19693
19694@@ -118,6 +118,15 @@ extern int page_is_ram(unsigned long pag
19695 #endif
19696 #define __KERNEL_START (__PAGE_OFFSET + __PHYSICAL_START)
19697
19698+#ifdef CONFIG_PAX_KERNEXEC
19699+#define __KERNEL_TEXT_OFFSET (__PAGE_OFFSET + ((__PHYSICAL_START + ~(4*1024*1024)) & (4*1024*1024)))
19700+#ifndef __ASSEMBLY__
19701+extern unsigned char MODULES_VADDR[];
19702+extern unsigned char MODULES_END[];
19703+#endif
19704+#else
19705+#define __KERNEL_TEXT_OFFSET (0)
19706+#endif
19707
19708 #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
19709 #define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE)
19710@@ -137,6 +146,19 @@ extern int page_is_ram(unsigned long pag
19711 ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
19712 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
19713
19714+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
19715+#ifdef CONFIG_PAX_MPROTECT
19716+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
19717+ ((current->mm->pax_flags & (MF_PAX_PAGEEXEC|MF_PAX_SEGMEXEC))?0:VM_EXEC))
19718+#else
19719+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & (MF_PAX_PAGEEXEC|MF_PAX_SEGMEXEC))?0:VM_EXEC))
19720+#endif
19721+#endif
19722+
19723+#ifdef CONFIG_PAX_PAGEEXEC
19724+#define CONFIG_ARCH_TRACK_EXEC_LIMIT 1
19725+#endif
19726+
19727 #endif /* __KERNEL__ */
19728
19729 #include <asm-generic/memory_model.h>
19730diff -urNp linux-2.6.17.11/include/asm-i386/pgalloc.h linux-2.6.17.11/include/asm-i386/pgalloc.h
19731--- linux-2.6.17.11/include/asm-i386/pgalloc.h 2006-08-07 00:18:54.000000000 -0400
19732+++ linux-2.6.17.11/include/asm-i386/pgalloc.h 2006-08-12 08:17:55.000000000 -0400
19733@@ -3,11 +3,17 @@
19734
19735 #include <linux/config.h>
19736 #include <asm/fixmap.h>
19737+#include <asm/desc.h>
19738 #include <linux/threads.h>
19739 #include <linux/mm.h> /* for struct page */
19740
19741+#ifdef CONFIG_PAX_NOVSYSCALL
19742+#define pmd_populate_kernel(mm, pmd, pte) \
19743+ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)))
19744+#else
19745 #define pmd_populate_kernel(mm, pmd, pte) \
19746 set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
19747+#endif
19748
19749 #define pmd_populate(mm, pmd, pte) \
19750 set_pmd(pmd, __pmd(_PAGE_TABLE + \
19751diff -urNp linux-2.6.17.11/include/asm-i386/pgtable.h linux-2.6.17.11/include/asm-i386/pgtable.h
19752--- linux-2.6.17.11/include/asm-i386/pgtable.h 2006-08-07 00:18:54.000000000 -0400
19753+++ linux-2.6.17.11/include/asm-i386/pgtable.h 2006-08-12 08:17:55.000000000 -0400
19754@@ -34,7 +34,6 @@ struct vm_area_struct;
19755 */
19756 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
19757 extern unsigned long empty_zero_page[1024];
19758-extern pgd_t swapper_pg_dir[1024];
19759 extern kmem_cache_t *pgd_cache;
19760 extern kmem_cache_t *pmd_cache;
19761 extern spinlock_t pgd_lock;
19762@@ -59,6 +58,11 @@ void paging_init(void);
19763 # include <asm/pgtable-2level-defs.h>
19764 #endif
19765
19766+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
19767+#ifdef CONFIG_X86_PAE
19768+extern pmd_t swapper_pm_dir[PTRS_PER_PGD][PTRS_PER_PMD];
19769+#endif
19770+
19771 #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
19772 #define PGDIR_MASK (~(PGDIR_SIZE-1))
19773
19774@@ -68,9 +72,11 @@ void paging_init(void);
19775 #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
19776 #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
19777
19778+#ifndef CONFIG_X86_PAE
19779 #define TWOLEVEL_PGDIR_SHIFT 22
19780 #define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
19781 #define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
19782+#endif
19783
19784 /* Just any arbitrary offset to the start of the vmalloc VM area: the
19785 * current 8MB value just means that there will be a 8MB "hole" after the
19786@@ -141,17 +147,26 @@ void paging_init(void);
19787
19788 #define PAGE_SHARED_EXEC \
19789 __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
19790-#define PAGE_COPY_NOEXEC \
19791- __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
19792 #define PAGE_COPY_EXEC \
19793 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
19794-#define PAGE_COPY \
19795- PAGE_COPY_NOEXEC
19796 #define PAGE_READONLY \
19797 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
19798 #define PAGE_READONLY_EXEC \
19799 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
19800
19801+#ifdef CONFIG_PAX_PAGEEXEC
19802+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED)
19803+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
19804+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
19805+#else
19806+# define PAGE_SHARED_NOEXEC PAGE_SHARED
19807+# define PAGE_COPY_NOEXEC \
19808+ __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
19809+# define PAGE_READONLY_NOEXEC PAGE_READONLY
19810+#endif
19811+
19812+#define PAGE_COPY \
19813+ PAGE_COPY_NOEXEC
19814 #define _PAGE_KERNEL \
19815 (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
19816 #define _PAGE_KERNEL_EXEC \
19817@@ -176,18 +191,18 @@ extern unsigned long long __PAGE_KERNEL,
19818 * This is the closest we can get..
19819 */
19820 #define __P000 PAGE_NONE
19821-#define __P001 PAGE_READONLY
19822-#define __P010 PAGE_COPY
19823-#define __P011 PAGE_COPY
19824+#define __P001 PAGE_READONLY_NOEXEC
19825+#define __P010 PAGE_COPY_NOEXEC
19826+#define __P011 PAGE_COPY_NOEXEC
19827 #define __P100 PAGE_READONLY_EXEC
19828 #define __P101 PAGE_READONLY_EXEC
19829 #define __P110 PAGE_COPY_EXEC
19830 #define __P111 PAGE_COPY_EXEC
19831
19832 #define __S000 PAGE_NONE
19833-#define __S001 PAGE_READONLY
19834-#define __S010 PAGE_SHARED
19835-#define __S011 PAGE_SHARED
19836+#define __S001 PAGE_READONLY_NOEXEC
19837+#define __S010 PAGE_SHARED_NOEXEC
19838+#define __S011 PAGE_SHARED_NOEXEC
19839 #define __S100 PAGE_READONLY_EXEC
19840 #define __S101 PAGE_READONLY_EXEC
19841 #define __S110 PAGE_SHARED_EXEC
19842@@ -431,6 +446,9 @@ extern void noexec_setup(const char *str
19843
19844 #endif /* !__ASSEMBLY__ */
19845
19846+#define HAVE_ARCH_UNMAPPED_AREA
19847+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
19848+
19849 #ifdef CONFIG_FLATMEM
19850 #define kern_addr_valid(addr) (1)
19851 #endif /* CONFIG_FLATMEM */
19852diff -urNp linux-2.6.17.11/include/asm-i386/processor.h linux-2.6.17.11/include/asm-i386/processor.h
19853--- linux-2.6.17.11/include/asm-i386/processor.h 2006-08-07 00:18:54.000000000 -0400
19854+++ linux-2.6.17.11/include/asm-i386/processor.h 2006-08-12 08:17:55.000000000 -0400
19855@@ -19,7 +19,6 @@
19856 #include <linux/cache.h>
19857 #include <linux/config.h>
19858 #include <linux/threads.h>
19859-#include <asm/percpu.h>
19860 #include <linux/cpumask.h>
19861
19862 /* flag for disabling the tsc */
19863@@ -94,8 +93,6 @@ struct cpuinfo_x86 {
19864
19865 extern struct cpuinfo_x86 boot_cpu_data;
19866 extern struct cpuinfo_x86 new_cpu_data;
19867-extern struct tss_struct doublefault_tss;
19868-DECLARE_PER_CPU(struct tss_struct, init_tss);
19869
19870 #ifdef CONFIG_SMP
19871 extern struct cpuinfo_x86 cpu_data[];
19872@@ -325,10 +322,19 @@ extern int bootloader_type;
19873 */
19874 #define TASK_SIZE (PAGE_OFFSET)
19875
19876+#ifdef CONFIG_PAX_SEGMEXEC
19877+#define SEGMEXEC_TASK_SIZE ((PAGE_OFFSET) / 2)
19878+#endif
19879+
19880 /* This decides where the kernel will search for a free chunk of vm
19881 * space during mmap's.
19882 */
19883+
19884+#ifdef CONFIG_PAX_SEGMEXEC
19885+#define TASK_UNMAPPED_BASE (PAGE_ALIGN((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3 : TASK_SIZE/3))
19886+#else
19887 #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
19888+#endif
19889
19890 #define HAVE_ARCH_PICK_MMAP_LAYOUT
19891
19892@@ -444,6 +450,9 @@ struct tss_struct {
19893
19894 #define ARCH_MIN_TASKALIGN 16
19895
19896+extern struct tss_struct doublefault_tss;
19897+extern struct tss_struct init_tss[NR_CPUS];
19898+
19899 struct thread_struct {
19900 /* cached TLS descriptors. */
19901 struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
19902@@ -472,6 +481,7 @@ struct thread_struct {
19903 };
19904
19905 #define INIT_THREAD { \
19906+ .esp0 = sizeof(init_stack) + (long)&init_stack - 8, \
19907 .vm86_info = NULL, \
19908 .sysenter_cs = __KERNEL_CS, \
19909 .io_bitmap_ptr = NULL, \
19910@@ -484,7 +494,7 @@ struct thread_struct {
19911 * be within the limit.
19912 */
19913 #define INIT_TSS { \
19914- .esp0 = sizeof(init_stack) + (long)&init_stack, \
19915+ .esp0 = sizeof(init_stack) + (long)&init_stack - 8, \
19916 .ss0 = __KERNEL_DS, \
19917 .ss1 = __KERNEL_CS, \
19918 .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
19919@@ -560,11 +570,7 @@ void show_trace(struct task_struct *task
19920 unsigned long get_wchan(struct task_struct *p);
19921
19922 #define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long))
19923-#define KSTK_TOP(info) \
19924-({ \
19925- unsigned long *__ptr = (unsigned long *)(info); \
19926- (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
19927-})
19928+#define KSTK_TOP(info) ((info)->task.thread.esp0)
19929
19930 /*
19931 * The below -8 is to reserve 8 bytes on top of the ring0 stack.
19932@@ -579,7 +585,7 @@ unsigned long get_wchan(struct task_stru
19933 #define task_pt_regs(task) \
19934 ({ \
19935 struct pt_regs *__regs__; \
19936- __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
19937+ __regs__ = (struct pt_regs *)((task)->thread.esp0); \
19938 __regs__ - 1; \
19939 })
19940
19941diff -urNp linux-2.6.17.11/include/asm-i386/ptrace.h linux-2.6.17.11/include/asm-i386/ptrace.h
19942--- linux-2.6.17.11/include/asm-i386/ptrace.h 2006-08-07 00:18:54.000000000 -0400
19943+++ linux-2.6.17.11/include/asm-i386/ptrace.h 2006-08-12 08:17:55.000000000 -0400
19944@@ -65,17 +65,18 @@ struct task_struct;
19945 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
19946
19947 /*
19948- * user_mode_vm(regs) determines whether a register set came from user mode.
19949+ * user_mode(regs) determines whether a register set came from user mode.
19950 * This is true if V8086 mode was enabled OR if the register set was from
19951 * protected mode with RPL-3 CS value. This tricky test checks that with
19952 * one comparison. Many places in the kernel can bypass this full check
19953- * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
19954+ * if they have already ruled out V8086 mode, so user_mode_novm(regs) can
19955+ * be used.
19956 */
19957-static inline int user_mode(struct pt_regs *regs)
19958+static inline int user_mode_novm(struct pt_regs *regs)
19959 {
19960 return (regs->xcs & 3) != 0;
19961 }
19962-static inline int user_mode_vm(struct pt_regs *regs)
19963+static inline int user_mode(struct pt_regs *regs)
19964 {
19965 return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0;
19966 }
19967diff -urNp linux-2.6.17.11/include/asm-i386/system.h linux-2.6.17.11/include/asm-i386/system.h
19968--- linux-2.6.17.11/include/asm-i386/system.h 2006-08-07 00:18:54.000000000 -0400
19969+++ linux-2.6.17.11/include/asm-i386/system.h 2006-08-12 08:17:55.000000000 -0400
19970@@ -5,6 +5,7 @@
19971 #include <linux/kernel.h>
19972 #include <asm/segment.h>
19973 #include <asm/cpufeature.h>
19974+#include <asm/page.h>
19975 #include <linux/bitops.h> /* for LOCK_PREFIX */
19976
19977 #ifdef __KERNEL__
19978@@ -151,7 +152,7 @@ static inline unsigned long get_limit(un
19979 unsigned long __limit;
19980 __asm__("lsll %1,%0"
19981 :"=r" (__limit):"r" (segment));
19982- return __limit+1;
19983+ return __limit;
19984 }
19985
19986 #define nop() __asm__ __volatile__ ("nop")
19987@@ -496,7 +497,7 @@ static inline void sched_cacheflush(void
19988 wbinvd();
19989 }
19990
19991-extern unsigned long arch_align_stack(unsigned long sp);
19992+#define arch_align_stack(x) (x)
19993 extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
19994
19995 void default_idle(void);
19996diff -urNp linux-2.6.17.11/include/asm-i386/uaccess.h linux-2.6.17.11/include/asm-i386/uaccess.h
19997--- linux-2.6.17.11/include/asm-i386/uaccess.h 2006-08-07 00:18:54.000000000 -0400
19998+++ linux-2.6.17.11/include/asm-i386/uaccess.h 2006-08-12 08:17:55.000000000 -0400
19999@@ -10,6 +10,8 @@
20000 #include <linux/prefetch.h>
20001 #include <linux/string.h>
20002 #include <asm/page.h>
20003+#include <asm/segment.h>
20004+#include <asm/desc.h>
20005
20006 #define VERIFY_READ 0
20007 #define VERIFY_WRITE 1
20008@@ -30,7 +32,8 @@
20009
20010 #define get_ds() (KERNEL_DS)
20011 #define get_fs() (current_thread_info()->addr_limit)
20012-#define set_fs(x) (current_thread_info()->addr_limit = (x))
20013+void __set_fs(mm_segment_t x, int cpu);
20014+void set_fs(mm_segment_t x);
20015
20016 #define segment_eq(a,b) ((a).seg == (b).seg)
20017
20018@@ -281,9 +284,12 @@ extern void __put_user_8(void);
20019
20020 #define __put_user_u64(x, addr, err) \
20021 __asm__ __volatile__( \
20022- "1: movl %%eax,0(%2)\n" \
20023- "2: movl %%edx,4(%2)\n" \
20024+ " movw %w5,%%ds\n" \
20025+ "1: movl %%eax,%%ds:0(%2)\n" \
20026+ "2: movl %%edx,%%ds:4(%2)\n" \
20027 "3:\n" \
20028+ " pushl %%ss\n" \
20029+ " popl %%ds\n" \
20030 ".section .fixup,\"ax\"\n" \
20031 "4: movl %3,%0\n" \
20032 " jmp 3b\n" \
20033@@ -294,7 +300,8 @@ extern void __put_user_8(void);
20034 " .long 2b,4b\n" \
20035 ".previous" \
20036 : "=r"(err) \
20037- : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
20038+ : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err), \
20039+ "r"(__USER_DS))
20040
20041 #ifdef CONFIG_X86_WP_WORKS_OK
20042
20043@@ -333,8 +340,11 @@ struct __large_struct { unsigned long bu
20044 */
20045 #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \
20046 __asm__ __volatile__( \
20047- "1: mov"itype" %"rtype"1,%2\n" \
20048+ " movw %w5,%%ds\n" \
20049+ "1: mov"itype" %"rtype"1,%%ds:%2\n" \
20050 "2:\n" \
20051+ " pushl %%ss\n" \
20052+ " popl %%ds\n" \
20053 ".section .fixup,\"ax\"\n" \
20054 "3: movl %3,%0\n" \
20055 " jmp 2b\n" \
20056@@ -344,7 +354,8 @@ struct __large_struct { unsigned long bu
20057 " .long 1b,3b\n" \
20058 ".previous" \
20059 : "=r"(err) \
20060- : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))
20061+ : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err), \
20062+ "r"(__USER_DS))
20063
20064
20065 #define __get_user_nocheck(x,ptr,size) \
20066@@ -372,8 +383,11 @@ do { \
20067
20068 #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \
20069 __asm__ __volatile__( \
20070- "1: mov"itype" %2,%"rtype"1\n" \
20071+ " movw %w5,%%ds\n" \
20072+ "1: mov"itype" %%ds:%2,%"rtype"1\n" \
20073 "2:\n" \
20074+ " pushl %%ss\n" \
20075+ " popl %%ds\n" \
20076 ".section .fixup,\"ax\"\n" \
20077 "3: movl %3,%0\n" \
20078 " xor"itype" %"rtype"1,%"rtype"1\n" \
20079@@ -384,7 +398,7 @@ do { \
20080 " .long 1b,3b\n" \
20081 ".previous" \
20082 : "=r"(err), ltype (x) \
20083- : "m"(__m(addr)), "i"(errret), "0"(err))
20084+ : "m"(__m(addr)), "i"(errret), "0"(err), "r"(__USER_DS))
20085
20086
20087 unsigned long __must_check __copy_to_user_ll(void __user *to,
20088diff -urNp linux-2.6.17.11/include/asm-ia64/elf.h linux-2.6.17.11/include/asm-ia64/elf.h
20089--- linux-2.6.17.11/include/asm-ia64/elf.h 2006-08-07 00:18:54.000000000 -0400
20090+++ linux-2.6.17.11/include/asm-ia64/elf.h 2006-08-12 08:17:55.000000000 -0400
20091@@ -163,6 +163,16 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR
20092 typedef struct ia64_fpreg elf_fpreg_t;
20093 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
20094
20095+#ifdef CONFIG_PAX_ASLR
20096+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
20097+
20098+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20099+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
20100+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20101+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
20102+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20103+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
20104+#endif
20105
20106
20107 struct pt_regs; /* forward declaration... */
20108diff -urNp linux-2.6.17.11/include/asm-ia64/kmap_types.h linux-2.6.17.11/include/asm-ia64/kmap_types.h
20109--- linux-2.6.17.11/include/asm-ia64/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20110+++ linux-2.6.17.11/include/asm-ia64/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20111@@ -23,7 +23,8 @@ D(9) KM_IRQ0,
20112 D(10) KM_IRQ1,
20113 D(11) KM_SOFTIRQ0,
20114 D(12) KM_SOFTIRQ1,
20115-D(13) KM_TYPE_NR
20116+D(13) KM_CLEARPAGE,
20117+D(14) KM_TYPE_NR
20118 };
20119
20120 #undef D
20121diff -urNp linux-2.6.17.11/include/asm-ia64/page.h linux-2.6.17.11/include/asm-ia64/page.h
20122--- linux-2.6.17.11/include/asm-ia64/page.h 2006-08-07 00:18:54.000000000 -0400
20123+++ linux-2.6.17.11/include/asm-ia64/page.h 2006-08-12 08:17:55.000000000 -0400
20124@@ -229,4 +229,13 @@ get_order (unsigned long size)
20125 (((current->personality & READ_IMPLIES_EXEC) != 0) \
20126 ? VM_EXEC : 0))
20127
20128+#ifdef CONFIG_PAX_PAGEEXEC
20129+#ifdef CONFIG_PAX_MPROTECT
20130+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20131+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20132+#else
20133+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20134+#endif
20135+#endif
20136+
20137 #endif /* _ASM_IA64_PAGE_H */
20138diff -urNp linux-2.6.17.11/include/asm-ia64/pgtable.h linux-2.6.17.11/include/asm-ia64/pgtable.h
20139--- linux-2.6.17.11/include/asm-ia64/pgtable.h 2006-08-07 00:18:54.000000000 -0400
20140+++ linux-2.6.17.11/include/asm-ia64/pgtable.h 2006-08-12 08:17:55.000000000 -0400
20141@@ -144,6 +144,17 @@
20142 #define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
20143 #define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
20144 #define PAGE_COPY_EXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX)
20145+
20146+#ifdef CONFIG_PAX_PAGEEXEC
20147+# define PAGE_SHARED_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW)
20148+# define PAGE_READONLY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
20149+# define PAGE_COPY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
20150+#else
20151+# define PAGE_SHARED_NOEXEC PAGE_SHARED
20152+# define PAGE_READONLY_NOEXEC PAGE_READONLY
20153+# define PAGE_COPY_NOEXEC PAGE_COPY
20154+#endif
20155+
20156 #define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
20157 #define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX)
20158 #define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX)
20159diff -urNp linux-2.6.17.11/include/asm-ia64/processor.h linux-2.6.17.11/include/asm-ia64/processor.h
20160--- linux-2.6.17.11/include/asm-ia64/processor.h 2006-08-07 00:18:54.000000000 -0400
20161+++ linux-2.6.17.11/include/asm-ia64/processor.h 2006-08-12 08:17:55.000000000 -0400
20162@@ -284,7 +284,7 @@ struct thread_struct {
20163 .on_ustack = 0, \
20164 .ksp = 0, \
20165 .map_base = DEFAULT_MAP_BASE, \
20166- .rbs_bot = STACK_TOP - DEFAULT_USER_STACK_SIZE, \
20167+ .rbs_bot = __STACK_TOP - DEFAULT_USER_STACK_SIZE, \
20168 .task_size = DEFAULT_TASK_SIZE, \
20169 .last_fph_cpu = -1, \
20170 INIT_THREAD_IA32 \
20171diff -urNp linux-2.6.17.11/include/asm-ia64/ustack.h linux-2.6.17.11/include/asm-ia64/ustack.h
20172--- linux-2.6.17.11/include/asm-ia64/ustack.h 2006-08-07 00:18:54.000000000 -0400
20173+++ linux-2.6.17.11/include/asm-ia64/ustack.h 2006-08-12 08:17:55.000000000 -0400
20174@@ -11,6 +11,6 @@
20175 #define MAX_USER_STACK_SIZE (RGN_MAP_LIMIT/2)
20176 /* Make a default stack size of 2GB */
20177 #define DEFAULT_USER_STACK_SIZE (1UL << 31)
20178-#define STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT)
20179+#define __STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT)
20180
20181 #endif /* _ASM_IA64_USTACK_H */
20182diff -urNp linux-2.6.17.11/include/asm-m32r/kmap_types.h linux-2.6.17.11/include/asm-m32r/kmap_types.h
20183--- linux-2.6.17.11/include/asm-m32r/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20184+++ linux-2.6.17.11/include/asm-m32r/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20185@@ -25,7 +25,8 @@ D(9) KM_IRQ0,
20186 D(10) KM_IRQ1,
20187 D(11) KM_SOFTIRQ0,
20188 D(12) KM_SOFTIRQ1,
20189-D(13) KM_TYPE_NR
20190+D(13) KM_CLEARPAGE,
20191+D(14) KM_TYPE_NR
20192 };
20193
20194 #undef D
20195diff -urNp linux-2.6.17.11/include/asm-m68k/kmap_types.h linux-2.6.17.11/include/asm-m68k/kmap_types.h
20196--- linux-2.6.17.11/include/asm-m68k/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20197+++ linux-2.6.17.11/include/asm-m68k/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20198@@ -15,6 +15,7 @@ enum km_type {
20199 KM_IRQ1,
20200 KM_SOFTIRQ0,
20201 KM_SOFTIRQ1,
20202+ KM_CLEARPAGE,
20203 KM_TYPE_NR
20204 };
20205
20206diff -urNp linux-2.6.17.11/include/asm-m68knommu/kmap_types.h linux-2.6.17.11/include/asm-m68knommu/kmap_types.h
20207--- linux-2.6.17.11/include/asm-m68knommu/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20208+++ linux-2.6.17.11/include/asm-m68knommu/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20209@@ -15,6 +15,7 @@ enum km_type {
20210 KM_IRQ1,
20211 KM_SOFTIRQ0,
20212 KM_SOFTIRQ1,
20213+ KM_CLEARPAGE,
20214 KM_TYPE_NR
20215 };
20216
20217diff -urNp linux-2.6.17.11/include/asm-mips/a.out.h linux-2.6.17.11/include/asm-mips/a.out.h
20218--- linux-2.6.17.11/include/asm-mips/a.out.h 2006-08-07 00:18:54.000000000 -0400
20219+++ linux-2.6.17.11/include/asm-mips/a.out.h 2006-08-12 08:17:55.000000000 -0400
20220@@ -36,10 +36,10 @@ struct exec
20221 #ifdef __KERNEL__
20222
20223 #ifdef CONFIG_32BIT
20224-#define STACK_TOP TASK_SIZE
20225+#define __STACK_TOP TASK_SIZE
20226 #endif
20227 #ifdef CONFIG_64BIT
20228-#define STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
20229+#define __STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
20230 #endif
20231
20232 #endif
20233diff -urNp linux-2.6.17.11/include/asm-mips/elf.h linux-2.6.17.11/include/asm-mips/elf.h
20234--- linux-2.6.17.11/include/asm-mips/elf.h 2006-08-07 00:18:54.000000000 -0400
20235+++ linux-2.6.17.11/include/asm-mips/elf.h 2006-08-12 08:17:55.000000000 -0400
20236@@ -372,4 +372,15 @@ extern int dump_task_fpu(struct task_str
20237 #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
20238 #endif
20239
20240+#ifdef CONFIG_PAX_ASLR
20241+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
20242+
20243+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20244+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
20245+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20246+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
20247+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20248+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
20249+#endif
20250+
20251 #endif /* _ASM_ELF_H */
20252diff -urNp linux-2.6.17.11/include/asm-mips/kmap_types.h linux-2.6.17.11/include/asm-mips/kmap_types.h
20253--- linux-2.6.17.11/include/asm-mips/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20254+++ linux-2.6.17.11/include/asm-mips/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20255@@ -23,7 +23,8 @@ D(9) KM_IRQ0,
20256 D(10) KM_IRQ1,
20257 D(11) KM_SOFTIRQ0,
20258 D(12) KM_SOFTIRQ1,
20259-D(13) KM_TYPE_NR
20260+D(13) KM_CLEARPAGE,
20261+D(14) KM_TYPE_NR
20262 };
20263
20264 #undef D
20265diff -urNp linux-2.6.17.11/include/asm-mips/page.h linux-2.6.17.11/include/asm-mips/page.h
20266--- linux-2.6.17.11/include/asm-mips/page.h 2006-08-07 00:18:54.000000000 -0400
20267+++ linux-2.6.17.11/include/asm-mips/page.h 2006-08-12 08:17:55.000000000 -0400
20268@@ -79,15 +79,17 @@ static inline void copy_user_page(void *
20269 #ifdef CONFIG_CPU_MIPS32
20270 typedef struct { unsigned long pte_low, pte_high; } pte_t;
20271 #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
20272+ #define __pte(x) ({ pte_t __pte = {(x), (x) >> 32}; __pte;})
20273 #else
20274 typedef struct { unsigned long long pte; } pte_t;
20275 #define pte_val(x) ((x).pte)
20276+ #define __pte(x) ((pte_t) { (x) } )
20277 #endif
20278 #else
20279 typedef struct { unsigned long pte; } pte_t;
20280 #define pte_val(x) ((x).pte)
20281-#endif
20282 #define __pte(x) ((pte_t) { (x) } )
20283+#endif
20284
20285 /*
20286 * For 3-level pagetables we defines these ourselves, for 2-level the
20287@@ -151,6 +153,15 @@ typedef struct { unsigned long pgprot; }
20288 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
20289 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
20290
20291+#ifdef CONFIG_PAX_PAGEEXEC
20292+#ifdef CONFIG_PAX_MPROTECT
20293+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20294+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20295+#else
20296+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20297+#endif
20298+#endif
20299+
20300 #define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE)
20301 #define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET)
20302
20303diff -urNp linux-2.6.17.11/include/asm-parisc/a.out.h linux-2.6.17.11/include/asm-parisc/a.out.h
20304--- linux-2.6.17.11/include/asm-parisc/a.out.h 2006-08-07 00:18:54.000000000 -0400
20305+++ linux-2.6.17.11/include/asm-parisc/a.out.h 2006-08-12 08:17:55.000000000 -0400
20306@@ -22,7 +22,7 @@ struct exec
20307 /* XXX: STACK_TOP actually should be STACK_BOTTOM for parisc.
20308 * prumpf */
20309
20310-#define STACK_TOP TASK_SIZE
20311+#define __STACK_TOP TASK_SIZE
20312
20313 #endif
20314
20315diff -urNp linux-2.6.17.11/include/asm-parisc/elf.h linux-2.6.17.11/include/asm-parisc/elf.h
20316--- linux-2.6.17.11/include/asm-parisc/elf.h 2006-08-07 00:18:54.000000000 -0400
20317+++ linux-2.6.17.11/include/asm-parisc/elf.h 2006-08-12 08:17:55.000000000 -0400
20318@@ -337,6 +337,17 @@ struct pt_regs; /* forward declaration..
20319
20320 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000)
20321
20322+#ifdef CONFIG_PAX_ASLR
20323+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000UL
20324+
20325+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20326+#define PAX_DELTA_MMAP_LEN(tsk) 16
20327+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20328+#define PAX_DELTA_EXEC_LEN(tsk) 16
20329+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20330+#define PAX_DELTA_STACK_LEN(tsk) 16
20331+#endif
20332+
20333 /* This yields a mask that user programs can use to figure out what
20334 instruction set this CPU supports. This could be done in user space,
20335 but it's not easy, and we've already done it here. */
20336diff -urNp linux-2.6.17.11/include/asm-parisc/kmap_types.h linux-2.6.17.11/include/asm-parisc/kmap_types.h
20337--- linux-2.6.17.11/include/asm-parisc/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20338+++ linux-2.6.17.11/include/asm-parisc/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20339@@ -23,7 +23,8 @@ D(9) KM_IRQ0,
20340 D(10) KM_IRQ1,
20341 D(11) KM_SOFTIRQ0,
20342 D(12) KM_SOFTIRQ1,
20343-D(13) KM_TYPE_NR
20344+D(13) KM_CLEARPAGE,
20345+D(14) KM_TYPE_NR
20346 };
20347
20348 #undef D
20349diff -urNp linux-2.6.17.11/include/asm-parisc/page.h linux-2.6.17.11/include/asm-parisc/page.h
20350--- linux-2.6.17.11/include/asm-parisc/page.h 2006-08-07 00:18:54.000000000 -0400
20351+++ linux-2.6.17.11/include/asm-parisc/page.h 2006-08-12 08:17:55.000000000 -0400
20352@@ -189,6 +189,15 @@ extern int npmem_ranges;
20353 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
20354 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
20355
20356+#ifdef CONFIG_PAX_PAGEEXEC
20357+#ifdef CONFIG_PAX_MPROTECT
20358+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20359+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20360+#else
20361+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20362+#endif
20363+#endif
20364+
20365 #endif /* __KERNEL__ */
20366
20367 #include <asm-generic/memory_model.h>
20368diff -urNp linux-2.6.17.11/include/asm-parisc/pgtable.h linux-2.6.17.11/include/asm-parisc/pgtable.h
20369--- linux-2.6.17.11/include/asm-parisc/pgtable.h 2006-08-07 00:18:54.000000000 -0400
20370+++ linux-2.6.17.11/include/asm-parisc/pgtable.h 2006-08-12 08:17:55.000000000 -0400
20371@@ -220,6 +220,17 @@ extern void *vmalloc_start;
20372 #define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED)
20373 #define PAGE_COPY PAGE_EXECREAD
20374 #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED)
20375+
20376+#ifdef CONFIG_PAX_PAGEEXEC
20377+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_ACCESSED)
20378+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
20379+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
20380+#else
20381+# define PAGE_SHARED_NOEXEC PAGE_SHARED
20382+# define PAGE_COPY_NOEXEC PAGE_COPY
20383+# define PAGE_READONLY_NOEXEC PAGE_READONLY
20384+#endif
20385+
20386 #define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
20387 #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
20388 #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
20389diff -urNp linux-2.6.17.11/include/asm-powerpc/a.out.h linux-2.6.17.11/include/asm-powerpc/a.out.h
20390--- linux-2.6.17.11/include/asm-powerpc/a.out.h 2006-08-07 00:18:54.000000000 -0400
20391+++ linux-2.6.17.11/include/asm-powerpc/a.out.h 2006-08-12 08:17:55.000000000 -0400
20392@@ -23,12 +23,12 @@ struct exec
20393 #define STACK_TOP_USER64 TASK_SIZE_USER64
20394 #define STACK_TOP_USER32 TASK_SIZE_USER32
20395
20396-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
20397+#define __STACK_TOP (test_thread_flag(TIF_32BIT) ? \
20398 STACK_TOP_USER32 : STACK_TOP_USER64)
20399
20400 #else /* __powerpc64__ */
20401
20402-#define STACK_TOP TASK_SIZE
20403+#define __STACK_TOP TASK_SIZE
20404
20405 #endif /* __powerpc64__ */
20406 #endif /* __KERNEL__ */
20407diff -urNp linux-2.6.17.11/include/asm-powerpc/elf.h linux-2.6.17.11/include/asm-powerpc/elf.h
20408--- linux-2.6.17.11/include/asm-powerpc/elf.h 2006-08-07 00:18:54.000000000 -0400
20409+++ linux-2.6.17.11/include/asm-powerpc/elf.h 2006-08-12 08:17:55.000000000 -0400
20410@@ -176,6 +176,26 @@ typedef elf_vrreg_t elf_vrregset_t32[ELF
20411
20412 #define ELF_ET_DYN_BASE (0x08000000)
20413
20414+#ifdef CONFIG_PAX_ASLR
20415+#define PAX_ELF_ET_DYN_BASE(tsk) (0x10000000UL)
20416+
20417+#ifdef __powerpc64__
20418+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20419+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
20420+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20421+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
20422+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20423+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
20424+#else
20425+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20426+#define PAX_DELTA_MMAP_LEN(tsk) 15
20427+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20428+#define PAX_DELTA_EXEC_LEN(tsk) 15
20429+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20430+#define PAX_DELTA_STACK_LEN(tsk) 15
20431+#endif
20432+#endif
20433+
20434 #ifdef __KERNEL__
20435
20436 /* Common routine for both 32-bit and 64-bit processes */
20437diff -urNp linux-2.6.17.11/include/asm-powerpc/kmap_types.h linux-2.6.17.11/include/asm-powerpc/kmap_types.h
20438--- linux-2.6.17.11/include/asm-powerpc/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20439+++ linux-2.6.17.11/include/asm-powerpc/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20440@@ -26,6 +26,7 @@ enum km_type {
20441 KM_SOFTIRQ1,
20442 KM_PPC_SYNC_PAGE,
20443 KM_PPC_SYNC_ICACHE,
20444+ KM_CLEARPAGE,
20445 KM_TYPE_NR
20446 };
20447
20448diff -urNp linux-2.6.17.11/include/asm-powerpc/page_64.h linux-2.6.17.11/include/asm-powerpc/page_64.h
20449--- linux-2.6.17.11/include/asm-powerpc/page_64.h 2006-08-07 00:18:54.000000000 -0400
20450+++ linux-2.6.17.11/include/asm-powerpc/page_64.h 2006-08-12 08:17:55.000000000 -0400
20451@@ -170,6 +170,15 @@ extern unsigned int HPAGE_SHIFT;
20452 (test_thread_flag(TIF_32BIT) ? \
20453 VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
20454
20455+#ifdef CONFIG_PAX_PAGEEXEC
20456+#ifdef CONFIG_PAX_MPROTECT
20457+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20458+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20459+#else
20460+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20461+#endif
20462+#endif
20463+
20464 #include <asm-generic/page.h>
20465
20466 #endif /* __KERNEL__ */
20467diff -urNp linux-2.6.17.11/include/asm-ppc/page.h linux-2.6.17.11/include/asm-ppc/page.h
20468--- linux-2.6.17.11/include/asm-ppc/page.h 2006-08-07 00:18:54.000000000 -0400
20469+++ linux-2.6.17.11/include/asm-ppc/page.h 2006-08-12 08:17:55.000000000 -0400
20470@@ -175,6 +175,15 @@ extern __inline__ int get_order(unsigned
20471 /* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */
20472 #define __HAVE_ARCH_GATE_AREA 1
20473
20474+#ifdef CONFIG_PAX_PAGEEXEC
20475+#ifdef CONFIG_PAX_MPROTECT
20476+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20477+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20478+#else
20479+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20480+#endif
20481+#endif
20482+
20483 #include <asm-generic/memory_model.h>
20484 #endif /* __KERNEL__ */
20485 #endif /* _PPC_PAGE_H */
20486diff -urNp linux-2.6.17.11/include/asm-ppc/pgtable.h linux-2.6.17.11/include/asm-ppc/pgtable.h
20487--- linux-2.6.17.11/include/asm-ppc/pgtable.h 2006-08-07 00:18:54.000000000 -0400
20488+++ linux-2.6.17.11/include/asm-ppc/pgtable.h 2006-08-12 08:17:55.000000000 -0400
20489@@ -441,11 +441,21 @@ extern unsigned long ioremap_bot, iorema
20490
20491 #define PAGE_NONE __pgprot(_PAGE_BASE)
20492 #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
20493-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
20494+#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC)
20495 #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
20496-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
20497+#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC | _PAGE_HWEXEC)
20498 #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
20499-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
20500+#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC)
20501+
20502+#if defined(CONFIG_PAX_PAGEEXEC) && !defined(CONFIG_40x) && !defined(CONFIG_44x)
20503+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_GUARDED)
20504+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
20505+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
20506+#else
20507+# define PAGE_SHARED_NOEXEC PAGE_SHARED
20508+# define PAGE_COPY_NOEXEC PAGE_COPY
20509+# define PAGE_READONLY_NOEXEC PAGE_READONLY
20510+#endif
20511
20512 #define PAGE_KERNEL __pgprot(_PAGE_RAM)
20513 #define PAGE_KERNEL_NOCACHE __pgprot(_PAGE_IO)
20514@@ -457,21 +467,21 @@ extern unsigned long ioremap_bot, iorema
20515 * This is the closest we can get..
20516 */
20517 #define __P000 PAGE_NONE
20518-#define __P001 PAGE_READONLY_X
20519-#define __P010 PAGE_COPY
20520-#define __P011 PAGE_COPY_X
20521-#define __P100 PAGE_READONLY
20522+#define __P001 PAGE_READONLY_NOEXEC
20523+#define __P010 PAGE_COPY_NOEXEC
20524+#define __P011 PAGE_COPY_NOEXEC
20525+#define __P100 PAGE_READONLY_X
20526 #define __P101 PAGE_READONLY_X
20527-#define __P110 PAGE_COPY
20528+#define __P110 PAGE_COPY_X
20529 #define __P111 PAGE_COPY_X
20530
20531 #define __S000 PAGE_NONE
20532-#define __S001 PAGE_READONLY_X
20533-#define __S010 PAGE_SHARED
20534-#define __S011 PAGE_SHARED_X
20535-#define __S100 PAGE_READONLY
20536+#define __S001 PAGE_READONLY_NOEXEC
20537+#define __S010 PAGE_SHARED_NOEXEC
20538+#define __S011 PAGE_SHARED_NOEXEC
20539+#define __S100 PAGE_READONLY_X
20540 #define __S101 PAGE_READONLY_X
20541-#define __S110 PAGE_SHARED
20542+#define __S110 PAGE_SHARED_X
20543 #define __S111 PAGE_SHARED_X
20544
20545 #ifndef __ASSEMBLY__
20546diff -urNp linux-2.6.17.11/include/asm-s390/kmap_types.h linux-2.6.17.11/include/asm-s390/kmap_types.h
20547--- linux-2.6.17.11/include/asm-s390/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20548+++ linux-2.6.17.11/include/asm-s390/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20549@@ -16,6 +16,7 @@ enum km_type {
20550 KM_IRQ1,
20551 KM_SOFTIRQ0,
20552 KM_SOFTIRQ1,
20553+ KM_CLEARPAGE,
20554 KM_TYPE_NR
20555 };
20556
20557diff -urNp linux-2.6.17.11/include/asm-sh/kmap_types.h linux-2.6.17.11/include/asm-sh/kmap_types.h
20558--- linux-2.6.17.11/include/asm-sh/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20559+++ linux-2.6.17.11/include/asm-sh/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20560@@ -25,7 +25,8 @@ D(9) KM_IRQ0,
20561 D(10) KM_IRQ1,
20562 D(11) KM_SOFTIRQ0,
20563 D(12) KM_SOFTIRQ1,
20564-D(13) KM_TYPE_NR
20565+D(13) KM_CLEARPAGE,
20566+D(14) KM_TYPE_NR
20567 };
20568
20569 #undef D
20570diff -urNp linux-2.6.17.11/include/asm-sparc/a.out.h linux-2.6.17.11/include/asm-sparc/a.out.h
20571--- linux-2.6.17.11/include/asm-sparc/a.out.h 2006-08-07 00:18:54.000000000 -0400
20572+++ linux-2.6.17.11/include/asm-sparc/a.out.h 2006-08-12 08:17:55.000000000 -0400
20573@@ -91,7 +91,7 @@ struct relocation_info /* used when head
20574
20575 #include <asm/page.h>
20576
20577-#define STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
20578+#define __STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
20579
20580 #endif /* __KERNEL__ */
20581
20582diff -urNp linux-2.6.17.11/include/asm-sparc/elf.h linux-2.6.17.11/include/asm-sparc/elf.h
20583--- linux-2.6.17.11/include/asm-sparc/elf.h 2006-08-07 00:18:54.000000000 -0400
20584+++ linux-2.6.17.11/include/asm-sparc/elf.h 2006-08-12 08:17:55.000000000 -0400
20585@@ -145,6 +145,17 @@ typedef struct {
20586
20587 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE)
20588
20589+#ifdef CONFIG_PAX_ASLR
20590+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000UL
20591+
20592+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20593+#define PAX_DELTA_MMAP_LEN(tsk) 16
20594+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20595+#define PAX_DELTA_EXEC_LEN(tsk) 16
20596+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20597+#define PAX_DELTA_STACK_LEN(tsk) 16
20598+#endif
20599+
20600 /* This yields a mask that user programs can use to figure out what
20601 instruction set this cpu supports. This can NOT be done in userspace
20602 on Sparc. */
20603diff -urNp linux-2.6.17.11/include/asm-sparc/kmap_types.h linux-2.6.17.11/include/asm-sparc/kmap_types.h
20604--- linux-2.6.17.11/include/asm-sparc/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20605+++ linux-2.6.17.11/include/asm-sparc/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20606@@ -15,6 +15,7 @@ enum km_type {
20607 KM_IRQ1,
20608 KM_SOFTIRQ0,
20609 KM_SOFTIRQ1,
20610+ KM_CLEARPAGE,
20611 KM_TYPE_NR
20612 };
20613
20614diff -urNp linux-2.6.17.11/include/asm-sparc/page.h linux-2.6.17.11/include/asm-sparc/page.h
20615--- linux-2.6.17.11/include/asm-sparc/page.h 2006-08-07 00:18:54.000000000 -0400
20616+++ linux-2.6.17.11/include/asm-sparc/page.h 2006-08-12 08:17:55.000000000 -0400
20617@@ -161,6 +161,15 @@ extern unsigned long pfn_base;
20618 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
20619 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
20620
20621+#ifdef CONFIG_PAX_PAGEEXEC
20622+#ifdef CONFIG_PAX_MPROTECT
20623+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20624+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20625+#else
20626+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20627+#endif
20628+#endif
20629+
20630 #endif /* __KERNEL__ */
20631
20632 #include <asm-generic/memory_model.h>
20633diff -urNp linux-2.6.17.11/include/asm-sparc/pgtable.h linux-2.6.17.11/include/asm-sparc/pgtable.h
20634--- linux-2.6.17.11/include/asm-sparc/pgtable.h 2006-08-07 00:18:54.000000000 -0400
20635+++ linux-2.6.17.11/include/asm-sparc/pgtable.h 2006-08-12 08:17:55.000000000 -0400
20636@@ -50,6 +50,13 @@ BTFIXUPDEF_INT(page_none)
20637 BTFIXUPDEF_INT(page_shared)
20638 BTFIXUPDEF_INT(page_copy)
20639 BTFIXUPDEF_INT(page_readonly)
20640+
20641+#ifdef CONFIG_PAX_PAGEEXEC
20642+BTFIXUPDEF_INT(page_shared_noexec)
20643+BTFIXUPDEF_INT(page_copy_noexec)
20644+BTFIXUPDEF_INT(page_readonly_noexec)
20645+#endif
20646+
20647 BTFIXUPDEF_INT(page_kernel)
20648
20649 #define PMD_SHIFT SUN4C_PMD_SHIFT
20650@@ -71,6 +78,16 @@ BTFIXUPDEF_INT(page_kernel)
20651 #define PAGE_COPY __pgprot(BTFIXUP_INT(page_copy))
20652 #define PAGE_READONLY __pgprot(BTFIXUP_INT(page_readonly))
20653
20654+#ifdef CONFIG_PAX_PAGEEXEC
20655+# define PAGE_SHARED_NOEXEC __pgprot(BTFIXUP_INT(page_shared_noexec))
20656+# define PAGE_COPY_NOEXEC __pgprot(BTFIXUP_INT(page_copy_noexec))
20657+# define PAGE_READONLY_NOEXEC __pgprot(BTFIXUP_INT(page_readonly_noexec))
20658+#else
20659+# define PAGE_SHARED_NOEXEC PAGE_SHARED
20660+# define PAGE_COPY_NOEXEC PAGE_COPY
20661+# define PAGE_READONLY_NOEXEC PAGE_READONLY
20662+#endif
20663+
20664 extern unsigned long page_kernel;
20665
20666 #ifdef MODULE
20667diff -urNp linux-2.6.17.11/include/asm-sparc/pgtsrmmu.h linux-2.6.17.11/include/asm-sparc/pgtsrmmu.h
20668--- linux-2.6.17.11/include/asm-sparc/pgtsrmmu.h 2006-08-07 00:18:54.000000000 -0400
20669+++ linux-2.6.17.11/include/asm-sparc/pgtsrmmu.h 2006-08-12 08:17:55.000000000 -0400
20670@@ -115,6 +115,16 @@
20671 SRMMU_EXEC | SRMMU_REF)
20672 #define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \
20673 SRMMU_EXEC | SRMMU_REF)
20674+
20675+#ifdef CONFIG_PAX_PAGEEXEC
20676+#define SRMMU_PAGE_SHARED_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
20677+ SRMMU_WRITE | SRMMU_REF)
20678+#define SRMMU_PAGE_COPY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
20679+ SRMMU_REF)
20680+#define SRMMU_PAGE_RDONLY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
20681+ SRMMU_REF)
20682+#endif
20683+
20684 #define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \
20685 SRMMU_DIRTY | SRMMU_REF)
20686
20687diff -urNp linux-2.6.17.11/include/asm-sparc/uaccess.h linux-2.6.17.11/include/asm-sparc/uaccess.h
20688--- linux-2.6.17.11/include/asm-sparc/uaccess.h 2006-08-07 00:18:54.000000000 -0400
20689+++ linux-2.6.17.11/include/asm-sparc/uaccess.h 2006-08-12 08:17:55.000000000 -0400
20690@@ -41,7 +41,7 @@
20691 * No one can read/write anything from userland in the kernel space by setting
20692 * large size and address near to PAGE_OFFSET - a fault will break his intentions.
20693 */
20694-#define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; })
20695+#define __user_ok(addr, size) ({ (void)(size); (addr) < __STACK_TOP; })
20696 #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
20697 #define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
20698 #define access_ok(type, addr, size) \
20699diff -urNp linux-2.6.17.11/include/asm-sparc64/a.out.h linux-2.6.17.11/include/asm-sparc64/a.out.h
20700--- linux-2.6.17.11/include/asm-sparc64/a.out.h 2006-08-07 00:18:54.000000000 -0400
20701+++ linux-2.6.17.11/include/asm-sparc64/a.out.h 2006-08-12 08:17:55.000000000 -0400
20702@@ -98,7 +98,7 @@ struct relocation_info /* used when head
20703 #define STACK_TOP32 ((1UL << 32UL) - PAGE_SIZE)
20704 #define STACK_TOP64 (0x0000080000000000UL - (1UL << 32UL))
20705
20706-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
20707+#define __STACK_TOP (test_thread_flag(TIF_32BIT) ? \
20708 STACK_TOP32 : STACK_TOP64)
20709
20710 #endif
20711diff -urNp linux-2.6.17.11/include/asm-sparc64/elf.h linux-2.6.17.11/include/asm-sparc64/elf.h
20712--- linux-2.6.17.11/include/asm-sparc64/elf.h 2006-08-07 00:18:54.000000000 -0400
20713+++ linux-2.6.17.11/include/asm-sparc64/elf.h 2006-08-12 08:17:55.000000000 -0400
20714@@ -142,6 +142,16 @@ typedef struct {
20715 #define ELF_ET_DYN_BASE 0x0000010000000000UL
20716 #endif
20717
20718+#ifdef CONFIG_PAX_ASLR
20719+#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_32BIT) ? 0x10000UL : 0x100000UL)
20720+
20721+#define PAX_DELTA_MMAP_LSB(tsk) (PAGE_SHIFT + 1)
20722+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 14 : 28 )
20723+#define PAX_DELTA_EXEC_LSB(tsk) (PAGE_SHIFT + 1)
20724+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 14 : 28 )
20725+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20726+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 15 : 29 )
20727+#endif
20728
20729 /* This yields a mask that user programs can use to figure out what
20730 instruction set this cpu supports. */
20731diff -urNp linux-2.6.17.11/include/asm-sparc64/kmap_types.h linux-2.6.17.11/include/asm-sparc64/kmap_types.h
20732--- linux-2.6.17.11/include/asm-sparc64/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20733+++ linux-2.6.17.11/include/asm-sparc64/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20734@@ -19,6 +19,7 @@ enum km_type {
20735 KM_IRQ1,
20736 KM_SOFTIRQ0,
20737 KM_SOFTIRQ1,
20738+ KM_CLEARPAGE,
20739 KM_TYPE_NR
20740 };
20741
20742diff -urNp linux-2.6.17.11/include/asm-sparc64/page.h linux-2.6.17.11/include/asm-sparc64/page.h
20743--- linux-2.6.17.11/include/asm-sparc64/page.h 2006-08-07 00:18:54.000000000 -0400
20744+++ linux-2.6.17.11/include/asm-sparc64/page.h 2006-08-12 08:17:55.000000000 -0400
20745@@ -142,6 +142,15 @@ typedef unsigned long pgprot_t;
20746 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
20747 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
20748
20749+#ifdef CONFIG_PAX_PAGEEXEC
20750+#ifdef CONFIG_PAX_MPROTECT
20751+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20752+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20753+#else
20754+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20755+#endif
20756+#endif
20757+
20758 #endif /* !(__KERNEL__) */
20759
20760 #include <asm-generic/page.h>
20761diff -urNp linux-2.6.17.11/include/asm-v850/kmap_types.h linux-2.6.17.11/include/asm-v850/kmap_types.h
20762--- linux-2.6.17.11/include/asm-v850/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20763+++ linux-2.6.17.11/include/asm-v850/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20764@@ -13,6 +13,7 @@ enum km_type {
20765 KM_PTE1,
20766 KM_IRQ0,
20767 KM_IRQ1,
20768+ KM_CLEARPAGE,
20769 KM_TYPE_NR
20770 };
20771
20772diff -urNp linux-2.6.17.11/include/asm-x86_64/a.out.h linux-2.6.17.11/include/asm-x86_64/a.out.h
20773--- linux-2.6.17.11/include/asm-x86_64/a.out.h 2006-08-07 00:18:54.000000000 -0400
20774+++ linux-2.6.17.11/include/asm-x86_64/a.out.h 2006-08-12 08:17:55.000000000 -0400
20775@@ -21,7 +21,7 @@ struct exec
20776
20777 #ifdef __KERNEL__
20778 #include <linux/thread_info.h>
20779-#define STACK_TOP TASK_SIZE
20780+#define __STACK_TOP TASK_SIZE
20781 #endif
20782
20783 #endif /* __A_OUT_GNU_H__ */
20784diff -urNp linux-2.6.17.11/include/asm-x86_64/elf.h linux-2.6.17.11/include/asm-x86_64/elf.h
20785--- linux-2.6.17.11/include/asm-x86_64/elf.h 2006-08-07 00:18:54.000000000 -0400
20786+++ linux-2.6.17.11/include/asm-x86_64/elf.h 2006-08-12 08:17:55.000000000 -0400
20787@@ -90,6 +90,17 @@ typedef struct user_i387_struct elf_fpre
20788
20789 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
20790
20791+#ifdef CONFIG_PAX_ASLR
20792+#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_IA32) ? 0x08048000UL : 0x400000UL)
20793+
20794+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20795+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
20796+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20797+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
20798+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20799+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
20800+#endif
20801+
20802 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
20803 now struct_user_regs, they are different). Assumes current is the process
20804 getting dumped. */
20805diff -urNp linux-2.6.17.11/include/asm-x86_64/ia32.h linux-2.6.17.11/include/asm-x86_64/ia32.h
20806--- linux-2.6.17.11/include/asm-x86_64/ia32.h 2006-08-07 00:18:54.000000000 -0400
20807+++ linux-2.6.17.11/include/asm-x86_64/ia32.h 2006-08-12 08:17:55.000000000 -0400
20808@@ -157,7 +157,13 @@ struct ustat32 {
20809 char f_fpack[6];
20810 };
20811
20812-#define IA32_STACK_TOP IA32_PAGE_OFFSET
20813+#ifdef CONFIG_PAX_RANDUSTACK
20814+#define IA32_DELTA_STACK (current->mm->delta_stack)
20815+#else
20816+#define IA32_DELTA_STACK 0UL
20817+#endif
20818+
20819+#define IA32_STACK_TOP (IA32_PAGE_OFFSET - IA32_DELTA_STACK)
20820
20821 #ifdef __KERNEL__
20822 struct user_desc;
20823diff -urNp linux-2.6.17.11/include/asm-x86_64/kmap_types.h linux-2.6.17.11/include/asm-x86_64/kmap_types.h
20824--- linux-2.6.17.11/include/asm-x86_64/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20825+++ linux-2.6.17.11/include/asm-x86_64/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20826@@ -13,6 +13,7 @@ enum km_type {
20827 KM_IRQ1,
20828 KM_SOFTIRQ0,
20829 KM_SOFTIRQ1,
20830+ KM_CLEARPAGE,
20831 KM_TYPE_NR
20832 };
20833
20834diff -urNp linux-2.6.17.11/include/asm-x86_64/page.h linux-2.6.17.11/include/asm-x86_64/page.h
20835--- linux-2.6.17.11/include/asm-x86_64/page.h 2006-08-07 00:18:54.000000000 -0400
20836+++ linux-2.6.17.11/include/asm-x86_64/page.h 2006-08-12 08:17:55.000000000 -0400
20837@@ -134,6 +134,15 @@ typedef struct { unsigned long pgprot; }
20838 (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
20839 VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
20840
20841+#ifdef CONFIG_PAX_PAGEEXEC
20842+#ifdef CONFIG_PAX_MPROTECT
20843+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20844+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20845+#else
20846+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20847+#endif
20848+#endif
20849+
20850 #define __HAVE_ARCH_GATE_AREA 1
20851
20852 #endif /* __KERNEL__ */
20853diff -urNp linux-2.6.17.11/include/asm-x86_64/pgalloc.h linux-2.6.17.11/include/asm-x86_64/pgalloc.h
20854--- linux-2.6.17.11/include/asm-x86_64/pgalloc.h 2006-08-07 00:18:54.000000000 -0400
20855+++ linux-2.6.17.11/include/asm-x86_64/pgalloc.h 2006-08-12 08:17:55.000000000 -0400
20856@@ -7,7 +7,7 @@
20857 #include <linux/mm.h>
20858
20859 #define pmd_populate_kernel(mm, pmd, pte) \
20860- set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
20861+ set_pmd(pmd, __pmd(_KERNPG_TABLE | __pa(pte)))
20862 #define pud_populate(mm, pud, pmd) \
20863 set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)))
20864 #define pgd_populate(mm, pgd, pud) \
20865diff -urNp linux-2.6.17.11/include/asm-x86_64/pgtable.h linux-2.6.17.11/include/asm-x86_64/pgtable.h
20866--- linux-2.6.17.11/include/asm-x86_64/pgtable.h 2006-08-07 00:18:54.000000000 -0400
20867+++ linux-2.6.17.11/include/asm-x86_64/pgtable.h 2006-08-12 08:17:55.000000000 -0400
20868@@ -180,6 +180,10 @@ static inline pte_t ptep_get_and_clear_f
20869 #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
20870 #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
20871 #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
20872+
20873+#define PAGE_READONLY_NOEXEC PAGE_READONLY
20874+#define PAGE_SHARED_NOEXEC PAGE_SHARED
20875+
20876 #define __PAGE_KERNEL \
20877 (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
20878 #define __PAGE_KERNEL_EXEC \
20879@@ -268,7 +272,13 @@ static inline pte_t pfn_pte(unsigned lon
20880 #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
20881 static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
20882 static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
20883-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
20884+extern inline int pte_exec(pte_t pte)
20885+{
20886+ if (__supported_pte_mask & _PAGE_NX)
20887+ return pte_val(pte) & _PAGE_NX;
20888+ else
20889+ return pte_val(pte) & _PAGE_USER;
20890+}
20891 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
20892 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
20893 static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
20894@@ -276,12 +286,26 @@ static inline int pte_file(pte_t pte) {
20895 static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_PSE; }
20896
20897 static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
20898-static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
20899+extern inline pte_t pte_exprotect(pte_t pte)
20900+{
20901+ if (__supported_pte_mask & _PAGE_NX)
20902+ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_NX));
20903+ else
20904+ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER));
20905+ return pte;
20906+}
20907 static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
20908 static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
20909 static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
20910 static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
20911-static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
20912+extern inline pte_t pte_mkexec(pte_t pte)
20913+{
20914+ if (__supported_pte_mask & _PAGE_NX)
20915+ set_pte(&pte, __pte(pte_val(pte) | _PAGE_NX));
20916+ else
20917+ set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER));
20918+ return pte;
20919+}
20920 static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
20921 static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
20922 static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
20923diff -urNp linux-2.6.17.11/include/asm-x86_64/system.h linux-2.6.17.11/include/asm-x86_64/system.h
20924--- linux-2.6.17.11/include/asm-x86_64/system.h 2006-08-07 00:18:54.000000000 -0400
20925+++ linux-2.6.17.11/include/asm-x86_64/system.h 2006-08-12 08:17:55.000000000 -0400
20926@@ -366,6 +366,6 @@ static inline unsigned long __cmpxchg(vo
20927
20928 void cpu_idle_wait(void);
20929
20930-extern unsigned long arch_align_stack(unsigned long sp);
20931+#define arch_align_stack(x) (x)
20932
20933 #endif
20934diff -urNp linux-2.6.17.11/include/asm-xtensa/kmap_types.h linux-2.6.17.11/include/asm-xtensa/kmap_types.h
20935--- linux-2.6.17.11/include/asm-xtensa/kmap_types.h 2006-08-07 00:18:54.000000000 -0400
20936+++ linux-2.6.17.11/include/asm-xtensa/kmap_types.h 2006-08-12 08:17:55.000000000 -0400
20937@@ -25,6 +25,7 @@ enum km_type {
20938 KM_IRQ1,
20939 KM_SOFTIRQ0,
20940 KM_SOFTIRQ1,
20941+ KM_CLEARPAGE,
20942 KM_TYPE_NR
20943 };
20944
20945diff -urNp linux-2.6.17.11/include/linux/a.out.h linux-2.6.17.11/include/linux/a.out.h
20946--- linux-2.6.17.11/include/linux/a.out.h 2006-08-07 00:18:54.000000000 -0400
20947+++ linux-2.6.17.11/include/linux/a.out.h 2006-08-12 08:17:55.000000000 -0400
20948@@ -7,6 +7,16 @@
20949
20950 #include <asm/a.out.h>
20951
20952+#ifdef CONFIG_PAX_RANDUSTACK
20953+#define __DELTA_STACK (current->mm->delta_stack)
20954+#else
20955+#define __DELTA_STACK 0UL
20956+#endif
20957+
20958+#ifndef STACK_TOP
20959+#define STACK_TOP (__STACK_TOP - __DELTA_STACK)
20960+#endif
20961+
20962 #endif /* __STRUCT_EXEC_OVERRIDE__ */
20963
20964 /* these go in the N_MACHTYPE field */
20965@@ -37,6 +47,14 @@ enum machine_type {
20966 M_MIPS2 = 152 /* MIPS R6000/R4000 binary */
20967 };
20968
20969+/* Constants for the N_FLAGS field */
20970+#define F_PAX_PAGEEXEC 1 /* Paging based non-executable pages */
20971+#define F_PAX_EMUTRAMP 2 /* Emulate trampolines */
20972+#define F_PAX_MPROTECT 4 /* Restrict mprotect() */
20973+#define F_PAX_RANDMMAP 8 /* Randomize mmap() base */
20974+/*#define F_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */
20975+#define F_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */
20976+
20977 #if !defined (N_MAGIC)
20978 #define N_MAGIC(exec) ((exec).a_info & 0xffff)
20979 #endif
20980diff -urNp linux-2.6.17.11/include/linux/binfmts.h linux-2.6.17.11/include/linux/binfmts.h
20981--- linux-2.6.17.11/include/linux/binfmts.h 2006-08-07 00:18:54.000000000 -0400
20982+++ linux-2.6.17.11/include/linux/binfmts.h 2006-08-12 08:17:55.000000000 -0400
20983@@ -7,10 +7,10 @@ struct pt_regs;
20984
20985 /*
20986 * MAX_ARG_PAGES defines the number of pages allocated for arguments
20987- * and envelope for the new program. 32 should suffice, this gives
20988- * a maximum env+arg of 128kB w/4KB pages!
20989+ * and envelope for the new program. 33 should suffice, this gives
20990+ * a maximum env+arg of 132kB w/4KB pages!
20991 */
20992-#define MAX_ARG_PAGES 32
20993+#define MAX_ARG_PAGES 33
20994
20995 /* sizeof(linux_binprm->buf) */
20996 #define BINPRM_BUF_SIZE 128
20997@@ -38,6 +38,7 @@ struct linux_binprm{
20998 unsigned interp_flags;
20999 unsigned interp_data;
21000 unsigned long loader, exec;
21001+ int misc;
21002 };
21003
21004 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
21005@@ -87,5 +88,8 @@ extern void compute_creds(struct linux_b
21006 extern int do_coredump(long signr, int exit_code, struct pt_regs * regs);
21007 extern int set_binfmt(struct linux_binfmt *new);
21008
21009+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp);
21010+void pax_report_insns(void *pc, void *sp);
21011+
21012 #endif /* __KERNEL__ */
21013 #endif /* _LINUX_BINFMTS_H */
21014diff -urNp linux-2.6.17.11/include/linux/capability.h linux-2.6.17.11/include/linux/capability.h
21015--- linux-2.6.17.11/include/linux/capability.h 2006-08-07 00:18:54.000000000 -0400
21016+++ linux-2.6.17.11/include/linux/capability.h 2006-08-12 08:17:55.000000000 -0400
21017@@ -358,6 +358,7 @@ static inline kernel_cap_t cap_invert(ke
21018 #define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)
21019
21020 int capable(int cap);
21021+int capable_nolog(int cap);
21022 int __capable(struct task_struct *t, int cap);
21023
21024 #endif /* __KERNEL__ */
21025diff -urNp linux-2.6.17.11/include/linux/elf.h linux-2.6.17.11/include/linux/elf.h
21026--- linux-2.6.17.11/include/linux/elf.h 2006-08-07 00:18:54.000000000 -0400
21027+++ linux-2.6.17.11/include/linux/elf.h 2006-08-12 08:17:55.000000000 -0400
21028@@ -5,6 +5,10 @@
21029 #include <linux/auxvec.h>
21030 #include <asm/elf.h>
21031
21032+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
21033+#undef elf_read_implies_exec
21034+#endif
21035+
21036 #ifndef elf_read_implies_exec
21037 /* Executables for which elf_read_implies_exec() returns TRUE will
21038 have the READ_IMPLIES_EXEC personality flag set automatically.
21039@@ -46,6 +50,16 @@ typedef __s64 Elf64_Sxword;
21040
21041 #define PT_GNU_STACK (PT_LOOS + 0x474e551)
21042
21043+#define PT_PAX_FLAGS (PT_LOOS + 0x5041580)
21044+
21045+/* Constants for the e_flags field */
21046+#define EF_PAX_PAGEEXEC 1 /* Paging based non-executable pages */
21047+#define EF_PAX_EMUTRAMP 2 /* Emulate trampolines */
21048+#define EF_PAX_MPROTECT 4 /* Restrict mprotect() */
21049+#define EF_PAX_RANDMMAP 8 /* Randomize mmap() base */
21050+/*#define EF_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */
21051+#define EF_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */
21052+
21053 /* These constants define the different elf file types */
21054 #define ET_NONE 0
21055 #define ET_REL 1
21056@@ -138,6 +152,8 @@ typedef __s64 Elf64_Sxword;
21057 #define DT_DEBUG 21
21058 #define DT_TEXTREL 22
21059 #define DT_JMPREL 23
21060+#define DT_FLAGS 30
21061+ #define DF_TEXTREL 0x00000004
21062 #define DT_LOPROC 0x70000000
21063 #define DT_HIPROC 0x7fffffff
21064
21065@@ -267,6 +283,19 @@ typedef struct elf64_hdr {
21066 #define PF_W 0x2
21067 #define PF_X 0x1
21068
21069+#define PF_PAGEEXEC (1U << 4) /* Enable PAGEEXEC */
21070+#define PF_NOPAGEEXEC (1U << 5) /* Disable PAGEEXEC */
21071+#define PF_SEGMEXEC (1U << 6) /* Enable SEGMEXEC */
21072+#define PF_NOSEGMEXEC (1U << 7) /* Disable SEGMEXEC */
21073+#define PF_MPROTECT (1U << 8) /* Enable MPROTECT */
21074+#define PF_NOMPROTECT (1U << 9) /* Disable MPROTECT */
21075+/*#define PF_RANDEXEC (1U << 10)*/ /* Enable RANDEXEC */
21076+/*#define PF_NORANDEXEC (1U << 11)*/ /* Disable RANDEXEC */
21077+#define PF_EMUTRAMP (1U << 12) /* Enable EMUTRAMP */
21078+#define PF_NOEMUTRAMP (1U << 13) /* Disable EMUTRAMP */
21079+#define PF_RANDMMAP (1U << 14) /* Enable RANDMMAP */
21080+#define PF_NORANDMMAP (1U << 15) /* Disable RANDMMAP */
21081+
21082 typedef struct elf32_phdr{
21083 Elf32_Word p_type;
21084 Elf32_Off p_offset;
21085@@ -359,6 +388,8 @@ typedef struct elf64_shdr {
21086 #define EI_OSABI 7
21087 #define EI_PAD 8
21088
21089+#define EI_PAX 14
21090+
21091 #define ELFMAG0 0x7f /* EI_MAG */
21092 #define ELFMAG1 'E'
21093 #define ELFMAG2 'L'
21094@@ -415,6 +446,7 @@ extern Elf32_Dyn _DYNAMIC [];
21095 #define elfhdr elf32_hdr
21096 #define elf_phdr elf32_phdr
21097 #define elf_note elf32_note
21098+#define elf_dyn Elf32_Dyn
21099
21100 #else
21101
21102@@ -422,6 +454,7 @@ extern Elf64_Dyn _DYNAMIC [];
21103 #define elfhdr elf64_hdr
21104 #define elf_phdr elf64_phdr
21105 #define elf_note elf64_note
21106+#define elf_dyn Elf64_Dyn
21107
21108 #endif
21109
21110diff -urNp linux-2.6.17.11/include/linux/gracl.h linux-2.6.17.11/include/linux/gracl.h
21111--- linux-2.6.17.11/include/linux/gracl.h 1969-12-31 19:00:00.000000000 -0500
21112+++ linux-2.6.17.11/include/linux/gracl.h 2006-08-12 08:17:55.000000000 -0400
21113@@ -0,0 +1,316 @@
21114+#ifndef GR_ACL_H
21115+#define GR_ACL_H
21116+
21117+#include <linux/grdefs.h>
21118+#include <linux/resource.h>
21119+#include <linux/dcache.h>
21120+#include <asm/resource.h>
21121+
21122+/* Major status information */
21123+
21124+#define GR_VERSION "grsecurity 2.1.9"
21125+#define GRSECURITY_VERSION 0x219
21126+
21127+enum {
21128+
21129+ SHUTDOWN = 0,
21130+ ENABLE = 1,
21131+ SPROLE = 2,
21132+ RELOAD = 3,
21133+ SEGVMOD = 4,
21134+ STATUS = 5,
21135+ UNSPROLE = 6,
21136+ PASSSET = 7,
21137+ SPROLEPAM = 8
21138+};
21139+
21140+/* Password setup definitions
21141+ * kernel/grhash.c */
21142+enum {
21143+ GR_PW_LEN = 128,
21144+ GR_SALT_LEN = 16,
21145+ GR_SHA_LEN = 32,
21146+};
21147+
21148+enum {
21149+ GR_SPROLE_LEN = 64,
21150+};
21151+
21152+#define GR_NLIMITS (RLIMIT_LOCKS + 2)
21153+
21154+/* Begin Data Structures */
21155+
21156+struct sprole_pw {
21157+ unsigned char *rolename;
21158+ unsigned char salt[GR_SALT_LEN];
21159+ unsigned char sum[GR_SHA_LEN]; /* 256-bit SHA hash of the password */
21160+};
21161+
21162+struct name_entry {
21163+ __u32 key;
21164+ ino_t inode;
21165+ dev_t device;
21166+ char *name;
21167+ __u16 len;
21168+ struct name_entry *prev;
21169+ struct name_entry *next;
21170+};
21171+
21172+struct inodev_entry {
21173+ struct name_entry *nentry;
21174+ struct inodev_entry *prev;
21175+ struct inodev_entry *next;
21176+};
21177+
21178+struct acl_role_db {
21179+ struct acl_role_label **r_hash;
21180+ __u32 r_size;
21181+};
21182+
21183+struct inodev_db {
21184+ struct inodev_entry **i_hash;
21185+ __u32 i_size;
21186+};
21187+
21188+struct name_db {
21189+ struct name_entry **n_hash;
21190+ __u32 n_size;
21191+};
21192+
21193+struct crash_uid {
21194+ uid_t uid;
21195+ unsigned long expires;
21196+};
21197+
21198+struct gr_hash_struct {
21199+ void **table;
21200+ void **nametable;
21201+ void *first;
21202+ __u32 table_size;
21203+ __u32 used_size;
21204+ int type;
21205+};
21206+
21207+/* Userspace Grsecurity ACL data structures */
21208+
21209+struct acl_subject_label {
21210+ char *filename;
21211+ ino_t inode;
21212+ dev_t device;
21213+ __u32 mode;
21214+ __u32 cap_mask;
21215+ __u32 cap_lower;
21216+
21217+ struct rlimit res[GR_NLIMITS];
21218+ __u16 resmask;
21219+
21220+ __u8 user_trans_type;
21221+ __u8 group_trans_type;
21222+ uid_t *user_transitions;
21223+ gid_t *group_transitions;
21224+ __u16 user_trans_num;
21225+ __u16 group_trans_num;
21226+
21227+ __u32 ip_proto[8];
21228+ __u32 ip_type;
21229+ struct acl_ip_label **ips;
21230+ __u32 ip_num;
21231+
21232+ __u32 crashes;
21233+ unsigned long expires;
21234+
21235+ struct acl_subject_label *parent_subject;
21236+ struct gr_hash_struct *hash;
21237+ struct acl_subject_label *prev;
21238+ struct acl_subject_label *next;
21239+
21240+ struct acl_object_label **obj_hash;
21241+ __u32 obj_hash_size;
21242+ __u16 pax_flags;
21243+};
21244+
21245+struct role_allowed_ip {
21246+ __u32 addr;
21247+ __u32 netmask;
21248+
21249+ struct role_allowed_ip *prev;
21250+ struct role_allowed_ip *next;
21251+};
21252+
21253+struct role_transition {
21254+ char *rolename;
21255+
21256+ struct role_transition *prev;
21257+ struct role_transition *next;
21258+};
21259+
21260+struct acl_role_label {
21261+ char *rolename;
21262+ uid_t uidgid;
21263+ __u16 roletype;
21264+
21265+ __u16 auth_attempts;
21266+ unsigned long expires;
21267+
21268+ struct acl_subject_label *root_label;
21269+ struct gr_hash_struct *hash;
21270+
21271+ struct acl_role_label *prev;
21272+ struct acl_role_label *next;
21273+
21274+ struct role_transition *transitions;
21275+ struct role_allowed_ip *allowed_ips;
21276+ uid_t *domain_children;
21277+ __u16 domain_child_num;
21278+
21279+ struct acl_subject_label **subj_hash;
21280+ __u32 subj_hash_size;
21281+};
21282+
21283+struct user_acl_role_db {
21284+ struct acl_role_label **r_table;
21285+ __u32 num_pointers; /* Number of allocations to track */
21286+ __u32 num_roles; /* Number of roles */
21287+ __u32 num_domain_children; /* Number of domain children */
21288+ __u32 num_subjects; /* Number of subjects */
21289+ __u32 num_objects; /* Number of objects */
21290+};
21291+
21292+struct acl_object_label {
21293+ char *filename;
21294+ ino_t inode;
21295+ dev_t device;
21296+ __u32 mode;
21297+
21298+ struct acl_subject_label *nested;
21299+ struct acl_object_label *globbed;
21300+
21301+ /* next two structures not used */
21302+
21303+ struct acl_object_label *prev;
21304+ struct acl_object_label *next;
21305+};
21306+
21307+struct acl_ip_label {
21308+ char *iface;
21309+ __u32 addr;
21310+ __u32 netmask;
21311+ __u16 low, high;
21312+ __u8 mode;
21313+ __u32 type;
21314+ __u32 proto[8];
21315+
21316+ /* next two structures not used */
21317+
21318+ struct acl_ip_label *prev;
21319+ struct acl_ip_label *next;
21320+};
21321+
21322+struct gr_arg {
21323+ struct user_acl_role_db role_db;
21324+ unsigned char pw[GR_PW_LEN];
21325+ unsigned char salt[GR_SALT_LEN];
21326+ unsigned char sum[GR_SHA_LEN];
21327+ unsigned char sp_role[GR_SPROLE_LEN];
21328+ struct sprole_pw *sprole_pws;
21329+ dev_t segv_device;
21330+ ino_t segv_inode;
21331+ uid_t segv_uid;
21332+ __u16 num_sprole_pws;
21333+ __u16 mode;
21334+};
21335+
21336+struct gr_arg_wrapper {
21337+ struct gr_arg *arg;
21338+ __u32 version;
21339+ __u32 size;
21340+};
21341+
21342+struct subject_map {
21343+ struct acl_subject_label *user;
21344+ struct acl_subject_label *kernel;
21345+ struct subject_map *prev;
21346+ struct subject_map *next;
21347+};
21348+
21349+struct acl_subj_map_db {
21350+ struct subject_map **s_hash;
21351+ __u32 s_size;
21352+};
21353+
21354+/* End Data Structures Section */
21355+
21356+/* Hash functions generated by empirical testing by Brad Spengler
21357+ Makes good use of the low bits of the inode. Generally 0-1 times
21358+ in loop for successful match. 0-3 for unsuccessful match.
21359+ Shift/add algorithm with modulus of table size and an XOR*/
21360+
21361+static __inline__ unsigned int
21362+rhash(const uid_t uid, const __u16 type, const unsigned int sz)
21363+{
21364+ return (((uid << type) + (uid ^ type)) % sz);
21365+}
21366+
21367+ static __inline__ unsigned int
21368+shash(const struct acl_subject_label *userp, const unsigned int sz)
21369+{
21370+ return ((const unsigned long)userp % sz);
21371+}
21372+
21373+static __inline__ unsigned int
21374+fhash(const ino_t ino, const dev_t dev, const unsigned int sz)
21375+{
21376+ return (((ino + dev) ^ ((ino << 13) + (ino << 23) + (dev << 9))) % sz);
21377+}
21378+
21379+static __inline__ unsigned int
21380+nhash(const char *name, const __u16 len, const unsigned int sz)
21381+{
21382+ return full_name_hash(name, len) % sz;
21383+}
21384+
21385+#define FOR_EACH_ROLE_START(role,iter) \
21386+ role = NULL; \
21387+ iter = 0; \
21388+ while (iter < acl_role_set.r_size) { \
21389+ if (role == NULL) \
21390+ role = acl_role_set.r_hash[iter]; \
21391+ if (role == NULL) { \
21392+ iter++; \
21393+ continue; \
21394+ }
21395+
21396+#define FOR_EACH_ROLE_END(role,iter) \
21397+ role = role->next; \
21398+ if (role == NULL) \
21399+ iter++; \
21400+ }
21401+
21402+#define FOR_EACH_SUBJECT_START(role,subj,iter) \
21403+ subj = NULL; \
21404+ iter = 0; \
21405+ while (iter < role->subj_hash_size) { \
21406+ if (subj == NULL) \
21407+ subj = role->subj_hash[iter]; \
21408+ if (subj == NULL) { \
21409+ iter++; \
21410+ continue; \
21411+ }
21412+
21413+#define FOR_EACH_SUBJECT_END(subj,iter) \
21414+ subj = subj->next; \
21415+ if (subj == NULL) \
21416+ iter++; \
21417+ }
21418+
21419+
21420+#define FOR_EACH_NESTED_SUBJECT_START(role,subj) \
21421+ subj = role->hash->first; \
21422+ while (subj != NULL) {
21423+
21424+#define FOR_EACH_NESTED_SUBJECT_END(subj) \
21425+ subj = subj->next; \
21426+ }
21427+
21428+#endif
21429+
21430diff -urNp linux-2.6.17.11/include/linux/gralloc.h linux-2.6.17.11/include/linux/gralloc.h
21431--- linux-2.6.17.11/include/linux/gralloc.h 1969-12-31 19:00:00.000000000 -0500
21432+++ linux-2.6.17.11/include/linux/gralloc.h 2006-08-12 08:17:55.000000000 -0400
21433@@ -0,0 +1,8 @@
21434+#ifndef __GRALLOC_H
21435+#define __GRALLOC_H
21436+
21437+void acl_free_all(void);
21438+int acl_alloc_stack_init(unsigned long size);
21439+void *acl_alloc(unsigned long len);
21440+
21441+#endif
21442diff -urNp linux-2.6.17.11/include/linux/grdefs.h linux-2.6.17.11/include/linux/grdefs.h
21443--- linux-2.6.17.11/include/linux/grdefs.h 1969-12-31 19:00:00.000000000 -0500
21444+++ linux-2.6.17.11/include/linux/grdefs.h 2006-08-12 08:17:55.000000000 -0400
21445@@ -0,0 +1,131 @@
21446+#ifndef GRDEFS_H
21447+#define GRDEFS_H
21448+
21449+/* Begin grsecurity status declarations */
21450+
21451+enum {
21452+ GR_READY = 0x01,
21453+ GR_STATUS_INIT = 0x00 // disabled state
21454+};
21455+
21456+/* Begin ACL declarations */
21457+
21458+/* Role flags */
21459+
21460+enum {
21461+ GR_ROLE_USER = 0x0001,
21462+ GR_ROLE_GROUP = 0x0002,
21463+ GR_ROLE_DEFAULT = 0x0004,
21464+ GR_ROLE_SPECIAL = 0x0008,
21465+ GR_ROLE_AUTH = 0x0010,
21466+ GR_ROLE_NOPW = 0x0020,
21467+ GR_ROLE_GOD = 0x0040,
21468+ GR_ROLE_LEARN = 0x0080,
21469+ GR_ROLE_TPE = 0x0100,
21470+ GR_ROLE_DOMAIN = 0x0200,
21471+ GR_ROLE_PAM = 0x0400
21472+};
21473+
21474+/* ACL Subject and Object mode flags */
21475+enum {
21476+ GR_DELETED = 0x80000000
21477+};
21478+
21479+/* ACL Object-only mode flags */
21480+enum {
21481+ GR_READ = 0x00000001,
21482+ GR_APPEND = 0x00000002,
21483+ GR_WRITE = 0x00000004,
21484+ GR_EXEC = 0x00000008,
21485+ GR_FIND = 0x00000010,
21486+ GR_INHERIT = 0x00000020,
21487+ GR_SETID = 0x00000040,
21488+ GR_CREATE = 0x00000080,
21489+ GR_DELETE = 0x00000100,
21490+ GR_LINK = 0x00000200,
21491+ GR_AUDIT_READ = 0x00000400,
21492+ GR_AUDIT_APPEND = 0x00000800,
21493+ GR_AUDIT_WRITE = 0x00001000,
21494+ GR_AUDIT_EXEC = 0x00002000,
21495+ GR_AUDIT_FIND = 0x00004000,
21496+ GR_AUDIT_INHERIT= 0x00008000,
21497+ GR_AUDIT_SETID = 0x00010000,
21498+ GR_AUDIT_CREATE = 0x00020000,
21499+ GR_AUDIT_DELETE = 0x00040000,
21500+ GR_AUDIT_LINK = 0x00080000,
21501+ GR_PTRACERD = 0x00100000,
21502+ GR_NOPTRACE = 0x00200000,
21503+ GR_SUPPRESS = 0x00400000,
21504+ GR_NOLEARN = 0x00800000
21505+};
21506+
21507+#define GR_AUDITS (GR_AUDIT_READ | GR_AUDIT_WRITE | GR_AUDIT_APPEND | GR_AUDIT_EXEC | \
21508+ GR_AUDIT_FIND | GR_AUDIT_INHERIT | GR_AUDIT_SETID | \
21509+ GR_AUDIT_CREATE | GR_AUDIT_DELETE | GR_AUDIT_LINK)
21510+
21511+/* ACL subject-only mode flags */
21512+enum {
21513+ GR_KILL = 0x00000001,
21514+ GR_VIEW = 0x00000002,
21515+ GR_PROTECTED = 0x00000004,
21516+ GR_LEARN = 0x00000008,
21517+ GR_OVERRIDE = 0x00000010,
21518+ /* just a placeholder, this mode is only used in userspace */
21519+ GR_DUMMY = 0x00000020,
21520+ GR_PROTSHM = 0x00000040,
21521+ GR_KILLPROC = 0x00000080,
21522+ GR_KILLIPPROC = 0x00000100,
21523+ /* just a placeholder, this mode is only used in userspace */
21524+ GR_NOTROJAN = 0x00000200,
21525+ GR_PROTPROCFD = 0x00000400,
21526+ GR_PROCACCT = 0x00000800,
21527+ GR_RELAXPTRACE = 0x00001000,
21528+ GR_NESTED = 0x00002000,
21529+ GR_INHERITLEARN = 0x00004000,
21530+ GR_PROCFIND = 0x00008000,
21531+ GR_POVERRIDE = 0x00010000,
21532+ GR_KERNELAUTH = 0x00020000,
21533+};
21534+
21535+enum {
21536+ GR_PAX_ENABLE_SEGMEXEC = 0x0001,
21537+ GR_PAX_ENABLE_PAGEEXEC = 0x0002,
21538+ GR_PAX_ENABLE_MPROTECT = 0x0004,
21539+ GR_PAX_ENABLE_RANDMMAP = 0x0008,
21540+ GR_PAX_ENABLE_EMUTRAMP = 0x0010,
21541+ GR_PAX_DISABLE_SEGMEXEC = 0x8001,
21542+ GR_PAX_DISABLE_PAGEEXEC = 0x8002,
21543+ GR_PAX_DISABLE_MPROTECT = 0x8004,
21544+ GR_PAX_DISABLE_RANDMMAP = 0x8008,
21545+ GR_PAX_DISABLE_EMUTRAMP = 0x8010,
21546+};
21547+
21548+enum {
21549+ GR_ID_USER = 0x01,
21550+ GR_ID_GROUP = 0x02,
21551+};
21552+
21553+enum {
21554+ GR_ID_ALLOW = 0x01,
21555+ GR_ID_DENY = 0x02,
21556+};
21557+
21558+#define GR_CRASH_RES 11
21559+#define GR_UIDTABLE_MAX 500
21560+
21561+/* begin resource learning section */
21562+enum {
21563+ GR_RLIM_CPU_BUMP = 60,
21564+ GR_RLIM_FSIZE_BUMP = 50000,
21565+ GR_RLIM_DATA_BUMP = 10000,
21566+ GR_RLIM_STACK_BUMP = 1000,
21567+ GR_RLIM_CORE_BUMP = 10000,
21568+ GR_RLIM_RSS_BUMP = 500000,
21569+ GR_RLIM_NPROC_BUMP = 1,
21570+ GR_RLIM_NOFILE_BUMP = 5,
21571+ GR_RLIM_MEMLOCK_BUMP = 50000,
21572+ GR_RLIM_AS_BUMP = 500000,
21573+ GR_RLIM_LOCKS_BUMP = 2
21574+};
21575+
21576+#endif
21577diff -urNp linux-2.6.17.11/include/linux/grinternal.h linux-2.6.17.11/include/linux/grinternal.h
21578--- linux-2.6.17.11/include/linux/grinternal.h 1969-12-31 19:00:00.000000000 -0500
21579+++ linux-2.6.17.11/include/linux/grinternal.h 2006-08-12 08:17:55.000000000 -0400
21580@@ -0,0 +1,211 @@
21581+#ifndef __GRINTERNAL_H
21582+#define __GRINTERNAL_H
21583+
21584+#ifdef CONFIG_GRKERNSEC
21585+
21586+#include <linux/fs.h>
21587+#include <linux/gracl.h>
21588+#include <linux/grdefs.h>
21589+#include <linux/grmsg.h>
21590+
21591+extern void gr_add_learn_entry(const char *fmt, ...);
21592+extern __u32 gr_search_file(const struct dentry *dentry, const __u32 mode,
21593+ const struct vfsmount *mnt);
21594+extern __u32 gr_check_create(const struct dentry *new_dentry,
21595+ const struct dentry *parent,
21596+ const struct vfsmount *mnt, const __u32 mode);
21597+extern int gr_check_protected_task(const struct task_struct *task);
21598+extern __u32 to_gr_audit(const __u32 reqmode);
21599+extern int gr_set_acls(const int type);
21600+
21601+extern int gr_acl_is_enabled(void);
21602+extern char gr_roletype_to_char(void);
21603+
21604+extern void gr_handle_alertkill(struct task_struct *task);
21605+extern char *gr_to_filename(const struct dentry *dentry,
21606+ const struct vfsmount *mnt);
21607+extern char *gr_to_filename1(const struct dentry *dentry,
21608+ const struct vfsmount *mnt);
21609+extern char *gr_to_filename2(const struct dentry *dentry,
21610+ const struct vfsmount *mnt);
21611+extern char *gr_to_filename3(const struct dentry *dentry,
21612+ const struct vfsmount *mnt);
21613+
21614+extern int grsec_enable_link;
21615+extern int grsec_enable_fifo;
21616+extern int grsec_enable_execve;
21617+extern int grsec_enable_shm;
21618+extern int grsec_enable_execlog;
21619+extern int grsec_enable_signal;
21620+extern int grsec_enable_forkfail;
21621+extern int grsec_enable_time;
21622+extern int grsec_enable_chroot_shmat;
21623+extern int grsec_enable_chroot_findtask;
21624+extern int grsec_enable_chroot_mount;
21625+extern int grsec_enable_chroot_double;
21626+extern int grsec_enable_chroot_pivot;
21627+extern int grsec_enable_chroot_chdir;
21628+extern int grsec_enable_chroot_chmod;
21629+extern int grsec_enable_chroot_mknod;
21630+extern int grsec_enable_chroot_fchdir;
21631+extern int grsec_enable_chroot_nice;
21632+extern int grsec_enable_chroot_execlog;
21633+extern int grsec_enable_chroot_caps;
21634+extern int grsec_enable_chroot_sysctl;
21635+extern int grsec_enable_chroot_unix;
21636+extern int grsec_enable_tpe;
21637+extern int grsec_tpe_gid;
21638+extern int grsec_enable_tpe_all;
21639+extern int grsec_enable_sidcaps;
21640+extern int grsec_enable_randpid;
21641+extern int grsec_enable_socket_all;
21642+extern int grsec_socket_all_gid;
21643+extern int grsec_enable_socket_client;
21644+extern int grsec_socket_client_gid;
21645+extern int grsec_enable_socket_server;
21646+extern int grsec_socket_server_gid;
21647+extern int grsec_audit_gid;
21648+extern int grsec_enable_group;
21649+extern int grsec_enable_audit_ipc;
21650+extern int grsec_enable_audit_textrel;
21651+extern int grsec_enable_mount;
21652+extern int grsec_enable_chdir;
21653+extern int grsec_resource_logging;
21654+extern int grsec_lock;
21655+
21656+extern struct task_struct *child_reaper;
21657+
21658+extern spinlock_t grsec_alert_lock;
21659+extern unsigned long grsec_alert_wtime;
21660+extern unsigned long grsec_alert_fyet;
21661+
21662+extern spinlock_t grsec_audit_lock;
21663+
21664+extern rwlock_t grsec_exec_file_lock;
21665+
21666+#define gr_task_fullpath(tsk) (tsk->exec_file ? \
21667+ gr_to_filename2(tsk->exec_file->f_dentry, \
21668+ tsk->exec_file->f_vfsmnt) : "/")
21669+
21670+#define gr_parent_task_fullpath(tsk) (tsk->parent->exec_file ? \
21671+ gr_to_filename3(tsk->parent->exec_file->f_dentry, \
21672+ tsk->parent->exec_file->f_vfsmnt) : "/")
21673+
21674+#define gr_task_fullpath0(tsk) (tsk->exec_file ? \
21675+ gr_to_filename(tsk->exec_file->f_dentry, \
21676+ tsk->exec_file->f_vfsmnt) : "/")
21677+
21678+#define gr_parent_task_fullpath0(tsk) (tsk->parent->exec_file ? \
21679+ gr_to_filename1(tsk->parent->exec_file->f_dentry, \
21680+ tsk->parent->exec_file->f_vfsmnt) : "/")
21681+
21682+#define proc_is_chrooted(tsk_a) ((tsk_a->pid > 1) && (tsk_a->fs != NULL) && \
21683+ ((tsk_a->fs->root->d_inode->i_sb->s_dev != \
21684+ child_reaper->fs->root->d_inode->i_sb->s_dev) || \
21685+ (tsk_a->fs->root->d_inode->i_ino != \
21686+ child_reaper->fs->root->d_inode->i_ino)))
21687+
21688+#define have_same_root(tsk_a,tsk_b) ((tsk_a->fs != NULL) && (tsk_b->fs != NULL) && \
21689+ (tsk_a->fs->root->d_inode->i_sb->s_dev == \
21690+ tsk_b->fs->root->d_inode->i_sb->s_dev) && \
21691+ (tsk_a->fs->root->d_inode->i_ino == \
21692+ tsk_b->fs->root->d_inode->i_ino))
21693+
21694+#define DEFAULTSECARGS(task) gr_task_fullpath(task), task->comm, \
21695+ task->pid, task->uid, \
21696+ task->euid, task->gid, task->egid, \
21697+ gr_parent_task_fullpath(task), \
21698+ task->parent->comm, task->parent->pid, \
21699+ task->parent->uid, task->parent->euid, \
21700+ task->parent->gid, task->parent->egid
21701+
21702+#define GR_CHROOT_CAPS ( \
21703+ CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | CAP_TO_MASK(CAP_NET_ADMIN) | \
21704+ CAP_TO_MASK(CAP_SYS_MODULE) | CAP_TO_MASK(CAP_SYS_RAWIO) | \
21705+ CAP_TO_MASK(CAP_SYS_PACCT) | CAP_TO_MASK(CAP_SYS_ADMIN) | \
21706+ CAP_TO_MASK(CAP_SYS_BOOT) | CAP_TO_MASK(CAP_SYS_TIME) | \
21707+ CAP_TO_MASK(CAP_NET_RAW) | CAP_TO_MASK(CAP_SYS_TTY_CONFIG) | \
21708+ CAP_TO_MASK(CAP_IPC_OWNER))
21709+
21710+#define security_learn(normal_msg,args...) \
21711+({ \
21712+ read_lock(&grsec_exec_file_lock); \
21713+ gr_add_learn_entry(normal_msg "\n", ## args); \
21714+ read_unlock(&grsec_exec_file_lock); \
21715+})
21716+
21717+enum {
21718+ GR_DO_AUDIT,
21719+ GR_DONT_AUDIT,
21720+ GR_DONT_AUDIT_GOOD
21721+};
21722+
21723+enum {
21724+ GR_TTYSNIFF,
21725+ GR_RBAC,
21726+ GR_RBAC_STR,
21727+ GR_STR_RBAC,
21728+ GR_RBAC_MODE2,
21729+ GR_RBAC_MODE3,
21730+ GR_FILENAME,
21731+ GR_NOARGS,
21732+ GR_ONE_INT,
21733+ GR_ONE_INT_TWO_STR,
21734+ GR_ONE_STR,
21735+ GR_STR_INT,
21736+ GR_TWO_INT,
21737+ GR_THREE_INT,
21738+ GR_FIVE_INT_TWO_STR,
21739+ GR_TWO_STR,
21740+ GR_THREE_STR,
21741+ GR_FOUR_STR,
21742+ GR_STR_FILENAME,
21743+ GR_FILENAME_STR,
21744+ GR_FILENAME_TWO_INT,
21745+ GR_FILENAME_TWO_INT_STR,
21746+ GR_TEXTREL,
21747+ GR_PTRACE,
21748+ GR_RESOURCE,
21749+ GR_CAP,
21750+ GR_SIG,
21751+ GR_CRASH1,
21752+ GR_CRASH2,
21753+ GR_PSACCT
21754+};
21755+
21756+#define gr_log_ttysniff(audit, msg, task) gr_log_varargs(audit, msg, GR_TTYSNIFF, task)
21757+#define gr_log_fs_rbac_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_RBAC, dentry, mnt)
21758+#define gr_log_fs_rbac_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_RBAC_STR, dentry, mnt, str)
21759+#define gr_log_fs_str_rbac(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_RBAC, str, dentry, mnt)
21760+#define gr_log_fs_rbac_mode2(audit, msg, dentry, mnt, str1, str2) gr_log_varargs(audit, msg, GR_RBAC_MODE2, dentry, mnt, str1, str2)
21761+#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)
21762+#define gr_log_fs_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_FILENAME, dentry, mnt)
21763+#define gr_log_noargs(audit, msg) gr_log_varargs(audit, msg, GR_NOARGS)
21764+#define gr_log_int(audit, msg, num) gr_log_varargs(audit, msg, GR_ONE_INT, num)
21765+#define gr_log_int_str2(audit, msg, num, str1, str2) gr_log_varargs(audit, msg, GR_ONE_INT_TWO_STR, num, str1, str2)
21766+#define gr_log_str(audit, msg, str) gr_log_varargs(audit, msg, GR_ONE_STR, str)
21767+#define gr_log_str_int(audit, msg, str, num) gr_log_varargs(audit, msg, GR_STR_INT, str, num)
21768+#define gr_log_int_int(audit, msg, num1, num2) gr_log_varargs(audit, msg, GR_TWO_INT, num1, num2)
21769+#define gr_log_int3(audit, msg, num1, num2, num3) gr_log_varargs(audit, msg, GR_THREE_INT, num1, num2, num3)
21770+#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)
21771+#define gr_log_str_str(audit, msg, str1, str2) gr_log_varargs(audit, msg, GR_TWO_STR, str1, str2)
21772+#define gr_log_str3(audit, msg, str1, str2, str3) gr_log_varargs(audit, msg, GR_THREE_STR, str1, str2, str3)
21773+#define gr_log_str4(audit, msg, str1, str2, str3, str4) gr_log_varargs(audit, msg, GR_FOUR_STR, str1, str2, str3, str4)
21774+#define gr_log_str_fs(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_FILENAME, str, dentry, mnt)
21775+#define gr_log_fs_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_FILENAME_STR, dentry, mnt, str)
21776+#define gr_log_fs_int2(audit, msg, dentry, mnt, num1, num2) gr_log_varargs(audit, msg, GR_FILENAME_TWO_INT, dentry, mnt, num1, num2)
21777+#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)
21778+#define gr_log_textrel_ulong_ulong(audit, msg, file, ulong1, ulong2) gr_log_varargs(audit, msg, GR_TEXTREL, file, ulong1, ulong2)
21779+#define gr_log_ptrace(audit, msg, task) gr_log_varargs(audit, msg, GR_PTRACE, task)
21780+#define gr_log_res_ulong2_str(audit, msg, task, ulong1, str, ulong2) gr_log_varargs(audit, msg, GR_RESOURCE, task, ulong1, str, ulong2)
21781+#define gr_log_cap(audit, msg, task, str) gr_log_varargs(audit, msg, GR_CAP, task, str)
21782+#define gr_log_sig(audit, msg, task, num) gr_log_varargs(audit, msg, GR_SIG, task, num)
21783+#define gr_log_crash1(audit, msg, task, ulong) gr_log_varargs(audit, msg, GR_CRASH1, task, ulong)
21784+#define gr_log_crash2(audit, msg, task, ulong1) gr_log_varargs(audit, msg, GR_CRASH2, task, ulong1)
21785+#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)
21786+
21787+extern void gr_log_varargs(int audit, const char *msg, int argtypes, ...);
21788+
21789+#endif
21790+
21791+#endif
21792diff -urNp linux-2.6.17.11/include/linux/grmsg.h linux-2.6.17.11/include/linux/grmsg.h
21793--- linux-2.6.17.11/include/linux/grmsg.h 1969-12-31 19:00:00.000000000 -0500
21794+++ linux-2.6.17.11/include/linux/grmsg.h 2006-08-12 08:17:55.000000000 -0400
21795@@ -0,0 +1,108 @@
21796+#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"
21797+#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"
21798+#define GR_PTRACE_ACL_MSG "denied ptrace of %.950s(%.16s:%d) by "
21799+#define GR_STOPMOD_MSG "denied modification of module state by "
21800+#define GR_IOPERM_MSG "denied use of ioperm() by "
21801+#define GR_IOPL_MSG "denied use of iopl() by "
21802+#define GR_SHMAT_ACL_MSG "denied attach of shared memory of UID %u, PID %d, ID %u by "
21803+#define GR_UNIX_CHROOT_MSG "denied connect() to abstract AF_UNIX socket outside of chroot by "
21804+#define GR_SHMAT_CHROOT_MSG "denied attach of shared memory outside of chroot by "
21805+#define GR_KMEM_MSG "denied write of /dev/kmem by "
21806+#define GR_PORT_OPEN_MSG "denied open of /dev/port by "
21807+#define GR_MEM_WRITE_MSG "denied write of /dev/mem by "
21808+#define GR_MEM_MMAP_MSG "denied mmap write of /dev/[k]mem by "
21809+#define GR_SYMLINK_MSG "not following symlink %.950s owned by %d.%d by "
21810+#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"
21811+#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"
21812+#define GR_HIDDEN_ACL_MSG "%s access to hidden file %.950s by "
21813+#define GR_OPEN_ACL_MSG "%s open of %.950s for%s%s by "
21814+#define GR_CREATE_ACL_MSG "%s create of %.950s for%s%s by "
21815+#define GR_FIFO_MSG "denied writing FIFO %.950s of %d.%d by "
21816+#define GR_MKNOD_CHROOT_MSG "denied mknod of %.950s from chroot by "
21817+#define GR_MKNOD_ACL_MSG "%s mknod of %.950s by "
21818+#define GR_UNIXCONNECT_ACL_MSG "%s connect() to the unix domain socket %.950s by "
21819+#define GR_TTYSNIFF_ACL_MSG "terminal being sniffed by IP:%u.%u.%u.%u %.480s[%.16s:%d], parent %.480s[%.16s:%d] against "
21820+#define GR_MKDIR_ACL_MSG "%s mkdir of %.950s by "
21821+#define GR_RMDIR_ACL_MSG "%s rmdir of %.950s by "
21822+#define GR_UNLINK_ACL_MSG "%s unlink of %.950s by "
21823+#define GR_SYMLINK_ACL_MSG "%s symlink from %.480s to %.480s by "
21824+#define GR_HARDLINK_MSG "denied hardlink of %.930s (owned by %d.%d) to %.30s for "
21825+#define GR_LINK_ACL_MSG "%s link of %.480s to %.480s by "
21826+#define GR_INHERIT_ACL_MSG "successful inherit of %.480s's ACL for %.480s by "
21827+#define GR_RENAME_ACL_MSG "%s rename of %.480s to %.480s by "
21828+#define GR_PTRACE_EXEC_ACL_MSG "denied ptrace of %.950s by "
21829+#define GR_NPROC_MSG "denied overstep of process limit by "
21830+#define GR_EXEC_ACL_MSG "%s execution of %.950s by "
21831+#define GR_EXEC_TPE_MSG "denied untrusted exec of %.950s by "
21832+#define GR_SEGVSTART_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning uid %u from login for %lu seconds"
21833+#define GR_SEGVNOSUID_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning execution for %lu seconds"
21834+#define GR_MOUNT_CHROOT_MSG "denied mount of %.30s as %.930s from chroot by "
21835+#define GR_PIVOT_CHROOT_MSG "denied pivot_root from chroot by "
21836+#define GR_TRUNCATE_ACL_MSG "%s truncate of %.950s by "
21837+#define GR_ATIME_ACL_MSG "%s access time change of %.950s by "
21838+#define GR_ACCESS_ACL_MSG "%s access of %.950s for%s%s%s by "
21839+#define GR_CHROOT_CHROOT_MSG "denied double chroot to %.950s by "
21840+#define GR_FCHMOD_ACL_MSG "%s fchmod of %.950s by "
21841+#define GR_CHMOD_CHROOT_MSG "denied chmod +s of %.950s by "
21842+#define GR_CHMOD_ACL_MSG "%s chmod of %.950s by "
21843+#define GR_CHROOT_FCHDIR_MSG "denied fchdir outside of chroot to %.950s by "
21844+#define GR_CHOWN_ACL_MSG "%s chown of %.950s by "
21845+#define GR_WRITLIB_ACL_MSG "denied load of writable library %.950s by "
21846+#define GR_INITF_ACL_MSG "init_variables() failed %s by "
21847+#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"
21848+#define GR_DEV_ACL_MSG "/dev/grsec: %d bytes sent %d required, being fed garbaged by "
21849+#define GR_SHUTS_ACL_MSG "shutdown auth success for "
21850+#define GR_SHUTF_ACL_MSG "shutdown auth failure for "
21851+#define GR_SHUTI_ACL_MSG "ignoring shutdown for disabled RBAC system for "
21852+#define GR_SEGVMODS_ACL_MSG "segvmod auth success for "
21853+#define GR_SEGVMODF_ACL_MSG "segvmod auth failure for "
21854+#define GR_SEGVMODI_ACL_MSG "ignoring segvmod for disabled RBAC system for "
21855+#define GR_ENABLE_ACL_MSG "%s RBAC system loaded by "
21856+#define GR_ENABLEF_ACL_MSG "unable to load %s for "
21857+#define GR_RELOADI_ACL_MSG "ignoring reload request for disabled RBAC system"
21858+#define GR_RELOAD_ACL_MSG "%s RBAC system reloaded by "
21859+#define GR_RELOADF_ACL_MSG "failed reload of %s for "
21860+#define GR_SPROLEI_ACL_MSG "ignoring change to special role for disabled RBAC system for "
21861+#define GR_SPROLES_ACL_MSG "successful change to special role %s (id %d) by "
21862+#define GR_SPROLEL_ACL_MSG "special role %s (id %d) exited by "
21863+#define GR_SPROLEF_ACL_MSG "special role %s failure for "
21864+#define GR_UNSPROLEI_ACL_MSG "ignoring unauth of special role for disabled RBAC system for "
21865+#define GR_UNSPROLES_ACL_MSG "successful unauth of special role %s (id %d) by "
21866+#define GR_UNSPROLEF_ACL_MSG "special role unauth of %s failure for "
21867+#define GR_INVMODE_ACL_MSG "invalid mode %d by "
21868+#define GR_PRIORITY_CHROOT_MSG "denied priority change of process (%.16s:%d) by "
21869+#define GR_FAILFORK_MSG "failed fork with errno %d by "
21870+#define GR_NICE_CHROOT_MSG "denied priority change by "
21871+#define GR_UNISIGLOG_MSG "signal %d sent to "
21872+#define GR_DUALSIGLOG_MSG "signal %d sent to " DEFAULTSECMSG " by "
21873+#define GR_SIG_ACL_MSG "denied send of signal %d to protected task " DEFAULTSECMSG " by "
21874+#define GR_SYSCTL_MSG "denied modification of grsecurity sysctl value : %.32s by "
21875+#define GR_SYSCTL_ACL_MSG "%s sysctl of %.950s for%s%s by "
21876+#define GR_TIME_MSG "time set by "
21877+#define GR_DEFACL_MSG "fatal: unable to find subject for (%.16s:%d), loaded by "
21878+#define GR_MMAP_ACL_MSG "%s executable mmap of %.950s by "
21879+#define GR_MPROTECT_ACL_MSG "%s executable mprotect of %.950s by "
21880+#define GR_SOCK_MSG "denied socket(%.16s,%.16s,%.16s) by "
21881+#define GR_SOCK2_MSG "denied socket(%d,%.16s,%.16s) by "
21882+#define GR_BIND_MSG "denied bind() by "
21883+#define GR_CONNECT_MSG "denied connect() by "
21884+#define GR_BIND_ACL_MSG "denied bind() to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by "
21885+#define GR_CONNECT_ACL_MSG "denied connect() to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by "
21886+#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"
21887+#define GR_EXEC_CHROOT_MSG "exec of %.980s within chroot by process "
21888+#define GR_CAP_ACL_MSG "use of %s denied for "
21889+#define GR_USRCHANGE_ACL_MSG "change to uid %u denied for "
21890+#define GR_GRPCHANGE_ACL_MSG "change to gid %u denied for "
21891+#define GR_REMOUNT_AUDIT_MSG "remount of %.30s by "
21892+#define GR_UNMOUNT_AUDIT_MSG "unmount of %.30s by "
21893+#define GR_MOUNT_AUDIT_MSG "mount of %.30s to %.64s by "
21894+#define GR_CHDIR_AUDIT_MSG "chdir to %.980s by "
21895+#define GR_EXEC_AUDIT_MSG "exec of %.930s (%.128s) by "
21896+#define GR_MSGQ_AUDIT_MSG "message queue created by "
21897+#define GR_MSGQR_AUDIT_MSG "message queue of uid:%u euid:%u removed by "
21898+#define GR_SEM_AUDIT_MSG "semaphore created by "
21899+#define GR_SEMR_AUDIT_MSG "semaphore of uid:%u euid:%u removed by "
21900+#define GR_SHM_AUDIT_MSG "shared memory of size %d created by "
21901+#define GR_SHMR_AUDIT_MSG "shared memory of uid:%u euid:%u removed by "
21902+#define GR_RESOURCE_MSG "denied resource overstep by requesting %lu for %.16s against limit %lu for "
21903+#define GR_TEXTREL_AUDIT_MSG "text relocation in %s, VMA:0x%08lx 0x%08lx by "
21904diff -urNp linux-2.6.17.11/include/linux/grsecurity.h linux-2.6.17.11/include/linux/grsecurity.h
21905--- linux-2.6.17.11/include/linux/grsecurity.h 1969-12-31 19:00:00.000000000 -0500
21906+++ linux-2.6.17.11/include/linux/grsecurity.h 2006-08-12 08:17:55.000000000 -0400
21907@@ -0,0 +1,196 @@
21908+#ifndef GR_SECURITY_H
21909+#define GR_SECURITY_H
21910+#include <linux/fs.h>
21911+#include <linux/binfmts.h>
21912+#include <linux/gracl.h>
21913+
21914+extern void gr_handle_brute_attach(struct task_struct *p);
21915+extern void gr_handle_brute_check(void);
21916+
21917+extern char gr_roletype_to_char(void);
21918+
21919+extern int gr_check_user_change(int real, int effective, int fs);
21920+extern int gr_check_group_change(int real, int effective, int fs);
21921+
21922+extern void gr_del_task_from_ip_table(struct task_struct *p);
21923+
21924+extern int gr_pid_is_chrooted(struct task_struct *p);
21925+extern int gr_handle_chroot_nice(void);
21926+extern int gr_handle_chroot_sysctl(const int op);
21927+extern int gr_handle_chroot_setpriority(struct task_struct *p,
21928+ const int niceval);
21929+extern int gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt);
21930+extern int gr_handle_chroot_chroot(const struct dentry *dentry,
21931+ const struct vfsmount *mnt);
21932+extern void gr_handle_chroot_caps(struct task_struct *task);
21933+extern void gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt);
21934+extern int gr_handle_chroot_chmod(const struct dentry *dentry,
21935+ const struct vfsmount *mnt, const int mode);
21936+extern int gr_handle_chroot_mknod(const struct dentry *dentry,
21937+ const struct vfsmount *mnt, const int mode);
21938+extern int gr_handle_chroot_mount(const struct dentry *dentry,
21939+ const struct vfsmount *mnt,
21940+ const char *dev_name);
21941+extern int gr_handle_chroot_pivot(void);
21942+extern int gr_handle_chroot_unix(const pid_t pid);
21943+
21944+extern int gr_handle_rawio(const struct inode *inode);
21945+extern int gr_handle_nproc(void);
21946+
21947+extern void gr_handle_ioperm(void);
21948+extern void gr_handle_iopl(void);
21949+
21950+extern int gr_tpe_allow(const struct file *file);
21951+
21952+extern int gr_random_pid(void);
21953+
21954+extern void gr_log_forkfail(const int retval);
21955+extern void gr_log_timechange(void);
21956+extern void gr_log_signal(const int sig, const struct task_struct *t);
21957+extern void gr_log_chdir(const struct dentry *dentry,
21958+ const struct vfsmount *mnt);
21959+extern void gr_log_chroot_exec(const struct dentry *dentry,
21960+ const struct vfsmount *mnt);
21961+extern void gr_handle_exec_args(struct linux_binprm *bprm, char **argv);
21962+extern void gr_log_remount(const char *devname, const int retval);
21963+extern void gr_log_unmount(const char *devname, const int retval);
21964+extern void gr_log_mount(const char *from, const char *to, const int retval);
21965+extern void gr_log_msgget(const int ret, const int msgflg);
21966+extern void gr_log_msgrm(const uid_t uid, const uid_t cuid);
21967+extern void gr_log_semget(const int err, const int semflg);
21968+extern void gr_log_semrm(const uid_t uid, const uid_t cuid);
21969+extern void gr_log_shmget(const int err, const int shmflg, const size_t size);
21970+extern void gr_log_shmrm(const uid_t uid, const uid_t cuid);
21971+extern void gr_log_textrel(struct vm_area_struct *vma);
21972+
21973+extern int gr_handle_follow_link(const struct inode *parent,
21974+ const struct inode *inode,
21975+ const struct dentry *dentry,
21976+ const struct vfsmount *mnt);
21977+extern int gr_handle_fifo(const struct dentry *dentry,
21978+ const struct vfsmount *mnt,
21979+ const struct dentry *dir, const int flag,
21980+ const int acc_mode);
21981+extern int gr_handle_hardlink(const struct dentry *dentry,
21982+ const struct vfsmount *mnt,
21983+ struct inode *inode,
21984+ const int mode, const char *to);
21985+
21986+extern int gr_task_is_capable(struct task_struct *task, const int cap);
21987+extern int gr_is_capable_nolog(const int cap);
21988+extern void gr_learn_resource(const struct task_struct *task, const int limit,
21989+ const unsigned long wanted, const int gt);
21990+extern void gr_copy_label(struct task_struct *tsk);
21991+extern void gr_handle_crash(struct task_struct *task, const int sig);
21992+extern int gr_handle_signal(const struct task_struct *p, const int sig);
21993+extern int gr_check_crash_uid(const uid_t uid);
21994+extern int gr_check_protected_task(const struct task_struct *task);
21995+extern int gr_acl_handle_mmap(const struct file *file,
21996+ const unsigned long prot);
21997+extern int gr_acl_handle_mprotect(const struct file *file,
21998+ const unsigned long prot);
21999+extern int gr_check_hidden_task(const struct task_struct *tsk);
22000+extern __u32 gr_acl_handle_truncate(const struct dentry *dentry,
22001+ const struct vfsmount *mnt);
22002+extern __u32 gr_acl_handle_utime(const struct dentry *dentry,
22003+ const struct vfsmount *mnt);
22004+extern __u32 gr_acl_handle_access(const struct dentry *dentry,
22005+ const struct vfsmount *mnt, const int fmode);
22006+extern __u32 gr_acl_handle_fchmod(const struct dentry *dentry,
22007+ const struct vfsmount *mnt, mode_t mode);
22008+extern __u32 gr_acl_handle_chmod(const struct dentry *dentry,
22009+ const struct vfsmount *mnt, mode_t mode);
22010+extern __u32 gr_acl_handle_chown(const struct dentry *dentry,
22011+ const struct vfsmount *mnt);
22012+extern int gr_handle_ptrace(struct task_struct *task, const long request);
22013+extern int gr_handle_proc_ptrace(struct task_struct *task);
22014+extern __u32 gr_acl_handle_execve(const struct dentry *dentry,
22015+ const struct vfsmount *mnt);
22016+extern int gr_check_crash_exec(const struct file *filp);
22017+extern int gr_acl_is_enabled(void);
22018+extern void gr_set_kernel_label(struct task_struct *task);
22019+extern void gr_set_role_label(struct task_struct *task, const uid_t uid,
22020+ const gid_t gid);
22021+extern int gr_set_proc_label(const struct dentry *dentry,
22022+ const struct vfsmount *mnt);
22023+extern __u32 gr_acl_handle_hidden_file(const struct dentry *dentry,
22024+ const struct vfsmount *mnt);
22025+extern __u32 gr_acl_handle_open(const struct dentry *dentry,
22026+ const struct vfsmount *mnt, const int fmode);
22027+extern __u32 gr_acl_handle_creat(const struct dentry *dentry,
22028+ const struct dentry *p_dentry,
22029+ const struct vfsmount *p_mnt, const int fmode,
22030+ const int imode);
22031+extern void gr_handle_create(const struct dentry *dentry,
22032+ const struct vfsmount *mnt);
22033+extern __u32 gr_acl_handle_mknod(const struct dentry *new_dentry,
22034+ const struct dentry *parent_dentry,
22035+ const struct vfsmount *parent_mnt,
22036+ const int mode);
22037+extern __u32 gr_acl_handle_mkdir(const struct dentry *new_dentry,
22038+ const struct dentry *parent_dentry,
22039+ const struct vfsmount *parent_mnt);
22040+extern __u32 gr_acl_handle_rmdir(const struct dentry *dentry,
22041+ const struct vfsmount *mnt);
22042+extern void gr_handle_delete(const ino_t ino, const dev_t dev);
22043+extern __u32 gr_acl_handle_unlink(const struct dentry *dentry,
22044+ const struct vfsmount *mnt);
22045+extern __u32 gr_acl_handle_symlink(const struct dentry *new_dentry,
22046+ const struct dentry *parent_dentry,
22047+ const struct vfsmount *parent_mnt,
22048+ const char *from);
22049+extern __u32 gr_acl_handle_link(const struct dentry *new_dentry,
22050+ const struct dentry *parent_dentry,
22051+ const struct vfsmount *parent_mnt,
22052+ const struct dentry *old_dentry,
22053+ const struct vfsmount *old_mnt, const char *to);
22054+extern int gr_acl_handle_rename(struct dentry *new_dentry,
22055+ struct dentry *parent_dentry,
22056+ const struct vfsmount *parent_mnt,
22057+ struct dentry *old_dentry,
22058+ struct inode *old_parent_inode,
22059+ struct vfsmount *old_mnt, const char *newname);
22060+extern void gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
22061+ struct dentry *old_dentry,
22062+ struct dentry *new_dentry,
22063+ struct vfsmount *mnt, const __u8 replace);
22064+extern __u32 gr_check_link(const struct dentry *new_dentry,
22065+ const struct dentry *parent_dentry,
22066+ const struct vfsmount *parent_mnt,
22067+ const struct dentry *old_dentry,
22068+ const struct vfsmount *old_mnt);
22069+extern int gr_acl_handle_filldir(const struct file *file, const char *name,
22070+ const unsigned int namelen, const ino_t ino);
22071+
22072+extern __u32 gr_acl_handle_unix(const struct dentry *dentry,
22073+ const struct vfsmount *mnt);
22074+extern void gr_acl_handle_exit(void);
22075+extern void gr_acl_handle_psacct(struct task_struct *task, const long code);
22076+extern int gr_acl_handle_procpidmem(const struct task_struct *task);
22077+extern __u32 gr_cap_rtnetlink(void);
22078+
22079+#ifdef CONFIG_SYSVIPC
22080+extern void gr_shm_exit(struct task_struct *task);
22081+#else
22082+static inline void gr_shm_exit(struct task_struct *task)
22083+{
22084+ return;
22085+}
22086+#endif
22087+
22088+#ifdef CONFIG_GRKERNSEC
22089+extern void gr_handle_mem_write(void);
22090+extern void gr_handle_kmem_write(void);
22091+extern void gr_handle_open_port(void);
22092+extern int gr_handle_mem_mmap(const unsigned long offset,
22093+ struct vm_area_struct *vma);
22094+
22095+extern unsigned long pax_get_random_long(void);
22096+#define get_random_long() pax_get_random_long()
22097+
22098+extern int grsec_enable_dmesg;
22099+extern int grsec_enable_randsrc;
22100+extern int grsec_enable_shm;
22101+#endif
22102+
22103+#endif
22104diff -urNp linux-2.6.17.11/include/linux/highmem.h linux-2.6.17.11/include/linux/highmem.h
22105--- linux-2.6.17.11/include/linux/highmem.h 2006-08-07 00:18:54.000000000 -0400
22106+++ linux-2.6.17.11/include/linux/highmem.h 2006-08-12 08:17:55.000000000 -0400
22107@@ -70,9 +70,9 @@ alloc_zeroed_user_highpage(struct vm_are
22108
22109 static inline void clear_highpage(struct page *page)
22110 {
22111- void *kaddr = kmap_atomic(page, KM_USER0);
22112+ void *kaddr = kmap_atomic(page, KM_CLEARPAGE);
22113 clear_page(kaddr);
22114- kunmap_atomic(kaddr, KM_USER0);
22115+ kunmap_atomic(kaddr, KM_CLEARPAGE);
22116 }
22117
22118 /*
22119diff -urNp linux-2.6.17.11/include/linux/mman.h linux-2.6.17.11/include/linux/mman.h
22120--- linux-2.6.17.11/include/linux/mman.h 2006-08-07 00:18:54.000000000 -0400
22121+++ linux-2.6.17.11/include/linux/mman.h 2006-08-12 08:17:55.000000000 -0400
22122@@ -59,6 +59,11 @@ static inline unsigned long
22123 calc_vm_flag_bits(unsigned long flags)
22124 {
22125 return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
22126+
22127+#ifdef CONFIG_PAX_SEGMEXEC
22128+ _calc_vm_trans(flags, MAP_MIRROR, VM_MIRROR) |
22129+#endif
22130+
22131 _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) |
22132 _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) |
22133 _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED );
22134diff -urNp linux-2.6.17.11/include/linux/mm.h linux-2.6.17.11/include/linux/mm.h
22135--- linux-2.6.17.11/include/linux/mm.h 2006-08-07 00:18:54.000000000 -0400
22136+++ linux-2.6.17.11/include/linux/mm.h 2006-08-12 08:17:55.000000000 -0400
22137@@ -38,6 +38,7 @@ extern int sysctl_legacy_va_layout;
22138 #include <asm/pgtable.h>
22139 #include <asm/processor.h>
22140 #include <asm/atomic.h>
22141+#include <asm/mman.h>
22142
22143 #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
22144
22145@@ -111,8 +112,43 @@ struct vm_area_struct {
22146 #ifdef CONFIG_NUMA
22147 struct mempolicy *vm_policy; /* NUMA policy for the VMA */
22148 #endif
22149+
22150+ unsigned long vm_mirror; /* PaX: mirror distance */
22151 };
22152
22153+#ifdef CONFIG_PAX_SOFTMODE
22154+extern unsigned int pax_softmode;
22155+#endif
22156+
22157+extern int pax_check_flags(unsigned long *);
22158+
22159+/* if tsk != current then task_lock must be held on it */
22160+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
22161+static inline unsigned long pax_get_flags(struct task_struct *tsk)
22162+{
22163+ if (likely(tsk->mm))
22164+ return tsk->mm->pax_flags;
22165+ else
22166+ return 0UL;
22167+}
22168+
22169+/* if tsk != current then task_lock must be held on it */
22170+static inline long pax_set_flags(struct task_struct *tsk, unsigned long flags)
22171+{
22172+ if (likely(tsk->mm)) {
22173+ tsk->mm->pax_flags = flags;
22174+ return 0;
22175+ }
22176+ return -EINVAL;
22177+}
22178+#endif
22179+
22180+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
22181+extern void pax_set_initial_flags(struct linux_binprm * bprm);
22182+#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
22183+extern void (*pax_set_initial_flags_func)(struct linux_binprm * bprm);
22184+#endif
22185+
22186 /*
22187 * This struct defines the per-mm list of VMAs for uClinux. If CONFIG_MMU is
22188 * disabled, then there's a single shared list of VMAs maintained by the
22189@@ -167,6 +203,18 @@ extern unsigned int kobjsize(const void
22190 #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */
22191 #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */
22192
22193+#ifdef CONFIG_PAX_SEGMEXEC
22194+#define VM_MIRROR 0x04000000 /* vma is mirroring another */
22195+#endif
22196+
22197+#ifdef CONFIG_PAX_MPROTECT
22198+#define VM_MAYNOTWRITE 0x08000000 /* vma cannot be granted VM_WRITE any more */
22199+#endif
22200+
22201+#ifdef __VM_STACK_FLAGS
22202+#define VM_STACK_DEFAULT_FLAGS (0x00000033 | __VM_STACK_FLAGS)
22203+#endif
22204+
22205 #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
22206 #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
22207 #endif
22208@@ -1058,5 +1106,11 @@ void drop_slab(void);
22209 extern int randomize_va_space;
22210 #endif
22211
22212+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
22213+extern void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot);
22214+#else
22215+static inline void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot) {}
22216+#endif
22217+
22218 #endif /* __KERNEL__ */
22219 #endif /* _LINUX_MM_H */
22220diff -urNp linux-2.6.17.11/include/linux/module.h linux-2.6.17.11/include/linux/module.h
22221--- linux-2.6.17.11/include/linux/module.h 2006-08-07 00:18:54.000000000 -0400
22222+++ linux-2.6.17.11/include/linux/module.h 2006-08-12 08:17:55.000000000 -0400
22223@@ -273,16 +273,16 @@ struct module
22224 int (*init)(void);
22225
22226 /* If this is non-NULL, vfree after init() returns */
22227- void *module_init;
22228+ void *module_init_rx, *module_init_rw;
22229
22230 /* Here is the actual code + data, vfree'd on unload. */
22231- void *module_core;
22232+ void *module_core_rx, *module_core_rw;
22233
22234 /* Here are the sizes of the init and core sections */
22235- unsigned long init_size, core_size;
22236+ unsigned long init_size_rw, core_size_rw;
22237
22238 /* The size of the executable code in each section. */
22239- unsigned long init_text_size, core_text_size;
22240+ unsigned long init_size_rx, core_size_rx;
22241
22242 /* Arch-specific module values */
22243 struct mod_arch_specific arch;
22244diff -urNp linux-2.6.17.11/include/linux/moduleloader.h linux-2.6.17.11/include/linux/moduleloader.h
22245--- linux-2.6.17.11/include/linux/moduleloader.h 2006-08-07 00:18:54.000000000 -0400
22246+++ linux-2.6.17.11/include/linux/moduleloader.h 2006-08-12 08:17:55.000000000 -0400
22247@@ -17,9 +17,21 @@ int module_frob_arch_sections(Elf_Ehdr *
22248 sections. Returns NULL on failure. */
22249 void *module_alloc(unsigned long size);
22250
22251+#ifdef CONFIG_PAX_KERNEXEC
22252+void *module_alloc_exec(unsigned long size);
22253+#else
22254+#define module_alloc_exec(x) module_alloc(x)
22255+#endif
22256+
22257 /* Free memory returned from module_alloc. */
22258 void module_free(struct module *mod, void *module_region);
22259
22260+#ifdef CONFIG_PAX_KERNEXEC
22261+void module_free_exec(struct module *mod, void *module_region);
22262+#else
22263+#define module_free_exec(x, y) module_free(x, y)
22264+#endif
22265+
22266 /* Apply the given relocation to the (simplified) ELF. Return -error
22267 or 0. */
22268 int apply_relocate(Elf_Shdr *sechdrs,
22269diff -urNp linux-2.6.17.11/include/linux/random.h linux-2.6.17.11/include/linux/random.h
22270--- linux-2.6.17.11/include/linux/random.h 2006-08-07 00:18:54.000000000 -0400
22271+++ linux-2.6.17.11/include/linux/random.h 2006-08-12 08:17:55.000000000 -0400
22272@@ -62,6 +62,8 @@ extern __u32 secure_tcpv6_sequence_numbe
22273 extern u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr,
22274 __u16 sport, __u16 dport);
22275
22276+extern unsigned long pax_get_random_long(void);
22277+
22278 #ifndef MODULE
22279 extern struct file_operations random_fops, urandom_fops;
22280 #endif
22281diff -urNp linux-2.6.17.11/include/linux/sched.h linux-2.6.17.11/include/linux/sched.h
22282--- linux-2.6.17.11/include/linux/sched.h 2006-08-07 00:18:54.000000000 -0400
22283+++ linux-2.6.17.11/include/linux/sched.h 2006-08-12 08:17:55.000000000 -0400
22284@@ -40,6 +40,7 @@
22285 #include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
22286
22287 struct exec_domain;
22288+struct linux_binprm;
22289
22290 /*
22291 * cloning flags:
22292@@ -350,8 +351,34 @@ struct mm_struct {
22293 /* aio bits */
22294 rwlock_t ioctx_list_lock;
22295 struct kioctx *ioctx_list;
22296+
22297+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
22298+ unsigned long pax_flags;
22299+#endif
22300+
22301+#ifdef CONFIG_PAX_DLRESOLVE
22302+ unsigned long call_dl_resolve;
22303+#endif
22304+
22305+#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
22306+ unsigned long call_syscall;
22307+#endif
22308+
22309+#ifdef CONFIG_PAX_ASLR
22310+ unsigned long delta_mmap; /* randomized offset */
22311+ unsigned long delta_exec; /* randomized offset */
22312+ unsigned long delta_stack; /* randomized offset */
22313+#endif
22314+
22315 };
22316
22317+#define MF_PAX_PAGEEXEC 0x01000000 /* Paging based non-executable pages */
22318+#define MF_PAX_EMUTRAMP 0x02000000 /* Emulate trampolines */
22319+#define MF_PAX_MPROTECT 0x04000000 /* Restrict mprotect() */
22320+#define MF_PAX_RANDMMAP 0x08000000 /* Randomize mmap() base */
22321+/*#define MF_PAX_RANDEXEC 0x10000000*/ /* Randomize ET_EXEC base */
22322+#define MF_PAX_SEGMEXEC 0x20000000 /* Segmentation based non-executable pages */
22323+
22324 struct sighand_struct {
22325 atomic_t count;
22326 struct k_sigaction action[_NSIG];
22327@@ -449,6 +476,15 @@ struct signal_struct {
22328 struct key *session_keyring; /* keyring inherited over fork */
22329 struct key *process_keyring; /* keyring private to this process */
22330 #endif
22331+
22332+#ifdef CONFIG_GRKERNSEC
22333+ u32 curr_ip;
22334+ u32 gr_saddr;
22335+ u32 gr_daddr;
22336+ u16 gr_sport;
22337+ u16 gr_dport;
22338+ u8 used_accept:1;
22339+#endif
22340 };
22341
22342 /* Context switch must be unlocked if interrupts are to be enabled */
22343@@ -881,6 +917,17 @@ struct task_struct {
22344 struct compat_robust_list_head __user *compat_robust_list;
22345 #endif
22346
22347+#ifdef CONFIG_GRKERNSEC
22348+ /* grsecurity */
22349+ struct acl_subject_label *acl;
22350+ struct acl_role_label *role;
22351+ struct file *exec_file;
22352+ u16 acl_role_id;
22353+ u8 acl_sp_role:1;
22354+ u8 is_writable:1;
22355+ u8 brute:1;
22356+#endif
22357+
22358 atomic_t fs_excl; /* holding fs exclusive resources */
22359 struct rcu_head rcu;
22360
22361@@ -1393,6 +1440,12 @@ extern void arch_pick_mmap_layout(struct
22362 static inline void arch_pick_mmap_layout(struct mm_struct *mm)
22363 {
22364 mm->mmap_base = TASK_UNMAPPED_BASE;
22365+
22366+#ifdef CONFIG_PAX_RANDMMAP
22367+ if (mm->pax_flags & MF_PAX_RANDMMAP)
22368+ mm->mmap_base += mm->delta_mmap;
22369+#endif
22370+
22371 mm->get_unmapped_area = arch_get_unmapped_area;
22372 mm->unmap_area = arch_unmap_area;
22373 }
22374diff -urNp linux-2.6.17.11/include/linux/shm.h linux-2.6.17.11/include/linux/shm.h
22375--- linux-2.6.17.11/include/linux/shm.h 2006-08-07 00:18:54.000000000 -0400
22376+++ linux-2.6.17.11/include/linux/shm.h 2006-08-12 08:17:55.000000000 -0400
22377@@ -86,6 +86,10 @@ struct shmid_kernel /* private to the ke
22378 pid_t shm_cprid;
22379 pid_t shm_lprid;
22380 struct user_struct *mlock_user;
22381+#ifdef CONFIG_GRKERNSEC
22382+ time_t shm_createtime;
22383+ pid_t shm_lapid;
22384+#endif
22385 };
22386
22387 /* shm_mode upper byte flags */
22388diff -urNp linux-2.6.17.11/include/linux/sysctl.h linux-2.6.17.11/include/linux/sysctl.h
22389--- linux-2.6.17.11/include/linux/sysctl.h 2006-08-07 00:18:54.000000000 -0400
22390+++ linux-2.6.17.11/include/linux/sysctl.h 2006-08-12 08:17:55.000000000 -0400
22391@@ -148,8 +148,21 @@ enum
22392 KERN_SPIN_RETRY=70, /* int: number of spinlock retries */
22393 KERN_ACPI_VIDEO_FLAGS=71, /* int: flags for setting up video after ACPI sleep */
22394 KERN_IA64_UNALIGNED=72, /* int: ia64 unaligned userland trap enable */
22395+#ifdef CONFIG_GRKERNSEC
22396+ KERN_GRSECURITY=98, /* grsecurity */
22397+#endif
22398+
22399+#ifdef CONFIG_PAX_SOFTMODE
22400+ KERN_PAX=99, /* PaX control */
22401+#endif
22402+
22403 };
22404
22405+#ifdef CONFIG_PAX_SOFTMODE
22406+enum {
22407+ PAX_SOFTMODE=1 /* PaX: disable/enable soft mode */
22408+};
22409+#endif
22410
22411 /* CTL_VM names: */
22412 enum
22413diff -urNp linux-2.6.17.11/init/Kconfig linux-2.6.17.11/init/Kconfig
22414--- linux-2.6.17.11/init/Kconfig 2006-08-07 00:18:54.000000000 -0400
22415+++ linux-2.6.17.11/init/Kconfig 2006-08-12 08:17:55.000000000 -0400
22416@@ -268,6 +268,7 @@ menuconfig EMBEDDED
22417 config KALLSYMS
22418 bool "Load all symbols for debugging/kksymoops" if EMBEDDED
22419 default y
22420+ depends on !GRKERNSEC_HIDESYM
22421 help
22422 Say Y here to let the kernel print out symbolic crash information and
22423 symbolic stack backtraces. This increases the size of the kernel
22424diff -urNp linux-2.6.17.11/init/main.c linux-2.6.17.11/init/main.c
22425--- linux-2.6.17.11/init/main.c 2006-08-07 00:18:54.000000000 -0400
22426+++ linux-2.6.17.11/init/main.c 2006-08-12 08:17:55.000000000 -0400
22427@@ -100,6 +100,7 @@ static inline void mark_rodata_ro(void)
22428 #ifdef CONFIG_TC
22429 extern void tc_init(void);
22430 #endif
22431+extern void grsecurity_init(void);
22432
22433 enum system_states system_state;
22434 EXPORT_SYMBOL(system_state);
22435@@ -150,6 +151,15 @@ static int __init maxcpus(char *str)
22436
22437 __setup("maxcpus=", maxcpus);
22438
22439+#ifdef CONFIG_PAX_SOFTMODE
22440+static int __init setup_pax_softmode(char *str)
22441+{
22442+ get_option(&str, &pax_softmode);
22443+ return 1;
22444+}
22445+__setup("pax_softmode=", setup_pax_softmode);
22446+#endif
22447+
22448 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
22449 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
22450 static const char *panic_later, *panic_param;
22451@@ -692,6 +702,8 @@ static int init(void * unused)
22452 prepare_namespace();
22453 }
22454
22455+ grsecurity_init();
22456+
22457 /*
22458 * Ok, we have completed the initial bootup, and
22459 * we're essentially up and running. Get rid of the
22460diff -urNp linux-2.6.17.11/ipc/msg.c linux-2.6.17.11/ipc/msg.c
22461--- linux-2.6.17.11/ipc/msg.c 2006-08-07 00:18:54.000000000 -0400
22462+++ linux-2.6.17.11/ipc/msg.c 2006-08-12 08:17:55.000000000 -0400
22463@@ -32,6 +32,7 @@
22464 #include <linux/audit.h>
22465 #include <linux/seq_file.h>
22466 #include <linux/mutex.h>
22467+#include <linux/grsecurity.h>
22468
22469 #include <asm/current.h>
22470 #include <asm/uaccess.h>
22471@@ -237,6 +238,9 @@ asmlinkage long sys_msgget (key_t key, i
22472 msg_unlock(msq);
22473 }
22474 mutex_unlock(&msg_ids.mutex);
22475+
22476+ gr_log_msgget(ret, msgflg);
22477+
22478 return ret;
22479 }
22480
22481@@ -495,6 +499,8 @@ asmlinkage long sys_msgctl (int msqid, i
22482 break;
22483 }
22484 case IPC_RMID:
22485+ gr_log_msgrm(ipcp->uid, ipcp->cuid);
22486+
22487 freeque (msq, msqid);
22488 break;
22489 }
22490diff -urNp linux-2.6.17.11/ipc/sem.c linux-2.6.17.11/ipc/sem.c
22491--- linux-2.6.17.11/ipc/sem.c 2006-08-07 00:18:54.000000000 -0400
22492+++ linux-2.6.17.11/ipc/sem.c 2006-08-12 08:17:55.000000000 -0400
22493@@ -79,6 +79,7 @@
22494 #include <linux/capability.h>
22495 #include <linux/seq_file.h>
22496 #include <linux/mutex.h>
22497+#include <linux/grsecurity.h>
22498
22499 #include <asm/uaccess.h>
22500 #include "util.h"
22501@@ -247,6 +248,9 @@ asmlinkage long sys_semget (key_t key, i
22502 }
22503
22504 mutex_unlock(&sem_ids.mutex);
22505+
22506+ gr_log_semget(err, semflg);
22507+
22508 return err;
22509 }
22510
22511@@ -840,6 +844,8 @@ static int semctl_down(int semid, int se
22512
22513 switch(cmd){
22514 case IPC_RMID:
22515+ gr_log_semrm(ipcp->uid, ipcp->cuid);
22516+
22517 freeary(sma, semid);
22518 err = 0;
22519 break;
22520diff -urNp linux-2.6.17.11/ipc/shm.c linux-2.6.17.11/ipc/shm.c
22521--- linux-2.6.17.11/ipc/shm.c 2006-08-07 00:18:54.000000000 -0400
22522+++ linux-2.6.17.11/ipc/shm.c 2006-08-12 08:17:55.000000000 -0400
22523@@ -33,6 +33,7 @@
22524 #include <linux/ptrace.h>
22525 #include <linux/seq_file.h>
22526 #include <linux/mutex.h>
22527+#include <linux/grsecurity.h>
22528
22529 #include <asm/uaccess.h>
22530
22531@@ -56,6 +57,14 @@ static void shm_close (struct vm_area_st
22532 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
22533 #endif
22534
22535+#ifdef CONFIG_GRKERNSEC
22536+extern int gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
22537+ const time_t shm_createtime, const uid_t cuid,
22538+ const int shmid);
22539+extern int gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
22540+ const time_t shm_createtime);
22541+#endif
22542+
22543 size_t shm_ctlmax = SHMMAX;
22544 size_t shm_ctlall = SHMALL;
22545 int shm_ctlmni = SHMMNI;
22546@@ -149,6 +158,17 @@ static void shm_close (struct vm_area_st
22547 shp->shm_lprid = current->tgid;
22548 shp->shm_dtim = get_seconds();
22549 shp->shm_nattch--;
22550+#ifdef CONFIG_GRKERNSEC_SHM
22551+ if (grsec_enable_shm) {
22552+ if (shp->shm_nattch == 0) {
22553+ shp->shm_perm.mode |= SHM_DEST;
22554+ shm_destroy(shp);
22555+ } else
22556+ shm_unlock(shp);
22557+ mutex_unlock(&shm_ids.mutex);
22558+ return;
22559+ }
22560+#endif
22561 if(shp->shm_nattch == 0 &&
22562 shp->shm_perm.mode & SHM_DEST)
22563 shm_destroy (shp);
22564@@ -248,6 +268,9 @@ static int newseg (key_t key, int shmflg
22565 shp->shm_lprid = 0;
22566 shp->shm_atim = shp->shm_dtim = 0;
22567 shp->shm_ctim = get_seconds();
22568+#ifdef CONFIG_GRKERNSEC
22569+ shp->shm_createtime = get_seconds();
22570+#endif
22571 shp->shm_segsz = size;
22572 shp->shm_nattch = 0;
22573 shp->id = shm_buildid(id,shp->shm_perm.seq);
22574@@ -302,6 +325,8 @@ asmlinkage long sys_shmget (key_t key, s
22575 }
22576 mutex_unlock(&shm_ids.mutex);
22577
22578+ gr_log_shmget(err, shmflg, size);
22579+
22580 return err;
22581 }
22582
22583@@ -615,6 +640,8 @@ asmlinkage long sys_shmctl (int shmid, i
22584 if (err)
22585 goto out_unlock_up;
22586
22587+ gr_log_shmrm(shp->shm_perm.uid, shp->shm_perm.cuid);
22588+
22589 if (shp->shm_nattch){
22590 shp->shm_perm.mode |= SHM_DEST;
22591 /* Do not find it any more */
22592@@ -763,9 +790,27 @@ long do_shmat(int shmid, char __user *sh
22593 return err;
22594 }
22595
22596+#ifdef CONFIG_GRKERNSEC
22597+ if (!gr_handle_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime,
22598+ shp->shm_perm.cuid, shmid)) {
22599+ shm_unlock(shp);
22600+ return -EACCES;
22601+ }
22602+
22603+ if (!gr_chroot_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime)) {
22604+ shm_unlock(shp);
22605+ return -EACCES;
22606+ }
22607+#endif
22608+
22609 file = shp->shm_file;
22610 size = i_size_read(file->f_dentry->d_inode);
22611 shp->shm_nattch++;
22612+
22613+#ifdef CONFIG_GRKERNSEC
22614+ shp->shm_lapid = current->pid;
22615+#endif
22616+
22617 shm_unlock(shp);
22618
22619 down_write(&current->mm->mmap_sem);
22620@@ -935,3 +980,24 @@ static int sysvipc_shm_proc_show(struct
22621 shp->shm_ctim);
22622 }
22623 #endif
22624+
22625+void gr_shm_exit(struct task_struct *task)
22626+{
22627+#ifdef CONFIG_GRKERNSEC_SHM
22628+ int i;
22629+ struct shmid_kernel *shp;
22630+
22631+ if (!grsec_enable_shm)
22632+ return;
22633+
22634+ for (i = 0; i <= shm_ids.max_id; i++) {
22635+ shp = shm_get(i);
22636+ if (shp && (shp->shm_cprid == task->pid) &&
22637+ (shp->shm_nattch <= 0)) {
22638+ shp->shm_perm.mode |= SHM_DEST;
22639+ shm_destroy(shp);
22640+ }
22641+ }
22642+#endif
22643+ return;
22644+}
22645diff -urNp linux-2.6.17.11/kernel/capability.c linux-2.6.17.11/kernel/capability.c
22646--- linux-2.6.17.11/kernel/capability.c 2006-08-07 00:18:54.000000000 -0400
22647+++ linux-2.6.17.11/kernel/capability.c 2006-08-12 08:17:55.000000000 -0400
22648@@ -12,6 +12,7 @@
22649 #include <linux/module.h>
22650 #include <linux/security.h>
22651 #include <linux/syscalls.h>
22652+#include <linux/grsecurity.h>
22653 #include <asm/uaccess.h>
22654
22655 unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
22656@@ -234,14 +235,25 @@ out:
22657 return ret;
22658 }
22659
22660+extern int gr_task_is_capable(struct task_struct *task, const int cap);
22661+extern int gr_is_capable_nolog(const int cap);
22662+
22663 int __capable(struct task_struct *t, int cap)
22664 {
22665- if (security_capable(t, cap) == 0) {
22666+ if ((security_capable(t, cap) == 0) && gr_task_is_capable(t, cap)) {
22667 t->flags |= PF_SUPERPRIV;
22668 return 1;
22669 }
22670 return 0;
22671 }
22672+int capable_nolog(int cap)
22673+{
22674+ if ((security_capable(current, cap) == 0) && gr_is_capable_nolog(cap)) {
22675+ current->flags |= PF_SUPERPRIV;
22676+ return 1;
22677+ }
22678+ return 0;
22679+}
22680 EXPORT_SYMBOL(__capable);
22681
22682 int capable(int cap)
22683@@ -249,3 +261,4 @@ int capable(int cap)
22684 return __capable(current, cap);
22685 }
22686 EXPORT_SYMBOL(capable);
22687+EXPORT_SYMBOL(capable_nolog);
22688diff -urNp linux-2.6.17.11/kernel/configs.c linux-2.6.17.11/kernel/configs.c
22689--- linux-2.6.17.11/kernel/configs.c 2006-08-07 00:18:54.000000000 -0400
22690+++ linux-2.6.17.11/kernel/configs.c 2006-08-12 08:17:55.000000000 -0400
22691@@ -89,8 +89,16 @@ static int __init ikconfig_init(void)
22692 struct proc_dir_entry *entry;
22693
22694 /* create the current config file */
22695+#ifdef CONFIG_GRKERNSEC_PROC_ADD
22696+#ifdef CONFIG_GRKERNSEC_PROC_USER
22697+ entry = create_proc_entry("config.gz", S_IFREG | S_IRUSR, &proc_root);
22698+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
22699+ entry = create_proc_entry("config.gz", S_IFREG | S_IRUSR | S_IRGRP, &proc_root);
22700+#endif
22701+#else
22702 entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
22703 &proc_root);
22704+#endif
22705 if (!entry)
22706 return -ENOMEM;
22707
22708diff -urNp linux-2.6.17.11/kernel/exit.c linux-2.6.17.11/kernel/exit.c
22709--- linux-2.6.17.11/kernel/exit.c 2006-08-07 00:18:54.000000000 -0400
22710+++ linux-2.6.17.11/kernel/exit.c 2006-08-12 08:17:55.000000000 -0400
22711@@ -36,6 +36,11 @@
22712 #include <linux/compat.h>
22713 #include <linux/pipe_fs_i.h>
22714 #include <linux/audit.h> /* for audit_free() */
22715+#include <linux/grsecurity.h>
22716+
22717+#ifdef CONFIG_GRKERNSEC
22718+extern rwlock_t grsec_exec_file_lock;
22719+#endif
22720
22721 #include <asm/uaccess.h>
22722 #include <asm/unistd.h>
22723@@ -115,6 +120,7 @@ static void __exit_signal(struct task_st
22724
22725 __unhash_process(tsk);
22726
22727+ gr_del_task_from_ip_table(tsk);
22728 tsk->signal = NULL;
22729 tsk->sighand = NULL;
22730 spin_unlock(&sighand->siglock);
22731@@ -287,6 +293,15 @@ static void reparent_to_init(void)
22732 {
22733 write_lock_irq(&tasklist_lock);
22734
22735+#ifdef CONFIG_GRKERNSEC
22736+ write_lock(&grsec_exec_file_lock);
22737+ if (current->exec_file) {
22738+ fput(current->exec_file);
22739+ current->exec_file = NULL;
22740+ }
22741+ write_unlock(&grsec_exec_file_lock);
22742+#endif
22743+
22744 ptrace_unlink(current);
22745 /* Reparent to init */
22746 remove_parent(current);
22747@@ -294,6 +309,8 @@ static void reparent_to_init(void)
22748 current->real_parent = child_reaper;
22749 add_parent(current);
22750
22751+ gr_set_kernel_label(current);
22752+
22753 /* Set the exit signal to SIGCHLD so we signal init on exit */
22754 current->exit_signal = SIGCHLD;
22755
22756@@ -390,6 +407,17 @@ void daemonize(const char *name, ...)
22757 vsnprintf(current->comm, sizeof(current->comm), name, args);
22758 va_end(args);
22759
22760+#ifdef CONFIG_GRKERNSEC
22761+ write_lock(&grsec_exec_file_lock);
22762+ if (current->exec_file) {
22763+ fput(current->exec_file);
22764+ current->exec_file = NULL;
22765+ }
22766+ write_unlock(&grsec_exec_file_lock);
22767+#endif
22768+
22769+ gr_set_kernel_label(current);
22770+
22771 /*
22772 * If we were started as result of loading a module, close all of the
22773 * user space pages. We don't need them, and if we didn't close them
22774@@ -905,9 +933,14 @@ fastcall NORET_TYPE void do_exit(long co
22775 #endif
22776 if (unlikely(tsk->audit_context))
22777 audit_free(tsk);
22778+
22779+ gr_acl_handle_psacct(tsk, code);
22780+ gr_acl_handle_exit();
22781+
22782 exit_mm(tsk);
22783
22784 exit_sem(tsk);
22785+ gr_shm_exit(tsk);
22786 __exit_files(tsk);
22787 __exit_fs(tsk);
22788 exit_namespace(tsk);
22789diff -urNp linux-2.6.17.11/kernel/fork.c linux-2.6.17.11/kernel/fork.c
22790--- linux-2.6.17.11/kernel/fork.c 2006-08-07 00:18:54.000000000 -0400
22791+++ linux-2.6.17.11/kernel/fork.c 2006-08-12 08:17:55.000000000 -0400
22792@@ -44,6 +44,7 @@
22793 #include <linux/rmap.h>
22794 #include <linux/acct.h>
22795 #include <linux/cn_proc.h>
22796+#include <linux/grsecurity.h>
22797
22798 #include <asm/pgtable.h>
22799 #include <asm/pgalloc.h>
22800@@ -198,8 +199,8 @@ static inline int dup_mmap(struct mm_str
22801 mm->locked_vm = 0;
22802 mm->mmap = NULL;
22803 mm->mmap_cache = NULL;
22804- mm->free_area_cache = oldmm->mmap_base;
22805- mm->cached_hole_size = ~0UL;
22806+ mm->free_area_cache = oldmm->free_area_cache;
22807+ mm->cached_hole_size = oldmm->cached_hole_size;
22808 mm->map_count = 0;
22809 cpus_clear(mm->cpu_vm_mask);
22810 mm->mm_rb = RB_ROOT;
22811@@ -324,7 +325,7 @@ static struct mm_struct * mm_init(struct
22812 spin_lock_init(&mm->page_table_lock);
22813 rwlock_init(&mm->ioctx_list_lock);
22814 mm->ioctx_list = NULL;
22815- mm->free_area_cache = TASK_UNMAPPED_BASE;
22816+ mm->free_area_cache = ~0UL;
22817 mm->cached_hole_size = ~0UL;
22818
22819 if (likely(!mm_alloc_pgd(mm))) {
22820@@ -956,6 +957,9 @@ static task_t *copy_process(unsigned lon
22821 goto fork_out;
22822
22823 retval = -EAGAIN;
22824+
22825+ gr_learn_resource(p, RLIMIT_NPROC, atomic_read(&p->user->processes), 0);
22826+
22827 if (atomic_read(&p->user->processes) >=
22828 p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
22829 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
22830@@ -1066,6 +1070,8 @@ static task_t *copy_process(unsigned lon
22831 if (retval)
22832 goto bad_fork_cleanup_namespace;
22833
22834+ gr_copy_label(p);
22835+
22836 p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
22837 /*
22838 * Clear TID on mm_release()?
22839@@ -1255,6 +1261,8 @@ bad_fork_cleanup_count:
22840 bad_fork_free:
22841 free_task(p);
22842 fork_out:
22843+ gr_log_forkfail(retval);
22844+
22845 return ERR_PTR(retval);
22846 }
22847
22848@@ -1328,6 +1336,8 @@ long do_fork(unsigned long clone_flags,
22849 if (!IS_ERR(p)) {
22850 struct completion vfork;
22851
22852+ gr_handle_brute_check();
22853+
22854 if (clone_flags & CLONE_VFORK) {
22855 p->vfork_done = &vfork;
22856 init_completion(&vfork);
22857diff -urNp linux-2.6.17.11/kernel/futex.c linux-2.6.17.11/kernel/futex.c
22858--- linux-2.6.17.11/kernel/futex.c 2006-08-07 00:18:54.000000000 -0400
22859+++ linux-2.6.17.11/kernel/futex.c 2006-08-12 08:17:55.000000000 -0400
22860@@ -151,6 +151,11 @@ static int get_futex_key(unsigned long u
22861 struct page *page;
22862 int err;
22863
22864+#ifdef CONFIG_PAX_SEGMEXEC
22865+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (uaddr >= SEGMEXEC_TASK_SIZE))
22866+ return -EFAULT;
22867+#endif
22868+
22869 /*
22870 * The futex address must be "naturally" aligned.
22871 */
22872diff -urNp linux-2.6.17.11/kernel/kallsyms.c linux-2.6.17.11/kernel/kallsyms.c
22873--- linux-2.6.17.11/kernel/kallsyms.c 2006-08-07 00:18:54.000000000 -0400
22874+++ linux-2.6.17.11/kernel/kallsyms.c 2006-08-12 08:17:55.000000000 -0400
22875@@ -301,7 +301,6 @@ static unsigned long get_ksymbol_core(st
22876
22877 static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
22878 {
22879- iter->name[0] = '\0';
22880 iter->nameoff = get_symbol_offset(new_pos);
22881 iter->pos = new_pos;
22882 }
22883@@ -380,7 +379,7 @@ static int kallsyms_open(struct inode *i
22884 struct kallsym_iter *iter;
22885 int ret;
22886
22887- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
22888+ iter = kzalloc(sizeof(*iter), GFP_KERNEL);
22889 if (!iter)
22890 return -ENOMEM;
22891 reset_iter(iter, 0);
22892@@ -411,7 +410,15 @@ static int __init kallsyms_init(void)
22893 {
22894 struct proc_dir_entry *entry;
22895
22896+#ifdef CONFIG_GRKERNSEC_PROC_ADD
22897+#ifdef CONFIG_GRKERNSEC_PROC_USER
22898+ entry = create_proc_entry("kallsyms", S_IFREG | S_IRUSR, NULL);
22899+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
22900+ entry = create_proc_entry("kallsyms", S_IFREG | S_IRUSR | S_IRGRP, NULL);
22901+#endif
22902+#else
22903 entry = create_proc_entry("kallsyms", 0444, NULL);
22904+#endif
22905 if (entry)
22906 entry->proc_fops = &kallsyms_operations;
22907 return 0;
22908diff -urNp linux-2.6.17.11/kernel/kprobes.c linux-2.6.17.11/kernel/kprobes.c
22909--- linux-2.6.17.11/kernel/kprobes.c 2006-08-07 00:18:54.000000000 -0400
22910+++ linux-2.6.17.11/kernel/kprobes.c 2006-08-12 08:17:55.000000000 -0400
22911@@ -106,7 +106,7 @@ kprobe_opcode_t __kprobes *get_insn_slot
22912 * kernel image and loaded module images reside. This is required
22913 * so x86_64 can correctly handle the %rip-relative fixups.
22914 */
22915- kip->insns = module_alloc(PAGE_SIZE);
22916+ kip->insns = module_alloc_exec(PAGE_SIZE);
22917 if (!kip->insns) {
22918 kfree(kip);
22919 return NULL;
22920diff -urNp linux-2.6.17.11/kernel/module.c linux-2.6.17.11/kernel/module.c
22921--- linux-2.6.17.11/kernel/module.c 2006-08-07 00:18:54.000000000 -0400
22922+++ linux-2.6.17.11/kernel/module.c 2006-08-12 08:17:55.000000000 -0400
22923@@ -40,10 +40,15 @@
22924 #include <linux/string.h>
22925 #include <linux/sched.h>
22926 #include <linux/mutex.h>
22927+#include <linux/kallsyms.h>
22928 #include <asm/uaccess.h>
22929 #include <asm/semaphore.h>
22930 #include <asm/cacheflush.h>
22931
22932+#ifdef CONFIG_PAX_KERNEXEC
22933+#include <asm/desc.h>
22934+#endif
22935+
22936 #if 0
22937 #define DEBUGP printk
22938 #else
22939@@ -66,6 +71,8 @@ static LIST_HEAD(modules);
22940
22941 static BLOCKING_NOTIFIER_HEAD(module_notify_list);
22942
22943+extern int gr_check_modstop(void);
22944+
22945 int register_module_notifier(struct notifier_block * nb)
22946 {
22947 return blocking_notifier_chain_register(&module_notify_list, nb);
22948@@ -594,6 +601,9 @@ sys_delete_module(const char __user *nam
22949 char name[MODULE_NAME_LEN];
22950 int ret, forced = 0;
22951
22952+ if (gr_check_modstop())
22953+ return -EPERM;
22954+
22955 if (!capable(CAP_SYS_MODULE))
22956 return -EPERM;
22957
22958@@ -1058,13 +1068,15 @@ static void free_module(struct module *m
22959 module_unload_free(mod);
22960
22961 /* This may be NULL, but that's OK */
22962- module_free(mod, mod->module_init);
22963+ module_free(mod, mod->module_init_rw);
22964+ module_free_exec(mod, mod->module_init_rx);
22965 kfree(mod->args);
22966 if (mod->percpu)
22967 percpu_modfree(mod->percpu);
22968
22969 /* Finally, free the core (containing the module structure) */
22970- module_free(mod, mod->module_core);
22971+ module_free_exec(mod, mod->module_core_rx);
22972+ module_free(mod, mod->module_core_rw);
22973 }
22974
22975 void *__symbol_get(const char *symbol)
22976@@ -1221,11 +1233,14 @@ static void layout_sections(struct modul
22977 || strncmp(secstrings + s->sh_name,
22978 ".init", 5) == 0)
22979 continue;
22980- s->sh_entsize = get_offset(&mod->core_size, s);
22981+ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
22982+ s->sh_entsize = get_offset(&mod->core_size_rw, s);
22983+ else
22984+ s->sh_entsize = get_offset(&mod->core_size_rx, s);
22985 DEBUGP("\t%s\n", secstrings + s->sh_name);
22986 }
22987 if (m == 0)
22988- mod->core_text_size = mod->core_size;
22989+ mod->core_size_rx = mod->core_size_rx;
22990 }
22991
22992 DEBUGP("Init section allocation order:\n");
22993@@ -1239,12 +1254,15 @@ static void layout_sections(struct modul
22994 || strncmp(secstrings + s->sh_name,
22995 ".init", 5) != 0)
22996 continue;
22997- s->sh_entsize = (get_offset(&mod->init_size, s)
22998- | INIT_OFFSET_MASK);
22999+ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
23000+ s->sh_entsize = get_offset(&mod->init_size_rw, s);
23001+ else
23002+ s->sh_entsize = get_offset(&mod->init_size_rx, s);
23003+ s->sh_entsize |= INIT_OFFSET_MASK;
23004 DEBUGP("\t%s\n", secstrings + s->sh_name);
23005 }
23006 if (m == 0)
23007- mod->init_text_size = mod->init_size;
23008+ mod->init_size_rx = mod->init_size_rx;
23009 }
23010 }
23011
23012@@ -1419,6 +1437,10 @@ static struct module *load_module(void _
23013 struct exception_table_entry *extable;
23014 mm_segment_t old_fs;
23015
23016+#ifdef CONFIG_PAX_KERNEXEC
23017+ unsigned long cr0;
23018+#endif
23019+
23020 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
23021 umod, len, uargs);
23022 if (len < sizeof(*hdr))
23023@@ -1568,21 +1590,57 @@ static struct module *load_module(void _
23024 layout_sections(mod, hdr, sechdrs, secstrings);
23025
23026 /* Do the allocs. */
23027- ptr = module_alloc(mod->core_size);
23028+ ptr = module_alloc(mod->core_size_rw);
23029 if (!ptr) {
23030 err = -ENOMEM;
23031 goto free_percpu;
23032 }
23033- memset(ptr, 0, mod->core_size);
23034- mod->module_core = ptr;
23035+ memset(ptr, 0, mod->core_size_rw);
23036+ mod->module_core_rw = ptr;
23037
23038- ptr = module_alloc(mod->init_size);
23039- if (!ptr && mod->init_size) {
23040+ ptr = module_alloc(mod->init_size_rw);
23041+ if (!ptr && mod->init_size_rw) {
23042 err = -ENOMEM;
23043- goto free_core;
23044+ goto free_core_rw;
23045 }
23046- memset(ptr, 0, mod->init_size);
23047- mod->module_init = ptr;
23048+ memset(ptr, 0, mod->init_size_rw);
23049+ mod->module_init_rw = ptr;
23050+
23051+ ptr = module_alloc_exec(mod->core_size_rx);
23052+ if (!ptr) {
23053+ err = -ENOMEM;
23054+ goto free_init_rw;
23055+ }
23056+
23057+#ifdef CONFIG_PAX_KERNEXEC
23058+ pax_open_kernel(cr0);
23059+#endif
23060+
23061+ memset(ptr, 0, mod->core_size_rx);
23062+
23063+#ifdef CONFIG_PAX_KERNEXEC
23064+ pax_close_kernel(cr0);
23065+#endif
23066+
23067+ mod->module_core_rx = ptr;
23068+
23069+ ptr = module_alloc_exec(mod->init_size_rx);
23070+ if (!ptr && mod->init_size_rx) {
23071+ err = -ENOMEM;
23072+ goto free_core_rx;
23073+ }
23074+
23075+#ifdef CONFIG_PAX_KERNEXEC
23076+ pax_open_kernel(cr0);
23077+#endif
23078+
23079+ memset(ptr, 0, mod->init_size_rx);
23080+
23081+#ifdef CONFIG_PAX_KERNEXEC
23082+ pax_close_kernel(cr0);
23083+#endif
23084+
23085+ mod->module_init_rx = ptr;
23086
23087 /* Transfer each section which specifies SHF_ALLOC */
23088 DEBUGP("final section addresses:\n");
23089@@ -1592,17 +1650,44 @@ static struct module *load_module(void _
23090 if (!(sechdrs[i].sh_flags & SHF_ALLOC))
23091 continue;
23092
23093- if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK)
23094- dest = mod->module_init
23095- + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
23096- else
23097- dest = mod->module_core + sechdrs[i].sh_entsize;
23098+ if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK) {
23099+ if ((sechdrs[i].sh_flags & SHF_WRITE) || !(sechdrs[i].sh_flags & SHF_ALLOC))
23100+ dest = mod->module_init_rw
23101+ + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
23102+ else
23103+ dest = mod->module_init_rx
23104+ + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
23105+ } else {
23106+ if ((sechdrs[i].sh_flags & SHF_WRITE) || !(sechdrs[i].sh_flags & SHF_ALLOC))
23107+ dest = mod->module_core_rw + sechdrs[i].sh_entsize;
23108+ else
23109+ dest = mod->module_core_rx + sechdrs[i].sh_entsize;
23110+ }
23111+
23112+ if (sechdrs[i].sh_type != SHT_NOBITS) {
23113
23114- if (sechdrs[i].sh_type != SHT_NOBITS)
23115- memcpy(dest, (void *)sechdrs[i].sh_addr,
23116- sechdrs[i].sh_size);
23117+#ifdef CONFIG_PAX_KERNEXEC
23118+ if (!(sechdrs[i].sh_flags & SHF_WRITE) && (sechdrs[i].sh_flags & SHF_ALLOC))
23119+ pax_open_kernel(cr0);
23120+#endif
23121+
23122+ memcpy(dest, (void *)sechdrs[i].sh_addr, sechdrs[i].sh_size);
23123+
23124+#ifdef CONFIG_PAX_KERNEXEC
23125+ if (!(sechdrs[i].sh_flags & SHF_WRITE) && (sechdrs[i].sh_flags & SHF_ALLOC))
23126+ pax_close_kernel(cr0);
23127+#endif
23128+
23129+ }
23130 /* Update sh_addr to point to copy in image. */
23131- sechdrs[i].sh_addr = (unsigned long)dest;
23132+
23133+#ifdef CONFIG_PAX_KERNEXEC
23134+ if (sechdrs[i].sh_flags & SHF_EXECINSTR)
23135+ sechdrs[i].sh_addr = (unsigned long)dest - __KERNEL_TEXT_OFFSET;
23136+ else
23137+#endif
23138+
23139+ sechdrs[i].sh_addr = (unsigned long)dest;
23140 DEBUGP("\t0x%lx %s\n", sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name);
23141 }
23142 /* Module has been moved. */
23143@@ -1623,8 +1708,18 @@ static struct module *load_module(void _
23144 setup_modinfo(mod, sechdrs, infoindex);
23145
23146 /* Fix up syms, so that st_value is a pointer to location. */
23147+
23148+#ifdef CONFIG_PAX_KERNEXEC
23149+ pax_open_kernel(cr0);
23150+#endif
23151+
23152 err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
23153 mod);
23154+
23155+#ifdef CONFIG_PAX_KERNEXEC
23156+ pax_close_kernel(cr0);
23157+#endif
23158+
23159 if (err < 0)
23160 goto cleanup;
23161
23162@@ -1666,11 +1761,20 @@ static struct module *load_module(void _
23163 if (!(sechdrs[info].sh_flags & SHF_ALLOC))
23164 continue;
23165
23166+#ifdef CONFIG_PAX_KERNEXEC
23167+ pax_open_kernel(cr0);
23168+#endif
23169+
23170 if (sechdrs[i].sh_type == SHT_REL)
23171 err = apply_relocate(sechdrs, strtab, symindex, i,mod);
23172 else if (sechdrs[i].sh_type == SHT_RELA)
23173 err = apply_relocate_add(sechdrs, strtab, symindex, i,
23174 mod);
23175+
23176+#ifdef CONFIG_PAX_KERNEXEC
23177+ pax_close_kernel(cr0);
23178+#endif
23179+
23180 if (err < 0)
23181 goto cleanup;
23182 }
23183@@ -1684,14 +1788,31 @@ static struct module *load_module(void _
23184 /* Set up and sort exception table */
23185 mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
23186 mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
23187+
23188+#ifdef CONFIG_PAX_KERNEXEC
23189+ pax_open_kernel(cr0);
23190+#endif
23191+
23192 sort_extable(extable, extable + mod->num_exentries);
23193
23194+#ifdef CONFIG_PAX_KERNEXEC
23195+ pax_close_kernel(cr0);
23196+#endif
23197+
23198 /* Finally, copy percpu area over. */
23199 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
23200 sechdrs[pcpuindex].sh_size);
23201
23202+#ifdef CONFIG_PAX_KERNEXEC
23203+ pax_open_kernel(cr0);
23204+#endif
23205+
23206 add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
23207
23208+#ifdef CONFIG_PAX_KERNEXEC
23209+ pax_close_kernel(cr0);
23210+#endif
23211+
23212 err = module_finalize(hdr, sechdrs, mod);
23213 if (err < 0)
23214 goto cleanup;
23215@@ -1705,12 +1826,12 @@ static struct module *load_module(void _
23216 * Do it before processing of module parameters, so the module
23217 * can provide parameter accessor functions of its own.
23218 */
23219- if (mod->module_init)
23220- flush_icache_range((unsigned long)mod->module_init,
23221- (unsigned long)mod->module_init
23222- + mod->init_size);
23223- flush_icache_range((unsigned long)mod->module_core,
23224- (unsigned long)mod->module_core + mod->core_size);
23225+ if (mod->module_init_rx)
23226+ flush_icache_range((unsigned long)mod->module_init_rx,
23227+ (unsigned long)mod->module_init_rx
23228+ + mod->init_size_rx);
23229+ flush_icache_range((unsigned long)mod->module_core_rx,
23230+ (unsigned long)mod->module_core_rx + mod->core_size_rx);
23231
23232 set_fs(old_fs);
23233
23234@@ -1748,9 +1869,13 @@ static struct module *load_module(void _
23235 module_arch_cleanup(mod);
23236 cleanup:
23237 module_unload_free(mod);
23238- module_free(mod, mod->module_init);
23239- free_core:
23240- module_free(mod, mod->module_core);
23241+ module_free_exec(mod, mod->module_init_rx);
23242+ free_core_rx:
23243+ module_free_exec(mod, mod->module_core_rx);
23244+ free_init_rw:
23245+ module_free(mod, mod->module_init_rw);
23246+ free_core_rw:
23247+ module_free(mod, mod->module_core_rw);
23248 free_percpu:
23249 if (percpu)
23250 percpu_modfree(percpu);
23251@@ -1786,6 +1911,9 @@ sys_init_module(void __user *umod,
23252 struct module *mod;
23253 int ret = 0;
23254
23255+ if (gr_check_modstop())
23256+ return -EPERM;
23257+
23258 /* Must have permission */
23259 if (!capable(CAP_SYS_MODULE))
23260 return -EPERM;
23261@@ -1836,10 +1964,12 @@ sys_init_module(void __user *umod,
23262 mod->state = MODULE_STATE_LIVE;
23263 /* Drop initial reference. */
23264 module_put(mod);
23265- module_free(mod, mod->module_init);
23266- mod->module_init = NULL;
23267- mod->init_size = 0;
23268- mod->init_text_size = 0;
23269+ module_free(mod, mod->module_init_rw);
23270+ module_free_exec(mod, mod->module_init_rx);
23271+ mod->module_init_rw = NULL;
23272+ mod->module_init_rx = NULL;
23273+ mod->init_size_rw = 0;
23274+ mod->init_size_rx = 0;
23275 mutex_unlock(&module_mutex);
23276
23277 return 0;
23278@@ -1870,10 +2000,14 @@ static const char *get_ksymbol(struct mo
23279 unsigned long nextval;
23280
23281 /* At worse, next value is at end of module */
23282- if (within(addr, mod->module_init, mod->init_size))
23283- nextval = (unsigned long)mod->module_init+mod->init_text_size;
23284- else
23285- nextval = (unsigned long)mod->module_core+mod->core_text_size;
23286+ if (within(addr, mod->module_init_rx, mod->init_size_rx))
23287+ nextval = (unsigned long)mod->module_init_rw;
23288+ else if (within(addr, mod->module_init_rw, mod->init_size_rw))
23289+ nextval = (unsigned long)mod->module_core_rx;
23290+ else if (within(addr, mod->module_core_rx, mod->core_size_rx))
23291+ nextval = (unsigned long)mod->module_core_rw;
23292+ else
23293+ nextval = (unsigned long)mod->module_core_rw+mod->core_size_rw;
23294
23295 /* Scan for closest preceeding symbol, and next symbol. (ELF
23296 starts real symbols at 1). */
23297@@ -1914,8 +2048,10 @@ const char *module_address_lookup(unsign
23298 struct module *mod;
23299
23300 list_for_each_entry(mod, &modules, list) {
23301- if (within(addr, mod->module_init, mod->init_size)
23302- || within(addr, mod->module_core, mod->core_size)) {
23303+ if (within(addr, mod->module_init_rx, mod->init_size_rx)
23304+ || within(addr, mod->module_init_rw, mod->init_size_rw)
23305+ || within(addr, mod->module_core_rx, mod->core_size_rx)
23306+ || within(addr, mod->module_core_rw, mod->core_size_rw)) {
23307 *modname = mod->name;
23308 return get_ksymbol(mod, addr, size, offset);
23309 }
23310@@ -1926,7 +2062,7 @@ const char *module_address_lookup(unsign
23311 struct module *module_get_kallsym(unsigned int symnum,
23312 unsigned long *value,
23313 char *type,
23314- char namebuf[128])
23315+ char namebuf[KSYM_NAME_LEN+1])
23316 {
23317 struct module *mod;
23318
23319@@ -1937,7 +2073,7 @@ struct module *module_get_kallsym(unsign
23320 *type = mod->symtab[symnum].st_info;
23321 strncpy(namebuf,
23322 mod->strtab + mod->symtab[symnum].st_name,
23323- 127);
23324+ KSYM_NAME_LEN);
23325 mutex_unlock(&module_mutex);
23326 return mod;
23327 }
23328@@ -2014,7 +2150,7 @@ static int m_show(struct seq_file *m, vo
23329 {
23330 struct module *mod = list_entry(p, struct module, list);
23331 seq_printf(m, "%s %lu",
23332- mod->name, mod->init_size + mod->core_size);
23333+ mod->name, mod->init_size_rx + mod->init_size_rw + mod->core_size_rx + mod->core_size_rw);
23334 print_unload_info(m, mod);
23335
23336 /* Informative for users. */
23337@@ -2023,7 +2159,7 @@ static int m_show(struct seq_file *m, vo
23338 mod->state == MODULE_STATE_COMING ? "Loading":
23339 "Live");
23340 /* Used by oprofile and other similar tools. */
23341- seq_printf(m, " 0x%p", mod->module_core);
23342+ seq_printf(m, " 0x%p 0x%p", mod->module_core_rx, mod->module_core_rw);
23343
23344 seq_printf(m, "\n");
23345 return 0;
23346@@ -2072,8 +2208,8 @@ struct module *__module_text_address(uns
23347 struct module *mod;
23348
23349 list_for_each_entry(mod, &modules, list)
23350- if (within(addr, mod->module_init, mod->init_text_size)
23351- || within(addr, mod->module_core, mod->core_text_size))
23352+ if (within(addr, mod->module_init_rx, mod->init_size_rx)
23353+ || within(addr, mod->module_core_rx, mod->core_size_rx))
23354 return mod;
23355 return NULL;
23356 }
23357diff -urNp linux-2.6.17.11/kernel/pid.c linux-2.6.17.11/kernel/pid.c
23358--- linux-2.6.17.11/kernel/pid.c 2006-08-07 00:18:54.000000000 -0400
23359+++ linux-2.6.17.11/kernel/pid.c 2006-08-12 08:17:55.000000000 -0400
23360@@ -26,6 +26,7 @@
23361 #include <linux/init.h>
23362 #include <linux/bootmem.h>
23363 #include <linux/hash.h>
23364+#include <linux/grsecurity.h>
23365
23366 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
23367 static struct hlist_head *pid_hash;
23368@@ -90,7 +91,9 @@ static int alloc_pidmap(void)
23369 int i, offset, max_scan, pid, last = last_pid;
23370 pidmap_t *map;
23371
23372- pid = last + 1;
23373+ pid = gr_random_pid();
23374+ if (!pid)
23375+ pid = last_pid + 1;
23376 if (pid >= pid_max)
23377 pid = RESERVED_PIDS;
23378 offset = pid & BITS_PER_PAGE_MASK;
23379@@ -269,7 +272,14 @@ struct task_struct * fastcall pid_task(s
23380 */
23381 task_t *find_task_by_pid_type(int type, int nr)
23382 {
23383- return pid_task(find_pid(nr), type);
23384+ task_t *task;
23385+
23386+ task = pid_task(find_pid(nr), type);
23387+
23388+ if (gr_pid_is_chrooted(task))
23389+ return NULL;
23390+
23391+ return task;
23392 }
23393
23394 EXPORT_SYMBOL(find_task_by_pid_type);
23395diff -urNp linux-2.6.17.11/kernel/posix-cpu-timers.c linux-2.6.17.11/kernel/posix-cpu-timers.c
23396--- linux-2.6.17.11/kernel/posix-cpu-timers.c 2006-08-07 00:18:54.000000000 -0400
23397+++ linux-2.6.17.11/kernel/posix-cpu-timers.c 2006-08-12 08:17:55.000000000 -0400
23398@@ -6,6 +6,7 @@
23399 #include <linux/posix-timers.h>
23400 #include <asm/uaccess.h>
23401 #include <linux/errno.h>
23402+#include <linux/grsecurity.h>
23403
23404 static int check_clock(const clockid_t which_clock)
23405 {
23406@@ -1125,6 +1126,7 @@ static void check_process_timers(struct
23407 __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
23408 return;
23409 }
23410+ gr_learn_resource(tsk, RLIMIT_CPU, psecs, 1);
23411 if (psecs >= sig->rlim[RLIMIT_CPU].rlim_cur) {
23412 /*
23413 * At the soft limit, send a SIGXCPU every second.
23414diff -urNp linux-2.6.17.11/kernel/printk.c linux-2.6.17.11/kernel/printk.c
23415--- linux-2.6.17.11/kernel/printk.c 2006-08-07 00:18:54.000000000 -0400
23416+++ linux-2.6.17.11/kernel/printk.c 2006-08-12 08:17:55.000000000 -0400
23417@@ -31,6 +31,7 @@
23418 #include <linux/security.h>
23419 #include <linux/bootmem.h>
23420 #include <linux/syscalls.h>
23421+#include <linux/grsecurity.h>
23422
23423 #include <asm/uaccess.h>
23424
23425@@ -185,6 +186,11 @@ int do_syslog(int type, char __user *buf
23426 char c;
23427 int error = 0;
23428
23429+#ifdef CONFIG_GRKERNSEC_DMESG
23430+ if (grsec_enable_dmesg && !capable(CAP_SYS_ADMIN))
23431+ return -EPERM;
23432+#endif
23433+
23434 error = security_syslog(type);
23435 if (error)
23436 return error;
23437diff -urNp linux-2.6.17.11/kernel/ptrace.c linux-2.6.17.11/kernel/ptrace.c
23438--- linux-2.6.17.11/kernel/ptrace.c 2006-08-07 00:18:54.000000000 -0400
23439+++ linux-2.6.17.11/kernel/ptrace.c 2006-08-12 08:17:55.000000000 -0400
23440@@ -18,6 +18,7 @@
23441 #include <linux/ptrace.h>
23442 #include <linux/security.h>
23443 #include <linux/signal.h>
23444+#include <linux/grsecurity.h>
23445
23446 #include <asm/pgtable.h>
23447 #include <asm/uaccess.h>
23448@@ -127,10 +128,10 @@ static int may_attach(struct task_struct
23449 (current->uid != task->uid) ||
23450 (current->gid != task->egid) ||
23451 (current->gid != task->sgid) ||
23452- (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
23453+ (current->gid != task->gid)) && !capable_nolog(CAP_SYS_PTRACE))
23454 return -EPERM;
23455 smp_rmb();
23456- if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
23457+ if (!task->mm->dumpable && !capable_nolog(CAP_SYS_PTRACE))
23458 return -EPERM;
23459
23460 return security_ptrace(current, task);
23461@@ -515,6 +516,11 @@ asmlinkage long sys_ptrace(long request,
23462 if (ret < 0)
23463 goto out_put_task_struct;
23464
23465+ if (gr_handle_ptrace(child, request)) {
23466+ ret = -EPERM;
23467+ goto out_put_task_struct;
23468+ }
23469+
23470 ret = arch_ptrace(child, request, addr, data);
23471 if (ret < 0)
23472 goto out_put_task_struct;
23473diff -urNp linux-2.6.17.11/kernel/resource.c linux-2.6.17.11/kernel/resource.c
23474--- linux-2.6.17.11/kernel/resource.c 2006-08-07 00:18:54.000000000 -0400
23475+++ linux-2.6.17.11/kernel/resource.c 2006-08-12 08:17:55.000000000 -0400
23476@@ -136,10 +136,27 @@ static int __init ioresources_init(void)
23477 {
23478 struct proc_dir_entry *entry;
23479
23480+#ifdef CONFIG_GRKERNSEC_PROC_ADD
23481+#ifdef CONFIG_GRKERNSEC_PROC_USER
23482+ entry = create_proc_entry("ioports", S_IRUSR, NULL);
23483+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
23484+ entry = create_proc_entry("ioports", S_IRUSR | S_IRGRP, NULL);
23485+#endif
23486+#else
23487 entry = create_proc_entry("ioports", 0, NULL);
23488+#endif
23489 if (entry)
23490 entry->proc_fops = &proc_ioports_operations;
23491+
23492+#ifdef CONFIG_GRKERNSEC_PROC_ADD
23493+#ifdef CONFIG_GRKERNSEC_PROC_USER
23494+ entry = create_proc_entry("iomem", S_IRUSR, NULL);
23495+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
23496+ entry = create_proc_entry("iomem", S_IRUSR | S_IRGRP, NULL);
23497+#endif
23498+#else
23499 entry = create_proc_entry("iomem", 0, NULL);
23500+#endif
23501 if (entry)
23502 entry->proc_fops = &proc_iomem_operations;
23503 return 0;
23504diff -urNp linux-2.6.17.11/kernel/sched.c linux-2.6.17.11/kernel/sched.c
23505--- linux-2.6.17.11/kernel/sched.c 2006-08-07 00:18:54.000000000 -0400
23506+++ linux-2.6.17.11/kernel/sched.c 2006-08-12 08:17:55.000000000 -0400
23507@@ -50,6 +50,7 @@
23508 #include <linux/times.h>
23509 #include <linux/acct.h>
23510 #include <linux/kprobes.h>
23511+#include <linux/grsecurity.h>
23512 #include <asm/tlb.h>
23513
23514 #include <asm/unistd.h>
23515@@ -3565,7 +3566,8 @@ asmlinkage long sys_nice(int increment)
23516 if (nice > 19)
23517 nice = 19;
23518
23519- if (increment < 0 && !can_nice(current, nice))
23520+ if (increment < 0 && (!can_nice(current, nice) ||
23521+ gr_handle_chroot_nice()))
23522 return -EPERM;
23523
23524 retval = security_task_setnice(current, nice);
23525diff -urNp linux-2.6.17.11/kernel/signal.c linux-2.6.17.11/kernel/signal.c
23526--- linux-2.6.17.11/kernel/signal.c 2006-08-07 00:18:54.000000000 -0400
23527+++ linux-2.6.17.11/kernel/signal.c 2006-08-12 08:17:55.000000000 -0400
23528@@ -25,6 +25,7 @@
23529 #include <linux/signal.h>
23530 #include <linux/audit.h>
23531 #include <linux/capability.h>
23532+#include <linux/grsecurity.h>
23533 #include <asm/param.h>
23534 #include <asm/uaccess.h>
23535 #include <asm/unistd.h>
23536@@ -577,16 +578,18 @@ static int check_kill_permission(int sig
23537 return error;
23538 error = -EPERM;
23539 if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
23540- && ((sig != SIGCONT) ||
23541+ && ((((sig != SIGCONT) ||
23542 (current->signal->session != t->signal->session))
23543 && (current->euid ^ t->suid) && (current->euid ^ t->uid)
23544 && (current->uid ^ t->suid) && (current->uid ^ t->uid)
23545- && !capable(CAP_KILL))
23546+ && !capable(CAP_KILL)) || gr_handle_signal(t, sig)))
23547 return error;
23548
23549 error = security_task_kill(t, info, sig);
23550- if (!error)
23551+ if (!error) {
23552 audit_signal_info(sig, t); /* Let audit system see the signal */
23553+ gr_log_signal(sig, t);
23554+ }
23555 return error;
23556 }
23557
23558@@ -764,7 +767,7 @@ out_set:
23559 (((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
23560
23561
23562-static int
23563+int
23564 specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
23565 {
23566 int ret = 0;
23567@@ -809,6 +812,10 @@ force_sig_info(int sig, struct siginfo *
23568 }
23569 recalc_sigpending_tsk(t);
23570 ret = specific_send_sig_info(sig, info, t);
23571+
23572+ gr_log_signal(sig, t);
23573+ gr_handle_crash(t, sig);
23574+
23575 spin_unlock_irqrestore(&t->sighand->siglock, flags);
23576
23577 return ret;
23578diff -urNp linux-2.6.17.11/kernel/sys.c linux-2.6.17.11/kernel/sys.c
23579--- linux-2.6.17.11/kernel/sys.c 2006-08-07 00:18:54.000000000 -0400
23580+++ linux-2.6.17.11/kernel/sys.c 2006-08-12 08:17:55.000000000 -0400
23581@@ -30,6 +30,7 @@
23582 #include <linux/tty.h>
23583 #include <linux/signal.h>
23584 #include <linux/cn_proc.h>
23585+#include <linux/grsecurity.h>
23586
23587 #include <linux/compat.h>
23588 #include <linux/syscalls.h>
23589@@ -442,6 +443,12 @@ static int set_one_prio(struct task_stru
23590 error = -EACCES;
23591 goto out;
23592 }
23593+
23594+ if (gr_handle_chroot_setpriority(p, niceval)) {
23595+ error = -EACCES;
23596+ goto out;
23597+ }
23598+
23599 no_nice = security_task_setnice(p, niceval);
23600 if (no_nice) {
23601 error = no_nice;
23602@@ -831,6 +838,9 @@ asmlinkage long sys_setregid(gid_t rgid,
23603 if (rgid != (gid_t) -1 ||
23604 (egid != (gid_t) -1 && egid != old_rgid))
23605 current->sgid = new_egid;
23606+
23607+ gr_set_role_label(current, current->uid, new_rgid);
23608+
23609 current->fsgid = new_egid;
23610 current->egid = new_egid;
23611 current->gid = new_rgid;
23612@@ -860,6 +870,9 @@ asmlinkage long sys_setgid(gid_t gid)
23613 current->mm->dumpable = suid_dumpable;
23614 smp_wmb();
23615 }
23616+
23617+ gr_set_role_label(current, current->uid, gid);
23618+
23619 current->gid = current->egid = current->sgid = current->fsgid = gid;
23620 }
23621 else if ((gid == current->gid) || (gid == current->sgid))
23622@@ -901,6 +914,9 @@ static int set_user(uid_t new_ruid, int
23623 current->mm->dumpable = suid_dumpable;
23624 smp_wmb();
23625 }
23626+
23627+ gr_set_role_label(current, new_ruid, current->gid);
23628+
23629 current->uid = new_ruid;
23630 return 0;
23631 }
23632@@ -1004,6 +1020,9 @@ asmlinkage long sys_setuid(uid_t uid)
23633 } else if ((uid != current->uid) && (uid != new_suid))
23634 return -EPERM;
23635
23636+ if (gr_check_crash_uid(uid))
23637+ return -EPERM;
23638+
23639 if (old_euid != uid)
23640 {
23641 current->mm->dumpable = suid_dumpable;
23642@@ -1109,8 +1128,10 @@ asmlinkage long sys_setresgid(gid_t rgid
23643 current->egid = egid;
23644 }
23645 current->fsgid = current->egid;
23646- if (rgid != (gid_t) -1)
23647+ if (rgid != (gid_t) -1) {
23648+ gr_set_role_label(current, current->uid, rgid);
23649 current->gid = rgid;
23650+ }
23651 if (sgid != (gid_t) -1)
23652 current->sgid = sgid;
23653
23654diff -urNp linux-2.6.17.11/kernel/sysctl.c linux-2.6.17.11/kernel/sysctl.c
23655--- linux-2.6.17.11/kernel/sysctl.c 2006-08-07 00:18:54.000000000 -0400
23656+++ linux-2.6.17.11/kernel/sysctl.c 2006-08-12 08:17:55.000000000 -0400
23657@@ -54,6 +54,14 @@ extern int proc_nr_files(ctl_table *tabl
23658 void __user *buffer, size_t *lenp, loff_t *ppos);
23659
23660 #if defined(CONFIG_SYSCTL)
23661+#include <linux/grsecurity.h>
23662+#include <linux/grinternal.h>
23663+
23664+extern __u32 gr_handle_sysctl(const ctl_table *table, const void *oldval,
23665+ const void *newval);
23666+extern int gr_handle_sysctl_mod(const char *dirname, const char *name,
23667+ const int op);
23668+extern int gr_handle_chroot_sysctl(const int op);
23669
23670 /* External variables not in a header file. */
23671 extern int C_A_D;
23672@@ -157,6 +165,22 @@ extern ctl_table inotify_table[];
23673 #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
23674 int sysctl_legacy_va_layout;
23675 #endif
23676+extern ctl_table grsecurity_table[];
23677+
23678+#ifdef CONFIG_PAX_SOFTMODE
23679+static ctl_table pax_table[] = {
23680+ {
23681+ .ctl_name = PAX_SOFTMODE,
23682+ .procname = "softmode",
23683+ .data = &pax_softmode,
23684+ .maxlen = sizeof(unsigned int),
23685+ .mode = 0600,
23686+ .proc_handler = &proc_dointvec,
23687+ },
23688+
23689+ { .ctl_name = 0 }
23690+};
23691+#endif
23692
23693 /* /proc declarations: */
23694
23695@@ -683,6 +707,24 @@ static ctl_table kern_table[] = {
23696 .proc_handler = &proc_dointvec,
23697 },
23698 #endif
23699+
23700+#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP)
23701+ {
23702+ .ctl_name = KERN_GRSECURITY,
23703+ .procname = "grsecurity",
23704+ .mode = 0500,
23705+ .child = grsecurity_table,
23706+ },
23707+#endif
23708+
23709+#ifdef CONFIG_PAX_SOFTMODE
23710+ {
23711+ .ctl_name = KERN_PAX,
23712+ .procname = "pax",
23713+ .mode = 0500,
23714+ .child = pax_table,
23715+ },
23716+#endif
23717 { .ctl_name = 0 }
23718 };
23719
23720@@ -1180,6 +1222,10 @@ static int test_perm(int mode, int op)
23721 static inline int ctl_perm(ctl_table *table, int op)
23722 {
23723 int error;
23724+ if (table->de && gr_handle_sysctl_mod(table->de->parent->name, table->de->name, op))
23725+ return -EACCES;
23726+ if (gr_handle_chroot_sysctl(op))
23727+ return -EACCES;
23728 error = security_sysctl(table, op);
23729 if (error)
23730 return error;
23731@@ -1216,6 +1262,10 @@ repeat:
23732 table = table->child;
23733 goto repeat;
23734 }
23735+
23736+ if (!gr_handle_sysctl(table, oldval, newval))
23737+ return -EPERM;
23738+
23739 error = do_sysctl_strategy(table, name, nlen,
23740 oldval, oldlenp,
23741 newval, newlen, context);
23742diff -urNp linux-2.6.17.11/kernel/time.c linux-2.6.17.11/kernel/time.c
23743--- linux-2.6.17.11/kernel/time.c 2006-08-07 00:18:54.000000000 -0400
23744+++ linux-2.6.17.11/kernel/time.c 2006-08-12 08:17:55.000000000 -0400
23745@@ -36,6 +36,7 @@
23746 #include <linux/security.h>
23747 #include <linux/fs.h>
23748 #include <linux/module.h>
23749+#include <linux/grsecurity.h>
23750
23751 #include <asm/uaccess.h>
23752 #include <asm/unistd.h>
23753@@ -93,6 +94,9 @@ asmlinkage long sys_stime(time_t __user
23754 return err;
23755
23756 do_settimeofday(&tv);
23757+
23758+ gr_log_timechange();
23759+
23760 return 0;
23761 }
23762
23763@@ -199,6 +203,8 @@ asmlinkage long sys_settimeofday(struct
23764 return -EFAULT;
23765 }
23766
23767+ gr_log_timechange();
23768+
23769 return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
23770 }
23771
23772diff -urNp linux-2.6.17.11/localversion-grsec linux-2.6.17.11/localversion-grsec
23773--- linux-2.6.17.11/localversion-grsec 1969-12-31 19:00:00.000000000 -0500
23774+++ linux-2.6.17.11/localversion-grsec 2006-08-12 08:17:55.000000000 -0400
23775@@ -0,0 +1 @@
23776+-grsec
23777diff -urNp linux-2.6.17.11/Makefile linux-2.6.17.11/Makefile
23778--- linux-2.6.17.11/Makefile 2006-08-23 19:30:00.000000000 -0400
23779+++ linux-2.6.17.11/Makefile 2006-08-23 19:30:12.000000000 -0400
23780@@ -518,7 +518,7 @@ export MODLIB
23781
23782
23783 ifeq ($(KBUILD_EXTMOD),)
23784-core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
23785+core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
23786
23787 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
23788 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
23789diff -urNp linux-2.6.17.11/mm/filemap.c linux-2.6.17.11/mm/filemap.c
23790--- linux-2.6.17.11/mm/filemap.c 2006-08-07 00:18:54.000000000 -0400
23791+++ linux-2.6.17.11/mm/filemap.c 2006-08-12 08:17:55.000000000 -0400
23792@@ -30,6 +30,7 @@
23793 #include <linux/security.h>
23794 #include <linux/syscalls.h>
23795 #include <linux/cpuset.h>
23796+#include <linux/grsecurity.h>
23797 #include "filemap.h"
23798 #include "internal.h"
23799
23800@@ -1650,7 +1651,13 @@ int generic_file_mmap(struct file * file
23801 struct address_space *mapping = file->f_mapping;
23802
23803 if (!mapping->a_ops->readpage)
23804- return -ENOEXEC;
23805+ return -ENODEV;
23806+
23807+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32)
23808+ if ((vma->vm_mm->pax_flags & MF_PAX_PAGEEXEC) && !(vma->vm_flags & VM_EXEC))
23809+ vma->vm_page_prot = __pgprot(pte_val(pte_exprotect(__pte(pgprot_val(vma->vm_page_prot)))));
23810+#endif
23811+
23812 file_accessed(file);
23813 vma->vm_ops = &generic_file_vm_ops;
23814 return 0;
23815@@ -1872,6 +1879,7 @@ inline int generic_write_checks(struct f
23816 *pos = i_size_read(inode);
23817
23818 if (limit != RLIM_INFINITY) {
23819+ gr_learn_resource(current, RLIMIT_FSIZE,*pos, 0);
23820 if (*pos >= limit) {
23821 send_sig(SIGXFSZ, current, 0);
23822 return -EFBIG;
23823diff -urNp linux-2.6.17.11/mm/madvise.c linux-2.6.17.11/mm/madvise.c
23824--- linux-2.6.17.11/mm/madvise.c 2006-08-07 00:18:54.000000000 -0400
23825+++ linux-2.6.17.11/mm/madvise.c 2006-08-12 08:17:55.000000000 -0400
23826@@ -15,9 +15,46 @@
23827 * We can potentially split a vm area into separate
23828 * areas, each area with its own behavior.
23829 */
23830+
23831+#ifdef CONFIG_PAX_SEGMEXEC
23832+static long __madvise_behavior(struct vm_area_struct * vma,
23833+ struct vm_area_struct **prev,
23834+ unsigned long start, unsigned long end, int behavior);
23835+
23836+static long madvise_behavior(struct vm_area_struct * vma,
23837+ struct vm_area_struct **prev,
23838+ unsigned long start, unsigned long end, int behavior)
23839+{
23840+ if (vma->vm_flags & VM_MIRROR) {
23841+ struct vm_area_struct * vma_m, * prev_m;
23842+ unsigned long start_m, end_m;
23843+ int error;
23844+
23845+ start_m = vma->vm_start + vma->vm_mirror;
23846+ vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m);
23847+ if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
23848+ start_m = start + vma->vm_mirror;
23849+ end_m = end + vma->vm_mirror;
23850+ error = __madvise_behavior(vma_m, &prev_m, start_m, end_m, behavior);
23851+ if (error)
23852+ return error;
23853+ } else {
23854+ printk("PAX: VMMIRROR: madvise bug in %s, %08lx\n", current->comm, vma->vm_start);
23855+ return -ENOMEM;
23856+ }
23857+ }
23858+
23859+ return __madvise_behavior(vma, prev, start, end, behavior);
23860+}
23861+
23862+static long __madvise_behavior(struct vm_area_struct * vma,
23863+ struct vm_area_struct **prev,
23864+ unsigned long start, unsigned long end, int behavior)
23865+#else
23866 static long madvise_behavior(struct vm_area_struct * vma,
23867 struct vm_area_struct **prev,
23868 unsigned long start, unsigned long end, int behavior)
23869+#endif
23870 {
23871 struct mm_struct * mm = vma->vm_mm;
23872 int error = 0;
23873diff -urNp linux-2.6.17.11/mm/memory.c linux-2.6.17.11/mm/memory.c
23874--- linux-2.6.17.11/mm/memory.c 2006-08-07 00:18:54.000000000 -0400
23875+++ linux-2.6.17.11/mm/memory.c 2006-08-12 08:17:55.000000000 -0400
23876@@ -48,6 +48,7 @@
23877 #include <linux/rmap.h>
23878 #include <linux/module.h>
23879 #include <linux/init.h>
23880+#include <linux/grsecurity.h>
23881
23882 #include <asm/pgalloc.h>
23883 #include <asm/uaccess.h>
23884@@ -320,6 +321,11 @@ int __pte_alloc(struct mm_struct *mm, pm
23885
23886 int __pte_alloc_kernel(pmd_t *pmd, unsigned long address)
23887 {
23888+
23889+#ifdef CONFIG_PAX_KERNEXEC
23890+ unsigned long cr0;
23891+#endif
23892+
23893 pte_t *new = pte_alloc_one_kernel(&init_mm, address);
23894 if (!new)
23895 return -ENOMEM;
23896@@ -327,8 +333,19 @@ int __pte_alloc_kernel(pmd_t *pmd, unsig
23897 spin_lock(&init_mm.page_table_lock);
23898 if (pmd_present(*pmd)) /* Another has populated it */
23899 pte_free_kernel(new);
23900- else
23901+ else {
23902+
23903+#ifdef CONFIG_PAX_KERNEXEC
23904+ pax_open_kernel(cr0);
23905+#endif
23906+
23907 pmd_populate_kernel(&init_mm, pmd, new);
23908+
23909+#ifdef CONFIG_PAX_KERNEXEC
23910+ pax_close_kernel(cr0);
23911+#endif
23912+
23913+ }
23914 spin_unlock(&init_mm.page_table_lock);
23915 return 0;
23916 }
23917@@ -1421,6 +1438,88 @@ static inline void cow_user_page(struct
23918 copy_user_highpage(dst, src, va);
23919 }
23920
23921+#ifdef CONFIG_PAX_SEGMEXEC
23922+/* PaX: if vma is mirrored, synchronize the mirror's PTE
23923+ *
23924+ * the ptl of the lower mapped page is held on entry and is not released on exit
23925+ * or inside to ensure atomic changes to the PTE states (swapout, mremap, munmap, etc)
23926+ */
23927+static void pax_mirror_fault(struct vm_area_struct *vma, unsigned long address, pte_t *pte)
23928+{
23929+ struct mm_struct *mm = vma->vm_mm;
23930+ unsigned long address_m, pfn_m;
23931+ struct vm_area_struct * vma_m = NULL;
23932+ pte_t * pte_m, entry_m;
23933+ struct page * page_m = NULL;
23934+
23935+ address_m = vma->vm_start + vma->vm_mirror;
23936+ vma_m = find_vma(mm, address_m);
23937+ BUG_ON(!vma_m || vma_m->vm_start != address_m);
23938+
23939+ address_m = address + vma->vm_mirror;
23940+ pte_m = pte_offset_map_nested(pmd_offset(pud_offset(pgd_offset(mm, address_m), address_m), address_m), address_m);
23941+
23942+ if (pte_same(*pte, *pte_m)) {
23943+ pte_unmap_nested(pte_m);
23944+ return;
23945+ }
23946+
23947+ pfn_m = pte_pfn(*pte);
23948+ if (pte_present(*pte_m)) {
23949+ page_m = vm_normal_page(vma_m, address_m, *pte_m);
23950+ if (page_m) {
23951+ flush_cache_page(vma_m, address_m, pfn_m);
23952+ flush_icache_page(vma_m, page_m);
23953+ }
23954+ }
23955+
23956+ if (pte_present(*pte_m))
23957+ entry_m = ptep_clear_flush(vma_m, address_m, pte_m);
23958+ else
23959+ entry_m = ptep_get_and_clear(mm, address_m, pte_m);
23960+
23961+ if (pte_none(entry_m)) {
23962+ } else if (pte_present(entry_m)) {
23963+ if (page_m) {
23964+ page_remove_rmap(page_m);
23965+ if (PageAnon(page_m))
23966+ dec_mm_counter(mm, anon_rss);
23967+ else
23968+ dec_mm_counter(mm, file_rss);
23969+ page_cache_release(page_m);
23970+ }
23971+ } else if (!pte_file(entry_m)) {
23972+ free_swap_and_cache(pte_to_swp_entry(entry_m));
23973+ } else {
23974+ printk(KERN_ERR "PAX: VMMIRROR: bug in mirror_fault: %08lx, %08lx, %08lx, %08lx\n",
23975+ address, vma->vm_start, address_m, vma_m->vm_start);
23976+ }
23977+
23978+ page_m = vm_normal_page(vma, address, *pte);
23979+ entry_m = pfn_pte(pfn_m, vma_m->vm_page_prot);
23980+ if (pte_write(*pte))
23981+ entry_m = maybe_mkwrite(pte_mkdirty(entry_m), vma_m);
23982+ if (page_m) {
23983+ page_cache_get(page_m);
23984+ /*
23985+ * we can test PAGE_MAPPING_ANON without holding page_map_lock because
23986+ * we hold the page table lock and have a reference to page_m
23987+ */
23988+ if (PageAnon(page_m)) {
23989+ page_add_anon_rmap(page_m, vma_m, address_m);
23990+ inc_mm_counter(mm, anon_rss);
23991+ } else {
23992+ page_add_file_rmap(page_m);
23993+ inc_mm_counter(mm, file_rss);
23994+ }
23995+ }
23996+ set_pte_at(mm, address_m, pte_m, entry_m);
23997+ update_mmu_cache(vma_m, address_m, entry_m);
23998+ lazy_mmu_prot_update(entry_m);
23999+ pte_unmap_nested(pte_m);
24000+}
24001+#endif
24002+
24003 /*
24004 * This routine handles present pages, when users try to write
24005 * to a shared page. It is done by copying the page to a new address
24006@@ -1511,6 +1610,12 @@ gotten:
24007 /* Free the old page.. */
24008 new_page = old_page;
24009 ret |= VM_FAULT_WRITE;
24010+
24011+#ifdef CONFIG_PAX_SEGMEXEC
24012+ if (vma->vm_flags & VM_MIRROR)
24013+ pax_mirror_fault(vma, address, page_table);
24014+#endif
24015+
24016 }
24017 if (new_page)
24018 page_cache_release(new_page);
24019@@ -1761,6 +1866,7 @@ int vmtruncate(struct inode * inode, lof
24020
24021 do_expand:
24022 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
24023+ gr_learn_resource(current, RLIMIT_FSIZE, offset, 1);
24024 if (limit != RLIM_INFINITY && offset > limit)
24025 goto out_sig;
24026 if (offset > inode->i_sb->s_maxbytes)
24027@@ -1950,6 +2056,12 @@ again:
24028 /* No need to invalidate - it was non-present before */
24029 update_mmu_cache(vma, address, pte);
24030 lazy_mmu_prot_update(pte);
24031+
24032+#ifdef CONFIG_PAX_SEGMEXEC
24033+ if (vma->vm_flags & VM_MIRROR)
24034+ pax_mirror_fault(vma, address, page_table);
24035+#endif
24036+
24037 unlock:
24038 pte_unmap_unlock(page_table, ptl);
24039 out:
24040@@ -2012,6 +2124,12 @@ static int do_anonymous_page(struct mm_s
24041 /* No need to invalidate - it was non-present before */
24042 update_mmu_cache(vma, address, entry);
24043 lazy_mmu_prot_update(entry);
24044+
24045+#ifdef CONFIG_PAX_SEGMEXEC
24046+ if (vma->vm_flags & VM_MIRROR)
24047+ pax_mirror_fault(vma, address, page_table);
24048+#endif
24049+
24050 unlock:
24051 pte_unmap_unlock(page_table, ptl);
24052 return VM_FAULT_MINOR;
24053@@ -2137,6 +2255,12 @@ retry:
24054 /* no need to invalidate: a not-present page shouldn't be cached */
24055 update_mmu_cache(vma, address, entry);
24056 lazy_mmu_prot_update(entry);
24057+
24058+#ifdef CONFIG_PAX_SEGMEXEC
24059+ if (vma->vm_flags & VM_MIRROR)
24060+ pax_mirror_fault(vma, address, page_table);
24061+#endif
24062+
24063 unlock:
24064 pte_unmap_unlock(page_table, ptl);
24065 return ret;
24066@@ -2246,6 +2370,12 @@ static inline int handle_pte_fault(struc
24067 flush_tlb_page(vma, address);
24068 }
24069 unlock:
24070+
24071+#ifdef CONFIG_PAX_SEGMEXEC
24072+ if (vma->vm_flags & VM_MIRROR)
24073+ pax_mirror_fault(vma, address, pte);
24074+#endif
24075+
24076 pte_unmap_unlock(pte, ptl);
24077 return VM_FAULT_MINOR;
24078 }
24079@@ -2268,6 +2398,49 @@ int __handle_mm_fault(struct mm_struct *
24080 if (unlikely(is_vm_hugetlb_page(vma)))
24081 return hugetlb_fault(mm, vma, address, write_access);
24082
24083+#ifdef CONFIG_PAX_SEGMEXEC
24084+ if (vma->vm_flags & VM_MIRROR) {
24085+ unsigned long address_m;
24086+ struct vm_area_struct * vma_m;
24087+ pgd_t *pgd_m;
24088+ pud_t *pud_m;
24089+ pmd_t *pmd_m;
24090+
24091+ address_m = vma->vm_start + vma->vm_mirror;
24092+ vma_m = find_vma(mm, address_m);
24093+
24094+ /* PaX: sanity checks */
24095+ if (!vma_m) {
24096+ printk(KERN_ERR "PAX: VMMIRROR: fault bug, %08lx, %p, %08lx, %p\n",
24097+ address, vma, address_m, vma_m);
24098+ return VM_FAULT_SIGBUS;
24099+ } else if (!(vma_m->vm_flags & VM_MIRROR) ||
24100+ vma_m->vm_start != address_m ||
24101+ vma->vm_end - vma->vm_start != vma_m->vm_end - vma_m->vm_start)
24102+ {
24103+ printk(KERN_ERR "PAX: VMMIRROR: fault bug2, %08lx, %08lx, %08lx, %08lx, %08lx\n",
24104+ address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
24105+ return VM_FAULT_SIGBUS;
24106+ }
24107+
24108+ if (address_m < address) {
24109+ address += vma->vm_mirror;
24110+ vma = vma_m;
24111+ }
24112+
24113+ address_m = address + vma->vm_mirror;
24114+ pgd_m = pgd_offset(mm, address_m);
24115+ pud_m = pud_alloc(mm, pgd_m, address_m);
24116+ if (!pud_m)
24117+ return VM_FAULT_OOM;
24118+ pmd_m = pmd_alloc(mm, pud_m, address_m);
24119+ if (!pmd_m)
24120+ return VM_FAULT_OOM;
24121+ if (!pmd_present(*pmd_m) && __pte_alloc(mm, pmd_m, address_m))
24122+ return VM_FAULT_OOM;
24123+ }
24124+#endif
24125+
24126 pgd = pgd_offset(mm, address);
24127 pud = pud_alloc(mm, pgd, address);
24128 if (!pud)
24129diff -urNp linux-2.6.17.11/mm/mempolicy.c linux-2.6.17.11/mm/mempolicy.c
24130--- linux-2.6.17.11/mm/mempolicy.c 2006-08-07 00:18:54.000000000 -0400
24131+++ linux-2.6.17.11/mm/mempolicy.c 2006-08-12 08:17:55.000000000 -0400
24132@@ -346,6 +346,12 @@ check_range(struct mm_struct *mm, unsign
24133 if (prev && prev->vm_end < vma->vm_start)
24134 return ERR_PTR(-EFAULT);
24135 }
24136+
24137+#ifdef CONFIG_PAX_SEGMEXEC
24138+ if (vma->vm_flags & VM_MIRROR)
24139+ return ERR_PTR(-EFAULT);
24140+#endif
24141+
24142 if (!is_vm_hugetlb_page(vma) &&
24143 ((flags & MPOL_MF_STRICT) ||
24144 ((flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) &&
24145diff -urNp linux-2.6.17.11/mm/mlock.c linux-2.6.17.11/mm/mlock.c
24146--- linux-2.6.17.11/mm/mlock.c 2006-08-07 00:18:54.000000000 -0400
24147+++ linux-2.6.17.11/mm/mlock.c 2006-08-12 08:17:55.000000000 -0400
24148@@ -10,14 +10,85 @@
24149 #include <linux/mm.h>
24150 #include <linux/mempolicy.h>
24151 #include <linux/syscalls.h>
24152+#include <linux/grsecurity.h>
24153
24154+static int __mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
24155+ unsigned long start, unsigned long end, unsigned int newflags);
24156
24157 static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
24158 unsigned long start, unsigned long end, unsigned int newflags)
24159 {
24160 struct mm_struct * mm = vma->vm_mm;
24161- pgoff_t pgoff;
24162 int pages;
24163+ int ret;
24164+
24165+#ifdef CONFIG_PAX_SEGMEXEC
24166+ struct vm_area_struct * vma_m = NULL, *prev_m;
24167+ unsigned long start_m = 0UL, end_m = 0UL, newflags_m = 0UL;
24168+
24169+ if (vma->vm_flags & VM_MIRROR) {
24170+ start_m = vma->vm_start + vma->vm_mirror;
24171+ vma_m = find_vma_prev(mm, start_m, &prev_m);
24172+ if (!vma_m || vma_m->vm_start != start_m || !(vma_m->vm_flags & VM_MIRROR)) {
24173+ printk("PAX: VMMIRROR: mlock bug in %s, %08lx\n", current->comm, vma->vm_start);
24174+ return -ENOMEM;
24175+ }
24176+
24177+ start_m = start + vma->vm_mirror;
24178+ end_m = end + vma->vm_mirror;
24179+ if (newflags & VM_LOCKED)
24180+ newflags_m = vma_m->vm_flags | VM_LOCKED;
24181+ else
24182+ newflags_m = vma_m->vm_flags & ~VM_LOCKED;
24183+ ret = __mlock_fixup(vma_m, &prev_m, start_m, end_m, newflags_m);
24184+ if (ret)
24185+ return ret;
24186+ }
24187+#endif
24188+
24189+ ret = __mlock_fixup(vma, prev, start, end, newflags);
24190+ if (ret)
24191+ return ret;
24192+
24193+ /*
24194+ * vm_flags is protected by the mmap_sem held in write mode.
24195+ * It's okay if try_to_unmap_one unmaps a page just after we
24196+ * set VM_LOCKED, make_pages_present below will bring it back.
24197+ */
24198+ vma->vm_flags = newflags;
24199+
24200+#ifdef CONFIG_PAX_SEGMEXEC
24201+ if (vma->vm_flags & VM_MIRROR)
24202+ vma_m->vm_flags = newflags_m;
24203+#endif
24204+
24205+ /*
24206+ * Keep track of amount of locked VM.
24207+ */
24208+ pages = (end - start) >> PAGE_SHIFT;
24209+ if (newflags & VM_LOCKED) {
24210+ pages = -pages;
24211+ if (!(newflags & VM_IO))
24212+ ret = make_pages_present(start, end);
24213+ }
24214+
24215+ mm->locked_vm -= pages;
24216+
24217+#ifdef CONFIG_PAX_SEGMEXEC
24218+ if (vma->vm_flags & VM_MIRROR)
24219+ mm->locked_vm -= pages;
24220+#endif
24221+
24222+ if (ret == -ENOMEM)
24223+ ret = -EAGAIN;
24224+ return ret;
24225+}
24226+
24227+static int __mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
24228+ unsigned long start, unsigned long end, unsigned int newflags)
24229+{
24230+ struct mm_struct * mm = vma->vm_mm;
24231+ pgoff_t pgoff;
24232 int ret = 0;
24233
24234 if (newflags == vma->vm_flags) {
24235@@ -30,7 +101,7 @@ static int mlock_fixup(struct vm_area_st
24236 vma->vm_file, pgoff, vma_policy(vma));
24237 if (*prev) {
24238 vma = *prev;
24239- goto success;
24240+ goto out;
24241 }
24242
24243 *prev = vma;
24244@@ -41,31 +112,9 @@ static int mlock_fixup(struct vm_area_st
24245 goto out;
24246 }
24247
24248- if (end != vma->vm_end) {
24249+ if (end != vma->vm_end)
24250 ret = split_vma(mm, vma, end, 0);
24251- if (ret)
24252- goto out;
24253- }
24254
24255-success:
24256- /*
24257- * vm_flags is protected by the mmap_sem held in write mode.
24258- * It's okay if try_to_unmap_one unmaps a page just after we
24259- * set VM_LOCKED, make_pages_present below will bring it back.
24260- */
24261- vma->vm_flags = newflags;
24262-
24263- /*
24264- * Keep track of amount of locked VM.
24265- */
24266- pages = (end - start) >> PAGE_SHIFT;
24267- if (newflags & VM_LOCKED) {
24268- pages = -pages;
24269- if (!(newflags & VM_IO))
24270- ret = make_pages_present(start, end);
24271- }
24272-
24273- vma->vm_mm->locked_vm -= pages;
24274 out:
24275 if (ret == -ENOMEM)
24276 ret = -EAGAIN;
24277@@ -84,6 +133,17 @@ static int do_mlock(unsigned long start,
24278 return -EINVAL;
24279 if (end == start)
24280 return 0;
24281+
24282+#ifdef CONFIG_PAX_SEGMEXEC
24283+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
24284+ if (end > SEGMEXEC_TASK_SIZE)
24285+ return -EINVAL;
24286+ } else
24287+#endif
24288+
24289+ if (end > TASK_SIZE)
24290+ return -EINVAL;
24291+
24292 vma = find_vma_prev(current->mm, start, &prev);
24293 if (!vma || vma->vm_start > start)
24294 return -ENOMEM;
24295@@ -141,6 +201,7 @@ asmlinkage long sys_mlock(unsigned long
24296 lock_limit >>= PAGE_SHIFT;
24297
24298 /* check against resource limits */
24299+ gr_learn_resource(current, RLIMIT_MEMLOCK, (current->mm->locked_vm << PAGE_SHIFT) + len, 1);
24300 if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
24301 error = do_mlock(start, len, 1);
24302 up_write(&current->mm->mmap_sem);
24303@@ -173,6 +234,16 @@ static int do_mlockall(int flags)
24304 for (vma = current->mm->mmap; vma ; vma = prev->vm_next) {
24305 unsigned int newflags;
24306
24307+#ifdef CONFIG_PAX_SEGMEXEC
24308+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
24309+ if (vma->vm_end > SEGMEXEC_TASK_SIZE)
24310+ break;
24311+ } else
24312+#endif
24313+
24314+ if (vma->vm_end > TASK_SIZE)
24315+ break;
24316+
24317 newflags = vma->vm_flags | VM_LOCKED;
24318 if (!(flags & MCL_CURRENT))
24319 newflags &= ~VM_LOCKED;
24320@@ -202,6 +273,7 @@ asmlinkage long sys_mlockall(int flags)
24321 lock_limit >>= PAGE_SHIFT;
24322
24323 ret = -ENOMEM;
24324+ gr_learn_resource(current, RLIMIT_MEMLOCK, current->mm->total_vm, 1);
24325 if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
24326 capable(CAP_IPC_LOCK))
24327 ret = do_mlockall(flags);
24328diff -urNp linux-2.6.17.11/mm/mmap.c linux-2.6.17.11/mm/mmap.c
24329--- linux-2.6.17.11/mm/mmap.c 2006-08-23 19:30:01.000000000 -0400
24330+++ linux-2.6.17.11/mm/mmap.c 2006-08-23 19:39:16.000000000 -0400
24331@@ -25,6 +25,7 @@
24332 #include <linux/mount.h>
24333 #include <linux/mempolicy.h>
24334 #include <linux/rmap.h>
24335+#include <linux/grsecurity.h>
24336
24337 #include <asm/uaccess.h>
24338 #include <asm/cacheflush.h>
24339@@ -240,6 +241,7 @@ asmlinkage unsigned long sys_brk(unsigne
24340 * not page aligned -Ram Gupta
24341 */
24342 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
24343+ gr_learn_resource(current, RLIMIT_DATA, brk - mm->start_data, 1);
24344 if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
24345 goto out;
24346
24347@@ -628,11 +630,17 @@ again: remove_next = 1 + (end > next->
24348 * If the vma has a ->close operation then the driver probably needs to release
24349 * per-vma resources, so we don't attempt to merge those.
24350 */
24351+#ifdef CONFIG_PAX_SEGMEXEC
24352+#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP | VM_MIRROR)
24353+#else
24354 #define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
24355+#endif
24356
24357 static inline int is_mergeable_vma(struct vm_area_struct *vma,
24358 struct file *file, unsigned long vm_flags)
24359 {
24360+ if ((vma->vm_flags | vm_flags) & VM_SPECIAL)
24361+ return 0;
24362 if (vma->vm_flags != vm_flags)
24363 return 0;
24364 if (vma->vm_file != file)
24365@@ -857,14 +865,11 @@ none:
24366 void vm_stat_account(struct mm_struct *mm, unsigned long flags,
24367 struct file *file, long pages)
24368 {
24369- const unsigned long stack_flags
24370- = VM_STACK_FLAGS & (VM_GROWSUP|VM_GROWSDOWN);
24371-
24372 if (file) {
24373 mm->shared_vm += pages;
24374 if ((flags & (VM_EXEC|VM_WRITE)) == VM_EXEC)
24375 mm->exec_vm += pages;
24376- } else if (flags & stack_flags)
24377+ } else if (flags & (VM_GROWSUP|VM_GROWSDOWN))
24378 mm->stack_vm += pages;
24379 if (flags & (VM_RESERVED|VM_IO))
24380 mm->reserved_vm += pages;
24381@@ -875,10 +880,55 @@ void vm_stat_account(struct mm_struct *m
24382 * The caller must hold down_write(current->mm->mmap_sem).
24383 */
24384
24385+#ifdef CONFIG_PAX_SEGMEXEC
24386+static unsigned long __do_mmap_pgoff(struct file * file, unsigned long addr,
24387+ unsigned long len, unsigned long prot,
24388+ unsigned long flags, unsigned long pgoff);
24389+
24390 unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
24391 unsigned long len, unsigned long prot,
24392 unsigned long flags, unsigned long pgoff)
24393 {
24394+ unsigned long ret = -EINVAL;
24395+
24396+ if (flags & MAP_MIRROR)
24397+ return ret;
24398+
24399+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) &&
24400+ (len > SEGMEXEC_TASK_SIZE || (addr > SEGMEXEC_TASK_SIZE-len)))
24401+ return ret;
24402+
24403+ ret = __do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
24404+
24405+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && ret < TASK_SIZE && ((flags & MAP_TYPE) == MAP_PRIVATE)
24406+
24407+#ifdef CONFIG_PAX_MPROTECT
24408+ && (!(current->mm->pax_flags & MF_PAX_MPROTECT) || ((prot & PROT_EXEC) && file && !(prot & PROT_WRITE)))
24409+#endif
24410+
24411+ )
24412+ {
24413+ unsigned long ret_m;
24414+ prot = prot & PROT_EXEC ? prot & ~PROT_WRITE : PROT_NONE;
24415+ ret_m = __do_mmap_pgoff(NULL, ret + SEGMEXEC_TASK_SIZE, 0UL, prot, flags | MAP_MIRROR | MAP_FIXED, ret);
24416+ if (ret_m >= TASK_SIZE) {
24417+ do_munmap(current->mm, ret, len);
24418+ ret = ret_m;
24419+ }
24420+ }
24421+
24422+ return ret;
24423+}
24424+
24425+static unsigned long __do_mmap_pgoff(struct file * file, unsigned long addr,
24426+ unsigned long len, unsigned long prot,
24427+ unsigned long flags, unsigned long pgoff)
24428+#else
24429+unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
24430+ unsigned long len, unsigned long prot,
24431+ unsigned long flags, unsigned long pgoff)
24432+#endif
24433+{
24434 struct mm_struct * mm = current->mm;
24435 struct vm_area_struct * vma, * prev;
24436 struct inode *inode;
24437@@ -889,6 +939,28 @@ unsigned long do_mmap_pgoff(struct file
24438 int accountable = 1;
24439 unsigned long charged = 0, reqprot = prot;
24440
24441+#ifdef CONFIG_PAX_SEGMEXEC
24442+ struct vm_area_struct * vma_m = NULL;
24443+
24444+ if (flags & MAP_MIRROR) {
24445+ /* PaX: sanity checks, to be removed when proved to be stable */
24446+ if (file || len || ((flags & MAP_TYPE) != MAP_PRIVATE))
24447+ return -EINVAL;
24448+
24449+ vma_m = find_vma(mm, pgoff);
24450+
24451+ if (!vma_m || is_vm_hugetlb_page(vma_m) ||
24452+ vma_m->vm_start != pgoff ||
24453+ (vma_m->vm_flags & VM_SPECIAL) ||
24454+ (prot & PROT_WRITE))
24455+ return -EINVAL;
24456+
24457+ file = vma_m->vm_file;
24458+ pgoff = vma_m->vm_pgoff;
24459+ len = vma_m->vm_end - vma_m->vm_start;
24460+ }
24461+#endif
24462+
24463 if (file) {
24464 if (is_file_hugepages(file))
24465 accountable = 0;
24466@@ -906,7 +978,7 @@ unsigned long do_mmap_pgoff(struct file
24467 * (the exception is when the underlying filesystem is noexec
24468 * mounted, in which case we dont add PROT_EXEC.)
24469 */
24470- if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
24471+ if ((prot & (PROT_READ | PROT_WRITE)) && (current->personality & READ_IMPLIES_EXEC))
24472 if (!(file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)))
24473 prot |= PROT_EXEC;
24474
24475@@ -933,7 +1005,7 @@ unsigned long do_mmap_pgoff(struct file
24476 /* Obtain the address to map to. we verify (or select) it and ensure
24477 * that it represents a valid section of the address space.
24478 */
24479- addr = get_unmapped_area(file, addr, len, pgoff, flags);
24480+ addr = get_unmapped_area(file, addr, len, pgoff, flags | ((prot & PROT_EXEC) ? MAP_EXECUTABLE : 0));
24481 if (addr & ~PAGE_MASK)
24482 return addr;
24483
24484@@ -944,6 +1016,24 @@ unsigned long do_mmap_pgoff(struct file
24485 vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) |
24486 mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
24487
24488+ if (file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
24489+ vm_flags &= ~VM_MAYEXEC;
24490+
24491+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
24492+ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
24493+
24494+#ifdef CONFIG_PAX_MPROTECT
24495+ if (mm->pax_flags & MF_PAX_MPROTECT) {
24496+ if ((prot & (PROT_WRITE | PROT_EXEC)) != PROT_EXEC)
24497+ vm_flags &= ~(VM_EXEC | VM_MAYEXEC);
24498+ else
24499+ vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
24500+ }
24501+#endif
24502+
24503+ }
24504+#endif
24505+
24506 if (flags & MAP_LOCKED) {
24507 if (!can_do_mlock())
24508 return -EPERM;
24509@@ -956,6 +1046,7 @@ unsigned long do_mmap_pgoff(struct file
24510 locked += mm->locked_vm;
24511 lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
24512 lock_limit >>= PAGE_SHIFT;
24513+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
24514 if (locked > lock_limit && !capable(CAP_IPC_LOCK))
24515 return -EAGAIN;
24516 }
24517@@ -1003,6 +1094,11 @@ unsigned long do_mmap_pgoff(struct file
24518 /*
24519 * Set pgoff according to addr for anon_vma.
24520 */
24521+
24522+#ifdef CONFIG_PAX_SEGMEXEC
24523+ if (!(flags & MAP_MIRROR))
24524+#endif
24525+
24526 pgoff = addr >> PAGE_SHIFT;
24527 break;
24528 default:
24529@@ -1014,14 +1110,17 @@ unsigned long do_mmap_pgoff(struct file
24530 if (error)
24531 return error;
24532
24533+ if (!gr_acl_handle_mmap(file, prot))
24534+ return -EACCES;
24535+
24536 /* Clear old maps */
24537 error = -ENOMEM;
24538-munmap_back:
24539 vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
24540 if (vma && vma->vm_start < addr + len) {
24541 if (do_munmap(mm, addr, len))
24542 return -ENOMEM;
24543- goto munmap_back;
24544+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
24545+ BUG_ON(vma && vma->vm_start < addr + len);
24546 }
24547
24548 /* Check against address space limit. */
24549@@ -1069,7 +1168,14 @@ munmap_back:
24550 vma->vm_start = addr;
24551 vma->vm_end = addr + len;
24552 vma->vm_flags = vm_flags;
24553- vma->vm_page_prot = protection_map[vm_flags & 0x0f];
24554+
24555+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32)
24556+ if ((file || !(mm->pax_flags & MF_PAX_PAGEEXEC)) && (vm_flags & (VM_READ|VM_WRITE)))
24557+ vma->vm_page_prot = protection_map[(vm_flags | VM_EXEC) & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
24558+ else
24559+#endif
24560+
24561+ vma->vm_page_prot = protection_map[vm_flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
24562 vma->vm_pgoff = pgoff;
24563
24564 if (file) {
24565@@ -1093,6 +1199,14 @@ munmap_back:
24566 goto free_vma;
24567 }
24568
24569+#ifdef CONFIG_PAX_SEGMEXEC
24570+ if (flags & MAP_MIRROR) {
24571+ vma_m->vm_flags |= VM_MIRROR;
24572+ vma_m->vm_mirror = vma->vm_start - vma_m->vm_start;
24573+ vma->vm_mirror = vma_m->vm_start - vma->vm_start;
24574+ }
24575+#endif
24576+
24577 /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform
24578 * shmem_zero_setup (perhaps called through /dev/zero's ->mmap)
24579 * that memory reservation must be checked; but that reservation
24580@@ -1128,6 +1242,7 @@ munmap_back:
24581 out:
24582 mm->total_vm += len >> PAGE_SHIFT;
24583 vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
24584+ track_exec_limit(mm, addr, addr + len, vm_flags);
24585 if (vm_flags & VM_LOCKED) {
24586 mm->locked_vm += len >> PAGE_SHIFT;
24587 make_pages_present(addr, addr + len);
24588@@ -1182,6 +1297,10 @@ arch_get_unmapped_area(struct file *filp
24589 if (len > TASK_SIZE)
24590 return -ENOMEM;
24591
24592+#ifdef CONFIG_PAX_RANDMMAP
24593+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
24594+#endif
24595+
24596 if (addr) {
24597 addr = PAGE_ALIGN(addr);
24598 vma = find_vma(mm, addr);
24599@@ -1192,7 +1311,7 @@ arch_get_unmapped_area(struct file *filp
24600 if (len > mm->cached_hole_size) {
24601 start_addr = addr = mm->free_area_cache;
24602 } else {
24603- start_addr = addr = TASK_UNMAPPED_BASE;
24604+ start_addr = addr = mm->mmap_base;
24605 mm->cached_hole_size = 0;
24606 }
24607
24608@@ -1204,9 +1323,8 @@ full_search:
24609 * Start a new search - just in case we missed
24610 * some holes.
24611 */
24612- if (start_addr != TASK_UNMAPPED_BASE) {
24613- addr = TASK_UNMAPPED_BASE;
24614- start_addr = addr;
24615+ if (start_addr != mm->mmap_base) {
24616+ start_addr = addr = mm->mmap_base;
24617 mm->cached_hole_size = 0;
24618 goto full_search;
24619 }
24620@@ -1231,7 +1349,7 @@ void arch_unmap_area(struct mm_struct *m
24621 /*
24622 * Is this a new hole at the lowest possible address?
24623 */
24624- if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache) {
24625+ if (addr >= mm->mmap_base && addr < mm->free_area_cache) {
24626 mm->free_area_cache = addr;
24627 mm->cached_hole_size = ~0UL;
24628 }
24629@@ -1249,12 +1367,16 @@ arch_get_unmapped_area_topdown(struct fi
24630 {
24631 struct vm_area_struct *vma;
24632 struct mm_struct *mm = current->mm;
24633- unsigned long addr = addr0;
24634+ unsigned long base = mm->mmap_base, addr = addr0;
24635
24636 /* requested length too big for entire address space */
24637 if (len > TASK_SIZE)
24638 return -ENOMEM;
24639
24640+#ifdef CONFIG_PAX_RANDMMAP
24641+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
24642+#endif
24643+
24644 /* requesting a specific address */
24645 if (addr) {
24646 addr = PAGE_ALIGN(addr);
24647@@ -1312,13 +1434,21 @@ bottomup:
24648 * can happen with large stack limits and large mmap()
24649 * allocations.
24650 */
24651+ mm->mmap_base = TASK_UNMAPPED_BASE;
24652+
24653+#ifdef CONFIG_PAX_RANDMMAP
24654+ if (mm->pax_flags & MF_PAX_RANDMMAP)
24655+ mm->mmap_base += mm->delta_mmap;
24656+#endif
24657+
24658+ mm->free_area_cache = mm->mmap_base;
24659 mm->cached_hole_size = ~0UL;
24660- mm->free_area_cache = TASK_UNMAPPED_BASE;
24661 addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
24662 /*
24663 * Restore the topdown base:
24664 */
24665- mm->free_area_cache = mm->mmap_base;
24666+ mm->mmap_base = base;
24667+ mm->free_area_cache = base;
24668 mm->cached_hole_size = ~0UL;
24669
24670 return addr;
24671@@ -1334,8 +1464,10 @@ void arch_unmap_area_topdown(struct mm_s
24672 mm->free_area_cache = addr;
24673
24674 /* dont allow allocations above current base */
24675- if (mm->free_area_cache > mm->mmap_base)
24676+ if (mm->free_area_cache > mm->mmap_base) {
24677 mm->free_area_cache = mm->mmap_base;
24678+ mm->cached_hole_size = ~0UL;
24679+ }
24680 }
24681
24682 unsigned long
24683@@ -1468,6 +1600,7 @@ static int acct_stack_growth(struct vm_a
24684 return -ENOMEM;
24685
24686 /* Stack limit test */
24687+ gr_learn_resource(current, RLIMIT_STACK, size, 1);
24688 if (size > rlim[RLIMIT_STACK].rlim_cur)
24689 return -ENOMEM;
24690
24691@@ -1477,6 +1610,7 @@ static int acct_stack_growth(struct vm_a
24692 unsigned long limit;
24693 locked = mm->locked_vm + grow;
24694 limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
24695+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
24696 if (locked > limit && !capable(CAP_IPC_LOCK))
24697 return -ENOMEM;
24698 }
24699@@ -1594,13 +1728,49 @@ int expand_stack(struct vm_area_struct *
24700 if (address < vma->vm_start) {
24701 unsigned long size, grow;
24702
24703+#ifdef CONFIG_PAX_SEGMEXEC
24704+ struct vm_area_struct *vma_m = NULL;
24705+ unsigned long address_m = 0UL;
24706+
24707+ if (vma->vm_flags & VM_MIRROR) {
24708+ address_m = vma->vm_start + vma->vm_mirror;
24709+ vma_m = find_vma(vma->vm_mm, address_m);
24710+ if (!vma_m || vma_m->vm_start != address_m ||
24711+ !(vma_m->vm_flags & VM_MIRROR) ||
24712+ vma->vm_end - vma->vm_start !=
24713+ vma_m->vm_end - vma_m->vm_start ||
24714+ vma->anon_vma != vma_m->anon_vma) {
24715+ printk(KERN_ERR "PAX: VMMIRROR: expand bug, %08lx, %08lx, %08lx, %08lx, %08lx\n",
24716+ address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
24717+ anon_vma_unlock(vma);
24718+ return -EFAULT;
24719+ }
24720+ address_m = address + vma->vm_mirror;
24721+ }
24722+#endif
24723+
24724 size = vma->vm_end - address;
24725 grow = (vma->vm_start - address) >> PAGE_SHIFT;
24726
24727+#ifdef CONFIG_PAX_SEGMEXEC
24728+ if (vma_m)
24729+ error = acct_stack_growth(vma, size, 2*grow);
24730+ else
24731+#endif
24732+
24733 error = acct_stack_growth(vma, size, grow);
24734 if (!error) {
24735 vma->vm_start = address;
24736 vma->vm_pgoff -= grow;
24737+ track_exec_limit(vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_flags);
24738+
24739+#ifdef CONFIG_PAX_SEGMEXEC
24740+ if (vma_m) {
24741+ vma_m->vm_start = address_m;
24742+ vma_m->vm_pgoff -= grow;
24743+ }
24744+#endif
24745+
24746 }
24747 }
24748 anon_vma_unlock(vma);
24749@@ -1762,7 +1932,24 @@ int split_vma(struct mm_struct * mm, str
24750 * work. This now handles partial unmappings.
24751 * Jeremy Fitzhardinge <jeremy@goop.org>
24752 */
24753+#ifdef CONFIG_PAX_SEGMEXEC
24754+static int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len);
24755+
24756+int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
24757+{
24758+ if (mm->pax_flags & MF_PAX_SEGMEXEC) {
24759+ int ret = __do_munmap(mm, start + SEGMEXEC_TASK_SIZE, len);
24760+ if (ret)
24761+ return ret;
24762+ }
24763+
24764+ return __do_munmap(mm, start, len);
24765+}
24766+
24767+static int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
24768+#else
24769 int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
24770+#endif
24771 {
24772 unsigned long end;
24773 struct vm_area_struct *vma, *prev, *last;
24774@@ -1816,6 +2003,8 @@ int do_munmap(struct mm_struct *mm, unsi
24775 /* Fix up all other VM information */
24776 remove_vma_list(mm, vma);
24777
24778+ track_exec_limit(mm, start, end, 0UL);
24779+
24780 return 0;
24781 }
24782
24783@@ -1828,6 +2017,12 @@ asmlinkage long sys_munmap(unsigned long
24784
24785 profile_munmap(addr);
24786
24787+#ifdef CONFIG_PAX_SEGMEXEC
24788+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) &&
24789+ (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len))
24790+ return -EINVAL;
24791+#endif
24792+
24793 down_write(&mm->mmap_sem);
24794 ret = do_munmap(mm, addr, len);
24795 up_write(&mm->mmap_sem);
24796@@ -1849,11 +2044,35 @@ static inline void verify_mm_writelocked
24797 * anonymous maps. eventually we may be able to do some
24798 * brk-specific accounting here.
24799 */
24800+#ifdef CONFIG_PAX_SEGMEXEC
24801+static unsigned long __do_brk(unsigned long addr, unsigned long len);
24802+
24803+unsigned long do_brk(unsigned long addr, unsigned long len)
24804+{
24805+ unsigned long ret;
24806+
24807+ ret = __do_brk(addr, len);
24808+ if (ret == addr && (current->mm->pax_flags & (MF_PAX_SEGMEXEC | MF_PAX_MPROTECT)) == MF_PAX_SEGMEXEC) {
24809+ unsigned long ret_m;
24810+
24811+ ret_m = __do_mmap_pgoff(NULL, addr + SEGMEXEC_TASK_SIZE, 0UL, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_MIRROR, addr);
24812+ if (ret_m > TASK_SIZE) {
24813+ do_munmap(current->mm, addr, len);
24814+ ret = ret_m;
24815+ }
24816+ }
24817+
24818+ return ret;
24819+}
24820+
24821+static unsigned long __do_brk(unsigned long addr, unsigned long len)
24822+#else
24823 unsigned long do_brk(unsigned long addr, unsigned long len)
24824+#endif
24825 {
24826 struct mm_struct * mm = current->mm;
24827 struct vm_area_struct * vma, * prev;
24828- unsigned long flags;
24829+ unsigned long flags, task_size = TASK_SIZE;
24830 struct rb_node ** rb_link, * rb_parent;
24831 pgoff_t pgoff = addr >> PAGE_SHIFT;
24832 int error;
24833@@ -1862,11 +2081,28 @@ unsigned long do_brk(unsigned long addr,
24834 if (!len)
24835 return addr;
24836
24837- if ((addr + len) > TASK_SIZE || (addr + len) < addr)
24838+#ifdef CONFIG_PAX_SEGMEXEC
24839+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
24840+ task_size = SEGMEXEC_TASK_SIZE;
24841+#endif
24842+
24843+ if ((addr + len) > task_size || (addr + len) < addr)
24844 return -EINVAL;
24845
24846 flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
24847
24848+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
24849+ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
24850+ flags &= ~VM_EXEC;
24851+
24852+#ifdef CONFIG_PAX_MPROTECT
24853+ if (mm->pax_flags & MF_PAX_MPROTECT)
24854+ flags &= ~VM_MAYEXEC;
24855+#endif
24856+
24857+ }
24858+#endif
24859+
24860 error = arch_mmap_check(addr, len, flags);
24861 if (error)
24862 return error;
24863@@ -1880,6 +2116,7 @@ unsigned long do_brk(unsigned long addr,
24864 locked += mm->locked_vm;
24865 lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
24866 lock_limit >>= PAGE_SHIFT;
24867+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
24868 if (locked > lock_limit && !capable(CAP_IPC_LOCK))
24869 return -EAGAIN;
24870 }
24871@@ -1893,12 +2130,12 @@ unsigned long do_brk(unsigned long addr,
24872 /*
24873 * Clear old maps. this also does some error checking for us
24874 */
24875- munmap_back:
24876 vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
24877 if (vma && vma->vm_start < addr + len) {
24878 if (do_munmap(mm, addr, len))
24879 return -ENOMEM;
24880- goto munmap_back;
24881+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
24882+ BUG_ON(vma && vma->vm_start < addr + len);
24883 }
24884
24885 /* Check against address space limits *after* clearing old maps... */
24886@@ -1930,7 +2167,14 @@ unsigned long do_brk(unsigned long addr,
24887 vma->vm_end = addr + len;
24888 vma->vm_pgoff = pgoff;
24889 vma->vm_flags = flags;
24890- vma->vm_page_prot = protection_map[flags & 0x0f];
24891+
24892+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32)
24893+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC))
24894+ vma->vm_page_prot = protection_map[(flags | VM_EXEC) & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
24895+ else
24896+#endif
24897+
24898+ vma->vm_page_prot = protection_map[flags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
24899 vma_link(mm, vma, prev, rb_link, rb_parent);
24900 out:
24901 mm->total_vm += len >> PAGE_SHIFT;
24902@@ -1938,6 +2182,7 @@ out:
24903 mm->locked_vm += len >> PAGE_SHIFT;
24904 make_pages_present(addr, addr + len);
24905 }
24906+ track_exec_limit(mm, addr, addr + len, flags);
24907 return addr;
24908 }
24909
24910@@ -2070,7 +2315,7 @@ int may_expand_vm(struct mm_struct *mm,
24911 unsigned long lim;
24912
24913 lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
24914-
24915+ gr_learn_resource(current, RLIMIT_AS, (cur + npages) << PAGE_SHIFT, 1);
24916 if (cur + npages > lim)
24917 return 0;
24918 return 1;
24919diff -urNp linux-2.6.17.11/mm/mprotect.c linux-2.6.17.11/mm/mprotect.c
24920--- linux-2.6.17.11/mm/mprotect.c 2006-08-07 00:18:54.000000000 -0400
24921+++ linux-2.6.17.11/mm/mprotect.c 2006-08-12 08:17:55.000000000 -0400
24922@@ -19,11 +19,18 @@
24923 #include <linux/mempolicy.h>
24924 #include <linux/personality.h>
24925 #include <linux/syscalls.h>
24926+#include <linux/grsecurity.h>
24927+
24928+#ifdef CONFIG_PAX_MPROTECT
24929+#include <linux/elf.h>
24930+#include <linux/fs.h>
24931+#endif
24932
24933 #include <asm/uaccess.h>
24934 #include <asm/pgtable.h>
24935 #include <asm/cacheflush.h>
24936 #include <asm/tlbflush.h>
24937+#include <asm/mmu_context.h>
24938
24939 static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
24940 unsigned long addr, unsigned long end, pgprot_t newprot)
24941@@ -98,6 +105,94 @@ static void change_protection(struct vm_
24942 flush_tlb_range(vma, start, end);
24943 }
24944
24945+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
24946+/* called while holding the mmap semaphor for writing */
24947+static inline void establish_user_cs_limit(struct mm_struct *mm, unsigned long start, unsigned long end)
24948+{
24949+ struct vm_area_struct *vma = find_vma(mm, start);
24950+
24951+ for (; vma && vma->vm_start < end; vma = vma->vm_next)
24952+ change_protection(vma, vma->vm_start, vma->vm_end, vma->vm_page_prot);
24953+
24954+}
24955+
24956+void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot)
24957+{
24958+ unsigned long oldlimit, newlimit = 0UL;
24959+
24960+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC))
24961+ return;
24962+
24963+ spin_lock(&mm->page_table_lock);
24964+ oldlimit = mm->context.user_cs_limit;
24965+ if ((prot & VM_EXEC) && oldlimit < end)
24966+ /* USER_CS limit moved up */
24967+ newlimit = end;
24968+ else if (!(prot & VM_EXEC) && start < oldlimit && oldlimit <= end)
24969+ /* USER_CS limit moved down */
24970+ newlimit = start;
24971+
24972+ if (newlimit) {
24973+ mm->context.user_cs_limit = newlimit;
24974+
24975+#ifdef CONFIG_SMP
24976+ wmb();
24977+ cpus_clear(mm->context.cpu_user_cs_mask);
24978+ cpu_set(smp_processor_id(), mm->context.cpu_user_cs_mask);
24979+#endif
24980+
24981+ set_user_cs(mm, smp_processor_id());
24982+ }
24983+ spin_unlock(&mm->page_table_lock);
24984+ if (newlimit == end)
24985+ establish_user_cs_limit(mm, oldlimit, end);
24986+}
24987+#endif
24988+
24989+#ifdef CONFIG_PAX_SEGMEXEC
24990+static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
24991+ unsigned long start, unsigned long end, unsigned int newflags);
24992+
24993+static int mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
24994+ unsigned long start, unsigned long end, unsigned int newflags)
24995+{
24996+ if (vma->vm_flags & VM_MIRROR) {
24997+ struct vm_area_struct * vma_m, * prev_m;
24998+ unsigned long start_m, end_m;
24999+ int error;
25000+
25001+ start_m = vma->vm_start + vma->vm_mirror;
25002+ vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m);
25003+ if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
25004+ start_m = start + vma->vm_mirror;
25005+ end_m = end + vma->vm_mirror;
25006+
25007+ if (vma_m->vm_start >= SEGMEXEC_TASK_SIZE && !(newflags & VM_EXEC))
25008+ error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, vma_m->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC));
25009+ else
25010+ error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, newflags);
25011+ if (error)
25012+ return error;
25013+ } else {
25014+ printk("PAX: VMMIRROR: mprotect bug in %s, %08lx\n", current->comm, vma->vm_start);
25015+ return -ENOMEM;
25016+ }
25017+ }
25018+
25019+ return __mprotect_fixup(vma, pprev, start, end, newflags);
25020+}
25021+
25022+static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
25023+ unsigned long start, unsigned long end, unsigned int newflags)
25024+{
25025+ struct mm_struct * mm = vma->vm_mm;
25026+ unsigned long oldflags = vma->vm_flags;
25027+ long nrpages = (end - start) >> PAGE_SHIFT;
25028+ unsigned long charged = 0;
25029+ pgprot_t newprot;
25030+ pgoff_t pgoff;
25031+ int error;
25032+#else
25033 static int
25034 mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
25035 unsigned long start, unsigned long end, unsigned long newflags)
25036@@ -114,6 +209,7 @@ mprotect_fixup(struct vm_area_struct *vm
25037 *pprev = vma;
25038 return 0;
25039 }
25040+#endif
25041
25042 /*
25043 * If we make a private mapping writable we increase our commit;
25044@@ -132,7 +228,13 @@ mprotect_fixup(struct vm_area_struct *vm
25045 }
25046 }
25047
25048- newprot = protection_map[newflags & 0xf];
25049+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_X86_32)
25050+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) && (newflags & (VM_READ|VM_WRITE)))
25051+ newprot = protection_map[(newflags | VM_EXEC) & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
25052+ else
25053+#endif
25054+
25055+ newprot = protection_map[newflags & (VM_READ|VM_WRITE|VM_EXEC|VM_SHARED)];
25056
25057 /*
25058 * First try to merge with previous and/or next vma.
25059@@ -179,6 +281,69 @@ fail:
25060 return error;
25061 }
25062
25063+#ifdef CONFIG_PAX_MPROTECT
25064+/* PaX: non-PIC ELF libraries need relocations on their executable segments
25065+ * therefore we'll grant them VM_MAYWRITE once during their life.
25066+ *
25067+ * The checks favour ld-linux.so behaviour which operates on a per ELF segment
25068+ * basis because we want to allow the common case and not the special ones.
25069+ */
25070+static inline void pax_handle_maywrite(struct vm_area_struct * vma, unsigned long start)
25071+{
25072+ struct elfhdr elf_h;
25073+ struct elf_phdr elf_p, p_dyn;
25074+ elf_dyn dyn;
25075+ unsigned long i, j = 65536UL / sizeof(struct elf_phdr);
25076+
25077+#ifndef CONFIG_PAX_NOELFRELOCS
25078+ if ((vma->vm_start != start) ||
25079+ !vma->vm_file ||
25080+ !(vma->vm_flags & VM_MAYEXEC) ||
25081+ (vma->vm_flags & VM_MAYNOTWRITE))
25082+#endif
25083+
25084+ return;
25085+
25086+ if (sizeof(elf_h) != kernel_read(vma->vm_file, 0UL, (char*)&elf_h, sizeof(elf_h)) ||
25087+ memcmp(elf_h.e_ident, ELFMAG, SELFMAG) ||
25088+
25089+#ifdef CONFIG_PAX_ETEXECRELOCS
25090+ (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC) ||
25091+#else
25092+ elf_h.e_type != ET_DYN ||
25093+#endif
25094+
25095+ !elf_check_arch(&elf_h) ||
25096+ elf_h.e_phentsize != sizeof(struct elf_phdr) ||
25097+ elf_h.e_phnum > j)
25098+ return;
25099+
25100+ for (i = 0UL; i < elf_h.e_phnum; i++) {
25101+ if (sizeof(elf_p) != kernel_read(vma->vm_file, elf_h.e_phoff + i*sizeof(elf_p), (char*)&elf_p, sizeof(elf_p)))
25102+ return;
25103+ if (elf_p.p_type == PT_DYNAMIC) {
25104+ p_dyn = elf_p;
25105+ j = i;
25106+ }
25107+ }
25108+ if (elf_h.e_phnum <= j)
25109+ return;
25110+
25111+ i = 0UL;
25112+ do {
25113+ if (sizeof(dyn) != kernel_read(vma->vm_file, p_dyn.p_offset + i*sizeof(dyn), (char*)&dyn, sizeof(dyn)))
25114+ return;
25115+ if (dyn.d_tag == DT_TEXTREL || (dyn.d_tag == DT_FLAGS && (dyn.d_un.d_val & DF_TEXTREL))) {
25116+ vma->vm_flags |= VM_MAYWRITE | VM_MAYNOTWRITE;
25117+ gr_log_textrel(vma);
25118+ return;
25119+ }
25120+ i++;
25121+ } while (dyn.d_tag != DT_NULL);
25122+ return;
25123+}
25124+#endif
25125+
25126 asmlinkage long
25127 sys_mprotect(unsigned long start, size_t len, unsigned long prot)
25128 {
25129@@ -198,6 +363,17 @@ sys_mprotect(unsigned long start, size_t
25130 end = start + len;
25131 if (end <= start)
25132 return -ENOMEM;
25133+
25134+#ifdef CONFIG_PAX_SEGMEXEC
25135+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
25136+ if (end > SEGMEXEC_TASK_SIZE)
25137+ return -EINVAL;
25138+ } else
25139+#endif
25140+
25141+ if (end > TASK_SIZE)
25142+ return -EINVAL;
25143+
25144 if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM))
25145 return -EINVAL;
25146
25147@@ -205,7 +381,7 @@ sys_mprotect(unsigned long start, size_t
25148 /*
25149 * Does the application expect PROT_READ to imply PROT_EXEC:
25150 */
25151- if (unlikely((prot & PROT_READ) &&
25152+ if (unlikely((prot & (PROT_READ | PROT_WRITE)) &&
25153 (current->personality & READ_IMPLIES_EXEC)))
25154 prot |= PROT_EXEC;
25155
25156@@ -238,6 +414,16 @@ sys_mprotect(unsigned long start, size_t
25157 if (start > vma->vm_start)
25158 prev = vma;
25159
25160+#ifdef CONFIG_PAX_MPROTECT
25161+ if ((vma->vm_mm->pax_flags & MF_PAX_MPROTECT) && (prot & PROT_WRITE))
25162+ pax_handle_maywrite(vma, start);
25163+#endif
25164+
25165+ if (!gr_acl_handle_mprotect(vma->vm_file, prot)) {
25166+ error = -EACCES;
25167+ goto out;
25168+ }
25169+
25170 for (nstart = start ; ; ) {
25171 unsigned long newflags;
25172
25173@@ -251,6 +437,12 @@ sys_mprotect(unsigned long start, size_t
25174 goto out;
25175 }
25176
25177+#ifdef CONFIG_PAX_MPROTECT
25178+ /* PaX: disallow write access after relocs are done, hopefully noone else needs it... */
25179+ if ((vma->vm_mm->pax_flags & MF_PAX_MPROTECT) && !(prot & PROT_WRITE) && (vma->vm_flags & VM_MAYNOTWRITE))
25180+ newflags &= ~VM_MAYWRITE;
25181+#endif
25182+
25183 error = security_file_mprotect(vma, reqprot, prot);
25184 if (error)
25185 goto out;
25186@@ -274,6 +466,9 @@ sys_mprotect(unsigned long start, size_t
25187 goto out;
25188 }
25189 }
25190+
25191+ track_exec_limit(current->mm, start, end, vm_flags);
25192+
25193 out:
25194 up_write(&current->mm->mmap_sem);
25195 return error;
25196diff -urNp linux-2.6.17.11/mm/mremap.c linux-2.6.17.11/mm/mremap.c
25197--- linux-2.6.17.11/mm/mremap.c 2006-08-07 00:18:54.000000000 -0400
25198+++ linux-2.6.17.11/mm/mremap.c 2006-08-12 08:17:55.000000000 -0400
25199@@ -106,6 +106,12 @@ static void move_ptes(struct vm_area_str
25200 pte = ptep_clear_flush(vma, old_addr, old_pte);
25201 /* ZERO_PAGE can be dependant on virtual addr */
25202 pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr);
25203+
25204+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
25205+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && !(vma->vm_flags & VM_EXEC))
25206+ pte_exprotect(pte);
25207+#endif
25208+
25209 set_pte_at(mm, new_addr, new_pte, pte);
25210 }
25211
25212@@ -253,6 +259,7 @@ unsigned long do_mremap(unsigned long ad
25213 struct vm_area_struct *vma;
25214 unsigned long ret = -EINVAL;
25215 unsigned long charged = 0;
25216+ unsigned long task_size = TASK_SIZE;
25217
25218 if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
25219 goto out;
25220@@ -271,6 +278,15 @@ unsigned long do_mremap(unsigned long ad
25221 if (!new_len)
25222 goto out;
25223
25224+#ifdef CONFIG_PAX_SEGMEXEC
25225+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
25226+ task_size = SEGMEXEC_TASK_SIZE;
25227+#endif
25228+
25229+ if (new_len > task_size || addr > task_size-new_len ||
25230+ old_len > task_size || addr > task_size-old_len)
25231+ goto out;
25232+
25233 /* new_addr is only valid if MREMAP_FIXED is specified */
25234 if (flags & MREMAP_FIXED) {
25235 if (new_addr & ~PAGE_MASK)
25236@@ -278,16 +294,13 @@ unsigned long do_mremap(unsigned long ad
25237 if (!(flags & MREMAP_MAYMOVE))
25238 goto out;
25239
25240- if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
25241+ if (new_addr > task_size - new_len)
25242 goto out;
25243
25244 /* Check if the location we're moving into overlaps the
25245 * old location at all, and fail if it does.
25246 */
25247- if ((new_addr <= addr) && (new_addr+new_len) > addr)
25248- goto out;
25249-
25250- if ((addr <= new_addr) && (addr+old_len) > new_addr)
25251+ if (addr + old_len > new_addr && new_addr + new_len > addr)
25252 goto out;
25253
25254 ret = do_munmap(mm, new_addr, new_len);
25255@@ -321,6 +334,14 @@ unsigned long do_mremap(unsigned long ad
25256 ret = -EINVAL;
25257 goto out;
25258 }
25259+
25260+#ifdef CONFIG_PAX_SEGMEXEC
25261+ if (vma->vm_flags & VM_MIRROR) {
25262+ ret = -EINVAL;
25263+ goto out;
25264+ }
25265+#endif
25266+
25267 /* We can't remap across vm area boundaries */
25268 if (old_len > vma->vm_end - addr)
25269 goto out;
25270@@ -354,7 +375,7 @@ unsigned long do_mremap(unsigned long ad
25271 if (old_len == vma->vm_end - addr &&
25272 !((flags & MREMAP_FIXED) && (addr != new_addr)) &&
25273 (old_len != new_len || !(flags & MREMAP_MAYMOVE))) {
25274- unsigned long max_addr = TASK_SIZE;
25275+ unsigned long max_addr = task_size;
25276 if (vma->vm_next)
25277 max_addr = vma->vm_next->vm_start;
25278 /* can we just expand the current mapping? */
25279@@ -372,6 +393,7 @@ unsigned long do_mremap(unsigned long ad
25280 addr + new_len);
25281 }
25282 ret = addr;
25283+ track_exec_limit(vma->vm_mm, vma->vm_start, addr + new_len, vma->vm_flags);
25284 goto out;
25285 }
25286 }
25287@@ -382,8 +404,8 @@ unsigned long do_mremap(unsigned long ad
25288 */
25289 ret = -ENOMEM;
25290 if (flags & MREMAP_MAYMOVE) {
25291+ unsigned long map_flags = 0;
25292 if (!(flags & MREMAP_FIXED)) {
25293- unsigned long map_flags = 0;
25294 if (vma->vm_flags & VM_MAYSHARE)
25295 map_flags |= MAP_SHARED;
25296
25297@@ -393,7 +415,12 @@ unsigned long do_mremap(unsigned long ad
25298 if (new_addr & ~PAGE_MASK)
25299 goto out;
25300 }
25301+ map_flags = vma->vm_flags;
25302 ret = move_vma(vma, addr, old_len, new_len, new_addr);
25303+ if (!(ret & ~PAGE_MASK)) {
25304+ track_exec_limit(current->mm, addr, addr + old_len, 0UL);
25305+ track_exec_limit(current->mm, new_addr, new_addr + new_len, map_flags);
25306+ }
25307 }
25308 out:
25309 if (ret & ~PAGE_MASK)
25310diff -urNp linux-2.6.17.11/mm/page_alloc.c linux-2.6.17.11/mm/page_alloc.c
25311--- linux-2.6.17.11/mm/page_alloc.c 2006-08-07 00:18:54.000000000 -0400
25312+++ linux-2.6.17.11/mm/page_alloc.c 2006-08-12 08:17:55.000000000 -0400
25313@@ -334,7 +334,7 @@ static inline int page_is_buddy(struct p
25314 static inline void __free_one_page(struct page *page,
25315 struct zone *zone, unsigned int order)
25316 {
25317- unsigned long page_idx;
25318+ unsigned long page_idx, index;
25319 int order_size = 1 << order;
25320
25321 if (unlikely(PageCompound(page)))
25322@@ -345,6 +345,11 @@ static inline void __free_one_page(struc
25323 BUG_ON(page_idx & (order_size - 1));
25324 BUG_ON(bad_range(zone, page));
25325
25326+#ifdef CONFIG_PAX_MEMORY_SANITIZE
25327+ for (index = order_size; index; --index)
25328+ clear_highpage(page + index - 1);
25329+#endif
25330+
25331 zone->free_pages += order_size;
25332 while (order < MAX_ORDER-1) {
25333 unsigned long combined_idx;
25334diff -urNp linux-2.6.17.11/mm/rmap.c linux-2.6.17.11/mm/rmap.c
25335--- linux-2.6.17.11/mm/rmap.c 2006-08-07 00:18:54.000000000 -0400
25336+++ linux-2.6.17.11/mm/rmap.c 2006-08-12 08:17:55.000000000 -0400
25337@@ -106,6 +106,19 @@ int anon_vma_prepare(struct vm_area_stru
25338 list_add(&vma->anon_vma_node, &anon_vma->head);
25339 allocated = NULL;
25340 }
25341+
25342+#ifdef CONFIG_PAX_SEGMEXEC
25343+ if (vma->vm_flags & VM_MIRROR) {
25344+ struct vm_area_struct *vma_m;
25345+
25346+ vma_m = find_vma(vma->vm_mm, vma->vm_start + vma->vm_mirror);
25347+ BUG_ON(!vma_m || vma_m->vm_start != vma->vm_start + vma->vm_mirror);
25348+ BUG_ON(vma_m->anon_vma || vma->vm_pgoff != vma_m->vm_pgoff);
25349+ vma_m->anon_vma = anon_vma;
25350+ __anon_vma_link(vma_m);
25351+ }
25352+#endif
25353+
25354 spin_unlock(&mm->page_table_lock);
25355
25356 if (locked)
25357diff -urNp linux-2.6.17.11/mm/shmem.c linux-2.6.17.11/mm/shmem.c
25358--- linux-2.6.17.11/mm/shmem.c 2006-08-07 00:18:54.000000000 -0400
25359+++ linux-2.6.17.11/mm/shmem.c 2006-08-12 08:17:55.000000000 -0400
25360@@ -2245,7 +2245,7 @@ static struct file_system_type tmpfs_fs_
25361 .get_sb = shmem_get_sb,
25362 .kill_sb = kill_litter_super,
25363 };
25364-static struct vfsmount *shm_mnt;
25365+struct vfsmount *shm_mnt;
25366
25367 static int __init init_tmpfs(void)
25368 {
25369diff -urNp linux-2.6.17.11/mm/slab.c linux-2.6.17.11/mm/slab.c
25370--- linux-2.6.17.11/mm/slab.c 2006-08-07 00:18:54.000000000 -0400
25371+++ linux-2.6.17.11/mm/slab.c 2006-08-12 08:17:55.000000000 -0400
25372@@ -1532,6 +1532,11 @@ static void store_stackinfo(struct kmem_
25373
25374 while (!kstack_end(sptr)) {
25375 svalue = *sptr++;
25376+
25377+#ifdef CONFIG_PAX_KERNEXEC
25378+ svalue += __KERNEL_TEXT_OFFSET;
25379+#endif
25380+
25381 if (kernel_text_address(svalue)) {
25382 *addr++ = svalue;
25383 size -= sizeof(unsigned long);
25384diff -urNp linux-2.6.17.11/mm/tiny-shmem.c linux-2.6.17.11/mm/tiny-shmem.c
25385--- linux-2.6.17.11/mm/tiny-shmem.c 2006-08-07 00:18:54.000000000 -0400
25386+++ linux-2.6.17.11/mm/tiny-shmem.c 2006-08-12 08:17:55.000000000 -0400
25387@@ -27,7 +27,7 @@ static struct file_system_type tmpfs_fs_
25388 .kill_sb = kill_litter_super,
25389 };
25390
25391-static struct vfsmount *shm_mnt;
25392+struct vfsmount *shm_mnt;
25393
25394 static int __init init_tmpfs(void)
25395 {
25396diff -urNp linux-2.6.17.11/mm/vmalloc.c linux-2.6.17.11/mm/vmalloc.c
25397--- linux-2.6.17.11/mm/vmalloc.c 2006-08-07 00:18:54.000000000 -0400
25398+++ linux-2.6.17.11/mm/vmalloc.c 2006-08-12 08:17:55.000000000 -0400
25399@@ -193,6 +193,8 @@ struct vm_struct *__get_vm_area_node(uns
25400
25401 write_lock(&vmlist_lock);
25402 for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
25403+ if (addr > end - size)
25404+ goto out;
25405 if ((unsigned long)tmp->addr < addr) {
25406 if((unsigned long)tmp->addr + tmp->size >= addr)
25407 addr = ALIGN(tmp->size +
25408@@ -204,8 +206,6 @@ struct vm_struct *__get_vm_area_node(uns
25409 if (size + addr <= (unsigned long)tmp->addr)
25410 goto found;
25411 addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);
25412- if (addr > end - size)
25413- goto out;
25414 }
25415
25416 found:
25417diff -urNp linux-2.6.17.11/net/ipv4/inet_connection_sock.c linux-2.6.17.11/net/ipv4/inet_connection_sock.c
25418--- linux-2.6.17.11/net/ipv4/inet_connection_sock.c 2006-08-07 00:18:54.000000000 -0400
25419+++ linux-2.6.17.11/net/ipv4/inet_connection_sock.c 2006-08-12 08:17:55.000000000 -0400
25420@@ -16,6 +16,7 @@
25421 #include <linux/config.h>
25422 #include <linux/module.h>
25423 #include <linux/jhash.h>
25424+#include <linux/grsecurity.h>
25425
25426 #include <net/inet_connection_sock.h>
25427 #include <net/inet_hashtables.h>
25428diff -urNp linux-2.6.17.11/net/ipv4/inet_hashtables.c linux-2.6.17.11/net/ipv4/inet_hashtables.c
25429--- linux-2.6.17.11/net/ipv4/inet_hashtables.c 2006-08-07 00:18:54.000000000 -0400
25430+++ linux-2.6.17.11/net/ipv4/inet_hashtables.c 2006-08-12 08:17:55.000000000 -0400
25431@@ -19,11 +19,14 @@
25432 #include <linux/sched.h>
25433 #include <linux/slab.h>
25434 #include <linux/wait.h>
25435+#include <linux/grsecurity.h>
25436
25437 #include <net/inet_connection_sock.h>
25438 #include <net/inet_hashtables.h>
25439 #include <net/ip.h>
25440
25441+extern void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet);
25442+
25443 /*
25444 * Allocate and initialize a new local port bind bucket.
25445 * The bindhash mutex for snum's hash chain must be held here.
25446@@ -310,6 +313,8 @@ ok:
25447 }
25448 spin_unlock(&head->lock);
25449
25450+ gr_update_task_in_ip_table(current, inet_sk(sk));
25451+
25452 if (tw) {
25453 inet_twsk_deschedule(tw, death_row);
25454 inet_twsk_put(tw);
25455diff -urNp linux-2.6.17.11/net/ipv4/netfilter/ipt_stealth.c linux-2.6.17.11/net/ipv4/netfilter/ipt_stealth.c
25456--- linux-2.6.17.11/net/ipv4/netfilter/ipt_stealth.c 1969-12-31 19:00:00.000000000 -0500
25457+++ linux-2.6.17.11/net/ipv4/netfilter/ipt_stealth.c 2006-08-23 21:37:53.000000000 -0400
25458@@ -0,0 +1,116 @@
25459+/* Kernel module to add stealth support.
25460+ *
25461+ * Copyright (C) 2002,2005 Brad Spengler <spender@grsecurity.net>
25462+ *
25463+ */
25464+
25465+#include <linux/kernel.h>
25466+#include <linux/module.h>
25467+#include <linux/skbuff.h>
25468+#include <linux/net.h>
25469+#include <linux/sched.h>
25470+#include <linux/inet.h>
25471+#include <linux/stddef.h>
25472+
25473+#include <net/ip.h>
25474+#include <net/sock.h>
25475+#include <net/tcp.h>
25476+#include <net/udp.h>
25477+#include <net/route.h>
25478+#include <net/inet_common.h>
25479+
25480+#include <linux/netfilter_ipv4/ip_tables.h>
25481+
25482+MODULE_LICENSE("GPL");
25483+
25484+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
25485+
25486+static int
25487+match(const struct sk_buff *skb,
25488+ const struct net_device *in,
25489+ const struct net_device *out,
25490+ const struct xt_match *match,
25491+ const void *matchinfo,
25492+ int offset,
25493+ unsigned int protoff,
25494+ int *hotdrop)
25495+{
25496+ struct iphdr *ip = skb->nh.iph;
25497+ struct tcphdr th;
25498+ struct udphdr uh;
25499+ struct sock *sk = NULL;
25500+
25501+ if (!ip || offset) return 0;
25502+
25503+ switch(ip->protocol) {
25504+ case IPPROTO_TCP:
25505+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &th, sizeof(th)) < 0) {
25506+ *hotdrop = 1;
25507+ return 0;
25508+ }
25509+ if (!(th.syn && !th.ack)) return 0;
25510+ sk = inet_lookup_listener(&tcp_hashinfo, ip->daddr, ntohs(th.dest), ((struct rtable*)skb->dst)->rt_iif);
25511+ break;
25512+ case IPPROTO_UDP:
25513+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &uh, sizeof(uh)) < 0) {
25514+ *hotdrop = 1;
25515+ return 0;
25516+ }
25517+ sk = udp_v4_lookup(ip->saddr, uh.source, ip->daddr, uh.dest, skb->dev->ifindex);
25518+ break;
25519+ default:
25520+ return 0;
25521+ }
25522+
25523+ if(!sk) // port is being listened on, match this
25524+ return 1;
25525+ else {
25526+ sock_put(sk);
25527+ return 0;
25528+ }
25529+}
25530+
25531+/* Called when user tries to insert an entry of this type. */
25532+static int
25533+checkentry(const char *tablename,
25534+ const void *nip,
25535+ const struct xt_match *match,
25536+ void *matchinfo,
25537+ unsigned int matchsize,
25538+ unsigned int hook_mask)
25539+{
25540+ const struct ipt_ip *ip = (const struct ipt_ip *)nip;
25541+ if (matchsize != IPT_ALIGN(0))
25542+ return 0;
25543+
25544+ if(((ip->proto == IPPROTO_TCP && !(ip->invflags & IPT_INV_PROTO)) ||
25545+ ((ip->proto == IPPROTO_UDP) && !(ip->invflags & IPT_INV_PROTO)))
25546+ && (hook_mask & (1 << NF_IP_LOCAL_IN)))
25547+ return 1;
25548+
25549+ printk("stealth: Only works on TCP and UDP for the INPUT chain.\n");
25550+
25551+ return 0;
25552+}
25553+
25554+
25555+static struct ipt_match stealth_match = {
25556+ .name = "stealth",
25557+ .match = match,
25558+ .checkentry = checkentry,
25559+ .destroy = NULL,
25560+ .me = THIS_MODULE
25561+};
25562+
25563+static int __init init(void)
25564+{
25565+ return ipt_register_match(&stealth_match);
25566+}
25567+
25568+static void __exit fini(void)
25569+{
25570+ ipt_unregister_match(&stealth_match);
25571+}
25572+
25573+module_init(init);
25574+module_exit(fini);
25575diff -urNp linux-2.6.17.11/net/ipv4/netfilter/Kconfig linux-2.6.17.11/net/ipv4/netfilter/Kconfig
25576--- linux-2.6.17.11/net/ipv4/netfilter/Kconfig 2006-08-07 00:18:54.000000000 -0400
25577+++ linux-2.6.17.11/net/ipv4/netfilter/Kconfig 2006-08-12 08:17:55.000000000 -0400
25578@@ -314,6 +314,21 @@ config IP_NF_MATCH_HASHLIMIT
25579 destination IP' or `500pps from any given source IP' with a single
25580 IPtables rule.
25581
25582+config IP_NF_MATCH_STEALTH
25583+ tristate "stealth match support"
25584+ depends on IP_NF_IPTABLES
25585+ help
25586+ Enabling this option will drop all syn packets coming to unserved tcp
25587+ ports as well as all packets coming to unserved udp ports. If you
25588+ are using your system to route any type of packets (ie. via NAT)
25589+ you should put this module at the end of your ruleset, since it will
25590+ drop packets that aren't going to ports that are listening on your
25591+ machine itself, it doesn't take into account that the packet might be
25592+ destined for someone on your internal network if you're using NAT for
25593+ instance.
25594+
25595+ To compile it as a module, choose M here. If unsure, say N.
25596+
25597 # `filter', generic and specific targets
25598 config IP_NF_FILTER
25599 tristate "Packet filtering"
25600@@ -614,4 +629,3 @@ config IP_NF_ARP_MANGLE
25601 hardware and network addresses.
25602
25603 endmenu
25604-
25605diff -urNp linux-2.6.17.11/net/ipv4/netfilter/Makefile linux-2.6.17.11/net/ipv4/netfilter/Makefile
25606--- linux-2.6.17.11/net/ipv4/netfilter/Makefile 2006-08-07 00:18:54.000000000 -0400
25607+++ linux-2.6.17.11/net/ipv4/netfilter/Makefile 2006-08-12 08:17:55.000000000 -0400
25608@@ -61,6 +61,7 @@ obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_ds
25609 obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
25610 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
25611 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
25612+obj-$(CONFIG_IP_NF_MATCH_STEALTH) += ipt_stealth.o
25613
25614 # targets
25615 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
25616diff -urNp linux-2.6.17.11/net/ipv4/tcp_ipv4.c linux-2.6.17.11/net/ipv4/tcp_ipv4.c
25617--- linux-2.6.17.11/net/ipv4/tcp_ipv4.c 2006-08-07 00:18:54.000000000 -0400
25618+++ linux-2.6.17.11/net/ipv4/tcp_ipv4.c 2006-08-12 08:17:55.000000000 -0400
25619@@ -62,6 +62,7 @@
25620 #include <linux/jhash.h>
25621 #include <linux/init.h>
25622 #include <linux/times.h>
25623+#include <linux/grsecurity.h>
25624
25625 #include <net/icmp.h>
25626 #include <net/inet_hashtables.h>
25627diff -urNp linux-2.6.17.11/net/ipv4/udp.c linux-2.6.17.11/net/ipv4/udp.c
25628--- linux-2.6.17.11/net/ipv4/udp.c 2006-08-07 00:18:54.000000000 -0400
25629+++ linux-2.6.17.11/net/ipv4/udp.c 2006-08-12 08:17:55.000000000 -0400
25630@@ -102,6 +102,7 @@
25631 #include <linux/skbuff.h>
25632 #include <linux/proc_fs.h>
25633 #include <linux/seq_file.h>
25634+#include <linux/grsecurity.h>
25635 #include <net/sock.h>
25636 #include <net/udp.h>
25637 #include <net/icmp.h>
25638@@ -110,6 +111,12 @@
25639 #include <net/checksum.h>
25640 #include <net/xfrm.h>
25641
25642+extern int gr_search_udp_recvmsg(const struct sock *sk,
25643+ const struct sk_buff *skb);
25644+extern int gr_search_udp_sendmsg(const struct sock *sk,
25645+ const struct sockaddr_in *addr);
25646+
25647+
25648 /*
25649 * Snmp MIB for the UDP layer
25650 */
25651@@ -266,8 +273,7 @@ static struct sock *udp_v4_lookup_longwa
25652 return result;
25653 }
25654
25655-static __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport,
25656- u32 daddr, u16 dport, int dif)
25657+struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
25658 {
25659 struct sock *sk;
25660
25661@@ -542,9 +548,16 @@ int udp_sendmsg(struct kiocb *iocb, stru
25662 dport = usin->sin_port;
25663 if (dport == 0)
25664 return -EINVAL;
25665+
25666+ if (!gr_search_udp_sendmsg(sk, usin))
25667+ return -EPERM;
25668 } else {
25669 if (sk->sk_state != TCP_ESTABLISHED)
25670 return -EDESTADDRREQ;
25671+
25672+ if (!gr_search_udp_sendmsg(sk, NULL))
25673+ return -EPERM;
25674+
25675 daddr = inet->daddr;
25676 dport = inet->dport;
25677 /* Open fast path for connected socket.
25678@@ -798,6 +811,11 @@ try_again:
25679 if (!skb)
25680 goto out;
25681
25682+ if (!gr_search_udp_recvmsg(sk, skb)) {
25683+ err = -EPERM;
25684+ goto out_free;
25685+ }
25686+
25687 copied = skb->len - sizeof(struct udphdr);
25688 if (copied > len) {
25689 copied = len;
25690diff -urNp linux-2.6.17.11/net/socket.c linux-2.6.17.11/net/socket.c
25691--- linux-2.6.17.11/net/socket.c 2006-08-07 00:18:54.000000000 -0400
25692+++ linux-2.6.17.11/net/socket.c 2006-08-12 08:17:55.000000000 -0400
25693@@ -86,6 +86,7 @@
25694 #include <linux/kmod.h>
25695 #include <linux/audit.h>
25696 #include <linux/wireless.h>
25697+#include <linux/in.h>
25698
25699 #include <asm/uaccess.h>
25700 #include <asm/unistd.h>
25701@@ -95,6 +96,21 @@
25702 #include <net/sock.h>
25703 #include <linux/netfilter.h>
25704
25705+extern void gr_attach_curr_ip(const struct sock *sk);
25706+extern int gr_handle_sock_all(const int family, const int type,
25707+ const int protocol);
25708+extern int gr_handle_sock_server(const struct sockaddr *sck);
25709+extern int gr_handle_sock_server_other(const struct socket *sck);
25710+extern int gr_handle_sock_client(const struct sockaddr *sck);
25711+extern int gr_search_connect(const struct socket * sock,
25712+ const struct sockaddr_in * addr);
25713+extern int gr_search_bind(const struct socket * sock,
25714+ const struct sockaddr_in * addr);
25715+extern int gr_search_listen(const struct socket * sock);
25716+extern int gr_search_accept(const struct socket * sock);
25717+extern int gr_search_socket(const int domain, const int type,
25718+ const int protocol);
25719+
25720 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
25721 static ssize_t sock_aio_read(struct kiocb *iocb, char __user *buf,
25722 size_t size, loff_t pos);
25723@@ -341,7 +357,7 @@ static struct super_block *sockfs_get_sb
25724 return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC);
25725 }
25726
25727-static struct vfsmount *sock_mnt __read_mostly;
25728+struct vfsmount *sock_mnt __read_mostly;
25729
25730 static struct file_system_type sock_fs_type = {
25731 .name = "sockfs",
25732@@ -1240,6 +1256,16 @@ asmlinkage long sys_socket(int family, i
25733 int retval;
25734 struct socket *sock;
25735
25736+ if(!gr_search_socket(family, type, protocol)) {
25737+ retval = -EACCES;
25738+ goto out;
25739+ }
25740+
25741+ if (gr_handle_sock_all(family, type, protocol)) {
25742+ retval = -EACCES;
25743+ goto out;
25744+ }
25745+
25746 retval = sock_create(family, type, protocol, &sock);
25747 if (retval < 0)
25748 goto out;
25749@@ -1335,16 +1361,25 @@ asmlinkage long sys_bind(int fd, struct
25750 {
25751 struct socket *sock;
25752 char address[MAX_SOCK_ADDR];
25753+ struct sockaddr *sck;
25754 int err, fput_needed;
25755
25756 if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
25757 {
25758 if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
25759+ sck = (struct sockaddr *)address;
25760+ if (!gr_search_bind(sock, (struct sockaddr_in *)sck) ||
25761+ gr_handle_sock_server(sck)) {
25762+ err = -EACCES;
25763+ goto error;
25764+ }
25765+
25766 err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
25767 if (!err)
25768 err = sock->ops->bind(sock,
25769 (struct sockaddr *)address, addrlen);
25770 }
25771+error:
25772 fput_light(sock->file, fput_needed);
25773 }
25774 return err;
25775@@ -1368,10 +1403,17 @@ asmlinkage long sys_listen(int fd, int b
25776 if ((unsigned) backlog > sysctl_somaxconn)
25777 backlog = sysctl_somaxconn;
25778
25779+ if (gr_handle_sock_server_other(sock) ||
25780+ !gr_search_listen(sock)) {
25781+ err = -EPERM;
25782+ goto error;
25783+ }
25784+
25785 err = security_socket_listen(sock, backlog);
25786 if (!err)
25787 err = sock->ops->listen(sock, backlog);
25788
25789+error:
25790 fput_light(sock->file, fput_needed);
25791 }
25792 return err;
25793@@ -1408,6 +1450,13 @@ asmlinkage long sys_accept(int fd, struc
25794 newsock->type = sock->type;
25795 newsock->ops = sock->ops;
25796
25797+ if (gr_handle_sock_server_other(sock) ||
25798+ !gr_search_accept(sock)) {
25799+ err = -EPERM;
25800+ sock_release(newsock);
25801+ goto out_put;
25802+ }
25803+
25804 /*
25805 * We don't need try_module_get here, as the listening socket (sock)
25806 * has the protocol module (sock->ops->owner) held.
25807@@ -1449,6 +1498,7 @@ asmlinkage long sys_accept(int fd, struc
25808 err = newfd;
25809
25810 security_socket_post_accept(sock, newsock);
25811+ gr_attach_curr_ip(newsock->sk);
25812
25813 out_put:
25814 fput_light(sock->file, fput_needed);
25815@@ -1477,6 +1527,7 @@ asmlinkage long sys_connect(int fd, stru
25816 {
25817 struct socket *sock;
25818 char address[MAX_SOCK_ADDR];
25819+ struct sockaddr *sck;
25820 int err, fput_needed;
25821
25822 sock = sockfd_lookup_light(fd, &err, &fput_needed);
25823@@ -1486,6 +1537,13 @@ asmlinkage long sys_connect(int fd, stru
25824 if (err < 0)
25825 goto out_put;
25826
25827+ sck = (struct sockaddr *)address;
25828+ if (!gr_search_connect(sock, (struct sockaddr_in *)sck) ||
25829+ gr_handle_sock_client(sck)) {
25830+ err = -EACCES;
25831+ goto out_put;
25832+ }
25833+
25834 err = security_socket_connect(sock, (struct sockaddr *)address, addrlen);
25835 if (err)
25836 goto out_put;
25837@@ -1740,6 +1798,7 @@ asmlinkage long sys_shutdown(int fd, int
25838 err = sock->ops->shutdown(sock, how);
25839 fput_light(sock->file, fput_needed);
25840 }
25841+
25842 return err;
25843 }
25844
25845diff -urNp linux-2.6.17.11/net/unix/af_unix.c linux-2.6.17.11/net/unix/af_unix.c
25846--- linux-2.6.17.11/net/unix/af_unix.c 2006-08-07 00:18:54.000000000 -0400
25847+++ linux-2.6.17.11/net/unix/af_unix.c 2006-08-12 08:17:55.000000000 -0400
25848@@ -117,6 +117,7 @@
25849 #include <linux/mount.h>
25850 #include <net/checksum.h>
25851 #include <linux/security.h>
25852+#include <linux/grsecurity.h>
25853
25854 int sysctl_unix_max_dgram_qlen = 10;
25855
25856@@ -680,6 +681,11 @@ static struct sock *unix_find_other(stru
25857 if (err)
25858 goto put_fail;
25859
25860+ if (!gr_acl_handle_unix(nd.dentry, nd.mnt)) {
25861+ err = -EACCES;
25862+ goto put_fail;
25863+ }
25864+
25865 err = -ECONNREFUSED;
25866 if (!S_ISSOCK(nd.dentry->d_inode->i_mode))
25867 goto put_fail;
25868@@ -703,6 +709,13 @@ static struct sock *unix_find_other(stru
25869 if (u) {
25870 struct dentry *dentry;
25871 dentry = unix_sk(u)->dentry;
25872+
25873+ if (!gr_handle_chroot_unix(u->sk_peercred.pid)) {
25874+ err = -EPERM;
25875+ sock_put(u);
25876+ goto fail;
25877+ }
25878+
25879 if (dentry)
25880 touch_atime(unix_sk(u)->mnt, dentry);
25881 } else
25882@@ -781,9 +794,18 @@ static int unix_bind(struct socket *sock
25883 */
25884 mode = S_IFSOCK |
25885 (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
25886+
25887+ if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) {
25888+ err = -EACCES;
25889+ goto out_mknod_dput;
25890+ }
25891+
25892 err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0);
25893 if (err)
25894 goto out_mknod_dput;
25895+
25896+ gr_handle_create(dentry, nd.mnt);
25897+
25898 mutex_unlock(&nd.dentry->d_inode->i_mutex);
25899 dput(nd.dentry);
25900 nd.dentry = dentry;
25901@@ -801,6 +823,10 @@ static int unix_bind(struct socket *sock
25902 goto out_unlock;
25903 }
25904
25905+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
25906+ sk->sk_peercred.pid = current->pid;
25907+#endif
25908+
25909 list = &unix_socket_table[addr->hash];
25910 } else {
25911 list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
25912diff -urNp linux-2.6.17.11/security/commoncap.c linux-2.6.17.11/security/commoncap.c
25913--- linux-2.6.17.11/security/commoncap.c 2006-08-07 00:18:54.000000000 -0400
25914+++ linux-2.6.17.11/security/commoncap.c 2006-08-12 08:17:55.000000000 -0400
25915@@ -24,6 +24,7 @@
25916 #include <linux/ptrace.h>
25917 #include <linux/xattr.h>
25918 #include <linux/hugetlb.h>
25919+#include <linux/grsecurity.h>
25920
25921 int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
25922 {
25923@@ -45,7 +46,15 @@ EXPORT_SYMBOL(cap_netlink_recv);
25924 int cap_capable (struct task_struct *tsk, int cap)
25925 {
25926 /* Derived from include/linux/sched.h:capable. */
25927- if (cap_raised(tsk->cap_effective, cap))
25928+ if (cap_raised (tsk->cap_effective, cap) && gr_task_is_capable(tsk, cap))
25929+ return 0;
25930+ return -EPERM;
25931+}
25932+
25933+int cap_capable_nolog (struct task_struct *tsk, int cap)
25934+{
25935+ /* Derived from include/linux/sched.h:capable. */
25936+ if (cap_raised (tsk->cap_effective, cap))
25937 return 0;
25938 return -EPERM;
25939 }
25940@@ -164,8 +173,11 @@ void cap_bprm_apply_creds (struct linux_
25941 }
25942 }
25943
25944- current->suid = current->euid = current->fsuid = bprm->e_uid;
25945- current->sgid = current->egid = current->fsgid = bprm->e_gid;
25946+ if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid))
25947+ current->suid = current->euid = current->fsuid = bprm->e_uid;
25948+
25949+ if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid))
25950+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
25951
25952 /* For init, we want to retain the capabilities set
25953 * in the init_task struct. Thus we skip the usual
25954@@ -176,6 +188,8 @@ void cap_bprm_apply_creds (struct linux_
25955 cap_intersect (new_permitted, bprm->cap_effective);
25956 }
25957
25958+ gr_handle_chroot_caps(current);
25959+
25960 /* AUD: Audit candidate if current->cap_effective is set */
25961
25962 current->keep_capabilities = 0;
25963@@ -321,12 +335,13 @@ int cap_vm_enough_memory(long pages)
25964 {
25965 int cap_sys_admin = 0;
25966
25967- if (cap_capable(current, CAP_SYS_ADMIN) == 0)
25968+ if (cap_capable_nolog(current, CAP_SYS_ADMIN) == 0)
25969 cap_sys_admin = 1;
25970 return __vm_enough_memory(pages, cap_sys_admin);
25971 }
25972
25973 EXPORT_SYMBOL(cap_capable);
25974+EXPORT_SYMBOL(cap_capable_nolog);
25975 EXPORT_SYMBOL(cap_settime);
25976 EXPORT_SYMBOL(cap_ptrace);
25977 EXPORT_SYMBOL(cap_capget);
25978diff -urNp linux-2.6.17.11/security/dummy.c linux-2.6.17.11/security/dummy.c
25979--- linux-2.6.17.11/security/dummy.c 2006-08-07 00:18:54.000000000 -0400
25980+++ linux-2.6.17.11/security/dummy.c 2006-08-12 08:17:55.000000000 -0400
25981@@ -29,6 +29,7 @@
25982 #include <linux/hugetlb.h>
25983 #include <linux/ptrace.h>
25984 #include <linux/file.h>
25985+#include <linux/grsecurity.h>
25986
25987 static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
25988 {
25989@@ -139,8 +140,11 @@ static void dummy_bprm_apply_creds (stru
25990 }
25991 }
25992
25993- current->suid = current->euid = current->fsuid = bprm->e_uid;
25994- current->sgid = current->egid = current->fsgid = bprm->e_gid;
25995+ if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid))
25996+ current->suid = current->euid = current->fsuid = bprm->e_uid;
25997+
25998+ if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid))
25999+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
26000
26001 dummy_capget(current, &current->cap_effective, &current->cap_inheritable, &current->cap_permitted);
26002 }
26003diff -urNp linux-2.6.17.11/security/Kconfig linux-2.6.17.11/security/Kconfig
26004--- linux-2.6.17.11/security/Kconfig 2006-08-07 00:18:54.000000000 -0400
26005+++ linux-2.6.17.11/security/Kconfig 2006-08-12 08:17:55.000000000 -0400
26006@@ -4,6 +4,453 @@
26007
26008 menu "Security options"
26009
26010+menu "PaX"
26011+
26012+config PAX
26013+ bool "Enable various PaX features"
26014+ depends on GRKERNSEC && (ALPHA || ARM || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || PPC64 || SPARC32 || SPARC64 || X86 || X86_64)
26015+ help
26016+ This allows you to enable various PaX features. PaX adds
26017+ intrusion prevention mechanisms to the kernel that reduce
26018+ the risks posed by exploitable memory corruption bugs.
26019+
26020+menu "PaX Control"
26021+ depends on PAX
26022+
26023+config PAX_SOFTMODE
26024+ bool 'Support soft mode'
26025+ help
26026+ Enabling this option will allow you to run PaX in soft mode, that
26027+ is, PaX features will not be enforced by default, only on executables
26028+ marked explicitly. You must also enable PT_PAX_FLAGS support as it
26029+ is the only way to mark executables for soft mode use.
26030+
26031+ Soft mode can be activated by using the "pax_softmode=1" kernel command
26032+ line option on boot. Furthermore you can control various PaX features
26033+ at runtime via the entries in /proc/sys/kernel/pax.
26034+
26035+config PAX_EI_PAX
26036+ bool 'Use legacy ELF header marking'
26037+ help
26038+ Enabling this option will allow you to control PaX features on
26039+ a per executable basis via the 'chpax' utility available at
26040+ http://pax.grsecurity.net/. The control flags will be read from
26041+ an otherwise reserved part of the ELF header. This marking has
26042+ numerous drawbacks (no support for soft-mode, toolchain does not
26043+ know about the non-standard use of the ELF header) therefore it
26044+ has been deprecated in favour of PT_PAX_FLAGS support.
26045+
26046+ If you have applications not marked by the PT_PAX_FLAGS ELF
26047+ program header then you MUST enable this option otherwise they
26048+ will not get any protection.
26049+
26050+ Note that if you enable PT_PAX_FLAGS marking support as well,
26051+ the PT_PAX_FLAG marks will override the legacy EI_PAX marks.
26052+
26053+config PAX_PT_PAX_FLAGS
26054+ bool 'Use ELF program header marking'
26055+ help
26056+ Enabling this option will allow you to control PaX features on
26057+ a per executable basis via the 'paxctl' utility available at
26058+ http://pax.grsecurity.net/. The control flags will be read from
26059+ a PaX specific ELF program header (PT_PAX_FLAGS). This marking
26060+ has the benefits of supporting both soft mode and being fully
26061+ integrated into the toolchain (the binutils patch is available
26062+ from http://pax.grsecurity.net).
26063+
26064+ If you have applications not marked by the PT_PAX_FLAGS ELF
26065+ program header then you MUST enable the EI_PAX marking support
26066+ otherwise they will not get any protection.
26067+
26068+ Note that if you enable the legacy EI_PAX marking support as well,
26069+ the EI_PAX marks will be overridden by the PT_PAX_FLAGS marks.
26070+
26071+choice
26072+ prompt 'MAC system integration'
26073+ default PAX_HAVE_ACL_FLAGS
26074+ help
26075+ Mandatory Access Control systems have the option of controlling
26076+ PaX flags on a per executable basis, choose the method supported
26077+ by your particular system.
26078+
26079+ - "none": if your MAC system does not interact with PaX,
26080+ - "direct": if your MAC system defines pax_set_flags() itself,
26081+ - "hook": if your MAC system uses the pax_set_flags_func callback.
26082+
26083+ NOTE: this option is for developers/integrators only.
26084+
26085+config PAX_NO_ACL_FLAGS
26086+ bool 'none'
26087+
26088+config PAX_HAVE_ACL_FLAGS
26089+ bool 'direct'
26090+
26091+config PAX_HOOK_ACL_FLAGS
26092+ bool 'hook'
26093+endchoice
26094+
26095+endmenu
26096+
26097+menu "Non-executable pages"
26098+ depends on PAX
26099+
26100+config PAX_NOEXEC
26101+ bool "Enforce non-executable pages"
26102+ 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 || X86_64)
26103+ help
26104+ By design some architectures do not allow for protecting memory
26105+ pages against execution or even if they do, Linux does not make
26106+ use of this feature. In practice this means that if a page is
26107+ readable (such as the stack or heap) it is also executable.
26108+
26109+ There is a well known exploit technique that makes use of this
26110+ fact and a common programming mistake where an attacker can
26111+ introduce code of his choice somewhere in the attacked program's
26112+ memory (typically the stack or the heap) and then execute it.
26113+
26114+ If the attacked program was running with different (typically
26115+ higher) privileges than that of the attacker, then he can elevate
26116+ his own privilege level (e.g. get a root shell, write to files for
26117+ which he does not have write access to, etc).
26118+
26119+ Enabling this option will let you choose from various features
26120+ that prevent the injection and execution of 'foreign' code in
26121+ a program.
26122+
26123+ This will also break programs that rely on the old behaviour and
26124+ expect that dynamically allocated memory via the malloc() family
26125+ of functions is executable (which it is not). Notable examples
26126+ are the XFree86 4.x server, the java runtime and wine.
26127+
26128+config PAX_PAGEEXEC
26129+ bool "Paging based non-executable pages"
26130+ depends on PAX_NOEXEC && (!X86_32 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MPENTIUM4 || MK7 || MK8 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MVIAC3_2)
26131+ select PAX_NOVSYSCALL if X86_32
26132+ help
26133+ This implementation is based on the paging feature of the CPU.
26134+ On i386 and ppc there is a variable but usually low performance
26135+ impact on applications. On alpha, ia64, parisc, sparc, sparc64
26136+ and x86_64 there is no performance impact.
26137+
26138+config PAX_SEGMEXEC
26139+ bool "Segmentation based non-executable pages"
26140+ depends on PAX_NOEXEC && X86_32
26141+ select PAX_NOVSYSCALL
26142+ help
26143+ This implementation is based on the segmentation feature of the
26144+ CPU and has little performance impact, however applications will
26145+ be limited to a 1.5 GB address space instead of the normal 3 GB.
26146+
26147+choice
26148+ prompt "Default non-executable page method"
26149+ depends on PAX_PAGEEXEC && PAX_SEGMEXEC
26150+ default PAX_DEFAULT_SEGMEXEC
26151+ help
26152+ Select the default non-executable page method applied to applications
26153+ that do not select one themselves.
26154+
26155+config PAX_DEFAULT_PAGEEXEC
26156+ bool "PAGEEXEC"
26157+
26158+config PAX_DEFAULT_SEGMEXEC
26159+ bool "SEGMEXEC"
26160+endchoice
26161+
26162+config PAX_EMUTRAMP
26163+ bool "Emulate trampolines" if (PAX_PAGEEXEC || PAX_SEGMEXEC) && (PARISC || PPC32 || X86_32)
26164+ default y if PARISC || PPC32
26165+ help
26166+ There are some programs and libraries that for one reason or
26167+ another attempt to execute special small code snippets from
26168+ non-executable memory pages. Most notable examples are the
26169+ signal handler return code generated by the kernel itself and
26170+ the GCC trampolines.
26171+
26172+ If you enabled CONFIG_PAX_PAGEEXEC or CONFIG_PAX_SEGMEXEC then
26173+ such programs will no longer work under your kernel.
26174+
26175+ As a remedy you can say Y here and use the 'chpax' or 'paxctl'
26176+ utilities to enable trampoline emulation for the affected programs
26177+ yet still have the protection provided by the non-executable pages.
26178+
26179+ On parisc and ppc you MUST enable this option and EMUSIGRT as
26180+ well, otherwise your system will not even boot.
26181+
26182+ Alternatively you can say N here and use the 'chpax' or 'paxctl'
26183+ utilities to disable CONFIG_PAX_PAGEEXEC and CONFIG_PAX_SEGMEXEC
26184+ for the affected files.
26185+
26186+ NOTE: enabling this feature *may* open up a loophole in the
26187+ protection provided by non-executable pages that an attacker
26188+ could abuse. Therefore the best solution is to not have any
26189+ files on your system that would require this option. This can
26190+ be achieved by not using libc5 (which relies on the kernel
26191+ signal handler return code) and not using or rewriting programs
26192+ that make use of the nested function implementation of GCC.
26193+ Skilled users can just fix GCC itself so that it implements
26194+ nested function calls in a way that does not interfere with PaX.
26195+
26196+config PAX_EMUSIGRT
26197+ bool "Automatically emulate sigreturn trampolines"
26198+ depends on PAX_EMUTRAMP && (PARISC || PPC32)
26199+ default y
26200+ help
26201+ Enabling this option will have the kernel automatically detect
26202+ and emulate signal return trampolines executing on the stack
26203+ that would otherwise lead to task termination.
26204+
26205+ This solution is intended as a temporary one for users with
26206+ legacy versions of libc (libc5, glibc 2.0, uClibc before 0.9.17,
26207+ Modula-3 runtime, etc) or executables linked to such, basically
26208+ everything that does not specify its own SA_RESTORER function in
26209+ normal executable memory like glibc 2.1+ does.
26210+
26211+ On parisc and ppc you MUST enable this option, otherwise your
26212+ system will not even boot.
26213+
26214+ NOTE: this feature cannot be disabled on a per executable basis
26215+ and since it *does* open up a loophole in the protection provided
26216+ by non-executable pages, the best solution is to not have any
26217+ files on your system that would require this option.
26218+
26219+config PAX_MPROTECT
26220+ bool "Restrict mprotect()"
26221+ depends on (PAX_PAGEEXEC || PAX_SEGMEXEC) && !PPC64
26222+ help
26223+ Enabling this option will prevent programs from
26224+ - changing the executable status of memory pages that were
26225+ not originally created as executable,
26226+ - making read-only executable pages writable again,
26227+ - creating executable pages from anonymous memory.
26228+
26229+ You should say Y here to complete the protection provided by
26230+ the enforcement of non-executable pages.
26231+
26232+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control
26233+ this feature on a per file basis.
26234+
26235+config PAX_NOELFRELOCS
26236+ bool "Disallow ELF text relocations"
26237+ depends on PAX_MPROTECT && !PAX_ETEXECRELOCS && (IA64 || X86 || X86_64)
26238+ help
26239+ Non-executable pages and mprotect() restrictions are effective
26240+ in preventing the introduction of new executable code into an
26241+ attacked task's address space. There remain only two venues
26242+ for this kind of attack: if the attacker can execute already
26243+ existing code in the attacked task then he can either have it
26244+ create and mmap() a file containing his code or have it mmap()
26245+ an already existing ELF library that does not have position
26246+ independent code in it and use mprotect() on it to make it
26247+ writable and copy his code there. While protecting against
26248+ the former approach is beyond PaX, the latter can be prevented
26249+ by having only PIC ELF libraries on one's system (which do not
26250+ need to relocate their code). If you are sure this is your case,
26251+ then enable this option otherwise be careful as you may not even
26252+ be able to boot or log on your system (for example, some PAM
26253+ modules are erroneously compiled as non-PIC by default).
26254+
26255+ NOTE: if you are using dynamic ELF executables (as suggested
26256+ when using ASLR) then you must have made sure that you linked
26257+ your files using the PIC version of crt1 (the et_dyn.tar.gz package
26258+ referenced there has already been updated to support this).
26259+
26260+config PAX_ETEXECRELOCS
26261+ bool "Allow ELF ET_EXEC text relocations"
26262+ depends on PAX_MPROTECT && (ALPHA || IA64 || PARISC)
26263+ default y
26264+ help
26265+ On some architectures there are incorrectly created applications
26266+ that require text relocations and would not work without enabling
26267+ this option. If you are an alpha, ia64 or parisc user, you should
26268+ enable this option and disable it once you have made sure that
26269+ none of your applications need it.
26270+
26271+config PAX_EMUPLT
26272+ bool "Automatically emulate ELF PLT"
26273+ depends on PAX_MPROTECT && (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64)
26274+ default y
26275+ help
26276+ Enabling this option will have the kernel automatically detect
26277+ and emulate the Procedure Linkage Table entries in ELF files.
26278+ On some architectures such entries are in writable memory, and
26279+ become non-executable leading to task termination. Therefore
26280+ it is mandatory that you enable this option on alpha, parisc, ppc,
26281+ sparc and sparc64, otherwise your system would not even boot.
26282+
26283+ NOTE: this feature *does* open up a loophole in the protection
26284+ provided by the non-executable pages, therefore the proper
26285+ solution is to modify the toolchain to produce a PLT that does
26286+ not need to be writable.
26287+
26288+config PAX_DLRESOLVE
26289+ bool
26290+ depends on PAX_EMUPLT && (SPARC32 || SPARC64)
26291+ default y
26292+
26293+config PAX_SYSCALL
26294+ bool
26295+ depends on PAX_PAGEEXEC && PPC32
26296+ default y
26297+
26298+config PAX_KERNEXEC
26299+ bool "Enforce non-executable kernel pages"
26300+ depends on PAX_NOEXEC && X86_32 && !HOTPLUG_PCI_COMPAQ_NVRAM && !PCI_BIOS && !EFI && !DEBUG_RODATA
26301+ select PAX_NOVSYSCALL
26302+ help
26303+ This is the kernel land equivalent of PAGEEXEC and MPROTECT,
26304+ that is, enabling this option will make it harder to inject
26305+ and execute 'foreign' code in kernel memory itself.
26306+
26307+endmenu
26308+
26309+menu "Address Space Layout Randomization"
26310+ depends on PAX
26311+
26312+config PAX_ASLR
26313+ bool "Address Space Layout Randomization"
26314+ depends on PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS
26315+ help
26316+ Many if not most exploit techniques rely on the knowledge of
26317+ certain addresses in the attacked program. The following options
26318+ will allow the kernel to apply a certain amount of randomization
26319+ to specific parts of the program thereby forcing an attacker to
26320+ guess them in most cases. Any failed guess will most likely crash
26321+ the attacked program which allows the kernel to detect such attempts
26322+ and react on them. PaX itself provides no reaction mechanisms,
26323+ instead it is strongly encouraged that you make use of Nergal's
26324+ segvguard (ftp://ftp.pl.openwall.com/misc/segvguard/) or grsecurity's
26325+ (http://www.grsecurity.net/) built-in crash detection features or
26326+ develop one yourself.
26327+
26328+ By saying Y here you can choose to randomize the following areas:
26329+ - top of the task's kernel stack
26330+ - top of the task's userland stack
26331+ - base address for mmap() requests that do not specify one
26332+ (this includes all libraries)
26333+ - base address of the main executable
26334+
26335+ It is strongly recommended to say Y here as address space layout
26336+ randomization has negligible impact on performance yet it provides
26337+ a very effective protection.
26338+
26339+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control
26340+ this feature on a per file basis.
26341+
26342+config PAX_RANDKSTACK
26343+ bool "Randomize kernel stack base"
26344+ depends on PAX_ASLR && X86_TSC && X86_32
26345+ help
26346+ By saying Y here the kernel will randomize every task's kernel
26347+ stack on every system call. This will not only force an attacker
26348+ to guess it but also prevent him from making use of possible
26349+ leaked information about it.
26350+
26351+ Since the kernel stack is a rather scarce resource, randomization
26352+ may cause unexpected stack overflows, therefore you should very
26353+ carefully test your system. Note that once enabled in the kernel
26354+ configuration, this feature cannot be disabled on a per file basis.
26355+
26356+config PAX_RANDUSTACK
26357+ bool "Randomize user stack base"
26358+ depends on PAX_ASLR
26359+ help
26360+ By saying Y here the kernel will randomize every task's userland
26361+ stack. The randomization is done in two steps where the second
26362+ one may apply a big amount of shift to the top of the stack and
26363+ cause problems for programs that want to use lots of memory (more
26364+ than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is).
26365+ For this reason the second step can be controlled by 'chpax' or
26366+ 'paxctl' on a per file basis.
26367+
26368+config PAX_RANDMMAP
26369+ bool "Randomize mmap() base"
26370+ depends on PAX_ASLR
26371+ help
26372+ By saying Y here the kernel will use a randomized base address for
26373+ mmap() requests that do not specify one themselves. As a result
26374+ all dynamically loaded libraries will appear at random addresses
26375+ and therefore be harder to exploit by a technique where an attacker
26376+ attempts to execute library code for his purposes (e.g. spawn a
26377+ shell from an exploited program that is running at an elevated
26378+ privilege level).
26379+
26380+ Furthermore, if a program is relinked as a dynamic ELF file, its
26381+ base address will be randomized as well, completing the full
26382+ randomization of the address space layout. Attacking such programs
26383+ becomes a guess game. You can find an example of doing this at
26384+ http://pax.grsecurity.net/et_dyn.tar.gz and practical samples at
26385+ http://www.grsecurity.net/grsec-gcc-specs.tar.gz .
26386+
26387+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control this
26388+ feature on a per file basis.
26389+
26390+config PAX_NOVSYSCALL
26391+ bool "Disable the vsyscall page"
26392+ depends on PAX_ASLR && X86_32
26393+ help
26394+ The Linux 2.6 kernel introduced a new feature that speeds up or
26395+ simplifies certain operations, such as system calls or returns
26396+ from signal handlers.
26397+
26398+ Unfortunately the implementation also gives a powerful instrument
26399+ into the hands of exploit writers: the so-called vsyscall page exists
26400+ in every task at the same fixed address and it contains machine code
26401+ that is very useful in performing the return-to-libc style attack.
26402+
26403+ Since this exploit technique cannot in general be protected against
26404+ via kernel solutions, this option will allow you to disable the use
26405+ of the vsyscall page and revert back to the old behaviour.
26406+
26407+endmenu
26408+
26409+menu "Miscellaneous hardening features"
26410+
26411+config PAX_MEMORY_SANITIZE
26412+ bool "Sanitize all freed memory"
26413+ help
26414+ By saying Y here the kernel will erase memory pages as soon as they
26415+ are freed. This in turn reduces the lifetime of data stored in the
26416+ pages, making it less likely that sensitive information such as
26417+ passwords, cryptographic secrets, etc stay in memory for too long.
26418+
26419+ This is especially useful for programs whose runtime is short, long
26420+ lived processes and the kernel itself benefit from this as long as
26421+ they operate on whole memory pages and ensure timely freeing of pages
26422+ that may hold sensitive information.
26423+
26424+ The tradeoff is performance impact, on a single CPU system kernel
26425+ compilation sees a 3% slowdown, other systems and workloads may vary
26426+ and you are advised to test this feature on your expected workload
26427+ before deploying it.
26428+
26429+ Note that this feature does not protect data stored in live pages,
26430+ e.g., process memory swapped to disk may stay there for a long time.
26431+
26432+config PAX_MEMORY_UDEREF
26433+ bool "Prevent invalid userland pointer dereference"
26434+ depends on X86_32
26435+ select PAX_NOVSYSCALL
26436+ help
26437+ By saying Y here the kernel will be prevented from dereferencing
26438+ userland pointers in contexts where the kernel expects only kernel
26439+ pointers. This is both a useful runtime debugging feature and a
26440+ security measure that prevents exploiting a class of kernel bugs.
26441+
26442+ The tradeoff is that some virtualization solutions may experience
26443+ a huge slowdown and therefore you should not enable this feature
26444+ for kernels meant to run in such environments. Whether a given VM
26445+ solution is affected or not is best determined by simply trying it
26446+ out, the performance impact will be obvious right on boot as this
26447+ mechanism engages from very early on. A good rule of thumb is that
26448+ VMs running on CPUs without hardware virtualization support (i.e.,
26449+ the majority of IA-32 CPUs) will likely experience the slowdown.
26450+
26451+endmenu
26452+
26453+endmenu
26454+
26455+source grsecurity/Kconfig
26456+
26457 config KEYS
26458 bool "Enable access key retention support"
26459 help
This page took 2.870176 seconds and 4 git commands to generate.