]> git.pld-linux.org Git - packages/kernel.git/blame - grsecurity-2.1.9-2.6.17.7.patch
- 2.6.27.8 [CVE-2008-5300]
[packages/kernel.git] / grsecurity-2.1.9-2.6.17.7.patch
CommitLineData
f1a4f855 1diff -urNp linux-2.6.17.7/Makefile linux-2.6.17.7/Makefile
2--- linux-2.6.17.7/Makefile 2006-07-24 23:36:01.000000000 -0400
3+++ linux-2.6.17.7/Makefile 2006-08-01 20:29:48.000000000 -0400
4@@ -518,7 +518,7 @@ export MODLIB
5
6
7 ifeq ($(KBUILD_EXTMOD),)
8-core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
9+core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
10
11 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
12 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
13diff -urNp linux-2.6.17.7/arch/alpha/kernel/module.c linux-2.6.17.7/arch/alpha/kernel/module.c
14--- linux-2.6.17.7/arch/alpha/kernel/module.c 2006-07-24 23:36:01.000000000 -0400
15+++ linux-2.6.17.7/arch/alpha/kernel/module.c 2006-08-01 20:29:45.000000000 -0400
16@@ -177,7 +177,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs,
17
18 /* The small sections were sorted to the end of the segment.
19 The following should definitely cover them. */
20- gp = (u64)me->module_core + me->core_size - 0x8000;
21+ gp = (u64)me->module_core_rw + me->core_size_rw - 0x8000;
22 got = sechdrs[me->arch.gotsecindex].sh_addr;
23
24 for (i = 0; i < n; i++) {
25diff -urNp linux-2.6.17.7/arch/alpha/kernel/osf_sys.c linux-2.6.17.7/arch/alpha/kernel/osf_sys.c
26--- linux-2.6.17.7/arch/alpha/kernel/osf_sys.c 2006-07-24 23:36:01.000000000 -0400
27+++ linux-2.6.17.7/arch/alpha/kernel/osf_sys.c 2006-08-01 20:29:45.000000000 -0400
28@@ -1273,6 +1273,10 @@ arch_get_unmapped_area(struct file *filp
29 merely specific addresses, but regions of memory -- perhaps
30 this feature should be incorporated into all ports? */
31
32+#ifdef CONFIG_PAX_RANDMMAP
33+ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
34+#endif
35+
36 if (addr) {
37 addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
38 if (addr != (unsigned long) -ENOMEM)
39@@ -1280,8 +1284,8 @@ arch_get_unmapped_area(struct file *filp
40 }
41
42 /* Next, try allocating at TASK_UNMAPPED_BASE. */
43- addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE),
44- len, limit);
45+ addr = arch_get_unmapped_area_1 (PAGE_ALIGN(current->mm->mmap_base), len, limit);
46+
47 if (addr != (unsigned long) -ENOMEM)
48 return addr;
49
50diff -urNp linux-2.6.17.7/arch/alpha/kernel/ptrace.c linux-2.6.17.7/arch/alpha/kernel/ptrace.c
51--- linux-2.6.17.7/arch/alpha/kernel/ptrace.c 2006-07-24 23:36:01.000000000 -0400
52+++ linux-2.6.17.7/arch/alpha/kernel/ptrace.c 2006-08-01 20:29:45.000000000 -0400
53@@ -15,6 +15,7 @@
f1a4f855 54 #include <linux/security.h>
55 #include <linux/signal.h>
77fa6d7d 56 #include <linux/vs_pid.h>
f1a4f855 57+#include <linux/grsecurity.h>
58
59 #include <asm/uaccess.h>
60 #include <asm/pgtable.h>
61@@ -283,6 +284,9 @@ do_sys_ptrace(long request, long pid, lo
62 goto out_notsk;
63 }
64
65+ if (gr_handle_ptrace(child, request))
66+ goto out;
67+
68 if (request == PTRACE_ATTACH) {
69 ret = ptrace_attach(child);
70 goto out;
71diff -urNp linux-2.6.17.7/arch/alpha/mm/fault.c linux-2.6.17.7/arch/alpha/mm/fault.c
72--- linux-2.6.17.7/arch/alpha/mm/fault.c 2006-07-24 23:36:01.000000000 -0400
73+++ linux-2.6.17.7/arch/alpha/mm/fault.c 2006-08-01 20:29:45.000000000 -0400
74@@ -25,6 +25,7 @@
75 #include <linux/smp_lock.h>
76 #include <linux/interrupt.h>
77 #include <linux/module.h>
78+#include <linux/binfmts.h>
79
80 #include <asm/system.h>
81 #include <asm/uaccess.h>
82@@ -56,6 +57,124 @@ __load_new_mm_context(struct mm_struct *
83 __reload_thread(pcb);
84 }
85
86+#ifdef CONFIG_PAX_PAGEEXEC
87+/*
88+ * PaX: decide what to do with offenders (regs->pc = fault address)
89+ *
90+ * returns 1 when task should be killed
91+ * 2 when patched PLT trampoline was detected
92+ * 3 when unpatched PLT trampoline was detected
93+ */
94+static int pax_handle_fetch_fault(struct pt_regs *regs)
95+{
96+
97+#ifdef CONFIG_PAX_EMUPLT
98+ int err;
99+
100+ do { /* PaX: patched PLT emulation #1 */
101+ unsigned int ldah, ldq, jmp;
102+
103+ err = get_user(ldah, (unsigned int *)regs->pc);
104+ err |= get_user(ldq, (unsigned int *)(regs->pc+4));
105+ err |= get_user(jmp, (unsigned int *)(regs->pc+8));
106+
107+ if (err)
108+ break;
109+
110+ if ((ldah & 0xFFFF0000U) == 0x277B0000U &&
111+ (ldq & 0xFFFF0000U) == 0xA77B0000U &&
112+ jmp == 0x6BFB0000U)
113+ {
114+ unsigned long r27, addr;
115+ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
116+ unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL;
117+
118+ addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
119+ err = get_user(r27, (unsigned long*)addr);
120+ if (err)
121+ break;
122+
123+ regs->r27 = r27;
124+ regs->pc = r27;
125+ return 2;
126+ }
127+ } while (0);
128+
129+ do { /* PaX: patched PLT emulation #2 */
130+ unsigned int ldah, lda, br;
131+
132+ err = get_user(ldah, (unsigned int *)regs->pc);
133+ err |= get_user(lda, (unsigned int *)(regs->pc+4));
134+ err |= get_user(br, (unsigned int *)(regs->pc+8));
135+
136+ if (err)
137+ break;
138+
139+ if ((ldah & 0xFFFF0000U)== 0x277B0000U &&
140+ (lda & 0xFFFF0000U) == 0xA77B0000U &&
141+ (br & 0xFFE00000U) == 0xC3E00000U)
142+ {
143+ unsigned long addr = br | 0xFFFFFFFFFFE00000UL;
144+ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
145+ unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL;
146+
147+ regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
148+ regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
149+ return 2;
150+ }
151+ } while (0);
152+
153+ do { /* PaX: unpatched PLT emulation */
154+ unsigned int br;
155+
156+ err = get_user(br, (unsigned int *)regs->pc);
157+
158+ if (!err && (br & 0xFFE00000U) == 0xC3800000U) {
159+ unsigned int br2, ldq, nop, jmp;
160+ unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver;
161+
162+ addr = regs->pc + 4 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
163+ err = get_user(br2, (unsigned int *)addr);
164+ err |= get_user(ldq, (unsigned int *)(addr+4));
165+ err |= get_user(nop, (unsigned int *)(addr+8));
166+ err |= get_user(jmp, (unsigned int *)(addr+12));
167+ err |= get_user(resolver, (unsigned long *)(addr+16));
168+
169+ if (err)
170+ break;
171+
172+ if (br2 == 0xC3600000U &&
173+ ldq == 0xA77B000CU &&
174+ nop == 0x47FF041FU &&
175+ jmp == 0x6B7B0000U)
176+ {
177+ regs->r28 = regs->pc+4;
178+ regs->r27 = addr+16;
179+ regs->pc = resolver;
180+ return 3;
181+ }
182+ }
183+ } while (0);
184+#endif
185+
186+ return 1;
187+}
188+
189+void pax_report_insns(void *pc, void *sp)
190+{
191+ unsigned long i;
192+
193+ printk(KERN_ERR "PAX: bytes at PC: ");
194+ for (i = 0; i < 5; i++) {
195+ unsigned int c;
196+ if (get_user(c, (unsigned int*)pc+i))
197+ printk("???????? ");
198+ else
199+ printk("%08x ", c);
200+ }
201+ printk("\n");
202+}
203+#endif
204
205 /*
206 * This routine handles page faults. It determines the address,
207@@ -133,8 +252,29 @@ do_page_fault(unsigned long address, uns
208 good_area:
209 si_code = SEGV_ACCERR;
210 if (cause < 0) {
211- if (!(vma->vm_flags & VM_EXEC))
212+ if (!(vma->vm_flags & VM_EXEC)) {
213+
214+#ifdef CONFIG_PAX_PAGEEXEC
215+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->pc)
216+ goto bad_area;
217+
218+ up_read(&mm->mmap_sem);
219+ switch(pax_handle_fetch_fault(regs)) {
220+
221+#ifdef CONFIG_PAX_EMUPLT
222+ case 2:
223+ case 3:
224+ return;
225+#endif
226+
227+ }
228+ pax_report_fault(regs, (void*)regs->pc, (void*)rdusp());
229+ do_exit(SIGKILL);
230+#else
231 goto bad_area;
232+#endif
233+
234+ }
235 } else if (!cause) {
236 /* Allow reads even for write-only mappings */
237 if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
238diff -urNp linux-2.6.17.7/arch/arm/mm/mmap.c linux-2.6.17.7/arch/arm/mm/mmap.c
239--- linux-2.6.17.7/arch/arm/mm/mmap.c 2006-07-24 23:36:01.000000000 -0400
240+++ linux-2.6.17.7/arch/arm/mm/mmap.c 2006-08-01 20:29:45.000000000 -0400
241@@ -62,6 +62,10 @@ arch_get_unmapped_area(struct file *filp
242 if (len > TASK_SIZE)
243 return -ENOMEM;
244
245+#ifdef CONFIG_PAX_RANDMMAP
246+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
247+#endif
248+
249 if (addr) {
250 if (do_align)
251 addr = COLOUR_ALIGN(addr, pgoff);
252@@ -76,7 +80,7 @@ arch_get_unmapped_area(struct file *filp
253 if (len > mm->cached_hole_size) {
254 start_addr = addr = mm->free_area_cache;
255 } else {
256- start_addr = addr = TASK_UNMAPPED_BASE;
257+ start_addr = addr = mm->mmap_base;
258 mm->cached_hole_size = 0;
259 }
260
261@@ -93,8 +97,8 @@ full_search:
262 * Start a new search - just in case we missed
263 * some holes.
264 */
265- if (start_addr != TASK_UNMAPPED_BASE) {
266- start_addr = addr = TASK_UNMAPPED_BASE;
267+ if (start_addr != mm->mmap_base) {
268+ start_addr = addr = mm->mmap_base;
269 mm->cached_hole_size = 0;
270 goto full_search;
271 }
272diff -urNp linux-2.6.17.7/arch/i386/Kconfig linux-2.6.17.7/arch/i386/Kconfig
273--- linux-2.6.17.7/arch/i386/Kconfig 2006-07-24 23:36:01.000000000 -0400
274+++ linux-2.6.17.7/arch/i386/Kconfig 2006-08-01 20:29:45.000000000 -0400
275@@ -980,7 +980,7 @@ endchoice
276
277 config PCI_BIOS
278 bool
279- depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
280+ depends on !X86_VISWS && PCI && PCI_GOBIOS
281 default y
282
283 config PCI_DIRECT
284diff -urNp linux-2.6.17.7/arch/i386/Kconfig.cpu linux-2.6.17.7/arch/i386/Kconfig.cpu
285--- linux-2.6.17.7/arch/i386/Kconfig.cpu 2006-07-24 23:36:01.000000000 -0400
286+++ linux-2.6.17.7/arch/i386/Kconfig.cpu 2006-08-01 20:29:45.000000000 -0400
287@@ -251,7 +251,7 @@ config X86_PPRO_FENCE
288
289 config X86_F00F_BUG
290 bool
291- depends on M586MMX || M586TSC || M586 || M486 || M386
292+ depends on (M586MMX || M586TSC || M586 || M486 || M386) && !PAX_KERNEXEC
293 default y
294
295 config X86_WP_WORKS_OK
296@@ -281,7 +281,7 @@ config X86_CMPXCHG64
297
298 config X86_ALIGNMENT_16
299 bool
300- depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
301+ depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
302 default y
303
304 config X86_GOOD_APIC
305diff -urNp linux-2.6.17.7/arch/i386/Kconfig.debug linux-2.6.17.7/arch/i386/Kconfig.debug
306--- linux-2.6.17.7/arch/i386/Kconfig.debug 2006-07-24 23:36:01.000000000 -0400
307+++ linux-2.6.17.7/arch/i386/Kconfig.debug 2006-08-01 20:29:45.000000000 -0400
308@@ -53,7 +53,7 @@ config DEBUG_PAGEALLOC
309
310 config DEBUG_RODATA
311 bool "Write protect kernel read-only data structures"
312- depends on DEBUG_KERNEL
313+ depends on DEBUG_KERNEL && 0
314 help
315 Mark the kernel read-only data as write-protected in the pagetables,
316 in order to catch accidental (and incorrect) writes to such const
317diff -urNp linux-2.6.17.7/arch/i386/boot/compressed/head.S linux-2.6.17.7/arch/i386/boot/compressed/head.S
318--- linux-2.6.17.7/arch/i386/boot/compressed/head.S 2006-07-24 23:36:01.000000000 -0400
319+++ linux-2.6.17.7/arch/i386/boot/compressed/head.S 2006-08-01 20:29:45.000000000 -0400
320@@ -39,11 +39,13 @@ startup_32:
321 movl %eax,%gs
322
323 lss stack_start,%esp
324+ movl 0x000000,%ecx
325 xorl %eax,%eax
326 1: incl %eax # check that A20 really IS enabled
327 movl %eax,0x000000 # loop forever if it isn't
328 cmpl %eax,0x100000
329 je 1b
330+ movl %ecx,0x000000
331
332 /*
333 * Initialize eflags. Some BIOS's leave bits like NT set. This would
334diff -urNp linux-2.6.17.7/arch/i386/kernel/acpi/sleep.c linux-2.6.17.7/arch/i386/kernel/acpi/sleep.c
335--- linux-2.6.17.7/arch/i386/kernel/acpi/sleep.c 2006-07-24 23:36:01.000000000 -0400
336+++ linux-2.6.17.7/arch/i386/kernel/acpi/sleep.c 2006-08-01 20:29:45.000000000 -0400
337@@ -10,6 +10,7 @@
338 #include <linux/dmi.h>
339 #include <asm/smp.h>
340 #include <asm/tlbflush.h>
341+#include <asm/desc.h>
342
343 /* address in low memory of the wakeup routine. */
344 unsigned long acpi_wakeup_address = 0;
345@@ -24,11 +25,22 @@ static void init_low_mapping(pgd_t * pgd
346 {
347 int pgd_ofs = 0;
348
349+#ifdef CONFIG_PAX_KERNEXEC
350+ unsigned long cr0;
351+
352+ pax_open_kernel(cr0);
353+#endif
354+
355 while ((pgd_ofs < pgd_limit)
356 && (pgd_ofs + USER_PTRS_PER_PGD < PTRS_PER_PGD)) {
357 set_pgd(pgd, *(pgd + USER_PTRS_PER_PGD));
358 pgd_ofs++, pgd++;
359 }
360+
361+#ifdef CONFIG_PAX_KERNEXEC
362+ pax_close_kernel(cr0);
363+#endif
364+
365 flush_tlb_all();
366 }
367
368@@ -55,7 +67,18 @@ int acpi_save_state_mem(void)
369 */
370 void acpi_restore_state_mem(void)
371 {
372+#ifdef CONFIG_PAX_KERNEXEC
373+ unsigned long cr0;
374+
375+ pax_open_kernel(cr0);
376+#endif
377+
378 zap_low_mappings();
379+
380+#ifdef CONFIG_PAX_KERNEXEC
381+ pax_close_kernel(cr0);
382+#endif
383+
384 }
385
386 /**
387diff -urNp linux-2.6.17.7/arch/i386/kernel/alternative.c linux-2.6.17.7/arch/i386/kernel/alternative.c
388--- linux-2.6.17.7/arch/i386/kernel/alternative.c 2006-07-24 23:36:01.000000000 -0400
389+++ linux-2.6.17.7/arch/i386/kernel/alternative.c 2006-08-01 20:29:45.000000000 -0400
390@@ -3,6 +3,7 @@
391 #include <linux/list.h>
392 #include <asm/alternative.h>
393 #include <asm/sections.h>
394+#include <asm/desc.h>
395
396 #define DEBUG 0
397 #if DEBUG
398@@ -101,71 +102,128 @@ void apply_alternatives(struct alt_instr
399 struct alt_instr *a;
400 int diff, i, k;
401
402+#ifdef CONFIG_PAX_KERNEXEC
403+ unsigned long cr0;
404+
405+ pax_open_kernel(cr0);
406+#endif
407+
408 DPRINTK("%s: alt table %p -> %p\n", __FUNCTION__, start, end);
409 for (a = start; a < end; a++) {
410 BUG_ON(a->replacementlen > a->instrlen);
411 if (!boot_cpu_has(a->cpuid))
412 continue;
413- memcpy(a->instr, a->replacement, a->replacementlen);
414+ memcpy(a->instr + __KERNEL_TEXT_OFFSET, a->replacement, a->replacementlen);
415 diff = a->instrlen - a->replacementlen;
416 /* Pad the rest with nops */
417 for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
418 k = diff;
419 if (k > ASM_NOP_MAX)
420 k = ASM_NOP_MAX;
421- memcpy(a->instr + i, noptable[k], k);
422+ memcpy(a->instr + i + __KERNEL_TEXT_OFFSET, noptable[k], k);
423 }
424 }
425+
426+#ifdef CONFIG_PAX_KERNEXEC
427+ pax_close_kernel(cr0);
428+#endif
429+
430 }
431
432 static void alternatives_smp_save(struct alt_instr *start, struct alt_instr *end)
433 {
434 struct alt_instr *a;
435
436+#ifdef CONFIG_PAX_KERNEXEC
437+ unsigned long cr0;
438+
439+ pax_open_kernel(cr0);
440+#endif
441+
442 DPRINTK("%s: alt table %p-%p\n", __FUNCTION__, start, end);
443 for (a = start; a < end; a++) {
444 memcpy(a->replacement + a->replacementlen,
445- a->instr,
446+ a->instr + __KERNEL_TEXT_OFFSET,
447 a->instrlen);
448 }
449+
450+#ifdef CONFIG_PAX_KERNEXEC
451+ pax_close_kernel(cr0);
452+#endif
453+
454 }
455
456 static void alternatives_smp_apply(struct alt_instr *start, struct alt_instr *end)
457 {
458 struct alt_instr *a;
459
460+#ifdef CONFIG_PAX_KERNEXEC
461+ unsigned long cr0;
462+
463+ pax_open_kernel(cr0);
464+#endif
465+
466 for (a = start; a < end; a++) {
467- memcpy(a->instr,
468+ memcpy(a->instr + __KERNEL_TEXT_OFFSET,
469 a->replacement + a->replacementlen,
470 a->instrlen);
471 }
472+
473+#ifdef CONFIG_PAX_KERNEXEC
474+ pax_close_kernel(cr0);
475+#endif
476+
477 }
478
479 static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
480 {
481- u8 **ptr;
482+ u8 *ptr;
483+
484+#ifdef CONFIG_PAX_KERNEXEC
485+ unsigned long cr0;
486
487- for (ptr = start; ptr < end; ptr++) {
488- if (*ptr < text)
489+ pax_open_kernel(cr0);
490+#endif
491+
492+ for (; start < end; start++) {
493+ ptr = *start + __KERNEL_TEXT_OFFSET;
494+ if (ptr < text)
495 continue;
496- if (*ptr > text_end)
497+ if (ptr > text_end)
498 continue;
499- **ptr = 0xf0; /* lock prefix */
500+ *ptr = 0xf0; /* lock prefix */
501 };
502+
503+#ifdef CONFIG_PAX_KERNEXEC
504+ pax_close_kernel(cr0);
505+#endif
506+
507 }
508
509 static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end)
510 {
511 unsigned char **noptable = find_nop_table();
512- u8 **ptr;
513+ u8 *ptr;
514+
515+#ifdef CONFIG_PAX_KERNEXEC
516+ unsigned long cr0;
517+
518+ pax_open_kernel(cr0);
519+#endif
520
521- for (ptr = start; ptr < end; ptr++) {
522- if (*ptr < text)
523+ for (; start < end; start++) {
524+ ptr = *start + __KERNEL_TEXT_OFFSET;
525+ if (ptr < text)
526 continue;
527- if (*ptr > text_end)
528+ if (ptr > text_end)
529 continue;
530- **ptr = noptable[1][0];
531+ *ptr = noptable[1][0];
532 };
533+
534+#ifdef CONFIG_PAX_KERNEXEC
535+ pax_close_kernel(cr0);
536+#endif
537+
538 }
539
540 struct smp_alt_module {
541diff -urNp linux-2.6.17.7/arch/i386/kernel/apic.c linux-2.6.17.7/arch/i386/kernel/apic.c
542--- linux-2.6.17.7/arch/i386/kernel/apic.c 2006-07-24 23:36:01.000000000 -0400
543+++ linux-2.6.17.7/arch/i386/kernel/apic.c 2006-08-01 20:29:45.000000000 -0400
544@@ -1176,7 +1176,7 @@ inline void smp_local_timer_interrupt(st
545 {
546 profile_tick(CPU_PROFILING, regs);
547 #ifdef CONFIG_SMP
548- update_process_times(user_mode_vm(regs));
549+ update_process_times(user_mode(regs));
550 #endif
551
552 /*
553diff -urNp linux-2.6.17.7/arch/i386/kernel/apm.c linux-2.6.17.7/arch/i386/kernel/apm.c
554--- linux-2.6.17.7/arch/i386/kernel/apm.c 2006-07-24 23:36:01.000000000 -0400
555+++ linux-2.6.17.7/arch/i386/kernel/apm.c 2006-08-01 20:29:45.000000000 -0400
556@@ -589,9 +589,18 @@ static u8 apm_bios_call(u32 func, u32 eb
557 struct desc_struct save_desc_40;
558 struct desc_struct *gdt;
559
560+#ifdef CONFIG_PAX_KERNEXEC
561+ unsigned long cr0;
562+#endif
563+
564 cpus = apm_save_cpus();
565
566 cpu = get_cpu();
567+
568+#ifdef CONFIG_PAX_KERNEXEC
569+ pax_open_kernel(cr0);
570+#endif
571+
572 gdt = get_cpu_gdt_table(cpu);
573 save_desc_40 = gdt[0x40 / 8];
574 gdt[0x40 / 8] = bad_bios_desc;
575@@ -603,6 +612,11 @@ static u8 apm_bios_call(u32 func, u32 eb
576 APM_DO_RESTORE_SEGS;
577 local_irq_restore(flags);
578 gdt[0x40 / 8] = save_desc_40;
579+
580+#ifdef CONFIG_PAX_KERNEXEC
581+ pax_close_kernel(cr0);
582+#endif
583+
584 put_cpu();
585 apm_restore_cpus(cpus);
586
587@@ -633,9 +647,18 @@ static u8 apm_bios_call_simple(u32 func,
588 struct desc_struct save_desc_40;
589 struct desc_struct *gdt;
590
591+#ifdef CONFIG_PAX_KERNEXEC
592+ unsigned long cr0;
593+#endif
594+
595 cpus = apm_save_cpus();
596
597 cpu = get_cpu();
598+
599+#ifdef CONFIG_PAX_KERNEXEC
600+ pax_open_kernel(cr0);
601+#endif
602+
603 gdt = get_cpu_gdt_table(cpu);
604 save_desc_40 = gdt[0x40 / 8];
605 gdt[0x40 / 8] = bad_bios_desc;
606@@ -647,6 +670,11 @@ static u8 apm_bios_call_simple(u32 func,
607 APM_DO_RESTORE_SEGS;
608 local_irq_restore(flags);
609 gdt[0x40 / 8] = save_desc_40;
610+
611+#ifdef CONFIG_PAX_KERNEXEC
612+ pax_close_kernel(cr0);
613+#endif
614+
615 put_cpu();
616 apm_restore_cpus(cpus);
617 return error;
618diff -urNp linux-2.6.17.7/arch/i386/kernel/asm-offsets.c linux-2.6.17.7/arch/i386/kernel/asm-offsets.c
619--- linux-2.6.17.7/arch/i386/kernel/asm-offsets.c 2006-07-24 23:36:01.000000000 -0400
620+++ linux-2.6.17.7/arch/i386/kernel/asm-offsets.c 2006-08-01 20:29:45.000000000 -0400
621@@ -68,5 +68,6 @@ void foo(void)
622 sizeof(struct tss_struct));
623
624 DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
625+ DEFINE(PTRS_PER_PTE_asm, PTRS_PER_PTE);
626 DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL));
627 }
628diff -urNp linux-2.6.17.7/arch/i386/kernel/cpu/common.c linux-2.6.17.7/arch/i386/kernel/cpu/common.c
629--- linux-2.6.17.7/arch/i386/kernel/cpu/common.c 2006-07-24 23:36:01.000000000 -0400
630+++ linux-2.6.17.7/arch/i386/kernel/cpu/common.c 2006-08-01 20:29:45.000000000 -0400
631@@ -4,7 +4,6 @@
632 #include <linux/smp.h>
633 #include <linux/module.h>
634 #include <linux/percpu.h>
635-#include <linux/bootmem.h>
636 #include <asm/semaphore.h>
637 #include <asm/processor.h>
638 #include <asm/i387.h>
639@@ -19,9 +18,6 @@
640
641 #include "cpu.h"
642
643-DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
644-EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
645-
646 DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
647 EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
648
649@@ -401,6 +397,10 @@ void __cpuinit identify_cpu(struct cpuin
650 if (this_cpu->c_init)
651 this_cpu->c_init(c);
652
653+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_NOVSYSCALL)
654+ clear_bit(X86_FEATURE_SEP, c->x86_capability);
655+#endif
656+
657 /* Disable the PN if appropriate */
658 squash_the_stupid_serial_number(c);
659
660@@ -590,11 +590,10 @@ void __init early_cpu_init(void)
661 void __cpuinit cpu_init(void)
662 {
663 int cpu = smp_processor_id();
664- struct tss_struct * t = &per_cpu(init_tss, cpu);
665+ struct tss_struct * t = init_tss + cpu;
666 struct thread_struct *thread = &current->thread;
667- struct desc_struct *gdt;
668+ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
669 __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
670- struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
671
672 if (cpu_test_and_set(cpu, cpu_initialized)) {
673 printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
674@@ -612,29 +611,11 @@ void __cpuinit cpu_init(void)
675 }
676
677 /*
678- * This is a horrible hack to allocate the GDT. The problem
679- * is that cpu_init() is called really early for the boot CPU
680- * (and hence needs bootmem) but much later for the secondary
681- * CPUs, when bootmem will have gone away
682- */
683- if (NODE_DATA(0)->bdata->node_bootmem_map) {
684- gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
685- /* alloc_bootmem_pages panics on failure, so no check */
686- memset(gdt, 0, PAGE_SIZE);
687- } else {
688- gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
689- if (unlikely(!gdt)) {
690- printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
691- for (;;)
692- local_irq_enable();
693- }
694- }
695-
696- /*
697 * Initialize the per-CPU GDT with the boot GDT,
698 * and set up the GDT descriptor:
699 */
700- memcpy(gdt, cpu_gdt_table, GDT_SIZE);
701+ if (cpu)
702+ memcpy(gdt, cpu_gdt_table, GDT_SIZE);
703
704 /* Set up GDT entry for 16bit stack */
705 *(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |=
706@@ -642,10 +623,10 @@ void __cpuinit cpu_init(void)
707 ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
708 (CPU_16BIT_STACK_SIZE - 1);
709
710- cpu_gdt_descr->size = GDT_SIZE - 1;
711- cpu_gdt_descr->address = (unsigned long)gdt;
712+ cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
713+ cpu_gdt_descr[cpu].address = (unsigned long)gdt;
714
715- load_gdt(cpu_gdt_descr);
716+ load_gdt(&cpu_gdt_descr[cpu]);
717 load_idt(&idt_descr);
718
719 /*
720@@ -660,7 +641,7 @@ void __cpuinit cpu_init(void)
721 load_esp0(t, thread);
722 set_tss_desc(cpu,t);
723 load_TR_desc();
724- load_LDT(&init_mm.context);
725+ _load_LDT(&init_mm.context);
726
727 #ifdef CONFIG_DOUBLEFAULT
728 /* Set up doublefault TSS pointer in the GDT */
729@@ -668,7 +649,7 @@ void __cpuinit cpu_init(void)
730 #endif
731
732 /* Clear %fs and %gs. */
733- asm volatile ("xorl %eax, %eax; movl %eax, %fs; movl %eax, %gs");
734+ asm volatile ("movl %0, %%fs; movl %0, %%gs" : : "r"(0));
735
736 /* Clear all 6 debug registers: */
737 set_debugreg(0, 0);
738diff -urNp linux-2.6.17.7/arch/i386/kernel/crash.c linux-2.6.17.7/arch/i386/kernel/crash.c
739--- linux-2.6.17.7/arch/i386/kernel/crash.c 2006-07-24 23:36:01.000000000 -0400
740+++ linux-2.6.17.7/arch/i386/kernel/crash.c 2006-08-01 20:29:45.000000000 -0400
741@@ -105,7 +105,7 @@ static int crash_nmi_callback(struct pt_
742 return 1;
743 local_irq_disable();
744
745- if (!user_mode_vm(regs)) {
746+ if (!user_mode(regs)) {
747 crash_fixup_ss_esp(&fixed_regs, regs);
748 regs = &fixed_regs;
749 }
750diff -urNp linux-2.6.17.7/arch/i386/kernel/doublefault.c linux-2.6.17.7/arch/i386/kernel/doublefault.c
751--- linux-2.6.17.7/arch/i386/kernel/doublefault.c 2006-07-24 23:36:01.000000000 -0400
752+++ linux-2.6.17.7/arch/i386/kernel/doublefault.c 2006-08-01 20:29:45.000000000 -0400
753@@ -11,7 +11,7 @@
754
755 #define DOUBLEFAULT_STACKSIZE (1024)
756 static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE];
757-#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE)
758+#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE-2)
759
760 #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000)
761
762@@ -56,10 +56,10 @@ struct tss_struct doublefault_tss __cach
763 .eip = (unsigned long) doublefault_fn,
764 .eflags = X86_EFLAGS_SF | 0x2, /* 0x2 bit is always set */
765 .esp = STACK_START,
766- .es = __USER_DS,
767+ .es = __KERNEL_DS,
768 .cs = __KERNEL_CS,
769 .ss = __KERNEL_DS,
770- .ds = __USER_DS,
771+ .ds = __KERNEL_DS,
772
773 .__cr3 = __pa(swapper_pg_dir)
774 };
775diff -urNp linux-2.6.17.7/arch/i386/kernel/efi.c linux-2.6.17.7/arch/i386/kernel/efi.c
776--- linux-2.6.17.7/arch/i386/kernel/efi.c 2006-07-24 23:36:01.000000000 -0400
777+++ linux-2.6.17.7/arch/i386/kernel/efi.c 2006-08-01 20:29:45.000000000 -0400
778@@ -64,82 +64,48 @@ extern void * boot_ioremap(unsigned long
779
780 static unsigned long efi_rt_eflags;
781 static DEFINE_SPINLOCK(efi_rt_lock);
782-static pgd_t efi_bak_pg_dir_pointer[2];
783+static pgd_t __initdata efi_bak_pg_dir_pointer[KERNEL_PGD_PTRS] __attribute__ ((aligned (4096)));
784
785-static void efi_call_phys_prelog(void)
786+static void __init efi_call_phys_prelog(void)
787 {
788- unsigned long cr4;
789- unsigned long temp;
790- struct Xgt_desc_struct *cpu_gdt_descr;
791-
792 spin_lock(&efi_rt_lock);
793 local_irq_save(efi_rt_eflags);
794
795- cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
796-
797- /*
798- * If I don't have PSE, I should just duplicate two entries in page
799- * directory. If I have PSE, I just need to duplicate one entry in
800- * page directory.
801- */
802- cr4 = read_cr4();
803-
804- if (cr4 & X86_CR4_PSE) {
805- efi_bak_pg_dir_pointer[0].pgd =
806- swapper_pg_dir[pgd_index(0)].pgd;
807- swapper_pg_dir[0].pgd =
808- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
809- } else {
810- efi_bak_pg_dir_pointer[0].pgd =
811- swapper_pg_dir[pgd_index(0)].pgd;
812- efi_bak_pg_dir_pointer[1].pgd =
813- swapper_pg_dir[pgd_index(0x400000)].pgd;
814- swapper_pg_dir[pgd_index(0)].pgd =
815- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
816- temp = PAGE_OFFSET + 0x400000;
817- swapper_pg_dir[pgd_index(0x400000)].pgd =
818- swapper_pg_dir[pgd_index(temp)].pgd;
819+ clone_pgd_range(efi_bak_pg_dir_pointer, swapper_pg_dir, KERNEL_PGD_PTRS);
820+ if (USER_PTRS_PER_PGD >= KERNEL_PGD_PTRS)
821+ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PTRS_PER_PGD, KERNEL_PGD_PTRS);
822+ else {
823+ unsigned long i;
824+ for (i = 0; i < KERNEL_PGD_PTRS; ++i)
825+ clone_pgd_range(swapper_pg_dir + i, swapper_pg_dir + USER_PTRS_PER_PGD + i, 1);
826 }
827
828 /*
829 * After the lock is released, the original page table is restored.
830 */
831- local_flush_tlb();
832+ __flush_tlb_all();
833
834- cpu_gdt_descr->address = __pa(cpu_gdt_descr->address);
835- load_gdt(cpu_gdt_descr);
836+ cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
837+ load_gdt((struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0]));
838 }
839
840-static void efi_call_phys_epilog(void)
841+static void __init efi_call_phys_epilog(void)
842 {
843- unsigned long cr4;
844- struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
845-
846- cpu_gdt_descr->address = (unsigned long)__va(cpu_gdt_descr->address);
847- load_gdt(cpu_gdt_descr);
848+ cpu_gdt_descr[0].address = (unsigned long) __va(cpu_gdt_descr[0].address);
849+ load_gdt(&cpu_gdt_descr[0]);
850
851- cr4 = read_cr4();
852-
853- if (cr4 & X86_CR4_PSE) {
854- swapper_pg_dir[pgd_index(0)].pgd =
855- efi_bak_pg_dir_pointer[0].pgd;
856- } else {
857- swapper_pg_dir[pgd_index(0)].pgd =
858- efi_bak_pg_dir_pointer[0].pgd;
859- swapper_pg_dir[pgd_index(0x400000)].pgd =
860- efi_bak_pg_dir_pointer[1].pgd;
861- }
862+ clone_pgd_range(swapper_pg_dir, efi_bak_pg_dir_pointer, KERNEL_PGD_PTRS);
863
864 /*
865 * After the lock is released, the original page table is restored.
866 */
867- local_flush_tlb();
868+ __flush_tlb_all();
869
870 local_irq_restore(efi_rt_eflags);
871 spin_unlock(&efi_rt_lock);
872 }
873
874-static efi_status_t
875+static efi_status_t __init
876 phys_efi_set_virtual_address_map(unsigned long memory_map_size,
877 unsigned long descriptor_size,
878 u32 descriptor_version,
879@@ -155,7 +121,7 @@ phys_efi_set_virtual_address_map(unsigne
880 return status;
881 }
882
883-static efi_status_t
884+static efi_status_t __init
885 phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
886 {
887 efi_status_t status;
888diff -urNp linux-2.6.17.7/arch/i386/kernel/efi_stub.S linux-2.6.17.7/arch/i386/kernel/efi_stub.S
889--- linux-2.6.17.7/arch/i386/kernel/efi_stub.S 2006-07-24 23:36:01.000000000 -0400
890+++ linux-2.6.17.7/arch/i386/kernel/efi_stub.S 2006-08-01 20:29:45.000000000 -0400
891@@ -7,6 +7,7 @@
892
893 #include <linux/config.h>
894 #include <linux/linkage.h>
895+#include <linux/init.h>
896 #include <asm/page.h>
897 #include <asm/pgtable.h>
898
899@@ -22,7 +23,7 @@
900 * service functions will comply with gcc calling convention, too.
901 */
902
903-.text
904+__INIT
905 ENTRY(efi_call_phys)
906 /*
907 * 0. The function can only be called in Linux kernel. So CS has been
908@@ -38,9 +39,7 @@ ENTRY(efi_call_phys)
909 * The mapping of lower virtual memory has been created in prelog and
910 * epilog.
911 */
912- movl $1f, %edx
913- subl $__PAGE_OFFSET, %edx
914- jmp *%edx
915+ jmp 1f-__PAGE_OFFSET
916 1:
917
918 /*
919@@ -49,14 +48,8 @@ ENTRY(efi_call_phys)
920 * parameter 2, ..., param n. To make things easy, we save the return
921 * address of efi_call_phys in a global variable.
922 */
923- popl %edx
924- movl %edx, saved_return_addr
925- /* get the function pointer into ECX*/
926- popl %ecx
927- movl %ecx, efi_rt_function_ptr
928- movl $2f, %edx
929- subl $__PAGE_OFFSET, %edx
930- pushl %edx
931+ popl (saved_return_addr)
932+ popl (efi_rt_function_ptr)
933
934 /*
935 * 3. Clear PG bit in %CR0.
936@@ -75,9 +68,8 @@ ENTRY(efi_call_phys)
937 /*
938 * 5. Call the physical function.
939 */
940- jmp *%ecx
941+ call *(efi_rt_function_ptr-__PAGE_OFFSET)
942
943-2:
944 /*
945 * 6. After EFI runtime service returns, control will return to
946 * following instruction. We'd better readjust stack pointer first.
947@@ -87,37 +79,29 @@ ENTRY(efi_call_phys)
948 /*
949 * 7. Restore PG bit
950 */
951- movl %cr0, %edx
952- orl $0x80000000, %edx
953- movl %edx, %cr0
954- jmp 1f
955-1:
956 /*
957 * 8. Now restore the virtual mode from flat mode by
958 * adding EIP with PAGE_OFFSET.
959 */
960- movl $1f, %edx
961- jmp *%edx
962+ movl %cr0, %edx
963+ orl $0x80000000, %edx
964+ movl %edx, %cr0
965+ jmp 1f+__PAGE_OFFSET
966 1:
967
968 /*
969 * 9. Balance the stack. And because EAX contain the return value,
970 * we'd better not clobber it.
971 */
972- leal efi_rt_function_ptr, %edx
973- movl (%edx), %ecx
974- pushl %ecx
975+ pushl (efi_rt_function_ptr)
976
977 /*
978- * 10. Push the saved return address onto the stack and return.
979+ * 10. Return to the saved return address.
980 */
981- leal saved_return_addr, %edx
982- movl (%edx), %ecx
983- pushl %ecx
984- ret
985+ jmpl *(saved_return_addr)
986 .previous
987
988-.data
989+__INITDATA
990 saved_return_addr:
991 .long 0
992 efi_rt_function_ptr:
993diff -urNp linux-2.6.17.7/arch/i386/kernel/entry.S linux-2.6.17.7/arch/i386/kernel/entry.S
994--- linux-2.6.17.7/arch/i386/kernel/entry.S 2006-07-24 23:36:01.000000000 -0400
995+++ linux-2.6.17.7/arch/i386/kernel/entry.S 2006-08-01 20:29:45.000000000 -0400
996@@ -82,7 +82,7 @@ VM_MASK = 0x00020000
997 #define resume_kernel restore_nocheck
998 #endif
999
1000-#define SAVE_ALL \
1001+#define __SAVE_ALL(_DS) \
1002 cld; \
1003 pushl %es; \
1004 pushl %ds; \
1005@@ -93,10 +93,24 @@ VM_MASK = 0x00020000
1006 pushl %edx; \
1007 pushl %ecx; \
1008 pushl %ebx; \
1009- movl $(__USER_DS), %edx; \
1010+ movl $(_DS), %edx; \
1011 movl %edx, %ds; \
1012 movl %edx, %es;
1013
1014+#ifdef CONFIG_PAX_KERNEXEC
1015+#define SAVE_ALL \
1016+ __SAVE_ALL(__KERNEL_DS) \
1017+ movl %cr0, %edx; \
1018+ movl %edx, %esi; \
1019+ orl $0x10000, %edx; \
1020+ xorl %edx, %esi; \
1021+ movl %edx, %cr0;
1022+#elif defined(CONFIG_PAX_NOVSYSCALL)
1023+#define SAVE_ALL __SAVE_ALL(__KERNEL_DS)
1024+#else
1025+#define SAVE_ALL __SAVE_ALL(__USER_DS)
1026+#endif
1027+
1028 #define RESTORE_INT_REGS \
1029 popl %ebx; \
1030 popl %ecx; \
1031@@ -146,7 +160,19 @@ ret_from_intr:
1032 movl EFLAGS(%esp), %eax # mix EFLAGS and CS
1033 movb CS(%esp), %al
1034 testl $(VM_MASK | 3), %eax
1035+
1036+#ifdef CONFIG_PAX_KERNEXEC
1037+ jnz resume_userspace
1038+
1039+ movl %cr0, %edx
1040+ xorl %esi, %edx
1041+ movl %edx, %cr0
1042+ jmp resume_kernel
1043+#else
1044 jz resume_kernel
1045+#endif
1046+
1047+
1048 ENTRY(resume_userspace)
1049 cli # make sure we don't miss an interrupt
1050 # setting need_resched or sigpending
1051@@ -213,13 +239,33 @@ sysenter_past_esp:
1052 movl TI_flags(%ebp), %ecx
1053 testw $_TIF_ALLWORK_MASK, %cx
1054 jne syscall_exit_work
1055+
1056+#ifdef CONFIG_PAX_RANDKSTACK
1057+ pushl %eax
1058+ call pax_randomize_kstack
1059+ popl %eax
1060+#endif
1061+
1062 /* if something modifies registers it must also disable sysexit */
1063 movl EIP(%esp), %edx
1064 movl OLDESP(%esp), %ecx
1065+1: mov DS(%esp), %ds
1066+2: mov ES(%esp), %es
1067 xorl %ebp,%ebp
1068 sti
1069 sysexit
1070
1071+.section .fixup,"ax"
1072+3: movl $0,DS(%esp)
1073+ jmp 1b
1074+4: movl $0,ES(%esp)
1075+ jmp 2b
1076+.previous
1077+.section __ex_table,"a"
1078+ .align 4
1079+ .long 1b,3b
1080+ .long 2b,4b
1081+.previous
1082
1083 # system call handler stub
1084 ENTRY(system_call)
1085@@ -247,6 +293,10 @@ syscall_exit:
1086 testw $_TIF_ALLWORK_MASK, %cx # current->work
1087 jne syscall_exit_work
1088
1089+#ifdef CONFIG_PAX_RANDKSTACK
1090+ call pax_randomize_kstack
1091+#endif
1092+
1093 restore_all:
1094 movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
1095 # Warning: OLDSS(%esp) contains the wrong/random values if we
1096@@ -402,7 +452,7 @@ syscall_badsys:
1097 * Build the entry stubs and pointer table with
1098 * some assembler magic.
1099 */
1100-.data
1101+.section .rodata,"a",@progbits
1102 ENTRY(interrupt)
1103 .text
1104
1105@@ -412,7 +462,7 @@ ENTRY(irq_entries_start)
1106 ALIGN
1107 1: pushl $vector-256
1108 jmp common_interrupt
1109-.data
1110+.section .rodata,"a",@progbits
1111 .long 1b
1112 .text
1113 vector=vector+1
1114@@ -459,10 +509,19 @@ error_code:
1115 movl ORIG_EAX(%esp), %edx # get the error code
1116 movl %eax, ORIG_EAX(%esp)
1117 movl %ecx, ES(%esp)
1118- movl $(__USER_DS), %ecx
1119+ movl $(__KERNEL_DS), %ecx
1120 movl %ecx, %ds
1121 movl %ecx, %es
1122 movl %esp,%eax # pt_regs pointer
1123+
1124+#ifdef CONFIG_PAX_KERNEXEC
1125+ movl %cr0, %ecx
1126+ movl %ecx, %esi
1127+ orl $0x10000, %ecx
1128+ xorl %ecx, %esi
1129+ movl %ecx, %cr0
1130+#endif
1131+
1132 call *%edi
1133 jmp ret_from_exception
1134
1135@@ -558,6 +617,13 @@ nmi_stack_correct:
1136 xorl %edx,%edx # zero error code
1137 movl %esp,%eax # pt_regs pointer
1138 call do_nmi
1139+
1140+#ifdef CONFIG_PAX_KERNEXEC
1141+ movl %cr0, %edx
1142+ xorl %esi, %edx
1143+ movl %edx, %cr0
1144+#endif
1145+
1146 jmp restore_all
1147
1148 nmi_stack_fixup:
1149@@ -588,6 +654,13 @@ nmi_16bit_stack:
1150 FIXUP_ESPFIX_STACK # %eax == %esp
1151 xorl %edx,%edx # zero error code
1152 call do_nmi
1153+
1154+#ifdef CONFIG_PAX_KERNEXEC
1155+ movl %cr0, %edx
1156+ xorl %esi, %edx
1157+ movl %edx, %cr0
1158+#endif
1159+
1160 RESTORE_REGS
1161 lss 12+4(%esp), %esp # back to 16bit stack
1162 1: iret
1163@@ -663,7 +736,6 @@ ENTRY(spurious_interrupt_bug)
1164 pushl $do_spurious_interrupt_bug
1165 jmp error_code
1166
1167-.section .rodata,"a"
1168 #include "syscall_table.S"
1169
1170 syscall_table_size=(.-sys_call_table)
1171diff -urNp linux-2.6.17.7/arch/i386/kernel/head.S linux-2.6.17.7/arch/i386/kernel/head.S
1172--- linux-2.6.17.7/arch/i386/kernel/head.S 2006-07-24 23:36:01.000000000 -0400
1173+++ linux-2.6.17.7/arch/i386/kernel/head.S 2006-08-01 20:29:45.000000000 -0400
1174@@ -46,6 +46,16 @@
1175 */
1176 #define INIT_MAP_BEYOND_END (128*1024)
1177
1178+#ifdef CONFIG_PAX_KERNEXEC
1179+/* PaX: fill first page in .text with int3 to catch NULL derefs in kernel mode */
1180+.fill 4096,1,0xcc
1181+#endif
1182+
1183+/*
1184+ * Real beginning of normal "text" segment
1185+ */
1186+ENTRY(stext)
1187+ENTRY(_stext)
1188
1189 /*
1190 * 32-bit kernel entrypoint; only used by the boot CPU. On entry,
1191@@ -67,6 +77,26 @@ ENTRY(startup_32)
1192 movl %eax,%fs
1193 movl %eax,%gs
1194
1195+#ifdef CONFIG_PAX_MEMORY_UDEREF
1196+ movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c09700),%eax
1197+ movl %eax,(cpu_gdt_table - __PAGE_OFFSET + GDT_ENTRY_KERNEL_DS * 8 + 4)
1198+ movl $((((__PAGE_OFFSET-1) & 0xf0000000) >> 12) | 0x00c0f300),%eax
1199+ movl %eax,(cpu_gdt_table - __PAGE_OFFSET + GDT_ENTRY_DEFAULT_USER_DS * 8 + 4)
1200+#endif
1201+
1202+#ifdef CONFIG_PAX_KERNEXEC
1203+ movl $ __KERNEL_TEXT_OFFSET,%eax
1204+ movw %ax,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 2)
1205+ rorl $16,%eax
1206+ movb %al,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 4)
1207+ movb %ah,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 7)
1208+
1209+ movb %al,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 4)
1210+ movb %ah,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 7)
1211+ rorl $16,%eax
1212+ movw %ax,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 2)
1213+#endif
1214+
1215 /*
1216 * Clear BSS first so that there are no surprises...
1217 * No need to cld as DF is already clear from cld above...
1218@@ -114,24 +144,42 @@ ENTRY(startup_32)
1219 * Warning: don't use %esi or the stack in this code. However, %esp
1220 * can be used as a GPR if you really need it...
1221 */
1222-page_pde_offset = (__PAGE_OFFSET >> 20);
1223-
1224+#ifdef CONFIG_X86_PAE
1225+page_pde_offset = ((__PAGE_OFFSET >> 21) * (4096 / PTRS_PER_PTE_asm));
1226+#else
1227+page_pde_offset = ((__PAGE_OFFSET >> 22) * (4096 / PTRS_PER_PTE_asm));
1228+#endif
1229 movl $(pg0 - __PAGE_OFFSET), %edi
1230+#ifdef CONFIG_X86_PAE
1231+ movl $(swapper_pm_dir - __PAGE_OFFSET), %edx
1232+#else
1233 movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
1234- movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */
1235+#endif
1236+ movl $0x063, %eax /* 0x063 = DIRTY+ACCESSED+PRESENT+RW */
1237 10:
1238- leal 0x007(%edi),%ecx /* Create PDE entry */
1239+ leal 0x063(%edi),%ecx /* Create PDE entry */
1240 movl %ecx,(%edx) /* Store identity PDE entry */
1241 movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */
1242+#ifdef CONFIG_X86_PAE
1243+ movl $0,4(%edx)
1244+ movl $0,page_pde_offset+4(%edx)
1245+ addl $8,%edx
1246+ movl $512, %ecx
1247+#else
1248 addl $4,%edx
1249 movl $1024, %ecx
1250+#endif
1251 11:
1252 stosl
1253+#ifdef CONFIG_X86_PAE
1254+ movl $0,(%edi)
1255+ addl $4,%edi
1256+#endif
1257 addl $0x1000,%eax
1258 loop 11b
1259 /* End condition: we must map up to and including INIT_MAP_BEYOND_END */
1260- /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */
1261- leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp
1262+ /* bytes beyond the end of our own page tables; the +0x063 is the attribute bits */
1263+ leal (INIT_MAP_BEYOND_END+0x063)(%edi),%ebp
1264 cmpl %ebp,%eax
1265 jb 10b
1266 movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
1267@@ -154,6 +202,11 @@ ENTRY(startup_32_smp)
1268 movl %eax,%fs
1269 movl %eax,%gs
1270
1271+ /* This is a secondary processor (AP) */
1272+ xorl %ebx,%ebx
1273+ incl %ebx
1274+#endif /* CONFIG_SMP */
1275+
1276 /*
1277 * New page tables may be in 4Mbyte page mode and may
1278 * be using the global pages.
1279@@ -169,26 +222,27 @@ ENTRY(startup_32_smp)
1280 * not yet offset PAGE_OFFSET..
1281 */
1282 #define cr4_bits mmu_cr4_features-__PAGE_OFFSET
1283+3:
1284 movl cr4_bits,%edx
1285 andl %edx,%edx
1286- jz 6f
1287+ jz 5f
1288 movl %cr4,%eax # Turn on paging options (PSE,PAE,..)
1289 orl %edx,%eax
1290 movl %eax,%cr4
1291
1292- btl $5, %eax # check if PAE is enabled
1293- jnc 6f
1294+#ifdef CONFIG_X86_PAE
1295+ movl %ebx,%edi
1296
1297 /* Check if extended functions are implemented */
1298 movl $0x80000000, %eax
1299 cpuid
1300 cmpl $0x80000000, %eax
1301- jbe 6f
1302+ jbe 4f
1303 mov $0x80000001, %eax
1304 cpuid
1305 /* Execute Disable bit supported? */
1306 btl $20, %edx
1307- jnc 6f
1308+ jnc 4f
1309
1310 /* Setup EFER (Extended Feature Enable Register) */
1311 movl $0xc0000080, %ecx
1312@@ -197,14 +251,12 @@ ENTRY(startup_32_smp)
1313 btsl $11, %eax
1314 /* Make changes effective */
1315 wrmsr
1316+ btsl $63,__supported_pte_mask-__PAGE_OFFSET
1317
1318-6:
1319- /* This is a secondary processor (AP) */
1320- xorl %ebx,%ebx
1321- incl %ebx
1322-
1323-3:
1324-#endif /* CONFIG_SMP */
1325+4:
1326+ movl %edi,%ebx
1327+#endif
1328+5:
1329
1330 /*
1331 * Enable paging
1332@@ -229,9 +281,7 @@ ENTRY(startup_32_smp)
1333
1334 #ifdef CONFIG_SMP
1335 andl %ebx,%ebx
1336- jz 1f /* Initial CPU cleans BSS */
1337- jmp checkCPUtype
1338-1:
1339+ jnz checkCPUtype /* Initial CPU cleans BSS */
1340 #endif /* CONFIG_SMP */
1341
1342 /*
1343@@ -308,8 +358,6 @@ is386: movl $2,%ecx # set MP
1344 ljmp $(__KERNEL_CS),$1f
1345 1: movl $(__KERNEL_DS),%eax # reload all the segment registers
1346 movl %eax,%ss # after changing gdt.
1347-
1348- movl $(__USER_DS),%eax # DS/ES contains default USER segment
1349 movl %eax,%ds
1350 movl %eax,%es
1351
1352@@ -412,32 +460,50 @@ ignore_int:
1353 #endif
1354 iret
1355
1356-/*
1357- * Real beginning of normal "text" segment
1358- */
1359-ENTRY(stext)
1360-ENTRY(_stext)
1361-
1362-/*
1363- * BSS section
1364- */
1365-.section ".bss.page_aligned","w"
1366+.section .swapper_pg_dir,"a",@progbits
1367 ENTRY(swapper_pg_dir)
1368+#ifdef CONFIG_X86_PAE
1369+ .long swapper_pm_dir-__PAGE_OFFSET+1
1370+ .long 0
1371+ .long swapper_pm_dir+512*8-__PAGE_OFFSET+1
1372+ .long 0
1373+ .long swapper_pm_dir+512*16-__PAGE_OFFSET+1
1374+ .long 0
1375+ .long swapper_pm_dir+512*24-__PAGE_OFFSET+1
1376+ .long 0
1377+#else
1378 .fill 1024,4,0
1379+#endif
1380+
1381+#ifdef CONFIG_X86_PAE
1382+.section .swapper_pm_dir,"a",@progbits
1383+ENTRY(swapper_pm_dir)
1384+ .fill 512,8,0
1385+ .fill 512,8,0
1386+ .fill 512,8,0
1387+ .fill 512,8,0
1388+#endif
1389+
1390+.section .empty_zero_page,"a",@progbits
1391 ENTRY(empty_zero_page)
1392 .fill 4096,1,0
1393
1394 /*
1395- * This starts the data section.
1396- */
1397-.data
1398+ * The IDT has to be page-aligned to simplify the Pentium
1399+ * F0 0F bug workaround.. We have a special link segment
1400+ * for this.
1401+ */
1402+.section .idt,"a",@progbits
1403+ENTRY(idt_table)
1404+ .fill 256,8,0
1405+
1406+.section .rodata,"a",@progbits
1407+ready: .byte 0
1408
1409 ENTRY(stack_start)
1410- .long init_thread_union+THREAD_SIZE
1411+ .long init_thread_union+THREAD_SIZE-8
1412 .long __BOOT_DS
1413
1414-ready: .byte 0
1415-
1416 int_msg:
1417 .asciz "Unknown interrupt or fault at EIP %p %p %p\n"
1418
1419@@ -465,7 +531,7 @@ idt_descr:
1420
1421 # boot GDT descriptor (later on used by CPU#0):
1422 .word 0 # 32 bit align gdt_desc.address
1423-cpu_gdt_descr:
1424+ENTRY(cpu_gdt_descr)
1425 .word GDT_ENTRIES*8-1
1426 .long cpu_gdt_table
1427
1428@@ -476,13 +542,13 @@ cpu_gdt_descr:
1429 .align L1_CACHE_BYTES
1430 ENTRY(boot_gdt_table)
1431 .fill GDT_ENTRY_BOOT_CS,8,0
1432- .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */
1433- .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */
1434+ .quad 0x00cf9b000000ffff /* kernel 4GB code at 0x00000000 */
1435+ .quad 0x00cf93000000ffff /* kernel 4GB data at 0x00000000 */
1436
1437 /*
1438 * The Global Descriptor Table contains 28 quadwords, per-CPU.
1439 */
1440- .align L1_CACHE_BYTES
1441+ .align 4096
1442 ENTRY(cpu_gdt_table)
1443 .quad 0x0000000000000000 /* NULL descriptor */
1444 .quad 0x0000000000000000 /* 0x0b reserved */
1445@@ -497,10 +563,10 @@ ENTRY(cpu_gdt_table)
1446 .quad 0x0000000000000000 /* 0x53 reserved */
1447 .quad 0x0000000000000000 /* 0x5b reserved */
1448
1449- .quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */
1450- .quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */
1451- .quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */
1452- .quad 0x00cff2000000ffff /* 0x7b user 4GB data at 0x00000000 */
1453+ .quad 0x00cf9b000000ffff /* 0x60 kernel 4GB code at 0x00000000 */
1454+ .quad 0x00cf93000000ffff /* 0x68 kernel 4GB data at 0x00000000 */
1455+ .quad 0x00cffb000000ffff /* 0x73 user 4GB code at 0x00000000 */
1456+ .quad 0x00cff3000000ffff /* 0x7b user 4GB data at 0x00000000 */
1457
1458 .quad 0x0000000000000000 /* 0x80 TSS descriptor */
1459 .quad 0x0000000000000000 /* 0x88 LDT descriptor */
1460@@ -510,24 +576,30 @@ ENTRY(cpu_gdt_table)
1461 * They code segments and data segments have fixed 64k limits,
1462 * the transfer segment sizes are set at run time.
1463 */
1464- .quad 0x00409a000000ffff /* 0x90 32-bit code */
1465- .quad 0x00009a000000ffff /* 0x98 16-bit code */
1466- .quad 0x000092000000ffff /* 0xa0 16-bit data */
1467- .quad 0x0000920000000000 /* 0xa8 16-bit data */
1468- .quad 0x0000920000000000 /* 0xb0 16-bit data */
1469+ .quad 0x00409b000000ffff /* 0x90 32-bit code */
1470+ .quad 0x00009b000000ffff /* 0x98 16-bit code */
1471+ .quad 0x000093000000ffff /* 0xa0 16-bit data */
1472+ .quad 0x0000930000000000 /* 0xa8 16-bit data */
1473+ .quad 0x0000930000000000 /* 0xb0 16-bit data */
1474
1475 /*
1476 * The APM segments have byte granularity and their bases
1477 * are set at run time. All have 64k limits.
1478 */
1479- .quad 0x00409a000000ffff /* 0xb8 APM CS code */
1480- .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */
1481- .quad 0x004092000000ffff /* 0xc8 APM DS data */
1482+ .quad 0x00409b000000ffff /* 0xb8 APM CS code */
1483+ .quad 0x00009b000000ffff /* 0xc0 APM CS 16 code (16 bit) */
1484+ .quad 0x004093000000ffff /* 0xc8 APM DS data */
1485
1486- .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */
1487+ .quad 0x0000930000000000 /* 0xd0 - ESPFIX 16-bit SS */
1488 .quad 0x0000000000000000 /* 0xd8 - unused */
1489 .quad 0x0000000000000000 /* 0xe0 - unused */
1490 .quad 0x0000000000000000 /* 0xe8 - unused */
1491 .quad 0x0000000000000000 /* 0xf0 - unused */
1492 .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */
1493
1494+ /* Be sure this is zeroed to avoid false validations in Xen */
1495+ .fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0
1496+
1497+#ifdef CONFIG_SMP
1498+ .fill (NR_CPUS-1) * (PAGE_SIZE_asm / 8),8,0 /* other CPU's GDT */
1499+#endif
1500diff -urNp linux-2.6.17.7/arch/i386/kernel/i386_ksyms.c linux-2.6.17.7/arch/i386/kernel/i386_ksyms.c
1501--- linux-2.6.17.7/arch/i386/kernel/i386_ksyms.c 2006-07-24 23:36:01.000000000 -0400
1502+++ linux-2.6.17.7/arch/i386/kernel/i386_ksyms.c 2006-08-01 20:52:30.000000000 -0400
1503@@ -3,12 +3,16 @@
1504 #include <asm/checksum.h>
1505 #include <asm/desc.h>
1506
1507+EXPORT_SYMBOL_GPL(cpu_gdt_table);
1508+
1509 EXPORT_SYMBOL(__down_failed);
1510 EXPORT_SYMBOL(__down_failed_interruptible);
1511 EXPORT_SYMBOL(__down_failed_trylock);
1512 EXPORT_SYMBOL(__up_wakeup);
1513 /* Networking helper routines. */
1514 EXPORT_SYMBOL(csum_partial_copy_generic);
1515+EXPORT_SYMBOL(csum_partial_copy_generic_to_user);
1516+EXPORT_SYMBOL(csum_partial_copy_generic_from_user);
1517
1518 EXPORT_SYMBOL(__get_user_1);
1519 EXPORT_SYMBOL(__get_user_2);
1520diff -urNp linux-2.6.17.7/arch/i386/kernel/init_task.c linux-2.6.17.7/arch/i386/kernel/init_task.c
1521--- linux-2.6.17.7/arch/i386/kernel/init_task.c 2006-07-24 23:36:01.000000000 -0400
1522+++ linux-2.6.17.7/arch/i386/kernel/init_task.c 2006-08-01 20:29:45.000000000 -0400
1523@@ -42,5 +42,5 @@ EXPORT_SYMBOL(init_task);
1524 * per-CPU TSS segments. Threads are completely 'soft' on Linux,
1525 * no more per-task TSS's.
1526 */
1527-DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS;
1528+struct tss_struct init_tss[NR_CPUS] ____cacheline_internodealigned_in_smp = { [0 ... NR_CPUS-1] = INIT_TSS };
1529
1530diff -urNp linux-2.6.17.7/arch/i386/kernel/ioport.c linux-2.6.17.7/arch/i386/kernel/ioport.c
1531--- linux-2.6.17.7/arch/i386/kernel/ioport.c 2006-07-24 23:36:01.000000000 -0400
1532+++ linux-2.6.17.7/arch/i386/kernel/ioport.c 2006-08-01 20:29:45.000000000 -0400
1533@@ -16,6 +16,7 @@
1534 #include <linux/stddef.h>
1535 #include <linux/slab.h>
1536 #include <linux/thread_info.h>
1537+#include <linux/grsecurity.h>
1538
1539 /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
1540 static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
1541@@ -64,9 +65,16 @@ asmlinkage long sys_ioperm(unsigned long
1542
1543 if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
1544 return -EINVAL;
1545+#ifdef CONFIG_GRKERNSEC_IO
1546+ if (turn_on) {
1547+ gr_handle_ioperm();
1548+#else
1549 if (turn_on && !capable(CAP_SYS_RAWIO))
1550+#endif
1551 return -EPERM;
1552-
1553+#ifdef CONFIG_GRKERNSEC_IO
1554+ }
1555+#endif
1556 /*
1557 * If it's the first ioperm() call in this thread's lifetime, set the
1558 * IO bitmap up. ioperm() is much less timing critical than clone(),
1559@@ -88,7 +96,7 @@ asmlinkage long sys_ioperm(unsigned long
1560 * because the ->io_bitmap_max value must match the bitmap
1561 * contents:
1562 */
1563- tss = &per_cpu(init_tss, get_cpu());
1564+ tss = init_tss + get_cpu();
1565
1566 set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
1567
1568@@ -142,8 +150,13 @@ asmlinkage long sys_iopl(unsigned long u
1569 return -EINVAL;
1570 /* Trying to gain more privileges? */
1571 if (level > old) {
1572+#ifdef CONFIG_GRKERNSEC_IO
1573+ gr_handle_iopl();
1574+ return -EPERM;
1575+#else
1576 if (!capable(CAP_SYS_RAWIO))
1577 return -EPERM;
1578+#endif
1579 }
1580 t->iopl = level << 12;
1581 regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl;
1582diff -urNp linux-2.6.17.7/arch/i386/kernel/irq.c linux-2.6.17.7/arch/i386/kernel/irq.c
1583--- linux-2.6.17.7/arch/i386/kernel/irq.c 2006-07-24 23:36:01.000000000 -0400
1584+++ linux-2.6.17.7/arch/i386/kernel/irq.c 2006-08-01 20:29:45.000000000 -0400
1585@@ -91,7 +91,7 @@ fastcall unsigned int do_IRQ(struct pt_r
1586 int arg1, arg2, ebx;
1587
1588 /* build the stack frame on the IRQ stack */
1589- isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
1590+ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)) - 2;
1591 irqctx->tinfo.task = curctx->tinfo.task;
1592 irqctx->tinfo.previous_esp = current_stack_pointer;
1593
1594@@ -119,10 +119,10 @@ fastcall unsigned int do_IRQ(struct pt_r
1595 * gcc's 3.0 and earlier don't handle that correctly.
1596 */
1597 static char softirq_stack[NR_CPUS * THREAD_SIZE]
1598- __attribute__((__aligned__(THREAD_SIZE)));
1599+ __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
1600
1601 static char hardirq_stack[NR_CPUS * THREAD_SIZE]
1602- __attribute__((__aligned__(THREAD_SIZE)));
1603+ __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
1604
1605 /*
1606 * allocate per-cpu stacks for hardirq and for softirq processing
1607@@ -182,7 +182,7 @@ asmlinkage void do_softirq(void)
1608 irqctx->tinfo.previous_esp = current_stack_pointer;
1609
1610 /* build the stack frame on the softirq stack */
1611- isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
1612+ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)) - 2;
1613
1614 asm volatile(
1615 " xchgl %%ebx,%%esp \n"
1616diff -urNp linux-2.6.17.7/arch/i386/kernel/ldt.c linux-2.6.17.7/arch/i386/kernel/ldt.c
1617--- linux-2.6.17.7/arch/i386/kernel/ldt.c 2006-07-24 23:36:01.000000000 -0400
1618+++ linux-2.6.17.7/arch/i386/kernel/ldt.c 2006-08-01 20:29:45.000000000 -0400
1619@@ -103,6 +103,19 @@ int init_new_context(struct task_struct
1620 retval = copy_ldt(&mm->context, &old_mm->context);
1621 up(&old_mm->context.sem);
1622 }
1623+
1624+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
1625+ if (!mm->context.user_cs_limit) {
1626+ mm->context.user_cs_base = 0UL;
1627+ mm->context.user_cs_limit = ~0UL;
1628+
1629+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
1630+ cpus_clear(mm->context.cpu_user_cs_mask);
1631+#endif
1632+
1633+ }
1634+#endif
1635+
1636 return retval;
1637 }
1638
1639@@ -160,7 +173,7 @@ static int read_default_ldt(void __user
1640 {
1641 int err;
1642 unsigned long size;
1643- void *address;
1644+ const void *address;
1645
1646 err = 0;
1647 address = &default_ldt[0];
1648@@ -215,6 +228,13 @@ static int write_ldt(void __user * ptr,
1649 }
1650 }
1651
1652+#ifdef CONFIG_PAX_SEGMEXEC
1653+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (ldt_info.contents & MODIFY_LDT_CONTENTS_CODE)) {
1654+ error = -EINVAL;
1655+ goto out_unlock;
1656+ }
1657+#endif
1658+
1659 entry_1 = LDT_entry_a(&ldt_info);
1660 entry_2 = LDT_entry_b(&ldt_info);
1661 if (oldmode)
1662diff -urNp linux-2.6.17.7/arch/i386/kernel/module.c linux-2.6.17.7/arch/i386/kernel/module.c
1663--- linux-2.6.17.7/arch/i386/kernel/module.c 2006-07-24 23:36:01.000000000 -0400
1664+++ linux-2.6.17.7/arch/i386/kernel/module.c 2006-08-01 20:29:45.000000000 -0400
1665@@ -21,6 +21,7 @@
1666 #include <linux/fs.h>
1667 #include <linux/string.h>
1668 #include <linux/kernel.h>
1669+#include <asm/desc.h>
1670
1671 #if 0
1672 #define DEBUGP printk
1673@@ -32,9 +33,30 @@ void *module_alloc(unsigned long size)
1674 {
1675 if (size == 0)
1676 return NULL;
1677+
1678+#ifdef CONFIG_PAX_KERNEXEC
1679+ return vmalloc(size);
1680+#else
1681 return vmalloc_exec(size);
1682+#endif
1683+
1684 }
1685
1686+#ifdef CONFIG_PAX_KERNEXEC
1687+void *module_alloc_exec(unsigned long size)
1688+{
1689+ struct vm_struct *area;
1690+
1691+ if (size == 0)
1692+ return NULL;
1693+
1694+ area = __get_vm_area(size, 0, (unsigned long)&MODULES_VADDR, (unsigned long)&MODULES_END);
1695+ if (area)
1696+ return area->addr;
1697+
1698+ return NULL;
1699+}
1700+#endif
1701
1702 /* Free memory returned from module_alloc */
1703 void module_free(struct module *mod, void *module_region)
1704@@ -44,6 +66,45 @@ void module_free(struct module *mod, voi
1705 table entries. */
1706 }
1707
1708+#ifdef CONFIG_PAX_KERNEXEC
1709+void module_free_exec(struct module *mod, void *module_region)
1710+{
1711+ struct vm_struct **p, *tmp;
1712+
1713+ if (!module_region)
1714+ return;
1715+
1716+ if ((PAGE_SIZE-1) & (unsigned long)module_region) {
1717+ printk(KERN_ERR "Trying to module_free_exec() bad address (%p)\n", module_region);
1718+ WARN_ON(1);
1719+ return;
1720+ }
1721+
1722+ write_lock(&vmlist_lock);
1723+ for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next)
1724+ if (tmp->addr == module_region)
1725+ break;
1726+
1727+ if (tmp) {
1728+ unsigned long cr0;
1729+
1730+ pax_open_kernel(cr0);
1731+ memset(tmp->addr, 0xCC, tmp->size);
1732+ pax_close_kernel(cr0);
1733+
1734+ *p = tmp->next;
1735+ kfree(tmp);
1736+ }
1737+ write_unlock(&vmlist_lock);
1738+
1739+ if (!tmp) {
1740+ printk(KERN_ERR "Trying to module_free_exec() nonexistent vm area (%p)\n",
1741+ module_region);
1742+ WARN_ON(1);
1743+ }
1744+}
1745+#endif
1746+
1747 /* We don't need anything special. */
1748 int module_frob_arch_sections(Elf_Ehdr *hdr,
1749 Elf_Shdr *sechdrs,
1750@@ -62,14 +123,16 @@ int apply_relocate(Elf32_Shdr *sechdrs,
1751 unsigned int i;
1752 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
1753 Elf32_Sym *sym;
1754- uint32_t *location;
1755+ uint32_t *plocation, location;
1756
1757 DEBUGP("Applying relocate section %u to %u\n", relsec,
1758 sechdrs[relsec].sh_info);
1759 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
1760 /* This is where to make the change */
1761- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
1762- + rel[i].r_offset;
1763+ plocation = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset;
1764+ location = (uint32_t)plocation;
1765+ if (sechdrs[sechdrs[relsec].sh_info].sh_flags & SHF_EXECINSTR)
1766+ plocation = (void *)plocation + __KERNEL_TEXT_OFFSET;
1767 /* This is the symbol it is referring to. Note that all
1768 undefined symbols have been resolved. */
1769 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
1770@@ -78,11 +141,11 @@ int apply_relocate(Elf32_Shdr *sechdrs,
1771 switch (ELF32_R_TYPE(rel[i].r_info)) {
1772 case R_386_32:
1773 /* We add the value into the location given */
1774- *location += sym->st_value;
1775+ *plocation += sym->st_value;
1776 break;
1777 case R_386_PC32:
1778 /* Add the value, subtract its postition */
1779- *location += sym->st_value - (uint32_t)location;
1780+ *plocation += sym->st_value - location;
1781 break;
1782 default:
1783 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
1784diff -urNp linux-2.6.17.7/arch/i386/kernel/process.c linux-2.6.17.7/arch/i386/kernel/process.c
1785--- linux-2.6.17.7/arch/i386/kernel/process.c 2006-07-24 23:36:01.000000000 -0400
1786+++ linux-2.6.17.7/arch/i386/kernel/process.c 2006-08-01 20:29:45.000000000 -0400
1787@@ -69,7 +69,7 @@ EXPORT_SYMBOL(boot_option_idle_override)
1788 */
1789 unsigned long thread_saved_pc(struct task_struct *tsk)
1790 {
1791- return ((unsigned long *)tsk->thread.esp)[3];
1792+ return tsk->thread.eip;
1793 }
1794
1795 /*
1796@@ -294,7 +294,7 @@ void show_regs(struct pt_regs * regs)
1797 printk("EIP: %04x:[<%08lx>] CPU: %d\n",0xffff & regs->xcs,regs->eip, smp_processor_id());
1798 print_symbol("EIP is at %s\n", regs->eip);
1799
1800- if (user_mode_vm(regs))
1801+ if (user_mode(regs))
1802 printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
1803 printk(" EFLAGS: %08lx %s (%s %.*s)\n",
1804 regs->eflags, print_tainted(), system_utsname.release,
1805@@ -343,8 +343,8 @@ int kernel_thread(int (*fn)(void *), voi
1806 regs.ebx = (unsigned long) fn;
1807 regs.edx = (unsigned long) arg;
1808
1809- regs.xds = __USER_DS;
1810- regs.xes = __USER_DS;
1811+ regs.xds = __KERNEL_DS;
1812+ regs.xes = __KERNEL_DS;
1813 regs.orig_eax = -1;
1814 regs.eip = (unsigned long) kernel_thread_helper;
1815 regs.xcs = __KERNEL_CS;
1816@@ -366,7 +366,7 @@ void exit_thread(void)
1817 /* The process may have allocated an io port bitmap... nuke it. */
1818 if (unlikely(NULL != t->io_bitmap_ptr)) {
1819 int cpu = get_cpu();
1820- struct tss_struct *tss = &per_cpu(init_tss, cpu);
1821+ struct tss_struct *tss = init_tss + cpu;
1822
1823 kfree(t->io_bitmap_ptr);
1824 t->io_bitmap_ptr = NULL;
1825@@ -386,6 +386,9 @@ void flush_thread(void)
1826 {
1827 struct task_struct *tsk = current;
1828
1829+ __asm__("mov %0,%%fs\n"
1830+ "mov %0,%%gs\n"
1831+ : : "r" (0) : "memory");
1832 memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
1833 memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
1834 /*
1835@@ -418,7 +421,7 @@ int copy_thread(int nr, unsigned long cl
1836 struct task_struct *tsk;
1837 int err;
1838
1839- childregs = task_pt_regs(p);
1840+ childregs = task_stack_page(p) + THREAD_SIZE - sizeof(struct pt_regs) - 8;
1841 *childregs = *regs;
1842 childregs->eax = 0;
1843 childregs->esp = esp;
1844@@ -461,6 +464,11 @@ int copy_thread(int nr, unsigned long cl
1845 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
1846 goto out;
1847
1848+#ifdef CONFIG_PAX_SEGMEXEC
1849+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
1850+ goto out;
1851+#endif
1852+
1853 desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
1854 desc->a = LDT_entry_a(&info);
1855 desc->b = LDT_entry_b(&info);
1856@@ -625,7 +633,11 @@ struct task_struct fastcall * __switch_t
1857 struct thread_struct *prev = &prev_p->thread,
1858 *next = &next_p->thread;
1859 int cpu = smp_processor_id();
1860- struct tss_struct *tss = &per_cpu(init_tss, cpu);
1861+ struct tss_struct *tss = init_tss + cpu;
1862+
1863+#ifdef CONFIG_PAX_KERNEXEC
1864+ unsigned long cr0;
1865+#endif
1866
1867 /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
1868
1869@@ -648,11 +660,23 @@ struct task_struct fastcall * __switch_t
1870 savesegment(fs, prev->fs);
1871 savesegment(gs, prev->gs);
1872
1873+#ifdef CONFIG_PAX_KERNEXEC
1874+ pax_open_kernel(cr0);
1875+#endif
1876+
1877+#ifdef CONFIG_PAX_MEMORY_UDEREF
1878+ __set_fs(get_fs(), cpu);
1879+#endif
1880+
1881 /*
1882 * Load the per-thread Thread-Local Storage descriptor.
1883 */
1884 load_TLS(next, cpu);
1885
1886+#ifdef CONFIG_PAX_KERNEXEC
1887+ pax_close_kernel(cr0);
1888+#endif
1889+
1890 /*
1891 * Restore %fs and %gs if needed.
1892 *
1893@@ -806,8 +830,18 @@ asmlinkage int sys_set_thread_area(struc
1894 struct desc_struct *desc;
1895 int cpu, idx;
1896
1897+#ifdef CONFIG_PAX_KERNEXEC
1898+ unsigned long cr0;
1899+#endif
1900+
1901 if (copy_from_user(&info, u_info, sizeof(info)))
1902 return -EFAULT;
1903+
1904+#ifdef CONFIG_PAX_SEGMEXEC
1905+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
1906+ return -EINVAL;
1907+#endif
1908+
1909 idx = info.entry_number;
1910
1911 /*
1912@@ -839,8 +873,17 @@ asmlinkage int sys_set_thread_area(struc
1913 desc->a = LDT_entry_a(&info);
1914 desc->b = LDT_entry_b(&info);
1915 }
1916+
1917+#ifdef CONFIG_PAX_KERNEXEC
1918+ pax_open_kernel(cr0);
1919+#endif
1920+
1921 load_TLS(t, cpu);
1922
1923+#ifdef CONFIG_PAX_KERNEXEC
1924+ pax_close_kernel(cr0);
1925+#endif
1926+
1927 put_cpu();
1928
1929 return 0;
1930@@ -896,9 +939,27 @@ asmlinkage int sys_get_thread_area(struc
1931 return 0;
1932 }
1933
1934-unsigned long arch_align_stack(unsigned long sp)
1935+#ifdef CONFIG_PAX_RANDKSTACK
1936+asmlinkage void pax_randomize_kstack(void)
1937 {
1938- if (randomize_va_space)
1939- sp -= get_random_int() % 8192;
1940- return sp & ~0xf;
1941+ struct tss_struct *tss = init_tss + smp_processor_id();
1942+ unsigned long time;
1943+
1944+ if (!randomize_va_space)
1945+ return;
1946+
1947+ rdtscl(time);
1948+
1949+ /* P4 seems to return a 0 LSB, ignore it */
1950+#ifdef CONFIG_MPENTIUM4
1951+ time &= 0x1EUL;
1952+ time <<= 2;
1953+#else
1954+ time &= 0xFUL;
1955+ time <<= 3;
1956+#endif
1957+
1958+ tss->esp0 ^= time;
1959+ current->thread.esp0 = tss->esp0;
1960 }
1961+#endif
1962diff -urNp linux-2.6.17.7/arch/i386/kernel/ptrace.c linux-2.6.17.7/arch/i386/kernel/ptrace.c
1963--- linux-2.6.17.7/arch/i386/kernel/ptrace.c 2006-07-24 23:36:01.000000000 -0400
1964+++ linux-2.6.17.7/arch/i386/kernel/ptrace.c 2006-08-01 20:29:45.000000000 -0400
1965@@ -17,6 +17,7 @@
1966 #include <linux/audit.h>
1967 #include <linux/seccomp.h>
1968 #include <linux/signal.h>
1969+#include <linux/grsecurity.h>
1970
1971 #include <asm/uaccess.h>
1972 #include <asm/pgtable.h>
1973@@ -342,6 +343,11 @@ ptrace_set_thread_area(struct task_struc
1974 if (copy_from_user(&info, user_desc, sizeof(info)))
1975 return -EFAULT;
1976
1977+#ifdef CONFIG_PAX_SEGMEXEC
1978+ if ((child->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
1979+ return -EINVAL;
1980+#endif
1981+
1982 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
1983 return -EINVAL;
1984
1985@@ -432,6 +438,17 @@ long arch_ptrace(struct task_struct *chi
1986 if(addr == (long) &dummy->u_debugreg[5]) break;
1987 if(addr < (long) &dummy->u_debugreg[4] &&
1988 ((unsigned long) data) >= TASK_SIZE-3) break;
1989+
1990+#ifdef CONFIG_GRKERNSEC
1991+ if(addr >= (long) &dummy->u_debugreg[0] &&
1992+ addr <= (long) &dummy->u_debugreg[3]){
1993+ long reg = (addr - (long) &dummy->u_debugreg[0]) >> 2;
1994+ long type = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 4*reg)) & 3;
1995+ long align = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 2 + 4*reg)) & 3;
1996+ if((type & 1) && (data & align))
1997+ break;
1998+ }
1999+#endif
2000
2001 /* Sanity-check data. Take one half-byte at once with
2002 * check = (val >> (16 + 4*i)) & 0xf. It contains the
2003@@ -645,7 +662,7 @@ void send_sigtrap(struct task_struct *ts
2004 info.si_code = TRAP_BRKPT;
2005
2006 /* User-mode eip? */
2007- info.si_addr = user_mode_vm(regs) ? (void __user *) regs->eip : NULL;
2008+ info.si_addr = user_mode(regs) ? (void __user *) regs->eip : NULL;
2009
2010 /* Send us the fakey SIGTRAP */
2011 force_sig_info(SIGTRAP, &info, tsk);
2012diff -urNp linux-2.6.17.7/arch/i386/kernel/reboot.c linux-2.6.17.7/arch/i386/kernel/reboot.c
2013--- linux-2.6.17.7/arch/i386/kernel/reboot.c 2006-07-24 23:36:01.000000000 -0400
2014+++ linux-2.6.17.7/arch/i386/kernel/reboot.c 2006-08-01 20:29:45.000000000 -0400
2015@@ -138,18 +138,18 @@ core_initcall(reboot_init);
2016 doesn't work with at least one type of 486 motherboard. It is easy
2017 to stop this code working; hence the copious comments. */
2018
2019-static unsigned long long
2020+static const unsigned long long
2021 real_mode_gdt_entries [3] =
2022 {
2023 0x0000000000000000ULL, /* Null descriptor */
2024- 0x00009a000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */
2025- 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
2026+ 0x00009b000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */
2027+ 0x000093000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
2028 };
2029
2030 static struct
2031 {
2032 unsigned short size __attribute__ ((packed));
2033- unsigned long long * base __attribute__ ((packed));
2034+ const unsigned long long * base __attribute__ ((packed));
2035 }
2036 real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries },
2037 real_mode_idt = { 0x3ff, NULL },
2038@@ -203,6 +203,10 @@ void machine_real_restart(unsigned char
2039 {
2040 unsigned long flags;
2041
2042+#ifdef CONFIG_PAX_KERNEXEC
2043+ unsigned long cr0;
2044+#endif
2045+
2046 local_irq_disable();
2047
2048 /* Write zero to CMOS register number 0x0f, which the BIOS POST
2049@@ -223,9 +227,17 @@ void machine_real_restart(unsigned char
2050 from the kernel segment. This assumes the kernel segment starts at
2051 virtual address PAGE_OFFSET. */
2052
2053+#ifdef CONFIG_PAX_KERNEXEC
2054+ pax_open_kernel(cr0);
2055+#endif
2056+
2057 memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
2058 sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
2059
2060+#ifdef CONFIG_PAX_KERNEXEC
2061+ pax_close_kernel(cr0);
2062+#endif
2063+
2064 /*
2065 * Use `swapper_pg_dir' as our page directory.
2066 */
2067diff -urNp linux-2.6.17.7/arch/i386/kernel/setup.c linux-2.6.17.7/arch/i386/kernel/setup.c
2068--- linux-2.6.17.7/arch/i386/kernel/setup.c 2006-07-24 23:36:01.000000000 -0400
2069+++ linux-2.6.17.7/arch/i386/kernel/setup.c 2006-08-01 20:29:45.000000000 -0400
2070@@ -88,7 +88,11 @@ struct cpuinfo_x86 new_cpu_data __initda
2071 struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
2072 EXPORT_SYMBOL(boot_cpu_data);
2073
2074+#ifdef CONFIG_X86_PAE
2075+unsigned long mmu_cr4_features = X86_CR4_PAE;
2076+#else
2077 unsigned long mmu_cr4_features;
2078+#endif
2079
2080 #ifdef CONFIG_ACPI
2081 int acpi_disabled = 0;
2082@@ -1493,14 +1497,14 @@ void __init setup_arch(char **cmdline_p)
2083
2084 if (!MOUNT_ROOT_RDONLY)
2085 root_mountflags &= ~MS_RDONLY;
2086- init_mm.start_code = (unsigned long) _text;
2087- init_mm.end_code = (unsigned long) _etext;
2088+ init_mm.start_code = (unsigned long) _text + __KERNEL_TEXT_OFFSET;
2089+ init_mm.end_code = (unsigned long) _etext + __KERNEL_TEXT_OFFSET;
2090 init_mm.end_data = (unsigned long) _edata;
2091 init_mm.brk = init_pg_tables_end + PAGE_OFFSET;
2092
2093- code_resource.start = virt_to_phys(_text);
2094- code_resource.end = virt_to_phys(_etext)-1;
2095- data_resource.start = virt_to_phys(_etext);
2096+ code_resource.start = virt_to_phys(_text + __KERNEL_TEXT_OFFSET);
2097+ code_resource.end = virt_to_phys(_etext + __KERNEL_TEXT_OFFSET)-1;
2098+ data_resource.start = virt_to_phys(_data);
2099 data_resource.end = virt_to_phys(_edata)-1;
2100
2101 parse_cmdline_early(cmdline_p);
2102diff -urNp linux-2.6.17.7/arch/i386/kernel/signal.c linux-2.6.17.7/arch/i386/kernel/signal.c
2103--- linux-2.6.17.7/arch/i386/kernel/signal.c 2006-07-24 23:36:01.000000000 -0400
2104+++ linux-2.6.17.7/arch/i386/kernel/signal.c 2006-08-01 20:29:45.000000000 -0400
2105@@ -351,7 +351,17 @@ static int setup_frame(int sig, struct k
2106 goto give_sigsegv;
2107 }
2108
2109+#ifdef CONFIG_PAX_NOVSYSCALL
2110+ restorer = frame->retcode;
2111+#else
2112 restorer = &__kernel_sigreturn;
2113+
2114+#ifdef CONFIG_PAX_SEGMEXEC
2115+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
2116+ restorer -= SEGMEXEC_TASK_SIZE;
2117+#endif
2118+#endif
2119+
2120 if (ka->sa.sa_flags & SA_RESTORER)
2121 restorer = ka->sa.sa_restorer;
2122
2123@@ -447,7 +457,18 @@ static int setup_rt_frame(int sig, struc
2124 goto give_sigsegv;
2125
2126 /* Set up to return from userspace. */
2127+
2128+#ifdef CONFIG_PAX_NOVSYSCALL
2129+ restorer = frame->retcode;
2130+#else
2131 restorer = &__kernel_rt_sigreturn;
2132+
2133+#ifdef CONFIG_PAX_SEGMEXEC
2134+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
2135+ restorer -= SEGMEXEC_TASK_SIZE;
2136+#endif
2137+#endif
2138+
2139 if (ka->sa.sa_flags & SA_RESTORER)
2140 restorer = ka->sa.sa_restorer;
2141 err |= __put_user(restorer, &frame->pretcode);
2142@@ -580,7 +601,7 @@ static void fastcall do_signal(struct pt
2143 * before reaching here, so testing against kernel
2144 * CS suffices.
2145 */
2146- if (!user_mode(regs))
2147+ if (!user_mode_novm(regs))
2148 return;
2149
2150 if (test_thread_flag(TIF_RESTORE_SIGMASK))
2151diff -urNp linux-2.6.17.7/arch/i386/kernel/sys_i386.c linux-2.6.17.7/arch/i386/kernel/sys_i386.c
2152--- linux-2.6.17.7/arch/i386/kernel/sys_i386.c 2006-07-24 23:36:01.000000000 -0400
2153+++ linux-2.6.17.7/arch/i386/kernel/sys_i386.c 2006-08-01 20:29:45.000000000 -0400
2154@@ -99,6 +99,191 @@ out:
2155 return err;
2156 }
2157
2158+unsigned long
2159+arch_get_unmapped_area(struct file *filp, unsigned long addr,
2160+ unsigned long len, unsigned long pgoff, unsigned long flags)
2161+{
2162+ struct mm_struct *mm = current->mm;
2163+ struct vm_area_struct *vma;
2164+ unsigned long start_addr, task_size = TASK_SIZE;
2165+
2166+#ifdef CONFIG_PAX_SEGMEXEC
2167+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
2168+ task_size = SEGMEXEC_TASK_SIZE;
2169+#endif
2170+
2171+ if (len > task_size)
2172+ return -ENOMEM;
2173+
2174+#ifdef CONFIG_PAX_RANDMMAP
2175+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
2176+#endif
2177+
2178+ if (addr) {
2179+ addr = PAGE_ALIGN(addr);
2180+ vma = find_vma(mm, addr);
2181+ if (task_size - len >= addr &&
2182+ (!vma || addr + len <= vma->vm_start))
2183+ return addr;
2184+ }
2185+ if (len > mm->cached_hole_size) {
2186+ start_addr = addr = mm->free_area_cache;
2187+ } else {
2188+ start_addr = addr = mm->mmap_base;
2189+ mm->cached_hole_size = 0;
2190+ }
2191+
2192+#ifdef CONFIG_PAX_PAGEEXEC
2193+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE) && start_addr >= mm->mmap_base) {
2194+ start_addr = 0x00110000UL;
2195+
2196+#ifdef CONFIG_PAX_RANDMMAP
2197+ if (mm->pax_flags & MF_PAX_RANDMMAP)
2198+ start_addr += mm->delta_mmap & 0x03FFF000UL;
2199+#endif
2200+
2201+ if (mm->start_brk <= start_addr && start_addr < mm->mmap_base)
2202+ start_addr = addr = mm->mmap_base;
2203+ else
2204+ addr = start_addr;
2205+ }
2206+#endif
2207+
2208+full_search:
2209+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
2210+ /* At this point: (!vma || addr < vma->vm_end). */
2211+ if (task_size - len < addr) {
2212+ /*
2213+ * Start a new search - just in case we missed
2214+ * some holes.
2215+ */
2216+ if (start_addr != mm->mmap_base) {
2217+ start_addr = addr = mm->mmap_base;
2218+ mm->cached_hole_size = 0;
2219+ goto full_search;
2220+ }
2221+ return -ENOMEM;
2222+ }
2223+ if (!vma || addr + len <= vma->vm_start) {
2224+ /*
2225+ * Remember the place where we stopped the search:
2226+ */
2227+ mm->free_area_cache = addr + len;
2228+ return addr;
2229+ }
2230+ if (addr + mm->cached_hole_size < vma->vm_start)
2231+ mm->cached_hole_size = vma->vm_start - addr;
2232+ addr = vma->vm_end;
2233+ if (mm->start_brk <= addr && addr < mm->mmap_base) {
2234+ start_addr = addr = mm->mmap_base;
2235+ goto full_search;
2236+ }
2237+ }
2238+}
2239+
2240+unsigned long
2241+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
2242+ const unsigned long len, const unsigned long pgoff,
2243+ const unsigned long flags)
2244+{
2245+ struct vm_area_struct *vma;
2246+ struct mm_struct *mm = current->mm;
2247+ unsigned long base = mm->mmap_base, addr = addr0, task_size = TASK_SIZE;
2248+
2249+#ifdef CONFIG_PAX_SEGMEXEC
2250+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
2251+ task_size = SEGMEXEC_TASK_SIZE;
2252+#endif
2253+
2254+ /* requested length too big for entire address space */
2255+ if (len > task_size)
2256+ return -ENOMEM;
2257+
2258+#ifdef CONFIG_PAX_PAGEEXEC
2259+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE))
2260+ goto bottomup;
2261+#endif
2262+
2263+#ifdef CONFIG_PAX_RANDMMAP
2264+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
2265+#endif
2266+
2267+ /* requesting a specific address */
2268+ if (addr) {
2269+ addr = PAGE_ALIGN(addr);
2270+ vma = find_vma(mm, addr);
2271+ if (task_size - len >= addr &&
2272+ (!vma || addr + len <= vma->vm_start))
2273+ return addr;
2274+ }
2275+
2276+ /* check if free_area_cache is useful for us */
2277+ if (len <= mm->cached_hole_size) {
2278+ mm->cached_hole_size = 0;
2279+ mm->free_area_cache = mm->mmap_base;
2280+ }
2281+
2282+ /* either no address requested or can't fit in requested address hole */
2283+ addr = mm->free_area_cache;
2284+
2285+ /* make sure it can fit in the remaining address space */
2286+ if (addr > len) {
2287+ vma = find_vma(mm, addr-len);
2288+ if (!vma || addr <= vma->vm_start)
2289+ /* remember the address as a hint for next time */
2290+ return (mm->free_area_cache = addr-len);
2291+ }
2292+
2293+ if (mm->mmap_base < len)
2294+ goto bottomup;
2295+
2296+ addr = mm->mmap_base-len;
2297+
2298+ do {
2299+ /*
2300+ * Lookup failure means no vma is above this address,
2301+ * else if new region fits below vma->vm_start,
2302+ * return with success:
2303+ */
2304+ vma = find_vma(mm, addr);
2305+ if (!vma || addr+len <= vma->vm_start)
2306+ /* remember the address as a hint for next time */
2307+ return (mm->free_area_cache = addr);
2308+
2309+ /* remember the largest hole we saw so far */
2310+ if (addr + mm->cached_hole_size < vma->vm_start)
2311+ mm->cached_hole_size = vma->vm_start - addr;
2312+
2313+ /* try just below the current vma->vm_start */
2314+ addr = vma->vm_start-len;
2315+ } while (len < vma->vm_start);
2316+
2317+bottomup:
2318+ /*
2319+ * A failed mmap() very likely causes application failure,
2320+ * so fall back to the bottom-up function here. This scenario
2321+ * can happen with large stack limits and large mmap()
2322+ * allocations.
2323+ */
2324+ mm->mmap_base = TASK_UNMAPPED_BASE;
2325+
2326+#ifdef CONFIG_PAX_RANDMMAP
2327+ if (mm->pax_flags & MF_PAX_RANDMMAP)
2328+ mm->mmap_base += mm->delta_mmap;
2329+#endif
2330+
2331+ mm->free_area_cache = mm->mmap_base;
2332+ mm->cached_hole_size = ~0UL;
2333+ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
2334+ /*
2335+ * Restore the topdown base:
2336+ */
2337+ mm->mmap_base = base;
2338+ mm->free_area_cache = base;
2339+ mm->cached_hole_size = ~0UL;
2340+
2341+ return addr;
2342+}
2343
2344 struct sel_arg_struct {
2345 unsigned long n;
2346diff -urNp linux-2.6.17.7/arch/i386/kernel/syscall_table.S linux-2.6.17.7/arch/i386/kernel/syscall_table.S
2347--- linux-2.6.17.7/arch/i386/kernel/syscall_table.S 2006-07-24 23:36:01.000000000 -0400
2348+++ linux-2.6.17.7/arch/i386/kernel/syscall_table.S 2006-08-01 20:29:45.000000000 -0400
2349@@ -1,3 +1,4 @@
2350+.section .rodata,"a",@progbits
2351 ENTRY(sys_call_table)
2352 .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
2353 .long sys_exit
2354diff -urNp linux-2.6.17.7/arch/i386/kernel/sysenter.c linux-2.6.17.7/arch/i386/kernel/sysenter.c
2355--- linux-2.6.17.7/arch/i386/kernel/sysenter.c 2006-07-24 23:36:01.000000000 -0400
2356+++ linux-2.6.17.7/arch/i386/kernel/sysenter.c 2006-08-01 20:29:45.000000000 -0400
2357@@ -24,7 +24,7 @@ extern asmlinkage void sysenter_entry(vo
2358 void enable_sep_cpu(void)
2359 {
2360 int cpu = get_cpu();
2361- struct tss_struct *tss = &per_cpu(init_tss, cpu);
2362+ struct tss_struct *tss = init_tss + cpu;
2363
2364 if (!boot_cpu_has(X86_FEATURE_SEP)) {
2365 put_cpu();
2366@@ -48,6 +48,7 @@ extern const char vsyscall_sysenter_star
2367
2368 int __init sysenter_setup(void)
2369 {
2370+#ifndef CONFIG_PAX_NOVSYSCALL
2371 void *page = (void *)get_zeroed_page(GFP_ATOMIC);
2372
2373 __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
2374@@ -62,6 +63,7 @@ int __init sysenter_setup(void)
2375 memcpy(page,
2376 &vsyscall_sysenter_start,
2377 &vsyscall_sysenter_end - &vsyscall_sysenter_start);
2378+#endif
2379
2380 return 0;
2381 }
2382diff -urNp linux-2.6.17.7/arch/i386/kernel/traps.c linux-2.6.17.7/arch/i386/kernel/traps.c
2383--- linux-2.6.17.7/arch/i386/kernel/traps.c 2006-07-24 23:36:01.000000000 -0400
2384+++ linux-2.6.17.7/arch/i386/kernel/traps.c 2006-08-01 20:29:45.000000000 -0400
2385@@ -28,6 +28,7 @@
2386 #include <linux/utsname.h>
2387 #include <linux/kprobes.h>
2388 #include <linux/kexec.h>
2389+#include <linux/binfmts.h>
2390
2391 #ifdef CONFIG_EISA
2392 #include <linux/ioport.h>
2393@@ -58,18 +59,13 @@
2394
2395 asmlinkage int system_call(void);
2396
2397-struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
2398+const struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
2399 { 0, 0 }, { 0, 0 } };
2400
2401 /* Do we ignore FPU interrupts ? */
2402 char ignore_fpu_irq = 0;
2403
2404-/*
2405- * The IDT has to be page-aligned to simplify the Pentium
2406- * F0 0F bug workaround.. We have a special link segment
2407- * for this.
2408- */
2409-struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
2410+extern struct desc_struct idt_table[256];
2411
2412 asmlinkage void divide_error(void);
2413 asmlinkage void debug(void);
2414@@ -144,18 +140,22 @@ static inline unsigned long print_contex
2415 {
2416 unsigned long addr;
2417 int printed = 0; /* nr of entries already printed on current line */
2418+ int i = kstack_depth_to_print;
2419
2420 #ifdef CONFIG_FRAME_POINTER
2421 while (valid_stack_ptr(tinfo, (void *)ebp)) {
2422 addr = *(unsigned long *)(ebp + 4);
2423 printed = print_addr_and_symbol(addr, log_lvl, printed);
2424 ebp = *(unsigned long *)ebp;
2425+ --i;
2426 }
2427 #else
2428 while (valid_stack_ptr(tinfo, stack)) {
2429 addr = *stack++;
2430- if (__kernel_text_address(addr))
2431+ if (__kernel_text_address(addr)) {
2432 printed = print_addr_and_symbol(addr, log_lvl, printed);
2433+ --i;
2434+ }
2435 }
2436 #endif
2437 if (printed)
2438@@ -249,7 +249,7 @@ void show_registers(struct pt_regs *regs
2439
2440 esp = (unsigned long) (&regs->esp);
2441 savesegment(ss, ss);
2442- if (user_mode_vm(regs)) {
2443+ if (user_mode(regs)) {
2444 in_kernel = 0;
2445 esp = regs->esp;
2446 ss = regs->xss & 0xffff;
2447@@ -276,13 +276,15 @@ void show_registers(struct pt_regs *regs
2448 */
2449 if (in_kernel) {
2450 u8 __user *eip;
2451+ mm_segment_t old_fs = get_fs();
2452
2453 printk("\n" KERN_EMERG "Stack: ");
2454 show_stack_log_lvl(NULL, (unsigned long *)esp, KERN_EMERG);
2455
2456 printk(KERN_EMERG "Code: ");
2457
2458- eip = (u8 __user *)regs->eip - 43;
2459+ set_fs(KERNEL_DS);
2460+ eip = (u8 __user *)regs->eip - 43 + __KERNEL_TEXT_OFFSET;
2461 for (i = 0; i < 64; i++, eip++) {
2462 unsigned char c;
2463
2464@@ -290,11 +292,12 @@ void show_registers(struct pt_regs *regs
2465 printk(" Bad EIP value.");
2466 break;
2467 }
2468- if (eip == (u8 __user *)regs->eip)
2469+ if (eip == (u8 __user *)regs->eip + __KERNEL_TEXT_OFFSET)
2470 printk("<%02x> ", c);
2471 else
2472 printk("%02x ", c);
2473 }
2474+ set_fs(old_fs);
2475 }
2476 printk("\n");
2477 }
2478@@ -306,9 +309,11 @@ static void handle_BUG(struct pt_regs *r
2479 char *file;
2480 char c;
2481 unsigned long eip;
2482+ mm_segment_t old_fs = get_fs();
2483
2484- eip = regs->eip;
2485+ eip = regs->eip + __KERNEL_TEXT_OFFSET;
2486
2487+ set_fs(KERNEL_DS);
2488 if (eip < PAGE_OFFSET)
2489 goto no_bug;
2490 if (__get_user(ud2, (unsigned short __user *)eip))
2491@@ -325,10 +330,12 @@ static void handle_BUG(struct pt_regs *r
2492 printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line);
2493
2494 no_bug:
2495+ set_fs(old_fs);
2496 return;
2497
2498 /* Here we know it was a BUG but file-n-line is unavailable */
2499 bug:
2500+ set_fs(old_fs);
2501 printk(KERN_EMERG "Kernel BUG\n");
2502 }
2503
2504@@ -430,7 +437,7 @@ void die(const char * str, struct pt_reg
2505
2506 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
2507 {
2508- if (!user_mode_vm(regs))
2509+ if (!user_mode(regs))
2510 die(str, regs, err);
2511 }
2512
2513@@ -448,7 +455,7 @@ static void __kprobes do_trap(int trapnr
2514 goto trap_signal;
2515 }
2516
2517- if (!user_mode(regs))
2518+ if (!user_mode_novm(regs))
2519 goto kernel_trap;
2520
2521 trap_signal: {
2522@@ -536,7 +543,7 @@ fastcall void __kprobes do_general_prote
2523 long error_code)
2524 {
2525 int cpu = get_cpu();
2526- struct tss_struct *tss = &per_cpu(init_tss, cpu);
2527+ struct tss_struct *tss = &init_tss[cpu];
2528 struct thread_struct *thread = &current->thread;
2529
2530 /*
2531@@ -572,9 +579,25 @@ fastcall void __kprobes do_general_prote
2532 if (regs->eflags & VM_MASK)
2533 goto gp_in_vm86;
2534
2535- if (!user_mode(regs))
2536+ if (!user_mode_novm(regs))
2537 goto gp_in_kernel;
2538
2539+#ifdef CONFIG_PAX_PAGEEXEC
2540+ if (current->mm && (current->mm->pax_flags & MF_PAX_PAGEEXEC)) {
2541+ struct mm_struct *mm = current->mm;
2542+ unsigned long limit;
2543+
2544+ down_write(&mm->mmap_sem);
2545+ limit = mm->context.user_cs_limit;
2546+ if (limit < TASK_SIZE) {
2547+ track_exec_limit(mm, limit, TASK_SIZE, PROT_EXEC);
2548+ up_write(&mm->mmap_sem);
2549+ return;
2550+ }
2551+ up_write(&mm->mmap_sem);
2552+ }
2553+#endif
2554+
2555 current->thread.error_code = error_code;
2556 current->thread.trap_no = 13;
2557 force_sig(SIGSEGV, current);
2558@@ -590,6 +613,13 @@ gp_in_kernel:
2559 if (notify_die(DIE_GPF, "general protection fault", regs,
2560 error_code, 13, SIGSEGV) == NOTIFY_STOP)
2561 return;
2562+
2563+#ifdef CONFIG_PAX_KERNEXEC
2564+ if ((regs->xcs & 0xFFFF) == __KERNEL_CS)
2565+ die("PAX: suspicious general protection fault", regs, error_code);
2566+ else
2567+#endif
2568+
2569 die("general protection fault", regs, error_code);
2570 }
2571 }
2572@@ -663,7 +693,7 @@ void die_nmi (struct pt_regs *regs, cons
2573 /* If we are in kernel we are probably nested up pretty bad
2574 * and might aswell get out now while we still can.
2575 */
2576- if (!user_mode_vm(regs)) {
2577+ if (!user_mode(regs)) {
2578 current->thread.trap_no = 2;
2579 crash_kexec(regs);
2580 }
2581@@ -816,7 +846,7 @@ fastcall void __kprobes do_debug(struct
2582 * check for kernel mode by just checking the CPL
2583 * of CS.
2584 */
2585- if (!user_mode(regs))
2586+ if (!user_mode_novm(regs))
2587 goto clear_TF_reenable;
2588 }
2589
2590@@ -1106,7 +1136,19 @@ do { \
2591 */
2592 void set_intr_gate(unsigned int n, void *addr)
2593 {
2594+
2595+#ifdef CONFIG_PAX_KERNEXEC
2596+ unsigned long cr0;
2597+
2598+ pax_open_kernel(cr0);
2599+#endif
2600+
2601 _set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
2602+
2603+#ifdef CONFIG_PAX_KERNEXEC
2604+ pax_close_kernel(cr0);
2605+#endif
2606+
2607 }
2608
2609 /*
2610diff -urNp linux-2.6.17.7/arch/i386/kernel/vm86.c linux-2.6.17.7/arch/i386/kernel/vm86.c
2611--- linux-2.6.17.7/arch/i386/kernel/vm86.c 2006-07-24 23:36:01.000000000 -0400
2612+++ linux-2.6.17.7/arch/i386/kernel/vm86.c 2006-08-01 20:29:45.000000000 -0400
2613@@ -123,7 +123,7 @@ struct pt_regs * fastcall save_v86_state
2614 do_exit(SIGSEGV);
2615 }
2616
2617- tss = &per_cpu(init_tss, get_cpu());
2618+ tss = init_tss + get_cpu();
2619 current->thread.esp0 = current->thread.saved_esp0;
2620 current->thread.sysenter_cs = __KERNEL_CS;
2621 load_esp0(tss, &current->thread);
2622@@ -297,7 +297,7 @@ static void do_sys_vm86(struct kernel_vm
2623 savesegment(fs, tsk->thread.saved_fs);
2624 savesegment(gs, tsk->thread.saved_gs);
2625
2626- tss = &per_cpu(init_tss, get_cpu());
2627+ tss = init_tss + get_cpu();
2628 tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
2629 if (cpu_has_sep)
2630 tsk->thread.sysenter_cs = 0;
2631diff -urNp linux-2.6.17.7/arch/i386/kernel/vmlinux.lds.S linux-2.6.17.7/arch/i386/kernel/vmlinux.lds.S
2632--- linux-2.6.17.7/arch/i386/kernel/vmlinux.lds.S 2006-07-24 23:36:01.000000000 -0400
2633+++ linux-2.6.17.7/arch/i386/kernel/vmlinux.lds.S 2006-08-01 20:29:45.000000000 -0400
2634@@ -4,10 +4,19 @@
2635
2636 #define LOAD_OFFSET __PAGE_OFFSET
2637
2638+#include <linux/config.h>
2639+
2640 #include <asm-generic/vmlinux.lds.h>
2641 #include <asm/thread_info.h>
2642 #include <asm/page.h>
2643 #include <asm/cache.h>
2644+#include <asm/segment.h>
2645+
2646+#ifdef CONFIG_X86_PAE
2647+#define PMD_SHIFT 21
2648+#else
2649+#define PMD_SHIFT 22
2650+#endif
2651
2652 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
2653 OUTPUT_ARCH(i386)
2654@@ -16,59 +25,14 @@ jiffies = jiffies_64;
2655 SECTIONS
2656 {
2657 . = __KERNEL_START;
2658- phys_startup_32 = startup_32 - LOAD_OFFSET;
2659- /* read-only */
2660- _text = .; /* Text and read-only data */
2661- .text : AT(ADDR(.text) - LOAD_OFFSET) {
2662- *(.text)
2663- SCHED_TEXT
2664- LOCK_TEXT
2665- KPROBES_TEXT
2666- *(.fixup)
2667- *(.gnu.warning)
2668- } = 0x9090
2669-
2670- _etext = .; /* End of text section */
2671-
2672- . = ALIGN(16); /* Exception table */
2673- __start___ex_table = .;
2674- __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
2675- __stop___ex_table = .;
2676-
2677- RODATA
2678+ phys_startup_32 = startup_32 - LOAD_OFFSET + __KERNEL_TEXT_OFFSET;
2679
2680- /* writeable */
2681- .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
2682- *(.data)
2683- CONSTRUCTORS
2684+ .text.startup : AT(ADDR(.text.startup) - LOAD_OFFSET) {
2685+ BYTE(0xEA) /* jmp far */
2686+ LONG(phys_startup_32)
2687+ SHORT(__BOOT_CS)
2688 }
2689
2690- . = ALIGN(4096);
2691- __nosave_begin = .;
2692- .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
2693- . = ALIGN(4096);
2694- __nosave_end = .;
2695-
2696- . = ALIGN(4096);
2697- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
2698- *(.data.idt)
2699- }
2700-
2701- . = ALIGN(32);
2702- .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
2703- *(.data.cacheline_aligned)
2704- }
2705-
2706- /* rarely changed data like cpu maps */
2707- . = ALIGN(32);
2708- .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
2709- _edata = .; /* End of data section */
2710-
2711- . = ALIGN(THREAD_SIZE); /* init_task */
2712- .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
2713- *(.data.init_task)
2714- }
2715-
2716 /* might get freed after init */
2717 . = ALIGN(4096);
2718 __smp_alt_begin = .;
2719@@ -92,11 +56,6 @@ SECTIONS
2720 /* will be freed after init */
2721 . = ALIGN(4096); /* Init code and data */
2722 __init_begin = .;
2723- .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
2724- _sinittext = .;
2725- *(.init.text)
2726- _einittext = .;
2727- }
2728 .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
2729 . = ALIGN(16);
2730 __setup_start = .;
2731@@ -128,9 +87,7 @@ SECTIONS
2732 .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
2733 *(.altinstr_replacement)
2734 }
2735- /* .exit.text is discard at runtime, not link time, to deal with references
2736- from .altinstructions and .eh_frame */
2737- .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
2738+
2739 .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
2740 . = ALIGN(4096);
2741 __initramfs_start = .;
2742@@ -140,10 +97,108 @@ SECTIONS
2743 __per_cpu_start = .;
2744 .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
2745 __per_cpu_end = .;
2746+
2747+ /* read-only */
2748+
2749 . = ALIGN(4096);
2750- __init_end = .;
2751+ .init.text (. - __KERNEL_TEXT_OFFSET) : AT(ADDR(.init.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
2752+ _sinittext = .;
2753+ *(.init.text)
2754+ _einittext = .;
2755+ }
2756+
2757+ /* .exit.text is discard at runtime, not link time, to deal with references
2758+ from .altinstructions and .eh_frame */
2759+ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { *(.exit.text) }
2760+
2761+#ifdef CONFIG_PAX_KERNEXEC
2762+ .text.align : AT(ADDR(.text.align) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
2763+ . = ALIGN(__KERNEL_TEXT_OFFSET - LOAD_OFFSET) - 1;
2764+ BYTE(0)
2765+ }
2766+#else
2767+ . = ALIGN(4096);
2768+#endif
2769+
2770+ __init_end = . + __KERNEL_TEXT_OFFSET;
2771 /* freed after init ends here */
2772-
2773+
2774+ _text = .; /* Text and read-only data */
2775+ .text : AT(ADDR(.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
2776+ *(.text)
2777+ SCHED_TEXT
2778+ LOCK_TEXT
2779+ KPROBES_TEXT
2780+ *(.fixup)
2781+ *(.gnu.warning)
2782+ } = 0x9090
2783+
2784+ _etext = .; /* End of text section */
2785+ . += __KERNEL_TEXT_OFFSET;
2786+ . = ALIGN(16); /* Exception table */
2787+ __start___ex_table = .;
2788+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
2789+ __stop___ex_table = .;
2790+
2791+ . = ALIGN(4096);
2792+ .rodata.page_aligned : AT(ADDR(.rodata.page_aligned) - LOAD_OFFSET) {
2793+ *(.empty_zero_page)
2794+
2795+#ifdef CONFIG_X86_PAE
2796+ *(.swapper_pm_dir)
2797+#endif
2798+
2799+ *(.swapper_pg_dir)
2800+ *(.idt)
2801+ }
2802+
2803+ RODATA
2804+
2805+#ifdef CONFIG_PAX_KERNEXEC
2806+ . = ALIGN(4096);
2807+ MODULES_VADDR = .;
2808+
2809+ .module.text : AT(ADDR(.module.text) - LOAD_OFFSET) {
2810+ . += (4 * 1024 * 1024);
2811+ . = ALIGN(1 << PMD_SHIFT) - 1;
2812+ BYTE(0)
2813+ }
2814+
2815+ MODULES_END = .;
2816+#else
2817+ . = ALIGN(32);
2818+#endif
2819+
2820+ /* writeable */
2821+ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
2822+ _data = .;
2823+ *(.data)
2824+ CONSTRUCTORS
2825+ }
2826+
2827+ . = ALIGN(4096);
2828+ __nosave_begin = .;
2829+ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
2830+ . = ALIGN(4096);
2831+ __nosave_end = .;
2832+
2833+ . = ALIGN(32);
2834+ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
2835+ *(.data.cacheline_aligned)
2836+ }
2837+
2838+ /* rarely changed data like cpu maps */
2839+ . = ALIGN(32);
2840+ .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
2841+
2842+ . = ALIGN(THREAD_SIZE); /* init_task */
2843+ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
2844+ *(.data.init_task)
2845+ }
2846+
2847+ _edata = .; /* End of data section */
2848+
2849+ . = ALIGN(4096);
2850 __bss_start = .; /* BSS */
2851 .bss.page_aligned : AT(ADDR(.bss.page_aligned) - LOAD_OFFSET) {
2852 *(.bss.page_aligned)
2853diff -urNp linux-2.6.17.7/arch/i386/lib/checksum.S linux-2.6.17.7/arch/i386/lib/checksum.S
2854--- linux-2.6.17.7/arch/i386/lib/checksum.S 2006-07-24 23:36:01.000000000 -0400
2855+++ linux-2.6.17.7/arch/i386/lib/checksum.S 2006-08-01 20:29:45.000000000 -0400
2856@@ -27,7 +27,8 @@
2857
2858 #include <linux/config.h>
2859 #include <asm/errno.h>
2860-
2861+#include <asm/segment.h>
2862+
2863 /*
2864 * computes a partial checksum, e.g. for TCP/UDP fragments
2865 */
2866@@ -281,12 +282,23 @@ unsigned int csum_partial_copy_generic (
2867
2868 .align 4
2869 .globl csum_partial_copy_generic
2870-
2871+.globl csum_partial_copy_generic_to_user
2872+.globl csum_partial_copy_generic_from_user
2873+
2874 #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
2875
2876 #define ARGBASE 16
2877 #define FP 12
2878-
2879+
2880+csum_partial_copy_generic_to_user:
2881+ pushl $(__USER_DS)
2882+ popl %es
2883+ jmp csum_partial_copy_generic
2884+
2885+csum_partial_copy_generic_from_user:
2886+ pushl $(__USER_DS)
2887+ popl %ds
2888+
2889 csum_partial_copy_generic:
2890 subl $4,%esp
2891 pushl %edi
2892@@ -305,7 +317,7 @@ csum_partial_copy_generic:
2893 jmp 4f
2894 SRC(1: movw (%esi), %bx )
2895 addl $2, %esi
2896-DST( movw %bx, (%edi) )
2897+DST( movw %bx, %es:(%edi) )
2898 addl $2, %edi
2899 addw %bx, %ax
2900 adcl $0, %eax
2901@@ -317,30 +329,30 @@ DST( movw %bx, (%edi) )
2902 SRC(1: movl (%esi), %ebx )
2903 SRC( movl 4(%esi), %edx )
2904 adcl %ebx, %eax
2905-DST( movl %ebx, (%edi) )
2906+DST( movl %ebx, %es:(%edi) )
2907 adcl %edx, %eax
2908-DST( movl %edx, 4(%edi) )
2909+DST( movl %edx, %es:4(%edi) )
2910
2911 SRC( movl 8(%esi), %ebx )
2912 SRC( movl 12(%esi), %edx )
2913 adcl %ebx, %eax
2914-DST( movl %ebx, 8(%edi) )
2915+DST( movl %ebx, %es:8(%edi) )
2916 adcl %edx, %eax
2917-DST( movl %edx, 12(%edi) )
2918+DST( movl %edx, %es:12(%edi) )
2919
2920 SRC( movl 16(%esi), %ebx )
2921 SRC( movl 20(%esi), %edx )
2922 adcl %ebx, %eax
2923-DST( movl %ebx, 16(%edi) )
2924+DST( movl %ebx, %es:16(%edi) )
2925 adcl %edx, %eax
2926-DST( movl %edx, 20(%edi) )
2927+DST( movl %edx, %es:20(%edi) )
2928
2929 SRC( movl 24(%esi), %ebx )
2930 SRC( movl 28(%esi), %edx )
2931 adcl %ebx, %eax
2932-DST( movl %ebx, 24(%edi) )
2933+DST( movl %ebx, %es:24(%edi) )
2934 adcl %edx, %eax
2935-DST( movl %edx, 28(%edi) )
2936+DST( movl %edx, %es:28(%edi) )
2937
2938 lea 32(%esi), %esi
2939 lea 32(%edi), %edi
2940@@ -354,7 +366,7 @@ DST( movl %edx, 28(%edi) )
2941 shrl $2, %edx # This clears CF
2942 SRC(3: movl (%esi), %ebx )
2943 adcl %ebx, %eax
2944-DST( movl %ebx, (%edi) )
2945+DST( movl %ebx, %es:(%edi) )
2946 lea 4(%esi), %esi
2947 lea 4(%edi), %edi
2948 dec %edx
2949@@ -366,12 +378,12 @@ DST( movl %ebx, (%edi) )
2950 jb 5f
2951 SRC( movw (%esi), %cx )
2952 leal 2(%esi), %esi
2953-DST( movw %cx, (%edi) )
2954+DST( movw %cx, %es:(%edi) )
2955 leal 2(%edi), %edi
2956 je 6f
2957 shll $16,%ecx
2958 SRC(5: movb (%esi), %cl )
2959-DST( movb %cl, (%edi) )
2960+DST( movb %cl, %es:(%edi) )
2961 6: addl %ecx, %eax
2962 adcl $0, %eax
2963 7:
2964@@ -382,7 +394,7 @@ DST( movb %cl, (%edi) )
2965
2966 6001:
2967 movl ARGBASE+20(%esp), %ebx # src_err_ptr
2968- movl $-EFAULT, (%ebx)
2969+ movl $-EFAULT, %ss:(%ebx)
2970
2971 # zero the complete destination - computing the rest
2972 # is too much work
2973@@ -395,11 +407,15 @@ DST( movb %cl, (%edi) )
2974
2975 6002:
2976 movl ARGBASE+24(%esp), %ebx # dst_err_ptr
2977- movl $-EFAULT,(%ebx)
2978+ movl $-EFAULT,%ss:(%ebx)
2979 jmp 5000b
2980
2981 .previous
2982
2983+ pushl %ss
2984+ popl %ds
2985+ pushl %ss
2986+ popl %es
2987 popl %ebx
2988 popl %esi
2989 popl %edi
2990@@ -411,17 +427,28 @@ DST( movb %cl, (%edi) )
2991 /* Version for PentiumII/PPro */
2992
2993 #define ROUND1(x) \
2994+ nop; nop; nop; \
2995 SRC(movl x(%esi), %ebx ) ; \
2996 addl %ebx, %eax ; \
2997- DST(movl %ebx, x(%edi) ) ;
2998+ DST(movl %ebx, %es:x(%edi));
2999
3000 #define ROUND(x) \
3001+ nop; nop; nop; \
3002 SRC(movl x(%esi), %ebx ) ; \
3003 adcl %ebx, %eax ; \
3004- DST(movl %ebx, x(%edi) ) ;
3005+ DST(movl %ebx, %es:x(%edi));
3006
3007 #define ARGBASE 12
3008-
3009+
3010+csum_partial_copy_generic_to_user:
3011+ pushl $(__USER_DS)
3012+ popl %es
3013+ jmp csum_partial_copy_generic
3014+
3015+csum_partial_copy_generic_from_user:
3016+ pushl $(__USER_DS)
3017+ popl %ds
3018+
3019 csum_partial_copy_generic:
3020 pushl %ebx
3021 pushl %edi
3022@@ -440,7 +467,7 @@ csum_partial_copy_generic:
3023 subl %ebx, %edi
3024 lea -1(%esi),%edx
3025 andl $-32,%edx
3026- lea 3f(%ebx,%ebx), %ebx
3027+ lea 3f(%ebx,%ebx,2), %ebx
3028 testl %esi, %esi
3029 jmp *%ebx
3030 1: addl $64,%esi
3031@@ -461,19 +488,19 @@ csum_partial_copy_generic:
3032 jb 5f
3033 SRC( movw (%esi), %dx )
3034 leal 2(%esi), %esi
3035-DST( movw %dx, (%edi) )
3036+DST( movw %dx, %es:(%edi) )
3037 leal 2(%edi), %edi
3038 je 6f
3039 shll $16,%edx
3040 5:
3041 SRC( movb (%esi), %dl )
3042-DST( movb %dl, (%edi) )
3043+DST( movb %dl, %es:(%edi) )
3044 6: addl %edx, %eax
3045 adcl $0, %eax
3046 7:
3047 .section .fixup, "ax"
3048 6001: movl ARGBASE+20(%esp), %ebx # src_err_ptr
3049- movl $-EFAULT, (%ebx)
3050+ movl $-EFAULT, %ss:(%ebx)
3051 # zero the complete destination (computing the rest is too much work)
3052 movl ARGBASE+8(%esp),%edi # dst
3053 movl ARGBASE+12(%esp),%ecx # len
3054@@ -481,10 +508,14 @@ DST( movb %dl, (%edi) )
3055 rep; stosb
3056 jmp 7b
3057 6002: movl ARGBASE+24(%esp), %ebx # dst_err_ptr
3058- movl $-EFAULT, (%ebx)
3059+ movl $-EFAULT, %ss:(%ebx)
3060 jmp 7b
3061 .previous
3062
3063+ pushl %ss
3064+ popl %ds
3065+ pushl %ss
3066+ popl %es
3067 popl %esi
3068 popl %edi
3069 popl %ebx
3070diff -urNp linux-2.6.17.7/arch/i386/lib/getuser.S linux-2.6.17.7/arch/i386/lib/getuser.S
3071--- linux-2.6.17.7/arch/i386/lib/getuser.S 2006-07-24 23:36:01.000000000 -0400
3072+++ linux-2.6.17.7/arch/i386/lib/getuser.S 2006-08-01 20:29:45.000000000 -0400
3073@@ -9,6 +9,7 @@
3074 * return value.
3075 */
3076 #include <asm/thread_info.h>
3077+#include <asm/segment.h>
3078
3079
3080 /*
3081@@ -30,8 +31,12 @@ __get_user_1:
3082 GET_THREAD_INFO(%edx)
3083 cmpl TI_addr_limit(%edx),%eax
3084 jae bad_get_user
3085+ pushl $(__USER_DS)
3086+ popl %ds
3087 1: movzbl (%eax),%edx
3088 xorl %eax,%eax
3089+ pushl %ss
3090+ pop %ds
3091 ret
3092
3093 .align 4
3094@@ -42,7 +47,11 @@ __get_user_2:
3095 GET_THREAD_INFO(%edx)
3096 cmpl TI_addr_limit(%edx),%eax
3097 jae bad_get_user
3098+ pushl $(__USER_DS)
3099+ popl %ds
3100 2: movzwl -1(%eax),%edx
3101+ pushl %ss
3102+ pop %ds
3103 xorl %eax,%eax
3104 ret
3105
3106@@ -54,11 +63,17 @@ __get_user_4:
3107 GET_THREAD_INFO(%edx)
3108 cmpl TI_addr_limit(%edx),%eax
3109 jae bad_get_user
3110+ pushl $(__USER_DS)
3111+ popl %ds
3112 3: movl -3(%eax),%edx
3113+ pushl %ss
3114+ pop %ds
3115 xorl %eax,%eax
3116 ret
3117
3118 bad_get_user:
3119+ pushl %ss
3120+ pop %ds
3121 xorl %edx,%edx
3122 movl $-14,%eax
3123 ret
3124diff -urNp linux-2.6.17.7/arch/i386/lib/mmx.c linux-2.6.17.7/arch/i386/lib/mmx.c
3125--- linux-2.6.17.7/arch/i386/lib/mmx.c 2006-07-24 23:36:01.000000000 -0400
3126+++ linux-2.6.17.7/arch/i386/lib/mmx.c 2006-08-01 20:29:45.000000000 -0400
3127@@ -48,14 +48,30 @@ void *_mmx_memcpy(void *to, const void *
3128 " prefetch 256(%0)\n"
3129 "2: \n"
3130 ".section .fixup, \"ax\"\n"
3131- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3132+ "3: \n"
3133+
3134+#ifdef CONFIG_PAX_KERNEXEC
3135+ " cli\n"
3136+ " movl %%cr0, %%eax\n"
3137+ " andl $0xFFFEFFFF, %%eax\n"
3138+ " movl %%eax, %%cr0\n"
3139+#endif
3140+
3141+ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3142+
3143+#ifdef CONFIG_PAX_KERNEXEC
3144+ " orl $0x00010000, %%eax\n"
3145+ " movl %%eax, %%cr0\n"
3146+ " sti\n"
3147+#endif
3148+
3149 " jmp 2b\n"
3150 ".previous\n"
3151 ".section __ex_table,\"a\"\n"
3152 " .align 4\n"
3153 " .long 1b, 3b\n"
3154 ".previous"
3155- : : "r" (from) );
3156+ : : "r" (from) : "ax");
3157
3158
3159 for(; i>5; i--)
3160@@ -79,14 +95,30 @@ void *_mmx_memcpy(void *to, const void *
3161 " movq %%mm2, 48(%1)\n"
3162 " movq %%mm3, 56(%1)\n"
3163 ".section .fixup, \"ax\"\n"
3164- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3165+ "3:\n"
3166+
3167+#ifdef CONFIG_PAX_KERNEXEC
3168+ " cli\n"
3169+ " movl %%cr0, %%eax\n"
3170+ " andl $0xFFFEFFFF, %%eax\n"
3171+ " movl %%eax, %%cr0\n"
3172+#endif
3173+
3174+ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3175+
3176+#ifdef CONFIG_PAX_KERNEXEC
3177+ " orl $0x00010000, %%eax\n"
3178+ " movl %%eax, %%cr0\n"
3179+ " sti\n"
3180+#endif
3181+
3182 " jmp 2b\n"
3183 ".previous\n"
3184 ".section __ex_table,\"a\"\n"
3185 " .align 4\n"
3186 " .long 1b, 3b\n"
3187 ".previous"
3188- : : "r" (from), "r" (to) : "memory");
3189+ : : "r" (from), "r" (to) : "memory", "ax");
3190 from+=64;
3191 to+=64;
3192 }
3193@@ -179,14 +211,30 @@ static void fast_copy_page(void *to, voi
3194 " prefetch 256(%0)\n"
3195 "2: \n"
3196 ".section .fixup, \"ax\"\n"
3197- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3198+ "3: \n"
3199+
3200+#ifdef CONFIG_PAX_KERNEXEC
3201+ " cli\n"
3202+ " movl %%cr0, %%eax\n"
3203+ " andl $0xFFFEFFFF, %%eax\n"
3204+ " movl %%eax, %%cr0\n"
3205+#endif
3206+
3207+ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3208+
3209+#ifdef CONFIG_PAX_KERNEXEC
3210+ " orl $0x00010000, %%eax\n"
3211+ " movl %%eax, %%cr0\n"
3212+ " sti\n"
3213+#endif
3214+
3215 " jmp 2b\n"
3216 ".previous\n"
3217 ".section __ex_table,\"a\"\n"
3218 " .align 4\n"
3219 " .long 1b, 3b\n"
3220 ".previous"
3221- : : "r" (from) );
3222+ : : "r" (from) : "ax");
3223
3224 for(i=0; i<(4096-320)/64; i++)
3225 {
3226@@ -209,14 +257,30 @@ static void fast_copy_page(void *to, voi
3227 " movq 56(%0), %%mm7\n"
3228 " movntq %%mm7, 56(%1)\n"
3229 ".section .fixup, \"ax\"\n"
3230- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3231+ "3:\n"
3232+
3233+#ifdef CONFIG_PAX_KERNEXEC
3234+ " cli\n"
3235+ " movl %%cr0, %%eax\n"
3236+ " andl $0xFFFEFFFF, %%eax\n"
3237+ " movl %%eax, %%cr0\n"
3238+#endif
3239+
3240+ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3241+
3242+#ifdef CONFIG_PAX_KERNEXEC
3243+ " orl $0x00010000, %%eax\n"
3244+ " movl %%eax, %%cr0\n"
3245+ " sti\n"
3246+#endif
3247+
3248 " jmp 2b\n"
3249 ".previous\n"
3250 ".section __ex_table,\"a\"\n"
3251 " .align 4\n"
3252 " .long 1b, 3b\n"
3253 ".previous"
3254- : : "r" (from), "r" (to) : "memory");
3255+ : : "r" (from), "r" (to) : "memory", "ax");
3256 from+=64;
3257 to+=64;
3258 }
3259@@ -309,14 +373,30 @@ static void fast_copy_page(void *to, voi
3260 " prefetch 256(%0)\n"
3261 "2: \n"
3262 ".section .fixup, \"ax\"\n"
3263- "3: movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3264+ "3: \n"
3265+
3266+#ifdef CONFIG_PAX_KERNEXEC
3267+ " cli\n"
3268+ " movl %%cr0, %%eax\n"
3269+ " andl $0xFFFEFFFF, %%eax\n"
3270+ " movl %%eax, %%cr0\n"
3271+#endif
3272+
3273+ " movw $0x1AEB, 1b\n" /* jmp on 26 bytes */
3274+
3275+#ifdef CONFIG_PAX_KERNEXEC
3276+ " orl $0x00010000, %%eax\n"
3277+ " movl %%eax, %%cr0\n"
3278+ " sti\n"
3279+#endif
3280+
3281 " jmp 2b\n"
3282 ".previous\n"
3283 ".section __ex_table,\"a\"\n"
3284 " .align 4\n"
3285 " .long 1b, 3b\n"
3286 ".previous"
3287- : : "r" (from) );
3288+ : : "r" (from) : "ax");
3289
3290 for(i=0; i<4096/64; i++)
3291 {
3292@@ -339,14 +419,30 @@ static void fast_copy_page(void *to, voi
3293 " movq %%mm2, 48(%1)\n"
3294 " movq %%mm3, 56(%1)\n"
3295 ".section .fixup, \"ax\"\n"
3296- "3: movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3297+ "3:\n"
3298+
3299+#ifdef CONFIG_PAX_KERNEXEC
3300+ " cli\n"
3301+ " movl %%cr0, %%eax\n"
3302+ " andl $0xFFFEFFFF, %%eax\n"
3303+ " movl %%eax, %%cr0\n"
3304+#endif
3305+
3306+ " movw $0x05EB, 1b\n" /* jmp on 5 bytes */
3307+
3308+#ifdef CONFIG_PAX_KERNEXEC
3309+ " orl $0x00010000, %%eax\n"
3310+ " movl %%eax, %%cr0\n"
3311+ " sti\n"
3312+#endif
3313+
3314 " jmp 2b\n"
3315 ".previous\n"
3316 ".section __ex_table,\"a\"\n"
3317 " .align 4\n"
3318 " .long 1b, 3b\n"
3319 ".previous"
3320- : : "r" (from), "r" (to) : "memory");
3321+ : : "r" (from), "r" (to) : "memory", "ax");
3322 from+=64;
3323 to+=64;
3324 }
3325diff -urNp linux-2.6.17.7/arch/i386/lib/putuser.S linux-2.6.17.7/arch/i386/lib/putuser.S
3326--- linux-2.6.17.7/arch/i386/lib/putuser.S 2006-07-24 23:36:01.000000000 -0400
3327+++ linux-2.6.17.7/arch/i386/lib/putuser.S 2006-08-01 20:29:45.000000000 -0400
3328@@ -9,6 +9,7 @@
3329 * return value.
3330 */
3331 #include <asm/thread_info.h>
3332+#include <asm/segment.h>
3333
3334
3335 /*
3336@@ -33,7 +34,11 @@ __put_user_1:
3337 ENTER
3338 cmpl TI_addr_limit(%ebx),%ecx
3339 jae bad_put_user
3340+ pushl $(__USER_DS)
3341+ popl %ds
3342 1: movb %al,(%ecx)
3343+ pushl %ss
3344+ popl %ds
3345 xorl %eax,%eax
3346 EXIT
3347
3348@@ -45,7 +50,11 @@ __put_user_2:
3349 subl $1,%ebx
3350 cmpl %ebx,%ecx
3351 jae bad_put_user
3352+ pushl $(__USER_DS)
3353+ popl %ds
3354 2: movw %ax,(%ecx)
3355+ pushl %ss
3356+ popl %ds
3357 xorl %eax,%eax
3358 EXIT
3359
3360@@ -57,7 +66,11 @@ __put_user_4:
3361 subl $3,%ebx
3362 cmpl %ebx,%ecx
3363 jae bad_put_user
3364+ pushl $(__USER_DS)
3365+ popl %ds
3366 3: movl %eax,(%ecx)
3367+ pushl %ss
3368+ popl %ds
3369 xorl %eax,%eax
3370 EXIT
3371
3372@@ -69,12 +82,18 @@ __put_user_8:
3373 subl $7,%ebx
3374 cmpl %ebx,%ecx
3375 jae bad_put_user
3376+ pushl $(__USER_DS)
3377+ popl %ds
3378 4: movl %eax,(%ecx)
3379 5: movl %edx,4(%ecx)
3380+ pushl %ss
3381+ popl %ds
3382 xorl %eax,%eax
3383 EXIT
3384
3385 bad_put_user:
3386+ pushl %ss
3387+ popl %ds
3388 movl $-14,%eax
3389 EXIT
3390
3391diff -urNp linux-2.6.17.7/arch/i386/lib/usercopy.c linux-2.6.17.7/arch/i386/lib/usercopy.c
3392--- linux-2.6.17.7/arch/i386/lib/usercopy.c 2006-07-24 23:36:01.000000000 -0400
3393+++ linux-2.6.17.7/arch/i386/lib/usercopy.c 2006-08-01 20:29:45.000000000 -0400
3394@@ -33,6 +33,7 @@ do { \
3395 int __d0, __d1, __d2; \
3396 might_sleep(); \
3397 __asm__ __volatile__( \
3398+ " movw %w10,%%ds\n" \
3399 " testl %1,%1\n" \
3400 " jz 2f\n" \
3401 "0: lodsb\n" \
3402@@ -43,6 +44,8 @@ do { \
3403 " jnz 0b\n" \
3404 "1: subl %1,%0\n" \
3405 "2:\n" \
3406+ " pushl %%ss\n" \
3407+ " popl %%ds\n" \
3408 ".section .fixup,\"ax\"\n" \
3409 "3: movl %5,%0\n" \
3410 " jmp 2b\n" \
3411@@ -53,7 +56,8 @@ do { \
3412 ".previous" \
3413 : "=d"(res), "=c"(count), "=&a" (__d0), "=&S" (__d1), \
3414 "=&D" (__d2) \
3415- : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
3416+ : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst),\
3417+ "r"(__USER_DS) \
3418 : "memory"); \
3419 } while (0)
3420
3421@@ -123,10 +127,13 @@ do { \
3422 int __d0; \
3423 might_sleep(); \
3424 __asm__ __volatile__( \
3425+ " movw %w6,%%es\n" \
3426 "0: rep; stosl\n" \
3427 " movl %2,%0\n" \
3428 "1: rep; stosb\n" \
3429 "2:\n" \
3430+ " pushl %%ss\n" \
3431+ " popl %%es\n" \
3432 ".section .fixup,\"ax\"\n" \
3433 "3: lea 0(%2,%0,4),%0\n" \
3434 " jmp 2b\n" \
3435@@ -137,7 +144,8 @@ do { \
3436 " .long 1b,2b\n" \
3437 ".previous" \
3438 : "=&c"(size), "=&D" (__d0) \
3439- : "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0)); \
3440+ : "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0), \
3441+ "r"(__USER_DS)); \
3442 } while (0)
3443
3444 /**
3445@@ -198,14 +206,17 @@ long strnlen_user(const char __user *s,
3446 might_sleep();
3447
3448 __asm__ __volatile__(
3449+ " movw %w8,%%es\n"
3450 " testl %0, %0\n"
3451 " jz 3f\n"
3452- " andl %0,%%ecx\n"
3453+ " movl %0,%%ecx\n"
3454 "0: repne; scasb\n"
3455 " setne %%al\n"
3456 " subl %%ecx,%0\n"
3457 " addl %0,%%eax\n"
3458 "1:\n"
3459+ " pushl %%ss\n"
3460+ " popl %%es\n"
3461 ".section .fixup,\"ax\"\n"
3462 "2: xorl %%eax,%%eax\n"
3463 " jmp 1b\n"
3464@@ -217,7 +228,7 @@ long strnlen_user(const char __user *s,
3465 " .long 0b,2b\n"
3466 ".previous"
3467 :"=r" (n), "=D" (s), "=a" (res), "=c" (tmp)
3468- :"0" (n), "1" (s), "2" (0), "3" (mask)
3469+ :"0" (n), "1" (s), "2" (0), "3" (mask), "r" (__USER_DS)
3470 :"cc");
3471 return res & mask;
3472 }
3473@@ -229,6 +240,7 @@ __copy_user_intel(void __user *to, const
3474 {
3475 int d0, d1;
3476 __asm__ __volatile__(
3477+ " movw %w6, %%es\n"
3478 " .align 2,0x90\n"
3479 "1: movl 32(%4), %%eax\n"
3480 " cmpl $67, %0\n"
3481@@ -237,36 +249,36 @@ __copy_user_intel(void __user *to, const
3482 " .align 2,0x90\n"
3483 "3: movl 0(%4), %%eax\n"
3484 "4: movl 4(%4), %%edx\n"
3485- "5: movl %%eax, 0(%3)\n"
3486- "6: movl %%edx, 4(%3)\n"
3487+ "5: movl %%eax, %%es:0(%3)\n"
3488+ "6: movl %%edx, %%es:4(%3)\n"
3489 "7: movl 8(%4), %%eax\n"
3490 "8: movl 12(%4),%%edx\n"
3491- "9: movl %%eax, 8(%3)\n"
3492- "10: movl %%edx, 12(%3)\n"
3493+ "9: movl %%eax, %%es:8(%3)\n"
3494+ "10: movl %%edx, %%es:12(%3)\n"
3495 "11: movl 16(%4), %%eax\n"
3496 "12: movl 20(%4), %%edx\n"
3497- "13: movl %%eax, 16(%3)\n"
3498- "14: movl %%edx, 20(%3)\n"
3499+ "13: movl %%eax, %%es:16(%3)\n"
3500+ "14: movl %%edx, %%es:20(%3)\n"
3501 "15: movl 24(%4), %%eax\n"
3502 "16: movl 28(%4), %%edx\n"
3503- "17: movl %%eax, 24(%3)\n"
3504- "18: movl %%edx, 28(%3)\n"
3505+ "17: movl %%eax, %%es:24(%3)\n"
3506+ "18: movl %%edx, %%es:28(%3)\n"
3507 "19: movl 32(%4), %%eax\n"
3508 "20: movl 36(%4), %%edx\n"
3509- "21: movl %%eax, 32(%3)\n"
3510- "22: movl %%edx, 36(%3)\n"
3511+ "21: movl %%eax, %%es:32(%3)\n"
3512+ "22: movl %%edx, %%es:36(%3)\n"
3513 "23: movl 40(%4), %%eax\n"
3514 "24: movl 44(%4), %%edx\n"
3515- "25: movl %%eax, 40(%3)\n"
3516- "26: movl %%edx, 44(%3)\n"
3517+ "25: movl %%eax, %%es:40(%3)\n"
3518+ "26: movl %%edx, %%es:44(%3)\n"
3519 "27: movl 48(%4), %%eax\n"
3520 "28: movl 52(%4), %%edx\n"
3521- "29: movl %%eax, 48(%3)\n"
3522- "30: movl %%edx, 52(%3)\n"
3523+ "29: movl %%eax, %%es:48(%3)\n"
3524+ "30: movl %%edx, %%es:52(%3)\n"
3525 "31: movl 56(%4), %%eax\n"
3526 "32: movl 60(%4), %%edx\n"
3527- "33: movl %%eax, 56(%3)\n"
3528- "34: movl %%edx, 60(%3)\n"
3529+ "33: movl %%eax, %%es:56(%3)\n"
3530+ "34: movl %%edx, %%es:60(%3)\n"
3531 " addl $-64, %0\n"
3532 " addl $64, %4\n"
3533 " addl $64, %3\n"
3534@@ -280,6 +292,8 @@ __copy_user_intel(void __user *to, const
3535 "36: movl %%eax, %0\n"
3536 "37: rep; movsb\n"
3537 "100:\n"
3538+ " pushl %%ss\n"
3539+ " popl %%es\n"
3540 ".section .fixup,\"ax\"\n"
3541 "101: lea 0(%%eax,%0,4),%0\n"
3542 " jmp 100b\n"
3543@@ -326,7 +340,7 @@ __copy_user_intel(void __user *to, const
3544 " .long 99b,101b\n"
3545 ".previous"
3546 : "=&c"(size), "=&D" (d0), "=&S" (d1)
3547- : "1"(to), "2"(from), "0"(size)
3548+ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS)
3549 : "eax", "edx", "memory");
3550 return size;
3551 }
3552@@ -336,6 +350,7 @@ __copy_user_zeroing_intel(void *to, cons
3553 {
3554 int d0, d1;
3555 __asm__ __volatile__(
3556+ " movw %w6, %%ds\n"
3557 " .align 2,0x90\n"
3558 "0: movl 32(%4), %%eax\n"
3559 " cmpl $67, %0\n"
3560@@ -344,36 +359,36 @@ __copy_user_zeroing_intel(void *to, cons
3561 " .align 2,0x90\n"
3562 "2: movl 0(%4), %%eax\n"
3563 "21: movl 4(%4), %%edx\n"
3564- " movl %%eax, 0(%3)\n"
3565- " movl %%edx, 4(%3)\n"
3566+ " movl %%eax, %%es:0(%3)\n"
3567+ " movl %%edx, %%es:4(%3)\n"
3568 "3: movl 8(%4), %%eax\n"
3569 "31: movl 12(%4),%%edx\n"
3570- " movl %%eax, 8(%3)\n"
3571- " movl %%edx, 12(%3)\n"
3572+ " movl %%eax, %%es:8(%3)\n"
3573+ " movl %%edx, %%es:12(%3)\n"
3574 "4: movl 16(%4), %%eax\n"
3575 "41: movl 20(%4), %%edx\n"
3576- " movl %%eax, 16(%3)\n"
3577- " movl %%edx, 20(%3)\n"
3578+ " movl %%eax, %%es:16(%3)\n"
3579+ " movl %%edx, %%es:20(%3)\n"
3580 "10: movl 24(%4), %%eax\n"
3581 "51: movl 28(%4), %%edx\n"
3582- " movl %%eax, 24(%3)\n"
3583- " movl %%edx, 28(%3)\n"
3584+ " movl %%eax, %%es:24(%3)\n"
3585+ " movl %%edx, %%es:28(%3)\n"
3586 "11: movl 32(%4), %%eax\n"
3587 "61: movl 36(%4), %%edx\n"
3588- " movl %%eax, 32(%3)\n"
3589- " movl %%edx, 36(%3)\n"
3590+ " movl %%eax, %%es:32(%3)\n"
3591+ " movl %%edx, %%es:36(%3)\n"
3592 "12: movl 40(%4), %%eax\n"
3593 "71: movl 44(%4), %%edx\n"
3594- " movl %%eax, 40(%3)\n"
3595- " movl %%edx, 44(%3)\n"
3596+ " movl %%eax, %%es:40(%3)\n"
3597+ " movl %%edx, %%es:44(%3)\n"
3598 "13: movl 48(%4), %%eax\n"
3599 "81: movl 52(%4), %%edx\n"
3600- " movl %%eax, 48(%3)\n"
3601- " movl %%edx, 52(%3)\n"
3602+ " movl %%eax, %%es:48(%3)\n"
3603+ " movl %%edx, %%es:52(%3)\n"
3604 "14: movl 56(%4), %%eax\n"
3605 "91: movl 60(%4), %%edx\n"
3606- " movl %%eax, 56(%3)\n"
3607- " movl %%edx, 60(%3)\n"
3608+ " movl %%eax, %%es:56(%3)\n"
3609+ " movl %%edx, %%es:60(%3)\n"
3610 " addl $-64, %0\n"
3611 " addl $64, %4\n"
3612 " addl $64, %3\n"
3613@@ -387,6 +402,8 @@ __copy_user_zeroing_intel(void *to, cons
3614 " movl %%eax,%0\n"
3615 "7: rep; movsb\n"
3616 "8:\n"
3617+ " pushl %%ss\n"
3618+ " popl %%ds\n"
3619 ".section .fixup,\"ax\"\n"
3620 "9: lea 0(%%eax,%0,4),%0\n"
3621 "16: pushl %0\n"
3622@@ -421,7 +438,7 @@ __copy_user_zeroing_intel(void *to, cons
3623 " .long 7b,16b\n"
3624 ".previous"
3625 : "=&c"(size), "=&D" (d0), "=&S" (d1)
3626- : "1"(to), "2"(from), "0"(size)
3627+ : "1"(to), "2"(from), "0"(size), "r"(__USER_DS)
3628 : "eax", "edx", "memory");
3629 return size;
3630 }
3631@@ -441,6 +458,7 @@ __copy_user_intel(void __user *to, const
3632 do { \
3633 int __d0, __d1, __d2; \
3634 __asm__ __volatile__( \
3635+ " movw %w8,%%es\n" \
3636 " cmp $7,%0\n" \
3637 " jbe 1f\n" \
3638 " movl %1,%0\n" \
3639@@ -456,6 +474,8 @@ do { \
3640 " movl %3,%0\n" \
3641 "1: rep; movsb\n" \
3642 "2:\n" \
3643+ " pushl %%ss\n" \
3644+ " popl %%es\n" \
3645 ".section .fixup,\"ax\"\n" \
3646 "5: addl %3,%0\n" \
3647 " jmp 2b\n" \
3648@@ -469,7 +489,7 @@ do { \
3649 " .long 1b,2b\n" \
3650 ".previous" \
3651 : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \
3652- : "3"(size), "0"(size), "1"(to), "2"(from) \
3653+ : "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS)\
3654 : "memory"); \
3655 } while (0)
3656
3657@@ -477,6 +497,7 @@ do { \
3658 do { \
3659 int __d0, __d1, __d2; \
3660 __asm__ __volatile__( \
3661+ " movw %w8,%%ds\n" \
3662 " cmp $7,%0\n" \
3663 " jbe 1f\n" \
3664 " movl %1,%0\n" \
3665@@ -492,6 +513,8 @@ do { \
3666 " movl %3,%0\n" \
3667 "1: rep; movsb\n" \
3668 "2:\n" \
3669+ " pushl %%ss\n" \
3670+ " popl %%ds\n" \
3671 ".section .fixup,\"ax\"\n" \
3672 "5: addl %3,%0\n" \
3673 " jmp 6f\n" \
3674@@ -511,7 +534,7 @@ do { \
3675 " .long 1b,6b\n" \
3676 ".previous" \
3677 : "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2) \
3678- : "3"(size), "0"(size), "1"(to), "2"(from) \
3679+ : "3"(size), "0"(size), "1"(to), "2"(from), "r"(__USER_DS)\
3680 : "memory"); \
3681 } while (0)
3682
3683@@ -640,3 +663,45 @@ copy_from_user(void *to, const void __us
3684 return n;
3685 }
3686 EXPORT_SYMBOL(copy_from_user);
3687+
3688+#ifdef CONFIG_PAX_MEMORY_UDEREF
3689+void __set_fs(mm_segment_t x, int cpu)
3690+{
3691+ unsigned long limit = x.seg;
3692+
3693+ current_thread_info()->addr_limit = x;
3694+ if (likely(limit)) {
3695+ limit -= 1UL;
3696+ limit >>= 12;
3697+ }
3698+
3699+ get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_DS].a = (limit & 0xFFFFUL);
3700+ get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_DS].b = (limit & 0xF0000UL) | 0xC0F300UL;
3701+}
3702+
3703+void set_fs(mm_segment_t x)
3704+{
3705+ int cpu = get_cpu();
3706+
3707+#ifdef CONFIG_PAX_KERNEXEC
3708+ unsigned long cr0;
3709+
3710+ pax_open_kernel(cr0);
3711+#endif
3712+
3713+ __set_fs(x, cpu);
3714+
3715+#ifdef CONFIG_PAX_KERNEXEC
3716+ pax_close_kernel(cr0);
3717+#endif
3718+
3719+ put_cpu_no_resched();
3720+}
3721+#else
3722+void set_fs(mm_segment_t x)
3723+{
3724+ current_thread_info()->addr_limit = x;
3725+}
3726+#endif
3727+
3728+EXPORT_SYMBOL(set_fs);
3729diff -urNp linux-2.6.17.7/arch/i386/mach-voyager/voyager_smp.c linux-2.6.17.7/arch/i386/mach-voyager/voyager_smp.c
3730--- linux-2.6.17.7/arch/i386/mach-voyager/voyager_smp.c 2006-07-24 23:36:01.000000000 -0400
3731+++ linux-2.6.17.7/arch/i386/mach-voyager/voyager_smp.c 2006-08-01 20:29:45.000000000 -0400
3732@@ -1295,7 +1295,7 @@ smp_local_timer_interrupt(struct pt_regs
3733 per_cpu(prof_counter, cpu);
3734 }
3735
3736- update_process_times(user_mode_vm(regs));
3737+ update_process_times(user_mode(regs));
3738 }
3739
3740 if( ((1<<cpu) & voyager_extended_vic_processors) == 0)
3741diff -urNp linux-2.6.17.7/arch/i386/mm/boot_ioremap.c linux-2.6.17.7/arch/i386/mm/boot_ioremap.c
3742--- linux-2.6.17.7/arch/i386/mm/boot_ioremap.c 2006-07-24 23:36:01.000000000 -0400
3743+++ linux-2.6.17.7/arch/i386/mm/boot_ioremap.c 2006-08-01 20:29:45.000000000 -0400
3744@@ -8,53 +8,37 @@
3745 */
3746
3747
3748-/*
3749- * We need to use the 2-level pagetable functions, but CONFIG_X86_PAE
3750- * keeps that from happenning. If anyone has a better way, I'm listening.
3751- *
3752- * boot_pte_t is defined only if this all works correctly
3753- */
3754-
3755 #include <linux/config.h>
3756-#undef CONFIG_X86_PAE
3757 #include <asm/page.h>
3758 #include <asm/pgtable.h>
3759 #include <asm/tlbflush.h>
3760 #include <linux/init.h>
3761 #include <linux/stddef.h>
3762
3763-/*
3764- * I'm cheating here. It is known that the two boot PTE pages are
3765- * allocated next to each other. I'm pretending that they're just
3766- * one big array.
3767- */
3768-
3769-#define BOOT_PTE_PTRS (PTRS_PER_PTE*2)
3770-#define boot_pte_index(address) \
3771- (((address) >> PAGE_SHIFT) & (BOOT_PTE_PTRS - 1))
3772-
3773-static inline boot_pte_t* boot_vaddr_to_pte(void *address)
3774-{
3775- boot_pte_t* boot_pg = (boot_pte_t*)pg0;
3776- return &boot_pg[boot_pte_index((unsigned long)address)];
3777-}
3778
3779 /*
3780 * This is only for a caller who is clever enough to page-align
3781 * phys_addr and virtual_source, and who also has a preference
3782 * about which virtual address from which to steal ptes
3783 */
3784-static void __boot_ioremap(unsigned long phys_addr, unsigned long nrpages,
3785- void* virtual_source)
3786+static void __init __boot_ioremap(unsigned long phys_addr, unsigned int nrpages,
3787+ char* virtual_source)
3788 {
3789- boot_pte_t* pte;
3790- int i;
3791- char *vaddr = virtual_source;
3792+ pgd_t *pgd;
3793+ pud_t *pud;
3794+ pmd_t *pmd;
3795+ pte_t* pte;
3796+ unsigned int i;
3797+ unsigned long vaddr = (unsigned long)virtual_source;
3798+
3799+ pgd = pgd_offset_k(vaddr);
3800+ pud = pud_offset(pgd, vaddr);
3801+ pmd = pmd_offset(pud, vaddr);
3802+ pte = pte_offset_kernel(pmd, vaddr);
3803
3804- pte = boot_vaddr_to_pte(virtual_source);
3805 for (i=0; i < nrpages; i++, phys_addr += PAGE_SIZE, pte++) {
3806 set_pte(pte, pfn_pte(phys_addr>>PAGE_SHIFT, PAGE_KERNEL));
3807- __flush_tlb_one(&vaddr[i*PAGE_SIZE]);
3808+ __flush_tlb_one(&virtual_source[i*PAGE_SIZE]);
3809 }
3810 }
3811
3812diff -urNp linux-2.6.17.7/arch/i386/mm/extable.c linux-2.6.17.7/arch/i386/mm/extable.c
3813--- linux-2.6.17.7/arch/i386/mm/extable.c 2006-07-24 23:36:01.000000000 -0400
3814+++ linux-2.6.17.7/arch/i386/mm/extable.c 2006-08-01 20:29:45.000000000 -0400
3815@@ -12,7 +12,7 @@ int fixup_exception(struct pt_regs *regs
3816 const struct exception_table_entry *fixup;
3817
3818 #ifdef CONFIG_PNPBIOS
3819- if (unlikely((regs->xcs & ~15) == (GDT_ENTRY_PNPBIOS_BASE << 3)))
3820+ if (unlikely(regs->xcs == (GDT_ENTRY_PNPBIOS_BASE << 3)))
3821 {
3822 extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
3823 extern u32 pnp_bios_is_utter_crap;
3824diff -urNp linux-2.6.17.7/arch/i386/mm/fault.c linux-2.6.17.7/arch/i386/mm/fault.c
3825--- linux-2.6.17.7/arch/i386/mm/fault.c 2006-07-24 23:36:01.000000000 -0400
3826+++ linux-2.6.17.7/arch/i386/mm/fault.c 2006-08-01 20:29:45.000000000 -0400
3827@@ -22,6 +22,9 @@
3828 #include <linux/highmem.h>
3829 #include <linux/module.h>
3830 #include <linux/kprobes.h>
3831+#include <linux/unistd.h>
3832+#include <linux/compiler.h>
3833+#include <linux/binfmts.h>
3834
3835 #include <asm/system.h>
3836 #include <asm/uaccess.h>
3837@@ -82,11 +85,13 @@ static inline unsigned long get_segment_
3838
3839 /* Unlikely, but must come before segment checks. */
3840 if (unlikely((regs->eflags & VM_MASK) != 0))
3841- return eip + (seg << 4);
3842+ return (eip & 0xFFFF) + (seg << 4);
3843
3844 /* By far the most common cases. */
3845- if (likely(seg == __USER_CS || seg == __KERNEL_CS))
3846+ if (likely(seg == __USER_CS))
3847 return eip;
3848+ if (likely(seg == __KERNEL_CS))
3849+ return eip + __KERNEL_TEXT_OFFSET;
3850
3851 /* Check the segment exists, is within the current LDT/GDT size,
3852 that kernel/user (ring 0..3) has the appropriate privilege,
3853@@ -214,6 +219,30 @@ static noinline void force_sig_info_faul
3854
3855 fastcall void do_invalid_op(struct pt_regs *, unsigned long);
3856
3857+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
3858+static int pax_handle_fetch_fault(struct pt_regs *regs);
3859+#endif
3860+
3861+#ifdef CONFIG_PAX_PAGEEXEC
3862+static inline pmd_t * pax_get_pmd(struct mm_struct *mm, unsigned long address)
3863+{
3864+ pgd_t *pgd;
3865+ pud_t *pud;
3866+ pmd_t *pmd;
3867+
3868+ pgd = pgd_offset(mm, address);
3869+ if (!pgd_present(*pgd))
3870+ return NULL;
3871+ pud = pud_offset(pgd, address);
3872+ if (!pud_present(*pud))
3873+ return NULL;
3874+ pmd = pmd_offset(pud, address);
3875+ if (!pmd_present(*pmd))
3876+ return NULL;
3877+ return pmd;
3878+}
3879+#endif
3880+
3881 static inline pmd_t *vmalloc_sync_one(pgd_t *pgd, unsigned long address)
3882 {
3883 unsigned index = pgd_index(address);
3884@@ -295,13 +324,20 @@ fastcall void __kprobes do_page_fault(st
3885 struct mm_struct *mm;
3886 struct vm_area_struct * vma;
3887 unsigned long address;
3888- unsigned long page;
3889 int write, si_code;
3890
3891+#ifdef CONFIG_PAX_PAGEEXEC
3892+ pmd_t *pmd;
3893+ pte_t *pte;
3894+ spinlock_t *ptl;
3895+ unsigned char pte_mask;
3896+#endif
3897+
3898 /* get the address */
3899 address = read_cr2();
3900
3901 tsk = current;
3902+ mm = tsk->mm;
3903
3904 si_code = SEGV_MAPERR;
3905
3906@@ -340,14 +376,12 @@ fastcall void __kprobes do_page_fault(st
3907 if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
3908 local_irq_enable();
3909
3910- mm = tsk->mm;
3911-
3912 /*
3913 * If we're in an interrupt, have no user context or are running in an
3914 * atomic region then we must not take the fault..
3915 */
3916 if (in_atomic() || !mm)
3917- goto bad_area_nosemaphore;
3918+ goto bad_area_nopax;
3919
3920 /* When running in the kernel we expect faults to occur only to
3921 * addresses in user space. All other faults represent errors in the
3922@@ -367,10 +401,101 @@ fastcall void __kprobes do_page_fault(st
3923 if (!down_read_trylock(&mm->mmap_sem)) {
3924 if ((error_code & 4) == 0 &&
3925 !search_exception_tables(regs->eip))
3926- goto bad_area_nosemaphore;
3927+ goto bad_area_nopax;
3928 down_read(&mm->mmap_sem);
3929 }
3930
3931+#ifdef CONFIG_PAX_PAGEEXEC
3932+ if (unlikely((error_code & 5) != 5 ||
3933+ (regs->eflags & X86_EFLAGS_VM) ||
3934+ !(mm->pax_flags & MF_PAX_PAGEEXEC)))
3935+ goto not_pax_fault;
3936+
3937+ /* PaX: it's our fault, let's handle it if we can */
3938+
3939+ /* PaX: take a look at read faults before acquiring any locks */
3940+ if (unlikely(!(error_code & 2) && (regs->eip == address))) {
3941+ /* instruction fetch attempt from a protected page in user mode */
3942+ up_read(&mm->mmap_sem);
3943+ switch (pax_handle_fetch_fault(regs)) {
3944+
3945+#ifdef CONFIG_PAX_EMUTRAMP
3946+ case 2:
3947+ return;
3948+#endif
3949+
3950+ }
3951+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
3952+ do_exit(SIGKILL);
3953+ }
3954+
3955+ pmd = pax_get_pmd(mm, address);
3956+ if (unlikely(!pmd))
3957+ goto not_pax_fault;
3958+
3959+ pte = pte_offset_map_lock(mm, pmd, address, &ptl);
3960+ if (unlikely(!(pte_val(*pte) & _PAGE_PRESENT) || pte_user(*pte))) {
3961+ pte_unmap_unlock(pte, ptl);
3962+ goto not_pax_fault;
3963+ }
3964+
3965+ if (unlikely((error_code & 2) && !pte_write(*pte))) {
3966+ /* write attempt to a protected page in user mode */
3967+ pte_unmap_unlock(pte, ptl);
3968+ goto not_pax_fault;
3969+ }
3970+
3971+#ifdef CONFIG_SMP
3972+ if (likely(address > get_limit(regs->xcs) && cpu_isset(smp_processor_id(), mm->context.cpu_user_cs_mask)))
3973+#else
3974+ if (likely(address > get_limit(regs->xcs)))
3975+#endif
3976+ {
3977+ set_pte(pte, pte_mkread(*pte));
3978+ __flush_tlb_one(address);
3979+ pte_unmap_unlock(pte, ptl);
3980+ up_read(&mm->mmap_sem);
3981+ return;
3982+ }
3983+
3984+ pte_mask = _PAGE_ACCESSED | _PAGE_USER | ((error_code & 2) << (_PAGE_BIT_DIRTY-1));
3985+
3986+ /*
3987+ * PaX: fill DTLB with user rights and retry
3988+ */
3989+ __asm__ __volatile__ (
3990+ "movw %w4,%%ds\n"
3991+ "orb %2,%%ss:(%1)\n"
3992+#if defined(CONFIG_M586) || defined(CONFIG_M586TSC)
3993+/*
3994+ * PaX: let this uncommented 'invlpg' remind us on the behaviour of Intel's
3995+ * (and AMD's) TLBs. namely, they do not cache PTEs that would raise *any*
3996+ * page fault when examined during a TLB load attempt. this is true not only
3997+ * for PTEs holding a non-present entry but also present entries that will
3998+ * raise a page fault (such as those set up by PaX, or the copy-on-write
3999+ * mechanism). in effect it means that we do *not* need to flush the TLBs
4000+ * for our target pages since their PTEs are simply not in the TLBs at all.
4001+
4002+ * the best thing in omitting it is that we gain around 15-20% speed in the
4003+ * fast path of the page fault handler and can get rid of tracing since we
4004+ * can no longer flush unintended entries.
4005+ */
4006+ "invlpg (%0)\n"
4007+#endif
4008+ "testb $0,(%0)\n"
4009+ "xorb %3,%%ss:(%1)\n"
4010+ "pushl %%ss\n"
4011+ "popl %%ds\n"
4012+ :
4013+ : "q" (address), "r" (pte), "q" (pte_mask), "i" (_PAGE_USER), "r" (__USER_DS)
4014+ : "memory", "cc");
4015+ pte_unmap_unlock(pte, ptl);
4016+ up_read(&mm->mmap_sem);
4017+ return;
4018+
4019+not_pax_fault:
4020+#endif
4021+
4022 vma = find_vma(mm, address);
4023 if (!vma)
4024 goto bad_area;
4025@@ -456,6 +581,37 @@ bad_area:
4026 up_read(&mm->mmap_sem);
4027
4028 bad_area_nosemaphore:
4029+
4030+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
4031+ if (mm && (error_code & 4) && !(regs->eflags & X86_EFLAGS_VM)) {
4032+
4033+#ifdef CONFIG_PAX_PAGEEXEC
4034+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && !(error_code & 3) && (regs->eip == address)) {
4035+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
4036+ do_exit(SIGKILL);
4037+ }
4038+#endif
4039+
4040+#ifdef CONFIG_PAX_SEGMEXEC
4041+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && !(error_code & 3) && (regs->eip + SEGMEXEC_TASK_SIZE == address)) {
4042+
4043+ switch (pax_handle_fetch_fault(regs)) {
4044+
4045+#ifdef CONFIG_PAX_EMUTRAMP
4046+ case 2:
4047+ return;
4048+#endif
4049+
4050+ }
4051+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
4052+ do_exit(SIGKILL);
4053+ }
4054+#endif
4055+
4056+ }
4057+#endif
4058+
4059+bad_area_nopax:
4060 /* User mode accesses just cause a SIGSEGV */
4061 if (error_code & 4) {
4062 /*
4063@@ -523,6 +679,21 @@ no_context:
4064 if (address < PAGE_SIZE)
4065 printk(KERN_ALERT "BUG: unable to handle kernel NULL "
4066 "pointer dereference");
4067+
4068+#ifdef CONFIG_PAX_KERNEXEC
4069+#ifdef CONFIG_MODULES
4070+ else if (init_mm.start_code <= address && address < (unsigned long)MODULES_END)
4071+#else
4072+ else if (init_mm.start_code <= address && address < init_mm.end_code)
4073+#endif
4074+ if (tsk->signal->curr_ip)
4075+ printk(KERN_ERR "PAX: From %u.%u.%u.%u: %s:%d, uid/euid: %u/%u, attempted to modify kernel code",
4076+ NIPQUAD(tsk->signal->curr_ip), tsk->comm, tsk->pid, tsk->uid, tsk->euid);
4077+ else
4078+ printk(KERN_ERR "PAX: %s:%d, uid/euid: %u/%u, attempted to modify kernel code",
4079+ tsk->comm, tsk->pid, tsk->uid, tsk->euid);
4080+#endif
4081+
4082 else
4083 printk(KERN_ALERT "BUG: unable to handle kernel paging"
4084 " request");
4085@@ -530,24 +701,34 @@ no_context:
4086 printk(KERN_ALERT " printing eip:\n");
4087 printk("%08lx\n", regs->eip);
4088 }
4089- page = read_cr3();
4090- page = ((unsigned long *) __va(page))[address >> 22];
4091- if (oops_may_print())
4092- printk(KERN_ALERT "*pde = %08lx\n", page);
4093- /*
4094- * We must not directly access the pte in the highpte
4095- * case, the page table might be allocated in highmem.
4096- * And lets rather not kmap-atomic the pte, just in case
4097- * it's allocated already.
4098- */
4099+
4100+ if (oops_may_print()) {
4101+ unsigned long index = pgd_index(address);
4102+ pgd_t *pgd;
4103+ pud_t *pud;
4104+ pmd_t *pmd;
4105+ pte_t *pte;
4106+
4107+ pgd = index + (pgd_t *)__va(read_cr3());
4108+ printk(KERN_ALERT "*pgd = %*llx\n", sizeof(*pgd), (unsigned long long)pgd_val(*pgd));
4109+ if (pgd_present(*pgd)) {
4110+ pud = pud_offset(pgd, address);
4111+ pmd = pmd_offset(pud, address);
4112+ printk(KERN_ALERT "*pmd = %*llx\n", sizeof(*pmd), (unsigned long long)pmd_val(*pmd));
4113+ /*
4114+ * We must not directly access the pte in the highpte
4115+ * case, the page table might be allocated in highmem.
4116+ * And lets rather not kmap-atomic the pte, just in case
4117+ * it's allocated already.
4118+ */
4119 #ifndef CONFIG_HIGHPTE
4120- if ((page & 1) && oops_may_print()) {
4121- page &= PAGE_MASK;
4122- address &= 0x003ff000;
4123- page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
4124- printk(KERN_ALERT "*pte = %08lx\n", page);
4125- }
4126+ if (pmd_present(*pmd) && !pmd_large(*pmd)) {
4127+ pte = pte_offset_kernel(pmd, address);
4128+ printk(KERN_ALERT "*pte = %*llx\n", sizeof(*pte), (unsigned long long)pte_val(*pte));
4129+ }
4130 #endif
4131+ }
4132+ }
4133 tsk->thread.cr2 = address;
4134 tsk->thread.trap_no = 14;
4135 tsk->thread.error_code = error_code;
4136@@ -624,3 +805,105 @@ void vmalloc_sync_all(void)
4137 }
4138 }
4139 #endif
4140+
4141+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
4142+/*
4143+ * PaX: decide what to do with offenders (regs->eip = fault address)
4144+ *
4145+ * returns 1 when task should be killed
4146+ * 2 when gcc trampoline was detected
4147+ */
4148+static int pax_handle_fetch_fault(struct pt_regs *regs)
4149+{
4150+
4151+#ifdef CONFIG_PAX_EMUTRAMP
4152+ static const unsigned char trans[8] = {6, 1, 2, 0, 13, 5, 3, 4};
4153+ int err;
4154+#endif
4155+
4156+ if (regs->eflags & X86_EFLAGS_VM)
4157+ return 1;
4158+
4159+#ifdef CONFIG_PAX_EMUTRAMP
4160+ if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
4161+ return 1;
4162+
4163+ do { /* PaX: gcc trampoline emulation #1 */
4164+ unsigned char mov1, mov2;
4165+ unsigned short jmp;
4166+ unsigned long addr1, addr2;
4167+
4168+ err = get_user(mov1, (unsigned char __user *)regs->eip);
4169+ err |= get_user(addr1, (unsigned long __user *)(regs->eip + 1));
4170+ err |= get_user(mov2, (unsigned char __user *)(regs->eip + 5));
4171+ err |= get_user(addr2, (unsigned long __user *)(regs->eip + 6));
4172+ err |= get_user(jmp, (unsigned short __user *)(regs->eip + 10));
4173+
4174+ if (err)
4175+ break;
4176+
4177+ if ((mov1 & 0xF8) == 0xB8 &&
4178+ (mov2 & 0xF8) == 0xB8 &&
4179+ (mov1 & 0x07) != (mov2 & 0x07) &&
4180+ (jmp & 0xF8FF) == 0xE0FF &&
4181+ (mov2 & 0x07) == ((jmp>>8) & 0x07))
4182+ {
4183+ ((unsigned long *)regs)[trans[mov1 & 0x07]] = addr1;
4184+ ((unsigned long *)regs)[trans[mov2 & 0x07]] = addr2;
4185+ regs->eip = addr2;
4186+ return 2;
4187+ }
4188+ } while (0);
4189+
4190+ do { /* PaX: gcc trampoline emulation #2 */
4191+ unsigned char mov, jmp;
4192+ unsigned long addr1, addr2;
4193+
4194+ err = get_user(mov, (unsigned char __user *)regs->eip);
4195+ err |= get_user(addr1, (unsigned long __user *)(regs->eip + 1));
4196+ err |= get_user(jmp, (unsigned char __user *)(regs->eip + 5));
4197+ err |= get_user(addr2, (unsigned long __user *)(regs->eip + 6));
4198+
4199+ if (err)
4200+ break;
4201+
4202+ if ((mov & 0xF8) == 0xB8 &&
4203+ jmp == 0xE9)
4204+ {
4205+ ((unsigned long *)regs)[trans[mov & 0x07]] = addr1;
4206+ regs->eip += addr2 + 10;
4207+ return 2;
4208+ }
4209+ } while (0);
4210+#endif
4211+
4212+ return 1; /* PaX in action */
4213+}
4214+#endif
4215+
4216+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
4217+void pax_report_insns(void *pc, void *sp)
4218+{
4219+ long i;
4220+
4221+ printk(KERN_ERR "PAX: bytes at PC: ");
4222+ for (i = 0; i < 20; i++) {
4223+ unsigned char c;
4224+ if (get_user(c, (unsigned char __user *)pc+i))
4225+ printk("?? ");
4226+ else
4227+ printk("%02x ", c);
4228+ }
4229+ printk("\n");
4230+
4231+ printk(KERN_ERR "PAX: bytes at SP-4: ");
4232+ for (i = -1; i < 20; i++) {
4233+ unsigned long c;
4234+ if (get_user(c, (unsigned long __user *)sp+i))
4235+ printk("???????? ");
4236+ else
4237+ printk("%08lx ", c);
4238+ }
4239+ printk("\n");
4240+}
4241+#endif
4242diff -urNp linux-2.6.17.7/arch/i386/mm/hugetlbpage.c linux-2.6.17.7/arch/i386/mm/hugetlbpage.c
4243--- linux-2.6.17.7/arch/i386/mm/hugetlbpage.c 2006-07-24 23:36:01.000000000 -0400
4244+++ linux-2.6.17.7/arch/i386/mm/hugetlbpage.c 2006-08-01 20:29:45.000000000 -0400
4245@@ -121,7 +121,12 @@ static unsigned long hugetlb_get_unmappe
4246 {
4247 struct mm_struct *mm = current->mm;
4248 struct vm_area_struct *vma;
4249- unsigned long start_addr;
4250+ unsigned long start_addr, task_size = TASK_SIZE;
4251+
4252+#ifdef CONFIG_PAX_SEGMEXEC
4253+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
4254+ task_size = SEGMEXEC_TASK_SIZE;
4255+#endif
4256
4257 if (len > mm->cached_hole_size) {
4258 start_addr = mm->free_area_cache;
4259@@ -135,7 +140,7 @@ full_search:
4260
4261 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
4262 /* At this point: (!vma || addr < vma->vm_end). */
4263- if (TASK_SIZE - len < addr) {
4264+ if (task_size - len < addr) {
4265 /*
4266 * Start a new search - just in case we missed
4267 * some holes.
4268@@ -163,9 +168,8 @@ static unsigned long hugetlb_get_unmappe
4269 {
4270 struct mm_struct *mm = current->mm;
4271 struct vm_area_struct *vma, *prev_vma;
4272- unsigned long base = mm->mmap_base, addr = addr0;
4273+ unsigned long base = mm->mmap_base, addr;
4274 unsigned long largest_hole = mm->cached_hole_size;
4275- int first_time = 1;
4276
4277 /* don't allow allocations above current base */
4278 if (mm->free_area_cache > base)
4279@@ -175,7 +179,7 @@ static unsigned long hugetlb_get_unmappe
4280 largest_hole = 0;
4281 mm->free_area_cache = base;
4282 }
4283-try_again:
4284+
4285 /* make sure it can fit in the remaining address space */
4286 if (mm->free_area_cache < len)
4287 goto fail;
4288@@ -217,16 +221,6 @@ try_again:
4289
4290 fail:
4291 /*
4292- * if hint left us with no space for the requested
4293- * mapping then try again:
4294- */
4295- if (first_time) {
4296- mm->free_area_cache = base;
4297- largest_hole = 0;
4298- first_time = 0;
4299- goto try_again;
4300- }
4301- /*
4302 * A failed mmap() very likely causes application failure,
4303 * so fall back to the bottom-up function here. This scenario
4304 * can happen with large stack limits and large mmap()
4305@@ -252,16 +246,23 @@ hugetlb_get_unmapped_area(struct file *f
4306 {
4307 struct mm_struct *mm = current->mm;
4308 struct vm_area_struct *vma;
4309+ unsigned long task_size = TASK_SIZE;
4310
4311 if (len & ~HPAGE_MASK)
4312 return -EINVAL;
4313- if (len > TASK_SIZE)
4314+
4315+#ifdef CONFIG_PAX_SEGMEXEC
4316+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
4317+ task_size = SEGMEXEC_TASK_SIZE;
4318+#endif
4319+
4320+ if (len > task_size || addr > task_size - len)
4321 return -ENOMEM;
4322
4323 if (addr) {
4324 addr = ALIGN(addr, HPAGE_SIZE);
4325 vma = find_vma(mm, addr);
4326- if (TASK_SIZE - len >= addr &&
4327+ if (task_size - len >= addr &&
4328 (!vma || addr + len <= vma->vm_start))
4329 return addr;
4330 }
4331diff -urNp linux-2.6.17.7/arch/i386/mm/init.c linux-2.6.17.7/arch/i386/mm/init.c
4332--- linux-2.6.17.7/arch/i386/mm/init.c 2006-07-24 23:36:01.000000000 -0400
4333+++ linux-2.6.17.7/arch/i386/mm/init.c 2006-08-01 20:29:45.000000000 -0400
4334@@ -41,6 +41,7 @@
4335 #include <asm/tlb.h>
4336 #include <asm/tlbflush.h>
4337 #include <asm/sections.h>
4338+#include <asm/desc.h>
4339
4340 unsigned int __VMALLOC_RESERVE = 128 << 20;
4341
4342@@ -50,30 +51,6 @@ unsigned long highstart_pfn, highend_pfn
4343 static int noinline do_test_wp_bit(void);
4344
4345 /*
4346- * Creates a middle page table and puts a pointer to it in the
4347- * given global directory entry. This only returns the gd entry
4348- * in non-PAE compilation mode, since the middle layer is folded.
4349- */
4350-static pmd_t * __init one_md_table_init(pgd_t *pgd)
4351-{
4352- pud_t *pud;
4353- pmd_t *pmd_table;
4354-
4355-#ifdef CONFIG_X86_PAE
4356- pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
4357- set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
4358- pud = pud_offset(pgd, 0);
4359- if (pmd_table != pmd_offset(pud, 0))
4360- BUG();
4361-#else
4362- pud = pud_offset(pgd, 0);
4363- pmd_table = pmd_offset(pud, 0);
4364-#endif
4365-
4366- return pmd_table;
4367-}
4368-
4369-/*
4370 * Create a page table and place a pointer to it in a middle page
4371 * directory entry.
4372 */
4373@@ -81,7 +58,11 @@ static pte_t * __init one_page_table_ini
4374 {
4375 if (pmd_none(*pmd)) {
4376 pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
4377+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
4378+ set_pmd(pmd, __pmd(__pa(page_table) | _KERNPG_TABLE));
4379+#else
4380 set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
4381+#endif
4382 if (page_table != pte_offset_kernel(pmd, 0))
4383 BUG();
4384
4385@@ -116,8 +97,6 @@ static void __init page_table_range_init
4386 pgd = pgd_base + pgd_idx;
4387
4388 for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
4389- if (pgd_none(*pgd))
4390- one_md_table_init(pgd);
4391 pud = pud_offset(pgd, vaddr);
4392 pmd = pmd_offset(pud, vaddr);
4393 for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
4394@@ -130,11 +109,22 @@ static void __init page_table_range_init
4395 }
4396 }
4397
4398-static inline int is_kernel_text(unsigned long addr)
4399+static inline int is_kernel_text(unsigned long start, unsigned long end)
4400 {
4401- if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end)
4402- return 1;
4403- return 0;
4404+ unsigned long etext;
4405+
4406+#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
4407+ etext = (unsigned long)&MODULES_END - __KERNEL_TEXT_OFFSET;
4408+#else
4409+ etext = (unsigned long)&_etext;
4410+#endif
4411+
4412+ if ((start > etext + __KERNEL_TEXT_OFFSET ||
4413+ end <= (unsigned long)_stext + __KERNEL_TEXT_OFFSET) &&
4414+ (start > (unsigned long)_einittext + __KERNEL_TEXT_OFFSET ||
4415+ end <= (unsigned long)_sinittext + __KERNEL_TEXT_OFFSET))
4416+ return 0;
4417+ return 1;
4418 }
4419
4420 /*
4421@@ -146,26 +136,24 @@ static void __init kernel_physical_mappi
4422 {
4423 unsigned long pfn;
4424 pgd_t *pgd;
4425+ pud_t *pud;
4426 pmd_t *pmd;
4427 pte_t *pte;
4428- int pgd_idx, pmd_idx, pte_ofs;
4429+ unsigned int pgd_idx, pmd_idx, pte_ofs;
4430
4431 pgd_idx = pgd_index(PAGE_OFFSET);
4432 pgd = pgd_base + pgd_idx;
4433 pfn = 0;
4434
4435- for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
4436- pmd = one_md_table_init(pgd);
4437- if (pfn >= max_low_pfn)
4438- continue;
4439+ for (; pgd_idx < PTRS_PER_PGD && pfn < max_low_pfn; pgd++, pgd_idx++) {
4440+ pud = pud_offset(pgd, 0);
4441+ pmd = pmd_offset(pud, 0);
4442 for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
4443- unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;
4444+ unsigned long address = pfn * PAGE_SIZE + PAGE_OFFSET;
4445
4446 /* Map with big pages if possible, otherwise create normal page tables. */
4447 if (cpu_has_pse) {
4448- unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
4449-
4450- if (is_kernel_text(address) || is_kernel_text(address2))
4451+ if (is_kernel_text(address, address + PMD_SIZE))
4452 set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
4453 else
4454 set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
4455@@ -174,7 +162,7 @@ static void __init kernel_physical_mappi
4456 pte = one_page_table_init(pmd);
4457
4458 for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++) {
4459- if (is_kernel_text(address))
4460+ if (is_kernel_text(address, address + PAGE_SIZE))
4461 set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
4462 else
4463 set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
4464@@ -341,13 +329,6 @@ static void __init pagetable_init (void)
4465 unsigned long vaddr;
4466 pgd_t *pgd_base = swapper_pg_dir;
4467
4468-#ifdef CONFIG_X86_PAE
4469- int i;
4470- /* Init entries of the first-level page table to the zero page */
4471- for (i = 0; i < PTRS_PER_PGD; i++)
4472- set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
4473-#endif
4474-
4475 /* Enable PSE if available */
4476 if (cpu_has_pse) {
4477 set_in_cr4(X86_CR4_PSE);
4478@@ -371,17 +352,6 @@ static void __init pagetable_init (void)
4479 page_table_range_init(vaddr, 0, pgd_base);
4480
4481 permanent_kmaps_init(pgd_base);
4482-
4483-#ifdef CONFIG_X86_PAE
4484- /*
4485- * Add low memory identity-mappings - SMP needs it when
4486- * starting up on an AP from real-mode. In the non-PAE
4487- * case we already have these mappings through head.S.
4488- * All user-space mappings are explicitly cleared after
4489- * SMP startup.
4490- */
4491- set_pgd(&pgd_base[0], pgd_base[USER_PTRS_PER_PGD]);
4492-#endif
4493 }
4494
4495 #ifdef CONFIG_SOFTWARE_SUSPEND
4496@@ -423,7 +393,6 @@ void zap_low_mappings (void)
4497 flush_tlb_all();
4498 }
4499
4500-static int disable_nx __initdata = 0;
4501 u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
4502
4503 /*
4504@@ -437,11 +406,9 @@ u64 __supported_pte_mask __read_mostly =
4505 void __init noexec_setup(const char *str)
4506 {
4507 if (!strncmp(str, "on",2) && cpu_has_nx) {
4508- __supported_pte_mask |= _PAGE_NX;
4509- disable_nx = 0;
4510+ nx_enabled = 1;
4511 } else if (!strncmp(str,"off",3)) {
4512- disable_nx = 1;
4513- __supported_pte_mask &= ~_PAGE_NX;
4514+ nx_enabled = 0;
4515 }
4516 }
4517
4518@@ -450,17 +417,13 @@ int nx_enabled = 0;
4519
4520 static void __init set_nx(void)
4521 {
4522- unsigned int v[4], l, h;
4523+ if (!nx_enabled && cpu_has_nx) {
4524+ unsigned l, h;
4525
4526- if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
4527- cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
4528- if ((v[3] & (1 << 20)) && !disable_nx) {
4529- rdmsr(MSR_EFER, l, h);
4530- l |= EFER_NX;
4531- wrmsr(MSR_EFER, l, h);
4532- nx_enabled = 1;
4533- __supported_pte_mask |= _PAGE_NX;
4534- }
4535+ __supported_pte_mask &= ~_PAGE_NX;
4536+ rdmsr(MSR_EFER, l, h);
4537+ l &= ~EFER_NX;
4538+ wrmsr(MSR_EFER, l, h);
4539 }
4540 }
4541
4542@@ -512,14 +475,6 @@ void __init paging_init(void)
4543
4544 load_cr3(swapper_pg_dir);
4545
4546-#ifdef CONFIG_X86_PAE
4547- /*
4548- * We will bail out later - printk doesn't work right now so
4549- * the user would just see a hanging kernel.
4550- */
4551- if (cpu_has_pae)
4552- set_in_cr4(X86_CR4_PAE);
4553-#endif
4554 __flush_tlb_all();
4555
4556 kmap_init();
4557@@ -611,7 +566,7 @@ void __init mem_init(void)
4558 set_highmem_pages_init(bad_ppro);
4559
4560 codesize = (unsigned long) &_etext - (unsigned long) &_text;
4561- datasize = (unsigned long) &_edata - (unsigned long) &_etext;
4562+ datasize = (unsigned long) &_edata - (unsigned long) &_data;
4563 initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
4564
4565 kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
4566@@ -628,10 +583,6 @@ void __init mem_init(void)
4567 (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
4568 );
4569
4570-#ifdef CONFIG_X86_PAE
4571- if (!cpu_has_pae)
4572- panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
4573-#endif
4574 if (boot_cpu_data.wp_works_ok < 0)
4575 test_wp_bit();
4576
4577@@ -761,6 +712,37 @@ void free_init_pages(char *what, unsigne
4578
4579 void free_initmem(void)
4580 {
4581+
4582+#ifdef CONFIG_PAX_KERNEXEC
4583+ /* PaX: limit KERNEL_CS to actual size */
4584+ unsigned long addr, limit;
4585+ int cpu;
4586+ pgd_t *pgd;
4587+ pud_t *pud;
4588+ pmd_t *pmd;
4589+
4590+#ifdef CONFIG_MODULES
4591+ limit = (unsigned long)&MODULES_END - __KERNEL_TEXT_OFFSET;
4592+#else
4593+ limit = (unsigned long)&_etext;
4594+#endif
4595+ limit = (limit - 1UL) >> PAGE_SHIFT;
4596+
4597+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
4598+ get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].a = (get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].a & 0xFFFF0000UL) | (limit & 0x0FFFFUL);
4599+ get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].b = (get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].b & 0xFFF0FFFFUL) | (limit & 0xF0000UL);
4600+ }
4601+
4602+ /* PaX: make KERNEL_CS read-only */
4603+ for (addr = __KERNEL_TEXT_OFFSET; addr < (unsigned long)&_data; addr += PMD_SIZE) {
4604+ pgd = pgd_offset_k(addr);
4605+ pud = pud_offset(pgd, addr);
4606+ pmd = pmd_offset(pud, addr);
4607+ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW));
4608+ }
4609+ flush_tlb_all();
4610+#endif
4611+
4612 free_init_pages("unused kernel memory",
4613 (unsigned long)(&__init_begin),
4614 (unsigned long)(&__init_end));
4615diff -urNp linux-2.6.17.7/arch/i386/mm/mmap.c linux-2.6.17.7/arch/i386/mm/mmap.c
4616--- linux-2.6.17.7/arch/i386/mm/mmap.c 2006-07-24 23:36:01.000000000 -0400
4617+++ linux-2.6.17.7/arch/i386/mm/mmap.c 2006-08-01 20:29:45.000000000 -0400
4618@@ -34,12 +34,18 @@
4619 * Leave an at least ~128 MB hole.
4620 */
4621 #define MIN_GAP (128*1024*1024)
4622-#define MAX_GAP (TASK_SIZE/6*5)
4623+#define MAX_GAP (task_size/6*5)
4624
4625 static inline unsigned long mmap_base(struct mm_struct *mm)
4626 {
4627 unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
4628 unsigned long random_factor = 0;
4629+ unsigned long task_size = TASK_SIZE;
4630+
4631+#ifdef CONFIG_PAX_SEGMEXEC
4632+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
4633+ task_size = SEGMEXEC_TASK_SIZE;
4634+#endif
4635
4636 if (current->flags & PF_RANDOMIZE)
4637 random_factor = get_random_int() % (1024*1024);
4638@@ -49,7 +55,7 @@ static inline unsigned long mmap_base(st
4639 else if (gap > MAX_GAP)
4640 gap = MAX_GAP;
4641
4642- return PAGE_ALIGN(TASK_SIZE - gap - random_factor);
4643+ return PAGE_ALIGN(task_size - gap - random_factor);
4644 }
4645
4646 /*
4647@@ -66,10 +72,22 @@ void arch_pick_mmap_layout(struct mm_str
4648 (current->personality & ADDR_COMPAT_LAYOUT) ||
4649 current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
4650 mm->mmap_base = TASK_UNMAPPED_BASE;
4651+
4652+#ifdef CONFIG_PAX_RANDMMAP
4653+ if (mm->pax_flags & MF_PAX_RANDMMAP)
4654+ mm->mmap_base += mm->delta_mmap;
4655+#endif
4656+
4657 mm->get_unmapped_area = arch_get_unmapped_area;
4658 mm->unmap_area = arch_unmap_area;
4659 } else {
4660 mm->mmap_base = mmap_base(mm);
4661+
4662+#ifdef CONFIG_PAX_RANDMMAP
4663+ if (mm->pax_flags & MF_PAX_RANDMMAP)
4664+ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
4665+#endif
4666+
4667 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
4668 mm->unmap_area = arch_unmap_area_topdown;
4669 }
4670diff -urNp linux-2.6.17.7/arch/i386/mm/pageattr.c linux-2.6.17.7/arch/i386/mm/pageattr.c
4671--- linux-2.6.17.7/arch/i386/mm/pageattr.c 2006-07-24 23:36:01.000000000 -0400
4672+++ linux-2.6.17.7/arch/i386/mm/pageattr.c 2006-08-01 20:29:45.000000000 -0400
4673@@ -14,6 +14,7 @@
4674 #include <asm/tlbflush.h>
4675 #include <asm/pgalloc.h>
4676 #include <asm/sections.h>
4677+#include <asm/desc.h>
4678
4679 static DEFINE_SPINLOCK(cpa_lock);
4680 static struct list_head df_list = LIST_HEAD_INIT(df_list);
4681@@ -84,7 +85,18 @@ static void set_pmd_pte(pte_t *kpte, uns
4682 struct page *page;
4683 unsigned long flags;
4684
4685+#ifdef CONFIG_PAX_KERNEXEC
4686+ unsigned long cr0;
4687+
4688+ pax_open_kernel(cr0);
4689+#endif
4690+
4691 set_pte_atomic(kpte, pte); /* change init_mm */
4692+
4693+#ifdef CONFIG_PAX_KERNEXEC
4694+ pax_close_kernel(cr0);
4695+#endif
4696+
4697 if (PTRS_PER_PMD > 1)
4698 return;
4699
4700@@ -111,7 +123,7 @@ static inline void revert_page(struct pa
4701 pte_t *linear;
4702
4703 ref_prot =
4704- ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
4705+ ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext + __KERNEL_TEXT_OFFSET)
4706 ? PAGE_KERNEL_LARGE_EXEC : PAGE_KERNEL_LARGE;
4707
4708 linear = (pte_t *)
4709@@ -143,7 +155,7 @@ __change_page_attr(struct page *page, pg
4710 struct page *split;
4711
4712 ref_prot =
4713- ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
4714+ ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext + __KERNEL_TEXT_OFFSET)
4715 ? PAGE_KERNEL_EXEC : PAGE_KERNEL;
4716 split = split_large_page(address, prot, ref_prot);
4717 if (!split)
4718diff -urNp linux-2.6.17.7/arch/i386/oprofile/backtrace.c linux-2.6.17.7/arch/i386/oprofile/backtrace.c
4719--- linux-2.6.17.7/arch/i386/oprofile/backtrace.c 2006-07-24 23:36:01.000000000 -0400
4720+++ linux-2.6.17.7/arch/i386/oprofile/backtrace.c 2006-08-01 20:29:45.000000000 -0400
4721@@ -116,7 +116,7 @@ x86_backtrace(struct pt_regs * const reg
4722 head = (struct frame_head *)regs->ebp;
4723 #endif
4724
4725- if (!user_mode_vm(regs)) {
4726+ if (!user_mode(regs)) {
4727 while (depth-- && valid_kernel_stack(head, regs))
4728 head = dump_kernel_backtrace(head);
4729 return;
4730diff -urNp linux-2.6.17.7/arch/i386/power/cpu.c linux-2.6.17.7/arch/i386/power/cpu.c
4731--- linux-2.6.17.7/arch/i386/power/cpu.c 2006-07-24 23:36:01.000000000 -0400
4732+++ linux-2.6.17.7/arch/i386/power/cpu.c 2006-08-01 20:29:45.000000000 -0400
4733@@ -62,7 +62,7 @@ static void do_fpu_end(void)
4734 static void fix_processor_context(void)
4735 {
4736 int cpu = smp_processor_id();
4737- struct tss_struct * t = &per_cpu(init_tss, cpu);
4738+ struct tss_struct * t = init_tss + cpu;
4739
4740 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. */
4741
4742diff -urNp linux-2.6.17.7/arch/ia64/ia32/binfmt_elf32.c linux-2.6.17.7/arch/ia64/ia32/binfmt_elf32.c
4743--- linux-2.6.17.7/arch/ia64/ia32/binfmt_elf32.c 2006-07-24 23:36:01.000000000 -0400
4744+++ linux-2.6.17.7/arch/ia64/ia32/binfmt_elf32.c 2006-08-01 20:29:45.000000000 -0400
4745@@ -46,6 +46,17 @@ randomize_stack_top(unsigned long stack_
4746
4747 #define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack))
4748
4749+#ifdef CONFIG_PAX_ASLR
4750+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
4751+
4752+#define PAX_DELTA_MMAP_LSB(tsk) IA32_PAGE_SHIFT
4753+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - IA32_PAGE_SHIFT)
4754+#define PAX_DELTA_EXEC_LSB(tsk) IA32_PAGE_SHIFT
4755+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - IA32_PAGE_SHIFT)
4756+#define PAX_DELTA_STACK_LSB(tsk) IA32_PAGE_SHIFT
4757+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - IA32_PAGE_SHIFT)
4758+#endif
4759+
4760 /* Ugly but avoids duplication */
4761 #include "../../../fs/binfmt_elf.c"
4762
4763diff -urNp linux-2.6.17.7/arch/ia64/ia32/ia32priv.h linux-2.6.17.7/arch/ia64/ia32/ia32priv.h
4764--- linux-2.6.17.7/arch/ia64/ia32/ia32priv.h 2006-07-24 23:36:01.000000000 -0400
4765+++ linux-2.6.17.7/arch/ia64/ia32/ia32priv.h 2006-08-01 20:29:45.000000000 -0400
4766@@ -305,7 +305,14 @@ struct old_linux32_dirent {
4767 #define ELF_DATA ELFDATA2LSB
4768 #define ELF_ARCH EM_386
4769
4770-#define IA32_STACK_TOP IA32_PAGE_OFFSET
4771+#ifdef CONFIG_PAX_RANDUSTACK
4772+#define __IA32_DELTA_STACK (current->mm->delta_stack)
4773+#else
4774+#define __IA32_DELTA_STACK 0UL
4775+#endif
4776+
4777+#define IA32_STACK_TOP (IA32_PAGE_OFFSET - __IA32_DELTA_STACK)
4778+
4779 #define IA32_GATE_OFFSET IA32_PAGE_OFFSET
4780 #define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE
4781
4782diff -urNp linux-2.6.17.7/arch/ia64/kernel/module.c linux-2.6.17.7/arch/ia64/kernel/module.c
4783--- linux-2.6.17.7/arch/ia64/kernel/module.c 2006-07-24 23:36:01.000000000 -0400
4784+++ linux-2.6.17.7/arch/ia64/kernel/module.c 2006-08-01 20:29:45.000000000 -0400
4785@@ -322,7 +322,7 @@ module_alloc (unsigned long size)
4786 void
4787 module_free (struct module *mod, void *module_region)
4788 {
4789- if (mod->arch.init_unw_table && module_region == mod->module_init) {
4790+ if (mod->arch.init_unw_table && module_region == mod->module_init_rx) {
4791 unw_remove_unwind_table(mod->arch.init_unw_table);
4792 mod->arch.init_unw_table = NULL;
4793 }
4794@@ -500,15 +500,39 @@ module_frob_arch_sections (Elf_Ehdr *ehd
4795 }
4796
4797 static inline int
4798+in_init_rx (const struct module *mod, uint64_t addr)
4799+{
4800+ return addr - (uint64_t) mod->module_init_rx < mod->init_size_rx;
4801+}
4802+
4803+static inline int
4804+in_init_rw (const struct module *mod, uint64_t addr)
4805+{
4806+ return addr - (uint64_t) mod->module_init_rw < mod->init_size_rw;
4807+}
4808+
4809+static inline int
4810 in_init (const struct module *mod, uint64_t addr)
4811 {
4812- return addr - (uint64_t) mod->module_init < mod->init_size;
4813+ return in_init_rx(mod, value) || in_init_rw(mod, value);
4814+}
4815+
4816+static inline int
4817+in_core_rx (const struct module *mod, uint64_t addr)
4818+{
4819+ return addr - (uint64_t) mod->module_core_rx < mod->core_size_rx;
4820+}
4821+
4822+static inline int
4823+in_core_rw (const struct module *mod, uint64_t addr)
4824+{
4825+ return addr - (uint64_t) mod->module_core_rw < mod->core_size_rw;
4826 }
4827
4828 static inline int
4829 in_core (const struct module *mod, uint64_t addr)
4830 {
4831- return addr - (uint64_t) mod->module_core < mod->core_size;
4832+ return in_core_rx(mod, value) || in_core_rw(mod, value);
4833 }
4834
4835 static inline int
4836@@ -692,7 +716,14 @@ do_reloc (struct module *mod, uint8_t r_
4837 break;
4838
4839 case RV_BDREL:
4840- val -= (uint64_t) (in_init(mod, val) ? mod->module_init : mod->module_core);
4841+ if (in_init_rx(mod, val))
4842+ val -= (uint64_t) mod->module_init_rx;
4843+ else if (in_init_rw(mod, val))
4844+ val -= (uint64_t) mod->module_init_rw;
4845+ else if (in_core_rx(mod, val))
4846+ val -= (uint64_t) mod->module_core_rx;
4847+ else if (in_core_rw(mod, val))
4848+ val -= (uint64_t) mod->module_core_rw;
4849 break;
4850
4851 case RV_LTV:
4852@@ -826,15 +857,15 @@ apply_relocate_add (Elf64_Shdr *sechdrs,
4853 * addresses have been selected...
4854 */
4855 uint64_t gp;
4856- if (mod->core_size > MAX_LTOFF)
4857+ if (mod->core_size_rx + mod->core_size_rw > MAX_LTOFF)
4858 /*
4859 * This takes advantage of fact that SHF_ARCH_SMALL gets allocated
4860 * at the end of the module.
4861 */
4862- gp = mod->core_size - MAX_LTOFF / 2;
4863+ gp = mod->core_size_rx + mod->core_size_rw - MAX_LTOFF / 2;
4864 else
4865- gp = mod->core_size / 2;
4866- gp = (uint64_t) mod->module_core + ((gp + 7) & -8);
4867+ gp = (mod->core_size_rx + mod->core_size_rw) / 2;
4868+ gp = (uint64_t) mod->module_core_rx + ((gp + 7) & -8);
4869 mod->arch.gp = gp;
4870 DEBUGP("%s: placing gp at 0x%lx\n", __FUNCTION__, gp);
4871 }
4872diff -urNp linux-2.6.17.7/arch/ia64/kernel/ptrace.c linux-2.6.17.7/arch/ia64/kernel/ptrace.c
4873--- linux-2.6.17.7/arch/ia64/kernel/ptrace.c 2006-07-24 23:36:01.000000000 -0400
4874+++ linux-2.6.17.7/arch/ia64/kernel/ptrace.c 2006-08-01 20:29:45.000000000 -0400
4875@@ -18,6 +18,7 @@
f1a4f855 4876 #include <linux/audit.h>
4877 #include <linux/signal.h>
77fa6d7d 4878 #include <linux/vs_pid.h>
f1a4f855 4879+#include <linux/grsecurity.h>
4880
4881 #include <asm/pgtable.h>
4882 #include <asm/processor.h>
4883@@ -1447,6 +1448,9 @@ sys_ptrace (long request, pid_t pid, uns
4884 if (pid == 1) /* no messing around with init! */
4885 goto out_tsk;
4886
4887+ if (gr_handle_ptrace(child, request))
4888+ goto out_tsk;
4889+
4890 if (request == PTRACE_ATTACH) {
4891 ret = ptrace_attach(child);
4892 goto out_tsk;
4893diff -urNp linux-2.6.17.7/arch/ia64/kernel/sys_ia64.c linux-2.6.17.7/arch/ia64/kernel/sys_ia64.c
4894--- linux-2.6.17.7/arch/ia64/kernel/sys_ia64.c 2006-07-24 23:36:01.000000000 -0400
4895+++ linux-2.6.17.7/arch/ia64/kernel/sys_ia64.c 2006-08-01 20:29:45.000000000 -0400
4896@@ -38,6 +38,13 @@ arch_get_unmapped_area (struct file *fil
4897 if (REGION_NUMBER(addr) == RGN_HPAGE)
4898 addr = 0;
4899 #endif
4900+
4901+#ifdef CONFIG_PAX_RANDMMAP
4902+ if ((mm->pax_flags & MF_PAX_RANDMMAP) && addr && filp)
4903+ addr = mm->free_area_cache;
4904+ else
4905+#endif
4906+
4907 if (!addr)
4908 addr = mm->free_area_cache;
4909
4910@@ -56,9 +63,9 @@ arch_get_unmapped_area (struct file *fil
4911 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
4912 /* At this point: (!vma || addr < vma->vm_end). */
4913 if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) {
4914- if (start_addr != TASK_UNMAPPED_BASE) {
4915+ if (start_addr != mm->mmap_base) {
4916 /* Start a new search --- just in case we missed some holes. */
4917- addr = TASK_UNMAPPED_BASE;
4918+ addr = mm->mmap_base;
4919 goto full_search;
4920 }
4921 return -ENOMEM;
4922diff -urNp linux-2.6.17.7/arch/ia64/mm/fault.c linux-2.6.17.7/arch/ia64/mm/fault.c
4923--- linux-2.6.17.7/arch/ia64/mm/fault.c 2006-07-24 23:36:01.000000000 -0400
4924+++ linux-2.6.17.7/arch/ia64/mm/fault.c 2006-08-01 20:29:45.000000000 -0400
4925@@ -10,6 +10,7 @@
f1a4f855 4926 #include <linux/interrupt.h>
4927 #include <linux/kprobes.h>
77fa6d7d 4928 #include <linux/vs_memory.h>
f1a4f855 4929+#include <linux/binfmts.h>
4930
4931 #include <asm/pgtable.h>
4932 #include <asm/processor.h>
4933@@ -51,6 +52,23 @@ mapped_kernel_page_is_present (unsigned
4934 return pte_present(pte);
4935 }
4936
4937+#ifdef CONFIG_PAX_PAGEEXEC
4938+void pax_report_insns(void *pc, void *sp)
4939+{
4940+ unsigned long i;
4941+
4942+ printk(KERN_ERR "PAX: bytes at PC: ");
4943+ for (i = 0; i < 8; i++) {
4944+ unsigned int c;
4945+ if (get_user(c, (unsigned int*)pc+i))
4946+ printk("???????? ");
4947+ else
4948+ printk("%08x ", c);
4949+ }
4950+ printk("\n");
4951+}
4952+#endif
4953+
4954 void __kprobes
4955 ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
4956 {
4957@@ -116,9 +134,23 @@ ia64_do_page_fault (unsigned long addres
4958 | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)
4959 | (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_BIT));
4960
4961- if ((vma->vm_flags & mask) != mask)
4962+ if ((vma->vm_flags & mask) != mask) {
4963+
4964+#ifdef CONFIG_PAX_PAGEEXEC
4965+ if (!(vma->vm_flags & VM_EXEC) && (mask & VM_EXEC)) {
4966+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->cr_iip)
4967+ goto bad_area;
4968+
4969+ up_read(&mm->mmap_sem);
4970+ pax_report_fault(regs, (void*)regs->cr_iip, (void*)regs->r12);
4971+ do_exit(SIGKILL);
4972+ }
4973+#endif
4974+
4975 goto bad_area;
4976
4977+ }
4978+
4979 survive:
4980 /*
4981 * If for any reason at all we couldn't handle the fault, make
4982diff -urNp linux-2.6.17.7/arch/ia64/mm/init.c linux-2.6.17.7/arch/ia64/mm/init.c
4983--- linux-2.6.17.7/arch/ia64/mm/init.c 2006-07-24 23:36:01.000000000 -0400
4984+++ linux-2.6.17.7/arch/ia64/mm/init.c 2006-08-01 20:29:45.000000000 -0400
4985@@ -20,8 +20,8 @@
4986 #include <linux/swap.h>
4987 #include <linux/proc_fs.h>
4988 #include <linux/bitops.h>
4989+#include <linux/a.out.h>
4990
4991-#include <asm/a.out.h>
4992 #include <asm/dma.h>
4993 #include <asm/ia32.h>
4994 #include <asm/io.h>
4995diff -urNp linux-2.6.17.7/arch/mips/kernel/binfmt_elfn32.c linux-2.6.17.7/arch/mips/kernel/binfmt_elfn32.c
4996--- linux-2.6.17.7/arch/mips/kernel/binfmt_elfn32.c 2006-07-24 23:36:01.000000000 -0400
4997+++ linux-2.6.17.7/arch/mips/kernel/binfmt_elfn32.c 2006-08-01 20:29:45.000000000 -0400
4998@@ -50,6 +50,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
4999 #undef ELF_ET_DYN_BASE
5000 #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
5001
5002+#ifdef CONFIG_PAX_ASLR
5003+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
5004+
5005+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
5006+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5007+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
5008+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5009+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
5010+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5011+#endif
5012+
5013 #include <asm/processor.h>
5014 #include <linux/module.h>
5015 #include <linux/elfcore.h>
5016diff -urNp linux-2.6.17.7/arch/mips/kernel/binfmt_elfo32.c linux-2.6.17.7/arch/mips/kernel/binfmt_elfo32.c
5017--- linux-2.6.17.7/arch/mips/kernel/binfmt_elfo32.c 2006-07-24 23:36:01.000000000 -0400
5018+++ linux-2.6.17.7/arch/mips/kernel/binfmt_elfo32.c 2006-08-01 20:29:45.000000000 -0400
5019@@ -52,6 +52,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
5020 #undef ELF_ET_DYN_BASE
5021 #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
5022
5023+#ifdef CONFIG_PAX_ASLR
5024+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
5025+
5026+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
5027+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5028+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
5029+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5030+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
5031+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
5032+#endif
5033+
5034 #include <asm/processor.h>
5035 #include <linux/module.h>
5036 #include <linux/elfcore.h>
5037diff -urNp linux-2.6.17.7/arch/mips/kernel/syscall.c linux-2.6.17.7/arch/mips/kernel/syscall.c
5038--- linux-2.6.17.7/arch/mips/kernel/syscall.c 2006-07-24 23:36:01.000000000 -0400
5039+++ linux-2.6.17.7/arch/mips/kernel/syscall.c 2006-08-01 20:29:45.000000000 -0400
5040@@ -89,6 +89,11 @@ unsigned long arch_get_unmapped_area(str
5041 do_color_align = 0;
5042 if (filp || (flags & MAP_SHARED))
5043 do_color_align = 1;
5044+
5045+#ifdef CONFIG_PAX_RANDMMAP
5046+ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
5047+#endif
5048+
5049 if (addr) {
5050 if (do_color_align)
5051 addr = COLOUR_ALIGN(addr, pgoff);
5052@@ -99,7 +104,7 @@ unsigned long arch_get_unmapped_area(str
5053 (!vmm || addr + len <= vmm->vm_start))
5054 return addr;
5055 }
5056- addr = TASK_UNMAPPED_BASE;
5057+ addr = current->mm->mmap_base;
5058 if (do_color_align)
5059 addr = COLOUR_ALIGN(addr, pgoff);
5060 else
5061diff -urNp linux-2.6.17.7/arch/mips/mm/fault.c linux-2.6.17.7/arch/mips/mm/fault.c
5062--- linux-2.6.17.7/arch/mips/mm/fault.c 2006-07-24 23:36:01.000000000 -0400
5063+++ linux-2.6.17.7/arch/mips/mm/fault.c 2006-08-01 20:29:45.000000000 -0400
5064@@ -27,6 +27,23 @@
5065 #include <asm/ptrace.h>
5066 #include <asm/highmem.h> /* For VMALLOC_END */
5067
5068+#ifdef CONFIG_PAX_PAGEEXEC
5069+void pax_report_insns(void *pc)
5070+{
5071+ unsigned long i;
5072+
5073+ printk(KERN_ERR "PAX: bytes at PC: ");
5074+ for (i = 0; i < 5; i++) {
5075+ unsigned int c;
5076+ if (get_user(c, (unsigned int*)pc+i))
5077+ printk("???????? ");
5078+ else
5079+ printk("%08x ", c);
5080+ }
5081+ printk("\n");
5082+}
5083+#endif
5084+
5085 /*
5086 * This routine handles page faults. It determines the address,
5087 * and the problem, and then passes it off to one of the appropriate
5088diff -urNp linux-2.6.17.7/arch/parisc/kernel/module.c linux-2.6.17.7/arch/parisc/kernel/module.c
5089--- linux-2.6.17.7/arch/parisc/kernel/module.c 2006-07-24 23:36:01.000000000 -0400
5090+++ linux-2.6.17.7/arch/parisc/kernel/module.c 2006-08-01 20:29:45.000000000 -0400
5091@@ -72,16 +72,38 @@
5092
5093 /* three functions to determine where in the module core
5094 * or init pieces the location is */
5095+static inline int is_init_rx(struct module *me, void *loc)
5096+{
5097+ return (loc >= me->module_init_rx &&
5098+ loc < (me->module_init_rx + me->init_size_rx));
5099+}
5100+
5101+static inline int is_init_rw(struct module *me, void *loc)
5102+{
5103+ return (loc >= me->module_init_rw &&
5104+ loc < (me->module_init_rw + me->init_size_rw));
5105+}
5106+
5107 static inline int is_init(struct module *me, void *loc)
5108 {
5109- return (loc >= me->module_init &&
5110- loc <= (me->module_init + me->init_size));
5111+ return is_init_rx(me, loc) || is_init_rw(me, loc);
5112+}
5113+
5114+static inline int is_core_rx(struct module *me, void *loc)
5115+{
5116+ return (loc >= me->module_core_rx &&
5117+ loc < (me->module_core_rx + me->core_size_rx));
5118+}
5119+
5120+static inline int is_core_rw(struct module *me, void *loc)
5121+{
5122+ return (loc >= me->module_core_rw &&
5123+ loc < (me->module_core_rw + me->core_size_rw));
5124 }
5125
5126 static inline int is_core(struct module *me, void *loc)
5127 {
5128- return (loc >= me->module_core &&
5129- loc <= (me->module_core + me->core_size));
5130+ return is_core_rx(me, loc) || is_core_rw(me, loc);
5131 }
5132
5133 static inline int is_local(struct module *me, void *loc)
5134@@ -289,21 +311,21 @@ int module_frob_arch_sections(CONST Elf_
5135 }
5136
5137 /* align things a bit */
5138- me->core_size = ALIGN(me->core_size, 16);
5139- me->arch.got_offset = me->core_size;
5140- me->core_size += gots * sizeof(struct got_entry);
5141-
5142- me->core_size = ALIGN(me->core_size, 16);
5143- me->arch.fdesc_offset = me->core_size;
5144- me->core_size += fdescs * sizeof(Elf_Fdesc);
5145-
5146- me->core_size = ALIGN(me->core_size, 16);
5147- me->arch.stub_offset = me->core_size;
5148- me->core_size += stubs * sizeof(struct stub_entry);
5149-
5150- me->init_size = ALIGN(me->init_size, 16);
5151- me->arch.init_stub_offset = me->init_size;
5152- me->init_size += init_stubs * sizeof(struct stub_entry);
5153+ me->core_size_rw = ALIGN(me->core_size_rw, 16);
5154+ me->arch.got_offset = me->core_size_rw;
5155+ me->core_size_rw += gots * sizeof(struct got_entry);
5156+
5157+ me->core_size_rw = ALIGN(me->core_size_rw, 16);
5158+ me->arch.fdesc_offset = me->core_size_rw;
5159+ me->core_size_rw += fdescs * sizeof(Elf_Fdesc);
5160+
5161+ me->core_size_rx = ALIGN(me->core_size_rx, 16);
5162+ me->arch.stub_offset = me->core_size_rx;
5163+ me->core_size_rx += stubs * sizeof(struct stub_entry);
5164+
5165+ me->init_size_rx = ALIGN(me->init_size_rx, 16);
5166+ me->arch.init_stub_offset = me->init_size_rx;
5167+ me->init_size_rx += init_stubs * sizeof(struct stub_entry);
5168
5169 me->arch.got_max = gots;
5170 me->arch.fdesc_max = fdescs;
5171@@ -323,7 +345,7 @@ static Elf64_Word get_got(struct module
5172
5173 BUG_ON(value == 0);
5174
5175- got = me->module_core + me->arch.got_offset;
5176+ got = me->module_core_rw + me->arch.got_offset;
5177 for (i = 0; got[i].addr; i++)
5178 if (got[i].addr == value)
5179 goto out;
5180@@ -341,7 +363,7 @@ static Elf64_Word get_got(struct module
5181 #ifdef __LP64__
5182 static Elf_Addr get_fdesc(struct module *me, unsigned long value)
5183 {
5184- Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
5185+ Elf_Fdesc *fdesc = me->module_core_rw + me->arch.fdesc_offset;
5186
5187 if (!value) {
5188 printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
5189@@ -359,7 +381,7 @@ static Elf_Addr get_fdesc(struct module
5190
5191 /* Create new one */
5192 fdesc->addr = value;
5193- fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset;
5194+ fdesc->gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset;
5195 return (Elf_Addr)fdesc;
5196 }
5197 #endif /* __LP64__ */
5198@@ -373,12 +395,12 @@ static Elf_Addr get_stub(struct module *
5199 if(init_section) {
5200 i = me->arch.init_stub_count++;
5201 BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
5202- stub = me->module_init + me->arch.init_stub_offset +
5203+ stub = me->module_init_rx + me->arch.init_stub_offset +
5204 i * sizeof(struct stub_entry);
5205 } else {
5206 i = me->arch.stub_count++;
5207 BUG_ON(me->arch.stub_count > me->arch.stub_max);
5208- stub = me->module_core + me->arch.stub_offset +
5209+ stub = me->module_core_rx + me->arch.stub_offset +
5210 i * sizeof(struct stub_entry);
5211 }
5212
5213@@ -721,7 +743,7 @@ register_unwind_table(struct module *me,
5214
5215 table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr;
5216 end = table + sechdrs[me->arch.unwind_section].sh_size;
5217- gp = (Elf_Addr)me->module_core + me->arch.got_offset;
5218+ gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset;
5219
5220 DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
5221 me->arch.unwind_section, table, end, gp);
5222diff -urNp linux-2.6.17.7/arch/parisc/kernel/ptrace.c linux-2.6.17.7/arch/parisc/kernel/ptrace.c
5223--- linux-2.6.17.7/arch/parisc/kernel/ptrace.c 2006-07-24 23:36:01.000000000 -0400
5224+++ linux-2.6.17.7/arch/parisc/kernel/ptrace.c 2006-08-01 20:29:45.000000000 -0400
5225@@ -18,6 +18,7 @@
5226 #include <linux/security.h>
5227 #include <linux/compat.h>
5228 #include <linux/signal.h>
5229+#include <linux/grsecurity.h>
5230
5231 #include <asm/uaccess.h>
5232 #include <asm/pgtable.h>
5233diff -urNp linux-2.6.17.7/arch/parisc/kernel/sys_parisc.c linux-2.6.17.7/arch/parisc/kernel/sys_parisc.c
5234--- linux-2.6.17.7/arch/parisc/kernel/sys_parisc.c 2006-07-24 23:36:01.000000000 -0400
5235+++ linux-2.6.17.7/arch/parisc/kernel/sys_parisc.c 2006-08-01 20:29:45.000000000 -0400
5236@@ -105,7 +105,7 @@ unsigned long arch_get_unmapped_area(str
5237 if (len > TASK_SIZE)
5238 return -ENOMEM;
5239 if (!addr)
5240- addr = TASK_UNMAPPED_BASE;
5241+ addr = current->mm->mmap_base;
5242
5243 if (filp) {
5244 addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
5245diff -urNp linux-2.6.17.7/arch/parisc/kernel/traps.c linux-2.6.17.7/arch/parisc/kernel/traps.c
5246--- linux-2.6.17.7/arch/parisc/kernel/traps.c 2006-07-24 23:36:01.000000000 -0400
5247+++ linux-2.6.17.7/arch/parisc/kernel/traps.c 2006-08-01 20:29:45.000000000 -0400
5248@@ -711,9 +711,7 @@ void handle_interruption(int code, struc
5249
5250 down_read(&current->mm->mmap_sem);
5251 vma = find_vma(current->mm,regs->iaoq[0]);
5252- if (vma && (regs->iaoq[0] >= vma->vm_start)
5253- && (vma->vm_flags & VM_EXEC)) {
5254-
5255+ if (vma && (regs->iaoq[0] >= vma->vm_start)) {
5256 fault_address = regs->iaoq[0];
5257 fault_space = regs->iasq[0];
5258
5259diff -urNp linux-2.6.17.7/arch/parisc/mm/fault.c linux-2.6.17.7/arch/parisc/mm/fault.c
5260--- linux-2.6.17.7/arch/parisc/mm/fault.c 2006-07-24 23:36:01.000000000 -0400
5261+++ linux-2.6.17.7/arch/parisc/mm/fault.c 2006-08-01 20:29:45.000000000 -0400
5262@@ -16,6 +16,8 @@
5263 #include <linux/sched.h>
5264 #include <linux/interrupt.h>
5265 #include <linux/module.h>
5266+#include <linux/unistd.h>
5267+#include <linux/binfmts.h>
5268
5269 #include <asm/uaccess.h>
5270 #include <asm/traps.h>
5271@@ -57,7 +59,7 @@ DEFINE_PER_CPU(struct exception_data, ex
5272 static unsigned long
5273 parisc_acctyp(unsigned long code, unsigned int inst)
5274 {
5275- if (code == 6 || code == 16)
5276+ if (code == 6 || code == 7 || code == 16)
5277 return VM_EXEC;
5278
5279 switch (inst & 0xf0000000) {
5280@@ -143,6 +145,116 @@ parisc_acctyp(unsigned long code, unsign
5281 }
5282 #endif
5283
5284+#ifdef CONFIG_PAX_PAGEEXEC
5285+/*
5286+ * PaX: decide what to do with offenders (instruction_pointer(regs) = fault address)
5287+ *
5288+ * returns 1 when task should be killed
5289+ * 2 when rt_sigreturn trampoline was detected
5290+ * 3 when unpatched PLT trampoline was detected
5291+ */
5292+static int pax_handle_fetch_fault(struct pt_regs *regs)
5293+{
5294+
5295+#ifdef CONFIG_PAX_EMUPLT
5296+ int err;
5297+
5298+ do { /* PaX: unpatched PLT emulation */
5299+ unsigned int bl, depwi;
5300+
5301+ err = get_user(bl, (unsigned int*)instruction_pointer(regs));
5302+ err |= get_user(depwi, (unsigned int*)(instruction_pointer(regs)+4));
5303+
5304+ if (err)
5305+ break;
5306+
5307+ if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) {
5308+ unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12;
5309+
5310+ err = get_user(ldw, (unsigned int*)addr);
5311+ err |= get_user(bv, (unsigned int*)(addr+4));
5312+ err |= get_user(ldw2, (unsigned int*)(addr+8));
5313+
5314+ if (err)
5315+ break;
5316+
5317+ if (ldw == 0x0E801096U &&
5318+ bv == 0xEAC0C000U &&
5319+ ldw2 == 0x0E881095U)
5320+ {
5321+ unsigned int resolver, map;
5322+
5323+ err = get_user(resolver, (unsigned int*)(instruction_pointer(regs)+8));
5324+ err |= get_user(map, (unsigned int*)(instruction_pointer(regs)+12));
5325+ if (err)
5326+ break;
5327+
5328+ regs->gr[20] = instruction_pointer(regs)+8;
5329+ regs->gr[21] = map;
5330+ regs->gr[22] = resolver;
5331+ regs->iaoq[0] = resolver | 3UL;
5332+ regs->iaoq[1] = regs->iaoq[0] + 4;
5333+ return 3;
5334+ }
5335+ }
5336+ } while (0);
5337+#endif
5338+
5339+#ifdef CONFIG_PAX_EMUTRAMP
5340+
5341+#ifndef CONFIG_PAX_EMUSIGRT
5342+ if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
5343+ return 1;
5344+#endif
5345+
5346+ do { /* PaX: rt_sigreturn emulation */
5347+ unsigned int ldi1, ldi2, bel, nop;
5348+
5349+ err = get_user(ldi1, (unsigned int *)instruction_pointer(regs));
5350+ err |= get_user(ldi2, (unsigned int *)(instruction_pointer(regs)+4));
5351+ err |= get_user(bel, (unsigned int *)(instruction_pointer(regs)+8));
5352+ err |= get_user(nop, (unsigned int *)(instruction_pointer(regs)+12));
5353+
5354+ if (err)
5355+ break;
5356+
5357+ if ((ldi1 == 0x34190000U || ldi1 == 0x34190002U) &&
5358+ ldi2 == 0x3414015AU &&
5359+ bel == 0xE4008200U &&
5360+ nop == 0x08000240U)
5361+ {
5362+ regs->gr[25] = (ldi1 & 2) >> 1;
5363+ regs->gr[20] = __NR_rt_sigreturn;
5364+ regs->gr[31] = regs->iaoq[1] + 16;
5365+ regs->sr[0] = regs->iasq[1];
5366+ regs->iaoq[0] = 0x100UL;
5367+ regs->iaoq[1] = regs->iaoq[0] + 4;
5368+ regs->iasq[0] = regs->sr[2];
5369+ regs->iasq[1] = regs->sr[2];
5370+ return 2;
5371+ }
5372+ } while (0);
5373+#endif
5374+
5375+ return 1;
5376+}
5377+
5378+void pax_report_insns(void *pc, void *sp)
5379+{
5380+ unsigned long i;
5381+
5382+ printk(KERN_ERR "PAX: bytes at PC: ");
5383+ for (i = 0; i < 5; i++) {
5384+ unsigned int c;
5385+ if (get_user(c, (unsigned int*)pc+i))
5386+ printk("???????? ");
5387+ else
5388+ printk("%08x ", c);
5389+ }
5390+ printk("\n");
5391+}
5392+#endif
5393+
5394 void do_page_fault(struct pt_regs *regs, unsigned long code,
5395 unsigned long address)
5396 {
5397@@ -168,8 +280,33 @@ good_area:
5398
5399 acc_type = parisc_acctyp(code,regs->iir);
5400
5401- if ((vma->vm_flags & acc_type) != acc_type)
5402+ if ((vma->vm_flags & acc_type) != acc_type) {
5403+
5404+#ifdef CONFIG_PAX_PAGEEXEC
5405+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (acc_type & VM_EXEC) &&
5406+ (address & ~3UL) == instruction_pointer(regs))
5407+ {
5408+ up_read(&mm->mmap_sem);
5409+ switch(pax_handle_fetch_fault(regs)) {
5410+
5411+#ifdef CONFIG_PAX_EMUPLT
5412+ case 3:
5413+ return;
5414+#endif
5415+
5416+#ifdef CONFIG_PAX_EMUTRAMP
5417+ case 2:
5418+ return;
5419+#endif
5420+
5421+ }
5422+ pax_report_fault(regs, (void*)instruction_pointer(regs), (void*)regs->gr[30]);
5423+ do_exit(SIGKILL);
5424+ }
5425+#endif
5426+
5427 goto bad_area;
5428+ }
5429
5430 /*
5431 * If for any reason at all we couldn't handle the fault, make
5432diff -urNp linux-2.6.17.7/arch/powerpc/kernel/module_32.c linux-2.6.17.7/arch/powerpc/kernel/module_32.c
5433--- linux-2.6.17.7/arch/powerpc/kernel/module_32.c 2006-07-24 23:36:01.000000000 -0400
5434+++ linux-2.6.17.7/arch/powerpc/kernel/module_32.c 2006-08-01 20:29:45.000000000 -0400
5435@@ -123,7 +123,7 @@ int module_frob_arch_sections(Elf32_Ehdr
5436 me->arch.core_plt_section = i;
5437 }
5438 if (!me->arch.core_plt_section || !me->arch.init_plt_section) {
5439- printk("Module doesn't contain .plt or .init.plt sections.\n");
5440+ printk("Module %s doesn't contain .plt or .init.plt sections.\n", me->name);
5441 return -ENOEXEC;
5442 }
5443
5444@@ -164,11 +164,16 @@ static uint32_t do_plt_call(void *locati
5445
5446 DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location);
5447 /* Init, or core PLT? */
5448- if (location >= mod->module_core
5449- && location < mod->module_core + mod->core_size)
5450+ if ((location >= mod->module_core_rx && location < mod->module_core_rx + mod->core_size_rx) ||
5451+ (location >= mod->module_core_rw && location < mod->module_core_rw + mod->core_size_rw))
5452 entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
5453- else
5454+ else if ((location >= mod->module_init_rx && location < mod->module_init_rx + mod->init_size_rx) ||
5455+ (location >= mod->module_init_rw && location < mod->module_init_rw + mod->init_size_rw))
5456 entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
5457+ else {
5458+ printk(KERN_ERR "%s: invalid R_PPC_REL24 entry found\n", mod->name);
5459+ return ~0UL;
5460+ }
5461
5462 /* Find this entry, or if that fails, the next avail. entry */
5463 while (entry->jump[0]) {
5464diff -urNp linux-2.6.17.7/arch/powerpc/mm/fault.c linux-2.6.17.7/arch/powerpc/mm/fault.c
5465--- linux-2.6.17.7/arch/powerpc/mm/fault.c 2006-07-24 23:36:01.000000000 -0400
5466+++ linux-2.6.17.7/arch/powerpc/mm/fault.c 2006-08-01 20:29:45.000000000 -0400
5467@@ -29,6 +29,7 @@
5468 #include <linux/highmem.h>
5469 #include <linux/module.h>
5470 #include <linux/kprobes.h>
5471+#include <linux/binfmts.h>
5472
5473 #include <asm/page.h>
5474 #include <asm/pgtable.h>
5475@@ -103,6 +104,38 @@ static void do_dabr(struct pt_regs *regs
5476 }
5477 #endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
5478
5479+#ifdef CONFIG_PAX_PAGEEXEC
5480+/*
5481+ * PaX: decide what to do with offenders (regs->nip = fault address)
5482+ *
5483+ * returns 1 when task should be killed
5484+ */
5485+static int pax_handle_fetch_fault(struct pt_regs *regs)
5486+{
5487+
5488+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT)
5489+ int err;
5490+#endif
5491+
5492+ return 1;
5493+}
5494+
5495+void pax_report_insns(void *pc, void *sp)
5496+{
5497+ unsigned long i;
5498+
5499+ printk(KERN_ERR "PAX: bytes at PC: ");
5500+ for (i = 0; i < 5; i++) {
5501+ unsigned int c;
5502+ if (get_user(c, (unsigned int*)pc+i))
5503+ printk("???????? ");
5504+ else
5505+ printk("%08x ", c);
5506+ }
5507+ printk("\n");
5508+}
5509+#endif
5510+
5511 /*
5512 * For 600- and 800-family processors, the error_code parameter is DSISR
5513 * for a data fault, SRR1 for an instruction fault. For 400-family processors
5514@@ -335,6 +368,19 @@ bad_area:
5515 bad_area_nosemaphore:
5516 /* User mode accesses cause a SIGSEGV */
5517 if (user_mode(regs)) {
5518+
5519+#ifdef CONFIG_PAX_PAGEEXEC
5520+ if (mm->pax_flags & MF_PAX_PAGEEXEC) {
5521+ if (is_exec && (error_code & DSISR_PROTFAULT)) {
5522+ switch (pax_handle_fetch_fault(regs)) {
5523+ }
5524+
5525+ pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]);
5526+ do_exit(SIGKILL);
5527+ }
5528+ }
5529+#endif
5530+
5531 _exception(SIGSEGV, regs, code, address);
5532 return 0;
5533 }
5534diff -urNp linux-2.6.17.7/arch/powerpc/mm/mmap.c linux-2.6.17.7/arch/powerpc/mm/mmap.c
5535--- linux-2.6.17.7/arch/powerpc/mm/mmap.c 2006-07-24 23:36:01.000000000 -0400
5536+++ linux-2.6.17.7/arch/powerpc/mm/mmap.c 2006-08-01 20:29:45.000000000 -0400
5537@@ -74,10 +74,22 @@ void arch_pick_mmap_layout(struct mm_str
5538 */
5539 if (mmap_is_legacy()) {
5540 mm->mmap_base = TASK_UNMAPPED_BASE;
5541+
5542+#ifdef CONFIG_PAX_RANDMMAP
5543+ if (mm->pax_flags & MF_PAX_RANDMMAP)
5544+ mm->mmap_base += mm->delta_mmap;
5545+#endif
5546+
5547 mm->get_unmapped_area = arch_get_unmapped_area;
5548 mm->unmap_area = arch_unmap_area;
5549 } else {
5550 mm->mmap_base = mmap_base();
5551+
5552+#ifdef CONFIG_PAX_RANDMMAP
5553+ if (mm->pax_flags & MF_PAX_RANDMMAP)
5554+ mm->mmap_base -= mm->delta_mmap;
5555+#endif
5556+
5557 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
5558 mm->unmap_area = arch_unmap_area_topdown;
5559 }
5560diff -urNp linux-2.6.17.7/arch/ppc/mm/fault.c linux-2.6.17.7/arch/ppc/mm/fault.c
5561--- linux-2.6.17.7/arch/ppc/mm/fault.c 2006-07-24 23:36:01.000000000 -0400
5562+++ linux-2.6.17.7/arch/ppc/mm/fault.c 2006-08-01 20:29:46.000000000 -0400
5563@@ -26,6 +26,11 @@
5564 #include <linux/interrupt.h>
5565 #include <linux/highmem.h>
5566 #include <linux/module.h>
5567+#include <linux/slab.h>
5568+#include <linux/pagemap.h>
5569+#include <linux/compiler.h>
5570+#include <linux/binfmts.h>
5571+#include <linux/unistd.h>
5572
5573 #include <asm/page.h>
5574 #include <asm/pgtable.h>
5575@@ -49,6 +54,364 @@ unsigned long pte_misses; /* updated by
5576 unsigned long pte_errors; /* updated by do_page_fault() */
5577 unsigned int probingmem;
5578
5579+#ifdef CONFIG_PAX_EMUSIGRT
5580+void pax_syscall_close(struct vm_area_struct * vma)
5581+{
5582+ vma->vm_mm->call_syscall = 0UL;
5583+}
5584+
5585+static struct page* pax_syscall_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
5586+{
5587+ struct page* page;
5588+ unsigned int *kaddr;
5589+
5590+ page = alloc_page(GFP_HIGHUSER);
5591+ if (!page)
5592+ return NOPAGE_OOM;
5593+
5594+ kaddr = kmap(page);
5595+ memset(kaddr, 0, PAGE_SIZE);
5596+ kaddr[0] = 0x44000002U; /* sc */
5597+ __flush_dcache_icache(kaddr);
5598+ kunmap(page);
5599+ if (type)
5600+ *type = VM_FAULT_MAJOR;
5601+ return page;
5602+}
5603+
5604+static struct vm_operations_struct pax_vm_ops = {
5605+ .close = pax_syscall_close,
5606+ .nopage = pax_syscall_nopage,
5607+};
5608+
5609+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
5610+{
5611+ int ret;
5612+
5613+ memset(vma, 0, sizeof(*vma));
5614+ vma->vm_mm = current->mm;
5615+ vma->vm_start = addr;
5616+ vma->vm_end = addr + PAGE_SIZE;
5617+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
5618+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
5619+ vma->vm_ops = &pax_vm_ops;
5620+
5621+ ret = insert_vm_struct(current->mm, vma);
5622+ if (ret)
5623+ return ret;
5624+
5625+ ++current->mm->total_vm;
5626+ return 0;
5627+}
5628+#endif
5629+
5630+#ifdef CONFIG_PAX_PAGEEXEC
5631+/*
5632+ * PaX: decide what to do with offenders (regs->nip = fault address)
5633+ *
5634+ * returns 1 when task should be killed
5635+ * 2 when patched GOT trampoline was detected
5636+ * 3 when patched PLT trampoline was detected
5637+ * 4 when unpatched PLT trampoline was detected
5638+ * 5 when sigreturn trampoline was detected
5639+ * 7 when rt_sigreturn trampoline was detected
5640+ */
5641+static int pax_handle_fetch_fault(struct pt_regs *regs)
5642+{
5643+
5644+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT)
5645+ int err;
5646+#endif
5647+
5648+#ifdef CONFIG_PAX_EMUPLT
5649+ do { /* PaX: patched GOT emulation */
5650+ unsigned int blrl;
5651+
5652+ err = get_user(blrl, (unsigned int*)regs->nip);
5653+
5654+ if (!err && blrl == 0x4E800021U) {
5655+ unsigned long temp = regs->nip;
5656+
5657+ regs->nip = regs->link & 0xFFFFFFFCUL;
5658+ regs->link = temp + 4UL;
5659+ return 2;
5660+ }
5661+ } while (0);
5662+
5663+ do { /* PaX: patched PLT emulation #1 */
5664+ unsigned int b;
5665+
5666+ err = get_user(b, (unsigned int *)regs->nip);
5667+
5668+ if (!err && (b & 0xFC000003U) == 0x48000000U) {
5669+ regs->nip += (((b | 0xFC000000UL) ^ 0x02000000UL) + 0x02000000UL);
5670+ return 3;
5671+ }
5672+ } while (0);
5673+
5674+ do { /* PaX: unpatched PLT emulation #1 */
5675+ unsigned int li, b;
5676+
5677+ err = get_user(li, (unsigned int *)regs->nip);
5678+ err |= get_user(b, (unsigned int *)(regs->nip+4));
5679+
5680+ if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) {
5681+ unsigned int rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr;
5682+ unsigned long addr = b | 0xFC000000UL;
5683+
5684+ addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL);
5685+ err = get_user(rlwinm, (unsigned int*)addr);
5686+ err |= get_user(add, (unsigned int*)(addr+4));
5687+ err |= get_user(li2, (unsigned int*)(addr+8));
5688+ err |= get_user(addis2, (unsigned int*)(addr+12));
5689+ err |= get_user(mtctr, (unsigned int*)(addr+16));
5690+ err |= get_user(li3, (unsigned int*)(addr+20));
5691+ err |= get_user(addis3, (unsigned int*)(addr+24));
5692+ err |= get_user(bctr, (unsigned int*)(addr+28));
5693+
5694+ if (err)
5695+ break;
5696+
5697+ if (rlwinm == 0x556C083CU &&
5698+ add == 0x7D6C5A14U &&
5699+ (li2 & 0xFFFF0000U) == 0x39800000U &&
5700+ (addis2 & 0xFFFF0000U) == 0x3D8C0000U &&
5701+ mtctr == 0x7D8903A6U &&
5702+ (li3 & 0xFFFF0000U) == 0x39800000U &&
5703+ (addis3 & 0xFFFF0000U) == 0x3D8C0000U &&
5704+ bctr == 0x4E800420U)
5705+ {
5706+ regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5707+ regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5708+ regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16;
5709+ regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5710+ regs->ctr += (addis2 & 0xFFFFU) << 16;
5711+ regs->nip = regs->ctr;
5712+ return 4;
5713+ }
5714+ }
5715+ } while (0);
5716+
5717+#if 0
5718+ do { /* PaX: unpatched PLT emulation #2 */
5719+ unsigned int lis, lwzu, b, bctr;
5720+
5721+ err = get_user(lis, (unsigned int *)regs->nip);
5722+ err |= get_user(lwzu, (unsigned int *)(regs->nip+4));
5723+ err |= get_user(b, (unsigned int *)(regs->nip+8));
5724+ err |= get_user(bctr, (unsigned int *)(regs->nip+12));
5725+
5726+ if (err)
5727+ break;
5728+
5729+ if ((lis & 0xFFFF0000U) == 0x39600000U &&
5730+ (lwzu & 0xU) == 0xU &&
5731+ (b & 0xFC000003U) == 0x48000000U &&
5732+ bctr == 0x4E800420U)
5733+ {
5734+ unsigned int addis, addi, rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr;
5735+ unsigned long addr = b | 0xFC000000UL;
5736+
5737+ addr = regs->nip + 12 + ((addr ^ 0x02000000UL) + 0x02000000UL);
5738+ err = get_user(addis, (unsigned int*)addr);
5739+ err |= get_user(addi, (unsigned int*)(addr+4));
5740+ err |= get_user(rlwinm, (unsigned int*)(addr+8));
5741+ err |= get_user(add, (unsigned int*)(addr+12));
5742+ err |= get_user(li2, (unsigned int*)(addr+16));
5743+ err |= get_user(addis2, (unsigned int*)(addr+20));
5744+ err |= get_user(mtctr, (unsigned int*)(addr+24));
5745+ err |= get_user(li3, (unsigned int*)(addr+28));
5746+ err |= get_user(addis3, (unsigned int*)(addr+32));
5747+ err |= get_user(bctr, (unsigned int*)(addr+36));
5748+
5749+ if (err)
5750+ break;
5751+
5752+ if ((addis & 0xFFFF0000U) == 0x3D6B0000U &&
5753+ (addi & 0xFFFF0000U) == 0x396B0000U &&
5754+ rlwinm == 0x556C083CU &&
5755+ add == 0x7D6C5A14U &&
5756+ (li2 & 0xFFFF0000U) == 0x39800000U &&
5757+ (addis2 & 0xFFFF0000U) == 0x3D8C0000U &&
5758+ mtctr == 0x7D8903A6U &&
5759+ (li3 & 0xFFFF0000U) == 0x39800000U &&
5760+ (addis3 & 0xFFFF0000U) == 0x3D8C0000U &&
5761+ bctr == 0x4E800420U)
5762+ {
5763+ regs->gpr[PT_R11] =
5764+ regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5765+ regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5766+ regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16;
5767+ regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5768+ regs->ctr += (addis2 & 0xFFFFU) << 16;
5769+ regs->nip = regs->ctr;
5770+ return 4;
5771+ }
5772+ }
5773+ } while (0);
5774+#endif
5775+
5776+ do { /* PaX: unpatched PLT emulation #3 */
5777+ unsigned int li, b;
5778+
5779+ err = get_user(li, (unsigned int *)regs->nip);
5780+ err |= get_user(b, (unsigned int *)(regs->nip+4));
5781+
5782+ if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) {
5783+ unsigned int addis, lwz, mtctr, bctr;
5784+ unsigned long addr = b | 0xFC000000UL;
5785+
5786+ addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL);
5787+ err = get_user(addis, (unsigned int*)addr);
5788+ err |= get_user(lwz, (unsigned int*)(addr+4));
5789+ err |= get_user(mtctr, (unsigned int*)(addr+8));
5790+ err |= get_user(bctr, (unsigned int*)(addr+12));
5791+
5792+ if (err)
5793+ break;
5794+
5795+ if ((addis & 0xFFFF0000U) == 0x3D6B0000U &&
5796+ (lwz & 0xFFFF0000U) == 0x816B0000U &&
5797+ mtctr == 0x7D6903A6U &&
5798+ bctr == 0x4E800420U)
5799+ {
5800+ unsigned int r11;
5801+
5802+ addr = (addis << 16) + (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5803+ addr += (((lwz | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
5804+
5805+ err = get_user(r11, (unsigned int*)addr);
5806+ if (err)
5807+ break;
5808+
5809+ regs->gpr[PT_R11] = r11;
5810+ regs->ctr = r11;
5811+ regs->nip = r11;
5812+ return 4;
5813+ }
5814+ }
5815+ } while (0);
5816+#endif
5817+
5818+#ifdef CONFIG_PAX_EMUSIGRT
5819+ do { /* PaX: sigreturn emulation */
5820+ unsigned int li, sc;
5821+
5822+ err = get_user(li, (unsigned int *)regs->nip);
5823+ err |= get_user(sc, (unsigned int *)(regs->nip+4));
5824+
5825+ if (!err && li == 0x38000000U + __NR_sigreturn && sc == 0x44000002U) {
5826+ struct vm_area_struct *vma;
5827+ unsigned long call_syscall;
5828+
5829+ down_read(&current->mm->mmap_sem);
5830+ call_syscall = current->mm->call_syscall;
5831+ up_read(&current->mm->mmap_sem);
5832+ if (likely(call_syscall))
5833+ goto emulate;
5834+
5835+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
5836+
5837+ down_write(&current->mm->mmap_sem);
5838+ if (current->mm->call_syscall) {
5839+ call_syscall = current->mm->call_syscall;
5840+ up_write(&current->mm->mmap_sem);
5841+ if (vma) kmem_cache_free(vm_area_cachep, vma);
5842+ goto emulate;
5843+ }
5844+
5845+ call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
5846+ if (!vma || (call_syscall & ~PAGE_MASK)) {
5847+ up_write(&current->mm->mmap_sem);
5848+ if (vma) kmem_cache_free(vm_area_cachep, vma);
5849+ return 1;
5850+ }
5851+
5852+ if (pax_insert_vma(vma, call_syscall)) {
5853+ up_write(&current->mm->mmap_sem);
5854+ kmem_cache_free(vm_area_cachep, vma);
5855+ return 1;
5856+ }
5857+
5858+ current->mm->call_syscall = call_syscall;
5859+ up_write(&current->mm->mmap_sem);
5860+
5861+emulate:
5862+ regs->gpr[PT_R0] = __NR_sigreturn;
5863+ regs->nip = call_syscall;
5864+ return 5;
5865+ }
5866+ } while (0);
5867+
5868+ do { /* PaX: rt_sigreturn emulation */
5869+ unsigned int li, sc;
5870+
5871+ err = get_user(li, (unsigned int *)regs->nip);
5872+ err |= get_user(sc, (unsigned int *)(regs->nip+4));
5873+
5874+ if (!err && li == 0x38000000U + __NR_rt_sigreturn && sc == 0x44000002U) {
5875+ struct vm_area_struct *vma;
5876+ unsigned int call_syscall;
5877+
5878+ down_read(&current->mm->mmap_sem);
5879+ call_syscall = current->mm->call_syscall;
5880+ up_read(&current->mm->mmap_sem);
5881+ if (likely(call_syscall))
5882+ goto rt_emulate;
5883+
5884+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
5885+
5886+ down_write(&current->mm->mmap_sem);
5887+ if (current->mm->call_syscall) {
5888+ call_syscall = current->mm->call_syscall;
5889+ up_write(&current->mm->mmap_sem);
5890+ if (vma) kmem_cache_free(vm_area_cachep, vma);
5891+ goto rt_emulate;
5892+ }
5893+
5894+ call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
5895+ if (!vma || (call_syscall & ~PAGE_MASK)) {
5896+ up_write(&current->mm->mmap_sem);
5897+ if (vma) kmem_cache_free(vm_area_cachep, vma);
5898+ return 1;
5899+ }
5900+
5901+ if (pax_insert_vma(vma, call_syscall)) {
5902+ up_write(&current->mm->mmap_sem);
5903+ kmem_cache_free(vm_area_cachep, vma);
5904+ return 1;
5905+ }
5906+
5907+ current->mm->call_syscall = call_syscall;
5908+ up_write(&current->mm->mmap_sem);
5909+
5910+rt_emulate:
5911+ regs->gpr[PT_R0] = __NR_rt_sigreturn;
5912+ regs->nip = call_syscall;
5913+ return 6;
5914+ }
5915+ } while (0);
5916+#endif
5917+
5918+ return 1;
5919+}
5920+
5921+void pax_report_insns(void *pc, void *sp)
5922+{
5923+ unsigned long i;
5924+
5925+ printk(KERN_ERR "PAX: bytes at PC: ");
5926+ for (i = 0; i < 5; i++) {
5927+ unsigned int c;
5928+ if (get_user(c, (unsigned int*)pc+i))
5929+ printk("???????? ");
5930+ else
5931+ printk("%08x ", c);
5932+ }
5933+ printk("\n");
5934+}
5935+#endif
5936+
5937 /*
5938 * Check whether the instruction at regs->nip is a store using
5939 * an update addressing form which will update r1.
5940@@ -109,7 +472,7 @@ int do_page_fault(struct pt_regs *regs,
5941 * indicate errors in DSISR but can validly be set in SRR1.
5942 */
5943 if (TRAP(regs) == 0x400)
5944- error_code &= 0x48200000;
5945+ error_code &= 0x58200000;
5946 else
5947 is_write = error_code & 0x02000000;
5948 #endif /* CONFIG_4xx || CONFIG_BOOKE */
5949@@ -204,15 +567,14 @@ good_area:
5950 pte_t *ptep;
5951 pmd_t *pmdp;
5952
5953-#if 0
5954+#if 1
5955 /* It would be nice to actually enforce the VM execute
5956 permission on CPUs which can do so, but far too
5957 much stuff in userspace doesn't get the permissions
5958 right, so we let any page be executed for now. */
5959 if (! (vma->vm_flags & VM_EXEC))
5960 goto bad_area;
5961-#endif
5962-
5963+#else
5964 /* Since 4xx/Book-E supports per-page execute permission,
5965 * we lazily flush dcache to icache. */
5966 ptep = NULL;
5967@@ -235,6 +597,7 @@ good_area:
5968 pte_unmap_unlock(ptep, ptl);
5969 }
5970 #endif
5971+#endif
5972 /* a read */
5973 } else {
5974 /* protection fault */
5975@@ -280,6 +643,33 @@ bad_area:
5976
5977 /* User mode accesses cause a SIGSEGV */
5978 if (user_mode(regs)) {
5979+
5980+#ifdef CONFIG_PAX_PAGEEXEC
5981+ if (mm->pax_flags & MF_PAX_PAGEEXEC) {
5982+ if ((TRAP(regs) == 0x400) && (regs->nip == address)) {
5983+ switch (pax_handle_fetch_fault(regs)) {
5984+
5985+#ifdef CONFIG_PAX_EMUPLT
5986+ case 2:
5987+ case 3:
5988+ case 4:
5989+ return 0;
5990+#endif
5991+
5992+#ifdef CONFIG_PAX_EMUSIGRT
5993+ case 5:
5994+ case 6:
5995+ return 0;
5996+#endif
5997+
5998+ }
5999+
6000+ pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]);
6001+ do_exit(SIGKILL);
6002+ }
6003+ }
6004+#endif
6005+
6006 _exception(SIGSEGV, regs, code, address);
6007 return 0;
6008 }
6009diff -urNp linux-2.6.17.7/arch/s390/kernel/module.c linux-2.6.17.7/arch/s390/kernel/module.c
6010--- linux-2.6.17.7/arch/s390/kernel/module.c 2006-07-24 23:36:01.000000000 -0400
6011+++ linux-2.6.17.7/arch/s390/kernel/module.c 2006-08-01 20:29:46.000000000 -0400
6012@@ -164,11 +164,11 @@ module_frob_arch_sections(Elf_Ehdr *hdr,
6013
6014 /* Increase core size by size of got & plt and set start
6015 offsets for got and plt. */
6016- me->core_size = ALIGN(me->core_size, 4);
6017- me->arch.got_offset = me->core_size;
6018- me->core_size += me->arch.got_size;
6019- me->arch.plt_offset = me->core_size;
6020- me->core_size += me->arch.plt_size;
6021+ me->core_size_rw = ALIGN(me->core_size_rw, 4);
6022+ me->arch.got_offset = me->core_size_rw;
6023+ me->core_size_rw += me->arch.got_size;
6024+ me->arch.plt_offset = me->core_size_rx;
6025+ me->core_size_rx += me->arch.plt_size;
6026 return 0;
6027 }
6028
6029@@ -254,7 +254,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6030 if (info->got_initialized == 0) {
6031 Elf_Addr *gotent;
6032
6033- gotent = me->module_core + me->arch.got_offset +
6034+ gotent = me->module_core_rw + me->arch.got_offset +
6035 info->got_offset;
6036 *gotent = val;
6037 info->got_initialized = 1;
6038@@ -278,7 +278,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6039 else if (r_type == R_390_GOTENT ||
6040 r_type == R_390_GOTPLTENT)
6041 *(unsigned int *) loc =
6042- (val + (Elf_Addr) me->module_core - loc) >> 1;
6043+ (val + (Elf_Addr) me->module_core_rw - loc) >> 1;
6044 else if (r_type == R_390_GOT64 ||
6045 r_type == R_390_GOTPLT64)
6046 *(unsigned long *) loc = val;
6047@@ -292,7 +292,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6048 case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */
6049 if (info->plt_initialized == 0) {
6050 unsigned int *ip;
6051- ip = me->module_core + me->arch.plt_offset +
6052+ ip = me->module_core_rx + me->arch.plt_offset +
6053 info->plt_offset;
6054 #ifndef CONFIG_64BIT
6055 ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */
6056@@ -314,7 +314,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6057 val = me->arch.plt_offset - me->arch.got_offset +
6058 info->plt_offset + rela->r_addend;
6059 else
6060- val = (Elf_Addr) me->module_core +
6061+ val = (Elf_Addr) me->module_core_rx +
6062 me->arch.plt_offset + info->plt_offset +
6063 rela->r_addend - loc;
6064 if (r_type == R_390_PLT16DBL)
6065@@ -334,7 +334,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6066 case R_390_GOTOFF32: /* 32 bit offset to GOT. */
6067 case R_390_GOTOFF64: /* 64 bit offset to GOT. */
6068 val = val + rela->r_addend -
6069- ((Elf_Addr) me->module_core + me->arch.got_offset);
6070+ ((Elf_Addr) me->module_core_rw + me->arch.got_offset);
6071 if (r_type == R_390_GOTOFF16)
6072 *(unsigned short *) loc = val;
6073 else if (r_type == R_390_GOTOFF32)
6074@@ -344,7 +344,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
6075 break;
6076 case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */
6077 case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */
6078- val = (Elf_Addr) me->module_core + me->arch.got_offset +
6079+ val = (Elf_Addr) me->module_core_rw + me->arch.got_offset +
6080 rela->r_addend - loc;
6081 if (r_type == R_390_GOTPC)
6082 *(unsigned int *) loc = val;
6083diff -urNp linux-2.6.17.7/arch/sparc/Makefile linux-2.6.17.7/arch/sparc/Makefile
6084--- linux-2.6.17.7/arch/sparc/Makefile 2006-07-24 23:36:01.000000000 -0400
6085+++ linux-2.6.17.7/arch/sparc/Makefile 2006-08-01 20:29:46.000000000 -0400
6086@@ -34,7 +34,7 @@ libs-y += arch/sparc/prom/ arch/sparc/li
6087 # Renaming is done to avoid confusing pattern matching rules in 2.5.45 (multy-)
6088 INIT_Y := $(patsubst %/, %/built-in.o, $(init-y))
6089 CORE_Y := $(core-y)
6090-CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
6091+CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
6092 CORE_Y := $(patsubst %/, %/built-in.o, $(CORE_Y))
6093 DRIVERS_Y := $(patsubst %/, %/built-in.o, $(drivers-y))
6094 NET_Y := $(patsubst %/, %/built-in.o, $(net-y))
6095diff -urNp linux-2.6.17.7/arch/sparc/kernel/ptrace.c linux-2.6.17.7/arch/sparc/kernel/ptrace.c
6096--- linux-2.6.17.7/arch/sparc/kernel/ptrace.c 2006-07-24 23:36:01.000000000 -0400
6097+++ linux-2.6.17.7/arch/sparc/kernel/ptrace.c 2006-08-01 20:29:46.000000000 -0400
6098@@ -19,6 +19,7 @@
f1a4f855 6099 #include <linux/security.h>
6100 #include <linux/signal.h>
77fa6d7d 6101 #include <linux/vs_pid.h>
f1a4f855 6102+#include <linux/grsecurity.h>
6103
6104 #include <asm/pgtable.h>
6105 #include <asm/system.h>
6106@@ -300,6 +301,11 @@ asmlinkage void do_ptrace(struct pt_regs
6107 goto out;
6108 }
6109
6110+ if (gr_handle_ptrace(child, request)) {
6111+ pt_error_return(regs, EPERM);
6112+ goto out_tsk;
6113+ }
6114+
6115 if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
6116 || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
6117 if (ptrace_attach(child)) {
6118diff -urNp linux-2.6.17.7/arch/sparc/kernel/sys_sparc.c linux-2.6.17.7/arch/sparc/kernel/sys_sparc.c
6119--- linux-2.6.17.7/arch/sparc/kernel/sys_sparc.c 2006-07-24 23:36:01.000000000 -0400
6120+++ linux-2.6.17.7/arch/sparc/kernel/sys_sparc.c 2006-08-01 20:29:46.000000000 -0400
6121@@ -56,7 +56,7 @@ unsigned long arch_get_unmapped_area(str
6122 if (ARCH_SUN4C_SUN4 && len > 0x20000000)
6123 return -ENOMEM;
6124 if (!addr)
6125- addr = TASK_UNMAPPED_BASE;
6126+ addr = current->mm->mmap_base;
6127
6128 if (flags & MAP_SHARED)
6129 addr = COLOUR_ALIGN(addr);
6130diff -urNp linux-2.6.17.7/arch/sparc/mm/fault.c linux-2.6.17.7/arch/sparc/mm/fault.c
6131--- linux-2.6.17.7/arch/sparc/mm/fault.c 2006-07-24 23:36:01.000000000 -0400
6132+++ linux-2.6.17.7/arch/sparc/mm/fault.c 2006-08-01 20:29:46.000000000 -0400
6133@@ -21,6 +21,10 @@
6134 #include <linux/smp_lock.h>
6135 #include <linux/interrupt.h>
6136 #include <linux/module.h>
6137+#include <linux/slab.h>
6138+#include <linux/pagemap.h>
6139+#include <linux/compiler.h>
6140+#include <linux/binfmts.h>
6141
6142 #include <asm/system.h>
6143 #include <asm/page.h>
6144@@ -217,6 +221,252 @@ static unsigned long compute_si_addr(str
6145 return safe_compute_effective_address(regs, insn);
6146 }
6147
6148+#ifdef CONFIG_PAX_PAGEEXEC
6149+void pax_emuplt_close(struct vm_area_struct * vma)
6150+{
6151+ vma->vm_mm->call_dl_resolve = 0UL;
6152+}
6153+
6154+static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
6155+{
6156+ struct page* page;
6157+ unsigned int *kaddr;
6158+
6159+ page = alloc_page(GFP_HIGHUSER);
6160+ if (!page)
6161+ return NOPAGE_OOM;
6162+
6163+ kaddr = kmap(page);
6164+ memset(kaddr, 0, PAGE_SIZE);
6165+ kaddr[0] = 0x9DE3BFA8U; /* save */
6166+ flush_dcache_page(page);
6167+ kunmap(page);
6168+ if (type)
6169+ *type = VM_FAULT_MAJOR;
6170+
6171+ return page;
6172+}
6173+
6174+static struct vm_operations_struct pax_vm_ops = {
6175+ .close = pax_emuplt_close,
6176+ .nopage = pax_emuplt_nopage,
6177+};
6178+
6179+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
6180+{
6181+ int ret;
6182+
6183+ memset(vma, 0, sizeof(*vma));
6184+ vma->vm_mm = current->mm;
6185+ vma->vm_start = addr;
6186+ vma->vm_end = addr + PAGE_SIZE;
6187+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
6188+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
6189+ vma->vm_ops = &pax_vm_ops;
6190+
6191+ ret = insert_vm_struct(current->mm, vma);
6192+ if (ret)
6193+ return ret;
6194+
6195+ ++current->mm->total_vm;
6196+ return 0;
6197+}
6198+
6199+/*
6200+ * PaX: decide what to do with offenders (regs->pc = fault address)
6201+ *
6202+ * returns 1 when task should be killed
6203+ * 2 when patched PLT trampoline was detected
6204+ * 3 when unpatched PLT trampoline was detected
6205+ */
6206+static int pax_handle_fetch_fault(struct pt_regs *regs)
6207+{
6208+
6209+#ifdef CONFIG_PAX_EMUPLT
6210+ int err;
6211+
6212+ do { /* PaX: patched PLT emulation #1 */
6213+ unsigned int sethi1, sethi2, jmpl;
6214+
6215+ err = get_user(sethi1, (unsigned int*)regs->pc);
6216+ err |= get_user(sethi2, (unsigned int*)(regs->pc+4));
6217+ err |= get_user(jmpl, (unsigned int*)(regs->pc+8));
6218+
6219+ if (err)
6220+ break;
6221+
6222+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
6223+ (sethi2 & 0xFFC00000U) == 0x03000000U &&
6224+ (jmpl & 0xFFFFE000U) == 0x81C06000U)
6225+ {
6226+ unsigned int addr;
6227+
6228+ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
6229+ addr = regs->u_regs[UREG_G1];
6230+ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
6231+ regs->pc = addr;
6232+ regs->npc = addr+4;
6233+ return 2;
6234+ }
6235+ } while (0);
6236+
6237+ { /* PaX: patched PLT emulation #2 */
6238+ unsigned int ba;
6239+
6240+ err = get_user(ba, (unsigned int*)regs->pc);
6241+
6242+ if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
6243+ unsigned int addr;
6244+
6245+ addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
6246+ regs->pc = addr;
6247+ regs->npc = addr+4;
6248+ return 2;
6249+ }
6250+ }
6251+
6252+ do { /* PaX: patched PLT emulation #3 */
6253+ unsigned int sethi, jmpl, nop;
6254+
6255+ err = get_user(sethi, (unsigned int*)regs->pc);
6256+ err |= get_user(jmpl, (unsigned int*)(regs->pc+4));
6257+ err |= get_user(nop, (unsigned int*)(regs->pc+8));
6258+
6259+ if (err)
6260+ break;
6261+
6262+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
6263+ (jmpl & 0xFFFFE000U) == 0x81C06000U &&
6264+ nop == 0x01000000U)
6265+ {
6266+ unsigned int addr;
6267+
6268+ addr = (sethi & 0x003FFFFFU) << 10;
6269+ regs->u_regs[UREG_G1] = addr;
6270+ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
6271+ regs->pc = addr;
6272+ regs->npc = addr+4;
6273+ return 2;
6274+ }
6275+ } while (0);
6276+
6277+ do { /* PaX: unpatched PLT emulation step 1 */
6278+ unsigned int sethi, ba, nop;
6279+
6280+ err = get_user(sethi, (unsigned int*)regs->pc);
6281+ err |= get_user(ba, (unsigned int*)(regs->pc+4));
6282+ err |= get_user(nop, (unsigned int*)(regs->pc+8));
6283+
6284+ if (err)
6285+ break;
6286+
6287+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
6288+ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
6289+ nop == 0x01000000U)
6290+ {
6291+ unsigned int addr, save, call;
6292+
6293+ if ((ba & 0xFFC00000U) == 0x30800000U)
6294+ addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
6295+ else
6296+ addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2);
6297+
6298+ err = get_user(save, (unsigned int*)addr);
6299+ err |= get_user(call, (unsigned int*)(addr+4));
6300+ err |= get_user(nop, (unsigned int*)(addr+8));
6301+ if (err)
6302+ break;
6303+
6304+ if (save == 0x9DE3BFA8U &&
6305+ (call & 0xC0000000U) == 0x40000000U &&
6306+ nop == 0x01000000U)
6307+ {
6308+ struct vm_area_struct *vma;
6309+ unsigned long call_dl_resolve;
6310+
6311+ down_read(&current->mm->mmap_sem);
6312+ call_dl_resolve = current->mm->call_dl_resolve;
6313+ up_read(&current->mm->mmap_sem);
6314+ if (likely(call_dl_resolve))
6315+ goto emulate;
6316+
6317+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
6318+
6319+ down_write(&current->mm->mmap_sem);
6320+ if (current->mm->call_dl_resolve) {
6321+ call_dl_resolve = current->mm->call_dl_resolve;
6322+ up_write(&current->mm->mmap_sem);
6323+ if (vma) kmem_cache_free(vm_area_cachep, vma);
6324+ goto emulate;
6325+ }
6326+
6327+ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
6328+ if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
6329+ up_write(&current->mm->mmap_sem);
6330+ if (vma) kmem_cache_free(vm_area_cachep, vma);
6331+ return 1;
6332+ }
6333+
6334+ if (pax_insert_vma(vma, call_dl_resolve)) {
6335+ up_write(&current->mm->mmap_sem);
6336+ kmem_cache_free(vm_area_cachep, vma);
6337+ return 1;
6338+ }
6339+
6340+ current->mm->call_dl_resolve = call_dl_resolve;
6341+ up_write(&current->mm->mmap_sem);
6342+
6343+emulate:
6344+ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
6345+ regs->pc = call_dl_resolve;
6346+ regs->npc = addr+4;
6347+ return 3;
6348+ }
6349+ }
6350+ } while (0);
6351+
6352+ do { /* PaX: unpatched PLT emulation step 2 */
6353+ unsigned int save, call, nop;
6354+
6355+ err = get_user(save, (unsigned int*)(regs->pc-4));
6356+ err |= get_user(call, (unsigned int*)regs->pc);
6357+ err |= get_user(nop, (unsigned int*)(regs->pc+4));
6358+ if (err)
6359+ break;
6360+
6361+ if (save == 0x9DE3BFA8U &&
6362+ (call & 0xC0000000U) == 0x40000000U &&
6363+ nop == 0x01000000U)
6364+ {
6365+ unsigned int dl_resolve = regs->pc + ((((call | 0xC0000000U) ^ 0x20000000U) + 0x20000000U) << 2);
6366+
6367+ regs->u_regs[UREG_RETPC] = regs->pc;
6368+ regs->pc = dl_resolve;
6369+ regs->npc = dl_resolve+4;
6370+ return 3;
6371+ }
6372+ } while (0);
6373+#endif
6374+
6375+ return 1;
6376+}
6377+
6378+void pax_report_insns(void *pc, void *sp)
6379+{
6380+ unsigned long i;
6381+
6382+ printk(KERN_ERR "PAX: bytes at PC: ");
6383+ for (i = 0; i < 5; i++) {
6384+ unsigned int c;
6385+ if (get_user(c, (unsigned int*)pc+i))
6386+ printk("???????? ");
6387+ else
6388+ printk("%08x ", c);
6389+ }
6390+ printk("\n");
6391+}
6392+#endif
6393+
6394 asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
6395 unsigned long address)
6396 {
6397@@ -280,6 +530,24 @@ good_area:
6398 if(!(vma->vm_flags & VM_WRITE))
6399 goto bad_area;
6400 } else {
6401+
6402+#ifdef CONFIG_PAX_PAGEEXEC
6403+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && text_fault && !(vma->vm_flags & VM_EXEC)) {
6404+ up_read(&mm->mmap_sem);
6405+ switch (pax_handle_fetch_fault(regs)) {
6406+
6407+#ifdef CONFIG_PAX_EMUPLT
6408+ case 2:
6409+ case 3:
6410+ return;
6411+#endif
6412+
6413+ }
6414+ pax_report_fault(regs, (void*)regs->pc, (void*)regs->u_regs[UREG_FP]);
6415+ do_exit(SIGKILL);
6416+ }
6417+#endif
6418+
6419 /* Allow reads even for write-only mappings */
6420 if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
6421 goto bad_area;
6422diff -urNp linux-2.6.17.7/arch/sparc/mm/init.c linux-2.6.17.7/arch/sparc/mm/init.c
6423--- linux-2.6.17.7/arch/sparc/mm/init.c 2006-07-24 23:36:01.000000000 -0400
6424+++ linux-2.6.17.7/arch/sparc/mm/init.c 2006-08-01 20:29:46.000000000 -0400
6425@@ -333,17 +333,17 @@ void __init paging_init(void)
6426
6427 /* Initialize the protection map with non-constant, MMU dependent values. */
6428 protection_map[0] = PAGE_NONE;
6429- protection_map[1] = PAGE_READONLY;
6430- protection_map[2] = PAGE_COPY;
6431- protection_map[3] = PAGE_COPY;
6432+ protection_map[1] = PAGE_READONLY_NOEXEC;
6433+ protection_map[2] = PAGE_COPY_NOEXEC;
6434+ protection_map[3] = PAGE_COPY_NOEXEC;
6435 protection_map[4] = PAGE_READONLY;
6436 protection_map[5] = PAGE_READONLY;
6437 protection_map[6] = PAGE_COPY;
6438 protection_map[7] = PAGE_COPY;
6439 protection_map[8] = PAGE_NONE;
6440- protection_map[9] = PAGE_READONLY;
6441- protection_map[10] = PAGE_SHARED;
6442- protection_map[11] = PAGE_SHARED;
6443+ protection_map[9] = PAGE_READONLY_NOEXEC;
6444+ protection_map[10] = PAGE_SHARED_NOEXEC;
6445+ protection_map[11] = PAGE_SHARED_NOEXEC;
6446 protection_map[12] = PAGE_READONLY;
6447 protection_map[13] = PAGE_READONLY;
6448 protection_map[14] = PAGE_SHARED;
6449diff -urNp linux-2.6.17.7/arch/sparc/mm/srmmu.c linux-2.6.17.7/arch/sparc/mm/srmmu.c
6450--- linux-2.6.17.7/arch/sparc/mm/srmmu.c 2006-07-24 23:36:01.000000000 -0400
6451+++ linux-2.6.17.7/arch/sparc/mm/srmmu.c 2006-08-01 20:29:46.000000000 -0400
6452@@ -2161,6 +2161,13 @@ void __init ld_mmu_srmmu(void)
6453 BTFIXUPSET_INT(page_shared, pgprot_val(SRMMU_PAGE_SHARED));
6454 BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY));
6455 BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY));
6456+
6457+#ifdef CONFIG_PAX_PAGEEXEC
6458+ BTFIXUPSET_INT(page_shared_noexec, pgprot_val(SRMMU_PAGE_SHARED_NOEXEC));
6459+ BTFIXUPSET_INT(page_copy_noexec, pgprot_val(SRMMU_PAGE_COPY_NOEXEC));
6460+ BTFIXUPSET_INT(page_readonly_noexec, pgprot_val(SRMMU_PAGE_RDONLY_NOEXEC));
6461+#endif
6462+
6463 BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL));
6464 page_kernel = pgprot_val(SRMMU_PAGE_KERNEL);
6465
6466diff -urNp linux-2.6.17.7/arch/sparc64/kernel/ptrace.c linux-2.6.17.7/arch/sparc64/kernel/ptrace.c
6467--- linux-2.6.17.7/arch/sparc64/kernel/ptrace.c 2006-07-24 23:36:01.000000000 -0400
6468+++ linux-2.6.17.7/arch/sparc64/kernel/ptrace.c 2006-08-01 20:29:46.000000000 -0400
6469@@ -22,6 +22,7 @@
f1a4f855 6470 #include <linux/audit.h>
6471 #include <linux/signal.h>
77fa6d7d 6472 #include <linux/vs_pid.h>
f1a4f855 6473+#include <linux/grsecurity.h>
6474
6475 #include <asm/asi.h>
6476 #include <asm/pgtable.h>
6477@@ -213,6 +214,11 @@ asmlinkage void do_ptrace(struct pt_regs
6478 goto out;
6479 }
6480
6481+ if (gr_handle_ptrace(child, (long)request)) {
6482+ pt_error_return(regs, EPERM);
6483+ goto out_tsk;
6484+ }
6485+
6486 if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
6487 || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
6488 if (ptrace_attach(child)) {
6489diff -urNp linux-2.6.17.7/arch/sparc64/kernel/sys_sparc.c linux-2.6.17.7/arch/sparc64/kernel/sys_sparc.c
6490--- linux-2.6.17.7/arch/sparc64/kernel/sys_sparc.c 2006-07-24 23:36:01.000000000 -0400
6491+++ linux-2.6.17.7/arch/sparc64/kernel/sys_sparc.c 2006-08-01 20:29:46.000000000 -0400
6492@@ -140,6 +140,10 @@ unsigned long arch_get_unmapped_area(str
6493 if (filp || (flags & MAP_SHARED))
6494 do_color_align = 1;
6495
6496+#ifdef CONFIG_PAX_RANDMMAP
6497+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
6498+#endif
6499+
6500 if (addr) {
6501 if (do_color_align)
6502 addr = COLOUR_ALIGN(addr, pgoff);
6503@@ -153,9 +157,9 @@ unsigned long arch_get_unmapped_area(str
6504 }
6505
6506 if (len > mm->cached_hole_size) {
6507- start_addr = addr = mm->free_area_cache;
6508+ start_addr = addr = mm->free_area_cache;
6509 } else {
6510- start_addr = addr = TASK_UNMAPPED_BASE;
6511+ start_addr = addr = mm->mmap_base;
6512 mm->cached_hole_size = 0;
6513 }
6514
6515@@ -175,8 +179,8 @@ full_search:
6516 vma = find_vma(mm, VA_EXCLUDE_END);
6517 }
6518 if (unlikely(task_size < addr)) {
6519- if (start_addr != TASK_UNMAPPED_BASE) {
6520- start_addr = addr = TASK_UNMAPPED_BASE;
6521+ if (start_addr != mm->mmap_base) {
6522+ start_addr = addr = mm->mmap_base;
6523 mm->cached_hole_size = 0;
6524 goto full_search;
6525 }
6526diff -urNp linux-2.6.17.7/arch/sparc64/mm/fault.c linux-2.6.17.7/arch/sparc64/mm/fault.c
6527--- linux-2.6.17.7/arch/sparc64/mm/fault.c 2006-07-24 23:36:01.000000000 -0400
6528+++ linux-2.6.17.7/arch/sparc64/mm/fault.c 2006-08-01 20:29:46.000000000 -0400
6529@@ -19,6 +19,10 @@
6530 #include <linux/init.h>
6531 #include <linux/interrupt.h>
6532 #include <linux/kprobes.h>
6533+#include <linux/slab.h>
6534+#include <linux/pagemap.h>
6535+#include <linux/compiler.h>
6536+#include <linux/binfmts.h>
6537
6538 #include <asm/page.h>
6539 #include <asm/pgtable.h>
6540@@ -253,6 +257,369 @@ cannot_handle:
6541 unhandled_fault (address, current, regs);
6542 }
6543
6544+#ifdef CONFIG_PAX_PAGEEXEC
6545+#ifdef CONFIG_PAX_EMUPLT
6546+static void pax_emuplt_close(struct vm_area_struct * vma)
6547+{
6548+ vma->vm_mm->call_dl_resolve = 0UL;
6549+}
6550+
6551+static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
6552+{
6553+ struct page* page;
6554+ unsigned int *kaddr;
6555+
6556+ page = alloc_page(GFP_HIGHUSER);
6557+ if (!page)
6558+ return NOPAGE_OOM;
6559+
6560+ kaddr = kmap(page);
6561+ memset(kaddr, 0, PAGE_SIZE);
6562+ kaddr[0] = 0x9DE3BFA8U; /* save */
6563+ flush_dcache_page(page);
6564+ kunmap(page);
6565+ if (type)
6566+ *type = VM_FAULT_MAJOR;
6567+ return page;
6568+}
6569+
6570+static struct vm_operations_struct pax_vm_ops = {
6571+ .close = pax_emuplt_close,
6572+ .nopage = pax_emuplt_nopage,
6573+};
6574+
6575+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
6576+{
6577+ int ret;
6578+
6579+ memset(vma, 0, sizeof(*vma));
6580+ vma->vm_mm = current->mm;
6581+ vma->vm_start = addr;
6582+ vma->vm_end = addr + PAGE_SIZE;
6583+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
6584+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
6585+ vma->vm_ops = &pax_vm_ops;
6586+
6587+ ret = insert_vm_struct(current->mm, vma);
6588+ if (ret)
6589+ return ret;
6590+
6591+ ++current->mm->total_vm;
6592+ return 0;
6593+}
6594+#endif
6595+
6596+/*
6597+ * PaX: decide what to do with offenders (regs->tpc = fault address)
6598+ *
6599+ * returns 1 when task should be killed
6600+ * 2 when patched PLT trampoline was detected
6601+ * 3 when unpatched PLT trampoline was detected
6602+ */
6603+static int pax_handle_fetch_fault(struct pt_regs *regs)
6604+{
6605+
6606+#ifdef CONFIG_PAX_EMUPLT
6607+ int err;
6608+
6609+ do { /* PaX: patched PLT emulation #1 */
6610+ unsigned int sethi1, sethi2, jmpl;
6611+
6612+ err = get_user(sethi1, (unsigned int*)regs->tpc);
6613+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
6614+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+8));
6615+
6616+ if (err)
6617+ break;
6618+
6619+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
6620+ (sethi2 & 0xFFC00000U) == 0x03000000U &&
6621+ (jmpl & 0xFFFFE000U) == 0x81C06000U)
6622+ {
6623+ unsigned long addr;
6624+
6625+ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
6626+ addr = regs->u_regs[UREG_G1];
6627+ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
6628+ regs->tpc = addr;
6629+ regs->tnpc = addr+4;
6630+ return 2;
6631+ }
6632+ } while (0);
6633+
6634+ { /* PaX: patched PLT emulation #2 */
6635+ unsigned int ba;
6636+
6637+ err = get_user(ba, (unsigned int*)regs->tpc);
6638+
6639+ if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
6640+ unsigned long addr;
6641+
6642+ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
6643+ regs->tpc = addr;
6644+ regs->tnpc = addr+4;
6645+ return 2;
6646+ }
6647+ }
6648+
6649+ do { /* PaX: patched PLT emulation #3 */
6650+ unsigned int sethi, jmpl, nop;
6651+
6652+ err = get_user(sethi, (unsigned int*)regs->tpc);
6653+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+4));
6654+ err |= get_user(nop, (unsigned int*)(regs->tpc+8));
6655+
6656+ if (err)
6657+ break;
6658+
6659+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
6660+ (jmpl & 0xFFFFE000U) == 0x81C06000U &&
6661+ nop == 0x01000000U)
6662+ {
6663+ unsigned long addr;
6664+
6665+ addr = (sethi & 0x003FFFFFU) << 10;
6666+ regs->u_regs[UREG_G1] = addr;
6667+ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
6668+ regs->tpc = addr;
6669+ regs->tnpc = addr+4;
6670+ return 2;
6671+ }
6672+ } while (0);
6673+
6674+ do { /* PaX: patched PLT emulation #4 */
6675+ unsigned int mov1, call, mov2;
6676+
6677+ err = get_user(mov1, (unsigned int*)regs->tpc);
6678+ err |= get_user(call, (unsigned int*)(regs->tpc+4));
6679+ err |= get_user(mov2, (unsigned int*)(regs->tpc+8));
6680+
6681+ if (err)
6682+ break;
6683+
6684+ if (mov1 == 0x8210000FU &&
6685+ (call & 0xC0000000U) == 0x40000000U &&
6686+ mov2 == 0x9E100001U)
6687+ {
6688+ unsigned long addr;
6689+
6690+ regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC];
6691+ addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
6692+ regs->tpc = addr;
6693+ regs->tnpc = addr+4;
6694+ return 2;
6695+ }
6696+ } while (0);
6697+
6698+ do { /* PaX: patched PLT emulation #5 */
6699+ unsigned int sethi1, sethi2, or1, or2, sllx, jmpl, nop;
6700+
6701+ err = get_user(sethi1, (unsigned int*)regs->tpc);
6702+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
6703+ err |= get_user(or1, (unsigned int*)(regs->tpc+8));
6704+ err |= get_user(or2, (unsigned int*)(regs->tpc+12));
6705+ err |= get_user(sllx, (unsigned int*)(regs->tpc+16));
6706+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+20));
6707+ err |= get_user(nop, (unsigned int*)(regs->tpc+24));
6708+
6709+ if (err)
6710+ break;
6711+
6712+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
6713+ (sethi2 & 0xFFC00000U) == 0x0B000000U &&
6714+ (or1 & 0xFFFFE000U) == 0x82106000U &&
6715+ (or2 & 0xFFFFE000U) == 0x8A116000U &&
6716+ sllx == 0x83287020 &&
6717+ jmpl == 0x81C04005U &&
6718+ nop == 0x01000000U)
6719+ {
6720+ unsigned long addr;
6721+
6722+ regs->u_regs[UREG_G1] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU);
6723+ regs->u_regs[UREG_G1] <<= 32;
6724+ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU);
6725+ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
6726+ regs->tpc = addr;
6727+ regs->tnpc = addr+4;
6728+ return 2;
6729+ }
6730+ } while (0);
6731+
6732+ do { /* PaX: patched PLT emulation #6 */
6733+ unsigned int sethi1, sethi2, sllx, or, jmpl, nop;
6734+
6735+ err = get_user(sethi1, (unsigned int*)regs->tpc);
6736+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
6737+ err |= get_user(sllx, (unsigned int*)(regs->tpc+8));
6738+ err |= get_user(or, (unsigned int*)(regs->tpc+12));
6739+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+16));
6740+ err |= get_user(nop, (unsigned int*)(regs->tpc+20));
6741+
6742+ if (err)
6743+ break;
6744+
6745+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
6746+ (sethi2 & 0xFFC00000U) == 0x0B000000U &&
6747+ sllx == 0x83287020 &&
6748+ (or & 0xFFFFE000U) == 0x8A116000U &&
6749+ jmpl == 0x81C04005U &&
6750+ nop == 0x01000000U)
6751+ {
6752+ unsigned long addr;
6753+
6754+ regs->u_regs[UREG_G1] = (sethi1 & 0x003FFFFFU) << 10;
6755+ regs->u_regs[UREG_G1] <<= 32;
6756+ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or & 0x3FFU);
6757+ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
6758+ regs->tpc = addr;
6759+ regs->tnpc = addr+4;
6760+ return 2;
6761+ }
6762+ } while (0);
6763+
6764+ do { /* PaX: patched PLT emulation #7 */
6765+ unsigned int sethi, ba, nop;
6766+
6767+ err = get_user(sethi, (unsigned int*)regs->tpc);
6768+ err |= get_user(ba, (unsigned int*)(regs->tpc+4));
6769+ err |= get_user(nop, (unsigned int*)(regs->tpc+8));
6770+
6771+ if (err)
6772+ break;
6773+
6774+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
6775+ (ba & 0xFFF00000U) == 0x30600000U &&
6776+ nop == 0x01000000U)
6777+ {
6778+ unsigned long addr;
6779+
6780+ addr = (sethi & 0x003FFFFFU) << 10;
6781+ regs->u_regs[UREG_G1] = addr;
6782+ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
6783+ regs->tpc = addr;
6784+ regs->tnpc = addr+4;
6785+ return 2;
6786+ }
6787+ } while (0);
6788+
6789+ do { /* PaX: unpatched PLT emulation step 1 */
6790+ unsigned int sethi, ba, nop;
6791+
6792+ err = get_user(sethi, (unsigned int*)regs->tpc);
6793+ err |= get_user(ba, (unsigned int*)(regs->tpc+4));
6794+ err |= get_user(nop, (unsigned int*)(regs->tpc+8));
6795+
6796+ if (err)
6797+ break;
6798+
6799+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
6800+ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
6801+ nop == 0x01000000U)
6802+ {
6803+ unsigned long addr;
6804+ unsigned int save, call;
6805+
6806+ if ((ba & 0xFFC00000U) == 0x30800000U)
6807+ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
6808+ else
6809+ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
6810+
6811+ err = get_user(save, (unsigned int*)addr);
6812+ err |= get_user(call, (unsigned int*)(addr+4));
6813+ err |= get_user(nop, (unsigned int*)(addr+8));
6814+ if (err)
6815+ break;
6816+
6817+ if (save == 0x9DE3BFA8U &&
6818+ (call & 0xC0000000U) == 0x40000000U &&
6819+ nop == 0x01000000U)
6820+ {
6821+ struct vm_area_struct *vma;
6822+ unsigned long call_dl_resolve;
6823+
6824+ down_read(&current->mm->mmap_sem);
6825+ call_dl_resolve = current->mm->call_dl_resolve;
6826+ up_read(&current->mm->mmap_sem);
6827+ if (likely(call_dl_resolve))
6828+ goto emulate;
6829+
6830+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
6831+
6832+ down_write(&current->mm->mmap_sem);
6833+ if (current->mm->call_dl_resolve) {
6834+ call_dl_resolve = current->mm->call_dl_resolve;
6835+ up_write(&current->mm->mmap_sem);
6836+ if (vma) kmem_cache_free(vm_area_cachep, vma);
6837+ goto emulate;
6838+ }
6839+
6840+ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
6841+ if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
6842+ up_write(&current->mm->mmap_sem);
6843+ if (vma) kmem_cache_free(vm_area_cachep, vma);
6844+ return 1;
6845+ }
6846+
6847+ if (pax_insert_vma(vma, call_dl_resolve)) {
6848+ up_write(&current->mm->mmap_sem);
6849+ kmem_cache_free(vm_area_cachep, vma);
6850+ return 1;
6851+ }
6852+
6853+ current->mm->call_dl_resolve = call_dl_resolve;
6854+ up_write(&current->mm->mmap_sem);
6855+
6856+emulate:
6857+ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
6858+ regs->tpc = call_dl_resolve;
6859+ regs->tnpc = addr+4;
6860+ return 3;
6861+ }
6862+ }
6863+ } while (0);
6864+
6865+ do { /* PaX: unpatched PLT emulation step 2 */
6866+ unsigned int save, call, nop;
6867+
6868+ err = get_user(save, (unsigned int*)(regs->tpc-4));
6869+ err |= get_user(call, (unsigned int*)regs->tpc);
6870+ err |= get_user(nop, (unsigned int*)(regs->tpc+4));
6871+ if (err)
6872+ break;
6873+
6874+ if (save == 0x9DE3BFA8U &&
6875+ (call & 0xC0000000U) == 0x40000000U &&
6876+ nop == 0x01000000U)
6877+ {
6878+ unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
6879+
6880+ regs->u_regs[UREG_RETPC] = regs->tpc;
6881+ regs->tpc = dl_resolve;
6882+ regs->tnpc = dl_resolve+4;
6883+ return 3;
6884+ }
6885+ } while (0);
6886+#endif
6887+
6888+ return 1;
6889+}
6890+
6891+void pax_report_insns(void *pc, void *sp)
6892+{
6893+ unsigned long i;
6894+
6895+ printk(KERN_ERR "PAX: bytes at PC: ");
6896+ for (i = 0; i < 5; i++) {
6897+ unsigned int c;
6898+ if (get_user(c, (unsigned int*)pc+i))
6899+ printk("???????? ");
6900+ else
6901+ printk("%08x ", c);
6902+ }
6903+ printk("\n");
6904+}
6905+#endif
6906+
6907 asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
6908 {
6909 struct mm_struct *mm = current->mm;
6910@@ -295,8 +662,10 @@ asmlinkage void __kprobes do_sparc64_fau
6911 goto intr_or_no_mm;
6912
6913 if (test_thread_flag(TIF_32BIT)) {
6914- if (!(regs->tstate & TSTATE_PRIV))
6915+ if (!(regs->tstate & TSTATE_PRIV)) {
6916 regs->tpc &= 0xffffffff;
6917+ regs->tnpc &= 0xffffffff;
6918+ }
6919 address &= 0xffffffff;
6920 }
6921
6922@@ -313,6 +682,29 @@ asmlinkage void __kprobes do_sparc64_fau
6923 if (!vma)
6924 goto bad_area;
6925
6926+#ifdef CONFIG_PAX_PAGEEXEC
6927+ /* PaX: detect ITLB misses on non-exec pages */
6928+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && vma->vm_start <= address &&
6929+ !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB))
6930+ {
6931+ if (address != regs->tpc)
6932+ goto good_area;
6933+
6934+ up_read(&mm->mmap_sem);
6935+ switch (pax_handle_fetch_fault(regs)) {
6936+
6937+#ifdef CONFIG_PAX_EMUPLT
6938+ case 2:
6939+ case 3:
6940+ return;
6941+#endif
6942+
6943+ }
6944+ pax_report_fault(regs, (void*)regs->tpc, (void*)(regs->u_regs[UREG_FP] + STACK_BIAS));
6945+ do_exit(SIGKILL);
6946+ }
6947+#endif
6948+
6949 /* Pure DTLB misses do not tell us whether the fault causing
6950 * load/store/atomic was a write or not, it only says that there
6951 * was no match. So in such a case we (carefully) read the
6952diff -urNp linux-2.6.17.7/arch/v850/kernel/module.c linux-2.6.17.7/arch/v850/kernel/module.c
6953--- linux-2.6.17.7/arch/v850/kernel/module.c 2006-07-24 23:36:01.000000000 -0400
6954+++ linux-2.6.17.7/arch/v850/kernel/module.c 2006-08-01 20:29:46.000000000 -0400
6955@@ -150,8 +150,8 @@ static uint32_t do_plt_call (void *locat
6956 tramp[1] = ((val >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
6957
6958 /* Init, or core PLT? */
6959- if (location >= mod->module_core
6960- && location < mod->module_core + mod->core_size)
6961+ if (location >= mod->module_core_rx
6962+ && location < mod->module_core_rx + mod->core_size_rx)
6963 entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
6964 else
6965 entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
6966diff -urNp linux-2.6.17.7/arch/x86_64/boot/compressed/head.S linux-2.6.17.7/arch/x86_64/boot/compressed/head.S
6967--- linux-2.6.17.7/arch/x86_64/boot/compressed/head.S 2006-07-24 23:36:01.000000000 -0400
6968+++ linux-2.6.17.7/arch/x86_64/boot/compressed/head.S 2006-08-01 20:29:46.000000000 -0400
6969@@ -41,11 +41,13 @@ startup_32:
6970 movl %eax,%gs
6971
6972 lss stack_start,%esp
6973+ movl 0x000000,%ecx
6974 xorl %eax,%eax
6975 1: incl %eax # check that A20 really IS enabled
6976 movl %eax,0x000000 # loop forever if it isn't
6977 cmpl %eax,0x100000
6978 je 1b
6979+ movl %ecx,0x000000
6980
6981 /*
6982 * Initialize eflags. Some BIOS's leave bits like NT set. This would
6983diff -urNp linux-2.6.17.7/arch/x86_64/ia32/ia32_binfmt.c linux-2.6.17.7/arch/x86_64/ia32/ia32_binfmt.c
6984--- linux-2.6.17.7/arch/x86_64/ia32/ia32_binfmt.c 2006-07-24 23:36:01.000000000 -0400
6985+++ linux-2.6.17.7/arch/x86_64/ia32/ia32_binfmt.c 2006-08-01 20:29:46.000000000 -0400
6986@@ -186,6 +186,17 @@ struct elf_prpsinfo
6987 //#include <asm/ia32.h>
6988 #include <linux/elf.h>
6989
6990+#ifdef CONFIG_PAX_ASLR
6991+#define PAX_ELF_ET_DYN_BASE(tsk) 0x08048000UL
6992+
6993+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
6994+#define PAX_DELTA_MMAP_LEN(tsk) 16
6995+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
6996+#define PAX_DELTA_EXEC_LEN(tsk) 16
6997+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
6998+#define PAX_DELTA_STACK_LEN(tsk) 16
6999+#endif
7000+
7001 typedef struct user_i387_ia32_struct elf_fpregset_t;
7002 typedef struct user32_fxsr_struct elf_fpxregset_t;
7003
7004diff -urNp linux-2.6.17.7/arch/x86_64/ia32/mmap32.c linux-2.6.17.7/arch/x86_64/ia32/mmap32.c
7005--- linux-2.6.17.7/arch/x86_64/ia32/mmap32.c 2006-07-24 23:36:01.000000000 -0400
7006+++ linux-2.6.17.7/arch/x86_64/ia32/mmap32.c 2006-08-01 20:29:46.000000000 -0400
7007@@ -68,10 +68,22 @@ void ia32_pick_mmap_layout(struct mm_str
7008 (current->personality & ADDR_COMPAT_LAYOUT) ||
7009 current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
7010 mm->mmap_base = TASK_UNMAPPED_BASE;
7011+
7012+#ifdef CONFIG_PAX_RANDMMAP
7013+ if (mm->pax_flags & MF_PAX_RANDMMAP)
7014+ mm->mmap_base += mm->delta_mmap;
7015+#endif
7016+
7017 mm->get_unmapped_area = arch_get_unmapped_area;
7018 mm->unmap_area = arch_unmap_area;
7019 } else {
7020 mm->mmap_base = mmap_base(mm);
7021+
7022+#ifdef CONFIG_PAX_RANDMMAP
7023+ if (mm->pax_flags & MF_PAX_RANDMMAP)
7024+ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
7025+#endif
7026+
7027 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
7028 mm->unmap_area = arch_unmap_area_topdown;
7029 }
7030diff -urNp linux-2.6.17.7/arch/x86_64/kernel/process.c linux-2.6.17.7/arch/x86_64/kernel/process.c
7031--- linux-2.6.17.7/arch/x86_64/kernel/process.c 2006-07-24 23:36:01.000000000 -0400
7032+++ linux-2.6.17.7/arch/x86_64/kernel/process.c 2006-08-01 20:29:46.000000000 -0400
7033@@ -830,9 +830,3 @@ int dump_task_regs(struct task_struct *t
7034 return 1;
7035 }
7036
7037-unsigned long arch_align_stack(unsigned long sp)
7038-{
7039- if (randomize_va_space)
7040- sp -= get_random_int() % 8192;
7041- return sp & ~0xf;
7042-}
7043diff -urNp linux-2.6.17.7/arch/x86_64/kernel/ptrace.c linux-2.6.17.7/arch/x86_64/kernel/ptrace.c
7044--- linux-2.6.17.7/arch/x86_64/kernel/ptrace.c 2006-07-24 23:36:01.000000000 -0400
7045+++ linux-2.6.17.7/arch/x86_64/kernel/ptrace.c 2006-08-01 20:29:46.000000000 -0400
7046@@ -19,6 +19,7 @@
7047 #include <linux/audit.h>
7048 #include <linux/seccomp.h>
7049 #include <linux/signal.h>
7050+#include <linux/grsecurity.h>
7051
7052 #include <asm/uaccess.h>
7053 #include <asm/pgtable.h>
7054diff -urNp linux-2.6.17.7/arch/x86_64/kernel/setup64.c linux-2.6.17.7/arch/x86_64/kernel/setup64.c
7055--- linux-2.6.17.7/arch/x86_64/kernel/setup64.c 2006-07-24 23:36:01.000000000 -0400
7056+++ linux-2.6.17.7/arch/x86_64/kernel/setup64.c 2006-08-01 20:29:46.000000000 -0400
7057@@ -38,7 +38,6 @@ struct desc_ptr idt_descr = { 256 * 16 -
7058 char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
7059
7060 unsigned long __supported_pte_mask __read_mostly = ~0UL;
7061-static int do_not_nx __cpuinitdata = 0;
7062
7063 /* noexec=on|off
7064 Control non executable mappings for 64bit processes.
7065@@ -50,16 +49,14 @@ int __init nonx_setup(char *str)
7066 {
7067 if (!strncmp(str, "on", 2)) {
7068 __supported_pte_mask |= _PAGE_NX;
7069- do_not_nx = 0;
7070 } else if (!strncmp(str, "off", 3)) {
7071- do_not_nx = 1;
7072 __supported_pte_mask &= ~_PAGE_NX;
7073 }
7074 return 1;
7075 }
7076 __setup("noexec=", nonx_setup); /* parsed early actually */
7077
7078-int force_personality32 = 0;
7079+int force_personality32;
7080
7081 /* noexec32=on|off
7082 Control non executable heap for 32bit processes.
7083@@ -173,7 +170,7 @@ void __cpuinit check_efer(void)
7084 unsigned long efer;
7085
7086 rdmsrl(MSR_EFER, efer);
7087- if (!(efer & EFER_NX) || do_not_nx) {
7088+ if (!(efer & EFER_NX)) {
7089 __supported_pte_mask &= ~_PAGE_NX;
7090 }
7091 }
7092diff -urNp linux-2.6.17.7/arch/x86_64/kernel/sys_x86_64.c linux-2.6.17.7/arch/x86_64/kernel/sys_x86_64.c
7093--- linux-2.6.17.7/arch/x86_64/kernel/sys_x86_64.c 2006-07-24 23:36:01.000000000 -0400
7094+++ linux-2.6.17.7/arch/x86_64/kernel/sys_x86_64.c 2006-08-01 20:29:46.000000000 -0400
7095@@ -65,8 +65,8 @@ out:
7096 return error;
7097 }
7098
7099-static void find_start_end(unsigned long flags, unsigned long *begin,
7100- unsigned long *end)
7101+static void find_start_end(struct mm_struct *mm, unsigned long flags,
7102+ unsigned long *begin, unsigned long *end)
7103 {
7104 if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
7105 /* This is usually used needed to map code in small
7106@@ -79,7 +79,7 @@ static void find_start_end(unsigned long
7107 *begin = 0x40000000;
7108 *end = 0x80000000;
7109 } else {
7110- *begin = TASK_UNMAPPED_BASE;
7111+ *begin = mm->mmap_base;
7112 *end = TASK_SIZE;
7113 }
7114 }
7115@@ -93,11 +93,15 @@ arch_get_unmapped_area(struct file *filp
7116 unsigned long start_addr;
7117 unsigned long begin, end;
7118
7119- find_start_end(flags, &begin, &end);
7120+ find_start_end(mm, flags, &begin, &end);
7121
7122 if (len > end)
7123 return -ENOMEM;
7124
7125+#ifdef CONFIG_PAX_RANDMMAP
7126+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
7127+#endif
7128+
7129 if (addr) {
7130 addr = PAGE_ALIGN(addr);
7131 vma = find_vma(mm, addr);
7132diff -urNp linux-2.6.17.7/arch/x86_64/mm/fault.c linux-2.6.17.7/arch/x86_64/mm/fault.c
7133--- linux-2.6.17.7/arch/x86_64/mm/fault.c 2006-07-24 23:36:01.000000000 -0400
7134+++ linux-2.6.17.7/arch/x86_64/mm/fault.c 2006-08-01 20:29:46.000000000 -0400
7135@@ -24,6 +24,7 @@
7136 #include <linux/compiler.h>
7137 #include <linux/module.h>
7138 #include <linux/kprobes.h>
7139+#include <linux/binfmts.h>
7140
7141 #include <asm/system.h>
7142 #include <asm/uaccess.h>
7143@@ -294,6 +295,33 @@ static int vmalloc_fault(unsigned long a
7144 return 0;
7145 }
7146
7147+#ifdef CONFIG_PAX_PAGEEXEC
7148+void pax_report_insns(void *pc, void *sp)
7149+{
7150+ long i;
7151+
7152+ printk(KERN_ERR "PAX: bytes at PC: ");
7153+ for (i = 0; i < 20; i++) {
7154+ unsigned char c;
7155+ if (get_user(c, (unsigned char __user *)pc+i))
7156+ printk("?? ");
7157+ else
7158+ printk("%02x ", c);
7159+ }
7160+ printk("\n");
7161+
7162+ printk(KERN_ERR "PAX: bytes at SP-8: ");
7163+ for (i = -1; i < 10; i++) {
7164+ unsigned long c;
7165+ if (get_user(c, (unsigned long __user *)sp+i))
7166+ printk("???????????????? ");
7167+ else
7168+ printk("%016lx ", c);
7169+ }
7170+ printk("\n");
7171+}
7172+#endif
7173+
7174 int page_fault_trace = 0;
7175 int exception_trace = 1;
7176
7177@@ -423,6 +451,8 @@ asmlinkage void __kprobes do_page_fault(
7178 good_area:
7179 info.si_code = SEGV_ACCERR;
7180 write = 0;
7181+ if ((error_code & PF_INSTR) && !(vma->vm_flags & VM_EXEC))
7182+ goto bad_area;
7183 switch (error_code & (PF_PROT|PF_WRITE)) {
7184 default: /* 3: write, present */
7185 /* fall through */
7186@@ -489,7 +519,14 @@ bad_area_nosemaphore:
7187 tsk->comm, tsk->pid, address, regs->rip,
7188 regs->rsp, error_code);
7189 }
7190-
7191+
7192+#ifdef CONFIG_PAX_PAGEEXEC
7193+ if (mm && (mm->pax_flags & MF_PAX_PAGEEXEC) && (error_code & 16)) {
7194+ pax_report_fault(regs, (void*)regs->rip, (void*)regs->rsp);
7195+ do_exit(SIGKILL);
7196+ }
7197+#endif
7198+
7199 tsk->thread.cr2 = address;
7200 /* Kernel addresses are always protection faults */
7201 tsk->thread.error_code = error_code | (address >= TASK_SIZE);
7202diff -urNp linux-2.6.17.7/arch/x86_64/mm/mmap.c linux-2.6.17.7/arch/x86_64/mm/mmap.c
7203--- linux-2.6.17.7/arch/x86_64/mm/mmap.c 2006-07-24 23:36:01.000000000 -0400
7204+++ linux-2.6.17.7/arch/x86_64/mm/mmap.c 2006-08-01 20:29:46.000000000 -0400
7205@@ -24,6 +24,12 @@ void arch_pick_mmap_layout(struct mm_str
7206 unsigned rnd = get_random_int() & 0xfffffff;
7207 mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT;
7208 }
7209+
7210+#ifdef CONFIG_PAX_RANDMMAP
7211+ if (mm->pax_flags & MF_PAX_RANDMMAP)
7212+ mm->mmap_base += mm->delta_mmap;
7213+#endif
7214+
7215 mm->get_unmapped_area = arch_get_unmapped_area;
7216 mm->unmap_area = arch_unmap_area;
7217 }
7218diff -urNp linux-2.6.17.7/drivers/char/agp/frontend.c linux-2.6.17.7/drivers/char/agp/frontend.c
7219--- linux-2.6.17.7/drivers/char/agp/frontend.c 2006-07-24 23:36:01.000000000 -0400
7220+++ linux-2.6.17.7/drivers/char/agp/frontend.c 2006-08-01 20:29:46.000000000 -0400
7221@@ -841,7 +841,7 @@ static int agpioc_reserve_wrap(struct ag
7222 if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
7223 return -EFAULT;
7224
7225- if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
7226+ if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment_priv))
7227 return -EFAULT;
7228
7229 client = agp_find_client_by_pid(reserve.pid);
7230diff -urNp linux-2.6.17.7/drivers/char/keyboard.c linux-2.6.17.7/drivers/char/keyboard.c
7231--- linux-2.6.17.7/drivers/char/keyboard.c 2006-07-24 23:36:01.000000000 -0400
7232+++ linux-2.6.17.7/drivers/char/keyboard.c 2006-08-01 20:29:46.000000000 -0400
7233@@ -618,6 +618,16 @@ static void k_spec(struct vc_data *vc, u
7234 kbd->kbdmode == VC_MEDIUMRAW) &&
7235 value != KVAL(K_SAK))
7236 return; /* SAK is allowed even in raw mode */
7237+
7238+#if defined(CONFIG_GRKERNSEC_PROC) || defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
7239+ {
7240+ void *func = fn_handler[value];
7241+ if (func == fn_show_state || func == fn_show_ptregs ||
7242+ func == fn_show_mem)
7243+ return;
7244+ }
7245+#endif
7246+
7247 fn_handler[value](vc, regs);
7248 }
7249
7250diff -urNp linux-2.6.17.7/drivers/char/mem.c linux-2.6.17.7/drivers/char/mem.c
7251--- linux-2.6.17.7/drivers/char/mem.c 2006-07-24 23:36:01.000000000 -0400
7252+++ linux-2.6.17.7/drivers/char/mem.c 2006-08-01 20:29:46.000000000 -0400
7253@@ -28,6 +28,7 @@
7254 #include <linux/backing-dev.h>
7255 #include <linux/bootmem.h>
7256 #include <linux/pipe_fs_i.h>
7257+#include <linux/grsecurity.h>
7258
7259 #include <asm/uaccess.h>
7260 #include <asm/io.h>
7261@@ -36,6 +37,10 @@
7262 # include <linux/efi.h>
7263 #endif
7264
7265+#ifdef CONFIG_GRKERNSEC
7266+extern struct file_operations grsec_fops;
7267+#endif
7268+
7269 /*
7270 * Architectures vary in how they handle caching for addresses
7271 * outside of main memory.
7272@@ -175,6 +180,11 @@ static ssize_t write_mem(struct file * f
7273 if (!valid_phys_addr_range(p, count))
7274 return -EFAULT;
7275
7276+#ifdef CONFIG_GRKERNSEC_KMEM
7277+ gr_handle_mem_write();
7278+ return -EPERM;
7279+#endif
7280+
7281 written = 0;
7282
7283 #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
7284@@ -251,6 +261,11 @@ static int mmap_mem(struct file * file,
7285 size,
7286 vma->vm_page_prot);
7287
7288+#ifdef CONFIG_GRKERNSEC_KMEM
7289+ if (gr_handle_mem_mmap(vma->vm_pgoff << PAGE_SHIFT, vma))
7290+ return -EPERM;
7291+#endif
7292+
7293 /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
7294 if (remap_pfn_range(vma,
7295 vma->vm_start,
7296@@ -478,6 +493,11 @@ static ssize_t write_kmem(struct file *
7297 ssize_t written;
7298 char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
7299
7300+#ifdef CONFIG_GRKERNSEC_KMEM
7301+ gr_handle_kmem_write();
7302+ return -EPERM;
7303+#endif
7304+
7305 if (p < (unsigned long) high_memory) {
7306
7307 wrote = count;
7308@@ -618,7 +638,23 @@ static inline size_t read_zero_pagealign
7309 count = size;
7310
7311 zap_page_range(vma, addr, count, NULL);
7312- zeromap_page_range(vma, addr, count, PAGE_COPY);
7313+ zeromap_page_range(vma, addr, count, vma->vm_page_prot);
7314+
7315+#ifdef CONFIG_PAX_SEGMEXEC
7316+ if (vma->vm_flags & VM_MIRROR) {
7317+ unsigned long addr_m;
7318+ struct vm_area_struct * vma_m;
7319+
7320+ addr_m = vma->vm_start + vma->vm_mirror;
7321+ vma_m = find_vma(mm, addr_m);
7322+ if (vma_m && vma_m->vm_start == addr_m && (vma_m->vm_flags & VM_MIRROR)) {
7323+ addr_m = addr + vma->vm_mirror;
7324+ zap_page_range(vma_m, addr_m, count, NULL);
7325+ } else
7326+ printk(KERN_ERR "PAX: VMMIRROR: read_zero bug, %08lx, %08lx\n",
7327+ addr, vma->vm_start);
7328+ }
7329+#endif
7330
7331 size -= count;
7332 buf += count;
7333@@ -767,6 +803,16 @@ static loff_t memory_lseek(struct file *
7334
7335 static int open_port(struct inode * inode, struct file * filp)
7336 {
7337+#ifdef CONFIG_GRKERNSEC_KMEM
7338+ gr_handle_open_port();
7339+ return -EPERM;
7340+#endif
7341+
7342+ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
7343+}
7344+
7345+static int open_mem(struct inode * inode, struct file * filp)
7346+{
7347 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
7348 }
7349
7350@@ -774,7 +820,6 @@ static int open_port(struct inode * inod
7351 #define full_lseek null_lseek
7352 #define write_zero write_null
7353 #define read_full read_zero
7354-#define open_mem open_port
7355 #define open_kmem open_mem
7356 #define open_oldmem open_mem
7357
7358@@ -897,6 +942,11 @@ static int memory_open(struct inode * in
7359 filp->f_op = &oldmem_fops;
7360 break;
7361 #endif
7362+#ifdef CONFIG_GRKERNSEC
7363+ case 13:
7364+ filp->f_op = &grsec_fops;
7365+ break;
7366+#endif
7367 default:
7368 return -ENXIO;
7369 }
7370@@ -929,6 +979,9 @@ static const struct {
7371 #ifdef CONFIG_CRASH_DUMP
7372 {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
7373 #endif
7374+#ifdef CONFIG_GRKERNSEC
7375+ {13,"grsec", S_IRUSR | S_IWUGO, &grsec_fops},
7376+#endif
7377 };
7378
7379 static struct class *mem_class;
7380diff -urNp linux-2.6.17.7/drivers/char/random.c linux-2.6.17.7/drivers/char/random.c
7381--- linux-2.6.17.7/drivers/char/random.c 2006-07-24 23:36:01.000000000 -0400
7382+++ linux-2.6.17.7/drivers/char/random.c 2006-08-01 20:29:46.000000000 -0400
7383@@ -249,8 +249,13 @@
7384 /*
7385 * Configuration information
7386 */
7387+#ifdef CONFIG_GRKERNSEC_RANDNET
7388+#define INPUT_POOL_WORDS 512
7389+#define OUTPUT_POOL_WORDS 128
7390+#else
7391 #define INPUT_POOL_WORDS 128
7392 #define OUTPUT_POOL_WORDS 32
7393+#endif
7394 #define SEC_XFER_SIZE 512
7395
7396 /*
7397@@ -287,10 +292,17 @@ static struct poolinfo {
7398 int poolwords;
7399 int tap1, tap2, tap3, tap4, tap5;
7400 } poolinfo_table[] = {
7401+#ifdef CONFIG_GRKERNSEC_RANDNET
7402+ /* x^512 + x^411 + x^308 + x^208 +x^104 + x + 1 -- 225 */
7403+ { 512, 411, 308, 208, 104, 1 },
7404+ /* x^128 + x^103 + x^76 + x^51 + x^25 + x + 1 -- 105 */
7405+ { 128, 103, 76, 51, 25, 1 },
7406+#else
7407 /* x^128 + x^103 + x^76 + x^51 +x^25 + x + 1 -- 105 */
7408 { 128, 103, 76, 51, 25, 1 },
7409 /* x^32 + x^26 + x^20 + x^14 + x^7 + x + 1 -- 15 */
7410 { 32, 26, 20, 14, 7, 1 },
7411+#endif
7412 #if 0
7413 /* x^2048 + x^1638 + x^1231 + x^819 + x^411 + x + 1 -- 115 */
7414 { 2048, 1638, 1231, 819, 411, 1 },
7415@@ -1658,3 +1670,25 @@ randomize_range(unsigned long start, uns
7416 return 0;
7417 return PAGE_ALIGN(get_random_int() % range + start);
7418 }
7419+
7420+#if defined(CONFIG_PAX_ASLR) || defined(CONFIG_GRKERNSEC)
7421+unsigned long pax_get_random_long(void)
7422+{
7423+ static time_t rekey_time;
7424+ static __u32 secret[12];
7425+ time_t t;
7426+
7427+ /*
7428+ * Pick a random secret every REKEY_INTERVAL seconds.
7429+ */
7430+ t = get_seconds();
7431+ if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) {
7432+ rekey_time = t;
7433+ get_random_bytes(secret, sizeof(secret));
7434+ }
7435+
7436+ secret[1] = half_md4_transform(secret+8, secret);
7437+ secret[0] = half_md4_transform(secret+8, secret);
7438+ return *(unsigned long *)secret;
7439+}
7440+#endif
7441diff -urNp linux-2.6.17.7/drivers/char/vt_ioctl.c linux-2.6.17.7/drivers/char/vt_ioctl.c
7442--- linux-2.6.17.7/drivers/char/vt_ioctl.c 2006-07-24 23:36:01.000000000 -0400
7443+++ linux-2.6.17.7/drivers/char/vt_ioctl.c 2006-08-01 20:29:46.000000000 -0400
7444@@ -96,6 +96,12 @@ do_kdsk_ioctl(int cmd, struct kbentry __
7445 case KDSKBENT:
7446 if (!perm)
7447 return -EPERM;
7448+
7449+#ifdef CONFIG_GRKERNSEC
7450+ if (!capable(CAP_SYS_TTY_CONFIG))
7451+ return -EPERM;
7452+#endif
7453+
7454 if (!i && v == K_NOSUCHMAP) {
7455 /* disallocate map */
7456 key_map = key_maps[s];
7457@@ -236,6 +242,13 @@ do_kdgkb_ioctl(int cmd, struct kbsentry
7458 goto reterr;
7459 }
7460
7461+#ifdef CONFIG_GRKERNSEC
7462+ if (!capable(CAP_SYS_TTY_CONFIG)) {
7463+ ret = -EPERM;
7464+ goto reterr;
7465+ }
7466+#endif
7467+
7468 q = func_table[i];
7469 first_free = funcbufptr + (funcbufsize - funcbufleft);
7470 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
7471diff -urNp linux-2.6.17.7/drivers/ieee1394/hosts.c linux-2.6.17.7/drivers/ieee1394/hosts.c
7472--- linux-2.6.17.7/drivers/ieee1394/hosts.c 2006-07-24 23:36:01.000000000 -0400
7473+++ linux-2.6.17.7/drivers/ieee1394/hosts.c 2006-08-01 20:29:46.000000000 -0400
7474@@ -75,6 +75,7 @@ static int dummy_isoctl(struct hpsb_iso
7475 }
7476
7477 static struct hpsb_host_driver dummy_driver = {
7478+ .name = "dummy",
7479 .transmit_packet = dummy_transmit_packet,
7480 .devctl = dummy_devctl,
7481 .isoctl = dummy_isoctl
7482diff -urNp linux-2.6.17.7/drivers/ieee1394/ohci1394.c linux-2.6.17.7/drivers/ieee1394/ohci1394.c
7483--- linux-2.6.17.7/drivers/ieee1394/ohci1394.c 2006-07-24 23:36:01.000000000 -0400
7484+++ linux-2.6.17.7/drivers/ieee1394/ohci1394.c 2006-08-01 20:29:46.000000000 -0400
7485@@ -162,9 +162,9 @@ printk(level "%s: " fmt "\n" , OHCI1394_
7486 printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
7487
7488 /* Module Parameters */
7489-static int phys_dma = 1;
7490+static int phys_dma = 0;
7491 module_param(phys_dma, int, 0644);
7492-MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1).");
7493+MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 0).");
7494
7495 static void dma_trm_tasklet(unsigned long data);
7496 static void dma_trm_reset(struct dma_trm_ctx *d);
7497diff -urNp linux-2.6.17.7/drivers/mtd/devices/doc2001.c linux-2.6.17.7/drivers/mtd/devices/doc2001.c
7498--- linux-2.6.17.7/drivers/mtd/devices/doc2001.c 2006-07-24 23:36:01.000000000 -0400
7499+++ linux-2.6.17.7/drivers/mtd/devices/doc2001.c 2006-08-01 20:29:46.000000000 -0400
7500@@ -423,6 +423,8 @@ static int doc_read_ecc (struct mtd_info
7501 /* Don't allow read past end of device */
7502 if (from >= this->totlen)
7503 return -EINVAL;
7504+ if (!len)
7505+ return -EINVAL;
7506
7507 /* Don't allow a single read to cross a 512-byte block boundary */
7508 if (from + len > ((from | 0x1ff) + 1))
7509diff -urNp linux-2.6.17.7/drivers/net/pcnet32.c linux-2.6.17.7/drivers/net/pcnet32.c
7510--- linux-2.6.17.7/drivers/net/pcnet32.c 2006-07-24 23:36:01.000000000 -0400
7511+++ linux-2.6.17.7/drivers/net/pcnet32.c 2006-08-01 20:29:46.000000000 -0400
7512@@ -81,7 +81,7 @@ static int cards_found;
7513 /*
7514 * VLB I/O addresses
7515 */
7516-static unsigned int pcnet32_portlist[] __initdata =
7517+static unsigned int pcnet32_portlist[] __devinitdata =
7518 { 0x300, 0x320, 0x340, 0x360, 0 };
7519
7520 static int pcnet32_debug = 0;
7521diff -urNp linux-2.6.17.7/drivers/pci/proc.c linux-2.6.17.7/drivers/pci/proc.c
7522--- linux-2.6.17.7/drivers/pci/proc.c 2006-07-24 23:36:01.000000000 -0400
7523+++ linux-2.6.17.7/drivers/pci/proc.c 2006-08-01 20:29:46.000000000 -0400
7524@@ -473,7 +473,15 @@ static int __init pci_proc_init(void)
7525 {
7526 struct proc_dir_entry *entry;
7527 struct pci_dev *dev = NULL;
7528+#ifdef CONFIG_GRKERNSEC_PROC_ADD
7529+#ifdef CONFIG_GRKERNSEC_PROC_USER
7530+ proc_bus_pci_dir = proc_mkdir_mode("pci", S_IRUSR | S_IXUSR, proc_bus);
7531+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
7532+ proc_bus_pci_dir = proc_mkdir_mode("pci", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, proc_bus);
7533+#endif
7534+#else
7535 proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
7536+#endif
7537 entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
7538 if (entry)
7539 entry->proc_fops = &proc_bus_pci_dev_operations;
7540diff -urNp linux-2.6.17.7/drivers/pnp/pnpbios/bioscalls.c linux-2.6.17.7/drivers/pnp/pnpbios/bioscalls.c
7541--- linux-2.6.17.7/drivers/pnp/pnpbios/bioscalls.c 2006-07-24 23:36:01.000000000 -0400
7542+++ linux-2.6.17.7/drivers/pnp/pnpbios/bioscalls.c 2006-08-01 20:29:46.000000000 -0400
7543@@ -65,7 +65,7 @@ set_base(gdt[(selname) >> 3], (u32)(addr
7544 set_limit(gdt[(selname) >> 3], size); \
7545 } while(0)
7546
7547-static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
7548+static struct desc_struct bad_bios_desc = { 0, 0x00409300 };
7549
7550 /*
7551 * At some point we want to use this stack frame pointer to unwind
7552@@ -93,6 +93,10 @@ static inline u16 call_pnp_bios(u16 func
7553 struct desc_struct save_desc_40;
7554 int cpu;
7555
7556+#ifdef CONFIG_PAX_KERNEXEC
7557+ unsigned long cr0;
7558+#endif
7559+
7560 /*
7561 * PnP BIOSes are generally not terribly re-entrant.
7562 * Also, don't rely on them to save everything correctly.
7563@@ -107,6 +111,10 @@ static inline u16 call_pnp_bios(u16 func
7564 /* On some boxes IRQ's during PnP BIOS calls are deadly. */
7565 spin_lock_irqsave(&pnp_bios_lock, flags);
7566
7567+#ifdef CONFIG_PAX_KERNEXEC
7568+ pax_open_kernel(cr0);
7569+#endif
7570+
7571 /* The lock prevents us bouncing CPU here */
7572 if (ts1_size)
7573 Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
7574@@ -142,9 +150,14 @@ static inline u16 call_pnp_bios(u16 func
7575 "i" (0)
7576 : "memory"
7577 );
7578- spin_unlock_irqrestore(&pnp_bios_lock, flags);
7579
7580 get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40;
7581+
7582+#ifdef CONFIG_PAX_KERNEXEC
7583+ pax_close_kernel(cr0);
7584+#endif
7585+
7586+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
7587 put_cpu();
7588
7589 /* If we get here and this is set then the PnP BIOS faulted on us. */
7590diff -urNp linux-2.6.17.7/drivers/video/i810/i810_main.c linux-2.6.17.7/drivers/video/i810/i810_main.c
7591--- linux-2.6.17.7/drivers/video/i810/i810_main.c 2006-07-24 23:36:01.000000000 -0400
7592+++ linux-2.6.17.7/drivers/video/i810/i810_main.c 2006-08-01 20:29:46.000000000 -0400
7593@@ -1508,7 +1508,7 @@ static int i810fb_cursor(struct fb_info
7594 int size = ((cursor->image.width + 7) >> 3) *
7595 cursor->image.height;
7596 int i;
7597- u8 *data = kmalloc(64 * 8, GFP_ATOMIC);
7598+ u8 *data = kmalloc(64 * 8, GFP_KERNEL);
7599
7600 if (data == NULL)
7601 return -ENOMEM;
7602diff -urNp linux-2.6.17.7/drivers/video/vesafb.c linux-2.6.17.7/drivers/video/vesafb.c
7603--- linux-2.6.17.7/drivers/video/vesafb.c 2006-07-24 23:36:01.000000000 -0400
7604+++ linux-2.6.17.7/drivers/video/vesafb.c 2006-08-01 20:29:46.000000000 -0400
7605@@ -259,7 +259,7 @@ static int __init vesafb_probe(struct pl
7606 size_remap = size_total;
7607 vesafb_fix.smem_len = size_remap;
7608
7609-#ifndef __i386__
7610+#if !defined(__i386__) || defined(CONFIG_PAX_KERNEXEC)
7611 screen_info.vesapm_seg = 0;
7612 #endif
7613
7614diff -urNp linux-2.6.17.7/fs/Kconfig linux-2.6.17.7/fs/Kconfig
7615--- linux-2.6.17.7/fs/Kconfig 2006-07-24 23:36:01.000000000 -0400
7616+++ linux-2.6.17.7/fs/Kconfig 2006-08-01 20:29:46.000000000 -0400
7617@@ -794,7 +794,7 @@ config PROC_FS
7618
7619 config PROC_KCORE
7620 bool "/proc/kcore support" if !ARM
7621- depends on PROC_FS && MMU
7622+ depends on PROC_FS && MMU && !GRKERNSEC_PROC_ADD
7623
7624 config PROC_VMCORE
7625 bool "/proc/vmcore support (EXPERIMENTAL)"
7626diff -urNp linux-2.6.17.7/fs/binfmt_aout.c linux-2.6.17.7/fs/binfmt_aout.c
7627--- linux-2.6.17.7/fs/binfmt_aout.c 2006-07-24 23:36:01.000000000 -0400
7628+++ linux-2.6.17.7/fs/binfmt_aout.c 2006-08-01 20:29:46.000000000 -0400
7629@@ -24,6 +24,7 @@
f1a4f855 7630 #include <linux/personality.h>
7631 #include <linux/init.h>
77fa6d7d 7632 #include <linux/vs_memory.h>
f1a4f855 7633+#include <linux/grsecurity.h>
7634
7635 #include <asm/system.h>
7636 #include <asm/uaccess.h>
7637@@ -123,10 +124,12 @@ static int aout_core_dump(long signr, st
7638 /* If the size of the dump file exceeds the rlimit, then see what would happen
7639 if we wrote the stack, but not the data area. */
7640 #ifdef __sparc__
7641+ gr_learn_resource(current, RLIMIT_CORE, dump.u_dsize+dump.u_ssize, 1);
7642 if ((dump.u_dsize+dump.u_ssize) >
7643 current->signal->rlim[RLIMIT_CORE].rlim_cur)
7644 dump.u_dsize = 0;
7645 #else
7646+ gr_learn_resource(current, RLIMIT_CORE, (dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE, 1);
7647 if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
7648 current->signal->rlim[RLIMIT_CORE].rlim_cur)
7649 dump.u_dsize = 0;
7650@@ -134,10 +137,12 @@ static int aout_core_dump(long signr, st
7651
7652 /* Make sure we have enough room to write the stack and data areas. */
7653 #ifdef __sparc__
7654+ gr_learn_resource(current, RLIMIT_CORE, dump.u_ssize, 1);
7655 if ((dump.u_ssize) >
7656 current->signal->rlim[RLIMIT_CORE].rlim_cur)
7657 dump.u_ssize = 0;
7658 #else
7659+ gr_learn_resource(current, RLIMIT_CORE, (dump.u_ssize+1) * PAGE_SIZE, 1);
7660 if ((dump.u_ssize+1) * PAGE_SIZE >
7661 current->signal->rlim[RLIMIT_CORE].rlim_cur)
7662 dump.u_ssize = 0;
7663@@ -287,6 +292,8 @@ static int load_aout_binary(struct linux
7664 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
7665 if (rlim >= RLIM_INFINITY)
7666 rlim = ~0;
7667+
7668+ gr_learn_resource(current, RLIMIT_DATA, ex.a_data + ex.a_bss, 1);
7669 if (ex.a_data + ex.a_bss > rlim)
7670 return -ENOMEM;
7671
7672@@ -319,6 +326,28 @@ static int load_aout_binary(struct linux
7673 current->mm->mmap = NULL;
7674 compute_creds(bprm);
7675 current->flags &= ~PF_FORKNOEXEC;
7676+
7677+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
7678+ current->mm->pax_flags = 0UL;
7679+#endif
7680+
7681+#ifdef CONFIG_PAX_PAGEEXEC
7682+ if (!(N_FLAGS(ex) & F_PAX_PAGEEXEC)) {
7683+ current->mm->pax_flags |= MF_PAX_PAGEEXEC;
7684+
7685+#ifdef CONFIG_PAX_EMUTRAMP
7686+ if (N_FLAGS(ex) & F_PAX_EMUTRAMP)
7687+ current->mm->pax_flags |= MF_PAX_EMUTRAMP;
7688+#endif
7689+
7690+#ifdef CONFIG_PAX_MPROTECT
7691+ if (!(N_FLAGS(ex) & F_PAX_MPROTECT))
7692+ current->mm->pax_flags |= MF_PAX_MPROTECT;
7693+#endif
7694+
7695+ }
7696+#endif
7697+
7698 #ifdef __sparc__
7699 if (N_MAGIC(ex) == NMAGIC) {
7700 loff_t pos = fd_offset;
7701@@ -414,7 +443,7 @@ static int load_aout_binary(struct linux
7702
7703 down_write(&current->mm->mmap_sem);
7704 error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
7705- PROT_READ | PROT_WRITE | PROT_EXEC,
7706+ PROT_READ | PROT_WRITE,
7707 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
7708 fd_offset + ex.a_text);
7709 up_write(&current->mm->mmap_sem);
7710diff -urNp linux-2.6.17.7/fs/binfmt_elf.c linux-2.6.17.7/fs/binfmt_elf.c
7711--- linux-2.6.17.7/fs/binfmt_elf.c 2006-07-24 23:36:01.000000000 -0400
7712+++ linux-2.6.17.7/fs/binfmt_elf.c 2006-08-01 20:29:46.000000000 -0400
7713@@ -38,11 +38,16 @@
f1a4f855 7714 #include <linux/random.h>
77fa6d7d 7715 #include <linux/vs_memory.h>
7716 #include <linux/vs_cvirt.h>
f1a4f855 7717+#include <linux/grsecurity.h>
7718
7719 #include <asm/uaccess.h>
7720 #include <asm/param.h>
7721 #include <asm/page.h>
7722
7723+#ifdef CONFIG_PAX_SEGMEXEC
7724+#include <asm/desc.h>
7725+#endif
7726+
7727 #include <linux/elf.h>
7728
7729 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
7730@@ -90,6 +95,8 @@ static struct linux_binfmt elf_format =
7731
7732 static int set_brk(unsigned long start, unsigned long end)
7733 {
7734+ unsigned long e = end;
7735+
7736 start = ELF_PAGEALIGN(start);
7737 end = ELF_PAGEALIGN(end);
7738 if (end > start) {
7739@@ -100,7 +107,7 @@ static int set_brk(unsigned long start,
7740 if (BAD_ADDR(addr))
7741 return addr;
7742 }
7743- current->mm->start_brk = current->mm->brk = end;
7744+ current->mm->start_brk = current->mm->brk = e;
7745 return 0;
7746 }
7747
7748@@ -316,10 +323,9 @@ static unsigned long load_elf_interp(str
7749 {
7750 struct elf_phdr *elf_phdata;
7751 struct elf_phdr *eppnt;
7752- unsigned long load_addr = 0;
7753- int load_addr_set = 0;
7754+ unsigned long load_addr = 0, min_addr, max_addr, task_size = TASK_SIZE;
7755 unsigned long last_bss = 0, elf_bss = 0;
7756- unsigned long error = ~0UL;
7757+ unsigned long error = -EINVAL;
7758 int retval, i, size;
7759
7760 /* First of all, some simple consistency checks */
7761@@ -358,59 +364,80 @@ static unsigned long load_elf_interp(str
7762 goto out_close;
7763 }
7764
7765+#ifdef CONFIG_PAX_SEGMEXEC
7766+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
7767+ task_size = SEGMEXEC_TASK_SIZE;
7768+#endif
7769+
7770 eppnt = elf_phdata;
7771+ min_addr = task_size;
7772+ max_addr = 0;
7773+ error = -ENOMEM;
7774+
7775 for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
7776- if (eppnt->p_type == PT_LOAD) {
7777- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
7778- int elf_prot = 0;
7779- unsigned long vaddr = 0;
7780- unsigned long k, map_addr;
7781-
7782- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
7783- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
7784- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
7785- vaddr = eppnt->p_vaddr;
7786- if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
7787- elf_type |= MAP_FIXED;
7788-
7789- map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
7790- error = map_addr;
7791- if (BAD_ADDR(map_addr))
7792- goto out_close;
7793-
7794- if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
7795- load_addr = map_addr - ELF_PAGESTART(vaddr);
7796- load_addr_set = 1;
7797- }
7798-
7799- /*
7800- * Check to see if the section's size will overflow the
7801- * allowed task size. Note that p_filesz must always be
7802- * <= p_memsize so it is only necessary to check p_memsz.
7803- */
7804- k = load_addr + eppnt->p_vaddr;
7805- if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz ||
7806- eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) {
7807- error = -ENOMEM;
7808+ if (eppnt->p_type != PT_LOAD)
7809+ continue;
7810+
7811+ /*
7812+ * Check to see if the section's size will overflow the
7813+ * allowed task size. Note that p_filesz must always be
7814+ * <= p_memsize so it is only necessary to check p_memsz.
7815+ */
7816+ if (eppnt->p_filesz > eppnt->p_memsz || eppnt->p_vaddr >= eppnt->p_vaddr + eppnt->p_memsz)
7817+ goto out_close;
7818+
7819+ if (min_addr > ELF_PAGESTART(eppnt->p_vaddr))
7820+ min_addr = ELF_PAGESTART(eppnt->p_vaddr);
7821+ if (max_addr < ELF_PAGEALIGN(eppnt->p_vaddr + eppnt->p_memsz))
7822+ max_addr = ELF_PAGEALIGN(eppnt->p_vaddr + eppnt->p_memsz);
7823+ }
7824+ if (min_addr >= max_addr)
7825 goto out_close;
7826- }
7827
7828- /*
7829- * Find the end of the file mapping for this phdr, and keep
7830- * track of the largest address we see for this.
7831- */
7832- k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
7833- if (k > elf_bss)
7834- elf_bss = k;
7835-
7836- /*
7837- * Do the same thing for the memory mapping - between
7838- * elf_bss and last_bss is the bss section.
7839- */
7840- k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
7841- if (k > last_bss)
7842- last_bss = k;
7843- }
7844+ eppnt = elf_phdata;
7845+ for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
7846+ int elf_type = MAP_PRIVATE | MAP_DENYWRITE | MAP_FIXED;
7847+ int elf_prot = 0;
7848+ unsigned long vaddr;
7849+ unsigned long k, map_addr;
7850+
7851+ if (eppnt->p_type != PT_LOAD)
7852+ continue;
7853+
7854+ if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
7855+ if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
7856+ if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
7857+ vaddr = eppnt->p_vaddr;
7858+
7859+ if (!load_addr && interp_elf_ex->e_type == ET_DYN) {
7860+ load_addr = get_unmapped_area(interpreter, 0, max_addr - min_addr, 0, MAP_PRIVATE | MAP_EXECUTABLE);
7861+
7862+ if (load_addr > task_size)
7863+ goto out_close;
7864+
7865+ load_addr -= min_addr;
7866+ }
7867+
7868+ map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
7869+ error = map_addr;
7870+ if (BAD_ADDR(map_addr))
7871+ goto out_close;
7872+
7873+ /*
7874+ * Find the end of the file mapping for this phdr, and keep
7875+ * track of the largest address we see for this.
7876+ */
7877+ k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
7878+ if (k > elf_bss)
7879+ elf_bss = k;
7880+
7881+ /*
7882+ * Do the same thing for the memory mapping - between
7883+ * elf_bss and last_bss is the bss section.
7884+ */
7885+ k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
7886+ if (k > last_bss)
7887+ last_bss = k;
7888 }
7889
7890 /*
7891@@ -447,7 +474,7 @@ out:
7892 static unsigned long load_aout_interp(struct exec * interp_ex,
7893 struct file * interpreter)
7894 {
7895- unsigned long text_data, elf_entry = ~0UL;
7896+ unsigned long text_data, elf_entry = -EINVAL;
7897 char __user * addr;
7898 loff_t offset;
7899
7900@@ -491,6 +518,180 @@ out:
7901 return elf_entry;
7902 }
7903
7904+#if (defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)) && defined(CONFIG_PAX_SOFTMODE)
7905+static unsigned long pax_parse_softmode(const struct elf_phdr * const elf_phdata)
7906+{
7907+ unsigned long pax_flags = 0UL;
7908+
7909+#ifdef CONFIG_PAX_PAGEEXEC
7910+ if (elf_phdata->p_flags & PF_PAGEEXEC)
7911+ pax_flags |= MF_PAX_PAGEEXEC;
7912+#endif
7913+
7914+#ifdef CONFIG_PAX_SEGMEXEC
7915+ if (elf_phdata->p_flags & PF_SEGMEXEC)
7916+ pax_flags |= MF_PAX_SEGMEXEC;
7917+#endif
7918+
7919+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
7920+ if (pax_flags & MF_PAX_PAGEEXEC)
7921+ pax_flags &= ~MF_PAX_SEGMEXEC;
7922+#endif
7923+
7924+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
7925+ if (pax_flags & MF_PAX_SEGMEXEC)
7926+ pax_flags &= ~MF_PAX_PAGEEXEC;
7927+#endif
7928+
7929+#ifdef CONFIG_PAX_EMUTRAMP
7930+ if (elf_phdata->p_flags & PF_EMUTRAMP)
7931+ pax_flags |= MF_PAX_EMUTRAMP;
7932+#endif
7933+
7934+#ifdef CONFIG_PAX_MPROTECT
7935+ if (elf_phdata->p_flags & PF_MPROTECT)
7936+ pax_flags |= MF_PAX_MPROTECT;
7937+#endif
7938+
7939+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
7940+ if (randomize_va_space && (elf_phdata->p_flags & PF_RANDMMAP))
7941+ pax_flags |= MF_PAX_RANDMMAP;
7942+#endif
7943+
7944+ return pax_flags;
7945+}
7946+#endif
7947+
7948+#ifdef CONFIG_PAX_PT_PAX_FLAGS
7949+static unsigned long pax_parse_hardmode(const struct elf_phdr * const elf_phdata)
7950+{
7951+ unsigned long pax_flags = 0UL;
7952+
7953+#ifdef CONFIG_PAX_PAGEEXEC
7954+ if (!(elf_phdata->p_flags & PF_NOPAGEEXEC))
7955+ pax_flags |= MF_PAX_PAGEEXEC;
7956+#endif
7957+
7958+#ifdef CONFIG_PAX_SEGMEXEC
7959+ if (!(elf_phdata->p_flags & PF_NOSEGMEXEC))
7960+ pax_flags |= MF_PAX_SEGMEXEC;
7961+#endif
7962+
7963+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
7964+ if (pax_flags & MF_PAX_PAGEEXEC)
7965+ pax_flags &= ~MF_PAX_SEGMEXEC;
7966+#endif
7967+
7968+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
7969+ if (pax_flags & MF_PAX_SEGMEXEC)
7970+ pax_flags &= ~MF_PAX_PAGEEXEC;
7971+#endif
7972+
7973+#ifdef CONFIG_PAX_EMUTRAMP
7974+ if (!(elf_phdata->p_flags & PF_NOEMUTRAMP))
7975+ pax_flags |= MF_PAX_EMUTRAMP;
7976+#endif
7977+
7978+#ifdef CONFIG_PAX_MPROTECT
7979+ if (!(elf_phdata->p_flags & PF_NOMPROTECT))
7980+ pax_flags |= MF_PAX_MPROTECT;
7981+#endif
7982+
7983+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
7984+ if (randomize_va_space && !(elf_phdata->p_flags & PF_NORANDMMAP))
7985+ pax_flags |= MF_PAX_RANDMMAP;
7986+#endif
7987+
7988+ return pax_flags;
7989+}
7990+#endif
7991+
7992+#ifdef CONFIG_PAX_EI_PAX
7993+static unsigned long pax_parse_ei_pax(const struct elfhdr * const elf_ex)
7994+{
7995+ unsigned long pax_flags = 0UL;
7996+
7997+#ifdef CONFIG_PAX_PAGEEXEC
7998+ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_PAGEEXEC))
7999+ pax_flags |= MF_PAX_PAGEEXEC;
8000+#endif
8001+
8002+#ifdef CONFIG_PAX_SEGMEXEC
8003+ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_SEGMEXEC))
8004+ pax_flags |= MF_PAX_SEGMEXEC;
8005+#endif
8006+
8007+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
8008+ if (pax_flags & MF_PAX_PAGEEXEC)
8009+ pax_flags &= ~MF_PAX_SEGMEXEC;
8010+#endif
8011+
8012+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
8013+ if (pax_flags & MF_PAX_SEGMEXEC)
8014+ pax_flags &= ~MF_PAX_PAGEEXEC;
8015+#endif
8016+
8017+#ifdef CONFIG_PAX_EMUTRAMP
8018+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && (elf_ex->e_ident[EI_PAX] & EF_PAX_EMUTRAMP))
8019+ pax_flags |= MF_PAX_EMUTRAMP;
8020+#endif
8021+
8022+#ifdef CONFIG_PAX_MPROTECT
8023+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && !(elf_ex->e_ident[EI_PAX] & EF_PAX_MPROTECT))
8024+ pax_flags |= MF_PAX_MPROTECT;
8025+#endif
8026+
8027+#ifdef CONFIG_PAX_ASLR
8028+ if (randomize_va_space && !(elf_ex->e_ident[EI_PAX] & EF_PAX_RANDMMAP))
8029+ pax_flags |= MF_PAX_RANDMMAP;
8030+#endif
8031+
8032+ return pax_flags;
8033+}
8034+#endif
8035+
8036+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)
8037+static long pax_parse_elf_flags(const struct elfhdr * const elf_ex, const struct elf_phdr * const elf_phdata)
8038+{
8039+ unsigned long pax_flags = 0UL;
8040+
8041+#ifdef CONFIG_PAX_PT_PAX_FLAGS
8042+ unsigned long i;
8043+#endif
8044+
8045+#ifdef CONFIG_PAX_EI_PAX
8046+ pax_flags = pax_parse_ei_pax(elf_ex);
8047+#endif
8048+
8049+#ifdef CONFIG_PAX_PT_PAX_FLAGS
8050+ for (i = 0UL; i < elf_ex->e_phnum; i++)
8051+ if (elf_phdata[i].p_type == PT_PAX_FLAGS) {
8052+ if (((elf_phdata[i].p_flags & PF_PAGEEXEC) && (elf_phdata[i].p_flags & PF_NOPAGEEXEC)) ||
8053+ ((elf_phdata[i].p_flags & PF_SEGMEXEC) && (elf_phdata[i].p_flags & PF_NOSEGMEXEC)) ||
8054+ ((elf_phdata[i].p_flags & PF_EMUTRAMP) && (elf_phdata[i].p_flags & PF_NOEMUTRAMP)) ||
8055+ ((elf_phdata[i].p_flags & PF_MPROTECT) && (elf_phdata[i].p_flags & PF_NOMPROTECT)) ||
8056+ ((elf_phdata[i].p_flags & PF_RANDMMAP) && (elf_phdata[i].p_flags & PF_NORANDMMAP)))
8057+ return -EINVAL;
8058+
8059+#ifdef CONFIG_PAX_SOFTMODE
8060+ if (pax_softmode)
8061+ pax_flags = pax_parse_softmode(&elf_phdata[i]);
8062+ else
8063+#endif
8064+
8065+ pax_flags = pax_parse_hardmode(&elf_phdata[i]);
8066+ break;
8067+ }
8068+#endif
8069+
8070+ if (0 > pax_check_flags(&pax_flags))
8071+ return -EINVAL;
8072+
8073+ current->mm->pax_flags = pax_flags;
8074+ return 0;
8075+}
8076+#endif
8077+
8078 /*
8079 * These are the functions used to load ELF style executables and shared
8080 * libraries. There is no binary dependent code anywhere else.
8081@@ -527,7 +728,7 @@ static int load_elf_binary(struct linux_
8082 char * elf_interpreter = NULL;
8083 unsigned int interpreter_type = INTERPRETER_NONE;
8084 unsigned char ibcs2_interpreter = 0;
8085- unsigned long error;
8086+ unsigned long error = 0;
8087 struct elf_phdr * elf_ppnt, *elf_phdata;
8088 unsigned long elf_bss, elf_brk;
8089 int elf_exec_fileno;
8090@@ -545,6 +746,7 @@ static int load_elf_binary(struct linux_
8091 struct elfhdr interp_elf_ex;
8092 struct exec interp_ex;
8093 } *loc;
8094+ unsigned long task_size = TASK_SIZE;
8095
8096 loc = kmalloc(sizeof(*loc), GFP_KERNEL);
8097 if (!loc) {
8098@@ -770,14 +972,88 @@ static int load_elf_binary(struct linux_
8099 current->mm->end_code = 0;
8100 current->mm->mmap = NULL;
8101 current->flags &= ~PF_FORKNOEXEC;
8102+
8103+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
8104+ current->mm->pax_flags = 0UL;
8105+#endif
8106+
8107+#ifdef CONFIG_PAX_DLRESOLVE
8108+ current->mm->call_dl_resolve = 0UL;
8109+#endif
8110+
8111+#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
8112+ current->mm->call_syscall = 0UL;
8113+#endif
8114+
8115+#ifdef CONFIG_PAX_ASLR
8116+ current->mm->delta_mmap = 0UL;
8117+ current->mm->delta_exec = 0UL;
8118+ current->mm->delta_stack = 0UL;
8119+#endif
8120+
8121 current->mm->def_flags = def_flags;
8122
8123+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)
8124+ if (0 > pax_parse_elf_flags(&loc->elf_ex, elf_phdata)) {
8125+ send_sig(SIGKILL, current, 0);
8126+ goto out_free_dentry;
8127+ }
8128+#endif
8129+
8130+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
8131+ pax_set_initial_flags(bprm);
8132+#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
8133+ if (pax_set_initial_flags_func)
8134+ (pax_set_initial_flags_func)(bprm);
8135+#endif
8136+
8137+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
8138+ if (current->mm->pax_flags & MF_PAX_PAGEEXEC)
8139+ current->mm->context.user_cs_limit = PAGE_SIZE;
8140+#endif
8141+
8142+#ifdef CONFIG_PAX_SEGMEXEC
8143+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
8144+ int cpu = get_cpu();
8145+
8146+ current->mm->context.user_cs_base = SEGMEXEC_TASK_SIZE;
8147+ current->mm->context.user_cs_limit = -SEGMEXEC_TASK_SIZE;
8148+ set_user_cs(current->mm, cpu);
8149+ put_cpu();
8150+ task_size = SEGMEXEC_TASK_SIZE;
8151+ }
8152+#endif
8153+
8154+#ifdef CONFIG_PAX_ASLR
8155+ if (current->mm->pax_flags & MF_PAX_RANDMMAP) {
8156+#define pax_delta_mask(delta, lsb, len) (((delta) & ((1UL << (len)) - 1)) << (lsb))
8157+
8158+ current->mm->delta_mmap = pax_delta_mask(pax_get_random_long(), PAX_DELTA_MMAP_LSB(current), PAX_DELTA_MMAP_LEN(current));
8159+ current->mm->delta_exec = pax_delta_mask(pax_get_random_long(), PAX_DELTA_EXEC_LSB(current), PAX_DELTA_EXEC_LEN(current));
8160+ current->mm->delta_stack = pax_delta_mask(pax_get_random_long(), PAX_DELTA_STACK_LSB(current), PAX_DELTA_STACK_LEN(current));
8161+ }
8162+#endif
8163+
8164+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
8165+ if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
8166+ executable_stack = EXSTACK_DEFAULT;
8167+#endif
8168+
8169 /* Do this immediately, since STACK_TOP as used in setup_arg_pages
8170 may depend on the personality. */
8171 SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
8172+
8173+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
8174+ if (!(current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)))
8175+#endif
8176+
8177 if (elf_read_implies_exec(loc->elf_ex, executable_stack))
8178 current->personality |= READ_IMPLIES_EXEC;
8179
8180+#ifdef CONFIG_PAX_ASLR
8181+ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP))
8182+#endif
8183+
8184 if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
8185 current->flags |= PF_RANDOMIZE;
8186 arch_pick_mmap_layout(current->mm);
8187@@ -849,6 +1125,15 @@ static int load_elf_binary(struct linux_
8188 base, as well as whatever program they might try to exec. This
8189 is because the brk will follow the loader, and is not movable. */
8190 load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
8191+
8192+#ifdef CONFIG_PAX_RANDMMAP
8193+ /* PaX: randomize base address at the default exe base if requested */
8194+ if (current->mm->pax_flags & MF_PAX_RANDMMAP) {
8195+ load_bias = ELF_PAGESTART(PAX_ELF_ET_DYN_BASE(current) - vaddr + current->mm->delta_exec);
8196+ elf_flags |= MAP_FIXED;
8197+ }
8198+#endif
8199+
8200 }
8201
8202 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
8203@@ -876,9 +1161,9 @@ static int load_elf_binary(struct linux_
8204 * allowed task size. Note that p_filesz must always be
8205 * <= p_memsz so it is only necessary to check p_memsz.
8206 */
8207- if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
8208- elf_ppnt->p_memsz > TASK_SIZE ||
8209- TASK_SIZE - elf_ppnt->p_memsz < k) {
8210+ if (k > task_size || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
8211+ elf_ppnt->p_memsz > task_size ||
8212+ task_size - elf_ppnt->p_memsz < k) {
8213 /* set_brk can never work. Avoid overflows. */
8214 send_sig(SIGKILL, current, 0);
8215 goto out_free_dentry;
8216@@ -905,6 +1190,12 @@ static int load_elf_binary(struct linux_
8217 start_data += load_bias;
8218 end_data += load_bias;
8219
8220+#ifdef CONFIG_PAX_RANDMMAP
8221+ if (current->mm->pax_flags & MF_PAX_RANDMMAP)
8222+ elf_brk += PAGE_SIZE + pax_delta_mask(pax_get_random_long(), 4, PAGE_SHIFT);
8223+#undef pax_delta_mask
8224+#endif
8225+
8226 /* Calling set_brk effectively mmaps the pages that we need
8227 * for the bss and break sections. We must do this before
8228 * mapping in the interpreter, to make sure it doesn't wind
8229@@ -933,7 +1224,7 @@ static int load_elf_binary(struct linux_
8230 printk(KERN_ERR "Unable to load interpreter %.128s\n",
8231 elf_interpreter);
8232 force_sig(SIGSEGV, current);
8233- retval = -ENOEXEC; /* Nobody gets to see this, but.. */
8234+ retval = elf_entry; /* Nobody gets to see this, but.. */
8235 goto out_free_dentry;
8236 }
8237 reloc_func_desc = interp_load_addr;
8238@@ -1157,7 +1448,7 @@ static int dump_seek(struct file *file,
8239 *
8240 * I think we should skip something. But I am not sure how. H.J.
8241 */
8242-static int maydump(struct vm_area_struct *vma)
8243+static int maydump(struct vm_area_struct *vma, long signr)
8244 {
8245 /* Do not dump I/O mapped devices or special mappings */
8246 if (vma->vm_flags & (VM_IO | VM_RESERVED))
8247@@ -1168,7 +1459,7 @@ static int maydump(struct vm_area_struct
8248 return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
8249
8250 /* If it hasn't been written to, don't write it out */
8251- if (!vma->anon_vma)
8252+ if (signr != SIGKILL && !vma->anon_vma)
8253 return 0;
8254
8255 return 1;
8256@@ -1222,8 +1513,11 @@ static int writenote(struct memelfnote *
8257 #undef DUMP_SEEK
8258
8259 #define DUMP_WRITE(addr, nr) \
8260+ do { \
8261+ gr_learn_resource(current, RLIMIT_CORE, size + (nr), 1); \
8262 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
8263- goto end_coredump;
8264+ goto end_coredump; \
8265+ } while (0);
8266 #define DUMP_SEEK(off) \
8267 if (!dump_seek(file, (off))) \
8268 goto end_coredump;
8269@@ -1573,7 +1867,7 @@ static int elf_core_dump(long signr, str
8270 phdr.p_offset = offset;
8271 phdr.p_vaddr = vma->vm_start;
8272 phdr.p_paddr = 0;
8273- phdr.p_filesz = maydump(vma) ? sz : 0;
8274+ phdr.p_filesz = maydump(vma, signr) ? sz : 0;
8275 phdr.p_memsz = sz;
8276 offset += phdr.p_filesz;
8277 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
8278@@ -1606,7 +1900,7 @@ static int elf_core_dump(long signr, str
8279 for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
8280 unsigned long addr;
8281
8282- if (!maydump(vma))
8283+ if (!maydump(vma, signr))
8284 continue;
8285
8286 for (addr = vma->vm_start;
8287@@ -1625,6 +1919,7 @@ static int elf_core_dump(long signr, str
8288 void *kaddr;
8289 flush_cache_page(vma, addr, page_to_pfn(page));
8290 kaddr = kmap(page);
8291+ gr_learn_resource(current, RLIMIT_CORE, size + PAGE_SIZE, 1);
8292 if ((size += PAGE_SIZE) > limit ||
8293 !dump_write(file, kaddr,
8294 PAGE_SIZE)) {
8295diff -urNp linux-2.6.17.7/fs/binfmt_flat.c linux-2.6.17.7/fs/binfmt_flat.c
8296--- linux-2.6.17.7/fs/binfmt_flat.c 2006-07-24 23:36:01.000000000 -0400
8297+++ linux-2.6.17.7/fs/binfmt_flat.c 2006-08-01 20:29:46.000000000 -0400
8298@@ -552,7 +552,9 @@ static int load_flat_file(struct linux_b
8299 realdatastart = (unsigned long) -ENOMEM;
8300 printk("Unable to allocate RAM for process data, errno %d\n",
8301 (int)-datapos);
8302+ down_write(&current->mm->mmap_sem);
8303 do_munmap(current->mm, textpos, text_len);
8304+ up_write(&current->mm->mmap_sem);
8305 ret = realdatastart;
8306 goto err;
8307 }
8308@@ -574,8 +576,10 @@ static int load_flat_file(struct linux_b
8309 }
8310 if (result >= (unsigned long)-4096) {
8311 printk("Unable to read data+bss, errno %d\n", (int)-result);
8312+ down_write(&current->mm->mmap_sem);
8313 do_munmap(current->mm, textpos, text_len);
8314 do_munmap(current->mm, realdatastart, data_len + extra);
8315+ up_write(&current->mm->mmap_sem);
8316 ret = result;
8317 goto err;
8318 }
8319@@ -639,8 +643,10 @@ static int load_flat_file(struct linux_b
8320 }
8321 if (result >= (unsigned long)-4096) {
8322 printk("Unable to read code+data+bss, errno %d\n",(int)-result);
8323+ down_write(&current->mm->mmap_sem);
8324 do_munmap(current->mm, textpos, text_len + data_len + extra +
8325 MAX_SHARED_LIBS * sizeof(unsigned long));
8326+ up_write(&current->mm->mmap_sem);
8327 ret = result;
8328 goto err;
8329 }
8330diff -urNp linux-2.6.17.7/fs/binfmt_misc.c linux-2.6.17.7/fs/binfmt_misc.c
8331--- linux-2.6.17.7/fs/binfmt_misc.c 2006-07-24 23:36:01.000000000 -0400
8332+++ linux-2.6.17.7/fs/binfmt_misc.c 2006-08-01 20:29:46.000000000 -0400
8333@@ -112,9 +112,11 @@ static int load_misc_binary(struct linux
8334 struct files_struct *files = NULL;
8335
8336 retval = -ENOEXEC;
8337- if (!enabled)
8338+ if (!enabled || bprm->misc)
8339 goto _ret;
8340
8341+ bprm->misc++;
8342+
8343 /* to keep locking time low, we copy the interpreter string */
8344 read_lock(&entries_lock);
8345 fmt = check_file(bprm);
8346diff -urNp linux-2.6.17.7/fs/buffer.c linux-2.6.17.7/fs/buffer.c
8347--- linux-2.6.17.7/fs/buffer.c 2006-07-24 23:36:01.000000000 -0400
8348+++ linux-2.6.17.7/fs/buffer.c 2006-08-01 20:29:46.000000000 -0400
8349@@ -42,6 +42,7 @@
8350 #include <linux/bitops.h>
8351 #include <linux/mpage.h>
8352 #include <linux/bit_spinlock.h>
8353+#include <linux/grsecurity.h>
8354
8355 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
8356 static void invalidate_bh_lrus(void);
8357@@ -2162,6 +2163,7 @@ static int __generic_cont_expand(struct
8358
8359 err = -EFBIG;
8360 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
8361+ gr_learn_resource(current, RLIMIT_FSIZE, (unsigned long) size, 1);
8362 if (limit != RLIM_INFINITY && size > (loff_t)limit) {
8363 send_sig(SIGXFSZ, current, 0);
8364 goto out;
8365diff -urNp linux-2.6.17.7/fs/compat.c linux-2.6.17.7/fs/compat.c
8366--- linux-2.6.17.7/fs/compat.c 2006-07-24 23:36:01.000000000 -0400
8367+++ linux-2.6.17.7/fs/compat.c 2006-08-01 20:29:46.000000000 -0400
8368@@ -46,6 +46,7 @@
8369 #include <linux/rwsem.h>
8370 #include <linux/acct.h>
8371 #include <linux/mm.h>
8372+#include <linux/grsecurity.h>
8373
8374 #include <net/sock.h> /* siocdevprivate_ioctl */
8375
8376@@ -1498,6 +1499,11 @@ int compat_do_execve(char * filename,
8377 struct file *file;
8378 int retval;
8379 int i;
8380+#ifdef CONFIG_GRKERNSEC
8381+ struct file *old_exec_file;
8382+ struct acl_subject_label *old_acl;
8383+ struct rlimit old_rlim[RLIM_NLIMITS];
8384+#endif
8385
8386 retval = -ENOMEM;
8387 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
8388@@ -1515,6 +1521,15 @@ int compat_do_execve(char * filename,
8389 bprm->file = file;
8390 bprm->filename = filename;
8391 bprm->interp = filename;
8392+
8393+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->user->processes), 1);
8394+ retval = -EAGAIN;
8395+ if (gr_handle_nproc())
8396+ goto out_file;
8397+ retval = -EACCES;
8398+ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt))
8399+ goto out_file;
8400+
8401 bprm->mm = mm_alloc();
8402 retval = -ENOMEM;
8403 if (!bprm->mm)
8404@@ -1553,10 +1568,39 @@ int compat_do_execve(char * filename,
8405 if (retval < 0)
8406 goto out;
8407
8408+ if (!gr_tpe_allow(file)) {
8409+ retval = -EACCES;
8410+ goto out;
8411+ }
8412+
8413+ if (gr_check_crash_exec(file)) {
8414+ retval = -EACCES;
8415+ goto out;
8416+ }
8417+
8418+ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
8419+
8420+ gr_handle_exec_args(bprm, (char __user * __user *)argv);
8421+
8422+#ifdef CONFIG_GRKERNSEC
8423+ old_acl = current->acl;
8424+ memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim));
8425+ old_exec_file = current->exec_file;
8426+ get_file(file);
8427+ current->exec_file = file;
8428+#endif
8429+
8430+ gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
8431+
8432 retval = search_binary_handler(bprm, regs);
8433 if (retval >= 0) {
8434 free_arg_pages(bprm);
8435
8436+#ifdef CONFIG_GRKERNSEC
8437+ if (old_exec_file)
8438+ fput(old_exec_file);
8439+#endif
8440+
8441 /* execve success */
8442 security_bprm_free(bprm);
8443 acct_update_integrals(current);
8444@@ -1564,6 +1608,13 @@ int compat_do_execve(char * filename,
8445 return retval;
8446 }
8447
8448+#ifdef CONFIG_GRKERNSEC
8449+ current->acl = old_acl;
8450+ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim));
8451+ fput(current->exec_file);
8452+ current->exec_file = old_exec_file;
8453+#endif
8454+
8455 out:
8456 /* Something went wrong, return the inode and free the argument pages*/
8457 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
8458diff -urNp linux-2.6.17.7/fs/dcache.c linux-2.6.17.7/fs/dcache.c
8459--- linux-2.6.17.7/fs/dcache.c 2006-07-24 23:36:01.000000000 -0400
8460+++ linux-2.6.17.7/fs/dcache.c 2006-08-01 20:29:46.000000000 -0400
8461@@ -1389,7 +1389,7 @@ already_unhashed:
8462 *
8463 * "buflen" should be positive. Caller holds the dcache_lock.
8464 */
8465-static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
8466+char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
8467 struct dentry *root, struct vfsmount *rootmnt,
8468 char *buffer, int buflen)
8469 {
8470diff -urNp linux-2.6.17.7/fs/exec.c linux-2.6.17.7/fs/exec.c
8471--- linux-2.6.17.7/fs/exec.c 2006-07-24 23:36:01.000000000 -0400
8472+++ linux-2.6.17.7/fs/exec.c 2006-08-01 20:29:46.000000000 -0400
8473@@ -49,6 +49,8 @@
f1a4f855 8474 #include <linux/cn_proc.h>
77fa6d7d 8475 #include <linux/vs_cvirt.h>
8476 #include <linux/vs_memory.h>
f1a4f855 8477+#include <linux/random.h>
8478+#include <linux/grsecurity.h>
8479
8480 #include <asm/uaccess.h>
8481 #include <asm/mmu_context.h>
8482@@ -67,6 +69,15 @@ EXPORT_SYMBOL(suid_dumpable);
8483 static struct linux_binfmt *formats;
8484 static DEFINE_RWLOCK(binfmt_lock);
8485
8486+#ifdef CONFIG_PAX_SOFTMODE
8487+unsigned int pax_softmode;
8488+#endif
8489+
8490+#ifdef CONFIG_PAX_HOOK_ACL_FLAGS
8491+void (*pax_set_initial_flags_func)(struct linux_binprm * bprm);
8492+EXPORT_SYMBOL(pax_set_initial_flags_func);
8493+#endif
8494+
8495 int register_binfmt(struct linux_binfmt * fmt)
8496 {
8497 struct linux_binfmt ** tmp = &formats;
8498@@ -312,6 +323,10 @@ void install_arg_page(struct vm_area_str
8499 if (unlikely(anon_vma_prepare(vma)))
8500 goto out;
8501
8502+#ifdef CONFIG_PAX_SEGMEXEC
8503+ if (page_count(page) == 1)
8504+#endif
8505+
8506 flush_dcache_page(page);
8507 pte = get_locked_pte(mm, address, &ptl);
8508 if (!pte)
8509@@ -321,9 +336,21 @@ void install_arg_page(struct vm_area_str
8510 goto out;
8511 }
8512 inc_mm_counter(mm, anon_rss);
8513+
8514+#ifdef CONFIG_PAX_SEGMEXEC
8515+ if (page_count(page) == 1)
8516+#endif
8517+
8518 lru_cache_add_active(page);
8519 set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte(
8520 page, vma->vm_page_prot))));
8521+
8522+#ifdef CONFIG_PAX_SEGMEXEC
8523+ if (page_count(page) != 1)
8524+ page_add_anon_rmap(page, vma, address);
8525+ else
8526+#endif
8527+
8528 page_add_new_anon_rmap(page, vma, address);
8529 pte_unmap_unlock(pte, ptl);
8530
8531@@ -346,6 +373,10 @@ int setup_arg_pages(struct linux_binprm
8532 int i, ret;
8533 long arg_size;
8534
8535+#ifdef CONFIG_PAX_SEGMEXEC
8536+ struct vm_area_struct *mpnt_m = NULL;
8537+#endif
8538+
8539 #ifdef CONFIG_STACK_GROWSUP
8540 /* Move the argument and environment strings to the bottom of the
8541 * stack space.
8542@@ -410,6 +441,18 @@ int setup_arg_pages(struct linux_binprm
8543
8544 memset(mpnt, 0, sizeof(*mpnt));
8545
8546+#ifdef CONFIG_PAX_SEGMEXEC
8547+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (VM_STACK_FLAGS & VM_MAYEXEC)) {
8548+ mpnt_m = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
8549+ if (!mpnt_m) {
8550+ kmem_cache_free(vm_area_cachep, mpnt);
8551+ return -ENOMEM;
8552+ }
8553+
8554+ memset(mpnt_m, 0, sizeof(*mpnt_m));
8555+ }
8556+#endif
8557+
8558 down_write(&mm->mmap_sem);
8559 {
8560 mpnt->vm_mm = mm;
68731fcf 8561@@ -430,14 +473,51 @@ int setup_arg_pages(struct linux_binprm
f1a4f855 8562 else
8563 mpnt->vm_flags = VM_STACK_FLAGS;
8564 mpnt->vm_flags |= mm->def_flags;
8565+
8566+#ifdef CONFIG_PAX_PAGEEXEC
8567+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC))
8568+ mpnt->vm_page_prot = protection_map[(mpnt->vm_flags | VM_EXEC) & 0x7];
8569+ else
8570+#endif
8571+
8572 mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
8573 if ((ret = insert_vm_struct(mm, mpnt))) {
8574 up_write(&mm->mmap_sem);
8575 kmem_cache_free(vm_area_cachep, mpnt);
8576+
8577+#ifdef CONFIG_PAX_SEGMEXEC
8578+ if (mpnt_m)
8579+ kmem_cache_free(vm_area_cachep, mpnt_m);
8580+#endif
8581+
8582 return ret;
8583 }
68731fcf 8584 vx_vmpages_sub(mm, mm->total_vm - vma_pages(mpnt));
8585 mm->stack_vm = mm->total_vm;
f1a4f855 8586+
8587+#ifdef CONFIG_PAX_SEGMEXEC
8588+ if (mpnt_m) {
8589+ *mpnt_m = *mpnt;
8590+ if (!(mpnt->vm_flags & VM_EXEC)) {
8591+ mpnt_m->vm_flags &= ~(VM_READ | VM_WRITE | VM_EXEC);
8592+ mpnt_m->vm_page_prot = PAGE_NONE;
8593+ }
8594+ mpnt_m->vm_start += SEGMEXEC_TASK_SIZE;
8595+ mpnt_m->vm_end += SEGMEXEC_TASK_SIZE;
8596+ if ((ret = insert_vm_struct(mm, mpnt_m))) {
8597+ up_write(&mm->mmap_sem);
8598+ kmem_cache_free(vm_area_cachep, mpnt_m);
8599+ return ret;
8600+ }
8601+ mpnt_m->vm_flags |= VM_MIRROR;
8602+ mpnt->vm_flags |= VM_MIRROR;
8603+ mpnt_m->vm_mirror = mpnt->vm_start - mpnt_m->vm_start;
8604+ mpnt->vm_mirror = mpnt_m->vm_start - mpnt->vm_start;
8605+ mpnt_m->vm_pgoff = mpnt->vm_pgoff;
8606+ mm->total_vm += vma_pages(mpnt_m);
8607+ }
8608+#endif
8609+
8610 }
8611
8612 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
8613@@ -444,6 +524,14 @@ int setup_arg_pages(struct linux_binprm
8614 if (page) {
8615 bprm->page[i] = NULL;
8616 install_arg_page(mpnt, page, stack_base);
8617+
8618+#ifdef CONFIG_PAX_SEGMEXEC
8619+ if (mpnt_m) {
8620+ page_cache_get(page);
8621+ install_arg_page(mpnt_m, page, stack_base + SEGMEXEC_TASK_SIZE);
8622+ }
8623+#endif
8624+
8625 }
8626 stack_base += PAGE_SIZE;
8627 }
8628@@ -1147,6 +1235,11 @@ int do_execve(char * filename,
8629 struct file *file;
8630 int retval;
8631 int i;
8632+#ifdef CONFIG_GRKERNSEC
8633+ struct file *old_exec_file;
8634+ struct acl_subject_label *old_acl;
8635+ struct rlimit old_rlim[RLIM_NLIMITS];
8636+#endif
8637
8638 retval = -ENOMEM;
8639 bprm = kzalloc(sizeof(*bprm), GFP_KERNEL);
8640@@ -1158,10 +1251,29 @@ int do_execve(char * filename,
8641 if (IS_ERR(file))
8642 goto out_kfree;
8643
8644+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->user->processes), 1);
8645+
8646+ if (gr_handle_nproc()) {
8647+ allow_write_access(file);
8648+ fput(file);
8649+ return -EAGAIN;
8650+ }
8651+
8652+ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) {
8653+ allow_write_access(file);
8654+ fput(file);
8655+ return -EACCES;
8656+ }
8657+
8658 sched_exec();
8659
8660 bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
8661
8662+#ifdef CONFIG_PAX_RANDUSTACK
8663+ if (randomize_va_space)
8664+ bprm->p -= (pax_get_random_long() & ~(sizeof(void *)-1)) & ~PAGE_MASK;
8665+#endif
8666+
8667 bprm->file = file;
8668 bprm->filename = filename;
8669 bprm->interp = filename;
8670@@ -1203,8 +1315,38 @@ int do_execve(char * filename,
8671 if (retval < 0)
8672 goto out;
8673
8674+ if (!gr_tpe_allow(file)) {
8675+ retval = -EACCES;
8676+ goto out;
8677+ }
8678+
8679+ if (gr_check_crash_exec(file)) {
8680+ retval = -EACCES;
8681+ goto out;
8682+ }
8683+
8684+ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
8685+
8686+ gr_handle_exec_args(bprm, argv);
8687+
8688+#ifdef CONFIG_GRKERNSEC
8689+ old_acl = current->acl;
8690+ memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim));
8691+ old_exec_file = current->exec_file;
8692+ get_file(file);
8693+ current->exec_file = file;
8694+#endif
8695+
8696+ retval = gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
8697+ if (retval < 0)
8698+ goto out_fail;
8699+
8700 retval = search_binary_handler(bprm,regs);
8701 if (retval >= 0) {
8702+#ifdef CONFIG_GRKERNSEC
8703+ if (old_exec_file)
8704+ fput(old_exec_file);
8705+#endif
8706 free_arg_pages(bprm);
8707
8708 /* execve success */
8709@@ -1214,6 +1356,14 @@ int do_execve(char * filename,
8710 return retval;
8711 }
8712
8713+out_fail:
8714+#ifdef CONFIG_GRKERNSEC
8715+ current->acl = old_acl;
8716+ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim));
8717+ fput(current->exec_file);
8718+ current->exec_file = old_exec_file;
8719+#endif
8720+
8721 out:
8722 /* Something went wrong, return the inode and free the argument pages*/
8723 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
8724@@ -1374,6 +1524,114 @@ static void format_corename(char *corena
8725 *out_ptr = 0;
8726 }
8727
8728+int pax_check_flags(unsigned long * flags)
8729+{
8730+ int retval = 0;
8731+
8732+#if !defined(__i386__) || !defined(CONFIG_PAX_SEGMEXEC)
8733+ if (*flags & MF_PAX_SEGMEXEC)
8734+ {
8735+ *flags &= ~MF_PAX_SEGMEXEC;
8736+ retval = -EINVAL;
8737+ }
8738+#endif
8739+
8740+ if ((*flags & MF_PAX_PAGEEXEC)
8741+
8742+#ifdef CONFIG_PAX_PAGEEXEC
8743+ && (*flags & MF_PAX_SEGMEXEC)
8744+#endif
8745+
8746+ )
8747+ {
8748+ *flags &= ~MF_PAX_PAGEEXEC;
8749+ retval = -EINVAL;
8750+ }
8751+
8752+ if ((*flags & MF_PAX_MPROTECT)
8753+
8754+#ifdef CONFIG_PAX_MPROTECT
8755+ && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
8756+#endif
8757+
8758+ )
8759+ {
8760+ *flags &= ~MF_PAX_MPROTECT;
8761+ retval = -EINVAL;
8762+ }
8763+
8764+ if ((*flags & MF_PAX_EMUTRAMP)
8765+
8766+#ifdef CONFIG_PAX_EMUTRAMP
8767+ && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
8768+#endif
8769+
8770+ )
8771+ {
8772+ *flags &= ~MF_PAX_EMUTRAMP;
8773+ retval = -EINVAL;
8774+ }
8775+
8776+ return retval;
8777+}
8778+
8779+EXPORT_SYMBOL(pax_check_flags);
8780+
8781+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
8782+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp)
8783+{
8784+ struct task_struct *tsk = current;
8785+ struct mm_struct *mm = current->mm;
8786+ char* buffer_exec = (char*)__get_free_page(GFP_ATOMIC);
8787+ char* buffer_fault = (char*)__get_free_page(GFP_ATOMIC);
8788+ char* path_exec=NULL;
8789+ char* path_fault=NULL;
8790+ unsigned long start=0UL, end=0UL, offset=0UL;
8791+
8792+ if (buffer_exec && buffer_fault) {
8793+ struct vm_area_struct* vma, * vma_exec=NULL, * vma_fault=NULL;
8794+
8795+ down_read(&mm->mmap_sem);
8796+ vma = mm->mmap;
8797+ while (vma && (!vma_exec || !vma_fault)) {
8798+ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
8799+ vma_exec = vma;
8800+ if (vma->vm_start <= (unsigned long)pc && (unsigned long)pc < vma->vm_end)
8801+ vma_fault = vma;
8802+ vma = vma->vm_next;
8803+ }
8804+ if (vma_exec) {
8805+ path_exec = d_path(vma_exec->vm_file->f_dentry, vma_exec->vm_file->f_vfsmnt, buffer_exec, PAGE_SIZE);
8806+ if (IS_ERR(path_exec))
8807+ path_exec = "<path too long>";
8808+ }
8809+ if (vma_fault) {
8810+ start = vma_fault->vm_start;
8811+ end = vma_fault->vm_end;
8812+ offset = vma_fault->vm_pgoff << PAGE_SHIFT;
8813+ if (vma_fault->vm_file) {
8814+ path_fault = d_path(vma_fault->vm_file->f_dentry, vma_fault->vm_file->f_vfsmnt, buffer_fault, PAGE_SIZE);
8815+ if (IS_ERR(path_fault))
8816+ path_fault = "<path too long>";
8817+ } else
8818+ path_fault = "<anonymous mapping>";
8819+ }
8820+ up_read(&mm->mmap_sem);
8821+ }
8822+ if (tsk->signal->curr_ip)
8823+ 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);
8824+ else
8825+ printk(KERN_ERR "PAX: execution attempt in: %s, %08lx-%08lx %08lx\n", path_fault, start, end, offset);
8826+ printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, "
8827+ "PC: %p, SP: %p\n", path_exec, tsk->comm, tsk->pid,
8828+ tsk->uid, tsk->euid, pc, sp);
8829+ free_page((unsigned long)buffer_exec);
8830+ free_page((unsigned long)buffer_fault);
8831+ pax_report_insns(pc, sp);
8832+ do_coredump(SIGKILL, SIGKILL, regs);
8833+}
8834+#endif
8835+
8836 static void zap_threads (struct mm_struct *mm)
8837 {
8838 struct task_struct *g, *p;
8839@@ -1491,6 +1749,10 @@ int do_coredump(long signr, int exit_cod
8840 */
8841 clear_thread_flag(TIF_SIGPENDING);
8842
8843+ if (signr == SIGKILL || signr == SIGILL)
8844+ gr_handle_brute_attach(current);
8845+
8846+ gr_learn_resource(current, RLIMIT_CORE, binfmt->min_coredump, 1);
8847 if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
8848 goto fail_unlock;
8849
8850diff -urNp linux-2.6.17.7/fs/fcntl.c linux-2.6.17.7/fs/fcntl.c
8851--- linux-2.6.17.7/fs/fcntl.c 2006-07-24 23:36:01.000000000 -0400
8852+++ linux-2.6.17.7/fs/fcntl.c 2006-08-01 20:29:46.000000000 -0400
8853@@ -18,6 +18,7 @@
f1a4f855 8854 #include <linux/signal.h>
8855 #include <linux/rcupdate.h>
77fa6d7d 8856 #include <linux/vs_limit.h>
f1a4f855 8857+#include <linux/grsecurity.h>
8858
8859 #include <asm/poll.h>
8860 #include <asm/siginfo.h>
8861@@ -63,6 +64,7 @@ static int locate_fd(struct files_struct
8862 struct fdtable *fdt;
8863
8864 error = -EINVAL;
8865+ gr_learn_resource(current, RLIMIT_NOFILE, orig_start, 0);
8866 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
8867 goto out;
8868
8869@@ -83,6 +85,7 @@ repeat:
8870 }
8871
8872 error = -EMFILE;
8873+ gr_learn_resource(current, RLIMIT_NOFILE, newfd, 0);
8874 if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
8875 goto out;
8876
8877@@ -141,6 +144,8 @@ asmlinkage long sys_dup2(unsigned int ol
8878 struct files_struct * files = current->files;
8879 struct fdtable *fdt;
8880
8881+ gr_learn_resource(current, RLIMIT_NOFILE, newfd, 0);
8882+
8883 spin_lock(&files->file_lock);
8884 if (!(file = fcheck(oldfd)))
8885 goto out_unlock;
8886@@ -427,7 +432,8 @@ static inline int sigio_perm(struct task
8887 return (((fown->euid == 0) ||
8888 (fown->euid == p->suid) || (fown->euid == p->uid) ||
8889 (fown->uid == p->suid) || (fown->uid == p->uid)) &&
8890- !security_file_send_sigiotask(p, fown, sig));
8891+ !security_file_send_sigiotask(p, fown, sig) &&
8892+ !gr_check_protected_task(p) && !gr_pid_is_chrooted(p));
8893 }
8894
8895 static void send_sigio_to_task(struct task_struct *p,
8896diff -urNp linux-2.6.17.7/fs/namei.c linux-2.6.17.7/fs/namei.c
8897--- linux-2.6.17.7/fs/namei.c 2006-07-24 23:36:01.000000000 -0400
8898+++ linux-2.6.17.7/fs/namei.c 2006-08-01 20:29:46.000000000 -0400
8899@@ -32,6 +32,7 @@
77fa6d7d 8900 #include <linux/vserver/inode.h>
8901 #include <linux/vs_tag.h>
8902 #include <linux/vserver/debug.h>
f1a4f855 8903+#include <linux/grsecurity.h>
8904 #include <asm/namei.h>
8905 #include <asm/uaccess.h>
8906
8907@@ -611,6 +612,13 @@ static inline int do_follow_link(struct
8908 err = security_inode_follow_link(path->dentry, nd);
8909 if (err)
8910 goto loop;
8911+
8912+ if (gr_handle_follow_link(path->dentry->d_parent->d_inode,
8913+ path->dentry->d_inode, path->dentry, nd->mnt)) {
8914+ err = -EACCES;
8915+ goto loop;
8916+ }
8917+
8918 current->link_count++;
8919 current->total_link_count++;
8920 nd->depth++;
8921@@ -954,11 +962,18 @@ return_reval:
8922 break;
8923 }
8924 return_base:
8925+ if (!gr_acl_handle_hidden_file(nd->dentry, nd->mnt)) {
8926+ path_release(nd);
8927+ return -ENOENT;
8928+ }
8929 return 0;
8930 out_dput:
8931 dput_path(&next, nd);
8932 break;
8933 }
8934+ if (!gr_acl_handle_hidden_file(nd->dentry, nd->mnt))
8935+ err = -ENOENT;
8936+
8937 path_release(nd);
8938 return_err:
8939 return err;
8940@@ -1601,6 +1616,17 @@ int open_namei(int dfd, const char *path
8941 nd, flag);
8942 if (error)
8943 return error;
8944+
8945+ if (gr_handle_rawio(nd->dentry->d_inode)) {
8946+ error = -EPERM;
8947+ goto exit;
8948+ }
8949+
8950+ if (!gr_acl_handle_open(nd->dentry, nd->mnt, flag)) {
8951+ error = -EACCES;
8952+ goto exit;
8953+ }
8954+
8955 goto ok;
8956 }
8957
8958@@ -1641,9 +1667,16 @@ do_last:
8959
8960 /* Negative dentry, just create the file */
8961 if (!path.dentry->d_inode) {
8962+ if (!gr_acl_handle_creat(path.dentry, nd->dentry, nd->mnt, flag, mode)) {
8963+ error = -EACCES;
8964+ mutex_unlock(&dir->d_inode->i_mutex);
8965+ goto exit_dput;
8966+ }
8967 if (!IS_POSIXACL(dir->d_inode))
8968 mode &= ~current->fs->umask;
8969 error = vfs_create(dir->d_inode, path.dentry, mode, nd);
8970+ if (!error)
8971+ gr_handle_create(path.dentry, nd->mnt);
8972 mutex_unlock(&dir->d_inode->i_mutex);
8973 dput(nd->dentry);
8974 nd->dentry = path.dentry;
8975@@ -1658,6 +1691,23 @@ do_last:
8976 /*
8977 * It already exists.
8978 */
8979+
8980+ if (gr_handle_rawio(path.dentry->d_inode)) {
8981+ mutex_unlock(&dir->d_inode->i_mutex);
8982+ error = -EPERM;
8983+ goto exit_dput;
8984+ }
8985+ if (!gr_acl_handle_open(path.dentry, nd->mnt, flag)) {
8986+ mutex_unlock(&dir->d_inode->i_mutex);
8987+ error = -EACCES;
8988+ goto exit_dput;
8989+ }
8990+ if (gr_handle_fifo(path.dentry, nd->mnt, dir, flag, acc_mode)) {
8991+ mutex_unlock(&dir->d_inode->i_mutex);
8992+ error = -EACCES;
8993+ goto exit_dput;
8994+ }
8995+
8996 mutex_unlock(&dir->d_inode->i_mutex);
8997
8998 error = -EEXIST;
8999@@ -1711,6 +1761,13 @@ do_link:
9000 error = security_inode_follow_link(path.dentry, nd);
9001 if (error)
9002 goto exit_dput;
9003+
9004+ if (gr_handle_follow_link(path.dentry->d_parent->d_inode, path.dentry->d_inode,
9005+ path.dentry, nd->mnt)) {
9006+ error = -EACCES;
9007+ goto exit_dput;
9008+ }
9009+
9010 error = __do_follow_link(&path, nd);
9011 if (error) {
9012 /* Does someone understand code flow here? Or it is only
9013@@ -1837,6 +1894,22 @@ asmlinkage long sys_mknodat(int dfd, con
9014 if (!IS_POSIXACL(nd.dentry->d_inode))
9015 mode &= ~current->fs->umask;
9016 if (!IS_ERR(dentry)) {
9017+ if (gr_handle_chroot_mknod(dentry, nd.mnt, mode)) {
9018+ error = -EPERM;
9019+ dput(dentry);
9020+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
9021+ path_release(&nd);
9022+ goto out;
9023+ }
9024+
9025+ if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) {
9026+ error = -EACCES;
9027+ dput(dentry);
9028+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
9029+ path_release(&nd);
9030+ goto out;
9031+ }
9032+
9033 switch (mode & S_IFMT) {
9034 case 0: case S_IFREG:
9035 error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
9036@@ -1854,6 +1927,10 @@ asmlinkage long sys_mknodat(int dfd, con
9037 default:
9038 error = -EINVAL;
9039 }
9040+
9041+ if (!error)
9042+ gr_handle_create(dentry, nd.mnt);
9043+
9044 dput(dentry);
9045 }
9046 mutex_unlock(&nd.dentry->d_inode->i_mutex);
68731fcf 9047@@ -1908,10 +1985,19 @@ asmlinkage long sys_mkdirat(int dfd, con
f1a4f855 9048 dentry = lookup_create(&nd, 1);
9049 error = PTR_ERR(dentry);
9050 if (!IS_ERR(dentry)) {
9051+ error = 0;
9052 if (!IS_POSIXACL(nd.dentry->d_inode))
9053 mode &= ~current->fs->umask;
68731fcf 9054- error = vfs_mkdir(nd.dentry->d_inode, dentry,
9055- mode, &nd);
f1a4f855 9056+
9057+ if (!gr_acl_handle_mkdir(dentry, nd.dentry, nd.mnt))
9058+ error = -EACCES;
9059+
9060+ if (!error)
68731fcf 9061+ error = vfs_mkdir(nd.dentry->d_inode, dentry,
9062+ mode, &nd);
f1a4f855 9063+ if (!error)
9064+ gr_handle_create(dentry, nd.mnt);
9065+
9066 dput(dentry);
9067 }
9068 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9069@@ -1994,6 +2081,8 @@ static long do_rmdir(int dfd, const char
9070 char * name;
9071 struct dentry *dentry;
9072 struct nameidata nd;
9073+ ino_t saved_ino = 0;
9074+ dev_t saved_dev = 0;
9075
9076 name = getname(pathname);
9077 if(IS_ERR(name))
9078@@ -2018,7 +2107,21 @@ static long do_rmdir(int dfd, const char
9079 dentry = lookup_hash(&nd);
9080 error = PTR_ERR(dentry);
9081 if (!IS_ERR(dentry)) {
68731fcf 9082- error = vfs_rmdir(nd.dentry->d_inode, dentry, &nd);
f1a4f855 9083+ error = 0;
9084+ if (dentry->d_inode) {
9085+ if (dentry->d_inode->i_nlink <= 1) {
9086+ saved_ino = dentry->d_inode->i_ino;
9087+ saved_dev = dentry->d_inode->i_sb->s_dev;
9088+ }
9089+
9090+ if (!gr_acl_handle_rmdir(dentry, nd.mnt))
9091+ error = -EACCES;
9092+ }
9093+
9094+ if (!error)
68731fcf 9095+ error = vfs_rmdir(nd.dentry->d_inode, dentry, &nd);
f1a4f855 9096+ if (!error && (saved_dev || saved_ino))
9097+ gr_handle_delete(saved_ino, saved_dev);
9098 dput(dentry);
9099 }
9100 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9101@@ -2077,6 +2180,8 @@ static long do_unlinkat(int dfd, const c
9102 struct dentry *dentry;
9103 struct nameidata nd;
9104 struct inode *inode = NULL;
9105+ ino_t saved_ino = 0;
9106+ dev_t saved_dev = 0;
9107
9108 name = getname(pathname);
9109 if(IS_ERR(name))
9110@@ -2092,13 +2197,26 @@ static long do_unlinkat(int dfd, const c
9111 dentry = lookup_hash(&nd);
9112 error = PTR_ERR(dentry);
9113 if (!IS_ERR(dentry)) {
9114+ error = 0;
9115 /* Why not before? Because we want correct error value */
9116 if (nd.last.name[nd.last.len])
9117 goto slashes;
9118 inode = dentry->d_inode;
9119- if (inode)
9120+ if (inode) {
9121+ if (inode->i_nlink <= 1) {
9122+ saved_ino = inode->i_ino;
9123+ saved_dev = inode->i_sb->s_dev;
9124+ }
9125+
9126+ if (!gr_acl_handle_unlink(dentry, nd.mnt))
9127+ error = -EACCES;
9128+
9129 atomic_inc(&inode->i_count);
68731fcf 9130- error = vfs_unlink(nd.dentry->d_inode, dentry, &nd);
f1a4f855 9131+ }
9132+ if (!error)
68731fcf 9133+ error = vfs_unlink(nd.dentry->d_inode, dentry, &nd);
f1a4f855 9134+ if (!error && (saved_ino || saved_dev))
9135+ gr_handle_delete(saved_ino, saved_dev);
9136 exit2:
9137 dput(dentry);
9138 }
68731fcf 9139@@ -2176,8 +2294,15 @@ asmlinkage long sys_symlinkat(const char
f1a4f855 9140 dentry = lookup_create(&nd, 0);
9141 error = PTR_ERR(dentry);
9142 if (!IS_ERR(dentry)) {
68731fcf 9143- error = vfs_symlink(nd.dentry->d_inode, dentry,
9144- from, S_IALLUGO, &nd);
f1a4f855 9145+ error = 0;
9146+ if (!gr_acl_handle_symlink(dentry, nd.dentry, nd.mnt, from))
9147+ error = -EACCES;
9148+
9149+ if (!error)
68731fcf 9150+ error = vfs_symlink(nd.dentry->d_inode, dentry,
9151+ from, S_IALLUGO, &nd);
f1a4f855 9152+ if (!error)
9153+ gr_handle_create(dentry, nd.mnt);
9154 dput(dentry);
9155 }
9156 mutex_unlock(&nd.dentry->d_inode->i_mutex);
68731fcf 9157@@ -2268,8 +2394,20 @@ asmlinkage long sys_linkat(int olddfd, c
f1a4f855 9158 new_dentry = lookup_create(&nd, 0);
9159 error = PTR_ERR(new_dentry);
9160 if (!IS_ERR(new_dentry)) {
68731fcf 9161- error = vfs_link(old_nd.dentry, nd.dentry->d_inode,
9162- new_dentry, &nd);
f1a4f855 9163+ error = 0;
9164+ if (gr_handle_hardlink(old_nd.dentry, old_nd.mnt,
9165+ old_nd.dentry->d_inode,
9166+ old_nd.dentry->d_inode->i_mode, to))
9167+ error = -EPERM;
9168+ if (!gr_acl_handle_link(new_dentry, nd.dentry, nd.mnt,
9169+ old_nd.dentry, old_nd.mnt, to))
9170+ error = -EACCES;
9171+ if (!error)
68731fcf 9172+ error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry,
9173+ &nd);
f1a4f855 9174+ if (!error)
9175+ gr_handle_create(new_dentry, nd.mnt);
9176+
9177 dput(new_dentry);
9178 }
9179 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9180@@ -2494,8 +2633,16 @@ static int do_rename(int olddfd, const c
9181 if (new_dentry == trap)
9182 goto exit5;
9183
9184- error = vfs_rename(old_dir->d_inode, old_dentry,
9185+ error = gr_acl_handle_rename(new_dentry, newnd.dentry, newnd.mnt,
9186+ old_dentry, old_dir->d_inode, oldnd.mnt,
9187+ newname);
9188+
9189+ if (!error)
9190+ error = vfs_rename(old_dir->d_inode, old_dentry,
9191 new_dir->d_inode, new_dentry);
9192+ if (!error)
9193+ gr_handle_rename(old_dir->d_inode, newnd.dentry->d_inode, old_dentry,
9194+ new_dentry, oldnd.mnt, new_dentry->d_inode ? 1 : 0);
9195 exit5:
9196 dput(new_dentry);
9197 exit4:
9198diff -urNp linux-2.6.17.7/fs/namespace.c linux-2.6.17.7/fs/namespace.c
9199--- linux-2.6.17.7/fs/namespace.c 2006-07-24 23:36:01.000000000 -0400
9200+++ linux-2.6.17.7/fs/namespace.c 2006-08-01 20:29:46.000000000 -0400
9201@@ -23,6 +23,8 @@
f1a4f855 9202 #include <linux/mount.h>
77fa6d7d 9203 #include <linux/vserver/namespace.h>
9204 #include <linux/vserver/tag.h>
f1a4f855 9205+#include <linux/sched.h>
9206+#include <linux/grsecurity.h>
9207 #include <asm/uaccess.h>
9208 #include <asm/unistd.h>
9209 #include "pnode.h"
9210@@ -600,6 +602,8 @@ static int do_umount(struct vfsmount *mn
9211 DQUOT_OFF(sb);
9212 retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
9213 unlock_kernel();
9214+
9215+ gr_log_remount(mnt->mnt_devname, retval);
9216 }
9217 up_write(&sb->s_umount);
9218 return retval;
9219@@ -620,6 +624,9 @@ static int do_umount(struct vfsmount *mn
9220 security_sb_umount_busy(mnt);
9221 up_write(&namespace_sem);
9222 release_mounts(&umount_list);
9223+
9224+ gr_log_unmount(mnt->mnt_devname, retval);
9225+
9226 return retval;
9227 }
9228
9229@@ -1346,6 +1353,11 @@ long do_mount(char *dev_name, char *dir_
9230 if (retval)
9231 goto dput_out;
9232
9233+ if (gr_handle_chroot_mount(nd.dentry, nd.mnt, dev_name)) {
9234+ retval = -EPERM;
9235+ goto dput_out;
9236+ }
9237+
9238 if (flags & MS_REMOUNT)
9239 retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
9240 data_page);
9241@@ -1360,6 +1372,9 @@ long do_mount(char *dev_name, char *dir_
9242 dev_name, data_page);
9243 dput_out:
9244 path_release(&nd);
9245+
9246+ gr_log_mount(dev_name, dir_name, retval);
9247+
9248 return retval;
9249 }
9250
9251@@ -1612,6 +1627,9 @@ asmlinkage long sys_pivot_root(const cha
9252 if (!capable(CAP_SYS_ADMIN))
9253 return -EPERM;
9254
9255+ if (gr_handle_chroot_pivot())
9256+ return -EPERM;
9257+
9258 lock_kernel();
9259
9260 error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
9261diff -urNp linux-2.6.17.7/fs/open.c linux-2.6.17.7/fs/open.c
9262--- linux-2.6.17.7/fs/open.c 2006-07-24 23:36:01.000000000 -0400
9263+++ linux-2.6.17.7/fs/open.c 2006-08-01 20:29:46.000000000 -0400
9264@@ -28,6 +28,7 @@
77fa6d7d 9265 #include <linux/vs_limit.h>
9266 #include <linux/vs_dlimit.h>
9267 #include <linux/vserver/tag.h>
f1a4f855 9268+#include <linux/grsecurity.h>
9269
9270 #include <asm/unistd.h>
9271
9272@@ -207,6 +208,9 @@ int do_truncate(struct dentry *dentry, l
9273 if (length < 0)
9274 return -EINVAL;
9275
9276+ if (filp && !gr_acl_handle_truncate(dentry, filp->f_vfsmnt))
9277+ return -EACCES;
9278+
9279 newattrs.ia_size = length;
9280 newattrs.ia_valid = ATTR_SIZE | time_attrs;
9281 if (filp) {
9282@@ -407,6 +411,12 @@ asmlinkage long sys_utime(char __user *
9283 (error = vfs_permission(&nd, MAY_WRITE)) != 0)
9284 goto dput_and_out;
9285 }
9286+
9287+ if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) {
9288+ error = -EACCES;
9289+ goto dput_and_out;
9290+ }
9291+
9292 mutex_lock(&inode->i_mutex);
9293 error = notify_change(nd.dentry, &newattrs);
9294 mutex_unlock(&inode->i_mutex);
9295@@ -460,6 +470,12 @@ long do_utimes(int dfd, char __user *fil
9296 (error = vfs_permission(&nd, MAY_WRITE)) != 0)
9297 goto dput_and_out;
9298 }
9299+
9300+ if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) {
9301+ error = -EACCES;
9302+ goto dput_and_out;
9303+ }
9304+
9305 mutex_lock(&inode->i_mutex);
9306 error = notify_change(nd.dentry, &newattrs);
9307 mutex_unlock(&inode->i_mutex);
9308@@ -526,6 +542,10 @@ asmlinkage long sys_faccessat(int dfd, c
9309 if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
9310 && !special_file(nd.dentry->d_inode->i_mode))
9311 res = -EROFS;
9312+
9313+ if (!res && !gr_acl_handle_access(nd.dentry, nd.mnt, mode))
9314+ res = -EACCES;
9315+
9316 path_release(&nd);
9317 }
9318
9319@@ -554,6 +574,8 @@ asmlinkage long sys_chdir(const char __u
9320 if (error)
9321 goto dput_and_out;
9322
9323+ gr_log_chdir(nd.dentry, nd.mnt);
9324+
9325 set_fs_pwd(current->fs, nd.mnt, nd.dentry);
9326
9327 dput_and_out:
9328@@ -584,6 +606,13 @@ asmlinkage long sys_fchdir(unsigned int
9329 goto out_putf;
9330
9331 error = file_permission(file, MAY_EXEC);
9332+
9333+ if (!error && !gr_chroot_fchdir(dentry, mnt))
9334+ error = -EPERM;
9335+
9336+ if (!error)
9337+ gr_log_chdir(dentry, mnt);
9338+
9339 if (!error)
9340 set_fs_pwd(current->fs, mnt, dentry);
9341 out_putf:
9342@@ -609,8 +638,16 @@ asmlinkage long sys_chroot(const char __
9343 if (!capable(CAP_SYS_CHROOT))
9344 goto dput_and_out;
9345
9346+ if (gr_handle_chroot_chroot(nd.dentry, nd.mnt))
9347+ goto dput_and_out;
9348+
9349 set_fs_root(current->fs, nd.mnt, nd.dentry);
9350 set_fs_altroot();
9351+
9352+ gr_handle_chroot_caps(current);
9353+
9354+ gr_handle_chroot_chdir(nd.dentry, nd.mnt);
9355+
9356 error = 0;
9357 dput_and_out:
9358 path_release(&nd);
9359@@ -641,9 +678,22 @@ asmlinkage long sys_fchmod(unsigned int
9360 err = -EPERM;
9361 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
9362 goto out_putf;
9363+
9364+ if (!gr_acl_handle_fchmod(dentry, file->f_vfsmnt, mode)) {
9365+ err = -EACCES;
9366+ goto out_putf;
9367+ }
9368+
9369 mutex_lock(&inode->i_mutex);
9370 if (mode == (mode_t) -1)
9371 mode = inode->i_mode;
9372+
9373+ if (gr_handle_chroot_chmod(dentry, file->f_vfsmnt, mode)) {
9374+ err = -EPERM;
9375+ mutex_unlock(&inode->i_mutex);
9376+ goto out_putf;
9377+ }
9378+
9379 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
9380 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
9381 err = notify_change(dentry, &newattrs);
9382@@ -676,9 +726,21 @@ asmlinkage long sys_fchmodat(int dfd, co
9383 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
9384 goto dput_and_out;
9385
9386+ if (!gr_acl_handle_chmod(nd.dentry, nd.mnt, mode)) {
9387+ error = -EACCES;
9388+ goto dput_and_out;
9389+ };
9390+
9391 mutex_lock(&inode->i_mutex);
9392 if (mode == (mode_t) -1)
9393 mode = inode->i_mode;
9394+
9395+ if (gr_handle_chroot_chmod(nd.dentry, nd.mnt, mode)) {
9396+ error = -EACCES;
9397+ mutex_unlock(&inode->i_mutex);
9398+ goto dput_and_out;
9399+ }
9400+
9401 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
9402 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
9403 error = notify_change(nd.dentry, &newattrs);
f1a4f855 9404@@ -712,6 +774,12 @@ static int chown_common(struct dentry *
9405 error = -EPERM;
9406 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
9407 goto out;
9408+
9409+ if (!gr_acl_handle_chown(dentry, mnt)) {
9410+ error = -EACCES;
9411+ goto out;
9412+ }
9413+
9414 newattrs.ia_valid = ATTR_CTIME;
9415 if (user != (uid_t) -1) {
9416 newattrs.ia_valid |= ATTR_UID;
f1a4f855 9417@@ -995,6 +1063,7 @@ repeat:
9418 * N.B. For clone tasks sharing a files structure, this test
9419 * will limit the total number of files that can be opened.
9420 */
9421+ gr_learn_resource(current, RLIMIT_NOFILE, fd, 0);
9422 if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
9423 goto out;
9424
9425diff -urNp linux-2.6.17.7/fs/pipe.c linux-2.6.17.7/fs/pipe.c
9426--- linux-2.6.17.7/fs/pipe.c 2006-07-24 23:36:01.000000000 -0400
9427+++ linux-2.6.17.7/fs/pipe.c 2006-08-01 20:29:46.000000000 -0400
9428@@ -842,7 +842,7 @@ void free_pipe_info(struct inode *inode)
9429 inode->i_pipe = NULL;
9430 }
9431
9432-static struct vfsmount *pipe_mnt __read_mostly;
9433+struct vfsmount *pipe_mnt __read_mostly;
9434 static int pipefs_delete_dentry(struct dentry *dentry)
9435 {
9436 return 1;
9437diff -urNp linux-2.6.17.7/fs/proc/array.c linux-2.6.17.7/fs/proc/array.c
9438--- linux-2.6.17.7/fs/proc/array.c 2006-07-24 23:36:01.000000000 -0400
9439+++ linux-2.6.17.7/fs/proc/array.c 2006-08-01 20:29:46.000000000 -0400
9440@@ -293,6 +293,21 @@ static inline char *task_cap(struct task
9441 cap_t(p->cap_effective));
9442 }
9443
9444+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
9445+static inline char *task_pax(struct task_struct *p, char *buffer)
9446+{
9447+ if (p->mm)
9448+ return buffer + sprintf(buffer, "PaX:\t%c%c%c%c%c\n",
9449+ p->mm->pax_flags & MF_PAX_PAGEEXEC ? 'P' : 'p',
9450+ p->mm->pax_flags & MF_PAX_EMUTRAMP ? 'E' : 'e',
9451+ p->mm->pax_flags & MF_PAX_MPROTECT ? 'M' : 'm',
9452+ p->mm->pax_flags & MF_PAX_RANDMMAP ? 'R' : 'r',
9453+ p->mm->pax_flags & MF_PAX_SEGMEXEC ? 'S' : 's');
9454+ else
9455+ return buffer + sprintf(buffer, "PaX:\t-----\n");
9456+}
9457+#endif
9458+
9459 int proc_pid_status(struct task_struct *task, char * buffer)
9460 {
9461 char * orig = buffer;
9462@@ -311,9 +326,20 @@ int proc_pid_status(struct task_struct *
9463 #if defined(CONFIG_S390)
9464 buffer = task_show_regs(task, buffer);
9465 #endif
9466+
9467+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
9468+ buffer = task_pax(task, buffer);
9469+#endif
9470+
9471 return buffer - orig;
9472 }
9473
9474+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
9475+#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
9476+ (_mm->pax_flags & MF_PAX_RANDMMAP || \
9477+ _mm->pax_flags & MF_PAX_SEGMEXEC))
9478+#endif
9479+
9480 static int do_task_stat(struct task_struct *task, char * buffer, int whole)
9481 {
9482 unsigned long vsize, eip, esp, wchan = ~0UL;
9483@@ -398,6 +424,19 @@ static int do_task_stat(struct task_stru
9484 stime = task->stime;
9485 }
9486
9487+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
9488+ if (PAX_RAND_FLAGS(mm)) {
9489+ eip = 0;
9490+ esp = 0;
9491+ wchan = 0;
9492+ }
9493+#endif
9494+#ifdef CONFIG_GRKERNSEC_HIDESYM
9495+ wchan = 0;
9496+ eip =0;
9497+ esp =0;
9498+#endif
9499+
9500 /* scale priority and nice values from timeslices to -20..20 */
9501 /* to make it look like a "normal" Unix priority/nice value */
9502 priority = task_prio(task);
9503@@ -437,9 +476,15 @@ static int do_task_stat(struct task_stru
9504 vsize,
9505 mm ? get_mm_rss(mm) : 0,
9506 rsslim,
9507+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
9508+ PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->start_code : 0),
9509+ PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->end_code : 0),
9510+ PAX_RAND_FLAGS(mm) ? 0 : (mm ? mm->start_stack : 0),
9511+#else
9512 mm ? mm->start_code : 0,
9513 mm ? mm->end_code : 0,
9514 mm ? mm->start_stack : 0,
9515+#endif
9516 esp,
9517 eip,
9518 /* The signal information here is obsolete.
9519@@ -485,3 +530,14 @@ int proc_pid_statm(struct task_struct *t
9520 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
9521 size, resident, shared, text, lib, data, 0);
9522 }
9523+
9524+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
9525+int proc_pid_ipaddr(struct task_struct *task, char * buffer)
9526+{
9527+ int len;
9528+
9529+ len = sprintf(buffer, "%u.%u.%u.%u\n", NIPQUAD(task->signal->curr_ip));
9530+ return len;
9531+}
9532+#endif
9533+
9534diff -urNp linux-2.6.17.7/fs/proc/base.c linux-2.6.17.7/fs/proc/base.c
9535--- linux-2.6.17.7/fs/proc/base.c 2006-07-24 23:36:01.000000000 -0400
9536+++ linux-2.6.17.7/fs/proc/base.c 2006-08-01 20:29:46.000000000 -0400
9537@@ -72,6 +72,7 @@
f1a4f855 9538 #include <linux/poll.h>
77fa6d7d 9539 #include <linux/vs_network.h>
9540 #include <linux/vs_pid.h>
f1a4f855 9541+#include <linux/grsecurity.h>
9542 #include "internal.h"
9543
9544 /*
9545@@ -125,6 +126,9 @@ enum pid_directory_inos {
9546 #ifdef CONFIG_AUDITSYSCALL
9547 PROC_TGID_LOGINUID,
9548 #endif
9549+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
9550+ PROC_TGID_IPADDR,
9551+#endif
9552 PROC_TGID_OOM_SCORE,
9553 PROC_TGID_OOM_ADJUST,
9554 PROC_TID_INO,
9555@@ -204,6 +208,9 @@ static struct pid_entry tgid_base_stuff[
9556 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
9557 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
9558 E(PROC_TGID_MOUNTSTATS, "mountstats", S_IFREG|S_IRUSR),
9559+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
9560+ E(PROC_TGID_IPADDR, "ipaddr", S_IFREG|S_IRUSR),
9561+#endif
9562 #ifdef CONFIG_MMU
9563 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
9564 #endif
9565@@ -410,7 +417,7 @@ static int proc_task_root_link(struct in
9566 (task->parent == current && \
9567 (task->ptrace & PT_PTRACED) && \
9568 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
9569- security_ptrace(current,task) == 0))
9570+ security_ptrace(current,task) == 0 && !gr_handle_proc_ptrace(task)))
9571
9572 static int proc_pid_environ(struct task_struct *task, char * buffer)
9573 {
9574@@ -591,9 +598,25 @@ static int proc_check_root(struct inode
9575
9576 static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
9577 {
9578+ int ret = -EACCES;
9579+ struct task_struct *task;
9580+
9581 if (generic_permission(inode, mask, NULL) != 0)
9582- return -EACCES;
9583- return proc_check_root(inode);
9584+ goto out;
9585+
9586+ ret = proc_check_root(inode);
9587+ if (ret)
9588+ goto out;
9589+
9590+ task = proc_task(inode);
9591+
9592+ if (!task)
9593+ goto out;
9594+
9595+ ret = gr_acl_handle_procpidmem(task);
9596+
9597+out:
9598+ return ret;
9599 }
9600
9601 static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd)
9602@@ -1372,6 +1395,9 @@ static struct inode *proc_pid_make_inode
f1a4f855 9603 }
77fa6d7d 9604 /* procfs is xid tagged */
9605 inode->i_tag = (tag_t)vx_task_xid(task);
f1a4f855 9606+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
9607+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
9608+#endif
9609 security_task_to_inode(task, inode);
9610
9611 out:
9612@@ -1400,7 +1426,9 @@ static int pid_revalidate(struct dentry
9613 if (pid_alive(task)) {
9614 if (proc_type(inode) == PROC_TGID_INO || proc_type(inode) == PROC_TID_INO || task_dumpable(task)) {
9615 inode->i_uid = task->euid;
9616+#ifndef CONFIG_GRKERNSEC_PROC_USERGROUP
9617 inode->i_gid = task->egid;
9618+#endif
9619 } else {
9620 inode->i_uid = 0;
9621 inode->i_gid = 0;
9622@@ -1730,6 +1758,12 @@ static struct dentry *proc_pident_lookup
9623 inode->i_fop = &proc_info_file_operations;
9624 ei->op.proc_read = proc_pid_status;
9625 break;
9626+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
9627+ case PROC_TGID_IPADDR:
9628+ inode->i_fop = &proc_info_file_operations;
9629+ ei->op.proc_read = proc_pid_ipaddr;
9630+ break;
9631+#endif
9632 case PROC_TID_STAT:
9633 inode->i_fop = &proc_info_file_operations;
9634 ei->op.proc_read = proc_tid_stat;
77fa6d7d 9635@@ -2140,11 +2173,34 @@ struct dentry *proc_pid_lookup(struct in
9636 if (!proc_pid_visible(task, tgid))
9637 goto out_drop_task;
f1a4f855 9638
9639+ if (gr_check_hidden_task(task)) {
9640+ put_task_struct(task);
9641+ goto out;
9642+ }
9643+
9644+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9645+ if (current->uid && (task->uid != current->uid)
9646+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
9647+ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)
9648+#endif
9649+ ) {
9650+ put_task_struct(task);
9651+ goto out;
9652+ }
9653+#endif
9654+
9655 inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
77fa6d7d 9656 if (!inode)
9657 goto out_drop_task;
f1a4f855 9658
f1a4f855 9659+#ifdef CONFIG_GRKERNSEC_PROC_USER
9660+ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR;
9661+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9662+ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP;
9663+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
9664+#else
9665 inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
9666+#endif
9667 inode->i_op = &proc_tgid_base_inode_operations;
9668 inode->i_fop = &proc_tgid_base_operations;
9669 inode->i_flags|=S_IMMUTABLE;
9670@@ -2137,6 +2195,9 @@ out:
9671 static int get_tgid_list(int index, unsigned long version, unsigned int *tgids)
9672 {
9673 struct task_struct *p;
9674+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9675+ struct task_struct *tmp = current;
9676+#endif
9677 int nr_tgids = 0;
9678
9679 index--;
9680@@ -2157,6 +2218,18 @@ static int get_tgid_list(int index, unsi
9681 int tgid = p->pid;
9682 if (!pid_alive(p))
9683 continue;
9684+ if (gr_pid_is_chrooted(p))
9685+ continue;
9686+ if (gr_check_hidden_task(p))
9687+ continue;
9688+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9689+ if (tmp->uid && (p->uid != tmp->uid)
9690+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
9691+ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)
9692+#endif
9693+ )
9694+ continue;
9695+#endif
9696 if (--index >= 0)
9697 continue;
9698 tgids[nr_tgids] = tgid;
9699diff -urNp linux-2.6.17.7/fs/proc/inode.c linux-2.6.17.7/fs/proc/inode.c
9700--- linux-2.6.17.7/fs/proc/inode.c 2006-07-24 23:36:01.000000000 -0400
9701+++ linux-2.6.17.7/fs/proc/inode.c 2006-08-01 20:29:46.000000000 -0400
9702@@ -169,7 +169,11 @@ struct inode *proc_get_inode(struct supe
9703 if (de->mode) {
9704 inode->i_mode = de->mode;
9705 inode->i_uid = de->uid;
9706+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
9707+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
9708+#else
9709 inode->i_gid = de->gid;
9710+#endif
9711 }
9712 if (de->size)
9713 inode->i_size = de->size;
9714diff -urNp linux-2.6.17.7/fs/proc/internal.h linux-2.6.17.7/fs/proc/internal.h
9715--- linux-2.6.17.7/fs/proc/internal.h 2006-07-24 23:36:01.000000000 -0400
9716+++ linux-2.6.17.7/fs/proc/internal.h 2006-08-01 20:29:46.000000000 -0400
9717@@ -36,6 +36,9 @@ extern int proc_tid_stat(struct task_str
9718 extern int proc_tgid_stat(struct task_struct *, char *);
9719 extern int proc_pid_status(struct task_struct *, char *);
9720 extern int proc_pid_statm(struct task_struct *, char *);
9721+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
9722+extern int proc_pid_ipaddr(struct task_struct*,char*);
9723+#endif
9724
9725 void free_proc_entry(struct proc_dir_entry *de);
9726
9727diff -urNp linux-2.6.17.7/fs/proc/proc_misc.c linux-2.6.17.7/fs/proc/proc_misc.c
9728--- linux-2.6.17.7/fs/proc/proc_misc.c 2006-07-24 23:36:01.000000000 -0400
9729+++ linux-2.6.17.7/fs/proc/proc_misc.c 2006-08-01 20:29:46.000000000 -0400
9730@@ -651,6 +651,8 @@ void create_seq_entry(char *name, mode_t
9731 void __init proc_misc_init(void)
9732 {
9733 struct proc_dir_entry *entry;
9734+ int gr_mode = 0;
9735+
9736 static struct {
9737 char *name;
9738 int (*read_proc)(char*,char**,off_t,int,int*,void*);
9739@@ -666,7 +668,9 @@ void __init proc_misc_init(void)
9740 {"stram", stram_read_proc},
9741 #endif
9742 {"filesystems", filesystems_read_proc},
9743+#ifndef CONFIG_GRKERNSEC_PROC_ADD
9744 {"cmdline", cmdline_read_proc},
9745+#endif
9746 {"locks", locks_read_proc},
9747 {"execdomains", execdomains_read_proc},
9748 {NULL,}
9749@@ -674,19 +678,36 @@ void __init proc_misc_init(void)
9750 for (p = simple_ones; p->name; p++)
9751 create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
9752
9753+#ifdef CONFIG_GRKERNSEC_PROC_USER
9754+ gr_mode = S_IRUSR;
9755+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9756+ gr_mode = S_IRUSR | S_IRGRP;
9757+#endif
9758+#ifdef CONFIG_GRKERNSEC_PROC_ADD
9759+ create_proc_read_entry("cmdline", gr_mode, NULL, &cmdline_read_proc, NULL);
9760+#endif
9761+
9762 proc_symlink("mounts", NULL, "self/mounts");
9763
9764 /* And now for trickier ones */
9765 entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
9766 if (entry)
9767 entry->proc_fops = &proc_kmsg_operations;
9768+#ifdef CONFIG_GRKERNSEC_PROC_ADD
9769+ create_seq_entry("devices", gr_mode, &proc_devinfo_operations);
9770+#else
9771 create_seq_entry("devices", 0, &proc_devinfo_operations);
9772+#endif
9773 create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
9774 create_seq_entry("partitions", 0, &proc_partitions_operations);
9775 create_seq_entry("stat", 0, &proc_stat_operations);
9776 create_seq_entry("interrupts", 0, &proc_interrupts_operations);
9777 #ifdef CONFIG_SLAB
9778+#ifdef CONFIG_GRKERNSEC_PROC_ADD
9779+ create_seq_entry("slabinfo",S_IWUSR|gr_mode,&proc_slabinfo_operations);
9780+#else
9781 create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
9782+#endif
9783 #ifdef CONFIG_DEBUG_SLAB_LEAK
9784 create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations);
9785 #endif
9786@@ -701,7 +722,7 @@ void __init proc_misc_init(void)
9787 #ifdef CONFIG_SCHEDSTATS
9788 create_seq_entry("schedstat", 0, &proc_schedstat_operations);
9789 #endif
9790-#ifdef CONFIG_PROC_KCORE
9791+#if defined(CONFIG_PROC_KCORE) && !defined(CONFIG_GRKERNSEC_PROC_ADD)
9792 proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
9793 if (proc_root_kcore) {
9794 proc_root_kcore->proc_fops = &proc_kcore_operations;
9795diff -urNp linux-2.6.17.7/fs/proc/root.c linux-2.6.17.7/fs/proc/root.c
9796--- linux-2.6.17.7/fs/proc/root.c 2006-07-24 23:36:01.000000000 -0400
9797+++ linux-2.6.17.7/fs/proc/root.c 2006-08-01 20:29:46.000000000 -0400
9798@@ -53,7 +53,13 @@ void __init proc_root_init(void)
9799 return;
9800 }
9801 proc_misc_init();
9802+#ifdef CONFIG_GRKERNSEC_PROC_USER
9803+ proc_net = proc_mkdir_mode("net", S_IRUSR | S_IXUSR, NULL);
9804+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9805+ proc_net = proc_mkdir_mode("net", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL);
9806+#else
9807 proc_net = proc_mkdir("net", NULL);
9808+#endif
9809 proc_net_stat = proc_mkdir("net/stat", NULL);
9810
9811 #ifdef CONFIG_SYSVIPC
9812@@ -77,7 +83,15 @@ void __init proc_root_init(void)
9813 #ifdef CONFIG_PROC_DEVICETREE
9814 proc_device_tree_init();
9815 #endif
9816+#ifdef CONFIG_GRKERNSEC_PROC_ADD
9817+#ifdef CONFIG_GRKERNSEC_PROC_USER
9818+ proc_bus = proc_mkdir_mode("bus", S_IRUSR | S_IXUSR, NULL);
9819+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
9820+ proc_bus = proc_mkdir_mode("bus", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL);
9821+#endif
9822+#else
9823 proc_bus = proc_mkdir("bus", NULL);
9824+#endif
77fa6d7d 9825 proc_vx_init();
f1a4f855 9826 }
9827
f1a4f855 9828diff -urNp linux-2.6.17.7/fs/proc/task_mmu.c linux-2.6.17.7/fs/proc/task_mmu.c
9829--- linux-2.6.17.7/fs/proc/task_mmu.c 2006-07-24 23:36:01.000000000 -0400
9830+++ linux-2.6.17.7/fs/proc/task_mmu.c 2006-08-01 20:29:46.000000000 -0400
9831@@ -43,15 +43,27 @@ char *task_mem(struct mm_struct *mm, cha
9832 "VmStk:\t%8lu kB\n"
9833 "VmExe:\t%8lu kB\n"
9834 "VmLib:\t%8lu kB\n"
9835- "VmPTE:\t%8lu kB\n",
9836- hiwater_vm << (PAGE_SHIFT-10),
9837+ "VmPTE:\t%8lu kB\n"
9838+
9839+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
9840+ "CsBase:\t%8lx\nCsLim:\t%8lx\n"
9841+#endif
9842+
9843+ ,hiwater_vm << (PAGE_SHIFT-10),
9844 (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
9845 mm->locked_vm << (PAGE_SHIFT-10),
9846 hiwater_rss << (PAGE_SHIFT-10),
9847 total_rss << (PAGE_SHIFT-10),
9848 data << (PAGE_SHIFT-10),
9849 mm->stack_vm << (PAGE_SHIFT-10), text, lib,
9850- (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
9851+ (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10
9852+
9853+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
9854+ , mm->context.user_cs_base, mm->context.user_cs_limit
9855+#endif
9856+
9857+ );
9858+
9859 return buffer;
9860 }
9861
9862@@ -118,6 +130,12 @@ struct mem_size_stats
9863 unsigned long private_dirty;
9864 };
9865
9866+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
9867+#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
9868+ (_mm->pax_flags & MF_PAX_RANDMMAP || \
9869+ _mm->pax_flags & MF_PAX_SEGMEXEC))
9870+#endif
9871+
9872 static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
9873 {
9874 struct task_struct *task = m->private;
9875@@ -136,13 +154,30 @@ static int show_map_internal(struct seq_
9876 }
9877
9878 seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
9879+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
9880+ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_start,
9881+ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_end,
9882+#else
9883 vma->vm_start,
9884 vma->vm_end,
9885+#endif
9886+
9887+#if 0
9888+ flags & VM_MAYREAD ? flags & VM_READ ? 'R' : '+' : flags & VM_READ ? 'r' : '-',
9889+ flags & VM_MAYWRITE ? flags & VM_WRITE ? 'W' : '+' : flags & VM_WRITE ? 'w' : '-',
9890+ flags & VM_MAYEXEC ? flags & VM_EXEC ? 'X' : '+' : flags & VM_EXEC ? 'x' : '-',
9891+#else
9892 flags & VM_READ ? 'r' : '-',
9893 flags & VM_WRITE ? 'w' : '-',
9894 flags & VM_EXEC ? 'x' : '-',
9895+#endif
9896+
9897 flags & VM_MAYSHARE ? 's' : 'p',
9898+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
9899+ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_pgoff << PAGE_SHIFT,
9900+#else
9901 vma->vm_pgoff << PAGE_SHIFT,
9902+#endif
9903 MAJOR(dev), MINOR(dev), ino, &len);
9904
9905 /*
9906@@ -154,13 +189,13 @@ static int show_map_internal(struct seq_
9907 seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
9908 } else {
9909 if (mm) {
9910- if (vma->vm_start <= mm->start_brk &&
9911- vma->vm_end >= mm->brk) {
9912+ if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
9913 pad_len_spaces(m, len);
9914 seq_puts(m, "[heap]");
9915 } else {
9916- if (vma->vm_start <= mm->start_stack &&
9917- vma->vm_end >= mm->start_stack) {
9918+ if ((vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP)) ||
9919+ (vma->vm_start <= mm->start_stack &&
9920+ vma->vm_end >= mm->start_stack)) {
9921
9922 pad_len_spaces(m, len);
9923 seq_puts(m, "[stack]");
9924@@ -173,7 +208,25 @@ static int show_map_internal(struct seq_
9925 }
9926 seq_putc(m, '\n');
9927
9928- if (mss)
9929+
9930+ if (mss) {
9931+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
9932+ if (PAX_RAND_FLAGS(mm))
9933+ seq_printf(m,
9934+ "Size: %8lu kB\n"
9935+ "Rss: %8lu kB\n"
9936+ "Shared_Clean: %8lu kB\n"
9937+ "Shared_Dirty: %8lu kB\n"
9938+ "Private_Clean: %8lu kB\n"
9939+ "Private_Dirty: %8lu kB\n",
9940+ 0UL,
9941+ 0UL,
9942+ 0UL,
9943+ 0UL,
9944+ 0UL,
9945+ 0UL);
9946+ else
9947+#endif
9948 seq_printf(m,
9949 "Size: %8lu kB\n"
9950 "Rss: %8lu kB\n"
9951@@ -187,6 +240,7 @@ static int show_map_internal(struct seq_
9952 mss->shared_dirty >> 10,
9953 mss->private_clean >> 10,
9954 mss->private_dirty >> 10);
9955+ }
9956
9957 if (m->count < m->size) /* vma is copied successfully */
9958 m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
9959diff -urNp linux-2.6.17.7/fs/readdir.c linux-2.6.17.7/fs/readdir.c
9960--- linux-2.6.17.7/fs/readdir.c 2006-07-24 23:36:01.000000000 -0400
9961+++ linux-2.6.17.7/fs/readdir.c 2006-08-01 20:29:46.000000000 -0400
9962@@ -16,6 +16,8 @@
9963 #include <linux/security.h>
9964 #include <linux/syscalls.h>
9965 #include <linux/unistd.h>
9966+#include <linux/namei.h>
9967+#include <linux/grsecurity.h>
9968
9969 #include <asm/uaccess.h>
9970
9971@@ -65,6 +67,7 @@ struct old_linux_dirent {
9972
9973 struct readdir_callback {
9974 struct old_linux_dirent __user * dirent;
9975+ struct file * file;
9976 int result;
9977 };
9978
9979@@ -76,6 +79,10 @@ static int fillonedir(void * __buf, cons
9980
9981 if (buf->result)
9982 return -EINVAL;
9983+
9984+ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
9985+ return 0;
9986+
9987 buf->result++;
9988 dirent = buf->dirent;
9989 if (!access_ok(VERIFY_WRITE, dirent,
9990@@ -107,6 +114,7 @@ asmlinkage long old_readdir(unsigned int
9991
9992 buf.result = 0;
9993 buf.dirent = dirent;
9994+ buf.file = file;
9995
9996 error = vfs_readdir(file, fillonedir, &buf);
9997 if (error >= 0)
9998@@ -133,6 +141,7 @@ struct linux_dirent {
9999 struct getdents_callback {
10000 struct linux_dirent __user * current_dir;
10001 struct linux_dirent __user * previous;
10002+ struct file * file;
10003 int count;
10004 int error;
10005 };
10006@@ -147,6 +156,10 @@ static int filldir(void * __buf, const c
10007 buf->error = -EINVAL; /* only used if we fail.. */
10008 if (reclen > buf->count)
10009 return -EINVAL;
10010+
10011+ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
10012+ return 0;
10013+
10014 dirent = buf->previous;
10015 if (dirent) {
10016 if (__put_user(offset, &dirent->d_off))
10017@@ -191,6 +204,7 @@ asmlinkage long sys_getdents(unsigned in
10018
10019 buf.current_dir = dirent;
10020 buf.previous = NULL;
10021+ buf.file = file;
10022 buf.count = count;
10023 buf.error = 0;
10024
10025@@ -217,6 +231,7 @@ out:
10026 struct getdents_callback64 {
10027 struct linux_dirent64 __user * current_dir;
10028 struct linux_dirent64 __user * previous;
10029+ struct file * file;
10030 int count;
10031 int error;
10032 };
10033@@ -231,6 +246,10 @@ static int filldir64(void * __buf, const
10034 buf->error = -EINVAL; /* only used if we fail.. */
10035 if (reclen > buf->count)
10036 return -EINVAL;
10037+
10038+ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
10039+ return 0;
10040+
10041 dirent = buf->previous;
10042 if (dirent) {
10043 if (__put_user(offset, &dirent->d_off))
10044@@ -277,6 +296,7 @@ asmlinkage long sys_getdents64(unsigned
10045
10046 buf.current_dir = dirent;
10047 buf.previous = NULL;
10048+ buf.file = file;
10049 buf.count = count;
10050 buf.error = 0;
10051
10052diff -urNp linux-2.6.17.7/fs/xfs/linux-2.6/xfs_file.c linux-2.6.17.7/fs/xfs/linux-2.6/xfs_file.c
10053--- linux-2.6.17.7/fs/xfs/linux-2.6/xfs_file.c 2006-07-24 23:36:01.000000000 -0400
10054+++ linux-2.6.17.7/fs/xfs/linux-2.6/xfs_file.c 2006-08-01 20:29:46.000000000 -0400
10055@@ -461,6 +461,11 @@ xfs_file_mmap(
10056 vattr_t vattr;
10057 int error;
10058
10059+#ifdef CONFIG_PAX_PAGEEXEC
10060+ if (vma->vm_mm->pax_flags & MF_PAX_PAGEEXEC)
10061+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
10062+#endif
10063+
10064 vma->vm_ops = &xfs_file_vm_ops;
10065
10066 #ifdef CONFIG_XFS_DMAPI
10067diff -urNp linux-2.6.17.7/grsecurity/Kconfig linux-2.6.17.7/grsecurity/Kconfig
10068--- linux-2.6.17.7/grsecurity/Kconfig 1969-12-31 19:00:00.000000000 -0500
10069+++ linux-2.6.17.7/grsecurity/Kconfig 2006-08-01 20:29:47.000000000 -0400
10070@@ -0,0 +1,890 @@
10071+#
10072+# grecurity configuration
10073+#
10074+
10075+menu "Grsecurity"
10076+
10077+config GRKERNSEC
10078+ bool "Grsecurity"
10079+ select CRYPTO
10080+ select CRYPTO_SHA256
10081+ help
10082+ If you say Y here, you will be able to configure many features
10083+ that will enhance the security of your system. It is highly
10084+ recommended that you say Y here and read through the help
10085+ for each option so that you fully understand the features and
10086+ can evaluate their usefulness for your machine.
10087+
10088+choice
10089+ prompt "Security Level"
10090+ depends GRKERNSEC
10091+ default GRKERNSEC_CUSTOM
10092+
10093+config GRKERNSEC_LOW
10094+ bool "Low"
10095+ select GRKERNSEC_LINK
10096+ select GRKERNSEC_FIFO
10097+ select GRKERNSEC_RANDPID
10098+ select GRKERNSEC_EXECVE
10099+ select GRKERNSEC_RANDNET
10100+ select GRKERNSEC_DMESG
10101+ select GRKERNSEC_CHROOT_CHDIR
10102+ select GRKERNSEC_MODSTOP if (MODULES)
10103+
10104+ help
10105+ If you choose this option, several of the grsecurity options will
10106+ be enabled that will give you greater protection against a number
10107+ of attacks, while assuring that none of your software will have any
10108+ conflicts with the additional security measures. If you run a lot
10109+ of unusual software, or you are having problems with the higher
10110+ security levels, you should say Y here. With this option, the
10111+ following features are enabled:
10112+
10113+ - Linking restrictions
10114+ - FIFO restrictions
10115+ - Randomized PIDs
10116+ - Enforcing RLIMIT_NPROC on execve
10117+ - Restricted dmesg
10118+ - Enforced chdir("/") on chroot
10119+ - Runtime module disabling
10120+
10121+config GRKERNSEC_MEDIUM
10122+ bool "Medium"
10123+ select PAX
10124+ select PAX_EI_PAX
10125+ select PAX_PT_PAX_FLAGS
10126+ select PAX_HAVE_ACL_FLAGS
10127+ select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR)
10128+ select GRKERNSEC_CHROOT_SYSCTL
10129+ select GRKERNSEC_LINK
10130+ select GRKERNSEC_FIFO
10131+ select GRKERNSEC_RANDPID
10132+ select GRKERNSEC_EXECVE
10133+ select GRKERNSEC_DMESG
10134+ select GRKERNSEC_RANDNET
10135+ select GRKERNSEC_FORKFAIL
10136+ select GRKERNSEC_TIME
10137+ select GRKERNSEC_SIGNAL
10138+ select GRKERNSEC_CHROOT
10139+ select GRKERNSEC_CHROOT_UNIX
10140+ select GRKERNSEC_CHROOT_MOUNT
10141+ select GRKERNSEC_CHROOT_PIVOT
10142+ select GRKERNSEC_CHROOT_DOUBLE
10143+ select GRKERNSEC_CHROOT_CHDIR
10144+ select GRKERNSEC_CHROOT_MKNOD
10145+ select GRKERNSEC_PROC
10146+ select GRKERNSEC_PROC_USERGROUP
10147+ select GRKERNSEC_MODSTOP if (MODULES)
10148+ select PAX_RANDUSTACK
10149+ select PAX_ASLR
10150+ select PAX_RANDMMAP
10151+ select PAX_NOVSYSCALL if (X86 && !X86_64)
10152+
10153+ help
10154+ If you say Y here, several features in addition to those included
10155+ in the low additional security level will be enabled. These
10156+ features provide even more security to your system, though in rare
10157+ cases they may be incompatible with very old or poorly written
10158+ software. If you enable this option, make sure that your auth
10159+ service (identd) is running as gid 1001. With this option,
10160+ the following features (in addition to those provided in the
10161+ low additional security level) will be enabled:
10162+
10163+ - Randomized TCP source ports
10164+ - Failed fork logging
10165+ - Time change logging
10166+ - Signal logging
10167+ - Deny mounts in chroot
10168+ - Deny double chrooting
10169+ - Deny sysctl writes in chroot
10170+ - Deny mknod in chroot
10171+ - Deny access to abstract AF_UNIX sockets out of chroot
10172+ - Deny pivot_root in chroot
10173+ - Denied writes of /dev/kmem, /dev/mem, and /dev/port
10174+ - /proc restrictions with special GID set to 10 (usually wheel)
10175+ - Address Space Layout Randomization (ASLR)
10176+
10177+config GRKERNSEC_HIGH
10178+ bool "High"
10179+ select GRKERNSEC_LINK
10180+ select GRKERNSEC_FIFO
10181+ select GRKERNSEC_RANDPID
10182+ select GRKERNSEC_EXECVE
10183+ select GRKERNSEC_DMESG
10184+ select GRKERNSEC_FORKFAIL
10185+ select GRKERNSEC_TIME
10186+ select GRKERNSEC_SIGNAL
10187+ select GRKERNSEC_CHROOT_SHMAT
10188+ select GRKERNSEC_CHROOT_UNIX
10189+ select GRKERNSEC_CHROOT_MOUNT
10190+ select GRKERNSEC_CHROOT_FCHDIR
10191+ select GRKERNSEC_CHROOT_PIVOT
10192+ select GRKERNSEC_CHROOT_DOUBLE
10193+ select GRKERNSEC_CHROOT_CHDIR
10194+ select GRKERNSEC_CHROOT_MKNOD
10195+ select GRKERNSEC_CHROOT_CAPS
10196+ select GRKERNSEC_CHROOT_SYSCTL
10197+ select GRKERNSEC_CHROOT_FINDTASK
10198+ select GRKERNSEC_PROC
10199+ select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR)
10200+ select GRKERNSEC_HIDESYM
10201+ select GRKERNSEC_BRUTE
10202+ select GRKERNSEC_SHM if (SYSVIPC)
10203+ select GRKERNSEC_PROC_USERGROUP
10204+ select GRKERNSEC_KMEM
10205+ select GRKERNSEC_RESLOG
10206+ select GRKERNSEC_RANDNET
10207+ select GRKERNSEC_PROC_ADD
10208+ select GRKERNSEC_CHROOT_CHMOD
10209+ select GRKERNSEC_CHROOT_NICE
10210+ select GRKERNSEC_AUDIT_MOUNT
10211+ select GRKERNSEC_MODSTOP if (MODULES)
10212+ select PAX
10213+ select PAX_RANDUSTACK
10214+ select PAX_ASLR
10215+ select PAX_RANDMMAP
10216+ select PAX_NOEXEC
10217+ select PAX_MPROTECT
10218+ select PAX_EI_PAX
10219+ select PAX_PT_PAX_FLAGS
10220+ select PAX_HAVE_ACL_FLAGS
10221+ select PAX_KERNEXEC if (!X86_64 && !MODULES && !HOTPLUG_PCI_COMPAQ_NVRAM && !PCI_BIOS)
10222+ select PAX_RANDKSTACK if (X86_TSC && !X86_64)
10223+ select PAX_SEGMEXEC if (X86 && !X86_64)
10224+ select PAX_PAGEEXEC if (!X86)
10225+ select PAX_EMUPLT if (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64)
10226+ select PAX_DLRESOLVE if (SPARC32 || SPARC64)
10227+ select PAX_SYSCALL if (PPC32)
10228+ select PAX_EMUTRAMP if (PARISC)
10229+ select PAX_EMUSIGRT if (PARISC)
10230+ select PAX_NOVSYSCALL if (X86 && !X86_64)
10231+ select PAX_ETEXECRELOCS if (ALPHA || IA64 || PARISC)
10232+ help
10233+ If you say Y here, many of the features of grsecurity will be
10234+ enabled, which will protect you against many kinds of attacks
10235+ against your system. The heightened security comes at a cost
10236+ of an increased chance of incompatibilities with rare software
10237+ on your machine. Since this security level enables PaX, you should
10238+ view <http://pax.grsecurity.net> and read about the PaX
10239+ project. While you are there, download chpax and run it on
10240+ binaries that cause problems with PaX. Also remember that
10241+ since the /proc restrictions are enabled, you must run your
10242+ identd as gid 1001. This security level enables the following
10243+ features in addition to those listed in the low and medium
10244+ security levels:
10245+
10246+ - Additional /proc restrictions
10247+ - Chmod restrictions in chroot
10248+ - No signals, ptrace, or viewing of processes outside of chroot
10249+ - Capability restrictions in chroot
10250+ - Deny fchdir out of chroot
10251+ - Priority restrictions in chroot
10252+ - Segmentation-based implementation of PaX
10253+ - Mprotect restrictions
10254+ - Removal of addresses from /proc/<pid>/[smaps|maps|stat]
10255+ - Kernel stack randomization
10256+ - Mount/unmount/remount logging
10257+ - Kernel symbol hiding
10258+ - Destroy unused shared memory
10259+ - Prevention of memory exhaustion-based exploits
10260+config GRKERNSEC_CUSTOM
10261+ bool "Custom"
10262+ help
10263+ If you say Y here, you will be able to configure every grsecurity
10264+ option, which allows you to enable many more features that aren't
10265+ covered in the basic security levels. These additional features
10266+ include TPE, socket restrictions, and the sysctl system for
10267+ grsecurity. It is advised that you read through the help for
10268+ each option to determine its usefulness in your situation.
10269+
10270+endchoice
10271+
10272+menu "Address Space Protection"
10273+depends on GRKERNSEC
10274+
10275+config GRKERNSEC_KMEM
10276+ bool "Deny writing to /dev/kmem, /dev/mem, and /dev/port"
10277+ help
10278+ If you say Y here, /dev/kmem and /dev/mem won't be allowed to
10279+ be written to via mmap or otherwise to modify the running kernel.
10280+ /dev/port will also not be allowed to be opened. If you have module
10281+ support disabled, enabling this will close up four ways that are
10282+ currently used to insert malicious code into the running kernel.
10283+ Even with all these features enabled, we still highly recommend that
10284+ you use the RBAC system, as it is still possible for an attacker to
10285+ modify the running kernel through privileged I/O granted by ioperm/iopl.
10286+ If you are not using XFree86, you may be able to stop this additional
10287+ case by enabling the 'Disable privileged I/O' option. Though nothing
10288+ legitimately writes to /dev/kmem, XFree86 does need to write to /dev/mem,
10289+ but only to video memory, which is the only writing we allow in this
10290+ case. If /dev/kmem or /dev/mem are mmaped without PROT_WRITE, they will
10291+ not be allowed to mprotect it with PROT_WRITE later.
10292+ It is highly recommended that you say Y here if you meet all the
10293+ conditions above.
10294+
10295+config GRKERNSEC_IO
10296+ bool "Disable privileged I/O"
10297+ depends on X86
10298+ select RTC
10299+ help
10300+ If you say Y here, all ioperm and iopl calls will return an error.
10301+ Ioperm and iopl can be used to modify the running kernel.
10302+ Unfortunately, some programs need this access to operate properly,
10303+ the most notable of which are XFree86 and hwclock. hwclock can be
10304+ remedied by having RTC support in the kernel, so CONFIG_RTC is
10305+ enabled if this option is enabled, to ensure that hwclock operates
10306+ correctly. XFree86 still will not operate correctly with this option
10307+ enabled, so DO NOT CHOOSE Y IF YOU USE XFree86. If you use XFree86
10308+ and you still want to protect your kernel against modification,
10309+ use the RBAC system.
10310+
10311+config GRKERNSEC_PROC_MEMMAP
10312+ bool "Remove addresses from /proc/<pid>/[smaps|maps|stat]"
10313+ depends on PAX_NOEXEC || PAX_ASLR
10314+ help
10315+ If you say Y here, the /proc/<pid>/maps and /proc/<pid>/stat files will
10316+ give no information about the addresses of its mappings if
10317+ PaX features that rely on random addresses are enabled on the task.
10318+ If you use PaX it is greatly recommended that you say Y here as it
10319+ closes up a hole that makes the full ASLR useless for suid
10320+ binaries.
10321+
10322+config GRKERNSEC_BRUTE
10323+ bool "Deter exploit bruteforcing"
10324+ help
10325+ If you say Y here, attempts to bruteforce exploits against forking
10326+ daemons such as apache or sshd will be deterred. When a child of a
10327+ forking daemon is killed by PaX or crashes due to an illegal
10328+ instruction, the parent process will be delayed 30 seconds upon every
10329+ subsequent fork until the administrator is able to assess the
10330+ situation and restart the daemon. It is recommended that you also
10331+ enable signal logging in the auditing section so that logs are
10332+ generated when a process performs an illegal instruction.
10333+
10334+config GRKERNSEC_MODSTOP
10335+ bool "Runtime module disabling"
10336+ depends on MODULES
10337+ help
10338+ If you say Y here, you will be able to disable the ability to (un)load
10339+ modules at runtime. This feature is useful if you need the ability
10340+ to load kernel modules at boot time, but do not want to allow an
10341+ attacker to load a rootkit kernel module into the system, or to remove
10342+ a loaded kernel module important to system functioning. You should
10343+ enable the /dev/mem protection feature as well, since rootkits can be
10344+ inserted into the kernel via other methods than kernel modules. Since
10345+ an untrusted module could still be loaded by modifying init scripts and
10346+ rebooting the system, it is also recommended that you enable the RBAC
10347+ system. If you enable this option, a sysctl option with name
10348+ "disable_modules" will be created. Setting this option to "1" disables
10349+ module loading. After this option is set, no further writes to it are
10350+ allowed until the system is rebooted.
10351+
10352+config GRKERNSEC_HIDESYM
10353+ bool "Hide kernel symbols"
10354+ help
10355+ If you say Y here, getting information on loaded modules, and
10356+ displaying all kernel symbols through a syscall will be restricted
10357+ to users with CAP_SYS_MODULE. This option is only effective
10358+ provided the following conditions are met:
10359+ 1) The kernel using grsecurity is not precompiled by some distribution
10360+ 2) You are using the RBAC system and hiding other files such as your
10361+ kernel image and System.map
10362+ 3) You have the additional /proc restrictions enabled, which removes
10363+ /proc/kcore
10364+ If the above conditions are met, this option will aid to provide a
10365+ useful protection against local and remote kernel exploitation of
10366+ overflows and arbitrary read/write vulnerabilities.
10367+
10368+endmenu
10369+menu "Role Based Access Control Options"
10370+depends on GRKERNSEC
10371+
10372+config GRKERNSEC_ACL_HIDEKERN
10373+ bool "Hide kernel processes"
10374+ help
10375+ If you say Y here, all kernel threads will be hidden to all
10376+ processes but those whose subject has the "view hidden processes"
10377+ flag.
10378+
10379+config GRKERNSEC_ACL_MAXTRIES
10380+ int "Maximum tries before password lockout"
10381+ default 3
10382+ help
10383+ This option enforces the maximum number of times a user can attempt
10384+ to authorize themselves with the grsecurity RBAC system before being
10385+ denied the ability to attempt authorization again for a specified time.
10386+ The lower the number, the harder it will be to brute-force a password.
10387+
10388+config GRKERNSEC_ACL_TIMEOUT
10389+ int "Time to wait after max password tries, in seconds"
10390+ default 30
10391+ help
10392+ This option specifies the time the user must wait after attempting to
10393+ authorize to the RBAC system with the maximum number of invalid
10394+ passwords. The higher the number, the harder it will be to brute-force
10395+ a password.
10396+
10397+endmenu
10398+menu "Filesystem Protections"
10399+depends on GRKERNSEC
10400+
10401+config GRKERNSEC_PROC
10402+ bool "Proc restrictions"
10403+ help
10404+ If you say Y here, the permissions of the /proc filesystem
10405+ will be altered to enhance system security and privacy. You MUST
10406+ choose either a user only restriction or a user and group restriction.
10407+ Depending upon the option you choose, you can either restrict users to
10408+ see only the processes they themselves run, or choose a group that can
10409+ view all processes and files normally restricted to root if you choose
10410+ the "restrict to user only" option. NOTE: If you're running identd as
10411+ a non-root user, you will have to run it as the group you specify here.
10412+
10413+config GRKERNSEC_PROC_USER
10414+ bool "Restrict /proc to user only"
10415+ depends on GRKERNSEC_PROC
10416+ help
10417+ If you say Y here, non-root users will only be able to view their own
10418+ processes, and restricts them from viewing network-related information,
10419+ and viewing kernel symbol and module information.
10420+
10421+config GRKERNSEC_PROC_USERGROUP
10422+ bool "Allow special group"
10423+ depends on GRKERNSEC_PROC && !GRKERNSEC_PROC_USER
10424+ help
10425+ If you say Y here, you will be able to select a group that will be
10426+ able to view all processes, network-related information, and
10427+ kernel and symbol information. This option is useful if you want
10428+ to run identd as a non-root user.
10429+
10430+config GRKERNSEC_PROC_GID
10431+ int "GID for special group"
10432+ depends on GRKERNSEC_PROC_USERGROUP
10433+ default 1001
10434+
10435+config GRKERNSEC_PROC_ADD
10436+ bool "Additional restrictions"
10437+ depends on GRKERNSEC_PROC_USER || GRKERNSEC_PROC_USERGROUP
10438+ help
10439+ If you say Y here, additional restrictions will be placed on
10440+ /proc that keep normal users from viewing device information and
10441+ slabinfo information that could be useful for exploits.
10442+
10443+config GRKERNSEC_LINK
10444+ bool "Linking restrictions"
10445+ help
10446+ If you say Y here, /tmp race exploits will be prevented, since users
10447+ will no longer be able to follow symlinks owned by other users in
10448+ world-writable +t directories (i.e. /tmp), unless the owner of the
10449+ symlink is the owner of the directory. users will also not be
10450+ able to hardlink to files they do not own. If the sysctl option is
10451+ enabled, a sysctl option with name "linking_restrictions" is created.
10452+
10453+config GRKERNSEC_FIFO
10454+ bool "FIFO restrictions"
10455+ help
10456+ If you say Y here, users will not be able to write to FIFOs they don't
10457+ own in world-writable +t directories (i.e. /tmp), unless the owner of
10458+ the FIFO is the same owner of the directory it's held in. If the sysctl
10459+ option is enabled, a sysctl option with name "fifo_restrictions" is
10460+ created.
10461+
10462+config GRKERNSEC_CHROOT
10463+ bool "Chroot jail restrictions"
10464+ help
10465+ If you say Y here, you will be able to choose several options that will
10466+ make breaking out of a chrooted jail much more difficult. If you
10467+ encounter no software incompatibilities with the following options, it
10468+ is recommended that you enable each one.
10469+
10470+config GRKERNSEC_CHROOT_MOUNT
10471+ bool "Deny mounts"
10472+ depends on GRKERNSEC_CHROOT
10473+ help
10474+ If you say Y here, processes inside a chroot will not be able to
10475+ mount or remount filesystems. If the sysctl option is enabled, a
10476+ sysctl option with name "chroot_deny_mount" is created.
10477+
10478+config GRKERNSEC_CHROOT_DOUBLE
10479+ bool "Deny double-chroots"
10480+ depends on GRKERNSEC_CHROOT
10481+ help
10482+ If you say Y here, processes inside a chroot will not be able to chroot
10483+ again outside the chroot. This is a widely used method of breaking
10484+ out of a chroot jail and should not be allowed. If the sysctl
10485+ option is enabled, a sysctl option with name
10486+ "chroot_deny_chroot" is created.
10487+
10488+config GRKERNSEC_CHROOT_PIVOT
10489+ bool "Deny pivot_root in chroot"
10490+ depends on GRKERNSEC_CHROOT
10491+ help
10492+ If you say Y here, processes inside a chroot will not be able to use
10493+ a function called pivot_root() that was introduced in Linux 2.3.41. It
10494+ works similar to chroot in that it changes the root filesystem. This
10495+ function could be misused in a chrooted process to attempt to break out
10496+ of the chroot, and therefore should not be allowed. If the sysctl
10497+ option is enabled, a sysctl option with name "chroot_deny_pivot" is
10498+ created.
10499+
10500+config GRKERNSEC_CHROOT_CHDIR
10501+ bool "Enforce chdir(\"/\") on all chroots"
10502+ depends on GRKERNSEC_CHROOT
10503+ help
10504+ If you say Y here, the current working directory of all newly-chrooted
10505+ applications will be set to the the root directory of the chroot.
10506+ The man page on chroot(2) states:
10507+ Note that this call does not change the current working
10508+ directory, so that `.' can be outside the tree rooted at
10509+ `/'. In particular, the super-user can escape from a
10510+ `chroot jail' by doing `mkdir foo; chroot foo; cd ..'.
10511+
10512+ It is recommended that you say Y here, since it's not known to break
10513+ any software. If the sysctl option is enabled, a sysctl option with
10514+ name "chroot_enforce_chdir" is created.
10515+
10516+config GRKERNSEC_CHROOT_CHMOD
10517+ bool "Deny (f)chmod +s"
10518+ depends on GRKERNSEC_CHROOT
10519+ help
10520+ If you say Y here, processes inside a chroot will not be able to chmod
10521+ or fchmod files to make them have suid or sgid bits. This protects
10522+ against another published method of breaking a chroot. If the sysctl
10523+ option is enabled, a sysctl option with name "chroot_deny_chmod" is
10524+ created.
10525+
10526+config GRKERNSEC_CHROOT_FCHDIR
10527+ bool "Deny fchdir out of chroot"
10528+ depends on GRKERNSEC_CHROOT
10529+ help
10530+ If you say Y here, a well-known method of breaking chroots by fchdir'ing
10531+ to a file descriptor of the chrooting process that points to a directory
10532+ outside the filesystem will be stopped. If the sysctl option
10533+ is enabled, a sysctl option with name "chroot_deny_fchdir" is created.
10534+
10535+config GRKERNSEC_CHROOT_MKNOD
10536+ bool "Deny mknod"
10537+ depends on GRKERNSEC_CHROOT
10538+ help
10539+ If you say Y here, processes inside a chroot will not be allowed to
10540+ mknod. The problem with using mknod inside a chroot is that it
10541+ would allow an attacker to create a device entry that is the same
10542+ as one on the physical root of your system, which could range from
10543+ anything from the console device to a device for your harddrive (which
10544+ they could then use to wipe the drive or steal data). It is recommended
10545+ that you say Y here, unless you run into software incompatibilities.
10546+ If the sysctl option is enabled, a sysctl option with name
10547+ "chroot_deny_mknod" is created.
10548+
10549+config GRKERNSEC_CHROOT_SHMAT
10550+ bool "Deny shmat() out of chroot"
10551+ depends on GRKERNSEC_CHROOT
10552+ help
10553+ If you say Y here, processes inside a chroot will not be able to attach
10554+ to shared memory segments that were created outside of the chroot jail.
10555+ It is recommended that you say Y here. If the sysctl option is enabled,
10556+ a sysctl option with name "chroot_deny_shmat" is created.
10557+
10558+config GRKERNSEC_CHROOT_UNIX
10559+ bool "Deny access to abstract AF_UNIX sockets out of chroot"
10560+ depends on GRKERNSEC_CHROOT
10561+ help
10562+ If you say Y here, processes inside a chroot will not be able to
10563+ connect to abstract (meaning not belonging to a filesystem) Unix
10564+ domain sockets that were bound outside of a chroot. It is recommended
10565+ that you say Y here. If the sysctl option is enabled, a sysctl option
10566+ with name "chroot_deny_unix" is created.
10567+
10568+config GRKERNSEC_CHROOT_FINDTASK
10569+ bool "Protect outside processes"
10570+ depends on GRKERNSEC_CHROOT
10571+ help
10572+ If you say Y here, processes inside a chroot will not be able to
10573+ kill, send signals with fcntl, ptrace, capget, setpgid, getpgid,
10574+ getsid, or view any process outside of the chroot. If the sysctl
10575+ option is enabled, a sysctl option with name "chroot_findtask" is
10576+ created.
10577+
10578+config GRKERNSEC_CHROOT_NICE
10579+ bool "Restrict priority changes"
10580+ depends on GRKERNSEC_CHROOT
10581+ help
10582+ If you say Y here, processes inside a chroot will not be able to raise
10583+ the priority of processes in the chroot, or alter the priority of
10584+ processes outside the chroot. This provides more security than simply
10585+ removing CAP_SYS_NICE from the process' capability set. If the
10586+ sysctl option is enabled, a sysctl option with name "chroot_restrict_nice"
10587+ is created.
10588+
10589+config GRKERNSEC_CHROOT_SYSCTL
10590+ bool "Deny sysctl writes"
10591+ depends on GRKERNSEC_CHROOT
10592+ help
10593+ If you say Y here, an attacker in a chroot will not be able to
10594+ write to sysctl entries, either by sysctl(2) or through a /proc
10595+ interface. It is strongly recommended that you say Y here. If the
10596+ sysctl option is enabled, a sysctl option with name
10597+ "chroot_deny_sysctl" is created.
10598+
10599+config GRKERNSEC_CHROOT_CAPS
10600+ bool "Capability restrictions"
10601+ depends on GRKERNSEC_CHROOT
10602+ help
10603+ If you say Y here, the capabilities on all root processes within a
10604+ chroot jail will be lowered to stop module insertion, raw i/o,
10605+ system and net admin tasks, rebooting the system, modifying immutable
10606+ files, modifying IPC owned by another, and changing the system time.
10607+ This is left an option because it can break some apps. Disable this
10608+ if your chrooted apps are having problems performing those kinds of
10609+ tasks. If the sysctl option is enabled, a sysctl option with
10610+ name "chroot_caps" is created.
10611+
10612+endmenu
10613+menu "Kernel Auditing"
10614+depends on GRKERNSEC
10615+
10616+config GRKERNSEC_AUDIT_GROUP
10617+ bool "Single group for auditing"
10618+ help
10619+ If you say Y here, the exec, chdir, (un)mount, and ipc logging features
10620+ will only operate on a group you specify. This option is recommended
10621+ if you only want to watch certain users instead of having a large
10622+ amount of logs from the entire system. If the sysctl option is enabled,
10623+ a sysctl option with name "audit_group" is created.
10624+
10625+config GRKERNSEC_AUDIT_GID
10626+ int "GID for auditing"
10627+ depends on GRKERNSEC_AUDIT_GROUP
10628+ default 1007
10629+
10630+config GRKERNSEC_EXECLOG
10631+ bool "Exec logging"
10632+ help
10633+ If you say Y here, all execve() calls will be logged (since the
10634+ other exec*() calls are frontends to execve(), all execution
10635+ will be logged). Useful for shell-servers that like to keep track
10636+ of their users. If the sysctl option is enabled, a sysctl option with
10637+ name "exec_logging" is created.
10638+ WARNING: This option when enabled will produce a LOT of logs, especially
10639+ on an active system.
10640+
10641+config GRKERNSEC_RESLOG
10642+ bool "Resource logging"
10643+ help
10644+ If you say Y here, all attempts to overstep resource limits will
10645+ be logged with the resource name, the requested size, and the current
10646+ limit. It is highly recommended that you say Y here. If the sysctl
10647+ option is enabled, a sysctl option with name "resource_logging" is
10648+ created. If the RBAC system is enabled, the sysctl value is ignored.
10649+
10650+config GRKERNSEC_CHROOT_EXECLOG
10651+ bool "Log execs within chroot"
10652+ help
10653+ If you say Y here, all executions inside a chroot jail will be logged
10654+ to syslog. This can cause a large amount of logs if certain
10655+ applications (eg. djb's daemontools) are installed on the system, and
10656+ is therefore left as an option. If the sysctl option is enabled, a
10657+ sysctl option with name "chroot_execlog" is created.
10658+
10659+config GRKERNSEC_AUDIT_CHDIR
10660+ bool "Chdir logging"
10661+ help
10662+ If you say Y here, all chdir() calls will be logged. If the sysctl
10663+ option is enabled, a sysctl option with name "audit_chdir" is created.
10664+
10665+config GRKERNSEC_AUDIT_MOUNT
10666+ bool "(Un)Mount logging"
10667+ help
10668+ If you say Y here, all mounts and unmounts will be logged. If the
10669+ sysctl option is enabled, a sysctl option with name "audit_mount" is
10670+ created.
10671+
10672+config GRKERNSEC_AUDIT_IPC
10673+ bool "IPC logging"
10674+ help
10675+ If you say Y here, creation and removal of message queues, semaphores,
10676+ and shared memory will be logged. If the sysctl option is enabled, a
10677+ sysctl option with name "audit_ipc" is created.
10678+
10679+config GRKERNSEC_SIGNAL
10680+ bool "Signal logging"
10681+ help
10682+ If you say Y here, certain important signals will be logged, such as
10683+ SIGSEGV, which will as a result inform you of when a error in a program
10684+ occurred, which in some cases could mean a possible exploit attempt.
10685+ If the sysctl option is enabled, a sysctl option with name
10686+ "signal_logging" is created.
10687+
10688+config GRKERNSEC_FORKFAIL
10689+ bool "Fork failure logging"
10690+ help
10691+ If you say Y here, all failed fork() attempts will be logged.
10692+ This could suggest a fork bomb, or someone attempting to overstep
10693+ their process limit. If the sysctl option is enabled, a sysctl option
10694+ with name "forkfail_logging" is created.
10695+
10696+config GRKERNSEC_TIME
10697+ bool "Time change logging"
10698+ help
10699+ If you say Y here, any changes of the system clock will be logged.
10700+ If the sysctl option is enabled, a sysctl option with name
10701+ "timechange_logging" is created.
10702+
10703+config GRKERNSEC_PROC_IPADDR
10704+ bool "/proc/<pid>/ipaddr support"
10705+ help
10706+ If you say Y here, a new entry will be added to each /proc/<pid>
10707+ directory that contains the IP address of the person using the task.
10708+ The IP is carried across local TCP and AF_UNIX stream sockets.
10709+ This information can be useful for IDS/IPSes to perform remote response
10710+ to a local attack. The entry is readable by only the owner of the
10711+ process (and root if he has CAP_DAC_OVERRIDE, which can be removed via
10712+ the RBAC system), and thus does not create privacy concerns.
10713+
10714+config GRKERNSEC_AUDIT_TEXTREL
10715+ bool 'ELF text relocations logging (READ HELP)'
10716+ depends on PAX_MPROTECT
10717+ help
10718+ If you say Y here, text relocations will be logged with the filename
10719+ of the offending library or binary. The purpose of the feature is
10720+ to help Linux distribution developers get rid of libraries and
10721+ binaries that need text relocations which hinder the future progress
10722+ of PaX. Only Linux distribution developers should say Y here, and
10723+ never on a production machine, as this option creates an information
10724+ leak that could aid an attacker in defeating the randomization of
10725+ a single memory region. If the sysctl option is enabled, a sysctl
10726+ option with name "audit_textrel" is created.
10727+
10728+endmenu
10729+
10730+menu "Executable Protections"
10731+depends on GRKERNSEC
10732+
10733+config GRKERNSEC_EXECVE
10734+ bool "Enforce RLIMIT_NPROC on execs"
10735+ help
10736+ If you say Y here, users with a resource limit on processes will
10737+ have the value checked during execve() calls. The current system
10738+ only checks the system limit during fork() calls. If the sysctl option
10739+ is enabled, a sysctl option with name "execve_limiting" is created.
10740+
10741+config GRKERNSEC_SHM
10742+ bool "Destroy unused shared memory"
10743+ depends on SYSVIPC
10744+ help
10745+ If you say Y here, shared memory will be destroyed when no one is
10746+ attached to it. Otherwise, resources involved with the shared
10747+ memory can be used up and not be associated with any process (as the
10748+ shared memory still exists, and the creating process has exited). If
10749+ the sysctl option is enabled, a sysctl option with name
10750+ "destroy_unused_shm" is created.
10751+
10752+config GRKERNSEC_DMESG
10753+ bool "Dmesg(8) restriction"
10754+ help
10755+ If you say Y here, non-root users will not be able to use dmesg(8)
10756+ to view up to the last 4kb of messages in the kernel's log buffer.
10757+ If the sysctl option is enabled, a sysctl option with name "dmesg" is
10758+ created.
10759+
10760+config GRKERNSEC_RANDPID
10761+ bool "Randomized PIDs"
10762+ help
10763+ If you say Y here, all PIDs created on the system will be
10764+ pseudo-randomly generated. This is extremely effective along
10765+ with the /proc restrictions to disallow an attacker from guessing
10766+ pids of daemons, etc. PIDs are also used in some cases as part
10767+ of a naming system for temporary files, so this option would keep
10768+ those filenames from being predicted as well. We also use code
10769+ to make sure that PID numbers aren't reused too soon. If the sysctl
10770+ option is enabled, a sysctl option with name "rand_pids" is created.
10771+
10772+config GRKERNSEC_TPE
10773+ bool "Trusted Path Execution (TPE)"
10774+ help
10775+ If you say Y here, you will be able to choose a gid to add to the
10776+ supplementary groups of users you want to mark as "untrusted."
10777+ These users will not be able to execute any files that are not in
10778+ root-owned directories writable only by root. If the sysctl option
10779+ is enabled, a sysctl option with name "tpe" is created.
10780+
10781+config GRKERNSEC_TPE_ALL
10782+ bool "Partially restrict non-root users"
10783+ depends on GRKERNSEC_TPE
10784+ help
10785+ If you say Y here, All non-root users other than the ones in the
10786+ group specified in the main TPE option will only be allowed to
10787+ execute files in directories they own that are not group or
10788+ world-writable, or in directories owned by root and writable only by
10789+ root. If the sysctl option is enabled, a sysctl option with name
10790+ "tpe_restrict_all" is created.
10791+
10792+config GRKERNSEC_TPE_INVERT
10793+ bool "Invert GID option"
10794+ depends on GRKERNSEC_TPE
10795+ help
10796+ If you say Y here, the group you specify in the TPE configuration will
10797+ decide what group TPE restrictions will be *disabled* for. This
10798+ option is useful if you want TPE restrictions to be applied to most
10799+ users on the system.
10800+
10801+config GRKERNSEC_TPE_GID
10802+ int "GID for untrusted users"
10803+ depends on GRKERNSEC_TPE && !GRKERNSEC_TPE_INVERT
10804+ default 1005
10805+ help
10806+ If you have selected the "Invert GID option" above, setting this
10807+ GID determines what group TPE restrictions will be *disabled* for.
10808+ If you have not selected the "Invert GID option" above, setting this
10809+ GID determines what group TPE restrictions will be *enabled* for.
10810+ If the sysctl option is enabled, a sysctl option with name "tpe_gid"
10811+ is created.
10812+
10813+config GRKERNSEC_TPE_GID
10814+ int "GID for trusted users"
10815+ depends on GRKERNSEC_TPE && GRKERNSEC_TPE_INVERT
10816+ default 1005
10817+ help
10818+ If you have selected the "Invert GID option" above, setting this
10819+ GID determines what group TPE restrictions will be *disabled* for.
10820+ If you have not selected the "Invert GID option" above, setting this
10821+ GID determines what group TPE restrictions will be *enabled* for.
10822+ If the sysctl option is enabled, a sysctl option with name "tpe_gid"
10823+ is created.
10824+
10825+endmenu
10826+menu "Network Protections"
10827+depends on GRKERNSEC
10828+
10829+config GRKERNSEC_RANDNET
10830+ bool "Larger entropy pools"
10831+ help
10832+ If you say Y here, the entropy pools used for many features of Linux
10833+ and grsecurity will be doubled in size. Since several grsecurity
10834+ features use additional randomness, it is recommended that you say Y
10835+ here. Saying Y here has a similar effect as modifying
10836+ /proc/sys/kernel/random/poolsize.
10837+
10838+config GRKERNSEC_SOCKET
10839+ bool "Socket restrictions"
10840+ help
10841+ If you say Y here, you will be able to choose from several options.
10842+ If you assign a GID on your system and add it to the supplementary
10843+ groups of users you want to restrict socket access to, this patch
10844+ will perform up to three things, based on the option(s) you choose.
10845+
10846+config GRKERNSEC_SOCKET_ALL
10847+ bool "Deny any sockets to group"
10848+ depends on GRKERNSEC_SOCKET
10849+ help
10850+ If you say Y here, you will be able to choose a GID of whose users will
10851+ be unable to connect to other hosts from your machine or run server
10852+ applications from your machine. If the sysctl option is enabled, a
10853+ sysctl option with name "socket_all" is created.
10854+
10855+config GRKERNSEC_SOCKET_ALL_GID
10856+ int "GID to deny all sockets for"
10857+ depends on GRKERNSEC_SOCKET_ALL
10858+ default 1004
10859+ help
10860+ Here you can choose the GID to disable socket access for. Remember to
10861+ add the users you want socket access disabled for to the GID
10862+ specified here. If the sysctl option is enabled, a sysctl option
10863+ with name "socket_all_gid" is created.
10864+
10865+config GRKERNSEC_SOCKET_CLIENT
10866+ bool "Deny client sockets to group"
10867+ depends on GRKERNSEC_SOCKET
10868+ help
10869+ If you say Y here, you will be able to choose a GID of whose users will
10870+ be unable to connect to other hosts from your machine, but will be
10871+ able to run servers. If this option is enabled, all users in the group
10872+ you specify will have to use passive mode when initiating ftp transfers
10873+ from the shell on your machine. If the sysctl option is enabled, a
10874+ sysctl option with name "socket_client" is created.
10875+
10876+config GRKERNSEC_SOCKET_CLIENT_GID
10877+ int "GID to deny client sockets for"
10878+ depends on GRKERNSEC_SOCKET_CLIENT
10879+ default 1003
10880+ help
10881+ Here you can choose the GID to disable client socket access for.
10882+ Remember to add the users you want client socket access disabled for to
10883+ the GID specified here. If the sysctl option is enabled, a sysctl
10884+ option with name "socket_client_gid" is created.
10885+
10886+config GRKERNSEC_SOCKET_SERVER
10887+ bool "Deny server sockets to group"
10888+ depends on GRKERNSEC_SOCKET
10889+ help
10890+ If you say Y here, you will be able to choose a GID of whose users will
10891+ be unable to run server applications from your machine. If the sysctl
10892+ option is enabled, a sysctl option with name "socket_server" is created.
10893+
10894+config GRKERNSEC_SOCKET_SERVER_GID
10895+ int "GID to deny server sockets for"
10896+ depends on GRKERNSEC_SOCKET_SERVER
10897+ default 1002
10898+ help
10899+ Here you can choose the GID to disable server socket access for.
10900+ Remember to add the users you want server socket access disabled for to
10901+ the GID specified here. If the sysctl option is enabled, a sysctl
10902+ option with name "socket_server_gid" is created.
10903+
10904+endmenu
10905+menu "Sysctl support"
10906+depends on GRKERNSEC && SYSCTL
10907+
10908+config GRKERNSEC_SYSCTL
10909+ bool "Sysctl support"
10910+ help
10911+ If you say Y here, you will be able to change the options that
10912+ grsecurity runs with at bootup, without having to recompile your
10913+ kernel. You can echo values to files in /proc/sys/kernel/grsecurity
10914+ to enable (1) or disable (0) various features. All the sysctl entries
10915+ are mutable until the "grsec_lock" entry is set to a non-zero value.
10916+ All features enabled in the kernel configuration are disabled at boot
10917+ if you do not say Y to the "Turn on features by default" option.
10918+ All options should be set at startup, and the grsec_lock entry should
10919+ be set to a non-zero value after all the options are set.
10920+ *THIS IS EXTREMELY IMPORTANT*
10921+
10922+config GRKERNSEC_SYSCTL_ON
10923+ bool "Turn on features by default"
10924+ depends on GRKERNSEC_SYSCTL
10925+ help
10926+ If you say Y here, instead of having all features enabled in the
10927+ kernel configuration disabled at boot time, the features will be
10928+ enabled at boot time. It is recommended you say Y here unless
10929+ there is some reason you would want all sysctl-tunable features to
10930+ be disabled by default. As mentioned elsewhere, it is important
10931+ to enable the grsec_lock entry once you have finished modifying
10932+ the sysctl entries.
10933+
10934+endmenu
10935+menu "Logging Options"
10936+depends on GRKERNSEC
10937+
10938+config GRKERNSEC_FLOODTIME
10939+ int "Seconds in between log messages (minimum)"
10940+ default 10
10941+ help
10942+ This option allows you to enforce the number of seconds between
10943+ grsecurity log messages. The default should be suitable for most
10944+ people, however, if you choose to change it, choose a value small enough
10945+ to allow informative logs to be produced, but large enough to
10946+ prevent flooding.
10947+
10948+config GRKERNSEC_FLOODBURST
10949+ int "Number of messages in a burst (maximum)"
10950+ default 4
10951+ help
10952+ This option allows you to choose the maximum number of messages allowed
10953+ within the flood time interval you chose in a separate option. The
10954+ default should be suitable for most people, however if you find that
10955+ many of your logs are being interpreted as flooding, you may want to
10956+ raise this value.
10957+
10958+endmenu
10959+
10960+endmenu
10961diff -urNp linux-2.6.17.7/grsecurity/Makefile linux-2.6.17.7/grsecurity/Makefile
10962--- linux-2.6.17.7/grsecurity/Makefile 1969-12-31 19:00:00.000000000 -0500
10963+++ linux-2.6.17.7/grsecurity/Makefile 2006-08-01 20:29:47.000000000 -0400
10964@@ -0,0 +1,20 @@
10965+# grsecurity's ACL system was originally written in 2001 by Michael Dalton
10966+# during 2001-2005 it has been completely redesigned by Brad Spengler
10967+# into an RBAC system
10968+#
10969+# All code in this directory and various hooks inserted throughout the kernel
10970+# are copyright Brad Spengler, and released under the GPL v2 or higher
10971+
10972+obj-y = grsec_chdir.o grsec_chroot.o grsec_exec.o grsec_fifo.o grsec_fork.o \
10973+ grsec_mount.o grsec_rand.o grsec_sig.o grsec_sock.o grsec_sysctl.o \
10974+ grsec_time.o grsec_tpe.o grsec_ipc.o grsec_link.o grsec_textrel.o
10975+
10976+obj-$(CONFIG_GRKERNSEC) += grsec_init.o grsum.o gracl.o gracl_ip.o gracl_segv.o \
10977+ gracl_cap.o gracl_alloc.o gracl_shm.o grsec_mem.o gracl_fs.o \
10978+ gracl_learn.o grsec_log.o
10979+obj-$(CONFIG_GRKERNSEC_RESLOG) += gracl_res.o
10980+
10981+ifndef CONFIG_GRKERNSEC
10982+obj-y += grsec_disabled.o
10983+endif
10984+
10985diff -urNp linux-2.6.17.7/grsecurity/gracl.c linux-2.6.17.7/grsecurity/gracl.c
10986--- linux-2.6.17.7/grsecurity/gracl.c 1969-12-31 19:00:00.000000000 -0500
10987+++ linux-2.6.17.7/grsecurity/gracl.c 2006-08-01 20:29:47.000000000 -0400
10988@@ -0,0 +1,3547 @@
10989+#include <linux/kernel.h>
10990+#include <linux/module.h>
10991+#include <linux/sched.h>
10992+#include <linux/mm.h>
10993+#include <linux/file.h>
10994+#include <linux/fs.h>
10995+#include <linux/namei.h>
10996+#include <linux/mount.h>
10997+#include <linux/tty.h>
10998+#include <linux/proc_fs.h>
10999+#include <linux/smp_lock.h>
11000+#include <linux/slab.h>
11001+#include <linux/vmalloc.h>
11002+#include <linux/types.h>
11003+#include <linux/capability.h>
11004+#include <linux/sysctl.h>
11005+#include <linux/netdevice.h>
11006+#include <linux/ptrace.h>
11007+#include <linux/gracl.h>
11008+#include <linux/gralloc.h>
11009+#include <linux/grsecurity.h>
11010+#include <linux/grinternal.h>
11011+#include <linux/percpu.h>
11012+
11013+#include <asm/uaccess.h>
11014+#include <asm/errno.h>
11015+#include <asm/mman.h>
11016+
11017+static struct acl_role_db acl_role_set;
11018+static struct name_db name_set;
11019+static struct inodev_db inodev_set;
11020+
11021+/* for keeping track of userspace pointers used for subjects, so we
11022+ can share references in the kernel as well
11023+*/
11024+
11025+static struct dentry *real_root;
11026+static struct vfsmount *real_root_mnt;
11027+
11028+static struct acl_subj_map_db subj_map_set;
11029+
11030+static struct acl_role_label *default_role;
11031+
11032+static u16 acl_sp_role_value;
11033+
11034+extern char *gr_shared_page[4];
11035+static DECLARE_MUTEX(gr_dev_sem);
11036+rwlock_t gr_inode_lock = RW_LOCK_UNLOCKED;
11037+
11038+struct gr_arg *gr_usermode;
11039+
11040+static unsigned int gr_status = GR_STATUS_INIT;
11041+
11042+extern int chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum);
11043+extern void gr_clear_learn_entries(void);
11044+
11045+#ifdef CONFIG_GRKERNSEC_RESLOG
11046+extern void gr_log_resource(const struct task_struct *task,
11047+ const int res, const unsigned long wanted, const int gt);
11048+#endif
11049+
11050+extern char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
11051+ struct dentry *root, struct vfsmount *rootmnt,
11052+ char *buffer, int buflen);
11053+
11054+unsigned char *gr_system_salt;
11055+unsigned char *gr_system_sum;
11056+
11057+static struct sprole_pw **acl_special_roles = NULL;
11058+static __u16 num_sprole_pws = 0;
11059+
11060+static struct acl_role_label *kernel_role = NULL;
11061+
11062+static unsigned int gr_auth_attempts = 0;
11063+static unsigned long gr_auth_expires = 0UL;
11064+
11065+extern struct vfsmount *sock_mnt;
11066+extern struct vfsmount *pipe_mnt;
11067+extern struct vfsmount *shm_mnt;
11068+static struct acl_object_label *fakefs_obj;
11069+
11070+extern int gr_init_uidset(void);
11071+extern void gr_free_uidset(void);
11072+extern void gr_remove_uid(uid_t uid);
11073+extern int gr_find_uid(uid_t uid);
11074+
11075+__inline__ int
11076+gr_acl_is_enabled(void)
11077+{
11078+ return (gr_status & GR_READY);
11079+}
11080+
11081+char gr_roletype_to_char(void)
11082+{
11083+ switch (current->role->roletype &
11084+ (GR_ROLE_DEFAULT | GR_ROLE_USER | GR_ROLE_GROUP |
11085+ GR_ROLE_SPECIAL)) {
11086+ case GR_ROLE_DEFAULT:
11087+ return 'D';
11088+ case GR_ROLE_USER:
11089+ return 'U';
11090+ case GR_ROLE_GROUP:
11091+ return 'G';
11092+ case GR_ROLE_SPECIAL:
11093+ return 'S';
11094+ }
11095+
11096+ return 'X';
11097+}
11098+
11099+__inline__ int
11100+gr_acl_tpe_check(void)
11101+{
11102+ if (unlikely(!(gr_status & GR_READY)))
11103+ return 0;
11104+ if (current->role->roletype & GR_ROLE_TPE)
11105+ return 1;
11106+ else
11107+ return 0;
11108+}
11109+
11110+int
11111+gr_handle_rawio(const struct inode *inode)
11112+{
11113+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
11114+ if (inode && S_ISBLK(inode->i_mode) &&
11115+ grsec_enable_chroot_caps && proc_is_chrooted(current) &&
11116+ !capable(CAP_SYS_RAWIO))
11117+ return 1;
11118+#endif
11119+ return 0;
11120+}
11121+
11122+static int
11123+gr_streq(const char *a, const char *b, const unsigned int lena, const unsigned int lenb)
11124+{
11125+ int i;
11126+ unsigned long *l1;
11127+ unsigned long *l2;
11128+ unsigned char *c1;
11129+ unsigned char *c2;
11130+ int num_longs;
11131+
11132+ if (likely(lena != lenb))
11133+ return 0;
11134+
11135+ l1 = (unsigned long *)a;
11136+ l2 = (unsigned long *)b;
11137+
11138+ num_longs = lena / sizeof(unsigned long);
11139+
11140+ for (i = num_longs; i--; l1++, l2++) {
11141+ if (unlikely(*l1 != *l2))
11142+ return 0;
11143+ }
11144+
11145+ c1 = (unsigned char *) l1;
11146+ c2 = (unsigned char *) l2;
11147+
11148+ i = lena - (num_longs * sizeof(unsigned long));
11149+
11150+ for (; i--; c1++, c2++) {
11151+ if (unlikely(*c1 != *c2))
11152+ return 0;
11153+ }
11154+
11155+ return 1;
11156+}
11157+
11158+static char *
11159+gen_full_path(struct dentry *dentry, struct vfsmount *vfsmnt,
11160+ struct dentry *root, struct vfsmount *rootmnt, char *buf, int buflen)
11161+{
11162+ char *end = buf + buflen;
11163+ char *retval;
11164+ int namelen = 0;
11165+
11166+ *--end = '\0';
11167+
11168+ retval = end - 1;
11169+ *retval = '/';
11170+
11171+ if (dentry == root && vfsmnt == rootmnt)
11172+ return retval;
11173+ if (dentry != vfsmnt->mnt_root && !IS_ROOT(dentry)) {
11174+ namelen = strlen(dentry->d_name.name);
11175+ buflen -= namelen;
11176+ if (buflen < 2)
11177+ goto err;
11178+ if (dentry->d_parent != root || vfsmnt != rootmnt)
11179+ buflen--;
11180+ }
11181+
11182+ retval = __d_path(dentry->d_parent, vfsmnt, root, rootmnt, buf, buflen);
11183+ if (unlikely(IS_ERR(retval)))
11184+err:
11185+ retval = strcpy(buf, "<path too long>");
11186+ else if (namelen != 0) {
11187+ end = buf + buflen - 1; // accounts for null termination
11188+ if (dentry->d_parent != root || vfsmnt != rootmnt)
11189+ *end++ = '/'; // accounted for above with buflen--
11190+ memcpy(end, dentry->d_name.name, namelen);
11191+ }
11192+
11193+ return retval;
11194+}
11195+
11196+static char *
11197+__d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
11198+ char *buf, int buflen)
11199+{
11200+ char *res;
11201+
11202+ /* we can use real_root, real_root_mnt, because this is only called
11203+ by the RBAC system */
11204+ res = gen_full_path((struct dentry *)dentry, (struct vfsmount *)vfsmnt, real_root, real_root_mnt, buf, buflen);
11205+
11206+ return res;
11207+}
11208+
11209+static char *
11210+d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
11211+ char *buf, int buflen)
11212+{
11213+ char *res;
11214+ struct dentry *root;
11215+ struct vfsmount *rootmnt;
11216+
11217+ /* we can't use real_root, real_root_mnt, because they belong only to the RBAC system */
11218+ read_lock(&child_reaper->fs->lock);
11219+ root = dget(child_reaper->fs->root);
11220+ rootmnt = mntget(child_reaper->fs->rootmnt);
11221+ read_unlock(&child_reaper->fs->lock);
11222+
11223+ spin_lock(&dcache_lock);
11224+ res = gen_full_path((struct dentry *)dentry, (struct vfsmount *)vfsmnt, root, rootmnt, buf, buflen);
11225+ spin_unlock(&dcache_lock);
11226+
11227+ dput(root);
11228+ mntput(rootmnt);
11229+ return res;
11230+}
11231+
11232+static char *
11233+gr_to_filename_rbac(const struct dentry *dentry, const struct vfsmount *mnt)
11234+{
11235+ char *ret;
11236+ spin_lock(&dcache_lock);
11237+ ret = __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()),
11238+ PAGE_SIZE);
11239+ spin_unlock(&dcache_lock);
11240+ return ret;
11241+}
11242+
11243+char *
11244+gr_to_filename_nolock(const struct dentry *dentry, const struct vfsmount *mnt)
11245+{
11246+ return __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()),
11247+ PAGE_SIZE);
11248+}
11249+
11250+char *
11251+gr_to_filename(const struct dentry *dentry, const struct vfsmount *mnt)
11252+{
11253+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()),
11254+ PAGE_SIZE);
11255+}
11256+
11257+char *
11258+gr_to_filename1(const struct dentry *dentry, const struct vfsmount *mnt)
11259+{
11260+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[1], smp_processor_id()),
11261+ PAGE_SIZE);
11262+}
11263+
11264+char *
11265+gr_to_filename2(const struct dentry *dentry, const struct vfsmount *mnt)
11266+{
11267+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[2], smp_processor_id()),
11268+ PAGE_SIZE);
11269+}
11270+
11271+char *
11272+gr_to_filename3(const struct dentry *dentry, const struct vfsmount *mnt)
11273+{
11274+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[3], smp_processor_id()),
11275+ PAGE_SIZE);
11276+}
11277+
11278+__inline__ __u32
11279+to_gr_audit(const __u32 reqmode)
11280+{
11281+ /* masks off auditable permission flags, then shifts them to create
11282+ auditing flags, and adds the special case of append auditing if
11283+ we're requesting write */
11284+ return (((reqmode & GR_AUDIT_READ) << 10) | ((reqmode & GR_WRITE) ? GR_AUDIT_APPEND : 0));
11285+}
11286+
11287+struct acl_subject_label *
11288+lookup_subject_map(const struct acl_subject_label *userp)
11289+{
11290+ unsigned int index = shash(userp, subj_map_set.s_size);
11291+ struct subject_map *match;
11292+
11293+ match = subj_map_set.s_hash[index];
11294+
11295+ while (match && match->user != userp)
11296+ match = match->next;
11297+
11298+ if (match != NULL)
11299+ return match->kernel;
11300+ else
11301+ return NULL;
11302+}
11303+
11304+static void
11305+insert_subj_map_entry(struct subject_map *subjmap)
11306+{
11307+ unsigned int index = shash(subjmap->user, subj_map_set.s_size);
11308+ struct subject_map **curr;
11309+
11310+ subjmap->prev = NULL;
11311+
11312+ curr = &subj_map_set.s_hash[index];
11313+ if (*curr != NULL)
11314+ (*curr)->prev = subjmap;
11315+
11316+ subjmap->next = *curr;
11317+ *curr = subjmap;
11318+
11319+ return;
11320+}
11321+
11322+static struct acl_role_label *
11323+lookup_acl_role_label(const struct task_struct *task, const uid_t uid,
11324+ const gid_t gid)
11325+{
11326+ unsigned int index = rhash(uid, GR_ROLE_USER, acl_role_set.r_size);
11327+ struct acl_role_label *match;
11328+ struct role_allowed_ip *ipp;
11329+ unsigned int x;
11330+
11331+ match = acl_role_set.r_hash[index];
11332+
11333+ while (match) {
11334+ if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_USER)) == (GR_ROLE_DOMAIN | GR_ROLE_USER)) {
11335+ for (x = 0; x < match->domain_child_num; x++) {
11336+ if (match->domain_children[x] == uid)
11337+ goto found;
11338+ }
11339+ } else if (match->uidgid == uid && match->roletype & GR_ROLE_USER)
11340+ break;
11341+ match = match->next;
11342+ }
11343+found:
11344+ if (match == NULL) {
11345+ try_group:
11346+ index = rhash(gid, GR_ROLE_GROUP, acl_role_set.r_size);
11347+ match = acl_role_set.r_hash[index];
11348+
11349+ while (match) {
11350+ if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) == (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) {
11351+ for (x = 0; x < match->domain_child_num; x++) {
11352+ if (match->domain_children[x] == gid)
11353+ goto found2;
11354+ }
11355+ } else if (match->uidgid == gid && match->roletype & GR_ROLE_GROUP)
11356+ break;
11357+ match = match->next;
11358+ }
11359+found2:
11360+ if (match == NULL)
11361+ match = default_role;
11362+ if (match->allowed_ips == NULL)
11363+ return match;
11364+ else {
11365+ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
11366+ if (likely
11367+ ((ntohl(task->signal->curr_ip) & ipp->netmask) ==
11368+ (ntohl(ipp->addr) & ipp->netmask)))
11369+ return match;
11370+ }
11371+ match = default_role;
11372+ }
11373+ } else if (match->allowed_ips == NULL) {
11374+ return match;
11375+ } else {
11376+ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
11377+ if (likely
11378+ ((ntohl(task->signal->curr_ip) & ipp->netmask) ==
11379+ (ntohl(ipp->addr) & ipp->netmask)))
11380+ return match;
11381+ }
11382+ goto try_group;
11383+ }
11384+
11385+ return match;
11386+}
11387+
11388+struct acl_subject_label *
11389+lookup_acl_subj_label(const ino_t ino, const dev_t dev,
11390+ const struct acl_role_label *role)
11391+{
11392+ unsigned int index = fhash(ino, dev, role->subj_hash_size);
11393+ struct acl_subject_label *match;
11394+
11395+ match = role->subj_hash[index];
11396+
11397+ while (match && (match->inode != ino || match->device != dev ||
11398+ (match->mode & GR_DELETED))) {
11399+ match = match->next;
11400+ }
11401+
11402+ if (match && !(match->mode & GR_DELETED))
11403+ return match;
11404+ else
11405+ return NULL;
11406+}
11407+
11408+static struct acl_object_label *
11409+lookup_acl_obj_label(const ino_t ino, const dev_t dev,
11410+ const struct acl_subject_label *subj)
11411+{
11412+ unsigned int index = fhash(ino, dev, subj->obj_hash_size);
11413+ struct acl_object_label *match;
11414+
11415+ match = subj->obj_hash[index];
11416+
11417+ while (match && (match->inode != ino || match->device != dev ||
11418+ (match->mode & GR_DELETED))) {
11419+ match = match->next;
11420+ }
11421+
11422+ if (match && !(match->mode & GR_DELETED))
11423+ return match;
11424+ else
11425+ return NULL;
11426+}
11427+
11428+static struct acl_object_label *
11429+lookup_acl_obj_label_create(const ino_t ino, const dev_t dev,
11430+ const struct acl_subject_label *subj)
11431+{
11432+ unsigned int index = fhash(ino, dev, subj->obj_hash_size);
11433+ struct acl_object_label *match;
11434+
11435+ match = subj->obj_hash[index];
11436+
11437+ while (match && (match->inode != ino || match->device != dev ||
11438+ !(match->mode & GR_DELETED))) {
11439+ match = match->next;
11440+ }
11441+
11442+ if (match && (match->mode & GR_DELETED))
11443+ return match;
11444+
11445+ match = subj->obj_hash[index];
11446+
11447+ while (match && (match->inode != ino || match->device != dev ||
11448+ (match->mode & GR_DELETED))) {
11449+ match = match->next;
11450+ }
11451+
11452+ if (match && !(match->mode & GR_DELETED))
11453+ return match;
11454+ else
11455+ return NULL;
11456+}
11457+
11458+static struct name_entry *
11459+lookup_name_entry(const char *name)
11460+{
11461+ unsigned int len = strlen(name);
11462+ unsigned int key = full_name_hash(name, len);
11463+ unsigned int index = key % name_set.n_size;
11464+ struct name_entry *match;
11465+
11466+ match = name_set.n_hash[index];
11467+
11468+ while (match && (match->key != key || !gr_streq(match->name, name, match->len, len)))
11469+ match = match->next;
11470+
11471+ return match;
11472+}
11473+
11474+static struct inodev_entry *
11475+lookup_inodev_entry(const ino_t ino, const dev_t dev)
11476+{
11477+ unsigned int index = fhash(ino, dev, inodev_set.i_size);
11478+ struct inodev_entry *match;
11479+
11480+ match = inodev_set.i_hash[index];
11481+
11482+ while (match && (match->nentry->inode != ino || match->nentry->device != dev))
11483+ match = match->next;
11484+
11485+ return match;
11486+}
11487+
11488+static void
11489+insert_inodev_entry(struct inodev_entry *entry)
11490+{
11491+ unsigned int index = fhash(entry->nentry->inode, entry->nentry->device,
11492+ inodev_set.i_size);
11493+ struct inodev_entry **curr;
11494+
11495+ entry->prev = NULL;
11496+
11497+ curr = &inodev_set.i_hash[index];
11498+ if (*curr != NULL)
11499+ (*curr)->prev = entry;
11500+
11501+ entry->next = *curr;
11502+ *curr = entry;
11503+
11504+ return;
11505+}
11506+
11507+static void
11508+__insert_acl_role_label(struct acl_role_label *role, uid_t uidgid)
11509+{
11510+ unsigned int index =
11511+ rhash(uidgid, role->roletype & (GR_ROLE_USER | GR_ROLE_GROUP), acl_role_set.r_size);
11512+ struct acl_role_label **curr;
11513+
11514+ role->prev = NULL;
11515+
11516+ curr = &acl_role_set.r_hash[index];
11517+ if (*curr != NULL)
11518+ (*curr)->prev = role;
11519+
11520+ role->next = *curr;
11521+ *curr = role;
11522+
11523+ return;
11524+}
11525+
11526+static void
11527+insert_acl_role_label(struct acl_role_label *role)
11528+{
11529+ int i;
11530+
11531+ if (role->roletype & GR_ROLE_DOMAIN) {
11532+ for (i = 0; i < role->domain_child_num; i++)
11533+ __insert_acl_role_label(role, role->domain_children[i]);
11534+ } else
11535+ __insert_acl_role_label(role, role->uidgid);
11536+}
11537+
11538+static int
11539+insert_name_entry(char *name, const ino_t inode, const dev_t device)
11540+{
11541+ struct name_entry **curr, *nentry;
11542+ struct inodev_entry *ientry;
11543+ unsigned int len = strlen(name);
11544+ unsigned int key = full_name_hash(name, len);
11545+ unsigned int index = key % name_set.n_size;
11546+
11547+ curr = &name_set.n_hash[index];
11548+
11549+ while (*curr && ((*curr)->key != key || !gr_streq((*curr)->name, name, (*curr)->len, len)))
11550+ curr = &((*curr)->next);
11551+
11552+ if (*curr != NULL)
11553+ return 1;
11554+
11555+ nentry = acl_alloc(sizeof (struct name_entry));
11556+ if (nentry == NULL)
11557+ return 0;
11558+ ientry = acl_alloc(sizeof (struct inodev_entry));
11559+ if (ientry == NULL)
11560+ return 0;
11561+ ientry->nentry = nentry;
11562+
11563+ nentry->key = key;
11564+ nentry->name = name;
11565+ nentry->inode = inode;
11566+ nentry->device = device;
11567+ nentry->len = len;
11568+
11569+ nentry->prev = NULL;
11570+ curr = &name_set.n_hash[index];
11571+ if (*curr != NULL)
11572+ (*curr)->prev = nentry;
11573+ nentry->next = *curr;
11574+ *curr = nentry;
11575+
11576+ /* insert us into the table searchable by inode/dev */
11577+ insert_inodev_entry(ientry);
11578+
11579+ return 1;
11580+}
11581+
11582+static void
11583+insert_acl_obj_label(struct acl_object_label *obj,
11584+ struct acl_subject_label *subj)
11585+{
11586+ unsigned int index =
11587+ fhash(obj->inode, obj->device, subj->obj_hash_size);
11588+ struct acl_object_label **curr;
11589+
11590+
11591+ obj->prev = NULL;
11592+
11593+ curr = &subj->obj_hash[index];
11594+ if (*curr != NULL)
11595+ (*curr)->prev = obj;
11596+
11597+ obj->next = *curr;
11598+ *curr = obj;
11599+
11600+ return;
11601+}
11602+
11603+static void
11604+insert_acl_subj_label(struct acl_subject_label *obj,
11605+ struct acl_role_label *role)
11606+{
11607+ unsigned int index = fhash(obj->inode, obj->device, role->subj_hash_size);
11608+ struct acl_subject_label **curr;
11609+
11610+ obj->prev = NULL;
11611+
11612+ curr = &role->subj_hash[index];
11613+ if (*curr != NULL)
11614+ (*curr)->prev = obj;
11615+
11616+ obj->next = *curr;
11617+ *curr = obj;
11618+
11619+ return;
11620+}
11621+
11622+/* allocating chained hash tables, so optimal size is where lambda ~ 1 */
11623+
11624+static void *
11625+create_table(__u32 * len, int elementsize)
11626+{
11627+ unsigned int table_sizes[] = {
11628+ 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381,
11629+ 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
11630+ 4194301, 8388593, 16777213, 33554393, 67108859, 134217689,
11631+ 268435399, 536870909, 1073741789, 2147483647
11632+ };
11633+ void *newtable = NULL;
11634+ unsigned int pwr = 0;
11635+
11636+ while ((pwr < ((sizeof (table_sizes) / sizeof (table_sizes[0])) - 1)) &&
11637+ table_sizes[pwr] <= *len)
11638+ pwr++;
11639+
11640+ if (table_sizes[pwr] <= *len)
11641+ return newtable;
11642+
11643+ if ((table_sizes[pwr] * elementsize) <= PAGE_SIZE)
11644+ newtable =
11645+ kmalloc(table_sizes[pwr] * elementsize, GFP_KERNEL);
11646+ else
11647+ newtable = vmalloc(table_sizes[pwr] * elementsize);
11648+
11649+ *len = table_sizes[pwr];
11650+
11651+ return newtable;
11652+}
11653+
11654+static int
11655+init_variables(const struct gr_arg *arg)
11656+{
11657+ unsigned int stacksize;
11658+
11659+ subj_map_set.s_size = arg->role_db.num_subjects;
11660+ acl_role_set.r_size = arg->role_db.num_roles + arg->role_db.num_domain_children;
11661+ name_set.n_size = arg->role_db.num_objects;
11662+ inodev_set.i_size = arg->role_db.num_objects;
11663+
11664+ if (!subj_map_set.s_size || !acl_role_set.r_size ||
11665+ !name_set.n_size || !inodev_set.i_size)
11666+ return 1;
11667+
11668+ if (!gr_init_uidset())
11669+ return 1;
11670+
11671+ /* set up the stack that holds allocation info */
11672+
11673+ stacksize = arg->role_db.num_pointers + 5;
11674+
11675+ if (!acl_alloc_stack_init(stacksize))
11676+ return 1;
11677+
11678+ /* grab reference for the real root dentry and vfsmount */
11679+ read_lock(&child_reaper->fs->lock);
11680+ real_root_mnt = mntget(child_reaper->fs->rootmnt);
11681+ real_root = dget(child_reaper->fs->root);
11682+ read_unlock(&child_reaper->fs->lock);
11683+
11684+ fakefs_obj = acl_alloc(sizeof(struct acl_object_label));
11685+ if (fakefs_obj == NULL)
11686+ return 1;
11687+ fakefs_obj->mode = GR_FIND | GR_READ | GR_WRITE | GR_EXEC;
11688+
11689+ subj_map_set.s_hash =
11690+ (struct subject_map **) create_table(&subj_map_set.s_size, sizeof(void *));
11691+ acl_role_set.r_hash =
11692+ (struct acl_role_label **) create_table(&acl_role_set.r_size, sizeof(void *));
11693+ name_set.n_hash = (struct name_entry **) create_table(&name_set.n_size, sizeof(void *));
11694+ inodev_set.i_hash =
11695+ (struct inodev_entry **) create_table(&inodev_set.i_size, sizeof(void *));
11696+
11697+ if (!subj_map_set.s_hash || !acl_role_set.r_hash ||
11698+ !name_set.n_hash || !inodev_set.i_hash)
11699+ return 1;
11700+
11701+ memset(subj_map_set.s_hash, 0,
11702+ sizeof(struct subject_map *) * subj_map_set.s_size);
11703+ memset(acl_role_set.r_hash, 0,
11704+ sizeof (struct acl_role_label *) * acl_role_set.r_size);
11705+ memset(name_set.n_hash, 0,
11706+ sizeof (struct name_entry *) * name_set.n_size);
11707+ memset(inodev_set.i_hash, 0,
11708+ sizeof (struct inodev_entry *) * inodev_set.i_size);
11709+
11710+ return 0;
11711+}
11712+
11713+/* free information not needed after startup
11714+ currently contains user->kernel pointer mappings for subjects
11715+*/
11716+
11717+static void
11718+free_init_variables(void)
11719+{
11720+ __u32 i;
11721+
11722+ if (subj_map_set.s_hash) {
11723+ for (i = 0; i < subj_map_set.s_size; i++) {
11724+ if (subj_map_set.s_hash[i]) {
11725+ kfree(subj_map_set.s_hash[i]);
11726+ subj_map_set.s_hash[i] = NULL;
11727+ }
11728+ }
11729+
11730+ if ((subj_map_set.s_size * sizeof (struct subject_map *)) <=
11731+ PAGE_SIZE)
11732+ kfree(subj_map_set.s_hash);
11733+ else
11734+ vfree(subj_map_set.s_hash);
11735+ }
11736+
11737+ return;
11738+}
11739+
11740+static void
11741+free_variables(void)
11742+{
11743+ struct acl_subject_label *s;
11744+ struct acl_role_label *r;
11745+ struct task_struct *task, *task2;
11746+ unsigned int i, x;
11747+
11748+ gr_clear_learn_entries();
11749+
11750+ read_lock(&tasklist_lock);
11751+ do_each_thread(task2, task) {
11752+ task->acl_sp_role = 0;
11753+ task->acl_role_id = 0;
11754+ task->acl = NULL;
11755+ task->role = NULL;
11756+ } while_each_thread(task2, task);
11757+ read_unlock(&tasklist_lock);
11758+
11759+ /* release the reference to the real root dentry and vfsmount */
11760+ if (real_root)
11761+ dput(real_root);
11762+ real_root = NULL;
11763+ if (real_root_mnt)
11764+ mntput(real_root_mnt);
11765+ real_root_mnt = NULL;
11766+
11767+ /* free all object hash tables */
11768+
11769+ FOR_EACH_ROLE_START(r, i)
11770+ if (r->subj_hash == NULL)
11771+ break;
11772+ FOR_EACH_SUBJECT_START(r, s, x)
11773+ if (s->obj_hash == NULL)
11774+ break;
11775+ if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE)
11776+ kfree(s->obj_hash);
11777+ else
11778+ vfree(s->obj_hash);
11779+ FOR_EACH_SUBJECT_END(s, x)
11780+ FOR_EACH_NESTED_SUBJECT_START(r, s)
11781+ if (s->obj_hash == NULL)
11782+ break;
11783+ if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE)
11784+ kfree(s->obj_hash);
11785+ else
11786+ vfree(s->obj_hash);
11787+ FOR_EACH_NESTED_SUBJECT_END(s)
11788+ if ((r->subj_hash_size * sizeof (struct acl_subject_label *)) <= PAGE_SIZE)
11789+ kfree(r->subj_hash);
11790+ else
11791+ vfree(r->subj_hash);
11792+ r->subj_hash = NULL;
11793+ FOR_EACH_ROLE_END(r,i)
11794+
11795+ acl_free_all();
11796+
11797+ if (acl_role_set.r_hash) {
11798+ if ((acl_role_set.r_size * sizeof (struct acl_role_label *)) <=
11799+ PAGE_SIZE)
11800+ kfree(acl_role_set.r_hash);
11801+ else
11802+ vfree(acl_role_set.r_hash);
11803+ }
11804+ if (name_set.n_hash) {
11805+ if ((name_set.n_size * sizeof (struct name_entry *)) <=
11806+ PAGE_SIZE)
11807+ kfree(name_set.n_hash);
11808+ else
11809+ vfree(name_set.n_hash);
11810+ }
11811+
11812+ if (inodev_set.i_hash) {
11813+ if ((inodev_set.i_size * sizeof (struct inodev_entry *)) <=
11814+ PAGE_SIZE)
11815+ kfree(inodev_set.i_hash);
11816+ else
11817+ vfree(inodev_set.i_hash);
11818+ }
11819+
11820+ gr_free_uidset();
11821+
11822+ memset(&name_set, 0, sizeof (struct name_db));
11823+ memset(&inodev_set, 0, sizeof (struct inodev_db));
11824+ memset(&acl_role_set, 0, sizeof (struct acl_role_db));
11825+ memset(&subj_map_set, 0, sizeof (struct acl_subj_map_db));
11826+
11827+ default_role = NULL;
11828+
11829+ return;
11830+}
11831+
11832+static __u32
11833+count_user_objs(struct acl_object_label *userp)
11834+{
11835+ struct acl_object_label o_tmp;
11836+ __u32 num = 0;
11837+
11838+ while (userp) {
11839+ if (copy_from_user(&o_tmp, userp,
11840+ sizeof (struct acl_object_label)))
11841+ break;
11842+
11843+ userp = o_tmp.prev;
11844+ num++;
11845+ }
11846+
11847+ return num;
11848+}
11849+
11850+static struct acl_subject_label *
11851+do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role);
11852+
11853+static int
11854+copy_user_glob(struct acl_object_label *obj)
11855+{
11856+ struct acl_object_label *g_tmp, **guser;
11857+ unsigned int len;
11858+ char *tmp;
11859+
11860+ if (obj->globbed == NULL)
11861+ return 0;
11862+
11863+ guser = &obj->globbed;
11864+ while (*guser) {
11865+ g_tmp = (struct acl_object_label *)
11866+ acl_alloc(sizeof (struct acl_object_label));
11867+ if (g_tmp == NULL)
11868+ return -ENOMEM;
11869+
11870+ if (copy_from_user(g_tmp, *guser,
11871+ sizeof (struct acl_object_label)))
11872+ return -EFAULT;
11873+
11874+ len = strnlen_user(g_tmp->filename, PATH_MAX);
11875+
11876+ if (!len || len >= PATH_MAX)
11877+ return -EINVAL;
11878+
11879+ if ((tmp = (char *) acl_alloc(len)) == NULL)
11880+ return -ENOMEM;
11881+
11882+ if (copy_from_user(tmp, g_tmp->filename, len))
11883+ return -EFAULT;
11884+
11885+ g_tmp->filename = tmp;
11886+
11887+ *guser = g_tmp;
11888+ guser = &(g_tmp->next);
11889+ }
11890+
11891+ return 0;
11892+}
11893+
11894+static int
11895+copy_user_objs(struct acl_object_label *userp, struct acl_subject_label *subj,
11896+ struct acl_role_label *role)
11897+{
11898+ struct acl_object_label *o_tmp;
11899+ unsigned int len;
11900+ int ret;
11901+ char *tmp;
11902+
11903+ while (userp) {
11904+ if ((o_tmp = (struct acl_object_label *)
11905+ acl_alloc(sizeof (struct acl_object_label))) == NULL)
11906+ return -ENOMEM;
11907+
11908+ if (copy_from_user(o_tmp, userp,
11909+ sizeof (struct acl_object_label)))
11910+ return -EFAULT;
11911+
11912+ userp = o_tmp->prev;
11913+
11914+ len = strnlen_user(o_tmp->filename, PATH_MAX);
11915+
11916+ if (!len || len >= PATH_MAX)
11917+ return -EINVAL;
11918+
11919+ if ((tmp = (char *) acl_alloc(len)) == NULL)
11920+ return -ENOMEM;
11921+
11922+ if (copy_from_user(tmp, o_tmp->filename, len))
11923+ return -EFAULT;
11924+
11925+ o_tmp->filename = tmp;
11926+
11927+ insert_acl_obj_label(o_tmp, subj);
11928+ if (!insert_name_entry(o_tmp->filename, o_tmp->inode,
11929+ o_tmp->device))
11930+ return -ENOMEM;
11931+
11932+ ret = copy_user_glob(o_tmp);
11933+ if (ret)
11934+ return ret;
11935+
11936+ if (o_tmp->nested) {
11937+ o_tmp->nested = do_copy_user_subj(o_tmp->nested, role);
11938+ if (IS_ERR(o_tmp->nested))
11939+ return PTR_ERR(o_tmp->nested);
11940+
11941+ /* insert into nested subject list */
11942+ o_tmp->nested->next = role->hash->first;
11943+ role->hash->first = o_tmp->nested;
11944+ }
11945+ }
11946+
11947+ return 0;
11948+}
11949+
11950+static __u32
11951+count_user_subjs(struct acl_subject_label *userp)
11952+{
11953+ struct acl_subject_label s_tmp;
11954+ __u32 num = 0;
11955+
11956+ while (userp) {
11957+ if (copy_from_user(&s_tmp, userp,
11958+ sizeof (struct acl_subject_label)))
11959+ break;
11960+
11961+ userp = s_tmp.prev;
11962+ /* do not count nested subjects against this count, since
11963+ they are not included in the hash table, but are
11964+ attached to objects. We have already counted
11965+ the subjects in userspace for the allocation
11966+ stack
11967+ */
11968+ if (!(s_tmp.mode & GR_NESTED))
11969+ num++;
11970+ }
11971+
11972+ return num;
11973+}
11974+
11975+static int
11976+copy_user_allowedips(struct acl_role_label *rolep)
11977+{
11978+ struct role_allowed_ip *ruserip, *rtmp = NULL, *rlast;
11979+
11980+ ruserip = rolep->allowed_ips;
11981+
11982+ while (ruserip) {
11983+ rlast = rtmp;
11984+
11985+ if ((rtmp = (struct role_allowed_ip *)
11986+ acl_alloc(sizeof (struct role_allowed_ip))) == NULL)
11987+ return -ENOMEM;
11988+
11989+ if (copy_from_user(rtmp, ruserip,
11990+ sizeof (struct role_allowed_ip)))
11991+ return -EFAULT;
11992+
11993+ ruserip = rtmp->prev;
11994+
11995+ if (!rlast) {
11996+ rtmp->prev = NULL;
11997+ rolep->allowed_ips = rtmp;
11998+ } else {
11999+ rlast->next = rtmp;
12000+ rtmp->prev = rlast;
12001+ }
12002+
12003+ if (!ruserip)
12004+ rtmp->next = NULL;
12005+ }
12006+
12007+ return 0;
12008+}
12009+
12010+static int
12011+copy_user_transitions(struct acl_role_label *rolep)
12012+{
12013+ struct role_transition *rusertp, *rtmp = NULL, *rlast;
12014+
12015+ unsigned int len;
12016+ char *tmp;
12017+
12018+ rusertp = rolep->transitions;
12019+
12020+ while (rusertp) {
12021+ rlast = rtmp;
12022+
12023+ if ((rtmp = (struct role_transition *)
12024+ acl_alloc(sizeof (struct role_transition))) == NULL)
12025+ return -ENOMEM;
12026+
12027+ if (copy_from_user(rtmp, rusertp,
12028+ sizeof (struct role_transition)))
12029+ return -EFAULT;
12030+
12031+ rusertp = rtmp->prev;
12032+
12033+ len = strnlen_user(rtmp->rolename, GR_SPROLE_LEN);
12034+
12035+ if (!len || len >= GR_SPROLE_LEN)
12036+ return -EINVAL;
12037+
12038+ if ((tmp = (char *) acl_alloc(len)) == NULL)
12039+ return -ENOMEM;
12040+
12041+ if (copy_from_user(tmp, rtmp->rolename, len))
12042+ return -EFAULT;
12043+
12044+ rtmp->rolename = tmp;
12045+
12046+ if (!rlast) {
12047+ rtmp->prev = NULL;
12048+ rolep->transitions = rtmp;
12049+ } else {
12050+ rlast->next = rtmp;
12051+ rtmp->prev = rlast;
12052+ }
12053+
12054+ if (!rusertp)
12055+ rtmp->next = NULL;
12056+ }
12057+
12058+ return 0;
12059+}
12060+
12061+static struct acl_subject_label *
12062+do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role)
12063+{
12064+ struct acl_subject_label *s_tmp = NULL, *s_tmp2;
12065+ unsigned int len;
12066+ char *tmp;
12067+ __u32 num_objs;
12068+ struct acl_ip_label **i_tmp, *i_utmp2;
12069+ struct gr_hash_struct ghash;
12070+ struct subject_map *subjmap;
12071+ unsigned int i_num;
12072+ int err;
12073+
12074+ s_tmp = lookup_subject_map(userp);
12075+
12076+ /* we've already copied this subject into the kernel, just return
12077+ the reference to it, and don't copy it over again
12078+ */
12079+ if (s_tmp)
12080+ return(s_tmp);
12081+
12082+ if ((s_tmp = (struct acl_subject_label *)
12083+ acl_alloc(sizeof (struct acl_subject_label))) == NULL)
12084+ return ERR_PTR(-ENOMEM);
12085+
12086+ subjmap = (struct subject_map *)kmalloc(sizeof (struct subject_map), GFP_KERNEL);
12087+ if (subjmap == NULL)
12088+ return ERR_PTR(-ENOMEM);
12089+
12090+ subjmap->user = userp;
12091+ subjmap->kernel = s_tmp;
12092+ insert_subj_map_entry(subjmap);
12093+
12094+ if (copy_from_user(s_tmp, userp,
12095+ sizeof (struct acl_subject_label)))
12096+ return ERR_PTR(-EFAULT);
12097+
12098+ len = strnlen_user(s_tmp->filename, PATH_MAX);
12099+
12100+ if (!len || len >= PATH_MAX)
12101+ return ERR_PTR(-EINVAL);
12102+
12103+ if ((tmp = (char *) acl_alloc(len)) == NULL)
12104+ return ERR_PTR(-ENOMEM);
12105+
12106+ if (copy_from_user(tmp, s_tmp->filename, len))
12107+ return ERR_PTR(-EFAULT);
12108+
12109+ s_tmp->filename = tmp;
12110+
12111+ if (!strcmp(s_tmp->filename, "/"))
12112+ role->root_label = s_tmp;
12113+
12114+ if (copy_from_user(&ghash, s_tmp->hash, sizeof(struct gr_hash_struct)))
12115+ return ERR_PTR(-EFAULT);
12116+
12117+ /* copy user and group transition tables */
12118+
12119+ if (s_tmp->user_trans_num) {
12120+ uid_t *uidlist;
12121+
12122+ uidlist = (uid_t *)acl_alloc(s_tmp->user_trans_num * sizeof(uid_t));
12123+ if (uidlist == NULL)
12124+ return ERR_PTR(-ENOMEM);
12125+ if (copy_from_user(uidlist, s_tmp->user_transitions, s_tmp->user_trans_num * sizeof(uid_t)))
12126+ return ERR_PTR(-EFAULT);
12127+
12128+ s_tmp->user_transitions = uidlist;
12129+ }
12130+
12131+ if (s_tmp->group_trans_num) {
12132+ gid_t *gidlist;
12133+
12134+ gidlist = (gid_t *)acl_alloc(s_tmp->group_trans_num * sizeof(gid_t));
12135+ if (gidlist == NULL)
12136+ return ERR_PTR(-ENOMEM);
12137+ if (copy_from_user(gidlist, s_tmp->group_transitions, s_tmp->group_trans_num * sizeof(gid_t)))
12138+ return ERR_PTR(-EFAULT);
12139+
12140+ s_tmp->group_transitions = gidlist;
12141+ }
12142+
12143+ /* set up object hash table */
12144+ num_objs = count_user_objs(ghash.first);
12145+
12146+ s_tmp->obj_hash_size = num_objs;
12147+ s_tmp->obj_hash =
12148+ (struct acl_object_label **)
12149+ create_table(&(s_tmp->obj_hash_size), sizeof(void *));
12150+
12151+ if (!s_tmp->obj_hash)
12152+ return ERR_PTR(-ENOMEM);
12153+
12154+ memset(s_tmp->obj_hash, 0,
12155+ s_tmp->obj_hash_size *
12156+ sizeof (struct acl_object_label *));
12157+
12158+ /* add in objects */
12159+ err = copy_user_objs(ghash.first, s_tmp, role);
12160+
12161+ if (err)
12162+ return ERR_PTR(err);
12163+
12164+ /* set pointer for parent subject */
12165+ if (s_tmp->parent_subject) {
12166+ s_tmp2 = do_copy_user_subj(s_tmp->parent_subject, role);
12167+
12168+ if (IS_ERR(s_tmp2))
12169+ return s_tmp2;
12170+
12171+ s_tmp->parent_subject = s_tmp2;
12172+ }
12173+
12174+ /* add in ip acls */
12175+
12176+ if (!s_tmp->ip_num) {
12177+ s_tmp->ips = NULL;
12178+ goto insert;
12179+ }
12180+
12181+ i_tmp =
12182+ (struct acl_ip_label **) acl_alloc(s_tmp->ip_num *
12183+ sizeof (struct
12184+ acl_ip_label *));
12185+
12186+ if (!i_tmp)
12187+ return ERR_PTR(-ENOMEM);
12188+
12189+ for (i_num = 0; i_num < s_tmp->ip_num; i_num++) {
12190+ *(i_tmp + i_num) =
12191+ (struct acl_ip_label *)
12192+ acl_alloc(sizeof (struct acl_ip_label));
12193+ if (!*(i_tmp + i_num))
12194+ return ERR_PTR(-ENOMEM);
12195+
12196+ if (copy_from_user
12197+ (&i_utmp2, s_tmp->ips + i_num,
12198+ sizeof (struct acl_ip_label *)))
12199+ return ERR_PTR(-EFAULT);
12200+
12201+ if (copy_from_user
12202+ (*(i_tmp + i_num), i_utmp2,
12203+ sizeof (struct acl_ip_label)))
12204+ return ERR_PTR(-EFAULT);
12205+
12206+ if ((*(i_tmp + i_num))->iface == NULL)
12207+ continue;
12208+
12209+ len = strnlen_user((*(i_tmp + i_num))->iface, IFNAMSIZ);
12210+ if (!len || len >= IFNAMSIZ)
12211+ return ERR_PTR(-EINVAL);
12212+ tmp = acl_alloc(len);
12213+ if (tmp == NULL)
12214+ return ERR_PTR(-ENOMEM);
12215+ if (copy_from_user(tmp, (*(i_tmp + i_num))->iface, len))
12216+ return ERR_PTR(-EFAULT);
12217+ (*(i_tmp + i_num))->iface = tmp;
12218+ }
12219+
12220+ s_tmp->ips = i_tmp;
12221+
12222+insert:
12223+ if (!insert_name_entry(s_tmp->filename, s_tmp->inode,
12224+ s_tmp->device))
12225+ return ERR_PTR(-ENOMEM);
12226+
12227+ return s_tmp;
12228+}
12229+
12230+static int
12231+copy_user_subjs(struct acl_subject_label *userp, struct acl_role_label *role)
12232+{
12233+ struct acl_subject_label s_pre;
12234+ struct acl_subject_label * ret;
12235+ int err;
12236+
12237+ while (userp) {
12238+ if (copy_from_user(&s_pre, userp,
12239+ sizeof (struct acl_subject_label)))
12240+ return -EFAULT;
12241+
12242+ /* do not add nested subjects here, add
12243+ while parsing objects
12244+ */
12245+
12246+ if (s_pre.mode & GR_NESTED) {
12247+ userp = s_pre.prev;
12248+ continue;
12249+ }
12250+
12251+ ret = do_copy_user_subj(userp, role);
12252+
12253+ err = PTR_ERR(ret);
12254+ if (IS_ERR(ret))
12255+ return err;
12256+
12257+ insert_acl_subj_label(ret, role);
12258+
12259+ userp = s_pre.prev;
12260+ }
12261+
12262+ return 0;
12263+}
12264+
12265+static int
12266+copy_user_acl(struct gr_arg *arg)
12267+{
12268+ struct acl_role_label *r_tmp = NULL, **r_utmp, *r_utmp2;
12269+ struct sprole_pw *sptmp;
12270+ struct gr_hash_struct *ghash;
12271+ uid_t *domainlist;
12272+ unsigned int r_num;
12273+ unsigned int len;
12274+ char *tmp;
12275+ int err = 0;
12276+ __u16 i;
12277+ __u32 num_subjs;
12278+
12279+ /* we need a default and kernel role */
12280+ if (arg->role_db.num_roles < 2)
12281+ return -EINVAL;
12282+
12283+ /* copy special role authentication info from userspace */
12284+
12285+ num_sprole_pws = arg->num_sprole_pws;
12286+ acl_special_roles = (struct sprole_pw **) acl_alloc(num_sprole_pws * sizeof(struct sprole_pw *));
12287+
12288+ if (!acl_special_roles) {
12289+ err = -ENOMEM;
12290+ goto cleanup;
12291+ }
12292+
12293+ for (i = 0; i < num_sprole_pws; i++) {
12294+ sptmp = (struct sprole_pw *) acl_alloc(sizeof(struct sprole_pw));
12295+ if (!sptmp) {
12296+ err = -ENOMEM;
12297+ goto cleanup;
12298+ }
12299+ if (copy_from_user(sptmp, arg->sprole_pws + i,
12300+ sizeof (struct sprole_pw))) {
12301+ err = -EFAULT;
12302+ goto cleanup;
12303+ }
12304+
12305+ len =
12306+ strnlen_user(sptmp->rolename, GR_SPROLE_LEN);
12307+
12308+ if (!len || len >= GR_SPROLE_LEN) {
12309+ err = -EINVAL;
12310+ goto cleanup;
12311+ }
12312+
12313+ if ((tmp = (char *) acl_alloc(len)) == NULL) {
12314+ err = -ENOMEM;
12315+ goto cleanup;
12316+ }
12317+
12318+ if (copy_from_user(tmp, sptmp->rolename, len)) {
12319+ err = -EFAULT;
12320+ goto cleanup;
12321+ }
12322+
12323+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
12324+ printk(KERN_ALERT "Copying special role %s\n", tmp);
12325+#endif
12326+ sptmp->rolename = tmp;
12327+ acl_special_roles[i] = sptmp;
12328+ }
12329+
12330+ r_utmp = (struct acl_role_label **) arg->role_db.r_table;
12331+
12332+ for (r_num = 0; r_num < arg->role_db.num_roles; r_num++) {
12333+ r_tmp = acl_alloc(sizeof (struct acl_role_label));
12334+
12335+ if (!r_tmp) {
12336+ err = -ENOMEM;
12337+ goto cleanup;
12338+ }
12339+
12340+ if (copy_from_user(&r_utmp2, r_utmp + r_num,
12341+ sizeof (struct acl_role_label *))) {
12342+ err = -EFAULT;
12343+ goto cleanup;
12344+ }
12345+
12346+ if (copy_from_user(r_tmp, r_utmp2,
12347+ sizeof (struct acl_role_label))) {
12348+ err = -EFAULT;
12349+ goto cleanup;
12350+ }
12351+
12352+ len = strnlen_user(r_tmp->rolename, GR_SPROLE_LEN);
12353+
12354+ if (!len || len >= PATH_MAX) {
12355+ err = -EINVAL;
12356+ goto cleanup;
12357+ }
12358+
12359+ if ((tmp = (char *) acl_alloc(len)) == NULL) {
12360+ err = -ENOMEM;
12361+ goto cleanup;
12362+ }
12363+ if (copy_from_user(tmp, r_tmp->rolename, len)) {
12364+ err = -EFAULT;
12365+ goto cleanup;
12366+ }
12367+ r_tmp->rolename = tmp;
12368+
12369+ if (!strcmp(r_tmp->rolename, "default")
12370+ && (r_tmp->roletype & GR_ROLE_DEFAULT)) {
12371+ default_role = r_tmp;
12372+ } else if (!strcmp(r_tmp->rolename, ":::kernel:::")) {
12373+ kernel_role = r_tmp;
12374+ }
12375+
12376+ if ((ghash = (struct gr_hash_struct *) acl_alloc(sizeof(struct gr_hash_struct))) == NULL) {
12377+ err = -ENOMEM;
12378+ goto cleanup;
12379+ }
12380+ if (copy_from_user(ghash, r_tmp->hash, sizeof(struct gr_hash_struct))) {
12381+ err = -EFAULT;
12382+ goto cleanup;
12383+ }
12384+
12385+ r_tmp->hash = ghash;
12386+
12387+ num_subjs = count_user_subjs(r_tmp->hash->first);
12388+
12389+ r_tmp->subj_hash_size = num_subjs;
12390+ r_tmp->subj_hash =
12391+ (struct acl_subject_label **)
12392+ create_table(&(r_tmp->subj_hash_size), sizeof(void *));
12393+
12394+ if (!r_tmp->subj_hash) {
12395+ err = -ENOMEM;
12396+ goto cleanup;
12397+ }
12398+
12399+ err = copy_user_allowedips(r_tmp);
12400+ if (err)
12401+ goto cleanup;
12402+
12403+ /* copy domain info */
12404+ if (r_tmp->domain_children != NULL) {
12405+ domainlist = acl_alloc(r_tmp->domain_child_num * sizeof(uid_t));
12406+ if (domainlist == NULL) {
12407+ err = -ENOMEM;
12408+ goto cleanup;
12409+ }
12410+ if (copy_from_user(domainlist, r_tmp->domain_children, r_tmp->domain_child_num * sizeof(uid_t))) {
12411+ err = -EFAULT;
12412+ goto cleanup;
12413+ }
12414+ r_tmp->domain_children = domainlist;
12415+ }
12416+
12417+ err = copy_user_transitions(r_tmp);
12418+ if (err)
12419+ goto cleanup;
12420+
12421+ memset(r_tmp->subj_hash, 0,
12422+ r_tmp->subj_hash_size *
12423+ sizeof (struct acl_subject_label *));
12424+
12425+ err = copy_user_subjs(r_tmp->hash->first, r_tmp);
12426+
12427+ if (err)
12428+ goto cleanup;
12429+
12430+ /* set nested subject list to null */
12431+ r_tmp->hash->first = NULL;
12432+
12433+ insert_acl_role_label(r_tmp);
12434+ }
12435+
12436+ goto return_err;
12437+ cleanup:
12438+ free_variables();
12439+ return_err:
12440+ return err;
12441+
12442+}
12443+
12444+static int
12445+gracl_init(struct gr_arg *args)
12446+{
12447+ int error = 0;
12448+
12449+ memcpy(gr_system_salt, args->salt, GR_SALT_LEN);
12450+ memcpy(gr_system_sum, args->sum, GR_SHA_LEN);
12451+
12452+ if (init_variables(args)) {
12453+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_INITF_ACL_MSG, GR_VERSION);
12454+ error = -ENOMEM;
12455+ free_variables();
12456+ goto out;
12457+ }
12458+
12459+ error = copy_user_acl(args);
12460+ free_init_variables();
12461+ if (error) {
12462+ free_variables();
12463+ goto out;
12464+ }
12465+
12466+ if ((error = gr_set_acls(0))) {
12467+ free_variables();
12468+ goto out;
12469+ }
12470+
12471+ gr_status |= GR_READY;
12472+ out:
12473+ return error;
12474+}
12475+
12476+/* derived from glibc fnmatch() 0: match, 1: no match*/
12477+
12478+static int
12479+glob_match(const char *p, const char *n)
12480+{
12481+ char c;
12482+
12483+ while ((c = *p++) != '\0') {
12484+ switch (c) {
12485+ case '?':
12486+ if (*n == '\0')
12487+ return 1;
12488+ else if (*n == '/')
12489+ return 1;
12490+ break;
12491+ case '\\':
12492+ if (*n != c)
12493+ return 1;
12494+ break;
12495+ case '*':
12496+ for (c = *p++; c == '?' || c == '*'; c = *p++) {
12497+ if (*n == '/')
12498+ return 1;
12499+ else if (c == '?') {
12500+ if (*n == '\0')
12501+ return 1;
12502+ else
12503+ ++n;
12504+ }
12505+ }
12506+ if (c == '\0') {
12507+ return 0;
12508+ } else {
12509+ const char *endp;
12510+
12511+ if ((endp = strchr(n, '/')) == NULL)
12512+ endp = n + strlen(n);
12513+
12514+ if (c == '[') {
12515+ for (--p; n < endp; ++n)
12516+ if (!glob_match(p, n))
12517+ return 0;
12518+ } else if (c == '/') {
12519+ while (*n != '\0' && *n != '/')
12520+ ++n;
12521+ if (*n == '/' && !glob_match(p, n + 1))
12522+ return 0;
12523+ } else {
12524+ for (--p; n < endp; ++n)
12525+ if (*n == c && !glob_match(p, n))
12526+ return 0;
12527+ }
12528+
12529+ return 1;
12530+ }
12531+ case '[':
12532+ {
12533+ int not;
12534+ char cold;
12535+
12536+ if (*n == '\0' || *n == '/')
12537+ return 1;
12538+
12539+ not = (*p == '!' || *p == '^');
12540+ if (not)
12541+ ++p;
12542+
12543+ c = *p++;
12544+ for (;;) {
12545+ unsigned char fn = (unsigned char)*n;
12546+
12547+ if (c == '\0')
12548+ return 1;
12549+ else {
12550+ if (c == fn)
12551+ goto matched;
12552+ cold = c;
12553+ c = *p++;
12554+
12555+ if (c == '-' && *p != ']') {
12556+ unsigned char cend = *p++;
12557+
12558+ if (cend == '\0')
12559+ return 1;
12560+
12561+ if (cold <= fn && fn <= cend)
12562+ goto matched;
12563+
12564+ c = *p++;
12565+ }
12566+ }
12567+
12568+ if (c == ']')
12569+ break;
12570+ }
12571+ if (!not)
12572+ return 1;
12573+ break;
12574+ matched:
12575+ while (c != ']') {
12576+ if (c == '\0')
12577+ return 1;
12578+
12579+ c = *p++;
12580+ }
12581+ if (not)
12582+ return 1;
12583+ }
12584+ break;
12585+ default:
12586+ if (c != *n)
12587+ return 1;
12588+ }
12589+
12590+ ++n;
12591+ }
12592+
12593+ if (*n == '\0')
12594+ return 0;
12595+
12596+ if (*n == '/')
12597+ return 0;
12598+
12599+ return 1;
12600+}
12601+
12602+static struct acl_object_label *
12603+chk_glob_label(struct acl_object_label *globbed,
12604+ struct dentry *dentry, struct vfsmount *mnt, char **path)
12605+{
12606+ struct acl_object_label *tmp;
12607+
12608+ if (*path == NULL)
12609+ *path = gr_to_filename_nolock(dentry, mnt);
12610+
12611+ tmp = globbed;
12612+
12613+ while (tmp) {
12614+ if (!glob_match(tmp->filename, *path))
12615+ return tmp;
12616+ tmp = tmp->next;
12617+ }
12618+
12619+ return NULL;
12620+}
12621+
12622+static struct acl_object_label *
12623+__full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
12624+ const ino_t curr_ino, const dev_t curr_dev,
12625+ const struct acl_subject_label *subj, char **path)
12626+{
12627+ struct acl_subject_label *tmpsubj;
12628+ struct acl_object_label *retval;
12629+ struct acl_object_label *retval2;
12630+
12631+ tmpsubj = (struct acl_subject_label *) subj;
12632+ read_lock(&gr_inode_lock);
12633+ do {
12634+ retval = lookup_acl_obj_label(curr_ino, curr_dev, tmpsubj);
12635+ if (retval) {
12636+ if (retval->globbed) {
12637+ retval2 = chk_glob_label(retval->globbed, (struct dentry *)orig_dentry,
12638+ (struct vfsmount *)orig_mnt, path);
12639+ if (retval2)
12640+ retval = retval2;
12641+ }
12642+ break;
12643+ }
12644+ } while ((tmpsubj = tmpsubj->parent_subject));
12645+ read_unlock(&gr_inode_lock);
12646+
12647+ return retval;
12648+}
12649+
12650+static __inline__ struct acl_object_label *
12651+full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
12652+ const struct dentry *curr_dentry,
12653+ const struct acl_subject_label *subj, char **path)
12654+{
12655+ return __full_lookup(orig_dentry, orig_mnt,
12656+ curr_dentry->d_inode->i_ino,
12657+ curr_dentry->d_inode->i_sb->s_dev, subj, path);
12658+}
12659+
12660+static struct acl_object_label *
12661+__chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
12662+ const struct acl_subject_label *subj, char *path)
12663+{
12664+ struct dentry *dentry = (struct dentry *) l_dentry;
12665+ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
12666+ struct acl_object_label *retval;
12667+
12668+ spin_lock(&dcache_lock);
12669+
12670+ if (unlikely(mnt == shm_mnt || mnt == pipe_mnt || mnt == sock_mnt)) {
12671+ retval = fakefs_obj;
12672+ goto out;
12673+ }
12674+
12675+ for (;;) {
12676+ if (dentry == real_root && mnt == real_root_mnt)
12677+ break;
12678+
12679+ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) {
12680+ if (mnt->mnt_parent == mnt)
12681+ break;
12682+
12683+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
12684+ if (retval != NULL)
12685+ goto out;
12686+
12687+ dentry = mnt->mnt_mountpoint;
12688+ mnt = mnt->mnt_parent;
12689+ continue;
12690+ }
12691+
12692+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
12693+ if (retval != NULL)
12694+ goto out;
12695+
12696+ dentry = dentry->d_parent;
12697+ }
12698+
12699+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
12700+
12701+ if (retval == NULL)
12702+ retval = full_lookup(l_dentry, l_mnt, real_root, subj, &path);
12703+out:
12704+ spin_unlock(&dcache_lock);
12705+ return retval;
12706+}
12707+
12708+static __inline__ struct acl_object_label *
12709+chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
12710+ const struct acl_subject_label *subj)
12711+{
12712+ char *path = NULL;
12713+ return __chk_obj_label(l_dentry, l_mnt, subj, path);
12714+}
12715+
12716+static __inline__ struct acl_object_label *
12717+chk_obj_create_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
12718+ const struct acl_subject_label *subj, char *path)
12719+{
12720+ return __chk_obj_label(l_dentry, l_mnt, subj, path);
12721+}
12722+
12723+static struct acl_subject_label *
12724+chk_subj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
12725+ const struct acl_role_label *role)
12726+{
12727+ struct dentry *dentry = (struct dentry *) l_dentry;
12728+ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
12729+ struct acl_subject_label *retval;
12730+
12731+ spin_lock(&dcache_lock);
12732+
12733+ for (;;) {
12734+ if (dentry == real_root && mnt == real_root_mnt)
12735+ break;
12736+ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) {
12737+ if (mnt->mnt_parent == mnt)
12738+ break;
12739+
12740+ read_lock(&gr_inode_lock);
12741+ retval =
12742+ lookup_acl_subj_label(dentry->d_inode->i_ino,
12743+ dentry->d_inode->i_sb->s_dev, role);
12744+ read_unlock(&gr_inode_lock);
12745+ if (retval != NULL)
12746+ goto out;
12747+
12748+ dentry = mnt->mnt_mountpoint;
12749+ mnt = mnt->mnt_parent;
12750+ continue;
12751+ }
12752+
12753+ read_lock(&gr_inode_lock);
12754+ retval = lookup_acl_subj_label(dentry->d_inode->i_ino,
12755+ dentry->d_inode->i_sb->s_dev, role);
12756+ read_unlock(&gr_inode_lock);
12757+ if (retval != NULL)
12758+ goto out;
12759+
12760+ dentry = dentry->d_parent;
12761+ }
12762+
12763+ read_lock(&gr_inode_lock);
12764+ retval = lookup_acl_subj_label(dentry->d_inode->i_ino,
12765+ dentry->d_inode->i_sb->s_dev, role);
12766+ read_unlock(&gr_inode_lock);
12767+
12768+ if (unlikely(retval == NULL)) {
12769+ read_lock(&gr_inode_lock);
12770+ retval = lookup_acl_subj_label(real_root->d_inode->i_ino,
12771+ real_root->d_inode->i_sb->s_dev, role);
12772+ read_unlock(&gr_inode_lock);
12773+ }
12774+out:
12775+ spin_unlock(&dcache_lock);
12776+
12777+ return retval;
12778+}
12779+
12780+static void
12781+gr_log_learn(const struct task_struct *task, const struct dentry *dentry, const struct vfsmount *mnt, const __u32 mode)
12782+{
12783+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, task->role->roletype,
12784+ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_dentry,
12785+ task->exec_file->f_vfsmnt) : task->acl->filename, task->acl->filename,
12786+ 1, 1, gr_to_filename(dentry, mnt), (unsigned long) mode, NIPQUAD(task->signal->curr_ip));
12787+
12788+ return;
12789+}
12790+
12791+static void
12792+gr_log_learn_id_change(const struct task_struct *task, const char type, const unsigned int real,
12793+ const unsigned int effective, const unsigned int fs)
12794+{
12795+ security_learn(GR_ID_LEARN_MSG, task->role->rolename, task->role->roletype,
12796+ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_dentry,
12797+ task->exec_file->f_vfsmnt) : task->acl->filename, task->acl->filename,
12798+ type, real, effective, fs, NIPQUAD(task->signal->curr_ip));
12799+
12800+ return;
12801+}
12802+
12803+__u32
12804+gr_check_link(const struct dentry * new_dentry,
12805+ const struct dentry * parent_dentry,
12806+ const struct vfsmount * parent_mnt,
12807+ const struct dentry * old_dentry, const struct vfsmount * old_mnt)
12808+{
12809+ struct acl_object_label *obj;
12810+ __u32 oldmode, newmode;
12811+ __u32 needmode;
12812+
12813+ if (unlikely(!(gr_status & GR_READY)))
12814+ return (GR_CREATE | GR_LINK);
12815+
12816+ obj = chk_obj_label(old_dentry, old_mnt, current->acl);
12817+ oldmode = obj->mode;
12818+
12819+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
12820+ oldmode |= (GR_CREATE | GR_LINK);
12821+
12822+ needmode = GR_CREATE | GR_AUDIT_CREATE | GR_SUPPRESS;
12823+ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID))
12824+ needmode |= GR_SETID | GR_AUDIT_SETID;
12825+
12826+ newmode =
12827+ gr_check_create(new_dentry, parent_dentry, parent_mnt,
12828+ oldmode | needmode);
12829+
12830+ needmode = newmode & (GR_FIND | GR_APPEND | GR_WRITE | GR_EXEC |
12831+ GR_SETID | GR_READ | GR_FIND | GR_DELETE |
12832+ GR_INHERIT | GR_AUDIT_INHERIT);
12833+
12834+ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID) && !(newmode & GR_SETID))
12835+ goto bad;
12836+
12837+ if ((oldmode & needmode) != needmode)
12838+ goto bad;
12839+
12840+ needmode = oldmode & (GR_NOPTRACE | GR_PTRACERD | GR_INHERIT | GR_AUDITS);
12841+ if ((newmode & needmode) != needmode)
12842+ goto bad;
12843+
12844+ if ((newmode & (GR_CREATE | GR_LINK)) == (GR_CREATE | GR_LINK))
12845+ return newmode;
12846+bad:
12847+ needmode = oldmode;
12848+ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID))
12849+ needmode |= GR_SETID;
12850+
12851+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) {
12852+ gr_log_learn(current, old_dentry, old_mnt, needmode);
12853+ return (GR_CREATE | GR_LINK);
12854+ } else if (newmode & GR_SUPPRESS)
12855+ return GR_SUPPRESS;
12856+ else
12857+ return 0;
12858+}
12859+
12860+__u32
12861+gr_search_file(const struct dentry * dentry, const __u32 mode,
12862+ const struct vfsmount * mnt)
12863+{
12864+ __u32 retval = mode;
12865+ struct acl_subject_label *curracl;
12866+ struct acl_object_label *currobj;
12867+
12868+ if (unlikely(!(gr_status & GR_READY)))
12869+ return (mode & ~GR_AUDITS);
12870+
12871+ curracl = current->acl;
12872+
12873+ currobj = chk_obj_label(dentry, mnt, curracl);
12874+ retval = currobj->mode & mode;
12875+
12876+ if (unlikely
12877+ ((curracl->mode & (GR_LEARN | GR_INHERITLEARN)) && !(mode & GR_NOPTRACE)
12878+ && (retval != (mode & ~(GR_AUDITS | GR_SUPPRESS))))) {
12879+ __u32 new_mode = mode;
12880+
12881+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
12882+
12883+ retval = new_mode;
12884+
12885+ if (new_mode & GR_EXEC && curracl->mode & GR_INHERITLEARN)
12886+ new_mode |= GR_INHERIT;
12887+
12888+ if (!(mode & GR_NOLEARN))
12889+ gr_log_learn(current, dentry, mnt, new_mode);
12890+ }
12891+
12892+ return retval;
12893+}
12894+
12895+__u32
12896+gr_check_create(const struct dentry * new_dentry, const struct dentry * parent,
12897+ const struct vfsmount * mnt, const __u32 mode)
12898+{
12899+ struct name_entry *match;
12900+ struct acl_object_label *matchpo;
12901+ struct acl_subject_label *curracl;
12902+ char *path;
12903+ __u32 retval;
12904+
12905+ if (unlikely(!(gr_status & GR_READY)))
12906+ return (mode & ~GR_AUDITS);
12907+
12908+ preempt_disable();
12909+ path = gr_to_filename_rbac(new_dentry, mnt);
12910+ match = lookup_name_entry(path);
12911+
12912+ if (!match)
12913+ goto check_parent;
12914+
12915+ curracl = current->acl;
12916+
12917+ read_lock(&gr_inode_lock);
12918+ matchpo = lookup_acl_obj_label_create(match->inode, match->device, curracl);
12919+ read_unlock(&gr_inode_lock);
12920+
12921+ if (matchpo) {
12922+ if ((matchpo->mode & mode) !=
12923+ (mode & ~(GR_AUDITS | GR_SUPPRESS))
12924+ && curracl->mode & (GR_LEARN | GR_INHERITLEARN)) {
12925+ __u32 new_mode = mode;
12926+
12927+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
12928+
12929+ gr_log_learn(current, new_dentry, mnt, new_mode);
12930+
12931+ preempt_enable();
12932+ return new_mode;
12933+ }
12934+ preempt_enable();
12935+ return (matchpo->mode & mode);
12936+ }
12937+
12938+ check_parent:
12939+ curracl = current->acl;
12940+
12941+ matchpo = chk_obj_create_label(parent, mnt, curracl, path);
12942+ retval = matchpo->mode & mode;
12943+
12944+ if ((retval != (mode & ~(GR_AUDITS | GR_SUPPRESS)))
12945+ && (curracl->mode & (GR_LEARN | GR_INHERITLEARN))) {
12946+ __u32 new_mode = mode;
12947+
12948+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
12949+
12950+ gr_log_learn(current, new_dentry, mnt, new_mode);
12951+ preempt_enable();
12952+ return new_mode;
12953+ }
12954+
12955+ preempt_enable();
12956+ return retval;
12957+}
12958+
12959+int
12960+gr_check_hidden_task(const struct task_struct *task)
12961+{
12962+ if (unlikely(!(gr_status & GR_READY)))
12963+ return 0;
12964+
12965+ if (!(task->acl->mode & GR_PROCFIND) && !(current->acl->mode & GR_VIEW))
12966+ return 1;
12967+
12968+ return 0;
12969+}
12970+
12971+int
12972+gr_check_protected_task(const struct task_struct *task)
12973+{
12974+ if (unlikely(!(gr_status & GR_READY) || !task))
12975+ return 0;
12976+
12977+ if ((task->acl->mode & GR_PROTECTED) && !(current->acl->mode & GR_KILL) &&
12978+ task->acl != current->acl)
12979+ return 1;
12980+
12981+ return 0;
12982+}
12983+
12984+void
12985+gr_copy_label(struct task_struct *tsk)
12986+{
12987+ tsk->signal->used_accept = 0;
12988+ tsk->acl_sp_role = 0;
12989+ tsk->acl_role_id = current->acl_role_id;
12990+ tsk->acl = current->acl;
12991+ tsk->role = current->role;
12992+ tsk->signal->curr_ip = current->signal->curr_ip;
12993+ if (current->exec_file)
12994+ get_file(current->exec_file);
12995+ tsk->exec_file = current->exec_file;
12996+ tsk->is_writable = current->is_writable;
12997+ if (unlikely(current->signal->used_accept))
12998+ current->signal->curr_ip = 0;
12999+
13000+ return;
13001+}
13002+
13003+static void
13004+gr_set_proc_res(struct task_struct *task)
13005+{
13006+ struct acl_subject_label *proc;
13007+ unsigned short i;
13008+
13009+ proc = task->acl;
13010+
13011+ if (proc->mode & (GR_LEARN | GR_INHERITLEARN))
13012+ return;
13013+
13014+ for (i = 0; i < (GR_NLIMITS - 1); i++) {
13015+ if (!(proc->resmask & (1 << i)))
13016+ continue;
13017+
13018+ task->signal->rlim[i].rlim_cur = proc->res[i].rlim_cur;
13019+ task->signal->rlim[i].rlim_max = proc->res[i].rlim_max;
13020+ }
13021+
13022+ return;
13023+}
13024+
13025+int
13026+gr_check_user_change(int real, int effective, int fs)
13027+{
13028+ unsigned int i;
13029+ __u16 num;
13030+ uid_t *uidlist;
13031+ int curuid;
13032+ int realok = 0;
13033+ int effectiveok = 0;
13034+ int fsok = 0;
13035+
13036+ if (unlikely(!(gr_status & GR_READY)))
13037+ return 0;
13038+
13039+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
13040+ gr_log_learn_id_change(current, 'u', real, effective, fs);
13041+
13042+ num = current->acl->user_trans_num;
13043+ uidlist = current->acl->user_transitions;
13044+
13045+ if (uidlist == NULL)
13046+ return 0;
13047+
13048+ if (real == -1)
13049+ realok = 1;
13050+ if (effective == -1)
13051+ effectiveok = 1;
13052+ if (fs == -1)
13053+ fsok = 1;
13054+
13055+ if (current->acl->user_trans_type & GR_ID_ALLOW) {
13056+ for (i = 0; i < num; i++) {
13057+ curuid = (int)uidlist[i];
13058+ if (real == curuid)
13059+ realok = 1;
13060+ if (effective == curuid)
13061+ effectiveok = 1;
13062+ if (fs == curuid)
13063+ fsok = 1;
13064+ }
13065+ } else if (current->acl->user_trans_type & GR_ID_DENY) {
13066+ for (i = 0; i < num; i++) {
13067+ curuid = (int)uidlist[i];
13068+ if (real == curuid)
13069+ break;
13070+ if (effective == curuid)
13071+ break;
13072+ if (fs == curuid)
13073+ break;
13074+ }
13075+ /* not in deny list */
13076+ if (i == num) {
13077+ realok = 1;
13078+ effectiveok = 1;
13079+ fsok = 1;
13080+ }
13081+ }
13082+
13083+ if (realok && effectiveok && fsok)
13084+ return 0;
13085+ else {
13086+ gr_log_int(GR_DONT_AUDIT, GR_USRCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real);
13087+ return 1;
13088+ }
13089+}
13090+
13091+int
13092+gr_check_group_change(int real, int effective, int fs)
13093+{
13094+ unsigned int i;
13095+ __u16 num;
13096+ gid_t *gidlist;
13097+ int curgid;
13098+ int realok = 0;
13099+ int effectiveok = 0;
13100+ int fsok = 0;
13101+
13102+ if (unlikely(!(gr_status & GR_READY)))
13103+ return 0;
13104+
13105+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
13106+ gr_log_learn_id_change(current, 'g', real, effective, fs);
13107+
13108+ num = current->acl->group_trans_num;
13109+ gidlist = current->acl->group_transitions;
13110+
13111+ if (gidlist == NULL)
13112+ return 0;
13113+
13114+ if (real == -1)
13115+ realok = 1;
13116+ if (effective == -1)
13117+ effectiveok = 1;
13118+ if (fs == -1)
13119+ fsok = 1;
13120+
13121+ if (current->acl->group_trans_type & GR_ID_ALLOW) {
13122+ for (i = 0; i < num; i++) {
13123+ curgid = (int)gidlist[i];
13124+ if (real == curgid)
13125+ realok = 1;
13126+ if (effective == curgid)
13127+ effectiveok = 1;
13128+ if (fs == curgid)
13129+ fsok = 1;
13130+ }
13131+ } else if (current->acl->group_trans_type & GR_ID_DENY) {
13132+ for (i = 0; i < num; i++) {
13133+ curgid = (int)gidlist[i];
13134+ if (real == curgid)
13135+ break;
13136+ if (effective == curgid)
13137+ break;
13138+ if (fs == curgid)
13139+ break;
13140+ }
13141+ /* not in deny list */
13142+ if (i == num) {
13143+ realok = 1;
13144+ effectiveok = 1;
13145+ fsok = 1;
13146+ }
13147+ }
13148+
13149+ if (realok && effectiveok && fsok)
13150+ return 0;
13151+ else {
13152+ gr_log_int(GR_DONT_AUDIT, GR_GRPCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real);
13153+ return 1;
13154+ }
13155+}
13156+
13157+void
13158+gr_set_role_label(struct task_struct *task, const uid_t uid, const uid_t gid)
13159+{
13160+ struct acl_role_label *role = task->role;
13161+ struct acl_subject_label *subj = NULL;
13162+ struct acl_object_label *obj;
13163+ struct file *filp;
13164+
13165+ if (unlikely(!(gr_status & GR_READY)))
13166+ return;
13167+
13168+ filp = task->exec_file;
13169+
13170+ /* kernel process, we'll give them the kernel role */
13171+ if (unlikely(!filp)) {
13172+ task->role = kernel_role;
13173+ task->acl = kernel_role->root_label;
13174+ return;
13175+ } else if (!task->role || !(task->role->roletype & GR_ROLE_SPECIAL))
13176+ role = lookup_acl_role_label(task, uid, gid);
13177+
13178+ /* perform subject lookup in possibly new role
13179+ we can use this result below in the case where role == task->role
13180+ */
13181+ subj = chk_subj_label(filp->f_dentry, filp->f_vfsmnt, role);
13182+
13183+ /* if we changed uid/gid, but result in the same role
13184+ and are using inheritance, don't lose the inherited subject
13185+ if current subject is other than what normal lookup
13186+ would result in, we arrived via inheritance, don't
13187+ lose subject
13188+ */
13189+ if (role != task->role || (!(task->acl->mode & GR_INHERITLEARN) &&
13190+ (subj == task->acl)))
13191+ task->acl = subj;
13192+
13193+ task->role = role;
13194+
13195+ task->is_writable = 0;
13196+
13197+ /* ignore additional mmap checks for processes that are writable
13198+ by the default ACL */
13199+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
13200+ if (unlikely(obj->mode & GR_WRITE))
13201+ task->is_writable = 1;
13202+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label);
13203+ if (unlikely(obj->mode & GR_WRITE))
13204+ task->is_writable = 1;
13205+
13206+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
13207+ printk(KERN_ALERT "Set role label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
13208+#endif
13209+
13210+ gr_set_proc_res(task);
13211+
13212+ return;
13213+}
13214+
13215+int
13216+gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
13217+{
13218+ struct task_struct *task = current;
13219+ struct acl_subject_label *newacl;
13220+ struct acl_object_label *obj;
13221+ __u32 retmode;
13222+
13223+ if (unlikely(!(gr_status & GR_READY)))
13224+ return 0;
13225+
13226+ newacl = chk_subj_label(dentry, mnt, task->role);
13227+
13228+ task_lock(task);
13229+ if (((task->ptrace & PT_PTRACED) && !(task->acl->mode &
13230+ GR_POVERRIDE) && (task->acl != newacl) &&
13231+ !(task->role->roletype & GR_ROLE_GOD) &&
13232+ !gr_search_file(dentry, GR_PTRACERD, mnt) &&
13233+ !(task->acl->mode & (GR_LEARN | GR_INHERITLEARN))) ||
13234+ (atomic_read(&task->fs->count) > 1 ||
13235+ atomic_read(&task->files->count) > 1 ||
13236+ atomic_read(&task->sighand->count) > 1)) {
13237+ task_unlock(task);
13238+ gr_log_fs_generic(GR_DONT_AUDIT, GR_PTRACE_EXEC_ACL_MSG, dentry, mnt);
13239+ return -EACCES;
13240+ }
13241+ task_unlock(task);
13242+
13243+ obj = chk_obj_label(dentry, mnt, task->acl);
13244+ retmode = obj->mode & (GR_INHERIT | GR_AUDIT_INHERIT);
13245+
13246+ if (!(task->acl->mode & GR_INHERITLEARN) &&
13247+ ((newacl->mode & GR_LEARN) || !(retmode & GR_INHERIT))) {
13248+ if (obj->nested)
13249+ task->acl = obj->nested;
13250+ else
13251+ task->acl = newacl;
13252+ } else if (retmode & GR_INHERIT && retmode & GR_AUDIT_INHERIT)
13253+ gr_log_str_fs(GR_DO_AUDIT, GR_INHERIT_ACL_MSG, task->acl->filename, dentry, mnt);
13254+
13255+ task->is_writable = 0;
13256+
13257+ /* ignore additional mmap checks for processes that are writable
13258+ by the default ACL */
13259+ obj = chk_obj_label(dentry, mnt, default_role->root_label);
13260+ if (unlikely(obj->mode & GR_WRITE))
13261+ task->is_writable = 1;
13262+ obj = chk_obj_label(dentry, mnt, task->role->root_label);
13263+ if (unlikely(obj->mode & GR_WRITE))
13264+ task->is_writable = 1;
13265+
13266+ gr_set_proc_res(task);
13267+
13268+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
13269+ printk(KERN_ALERT "Set subject label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
13270+#endif
13271+ return 0;
13272+}
13273+
13274+static void
13275+do_handle_delete(const ino_t ino, const dev_t dev)
13276+{
13277+ struct acl_object_label *matchpo;
13278+ struct acl_subject_label *matchps;
13279+ struct acl_subject_label *subj;
13280+ struct acl_role_label *role;
13281+ unsigned int i, x;
13282+
13283+ FOR_EACH_ROLE_START(role, i)
13284+ FOR_EACH_SUBJECT_START(role, subj, x)
13285+ if ((matchpo = lookup_acl_obj_label(ino, dev, subj)) != NULL)
13286+ matchpo->mode |= GR_DELETED;
13287+ FOR_EACH_SUBJECT_END(subj,x)
13288+ FOR_EACH_NESTED_SUBJECT_START(role, subj)
13289+ if (subj->inode == ino && subj->device == dev)
13290+ subj->mode |= GR_DELETED;
13291+ FOR_EACH_NESTED_SUBJECT_END(subj)
13292+ if ((matchps = lookup_acl_subj_label(ino, dev, role)) != NULL)
13293+ matchps->mode |= GR_DELETED;
13294+ FOR_EACH_ROLE_END(role,i)
13295+
13296+ return;
13297+}
13298+
13299+void
13300+gr_handle_delete(const ino_t ino, const dev_t dev)
13301+{
13302+ if (unlikely(!(gr_status & GR_READY)))
13303+ return;
13304+
13305+ write_lock(&gr_inode_lock);
13306+ if (unlikely((unsigned long)lookup_inodev_entry(ino, dev)))
13307+ do_handle_delete(ino, dev);
13308+ write_unlock(&gr_inode_lock);
13309+
13310+ return;
13311+}
13312+
13313+static void
13314+update_acl_obj_label(const ino_t oldinode, const dev_t olddevice,
13315+ const ino_t newinode, const dev_t newdevice,
13316+ struct acl_subject_label *subj)
13317+{
13318+ unsigned int index = fhash(oldinode, olddevice, subj->obj_hash_size);
13319+ struct acl_object_label *match;
13320+
13321+ match = subj->obj_hash[index];
13322+
13323+ while (match && (match->inode != oldinode ||
13324+ match->device != olddevice ||
13325+ !(match->mode & GR_DELETED)))
13326+ match = match->next;
13327+
13328+ if (match && (match->inode == oldinode)
13329+ && (match->device == olddevice)
13330+ && (match->mode & GR_DELETED)) {
13331+ if (match->prev == NULL) {
13332+ subj->obj_hash[index] = match->next;
13333+ if (match->next != NULL)
13334+ match->next->prev = NULL;
13335+ } else {
13336+ match->prev->next = match->next;
13337+ if (match->next != NULL)
13338+ match->next->prev = match->prev;
13339+ }
13340+ match->prev = NULL;
13341+ match->next = NULL;
13342+ match->inode = newinode;
13343+ match->device = newdevice;
13344+ match->mode &= ~GR_DELETED;
13345+
13346+ insert_acl_obj_label(match, subj);
13347+ }
13348+
13349+ return;
13350+}
13351+
13352+static void
13353+update_acl_subj_label(const ino_t oldinode, const dev_t olddevice,
13354+ const ino_t newinode, const dev_t newdevice,
13355+ struct acl_role_label *role)
13356+{
13357+ unsigned int index = fhash(oldinode, olddevice, role->subj_hash_size);
13358+ struct acl_subject_label *match;
13359+
13360+ match = role->subj_hash[index];
13361+
13362+ while (match && (match->inode != oldinode ||
13363+ match->device != olddevice ||
13364+ !(match->mode & GR_DELETED)))
13365+ match = match->next;
13366+
13367+ if (match && (match->inode == oldinode)
13368+ && (match->device == olddevice)
13369+ && (match->mode & GR_DELETED)) {
13370+ if (match->prev == NULL) {
13371+ role->subj_hash[index] = match->next;
13372+ if (match->next != NULL)
13373+ match->next->prev = NULL;
13374+ } else {
13375+ match->prev->next = match->next;
13376+ if (match->next != NULL)
13377+ match->next->prev = match->prev;
13378+ }
13379+ match->prev = NULL;
13380+ match->next = NULL;
13381+ match->inode = newinode;
13382+ match->device = newdevice;
13383+ match->mode &= ~GR_DELETED;
13384+
13385+ insert_acl_subj_label(match, role);
13386+ }
13387+
13388+ return;
13389+}
13390+
13391+static void
13392+update_inodev_entry(const ino_t oldinode, const dev_t olddevice,
13393+ const ino_t newinode, const dev_t newdevice)
13394+{
13395+ unsigned int index = fhash(oldinode, olddevice, inodev_set.i_size);
13396+ struct inodev_entry *match;
13397+
13398+ match = inodev_set.i_hash[index];
13399+
13400+ while (match && (match->nentry->inode != oldinode ||
13401+ match->nentry->device != olddevice))
13402+ match = match->next;
13403+
13404+ if (match && (match->nentry->inode == oldinode)
13405+ && (match->nentry->device == olddevice)) {
13406+ if (match->prev == NULL) {
13407+ inodev_set.i_hash[index] = match->next;
13408+ if (match->next != NULL)
13409+ match->next->prev = NULL;
13410+ } else {
13411+ match->prev->next = match->next;
13412+ if (match->next != NULL)
13413+ match->next->prev = match->prev;
13414+ }
13415+ match->prev = NULL;
13416+ match->next = NULL;
13417+ match->nentry->inode = newinode;
13418+ match->nentry->device = newdevice;
13419+
13420+ insert_inodev_entry(match);
13421+ }
13422+
13423+ return;
13424+}
13425+
13426+static void
13427+do_handle_create(const struct name_entry *matchn, const struct dentry *dentry,
13428+ const struct vfsmount *mnt)
13429+{
13430+ struct acl_subject_label *subj;
13431+ struct acl_role_label *role;
13432+ unsigned int i, x;
13433+
13434+ FOR_EACH_ROLE_START(role, i)
13435+ update_acl_subj_label(matchn->inode, matchn->device,
13436+ dentry->d_inode->i_ino,
13437+ dentry->d_inode->i_sb->s_dev, role);
13438+
13439+ FOR_EACH_NESTED_SUBJECT_START(role, subj)
13440+ if ((subj->inode == dentry->d_inode->i_ino) &&
13441+ (subj->device == dentry->d_inode->i_sb->s_dev)) {
13442+ subj->inode = dentry->d_inode->i_ino;
13443+ subj->device = dentry->d_inode->i_sb->s_dev;
13444+ }
13445+ FOR_EACH_NESTED_SUBJECT_END(subj)
13446+ FOR_EACH_SUBJECT_START(role, subj, x)
13447+ update_acl_obj_label(matchn->inode, matchn->device,
13448+ dentry->d_inode->i_ino,
13449+ dentry->d_inode->i_sb->s_dev, subj);
13450+ FOR_EACH_SUBJECT_END(subj,x)
13451+ FOR_EACH_ROLE_END(role,i)
13452+
13453+ update_inodev_entry(matchn->inode, matchn->device,
13454+ dentry->d_inode->i_ino, dentry->d_inode->i_sb->s_dev);
13455+
13456+ return;
13457+}
13458+
13459+void
13460+gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
13461+{
13462+ struct name_entry *matchn;
13463+
13464+ if (unlikely(!(gr_status & GR_READY)))
13465+ return;
13466+
13467+ preempt_disable();
13468+ matchn = lookup_name_entry(gr_to_filename_rbac(dentry, mnt));
13469+
13470+ if (unlikely((unsigned long)matchn)) {
13471+ write_lock(&gr_inode_lock);
13472+ do_handle_create(matchn, dentry, mnt);
13473+ write_unlock(&gr_inode_lock);
13474+ }
13475+ preempt_enable();
13476+
13477+ return;
13478+}
13479+
13480+void
13481+gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
13482+ struct dentry *old_dentry,
13483+ struct dentry *new_dentry,
13484+ struct vfsmount *mnt, const __u8 replace)
13485+{
13486+ struct name_entry *matchn;
13487+
13488+ if (unlikely(!(gr_status & GR_READY)))
13489+ return;
13490+
13491+ preempt_disable();
13492+ matchn = lookup_name_entry(gr_to_filename_rbac(new_dentry, mnt));
13493+
13494+ /* we wouldn't have to check d_inode if it weren't for
13495+ NFS silly-renaming
13496+ */
13497+
13498+ write_lock(&gr_inode_lock);
13499+ if (unlikely(replace && new_dentry->d_inode)) {
13500+ if (unlikely(lookup_inodev_entry(new_dentry->d_inode->i_ino,
13501+ new_dentry->d_inode->i_sb->s_dev) &&
13502+ (old_dentry->d_inode->i_nlink <= 1)))
13503+ do_handle_delete(new_dentry->d_inode->i_ino,
13504+ new_dentry->d_inode->i_sb->s_dev);
13505+ }
13506+
13507+ if (unlikely(lookup_inodev_entry(old_dentry->d_inode->i_ino,
13508+ old_dentry->d_inode->i_sb->s_dev) &&
13509+ (old_dentry->d_inode->i_nlink <= 1)))
13510+ do_handle_delete(old_dentry->d_inode->i_ino,
13511+ old_dentry->d_inode->i_sb->s_dev);
13512+
13513+ if (unlikely((unsigned long)matchn))
13514+ do_handle_create(matchn, old_dentry, mnt);
13515+
13516+ write_unlock(&gr_inode_lock);
13517+ preempt_enable();
13518+
13519+ return;
13520+}
13521+
13522+static int
13523+lookup_special_role_auth(__u16 mode, const char *rolename, unsigned char **salt,
13524+ unsigned char **sum)
13525+{
13526+ struct acl_role_label *r;
13527+ struct role_allowed_ip *ipp;
13528+ struct role_transition *trans;
13529+ unsigned int i;
13530+ int found = 0;
13531+
13532+ /* check transition table */
13533+
13534+ for (trans = current->role->transitions; trans; trans = trans->next) {
13535+ if (!strcmp(rolename, trans->rolename)) {
13536+ found = 1;
13537+ break;
13538+ }
13539+ }
13540+
13541+ if (!found)
13542+ return 0;
13543+
13544+ /* handle special roles that do not require authentication
13545+ and check ip */
13546+
13547+ FOR_EACH_ROLE_START(r, i)
13548+ if (!strcmp(rolename, r->rolename) &&
13549+ (r->roletype & GR_ROLE_SPECIAL)) {
13550+ found = 0;
13551+ if (r->allowed_ips != NULL) {
13552+ for (ipp = r->allowed_ips; ipp; ipp = ipp->next) {
13553+ if ((ntohl(current->signal->curr_ip) & ipp->netmask) ==
13554+ (ntohl(ipp->addr) & ipp->netmask))
13555+ found = 1;
13556+ }
13557+ } else
13558+ found = 2;
13559+ if (!found)
13560+ return 0;
13561+
13562+ if (((mode == SPROLE) && (r->roletype & GR_ROLE_NOPW)) ||
13563+ ((mode == SPROLEPAM) && (r->roletype & GR_ROLE_PAM))) {
13564+ *salt = NULL;
13565+ *sum = NULL;
13566+ return 1;
13567+ }
13568+ }
13569+ FOR_EACH_ROLE_END(r,i)
13570+
13571+ for (i = 0; i < num_sprole_pws; i++) {
13572+ if (!strcmp(rolename, acl_special_roles[i]->rolename)) {
13573+ *salt = acl_special_roles[i]->salt;
13574+ *sum = acl_special_roles[i]->sum;
13575+ return 1;
13576+ }
13577+ }
13578+
13579+ return 0;
13580+}
13581+
13582+static void
13583+assign_special_role(char *rolename)
13584+{
13585+ struct acl_object_label *obj;
13586+ struct acl_role_label *r;
13587+ struct acl_role_label *assigned = NULL;
13588+ struct task_struct *tsk;
13589+ struct file *filp;
13590+ unsigned int i;
13591+
13592+ FOR_EACH_ROLE_START(r, i)
13593+ if (!strcmp(rolename, r->rolename) &&
13594+ (r->roletype & GR_ROLE_SPECIAL))
13595+ assigned = r;
13596+ FOR_EACH_ROLE_END(r,i)
13597+
13598+ if (!assigned)
13599+ return;
13600+
13601+ read_lock(&tasklist_lock);
13602+ read_lock(&grsec_exec_file_lock);
13603+
13604+ tsk = current->parent;
13605+ if (tsk == NULL)
13606+ goto out_unlock;
13607+
13608+ filp = tsk->exec_file;
13609+ if (filp == NULL)
13610+ goto out_unlock;
13611+
13612+ tsk->is_writable = 0;
13613+
13614+ tsk->acl_sp_role = 1;
13615+ tsk->acl_role_id = ++acl_sp_role_value;
13616+ tsk->role = assigned;
13617+ tsk->acl = chk_subj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role);
13618+
13619+ /* ignore additional mmap checks for processes that are writable
13620+ by the default ACL */
13621+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
13622+ if (unlikely(obj->mode & GR_WRITE))
13623+ tsk->is_writable = 1;
13624+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role->root_label);
13625+ if (unlikely(obj->mode & GR_WRITE))
13626+ tsk->is_writable = 1;
13627+
13628+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
13629+ printk(KERN_ALERT "Assigning special role:%s subject:%s to process (%s:%d)\n", tsk->role->rolename, tsk->acl->filename, tsk->comm, tsk->pid);
13630+#endif
13631+
13632+out_unlock:
13633+ read_unlock(&grsec_exec_file_lock);
13634+ read_unlock(&tasklist_lock);
13635+ return;
13636+}
13637+
13638+int gr_check_secure_terminal(struct task_struct *task)
13639+{
13640+ struct task_struct *p, *p2, *p3;
13641+ struct files_struct *files;
13642+ struct fdtable *fdt;
13643+ struct file *our_file = NULL, *file;
13644+ int i;
13645+
13646+ if (task->signal->tty == NULL)
13647+ return 1;
13648+
13649+ files = get_files_struct(task);
13650+ if (files != NULL) {
13651+ rcu_read_lock();
13652+ fdt = files_fdtable(files);
13653+ for (i=0; i < fdt->max_fds; i++) {
13654+ file = fcheck_files(files, i);
13655+ if (file && (our_file == NULL) && (file->private_data == task->signal->tty)) {
13656+ get_file(file);
13657+ our_file = file;
13658+ }
13659+ }
13660+ rcu_read_unlock();
13661+ put_files_struct(files);
13662+ }
13663+
13664+ if (our_file == NULL)
13665+ return 1;
13666+
13667+ read_lock(&tasklist_lock);
13668+ do_each_thread(p2, p) {
13669+ files = get_files_struct(p);
13670+ if (files == NULL ||
13671+ (p->signal && p->signal->tty == task->signal->tty)) {
13672+ if (files != NULL)
13673+ put_files_struct(files);
13674+ continue;
13675+ }
13676+ rcu_read_lock();
13677+ fdt = files_fdtable(files);
13678+ for (i=0; i < fdt->max_fds; i++) {
13679+ file = fcheck_files(files, i);
13680+ if (file && S_ISCHR(file->f_dentry->d_inode->i_mode) &&
13681+ file->f_dentry->d_inode->i_rdev == our_file->f_dentry->d_inode->i_rdev) {
13682+ p3 = task;
13683+ while (p3->pid > 0) {
13684+ if (p3 == p)
13685+ break;
13686+ p3 = p3->parent;
13687+ }
13688+ if (p3 == p)
13689+ break;
13690+ gr_log_ttysniff(GR_DONT_AUDIT_GOOD, GR_TTYSNIFF_ACL_MSG, p);
13691+ gr_handle_alertkill(p);
13692+ rcu_read_unlock();
13693+ put_files_struct(files);
13694+ read_unlock(&tasklist_lock);
13695+ fput(our_file);
13696+ return 0;
13697+ }
13698+ }
13699+ rcu_read_unlock();
13700+ put_files_struct(files);
13701+ } while_each_thread(p2, p);
13702+ read_unlock(&tasklist_lock);
13703+
13704+ fput(our_file);
13705+ return 1;
13706+}
13707+
13708+ssize_t
13709+write_grsec_handler(struct file *file, const char * buf, size_t count, loff_t *ppos)
13710+{
13711+ struct gr_arg_wrapper uwrap;
13712+ unsigned char *sprole_salt;
13713+ unsigned char *sprole_sum;
13714+ int error = sizeof (struct gr_arg_wrapper);
13715+ int error2 = 0;
13716+
13717+ down(&gr_dev_sem);
13718+
13719+ if ((gr_status & GR_READY) && !(current->acl->mode & GR_KERNELAUTH)) {
13720+ error = -EPERM;
13721+ goto out;
13722+ }
13723+
13724+ if (count != sizeof (struct gr_arg_wrapper)) {
13725+ gr_log_int_int(GR_DONT_AUDIT_GOOD, GR_DEV_ACL_MSG, (int)count, (int)sizeof(struct gr_arg_wrapper));
13726+ error = -EINVAL;
13727+ goto out;
13728+ }
13729+
13730+
13731+ if (gr_auth_expires && time_after_eq(get_seconds(), gr_auth_expires)) {
13732+ gr_auth_expires = 0;
13733+ gr_auth_attempts = 0;
13734+ }
13735+
13736+ if (copy_from_user(&uwrap, buf, sizeof (struct gr_arg_wrapper))) {
13737+ error = -EFAULT;
13738+ goto out;
13739+ }
13740+
13741+ if ((uwrap.version != GRSECURITY_VERSION) || (uwrap.size != sizeof(struct gr_arg))) {
13742+ error = -EINVAL;
13743+ goto out;
13744+ }
13745+
13746+ if (copy_from_user(gr_usermode, uwrap.arg, sizeof (struct gr_arg))) {
13747+ error = -EFAULT;
13748+ goto out;
13749+ }
13750+
13751+ if (gr_usermode->mode != SPROLE && gr_usermode->mode != SPROLEPAM &&
13752+ gr_auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES &&
13753+ time_after(gr_auth_expires, get_seconds())) {
13754+ error = -EBUSY;
13755+ goto out;
13756+ }
13757+
13758+ /* if non-root trying to do anything other than use a special role,
13759+ do not attempt authentication, do not count towards authentication
13760+ locking
13761+ */
13762+
13763+ if (gr_usermode->mode != SPROLE && gr_usermode->mode != STATUS &&
13764+ gr_usermode->mode != UNSPROLE && gr_usermode->mode != SPROLEPAM &&
13765+ current->uid) {
13766+ error = -EPERM;
13767+ goto out;
13768+ }
13769+
13770+ /* ensure pw and special role name are null terminated */
13771+
13772+ gr_usermode->pw[GR_PW_LEN - 1] = '\0';
13773+ gr_usermode->sp_role[GR_SPROLE_LEN - 1] = '\0';
13774+
13775+ /* Okay.
13776+ * We have our enough of the argument structure..(we have yet
13777+ * to copy_from_user the tables themselves) . Copy the tables
13778+ * only if we need them, i.e. for loading operations. */
13779+
13780+ switch (gr_usermode->mode) {
13781+ case STATUS:
13782+ if (gr_status & GR_READY) {
13783+ error = 1;
13784+ if (!gr_check_secure_terminal(current))
13785+ error = 3;
13786+ } else
13787+ error = 2;
13788+ goto out;
13789+ case SHUTDOWN:
13790+ if ((gr_status & GR_READY)
13791+ && !(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
13792+ gr_status &= ~GR_READY;
13793+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTS_ACL_MSG);
13794+ free_variables();
13795+ memset(gr_usermode, 0, sizeof (struct gr_arg));
13796+ memset(gr_system_salt, 0, GR_SALT_LEN);
13797+ memset(gr_system_sum, 0, GR_SHA_LEN);
13798+ } else if (gr_status & GR_READY) {
13799+ gr_log_noargs(GR_DONT_AUDIT, GR_SHUTF_ACL_MSG);
13800+ error = -EPERM;
13801+ } else {
13802+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTI_ACL_MSG);
13803+ error = -EAGAIN;
13804+ }
13805+ break;
13806+ case ENABLE:
13807+ if (!(gr_status & GR_READY) && !(error2 = gracl_init(gr_usermode)))
13808+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_ENABLE_ACL_MSG, GR_VERSION);
13809+ else {
13810+ if (gr_status & GR_READY)
13811+ error = -EAGAIN;
13812+ else
13813+ error = error2;
13814+ gr_log_str(GR_DONT_AUDIT, GR_ENABLEF_ACL_MSG, GR_VERSION);
13815+ }
13816+ break;
13817+ case RELOAD:
13818+ if (!(gr_status & GR_READY)) {
13819+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOADI_ACL_MSG, GR_VERSION);
13820+ error = -EAGAIN;
13821+ } else if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
13822+ lock_kernel();
13823+ gr_status &= ~GR_READY;
13824+ free_variables();
13825+ if (!(error2 = gracl_init(gr_usermode))) {
13826+ unlock_kernel();
13827+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOAD_ACL_MSG, GR_VERSION);
13828+ } else {
13829+ unlock_kernel();
13830+ error = error2;
13831+ gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION);
13832+ }
13833+ } else {
13834+ gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION);
13835+ error = -EPERM;
13836+ }
13837+ break;
13838+ case SEGVMOD:
13839+ if (unlikely(!(gr_status & GR_READY))) {
13840+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODI_ACL_MSG);
13841+ error = -EAGAIN;
13842+ break;
13843+ }
13844+
13845+ if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
13846+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODS_ACL_MSG);
13847+ if (gr_usermode->segv_device && gr_usermode->segv_inode) {
13848+ struct acl_subject_label *segvacl;
13849+ segvacl =
13850+ lookup_acl_subj_label(gr_usermode->segv_inode,
13851+ gr_usermode->segv_device,
13852+ current->role);
13853+ if (segvacl) {
13854+ segvacl->crashes = 0;
13855+ segvacl->expires = 0;
13856+ }
13857+ } else if (gr_find_uid(gr_usermode->segv_uid) >= 0) {
13858+ gr_remove_uid(gr_usermode->segv_uid);
13859+ }
13860+ } else {
13861+ gr_log_noargs(GR_DONT_AUDIT, GR_SEGVMODF_ACL_MSG);
13862+ error = -EPERM;
13863+ }
13864+ break;
13865+ case SPROLE:
13866+ case SPROLEPAM:
13867+ if (unlikely(!(gr_status & GR_READY))) {
13868+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SPROLEI_ACL_MSG);
13869+ error = -EAGAIN;
13870+ break;
13871+ }
13872+
13873+ if (current->role->expires && time_after_eq(get_seconds(), current->role->expires)) {
13874+ current->role->expires = 0;
13875+ current->role->auth_attempts = 0;
13876+ }
13877+
13878+ if (current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES &&
13879+ time_after(current->role->expires, get_seconds())) {
13880+ error = -EBUSY;
13881+ goto out;
13882+ }
13883+
13884+ if (lookup_special_role_auth
13885+ (gr_usermode->mode, gr_usermode->sp_role, &sprole_salt, &sprole_sum)
13886+ && ((!sprole_salt && !sprole_sum)
13887+ || !(chkpw(gr_usermode, sprole_salt, sprole_sum)))) {
13888+ char *p = "";
13889+ assign_special_role(gr_usermode->sp_role);
13890+ read_lock(&tasklist_lock);
13891+ if (current->parent)
13892+ p = current->parent->role->rolename;
13893+ read_unlock(&tasklist_lock);
13894+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLES_ACL_MSG,
13895+ p, acl_sp_role_value);
13896+ } else {
13897+ gr_log_str(GR_DONT_AUDIT, GR_SPROLEF_ACL_MSG, gr_usermode->sp_role);
13898+ error = -EPERM;
13899+ if(!(current->role->auth_attempts++))
13900+ current->role->expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT;
13901+
13902+ goto out;
13903+ }
13904+ break;
13905+ case UNSPROLE:
13906+ if (unlikely(!(gr_status & GR_READY))) {
13907+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_UNSPROLEI_ACL_MSG);
13908+ error = -EAGAIN;
13909+ break;
13910+ }
13911+
13912+ if (current->role->roletype & GR_ROLE_SPECIAL) {
13913+ char *p = "";
13914+ int i = 0;
13915+
13916+ read_lock(&tasklist_lock);
13917+ if (current->parent) {
13918+ p = current->parent->role->rolename;
13919+ i = current->parent->acl_role_id;
13920+ }
13921+ read_unlock(&tasklist_lock);
13922+
13923+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_UNSPROLES_ACL_MSG, p, i);
13924+ gr_set_acls(1);
13925+ } else {
13926+ gr_log_str(GR_DONT_AUDIT, GR_UNSPROLEF_ACL_MSG, current->role->rolename);
13927+ error = -EPERM;
13928+ goto out;
13929+ }
13930+ break;
13931+ default:
13932+ gr_log_int(GR_DONT_AUDIT, GR_INVMODE_ACL_MSG, gr_usermode->mode);
13933+ error = -EINVAL;
13934+ break;
13935+ }
13936+
13937+ if (error != -EPERM)
13938+ goto out;
13939+
13940+ if(!(gr_auth_attempts++))
13941+ gr_auth_expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT;
13942+
13943+ out:
13944+ up(&gr_dev_sem);
13945+ return error;
13946+}
13947+
13948+int
13949+gr_set_acls(const int type)
13950+{
13951+ struct acl_object_label *obj;
13952+ struct task_struct *task, *task2;
13953+ struct file *filp;
13954+ struct acl_role_label *role = current->role;
13955+ __u16 acl_role_id = current->acl_role_id;
13956+
13957+ read_lock(&tasklist_lock);
13958+ read_lock(&grsec_exec_file_lock);
13959+ do_each_thread(task2, task) {
13960+ /* check to see if we're called from the exit handler,
13961+ if so, only replace ACLs that have inherited the admin
13962+ ACL */
13963+
13964+ if (type && (task->role != role ||
13965+ task->acl_role_id != acl_role_id))
13966+ continue;
13967+
13968+ task->acl_role_id = 0;
13969+ task->acl_sp_role = 0;
13970+
13971+ if ((filp = task->exec_file)) {
13972+ task->role = lookup_acl_role_label(task, task->uid, task->gid);
13973+
13974+ task->acl =
13975+ chk_subj_label(filp->f_dentry, filp->f_vfsmnt,
13976+ task->role);
13977+ if (task->acl) {
13978+ struct acl_subject_label *curr;
13979+ curr = task->acl;
13980+
13981+ task->is_writable = 0;
13982+ /* ignore additional mmap checks for processes that are writable
13983+ by the default ACL */
13984+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
13985+ if (unlikely(obj->mode & GR_WRITE))
13986+ task->is_writable = 1;
13987+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label);
13988+ if (unlikely(obj->mode & GR_WRITE))
13989+ task->is_writable = 1;
13990+
13991+ gr_set_proc_res(task);
13992+
13993+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
13994+ printk(KERN_ALERT "gr_set_acls for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
13995+#endif
13996+ } else {
13997+ read_unlock(&grsec_exec_file_lock);
13998+ read_unlock(&tasklist_lock);
13999+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_DEFACL_MSG, task->comm, task->pid);
14000+ return 1;
14001+ }
14002+ } else {
14003+ // it's a kernel process
14004+ task->role = kernel_role;
14005+ task->acl = kernel_role->root_label;
14006+#ifdef CONFIG_GRKERNSEC_ACL_HIDEKERN
14007+ task->acl->mode &= ~GR_PROCFIND;
14008+#endif
14009+ }
14010+ } while_each_thread(task2, task);
14011+ read_unlock(&grsec_exec_file_lock);
14012+ read_unlock(&tasklist_lock);
14013+ return 0;
14014+}
14015+
14016+void
14017+gr_learn_resource(const struct task_struct *task,
14018+ const int res, const unsigned long wanted, const int gt)
14019+{
14020+ struct acl_subject_label *acl;
14021+
14022+ if (unlikely((gr_status & GR_READY) &&
14023+ task->acl && (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))))
14024+ goto skip_reslog;
14025+
14026+#ifdef CONFIG_GRKERNSEC_RESLOG
14027+ gr_log_resource(task, res, wanted, gt);
14028+#endif
14029+ skip_reslog:
14030+
14031+ if (unlikely(!(gr_status & GR_READY) || !wanted))
14032+ return;
14033+
14034+ acl = task->acl;
14035+
14036+ if (likely(!acl || !(acl->mode & (GR_LEARN | GR_INHERITLEARN)) ||
14037+ !(acl->resmask & (1 << (unsigned short) res))))
14038+ return;
14039+
14040+ if (wanted >= acl->res[res].rlim_cur) {
14041+ unsigned long res_add;
14042+
14043+ res_add = wanted;
14044+ switch (res) {
14045+ case RLIMIT_CPU:
14046+ res_add += GR_RLIM_CPU_BUMP;
14047+ break;
14048+ case RLIMIT_FSIZE:
14049+ res_add += GR_RLIM_FSIZE_BUMP;
14050+ break;
14051+ case RLIMIT_DATA:
14052+ res_add += GR_RLIM_DATA_BUMP;
14053+ break;
14054+ case RLIMIT_STACK:
14055+ res_add += GR_RLIM_STACK_BUMP;
14056+ break;
14057+ case RLIMIT_CORE:
14058+ res_add += GR_RLIM_CORE_BUMP;
14059+ break;
14060+ case RLIMIT_RSS:
14061+ res_add += GR_RLIM_RSS_BUMP;
14062+ break;
14063+ case RLIMIT_NPROC:
14064+ res_add += GR_RLIM_NPROC_BUMP;
14065+ break;
14066+ case RLIMIT_NOFILE:
14067+ res_add += GR_RLIM_NOFILE_BUMP;
14068+ break;
14069+ case RLIMIT_MEMLOCK:
14070+ res_add += GR_RLIM_MEMLOCK_BUMP;
14071+ break;
14072+ case RLIMIT_AS:
14073+ res_add += GR_RLIM_AS_BUMP;
14074+ break;
14075+ case RLIMIT_LOCKS:
14076+ res_add += GR_RLIM_LOCKS_BUMP;
14077+ break;
14078+ }
14079+
14080+ acl->res[res].rlim_cur = res_add;
14081+
14082+ if (wanted > acl->res[res].rlim_max)
14083+ acl->res[res].rlim_max = res_add;
14084+
14085+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
14086+ task->role->roletype, acl->filename,
14087+ acl->res[res].rlim_cur, acl->res[res].rlim_max,
14088+ "", (unsigned long) res);
14089+ }
14090+
14091+ return;
14092+}
14093+
14094+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
14095+void
14096+pax_set_initial_flags(struct linux_binprm *bprm)
14097+{
14098+ struct task_struct *task = current;
14099+ struct acl_subject_label *proc;
14100+ unsigned long flags;
14101+
14102+ if (unlikely(!(gr_status & GR_READY)))
14103+ return;
14104+
14105+ flags = pax_get_flags(task);
14106+
14107+ proc = task->acl;
14108+
14109+ if (proc->pax_flags & GR_PAX_DISABLE_PAGEEXEC)
14110+ flags &= ~MF_PAX_PAGEEXEC;
14111+ if (proc->pax_flags & GR_PAX_DISABLE_SEGMEXEC)
14112+ flags &= ~MF_PAX_SEGMEXEC;
14113+ if (proc->pax_flags & GR_PAX_DISABLE_RANDMMAP)
14114+ flags &= ~MF_PAX_RANDMMAP;
14115+ if (proc->pax_flags & GR_PAX_DISABLE_EMUTRAMP)
14116+ flags &= ~MF_PAX_EMUTRAMP;
14117+ if (proc->pax_flags & GR_PAX_DISABLE_MPROTECT)
14118+ flags &= ~MF_PAX_MPROTECT;
14119+
14120+ if (proc->pax_flags & GR_PAX_ENABLE_PAGEEXEC)
14121+ flags |= MF_PAX_PAGEEXEC;
14122+ if (proc->pax_flags & GR_PAX_ENABLE_SEGMEXEC)
14123+ flags |= MF_PAX_SEGMEXEC;
14124+ if (proc->pax_flags & GR_PAX_ENABLE_RANDMMAP)
14125+ flags |= MF_PAX_RANDMMAP;
14126+ if (proc->pax_flags & GR_PAX_ENABLE_EMUTRAMP)
14127+ flags |= MF_PAX_EMUTRAMP;
14128+ if (proc->pax_flags & GR_PAX_ENABLE_MPROTECT)
14129+ flags |= MF_PAX_MPROTECT;
14130+
14131+ pax_set_flags(task, flags);
14132+
14133+ return;
14134+}
14135+#endif
14136+
14137+#ifdef CONFIG_SYSCTL
14138+extern struct proc_dir_entry *proc_sys_root;
14139+
14140+/* the following function is called under the BKL */
14141+
14142+__u32
14143+gr_handle_sysctl(const struct ctl_table *table, const void *oldval,
14144+ const void *newval)
14145+{
14146+ struct proc_dir_entry *tmp;
14147+ struct nameidata nd;
14148+ const char *proc_sys = "/proc/sys";
14149+ char *path;
14150+ struct acl_object_label *obj;
14151+ unsigned short len = 0, pos = 0, depth = 0, i;
14152+ __u32 err = 0;
14153+ __u32 mode = 0;
14154+
14155+ if (unlikely(!(gr_status & GR_READY)))
14156+ return 1;
14157+
14158+ path = per_cpu_ptr(gr_shared_page[0], smp_processor_id());
14159+
14160+ if (oldval)
14161+ mode |= GR_READ;
14162+ if (newval)
14163+ mode |= GR_WRITE;
14164+
14165+ /* convert the requested sysctl entry into a pathname */
14166+
14167+ for (tmp = table->de; tmp != proc_sys_root; tmp = tmp->parent) {
14168+ len += strlen(tmp->name);
14169+ len++;
14170+ depth++;
14171+ }
14172+
14173+ if ((len + depth + strlen(proc_sys) + 1) > PAGE_SIZE)
14174+ return 0; /* deny */
14175+
14176+ memset(path, 0, PAGE_SIZE);
14177+
14178+ memcpy(path, proc_sys, strlen(proc_sys));
14179+
14180+ pos += strlen(proc_sys);
14181+
14182+ for (; depth > 0; depth--) {
14183+ path[pos] = '/';
14184+ pos++;
14185+ for (i = 1, tmp = table->de; tmp != proc_sys_root;
14186+ tmp = tmp->parent) {
14187+ if (depth == i) {
14188+ memcpy(path + pos, tmp->name,
14189+ strlen(tmp->name));
14190+ pos += strlen(tmp->name);
14191+ }
14192+ i++;
14193+ }
14194+ }
14195+
14196+ err = path_lookup(path, LOOKUP_FOLLOW, &nd);
14197+
14198+ if (err)
14199+ goto out;
14200+
14201+ obj = chk_obj_label(nd.dentry, nd.mnt, current->acl);
14202+ err = obj->mode & (mode | to_gr_audit(mode) | GR_SUPPRESS);
14203+
14204+ if (unlikely((current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) &&
14205+ ((err & mode) != mode))) {
14206+ __u32 new_mode = mode;
14207+
14208+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
14209+
14210+ err = new_mode;
14211+ gr_log_learn(current, nd.dentry, nd.mnt, new_mode);
14212+ } else if ((err & mode) != mode && !(err & GR_SUPPRESS)) {
14213+ gr_log_str4(GR_DONT_AUDIT, GR_SYSCTL_ACL_MSG, "denied",
14214+ path, (mode & GR_READ) ? " reading" : "",
14215+ (mode & GR_WRITE) ? " writing" : "");
14216+ err = 0;
14217+ } else if ((err & mode) != mode) {
14218+ err = 0;
14219+ } else if (((err & mode) == mode) && (err & GR_AUDITS)) {
14220+ gr_log_str4(GR_DO_AUDIT, GR_SYSCTL_ACL_MSG, "successful",
14221+ path, (mode & GR_READ) ? " reading" : "",
14222+ (mode & GR_WRITE) ? " writing" : "");
14223+ }
14224+
14225+ path_release(&nd);
14226+
14227+ out:
14228+ return err;
14229+}
14230+#endif
14231+
14232+int
14233+gr_handle_proc_ptrace(struct task_struct *task)
14234+{
14235+ struct file *filp;
14236+ struct task_struct *tmp = task;
14237+ struct task_struct *curtemp = current;
14238+ __u32 retmode;
14239+
14240+ if (unlikely(!(gr_status & GR_READY)))
14241+ return 0;
14242+
14243+ read_lock(&tasklist_lock);
14244+ read_lock(&grsec_exec_file_lock);
14245+ filp = task->exec_file;
14246+
14247+ while (tmp->pid > 0) {
14248+ if (tmp == curtemp)
14249+ break;
14250+ tmp = tmp->parent;
14251+ }
14252+
14253+ if (!filp || (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE))) {
14254+ read_unlock(&grsec_exec_file_lock);
14255+ read_unlock(&tasklist_lock);
14256+ return 1;
14257+ }
14258+
14259+ retmode = gr_search_file(filp->f_dentry, GR_NOPTRACE, filp->f_vfsmnt);
14260+ read_unlock(&grsec_exec_file_lock);
14261+ read_unlock(&tasklist_lock);
14262+
14263+ if (retmode & GR_NOPTRACE)
14264+ return 1;
14265+
14266+ if (!(current->acl->mode & GR_POVERRIDE) && !(current->role->roletype & GR_ROLE_GOD)
14267+ && (current->acl != task->acl || (current->acl != current->role->root_label
14268+ && current->pid != task->pid)))
14269+ return 1;
14270+
14271+ return 0;
14272+}
14273+
14274+int
14275+gr_handle_ptrace(struct task_struct *task, const long request)
14276+{
14277+ struct task_struct *tmp = task;
14278+ struct task_struct *curtemp = current;
14279+ __u32 retmode;
14280+
14281+ if (unlikely(!(gr_status & GR_READY)))
14282+ return 0;
14283+
14284+ read_lock(&tasklist_lock);
14285+ while (tmp->pid > 0) {
14286+ if (tmp == curtemp)
14287+ break;
14288+ tmp = tmp->parent;
14289+ }
14290+
14291+ if (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE)) {
14292+ read_unlock(&tasklist_lock);
14293+ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
14294+ return 1;
14295+ }
14296+ read_unlock(&tasklist_lock);
14297+
14298+ read_lock(&grsec_exec_file_lock);
14299+ if (unlikely(!task->exec_file)) {
14300+ read_unlock(&grsec_exec_file_lock);
14301+ return 0;
14302+ }
14303+
14304+ retmode = gr_search_file(task->exec_file->f_dentry, GR_PTRACERD | GR_NOPTRACE, task->exec_file->f_vfsmnt);
14305+ read_unlock(&grsec_exec_file_lock);
14306+
14307+ if (retmode & GR_NOPTRACE) {
14308+ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
14309+ return 1;
14310+ }
14311+
14312+ if (retmode & GR_PTRACERD) {
14313+ switch (request) {
14314+ case PTRACE_POKETEXT:
14315+ case PTRACE_POKEDATA:
14316+ case PTRACE_POKEUSR:
14317+#if !defined(CONFIG_PPC32) && !defined(CONFIG_PPC64) && !defined(CONFIG_PARISC) && !defined(CONFIG_ALPHA) && !defined(CONFIG_IA64)
14318+ case PTRACE_SETREGS:
14319+ case PTRACE_SETFPREGS:
14320+#endif
14321+#ifdef CONFIG_X86
14322+ case PTRACE_SETFPXREGS:
14323+#endif
14324+#ifdef CONFIG_ALTIVEC
14325+ case PTRACE_SETVRREGS:
14326+#endif
14327+ return 1;
14328+ default:
14329+ return 0;
14330+ }
14331+ } else if (!(current->acl->mode & GR_POVERRIDE) &&
14332+ !(current->role->roletype & GR_ROLE_GOD) &&
14333+ (current->acl != task->acl)) {
14334+ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
14335+ return 1;
14336+ }
14337+
14338+ return 0;
14339+}
14340+
14341+static int is_writable_mmap(const struct file *filp)
14342+{
14343+ struct task_struct *task = current;
14344+ struct acl_object_label *obj, *obj2;
14345+
14346+ if (gr_status & GR_READY && !(task->acl->mode & GR_OVERRIDE) &&
14347+ !task->is_writable && S_ISREG(filp->f_dentry->d_inode->i_mode)) {
14348+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
14349+ obj2 = chk_obj_label(filp->f_dentry, filp->f_vfsmnt,
14350+ task->role->root_label);
14351+ if (unlikely((obj->mode & GR_WRITE) || (obj2->mode & GR_WRITE))) {
14352+ gr_log_fs_generic(GR_DONT_AUDIT, GR_WRITLIB_ACL_MSG, filp->f_dentry, filp->f_vfsmnt);
14353+ return 1;
14354+ }
14355+ }
14356+ return 0;
14357+}
14358+
14359+int
14360+gr_acl_handle_mmap(const struct file *file, const unsigned long prot)
14361+{
14362+ __u32 mode;
14363+
14364+ if (unlikely(!file || !(prot & PROT_EXEC)))
14365+ return 1;
14366+
14367+ if (is_writable_mmap(file))
14368+ return 0;
14369+
14370+ mode =
14371+ gr_search_file(file->f_dentry,
14372+ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
14373+ file->f_vfsmnt);
14374+
14375+ if (!gr_tpe_allow(file))
14376+ return 0;
14377+
14378+ if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) {
14379+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MMAP_ACL_MSG, file->f_dentry, file->f_vfsmnt);
14380+ return 0;
14381+ } else if (unlikely(!(mode & GR_EXEC))) {
14382+ return 0;
14383+ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
14384+ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MMAP_ACL_MSG, file->f_dentry, file->f_vfsmnt);
14385+ return 1;
14386+ }
14387+
14388+ return 1;
14389+}
14390+
14391+int
14392+gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
14393+{
14394+ __u32 mode;
14395+
14396+ if (unlikely(!file || !(prot & PROT_EXEC)))
14397+ return 1;
14398+
14399+ if (is_writable_mmap(file))
14400+ return 0;
14401+
14402+ mode =
14403+ gr_search_file(file->f_dentry,
14404+ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
14405+ file->f_vfsmnt);
14406+
14407+ if (!gr_tpe_allow(file))
14408+ return 0;
14409+
14410+ if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) {
14411+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MPROTECT_ACL_MSG, file->f_dentry, file->f_vfsmnt);
14412+ return 0;
14413+ } else if (unlikely(!(mode & GR_EXEC))) {
14414+ return 0;
14415+ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
14416+ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MPROTECT_ACL_MSG, file->f_dentry, file->f_vfsmnt);
14417+ return 1;
14418+ }
14419+
14420+ return 1;
14421+}
14422+
14423+void
14424+gr_acl_handle_psacct(struct task_struct *task, const long code)
14425+{
14426+ unsigned long runtime;
14427+ unsigned long cputime;
14428+ unsigned int wday, cday;
14429+ __u8 whr, chr;
14430+ __u8 wmin, cmin;
14431+ __u8 wsec, csec;
14432+
14433+ if (unlikely(!(gr_status & GR_READY) || !task->acl ||
14434+ !(task->acl->mode & GR_PROCACCT)))
14435+ return;
14436+
14437+ runtime = xtime.tv_sec - task->start_time.tv_sec;
14438+ wday = runtime / (3600 * 24);
14439+ runtime -= wday * (3600 * 24);
14440+ whr = runtime / 3600;
14441+ runtime -= whr * 3600;
14442+ wmin = runtime / 60;
14443+ runtime -= wmin * 60;
14444+ wsec = runtime;
14445+
14446+ cputime = (task->utime + task->stime) / HZ;
14447+ cday = cputime / (3600 * 24);
14448+ cputime -= cday * (3600 * 24);
14449+ chr = cputime / 3600;
14450+ cputime -= chr * 3600;
14451+ cmin = cputime / 60;
14452+ cputime -= cmin * 60;
14453+ csec = cputime;
14454+
14455+ gr_log_procacct(GR_DO_AUDIT, GR_ACL_PROCACCT_MSG, task, wday, whr, wmin, wsec, cday, chr, cmin, csec, code);
14456+
14457+ return;
14458+}
14459+
14460+void gr_set_kernel_label(struct task_struct *task)
14461+{
14462+ if (gr_status & GR_READY) {
14463+ task->role = kernel_role;
14464+ task->acl = kernel_role->root_label;
14465+ }
14466+ return;
14467+}
14468+
14469+int gr_acl_handle_filldir(const struct file *file, const char *name, const unsigned int namelen, const ino_t ino)
14470+{
14471+ struct task_struct *task = current;
14472+ struct dentry *dentry = file->f_dentry;
14473+ struct vfsmount *mnt = file->f_vfsmnt;
14474+ struct acl_object_label *obj, *tmp;
14475+ struct acl_subject_label *subj;
14476+ unsigned int bufsize;
14477+ int is_not_root;
14478+ char *path;
14479+
14480+ if (unlikely(!(gr_status & GR_READY)))
14481+ return 1;
14482+
14483+ if (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))
14484+ return 1;
14485+
14486+ subj = task->acl;
14487+ do {
14488+ obj = lookup_acl_obj_label(ino, dentry->d_inode->i_sb->s_dev, subj);
14489+ if (obj != NULL)
14490+ return (obj->mode & GR_FIND) ? 1 : 0;
14491+ } while ((subj = subj->parent_subject));
14492+
14493+ obj = chk_obj_label(dentry, mnt, task->acl);
14494+ if (obj->globbed == NULL)
14495+ return (obj->mode & GR_FIND) ? 1 : 0;
14496+
14497+ is_not_root = ((obj->filename[0] == '/') &&
14498+ (obj->filename[1] == '\0')) ? 0 : 1;
14499+ bufsize = PAGE_SIZE - namelen - is_not_root;
14500+
14501+ /* check bufsize > PAGE_SIZE || bufsize == 0 */
14502+ if (unlikely((bufsize - 1) > (PAGE_SIZE - 1)))
14503+ return 1;
14504+
14505+ preempt_disable();
14506+ path = d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()),
14507+ bufsize);
14508+
14509+ bufsize = strlen(path);
14510+
14511+ /* if base is "/", don't append an additional slash */
14512+ if (is_not_root)
14513+ *(path + bufsize) = '/';
14514+ memcpy(path + bufsize + is_not_root, name, namelen);
14515+ *(path + bufsize + namelen + is_not_root) = '\0';
14516+
14517+ tmp = obj->globbed;
14518+ while (tmp) {
14519+ if (!glob_match(tmp->filename, path)) {
14520+ preempt_enable();
14521+ return (tmp->mode & GR_FIND) ? 1 : 0;
14522+ }
14523+ tmp = tmp->next;
14524+ }
14525+ preempt_enable();
14526+ return (obj->mode & GR_FIND) ? 1 : 0;
14527+}
14528+
14529+EXPORT_SYMBOL(gr_learn_resource);
14530+EXPORT_SYMBOL(gr_set_kernel_label);
14531+#ifdef CONFIG_SECURITY
14532+EXPORT_SYMBOL(gr_check_user_change);
14533+EXPORT_SYMBOL(gr_check_group_change);
14534+#endif
14535+
14536diff -urNp linux-2.6.17.7/grsecurity/gracl_alloc.c linux-2.6.17.7/grsecurity/gracl_alloc.c
14537--- linux-2.6.17.7/grsecurity/gracl_alloc.c 1969-12-31 19:00:00.000000000 -0500
14538+++ linux-2.6.17.7/grsecurity/gracl_alloc.c 2006-08-01 20:29:46.000000000 -0400
14539@@ -0,0 +1,91 @@
14540+#include <linux/kernel.h>
14541+#include <linux/mm.h>
14542+#include <linux/slab.h>
14543+#include <linux/vmalloc.h>
14544+#include <linux/gracl.h>
14545+#include <linux/grsecurity.h>
14546+
14547+static unsigned long alloc_stack_next = 1;
14548+static unsigned long alloc_stack_size = 1;
14549+static void **alloc_stack;
14550+
14551+static __inline__ int
14552+alloc_pop(void)
14553+{
14554+ if (alloc_stack_next == 1)
14555+ return 0;
14556+
14557+ kfree(alloc_stack[alloc_stack_next - 2]);
14558+
14559+ alloc_stack_next--;
14560+
14561+ return 1;
14562+}
14563+
14564+static __inline__ void
14565+alloc_push(void *buf)
14566+{
14567+ if (alloc_stack_next >= alloc_stack_size)
14568+ BUG();
14569+
14570+ alloc_stack[alloc_stack_next - 1] = buf;
14571+
14572+ alloc_stack_next++;
14573+
14574+ return;
14575+}
14576+
14577+void *
14578+acl_alloc(unsigned long len)
14579+{
14580+ void *ret;
14581+
14582+ if (len > PAGE_SIZE)
14583+ BUG();
14584+
14585+ ret = kmalloc(len, GFP_KERNEL);
14586+
14587+ if (ret)
14588+ alloc_push(ret);
14589+
14590+ return ret;
14591+}
14592+
14593+void
14594+acl_free_all(void)
14595+{
14596+ if (gr_acl_is_enabled() || !alloc_stack)
14597+ return;
14598+
14599+ while (alloc_pop()) ;
14600+
14601+ if (alloc_stack) {
14602+ if ((alloc_stack_size * sizeof (void *)) <= PAGE_SIZE)
14603+ kfree(alloc_stack);
14604+ else
14605+ vfree(alloc_stack);
14606+ }
14607+
14608+ alloc_stack = NULL;
14609+ alloc_stack_size = 1;
14610+ alloc_stack_next = 1;
14611+
14612+ return;
14613+}
14614+
14615+int
14616+acl_alloc_stack_init(unsigned long size)
14617+{
14618+ if ((size * sizeof (void *)) <= PAGE_SIZE)
14619+ alloc_stack =
14620+ (void **) kmalloc(size * sizeof (void *), GFP_KERNEL);
14621+ else
14622+ alloc_stack = (void **) vmalloc(size * sizeof (void *));
14623+
14624+ alloc_stack_size = size;
14625+
14626+ if (!alloc_stack)
14627+ return 0;
14628+ else
14629+ return 1;
14630+}
14631diff -urNp linux-2.6.17.7/grsecurity/gracl_cap.c linux-2.6.17.7/grsecurity/gracl_cap.c
14632--- linux-2.6.17.7/grsecurity/gracl_cap.c 1969-12-31 19:00:00.000000000 -0500
14633+++ linux-2.6.17.7/grsecurity/gracl_cap.c 2006-08-01 20:29:47.000000000 -0400
14634@@ -0,0 +1,110 @@
14635+#include <linux/kernel.h>
14636+#include <linux/module.h>
14637+#include <linux/sched.h>
14638+#include <linux/capability.h>
14639+#include <linux/gracl.h>
14640+#include <linux/grsecurity.h>
14641+#include <linux/grinternal.h>
14642+
14643+static const char *captab_log[] = {
14644+ "CAP_CHOWN",
14645+ "CAP_DAC_OVERRIDE",
14646+ "CAP_DAC_READ_SEARCH",
14647+ "CAP_FOWNER",
14648+ "CAP_FSETID",
14649+ "CAP_KILL",
14650+ "CAP_SETGID",
14651+ "CAP_SETUID",
14652+ "CAP_SETPCAP",
14653+ "CAP_LINUX_IMMUTABLE",
14654+ "CAP_NET_BIND_SERVICE",
14655+ "CAP_NET_BROADCAST",
14656+ "CAP_NET_ADMIN",
14657+ "CAP_NET_RAW",
14658+ "CAP_IPC_LOCK",
14659+ "CAP_IPC_OWNER",
14660+ "CAP_SYS_MODULE",
14661+ "CAP_SYS_RAWIO",
14662+ "CAP_SYS_CHROOT",
14663+ "CAP_SYS_PTRACE",
14664+ "CAP_SYS_PACCT",
14665+ "CAP_SYS_ADMIN",
14666+ "CAP_SYS_BOOT",
14667+ "CAP_SYS_NICE",
14668+ "CAP_SYS_RESOURCE",
14669+ "CAP_SYS_TIME",
14670+ "CAP_SYS_TTY_CONFIG",
14671+ "CAP_MKNOD",
14672+ "CAP_LEASE"
14673+};
14674+
14675+EXPORT_SYMBOL(gr_task_is_capable);
14676+
14677+int
14678+gr_task_is_capable(struct task_struct *task, const int cap)
14679+{
14680+ struct acl_subject_label *curracl;
14681+ __u32 cap_drop = 0, cap_mask = 0;
14682+
14683+ if (!gr_acl_is_enabled())
14684+ return 1;
14685+
14686+ curracl = task->acl;
14687+
14688+ cap_drop = curracl->cap_lower;
14689+ cap_mask = curracl->cap_mask;
14690+
14691+ while ((curracl = curracl->parent_subject)) {
14692+ if (!(cap_mask & (1 << cap)) && (curracl->cap_mask & (1 << cap)))
14693+ cap_drop |= curracl->cap_lower & (1 << cap);
14694+ cap_mask |= curracl->cap_mask;
14695+ }
14696+
14697+ if (!cap_raised(cap_drop, cap))
14698+ return 1;
14699+
14700+ curracl = task->acl;
14701+
14702+ if ((curracl->mode & (GR_LEARN | GR_INHERITLEARN))
14703+ && cap_raised(task->cap_effective, cap)) {
14704+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
14705+ task->role->roletype, task->uid,
14706+ task->gid, task->exec_file ?
14707+ gr_to_filename(task->exec_file->f_dentry,
14708+ task->exec_file->f_vfsmnt) : curracl->filename,
14709+ curracl->filename, 0UL,
14710+ 0UL, "", (unsigned long) cap, NIPQUAD(task->signal->curr_ip));
14711+ return 1;
14712+ }
14713+
14714+ if ((cap >= 0) && (cap < (sizeof(captab_log)/sizeof(captab_log[0]))) && cap_raised(task->cap_effective, cap))
14715+ gr_log_cap(GR_DONT_AUDIT, GR_CAP_ACL_MSG, task, captab_log[cap]);
14716+
14717+ return 0;
14718+}
14719+
14720+int
14721+gr_is_capable_nolog(const int cap)
14722+{
14723+ struct acl_subject_label *curracl;
14724+ __u32 cap_drop = 0, cap_mask = 0;
14725+
14726+ if (!gr_acl_is_enabled())
14727+ return 1;
14728+
14729+ curracl = current->acl;
14730+
14731+ cap_drop = curracl->cap_lower;
14732+ cap_mask = curracl->cap_mask;
14733+
14734+ while ((curracl = curracl->parent_subject)) {
14735+ cap_drop |= curracl->cap_lower & (cap_mask & ~curracl->cap_mask);
14736+ cap_mask |= curracl->cap_mask;
14737+ }
14738+
14739+ if (!cap_raised(cap_drop, cap))
14740+ return 1;
14741+
14742+ return 0;
14743+}
14744+
14745diff -urNp linux-2.6.17.7/grsecurity/gracl_fs.c linux-2.6.17.7/grsecurity/gracl_fs.c
14746--- linux-2.6.17.7/grsecurity/gracl_fs.c 1969-12-31 19:00:00.000000000 -0500
14747+++ linux-2.6.17.7/grsecurity/gracl_fs.c 2006-08-01 20:29:47.000000000 -0400
14748@@ -0,0 +1,423 @@
14749+#include <linux/kernel.h>
14750+#include <linux/sched.h>
14751+#include <linux/types.h>
14752+#include <linux/fs.h>
14753+#include <linux/file.h>
14754+#include <linux/stat.h>
14755+#include <linux/grsecurity.h>
14756+#include <linux/grinternal.h>
14757+#include <linux/gracl.h>
14758+
14759+__u32
14760+gr_acl_handle_hidden_file(const struct dentry * dentry,
14761+ const struct vfsmount * mnt)
14762+{
14763+ __u32 mode;
14764+
14765+ if (unlikely(!dentry->d_inode))
14766+ return GR_FIND;
14767+
14768+ mode =
14769+ gr_search_file(dentry, GR_FIND | GR_AUDIT_FIND | GR_SUPPRESS, mnt);
14770+
14771+ if (unlikely(mode & GR_FIND && mode & GR_AUDIT_FIND)) {
14772+ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt);
14773+ return mode;
14774+ } else if (unlikely(!(mode & GR_FIND) && !(mode & GR_SUPPRESS))) {
14775+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt);
14776+ return 0;
14777+ } else if (unlikely(!(mode & GR_FIND)))
14778+ return 0;
14779+
14780+ return GR_FIND;
14781+}
14782+
14783+__u32
14784+gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
14785+ const int fmode)
14786+{
14787+ __u32 reqmode = GR_FIND;
14788+ __u32 mode;
14789+
14790+ if (unlikely(!dentry->d_inode))
14791+ return reqmode;
14792+
14793+ if (unlikely(fmode & O_APPEND))
14794+ reqmode |= GR_APPEND;
14795+ else if (unlikely(fmode & FMODE_WRITE))
14796+ reqmode |= GR_WRITE;
14797+ if (likely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
14798+ reqmode |= GR_READ;
14799+
14800+ mode =
14801+ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
14802+ mnt);
14803+
14804+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
14805+ gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt,
14806+ reqmode & GR_READ ? " reading" : "",
14807+ reqmode & GR_WRITE ? " writing" : reqmode &
14808+ GR_APPEND ? " appending" : "");
14809+ return reqmode;
14810+ } else
14811+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
14812+ {
14813+ gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt,
14814+ reqmode & GR_READ ? " reading" : "",
14815+ reqmode & GR_WRITE ? " writing" : reqmode &
14816+ GR_APPEND ? " appending" : "");
14817+ return 0;
14818+ } else if (unlikely((mode & reqmode) != reqmode))
14819+ return 0;
14820+
14821+ return reqmode;
14822+}
14823+
14824+__u32
14825+gr_acl_handle_creat(const struct dentry * dentry,
14826+ const struct dentry * p_dentry,
14827+ const struct vfsmount * p_mnt, const int fmode,
14828+ const int imode)
14829+{
14830+ __u32 reqmode = GR_WRITE | GR_CREATE;
14831+ __u32 mode;
14832+
14833+ if (unlikely(fmode & O_APPEND))
14834+ reqmode |= GR_APPEND;
14835+ if (unlikely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
14836+ reqmode |= GR_READ;
14837+ if (unlikely((fmode & O_CREAT) && (imode & (S_ISUID | S_ISGID))))
14838+ reqmode |= GR_SETID;
14839+
14840+ mode =
14841+ gr_check_create(dentry, p_dentry, p_mnt,
14842+ reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
14843+
14844+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
14845+ gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt,
14846+ reqmode & GR_READ ? " reading" : "",
14847+ reqmode & GR_WRITE ? " writing" : reqmode &
14848+ GR_APPEND ? " appending" : "");
14849+ return reqmode;
14850+ } else
14851+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
14852+ {
14853+ gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt,
14854+ reqmode & GR_READ ? " reading" : "",
14855+ reqmode & GR_WRITE ? " writing" : reqmode &
14856+ GR_APPEND ? " appending" : "");
14857+ return 0;
14858+ } else if (unlikely((mode & reqmode) != reqmode))
14859+ return 0;
14860+
14861+ return reqmode;
14862+}
14863+
14864+__u32
14865+gr_acl_handle_access(const struct dentry * dentry, const struct vfsmount * mnt,
14866+ const int fmode)
14867+{
14868+ __u32 mode, reqmode = GR_FIND;
14869+
14870+ if ((fmode & S_IXOTH) && !S_ISDIR(dentry->d_inode->i_mode))
14871+ reqmode |= GR_EXEC;
14872+ if (fmode & S_IWOTH)
14873+ reqmode |= GR_WRITE;
14874+ if (fmode & S_IROTH)
14875+ reqmode |= GR_READ;
14876+
14877+ mode =
14878+ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
14879+ mnt);
14880+
14881+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
14882+ gr_log_fs_rbac_mode3(GR_DO_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt,
14883+ reqmode & GR_READ ? " reading" : "",
14884+ reqmode & GR_WRITE ? " writing" : "",
14885+ reqmode & GR_EXEC ? " executing" : "");
14886+ return reqmode;
14887+ } else
14888+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
14889+ {
14890+ gr_log_fs_rbac_mode3(GR_DONT_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt,
14891+ reqmode & GR_READ ? " reading" : "",
14892+ reqmode & GR_WRITE ? " writing" : "",
14893+ reqmode & GR_EXEC ? " executing" : "");
14894+ return 0;
14895+ } else if (unlikely((mode & reqmode) != reqmode))
14896+ return 0;
14897+
14898+ return reqmode;
14899+}
14900+
14901+static __u32 generic_fs_handler(const struct dentry *dentry, const struct vfsmount *mnt, __u32 reqmode, const char *fmt)
14902+{
14903+ __u32 mode;
14904+
14905+ mode = gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, mnt);
14906+
14907+ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) {
14908+ gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, dentry, mnt);
14909+ return mode;
14910+ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) {
14911+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, dentry, mnt);
14912+ return 0;
14913+ } else if (unlikely((mode & (reqmode)) != (reqmode)))
14914+ return 0;
14915+
14916+ return (reqmode);
14917+}
14918+
14919+__u32
14920+gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
14921+{
14922+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_RMDIR_ACL_MSG);
14923+}
14924+
14925+__u32
14926+gr_acl_handle_unlink(const struct dentry *dentry, const struct vfsmount *mnt)
14927+{
14928+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_UNLINK_ACL_MSG);
14929+}
14930+
14931+__u32
14932+gr_acl_handle_truncate(const struct dentry *dentry, const struct vfsmount *mnt)
14933+{
14934+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_TRUNCATE_ACL_MSG);
14935+}
14936+
14937+__u32
14938+gr_acl_handle_utime(const struct dentry *dentry, const struct vfsmount *mnt)
14939+{
14940+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_ATIME_ACL_MSG);
14941+}
14942+
14943+__u32
14944+gr_acl_handle_fchmod(const struct dentry *dentry, const struct vfsmount *mnt,
14945+ mode_t mode)
14946+{
14947+ if (unlikely(dentry->d_inode && S_ISSOCK(dentry->d_inode->i_mode)))
14948+ return 1;
14949+
14950+ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
14951+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
14952+ GR_FCHMOD_ACL_MSG);
14953+ } else {
14954+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_FCHMOD_ACL_MSG);
14955+ }
14956+}
14957+
14958+__u32
14959+gr_acl_handle_chmod(const struct dentry *dentry, const struct vfsmount *mnt,
14960+ mode_t mode)
14961+{
14962+ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
14963+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
14964+ GR_CHMOD_ACL_MSG);
14965+ } else {
14966+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHMOD_ACL_MSG);
14967+ }
14968+}
14969+
14970+__u32
14971+gr_acl_handle_chown(const struct dentry *dentry, const struct vfsmount *mnt)
14972+{
14973+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHOWN_ACL_MSG);
14974+}
14975+
14976+__u32
14977+gr_acl_handle_execve(const struct dentry *dentry, const struct vfsmount *mnt)
14978+{
14979+ return generic_fs_handler(dentry, mnt, GR_EXEC, GR_EXEC_ACL_MSG);
14980+}
14981+
14982+__u32
14983+gr_acl_handle_unix(const struct dentry *dentry, const struct vfsmount *mnt)
14984+{
14985+ return generic_fs_handler(dentry, mnt, GR_READ | GR_WRITE,
14986+ GR_UNIXCONNECT_ACL_MSG);
14987+}
14988+
14989+/* hardlinks require at minimum create permission,
14990+ any additional privilege required is based on the
14991+ privilege of the file being linked to
14992+*/
14993+__u32
14994+gr_acl_handle_link(const struct dentry * new_dentry,
14995+ const struct dentry * parent_dentry,
14996+ const struct vfsmount * parent_mnt,
14997+ const struct dentry * old_dentry,
14998+ const struct vfsmount * old_mnt, const char *to)
14999+{
15000+ __u32 mode;
15001+ __u32 needmode = GR_CREATE | GR_LINK;
15002+ __u32 needaudit = GR_AUDIT_CREATE | GR_AUDIT_LINK;
15003+
15004+ mode =
15005+ gr_check_link(new_dentry, parent_dentry, parent_mnt, old_dentry,
15006+ old_mnt);
15007+
15008+ if (unlikely(((mode & needmode) == needmode) && (mode & needaudit))) {
15009+ gr_log_fs_rbac_str(GR_DO_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to);
15010+ return mode;
15011+ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
15012+ gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to);
15013+ return 0;
15014+ } else if (unlikely((mode & needmode) != needmode))
15015+ return 0;
15016+
15017+ return 1;
15018+}
15019+
15020+__u32
15021+gr_acl_handle_symlink(const struct dentry * new_dentry,
15022+ const struct dentry * parent_dentry,
15023+ const struct vfsmount * parent_mnt, const char *from)
15024+{
15025+ __u32 needmode = GR_WRITE | GR_CREATE;
15026+ __u32 mode;
15027+
15028+ mode =
15029+ gr_check_create(new_dentry, parent_dentry, parent_mnt,
15030+ GR_CREATE | GR_AUDIT_CREATE |
15031+ GR_WRITE | GR_AUDIT_WRITE | GR_SUPPRESS);
15032+
15033+ if (unlikely(mode & GR_WRITE && mode & GR_AUDITS)) {
15034+ gr_log_fs_str_rbac(GR_DO_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt);
15035+ return mode;
15036+ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
15037+ gr_log_fs_str_rbac(GR_DONT_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt);
15038+ return 0;
15039+ } else if (unlikely((mode & needmode) != needmode))
15040+ return 0;
15041+
15042+ return (GR_WRITE | GR_CREATE);
15043+}
15044+
15045+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)
15046+{
15047+ __u32 mode;
15048+
15049+ mode = gr_check_create(new_dentry, parent_dentry, parent_mnt, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
15050+
15051+ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) {
15052+ gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, new_dentry, parent_mnt);
15053+ return mode;
15054+ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) {
15055+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, new_dentry, parent_mnt);
15056+ return 0;
15057+ } else if (unlikely((mode & (reqmode)) != (reqmode)))
15058+ return 0;
15059+
15060+ return (reqmode);
15061+}
15062+
15063+__u32
15064+gr_acl_handle_mknod(const struct dentry * new_dentry,
15065+ const struct dentry * parent_dentry,
15066+ const struct vfsmount * parent_mnt,
15067+ const int mode)
15068+{
15069+ __u32 reqmode = GR_WRITE | GR_CREATE;
15070+ if (unlikely(mode & (S_ISUID | S_ISGID)))
15071+ reqmode |= GR_SETID;
15072+
15073+ return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
15074+ reqmode, GR_MKNOD_ACL_MSG);
15075+}
15076+
15077+__u32
15078+gr_acl_handle_mkdir(const struct dentry *new_dentry,
15079+ const struct dentry *parent_dentry,
15080+ const struct vfsmount *parent_mnt)
15081+{
15082+ return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
15083+ GR_WRITE | GR_CREATE, GR_MKDIR_ACL_MSG);
15084+}
15085+
15086+#define RENAME_CHECK_SUCCESS(old, new) \
15087+ (((old & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)) && \
15088+ ((new & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)))
15089+
15090+int
15091+gr_acl_handle_rename(struct dentry *new_dentry,
15092+ struct dentry *parent_dentry,
15093+ const struct vfsmount *parent_mnt,
15094+ struct dentry *old_dentry,
15095+ struct inode *old_parent_inode,
15096+ struct vfsmount *old_mnt, const char *newname)
15097+{
15098+ __u32 comp1, comp2;
15099+ int error = 0;
15100+
15101+ if (unlikely(!gr_acl_is_enabled()))
15102+ return 0;
15103+
15104+ if (!new_dentry->d_inode) {
15105+ comp1 = gr_check_create(new_dentry, parent_dentry, parent_mnt,
15106+ GR_READ | GR_WRITE | GR_CREATE | GR_AUDIT_READ |
15107+ GR_AUDIT_WRITE | GR_AUDIT_CREATE | GR_SUPPRESS);
15108+ comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE |
15109+ GR_DELETE | GR_AUDIT_DELETE |
15110+ GR_AUDIT_READ | GR_AUDIT_WRITE |
15111+ GR_SUPPRESS, old_mnt);
15112+ } else {
15113+ comp1 = gr_search_file(new_dentry, GR_READ | GR_WRITE |
15114+ GR_CREATE | GR_DELETE |
15115+ GR_AUDIT_CREATE | GR_AUDIT_DELETE |
15116+ GR_AUDIT_READ | GR_AUDIT_WRITE |
15117+ GR_SUPPRESS, parent_mnt);
15118+ comp2 =
15119+ gr_search_file(old_dentry,
15120+ GR_READ | GR_WRITE | GR_AUDIT_READ |
15121+ GR_DELETE | GR_AUDIT_DELETE |
15122+ GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt);
15123+ }
15124+
15125+ if (RENAME_CHECK_SUCCESS(comp1, comp2) &&
15126+ ((comp1 & GR_AUDITS) || (comp2 & GR_AUDITS)))
15127+ gr_log_fs_rbac_str(GR_DO_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname);
15128+ else if (!RENAME_CHECK_SUCCESS(comp1, comp2) && !(comp1 & GR_SUPPRESS)
15129+ && !(comp2 & GR_SUPPRESS)) {
15130+ gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname);
15131+ error = -EACCES;
15132+ } else if (unlikely(!RENAME_CHECK_SUCCESS(comp1, comp2)))
15133+ error = -EACCES;
15134+
15135+ return error;
15136+}
15137+
15138+void
15139+gr_acl_handle_exit(void)
15140+{
15141+ u16 id;
15142+ char *rolename;
15143+ struct file *exec_file;
15144+
15145+ if (unlikely(current->acl_sp_role && gr_acl_is_enabled())) {
15146+ id = current->acl_role_id;
15147+ rolename = current->role->rolename;
15148+ gr_set_acls(1);
15149+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLEL_ACL_MSG, rolename, id);
15150+ }
15151+
15152+ write_lock(&grsec_exec_file_lock);
15153+ exec_file = current->exec_file;
15154+ current->exec_file = NULL;
15155+ write_unlock(&grsec_exec_file_lock);
15156+
15157+ if (exec_file)
15158+ fput(exec_file);
15159+}
15160+
15161+int
15162+gr_acl_handle_procpidmem(const struct task_struct *task)
15163+{
15164+ if (unlikely(!gr_acl_is_enabled()))
15165+ return 0;
15166+
15167+ if (task->acl->mode & GR_PROTPROCFD)
15168+ return -EACCES;
15169+
15170+ return 0;
15171+}
15172diff -urNp linux-2.6.17.7/grsecurity/gracl_ip.c linux-2.6.17.7/grsecurity/gracl_ip.c
15173--- linux-2.6.17.7/grsecurity/gracl_ip.c 1969-12-31 19:00:00.000000000 -0500
15174+++ linux-2.6.17.7/grsecurity/gracl_ip.c 2006-08-01 20:29:47.000000000 -0400
15175@@ -0,0 +1,313 @@
15176+#include <linux/kernel.h>
15177+#include <asm/uaccess.h>
15178+#include <asm/errno.h>
15179+#include <net/sock.h>
15180+#include <linux/file.h>
15181+#include <linux/fs.h>
15182+#include <linux/net.h>
15183+#include <linux/in.h>
15184+#include <linux/skbuff.h>
15185+#include <linux/ip.h>
15186+#include <linux/udp.h>
15187+#include <linux/smp_lock.h>
15188+#include <linux/types.h>
15189+#include <linux/sched.h>
15190+#include <linux/netdevice.h>
15191+#include <linux/inetdevice.h>
15192+#include <linux/gracl.h>
15193+#include <linux/grsecurity.h>
15194+#include <linux/grinternal.h>
15195+
15196+#define GR_BIND 0x01
15197+#define GR_CONNECT 0x02
15198+#define GR_INVERT 0x04
15199+
15200+static const char * gr_protocols[256] = {
15201+ "ip", "icmp", "igmp", "ggp", "ipencap", "st", "tcp", "cbt",
15202+ "egp", "igp", "bbn-rcc", "nvp", "pup", "argus", "emcon", "xnet",
15203+ "chaos", "udp", "mux", "dcn", "hmp", "prm", "xns-idp", "trunk-1",
15204+ "trunk-2", "leaf-1", "leaf-2", "rdp", "irtp", "iso-tp4", "netblt", "mfe-nsp",
15205+ "merit-inp", "sep", "3pc", "idpr", "xtp", "ddp", "idpr-cmtp", "tp++",
15206+ "il", "ipv6", "sdrp", "ipv6-route", "ipv6-frag", "idrp", "rsvp", "gre",
15207+ "mhrp", "bna", "ipv6-crypt", "ipv6-auth", "i-nlsp", "swipe", "narp", "mobile",
15208+ "tlsp", "skip", "ipv6-icmp", "ipv6-nonxt", "ipv6-opts", "unknown:61", "cftp", "unknown:63",
15209+ "sat-expak", "kryptolan", "rvd", "ippc", "unknown:68", "sat-mon", "visa", "ipcv",
15210+ "cpnx", "cphb", "wsn", "pvp", "br-sat-mon", "sun-nd", "wb-mon", "wb-expak",
15211+ "iso-ip", "vmtp", "secure-vmtp", "vines", "ttp", "nfsnet-igp", "dgp", "tcf",
15212+ "eigrp", "ospf", "sprite-rpc", "larp", "mtp", "ax.25", "ipip", "micp",
15213+ "scc-sp", "etherip", "encap", "unknown:99", "gmtp", "ifmp", "pnni", "pim",
15214+ "aris", "scps", "qnx", "a/n", "ipcomp", "snp", "compaq-peer", "ipx-in-ip",
15215+ "vrrp", "pgm", "unknown:114", "l2tp", "ddx", "iatp", "stp", "srp",
15216+ "uti", "smp", "sm", "ptp", "isis", "fire", "crtp", "crdup",
15217+ "sscopmce", "iplt", "sps", "pipe", "sctp", "fc", "unkown:134", "unknown:135",
15218+ "unknown:136", "unknown:137", "unknown:138", "unknown:139", "unknown:140", "unknown:141", "unknown:142", "unknown:143",
15219+ "unknown:144", "unknown:145", "unknown:146", "unknown:147", "unknown:148", "unknown:149", "unknown:150", "unknown:151",
15220+ "unknown:152", "unknown:153", "unknown:154", "unknown:155", "unknown:156", "unknown:157", "unknown:158", "unknown:159",
15221+ "unknown:160", "unknown:161", "unknown:162", "unknown:163", "unknown:164", "unknown:165", "unknown:166", "unknown:167",
15222+ "unknown:168", "unknown:169", "unknown:170", "unknown:171", "unknown:172", "unknown:173", "unknown:174", "unknown:175",
15223+ "unknown:176", "unknown:177", "unknown:178", "unknown:179", "unknown:180", "unknown:181", "unknown:182", "unknown:183",
15224+ "unknown:184", "unknown:185", "unknown:186", "unknown:187", "unknown:188", "unknown:189", "unknown:190", "unknown:191",
15225+ "unknown:192", "unknown:193", "unknown:194", "unknown:195", "unknown:196", "unknown:197", "unknown:198", "unknown:199",
15226+ "unknown:200", "unknown:201", "unknown:202", "unknown:203", "unknown:204", "unknown:205", "unknown:206", "unknown:207",
15227+ "unknown:208", "unknown:209", "unknown:210", "unknown:211", "unknown:212", "unknown:213", "unknown:214", "unknown:215",
15228+ "unknown:216", "unknown:217", "unknown:218", "unknown:219", "unknown:220", "unknown:221", "unknown:222", "unknown:223",
15229+ "unknown:224", "unknown:225", "unknown:226", "unknown:227", "unknown:228", "unknown:229", "unknown:230", "unknown:231",
15230+ "unknown:232", "unknown:233", "unknown:234", "unknown:235", "unknown:236", "unknown:237", "unknown:238", "unknown:239",
15231+ "unknown:240", "unknown:241", "unknown:242", "unknown:243", "unknown:244", "unknown:245", "unknown:246", "unknown:247",
15232+ "unknown:248", "unknown:249", "unknown:250", "unknown:251", "unknown:252", "unknown:253", "unknown:254", "unknown:255",
15233+ };
15234+
15235+static const char * gr_socktypes[11] = {
15236+ "unknown:0", "stream", "dgram", "raw", "rdm", "seqpacket", "unknown:6",
15237+ "unknown:7", "unknown:8", "unknown:9", "packet"
15238+ };
15239+
15240+const char *
15241+gr_proto_to_name(unsigned char proto)
15242+{
15243+ return gr_protocols[proto];
15244+}
15245+
15246+const char *
15247+gr_socktype_to_name(unsigned char type)
15248+{
15249+ return gr_socktypes[type];
15250+}
15251+
15252+int
15253+gr_search_socket(const int domain, const int type, const int protocol)
15254+{
15255+ struct acl_subject_label *curr;
15256+
15257+ if (unlikely(!gr_acl_is_enabled()))
15258+ goto exit;
15259+
15260+ if ((domain < 0) || (type < 0) || (protocol < 0) || (domain != PF_INET)
15261+ || (domain >= NPROTO) || (type >= SOCK_MAX) || (protocol > 255))
15262+ goto exit; // let the kernel handle it
15263+
15264+ curr = current->acl;
15265+
15266+ if (!curr->ips)
15267+ goto exit;
15268+
15269+ if ((curr->ip_type & (1 << type)) &&
15270+ (curr->ip_proto[protocol / 32] & (1 << (protocol % 32))))
15271+ goto exit;
15272+
15273+ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
15274+ /* we don't place acls on raw sockets , and sometimes
15275+ dgram/ip sockets are opened for ioctl and not
15276+ bind/connect, so we'll fake a bind learn log */
15277+ if (type == SOCK_RAW || type == SOCK_PACKET) {
15278+ __u32 fakeip = 0;
15279+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
15280+ current->role->roletype, current->uid,
15281+ current->gid, current->exec_file ?
15282+ gr_to_filename(current->exec_file->f_dentry,
15283+ current->exec_file->f_vfsmnt) :
15284+ curr->filename, curr->filename,
15285+ NIPQUAD(fakeip), 0, type,
15286+ protocol, GR_CONNECT,
15287+NIPQUAD(current->signal->curr_ip));
15288+ } else if ((type == SOCK_DGRAM) && (protocol == IPPROTO_IP)) {
15289+ __u32 fakeip = 0;
15290+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
15291+ current->role->roletype, current->uid,
15292+ current->gid, current->exec_file ?
15293+ gr_to_filename(current->exec_file->f_dentry,
15294+ current->exec_file->f_vfsmnt) :
15295+ curr->filename, curr->filename,
15296+ NIPQUAD(fakeip), 0, type,
15297+ protocol, GR_BIND, NIPQUAD(current->signal->curr_ip));
15298+ }
15299+ /* we'll log when they use connect or bind */
15300+ goto exit;
15301+ }
15302+
15303+ gr_log_str3(GR_DONT_AUDIT, GR_SOCK_MSG, "inet",
15304+ gr_socktype_to_name(type), gr_proto_to_name(protocol));
15305+
15306+ return 0;
15307+ exit:
15308+ return 1;
15309+}
15310+
15311+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)
15312+{
15313+ if ((ip->mode & mode) &&
15314+ (ip_port >= ip->low) &&
15315+ (ip_port <= ip->high) &&
15316+ ((ntohl(ip_addr) & our_netmask) ==
15317+ (ntohl(our_addr) & our_netmask))
15318+ && (ip->proto[protocol / 32] & (1 << (protocol % 32)))
15319+ && (ip->type & (1 << type))) {
15320+ if (ip->mode & GR_INVERT)
15321+ return 2; // specifically denied
15322+ else
15323+ return 1; // allowed
15324+ }
15325+
15326+ return 0; // not specifically allowed, may continue parsing
15327+}
15328+
15329+static int
15330+gr_search_connectbind(const int mode, const struct sock *sk,
15331+ const struct sockaddr_in *addr, const int type)
15332+{
15333+ char iface[IFNAMSIZ] = {0};
15334+ struct acl_subject_label *curr;
15335+ struct acl_ip_label *ip;
15336+ struct net_device *dev;
15337+ struct in_device *idev;
15338+ unsigned long i;
15339+ int ret;
15340+ __u32 ip_addr = 0;
15341+ __u32 our_addr;
15342+ __u32 our_netmask;
15343+ char *p;
15344+ __u16 ip_port = 0;
15345+
15346+ if (unlikely(!gr_acl_is_enabled() || sk->sk_family != PF_INET))
15347+ return 1;
15348+
15349+ curr = current->acl;
15350+
15351+ if (!curr->ips)
15352+ return 1;
15353+
15354+ ip_addr = addr->sin_addr.s_addr;
15355+ ip_port = ntohs(addr->sin_port);
15356+
15357+ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
15358+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
15359+ current->role->roletype, current->uid,
15360+ current->gid, current->exec_file ?
15361+ gr_to_filename(current->exec_file->f_dentry,
15362+ current->exec_file->f_vfsmnt) :
15363+ curr->filename, curr->filename,
15364+ NIPQUAD(ip_addr), ip_port, type,
15365+ sk->sk_protocol, mode, NIPQUAD(current->signal->curr_ip));
15366+ return 1;
15367+ }
15368+
15369+ for (i = 0; i < curr->ip_num; i++) {
15370+ ip = *(curr->ips + i);
15371+ if (ip->iface != NULL) {
15372+ strncpy(iface, ip->iface, IFNAMSIZ - 1);
15373+ p = strchr(iface, ':');
15374+ if (p != NULL)
15375+ *p = '\0';
15376+ dev = dev_get_by_name(iface);
15377+ if (dev == NULL)
15378+ continue;
15379+ idev = in_dev_get(dev);
15380+ if (idev == NULL) {
15381+ dev_put(dev);
15382+ continue;
15383+ }
15384+ rcu_read_lock();
15385+ for_ifa(idev) {
15386+ if (!strcmp(ip->iface, ifa->ifa_label)) {
15387+ our_addr = ifa->ifa_address;
15388+ our_netmask = 0xffffffff;
15389+ ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask);
15390+ if (ret == 1) {
15391+ rcu_read_unlock();
15392+ in_dev_put(idev);
15393+ dev_put(dev);
15394+ return 1;
15395+ } else if (ret == 2) {
15396+ rcu_read_unlock();
15397+ in_dev_put(idev);
15398+ dev_put(dev);
15399+ goto denied;
15400+ }
15401+ }
15402+ } endfor_ifa(idev);
15403+ rcu_read_unlock();
15404+ in_dev_put(idev);
15405+ dev_put(dev);
15406+ } else {
15407+ our_addr = ip->addr;
15408+ our_netmask = ip->netmask;
15409+ ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask);
15410+ if (ret == 1)
15411+ return 1;
15412+ else if (ret == 2)
15413+ goto denied;
15414+ }
15415+ }
15416+
15417+denied:
15418+ if (mode == GR_BIND)
15419+ 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));
15420+ else if (mode == GR_CONNECT)
15421+ 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));
15422+
15423+ return 0;
15424+}
15425+
15426+int
15427+gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
15428+{
15429+ return gr_search_connectbind(GR_CONNECT, sock->sk, addr, sock->type);
15430+}
15431+
15432+int
15433+gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
15434+{
15435+ return gr_search_connectbind(GR_BIND, sock->sk, addr, sock->type);
15436+}
15437+
15438+int gr_search_listen(const struct socket *sock)
15439+{
15440+ struct sock *sk = sock->sk;
15441+ struct sockaddr_in addr;
15442+
15443+ addr.sin_addr.s_addr = inet_sk(sk)->saddr;
15444+ addr.sin_port = inet_sk(sk)->sport;
15445+
15446+ return gr_search_connectbind(GR_BIND, sock->sk, &addr, sock->type);
15447+}
15448+
15449+int gr_search_accept(const struct socket *sock)
15450+{
15451+ struct sock *sk = sock->sk;
15452+ struct sockaddr_in addr;
15453+
15454+ addr.sin_addr.s_addr = inet_sk(sk)->saddr;
15455+ addr.sin_port = inet_sk(sk)->sport;
15456+
15457+ return gr_search_connectbind(GR_BIND, sock->sk, &addr, sock->type);
15458+}
15459+
15460+int
15461+gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
15462+{
15463+ if (addr)
15464+ return gr_search_connectbind(GR_CONNECT, sk, addr, SOCK_DGRAM);
15465+ else {
15466+ struct sockaddr_in sin;
15467+ const struct inet_sock *inet = inet_sk(sk);
15468+
15469+ sin.sin_addr.s_addr = inet->daddr;
15470+ sin.sin_port = inet->dport;
15471+
15472+ return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM);
15473+ }
15474+}
15475+
15476+int
15477+gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
15478+{
15479+ struct sockaddr_in sin;
15480+
15481+ if (unlikely(skb->len < sizeof (struct udphdr)))
15482+ return 1; // skip this packet
15483+
15484+ sin.sin_addr.s_addr = skb->nh.iph->saddr;
15485+ sin.sin_port = skb->h.uh->source;
15486+
15487+ return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM);
15488+}
15489diff -urNp linux-2.6.17.7/grsecurity/gracl_learn.c linux-2.6.17.7/grsecurity/gracl_learn.c
15490--- linux-2.6.17.7/grsecurity/gracl_learn.c 1969-12-31 19:00:00.000000000 -0500
15491+++ linux-2.6.17.7/grsecurity/gracl_learn.c 2006-08-01 20:29:47.000000000 -0400
15492@@ -0,0 +1,204 @@
15493+#include <linux/kernel.h>
15494+#include <linux/mm.h>
15495+#include <linux/sched.h>
15496+#include <linux/poll.h>
15497+#include <linux/smp_lock.h>
15498+#include <linux/string.h>
15499+#include <linux/file.h>
15500+#include <linux/types.h>
15501+#include <linux/vmalloc.h>
15502+#include <linux/grinternal.h>
15503+
15504+extern ssize_t write_grsec_handler(struct file * file, const char __user * buf,
15505+ size_t count, loff_t *ppos);
15506+extern int gr_acl_is_enabled(void);
15507+
15508+static DECLARE_WAIT_QUEUE_HEAD(learn_wait);
15509+static int gr_learn_attached;
15510+
15511+/* use a 512k buffer */
15512+#define LEARN_BUFFER_SIZE (512 * 1024)
15513+
15514+static spinlock_t gr_learn_lock = SPIN_LOCK_UNLOCKED;
15515+static DECLARE_MUTEX(gr_learn_user_sem);
15516+
15517+/* we need to maintain two buffers, so that the kernel context of grlearn
15518+ uses a semaphore around the userspace copying, and the other kernel contexts
15519+ use a spinlock when copying into the buffer, since they cannot sleep
15520+*/
15521+static char *learn_buffer;
15522+static char *learn_buffer_user;
15523+static int learn_buffer_len;
15524+static int learn_buffer_user_len;
15525+
15526+static ssize_t
15527+read_learn(struct file *file, char __user * buf, size_t count, loff_t * ppos)
15528+{
15529+ DECLARE_WAITQUEUE(wait, current);
15530+ ssize_t retval = 0;
15531+
15532+ add_wait_queue(&learn_wait, &wait);
15533+ set_current_state(TASK_INTERRUPTIBLE);
15534+ do {
15535+ down(&gr_learn_user_sem);
15536+ spin_lock(&gr_learn_lock);
15537+ if (learn_buffer_len)
15538+ break;
15539+ spin_unlock(&gr_learn_lock);
15540+ up(&gr_learn_user_sem);
15541+ if (file->f_flags & O_NONBLOCK) {
15542+ retval = -EAGAIN;
15543+ goto out;
15544+ }
15545+ if (signal_pending(current)) {
15546+ retval = -ERESTARTSYS;
15547+ goto out;
15548+ }
15549+
15550+ schedule();
15551+ } while (1);
15552+
15553+ memcpy(learn_buffer_user, learn_buffer, learn_buffer_len);
15554+ learn_buffer_user_len = learn_buffer_len;
15555+ retval = learn_buffer_len;
15556+ learn_buffer_len = 0;
15557+
15558+ spin_unlock(&gr_learn_lock);
15559+
15560+ if (copy_to_user(buf, learn_buffer_user, learn_buffer_user_len))
15561+ retval = -EFAULT;
15562+
15563+ up(&gr_learn_user_sem);
15564+out:
15565+ set_current_state(TASK_RUNNING);
15566+ remove_wait_queue(&learn_wait, &wait);
15567+ return retval;
15568+}
15569+
15570+static unsigned int
15571+poll_learn(struct file * file, poll_table * wait)
15572+{
15573+ poll_wait(file, &learn_wait, wait);
15574+
15575+ if (learn_buffer_len)
15576+ return (POLLIN | POLLRDNORM);
15577+
15578+ return 0;
15579+}
15580+
15581+void
15582+gr_clear_learn_entries(void)
15583+{
15584+ char *tmp;
15585+
15586+ down(&gr_learn_user_sem);
15587+ if (learn_buffer != NULL) {
15588+ spin_lock(&gr_learn_lock);
15589+ tmp = learn_buffer;
15590+ learn_buffer = NULL;
15591+ spin_unlock(&gr_learn_lock);
15592+ vfree(learn_buffer);
15593+ }
15594+ if (learn_buffer_user != NULL) {
15595+ vfree(learn_buffer_user);
15596+ learn_buffer_user = NULL;
15597+ }
15598+ learn_buffer_len = 0;
15599+ up(&gr_learn_user_sem);
15600+
15601+ return;
15602+}
15603+
15604+void
15605+gr_add_learn_entry(const char *fmt, ...)
15606+{
15607+ va_list args;
15608+ unsigned int len;
15609+
15610+ if (!gr_learn_attached)
15611+ return;
15612+
15613+ spin_lock(&gr_learn_lock);
15614+
15615+ /* leave a gap at the end so we know when it's "full" but don't have to
15616+ compute the exact length of the string we're trying to append
15617+ */
15618+ if (learn_buffer_len > LEARN_BUFFER_SIZE - 16384) {
15619+ spin_unlock(&gr_learn_lock);
15620+ wake_up_interruptible(&learn_wait);
15621+ return;
15622+ }
15623+ if (learn_buffer == NULL) {
15624+ spin_unlock(&gr_learn_lock);
15625+ return;
15626+ }
15627+
15628+ va_start(args, fmt);
15629+ len = vsnprintf(learn_buffer + learn_buffer_len, LEARN_BUFFER_SIZE - learn_buffer_len, fmt, args);
15630+ va_end(args);
15631+
15632+ learn_buffer_len += len + 1;
15633+
15634+ spin_unlock(&gr_learn_lock);
15635+ wake_up_interruptible(&learn_wait);
15636+
15637+ return;
15638+}
15639+
15640+static int
15641+open_learn(struct inode *inode, struct file *file)
15642+{
15643+ if (file->f_mode & FMODE_READ && gr_learn_attached)
15644+ return -EBUSY;
15645+ if (file->f_mode & FMODE_READ) {
15646+ down(&gr_learn_user_sem);
15647+ if (learn_buffer == NULL)
15648+ learn_buffer = vmalloc(LEARN_BUFFER_SIZE);
15649+ if (learn_buffer_user == NULL)
15650+ learn_buffer_user = vmalloc(LEARN_BUFFER_SIZE);
15651+ if (learn_buffer == NULL)
15652+ return -ENOMEM;
15653+ if (learn_buffer_user == NULL)
15654+ return -ENOMEM;
15655+ learn_buffer_len = 0;
15656+ learn_buffer_user_len = 0;
15657+ gr_learn_attached = 1;
15658+ up(&gr_learn_user_sem);
15659+ }
15660+ return 0;
15661+}
15662+
15663+static int
15664+close_learn(struct inode *inode, struct file *file)
15665+{
15666+ char *tmp;
15667+
15668+ if (file->f_mode & FMODE_READ) {
15669+ down(&gr_learn_user_sem);
15670+ if (learn_buffer != NULL) {
15671+ spin_lock(&gr_learn_lock);
15672+ tmp = learn_buffer;
15673+ learn_buffer = NULL;
15674+ spin_unlock(&gr_learn_lock);
15675+ vfree(tmp);
15676+ }
15677+ if (learn_buffer_user != NULL) {
15678+ vfree(learn_buffer_user);
15679+ learn_buffer_user = NULL;
15680+ }
15681+ learn_buffer_len = 0;
15682+ learn_buffer_user_len = 0;
15683+ gr_learn_attached = 0;
15684+ up(&gr_learn_user_sem);
15685+ }
15686+
15687+ return 0;
15688+}
15689+
15690+struct file_operations grsec_fops = {
15691+ .read = read_learn,
15692+ .write = write_grsec_handler,
15693+ .open = open_learn,
15694+ .release = close_learn,
15695+ .poll = poll_learn,
15696+};
15697diff -urNp linux-2.6.17.7/grsecurity/gracl_res.c linux-2.6.17.7/grsecurity/gracl_res.c
15698--- linux-2.6.17.7/grsecurity/gracl_res.c 1969-12-31 19:00:00.000000000 -0500
15699+++ linux-2.6.17.7/grsecurity/gracl_res.c 2006-08-01 20:29:47.000000000 -0400
15700@@ -0,0 +1,45 @@
15701+#include <linux/kernel.h>
15702+#include <linux/sched.h>
15703+#include <linux/gracl.h>
15704+#include <linux/grinternal.h>
15705+
15706+static const char *restab_log[] = {
15707+ [RLIMIT_CPU] = "RLIMIT_CPU",
15708+ [RLIMIT_FSIZE] = "RLIMIT_FSIZE",
15709+ [RLIMIT_DATA] = "RLIMIT_DATA",
15710+ [RLIMIT_STACK] = "RLIMIT_STACK",
15711+ [RLIMIT_CORE] = "RLIMIT_CORE",
15712+ [RLIMIT_RSS] = "RLIMIT_RSS",
15713+ [RLIMIT_NPROC] = "RLIMIT_NPROC",
15714+ [RLIMIT_NOFILE] = "RLIMIT_NOFILE",
15715+ [RLIMIT_MEMLOCK] = "RLIMIT_MEMLOCK",
15716+ [RLIMIT_AS] = "RLIMIT_AS",
15717+ [RLIMIT_LOCKS] = "RLIMIT_LOCKS",
15718+ [RLIMIT_LOCKS + 1] = "RLIMIT_CRASH"
15719+};
15720+
15721+void
15722+gr_log_resource(const struct task_struct *task,
15723+ const int res, const unsigned long wanted, const int gt)
15724+{
15725+ if (res == RLIMIT_NPROC &&
15726+ (cap_raised(task->cap_effective, CAP_SYS_ADMIN) ||
15727+ cap_raised(task->cap_effective, CAP_SYS_RESOURCE)))
15728+ return;
15729+ else if (res == RLIMIT_MEMLOCK &&
15730+ cap_raised(task->cap_effective, CAP_IPC_LOCK))
15731+ return;
15732+
15733+ if (!gr_acl_is_enabled() && !grsec_resource_logging)
15734+ return;
15735+
15736+ preempt_disable();
15737+
15738+ if (unlikely(((gt && wanted > task->signal->rlim[res].rlim_cur) ||
15739+ (!gt && wanted >= task->signal->rlim[res].rlim_cur)) &&
15740+ task->signal->rlim[res].rlim_cur != RLIM_INFINITY))
15741+ gr_log_res_ulong2_str(GR_DONT_AUDIT, GR_RESOURCE_MSG, task, wanted, restab_log[res], task->signal->rlim[res].rlim_cur);
15742+ preempt_enable_no_resched();
15743+
15744+ return;
15745+}
15746diff -urNp linux-2.6.17.7/grsecurity/gracl_segv.c linux-2.6.17.7/grsecurity/gracl_segv.c
15747--- linux-2.6.17.7/grsecurity/gracl_segv.c 1969-12-31 19:00:00.000000000 -0500
15748+++ linux-2.6.17.7/grsecurity/gracl_segv.c 2006-08-01 20:29:47.000000000 -0400
15749@@ -0,0 +1,295 @@
15750+#include <linux/kernel.h>
15751+#include <linux/mm.h>
15752+#include <asm/uaccess.h>
15753+#include <asm/errno.h>
15754+#include <asm/mman.h>
15755+#include <net/sock.h>
15756+#include <linux/file.h>
15757+#include <linux/fs.h>
15758+#include <linux/net.h>
15759+#include <linux/in.h>
15760+#include <linux/smp_lock.h>
15761+#include <linux/slab.h>
15762+#include <linux/types.h>
15763+#include <linux/sched.h>
15764+#include <linux/timer.h>
15765+#include <linux/gracl.h>
15766+#include <linux/grsecurity.h>
15767+#include <linux/grinternal.h>
15768+
15769+static struct crash_uid *uid_set;
15770+static unsigned short uid_used;
15771+static spinlock_t gr_uid_lock = SPIN_LOCK_UNLOCKED;
15772+extern rwlock_t gr_inode_lock;
15773+extern struct acl_subject_label *
15774+ lookup_acl_subj_label(const ino_t inode, const dev_t dev,
15775+ struct acl_role_label *role);
15776+extern int specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t);
15777+
15778+int
15779+gr_init_uidset(void)
15780+{
15781+ uid_set =
15782+ kmalloc(GR_UIDTABLE_MAX * sizeof (struct crash_uid), GFP_KERNEL);
15783+ uid_used = 0;
15784+
15785+ return uid_set ? 1 : 0;
15786+}
15787+
15788+void
15789+gr_free_uidset(void)
15790+{
15791+ if (uid_set)
15792+ kfree(uid_set);
15793+
15794+ return;
15795+}
15796+
15797+int
15798+gr_find_uid(const uid_t uid)
15799+{
15800+ struct crash_uid *tmp = uid_set;
15801+ uid_t buid;
15802+ int low = 0, high = uid_used - 1, mid;
15803+
15804+ while (high >= low) {
15805+ mid = (low + high) >> 1;
15806+ buid = tmp[mid].uid;
15807+ if (buid == uid)
15808+ return mid;
15809+ if (buid > uid)
15810+ high = mid - 1;
15811+ if (buid < uid)
15812+ low = mid + 1;
15813+ }
15814+
15815+ return -1;
15816+}
15817+
15818+static __inline__ void
15819+gr_insertsort(void)
15820+{
15821+ unsigned short i, j;
15822+ struct crash_uid index;
15823+
15824+ for (i = 1; i < uid_used; i++) {
15825+ index = uid_set[i];
15826+ j = i;
15827+ while ((j > 0) && uid_set[j - 1].uid > index.uid) {
15828+ uid_set[j] = uid_set[j - 1];
15829+ j--;
15830+ }
15831+ uid_set[j] = index;
15832+ }
15833+
15834+ return;
15835+}
15836+
15837+static __inline__ void
15838+gr_insert_uid(const uid_t uid, const unsigned long expires)
15839+{
15840+ int loc;
15841+
15842+ if (uid_used == GR_UIDTABLE_MAX)
15843+ return;
15844+
15845+ loc = gr_find_uid(uid);
15846+
15847+ if (loc >= 0) {
15848+ uid_set[loc].expires = expires;
15849+ return;
15850+ }
15851+
15852+ uid_set[uid_used].uid = uid;
15853+ uid_set[uid_used].expires = expires;
15854+ uid_used++;
15855+
15856+ gr_insertsort();
15857+
15858+ return;
15859+}
15860+
15861+void
15862+gr_remove_uid(const unsigned short loc)
15863+{
15864+ unsigned short i;
15865+
15866+ for (i = loc + 1; i < uid_used; i++)
15867+ uid_set[i - 1] = uid_set[i];
15868+
15869+ uid_used--;
15870+
15871+ return;
15872+}
15873+
15874+int
15875+gr_check_crash_uid(const uid_t uid)
15876+{
15877+ int loc;
15878+ int ret = 0;
15879+
15880+ if (unlikely(!gr_acl_is_enabled()))
15881+ return 0;
15882+
15883+ spin_lock(&gr_uid_lock);
15884+ loc = gr_find_uid(uid);
15885+
15886+ if (loc < 0)
15887+ goto out_unlock;
15888+
15889+ if (time_before_eq(uid_set[loc].expires, get_seconds()))
15890+ gr_remove_uid(loc);
15891+ else
15892+ ret = 1;
15893+
15894+out_unlock:
15895+ spin_unlock(&gr_uid_lock);
15896+ return ret;
15897+}
15898+
15899+static __inline__ int
15900+proc_is_setxid(const struct task_struct *task)
15901+{
15902+ if (task->uid != task->euid || task->uid != task->suid ||
15903+ task->uid != task->fsuid)
15904+ return 1;
15905+ if (task->gid != task->egid || task->gid != task->sgid ||
15906+ task->gid != task->fsgid)
15907+ return 1;
15908+
15909+ return 0;
15910+}
15911+static __inline__ int
15912+gr_fake_force_sig(int sig, struct task_struct *t)
15913+{
15914+ unsigned long int flags;
15915+ int ret;
15916+
15917+ spin_lock_irqsave(&t->sighand->siglock, flags);
15918+ if (sigismember(&t->blocked, sig) || t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) {
15919+ t->sighand->action[sig-1].sa.sa_handler = SIG_DFL;
15920+ sigdelset(&t->blocked, sig);
15921+ recalc_sigpending_tsk(t);
15922+ }
15923+ ret = specific_send_sig_info(sig, (void*)1L, t);
15924+ spin_unlock_irqrestore(&t->sighand->siglock, flags);
15925+
15926+ return ret;
15927+}
15928+
15929+void
15930+gr_handle_crash(struct task_struct *task, const int sig)
15931+{
15932+ struct acl_subject_label *curr;
15933+ struct acl_subject_label *curr2;
15934+ struct task_struct *tsk, *tsk2;
15935+
15936+ if (sig != SIGSEGV && sig != SIGKILL && sig != SIGBUS && sig != SIGILL)
15937+ return;
15938+
15939+ if (unlikely(!gr_acl_is_enabled()))
15940+ return;
15941+
15942+ curr = task->acl;
15943+
15944+ if (!(curr->resmask & (1 << GR_CRASH_RES)))
15945+ return;
15946+
15947+ if (time_before_eq(curr->expires, get_seconds())) {
15948+ curr->expires = 0;
15949+ curr->crashes = 0;
15950+ }
15951+
15952+ curr->crashes++;
15953+
15954+ if (!curr->expires)
15955+ curr->expires = get_seconds() + curr->res[GR_CRASH_RES].rlim_max;
15956+
15957+ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
15958+ time_after(curr->expires, get_seconds())) {
15959+ if (task->uid && proc_is_setxid(task)) {
15960+ gr_log_crash1(GR_DONT_AUDIT, GR_SEGVSTART_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
15961+ spin_lock(&gr_uid_lock);
15962+ gr_insert_uid(task->uid, curr->expires);
15963+ spin_unlock(&gr_uid_lock);
15964+ curr->expires = 0;
15965+ curr->crashes = 0;
15966+ read_lock(&tasklist_lock);
15967+ do_each_thread(tsk2, tsk) {
15968+ if (tsk != task && tsk->uid == task->uid)
15969+ gr_fake_force_sig(SIGKILL, tsk);
15970+ } while_each_thread(tsk2, tsk);
15971+ read_unlock(&tasklist_lock);
15972+ } else {
15973+ gr_log_crash2(GR_DONT_AUDIT, GR_SEGVNOSUID_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
15974+ read_lock(&tasklist_lock);
15975+ do_each_thread(tsk2, tsk) {
15976+ if (likely(tsk != task)) {
15977+ curr2 = tsk->acl;
15978+
15979+ if (curr2->device == curr->device &&
15980+ curr2->inode == curr->inode)
15981+ gr_fake_force_sig(SIGKILL, tsk);
15982+ }
15983+ } while_each_thread(tsk2, tsk);
15984+ read_unlock(&tasklist_lock);
15985+ }
15986+ }
15987+
15988+ return;
15989+}
15990+
15991+int
15992+gr_check_crash_exec(const struct file *filp)
15993+{
15994+ struct acl_subject_label *curr;
15995+
15996+ if (unlikely(!gr_acl_is_enabled()))
15997+ return 0;
15998+
15999+ read_lock(&gr_inode_lock);
16000+ curr = lookup_acl_subj_label(filp->f_dentry->d_inode->i_ino,
16001+ filp->f_dentry->d_inode->i_sb->s_dev,
16002+ current->role);
16003+ read_unlock(&gr_inode_lock);
16004+
16005+ if (!curr || !(curr->resmask & (1 << GR_CRASH_RES)) ||
16006+ (!curr->crashes && !curr->expires))
16007+ return 0;
16008+
16009+ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
16010+ time_after(curr->expires, get_seconds()))
16011+ return 1;
16012+ else if (time_before_eq(curr->expires, get_seconds())) {
16013+ curr->crashes = 0;
16014+ curr->expires = 0;
16015+ }
16016+
16017+ return 0;
16018+}
16019+
16020+void
16021+gr_handle_alertkill(struct task_struct *task)
16022+{
16023+ struct acl_subject_label *curracl;
16024+ __u32 curr_ip;
16025+ struct task_struct *p, *p2;
16026+
16027+ if (unlikely(!gr_acl_is_enabled()))
16028+ return;
16029+
16030+ curracl = task->acl;
16031+ curr_ip = task->signal->curr_ip;
16032+
16033+ if ((curracl->mode & GR_KILLIPPROC) && curr_ip) {
16034+ read_lock(&tasklist_lock);
16035+ do_each_thread(p2, p) {
16036+ if (p->signal->curr_ip == curr_ip)
16037+ gr_fake_force_sig(SIGKILL, p);
16038+ } while_each_thread(p2, p);
16039+ read_unlock(&tasklist_lock);
16040+ } else if (curracl->mode & GR_KILLPROC)
16041+ gr_fake_force_sig(SIGKILL, task);
16042+
16043+ return;
16044+}
16045diff -urNp linux-2.6.17.7/grsecurity/gracl_shm.c linux-2.6.17.7/grsecurity/gracl_shm.c
16046--- linux-2.6.17.7/grsecurity/gracl_shm.c 1969-12-31 19:00:00.000000000 -0500
16047+++ linux-2.6.17.7/grsecurity/gracl_shm.c 2006-08-01 20:29:47.000000000 -0400
0362670a 16048@@ -0,0 +1,34 @@
f1a4f855 16049+#include <linux/kernel.h>
16050+#include <linux/mm.h>
16051+#include <linux/sched.h>
16052+#include <linux/file.h>
16053+#include <linux/ipc.h>
16054+#include <linux/gracl.h>
16055+#include <linux/grsecurity.h>
16056+#include <linux/grinternal.h>
0362670a 16057+#include <linux/vs_pid.h>
f1a4f855 16058+
16059+int
16060+gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
16061+ const time_t shm_createtime, const uid_t cuid, const int shmid)
16062+{
16063+ struct task_struct *task;
16064+
16065+ if (!gr_acl_is_enabled())
16066+ return 1;
16067+
16068+ task = find_task_by_pid(shm_cprid);
16069+
16070+ if (unlikely(!task))
16071+ task = find_task_by_pid(shm_lapid);
16072+
16073+ if (unlikely(task && (time_before((unsigned long)task->start_time.tv_sec, (unsigned long)shm_createtime) ||
16074+ (task->pid == shm_lapid)) &&
16075+ (task->acl->mode & GR_PROTSHM) &&
16076+ (task->acl != current->acl))) {
16077+ gr_log_int3(GR_DONT_AUDIT, GR_SHMAT_ACL_MSG, cuid, shm_cprid, shmid);
16078+ return 0;
16079+ }
16080+
16081+ return 1;
16082+}
16083diff -urNp linux-2.6.17.7/grsecurity/grsec_chdir.c linux-2.6.17.7/grsecurity/grsec_chdir.c
16084--- linux-2.6.17.7/grsecurity/grsec_chdir.c 1969-12-31 19:00:00.000000000 -0500
16085+++ linux-2.6.17.7/grsecurity/grsec_chdir.c 2006-08-01 20:29:47.000000000 -0400
16086@@ -0,0 +1,19 @@
16087+#include <linux/kernel.h>
16088+#include <linux/sched.h>
16089+#include <linux/fs.h>
16090+#include <linux/file.h>
16091+#include <linux/grsecurity.h>
16092+#include <linux/grinternal.h>
16093+
16094+void
16095+gr_log_chdir(const struct dentry *dentry, const struct vfsmount *mnt)
16096+{
16097+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
16098+ if ((grsec_enable_chdir && grsec_enable_group &&
16099+ in_group_p(grsec_audit_gid)) || (grsec_enable_chdir &&
16100+ !grsec_enable_group)) {
16101+ gr_log_fs_generic(GR_DO_AUDIT, GR_CHDIR_AUDIT_MSG, dentry, mnt);
16102+ }
16103+#endif
16104+ return;
16105+}
16106diff -urNp linux-2.6.17.7/grsecurity/grsec_chroot.c linux-2.6.17.7/grsecurity/grsec_chroot.c
16107--- linux-2.6.17.7/grsecurity/grsec_chroot.c 1969-12-31 19:00:00.000000000 -0500
16108+++ linux-2.6.17.7/grsecurity/grsec_chroot.c 2006-08-01 20:29:47.000000000 -0400
16109@@ -0,0 +1,332 @@
16110+#include <linux/kernel.h>
16111+#include <linux/module.h>
16112+#include <linux/sched.h>
16113+#include <linux/file.h>
16114+#include <linux/fs.h>
16115+#include <linux/mount.h>
16116+#include <linux/types.h>
16117+#include <linux/grinternal.h>
16118+
16119+int
16120+gr_handle_chroot_unix(const pid_t pid)
16121+{
16122+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
16123+ struct pid *spid = NULL;
16124+
16125+ if (unlikely(!grsec_enable_chroot_unix))
16126+ return 1;
16127+
16128+ if (likely(!proc_is_chrooted(current)))
16129+ return 1;
16130+
16131+ read_lock(&tasklist_lock);
16132+
16133+ spid = find_pid(pid);
16134+ if (spid) {
16135+ struct task_struct *p;
16136+ p = pid_task(spid, PIDTYPE_PID);
16137+ task_lock(p);
16138+ if (unlikely(!have_same_root(current, p))) {
16139+ task_unlock(p);
16140+ read_unlock(&tasklist_lock);
16141+ gr_log_noargs(GR_DONT_AUDIT, GR_UNIX_CHROOT_MSG);
16142+ return 0;
16143+ }
16144+ task_unlock(p);
16145+ }
16146+ read_unlock(&tasklist_lock);
16147+#endif
16148+ return 1;
16149+}
16150+
16151+int
16152+gr_handle_chroot_nice(void)
16153+{
16154+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
16155+ if (grsec_enable_chroot_nice && proc_is_chrooted(current)) {
16156+ gr_log_noargs(GR_DONT_AUDIT, GR_NICE_CHROOT_MSG);
16157+ return -EPERM;
16158+ }
16159+#endif
16160+ return 0;
16161+}
16162+
16163+int
16164+gr_handle_chroot_setpriority(struct task_struct *p, const int niceval)
16165+{
16166+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
16167+ if (grsec_enable_chroot_nice && (niceval < task_nice(p))
16168+ && proc_is_chrooted(current)) {
16169+ gr_log_str_int(GR_DONT_AUDIT, GR_PRIORITY_CHROOT_MSG, p->comm, p->pid);
16170+ return -EACCES;
16171+ }
16172+#endif
16173+ return 0;
16174+}
16175+
16176+int
16177+gr_handle_chroot_rawio(const struct inode *inode)
16178+{
16179+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
16180+ if (grsec_enable_chroot_caps && proc_is_chrooted(current) &&
16181+ inode && S_ISBLK(inode->i_mode) && !capable(CAP_SYS_RAWIO))
16182+ return 1;
16183+#endif
16184+ return 0;
16185+}
16186+
16187+int
16188+gr_pid_is_chrooted(struct task_struct *p)
16189+{
16190+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
16191+ if (!grsec_enable_chroot_findtask || !proc_is_chrooted(current) || !p)
16192+ return 0;
16193+
16194+ task_lock(p);
16195+ if ((p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) ||
16196+ !have_same_root(current, p)) {
16197+ task_unlock(p);
16198+ return 1;
16199+ }
16200+ task_unlock(p);
16201+#endif
16202+ return 0;
16203+}
16204+
16205+EXPORT_SYMBOL(gr_pid_is_chrooted);
16206+
16207+#if defined(CONFIG_GRKERNSEC_CHROOT_DOUBLE) || defined(CONFIG_GRKERNSEC_CHROOT_FCHDIR)
16208+int gr_is_outside_chroot(const struct dentry *u_dentry, const struct vfsmount *u_mnt)
16209+{
16210+ struct dentry *dentry = (struct dentry *)u_dentry;
16211+ struct vfsmount *mnt = (struct vfsmount *)u_mnt;
16212+ struct dentry *realroot;
16213+ struct vfsmount *realrootmnt;
16214+ struct dentry *currentroot;
16215+ struct vfsmount *currentmnt;
16216+ int ret = 1;
16217+
16218+ read_lock(&child_reaper->fs->lock);
16219+ realrootmnt = mntget(child_reaper->fs->rootmnt);
16220+ realroot = dget(child_reaper->fs->root);
16221+ read_unlock(&child_reaper->fs->lock);
16222+
16223+ read_lock(&current->fs->lock);
16224+ currentmnt = mntget(current->fs->rootmnt);
16225+ currentroot = dget(current->fs->root);
16226+ read_unlock(&current->fs->lock);
16227+
16228+ spin_lock(&dcache_lock);
16229+ for (;;) {
16230+ if (unlikely((dentry == realroot && mnt == realrootmnt)
16231+ || (dentry == currentroot && mnt == currentmnt)))
16232+ break;
16233+ if (unlikely(dentry == mnt->mnt_root || IS_ROOT(dentry))) {
16234+ if (mnt->mnt_parent == mnt)
16235+ break;
16236+ dentry = mnt->mnt_mountpoint;
16237+ mnt = mnt->mnt_parent;
16238+ continue;
16239+ }
16240+ dentry = dentry->d_parent;
16241+ }
16242+ spin_unlock(&dcache_lock);
16243+
16244+ dput(currentroot);
16245+ mntput(currentmnt);
16246+
16247+ /* access is outside of chroot */
16248+ if (dentry == realroot && mnt == realrootmnt)
16249+ ret = 0;
16250+
16251+ dput(realroot);
16252+ mntput(realrootmnt);
16253+ return ret;
16254+}
16255+#endif
16256+
16257+int
16258+gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt)
16259+{
16260+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
16261+ if (!grsec_enable_chroot_fchdir)
16262+ return 1;
16263+
16264+ if (!proc_is_chrooted(current))
16265+ return 1;
16266+ else if (!gr_is_outside_chroot(u_dentry, u_mnt)) {
16267+ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_FCHDIR_MSG, u_dentry, u_mnt);
16268+ return 0;
16269+ }
16270+#endif
16271+ return 1;
16272+}
16273+
16274+int
16275+gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
16276+ const time_t shm_createtime)
16277+{
16278+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
16279+ struct pid *pid = NULL;
16280+ time_t starttime;
16281+
16282+ if (unlikely(!grsec_enable_chroot_shmat))
16283+ return 1;
16284+
16285+ if (likely(!proc_is_chrooted(current)))
16286+ return 1;
16287+
16288+ read_lock(&tasklist_lock);
16289+
16290+ pid = find_pid(shm_cprid);
16291+ if (pid) {
16292+ struct task_struct *p;
16293+ p = pid_task(pid, PIDTYPE_PID);
16294+ task_lock(p);
16295+ starttime = p->start_time.tv_sec;
16296+ if (unlikely(!have_same_root(current, p) &&
16297+ time_before((unsigned long)starttime, (unsigned long)shm_createtime))) {
16298+ task_unlock(p);
16299+ read_unlock(&tasklist_lock);
16300+ gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG);
16301+ return 0;
16302+ }
16303+ task_unlock(p);
16304+ } else {
16305+ pid = find_pid(shm_lapid);
16306+ if (pid) {
16307+ struct task_struct *p;
16308+ p = pid_task(pid, PIDTYPE_PID);
16309+ task_lock(p);
16310+ if (unlikely(!have_same_root(current, p))) {
16311+ task_unlock(p);
16312+ read_unlock(&tasklist_lock);
16313+ gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG);
16314+ return 0;
16315+ }
16316+ task_unlock(p);
16317+ }
16318+ }
16319+
16320+ read_unlock(&tasklist_lock);
16321+#endif
16322+ return 1;
16323+}
16324+
16325+void
16326+gr_log_chroot_exec(const struct dentry *dentry, const struct vfsmount *mnt)
16327+{
16328+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
16329+ if (grsec_enable_chroot_execlog && proc_is_chrooted(current))
16330+ gr_log_fs_generic(GR_DO_AUDIT, GR_EXEC_CHROOT_MSG, dentry, mnt);
16331+#endif
16332+ return;
16333+}
16334+
16335+int
16336+gr_handle_chroot_mknod(const struct dentry *dentry,
16337+ const struct vfsmount *mnt, const int mode)
16338+{
16339+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
16340+ if (grsec_enable_chroot_mknod && !S_ISFIFO(mode) && !S_ISREG(mode) &&
16341+ proc_is_chrooted(current)) {
16342+ gr_log_fs_generic(GR_DONT_AUDIT, GR_MKNOD_CHROOT_MSG, dentry, mnt);
16343+ return -EPERM;
16344+ }
16345+#endif
16346+ return 0;
16347+}
16348+
16349+int
16350+gr_handle_chroot_mount(const struct dentry *dentry,
16351+ const struct vfsmount *mnt, const char *dev_name)
16352+{
16353+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
16354+ if (grsec_enable_chroot_mount && proc_is_chrooted(current)) {
16355+ gr_log_str_fs(GR_DONT_AUDIT, GR_MOUNT_CHROOT_MSG, dev_name, dentry, mnt);
16356+ return -EPERM;
16357+ }
16358+#endif
16359+ return 0;
16360+}
16361+
16362+int
16363+gr_handle_chroot_pivot(void)
16364+{
16365+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
16366+ if (grsec_enable_chroot_pivot && proc_is_chrooted(current)) {
16367+ gr_log_noargs(GR_DONT_AUDIT, GR_PIVOT_CHROOT_MSG);
16368+ return -EPERM;
16369+ }
16370+#endif
16371+ return 0;
16372+}
16373+
16374+int
16375+gr_handle_chroot_chroot(const struct dentry *dentry, const struct vfsmount *mnt)
16376+{
16377+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
16378+ if (grsec_enable_chroot_double && proc_is_chrooted(current) &&
16379+ !gr_is_outside_chroot(dentry, mnt)) {
16380+ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_CHROOT_MSG, dentry, mnt);
16381+ return -EPERM;
16382+ }
16383+#endif
16384+ return 0;
16385+}
16386+
16387+void
16388+gr_handle_chroot_caps(struct task_struct *task)
16389+{
16390+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
16391+ if (grsec_enable_chroot_caps && proc_is_chrooted(task)) {
16392+ task->cap_permitted =
16393+ cap_drop(task->cap_permitted, GR_CHROOT_CAPS);
16394+ task->cap_inheritable =
16395+ cap_drop(task->cap_inheritable, GR_CHROOT_CAPS);
16396+ task->cap_effective =
16397+ cap_drop(task->cap_effective, GR_CHROOT_CAPS);
16398+ }
16399+#endif
16400+ return;
16401+}
16402+
16403+int
16404+gr_handle_chroot_sysctl(const int op)
16405+{
16406+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
16407+ if (grsec_enable_chroot_sysctl && proc_is_chrooted(current)
16408+ && (op & 002))
16409+ return -EACCES;
16410+#endif
16411+ return 0;
16412+}
16413+
16414+void
16415+gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt)
16416+{
16417+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
16418+ if (grsec_enable_chroot_chdir)
16419+ set_fs_pwd(current->fs, mnt, dentry);
16420+#endif
16421+ return;
16422+}
16423+
16424+int
16425+gr_handle_chroot_chmod(const struct dentry *dentry,
16426+ const struct vfsmount *mnt, const int mode)
16427+{
16428+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
16429+ if (grsec_enable_chroot_chmod &&
16430+ ((mode & S_ISUID) || ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) &&
16431+ proc_is_chrooted(current)) {
16432+ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHMOD_CHROOT_MSG, dentry, mnt);
16433+ return -EPERM;
16434+ }
16435+#endif
16436+ return 0;
16437+}
16438+
16439+#ifdef CONFIG_SECURITY
16440+EXPORT_SYMBOL(gr_handle_chroot_caps);
16441+#endif
16442diff -urNp linux-2.6.17.7/grsecurity/grsec_disabled.c linux-2.6.17.7/grsecurity/grsec_disabled.c
16443--- linux-2.6.17.7/grsecurity/grsec_disabled.c 1969-12-31 19:00:00.000000000 -0500
16444+++ linux-2.6.17.7/grsecurity/grsec_disabled.c 2006-08-01 20:29:47.000000000 -0400
16445@@ -0,0 +1,418 @@
16446+#include <linux/kernel.h>
16447+#include <linux/module.h>
16448+#include <linux/config.h>
16449+#include <linux/sched.h>
16450+#include <linux/file.h>
16451+#include <linux/fs.h>
16452+#include <linux/kdev_t.h>
16453+#include <linux/net.h>
16454+#include <linux/in.h>
16455+#include <linux/ip.h>
16456+#include <linux/skbuff.h>
16457+#include <linux/sysctl.h>
16458+
16459+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
16460+void
16461+pax_set_initial_flags(struct linux_binprm *bprm)
16462+{
16463+ return;
16464+}
16465+#endif
16466+
16467+#ifdef CONFIG_SYSCTL
16468+__u32
16469+gr_handle_sysctl(const struct ctl_table * table, __u32 mode)
16470+{
16471+ return mode;
16472+}
16473+#endif
16474+
16475+int
16476+gr_acl_is_enabled(void)
16477+{
16478+ return 0;
16479+}
16480+
16481+int
16482+gr_handle_rawio(const struct inode *inode)
16483+{
16484+ return 0;
16485+}
16486+
16487+void
16488+gr_acl_handle_psacct(struct task_struct *task, const long code)
16489+{
16490+ return;
16491+}
16492+
16493+int
16494+gr_handle_ptrace(struct task_struct *task, const long request)
16495+{
16496+ return 0;
16497+}
16498+
16499+int
16500+gr_handle_proc_ptrace(struct task_struct *task)
16501+{
16502+ return 0;
16503+}
16504+
16505+void
16506+gr_learn_resource(const struct task_struct *task,
16507+ const int res, const unsigned long wanted, const int gt)
16508+{
16509+ return;
16510+}
16511+
16512+int
16513+gr_set_acls(const int type)
16514+{
16515+ return 0;
16516+}
16517+
16518+int
16519+gr_check_hidden_task(const struct task_struct *tsk)
16520+{
16521+ return 0;
16522+}
16523+
16524+int
16525+gr_check_protected_task(const struct task_struct *task)
16526+{
16527+ return 0;
16528+}
16529+
16530+void
16531+gr_copy_label(struct task_struct *tsk)
16532+{
16533+ return;
16534+}
16535+
16536+void
16537+gr_set_pax_flags(struct task_struct *task)
16538+{
16539+ return;
16540+}
16541+
16542+int
16543+gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
16544+{
16545+ return 0;
16546+}
16547+
16548+void
16549+gr_handle_delete(const ino_t ino, const dev_t dev)
16550+{
16551+ return;
16552+}
16553+
16554+void
16555+gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
16556+{
16557+ return;
16558+}
16559+
16560+void
16561+gr_handle_crash(struct task_struct *task, const int sig)
16562+{
16563+ return;
16564+}
16565+
16566+int
16567+gr_check_crash_exec(const struct file *filp)
16568+{
16569+ return 0;
16570+}
16571+
16572+int
16573+gr_check_crash_uid(const uid_t uid)
16574+{
16575+ return 0;
16576+}
16577+
16578+void
16579+gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
16580+ struct dentry *old_dentry,
16581+ struct dentry *new_dentry,
16582+ struct vfsmount *mnt, const __u8 replace)
16583+{
16584+ return;
16585+}
16586+
16587+int
16588+gr_search_socket(const int family, const int type, const int protocol)
16589+{
16590+ return 1;
16591+}
16592+
16593+int
16594+gr_search_connectbind(const int mode, const struct socket *sock,
16595+ const struct sockaddr_in *addr)
16596+{
16597+ return 1;
16598+}
16599+
16600+int
16601+gr_task_is_capable(struct task_struct *task, const int cap)
16602+{
16603+ return 1;
16604+}
16605+
16606+int
16607+gr_is_capable_nolog(const int cap)
16608+{
16609+ return 1;
16610+}
16611+
16612+void
16613+gr_handle_alertkill(struct task_struct *task)
16614+{
16615+ return;
16616+}
16617+
16618+__u32
16619+gr_acl_handle_execve(const struct dentry * dentry, const struct vfsmount * mnt)
16620+{
16621+ return 1;
16622+}
16623+
16624+__u32
16625+gr_acl_handle_hidden_file(const struct dentry * dentry,
16626+ const struct vfsmount * mnt)
16627+{
16628+ return 1;
16629+}
16630+
16631+__u32
16632+gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
16633+ const int fmode)
16634+{
16635+ return 1;
16636+}
16637+
16638+__u32
16639+gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
16640+{
16641+ return 1;
16642+}
16643+
16644+__u32
16645+gr_acl_handle_unlink(const struct dentry * dentry, const struct vfsmount * mnt)
16646+{
16647+ return 1;
16648+}
16649+
16650+int
16651+gr_acl_handle_mmap(const struct file *file, const unsigned long prot,
16652+ unsigned int *vm_flags)
16653+{
16654+ return 1;
16655+}
16656+
16657+__u32
16658+gr_acl_handle_truncate(const struct dentry * dentry,
16659+ const struct vfsmount * mnt)
16660+{
16661+ return 1;
16662+}
16663+
16664+__u32
16665+gr_acl_handle_utime(const struct dentry * dentry, const struct vfsmount * mnt)
16666+{
16667+ return 1;
16668+}
16669+
16670+__u32
16671+gr_acl_handle_access(const struct dentry * dentry,
16672+ const struct vfsmount * mnt, const int fmode)
16673+{
16674+ return 1;
16675+}
16676+
16677+__u32
16678+gr_acl_handle_fchmod(const struct dentry * dentry, const struct vfsmount * mnt,
16679+ mode_t mode)
16680+{
16681+ return 1;
16682+}
16683+
16684+__u32
16685+gr_acl_handle_chmod(const struct dentry * dentry, const struct vfsmount * mnt,
16686+ mode_t mode)
16687+{
16688+ return 1;
16689+}
16690+
16691+__u32
16692+gr_acl_handle_chown(const struct dentry * dentry, const struct vfsmount * mnt)
16693+{
16694+ return 1;
16695+}
16696+
16697+void
16698+grsecurity_init(void)
16699+{
16700+ return;
16701+}
16702+
16703+__u32
16704+gr_acl_handle_mknod(const struct dentry * new_dentry,
16705+ const struct dentry * parent_dentry,
16706+ const struct vfsmount * parent_mnt,
16707+ const int mode)
16708+{
16709+ return 1;
16710+}
16711+
16712+__u32
16713+gr_acl_handle_mkdir(const struct dentry * new_dentry,
16714+ const struct dentry * parent_dentry,
16715+ const struct vfsmount * parent_mnt)
16716+{
16717+ return 1;
16718+}
16719+
16720+__u32
16721+gr_acl_handle_symlink(const struct dentry * new_dentry,
16722+ const struct dentry * parent_dentry,
16723+ const struct vfsmount * parent_mnt, const char *from)
16724+{
16725+ return 1;
16726+}
16727+
16728+__u32
16729+gr_acl_handle_link(const struct dentry * new_dentry,
16730+ const struct dentry * parent_dentry,
16731+ const struct vfsmount * parent_mnt,
16732+ const struct dentry * old_dentry,
16733+ const struct vfsmount * old_mnt, const char *to)
16734+{
16735+ return 1;
16736+}
16737+
16738+int
16739+gr_acl_handle_rename(const struct dentry *new_dentry,
16740+ const struct dentry *parent_dentry,
16741+ const struct vfsmount *parent_mnt,
16742+ const struct dentry *old_dentry,
16743+ const struct inode *old_parent_inode,
16744+ const struct vfsmount *old_mnt, const char *newname)
16745+{
16746+ return 0;
16747+}
16748+
16749+int
16750+gr_acl_handle_filldir(const struct file *file, const char *name,
16751+ const int namelen, const ino_t ino)
16752+{
16753+ return 1;
16754+}
16755+
16756+int
16757+gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
16758+ const time_t shm_createtime, const uid_t cuid, const int shmid)
16759+{
16760+ return 1;
16761+}
16762+
16763+int
16764+gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
16765+{
16766+ return 1;
16767+}
16768+
16769+int
16770+gr_search_accept(const struct socket *sock)
16771+{
16772+ return 1;
16773+}
16774+
16775+int
16776+gr_search_listen(const struct socket *sock)
16777+{
16778+ return 1;
16779+}
16780+
16781+int
16782+gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
16783+{
16784+ return 1;
16785+}
16786+
16787+__u32
16788+gr_acl_handle_unix(const struct dentry * dentry, const struct vfsmount * mnt)
16789+{
16790+ return 1;
16791+}
16792+
16793+__u32
16794+gr_acl_handle_creat(const struct dentry * dentry,
16795+ const struct dentry * p_dentry,
16796+ const struct vfsmount * p_mnt, const int fmode,
16797+ const int imode)
16798+{
16799+ return 1;
16800+}
16801+
16802+void
16803+gr_acl_handle_exit(void)
16804+{
16805+ return;
16806+}
16807+
16808+int
16809+gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
16810+{
16811+ return 1;
16812+}
16813+
16814+void
16815+gr_set_role_label(const uid_t uid, const gid_t gid)
16816+{
16817+ return;
16818+}
16819+
16820+int
16821+gr_acl_handle_procpidmem(const struct task_struct *task)
16822+{
16823+ return 0;
16824+}
16825+
16826+int
16827+gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
16828+{
16829+ return 1;
16830+}
16831+
16832+int
16833+gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
16834+{
16835+ return 1;
16836+}
16837+
16838+void
16839+gr_set_kernel_label(struct task_struct *task)
16840+{
16841+ return;
16842+}
16843+
16844+int
16845+gr_check_user_change(int real, int effective, int fs)
16846+{
16847+ return 0;
16848+}
16849+
16850+int
16851+gr_check_group_change(int real, int effective, int fs)
16852+{
16853+ return 0;
16854+}
16855+
16856+
16857+EXPORT_SYMBOL(gr_task_is_capable);
16858+EXPORT_SYMBOL(gr_learn_resource);
16859+EXPORT_SYMBOL(gr_set_kernel_label);
16860+#ifdef CONFIG_SECURITY
16861+EXPORT_SYMBOL(gr_check_user_change);
16862+EXPORT_SYMBOL(gr_check_group_change);
16863+#endif
16864diff -urNp linux-2.6.17.7/grsecurity/grsec_exec.c linux-2.6.17.7/grsecurity/grsec_exec.c
16865--- linux-2.6.17.7/grsecurity/grsec_exec.c 1969-12-31 19:00:00.000000000 -0500
16866+++ linux-2.6.17.7/grsecurity/grsec_exec.c 2006-08-01 20:29:47.000000000 -0400
16867@@ -0,0 +1,88 @@
16868+#include <linux/kernel.h>
16869+#include <linux/sched.h>
16870+#include <linux/file.h>
16871+#include <linux/binfmts.h>
16872+#include <linux/smp_lock.h>
16873+#include <linux/fs.h>
16874+#include <linux/types.h>
16875+#include <linux/grdefs.h>
16876+#include <linux/grinternal.h>
16877+#include <linux/capability.h>
16878+
16879+#include <asm/uaccess.h>
16880+
16881+#ifdef CONFIG_GRKERNSEC_EXECLOG
16882+static char gr_exec_arg_buf[132];
16883+static DECLARE_MUTEX(gr_exec_arg_sem);
16884+#endif
16885+
16886+int
16887+gr_handle_nproc(void)
16888+{
16889+#ifdef CONFIG_GRKERNSEC_EXECVE
16890+ if (grsec_enable_execve && current->user &&
16891+ (atomic_read(&current->user->processes) >
16892+ current->signal->rlim[RLIMIT_NPROC].rlim_cur) &&
16893+ !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) {
16894+ gr_log_noargs(GR_DONT_AUDIT, GR_NPROC_MSG);
16895+ return -EAGAIN;
16896+ }
16897+#endif
16898+ return 0;
16899+}
16900+
16901+void
16902+gr_handle_exec_args(struct linux_binprm *bprm, const char __user *__user *argv)
16903+{
16904+#ifdef CONFIG_GRKERNSEC_EXECLOG
16905+ char *grarg = gr_exec_arg_buf;
16906+ unsigned int i, x, execlen = 0;
16907+ char c;
16908+
16909+ if (!((grsec_enable_execlog && grsec_enable_group &&
16910+ in_group_p(grsec_audit_gid))
16911+ || (grsec_enable_execlog && !grsec_enable_group)))
16912+ return;
16913+
16914+ down(&gr_exec_arg_sem);
16915+ memset(grarg, 0, sizeof(gr_exec_arg_buf));
16916+
16917+ if (unlikely(argv == NULL))
16918+ goto log;
16919+
16920+ for (i = 0; i < bprm->argc && execlen < 128; i++) {
16921+ const char __user *p;
16922+ unsigned int len;
16923+
16924+ if (copy_from_user(&p, argv + i, sizeof(p)))
16925+ goto log;
16926+ if (!p)
16927+ goto log;
16928+ len = strnlen_user(p, 128 - execlen);
16929+ if (len > 128 - execlen)
16930+ len = 128 - execlen;
16931+ else if (len > 0)
16932+ len--;
16933+ if (copy_from_user(grarg + execlen, p, len))
16934+ goto log;
16935+
16936+ /* rewrite unprintable characters */
16937+ for (x = 0; x < len; x++) {
16938+ c = *(grarg + execlen + x);
16939+ if (c < 32 || c > 126)
16940+ *(grarg + execlen + x) = ' ';
16941+ }
16942+
16943+ execlen += len;
16944+ *(grarg + execlen) = ' ';
16945+ *(grarg + execlen + 1) = '\0';
16946+ execlen++;
16947+ }
16948+
16949+ log:
16950+ gr_log_fs_str(GR_DO_AUDIT, GR_EXEC_AUDIT_MSG, bprm->file->f_dentry,
16951+ bprm->file->f_vfsmnt, grarg);
16952+ up(&gr_exec_arg_sem);
16953+#endif
16954+ return;
16955+}
16956diff -urNp linux-2.6.17.7/grsecurity/grsec_fifo.c linux-2.6.17.7/grsecurity/grsec_fifo.c
16957--- linux-2.6.17.7/grsecurity/grsec_fifo.c 1969-12-31 19:00:00.000000000 -0500
16958+++ linux-2.6.17.7/grsecurity/grsec_fifo.c 2006-08-01 20:29:47.000000000 -0400
16959@@ -0,0 +1,22 @@
16960+#include <linux/kernel.h>
16961+#include <linux/sched.h>
16962+#include <linux/fs.h>
16963+#include <linux/file.h>
16964+#include <linux/grinternal.h>
16965+
16966+int
16967+gr_handle_fifo(const struct dentry *dentry, const struct vfsmount *mnt,
16968+ const struct dentry *dir, const int flag, const int acc_mode)
16969+{
16970+#ifdef CONFIG_GRKERNSEC_FIFO
16971+ if (grsec_enable_fifo && S_ISFIFO(dentry->d_inode->i_mode) &&
16972+ !(flag & O_EXCL) && (dir->d_inode->i_mode & S_ISVTX) &&
16973+ (dentry->d_inode->i_uid != dir->d_inode->i_uid) &&
16974+ (current->fsuid != dentry->d_inode->i_uid)) {
16975+ if (!generic_permission(dentry->d_inode, acc_mode, NULL))
16976+ gr_log_fs_int2(GR_DONT_AUDIT, GR_FIFO_MSG, dentry, mnt, dentry->d_inode->i_uid, dentry->d_inode->i_gid);
16977+ return -EACCES;
16978+ }
16979+#endif
16980+ return 0;
16981+}
16982diff -urNp linux-2.6.17.7/grsecurity/grsec_fork.c linux-2.6.17.7/grsecurity/grsec_fork.c
16983--- linux-2.6.17.7/grsecurity/grsec_fork.c 1969-12-31 19:00:00.000000000 -0500
16984+++ linux-2.6.17.7/grsecurity/grsec_fork.c 2006-08-01 20:49:45.000000000 -0400
16985@@ -0,0 +1,15 @@
16986+#include <linux/kernel.h>
16987+#include <linux/sched.h>
16988+#include <linux/grsecurity.h>
16989+#include <linux/grinternal.h>
16990+#include <linux/errno.h>
16991+
16992+void
16993+gr_log_forkfail(const int retval)
16994+{
16995+#ifdef CONFIG_GRKERNSEC_FORKFAIL
16996+ if (grsec_enable_forkfail && retval != -ERESTARTNOINTR)
16997+ gr_log_int(GR_DONT_AUDIT, GR_FAILFORK_MSG, retval);
16998+#endif
16999+ return;
17000+}
17001diff -urNp linux-2.6.17.7/grsecurity/grsec_init.c linux-2.6.17.7/grsecurity/grsec_init.c
17002--- linux-2.6.17.7/grsecurity/grsec_init.c 1969-12-31 19:00:00.000000000 -0500
17003+++ linux-2.6.17.7/grsecurity/grsec_init.c 2006-08-01 20:29:47.000000000 -0400
17004@@ -0,0 +1,236 @@
17005+#include <linux/kernel.h>
17006+#include <linux/sched.h>
17007+#include <linux/mm.h>
17008+#include <linux/smp_lock.h>
17009+#include <linux/gracl.h>
17010+#include <linux/slab.h>
17011+#include <linux/vmalloc.h>
17012+#include <linux/percpu.h>
17013+
17014+int grsec_enable_shm;
17015+int grsec_enable_link;
17016+int grsec_enable_dmesg;
17017+int grsec_enable_fifo;
17018+int grsec_enable_execve;
17019+int grsec_enable_execlog;
17020+int grsec_enable_signal;
17021+int grsec_enable_forkfail;
17022+int grsec_enable_time;
17023+int grsec_enable_audit_textrel;
17024+int grsec_enable_group;
17025+int grsec_audit_gid;
17026+int grsec_enable_chdir;
17027+int grsec_enable_audit_ipc;
17028+int grsec_enable_mount;
17029+int grsec_enable_chroot_findtask;
17030+int grsec_enable_chroot_mount;
17031+int grsec_enable_chroot_shmat;
17032+int grsec_enable_chroot_fchdir;
17033+int grsec_enable_chroot_double;
17034+int grsec_enable_chroot_pivot;
17035+int grsec_enable_chroot_chdir;
17036+int grsec_enable_chroot_chmod;
17037+int grsec_enable_chroot_mknod;
17038+int grsec_enable_chroot_nice;
17039+int grsec_enable_chroot_execlog;
17040+int grsec_enable_chroot_caps;
17041+int grsec_enable_chroot_sysctl;
17042+int grsec_enable_chroot_unix;
17043+int grsec_enable_tpe;
17044+int grsec_tpe_gid;
17045+int grsec_enable_tpe_all;
17046+int grsec_enable_randpid;
17047+int grsec_enable_socket_all;
17048+int grsec_socket_all_gid;
17049+int grsec_enable_socket_client;
17050+int grsec_socket_client_gid;
17051+int grsec_enable_socket_server;
17052+int grsec_socket_server_gid;
17053+int grsec_resource_logging;
17054+int grsec_lock;
17055+
17056+spinlock_t grsec_alert_lock = SPIN_LOCK_UNLOCKED;
17057+unsigned long grsec_alert_wtime = 0;
17058+unsigned long grsec_alert_fyet = 0;
17059+
17060+spinlock_t grsec_audit_lock = SPIN_LOCK_UNLOCKED;
17061+
17062+rwlock_t grsec_exec_file_lock = RW_LOCK_UNLOCKED;
17063+
17064+char *gr_shared_page[4];
17065+
17066+char *gr_alert_log_fmt;
17067+char *gr_audit_log_fmt;
17068+char *gr_alert_log_buf;
17069+char *gr_audit_log_buf;
17070+
17071+extern struct gr_arg *gr_usermode;
17072+extern unsigned char *gr_system_salt;
17073+extern unsigned char *gr_system_sum;
17074+
17075+void
17076+grsecurity_init(void)
17077+{
17078+ int j;
17079+ /* create the per-cpu shared pages */
17080+
17081+ preempt_disable();
17082+ for (j = 0; j < 4; j++) {
17083+ gr_shared_page[j] = (char *)__alloc_percpu(PAGE_SIZE);
17084+ if (gr_shared_page[j] == NULL) {
17085+ panic("Unable to allocate grsecurity shared page");
17086+ return;
17087+ }
17088+ }
17089+ preempt_enable();
17090+
17091+ /* allocate log buffers */
17092+ gr_alert_log_fmt = kmalloc(512, GFP_KERNEL);
17093+ if (!gr_alert_log_fmt) {
17094+ panic("Unable to allocate grsecurity alert log format buffer");
17095+ return;
17096+ }
17097+ gr_audit_log_fmt = kmalloc(512, GFP_KERNEL);
17098+ if (!gr_audit_log_fmt) {
17099+ panic("Unable to allocate grsecurity audit log format buffer");
17100+ return;
17101+ }
17102+ gr_alert_log_buf = (char *) get_zeroed_page(GFP_KERNEL);
17103+ if (!gr_alert_log_buf) {
17104+ panic("Unable to allocate grsecurity alert log buffer");
17105+ return;
17106+ }
17107+ gr_audit_log_buf = (char *) get_zeroed_page(GFP_KERNEL);
17108+ if (!gr_audit_log_buf) {
17109+ panic("Unable to allocate grsecurity audit log buffer");
17110+ return;
17111+ }
17112+
17113+ /* allocate memory for authentication structure */
17114+ gr_usermode = kmalloc(sizeof(struct gr_arg), GFP_KERNEL);
17115+ gr_system_salt = kmalloc(GR_SALT_LEN, GFP_KERNEL);
17116+ gr_system_sum = kmalloc(GR_SHA_LEN, GFP_KERNEL);
17117+
17118+ if (!gr_usermode || !gr_system_salt || !gr_system_sum) {
17119+ panic("Unable to allocate grsecurity authentication structure");
17120+ return;
17121+ }
17122+
17123+#if !defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_SYSCTL_ON)
17124+#ifndef CONFIG_GRKERNSEC_SYSCTL
17125+ grsec_lock = 1;
17126+#endif
17127+#ifdef CONFIG_GRKERNSEC_SHM
17128+ grsec_enable_shm = 1;
17129+#endif
17130+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
17131+ grsec_enable_audit_textrel = 1;
17132+#endif
17133+#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
17134+ grsec_enable_group = 1;
17135+ grsec_audit_gid = CONFIG_GRKERNSEC_AUDIT_GID;
17136+#endif
17137+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
17138+ grsec_enable_chdir = 1;
17139+#endif
17140+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
17141+ grsec_enable_audit_ipc = 1;
17142+#endif
17143+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
17144+ grsec_enable_mount = 1;
17145+#endif
17146+#ifdef CONFIG_GRKERNSEC_LINK
17147+ grsec_enable_link = 1;
17148+#endif
17149+#ifdef CONFIG_GRKERNSEC_DMESG
17150+ grsec_enable_dmesg = 1;
17151+#endif
17152+#ifdef CONFIG_GRKERNSEC_FIFO
17153+ grsec_enable_fifo = 1;
17154+#endif
17155+#ifdef CONFIG_GRKERNSEC_EXECVE
17156+ grsec_enable_execve = 1;
17157+#endif
17158+#ifdef CONFIG_GRKERNSEC_EXECLOG
17159+ grsec_enable_execlog = 1;
17160+#endif
17161+#ifdef CONFIG_GRKERNSEC_SIGNAL
17162+ grsec_enable_signal = 1;
17163+#endif
17164+#ifdef CONFIG_GRKERNSEC_FORKFAIL
17165+ grsec_enable_forkfail = 1;
17166+#endif
17167+#ifdef CONFIG_GRKERNSEC_TIME
17168+ grsec_enable_time = 1;
17169+#endif
17170+#ifdef CONFIG_GRKERNSEC_RESLOG
17171+ grsec_resource_logging = 1;
17172+#endif
17173+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
17174+ grsec_enable_chroot_findtask = 1;
17175+#endif
17176+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
17177+ grsec_enable_chroot_unix = 1;
17178+#endif
17179+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
17180+ grsec_enable_chroot_mount = 1;
17181+#endif
17182+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
17183+ grsec_enable_chroot_fchdir = 1;
17184+#endif
17185+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
17186+ grsec_enable_chroot_shmat = 1;
17187+#endif
17188+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
17189+ grsec_enable_chroot_double = 1;
17190+#endif
17191+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
17192+ grsec_enable_chroot_pivot = 1;
17193+#endif
17194+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
17195+ grsec_enable_chroot_chdir = 1;
17196+#endif
17197+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
17198+ grsec_enable_chroot_chmod = 1;
17199+#endif
17200+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
17201+ grsec_enable_chroot_mknod = 1;
17202+#endif
17203+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
17204+ grsec_enable_chroot_nice = 1;
17205+#endif
17206+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
17207+ grsec_enable_chroot_execlog = 1;
17208+#endif
17209+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
17210+ grsec_enable_chroot_caps = 1;
17211+#endif
17212+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
17213+ grsec_enable_chroot_sysctl = 1;
17214+#endif
17215+#ifdef CONFIG_GRKERNSEC_TPE
17216+ grsec_enable_tpe = 1;
17217+ grsec_tpe_gid = CONFIG_GRKERNSEC_TPE_GID;
17218+#ifdef CONFIG_GRKERNSEC_TPE_ALL
17219+ grsec_enable_tpe_all = 1;
17220+#endif
17221+#endif
17222+#ifdef CONFIG_GRKERNSEC_RANDPID
17223+ grsec_enable_randpid = 1;
17224+#endif
17225+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
17226+ grsec_enable_socket_all = 1;
17227+ grsec_socket_all_gid = CONFIG_GRKERNSEC_SOCKET_ALL_GID;
17228+#endif
17229+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
17230+ grsec_enable_socket_client = 1;
17231+ grsec_socket_client_gid = CONFIG_GRKERNSEC_SOCKET_CLIENT_GID;
17232+#endif
17233+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
17234+ grsec_enable_socket_server = 1;
17235+ grsec_socket_server_gid = CONFIG_GRKERNSEC_SOCKET_SERVER_GID;
17236+#endif
17237+#endif
17238+
17239+ return;
17240+}
17241diff -urNp linux-2.6.17.7/grsecurity/grsec_ipc.c linux-2.6.17.7/grsecurity/grsec_ipc.c
17242--- linux-2.6.17.7/grsecurity/grsec_ipc.c 1969-12-31 19:00:00.000000000 -0500
17243+++ linux-2.6.17.7/grsecurity/grsec_ipc.c 2006-08-01 20:29:47.000000000 -0400
17244@@ -0,0 +1,81 @@
17245+#include <linux/kernel.h>
17246+#include <linux/sched.h>
17247+#include <linux/types.h>
17248+#include <linux/ipc.h>
17249+#include <linux/grsecurity.h>
17250+#include <linux/grinternal.h>
17251+
17252+void
17253+gr_log_msgget(const int ret, const int msgflg)
17254+{
17255+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
17256+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
17257+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
17258+ !grsec_enable_group)) && (ret >= 0)
17259+ && (msgflg & IPC_CREAT))
17260+ gr_log_noargs(GR_DO_AUDIT, GR_MSGQ_AUDIT_MSG);
17261+#endif
17262+ return;
17263+}
17264+
17265+void
17266+gr_log_msgrm(const uid_t uid, const uid_t cuid)
17267+{
17268+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
17269+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
17270+ grsec_enable_audit_ipc) ||
17271+ (grsec_enable_audit_ipc && !grsec_enable_group))
17272+ gr_log_int_int(GR_DO_AUDIT, GR_MSGQR_AUDIT_MSG, uid, cuid);
17273+#endif
17274+ return;
17275+}
17276+
17277+void
17278+gr_log_semget(const int err, const int semflg)
17279+{
17280+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
17281+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
17282+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
17283+ !grsec_enable_group)) && (err >= 0)
17284+ && (semflg & IPC_CREAT))
17285+ gr_log_noargs(GR_DO_AUDIT, GR_SEM_AUDIT_MSG);
17286+#endif
17287+ return;
17288+}
17289+
17290+void
17291+gr_log_semrm(const uid_t uid, const uid_t cuid)
17292+{
17293+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
17294+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
17295+ grsec_enable_audit_ipc) ||
17296+ (grsec_enable_audit_ipc && !grsec_enable_group))
17297+ gr_log_int_int(GR_DO_AUDIT, GR_SEMR_AUDIT_MSG, uid, cuid);
17298+#endif
17299+ return;
17300+}
17301+
17302+void
17303+gr_log_shmget(const int err, const int shmflg, const size_t size)
17304+{
17305+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
17306+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
17307+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
17308+ !grsec_enable_group)) && (err >= 0)
17309+ && (shmflg & IPC_CREAT))
17310+ gr_log_int(GR_DO_AUDIT, GR_SHM_AUDIT_MSG, size);
17311+#endif
17312+ return;
17313+}
17314+
17315+void
17316+gr_log_shmrm(const uid_t uid, const uid_t cuid)
17317+{
17318+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
17319+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
17320+ grsec_enable_audit_ipc) ||
17321+ (grsec_enable_audit_ipc && !grsec_enable_group))
17322+ gr_log_int_int(GR_DO_AUDIT, GR_SHMR_AUDIT_MSG, uid, cuid);
17323+#endif
17324+ return;
17325+}
17326diff -urNp linux-2.6.17.7/grsecurity/grsec_link.c linux-2.6.17.7/grsecurity/grsec_link.c
17327--- linux-2.6.17.7/grsecurity/grsec_link.c 1969-12-31 19:00:00.000000000 -0500
17328+++ linux-2.6.17.7/grsecurity/grsec_link.c 2006-08-01 20:29:47.000000000 -0400
17329@@ -0,0 +1,39 @@
17330+#include <linux/kernel.h>
17331+#include <linux/sched.h>
17332+#include <linux/fs.h>
17333+#include <linux/file.h>
17334+#include <linux/grinternal.h>
17335+
17336+int
17337+gr_handle_follow_link(const struct inode *parent,
17338+ const struct inode *inode,
17339+ const struct dentry *dentry, const struct vfsmount *mnt)
17340+{
17341+#ifdef CONFIG_GRKERNSEC_LINK
17342+ if (grsec_enable_link && S_ISLNK(inode->i_mode) &&
17343+ (parent->i_mode & S_ISVTX) && (parent->i_uid != inode->i_uid) &&
17344+ (parent->i_mode & S_IWOTH) && (current->fsuid != inode->i_uid)) {
17345+ gr_log_fs_int2(GR_DONT_AUDIT, GR_SYMLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid);
17346+ return -EACCES;
17347+ }
17348+#endif
17349+ return 0;
17350+}
17351+
17352+int
17353+gr_handle_hardlink(const struct dentry *dentry,
17354+ const struct vfsmount *mnt,
17355+ struct inode *inode, const int mode, const char *to)
17356+{
17357+#ifdef CONFIG_GRKERNSEC_LINK
17358+ if (grsec_enable_link && current->fsuid != inode->i_uid &&
17359+ (!S_ISREG(mode) || (mode & S_ISUID) ||
17360+ ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) ||
17361+ (generic_permission(inode, MAY_READ | MAY_WRITE, NULL))) &&
17362+ !capable(CAP_FOWNER) && current->uid) {
17363+ gr_log_fs_int2_str(GR_DONT_AUDIT, GR_HARDLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid, to);
17364+ return -EPERM;
17365+ }
17366+#endif
17367+ return 0;
17368+}
17369diff -urNp linux-2.6.17.7/grsecurity/grsec_log.c linux-2.6.17.7/grsecurity/grsec_log.c
17370--- linux-2.6.17.7/grsecurity/grsec_log.c 1969-12-31 19:00:00.000000000 -0500
17371+++ linux-2.6.17.7/grsecurity/grsec_log.c 2006-08-01 20:29:47.000000000 -0400
17372@@ -0,0 +1,265 @@
17373+#include <linux/kernel.h>
17374+#include <linux/sched.h>
17375+#include <linux/file.h>
17376+#include <linux/tty.h>
17377+#include <linux/fs.h>
17378+#include <linux/grinternal.h>
17379+
17380+#define BEGIN_LOCKS(x) \
17381+ read_lock(&tasklist_lock); \
17382+ read_lock(&grsec_exec_file_lock); \
17383+ if (x != GR_DO_AUDIT) \
17384+ spin_lock(&grsec_alert_lock); \
17385+ else \
17386+ spin_lock(&grsec_audit_lock)
17387+
17388+#define END_LOCKS(x) \
17389+ if (x != GR_DO_AUDIT) \
17390+ spin_unlock(&grsec_alert_lock); \
17391+ else \
17392+ spin_unlock(&grsec_audit_lock); \
17393+ read_unlock(&grsec_exec_file_lock); \
17394+ read_unlock(&tasklist_lock); \
17395+ if (x == GR_DONT_AUDIT) \
17396+ gr_handle_alertkill(current)
17397+
17398+enum {
17399+ FLOODING,
17400+ NO_FLOODING
17401+};
17402+
17403+extern char *gr_alert_log_fmt;
17404+extern char *gr_audit_log_fmt;
17405+extern char *gr_alert_log_buf;
17406+extern char *gr_audit_log_buf;
17407+
17408+static int gr_log_start(int audit)
17409+{
17410+ char *loglevel = (audit == GR_DO_AUDIT) ? KERN_INFO : KERN_ALERT;
17411+ char *fmt = (audit == GR_DO_AUDIT) ? gr_audit_log_fmt : gr_alert_log_fmt;
17412+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
17413+
17414+ if (audit == GR_DO_AUDIT)
17415+ goto set_fmt;
17416+
17417+ if (!grsec_alert_wtime || jiffies - grsec_alert_wtime > CONFIG_GRKERNSEC_FLOODTIME * HZ) {
17418+ grsec_alert_wtime = jiffies;
17419+ grsec_alert_fyet = 0;
17420+ } else if ((jiffies - grsec_alert_wtime < CONFIG_GRKERNSEC_FLOODTIME * HZ) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) {
17421+ grsec_alert_fyet++;
17422+ } else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) {
17423+ grsec_alert_wtime = jiffies;
17424+ grsec_alert_fyet++;
17425+ printk(KERN_ALERT "grsec: more alerts, logging disabled for %d seconds\n", CONFIG_GRKERNSEC_FLOODTIME);
17426+ return FLOODING;
17427+ } else return FLOODING;
17428+
17429+set_fmt:
17430+ memset(buf, 0, PAGE_SIZE);
17431+ if (current->signal->curr_ip && gr_acl_is_enabled()) {
17432+ sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: (%.64s:%c:%.950s) ");
17433+ snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip), current->role->rolename, gr_roletype_to_char(), current->acl->filename);
17434+ } else if (current->signal->curr_ip) {
17435+ sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: ");
17436+ snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip));
17437+ } else if (gr_acl_is_enabled()) {
17438+ sprintf(fmt, "%s%s", loglevel, "grsec: (%.64s:%c:%.950s) ");
17439+ snprintf(buf, PAGE_SIZE - 1, fmt, current->role->rolename, gr_roletype_to_char(), current->acl->filename);
17440+ } else {
17441+ sprintf(fmt, "%s%s", loglevel, "grsec: ");
17442+ strcpy(buf, fmt);
17443+ }
17444+
17445+ return NO_FLOODING;
17446+}
17447+
17448+static void gr_log_middle(int audit, const char *msg, va_list ap)
17449+{
17450+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
17451+ unsigned int len = strlen(buf);
17452+
17453+ vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap);
17454+
17455+ return;
17456+}
17457+
17458+static void gr_log_middle_varargs(int audit, const char *msg, ...)
17459+{
17460+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
17461+ unsigned int len = strlen(buf);
17462+ va_list ap;
17463+
17464+ va_start(ap, msg);
17465+ vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap);
17466+ va_end(ap);
17467+
17468+ return;
17469+}
17470+
17471+static void gr_log_end(int audit)
17472+{
17473+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
17474+ unsigned int len = strlen(buf);
17475+
17476+ snprintf(buf + len, PAGE_SIZE - len - 1, DEFAULTSECMSG, DEFAULTSECARGS(current));
17477+ printk("%s\n", buf);
17478+
17479+ return;
17480+}
17481+
17482+void gr_log_varargs(int audit, const char *msg, int argtypes, ...)
17483+{
17484+ int logtype;
17485+ char *result = (audit == GR_DO_AUDIT) ? "successful" : "denied";
17486+ char *str1, *str2, *str3;
17487+ int num1, num2;
17488+ unsigned long ulong1, ulong2;
17489+ struct dentry *dentry;
17490+ struct vfsmount *mnt;
17491+ struct file *file;
17492+ struct task_struct *task;
17493+ va_list ap;
17494+
17495+ BEGIN_LOCKS(audit);
17496+ logtype = gr_log_start(audit);
17497+ if (logtype == FLOODING) {
17498+ END_LOCKS(audit);
17499+ return;
17500+ }
17501+ va_start(ap, argtypes);
17502+ switch (argtypes) {
17503+ case GR_TTYSNIFF:
17504+ task = va_arg(ap, struct task_struct *);
17505+ 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);
17506+ break;
17507+ case GR_RBAC:
17508+ dentry = va_arg(ap, struct dentry *);
17509+ mnt = va_arg(ap, struct vfsmount *);
17510+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt));
17511+ break;
17512+ case GR_RBAC_STR:
17513+ dentry = va_arg(ap, struct dentry *);
17514+ mnt = va_arg(ap, struct vfsmount *);
17515+ str1 = va_arg(ap, char *);
17516+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1);
17517+ break;
17518+ case GR_STR_RBAC:
17519+ str1 = va_arg(ap, char *);
17520+ dentry = va_arg(ap, struct dentry *);
17521+ mnt = va_arg(ap, struct vfsmount *);
17522+ gr_log_middle_varargs(audit, msg, result, str1, gr_to_filename(dentry, mnt));
17523+ break;
17524+ case GR_RBAC_MODE2:
17525+ dentry = va_arg(ap, struct dentry *);
17526+ mnt = va_arg(ap, struct vfsmount *);
17527+ str1 = va_arg(ap, char *);
17528+ str2 = va_arg(ap, char *);
17529+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2);
17530+ break;
17531+ case GR_RBAC_MODE3:
17532+ dentry = va_arg(ap, struct dentry *);
17533+ mnt = va_arg(ap, struct vfsmount *);
17534+ str1 = va_arg(ap, char *);
17535+ str2 = va_arg(ap, char *);
17536+ str3 = va_arg(ap, char *);
17537+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2, str3);
17538+ break;
17539+ case GR_FILENAME:
17540+ dentry = va_arg(ap, struct dentry *);
17541+ mnt = va_arg(ap, struct vfsmount *);
17542+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt));
17543+ break;
17544+ case GR_STR_FILENAME:
17545+ str1 = va_arg(ap, char *);
17546+ dentry = va_arg(ap, struct dentry *);
17547+ mnt = va_arg(ap, struct vfsmount *);
17548+ gr_log_middle_varargs(audit, msg, str1, gr_to_filename(dentry, mnt));
17549+ break;
17550+ case GR_FILENAME_STR:
17551+ dentry = va_arg(ap, struct dentry *);
17552+ mnt = va_arg(ap, struct vfsmount *);
17553+ str1 = va_arg(ap, char *);
17554+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), str1);
17555+ break;
17556+ case GR_FILENAME_TWO_INT:
17557+ dentry = va_arg(ap, struct dentry *);
17558+ mnt = va_arg(ap, struct vfsmount *);
17559+ num1 = va_arg(ap, int);
17560+ num2 = va_arg(ap, int);
17561+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2);
17562+ break;
17563+ case GR_FILENAME_TWO_INT_STR:
17564+ dentry = va_arg(ap, struct dentry *);
17565+ mnt = va_arg(ap, struct vfsmount *);
17566+ num1 = va_arg(ap, int);
17567+ num2 = va_arg(ap, int);
17568+ str1 = va_arg(ap, char *);
17569+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2, str1);
17570+ break;
17571+ case GR_TEXTREL:
17572+ file = va_arg(ap, struct file *);
17573+ ulong1 = va_arg(ap, unsigned long);
17574+ ulong2 = va_arg(ap, unsigned long);
17575+ gr_log_middle_varargs(audit, msg, file ? gr_to_filename(file->f_dentry, file->f_vfsmnt) : "<anonymous mapping>", ulong1, ulong2);
17576+ break;
17577+ case GR_PTRACE:
17578+ task = va_arg(ap, struct task_struct *);
17579+ 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);
17580+ break;
17581+ case GR_RESOURCE:
17582+ task = va_arg(ap, struct task_struct *);
17583+ ulong1 = va_arg(ap, unsigned long);
17584+ str1 = va_arg(ap, char *);
17585+ ulong2 = va_arg(ap, unsigned long);
17586+ 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);
17587+ break;
17588+ case GR_CAP:
17589+ task = va_arg(ap, struct task_struct *);
17590+ str1 = va_arg(ap, char *);
17591+ 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);
17592+ break;
17593+ case GR_SIG:
17594+ task = va_arg(ap, struct task_struct *);
17595+ num1 = va_arg(ap, int);
17596+ 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);
17597+ break;
17598+ case GR_CRASH1:
17599+ task = va_arg(ap, struct task_struct *);
17600+ ulong1 = va_arg(ap, unsigned long);
17601+ 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);
17602+ break;
17603+ case GR_CRASH2:
17604+ task = va_arg(ap, struct task_struct *);
17605+ ulong1 = va_arg(ap, unsigned long);
17606+ 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);
17607+ break;
17608+ case GR_PSACCT:
17609+ {
17610+ unsigned int wday, cday;
17611+ __u8 whr, chr;
17612+ __u8 wmin, cmin;
17613+ __u8 wsec, csec;
17614+ char cur_tty[64] = { 0 };
17615+ char parent_tty[64] = { 0 };
17616+
17617+ task = va_arg(ap, struct task_struct *);
17618+ wday = va_arg(ap, unsigned int);
17619+ cday = va_arg(ap, unsigned int);
17620+ whr = va_arg(ap, int);
17621+ chr = va_arg(ap, int);
17622+ wmin = va_arg(ap, int);
17623+ cmin = va_arg(ap, int);
17624+ wsec = va_arg(ap, int);
17625+ csec = va_arg(ap, int);
17626+ ulong1 = va_arg(ap, unsigned long);
17627+
17628+ 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);
17629+ }
17630+ break;
17631+ default:
17632+ gr_log_middle(audit, msg, ap);
17633+ }
17634+ va_end(ap);
17635+ gr_log_end(audit);
17636+ END_LOCKS(audit);
17637+}
17638diff -urNp linux-2.6.17.7/grsecurity/grsec_mem.c linux-2.6.17.7/grsecurity/grsec_mem.c
17639--- linux-2.6.17.7/grsecurity/grsec_mem.c 1969-12-31 19:00:00.000000000 -0500
17640+++ linux-2.6.17.7/grsecurity/grsec_mem.c 2006-08-01 20:29:47.000000000 -0400
17641@@ -0,0 +1,71 @@
17642+#include <linux/kernel.h>
17643+#include <linux/sched.h>
17644+#include <linux/mm.h>
17645+#include <linux/mman.h>
17646+#include <linux/grinternal.h>
17647+
17648+void
17649+gr_handle_ioperm(void)
17650+{
17651+ gr_log_noargs(GR_DONT_AUDIT, GR_IOPERM_MSG);
17652+ return;
17653+}
17654+
17655+void
17656+gr_handle_iopl(void)
17657+{
17658+ gr_log_noargs(GR_DONT_AUDIT, GR_IOPL_MSG);
17659+ return;
17660+}
17661+
17662+void
17663+gr_handle_mem_write(void)
17664+{
17665+ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_WRITE_MSG);
17666+ return;
17667+}
17668+
17669+void
17670+gr_handle_kmem_write(void)
17671+{
17672+ gr_log_noargs(GR_DONT_AUDIT, GR_KMEM_MSG);
17673+ return;
17674+}
17675+
17676+void
17677+gr_handle_open_port(void)
17678+{
17679+ gr_log_noargs(GR_DONT_AUDIT, GR_PORT_OPEN_MSG);
17680+ return;
17681+}
17682+
17683+int
17684+gr_handle_mem_mmap(const unsigned long offset, struct vm_area_struct *vma)
17685+{
17686+ unsigned long start, end;
17687+
17688+ start = offset;
17689+ end = start + vma->vm_end - vma->vm_start;
17690+
17691+ if (start > end) {
17692+ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_MMAP_MSG);
17693+ return -EPERM;
17694+ }
17695+
17696+ /* allowed ranges : ISA I/O BIOS */
17697+ if ((start >= __pa(high_memory))
17698+#ifdef CONFIG_X86
17699+ || (start >= 0x000a0000 && end <= 0x00100000)
17700+ || (start >= 0x00000000 && end <= 0x00001000)
17701+#endif
17702+ )
17703+ return 0;
17704+
17705+ if (vma->vm_flags & VM_WRITE) {
17706+ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_MMAP_MSG);
17707+ return -EPERM;
17708+ } else
17709+ vma->vm_flags &= ~VM_MAYWRITE;
17710+
17711+ return 0;
17712+}
17713diff -urNp linux-2.6.17.7/grsecurity/grsec_mount.c linux-2.6.17.7/grsecurity/grsec_mount.c
17714--- linux-2.6.17.7/grsecurity/grsec_mount.c 1969-12-31 19:00:00.000000000 -0500
17715+++ linux-2.6.17.7/grsecurity/grsec_mount.c 2006-08-01 20:29:47.000000000 -0400
17716@@ -0,0 +1,34 @@
17717+#include <linux/kernel.h>
17718+#include <linux/sched.h>
17719+#include <linux/grsecurity.h>
17720+#include <linux/grinternal.h>
17721+
17722+void
17723+gr_log_remount(const char *devname, const int retval)
17724+{
17725+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
17726+ if (grsec_enable_mount && (retval >= 0))
17727+ gr_log_str(GR_DO_AUDIT, GR_REMOUNT_AUDIT_MSG, devname ? devname : "none");
17728+#endif
17729+ return;
17730+}
17731+
17732+void
17733+gr_log_unmount(const char *devname, const int retval)
17734+{
17735+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
17736+ if (grsec_enable_mount && (retval >= 0))
17737+ gr_log_str(GR_DO_AUDIT, GR_UNMOUNT_AUDIT_MSG, devname ? devname : "none");
17738+#endif
17739+ return;
17740+}
17741+
17742+void
17743+gr_log_mount(const char *from, const char *to, const int retval)
17744+{
17745+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
17746+ if (grsec_enable_mount && (retval >= 0))
17747+ gr_log_str_str(GR_DO_AUDIT, GR_MOUNT_AUDIT_MSG, from, to);
17748+#endif
17749+ return;
17750+}
17751diff -urNp linux-2.6.17.7/grsecurity/grsec_rand.c linux-2.6.17.7/grsecurity/grsec_rand.c
17752--- linux-2.6.17.7/grsecurity/grsec_rand.c 1969-12-31 19:00:00.000000000 -0500
17753+++ linux-2.6.17.7/grsecurity/grsec_rand.c 2006-08-01 20:29:47.000000000 -0400
17754@@ -0,0 +1,26 @@
17755+#include <linux/kernel.h>
17756+#include <linux/sched.h>
17757+#include <linux/smp_lock.h>
17758+#include <linux/grsecurity.h>
17759+#include <linux/grinternal.h>
17760+
17761+extern int pid_max;
17762+
17763+int
17764+gr_random_pid(void)
17765+{
17766+#ifdef CONFIG_GRKERNSEC_RANDPID
17767+ int pid;
17768+
17769+ if (grsec_enable_randpid && current->fs->root) {
17770+ /* return a pid in the range 1 ... pid_max - 1
17771+ optimize this so we don't have to do a real division
17772+ */
17773+ pid = 1 + (get_random_long() % pid_max);
17774+ if (pid == pid_max)
17775+ pid = pid_max - 1;
17776+ return pid;
17777+ }
17778+#endif
17779+ return 0;
17780+}
17781diff -urNp linux-2.6.17.7/grsecurity/grsec_sig.c linux-2.6.17.7/grsecurity/grsec_sig.c
17782--- linux-2.6.17.7/grsecurity/grsec_sig.c 1969-12-31 19:00:00.000000000 -0500
17783+++ linux-2.6.17.7/grsecurity/grsec_sig.c 2006-08-01 20:29:47.000000000 -0400
17784@@ -0,0 +1,59 @@
17785+#include <linux/kernel.h>
17786+#include <linux/sched.h>
17787+#include <linux/grsecurity.h>
17788+#include <linux/grinternal.h>
17789+
17790+void
17791+gr_log_signal(const int sig, const struct task_struct *t)
17792+{
17793+#ifdef CONFIG_GRKERNSEC_SIGNAL
17794+ if (grsec_enable_signal && ((sig == SIGSEGV) || (sig == SIGILL) ||
17795+ (sig == SIGABRT) || (sig == SIGBUS))) {
17796+ if (t->pid == current->pid) {
17797+ gr_log_int(GR_DONT_AUDIT_GOOD, GR_UNISIGLOG_MSG, sig);
17798+ } else {
17799+ gr_log_sig(GR_DONT_AUDIT_GOOD, GR_DUALSIGLOG_MSG, t, sig);
17800+ }
17801+ }
17802+#endif
17803+ return;
17804+}
17805+
17806+int
17807+gr_handle_signal(const struct task_struct *p, const int sig)
17808+{
17809+#ifdef CONFIG_GRKERNSEC
17810+ if (current->pid > 1 && gr_check_protected_task(p)) {
17811+ gr_log_sig(GR_DONT_AUDIT, GR_SIG_ACL_MSG, p, sig);
17812+ return -EPERM;
17813+ } else if (gr_pid_is_chrooted((struct task_struct *)p)) {
17814+ return -EPERM;
17815+ }
17816+#endif
17817+ return 0;
17818+}
17819+
17820+void gr_handle_brute_attach(struct task_struct *p)
17821+{
17822+#ifdef CONFIG_GRKERNSEC_BRUTE
17823+ read_lock(&tasklist_lock);
17824+ read_lock(&grsec_exec_file_lock);
17825+ if (p->parent && p->parent->exec_file == p->exec_file)
17826+ p->parent->brute = 1;
17827+ read_unlock(&grsec_exec_file_lock);
17828+ read_unlock(&tasklist_lock);
17829+#endif
17830+ return;
17831+}
17832+
17833+void gr_handle_brute_check(void)
17834+{
17835+#ifdef CONFIG_GRKERNSEC_BRUTE
17836+ if (current->brute) {
17837+ set_current_state(TASK_UNINTERRUPTIBLE);
17838+ schedule_timeout(30 * HZ);
17839+ }
17840+#endif
17841+ return;
17842+}
17843+
17844diff -urNp linux-2.6.17.7/grsecurity/grsec_sock.c linux-2.6.17.7/grsecurity/grsec_sock.c
17845--- linux-2.6.17.7/grsecurity/grsec_sock.c 1969-12-31 19:00:00.000000000 -0500
17846+++ linux-2.6.17.7/grsecurity/grsec_sock.c 2006-08-01 20:29:47.000000000 -0400
17847@@ -0,0 +1,263 @@
17848+#include <linux/kernel.h>
17849+#include <linux/module.h>
17850+#include <linux/sched.h>
17851+#include <linux/file.h>
17852+#include <linux/net.h>
17853+#include <linux/in.h>
17854+#include <linux/ip.h>
17855+#include <net/sock.h>
17856+#include <net/inet_sock.h>
17857+#include <linux/grsecurity.h>
17858+#include <linux/grinternal.h>
17859+#include <linux/gracl.h>
17860+
17861+#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE)
17862+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
17863+EXPORT_SYMBOL(udp_v4_lookup);
17864+#endif
17865+
17866+EXPORT_SYMBOL(gr_cap_rtnetlink);
17867+
17868+extern int gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb);
17869+extern int gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr);
17870+
17871+EXPORT_SYMBOL(gr_search_udp_recvmsg);
17872+EXPORT_SYMBOL(gr_search_udp_sendmsg);
17873+
17874+#ifdef CONFIG_UNIX_MODULE
17875+EXPORT_SYMBOL(gr_acl_handle_unix);
17876+EXPORT_SYMBOL(gr_acl_handle_mknod);
17877+EXPORT_SYMBOL(gr_handle_chroot_unix);
17878+EXPORT_SYMBOL(gr_handle_create);
17879+#endif
17880+
17881+#ifdef CONFIG_GRKERNSEC
17882+#define gr_conn_table_size 32749
17883+struct conn_table_entry {
17884+ struct conn_table_entry *next;
17885+ struct signal_struct *sig;
17886+};
17887+
17888+struct conn_table_entry *gr_conn_table[gr_conn_table_size];
17889+spinlock_t gr_conn_table_lock = SPIN_LOCK_UNLOCKED;
17890+
17891+extern const char * gr_socktype_to_name(unsigned char type);
17892+extern const char * gr_proto_to_name(unsigned char proto);
17893+
17894+static __inline__ int
17895+conn_hash(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, unsigned int size)
17896+{
17897+ return ((daddr + saddr + (sport << 8) + (dport << 16)) % size);
17898+}
17899+
17900+static __inline__ int
17901+conn_match(const struct signal_struct *sig, __u32 saddr, __u32 daddr,
17902+ __u16 sport, __u16 dport)
17903+{
17904+ if (unlikely(sig->gr_saddr == saddr && sig->gr_daddr == daddr &&
17905+ sig->gr_sport == sport && sig->gr_dport == dport))
17906+ return 1;
17907+ else
17908+ return 0;
17909+}
17910+
17911+static void gr_add_to_task_ip_table_nolock(struct signal_struct *sig, struct conn_table_entry *newent)
17912+{
17913+ struct conn_table_entry **match;
17914+ unsigned int index;
17915+
17916+ index = conn_hash(sig->gr_saddr, sig->gr_daddr,
17917+ sig->gr_sport, sig->gr_dport,
17918+ gr_conn_table_size);
17919+
17920+ newent->sig = sig;
17921+
17922+ match = &gr_conn_table[index];
17923+ newent->next = *match;
17924+ *match = newent;
17925+
17926+ return;
17927+}
17928+
17929+static void gr_del_task_from_ip_table_nolock(struct signal_struct *sig)
17930+{
17931+ struct conn_table_entry *match, *last = NULL;
17932+ unsigned int index;
17933+
17934+ index = conn_hash(sig->gr_saddr, sig->gr_daddr,
17935+ sig->gr_sport, sig->gr_dport,
17936+ gr_conn_table_size);
17937+
17938+ match = gr_conn_table[index];
17939+ while (match && !conn_match(match->sig,
17940+ sig->gr_saddr, sig->gr_daddr, sig->gr_sport,
17941+ sig->gr_dport)) {
17942+ last = match;
17943+ match = match->next;
17944+ }
17945+
17946+ if (match) {
17947+ if (last)
17948+ last->next = match->next;
17949+ else
17950+ gr_conn_table[index] = NULL;
17951+ kfree(match);
17952+ }
17953+
17954+ return;
17955+}
17956+
17957+static struct signal_struct * gr_lookup_task_ip_table(__u32 saddr, __u32 daddr,
17958+ __u16 sport, __u16 dport)
17959+{
17960+ struct conn_table_entry *match;
17961+ unsigned int index;
17962+
17963+ index = conn_hash(saddr, daddr, sport, dport, gr_conn_table_size);
17964+
17965+ match = gr_conn_table[index];
17966+ while (match && !conn_match(match->sig, saddr, daddr, sport, dport))
17967+ match = match->next;
17968+
17969+ if (match)
17970+ return match->sig;
17971+ else
17972+ return NULL;
17973+}
17974+
17975+#endif
17976+
17977+void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet)
17978+{
17979+#ifdef CONFIG_GRKERNSEC
17980+ struct signal_struct *sig = task->signal;
17981+ struct conn_table_entry *newent;
17982+
17983+ newent = kmalloc(sizeof(struct conn_table_entry), GFP_ATOMIC);
17984+ if (newent == NULL)
17985+ return;
17986+ /* no bh lock needed since we are called with bh disabled */
17987+ spin_lock(&gr_conn_table_lock);
17988+ gr_del_task_from_ip_table_nolock(sig);
17989+ sig->gr_saddr = inet->rcv_saddr;
17990+ sig->gr_daddr = inet->daddr;
17991+ sig->gr_sport = inet->sport;
17992+ sig->gr_dport = inet->dport;
17993+ gr_add_to_task_ip_table_nolock(sig, newent);
17994+ spin_unlock(&gr_conn_table_lock);
17995+#endif
17996+ return;
17997+}
17998+
17999+void gr_del_task_from_ip_table(struct task_struct *task)
18000+{
18001+#ifdef CONFIG_GRKERNSEC
18002+ spin_lock(&gr_conn_table_lock);
18003+ gr_del_task_from_ip_table_nolock(task->signal);
18004+ spin_unlock(&gr_conn_table_lock);
18005+#endif
18006+ return;
18007+}
18008+
18009+void
18010+gr_attach_curr_ip(const struct sock *sk)
18011+{
18012+#ifdef CONFIG_GRKERNSEC
18013+ struct signal_struct *p, *set;
18014+ const struct inet_sock *inet = inet_sk(sk);
18015+
18016+ if (unlikely(sk->sk_protocol != IPPROTO_TCP))
18017+ return;
18018+
18019+ set = current->signal;
18020+
18021+ spin_lock_bh(&gr_conn_table_lock);
18022+ p = gr_lookup_task_ip_table(inet->daddr, inet->rcv_saddr,
18023+ inet->dport, inet->sport);
18024+ if (unlikely(p != NULL)) {
18025+ set->curr_ip = p->curr_ip;
18026+ set->used_accept = 1;
18027+ gr_del_task_from_ip_table_nolock(p);
18028+ spin_unlock_bh(&gr_conn_table_lock);
18029+ return;
18030+ }
18031+ spin_unlock_bh(&gr_conn_table_lock);
18032+
18033+ set->curr_ip = inet->daddr;
18034+ set->used_accept = 1;
18035+#endif
18036+ return;
18037+}
18038+
18039+int
18040+gr_handle_sock_all(const int family, const int type, const int protocol)
18041+{
18042+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
18043+ if (grsec_enable_socket_all && in_group_p(grsec_socket_all_gid) &&
18044+ (family != AF_UNIX) && (family != AF_LOCAL)) {
18045+ gr_log_int_str2(GR_DONT_AUDIT, GR_SOCK2_MSG, family, gr_socktype_to_name(type), gr_proto_to_name(protocol));
18046+ return -EACCES;
18047+ }
18048+#endif
18049+ return 0;
18050+}
18051+
18052+int
18053+gr_handle_sock_server(const struct sockaddr *sck)
18054+{
18055+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
18056+ if (grsec_enable_socket_server &&
18057+ in_group_p(grsec_socket_server_gid) &&
18058+ sck && (sck->sa_family != AF_UNIX) &&
18059+ (sck->sa_family != AF_LOCAL)) {
18060+ gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
18061+ return -EACCES;
18062+ }
18063+#endif
18064+ return 0;
18065+}
18066+
18067+int
18068+gr_handle_sock_server_other(const struct sock *sck)
18069+{
18070+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
18071+ if (grsec_enable_socket_server &&
18072+ in_group_p(grsec_socket_server_gid) &&
18073+ sck && (sck->sk_family != AF_UNIX) &&
18074+ (sck->sk_family != AF_LOCAL)) {
18075+ gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
18076+ return -EACCES;
18077+ }
18078+#endif
18079+ return 0;
18080+}
18081+
18082+int
18083+gr_handle_sock_client(const struct sockaddr *sck)
18084+{
18085+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
18086+ if (grsec_enable_socket_client && in_group_p(grsec_socket_client_gid) &&
18087+ sck && (sck->sa_family != AF_UNIX) &&
18088+ (sck->sa_family != AF_LOCAL)) {
18089+ gr_log_noargs(GR_DONT_AUDIT, GR_CONNECT_MSG);
18090+ return -EACCES;
18091+ }
18092+#endif
18093+ return 0;
18094+}
18095+
18096+__u32
18097+gr_cap_rtnetlink(void)
18098+{
18099+#ifdef CONFIG_GRKERNSEC
18100+ if (!gr_acl_is_enabled())
18101+ return current->cap_effective;
18102+ else if (cap_raised(current->cap_effective, CAP_NET_ADMIN) &&
18103+ gr_task_is_capable(current, CAP_NET_ADMIN))
18104+ return current->cap_effective;
18105+ else
18106+ return 0;
18107+#else
18108+ return current->cap_effective;
18109+#endif
18110+}
18111diff -urNp linux-2.6.17.7/grsecurity/grsec_sysctl.c linux-2.6.17.7/grsecurity/grsec_sysctl.c
18112--- linux-2.6.17.7/grsecurity/grsec_sysctl.c 1969-12-31 19:00:00.000000000 -0500
18113+++ linux-2.6.17.7/grsecurity/grsec_sysctl.c 2006-08-01 20:29:47.000000000 -0400
18114@@ -0,0 +1,466 @@
18115+#include <linux/kernel.h>
18116+#include <linux/sched.h>
18117+#include <linux/sysctl.h>
18118+#include <linux/grsecurity.h>
18119+#include <linux/grinternal.h>
18120+
18121+#ifdef CONFIG_GRKERNSEC_MODSTOP
18122+int grsec_modstop;
18123+#endif
18124+
18125+int
18126+gr_handle_sysctl_mod(const char *dirname, const char *name, const int op)
18127+{
18128+#ifdef CONFIG_GRKERNSEC_SYSCTL
18129+ if (!strcmp(dirname, "grsecurity") && grsec_lock && (op & 002)) {
18130+ gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name);
18131+ return -EACCES;
18132+ }
18133+#endif
18134+#ifdef CONFIG_GRKERNSEC_MODSTOP
18135+ if (!strcmp(dirname, "grsecurity") && !strcmp(name, "disable_modules") &&
18136+ grsec_modstop && (op & 002)) {
18137+ gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name);
18138+ return -EACCES;
18139+ }
18140+#endif
18141+ return 0;
18142+}
18143+
18144+#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP)
18145+enum {GS_LINK=1, GS_FIFO, GS_EXECVE, GS_EXECLOG, GS_SIGNAL,
18146+GS_FORKFAIL, GS_TIME, GS_CHROOT_SHMAT, GS_CHROOT_UNIX, GS_CHROOT_MNT,
18147+GS_CHROOT_FCHDIR, GS_CHROOT_DBL, GS_CHROOT_PVT, GS_CHROOT_CD, GS_CHROOT_CM,
18148+GS_CHROOT_MK, GS_CHROOT_NI, GS_CHROOT_EXECLOG, GS_CHROOT_CAPS,
18149+GS_CHROOT_SYSCTL, GS_TPE, GS_TPE_GID, GS_TPE_ALL, GS_SIDCAPS,
18150+GS_RANDPID, GS_SOCKET_ALL, GS_SOCKET_ALL_GID, GS_SOCKET_CLIENT,
18151+GS_SOCKET_CLIENT_GID, GS_SOCKET_SERVER, GS_SOCKET_SERVER_GID,
18152+GS_GROUP, GS_GID, GS_ACHDIR, GS_AMOUNT, GS_AIPC, GS_DMSG,
18153+GS_TEXTREL, GS_FINDTASK, GS_SHM, GS_LOCK, GS_MODSTOP, GS_RESLOG};
18154+
18155+
18156+ctl_table grsecurity_table[] = {
18157+#ifdef CONFIG_GRKERNSEC_SYSCTL
18158+#ifdef CONFIG_GRKERNSEC_LINK
18159+ {
18160+ .ctl_name = GS_LINK,
18161+ .procname = "linking_restrictions",
18162+ .data = &grsec_enable_link,
18163+ .maxlen = sizeof(int),
18164+ .mode = 0600,
18165+ .proc_handler = &proc_dointvec,
18166+ },
18167+#endif
18168+#ifdef CONFIG_GRKERNSEC_FIFO
18169+ {
18170+ .ctl_name = GS_FIFO,
18171+ .procname = "fifo_restrictions",
18172+ .data = &grsec_enable_fifo,
18173+ .maxlen = sizeof(int),
18174+ .mode = 0600,
18175+ .proc_handler = &proc_dointvec,
18176+ },
18177+#endif
18178+#ifdef CONFIG_GRKERNSEC_EXECVE
18179+ {
18180+ .ctl_name = GS_EXECVE,
18181+ .procname = "execve_limiting",
18182+ .data = &grsec_enable_execve,
18183+ .maxlen = sizeof(int),
18184+ .mode = 0600,
18185+ .proc_handler = &proc_dointvec,
18186+ },
18187+#endif
18188+#ifdef CONFIG_GRKERNSEC_EXECLOG
18189+ {
18190+ .ctl_name = GS_EXECLOG,
18191+ .procname = "exec_logging",
18192+ .data = &grsec_enable_execlog,
18193+ .maxlen = sizeof(int),
18194+ .mode = 0600,
18195+ .proc_handler = &proc_dointvec,
18196+ },
18197+#endif
18198+#ifdef CONFIG_GRKERNSEC_SIGNAL
18199+ {
18200+ .ctl_name = GS_SIGNAL,
18201+ .procname = "signal_logging",
18202+ .data = &grsec_enable_signal,
18203+ .maxlen = sizeof(int),
18204+ .mode = 0600,
18205+ .proc_handler = &proc_dointvec,
18206+ },
18207+#endif
18208+#ifdef CONFIG_GRKERNSEC_FORKFAIL
18209+ {
18210+ .ctl_name = GS_FORKFAIL,
18211+ .procname = "forkfail_logging",
18212+ .data = &grsec_enable_forkfail,
18213+ .maxlen = sizeof(int),
18214+ .mode = 0600,
18215+ .proc_handler = &proc_dointvec,
18216+ },
18217+#endif
18218+#ifdef CONFIG_GRKERNSEC_TIME
18219+ {
18220+ .ctl_name = GS_TIME,
18221+ .procname = "timechange_logging",
18222+ .data = &grsec_enable_time,
18223+ .maxlen = sizeof(int),
18224+ .mode = 0600,
18225+ .proc_handler = &proc_dointvec,
18226+ },
18227+#endif
18228+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
18229+ {
18230+ .ctl_name = GS_CHROOT_SHMAT,
18231+ .procname = "chroot_deny_shmat",
18232+ .data = &grsec_enable_chroot_shmat,
18233+ .maxlen = sizeof(int),
18234+ .mode = 0600,
18235+ .proc_handler = &proc_dointvec,
18236+ },
18237+#endif
18238+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
18239+ {
18240+ .ctl_name = GS_CHROOT_UNIX,
18241+ .procname = "chroot_deny_unix",
18242+ .data = &grsec_enable_chroot_unix,
18243+ .maxlen = sizeof(int),
18244+ .mode = 0600,
18245+ .proc_handler = &proc_dointvec,
18246+ },
18247+#endif
18248+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
18249+ {
18250+ .ctl_name = GS_CHROOT_MNT,
18251+ .procname = "chroot_deny_mount",
18252+ .data = &grsec_enable_chroot_mount,
18253+ .maxlen = sizeof(int),
18254+ .mode = 0600,
18255+ .proc_handler = &proc_dointvec,
18256+ },
18257+#endif
18258+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
18259+ {
18260+ .ctl_name = GS_CHROOT_FCHDIR,
18261+ .procname = "chroot_deny_fchdir",
18262+ .data = &grsec_enable_chroot_fchdir,
18263+ .maxlen = sizeof(int),
18264+ .mode = 0600,
18265+ .proc_handler = &proc_dointvec,
18266+ },
18267+#endif
18268+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
18269+ {
18270+ .ctl_name = GS_CHROOT_DBL,
18271+ .procname = "chroot_deny_chroot",
18272+ .data = &grsec_enable_chroot_double,
18273+ .maxlen = sizeof(int),
18274+ .mode = 0600,
18275+ .proc_handler = &proc_dointvec,
18276+ },
18277+#endif
18278+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
18279+ {
18280+ .ctl_name = GS_CHROOT_PVT,
18281+ .procname = "chroot_deny_pivot",
18282+ .data = &grsec_enable_chroot_pivot,
18283+ .maxlen = sizeof(int),
18284+ .mode = 0600,
18285+ .proc_handler = &proc_dointvec,
18286+ },
18287+#endif
18288+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
18289+ {
18290+ .ctl_name = GS_CHROOT_CD,
18291+ .procname = "chroot_enforce_chdir",
18292+ .data = &grsec_enable_chroot_chdir,
18293+ .maxlen = sizeof(int),
18294+ .mode = 0600,
18295+ .proc_handler = &proc_dointvec,
18296+ },
18297+#endif
18298+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
18299+ {
18300+ .ctl_name = GS_CHROOT_CM,
18301+ .procname = "chroot_deny_chmod",
18302+ .data = &grsec_enable_chroot_chmod,
18303+ .maxlen = sizeof(int),
18304+ .mode = 0600,
18305+ .proc_handler = &proc_dointvec,
18306+ },
18307+#endif
18308+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
18309+ {
18310+ .ctl_name = GS_CHROOT_MK,
18311+ .procname = "chroot_deny_mknod",
18312+ .data = &grsec_enable_chroot_mknod,
18313+ .maxlen = sizeof(int),
18314+ .mode = 0600,
18315+ .proc_handler = &proc_dointvec,
18316+ },
18317+#endif
18318+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
18319+ {
18320+ .ctl_name = GS_CHROOT_NI,
18321+ .procname = "chroot_restrict_nice",
18322+ .data = &grsec_enable_chroot_nice,
18323+ .maxlen = sizeof(int),
18324+ .mode = 0600,
18325+ .proc_handler = &proc_dointvec,
18326+ },
18327+#endif
18328+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
18329+ {
18330+ .ctl_name = GS_CHROOT_EXECLOG,
18331+ .procname = "chroot_execlog",
18332+ .data = &grsec_enable_chroot_execlog,
18333+ .maxlen = sizeof(int),
18334+ .mode = 0600,
18335+ .proc_handler = &proc_dointvec,
18336+ },
18337+#endif
18338+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
18339+ {
18340+ .ctl_name = GS_CHROOT_CAPS,
18341+ .procname = "chroot_caps",
18342+ .data = &grsec_enable_chroot_caps,
18343+ .maxlen = sizeof(int),
18344+ .mode = 0600,
18345+ .proc_handler = &proc_dointvec,
18346+ },
18347+#endif
18348+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
18349+ {
18350+ .ctl_name = GS_CHROOT_SYSCTL,
18351+ .procname = "chroot_deny_sysctl",
18352+ .data = &grsec_enable_chroot_sysctl,
18353+ .maxlen = sizeof(int),
18354+ .mode = 0600,
18355+ .proc_handler = &proc_dointvec,
18356+ },
18357+#endif
18358+#ifdef CONFIG_GRKERNSEC_TPE
18359+ {
18360+ .ctl_name = GS_TPE,
18361+ .procname = "tpe",
18362+ .data = &grsec_enable_tpe,
18363+ .maxlen = sizeof(int),
18364+ .mode = 0600,
18365+ .proc_handler = &proc_dointvec,
18366+ },
18367+ {
18368+ .ctl_name = GS_TPE_GID,
18369+ .procname = "tpe_gid",
18370+ .data = &grsec_tpe_gid,
18371+ .maxlen = sizeof(int),
18372+ .mode = 0600,
18373+ .proc_handler = &proc_dointvec,
18374+ },
18375+#endif
18376+#ifdef CONFIG_GRKERNSEC_TPE_ALL
18377+ {
18378+ .ctl_name = GS_TPE_ALL,
18379+ .procname = "tpe_restrict_all",
18380+ .data = &grsec_enable_tpe_all,
18381+ .maxlen = sizeof(int),
18382+ .mode = 0600,
18383+ .proc_handler = &proc_dointvec,
18384+ },
18385+#endif
18386+#ifdef CONFIG_GRKERNSEC_RANDPID
18387+ {
18388+ .ctl_name = GS_RANDPID,
18389+ .procname = "rand_pids",
18390+ .data = &grsec_enable_randpid,
18391+ .maxlen = sizeof(int),
18392+ .mode = 0600,
18393+ .proc_handler = &proc_dointvec,
18394+ },
18395+#endif
18396+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
18397+ {
18398+ .ctl_name = GS_SOCKET_ALL,
18399+ .procname = "socket_all",
18400+ .data = &grsec_enable_socket_all,
18401+ .maxlen = sizeof(int),
18402+ .mode = 0600,
18403+ .proc_handler = &proc_dointvec,
18404+ },
18405+ {
18406+ .ctl_name = GS_SOCKET_ALL_GID,
18407+ .procname = "socket_all_gid",
18408+ .data = &grsec_socket_all_gid,
18409+ .maxlen = sizeof(int),
18410+ .mode = 0600,
18411+ .proc_handler = &proc_dointvec,
18412+ },
18413+#endif
18414+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
18415+ {
18416+ .ctl_name = GS_SOCKET_CLIENT,
18417+ .procname = "socket_client",
18418+ .data = &grsec_enable_socket_client,
18419+ .maxlen = sizeof(int),
18420+ .mode = 0600,
18421+ .proc_handler = &proc_dointvec,
18422+ },
18423+ {
18424+ .ctl_name = GS_SOCKET_CLIENT_GID,
18425+ .procname = "socket_client_gid",
18426+ .data = &grsec_socket_client_gid,
18427+ .maxlen = sizeof(int),
18428+ .mode = 0600,
18429+ .proc_handler = &proc_dointvec,
18430+ },
18431+#endif
18432+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
18433+ {
18434+ .ctl_name = GS_SOCKET_SERVER,
18435+ .procname = "socket_server",
18436+ .data = &grsec_enable_socket_server,
18437+ .maxlen = sizeof(int),
18438+ .mode = 0600,
18439+ .proc_handler = &proc_dointvec,
18440+ },
18441+ {
18442+ .ctl_name = GS_SOCKET_SERVER_GID,
18443+ .procname = "socket_server_gid",
18444+ .data = &grsec_socket_server_gid,
18445+ .maxlen = sizeof(int),
18446+ .mode = 0600,
18447+ .proc_handler = &proc_dointvec,
18448+ },
18449+#endif
18450+#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
18451+ {
18452+ .ctl_name = GS_GROUP,
18453+ .procname = "audit_group",
18454+ .data = &grsec_enable_group,
18455+ .maxlen = sizeof(int),
18456+ .mode = 0600,
18457+ .proc_handler = &proc_dointvec,
18458+ },
18459+ {
18460+ .ctl_name = GS_GID,
18461+ .procname = "audit_gid",
18462+ .data = &grsec_audit_gid,
18463+ .maxlen = sizeof(int),
18464+ .mode = 0600,
18465+ .proc_handler = &proc_dointvec,
18466+ },
18467+#endif
18468+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
18469+ {
18470+ .ctl_name = GS_ACHDIR,
18471+ .procname = "audit_chdir",
18472+ .data = &grsec_enable_chdir,
18473+ .maxlen = sizeof(int),
18474+ .mode = 0600,
18475+ .proc_handler = &proc_dointvec,
18476+ },
18477+#endif
18478+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
18479+ {
18480+ .ctl_name = GS_AMOUNT,
18481+ .procname = "audit_mount",
18482+ .data = &grsec_enable_mount,
18483+ .maxlen = sizeof(int),
18484+ .mode = 0600,
18485+ .proc_handler = &proc_dointvec,
18486+ },
18487+#endif
18488+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
18489+ {
18490+ .ctl_name = GS_AIPC,
18491+ .procname = "audit_ipc",
18492+ .data = &grsec_enable_audit_ipc,
18493+ .maxlen = sizeof(int),
18494+ .mode = 0600,
18495+ .proc_handler = &proc_dointvec,
18496+ },
18497+#endif
18498+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
18499+ {
18500+ .ctl_name = GS_TEXTREL,
18501+ .procname = "audit_textrel",
18502+ .data = &grsec_enable_audit_textrel,
18503+ .maxlen = sizeof(int),
18504+ .mode = 0600,
18505+ .proc_handler = &proc_dointvec,
18506+ },
18507+#endif
18508+#ifdef CONFIG_GRKERNSEC_DMESG
18509+ {
18510+ .ctl_name = GS_DMSG,
18511+ .procname = "dmesg",
18512+ .data = &grsec_enable_dmesg,
18513+ .maxlen = sizeof(int),
18514+ .mode = 0600,
18515+ .proc_handler = &proc_dointvec,
18516+ },
18517+#endif
18518+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
18519+ {
18520+ .ctl_name = GS_FINDTASK,
18521+ .procname = "chroot_findtask",
18522+ .data = &grsec_enable_chroot_findtask,
18523+ .maxlen = sizeof(int),
18524+ .mode = 0600,
18525+ .proc_handler = &proc_dointvec,
18526+ },
18527+#endif
18528+#ifdef CONFIG_GRKERNSEC_SHM
18529+ {
18530+ .ctl_name = GS_SHM,
18531+ .procname = "destroy_unused_shm",
18532+ .data = &grsec_enable_shm,
18533+ .maxlen = sizeof(int),
18534+ .mode = 0600,
18535+ .proc_handler = &proc_dointvec,
18536+ },
18537+#endif
18538+#ifdef CONFIG_GRKERNSEC_RESLOG
18539+ {
18540+ .ctl_name = GS_RESLOG,
18541+ .procname = "resource_logging",
18542+ .data = &grsec_resource_logging,
18543+ .maxlen = sizeof(int),
18544+ .mode = 0600,
18545+ .proc_handler = &proc_dointvec,
18546+ },
18547+#endif
18548+ {
18549+ .ctl_name = GS_LOCK,
18550+ .procname = "grsec_lock",
18551+ .data = &grsec_lock,
18552+ .maxlen = sizeof(int),
18553+ .mode = 0600,
18554+ .proc_handler = &proc_dointvec,
18555+ },
18556+#endif
18557+#ifdef CONFIG_GRKERNSEC_MODSTOP
18558+ {
18559+ .ctl_name = GS_MODSTOP,
18560+ .procname = "disable_modules",
18561+ .data = &grsec_modstop,
18562+ .maxlen = sizeof(int),
18563+ .mode = 0600,
18564+ .proc_handler = &proc_dointvec,
18565+ },
18566+#endif
18567+ { .ctl_name = 0 }
18568+};
18569+#endif
18570+
18571+int gr_check_modstop(void)
18572+{
18573+#ifdef CONFIG_GRKERNSEC_MODSTOP
18574+ if (grsec_modstop == 1) {
18575+ gr_log_noargs(GR_DONT_AUDIT, GR_STOPMOD_MSG);
18576+ return 1;
18577+ }
18578+#endif
18579+ return 0;
18580+}
18581diff -urNp linux-2.6.17.7/grsecurity/grsec_textrel.c linux-2.6.17.7/grsecurity/grsec_textrel.c
18582--- linux-2.6.17.7/grsecurity/grsec_textrel.c 1969-12-31 19:00:00.000000000 -0500
18583+++ linux-2.6.17.7/grsecurity/grsec_textrel.c 2006-08-01 20:29:47.000000000 -0400
18584@@ -0,0 +1,16 @@
18585+#include <linux/kernel.h>
18586+#include <linux/sched.h>
18587+#include <linux/mm.h>
18588+#include <linux/file.h>
18589+#include <linux/grinternal.h>
18590+#include <linux/grsecurity.h>
18591+
18592+void
18593+gr_log_textrel(struct vm_area_struct * vma)
18594+{
18595+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
18596+ if (grsec_enable_audit_textrel)
18597+ gr_log_textrel_ulong_ulong(GR_DO_AUDIT, GR_TEXTREL_AUDIT_MSG, vma->vm_file, vma->vm_start, vma->vm_pgoff);
18598+#endif
18599+ return;
18600+}
18601diff -urNp linux-2.6.17.7/grsecurity/grsec_time.c linux-2.6.17.7/grsecurity/grsec_time.c
18602--- linux-2.6.17.7/grsecurity/grsec_time.c 1969-12-31 19:00:00.000000000 -0500
18603+++ linux-2.6.17.7/grsecurity/grsec_time.c 2006-08-01 20:29:47.000000000 -0400
18604@@ -0,0 +1,13 @@
18605+#include <linux/kernel.h>
18606+#include <linux/sched.h>
18607+#include <linux/grinternal.h>
18608+
18609+void
18610+gr_log_timechange(void)
18611+{
18612+#ifdef CONFIG_GRKERNSEC_TIME
18613+ if (grsec_enable_time)
18614+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_TIME_MSG);
18615+#endif
18616+ return;
18617+}
18618diff -urNp linux-2.6.17.7/grsecurity/grsec_tpe.c linux-2.6.17.7/grsecurity/grsec_tpe.c
18619--- linux-2.6.17.7/grsecurity/grsec_tpe.c 1969-12-31 19:00:00.000000000 -0500
18620+++ linux-2.6.17.7/grsecurity/grsec_tpe.c 2006-08-01 20:29:47.000000000 -0400
18621@@ -0,0 +1,37 @@
18622+#include <linux/kernel.h>
18623+#include <linux/sched.h>
18624+#include <linux/file.h>
18625+#include <linux/fs.h>
18626+#include <linux/grinternal.h>
18627+
18628+extern int gr_acl_tpe_check(void);
18629+
18630+int
18631+gr_tpe_allow(const struct file *file)
18632+{
18633+#ifdef CONFIG_GRKERNSEC
18634+ struct inode *inode = file->f_dentry->d_parent->d_inode;
18635+
18636+ if (current->uid && ((grsec_enable_tpe &&
18637+#ifdef CONFIG_GRKERNSEC_TPE_INVERT
18638+ !in_group_p(grsec_tpe_gid)
18639+#else
18640+ in_group_p(grsec_tpe_gid)
18641+#endif
18642+ ) || gr_acl_tpe_check()) &&
18643+ (inode->i_uid || (!inode->i_uid && ((inode->i_mode & S_IWGRP) ||
18644+ (inode->i_mode & S_IWOTH))))) {
18645+ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_dentry, file->f_vfsmnt);
18646+ return 0;
18647+ }
18648+#ifdef CONFIG_GRKERNSEC_TPE_ALL
18649+ if (current->uid && grsec_enable_tpe && grsec_enable_tpe_all &&
18650+ ((inode->i_uid && (inode->i_uid != current->uid)) ||
18651+ (inode->i_mode & S_IWGRP) || (inode->i_mode & S_IWOTH))) {
18652+ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_dentry, file->f_vfsmnt);
18653+ return 0;
18654+ }
18655+#endif
18656+#endif
18657+ return 1;
18658+}
18659diff -urNp linux-2.6.17.7/grsecurity/grsum.c linux-2.6.17.7/grsecurity/grsum.c
18660--- linux-2.6.17.7/grsecurity/grsum.c 1969-12-31 19:00:00.000000000 -0500
18661+++ linux-2.6.17.7/grsecurity/grsum.c 2006-08-01 20:29:47.000000000 -0400
18662@@ -0,0 +1,59 @@
18663+#include <linux/kernel.h>
18664+#include <linux/sched.h>
18665+#include <linux/mm.h>
18666+#include <asm/scatterlist.h>
18667+#include <linux/crypto.h>
18668+#include <linux/gracl.h>
18669+
18670+
18671+#if !defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE) || !defined(CONFIG_CRYPTO_SHA256) || defined(CONFIG_CRYPTO_SHA256_MODULE)
18672+#error "crypto and sha256 must be built into the kernel"
18673+#endif
18674+
18675+int
18676+chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum)
18677+{
18678+ char *p;
18679+ struct crypto_tfm *tfm;
18680+ unsigned char temp_sum[GR_SHA_LEN];
18681+ struct scatterlist sg[2];
18682+ volatile int retval = 0;
18683+ volatile int dummy = 0;
18684+ unsigned int i;
18685+
18686+ tfm = crypto_alloc_tfm("sha256", 0);
18687+ if (tfm == NULL) {
18688+ /* should never happen, since sha256 should be built in */
18689+ return 1;
18690+ }
18691+
18692+ crypto_digest_init(tfm);
18693+
18694+ p = salt;
18695+ sg[0].page = virt_to_page(p);
18696+ sg[0].offset = ((long) p & ~PAGE_MASK);
18697+ sg[0].length = GR_SALT_LEN;
18698+
18699+ crypto_digest_update(tfm, sg, 1);
18700+
18701+ p = entry->pw;
18702+ sg[0].page = virt_to_page(p);
18703+ sg[0].offset = ((long) p & ~PAGE_MASK);
18704+ sg[0].length = strlen(entry->pw);
18705+
18706+ crypto_digest_update(tfm, sg, 1);
18707+
18708+ crypto_digest_final(tfm, temp_sum);
18709+
18710+ memset(entry->pw, 0, GR_PW_LEN);
18711+
18712+ for (i = 0; i < GR_SHA_LEN; i++)
18713+ if (sum[i] != temp_sum[i])
18714+ retval = 1;
18715+ else
18716+ dummy = 1; // waste a cycle
18717+
18718+ crypto_free_tfm(tfm);
18719+
18720+ return retval;
18721+}
18722diff -urNp linux-2.6.17.7/include/asm-alpha/a.out.h linux-2.6.17.7/include/asm-alpha/a.out.h
18723--- linux-2.6.17.7/include/asm-alpha/a.out.h 2006-07-24 23:36:01.000000000 -0400
18724+++ linux-2.6.17.7/include/asm-alpha/a.out.h 2006-08-01 20:29:47.000000000 -0400
18725@@ -98,7 +98,7 @@ struct exec
18726 set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000L \
18727 ? ADDR_LIMIT_32BIT : 0) | PER_OSF4))
18728
18729-#define STACK_TOP \
18730+#define __STACK_TOP \
18731 (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL)
18732
18733 #endif
18734diff -urNp linux-2.6.17.7/include/asm-alpha/elf.h linux-2.6.17.7/include/asm-alpha/elf.h
18735--- linux-2.6.17.7/include/asm-alpha/elf.h 2006-07-24 23:36:01.000000000 -0400
18736+++ linux-2.6.17.7/include/asm-alpha/elf.h 2006-08-01 20:29:47.000000000 -0400
18737@@ -91,6 +91,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
18738
18739 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
18740
18741+#ifdef CONFIG_PAX_ASLR
18742+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 0x10000 : 0x120000000UL)
18743+
18744+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18745+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28)
18746+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18747+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28)
18748+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18749+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 19)
18750+#endif
18751+
18752 /* $0 is set by ld.so to a pointer to a function which might be
18753 registered using atexit. This provides a mean for the dynamic
18754 linker to call DT_FINI functions for shared libraries that have
18755diff -urNp linux-2.6.17.7/include/asm-alpha/kmap_types.h linux-2.6.17.7/include/asm-alpha/kmap_types.h
18756--- linux-2.6.17.7/include/asm-alpha/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
18757+++ linux-2.6.17.7/include/asm-alpha/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
18758@@ -25,7 +25,8 @@ D(9) KM_IRQ0,
18759 D(10) KM_IRQ1,
18760 D(11) KM_SOFTIRQ0,
18761 D(12) KM_SOFTIRQ1,
18762-D(13) KM_TYPE_NR
18763+D(13) KM_CLEARPAGE,
18764+D(14) KM_TYPE_NR
18765 };
18766
18767 #undef D
18768diff -urNp linux-2.6.17.7/include/asm-alpha/page.h linux-2.6.17.7/include/asm-alpha/page.h
18769--- linux-2.6.17.7/include/asm-alpha/page.h 2006-07-24 23:36:01.000000000 -0400
18770+++ linux-2.6.17.7/include/asm-alpha/page.h 2006-08-01 20:29:47.000000000 -0400
18771@@ -93,6 +93,16 @@ typedef unsigned long pgprot_t;
18772
18773 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
18774 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18775+
18776+#ifdef CONFIG_PAX_PAGEEXEC
18777+#ifdef CONFIG_PAX_MPROTECT
18778+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18779+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18780+#else
18781+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18782+#endif
18783+#endif
18784+
18785 #endif /* __KERNEL__ */
18786
18787 #include <asm-generic/memory_model.h>
18788diff -urNp linux-2.6.17.7/include/asm-alpha/pgtable.h linux-2.6.17.7/include/asm-alpha/pgtable.h
18789--- linux-2.6.17.7/include/asm-alpha/pgtable.h 2006-07-24 23:36:01.000000000 -0400
18790+++ linux-2.6.17.7/include/asm-alpha/pgtable.h 2006-08-01 20:29:47.000000000 -0400
18791@@ -102,6 +102,17 @@ struct vm_area_struct;
18792 #define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS)
18793 #define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
18794 #define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
18795+
18796+#ifdef CONFIG_PAX_PAGEEXEC
18797+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOE)
18798+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE)
18799+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE)
18800+#else
18801+# define PAGE_SHARED_NOEXEC PAGE_SHARED
18802+# define PAGE_COPY_NOEXEC PAGE_COPY
18803+# define PAGE_READONLY_NOEXEC PAGE_READONLY
18804+#endif
18805+
18806 #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
18807
18808 #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
18809diff -urNp linux-2.6.17.7/include/asm-arm/a.out.h linux-2.6.17.7/include/asm-arm/a.out.h
18810--- linux-2.6.17.7/include/asm-arm/a.out.h 2006-07-24 23:36:01.000000000 -0400
18811+++ linux-2.6.17.7/include/asm-arm/a.out.h 2006-08-01 20:29:47.000000000 -0400
18812@@ -28,7 +28,7 @@ struct exec
18813 #define M_ARM 103
18814
18815 #ifdef __KERNEL__
18816-#define STACK_TOP ((current->personality == PER_LINUX_32BIT) ? \
18817+#define __STACK_TOP ((current->personality == PER_LINUX_32BIT) ? \
18818 TASK_SIZE : TASK_SIZE_26)
18819 #endif
18820
18821diff -urNp linux-2.6.17.7/include/asm-arm/elf.h linux-2.6.17.7/include/asm-arm/elf.h
18822--- linux-2.6.17.7/include/asm-arm/elf.h 2006-07-24 23:36:01.000000000 -0400
18823+++ linux-2.6.17.7/include/asm-arm/elf.h 2006-08-01 20:29:47.000000000 -0400
18824@@ -56,6 +56,17 @@ typedef struct user_fp elf_fpregset_t;
18825
18826 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
18827
18828+#ifdef CONFIG_PAX_ASLR
18829+#define PAX_ELF_ET_DYN_BASE(tsk) 0x00008000UL
18830+
18831+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18832+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
18833+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18834+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
18835+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18836+#define PAX_DELTA_STACK_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
18837+#endif
18838+
18839 /* When the program starts, a1 contains a pointer to a function to be
18840 registered with atexit, as per the SVR4 ABI. A value of 0 means we
18841 have no such handler. */
18842diff -urNp linux-2.6.17.7/include/asm-arm/kmap_types.h linux-2.6.17.7/include/asm-arm/kmap_types.h
18843--- linux-2.6.17.7/include/asm-arm/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
18844+++ linux-2.6.17.7/include/asm-arm/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
18845@@ -18,6 +18,7 @@ enum km_type {
18846 KM_IRQ1,
18847 KM_SOFTIRQ0,
18848 KM_SOFTIRQ1,
18849+ KM_CLEARPAGE,
18850 KM_TYPE_NR
18851 };
18852
18853diff -urNp linux-2.6.17.7/include/asm-arm26/kmap_types.h linux-2.6.17.7/include/asm-arm26/kmap_types.h
18854--- linux-2.6.17.7/include/asm-arm26/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
18855+++ linux-2.6.17.7/include/asm-arm26/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
18856@@ -6,7 +6,8 @@
18857 */
18858 enum km_type {
18859 KM_IRQ0,
18860- KM_USER1
18861+ KM_USER1,
18862+ KM_CLEARPAGE
18863 };
18864
18865 #endif
18866diff -urNp linux-2.6.17.7/include/asm-cris/kmap_types.h linux-2.6.17.7/include/asm-cris/kmap_types.h
18867--- linux-2.6.17.7/include/asm-cris/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
18868+++ linux-2.6.17.7/include/asm-cris/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
18869@@ -19,6 +19,7 @@ enum km_type {
18870 KM_IRQ1,
18871 KM_SOFTIRQ0,
18872 KM_SOFTIRQ1,
18873+ KM_CLEARPAGE,
18874 KM_TYPE_NR
18875 };
18876
18877diff -urNp linux-2.6.17.7/include/asm-frv/kmap_types.h linux-2.6.17.7/include/asm-frv/kmap_types.h
18878--- linux-2.6.17.7/include/asm-frv/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
18879+++ linux-2.6.17.7/include/asm-frv/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
18880@@ -23,6 +23,7 @@ enum km_type {
18881 KM_IRQ1,
18882 KM_SOFTIRQ0,
18883 KM_SOFTIRQ1,
18884+ KM_CLEARPAGE,
18885 KM_TYPE_NR
18886 };
18887
18888diff -urNp linux-2.6.17.7/include/asm-h8300/kmap_types.h linux-2.6.17.7/include/asm-h8300/kmap_types.h
18889--- linux-2.6.17.7/include/asm-h8300/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
18890+++ linux-2.6.17.7/include/asm-h8300/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
18891@@ -15,6 +15,7 @@ enum km_type {
18892 KM_IRQ1,
18893 KM_SOFTIRQ0,
18894 KM_SOFTIRQ1,
18895+ KM_CLEARPAGE,
18896 KM_TYPE_NR
18897 };
18898
18899diff -urNp linux-2.6.17.7/include/asm-i386/a.out.h linux-2.6.17.7/include/asm-i386/a.out.h
18900--- linux-2.6.17.7/include/asm-i386/a.out.h 2006-07-24 23:36:01.000000000 -0400
18901+++ linux-2.6.17.7/include/asm-i386/a.out.h 2006-08-01 20:29:47.000000000 -0400
18902@@ -19,7 +19,11 @@ struct exec
18903
18904 #ifdef __KERNEL__
18905
18906-#define STACK_TOP TASK_SIZE
18907+#ifdef CONFIG_PAX_SEGMEXEC
18908+#define __STACK_TOP ((current->mm->pax_flags & MF_PAX_SEGMEXEC)?TASK_SIZE/2:TASK_SIZE)
18909+#else
18910+#define __STACK_TOP TASK_SIZE
18911+#endif
18912
18913 #endif
18914
18915diff -urNp linux-2.6.17.7/include/asm-i386/alternative.h linux-2.6.17.7/include/asm-i386/alternative.h
18916--- linux-2.6.17.7/include/asm-i386/alternative.h 2006-07-24 23:36:01.000000000 -0400
18917+++ linux-2.6.17.7/include/asm-i386/alternative.h 2006-08-01 20:29:47.000000000 -0400
18918@@ -47,7 +47,7 @@ extern void alternatives_smp_switch(int
18919 " .byte 662b-661b\n" /* sourcelen */ \
18920 " .byte 664f-663f\n" /* replacementlen */ \
18921 ".previous\n" \
18922- ".section .altinstr_replacement,\"ax\"\n" \
18923+ ".section .altinstr_replacement,\"a\"\n" \
18924 "663:\n\t" newinstr "\n664:\n" /* replacement */\
18925 ".previous" :: "i" (feature) : "memory")
18926
18927@@ -71,7 +71,7 @@ extern void alternatives_smp_switch(int
18928 " .byte 662b-661b\n" /* sourcelen */ \
18929 " .byte 664f-663f\n" /* replacementlen */ \
18930 ".previous\n" \
18931- ".section .altinstr_replacement,\"ax\"\n" \
18932+ ".section .altinstr_replacement,\"a\"\n" \
18933 "663:\n\t" newinstr "\n664:\n" /* replacement */\
18934 ".previous" :: "i" (feature), ##input)
18935
18936@@ -110,7 +110,7 @@ extern void alternatives_smp_switch(int
18937 " .byte 662b-661b\n" /* sourcelen */ \
18938 " .byte 664f-663f\n" /* replacementlen */ \
18939 ".previous\n" \
18940- ".section .smp_altinstr_replacement,\"awx\"\n" \
18941+ ".section .smp_altinstr_replacement,\"aw\"\n" \
18942 "663:\n\t" upinstr "\n" /* replacement */ \
18943 "664:\n\t.fill 662b-661b,1,0x42\n" /* space for original */ \
18944 ".previous" : args)
18945diff -urNp linux-2.6.17.7/include/asm-i386/auxvec.h linux-2.6.17.7/include/asm-i386/auxvec.h
18946--- linux-2.6.17.7/include/asm-i386/auxvec.h 2006-07-24 23:36:01.000000000 -0400
18947+++ linux-2.6.17.7/include/asm-i386/auxvec.h 2006-08-01 20:29:47.000000000 -0400
18948@@ -5,7 +5,9 @@
18949 * Architecture-neutral AT_ values in 0-17, leave some room
18950 * for more of them, start the x86-specific ones at 32.
18951 */
18952+#ifndef CONFIG_PAX_NOVSYSCALL
18953 #define AT_SYSINFO 32
18954 #define AT_SYSINFO_EHDR 33
18955+#endif
18956
18957 #endif
18958diff -urNp linux-2.6.17.7/include/asm-i386/checksum.h linux-2.6.17.7/include/asm-i386/checksum.h
18959--- linux-2.6.17.7/include/asm-i386/checksum.h 2006-07-24 23:36:01.000000000 -0400
18960+++ linux-2.6.17.7/include/asm-i386/checksum.h 2006-08-01 20:29:47.000000000 -0400
18961@@ -30,6 +30,12 @@ asmlinkage unsigned int csum_partial(con
18962 asmlinkage unsigned int csum_partial_copy_generic(const unsigned char *src, unsigned char *dst,
18963 int len, int sum, int *src_err_ptr, int *dst_err_ptr);
18964
18965+asmlinkage unsigned int csum_partial_copy_generic_to_user(const unsigned char *src, unsigned char *dst,
18966+ int len, int sum, int *src_err_ptr, int *dst_err_ptr);
18967+
18968+asmlinkage unsigned int csum_partial_copy_generic_from_user(const unsigned char *src, unsigned char *dst,
18969+ int len, int sum, int *src_err_ptr, int *dst_err_ptr);
18970+
18971 /*
18972 * Note: when you get a NULL pointer exception here this means someone
18973 * passed in an incorrect kernel address to one of these functions.
18974@@ -49,7 +55,7 @@ unsigned int csum_partial_copy_from_user
18975 int len, int sum, int *err_ptr)
18976 {
18977 might_sleep();
18978- return csum_partial_copy_generic((__force unsigned char *)src, dst,
18979+ return csum_partial_copy_generic_from_user((__force unsigned char *)src, dst,
18980 len, sum, err_ptr, NULL);
18981 }
18982
18983@@ -183,7 +189,7 @@ static __inline__ unsigned int csum_and_
18984 {
18985 might_sleep();
18986 if (access_ok(VERIFY_WRITE, dst, len))
18987- return csum_partial_copy_generic(src, (__force unsigned char *)dst, len, sum, NULL, err_ptr);
18988+ return csum_partial_copy_generic_to_user(src, (__force unsigned char *)dst, len, sum, NULL, err_ptr);
18989
18990 if (len)
18991 *err_ptr = -EFAULT;
18992diff -urNp linux-2.6.17.7/include/asm-i386/desc.h linux-2.6.17.7/include/asm-i386/desc.h
18993--- linux-2.6.17.7/include/asm-i386/desc.h 2006-07-24 23:36:01.000000000 -0400
18994+++ linux-2.6.17.7/include/asm-i386/desc.h 2006-08-01 20:29:47.000000000 -0400
18995@@ -10,11 +10,13 @@
18996
18997 #include <linux/preempt.h>
18998 #include <linux/smp.h>
18999-#include <linux/percpu.h>
19000+#include <linux/sched.h>
19001
19002 #include <asm/mmu.h>
19003+#include <asm/pgtable.h>
19004+#include <asm/tlbflush.h>
19005
19006-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
19007+extern struct desc_struct cpu_gdt_table[NR_CPUS][PAGE_SIZE / sizeof(struct desc_struct)];
19008
19009 DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
19010
19011@@ -24,13 +26,53 @@ struct Xgt_desc_struct {
19012 unsigned short pad;
19013 } __attribute__ ((packed));
19014
19015-extern struct Xgt_desc_struct idt_descr;
19016-DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
19017-
19018+extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
19019
19020 static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
19021 {
19022- return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
19023+ return cpu_gdt_table[cpu];
19024+}
19025+
19026+#define pax_open_kernel(cr0) \
19027+do { \
19028+ typecheck(unsigned long,cr0); \
19029+ preempt_disable(); \
19030+ cr0 = read_cr0(); \
19031+ write_cr0(cr0 & ~0x10000UL); \
19032+} while(0)
19033+
19034+#define pax_close_kernel(cr0) \
19035+do { \
19036+ typecheck(unsigned long,cr0); \
19037+ write_cr0(cr0); \
19038+ preempt_enable_no_resched(); \
19039+} while(0)
19040+
19041+static inline void set_user_cs(struct mm_struct *mm, int cpu)
19042+{
19043+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
19044+ unsigned long base = mm->context.user_cs_base;
19045+ unsigned long limit = mm->context.user_cs_limit;
19046+
19047+#ifdef CONFIG_PAX_KERNEXEC
19048+ unsigned long cr0;
19049+
19050+ pax_open_kernel(cr0);
19051+#endif
19052+
19053+ if (likely(limit)) {
19054+ limit -= 1UL;
19055+ limit >>= 12;
19056+ }
19057+
19058+ get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS].a = (limit & 0xFFFFUL) | (base << 16);
19059+ get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS].b = (limit & 0xF0000UL) | 0xC0FB00UL | (base & 0xFF000000UL) | ((base >> 16) & 0xFFUL);
19060+
19061+#ifdef CONFIG_PAX_KERNEXEC
19062+ pax_close_kernel(cr0);
19063+#endif
19064+
19065+#endif
19066 }
19067
19068 #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
19069@@ -50,7 +92,7 @@ static inline struct desc_struct *get_cp
19070 * This is the ldt that every process will get unless we need
19071 * something other than this.
19072 */
19073-extern struct desc_struct default_ldt[];
19074+extern const struct desc_struct default_ldt[];
19075 extern void set_intr_gate(unsigned int irq, void * addr);
19076
19077 #define _set_tssldt_desc(n,addr,limit,type) \
19078@@ -64,7 +106,7 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\
19079 "rorl $16,%1" \
19080 : "=m"(*(n)) : "q" (addr), "r"(n), "ir"(limit), "i"(type))
19081
19082-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
19083+static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
19084 {
19085 _set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr,
19086 offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
19087@@ -72,11 +114,28 @@ static inline void __set_tss_desc(unsign
19088
19089 #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
19090
19091-static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
19092+static inline void __set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size)
19093 {
19094 _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
19095 }
19096
19097+static inline void set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size)
19098+{
19099+
19100+#ifdef CONFIG_PAX_KERNEXEC
19101+ unsigned long cr0;
19102+
19103+ pax_open_kernel(cr0);
19104+#endif
19105+
19106+ _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
19107+
19108+#ifdef CONFIG_PAX_KERNEXEC
19109+ pax_close_kernel(cr0);
19110+#endif
19111+
19112+}
19113+
19114 #define LDT_entry_a(info) \
19115 ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
19116
19117@@ -90,7 +149,7 @@ static inline void set_ldt_desc(unsigned
19118 ((info)->seg_32bit << 22) | \
19119 ((info)->limit_in_pages << 23) | \
19120 ((info)->useable << 20) | \
19121- 0x7000)
19122+ 0x7100)
19123
19124 #define LDT_empty(info) (\
19125 (info)->base_addr == 0 && \
19126@@ -134,7 +193,7 @@ static inline void clear_LDT(void)
19127 */
19128 static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
19129 {
19130- void *segments = pc->ldt;
19131+ const void *segments = pc->ldt;
19132 int count = pc->size;
19133
19134 if (likely(!count)) {
19135@@ -162,6 +221,22 @@ static inline unsigned long get_desc_bas
19136 return base;
19137 }
19138
19139+static inline void _load_LDT(mm_context_t *pc)
19140+{
19141+ int cpu = get_cpu();
19142+ const void *segments = pc->ldt;
19143+ int count = pc->size;
19144+
19145+ if (likely(!count)) {
19146+ segments = &default_ldt[0];
19147+ count = 5;
19148+ }
19149+
19150+ __set_ldt_desc(cpu, segments, count);
19151+ load_LDT_desc();
19152+ put_cpu();
19153+}
19154+
19155 #endif /* !__ASSEMBLY__ */
19156
19157 #endif
19158diff -urNp linux-2.6.17.7/include/asm-i386/elf.h linux-2.6.17.7/include/asm-i386/elf.h
19159--- linux-2.6.17.7/include/asm-i386/elf.h 2006-07-24 23:36:01.000000000 -0400
19160+++ linux-2.6.17.7/include/asm-i386/elf.h 2006-08-01 20:29:47.000000000 -0400
77fa6d7d 19161@@ -71,6 +71,17 @@ typedef struct user_fxsr_struct elf_fpxr
f1a4f855 19162
77fa6d7d 19163 #define ELF_ET_DYN_BASE ((TASK_UNMAPPED_BASE) * 2)
68731fcf 19164
f1a4f855 19165+#ifdef CONFIG_PAX_ASLR
19166+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000000UL
19167+
19168+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
19169+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
19170+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
19171+#define PAX_DELTA_EXEC_LEN(tsk) 15
19172+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
19173+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
19174+#endif
68731fcf 19175+
f1a4f855 19176 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
19177 now struct_user_regs, they are different) */
68731fcf 19178
f1a4f855 19179@@ -131,7 +146,14 @@ extern int dump_task_extended_fpu (struc
19180
19181 #define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
19182 #define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
19183+
19184+#ifndef CONFIG_PAX_NOVSYSCALL
19185+#ifdef CONFIG_PAX_SEGMEXEC
19186+#define VSYSCALL_ENTRY ((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? (unsigned long) &__kernel_vsyscall - SEGMEXEC_TASK_SIZE : (unsigned long) &__kernel_vsyscall)
19187+#else
19188 #define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall)
19189+#endif
19190+
19191 extern void __kernel_vsyscall;
19192
19193 #define ARCH_DLINFO \
19194@@ -187,3 +209,5 @@ do { \
19195 #endif
19196
19197 #endif
19198+
19199+#endif
19200diff -urNp linux-2.6.17.7/include/asm-i386/kmap_types.h linux-2.6.17.7/include/asm-i386/kmap_types.h
19201--- linux-2.6.17.7/include/asm-i386/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
19202+++ linux-2.6.17.7/include/asm-i386/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
19203@@ -23,7 +23,8 @@ D(9) KM_IRQ0,
19204 D(10) KM_IRQ1,
19205 D(11) KM_SOFTIRQ0,
19206 D(12) KM_SOFTIRQ1,
19207-D(13) KM_TYPE_NR
19208+D(13) KM_CLEARPAGE,
19209+D(14) KM_TYPE_NR
19210 };
19211
19212 #undef D
19213diff -urNp linux-2.6.17.7/include/asm-i386/mach-default/apm.h linux-2.6.17.7/include/asm-i386/mach-default/apm.h
19214--- linux-2.6.17.7/include/asm-i386/mach-default/apm.h 2006-07-24 23:36:01.000000000 -0400
19215+++ linux-2.6.17.7/include/asm-i386/mach-default/apm.h 2006-08-01 20:29:47.000000000 -0400
19216@@ -36,7 +36,7 @@ static inline void apm_bios_call_asm(u32
19217 __asm__ __volatile__(APM_DO_ZERO_SEGS
19218 "pushl %%edi\n\t"
19219 "pushl %%ebp\n\t"
19220- "lcall *%%cs:apm_bios_entry\n\t"
19221+ "lcall *%%ss:apm_bios_entry\n\t"
19222 "setc %%al\n\t"
19223 "popl %%ebp\n\t"
19224 "popl %%edi\n\t"
19225@@ -60,7 +60,7 @@ static inline u8 apm_bios_call_simple_as
19226 __asm__ __volatile__(APM_DO_ZERO_SEGS
19227 "pushl %%edi\n\t"
19228 "pushl %%ebp\n\t"
19229- "lcall *%%cs:apm_bios_entry\n\t"
19230+ "lcall *%%ss:apm_bios_entry\n\t"
19231 "setc %%bl\n\t"
19232 "popl %%ebp\n\t"
19233 "popl %%edi\n\t"
19234diff -urNp linux-2.6.17.7/include/asm-i386/mach-default/do_timer.h linux-2.6.17.7/include/asm-i386/mach-default/do_timer.h
19235--- linux-2.6.17.7/include/asm-i386/mach-default/do_timer.h 2006-07-24 23:36:01.000000000 -0400
19236+++ linux-2.6.17.7/include/asm-i386/mach-default/do_timer.h 2006-08-01 20:29:47.000000000 -0400
19237@@ -18,7 +18,7 @@ static inline void do_timer_interrupt_ho
19238 {
19239 do_timer(regs);
19240 #ifndef CONFIG_SMP
19241- update_process_times(user_mode_vm(regs));
19242+ update_process_times(user_mode(regs));
19243 #endif
19244 /*
19245 * In the SMP case we use the local APIC timer interrupt to do the
19246diff -urNp linux-2.6.17.7/include/asm-i386/mach-visws/do_timer.h linux-2.6.17.7/include/asm-i386/mach-visws/do_timer.h
19247--- linux-2.6.17.7/include/asm-i386/mach-visws/do_timer.h 2006-07-24 23:36:01.000000000 -0400
19248+++ linux-2.6.17.7/include/asm-i386/mach-visws/do_timer.h 2006-08-01 20:29:47.000000000 -0400
19249@@ -11,7 +11,7 @@ static inline void do_timer_interrupt_ho
19250
19251 do_timer(regs);
19252 #ifndef CONFIG_SMP
19253- update_process_times(user_mode_vm(regs));
19254+ update_process_times(user_mode(regs));
19255 #endif
19256 /*
19257 * In the SMP case we use the local APIC timer interrupt to do the
19258diff -urNp linux-2.6.17.7/include/asm-i386/mach-voyager/do_timer.h linux-2.6.17.7/include/asm-i386/mach-voyager/do_timer.h
19259--- linux-2.6.17.7/include/asm-i386/mach-voyager/do_timer.h 2006-07-24 23:36:01.000000000 -0400
19260+++ linux-2.6.17.7/include/asm-i386/mach-voyager/do_timer.h 2006-08-01 20:29:47.000000000 -0400
19261@@ -5,7 +5,7 @@ static inline void do_timer_interrupt_ho
19262 {
19263 do_timer(regs);
19264 #ifndef CONFIG_SMP
19265- update_process_times(user_mode_vm(regs));
19266+ update_process_times(user_mode(regs));
19267 #endif
19268
19269 voyager_timer_interrupt(regs);
19270diff -urNp linux-2.6.17.7/include/asm-i386/mman.h linux-2.6.17.7/include/asm-i386/mman.h
19271--- linux-2.6.17.7/include/asm-i386/mman.h 2006-07-24 23:36:01.000000000 -0400
19272+++ linux-2.6.17.7/include/asm-i386/mman.h 2006-08-01 20:29:47.000000000 -0400
19273@@ -11,6 +11,10 @@
19274 #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
19275 #define MAP_NONBLOCK 0x10000 /* do not block on IO */
19276
19277+#ifdef CONFIG_PAX_SEGMEXEC
19278+#define MAP_MIRROR 0x20000
19279+#endif
19280+
19281 #define MCL_CURRENT 1 /* lock all current mappings */
19282 #define MCL_FUTURE 2 /* lock all future mappings */
19283
19284diff -urNp linux-2.6.17.7/include/asm-i386/mmu.h linux-2.6.17.7/include/asm-i386/mmu.h
19285--- linux-2.6.17.7/include/asm-i386/mmu.h 2006-07-24 23:36:01.000000000 -0400
19286+++ linux-2.6.17.7/include/asm-i386/mmu.h 2006-08-01 20:29:47.000000000 -0400
19287@@ -12,6 +12,17 @@ typedef struct {
19288 int size;
19289 struct semaphore sem;
19290 void *ldt;
19291+
19292+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
19293+ unsigned long user_cs_base;
19294+ unsigned long user_cs_limit;
19295+
19296+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
19297+ cpumask_t cpu_user_cs_mask;
19298+#endif
19299+
19300+#endif
19301+
19302 } mm_context_t;
19303
19304 #endif
19305diff -urNp linux-2.6.17.7/include/asm-i386/mmu_context.h linux-2.6.17.7/include/asm-i386/mmu_context.h
19306--- linux-2.6.17.7/include/asm-i386/mmu_context.h 2006-07-24 23:36:01.000000000 -0400
19307+++ linux-2.6.17.7/include/asm-i386/mmu_context.h 2006-08-01 20:29:47.000000000 -0400
19308@@ -46,6 +46,18 @@ static inline void switch_mm(struct mm_s
19309 */
19310 if (unlikely(prev->context.ldt != next->context.ldt))
19311 load_LDT_nolock(&next->context, cpu);
19312+
19313+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
19314+ cpu_clear(cpu, prev->context.cpu_user_cs_mask);
19315+ cpu_set(cpu, next->context.cpu_user_cs_mask);
19316+#endif
19317+
19318+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
19319+ if (prev->context.user_cs_base != next->context.user_cs_base ||
19320+ prev->context.user_cs_limit != next->context.user_cs_limit)
19321+#endif
19322+
19323+ set_user_cs(next, cpu);
19324 }
19325 #ifdef CONFIG_SMP
19326 else {
19327@@ -58,6 +70,12 @@ static inline void switch_mm(struct mm_s
19328 */
19329 load_cr3(next->pgd);
19330 load_LDT_nolock(&next->context, cpu);
19331+
19332+#ifdef CONFIG_PAX_PAGEEXEC
19333+ cpu_set(cpu, next->context.cpu_user_cs_mask);
19334+#endif
19335+
19336+ set_user_cs(next, cpu);
19337 }
19338 }
19339 #endif
19340diff -urNp linux-2.6.17.7/include/asm-i386/module.h linux-2.6.17.7/include/asm-i386/module.h
19341--- linux-2.6.17.7/include/asm-i386/module.h 2006-07-24 23:36:01.000000000 -0400
19342+++ linux-2.6.17.7/include/asm-i386/module.h 2006-08-01 20:29:47.000000000 -0400
19343@@ -72,6 +72,12 @@ struct mod_arch_specific
19344 #define MODULE_STACKSIZE ""
19345 #endif
19346
19347-#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE
19348+#ifdef CONFIG_GRKERNSEC
19349+#define MODULE_GRSEC "GRSECURITY "
19350+#else
19351+#define MODULE_GRSEC ""
19352+#endif
19353+
19354+#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE MODULE_GRSEC
19355
19356 #endif /* _ASM_I386_MODULE_H */
19357diff -urNp linux-2.6.17.7/include/asm-i386/page.h linux-2.6.17.7/include/asm-i386/page.h
19358--- linux-2.6.17.7/include/asm-i386/page.h 2006-07-24 23:36:01.000000000 -0400
19359+++ linux-2.6.17.7/include/asm-i386/page.h 2006-08-01 20:29:47.000000000 -0400
19360@@ -57,7 +57,6 @@ typedef struct { unsigned long long pgpr
19361 typedef struct { unsigned long pte_low; } pte_t;
19362 typedef struct { unsigned long pgd; } pgd_t;
19363 typedef struct { unsigned long pgprot; } pgprot_t;
19364-#define boot_pte_t pte_t /* or would you rather have a typedef */
19365 #define pte_val(x) ((x).pte_low)
19366 #define HPAGE_SHIFT 22
19367 #endif
19368@@ -118,6 +117,15 @@ extern int page_is_ram(unsigned long pag
19369 #endif
19370 #define __KERNEL_START (__PAGE_OFFSET + __PHYSICAL_START)
19371
19372+#ifdef CONFIG_PAX_KERNEXEC
19373+#define __KERNEL_TEXT_OFFSET (__PAGE_OFFSET + ((__PHYSICAL_START + ~(4*1024*1024)) & (4*1024*1024)))
19374+#ifndef __ASSEMBLY__
19375+extern unsigned char MODULES_VADDR[];
19376+extern unsigned char MODULES_END[];
19377+#endif
19378+#else
19379+#define __KERNEL_TEXT_OFFSET (0)
19380+#endif
19381
19382 #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
19383 #define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE)
19384@@ -137,6 +145,19 @@ extern int page_is_ram(unsigned long pag
19385 ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
19386 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
19387
19388+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
19389+#ifdef CONFIG_PAX_MPROTECT
19390+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
19391+ ((current->mm->pax_flags & (MF_PAX_PAGEEXEC|MF_PAX_SEGMEXEC))?0:VM_EXEC))
19392+#else
19393+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & (MF_PAX_PAGEEXEC|MF_PAX_SEGMEXEC))?0:VM_EXEC))
19394+#endif
19395+#endif
19396+
19397+#ifdef CONFIG_PAX_PAGEEXEC
19398+#define CONFIG_ARCH_TRACK_EXEC_LIMIT 1
19399+#endif
19400+
19401 #endif /* __KERNEL__ */
19402
19403 #include <asm-generic/memory_model.h>
19404diff -urNp linux-2.6.17.7/include/asm-i386/pgalloc.h linux-2.6.17.7/include/asm-i386/pgalloc.h
19405--- linux-2.6.17.7/include/asm-i386/pgalloc.h 2006-07-24 23:36:01.000000000 -0400
19406+++ linux-2.6.17.7/include/asm-i386/pgalloc.h 2006-08-01 20:29:47.000000000 -0400
19407@@ -3,11 +3,17 @@
19408
19409 #include <linux/config.h>
19410 #include <asm/fixmap.h>
19411+#include <asm/desc.h>
19412 #include <linux/threads.h>
19413 #include <linux/mm.h> /* for struct page */
19414
19415+#ifdef CONFIG_PAX_NOVSYSCALL
19416+#define pmd_populate_kernel(mm, pmd, pte) \
19417+ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)))
19418+#else
19419 #define pmd_populate_kernel(mm, pmd, pte) \
19420 set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
19421+#endif
19422
19423 #define pmd_populate(mm, pmd, pte) \
19424 set_pmd(pmd, __pmd(_PAGE_TABLE + \
19425diff -urNp linux-2.6.17.7/include/asm-i386/pgtable.h linux-2.6.17.7/include/asm-i386/pgtable.h
19426--- linux-2.6.17.7/include/asm-i386/pgtable.h 2006-07-24 23:36:01.000000000 -0400
19427+++ linux-2.6.17.7/include/asm-i386/pgtable.h 2006-08-01 20:29:47.000000000 -0400
19428@@ -34,7 +34,6 @@ struct vm_area_struct;
19429 */
19430 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
19431 extern unsigned long empty_zero_page[1024];
19432-extern pgd_t swapper_pg_dir[1024];
19433 extern kmem_cache_t *pgd_cache;
19434 extern kmem_cache_t *pmd_cache;
19435 extern spinlock_t pgd_lock;
19436@@ -59,6 +58,11 @@ void paging_init(void);
19437 # include <asm/pgtable-2level-defs.h>
19438 #endif
19439
19440+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
19441+#ifdef CONFIG_X86_PAE
19442+extern pmd_t swapper_pm_dir[PTRS_PER_PGD][PTRS_PER_PMD];
19443+#endif
19444+
19445 #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
19446 #define PGDIR_MASK (~(PGDIR_SIZE-1))
19447
19448@@ -68,9 +72,11 @@ void paging_init(void);
19449 #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
19450 #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
19451
19452+#ifndef CONFIG_X86_PAE
19453 #define TWOLEVEL_PGDIR_SHIFT 22
19454 #define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
19455 #define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
19456+#endif
19457
19458 /* Just any arbitrary offset to the start of the vmalloc VM area: the
19459 * current 8MB value just means that there will be a 8MB "hole" after the
19460@@ -141,17 +147,26 @@ void paging_init(void);
19461
19462 #define PAGE_SHARED_EXEC \
19463 __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
19464-#define PAGE_COPY_NOEXEC \
19465- __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
19466 #define PAGE_COPY_EXEC \
19467 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
19468-#define PAGE_COPY \
19469- PAGE_COPY_NOEXEC
19470 #define PAGE_READONLY \
19471 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
19472 #define PAGE_READONLY_EXEC \
19473 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
19474
19475+#ifdef CONFIG_PAX_PAGEEXEC
19476+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED)
19477+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
19478+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
19479+#else
19480+# define PAGE_SHARED_NOEXEC PAGE_SHARED
19481+# define PAGE_COPY_NOEXEC \
19482+ __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
19483+# define PAGE_READONLY_NOEXEC PAGE_READONLY
19484+#endif
19485+
19486+#define PAGE_COPY \
19487+ PAGE_COPY_NOEXEC
19488 #define _PAGE_KERNEL \
19489 (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
19490 #define _PAGE_KERNEL_EXEC \
19491@@ -176,18 +191,18 @@ extern unsigned long long __PAGE_KERNEL,
19492 * This is the closest we can get..
19493 */
19494 #define __P000 PAGE_NONE
19495-#define __P001 PAGE_READONLY
19496-#define __P010 PAGE_COPY
19497-#define __P011 PAGE_COPY
19498+#define __P001 PAGE_READONLY_NOEXEC
19499+#define __P010 PAGE_COPY_NOEXEC
19500+#define __P011 PAGE_COPY_NOEXEC
19501 #define __P100 PAGE_READONLY_EXEC
19502 #define __P101 PAGE_READONLY_EXEC
19503 #define __P110 PAGE_COPY_EXEC
19504 #define __P111 PAGE_COPY_EXEC
19505
19506 #define __S000 PAGE_NONE
19507-#define __S001 PAGE_READONLY
19508-#define __S010 PAGE_SHARED
19509-#define __S011 PAGE_SHARED
19510+#define __S001 PAGE_READONLY_NOEXEC
19511+#define __S010 PAGE_SHARED_NOEXEC
19512+#define __S011 PAGE_SHARED_NOEXEC
19513 #define __S100 PAGE_READONLY_EXEC
19514 #define __S101 PAGE_READONLY_EXEC
19515 #define __S110 PAGE_SHARED_EXEC
19516@@ -431,6 +446,9 @@ extern void noexec_setup(const char *str
19517
19518 #endif /* !__ASSEMBLY__ */
19519
19520+#define HAVE_ARCH_UNMAPPED_AREA
19521+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
19522+
19523 #ifdef CONFIG_FLATMEM
19524 #define kern_addr_valid(addr) (1)
19525 #endif /* CONFIG_FLATMEM */
19526diff -urNp linux-2.6.17.7/include/asm-i386/processor.h linux-2.6.17.7/include/asm-i386/processor.h
19527--- linux-2.6.17.7/include/asm-i386/processor.h 2006-07-24 23:36:01.000000000 -0400
19528+++ linux-2.6.17.7/include/asm-i386/processor.h 2006-08-01 20:29:47.000000000 -0400
19529@@ -19,7 +19,6 @@
19530 #include <linux/cache.h>
19531 #include <linux/config.h>
19532 #include <linux/threads.h>
19533-#include <asm/percpu.h>
19534 #include <linux/cpumask.h>
19535
19536 /* flag for disabling the tsc */
19537@@ -94,8 +93,6 @@ struct cpuinfo_x86 {
19538
19539 extern struct cpuinfo_x86 boot_cpu_data;
19540 extern struct cpuinfo_x86 new_cpu_data;
19541-extern struct tss_struct doublefault_tss;
19542-DECLARE_PER_CPU(struct tss_struct, init_tss);
19543
19544 #ifdef CONFIG_SMP
19545 extern struct cpuinfo_x86 cpu_data[];
19546@@ -325,10 +322,19 @@ extern int bootloader_type;
19547 */
19548 #define TASK_SIZE (PAGE_OFFSET)
19549
19550+#ifdef CONFIG_PAX_SEGMEXEC
19551+#define SEGMEXEC_TASK_SIZE ((PAGE_OFFSET) / 2)
19552+#endif
19553+
19554 /* This decides where the kernel will search for a free chunk of vm
19555 * space during mmap's.
19556 */
19557+
19558+#ifdef CONFIG_PAX_SEGMEXEC
19559+#define TASK_UNMAPPED_BASE (PAGE_ALIGN((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3 : TASK_SIZE/3))
19560+#else
19561 #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
19562+#endif
19563
19564 #define HAVE_ARCH_PICK_MMAP_LAYOUT
19565
19566@@ -444,6 +450,9 @@ struct tss_struct {
19567
19568 #define ARCH_MIN_TASKALIGN 16
19569
19570+extern struct tss_struct doublefault_tss;
19571+extern struct tss_struct init_tss[NR_CPUS];
19572+
19573 struct thread_struct {
19574 /* cached TLS descriptors. */
19575 struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
19576@@ -472,6 +481,7 @@ struct thread_struct {
19577 };
19578
19579 #define INIT_THREAD { \
19580+ .esp0 = sizeof(init_stack) + (long)&init_stack - 8, \
19581 .vm86_info = NULL, \
19582 .sysenter_cs = __KERNEL_CS, \
19583 .io_bitmap_ptr = NULL, \
19584@@ -484,7 +494,7 @@ struct thread_struct {
19585 * be within the limit.
19586 */
19587 #define INIT_TSS { \
19588- .esp0 = sizeof(init_stack) + (long)&init_stack, \
19589+ .esp0 = sizeof(init_stack) + (long)&init_stack - 8, \
19590 .ss0 = __KERNEL_DS, \
19591 .ss1 = __KERNEL_CS, \
19592 .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
19593@@ -560,11 +570,7 @@ void show_trace(struct task_struct *task
19594 unsigned long get_wchan(struct task_struct *p);
19595
19596 #define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long))
19597-#define KSTK_TOP(info) \
19598-({ \
19599- unsigned long *__ptr = (unsigned long *)(info); \
19600- (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
19601-})
19602+#define KSTK_TOP(info) ((info)->task.thread.esp0)
19603
19604 /*
19605 * The below -8 is to reserve 8 bytes on top of the ring0 stack.
19606@@ -579,7 +585,7 @@ unsigned long get_wchan(struct task_stru
19607 #define task_pt_regs(task) \
19608 ({ \
19609 struct pt_regs *__regs__; \
19610- __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
19611+ __regs__ = (struct pt_regs *)((task)->thread.esp0); \
19612 __regs__ - 1; \
19613 })
19614
19615diff -urNp linux-2.6.17.7/include/asm-i386/ptrace.h linux-2.6.17.7/include/asm-i386/ptrace.h
19616--- linux-2.6.17.7/include/asm-i386/ptrace.h 2006-07-24 23:36:01.000000000 -0400
19617+++ linux-2.6.17.7/include/asm-i386/ptrace.h 2006-08-01 20:29:47.000000000 -0400
19618@@ -65,17 +65,18 @@ struct task_struct;
19619 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
19620
19621 /*
19622- * user_mode_vm(regs) determines whether a register set came from user mode.
19623+ * user_mode(regs) determines whether a register set came from user mode.
19624 * This is true if V8086 mode was enabled OR if the register set was from
19625 * protected mode with RPL-3 CS value. This tricky test checks that with
19626 * one comparison. Many places in the kernel can bypass this full check
19627- * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
19628+ * if they have already ruled out V8086 mode, so user_mode_novm(regs) can
19629+ * be used.
19630 */
19631-static inline int user_mode(struct pt_regs *regs)
19632+static inline int user_mode_novm(struct pt_regs *regs)
19633 {
19634 return (regs->xcs & 3) != 0;
19635 }
19636-static inline int user_mode_vm(struct pt_regs *regs)
19637+static inline int user_mode(struct pt_regs *regs)
19638 {
19639 return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0;
19640 }
19641diff -urNp linux-2.6.17.7/include/asm-i386/system.h linux-2.6.17.7/include/asm-i386/system.h
19642--- linux-2.6.17.7/include/asm-i386/system.h 2006-07-24 23:36:01.000000000 -0400
19643+++ linux-2.6.17.7/include/asm-i386/system.h 2006-08-01 20:29:47.000000000 -0400
19644@@ -5,6 +5,7 @@
19645 #include <linux/kernel.h>
19646 #include <asm/segment.h>
19647 #include <asm/cpufeature.h>
19648+#include <asm/page.h>
19649 #include <linux/bitops.h> /* for LOCK_PREFIX */
19650
19651 #ifdef __KERNEL__
19652@@ -151,7 +152,7 @@ static inline unsigned long get_limit(un
19653 unsigned long __limit;
19654 __asm__("lsll %1,%0"
19655 :"=r" (__limit):"r" (segment));
19656- return __limit+1;
19657+ return __limit;
19658 }
19659
19660 #define nop() __asm__ __volatile__ ("nop")
19661@@ -496,7 +497,7 @@ static inline void sched_cacheflush(void
19662 wbinvd();
19663 }
19664
19665-extern unsigned long arch_align_stack(unsigned long sp);
19666+#define arch_align_stack(x) (x)
19667 extern void free_init_pages(char *what, unsigned long begin, unsigned long end);
19668
19669 void default_idle(void);
19670diff -urNp linux-2.6.17.7/include/asm-i386/uaccess.h linux-2.6.17.7/include/asm-i386/uaccess.h
19671--- linux-2.6.17.7/include/asm-i386/uaccess.h 2006-07-24 23:36:01.000000000 -0400
19672+++ linux-2.6.17.7/include/asm-i386/uaccess.h 2006-08-01 20:29:47.000000000 -0400
19673@@ -10,6 +10,8 @@
19674 #include <linux/prefetch.h>
19675 #include <linux/string.h>
19676 #include <asm/page.h>
19677+#include <asm/segment.h>
19678+#include <asm/desc.h>
19679
19680 #define VERIFY_READ 0
19681 #define VERIFY_WRITE 1
19682@@ -30,7 +32,8 @@
19683
19684 #define get_ds() (KERNEL_DS)
19685 #define get_fs() (current_thread_info()->addr_limit)
19686-#define set_fs(x) (current_thread_info()->addr_limit = (x))
19687+void __set_fs(mm_segment_t x, int cpu);
19688+void set_fs(mm_segment_t x);
19689
19690 #define segment_eq(a,b) ((a).seg == (b).seg)
19691
19692@@ -281,9 +284,12 @@ extern void __put_user_8(void);
19693
19694 #define __put_user_u64(x, addr, err) \
19695 __asm__ __volatile__( \
19696- "1: movl %%eax,0(%2)\n" \
19697- "2: movl %%edx,4(%2)\n" \
19698+ " movw %w5,%%ds\n" \
19699+ "1: movl %%eax,%%ds:0(%2)\n" \
19700+ "2: movl %%edx,%%ds:4(%2)\n" \
19701 "3:\n" \
19702+ " pushl %%ss\n" \
19703+ " popl %%ds\n" \
19704 ".section .fixup,\"ax\"\n" \
19705 "4: movl %3,%0\n" \
19706 " jmp 3b\n" \
19707@@ -294,7 +300,8 @@ extern void __put_user_8(void);
19708 " .long 2b,4b\n" \
19709 ".previous" \
19710 : "=r"(err) \
19711- : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err))
19712+ : "A" (x), "r" (addr), "i"(-EFAULT), "0"(err), \
19713+ "r"(__USER_DS))
19714
19715 #ifdef CONFIG_X86_WP_WORKS_OK
19716
19717@@ -333,8 +340,11 @@ struct __large_struct { unsigned long bu
19718 */
19719 #define __put_user_asm(x, addr, err, itype, rtype, ltype, errret) \
19720 __asm__ __volatile__( \
19721- "1: mov"itype" %"rtype"1,%2\n" \
19722+ " movw %w5,%%ds\n" \
19723+ "1: mov"itype" %"rtype"1,%%ds:%2\n" \
19724 "2:\n" \
19725+ " pushl %%ss\n" \
19726+ " popl %%ds\n" \
19727 ".section .fixup,\"ax\"\n" \
19728 "3: movl %3,%0\n" \
19729 " jmp 2b\n" \
19730@@ -344,7 +354,8 @@ struct __large_struct { unsigned long bu
19731 " .long 1b,3b\n" \
19732 ".previous" \
19733 : "=r"(err) \
19734- : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err))
19735+ : ltype (x), "m"(__m(addr)), "i"(errret), "0"(err), \
19736+ "r"(__USER_DS))
19737
19738
19739 #define __get_user_nocheck(x,ptr,size) \
19740@@ -372,8 +383,11 @@ do { \
19741
19742 #define __get_user_asm(x, addr, err, itype, rtype, ltype, errret) \
19743 __asm__ __volatile__( \
19744- "1: mov"itype" %2,%"rtype"1\n" \
19745+ " movw %w5,%%ds\n" \
19746+ "1: mov"itype" %%ds:%2,%"rtype"1\n" \
19747 "2:\n" \
19748+ " pushl %%ss\n" \
19749+ " popl %%ds\n" \
19750 ".section .fixup,\"ax\"\n" \
19751 "3: movl %3,%0\n" \
19752 " xor"itype" %"rtype"1,%"rtype"1\n" \
19753@@ -384,7 +398,7 @@ do { \
19754 " .long 1b,3b\n" \
19755 ".previous" \
19756 : "=r"(err), ltype (x) \
19757- : "m"(__m(addr)), "i"(errret), "0"(err))
19758+ : "m"(__m(addr)), "i"(errret), "0"(err), "r"(__USER_DS))
19759
19760
19761 unsigned long __must_check __copy_to_user_ll(void __user *to,
19762diff -urNp linux-2.6.17.7/include/asm-ia64/elf.h linux-2.6.17.7/include/asm-ia64/elf.h
19763--- linux-2.6.17.7/include/asm-ia64/elf.h 2006-07-24 23:36:01.000000000 -0400
19764+++ linux-2.6.17.7/include/asm-ia64/elf.h 2006-08-01 20:29:47.000000000 -0400
19765@@ -163,6 +163,16 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR
19766 typedef struct ia64_fpreg elf_fpreg_t;
19767 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
19768
19769+#ifdef CONFIG_PAX_ASLR
19770+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
19771+
19772+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
19773+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
19774+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
19775+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
19776+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
19777+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
19778+#endif
19779
19780
19781 struct pt_regs; /* forward declaration... */
19782diff -urNp linux-2.6.17.7/include/asm-ia64/kmap_types.h linux-2.6.17.7/include/asm-ia64/kmap_types.h
19783--- linux-2.6.17.7/include/asm-ia64/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
19784+++ linux-2.6.17.7/include/asm-ia64/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
19785@@ -23,7 +23,8 @@ D(9) KM_IRQ0,
19786 D(10) KM_IRQ1,
19787 D(11) KM_SOFTIRQ0,
19788 D(12) KM_SOFTIRQ1,
19789-D(13) KM_TYPE_NR
19790+D(13) KM_CLEARPAGE,
19791+D(14) KM_TYPE_NR
19792 };
19793
19794 #undef D
19795diff -urNp linux-2.6.17.7/include/asm-ia64/page.h linux-2.6.17.7/include/asm-ia64/page.h
19796--- linux-2.6.17.7/include/asm-ia64/page.h 2006-07-24 23:36:01.000000000 -0400
19797+++ linux-2.6.17.7/include/asm-ia64/page.h 2006-08-01 20:29:47.000000000 -0400
19798@@ -229,4 +229,13 @@ get_order (unsigned long size)
19799 (((current->personality & READ_IMPLIES_EXEC) != 0) \
19800 ? VM_EXEC : 0))
19801
19802+#ifdef CONFIG_PAX_PAGEEXEC
19803+#ifdef CONFIG_PAX_MPROTECT
19804+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
19805+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
19806+#else
19807+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
19808+#endif
19809+#endif
19810+
19811 #endif /* _ASM_IA64_PAGE_H */
19812diff -urNp linux-2.6.17.7/include/asm-ia64/pgtable.h linux-2.6.17.7/include/asm-ia64/pgtable.h
19813--- linux-2.6.17.7/include/asm-ia64/pgtable.h 2006-07-24 23:36:01.000000000 -0400
19814+++ linux-2.6.17.7/include/asm-ia64/pgtable.h 2006-08-01 20:29:47.000000000 -0400
19815@@ -144,6 +144,17 @@
19816 #define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
19817 #define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
19818 #define PAGE_COPY_EXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX)
19819+
19820+#ifdef CONFIG_PAX_PAGEEXEC
19821+# define PAGE_SHARED_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW)
19822+# define PAGE_READONLY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
19823+# define PAGE_COPY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
19824+#else
19825+# define PAGE_SHARED_NOEXEC PAGE_SHARED
19826+# define PAGE_READONLY_NOEXEC PAGE_READONLY
19827+# define PAGE_COPY_NOEXEC PAGE_COPY
19828+#endif
19829+
19830 #define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
19831 #define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX)
19832 #define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX)
19833diff -urNp linux-2.6.17.7/include/asm-ia64/processor.h linux-2.6.17.7/include/asm-ia64/processor.h
19834--- linux-2.6.17.7/include/asm-ia64/processor.h 2006-07-24 23:36:01.000000000 -0400
19835+++ linux-2.6.17.7/include/asm-ia64/processor.h 2006-08-01 20:29:47.000000000 -0400
19836@@ -284,7 +284,7 @@ struct thread_struct {
19837 .on_ustack = 0, \
19838 .ksp = 0, \
19839 .map_base = DEFAULT_MAP_BASE, \
19840- .rbs_bot = STACK_TOP - DEFAULT_USER_STACK_SIZE, \
19841+ .rbs_bot = __STACK_TOP - DEFAULT_USER_STACK_SIZE, \
19842 .task_size = DEFAULT_TASK_SIZE, \
19843 .last_fph_cpu = -1, \
19844 INIT_THREAD_IA32 \
19845diff -urNp linux-2.6.17.7/include/asm-ia64/ustack.h linux-2.6.17.7/include/asm-ia64/ustack.h
19846--- linux-2.6.17.7/include/asm-ia64/ustack.h 2006-07-24 23:36:01.000000000 -0400
19847+++ linux-2.6.17.7/include/asm-ia64/ustack.h 2006-08-01 20:29:47.000000000 -0400
19848@@ -11,6 +11,6 @@
19849 #define MAX_USER_STACK_SIZE (RGN_MAP_LIMIT/2)
19850 /* Make a default stack size of 2GB */
19851 #define DEFAULT_USER_STACK_SIZE (1UL << 31)
19852-#define STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT)
19853+#define __STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT)
19854
19855 #endif /* _ASM_IA64_USTACK_H */
19856diff -urNp linux-2.6.17.7/include/asm-m32r/kmap_types.h linux-2.6.17.7/include/asm-m32r/kmap_types.h
19857--- linux-2.6.17.7/include/asm-m32r/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
19858+++ linux-2.6.17.7/include/asm-m32r/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
19859@@ -25,7 +25,8 @@ D(9) KM_IRQ0,
19860 D(10) KM_IRQ1,
19861 D(11) KM_SOFTIRQ0,
19862 D(12) KM_SOFTIRQ1,
19863-D(13) KM_TYPE_NR
19864+D(13) KM_CLEARPAGE,
19865+D(14) KM_TYPE_NR
19866 };
19867
19868 #undef D
19869diff -urNp linux-2.6.17.7/include/asm-m68k/kmap_types.h linux-2.6.17.7/include/asm-m68k/kmap_types.h
19870--- linux-2.6.17.7/include/asm-m68k/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
19871+++ linux-2.6.17.7/include/asm-m68k/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
19872@@ -15,6 +15,7 @@ enum km_type {
19873 KM_IRQ1,
19874 KM_SOFTIRQ0,
19875 KM_SOFTIRQ1,
19876+ KM_CLEARPAGE,
19877 KM_TYPE_NR
19878 };
19879
19880diff -urNp linux-2.6.17.7/include/asm-m68knommu/kmap_types.h linux-2.6.17.7/include/asm-m68knommu/kmap_types.h
19881--- linux-2.6.17.7/include/asm-m68knommu/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
19882+++ linux-2.6.17.7/include/asm-m68knommu/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
19883@@ -15,6 +15,7 @@ enum km_type {
19884 KM_IRQ1,
19885 KM_SOFTIRQ0,
19886 KM_SOFTIRQ1,
19887+ KM_CLEARPAGE,
19888 KM_TYPE_NR
19889 };
19890
19891diff -urNp linux-2.6.17.7/include/asm-mips/a.out.h linux-2.6.17.7/include/asm-mips/a.out.h
19892--- linux-2.6.17.7/include/asm-mips/a.out.h 2006-07-24 23:36:01.000000000 -0400
19893+++ linux-2.6.17.7/include/asm-mips/a.out.h 2006-08-01 20:29:47.000000000 -0400
19894@@ -36,10 +36,10 @@ struct exec
19895 #ifdef __KERNEL__
19896
19897 #ifdef CONFIG_32BIT
19898-#define STACK_TOP TASK_SIZE
19899+#define __STACK_TOP TASK_SIZE
19900 #endif
19901 #ifdef CONFIG_64BIT
19902-#define STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
19903+#define __STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
19904 #endif
19905
19906 #endif
19907diff -urNp linux-2.6.17.7/include/asm-mips/elf.h linux-2.6.17.7/include/asm-mips/elf.h
19908--- linux-2.6.17.7/include/asm-mips/elf.h 2006-07-24 23:36:01.000000000 -0400
19909+++ linux-2.6.17.7/include/asm-mips/elf.h 2006-08-01 20:29:47.000000000 -0400
19910@@ -372,4 +372,15 @@ extern int dump_task_fpu(struct task_str
19911 #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
19912 #endif
19913
19914+#ifdef CONFIG_PAX_ASLR
19915+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
19916+
19917+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
19918+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
19919+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
19920+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
19921+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
19922+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
19923+#endif
19924+
19925 #endif /* _ASM_ELF_H */
19926diff -urNp linux-2.6.17.7/include/asm-mips/kmap_types.h linux-2.6.17.7/include/asm-mips/kmap_types.h
19927--- linux-2.6.17.7/include/asm-mips/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
19928+++ linux-2.6.17.7/include/asm-mips/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
19929@@ -23,7 +23,8 @@ D(9) KM_IRQ0,
19930 D(10) KM_IRQ1,
19931 D(11) KM_SOFTIRQ0,
19932 D(12) KM_SOFTIRQ1,
19933-D(13) KM_TYPE_NR
19934+D(13) KM_CLEARPAGE,
19935+D(14) KM_TYPE_NR
19936 };
19937
19938 #undef D
19939diff -urNp linux-2.6.17.7/include/asm-mips/page.h linux-2.6.17.7/include/asm-mips/page.h
19940--- linux-2.6.17.7/include/asm-mips/page.h 2006-07-24 23:36:01.000000000 -0400
19941+++ linux-2.6.17.7/include/asm-mips/page.h 2006-08-01 20:29:47.000000000 -0400
19942@@ -151,6 +151,15 @@ typedef struct { unsigned long pgprot; }
19943 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
19944 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
19945
19946+#ifdef CONFIG_PAX_PAGEEXEC
19947+#ifdef CONFIG_PAX_MPROTECT
19948+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
19949+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
19950+#else
19951+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
19952+#endif
19953+#endif
19954+
19955 #define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE)
19956 #define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET)
19957
19958diff -urNp linux-2.6.17.7/include/asm-parisc/a.out.h linux-2.6.17.7/include/asm-parisc/a.out.h
19959--- linux-2.6.17.7/include/asm-parisc/a.out.h 2006-07-24 23:36:01.000000000 -0400
19960+++ linux-2.6.17.7/include/asm-parisc/a.out.h 2006-08-01 20:29:47.000000000 -0400
19961@@ -22,7 +22,7 @@ struct exec
19962 /* XXX: STACK_TOP actually should be STACK_BOTTOM for parisc.
19963 * prumpf */
19964
19965-#define STACK_TOP TASK_SIZE
19966+#define __STACK_TOP TASK_SIZE
19967
19968 #endif
19969
19970diff -urNp linux-2.6.17.7/include/asm-parisc/elf.h linux-2.6.17.7/include/asm-parisc/elf.h
19971--- linux-2.6.17.7/include/asm-parisc/elf.h 2006-07-24 23:36:01.000000000 -0400
19972+++ linux-2.6.17.7/include/asm-parisc/elf.h 2006-08-01 20:29:47.000000000 -0400
19973@@ -337,6 +337,17 @@ struct pt_regs; /* forward declaration..
19974
19975 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000)
19976
19977+#ifdef CONFIG_PAX_ASLR
19978+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000UL
19979+
19980+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
19981+#define PAX_DELTA_MMAP_LEN(tsk) 16
19982+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
19983+#define PAX_DELTA_EXEC_LEN(tsk) 16
19984+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
19985+#define PAX_DELTA_STACK_LEN(tsk) 16
19986+#endif
19987+
19988 /* This yields a mask that user programs can use to figure out what
19989 instruction set this CPU supports. This could be done in user space,
19990 but it's not easy, and we've already done it here. */
19991diff -urNp linux-2.6.17.7/include/asm-parisc/kmap_types.h linux-2.6.17.7/include/asm-parisc/kmap_types.h
19992--- linux-2.6.17.7/include/asm-parisc/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
19993+++ linux-2.6.17.7/include/asm-parisc/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
19994@@ -23,7 +23,8 @@ D(9) KM_IRQ0,
19995 D(10) KM_IRQ1,
19996 D(11) KM_SOFTIRQ0,
19997 D(12) KM_SOFTIRQ1,
19998-D(13) KM_TYPE_NR
19999+D(13) KM_CLEARPAGE,
20000+D(14) KM_TYPE_NR
20001 };
20002
20003 #undef D
20004diff -urNp linux-2.6.17.7/include/asm-parisc/page.h linux-2.6.17.7/include/asm-parisc/page.h
20005--- linux-2.6.17.7/include/asm-parisc/page.h 2006-07-24 23:36:01.000000000 -0400
20006+++ linux-2.6.17.7/include/asm-parisc/page.h 2006-08-01 20:29:47.000000000 -0400
20007@@ -189,6 +189,15 @@ extern int npmem_ranges;
20008 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
20009 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
20010
20011+#ifdef CONFIG_PAX_PAGEEXEC
20012+#ifdef CONFIG_PAX_MPROTECT
20013+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20014+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20015+#else
20016+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20017+#endif
20018+#endif
20019+
20020 #endif /* __KERNEL__ */
20021
20022 #include <asm-generic/memory_model.h>
20023diff -urNp linux-2.6.17.7/include/asm-parisc/pgtable.h linux-2.6.17.7/include/asm-parisc/pgtable.h
20024--- linux-2.6.17.7/include/asm-parisc/pgtable.h 2006-07-24 23:36:01.000000000 -0400
20025+++ linux-2.6.17.7/include/asm-parisc/pgtable.h 2006-08-01 20:29:47.000000000 -0400
20026@@ -220,6 +220,17 @@ extern void *vmalloc_start;
20027 #define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED)
20028 #define PAGE_COPY PAGE_EXECREAD
20029 #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED)
20030+
20031+#ifdef CONFIG_PAX_PAGEEXEC
20032+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_ACCESSED)
20033+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
20034+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
20035+#else
20036+# define PAGE_SHARED_NOEXEC PAGE_SHARED
20037+# define PAGE_COPY_NOEXEC PAGE_COPY
20038+# define PAGE_READONLY_NOEXEC PAGE_READONLY
20039+#endif
20040+
20041 #define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
20042 #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
20043 #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
20044diff -urNp linux-2.6.17.7/include/asm-powerpc/a.out.h linux-2.6.17.7/include/asm-powerpc/a.out.h
20045--- linux-2.6.17.7/include/asm-powerpc/a.out.h 2006-07-24 23:36:01.000000000 -0400
20046+++ linux-2.6.17.7/include/asm-powerpc/a.out.h 2006-08-01 20:29:47.000000000 -0400
20047@@ -23,12 +23,12 @@ struct exec
20048 #define STACK_TOP_USER64 TASK_SIZE_USER64
20049 #define STACK_TOP_USER32 TASK_SIZE_USER32
20050
20051-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
20052+#define __STACK_TOP (test_thread_flag(TIF_32BIT) ? \
20053 STACK_TOP_USER32 : STACK_TOP_USER64)
20054
20055 #else /* __powerpc64__ */
20056
20057-#define STACK_TOP TASK_SIZE
20058+#define __STACK_TOP TASK_SIZE
20059
20060 #endif /* __powerpc64__ */
20061 #endif /* __KERNEL__ */
20062diff -urNp linux-2.6.17.7/include/asm-powerpc/elf.h linux-2.6.17.7/include/asm-powerpc/elf.h
20063--- linux-2.6.17.7/include/asm-powerpc/elf.h 2006-07-24 23:36:01.000000000 -0400
20064+++ linux-2.6.17.7/include/asm-powerpc/elf.h 2006-08-01 20:29:47.000000000 -0400
20065@@ -176,6 +176,26 @@ typedef elf_vrreg_t elf_vrregset_t32[ELF
20066
20067 #define ELF_ET_DYN_BASE (0x08000000)
20068
20069+#ifdef CONFIG_PAX_ASLR
20070+#define PAX_ELF_ET_DYN_BASE(tsk) (0x10000000UL)
20071+
20072+#ifdef __powerpc64__
20073+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20074+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
20075+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20076+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
20077+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20078+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
20079+#else
20080+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20081+#define PAX_DELTA_MMAP_LEN(tsk) 15
20082+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20083+#define PAX_DELTA_EXEC_LEN(tsk) 15
20084+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20085+#define PAX_DELTA_STACK_LEN(tsk) 15
20086+#endif
20087+#endif
20088+
20089 #ifdef __KERNEL__
20090
20091 /* Common routine for both 32-bit and 64-bit processes */
20092diff -urNp linux-2.6.17.7/include/asm-powerpc/kmap_types.h linux-2.6.17.7/include/asm-powerpc/kmap_types.h
20093--- linux-2.6.17.7/include/asm-powerpc/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
20094+++ linux-2.6.17.7/include/asm-powerpc/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
20095@@ -26,6 +26,7 @@ enum km_type {
20096 KM_SOFTIRQ1,
20097 KM_PPC_SYNC_PAGE,
20098 KM_PPC_SYNC_ICACHE,
20099+ KM_CLEARPAGE,
20100 KM_TYPE_NR
20101 };
20102
20103diff -urNp linux-2.6.17.7/include/asm-powerpc/page_64.h linux-2.6.17.7/include/asm-powerpc/page_64.h
20104--- linux-2.6.17.7/include/asm-powerpc/page_64.h 2006-07-24 23:36:01.000000000 -0400
20105+++ linux-2.6.17.7/include/asm-powerpc/page_64.h 2006-08-01 20:29:47.000000000 -0400
20106@@ -170,6 +170,15 @@ extern unsigned int HPAGE_SHIFT;
20107 (test_thread_flag(TIF_32BIT) ? \
20108 VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
20109
20110+#ifdef CONFIG_PAX_PAGEEXEC
20111+#ifdef CONFIG_PAX_MPROTECT
20112+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20113+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20114+#else
20115+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20116+#endif
20117+#endif
20118+
20119 #include <asm-generic/page.h>
20120
20121 #endif /* __KERNEL__ */
20122diff -urNp linux-2.6.17.7/include/asm-ppc/page.h linux-2.6.17.7/include/asm-ppc/page.h
20123--- linux-2.6.17.7/include/asm-ppc/page.h 2006-07-24 23:36:01.000000000 -0400
20124+++ linux-2.6.17.7/include/asm-ppc/page.h 2006-08-01 20:29:47.000000000 -0400
20125@@ -175,6 +175,15 @@ extern __inline__ int get_order(unsigned
20126 /* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */
20127 #define __HAVE_ARCH_GATE_AREA 1
20128
20129+#ifdef CONFIG_PAX_PAGEEXEC
20130+#ifdef CONFIG_PAX_MPROTECT
20131+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20132+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20133+#else
20134+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20135+#endif
20136+#endif
20137+
20138 #include <asm-generic/memory_model.h>
20139 #endif /* __KERNEL__ */
20140 #endif /* _PPC_PAGE_H */
20141diff -urNp linux-2.6.17.7/include/asm-ppc/pgtable.h linux-2.6.17.7/include/asm-ppc/pgtable.h
20142--- linux-2.6.17.7/include/asm-ppc/pgtable.h 2006-07-24 23:36:01.000000000 -0400
20143+++ linux-2.6.17.7/include/asm-ppc/pgtable.h 2006-08-01 20:29:47.000000000 -0400
20144@@ -441,11 +441,21 @@ extern unsigned long ioremap_bot, iorema
20145
20146 #define PAGE_NONE __pgprot(_PAGE_BASE)
20147 #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
20148-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
20149+#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC)
20150 #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
20151-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
20152+#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC | _PAGE_HWEXEC)
20153 #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
20154-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
20155+#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC)
20156+
20157+#if defined(CONFIG_PAX_PAGEEXEC) && !defined(CONFIG_40x) && !defined(CONFIG_44x)
20158+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_GUARDED)
20159+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
20160+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
20161+#else
20162+# define PAGE_SHARED_NOEXEC PAGE_SHARED
20163+# define PAGE_COPY_NOEXEC PAGE_COPY
20164+# define PAGE_READONLY_NOEXEC PAGE_READONLY
20165+#endif
20166
20167 #define PAGE_KERNEL __pgprot(_PAGE_RAM)
20168 #define PAGE_KERNEL_NOCACHE __pgprot(_PAGE_IO)
20169@@ -457,21 +467,21 @@ extern unsigned long ioremap_bot, iorema
20170 * This is the closest we can get..
20171 */
20172 #define __P000 PAGE_NONE
20173-#define __P001 PAGE_READONLY_X
20174-#define __P010 PAGE_COPY
20175-#define __P011 PAGE_COPY_X
20176-#define __P100 PAGE_READONLY
20177+#define __P001 PAGE_READONLY_NOEXEC
20178+#define __P010 PAGE_COPY_NOEXEC
20179+#define __P011 PAGE_COPY_NOEXEC
20180+#define __P100 PAGE_READONLY_X
20181 #define __P101 PAGE_READONLY_X
20182-#define __P110 PAGE_COPY
20183+#define __P110 PAGE_COPY_X
20184 #define __P111 PAGE_COPY_X
20185
20186 #define __S000 PAGE_NONE
20187-#define __S001 PAGE_READONLY_X
20188-#define __S010 PAGE_SHARED
20189-#define __S011 PAGE_SHARED_X
20190-#define __S100 PAGE_READONLY
20191+#define __S001 PAGE_READONLY_NOEXEC
20192+#define __S010 PAGE_SHARED_NOEXEC
20193+#define __S011 PAGE_SHARED_NOEXEC
20194+#define __S100 PAGE_READONLY_X
20195 #define __S101 PAGE_READONLY_X
20196-#define __S110 PAGE_SHARED
20197+#define __S110 PAGE_SHARED_X
20198 #define __S111 PAGE_SHARED_X
20199
20200 #ifndef __ASSEMBLY__
20201diff -urNp linux-2.6.17.7/include/asm-s390/kmap_types.h linux-2.6.17.7/include/asm-s390/kmap_types.h
20202--- linux-2.6.17.7/include/asm-s390/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
20203+++ linux-2.6.17.7/include/asm-s390/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
20204@@ -16,6 +16,7 @@ enum km_type {
20205 KM_IRQ1,
20206 KM_SOFTIRQ0,
20207 KM_SOFTIRQ1,
20208+ KM_CLEARPAGE,
20209 KM_TYPE_NR
20210 };
20211
20212diff -urNp linux-2.6.17.7/include/asm-sh/kmap_types.h linux-2.6.17.7/include/asm-sh/kmap_types.h
20213--- linux-2.6.17.7/include/asm-sh/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
20214+++ linux-2.6.17.7/include/asm-sh/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
20215@@ -25,7 +25,8 @@ D(9) KM_IRQ0,
20216 D(10) KM_IRQ1,
20217 D(11) KM_SOFTIRQ0,
20218 D(12) KM_SOFTIRQ1,
20219-D(13) KM_TYPE_NR
20220+D(13) KM_CLEARPAGE,
20221+D(14) KM_TYPE_NR
20222 };
20223
20224 #undef D
20225diff -urNp linux-2.6.17.7/include/asm-sparc/a.out.h linux-2.6.17.7/include/asm-sparc/a.out.h
20226--- linux-2.6.17.7/include/asm-sparc/a.out.h 2006-07-24 23:36:01.000000000 -0400
20227+++ linux-2.6.17.7/include/asm-sparc/a.out.h 2006-08-01 20:29:47.000000000 -0400
20228@@ -91,7 +91,7 @@ struct relocation_info /* used when head
20229
20230 #include <asm/page.h>
20231
20232-#define STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
20233+#define __STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
20234
20235 #endif /* __KERNEL__ */
20236
20237diff -urNp linux-2.6.17.7/include/asm-sparc/elf.h linux-2.6.17.7/include/asm-sparc/elf.h
20238--- linux-2.6.17.7/include/asm-sparc/elf.h 2006-07-24 23:36:01.000000000 -0400
20239+++ linux-2.6.17.7/include/asm-sparc/elf.h 2006-08-01 20:29:47.000000000 -0400
20240@@ -145,6 +145,17 @@ typedef struct {
20241
20242 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE)
20243
20244+#ifdef CONFIG_PAX_ASLR
20245+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000UL
20246+
20247+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20248+#define PAX_DELTA_MMAP_LEN(tsk) 16
20249+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20250+#define PAX_DELTA_EXEC_LEN(tsk) 16
20251+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20252+#define PAX_DELTA_STACK_LEN(tsk) 16
20253+#endif
20254+
20255 /* This yields a mask that user programs can use to figure out what
20256 instruction set this cpu supports. This can NOT be done in userspace
20257 on Sparc. */
20258diff -urNp linux-2.6.17.7/include/asm-sparc/kmap_types.h linux-2.6.17.7/include/asm-sparc/kmap_types.h
20259--- linux-2.6.17.7/include/asm-sparc/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
20260+++ linux-2.6.17.7/include/asm-sparc/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
20261@@ -15,6 +15,7 @@ enum km_type {
20262 KM_IRQ1,
20263 KM_SOFTIRQ0,
20264 KM_SOFTIRQ1,
20265+ KM_CLEARPAGE,
20266 KM_TYPE_NR
20267 };
20268
20269diff -urNp linux-2.6.17.7/include/asm-sparc/page.h linux-2.6.17.7/include/asm-sparc/page.h
20270--- linux-2.6.17.7/include/asm-sparc/page.h 2006-07-24 23:36:01.000000000 -0400
20271+++ linux-2.6.17.7/include/asm-sparc/page.h 2006-08-01 20:29:47.000000000 -0400
20272@@ -161,6 +161,15 @@ extern unsigned long pfn_base;
20273 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
20274 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
20275
20276+#ifdef CONFIG_PAX_PAGEEXEC
20277+#ifdef CONFIG_PAX_MPROTECT
20278+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20279+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20280+#else
20281+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20282+#endif
20283+#endif
20284+
20285 #endif /* __KERNEL__ */
20286
20287 #include <asm-generic/memory_model.h>
20288diff -urNp linux-2.6.17.7/include/asm-sparc/pgtable.h linux-2.6.17.7/include/asm-sparc/pgtable.h
20289--- linux-2.6.17.7/include/asm-sparc/pgtable.h 2006-07-24 23:36:01.000000000 -0400
20290+++ linux-2.6.17.7/include/asm-sparc/pgtable.h 2006-08-01 20:29:47.000000000 -0400
20291@@ -50,6 +50,13 @@ BTFIXUPDEF_INT(page_none)
20292 BTFIXUPDEF_INT(page_shared)
20293 BTFIXUPDEF_INT(page_copy)
20294 BTFIXUPDEF_INT(page_readonly)
20295+
20296+#ifdef CONFIG_PAX_PAGEEXEC
20297+BTFIXUPDEF_INT(page_shared_noexec)
20298+BTFIXUPDEF_INT(page_copy_noexec)
20299+BTFIXUPDEF_INT(page_readonly_noexec)
20300+#endif
20301+
20302 BTFIXUPDEF_INT(page_kernel)
20303
20304 #define PMD_SHIFT SUN4C_PMD_SHIFT
20305@@ -71,6 +78,16 @@ BTFIXUPDEF_INT(page_kernel)
20306 #define PAGE_COPY __pgprot(BTFIXUP_INT(page_copy))
20307 #define PAGE_READONLY __pgprot(BTFIXUP_INT(page_readonly))
20308
20309+#ifdef CONFIG_PAX_PAGEEXEC
20310+# define PAGE_SHARED_NOEXEC __pgprot(BTFIXUP_INT(page_shared_noexec))
20311+# define PAGE_COPY_NOEXEC __pgprot(BTFIXUP_INT(page_copy_noexec))
20312+# define PAGE_READONLY_NOEXEC __pgprot(BTFIXUP_INT(page_readonly_noexec))
20313+#else
20314+# define PAGE_SHARED_NOEXEC PAGE_SHARED
20315+# define PAGE_COPY_NOEXEC PAGE_COPY
20316+# define PAGE_READONLY_NOEXEC PAGE_READONLY
20317+#endif
20318+
20319 extern unsigned long page_kernel;
20320
20321 #ifdef MODULE
20322diff -urNp linux-2.6.17.7/include/asm-sparc/pgtsrmmu.h linux-2.6.17.7/include/asm-sparc/pgtsrmmu.h
20323--- linux-2.6.17.7/include/asm-sparc/pgtsrmmu.h 2006-07-24 23:36:01.000000000 -0400
20324+++ linux-2.6.17.7/include/asm-sparc/pgtsrmmu.h 2006-08-01 20:29:47.000000000 -0400
20325@@ -115,6 +115,16 @@
20326 SRMMU_EXEC | SRMMU_REF)
20327 #define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \
20328 SRMMU_EXEC | SRMMU_REF)
20329+
20330+#ifdef CONFIG_PAX_PAGEEXEC
20331+#define SRMMU_PAGE_SHARED_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
20332+ SRMMU_WRITE | SRMMU_REF)
20333+#define SRMMU_PAGE_COPY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
20334+ SRMMU_REF)
20335+#define SRMMU_PAGE_RDONLY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
20336+ SRMMU_REF)
20337+#endif
20338+
20339 #define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \
20340 SRMMU_DIRTY | SRMMU_REF)
20341
20342diff -urNp linux-2.6.17.7/include/asm-sparc/uaccess.h linux-2.6.17.7/include/asm-sparc/uaccess.h
20343--- linux-2.6.17.7/include/asm-sparc/uaccess.h 2006-07-24 23:36:01.000000000 -0400
20344+++ linux-2.6.17.7/include/asm-sparc/uaccess.h 2006-08-01 20:29:47.000000000 -0400
20345@@ -41,7 +41,7 @@
20346 * No one can read/write anything from userland in the kernel space by setting
20347 * large size and address near to PAGE_OFFSET - a fault will break his intentions.
20348 */
20349-#define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; })
20350+#define __user_ok(addr, size) ({ (void)(size); (addr) < __STACK_TOP; })
20351 #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
20352 #define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
20353 #define access_ok(type, addr, size) \
20354diff -urNp linux-2.6.17.7/include/asm-sparc64/a.out.h linux-2.6.17.7/include/asm-sparc64/a.out.h
20355--- linux-2.6.17.7/include/asm-sparc64/a.out.h 2006-07-24 23:36:01.000000000 -0400
20356+++ linux-2.6.17.7/include/asm-sparc64/a.out.h 2006-08-01 20:29:47.000000000 -0400
20357@@ -98,7 +98,7 @@ struct relocation_info /* used when head
20358 #define STACK_TOP32 ((1UL << 32UL) - PAGE_SIZE)
20359 #define STACK_TOP64 (0x0000080000000000UL - (1UL << 32UL))
20360
20361-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
20362+#define __STACK_TOP (test_thread_flag(TIF_32BIT) ? \
20363 STACK_TOP32 : STACK_TOP64)
20364
20365 #endif
20366diff -urNp linux-2.6.17.7/include/asm-sparc64/elf.h linux-2.6.17.7/include/asm-sparc64/elf.h
20367--- linux-2.6.17.7/include/asm-sparc64/elf.h 2006-07-24 23:36:01.000000000 -0400
20368+++ linux-2.6.17.7/include/asm-sparc64/elf.h 2006-08-01 20:29:47.000000000 -0400
20369@@ -142,6 +142,16 @@ typedef struct {
20370 #define ELF_ET_DYN_BASE 0x0000010000000000UL
20371 #endif
20372
20373+#ifdef CONFIG_PAX_ASLR
20374+#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_32BIT) ? 0x10000UL : 0x100000UL)
20375+
20376+#define PAX_DELTA_MMAP_LSB(tsk) (PAGE_SHIFT + 1)
20377+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 14 : 28 )
20378+#define PAX_DELTA_EXEC_LSB(tsk) (PAGE_SHIFT + 1)
20379+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 14 : 28 )
20380+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20381+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 15 : 29 )
20382+#endif
20383
20384 /* This yields a mask that user programs can use to figure out what
20385 instruction set this cpu supports. */
20386diff -urNp linux-2.6.17.7/include/asm-sparc64/kmap_types.h linux-2.6.17.7/include/asm-sparc64/kmap_types.h
20387--- linux-2.6.17.7/include/asm-sparc64/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
20388+++ linux-2.6.17.7/include/asm-sparc64/kmap_types.h 2006-08-01 20:29:47.000000000 -0400
20389@@ -19,6 +19,7 @@ enum km_type {
20390 KM_IRQ1,
20391 KM_SOFTIRQ0,
20392 KM_SOFTIRQ1,
20393+ KM_CLEARPAGE,
20394 KM_TYPE_NR
20395 };
20396
20397diff -urNp linux-2.6.17.7/include/asm-sparc64/page.h linux-2.6.17.7/include/asm-sparc64/page.h
20398--- linux-2.6.17.7/include/asm-sparc64/page.h 2006-07-24 23:36:01.000000000 -0400
20399+++ linux-2.6.17.7/include/asm-sparc64/page.h 2006-08-01 20:29:47.000000000 -0400
20400@@ -142,6 +142,15 @@ typedef unsigned long pgprot_t;
20401 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
20402 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
20403
20404+#ifdef CONFIG_PAX_PAGEEXEC
20405+#ifdef CONFIG_PAX_MPROTECT
20406+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20407+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20408+#else
20409+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20410+#endif
20411+#endif
20412+
20413 #endif /* !(__KERNEL__) */
20414
20415 #include <asm-generic/page.h>
20416diff -urNp linux-2.6.17.7/include/asm-v850/kmap_types.h linux-2.6.17.7/include/asm-v850/kmap_types.h
20417--- linux-2.6.17.7/include/asm-v850/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
20418+++ linux-2.6.17.7/include/asm-v850/kmap_types.h 2006-08-01 20:29:48.000000000 -0400
20419@@ -13,6 +13,7 @@ enum km_type {
20420 KM_PTE1,
20421 KM_IRQ0,
20422 KM_IRQ1,
20423+ KM_CLEARPAGE,
20424 KM_TYPE_NR
20425 };
20426
20427diff -urNp linux-2.6.17.7/include/asm-x86_64/a.out.h linux-2.6.17.7/include/asm-x86_64/a.out.h
20428--- linux-2.6.17.7/include/asm-x86_64/a.out.h 2006-07-24 23:36:01.000000000 -0400
20429+++ linux-2.6.17.7/include/asm-x86_64/a.out.h 2006-08-01 20:29:48.000000000 -0400
20430@@ -21,7 +21,7 @@ struct exec
20431
20432 #ifdef __KERNEL__
20433 #include <linux/thread_info.h>
20434-#define STACK_TOP TASK_SIZE
20435+#define __STACK_TOP TASK_SIZE
20436 #endif
20437
20438 #endif /* __A_OUT_GNU_H__ */
20439diff -urNp linux-2.6.17.7/include/asm-x86_64/elf.h linux-2.6.17.7/include/asm-x86_64/elf.h
20440--- linux-2.6.17.7/include/asm-x86_64/elf.h 2006-07-24 23:36:01.000000000 -0400
20441+++ linux-2.6.17.7/include/asm-x86_64/elf.h 2006-08-01 20:29:48.000000000 -0400
20442@@ -90,6 +90,17 @@ typedef struct user_i387_struct elf_fpre
20443
20444 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
20445
20446+#ifdef CONFIG_PAX_ASLR
20447+#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_IA32) ? 0x08048000UL : 0x400000UL)
20448+
20449+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
20450+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
20451+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
20452+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
20453+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
20454+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
20455+#endif
20456+
20457 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
20458 now struct_user_regs, they are different). Assumes current is the process
20459 getting dumped. */
20460diff -urNp linux-2.6.17.7/include/asm-x86_64/ia32.h linux-2.6.17.7/include/asm-x86_64/ia32.h
20461--- linux-2.6.17.7/include/asm-x86_64/ia32.h 2006-07-24 23:36:01.000000000 -0400
20462+++ linux-2.6.17.7/include/asm-x86_64/ia32.h 2006-08-01 20:29:48.000000000 -0400
20463@@ -157,7 +157,13 @@ struct ustat32 {
20464 char f_fpack[6];
20465 };
20466
20467-#define IA32_STACK_TOP IA32_PAGE_OFFSET
20468+#ifdef CONFIG_PAX_RANDUSTACK
20469+#define IA32_DELTA_STACK (current->mm->delta_stack)
20470+#else
20471+#define IA32_DELTA_STACK 0UL
20472+#endif
20473+
20474+#define IA32_STACK_TOP (IA32_PAGE_OFFSET - IA32_DELTA_STACK)
20475
20476 #ifdef __KERNEL__
20477 struct user_desc;
20478diff -urNp linux-2.6.17.7/include/asm-x86_64/kmap_types.h linux-2.6.17.7/include/asm-x86_64/kmap_types.h
20479--- linux-2.6.17.7/include/asm-x86_64/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
20480+++ linux-2.6.17.7/include/asm-x86_64/kmap_types.h 2006-08-01 20:29:48.000000000 -0400
20481@@ -13,6 +13,7 @@ enum km_type {
20482 KM_IRQ1,
20483 KM_SOFTIRQ0,
20484 KM_SOFTIRQ1,
20485+ KM_CLEARPAGE,
20486 KM_TYPE_NR
20487 };
20488
20489diff -urNp linux-2.6.17.7/include/asm-x86_64/page.h linux-2.6.17.7/include/asm-x86_64/page.h
20490--- linux-2.6.17.7/include/asm-x86_64/page.h 2006-07-24 23:36:01.000000000 -0400
20491+++ linux-2.6.17.7/include/asm-x86_64/page.h 2006-08-01 20:29:48.000000000 -0400
20492@@ -134,6 +134,15 @@ typedef struct { unsigned long pgprot; }
20493 (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
20494 VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
20495
20496+#ifdef CONFIG_PAX_PAGEEXEC
20497+#ifdef CONFIG_PAX_MPROTECT
20498+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
20499+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20500+#else
20501+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
20502+#endif
20503+#endif
20504+
20505 #define __HAVE_ARCH_GATE_AREA 1
20506
20507 #endif /* __KERNEL__ */
20508diff -urNp linux-2.6.17.7/include/asm-x86_64/pgalloc.h linux-2.6.17.7/include/asm-x86_64/pgalloc.h
20509--- linux-2.6.17.7/include/asm-x86_64/pgalloc.h 2006-07-24 23:36:01.000000000 -0400
20510+++ linux-2.6.17.7/include/asm-x86_64/pgalloc.h 2006-08-01 20:29:48.000000000 -0400
20511@@ -7,7 +7,7 @@
20512 #include <linux/mm.h>
20513
20514 #define pmd_populate_kernel(mm, pmd, pte) \
20515- set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
20516+ set_pmd(pmd, __pmd(_KERNPG_TABLE | __pa(pte)))
20517 #define pud_populate(mm, pud, pmd) \
20518 set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)))
20519 #define pgd_populate(mm, pgd, pud) \
20520diff -urNp linux-2.6.17.7/include/asm-x86_64/pgtable.h linux-2.6.17.7/include/asm-x86_64/pgtable.h
20521--- linux-2.6.17.7/include/asm-x86_64/pgtable.h 2006-07-24 23:36:01.000000000 -0400
20522+++ linux-2.6.17.7/include/asm-x86_64/pgtable.h 2006-08-01 20:29:48.000000000 -0400
20523@@ -180,6 +180,10 @@ static inline pte_t ptep_get_and_clear_f
20524 #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
20525 #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
20526 #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
20527+
20528+#define PAGE_READONLY_NOEXEC PAGE_READONLY
20529+#define PAGE_SHARED_NOEXEC PAGE_SHARED
20530+
20531 #define __PAGE_KERNEL \
20532 (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
20533 #define __PAGE_KERNEL_EXEC \
20534@@ -268,7 +272,13 @@ static inline pte_t pfn_pte(unsigned lon
20535 #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
20536 static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
20537 static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
20538-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
20539+extern inline int pte_exec(pte_t pte)
20540+{
20541+ if (__supported_pte_mask & _PAGE_NX)
20542+ return pte_val(pte) & _PAGE_NX;
20543+ else
20544+ return pte_val(pte) & _PAGE_USER;
20545+}
20546 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
20547 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
20548 static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
20549@@ -276,12 +286,26 @@ static inline int pte_file(pte_t pte) {
20550 static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_PSE; }
20551
20552 static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
20553-static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
20554+extern inline pte_t pte_exprotect(pte_t pte)
20555+{
20556+ if (__supported_pte_mask & _PAGE_NX)
20557+ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_NX));
20558+ else
20559+ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER));
20560+ return pte;
20561+}
20562 static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
20563 static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
20564 static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
20565 static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
20566-static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
20567+extern inline pte_t pte_mkexec(pte_t pte)
20568+{
20569+ if (__supported_pte_mask & _PAGE_NX)
20570+ set_pte(&pte, __pte(pte_val(pte) | _PAGE_NX));
20571+ else
20572+ set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER));
20573+ return pte;
20574+}
20575 static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
20576 static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
20577 static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
20578diff -urNp linux-2.6.17.7/include/asm-x86_64/system.h linux-2.6.17.7/include/asm-x86_64/system.h
20579--- linux-2.6.17.7/include/asm-x86_64/system.h 2006-07-24 23:36:01.000000000 -0400
20580+++ linux-2.6.17.7/include/asm-x86_64/system.h 2006-08-01 20:29:48.000000000 -0400
20581@@ -366,6 +366,6 @@ static inline unsigned long __cmpxchg(vo
20582
20583 void cpu_idle_wait(void);
20584
20585-extern unsigned long arch_align_stack(unsigned long sp);
20586+#define arch_align_stack(x) (x)
20587
20588 #endif
20589diff -urNp linux-2.6.17.7/include/asm-xtensa/kmap_types.h linux-2.6.17.7/include/asm-xtensa/kmap_types.h
20590--- linux-2.6.17.7/include/asm-xtensa/kmap_types.h 2006-07-24 23:36:01.000000000 -0400
20591+++ linux-2.6.17.7/include/asm-xtensa/kmap_types.h 2006-08-01 20:29:48.000000000 -0400
20592@@ -25,6 +25,7 @@ enum km_type {
20593 KM_IRQ1,
20594 KM_SOFTIRQ0,
20595 KM_SOFTIRQ1,
20596+ KM_CLEARPAGE,
20597 KM_TYPE_NR
20598 };
20599
20600diff -urNp linux-2.6.17.7/include/linux/a.out.h linux-2.6.17.7/include/linux/a.out.h
20601--- linux-2.6.17.7/include/linux/a.out.h 2006-07-24 23:36:01.000000000 -0400
20602+++ linux-2.6.17.7/include/linux/a.out.h 2006-08-01 20:29:48.000000000 -0400
20603@@ -7,6 +7,16 @@
20604
20605 #include <asm/a.out.h>
20606
20607+#ifdef CONFIG_PAX_RANDUSTACK
20608+#define __DELTA_STACK (current->mm->delta_stack)
20609+#else
20610+#define __DELTA_STACK 0UL
20611+#endif
20612+
20613+#ifndef STACK_TOP
20614+#define STACK_TOP (__STACK_TOP - __DELTA_STACK)
20615+#endif
20616+
20617 #endif /* __STRUCT_EXEC_OVERRIDE__ */
20618
20619 /* these go in the N_MACHTYPE field */
20620@@ -37,6 +47,14 @@ enum machine_type {
20621 M_MIPS2 = 152 /* MIPS R6000/R4000 binary */
20622 };
20623
20624+/* Constants for the N_FLAGS field */
20625+#define F_PAX_PAGEEXEC 1 /* Paging based non-executable pages */
20626+#define F_PAX_EMUTRAMP 2 /* Emulate trampolines */
20627+#define F_PAX_MPROTECT 4 /* Restrict mprotect() */
20628+#define F_PAX_RANDMMAP 8 /* Randomize mmap() base */
20629+/*#define F_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */
20630+#define F_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */
20631+
20632 #if !defined (N_MAGIC)
20633 #define N_MAGIC(exec) ((exec).a_info & 0xffff)
20634 #endif
20635diff -urNp linux-2.6.17.7/include/linux/binfmts.h linux-2.6.17.7/include/linux/binfmts.h
20636--- linux-2.6.17.7/include/linux/binfmts.h 2006-07-24 23:36:01.000000000 -0400
20637+++ linux-2.6.17.7/include/linux/binfmts.h 2006-08-01 20:29:48.000000000 -0400
20638@@ -7,10 +7,10 @@ struct pt_regs;
20639
20640 /*
20641 * MAX_ARG_PAGES defines the number of pages allocated for arguments
20642- * and envelope for the new program. 32 should suffice, this gives
20643- * a maximum env+arg of 128kB w/4KB pages!
20644+ * and envelope for the new program. 33 should suffice, this gives
20645+ * a maximum env+arg of 132kB w/4KB pages!
20646 */
20647-#define MAX_ARG_PAGES 32
20648+#define MAX_ARG_PAGES 33
20649
20650 /* sizeof(linux_binprm->buf) */
20651 #define BINPRM_BUF_SIZE 128
20652@@ -38,6 +38,7 @@ struct linux_binprm{
20653 unsigned interp_flags;
20654 unsigned interp_data;
20655 unsigned long loader, exec;
20656+ int misc;
20657 };
20658
20659 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
20660@@ -87,5 +88,8 @@ extern void compute_creds(struct linux_b
20661 extern int do_coredump(long signr, int exit_code, struct pt_regs * regs);
20662 extern int set_binfmt(struct linux_binfmt *new);
20663
20664+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp);
20665+void pax_report_insns(void *pc, void *sp);
20666+
20667 #endif /* __KERNEL__ */
20668 #endif /* _LINUX_BINFMTS_H */
20669diff -urNp linux-2.6.17.7/include/linux/capability.h linux-2.6.17.7/include/linux/capability.h
20670--- linux-2.6.17.7/include/linux/capability.h 2006-07-24 23:36:01.000000000 -0400
20671+++ linux-2.6.17.7/include/linux/capability.h 2006-08-01 20:29:48.000000000 -0400
20672@@ -358,6 +358,7 @@ static inline kernel_cap_t cap_invert(ke
20673 #define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)
20674
20675 int capable(int cap);
20676+int capable_nolog(int cap);
20677 int __capable(struct task_struct *t, int cap);
20678
20679 #endif /* __KERNEL__ */
20680diff -urNp linux-2.6.17.7/include/linux/elf.h linux-2.6.17.7/include/linux/elf.h
20681--- linux-2.6.17.7/include/linux/elf.h 2006-07-24 23:36:01.000000000 -0400
20682+++ linux-2.6.17.7/include/linux/elf.h 2006-08-01 20:29:48.000000000 -0400
20683@@ -5,6 +5,10 @@
20684 #include <linux/auxvec.h>
20685 #include <asm/elf.h>
20686
20687+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
20688+#undef elf_read_implies_exec
20689+#endif
20690+
20691 #ifndef elf_read_implies_exec
20692 /* Executables for which elf_read_implies_exec() returns TRUE will
20693 have the READ_IMPLIES_EXEC personality flag set automatically.
20694@@ -46,6 +50,16 @@ typedef __s64 Elf64_Sxword;
20695
20696 #define PT_GNU_STACK (PT_LOOS + 0x474e551)
20697
20698+#define PT_PAX_FLAGS (PT_LOOS + 0x5041580)
20699+
20700+/* Constants for the e_flags field */
20701+#define EF_PAX_PAGEEXEC 1 /* Paging based non-executable pages */
20702+#define EF_PAX_EMUTRAMP 2 /* Emulate trampolines */
20703+#define EF_PAX_MPROTECT 4 /* Restrict mprotect() */
20704+#define EF_PAX_RANDMMAP 8 /* Randomize mmap() base */
20705+/*#define EF_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */
20706+#define EF_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */
20707+
20708 /* These constants define the different elf file types */
20709 #define ET_NONE 0
20710 #define ET_REL 1
20711@@ -138,6 +152,8 @@ typedef __s64 Elf64_Sxword;
20712 #define DT_DEBUG 21
20713 #define DT_TEXTREL 22
20714 #define DT_JMPREL 23
20715+#define DT_FLAGS 30
20716+ #define DF_TEXTREL 0x00000004
20717 #define DT_LOPROC 0x70000000
20718 #define DT_HIPROC 0x7fffffff
20719
20720@@ -267,6 +283,19 @@ typedef struct elf64_hdr {
20721 #define PF_W 0x2
20722 #define PF_X 0x1
20723
20724+#define PF_PAGEEXEC (1U << 4) /* Enable PAGEEXEC */
20725+#define PF_NOPAGEEXEC (1U << 5) /* Disable PAGEEXEC */
20726+#define PF_SEGMEXEC (1U << 6) /* Enable SEGMEXEC */
20727+#define PF_NOSEGMEXEC (1U << 7) /* Disable SEGMEXEC */
20728+#define PF_MPROTECT (1U << 8) /* Enable MPROTECT */
20729+#define PF_NOMPROTECT (1U << 9) /* Disable MPROTECT */
20730+/*#define PF_RANDEXEC (1U << 10)*/ /* Enable RANDEXEC */
20731+/*#define PF_NORANDEXEC (1U << 11)*/ /* Disable RANDEXEC */
20732+#define PF_EMUTRAMP (1U << 12) /* Enable EMUTRAMP */
20733+#define PF_NOEMUTRAMP (1U << 13) /* Disable EMUTRAMP */
20734+#define PF_RANDMMAP (1U << 14) /* Enable RANDMMAP */
20735+#define PF_NORANDMMAP (1U << 15) /* Disable RANDMMAP */
20736+
20737 typedef struct elf32_phdr{
20738 Elf32_Word p_type;
20739 Elf32_Off p_offset;
20740@@ -359,6 +388,8 @@ typedef struct elf64_shdr {
20741 #define EI_OSABI 7
20742 #define EI_PAD 8
20743
20744+#define EI_PAX 14
20745+
20746 #define ELFMAG0 0x7f /* EI_MAG */
20747 #define ELFMAG1 'E'
20748 #define ELFMAG2 'L'
20749@@ -415,6 +446,7 @@ extern Elf32_Dyn _DYNAMIC [];
20750 #define elfhdr elf32_hdr
20751 #define elf_phdr elf32_phdr
20752 #define elf_note elf32_note
20753+#define elf_dyn Elf32_Dyn
20754
20755 #else
20756
20757@@ -422,6 +454,7 @@ extern Elf64_Dyn _DYNAMIC [];
20758 #define elfhdr elf64_hdr
20759 #define elf_phdr elf64_phdr
20760 #define elf_note elf64_note
20761+#define elf_dyn Elf64_Dyn
20762
20763 #endif
20764
20765diff -urNp linux-2.6.17.7/include/linux/gracl.h linux-2.6.17.7/include/linux/gracl.h
20766--- linux-2.6.17.7/include/linux/gracl.h 1969-12-31 19:00:00.000000000 -0500
20767+++ linux-2.6.17.7/include/linux/gracl.h 2006-08-01 20:29:48.000000000 -0400
20768@@ -0,0 +1,316 @@
20769+#ifndef GR_ACL_H
20770+#define GR_ACL_H
20771+
20772+#include <linux/grdefs.h>
20773+#include <linux/resource.h>
20774+#include <linux/dcache.h>
20775+#include <asm/resource.h>
20776+
20777+/* Major status information */
20778+
20779+#define GR_VERSION "grsecurity 2.1.9"
20780+#define GRSECURITY_VERSION 0x219
20781+
20782+enum {
20783+
20784+ SHUTDOWN = 0,
20785+ ENABLE = 1,
20786+ SPROLE = 2,
20787+ RELOAD = 3,
20788+ SEGVMOD = 4,
20789+ STATUS = 5,
20790+ UNSPROLE = 6,
20791+ PASSSET = 7,
20792+ SPROLEPAM = 8
20793+};
20794+
20795+/* Password setup definitions
20796+ * kernel/grhash.c */
20797+enum {
20798+ GR_PW_LEN = 128,
20799+ GR_SALT_LEN = 16,
20800+ GR_SHA_LEN = 32,
20801+};
20802+
20803+enum {
20804+ GR_SPROLE_LEN = 64,
20805+};
20806+
20807+#define GR_NLIMITS (RLIMIT_LOCKS + 2)
20808+
20809+/* Begin Data Structures */
20810+
20811+struct sprole_pw {
20812+ unsigned char *rolename;
20813+ unsigned char salt[GR_SALT_LEN];
20814+ unsigned char sum[GR_SHA_LEN]; /* 256-bit SHA hash of the password */
20815+};
20816+
20817+struct name_entry {
20818+ __u32 key;
20819+ ino_t inode;
20820+ dev_t device;
20821+ char *name;
20822+ __u16 len;
20823+ struct name_entry *prev;
20824+ struct name_entry *next;
20825+};
20826+
20827+struct inodev_entry {
20828+ struct name_entry *nentry;
20829+ struct inodev_entry *prev;
20830+ struct inodev_entry *next;
20831+};
20832+
20833+struct acl_role_db {
20834+ struct acl_role_label **r_hash;
20835+ __u32 r_size;
20836+};
20837+
20838+struct inodev_db {
20839+ struct inodev_entry **i_hash;
20840+ __u32 i_size;
20841+};
20842+
20843+struct name_db {
20844+ struct name_entry **n_hash;
20845+ __u32 n_size;
20846+};
20847+
20848+struct crash_uid {
20849+ uid_t uid;
20850+ unsigned long expires;
20851+};
20852+
20853+struct gr_hash_struct {
20854+ void **table;
20855+ void **nametable;
20856+ void *first;
20857+ __u32 table_size;
20858+ __u32 used_size;
20859+ int type;
20860+};
20861+
20862+/* Userspace Grsecurity ACL data structures */
20863+
20864+struct acl_subject_label {
20865+ char *filename;
20866+ ino_t inode;
20867+ dev_t device;
20868+ __u32 mode;
20869+ __u32 cap_mask;
20870+ __u32 cap_lower;
20871+
20872+ struct rlimit res[GR_NLIMITS];
20873+ __u16 resmask;
20874+
20875+ __u8 user_trans_type;
20876+ __u8 group_trans_type;
20877+ uid_t *user_transitions;
20878+ gid_t *group_transitions;
20879+ __u16 user_trans_num;
20880+ __u16 group_trans_num;
20881+
20882+ __u32 ip_proto[8];
20883+ __u32 ip_type;
20884+ struct acl_ip_label **ips;
20885+ __u32 ip_num;
20886+
20887+ __u32 crashes;
20888+ unsigned long expires;
20889+
20890+ struct acl_subject_label *parent_subject;
20891+ struct gr_hash_struct *hash;
20892+ struct acl_subject_label *prev;
20893+ struct acl_subject_label *next;
20894+
20895+ struct acl_object_label **obj_hash;
20896+ __u32 obj_hash_size;
20897+ __u16 pax_flags;
20898+};
20899+
20900+struct role_allowed_ip {
20901+ __u32 addr;
20902+ __u32 netmask;
20903+
20904+ struct role_allowed_ip *prev;
20905+ struct role_allowed_ip *next;
20906+};
20907+
20908+struct role_transition {
20909+ char *rolename;
20910+
20911+ struct role_transition *prev;
20912+ struct role_transition *next;
20913+};
20914+
20915+struct acl_role_label {
20916+ char *rolename;
20917+ uid_t uidgid;
20918+ __u16 roletype;
20919+
20920+ __u16 auth_attempts;
20921+ unsigned long expires;
20922+
20923+ struct acl_subject_label *root_label;
20924+ struct gr_hash_struct *hash;
20925+
20926+ struct acl_role_label *prev;
20927+ struct acl_role_label *next;
20928+
20929+ struct role_transition *transitions;
20930+ struct role_allowed_ip *allowed_ips;
20931+ uid_t *domain_children;
20932+ __u16 domain_child_num;
20933+
20934+ struct acl_subject_label **subj_hash;
20935+ __u32 subj_hash_size;
20936+};
20937+
20938+struct user_acl_role_db {
20939+ struct acl_role_label **r_table;
20940+ __u32 num_pointers; /* Number of allocations to track */
20941+ __u32 num_roles; /* Number of roles */
20942+ __u32 num_domain_children; /* Number of domain children */
20943+ __u32 num_subjects; /* Number of subjects */
20944+ __u32 num_objects; /* Number of objects */
20945+};
20946+
20947+struct acl_object_label {
20948+ char *filename;
20949+ ino_t inode;
20950+ dev_t device;
20951+ __u32 mode;
20952+
20953+ struct acl_subject_label *nested;
20954+ struct acl_object_label *globbed;
20955+
20956+ /* next two structures not used */
20957+
20958+ struct acl_object_label *prev;
20959+ struct acl_object_label *next;
20960+};
20961+
20962+struct acl_ip_label {
20963+ char *iface;
20964+ __u32 addr;
20965+ __u32 netmask;
20966+ __u16 low, high;
20967+ __u8 mode;
20968+ __u32 type;
20969+ __u32 proto[8];
20970+
20971+ /* next two structures not used */
20972+
20973+ struct acl_ip_label *prev;
20974+ struct acl_ip_label *next;
20975+};
20976+
20977+struct gr_arg {
20978+ struct user_acl_role_db role_db;
20979+ unsigned char pw[GR_PW_LEN];
20980+ unsigned char salt[GR_SALT_LEN];
20981+ unsigned char sum[GR_SHA_LEN];
20982+ unsigned char sp_role[GR_SPROLE_LEN];
20983+ struct sprole_pw *sprole_pws;
20984+ dev_t segv_device;
20985+ ino_t segv_inode;
20986+ uid_t segv_uid;
20987+ __u16 num_sprole_pws;
20988+ __u16 mode;
20989+};
20990+
20991+struct gr_arg_wrapper {
20992+ struct gr_arg *arg;
20993+ __u32 version;
20994+ __u32 size;
20995+};
20996+
20997+struct subject_map {
20998+ struct acl_subject_label *user;
20999+ struct acl_subject_label *kernel;
21000+ struct subject_map *prev;
21001+ struct subject_map *next;
21002+};
21003+
21004+struct acl_subj_map_db {
21005+ struct subject_map **s_hash;
21006+ __u32 s_size;
21007+};
21008+
21009+/* End Data Structures Section */
21010+
21011+/* Hash functions generated by empirical testing by Brad Spengler
21012+ Makes good use of the low bits of the inode. Generally 0-1 times
21013+ in loop for successful match. 0-3 for unsuccessful match.
21014+ Shift/add algorithm with modulus of table size and an XOR*/
21015+
21016+static __inline__ unsigned int
21017+rhash(const uid_t uid, const __u16 type, const unsigned int sz)
21018+{
21019+ return (((uid << type) + (uid ^ type)) % sz);
21020+}
21021+
21022+ static __inline__ unsigned int
21023+shash(const struct acl_subject_label *userp, const unsigned int sz)
21024+{
21025+ return ((const unsigned long)userp % sz);
21026+}
21027+
21028+static __inline__ unsigned int
21029+fhash(const ino_t ino, const dev_t dev, const unsigned int sz)
21030+{
21031+ return (((ino + dev) ^ ((ino << 13) + (ino << 23) + (dev << 9))) % sz);
21032+}
21033+
21034+static __inline__ unsigned int
21035+nhash(const char *name, const __u16 len, const unsigned int sz)
21036+{
21037+ return full_name_hash(name, len) % sz;
21038+}
21039+
21040+#define FOR_EACH_ROLE_START(role,iter) \
21041+ role = NULL; \
21042+ iter = 0; \
21043+ while (iter < acl_role_set.r_size) { \
21044+ if (role == NULL) \
21045+ role = acl_role_set.r_hash[iter]; \
21046+ if (role == NULL) { \
21047+ iter++; \
21048+ continue; \
21049+ }
21050+
21051+#define FOR_EACH_ROLE_END(role,iter) \
21052+ role = role->next; \
21053+ if (role == NULL) \
21054+ iter++; \
21055+ }
21056+
21057+#define FOR_EACH_SUBJECT_START(role,subj,iter) \
21058+ subj = NULL; \
21059+ iter = 0; \
21060+ while (iter < role->subj_hash_size) { \
21061+ if (subj == NULL) \
21062+ subj = role->subj_hash[iter]; \
21063+ if (subj == NULL) { \
21064+ iter++; \
21065+ continue; \
21066+ }
21067+
21068+#define FOR_EACH_SUBJECT_END(subj,iter) \
21069+ subj = subj->next; \
21070+ if (subj == NULL) \
21071+ iter++; \
21072+ }
21073+
21074+
21075+#define FOR_EACH_NESTED_SUBJECT_START(role,subj) \
21076+ subj = role->hash->first; \
21077+ while (subj != NULL) {
21078+
21079+#define FOR_EACH_NESTED_SUBJECT_END(subj) \
21080+ subj = subj->next; \
21081+ }
21082+
21083+#endif
21084+
21085diff -urNp linux-2.6.17.7/include/linux/gralloc.h linux-2.6.17.7/include/linux/gralloc.h
21086--- linux-2.6.17.7/include/linux/gralloc.h 1969-12-31 19:00:00.000000000 -0500
21087+++ linux-2.6.17.7/include/linux/gralloc.h 2006-08-01 20:29:48.000000000 -0400
21088@@ -0,0 +1,8 @@
21089+#ifndef __GRALLOC_H
21090+#define __GRALLOC_H
21091+
21092+void acl_free_all(void);
21093+int acl_alloc_stack_init(unsigned long size);
21094+void *acl_alloc(unsigned long len);
21095+
21096+#endif
21097diff -urNp linux-2.6.17.7/include/linux/grdefs.h linux-2.6.17.7/include/linux/grdefs.h
21098--- linux-2.6.17.7/include/linux/grdefs.h 1969-12-31 19:00:00.000000000 -0500
21099+++ linux-2.6.17.7/include/linux/grdefs.h 2006-08-01 20:29:48.000000000 -0400
21100@@ -0,0 +1,131 @@
21101+#ifndef GRDEFS_H
21102+#define GRDEFS_H
21103+
21104+/* Begin grsecurity status declarations */
21105+
21106+enum {
21107+ GR_READY = 0x01,
21108+ GR_STATUS_INIT = 0x00 // disabled state
21109+};
21110+
21111+/* Begin ACL declarations */
21112+
21113+/* Role flags */
21114+
21115+enum {
21116+ GR_ROLE_USER = 0x0001,
21117+ GR_ROLE_GROUP = 0x0002,
21118+ GR_ROLE_DEFAULT = 0x0004,
21119+ GR_ROLE_SPECIAL = 0x0008,
21120+ GR_ROLE_AUTH = 0x0010,
21121+ GR_ROLE_NOPW = 0x0020,
21122+ GR_ROLE_GOD = 0x0040,
21123+ GR_ROLE_LEARN = 0x0080,
21124+ GR_ROLE_TPE = 0x0100,
21125+ GR_ROLE_DOMAIN = 0x0200,
21126+ GR_ROLE_PAM = 0x0400
21127+};
21128+
21129+/* ACL Subject and Object mode flags */
21130+enum {
21131+ GR_DELETED = 0x80000000
21132+};
21133+
21134+/* ACL Object-only mode flags */
21135+enum {
21136+ GR_READ = 0x00000001,
21137+ GR_APPEND = 0x00000002,
21138+ GR_WRITE = 0x00000004,
21139+ GR_EXEC = 0x00000008,
21140+ GR_FIND = 0x00000010,
21141+ GR_INHERIT = 0x00000020,
21142+ GR_SETID = 0x00000040,
21143+ GR_CREATE = 0x00000080,
21144+ GR_DELETE = 0x00000100,
21145+ GR_LINK = 0x00000200,
21146+ GR_AUDIT_READ = 0x00000400,
21147+ GR_AUDIT_APPEND = 0x00000800,
21148+ GR_AUDIT_WRITE = 0x00001000,
21149+ GR_AUDIT_EXEC = 0x00002000,
21150+ GR_AUDIT_FIND = 0x00004000,
21151+ GR_AUDIT_INHERIT= 0x00008000,
21152+ GR_AUDIT_SETID = 0x00010000,
21153+ GR_AUDIT_CREATE = 0x00020000,
21154+ GR_AUDIT_DELETE = 0x00040000,
21155+ GR_AUDIT_LINK = 0x00080000,
21156+ GR_PTRACERD = 0x00100000,
21157+ GR_NOPTRACE = 0x00200000,
21158+ GR_SUPPRESS = 0x00400000,
21159+ GR_NOLEARN = 0x00800000
21160+};
21161+
21162+#define GR_AUDITS (GR_AUDIT_READ | GR_AUDIT_WRITE | GR_AUDIT_APPEND | GR_AUDIT_EXEC | \
21163+ GR_AUDIT_FIND | GR_AUDIT_INHERIT | GR_AUDIT_SETID | \
21164+ GR_AUDIT_CREATE | GR_AUDIT_DELETE | GR_AUDIT_LINK)
21165+
21166+/* ACL subject-only mode flags */
21167+enum {
21168+ GR_KILL = 0x00000001,
21169+ GR_VIEW = 0x00000002,
21170+ GR_PROTECTED = 0x00000004,
21171+ GR_LEARN = 0x00000008,
21172+ GR_OVERRIDE = 0x00000010,
21173+ /* just a placeholder, this mode is only used in userspace */
21174+ GR_DUMMY = 0x00000020,
21175+ GR_PROTSHM = 0x00000040,
21176+ GR_KILLPROC = 0x00000080,
21177+ GR_KILLIPPROC = 0x00000100,
21178+ /* just a placeholder, this mode is only used in userspace */
21179+ GR_NOTROJAN = 0x00000200,
21180+ GR_PROTPROCFD = 0x00000400,
21181+ GR_PROCACCT = 0x00000800,
21182+ GR_RELAXPTRACE = 0x00001000,
21183+ GR_NESTED = 0x00002000,
21184+ GR_INHERITLEARN = 0x00004000,
21185+ GR_PROCFIND = 0x00008000,
21186+ GR_POVERRIDE = 0x00010000,
21187+ GR_KERNELAUTH = 0x00020000,
21188+};
21189+
21190+enum {
21191+ GR_PAX_ENABLE_SEGMEXEC = 0x0001,
21192+ GR_PAX_ENABLE_PAGEEXEC = 0x0002,
21193+ GR_PAX_ENABLE_MPROTECT = 0x0004,
21194+ GR_PAX_ENABLE_RANDMMAP = 0x0008,
21195+ GR_PAX_ENABLE_EMUTRAMP = 0x0010,
21196+ GR_PAX_DISABLE_SEGMEXEC = 0x8001,
21197+ GR_PAX_DISABLE_PAGEEXEC = 0x8002,
21198+ GR_PAX_DISABLE_MPROTECT = 0x8004,
21199+ GR_PAX_DISABLE_RANDMMAP = 0x8008,
21200+ GR_PAX_DISABLE_EMUTRAMP = 0x8010,
21201+};
21202+
21203+enum {
21204+ GR_ID_USER = 0x01,
21205+ GR_ID_GROUP = 0x02,
21206+};
21207+
21208+enum {
21209+ GR_ID_ALLOW = 0x01,
21210+ GR_ID_DENY = 0x02,
21211+};
21212+
21213+#define GR_CRASH_RES 11
21214+#define GR_UIDTABLE_MAX 500
21215+
21216+/* begin resource learning section */
21217+enum {
21218+ GR_RLIM_CPU_BUMP = 60,
21219+ GR_RLIM_FSIZE_BUMP = 50000,
21220+ GR_RLIM_DATA_BUMP = 10000,
21221+ GR_RLIM_STACK_BUMP = 1000,
21222+ GR_RLIM_CORE_BUMP = 10000,
21223+ GR_RLIM_RSS_BUMP = 500000,
21224+ GR_RLIM_NPROC_BUMP = 1,
21225+ GR_RLIM_NOFILE_BUMP = 5,
21226+ GR_RLIM_MEMLOCK_BUMP = 50000,
21227+ GR_RLIM_AS_BUMP = 500000,
21228+ GR_RLIM_LOCKS_BUMP = 2
21229+};
21230+
21231+#endif
21232diff -urNp linux-2.6.17.7/include/linux/grinternal.h linux-2.6.17.7/include/linux/grinternal.h
21233--- linux-2.6.17.7/include/linux/grinternal.h 1969-12-31 19:00:00.000000000 -0500
21234+++ linux-2.6.17.7/include/linux/grinternal.h 2006-08-01 20:29:48.000000000 -0400
21235@@ -0,0 +1,211 @@
21236+#ifndef __GRINTERNAL_H
21237+#define __GRINTERNAL_H
21238+
21239+#ifdef CONFIG_GRKERNSEC
21240+
21241+#include <linux/fs.h>
21242+#include <linux/gracl.h>
21243+#include <linux/grdefs.h>
21244+#include <linux/grmsg.h>
21245+
21246+extern void gr_add_learn_entry(const char *fmt, ...);
21247+extern __u32 gr_search_file(const struct dentry *dentry, const __u32 mode,
21248+ const struct vfsmount *mnt);
21249+extern __u32 gr_check_create(const struct dentry *new_dentry,
21250+ const struct dentry *parent,
21251+ const struct vfsmount *mnt, const __u32 mode);
21252+extern int gr_check_protected_task(const struct task_struct *task);
21253+extern __u32 to_gr_audit(const __u32 reqmode);
21254+extern int gr_set_acls(const int type);
21255+
21256+extern int gr_acl_is_enabled(void);
21257+extern char gr_roletype_to_char(void);
21258+
21259+extern void gr_handle_alertkill(struct task_struct *task);
21260+extern char *gr_to_filename(const struct dentry *dentry,
21261+ const struct vfsmount *mnt);
21262+extern char *gr_to_filename1(const struct dentry *dentry,
21263+ const struct vfsmount *mnt);
21264+extern char *gr_to_filename2(const struct dentry *dentry,
21265+ const struct vfsmount *mnt);
21266+extern char *gr_to_filename3(const struct dentry *dentry,
21267+ const struct vfsmount *mnt);
21268+
21269+extern int grsec_enable_link;
21270+extern int grsec_enable_fifo;
21271+extern int grsec_enable_execve;
21272+extern int grsec_enable_shm;
21273+extern int grsec_enable_execlog;
21274+extern int grsec_enable_signal;
21275+extern int grsec_enable_forkfail;
21276+extern int grsec_enable_time;
21277+extern int grsec_enable_chroot_shmat;
21278+extern int grsec_enable_chroot_findtask;
21279+extern int grsec_enable_chroot_mount;
21280+extern int grsec_enable_chroot_double;
21281+extern int grsec_enable_chroot_pivot;
21282+extern int grsec_enable_chroot_chdir;
21283+extern int grsec_enable_chroot_chmod;
21284+extern int grsec_enable_chroot_mknod;
21285+extern int grsec_enable_chroot_fchdir;
21286+extern int grsec_enable_chroot_nice;
21287+extern int grsec_enable_chroot_execlog;
21288+extern int grsec_enable_chroot_caps;
21289+extern int grsec_enable_chroot_sysctl;
21290+extern int grsec_enable_chroot_unix;
21291+extern int grsec_enable_tpe;
21292+extern int grsec_tpe_gid;
21293+extern int grsec_enable_tpe_all;
21294+extern int grsec_enable_sidcaps;
21295+extern int grsec_enable_randpid;
21296+extern int grsec_enable_socket_all;
21297+extern int grsec_socket_all_gid;
21298+extern int grsec_enable_socket_client;
21299+extern int grsec_socket_client_gid;
21300+extern int grsec_enable_socket_server;
21301+extern int grsec_socket_server_gid;
21302+extern int grsec_audit_gid;
21303+extern int grsec_enable_group;
21304+extern int grsec_enable_audit_ipc;
21305+extern int grsec_enable_audit_textrel;
21306+extern int grsec_enable_mount;
21307+extern int grsec_enable_chdir;
21308+extern int grsec_resource_logging;
21309+extern int grsec_lock;
21310+
21311+extern struct task_struct *child_reaper;
21312+
21313+extern spinlock_t grsec_alert_lock;
21314+extern unsigned long grsec_alert_wtime;
21315+extern unsigned long grsec_alert_fyet;
21316+
21317+extern spinlock_t grsec_audit_lock;
21318+
21319+extern rwlock_t grsec_exec_file_lock;
21320+
21321+#define gr_task_fullpath(tsk) (tsk->exec_file ? \
21322+ gr_to_filename2(tsk->exec_file->f_dentry, \
21323+ tsk->exec_file->f_vfsmnt) : "/")
21324+
21325+#define gr_parent_task_fullpath(tsk) (tsk->parent->exec_file ? \
21326+ gr_to_filename3(tsk->parent->exec_file->f_dentry, \
21327+ tsk->parent->exec_file->f_vfsmnt) : "/")
21328+
21329+#define gr_task_fullpath0(tsk) (tsk->exec_file ? \
21330+ gr_to_filename(tsk->exec_file->f_dentry, \
21331+ tsk->exec_file->f_vfsmnt) : "/")
21332+
21333+#define gr_parent_task_fullpath0(tsk) (tsk->parent->exec_file ? \
21334+ gr_to_filename1(tsk->parent->exec_file->f_dentry, \
21335+ tsk->parent->exec_file->f_vfsmnt) : "/")
21336+
21337+#define proc_is_chrooted(tsk_a) ((tsk_a->pid > 1) && (tsk_a->fs != NULL) && \
21338+ ((tsk_a->fs->root->d_inode->i_sb->s_dev != \
21339+ child_reaper->fs->root->d_inode->i_sb->s_dev) || \
21340+ (tsk_a->fs->root->d_inode->i_ino != \
21341+ child_reaper->fs->root->d_inode->i_ino)))
21342+
21343+#define have_same_root(tsk_a,tsk_b) ((tsk_a->fs != NULL) && (tsk_b->fs != NULL) && \
21344+ (tsk_a->fs->root->d_inode->i_sb->s_dev == \
21345+ tsk_b->fs->root->d_inode->i_sb->s_dev) && \
21346+ (tsk_a->fs->root->d_inode->i_ino == \
21347+ tsk_b->fs->root->d_inode->i_ino))
21348+
21349+#define DEFAULTSECARGS(task) gr_task_fullpath(task), task->comm, \
21350+ task->pid, task->uid, \
21351+ task->euid, task->gid, task->egid, \
21352+ gr_parent_task_fullpath(task), \
21353+ task->parent->comm, task->parent->pid, \
21354+ task->parent->uid, task->parent->euid, \
21355+ task->parent->gid, task->parent->egid
21356+
21357+#define GR_CHROOT_CAPS ( \
21358+ CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | CAP_TO_MASK(CAP_NET_ADMIN) | \
21359+ CAP_TO_MASK(CAP_SYS_MODULE) | CAP_TO_MASK(CAP_SYS_RAWIO) | \
21360+ CAP_TO_MASK(CAP_SYS_PACCT) | CAP_TO_MASK(CAP_SYS_ADMIN) | \
21361+ CAP_TO_MASK(CAP_SYS_BOOT) | CAP_TO_MASK(CAP_SYS_TIME) | \
21362+ CAP_TO_MASK(CAP_NET_RAW) | CAP_TO_MASK(CAP_SYS_TTY_CONFIG) | \
21363+ CAP_TO_MASK(CAP_IPC_OWNER))
21364+
21365+#define security_learn(normal_msg,args...) \
21366+({ \
21367+ read_lock(&grsec_exec_file_lock); \
21368+ gr_add_learn_entry(normal_msg "\n", ## args); \
21369+ read_unlock(&grsec_exec_file_lock); \
21370+})
21371+
21372+enum {
21373+ GR_DO_AUDIT,
21374+ GR_DONT_AUDIT,
21375+ GR_DONT_AUDIT_GOOD
21376+};
21377+
21378+enum {
21379+ GR_TTYSNIFF,
21380+ GR_RBAC,
21381+ GR_RBAC_STR,
21382+ GR_STR_RBAC,
21383+ GR_RBAC_MODE2,
21384+ GR_RBAC_MODE3,
21385+ GR_FILENAME,
21386+ GR_NOARGS,
21387+ GR_ONE_INT,
21388+ GR_ONE_INT_TWO_STR,
21389+ GR_ONE_STR,
21390+ GR_STR_INT,
21391+ GR_TWO_INT,
21392+ GR_THREE_INT,
21393+ GR_FIVE_INT_TWO_STR,
21394+ GR_TWO_STR,
21395+ GR_THREE_STR,
21396+ GR_FOUR_STR,
21397+ GR_STR_FILENAME,
21398+ GR_FILENAME_STR,
21399+ GR_FILENAME_TWO_INT,
21400+ GR_FILENAME_TWO_INT_STR,
21401+ GR_TEXTREL,
21402+ GR_PTRACE,
21403+ GR_RESOURCE,
21404+ GR_CAP,
21405+ GR_SIG,
21406+ GR_CRASH1,
21407+ GR_CRASH2,
21408+ GR_PSACCT
21409+};
21410+
21411+#define gr_log_ttysniff(audit, msg, task) gr_log_varargs(audit, msg, GR_TTYSNIFF, task)
21412+#define gr_log_fs_rbac_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_RBAC, dentry, mnt)
21413+#define gr_log_fs_rbac_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_RBAC_STR, dentry, mnt, str)
21414+#define gr_log_fs_str_rbac(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_RBAC, str, dentry, mnt)
21415+#define gr_log_fs_rbac_mode2(audit, msg, dentry, mnt, str1, str2) gr_log_varargs(audit, msg, GR_RBAC_MODE2, dentry, mnt, str1, str2)
21416+#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)
21417+#define gr_log_fs_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_FILENAME, dentry, mnt)
21418+#define gr_log_noargs(audit, msg) gr_log_varargs(audit, msg, GR_NOARGS)
21419+#define gr_log_int(audit, msg, num) gr_log_varargs(audit, msg, GR_ONE_INT, num)
21420+#define gr_log_int_str2(audit, msg, num, str1, str2) gr_log_varargs(audit, msg, GR_ONE_INT_TWO_STR, num, str1, str2)
21421+#define gr_log_str(audit, msg, str) gr_log_varargs(audit, msg, GR_ONE_STR, str)
21422+#define gr_log_str_int(audit, msg, str, num) gr_log_varargs(audit, msg, GR_STR_INT, str, num)
21423+#define gr_log_int_int(audit, msg, num1, num2) gr_log_varargs(audit, msg, GR_TWO_INT, num1, num2)
21424+#define gr_log_int3(audit, msg, num1, num2, num3) gr_log_varargs(audit, msg, GR_THREE_INT, num1, num2, num3)
21425+#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)
21426+#define gr_log_str_str(audit, msg, str1, str2) gr_log_varargs(audit, msg, GR_TWO_STR, str1, str2)
21427+#define gr_log_str3(audit, msg, str1, str2, str3) gr_log_varargs(audit, msg, GR_THREE_STR, str1, str2, str3)
21428+#define gr_log_str4(audit, msg, str1, str2, str3, str4) gr_log_varargs(audit, msg, GR_FOUR_STR, str1, str2, str3, str4)
21429+#define gr_log_str_fs(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_FILENAME, str, dentry, mnt)
21430+#define gr_log_fs_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_FILENAME_STR, dentry, mnt, str)
21431+#define gr_log_fs_int2(audit, msg, dentry, mnt, num1, num2) gr_log_varargs(audit, msg, GR_FILENAME_TWO_INT, dentry, mnt, num1, num2)
21432+#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)
21433+#define gr_log_textrel_ulong_ulong(audit, msg, file, ulong1, ulong2) gr_log_varargs(audit, msg, GR_TEXTREL, file, ulong1, ulong2)
21434+#define gr_log_ptrace(audit, msg, task) gr_log_varargs(audit, msg, GR_PTRACE, task)
21435+#define gr_log_res_ulong2_str(audit, msg, task, ulong1, str, ulong2) gr_log_varargs(audit, msg, GR_RESOURCE, task, ulong1, str, ulong2)
21436+#define gr_log_cap(audit, msg, task, str) gr_log_varargs(audit, msg, GR_CAP, task, str)
21437+#define gr_log_sig(audit, msg, task, num) gr_log_varargs(audit, msg, GR_SIG, task, num)
21438+#define gr_log_crash1(audit, msg, task, ulong) gr_log_varargs(audit, msg, GR_CRASH1, task, ulong)
21439+#define gr_log_crash2(audit, msg, task, ulong1) gr_log_varargs(audit, msg, GR_CRASH2, task, ulong1)
21440+#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)
21441+
21442+extern void gr_log_varargs(int audit, const char *msg, int argtypes, ...);
21443+
21444+#endif
21445+
21446+#endif
21447diff -urNp linux-2.6.17.7/include/linux/grmsg.h linux-2.6.17.7/include/linux/grmsg.h
21448--- linux-2.6.17.7/include/linux/grmsg.h 1969-12-31 19:00:00.000000000 -0500
21449+++ linux-2.6.17.7/include/linux/grmsg.h 2006-08-01 20:29:48.000000000 -0400
21450@@ -0,0 +1,108 @@
21451+#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"
21452+#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"
21453+#define GR_PTRACE_ACL_MSG "denied ptrace of %.950s(%.16s:%d) by "
21454+#define GR_STOPMOD_MSG "denied modification of module state by "
21455+#define GR_IOPERM_MSG "denied use of ioperm() by "
21456+#define GR_IOPL_MSG "denied use of iopl() by "
21457+#define GR_SHMAT_ACL_MSG "denied attach of shared memory of UID %u, PID %d, ID %u by "
21458+#define GR_UNIX_CHROOT_MSG "denied connect() to abstract AF_UNIX socket outside of chroot by "
21459+#define GR_SHMAT_CHROOT_MSG "denied attach of shared memory outside of chroot by "
21460+#define GR_KMEM_MSG "denied write of /dev/kmem by "
21461+#define GR_PORT_OPEN_MSG "denied open of /dev/port by "
21462+#define GR_MEM_WRITE_MSG "denied write of /dev/mem by "
21463+#define GR_MEM_MMAP_MSG "denied mmap write of /dev/[k]mem by "
21464+#define GR_SYMLINK_MSG "not following symlink %.950s owned by %d.%d by "
21465+#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"
21466+#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"
21467+#define GR_HIDDEN_ACL_MSG "%s access to hidden file %.950s by "
21468+#define GR_OPEN_ACL_MSG "%s open of %.950s for%s%s by "
21469+#define GR_CREATE_ACL_MSG "%s create of %.950s for%s%s by "
21470+#define GR_FIFO_MSG "denied writing FIFO %.950s of %d.%d by "
21471+#define GR_MKNOD_CHROOT_MSG "denied mknod of %.950s from chroot by "
21472+#define GR_MKNOD_ACL_MSG "%s mknod of %.950s by "
21473+#define GR_UNIXCONNECT_ACL_MSG "%s connect() to the unix domain socket %.950s by "
21474+#define GR_TTYSNIFF_ACL_MSG "terminal being sniffed by IP:%u.%u.%u.%u %.480s[%.16s:%d], parent %.480s[%.16s:%d] against "
21475+#define GR_MKDIR_ACL_MSG "%s mkdir of %.950s by "
21476+#define GR_RMDIR_ACL_MSG "%s rmdir of %.950s by "
21477+#define GR_UNLINK_ACL_MSG "%s unlink of %.950s by "
21478+#define GR_SYMLINK_ACL_MSG "%s symlink from %.480s to %.480s by "
21479+#define GR_HARDLINK_MSG "denied hardlink of %.930s (owned by %d.%d) to %.30s for "
21480+#define GR_LINK_ACL_MSG "%s link of %.480s to %.480s by "
21481+#define GR_INHERIT_ACL_MSG "successful inherit of %.480s's ACL for %.480s by "
21482+#define GR_RENAME_ACL_MSG "%s rename of %.480s to %.480s by "
21483+#define GR_PTRACE_EXEC_ACL_MSG "denied ptrace of %.950s by "
21484+#define GR_NPROC_MSG "denied overstep of process limit by "
21485+#define GR_EXEC_ACL_MSG "%s execution of %.950s by "
21486+#define GR_EXEC_TPE_MSG "denied untrusted exec of %.950s by "
21487+#define GR_SEGVSTART_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning uid %u from login for %lu seconds"
21488+#define GR_SEGVNOSUID_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning execution for %lu seconds"
21489+#define GR_MOUNT_CHROOT_MSG "denied mount of %.30s as %.930s from chroot by "
21490+#define GR_PIVOT_CHROOT_MSG "denied pivot_root from chroot by "
21491+#define GR_TRUNCATE_ACL_MSG "%s truncate of %.950s by "
21492+#define GR_ATIME_ACL_MSG "%s access time change of %.950s by "
21493+#define GR_ACCESS_ACL_MSG "%s access of %.950s for%s%s%s by "
21494+#define GR_CHROOT_CHROOT_MSG "denied double chroot to %.950s by "
21495+#define GR_FCHMOD_ACL_MSG "%s fchmod of %.950s by "
21496+#define GR_CHMOD_CHROOT_MSG "denied chmod +s of %.950s by "
21497+#define GR_CHMOD_ACL_MSG "%s chmod of %.950s by "
21498+#define GR_CHROOT_FCHDIR_MSG "denied fchdir outside of chroot to %.950s by "
21499+#define GR_CHOWN_ACL_MSG "%s chown of %.950s by "
21500+#define GR_WRITLIB_ACL_MSG "denied load of writable library %.950s by "
21501+#define GR_INITF_ACL_MSG "init_variables() failed %s by "
21502+#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"
21503+#define GR_DEV_ACL_MSG "/dev/grsec: %d bytes sent %d required, being fed garbaged by "
21504+#define GR_SHUTS_ACL_MSG "shutdown auth success for "
21505+#define GR_SHUTF_ACL_MSG "shutdown auth failure for "
21506+#define GR_SHUTI_ACL_MSG "ignoring shutdown for disabled RBAC system for "
21507+#define GR_SEGVMODS_ACL_MSG "segvmod auth success for "
21508+#define GR_SEGVMODF_ACL_MSG "segvmod auth failure for "
21509+#define GR_SEGVMODI_ACL_MSG "ignoring segvmod for disabled RBAC system for "
21510+#define GR_ENABLE_ACL_MSG "%s RBAC system loaded by "
21511+#define GR_ENABLEF_ACL_MSG "unable to load %s for "
21512+#define GR_RELOADI_ACL_MSG "ignoring reload request for disabled RBAC system"
21513+#define GR_RELOAD_ACL_MSG "%s RBAC system reloaded by "
21514+#define GR_RELOADF_ACL_MSG "failed reload of %s for "
21515+#define GR_SPROLEI_ACL_MSG "ignoring change to special role for disabled RBAC system for "
21516+#define GR_SPROLES_ACL_MSG "successful change to special role %s (id %d) by "
21517+#define GR_SPROLEL_ACL_MSG "special role %s (id %d) exited by "
21518+#define GR_SPROLEF_ACL_MSG "special role %s failure for "
21519+#define GR_UNSPROLEI_ACL_MSG "ignoring unauth of special role for disabled RBAC system for "
21520+#define GR_UNSPROLES_ACL_MSG "successful unauth of special role %s (id %d) by "
21521+#define GR_UNSPROLEF_ACL_MSG "special role unauth of %s failure for "
21522+#define GR_INVMODE_ACL_MSG "invalid mode %d by "
21523+#define GR_PRIORITY_CHROOT_MSG "denied priority change of process (%.16s:%d) by "
21524+#define GR_FAILFORK_MSG "failed fork with errno %d by "
21525+#define GR_NICE_CHROOT_MSG "denied priority change by "
21526+#define GR_UNISIGLOG_MSG "signal %d sent to "
21527+#define GR_DUALSIGLOG_MSG "signal %d sent to " DEFAULTSECMSG " by "
21528+#define GR_SIG_ACL_MSG "denied send of signal %d to protected task " DEFAULTSECMSG " by "
21529+#define GR_SYSCTL_MSG "denied modification of grsecurity sysctl value : %.32s by "
21530+#define GR_SYSCTL_ACL_MSG "%s sysctl of %.950s for%s%s by "
21531+#define GR_TIME_MSG "time set by "
21532+#define GR_DEFACL_MSG "fatal: unable to find subject for (%.16s:%d), loaded by "
21533+#define GR_MMAP_ACL_MSG "%s executable mmap of %.950s by "
21534+#define GR_MPROTECT_ACL_MSG "%s executable mprotect of %.950s by "
21535+#define GR_SOCK_MSG "denied socket(%.16s,%.16s,%.16s) by "
21536+#define GR_SOCK2_MSG "denied socket(%d,%.16s,%.16s) by "
21537+#define GR_BIND_MSG "denied bind() by "
21538+#define GR_CONNECT_MSG "denied connect() by "
21539+#define GR_BIND_ACL_MSG "denied bind() to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by "
21540+#define GR_CONNECT_ACL_MSG "denied connect() to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by "
21541+#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"
21542+#define GR_EXEC_CHROOT_MSG "exec of %.980s within chroot by process "
21543+#define GR_CAP_ACL_MSG "use of %s denied for "
21544+#define GR_USRCHANGE_ACL_MSG "change to uid %u denied for "
21545+#define GR_GRPCHANGE_ACL_MSG "change to gid %u denied for "
21546+#define GR_REMOUNT_AUDIT_MSG "remount of %.30s by "
21547+#define GR_UNMOUNT_AUDIT_MSG "unmount of %.30s by "
21548+#define GR_MOUNT_AUDIT_MSG "mount of %.30s to %.64s by "
21549+#define GR_CHDIR_AUDIT_MSG "chdir to %.980s by "
21550+#define GR_EXEC_AUDIT_MSG "exec of %.930s (%.128s) by "
21551+#define GR_MSGQ_AUDIT_MSG "message queue created by "
21552+#define GR_MSGQR_AUDIT_MSG "message queue of uid:%u euid:%u removed by "
21553+#define GR_SEM_AUDIT_MSG "semaphore created by "
21554+#define GR_SEMR_AUDIT_MSG "semaphore of uid:%u euid:%u removed by "
21555+#define GR_SHM_AUDIT_MSG "shared memory of size %d created by "
21556+#define GR_SHMR_AUDIT_MSG "shared memory of uid:%u euid:%u removed by "
21557+#define GR_RESOURCE_MSG "denied resource overstep by requesting %lu for %.16s against limit %lu for "
21558+#define GR_TEXTREL_AUDIT_MSG "text relocation in %s, VMA:0x%08lx 0x%08lx by "
21559diff -urNp linux-2.6.17.7/include/linux/grsecurity.h linux-2.6.17.7/include/linux/grsecurity.h
21560--- linux-2.6.17.7/include/linux/grsecurity.h 1969-12-31 19:00:00.000000000 -0500
21561+++ linux-2.6.17.7/include/linux/grsecurity.h 2006-08-01 20:29:48.000000000 -0400
21562@@ -0,0 +1,196 @@
21563+#ifndef GR_SECURITY_H
21564+#define GR_SECURITY_H
21565+#include <linux/fs.h>
21566+#include <linux/binfmts.h>
21567+#include <linux/gracl.h>
21568+
21569+extern void gr_handle_brute_attach(struct task_struct *p);
21570+extern void gr_handle_brute_check(void);
21571+
21572+extern char gr_roletype_to_char(void);
21573+
21574+extern int gr_check_user_change(int real, int effective, int fs);
21575+extern int gr_check_group_change(int real, int effective, int fs);
21576+
21577+extern void gr_del_task_from_ip_table(struct task_struct *p);
21578+
21579+extern int gr_pid_is_chrooted(struct task_struct *p);
21580+extern int gr_handle_chroot_nice(void);
21581+extern int gr_handle_chroot_sysctl(const int op);
21582+extern int gr_handle_chroot_setpriority(struct task_struct *p,
21583+ const int niceval);
21584+extern int gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt);
21585+extern int gr_handle_chroot_chroot(const struct dentry *dentry,
21586+ const struct vfsmount *mnt);
21587+extern void gr_handle_chroot_caps(struct task_struct *task);
21588+extern void gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt);
21589+extern int gr_handle_chroot_chmod(const struct dentry *dentry,
21590+ const struct vfsmount *mnt, const int mode);
21591+extern int gr_handle_chroot_mknod(const struct dentry *dentry,
21592+ const struct vfsmount *mnt, const int mode);
21593+extern int gr_handle_chroot_mount(const struct dentry *dentry,
21594+ const struct vfsmount *mnt,
21595+ const char *dev_name);
21596+extern int gr_handle_chroot_pivot(void);
21597+extern int gr_handle_chroot_unix(const pid_t pid);
21598+
21599+extern int gr_handle_rawio(const struct inode *inode);
21600+extern int gr_handle_nproc(void);
21601+
21602+extern void gr_handle_ioperm(void);
21603+extern void gr_handle_iopl(void);
21604+
21605+extern int gr_tpe_allow(const struct file *file);
21606+
21607+extern int gr_random_pid(void);
21608+
21609+extern void gr_log_forkfail(const int retval);
21610+extern void gr_log_timechange(void);
21611+extern void gr_log_signal(const int sig, const struct task_struct *t);
21612+extern void gr_log_chdir(const struct dentry *dentry,
21613+ const struct vfsmount *mnt);
21614+extern void gr_log_chroot_exec(const struct dentry *dentry,
21615+ const struct vfsmount *mnt);
21616+extern void gr_handle_exec_args(struct linux_binprm *bprm, char **argv);
21617+extern void gr_log_remount(const char *devname, const int retval);
21618+extern void gr_log_unmount(const char *devname, const int retval);
21619+extern void gr_log_mount(const char *from, const char *to, const int retval);
21620+extern void gr_log_msgget(const int ret, const int msgflg);
21621+extern void gr_log_msgrm(const uid_t uid, const uid_t cuid);
21622+extern void gr_log_semget(const int err, const int semflg);
21623+extern void gr_log_semrm(const uid_t uid, const uid_t cuid);
21624+extern void gr_log_shmget(const int err, const int shmflg, const size_t size);
21625+extern void gr_log_shmrm(const uid_t uid, const uid_t cuid);
21626+extern void gr_log_textrel(struct vm_area_struct *vma);
21627+
21628+extern int gr_handle_follow_link(const struct inode *parent,
21629+ const struct inode *inode,
21630+ const struct dentry *dentry,
21631+ const struct vfsmount *mnt);
21632+extern int gr_handle_fifo(const struct dentry *dentry,
21633+ const struct vfsmount *mnt,
21634+ const struct dentry *dir, const int flag,
21635+ const int acc_mode);
21636+extern int gr_handle_hardlink(const struct dentry *dentry,
21637+ const struct vfsmount *mnt,
21638+ struct inode *inode,
21639+ const int mode, const char *to);
21640+
21641+extern int gr_task_is_capable(struct task_struct *task, const int cap);
21642+extern int gr_is_capable_nolog(const int cap);
21643+extern void gr_learn_resource(const struct task_struct *task, const int limit,
21644+ const unsigned long wanted, const int gt);
21645+extern void gr_copy_label(struct task_struct *tsk);
21646+extern void gr_handle_crash(struct task_struct *task, const int sig);
21647+extern int gr_handle_signal(const struct task_struct *p, const int sig);
21648+extern int gr_check_crash_uid(const uid_t uid);
21649+extern int gr_check_protected_task(const struct task_struct *task);
21650+extern int gr_acl_handle_mmap(const struct file *file,
21651+ const unsigned long prot);
21652+extern int gr_acl_handle_mprotect(const struct file *file,
21653+ const unsigned long prot);
21654+extern int gr_check_hidden_task(const struct task_struct *tsk);
21655+extern __u32 gr_acl_handle_truncate(const struct dentry *dentry,
21656+ const struct vfsmount *mnt);
21657+extern __u32 gr_acl_handle_utime(const struct dentry *dentry,
21658+ const struct vfsmount *mnt);
21659+extern __u32 gr_acl_handle_access(const struct dentry *dentry,
21660+ const struct vfsmount *mnt, const int fmode);
21661+extern __u32 gr_acl_handle_fchmod(const struct dentry *dentry,
21662+ const struct vfsmount *mnt, mode_t mode);
21663+extern __u32 gr_acl_handle_chmod(const struct dentry *dentry,
21664+ const struct vfsmount *mnt, mode_t mode);
21665+extern __u32 gr_acl_handle_chown(const struct dentry *dentry,
21666+ const struct vfsmount *mnt);
21667+extern int gr_handle_ptrace(struct task_struct *task, const long request);
21668+extern int gr_handle_proc_ptrace(struct task_struct *task);
21669+extern __u32 gr_acl_handle_execve(const struct dentry *dentry,
21670+ const struct vfsmount *mnt);
21671+extern int gr_check_crash_exec(const struct file *filp);
21672+extern int gr_acl_is_enabled(void);
21673+extern void gr_set_kernel_label(struct task_struct *task);
21674+extern void gr_set_role_label(struct task_struct *task, const uid_t uid,
21675+ const gid_t gid);
21676+extern int gr_set_proc_label(const struct dentry *dentry,
21677+ const struct vfsmount *mnt);
21678+extern __u32 gr_acl_handle_hidden_file(const struct dentry *dentry,
21679+ const struct vfsmount *mnt);
21680+extern __u32 gr_acl_handle_open(const struct dentry *dentry,
21681+ const struct vfsmount *mnt, const int fmode);
21682+extern __u32 gr_acl_handle_creat(const struct dentry *dentry,
21683+ const struct dentry *p_dentry,
21684+ const struct vfsmount *p_mnt, const int fmode,
21685+ const int imode);
21686+extern void gr_handle_create(const struct dentry *dentry,
21687+ const struct vfsmount *mnt);
21688+extern __u32 gr_acl_handle_mknod(const struct dentry *new_dentry,
21689+ const struct dentry *parent_dentry,
21690+ const struct vfsmount *parent_mnt,
21691+ const int mode);
21692+extern __u32 gr_acl_handle_mkdir(const struct dentry *new_dentry,
21693+ const struct dentry *parent_dentry,
21694+ const struct vfsmount *parent_mnt);
21695+extern __u32 gr_acl_handle_rmdir(const struct dentry *dentry,
21696+ const struct vfsmount *mnt);
21697+extern void gr_handle_delete(const ino_t ino, const dev_t dev);
21698+extern __u32 gr_acl_handle_unlink(const struct dentry *dentry,
21699+ const struct vfsmount *mnt);
21700+extern __u32 gr_acl_handle_symlink(const struct dentry *new_dentry,
21701+ const struct dentry *parent_dentry,
21702+ const struct vfsmount *parent_mnt,
21703+ const char *from);
21704+extern __u32 gr_acl_handle_link(const struct dentry *new_dentry,
21705+ const struct dentry *parent_dentry,
21706+ const struct vfsmount *parent_mnt,
21707+ const struct dentry *old_dentry,
21708+ const struct vfsmount *old_mnt, const char *to);
21709+extern int gr_acl_handle_rename(struct dentry *new_dentry,
21710+ struct dentry *parent_dentry,
21711+ const struct vfsmount *parent_mnt,
21712+ struct dentry *old_dentry,
21713+ struct inode *old_parent_inode,
21714+ struct vfsmount *old_mnt, const char *newname);
21715+extern void gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
21716+ struct dentry *old_dentry,
21717+ struct dentry *new_dentry,
21718+ struct vfsmount *mnt, const __u8 replace);
21719+extern __u32 gr_check_link(const struct dentry *new_dentry,
21720+ const struct dentry *parent_dentry,
21721+ const struct vfsmount *parent_mnt,
21722+ const struct dentry *old_dentry,
21723+ const struct vfsmount *old_mnt);
21724+extern int gr_acl_handle_filldir(const struct file *file, const char *name,
21725+ const unsigned int namelen, const ino_t ino);
21726+
21727+extern __u32 gr_acl_handle_unix(const struct dentry *dentry,
21728+ const struct vfsmount *mnt);
21729+extern void gr_acl_handle_exit(void);
21730+extern void gr_acl_handle_psacct(struct task_struct *task, const long code);
21731+extern int gr_acl_handle_procpidmem(const struct task_struct *task);
21732+extern __u32 gr_cap_rtnetlink(void);
21733+
21734+#ifdef CONFIG_SYSVIPC
21735+extern void gr_shm_exit(struct task_struct *task);
21736+#else
21737+static inline void gr_shm_exit(struct task_struct *task)
21738+{
21739+ return;
21740+}
21741+#endif
21742+
21743+#ifdef CONFIG_GRKERNSEC
21744+extern void gr_handle_mem_write(void);
21745+extern void gr_handle_kmem_write(void);
21746+extern void gr_handle_open_port(void);
21747+extern int gr_handle_mem_mmap(const unsigned long offset,
21748+ struct vm_area_struct *vma);
21749+
21750+extern unsigned long pax_get_random_long(void);
21751+#define get_random_long() pax_get_random_long()
21752+
21753+extern int grsec_enable_dmesg;
21754+extern int grsec_enable_randsrc;
21755+extern int grsec_enable_shm;
21756+#endif
21757+
21758+#endif
21759diff -urNp linux-2.6.17.7/include/linux/highmem.h linux-2.6.17.7/include/linux/highmem.h
21760--- linux-2.6.17.7/include/linux/highmem.h 2006-07-24 23:36:01.000000000 -0400
21761+++ linux-2.6.17.7/include/linux/highmem.h 2006-08-01 20:29:48.000000000 -0400
21762@@ -70,9 +70,9 @@ alloc_zeroed_user_highpage(struct vm_are
21763
21764 static inline void clear_highpage(struct page *page)
21765 {
21766- void *kaddr = kmap_atomic(page, KM_USER0);
21767+ void *kaddr = kmap_atomic(page, KM_CLEARPAGE);
21768 clear_page(kaddr);
21769- kunmap_atomic(kaddr, KM_USER0);
21770+ kunmap_atomic(kaddr, KM_CLEARPAGE);
21771 }
21772
21773 /*
21774diff -urNp linux-2.6.17.7/include/linux/mm.h linux-2.6.17.7/include/linux/mm.h
21775--- linux-2.6.17.7/include/linux/mm.h 2006-07-24 23:36:01.000000000 -0400
21776+++ linux-2.6.17.7/include/linux/mm.h 2006-08-01 20:29:48.000000000 -0400
21777@@ -38,6 +38,7 @@ extern int sysctl_legacy_va_layout;
21778 #include <asm/pgtable.h>
21779 #include <asm/processor.h>
21780 #include <asm/atomic.h>
21781+#include <asm/mman.h>
21782
21783 #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
21784
21785@@ -111,8 +112,43 @@ struct vm_area_struct {
21786 #ifdef CONFIG_NUMA
21787 struct mempolicy *vm_policy; /* NUMA policy for the VMA */
21788 #endif
21789+
21790+ unsigned long vm_mirror; /* PaX: mirror distance */
21791 };
21792
21793+#ifdef CONFIG_PAX_SOFTMODE
21794+extern unsigned int pax_softmode;
21795+#endif
21796+
21797+extern int pax_check_flags(unsigned long *);
21798+
21799+/* if tsk != current then task_lock must be held on it */
21800+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
21801+static inline unsigned long pax_get_flags(struct task_struct *tsk)
21802+{
21803+ if (likely(tsk->mm))
21804+ return tsk->mm->pax_flags;
21805+ else
21806+ return 0UL;
21807+}
21808+
21809+/* if tsk != current then task_lock must be held on it */
21810+static inline long pax_set_flags(struct task_struct *tsk, unsigned long flags)
21811+{
21812+ if (likely(tsk->mm)) {
21813+ tsk->mm->pax_flags = flags;
21814+ return 0;
21815+ }
21816+ return -EINVAL;
21817+}
21818+#endif
21819+
21820+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
21821+extern void pax_set_initial_flags(struct linux_binprm * bprm);
21822+#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
21823+extern void (*pax_set_initial_flags_func)(struct linux_binprm * bprm);
21824+#endif
21825+
21826 /*
21827 * This struct defines the per-mm list of VMAs for uClinux. If CONFIG_MMU is
21828 * disabled, then there's a single shared list of VMAs maintained by the
21829@@ -167,6 +203,18 @@ extern unsigned int kobjsize(const void
21830 #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */
21831 #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */
21832
21833+#ifdef CONFIG_PAX_SEGMEXEC
21834+#define VM_MIRROR 0x04000000 /* vma is mirroring another */
21835+#endif
21836+
21837+#ifdef CONFIG_PAX_MPROTECT
21838+#define VM_MAYNOTWRITE 0x08000000 /* vma cannot be granted VM_WRITE any more */
21839+#endif
21840+
21841+#ifdef __VM_STACK_FLAGS
21842+#define VM_STACK_DEFAULT_FLAGS (0x00000033 | __VM_STACK_FLAGS)
21843+#endif
21844+
21845 #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
21846 #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
21847 #endif
21848@@ -1058,5 +1106,11 @@ void drop_slab(void);
21849 extern int randomize_va_space;
21850 #endif
21851
21852+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
21853+extern void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot);
21854+#else
21855+static inline void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot) {}
21856+#endif
21857+
21858 #endif /* __KERNEL__ */
21859 #endif /* _LINUX_MM_H */
21860diff -urNp linux-2.6.17.7/include/linux/mman.h linux-2.6.17.7/include/linux/mman.h
21861--- linux-2.6.17.7/include/linux/mman.h 2006-07-24 23:36:01.000000000 -0400
21862+++ linux-2.6.17.7/include/linux/mman.h 2006-08-01 20:29:48.000000000 -0400
21863@@ -59,6 +59,11 @@ static inline unsigned long
21864 calc_vm_flag_bits(unsigned long flags)
21865 {
21866 return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
21867+
21868+#ifdef CONFIG_PAX_SEGMEXEC
21869+ _calc_vm_trans(flags, MAP_MIRROR, VM_MIRROR) |
21870+#endif
21871+
21872 _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) |
21873 _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) |
21874 _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED );
21875diff -urNp linux-2.6.17.7/include/linux/module.h linux-2.6.17.7/include/linux/module.h
21876--- linux-2.6.17.7/include/linux/module.h 2006-07-24 23:36:01.000000000 -0400
21877+++ linux-2.6.17.7/include/linux/module.h 2006-08-01 20:29:48.000000000 -0400
21878@@ -273,16 +273,16 @@ struct module
21879 int (*init)(void);
21880
21881 /* If this is non-NULL, vfree after init() returns */
21882- void *module_init;
21883+ void *module_init_rx, *module_init_rw;
21884
21885 /* Here is the actual code + data, vfree'd on unload. */
21886- void *module_core;
21887+ void *module_core_rx, *module_core_rw;
21888
21889 /* Here are the sizes of the init and core sections */
21890- unsigned long init_size, core_size;
21891+ unsigned long init_size_rw, core_size_rw;
21892
21893 /* The size of the executable code in each section. */
21894- unsigned long init_text_size, core_text_size;
21895+ unsigned long init_size_rx, core_size_rx;
21896
21897 /* Arch-specific module values */
21898 struct mod_arch_specific arch;
21899diff -urNp linux-2.6.17.7/include/linux/moduleloader.h linux-2.6.17.7/include/linux/moduleloader.h
21900--- linux-2.6.17.7/include/linux/moduleloader.h 2006-07-24 23:36:01.000000000 -0400
21901+++ linux-2.6.17.7/include/linux/moduleloader.h 2006-08-01 20:29:48.000000000 -0400
21902@@ -17,9 +17,21 @@ int module_frob_arch_sections(Elf_Ehdr *
21903 sections. Returns NULL on failure. */
21904 void *module_alloc(unsigned long size);
21905
21906+#ifdef CONFIG_PAX_KERNEXEC
21907+void *module_alloc_exec(unsigned long size);
21908+#else
21909+#define module_alloc_exec(x) module_alloc(x)
21910+#endif
21911+
21912 /* Free memory returned from module_alloc. */
21913 void module_free(struct module *mod, void *module_region);
21914
21915+#ifdef CONFIG_PAX_KERNEXEC
21916+void module_free_exec(struct module *mod, void *module_region);
21917+#else
21918+#define module_free_exec(x, y) module_free(x, y)
21919+#endif
21920+
21921 /* Apply the given relocation to the (simplified) ELF. Return -error
21922 or 0. */
21923 int apply_relocate(Elf_Shdr *sechdrs,
21924diff -urNp linux-2.6.17.7/include/linux/random.h linux-2.6.17.7/include/linux/random.h
21925--- linux-2.6.17.7/include/linux/random.h 2006-07-24 23:36:01.000000000 -0400
21926+++ linux-2.6.17.7/include/linux/random.h 2006-08-01 20:29:48.000000000 -0400
21927@@ -62,6 +62,8 @@ extern __u32 secure_tcpv6_sequence_numbe
21928 extern u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr,
21929 __u16 sport, __u16 dport);
21930
21931+extern unsigned long pax_get_random_long(void);
21932+
21933 #ifndef MODULE
21934 extern struct file_operations random_fops, urandom_fops;
21935 #endif
21936diff -urNp linux-2.6.17.7/include/linux/sched.h linux-2.6.17.7/include/linux/sched.h
21937--- linux-2.6.17.7/include/linux/sched.h 2006-07-24 23:36:01.000000000 -0400
21938+++ linux-2.6.17.7/include/linux/sched.h 2006-08-01 20:29:48.000000000 -0400
21939@@ -40,6 +40,7 @@
21940 #include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
21941
21942 struct exec_domain;
21943+struct linux_binprm;
21944
21945 /*
21946 * cloning flags:
21947@@ -350,8 +351,34 @@ struct mm_struct {
21948 /* aio bits */
21949 rwlock_t ioctx_list_lock;
21950 struct kioctx *ioctx_list;
21951+
21952+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
21953+ unsigned long pax_flags;
21954+#endif
21955+
21956+#ifdef CONFIG_PAX_DLRESOLVE
21957+ unsigned long call_dl_resolve;
21958+#endif
21959+
21960+#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
21961+ unsigned long call_syscall;
21962+#endif
21963+
21964+#ifdef CONFIG_PAX_ASLR
21965+ unsigned long delta_mmap; /* randomized offset */
21966+ unsigned long delta_exec; /* randomized offset */
21967+ unsigned long delta_stack; /* randomized offset */
21968+#endif
21969+
21970 };
21971
21972+#define MF_PAX_PAGEEXEC 0x01000000 /* Paging based non-executable pages */
21973+#define MF_PAX_EMUTRAMP 0x02000000 /* Emulate trampolines */
21974+#define MF_PAX_MPROTECT 0x04000000 /* Restrict mprotect() */
21975+#define MF_PAX_RANDMMAP 0x08000000 /* Randomize mmap() base */
21976+/*#define MF_PAX_RANDEXEC 0x10000000*/ /* Randomize ET_EXEC base */
21977+#define MF_PAX_SEGMEXEC 0x20000000 /* Segmentation based non-executable pages */
21978+
21979 struct sighand_struct {
21980 atomic_t count;
21981 struct k_sigaction action[_NSIG];
21982@@ -449,6 +476,15 @@ struct signal_struct {
21983 struct key *session_keyring; /* keyring inherited over fork */
21984 struct key *process_keyring; /* keyring private to this process */
21985 #endif
21986+
21987+#ifdef CONFIG_GRKERNSEC
21988+ u32 curr_ip;
21989+ u32 gr_saddr;
21990+ u32 gr_daddr;
21991+ u16 gr_sport;
21992+ u16 gr_dport;
21993+ u8 used_accept:1;
21994+#endif
21995 };
21996
21997 /* Context switch must be unlocked if interrupts are to be enabled */
21998@@ -881,6 +917,17 @@ struct task_struct {
21999 struct compat_robust_list_head __user *compat_robust_list;
22000 #endif
22001
22002+#ifdef CONFIG_GRKERNSEC
22003+ /* grsecurity */
22004+ struct acl_subject_label *acl;
22005+ struct acl_role_label *role;
22006+ struct file *exec_file;
22007+ u16 acl_role_id;
22008+ u8 acl_sp_role:1;
22009+ u8 is_writable:1;
22010+ u8 brute:1;
22011+#endif
22012+
22013 atomic_t fs_excl; /* holding fs exclusive resources */
22014 struct rcu_head rcu;
22015
22016@@ -1393,6 +1440,12 @@ extern void arch_pick_mmap_layout(struct
22017 static inline void arch_pick_mmap_layout(struct mm_struct *mm)
22018 {
22019 mm->mmap_base = TASK_UNMAPPED_BASE;
22020+
22021+#ifdef CONFIG_PAX_RANDMMAP
22022+ if (mm->pax_flags & MF_PAX_RANDMMAP)
22023+ mm->mmap_base += mm->delta_mmap;
22024+#endif
22025+
22026 mm->get_unmapped_area = arch_get_unmapped_area;
22027 mm->unmap_area = arch_unmap_area;
22028 }
22029diff -urNp linux-2.6.17.7/include/linux/shm.h linux-2.6.17.7/include/linux/shm.h
22030--- linux-2.6.17.7/include/linux/shm.h 2006-07-24 23:36:01.000000000 -0400
22031+++ linux-2.6.17.7/include/linux/shm.h 2006-08-01 20:29:48.000000000 -0400
22032@@ -86,6 +86,10 @@ struct shmid_kernel /* private to the ke
22033 pid_t shm_cprid;
22034 pid_t shm_lprid;
22035 struct user_struct *mlock_user;
22036+#ifdef CONFIG_GRKERNSEC
22037+ time_t shm_createtime;
22038+ pid_t shm_lapid;
22039+#endif
22040 };
22041
22042 /* shm_mode upper byte flags */
22043diff -urNp linux-2.6.17.7/include/linux/sysctl.h linux-2.6.17.7/include/linux/sysctl.h
22044--- linux-2.6.17.7/include/linux/sysctl.h 2006-07-24 23:36:01.000000000 -0400
22045+++ linux-2.6.17.7/include/linux/sysctl.h 2006-08-01 20:29:48.000000000 -0400
428b7709 22046@@ -78,9 +78,22 @@
22047 INOTIFY_MAX_QUEUED_EVENTS=3 /* max queued events per instance */
f1a4f855 22048 };
22049
22050+#ifdef CONFIG_PAX_SOFTMODE
22051+enum {
22052+ PAX_SOFTMODE=1 /* PaX: disable/enable soft mode */
22053+};
22054+#endif
428b7709 22055+
22056 /* CTL_KERN names: */
f1a4f855 22057 enum
428b7709 22058 {
22059+#ifdef CONFIG_GRKERNSEC
22060+ KERN_GRSECURITY=98, /* grsecurity */
22061+#endif
22062+
22063+#ifdef CONFIG_PAX_SOFTMODE
22064+ KERN_PAX=99, /* PaX control */
22065+#endif
22066 KERN_OSTYPE=1, /* string: system version */
22067 KERN_OSRELEASE=2, /* string: system release */
22068 KERN_OSREV=3, /* int: system revision */
f1a4f855 22069diff -urNp linux-2.6.17.7/init/Kconfig linux-2.6.17.7/init/Kconfig
22070--- linux-2.6.17.7/init/Kconfig 2006-07-24 23:36:01.000000000 -0400
22071+++ linux-2.6.17.7/init/Kconfig 2006-08-01 20:29:48.000000000 -0400
22072@@ -268,6 +268,7 @@ menuconfig EMBEDDED
22073 config KALLSYMS
22074 bool "Load all symbols for debugging/kksymoops" if EMBEDDED
22075 default y
22076+ depends on !GRKERNSEC_HIDESYM
22077 help
22078 Say Y here to let the kernel print out symbolic crash information and
22079 symbolic stack backtraces. This increases the size of the kernel
22080diff -urNp linux-2.6.17.7/init/main.c linux-2.6.17.7/init/main.c
22081--- linux-2.6.17.7/init/main.c 2006-07-24 23:36:01.000000000 -0400
22082+++ linux-2.6.17.7/init/main.c 2006-08-01 20:29:48.000000000 -0400
22083@@ -100,6 +100,7 @@ static inline void mark_rodata_ro(void)
22084 #ifdef CONFIG_TC
22085 extern void tc_init(void);
22086 #endif
22087+extern void grsecurity_init(void);
22088
22089 enum system_states system_state;
22090 EXPORT_SYMBOL(system_state);
22091@@ -150,6 +151,15 @@ static int __init maxcpus(char *str)
22092
22093 __setup("maxcpus=", maxcpus);
22094
22095+#ifdef CONFIG_PAX_SOFTMODE
22096+static int __init setup_pax_softmode(char *str)
22097+{
22098+ get_option(&str, &pax_softmode);
22099+ return 1;
22100+}
22101+__setup("pax_softmode=", setup_pax_softmode);
22102+#endif
22103+
22104 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
22105 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
22106 static const char *panic_later, *panic_param;
22107@@ -692,6 +702,8 @@ static int init(void * unused)
22108 prepare_namespace();
22109 }
22110
22111+ grsecurity_init();
22112+
22113 /*
22114 * Ok, we have completed the initial bootup, and
22115 * we're essentially up and running. Get rid of the
22116diff -urNp linux-2.6.17.7/ipc/msg.c linux-2.6.17.7/ipc/msg.c
22117--- linux-2.6.17.7/ipc/msg.c 2006-07-24 23:36:01.000000000 -0400
22118+++ linux-2.6.17.7/ipc/msg.c 2006-08-01 20:29:48.000000000 -0400
22119@@ -32,6 +32,7 @@
22120 #include <linux/audit.h>
22121 #include <linux/seq_file.h>
22122 #include <linux/mutex.h>
22123+#include <linux/grsecurity.h>
22124
22125 #include <asm/current.h>
22126 #include <asm/uaccess.h>
22127@@ -237,6 +238,9 @@ asmlinkage long sys_msgget (key_t key, i
22128 msg_unlock(msq);
22129 }
22130 mutex_unlock(&msg_ids.mutex);
22131+
22132+ gr_log_msgget(ret, msgflg);
22133+
22134 return ret;
22135 }
22136
22137@@ -495,6 +499,8 @@ asmlinkage long sys_msgctl (int msqid, i
22138 break;
22139 }
22140 case IPC_RMID:
22141+ gr_log_msgrm(ipcp->uid, ipcp->cuid);
22142+
22143 freeque (msq, msqid);
22144 break;
22145 }
22146diff -urNp linux-2.6.17.7/ipc/sem.c linux-2.6.17.7/ipc/sem.c
22147--- linux-2.6.17.7/ipc/sem.c 2006-07-24 23:36:01.000000000 -0400
22148+++ linux-2.6.17.7/ipc/sem.c 2006-08-01 20:29:48.000000000 -0400
22149@@ -79,6 +79,7 @@
f1a4f855 22150 #include <linux/seq_file.h>
22151 #include <linux/mutex.h>
77fa6d7d 22152 #include <linux/vs_limit.h>
f1a4f855 22153+#include <linux/grsecurity.h>
22154
22155 #include <asm/uaccess.h>
22156 #include "util.h"
22157@@ -247,6 +248,9 @@ asmlinkage long sys_semget (key_t key, i
22158 }
22159
22160 mutex_unlock(&sem_ids.mutex);
22161+
22162+ gr_log_semget(err, semflg);
22163+
22164 return err;
22165 }
22166
22167@@ -840,6 +844,8 @@ static int semctl_down(int semid, int se
22168
22169 switch(cmd){
22170 case IPC_RMID:
22171+ gr_log_semrm(ipcp->uid, ipcp->cuid);
22172+
22173 freeary(sma, semid);
22174 err = 0;
22175 break;
22176diff -urNp linux-2.6.17.7/ipc/shm.c linux-2.6.17.7/ipc/shm.c
22177--- linux-2.6.17.7/ipc/shm.c 2006-07-24 23:36:01.000000000 -0400
22178+++ linux-2.6.17.7/ipc/shm.c 2006-08-01 20:29:48.000000000 -0400
22179@@ -33,6 +33,7 @@
f1a4f855 22180 #include <linux/mutex.h>
77fa6d7d 22181 #include <linux/vs_context.h>
22182 #include <linux/vs_limit.h>
f1a4f855 22183+#include <linux/grsecurity.h>
22184
22185 #include <asm/uaccess.h>
22186
22187@@ -56,6 +57,14 @@ static void shm_close (struct vm_area_st
22188 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
22189 #endif
22190
22191+#ifdef CONFIG_GRKERNSEC
22192+extern int gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
22193+ const time_t shm_createtime, const uid_t cuid,
22194+ const int shmid);
22195+extern int gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
22196+ const time_t shm_createtime);
22197+#endif
22198+
22199 size_t shm_ctlmax = SHMMAX;
22200 size_t shm_ctlall = SHMALL;
22201 int shm_ctlmni = SHMMNI;
22202@@ -149,6 +158,17 @@ static void shm_close (struct vm_area_st
22203 shp->shm_lprid = current->tgid;
22204 shp->shm_dtim = get_seconds();
22205 shp->shm_nattch--;
22206+#ifdef CONFIG_GRKERNSEC_SHM
22207+ if (grsec_enable_shm) {
22208+ if (shp->shm_nattch == 0) {
22209+ shp->shm_perm.mode |= SHM_DEST;
22210+ shm_destroy(shp);
22211+ } else
22212+ shm_unlock(shp);
22213+ mutex_unlock(&shm_ids.mutex);
22214+ return;
22215+ }
22216+#endif
22217 if(shp->shm_nattch == 0 &&
22218 shp->shm_perm.mode & SHM_DEST)
22219 shm_destroy (shp);
22220@@ -248,6 +268,9 @@ static int newseg (key_t key, int shmflg
22221 shp->shm_lprid = 0;
22222 shp->shm_atim = shp->shm_dtim = 0;
22223 shp->shm_ctim = get_seconds();
22224+#ifdef CONFIG_GRKERNSEC
22225+ shp->shm_createtime = get_seconds();
22226+#endif
22227 shp->shm_segsz = size;
22228 shp->shm_nattch = 0;
22229 shp->id = shm_buildid(id,shp->shm_perm.seq);
22230@@ -302,6 +325,8 @@ asmlinkage long sys_shmget (key_t key, s
22231 }
22232 mutex_unlock(&shm_ids.mutex);
22233
22234+ gr_log_shmget(err, shmflg, size);
22235+
22236 return err;
22237 }
22238
22239@@ -615,6 +640,8 @@ asmlinkage long sys_shmctl (int shmid, i
22240 if (err)
22241 goto out_unlock_up;
22242
22243+ gr_log_shmrm(shp->shm_perm.uid, shp->shm_perm.cuid);
22244+
22245 if (shp->shm_nattch){
22246 shp->shm_perm.mode |= SHM_DEST;
22247 /* Do not find it any more */
22248@@ -763,9 +790,27 @@ long do_shmat(int shmid, char __user *sh
22249 return err;
22250 }
22251
22252+#ifdef CONFIG_GRKERNSEC
22253+ if (!gr_handle_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime,
22254+ shp->shm_perm.cuid, shmid)) {
22255+ shm_unlock(shp);
22256+ return -EACCES;
22257+ }
22258+
22259+ if (!gr_chroot_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime)) {
22260+ shm_unlock(shp);
22261+ return -EACCES;
22262+ }
22263+#endif
22264+
22265 file = shp->shm_file;
22266 size = i_size_read(file->f_dentry->d_inode);
22267 shp->shm_nattch++;
22268+
22269+#ifdef CONFIG_GRKERNSEC
22270+ shp->shm_lapid = current->pid;
22271+#endif
22272+
22273 shm_unlock(shp);
22274
22275 down_write(&current->mm->mmap_sem);
22276@@ -935,3 +980,24 @@ static int sysvipc_shm_proc_show(struct
22277 shp->shm_ctim);
22278 }
22279 #endif
22280+
22281+void gr_shm_exit(struct task_struct *task)
22282+{
22283+#ifdef CONFIG_GRKERNSEC_SHM
22284+ int i;
22285+ struct shmid_kernel *shp;
22286+
22287+ if (!grsec_enable_shm)
22288+ return;
22289+
22290+ for (i = 0; i <= shm_ids.max_id; i++) {
22291+ shp = shm_get(i);
22292+ if (shp && (shp->shm_cprid == task->pid) &&
22293+ (shp->shm_nattch <= 0)) {
22294+ shp->shm_perm.mode |= SHM_DEST;
22295+ shm_destroy(shp);
22296+ }
22297+ }
22298+#endif
22299+ return;
22300+}
22301diff -urNp linux-2.6.17.7/kernel/capability.c linux-2.6.17.7/kernel/capability.c
22302--- linux-2.6.17.7/kernel/capability.c 2006-07-24 23:36:01.000000000 -0400
22303+++ linux-2.6.17.7/kernel/capability.c 2006-08-01 20:29:48.000000000 -0400
22304@@ -12,6 +12,7 @@
f1a4f855 22305 #include <linux/security.h>
22306 #include <linux/syscalls.h>
77fa6d7d 22307 #include <linux/vs_pid.h>
f1a4f855 22308+#include <linux/grsecurity.h>
22309 #include <asm/uaccess.h>
22310
22311 unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
22312@@ -234,14 +235,25 @@ out:
22313 return ret;
22314 }
22315
22316+extern int gr_task_is_capable(struct task_struct *task, const int cap);
22317+extern int gr_is_capable_nolog(const int cap);
22318+
22319 int __capable(struct task_struct *t, int cap)
22320 {
22321- if (security_capable(t, cap) == 0) {
22322+ if ((security_capable(t, cap) == 0) && gr_task_is_capable(t, cap)) {
22323 t->flags |= PF_SUPERPRIV;
22324 return 1;
22325 }
22326 return 0;
22327 }
22328+int capable_nolog(int cap)
22329+{
22330+ if ((security_capable(current, cap) == 0) && gr_is_capable_nolog(cap)) {
22331+ current->flags |= PF_SUPERPRIV;
22332+ return 1;
22333+ }
22334+ return 0;
22335+}
22336 EXPORT_SYMBOL(__capable);
22337
22338 int capable(int cap)
77fa6d7d 22339@@ -249,4 +261,5 @@ int capable(int cap)
f1a4f855 22340 return __capable(current, cap);
22341 }
22342 EXPORT_SYMBOL(capable);
22343+EXPORT_SYMBOL(capable_nolog);
77fa6d7d 22344
f1a4f855 22345diff -urNp linux-2.6.17.7/kernel/configs.c linux-2.6.17.7/kernel/configs.c
22346--- linux-2.6.17.7/kernel/configs.c 2006-07-24 23:36:01.000000000 -0400
22347+++ linux-2.6.17.7/kernel/configs.c 2006-08-01 20:29:48.000000000 -0400
22348@@ -89,8 +89,16 @@ static int __init ikconfig_init(void)
22349 struct proc_dir_entry *entry;
22350
22351 /* create the current config file */
22352+#ifdef CONFIG_GRKERNSEC_PROC_ADD
22353+#ifdef CONFIG_GRKERNSEC_PROC_USER
22354+ entry = create_proc_entry("config.gz", S_IFREG | S_IRUSR, &proc_root);
22355+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
22356+ entry = create_proc_entry("config.gz", S_IFREG | S_IRUSR | S_IRGRP, &proc_root);
22357+#endif
22358+#else
22359 entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
22360 &proc_root);
22361+#endif
22362 if (!entry)
22363 return -ENOMEM;
22364
22365diff -urNp linux-2.6.17.7/kernel/exit.c linux-2.6.17.7/kernel/exit.c
22366--- linux-2.6.17.7/kernel/exit.c 2006-07-24 23:36:01.000000000 -0400
22367+++ linux-2.6.17.7/kernel/exit.c 2006-08-01 20:29:48.000000000 -0400
77fa6d7d 22368@@ -41,5 +41,10 @@
22369 #include <linux/vs_network.h>
22370 #include <linux/vs_pid.h>
f1a4f855 22371+#include <linux/grsecurity.h>
22372+
22373+#ifdef CONFIG_GRKERNSEC
22374+extern rwlock_t grsec_exec_file_lock;
22375+#endif
22376
22377 #include <asm/uaccess.h>
22378 #include <asm/unistd.h>
22379@@ -115,6 +120,7 @@ static void __exit_signal(struct task_st
22380
22381 __unhash_process(tsk);
22382
22383+ gr_del_task_from_ip_table(tsk);
22384 tsk->signal = NULL;
22385 tsk->sighand = NULL;
22386 spin_unlock(&sighand->siglock);
22387@@ -287,6 +293,15 @@ static void reparent_to_init(void)
22388 {
22389 write_lock_irq(&tasklist_lock);
22390
22391+#ifdef CONFIG_GRKERNSEC
22392+ write_lock(&grsec_exec_file_lock);
22393+ if (current->exec_file) {
22394+ fput(current->exec_file);
22395+ current->exec_file = NULL;
22396+ }
22397+ write_unlock(&grsec_exec_file_lock);
22398+#endif
22399+
22400 ptrace_unlink(current);
22401 /* Reparent to init */
22402 remove_parent(current);
22403@@ -294,6 +309,8 @@ static void reparent_to_init(void)
22404 current->real_parent = child_reaper;
22405 add_parent(current);
22406
22407+ gr_set_kernel_label(current);
22408+
22409 /* Set the exit signal to SIGCHLD so we signal init on exit */
22410 current->exit_signal = SIGCHLD;
22411
22412@@ -390,6 +407,17 @@ void daemonize(const char *name, ...)
22413 vsnprintf(current->comm, sizeof(current->comm), name, args);
22414 va_end(args);
22415
22416+#ifdef CONFIG_GRKERNSEC
22417+ write_lock(&grsec_exec_file_lock);
22418+ if (current->exec_file) {
22419+ fput(current->exec_file);
22420+ current->exec_file = NULL;
22421+ }
22422+ write_unlock(&grsec_exec_file_lock);
22423+#endif
22424+
22425+ gr_set_kernel_label(current);
22426+
22427 /*
22428 * If we were started as result of loading a module, close all of the
22429 * user space pages. We don't need them, and if we didn't close them
22430@@ -905,9 +933,14 @@ fastcall NORET_TYPE void do_exit(long co
22431 #endif
22432 if (unlikely(tsk->audit_context))
22433 audit_free(tsk);
22434+
22435+ gr_acl_handle_psacct(tsk, code);
22436+ gr_acl_handle_exit();
22437+
22438 exit_mm(tsk);
22439
22440 exit_sem(tsk);
22441+ gr_shm_exit(tsk);
22442 __exit_files(tsk);
22443 __exit_fs(tsk);
22444 exit_namespace(tsk);
22445diff -urNp linux-2.6.17.7/kernel/fork.c linux-2.6.17.7/kernel/fork.c
22446--- linux-2.6.17.7/kernel/fork.c 2006-07-24 23:36:01.000000000 -0400
22447+++ linux-2.6.17.7/kernel/fork.c 2006-08-01 20:29:48.000000000 -0400
22448@@ -44,6 +44,7 @@
77fa6d7d 22449 #include <linux/vs_network.h>
22450 #include <linux/vs_limit.h>
22451 #include <linux/vs_memory.h>
f1a4f855 22452+#include <linux/grsecurity.h>
22453
22454 #include <asm/pgtable.h>
22455 #include <asm/pgalloc.h>
22456@@ -198,8 +199,8 @@ static inline int dup_mmap(struct mm_str
22457 mm->locked_vm = 0;
22458 mm->mmap = NULL;
22459 mm->mmap_cache = NULL;
22460- mm->free_area_cache = oldmm->mmap_base;
22461- mm->cached_hole_size = ~0UL;
22462+ mm->free_area_cache = oldmm->free_area_cache;
22463+ mm->cached_hole_size = oldmm->cached_hole_size;
22464 mm->map_count = 0;
22465 cpus_clear(mm->cpu_vm_mask);
22466 mm->mm_rb = RB_ROOT;
22467@@ -324,7 +325,7 @@ static struct mm_struct * mm_init(struct
22468 spin_lock_init(&mm->page_table_lock);
22469 rwlock_init(&mm->ioctx_list_lock);
22470 mm->ioctx_list = NULL;
22471- mm->free_area_cache = TASK_UNMAPPED_BASE;
22472+ mm->free_area_cache = ~0UL;
22473 mm->cached_hole_size = ~0UL;
22474
22475 if (likely(!mm_alloc_pgd(mm))) {
77fa6d7d 22476@@ -956,6 +957,8 @@ static task_t *copy_process(unsigned lon
22477 if (!vx_nproc_avail(1))
22478 goto bad_fork_cleanup_vm;
f1a4f855 22479
f1a4f855 22480+ gr_learn_resource(p, RLIMIT_NPROC, atomic_read(&p->user->processes), 0);
22481+
22482 if (atomic_read(&p->user->processes) >=
22483 p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
22484 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
22485@@ -1066,6 +1070,8 @@ static task_t *copy_process(unsigned lon
22486 if (retval)
22487 goto bad_fork_cleanup_namespace;
22488
22489+ gr_copy_label(p);
22490+
22491 p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
22492 /*
22493 * Clear TID on mm_release()?
22494@@ -1255,6 +1261,8 @@ bad_fork_cleanup_count:
22495 bad_fork_free:
22496 free_task(p);
22497 fork_out:
22498+ gr_log_forkfail(retval);
22499+
22500 return ERR_PTR(retval);
22501 }
22502
22503@@ -1328,6 +1336,8 @@ long do_fork(unsigned long clone_flags,
22504 if (!IS_ERR(p)) {
22505 struct completion vfork;
22506
22507+ gr_handle_brute_check();
22508+
22509 if (clone_flags & CLONE_VFORK) {
22510 p->vfork_done = &vfork;
22511 init_completion(&vfork);
22512diff -urNp linux-2.6.17.7/kernel/futex.c linux-2.6.17.7/kernel/futex.c
22513--- linux-2.6.17.7/kernel/futex.c 2006-07-24 23:36:01.000000000 -0400
22514+++ linux-2.6.17.7/kernel/futex.c 2006-08-01 20:29:48.000000000 -0400
22515@@ -151,6 +151,11 @@ static int get_futex_key(unsigned long u
22516 struct page *page;
22517 int err;
22518
22519+#ifdef CONFIG_PAX_SEGMEXEC
22520+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (uaddr >= SEGMEXEC_TASK_SIZE))
22521+ return -EFAULT;
22522+#endif
22523+
22524 /*
22525 * The futex address must be "naturally" aligned.
22526 */
22527diff -urNp linux-2.6.17.7/kernel/kallsyms.c linux-2.6.17.7/kernel/kallsyms.c
22528--- linux-2.6.17.7/kernel/kallsyms.c 2006-07-24 23:36:01.000000000 -0400
22529+++ linux-2.6.17.7/kernel/kallsyms.c 2006-08-01 20:29:48.000000000 -0400
22530@@ -301,7 +301,6 @@ static unsigned long get_ksymbol_core(st
22531
22532 static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
22533 {
22534- iter->name[0] = '\0';
22535 iter->nameoff = get_symbol_offset(new_pos);
22536 iter->pos = new_pos;
22537 }
22538@@ -380,7 +379,7 @@ static int kallsyms_open(struct inode *i
22539 struct kallsym_iter *iter;
22540 int ret;
22541
22542- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
22543+ iter = kzalloc(sizeof(*iter), GFP_KERNEL);
22544 if (!iter)
22545 return -ENOMEM;
22546 reset_iter(iter, 0);
22547@@ -411,7 +410,15 @@ static int __init kallsyms_init(void)
22548 {
22549 struct proc_dir_entry *entry;
22550
22551+#ifdef CONFIG_GRKERNSEC_PROC_ADD
22552+#ifdef CONFIG_GRKERNSEC_PROC_USER
22553+ entry = create_proc_entry("kallsyms", S_IFREG | S_IRUSR, NULL);
22554+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
22555+ entry = create_proc_entry("kallsyms", S_IFREG | S_IRUSR | S_IRGRP, NULL);
22556+#endif
22557+#else
22558 entry = create_proc_entry("kallsyms", 0444, NULL);
22559+#endif
22560 if (entry)
22561 entry->proc_fops = &kallsyms_operations;
22562 return 0;
22563diff -urNp linux-2.6.17.7/kernel/kprobes.c linux-2.6.17.7/kernel/kprobes.c
22564--- linux-2.6.17.7/kernel/kprobes.c 2006-07-24 23:36:01.000000000 -0400
22565+++ linux-2.6.17.7/kernel/kprobes.c 2006-08-01 20:29:48.000000000 -0400
22566@@ -106,7 +106,7 @@ kprobe_opcode_t __kprobes *get_insn_slot
22567 * kernel image and loaded module images reside. This is required
22568 * so x86_64 can correctly handle the %rip-relative fixups.
22569 */
22570- kip->insns = module_alloc(PAGE_SIZE);
22571+ kip->insns = module_alloc_exec(PAGE_SIZE);
22572 if (!kip->insns) {
22573 kfree(kip);
22574 return NULL;
22575diff -urNp linux-2.6.17.7/kernel/module.c linux-2.6.17.7/kernel/module.c
22576--- linux-2.6.17.7/kernel/module.c 2006-07-24 23:36:01.000000000 -0400
22577+++ linux-2.6.17.7/kernel/module.c 2006-08-01 20:29:48.000000000 -0400
22578@@ -40,10 +40,15 @@
22579 #include <linux/string.h>
22580 #include <linux/sched.h>
22581 #include <linux/mutex.h>
22582+#include <linux/kallsyms.h>
22583 #include <asm/uaccess.h>
22584 #include <asm/semaphore.h>
22585 #include <asm/cacheflush.h>
22586
22587+#ifdef CONFIG_PAX_KERNEXEC
22588+#include <asm/desc.h>
22589+#endif
22590+
22591 #if 0
22592 #define DEBUGP printk
22593 #else
22594@@ -66,6 +71,8 @@ static LIST_HEAD(modules);
22595
22596 static BLOCKING_NOTIFIER_HEAD(module_notify_list);
22597
22598+extern int gr_check_modstop(void);
22599+
22600 int register_module_notifier(struct notifier_block * nb)
22601 {
22602 return blocking_notifier_chain_register(&module_notify_list, nb);
22603@@ -594,6 +601,9 @@ sys_delete_module(const char __user *nam
22604 char name[MODULE_NAME_LEN];
22605 int ret, forced = 0;
22606
22607+ if (gr_check_modstop())
22608+ return -EPERM;
22609+
22610 if (!capable(CAP_SYS_MODULE))
22611 return -EPERM;
22612
22613@@ -1058,13 +1068,15 @@ static void free_module(struct module *m
22614 module_unload_free(mod);
22615
22616 /* This may be NULL, but that's OK */
22617- module_free(mod, mod->module_init);
22618+ module_free(mod, mod->module_init_rw);
22619+ module_free_exec(mod, mod->module_init_rx);
22620 kfree(mod->args);
22621 if (mod->percpu)
22622 percpu_modfree(mod->percpu);
22623
22624 /* Finally, free the core (containing the module structure) */
22625- module_free(mod, mod->module_core);
22626+ module_free_exec(mod, mod->module_core_rx);
22627+ module_free(mod, mod->module_core_rw);
22628 }
22629
22630 void *__symbol_get(const char *symbol)
22631@@ -1221,11 +1233,14 @@ static void layout_sections(struct modul
22632 || strncmp(secstrings + s->sh_name,
22633 ".init", 5) == 0)
22634 continue;
22635- s->sh_entsize = get_offset(&mod->core_size, s);
22636+ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
22637+ s->sh_entsize = get_offset(&mod->core_size_rw, s);
22638+ else
22639+ s->sh_entsize = get_offset(&mod->core_size_rx, s);
22640 DEBUGP("\t%s\n", secstrings + s->sh_name);
22641 }
22642 if (m == 0)
22643- mod->core_text_size = mod->core_size;
22644+ mod->core_size_rx = mod->core_size_rx;
22645 }
22646
22647 DEBUGP("Init section allocation order:\n");
22648@@ -1239,12 +1254,15 @@ static void layout_sections(struct modul
22649 || strncmp(secstrings + s->sh_name,
22650 ".init", 5) != 0)
22651 continue;
22652- s->sh_entsize = (get_offset(&mod->init_size, s)
22653- | INIT_OFFSET_MASK);
22654+ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
22655+ s->sh_entsize = get_offset(&mod->init_size_rw, s);
22656+ else
22657+ s->sh_entsize = get_offset(&mod->init_size_rx, s);
22658+ s->sh_entsize |= INIT_OFFSET_MASK;
22659 DEBUGP("\t%s\n", secstrings + s->sh_name);
22660 }
22661 if (m == 0)
22662- mod->init_text_size = mod->init_size;
22663+ mod->init_size_rx = mod->init_size_rx;
22664 }
22665 }
22666
22667@@ -1419,6 +1437,10 @@ static struct module *load_module(void _
22668 struct exception_table_entry *extable;
22669 mm_segment_t old_fs;
22670
22671+#ifdef CONFIG_PAX_KERNEXEC
22672+ unsigned long cr0;
22673+#endif
22674+
22675 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
22676 umod, len, uargs);
22677 if (len < sizeof(*hdr))
22678@@ -1568,21 +1590,57 @@ static struct module *load_module(void _
22679 layout_sections(mod, hdr, sechdrs, secstrings);
22680
22681 /* Do the allocs. */
22682- ptr = module_alloc(mod->core_size);
22683+ ptr = module_alloc(mod->core_size_rw);
22684 if (!ptr) {
22685 err = -ENOMEM;
22686 goto free_percpu;
22687 }
22688- memset(ptr, 0, mod->core_size);
22689- mod->module_core = ptr;
22690+ memset(ptr, 0, mod->core_size_rw);
22691+ mod->module_core_rw = ptr;
22692+
22693+ ptr = module_alloc(mod->init_size_rw);
22694+ if (!ptr && mod->init_size_rw) {
22695+ err = -ENOMEM;
22696+ goto free_core_rw;
22697+ }
22698+ memset(ptr, 0, mod->init_size_rw);
22699+ mod->module_init_rw = ptr;
22700+
22701+ ptr = module_alloc_exec(mod->core_size_rx);
22702+ if (!ptr) {
22703+ err = -ENOMEM;
22704+ goto free_init_rw;
22705+ }
22706+
22707+#ifdef CONFIG_PAX_KERNEXEC
22708+ pax_open_kernel(cr0);
22709+#endif
22710+
22711+ memset(ptr, 0, mod->core_size_rx);
22712+
22713+#ifdef CONFIG_PAX_KERNEXEC
22714+ pax_close_kernel(cr0);
22715+#endif
22716+
22717+ mod->module_core_rx = ptr;
22718
22719- ptr = module_alloc(mod->init_size);
22720- if (!ptr && mod->init_size) {
22721+ ptr = module_alloc_exec(mod->init_size_rx);
22722+ if (!ptr && mod->init_size_rx) {
22723 err = -ENOMEM;
22724- goto free_core;
22725+ goto free_core_rx;
22726 }
22727- memset(ptr, 0, mod->init_size);
22728- mod->module_init = ptr;
22729+
22730+#ifdef CONFIG_PAX_KERNEXEC
22731+ pax_open_kernel(cr0);
22732+#endif
22733+
22734+ memset(ptr, 0, mod->init_size_rx);
22735+
22736+#ifdef CONFIG_PAX_KERNEXEC
22737+ pax_close_kernel(cr0);
22738+#endif
22739+
22740+ mod->module_init_rx = ptr;
22741
22742 /* Transfer each section which specifies SHF_ALLOC */
22743 DEBUGP("final section addresses:\n");
22744@@ -1592,17 +1650,44 @@ static struct module *load_module(void _
22745 if (!(sechdrs[i].sh_flags & SHF_ALLOC))
22746 continue;
22747
22748- if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK)
22749- dest = mod->module_init
22750- + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
22751- else
22752- dest = mod->module_core + sechdrs[i].sh_entsize;
22753+ if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK) {
22754+ if ((sechdrs[i].sh_flags & SHF_WRITE) || !(sechdrs[i].sh_flags & SHF_ALLOC))
22755+ dest = mod->module_init_rw
22756+ + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
22757+ else
22758+ dest = mod->module_init_rx
22759+ + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
22760+ } else {
22761+ if ((sechdrs[i].sh_flags & SHF_WRITE) || !(sechdrs[i].sh_flags & SHF_ALLOC))
22762+ dest = mod->module_core_rw + sechdrs[i].sh_entsize;
22763+ else
22764+ dest = mod->module_core_rx + sechdrs[i].sh_entsize;
22765+ }
22766+
22767+ if (sechdrs[i].sh_type != SHT_NOBITS) {
22768+
22769+#ifdef CONFIG_PAX_KERNEXEC
22770+ if (!(sechdrs[i].sh_flags & SHF_WRITE) && (sechdrs[i].sh_flags & SHF_ALLOC))
22771+ pax_open_kernel(cr0);
22772+#endif
22773+
22774+ memcpy(dest, (void *)sechdrs[i].sh_addr, sechdrs[i].sh_size);
22775
22776- if (sechdrs[i].sh_type != SHT_NOBITS)
22777- memcpy(dest, (void *)sechdrs[i].sh_addr,
22778- sechdrs[i].sh_size);
22779+#ifdef CONFIG_PAX_KERNEXEC
22780+ if (!(sechdrs[i].sh_flags & SHF_WRITE) && (sechdrs[i].sh_flags & SHF_ALLOC))
22781+ pax_close_kernel(cr0);
22782+#endif
22783+
22784+ }
22785 /* Update sh_addr to point to copy in image. */
22786- sechdrs[i].sh_addr = (unsigned long)dest;
22787+
22788+#ifdef CONFIG_PAX_KERNEXEC
22789+ if (sechdrs[i].sh_flags & SHF_EXECINSTR)
22790+ sechdrs[i].sh_addr = (unsigned long)dest - __KERNEL_TEXT_OFFSET;
22791+ else
22792+#endif
22793+
22794+ sechdrs[i].sh_addr = (unsigned long)dest;
22795 DEBUGP("\t0x%lx %s\n", sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name);
22796 }
22797 /* Module has been moved. */
22798@@ -1623,8 +1708,18 @@ static struct module *load_module(void _
22799 setup_modinfo(mod, sechdrs, infoindex);
22800
22801 /* Fix up syms, so that st_value is a pointer to location. */
22802+
22803+#ifdef CONFIG_PAX_KERNEXEC
22804+ pax_open_kernel(cr0);
22805+#endif
22806+
22807 err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
22808 mod);
22809+
22810+#ifdef CONFIG_PAX_KERNEXEC
22811+ pax_close_kernel(cr0);
22812+#endif
22813+
22814 if (err < 0)
22815 goto cleanup;
22816
22817@@ -1666,11 +1761,20 @@ static struct module *load_module(void _
22818 if (!(sechdrs[info].sh_flags & SHF_ALLOC))
22819 continue;
22820
22821+#ifdef CONFIG_PAX_KERNEXEC
22822+ pax_open_kernel(cr0);
22823+#endif
22824+
22825 if (sechdrs[i].sh_type == SHT_REL)
22826 err = apply_relocate(sechdrs, strtab, symindex, i,mod);
22827 else if (sechdrs[i].sh_type == SHT_RELA)
22828 err = apply_relocate_add(sechdrs, strtab, symindex, i,
22829 mod);
22830+
22831+#ifdef CONFIG_PAX_KERNEXEC
22832+ pax_close_kernel(cr0);
22833+#endif
22834+
22835 if (err < 0)
22836 goto cleanup;
22837 }
22838@@ -1684,14 +1788,31 @@ static struct module *load_module(void _
22839 /* Set up and sort exception table */
22840 mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
22841 mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
22842+
22843+#ifdef CONFIG_PAX_KERNEXEC
22844+ pax_open_kernel(cr0);
22845+#endif
22846+
22847 sort_extable(extable, extable + mod->num_exentries);
22848
22849+#ifdef CONFIG_PAX_KERNEXEC
22850+ pax_close_kernel(cr0);
22851+#endif
22852+
22853 /* Finally, copy percpu area over. */
22854 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
22855 sechdrs[pcpuindex].sh_size);
22856
22857+#ifdef CONFIG_PAX_KERNEXEC
22858+ pax_open_kernel(cr0);
22859+#endif
22860+
22861 add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
22862
22863+#ifdef CONFIG_PAX_KERNEXEC
22864+ pax_close_kernel(cr0);
22865+#endif
22866+
22867 err = module_finalize(hdr, sechdrs, mod);
22868 if (err < 0)
22869 goto cleanup;
22870@@ -1705,12 +1826,12 @@ static struct module *load_module(void _
22871 * Do it before processing of module parameters, so the module
22872 * can provide parameter accessor functions of its own.
22873 */
22874- if (mod->module_init)
22875- flush_icache_range((unsigned long)mod->module_init,
22876- (unsigned long)mod->module_init
22877- + mod->init_size);
22878- flush_icache_range((unsigned long)mod->module_core,
22879- (unsigned long)mod->module_core + mod->core_size);
22880+ if (mod->module_init_rx)
22881+ flush_icache_range((unsigned long)mod->module_init_rx,
22882+ (unsigned long)mod->module_init_rx
22883+ + mod->init_size_rx);
22884+ flush_icache_range((unsigned long)mod->module_core_rx,
22885+ (unsigned long)mod->module_core_rx + mod->core_size_rx);
22886
22887 set_fs(old_fs);
22888
22889@@ -1748,9 +1869,13 @@ static struct module *load_module(void _
22890 module_arch_cleanup(mod);
22891 cleanup:
22892 module_unload_free(mod);
22893- module_free(mod, mod->module_init);
22894- free_core:
22895- module_free(mod, mod->module_core);
22896+ module_free_exec(mod, mod->module_init_rx);
22897+ free_core_rx:
22898+ module_free_exec(mod, mod->module_core_rx);
22899+ free_init_rw:
22900+ module_free(mod, mod->module_init_rw);
22901+ free_core_rw:
22902+ module_free(mod, mod->module_core_rw);
22903 free_percpu:
22904 if (percpu)
22905 percpu_modfree(percpu);
22906@@ -1786,6 +1911,9 @@ sys_init_module(void __user *umod,
22907 struct module *mod;
22908 int ret = 0;
22909
22910+ if (gr_check_modstop())
22911+ return -EPERM;
22912+
22913 /* Must have permission */
22914 if (!capable(CAP_SYS_MODULE))
22915 return -EPERM;
22916@@ -1836,10 +1964,12 @@ sys_init_module(void __user *umod,
22917 mod->state = MODULE_STATE_LIVE;
22918 /* Drop initial reference. */
22919 module_put(mod);
22920- module_free(mod, mod->module_init);
22921- mod->module_init = NULL;
22922- mod->init_size = 0;
22923- mod->init_text_size = 0;
22924+ module_free(mod, mod->module_init_rw);
22925+ module_free_exec(mod, mod->module_init_rx);
22926+ mod->module_init_rw = NULL;
22927+ mod->module_init_rx = NULL;
22928+ mod->init_size_rw = 0;
22929+ mod->init_size_rx = 0;
22930 mutex_unlock(&module_mutex);
22931
22932 return 0;
22933@@ -1870,10 +2000,14 @@ static const char *get_ksymbol(struct mo
22934 unsigned long nextval;
22935
22936 /* At worse, next value is at end of module */
22937- if (within(addr, mod->module_init, mod->init_size))
22938- nextval = (unsigned long)mod->module_init+mod->init_text_size;
22939- else
22940- nextval = (unsigned long)mod->module_core+mod->core_text_size;
22941+ if (within(addr, mod->module_init_rx, mod->init_size_rx))
22942+ nextval = (unsigned long)mod->module_init_rw;
22943+ else if (within(addr, mod->module_init_rw, mod->init_size_rw))
22944+ nextval = (unsigned long)mod->module_core_rx;
22945+ else if (within(addr, mod->module_core_rx, mod->core_size_rx))
22946+ nextval = (unsigned long)mod->module_core_rw;
22947+ else
22948+ nextval = (unsigned long)mod->module_core_rw+mod->core_size_rw;
22949
22950 /* Scan for closest preceeding symbol, and next symbol. (ELF
22951 starts real symbols at 1). */
22952@@ -1914,8 +2048,10 @@ const char *module_address_lookup(unsign
22953 struct module *mod;
22954
22955 list_for_each_entry(mod, &modules, list) {
22956- if (within(addr, mod->module_init, mod->init_size)
22957- || within(addr, mod->module_core, mod->core_size)) {
22958+ if (within(addr, mod->module_init_rx, mod->init_size_rx)
22959+ || within(addr, mod->module_init_rw, mod->init_size_rw)
22960+ || within(addr, mod->module_core_rx, mod->core_size_rx)
22961+ || within(addr, mod->module_core_rw, mod->core_size_rw)) {
22962 *modname = mod->name;
22963 return get_ksymbol(mod, addr, size, offset);
22964 }
22965@@ -1926,7 +2062,7 @@ const char *module_address_lookup(unsign
22966 struct module *module_get_kallsym(unsigned int symnum,
22967 unsigned long *value,
22968 char *type,
22969- char namebuf[128])
22970+ char namebuf[KSYM_NAME_LEN+1])
22971 {
22972 struct module *mod;
22973
22974@@ -1937,7 +2073,7 @@ struct module *module_get_kallsym(unsign
22975 *type = mod->symtab[symnum].st_info;
22976 strncpy(namebuf,
22977 mod->strtab + mod->symtab[symnum].st_name,
22978- 127);
22979+ KSYM_NAME_LEN);
22980 mutex_unlock(&module_mutex);
22981 return mod;
22982 }
22983@@ -2014,7 +2150,7 @@ static int m_show(struct seq_file *m, vo
22984 {
22985 struct module *mod = list_entry(p, struct module, list);
22986 seq_printf(m, "%s %lu",
22987- mod->name, mod->init_size + mod->core_size);
22988+ mod->name, mod->init_size_rx + mod->init_size_rw + mod->core_size_rx + mod->core_size_rw);
22989 print_unload_info(m, mod);
22990
22991 /* Informative for users. */
22992@@ -2023,7 +2159,7 @@ static int m_show(struct seq_file *m, vo
22993 mod->state == MODULE_STATE_COMING ? "Loading":
22994 "Live");
22995 /* Used by oprofile and other similar tools. */
22996- seq_printf(m, " 0x%p", mod->module_core);
22997+ seq_printf(m, " 0x%p 0x%p", mod->module_core_rx, mod->module_core_rw);
22998
22999 seq_printf(m, "\n");
23000 return 0;
23001@@ -2071,9 +2207,13 @@ struct module *__module_text_address(uns
23002 {
23003 struct module *mod;
23004
23005+#ifdef CONFIG_PAX_KERNEXEC
23006+ addr += __KERNEL_TEXT_OFFSET;
23007+#endif
23008+
23009 list_for_each_entry(mod, &modules, list)
23010- if (within(addr, mod->module_init, mod->init_text_size)
23011- || within(addr, mod->module_core, mod->core_text_size))
23012+ if (within(addr, mod->module_init_rx, mod->init_size_rx)
23013+ || within(addr, mod->module_core_rx, mod->core_size_rx))
23014 return mod;
23015 return NULL;
23016 }
23017diff -urNp linux-2.6.17.7/kernel/pid.c linux-2.6.17.7/kernel/pid.c
23018--- linux-2.6.17.7/kernel/pid.c 2006-07-24 23:36:01.000000000 -0400
23019+++ linux-2.6.17.7/kernel/pid.c 2006-08-01 20:29:48.000000000 -0400
23020@@ -26,6 +26,7 @@
23021 #include <linux/init.h>
23022 #include <linux/bootmem.h>
23023 #include <linux/hash.h>
23024+#include <linux/grsecurity.h>
23025
23026 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
23027 static struct hlist_head *pid_hash;
23028@@ -90,7 +91,9 @@ static int alloc_pidmap(void)
23029 int i, offset, max_scan, pid, last = last_pid;
23030 pidmap_t *map;
23031
23032- pid = last + 1;
23033+ pid = gr_random_pid();
23034+ if (!pid)
23035+ pid = last_pid + 1;
23036 if (pid >= pid_max)
23037 pid = RESERVED_PIDS;
23038 offset = pid & BITS_PER_PAGE_MASK;
23039@@ -269,7 +272,14 @@ struct task_struct * fastcall pid_task(s
23040 */
23041 task_t *find_task_by_pid_type(int type, int nr)
23042 {
23043- return pid_task(find_pid(nr), type);
23044+ task_t *task;
23045+
23046+ task = pid_task(find_pid(nr), type);
23047+
23048+ if (gr_pid_is_chrooted(task))
23049+ return NULL;
23050+
23051+ return task;
23052 }
23053
23054 EXPORT_SYMBOL(find_task_by_pid_type);
23055diff -urNp linux-2.6.17.7/kernel/posix-cpu-timers.c linux-2.6.17.7/kernel/posix-cpu-timers.c
23056--- linux-2.6.17.7/kernel/posix-cpu-timers.c 2006-07-24 23:36:01.000000000 -0400
23057+++ linux-2.6.17.7/kernel/posix-cpu-timers.c 2006-08-01 20:29:48.000000000 -0400
23058@@ -6,6 +6,7 @@
f1a4f855 23059 #include <asm/uaccess.h>
23060 #include <linux/errno.h>
77fa6d7d 23061 #include <linux/vs_pid.h>
f1a4f855 23062+#include <linux/grsecurity.h>
23063
23064 static int check_clock(const clockid_t which_clock)
23065 {
23066@@ -1125,6 +1126,7 @@ static void check_process_timers(struct
23067 __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
23068 return;
23069 }
23070+ gr_learn_resource(tsk, RLIMIT_CPU, psecs, 1);
23071 if (psecs >= sig->rlim[RLIMIT_CPU].rlim_cur) {
23072 /*
23073 * At the soft limit, send a SIGXCPU every second.
23074diff -urNp linux-2.6.17.7/kernel/printk.c linux-2.6.17.7/kernel/printk.c
23075--- linux-2.6.17.7/kernel/printk.c 2006-07-24 23:36:01.000000000 -0400
23076+++ linux-2.6.17.7/kernel/printk.c 2006-08-01 20:29:48.000000000 -0400
77fa6d7d 23077@@ -31,7 +31,8 @@
f1a4f855 23078 #include <linux/bootmem.h>
23079 #include <linux/syscalls.h>
77fa6d7d 23080 #include <linux/vs_context.h>
23081 #include <linux/vserver/cvirt.h>
f1a4f855 23082+#include <linux/grsecurity.h>
23083
23084 #include <asm/uaccess.h>
23085
23086@@ -185,6 +186,11 @@ int do_syslog(int type, char __user *buf
23087 char c;
23088 int error = 0;
23089
23090+#ifdef CONFIG_GRKERNSEC_DMESG
23091+ if (grsec_enable_dmesg && !capable(CAP_SYS_ADMIN))
23092+ return -EPERM;
23093+#endif
23094+
23095 error = security_syslog(type);
23096 if (error)
23097 return error;
23098diff -urNp linux-2.6.17.7/kernel/ptrace.c linux-2.6.17.7/kernel/ptrace.c
23099--- linux-2.6.17.7/kernel/ptrace.c 2006-07-24 23:36:01.000000000 -0400
23100+++ linux-2.6.17.7/kernel/ptrace.c 2006-08-01 20:29:48.000000000 -0400
23101@@ -18,6 +18,7 @@
f1a4f855 23102 #include <linux/security.h>
23103 #include <linux/signal.h>
77fa6d7d 23104 #include <linux/vs_pid.h>
f1a4f855 23105+#include <linux/grsecurity.h>
23106
23107 #include <asm/pgtable.h>
23108 #include <asm/uaccess.h>
23109@@ -127,10 +128,10 @@ static int may_attach(struct task_struct
23110 (current->uid != task->uid) ||
23111 (current->gid != task->egid) ||
23112 (current->gid != task->sgid) ||
23113- (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
23114+ (current->gid != task->gid)) && !capable_nolog(CAP_SYS_PTRACE))
23115 return -EPERM;
23116 smp_rmb();
23117- if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
23118+ if (!task->mm->dumpable && !capable_nolog(CAP_SYS_PTRACE))
23119 return -EPERM;
23120
23121 return security_ptrace(current, task);
23122@@ -515,6 +516,11 @@ asmlinkage long sys_ptrace(long request,
23123 if (ret < 0)
23124 goto out_put_task_struct;
23125
23126+ if (gr_handle_ptrace(child, request)) {
23127+ ret = -EPERM;
23128+ goto out_put_task_struct;
23129+ }
23130+
23131 ret = arch_ptrace(child, request, addr, data);
23132 if (ret < 0)
23133 goto out_put_task_struct;
23134diff -urNp linux-2.6.17.7/kernel/resource.c linux-2.6.17.7/kernel/resource.c
23135--- linux-2.6.17.7/kernel/resource.c 2006-07-24 23:36:01.000000000 -0400
23136+++ linux-2.6.17.7/kernel/resource.c 2006-08-01 20:29:48.000000000 -0400
23137@@ -136,10 +136,27 @@ static int __init ioresources_init(void)
23138 {
23139 struct proc_dir_entry *entry;
23140
23141+#ifdef CONFIG_GRKERNSEC_PROC_ADD
23142+#ifdef CONFIG_GRKERNSEC_PROC_USER
23143+ entry = create_proc_entry("ioports", S_IRUSR, NULL);
23144+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
23145+ entry = create_proc_entry("ioports", S_IRUSR | S_IRGRP, NULL);
23146+#endif
23147+#else
23148 entry = create_proc_entry("ioports", 0, NULL);
23149+#endif
23150 if (entry)
23151 entry->proc_fops = &proc_ioports_operations;
23152+
23153+#ifdef CONFIG_GRKERNSEC_PROC_ADD
23154+#ifdef CONFIG_GRKERNSEC_PROC_USER
23155+ entry = create_proc_entry("iomem", S_IRUSR, NULL);
23156+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
23157+ entry = create_proc_entry("iomem", S_IRUSR | S_IRGRP, NULL);
23158+#endif
23159+#else
23160 entry = create_proc_entry("iomem", 0, NULL);
23161+#endif
23162 if (entry)
23163 entry->proc_fops = &proc_iomem_operations;
23164 return 0;
23165diff -urNp linux-2.6.17.7/kernel/sched.c linux-2.6.17.7/kernel/sched.c
23166--- linux-2.6.17.7/kernel/sched.c 2006-07-24 23:36:01.000000000 -0400
23167+++ linux-2.6.17.7/kernel/sched.c 2006-08-01 20:29:48.000000000 -0400
23168@@ -50,6 +50,7 @@
23169 #include <linux/times.h>
23170 #include <linux/acct.h>
23171 #include <linux/kprobes.h>
23172+#include <linux/grsecurity.h>
23173 #include <asm/tlb.h>
23174
23175 #include <asm/unistd.h>
23176@@ -3565,7 +3566,8 @@ asmlinkage long sys_nice(int increment)
23177 if (nice > 19)
23178 nice = 19;
23179
23180- if (increment < 0 && !can_nice(current, nice))
23181+ if (increment < 0 && (!can_nice(current, nice) ||
23182+ gr_handle_chroot_nice()))
77fa6d7d 23183 return vx_flags(VXF_IGNEG_NICE, 0) ? 0 : -EPERM;
f1a4f855 23184
23185 retval = security_task_setnice(current, nice);
23186diff -urNp linux-2.6.17.7/kernel/signal.c linux-2.6.17.7/kernel/signal.c
23187--- linux-2.6.17.7/kernel/signal.c 2006-07-24 23:36:01.000000000 -0400
23188+++ linux-2.6.17.7/kernel/signal.c 2006-08-01 20:29:48.000000000 -0400
23189@@ -25,6 +25,7 @@
f1a4f855 23190 #include <linux/audit.h>
23191 #include <linux/capability.h>
77fa6d7d 23192 #include <linux/vs_pid.h>
f1a4f855 23193+#include <linux/grsecurity.h>
23194 #include <asm/param.h>
23195 #include <asm/uaccess.h>
23196 #include <asm/unistd.h>
77fa6d7d 23197@@ -583,11 +583,11 @@ static int check_kill_permission(int sig
23198 (!is_si_special(info) && SI_FROMUSER(info)));
23199
f1a4f855 23200 error = -EPERM;
77fa6d7d 23201- if (user && ((sig != SIGCONT) ||
23202+ if (user && ((((sig != SIGCONT) ||
f1a4f855 23203 (current->signal->session != t->signal->session))
23204 && (current->euid ^ t->suid) && (current->euid ^ t->uid)
23205 && (current->uid ^ t->suid) && (current->uid ^ t->uid)
23206- && !capable(CAP_KILL))
23207+ && !capable(CAP_KILL)) || gr_handle_signal(t, sig)))
23208 return error;
23209
77fa6d7d 23210 error = -ESRCH;
23211@@ -595,8 +595,10 @@ static int check_kill_permission(int sig
23212 return error;
23213
f1a4f855 23214 error = security_task_kill(t, info, sig);
23215- if (!error)
23216+ if (!error) {
23217 audit_signal_info(sig, t); /* Let audit system see the signal */
23218+ gr_log_signal(sig, t);
23219+ }
23220 return error;
23221 }
23222
23223@@ -764,7 +767,7 @@ out_set:
23224 (((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
23225
23226
23227-static int
23228+int
23229 specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
23230 {
23231 int ret = 0;
23232@@ -809,6 +812,10 @@ force_sig_info(int sig, struct siginfo *
23233 }
23234 recalc_sigpending_tsk(t);
23235 ret = specific_send_sig_info(sig, info, t);
23236+
23237+ gr_log_signal(sig, t);
23238+ gr_handle_crash(t, sig);
23239+
23240 spin_unlock_irqrestore(&t->sighand->siglock, flags);
23241
23242 return ret;
23243diff -urNp linux-2.6.17.7/kernel/sys.c linux-2.6.17.7/kernel/sys.c
23244--- linux-2.6.17.7/kernel/sys.c 2006-07-24 23:36:01.000000000 -0400
23245+++ linux-2.6.17.7/kernel/sys.c 2006-08-01 20:29:48.000000000 -0400
23246@@ -30,6 +30,7 @@
f1a4f855 23247 #include <linux/cn_proc.h>
77fa6d7d 23248 #include <linux/vs_cvirt.h>
23249 #include <linux/vs_pid.h>
f1a4f855 23250+#include <linux/grsecurity.h>
23251
23252 #include <linux/compat.h>
23253 #include <linux/syscalls.h>
23254@@ -442,6 +443,12 @@ static int set_one_prio(struct task_stru
23255 error = -EACCES;
23256 goto out;
23257 }
23258+
23259+ if (gr_handle_chroot_setpriority(p, niceval)) {
23260+ error = -EACCES;
23261+ goto out;
23262+ }
23263+
23264 no_nice = security_task_setnice(p, niceval);
23265 if (no_nice) {
23266 error = no_nice;
23267@@ -831,6 +838,9 @@ asmlinkage long sys_setregid(gid_t rgid,
23268 if (rgid != (gid_t) -1 ||
23269 (egid != (gid_t) -1 && egid != old_rgid))
23270 current->sgid = new_egid;
23271+
23272+ gr_set_role_label(current, current->uid, new_rgid);
23273+
23274 current->fsgid = new_egid;
23275 current->egid = new_egid;
23276 current->gid = new_rgid;
23277@@ -860,6 +870,9 @@ asmlinkage long sys_setgid(gid_t gid)
23278 current->mm->dumpable = suid_dumpable;
23279 smp_wmb();
23280 }
23281+
23282+ gr_set_role_label(current, current->uid, gid);
23283+
23284 current->gid = current->egid = current->sgid = current->fsgid = gid;
23285 }
23286 else if ((gid == current->gid) || (gid == current->sgid))
23287@@ -901,6 +914,9 @@ static int set_user(uid_t new_ruid, int
23288 current->mm->dumpable = suid_dumpable;
23289 smp_wmb();
23290 }
23291+
23292+ gr_set_role_label(current, new_ruid, current->gid);
23293+
23294 current->uid = new_ruid;
23295 return 0;
23296 }
23297@@ -1004,6 +1020,9 @@ asmlinkage long sys_setuid(uid_t uid)
23298 } else if ((uid != current->uid) && (uid != new_suid))
23299 return -EPERM;
23300
23301+ if (gr_check_crash_uid(uid))
23302+ return -EPERM;
23303+
23304 if (old_euid != uid)
23305 {
23306 current->mm->dumpable = suid_dumpable;
23307@@ -1109,8 +1128,10 @@ asmlinkage long sys_setresgid(gid_t rgid
23308 current->egid = egid;
23309 }
23310 current->fsgid = current->egid;
23311- if (rgid != (gid_t) -1)
23312+ if (rgid != (gid_t) -1) {
23313+ gr_set_role_label(current, current->uid, rgid);
23314 current->gid = rgid;
23315+ }
23316 if (sgid != (gid_t) -1)
23317 current->sgid = sgid;
23318
23319diff -urNp linux-2.6.17.7/kernel/sysctl.c linux-2.6.17.7/kernel/sysctl.c
23320--- linux-2.6.17.7/kernel/sysctl.c 2006-07-24 23:36:01.000000000 -0400
23321+++ linux-2.6.17.7/kernel/sysctl.c 2006-08-01 20:29:48.000000000 -0400
23322@@ -54,6 +54,14 @@ extern int proc_nr_files(ctl_table *tabl
23323 void __user *buffer, size_t *lenp, loff_t *ppos);
23324
23325 #if defined(CONFIG_SYSCTL)
23326+#include <linux/grsecurity.h>
23327+#include <linux/grinternal.h>
23328+
23329+extern __u32 gr_handle_sysctl(const ctl_table *table, const void *oldval,
23330+ const void *newval);
23331+extern int gr_handle_sysctl_mod(const char *dirname, const char *name,
23332+ const int op);
23333+extern int gr_handle_chroot_sysctl(const int op);
23334
23335 /* External variables not in a header file. */
23336 extern int C_A_D;
23337@@ -157,6 +165,22 @@ extern ctl_table inotify_table[];
23338 #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
23339 int sysctl_legacy_va_layout;
23340 #endif
23341+extern ctl_table grsecurity_table[];
23342+
23343+#ifdef CONFIG_PAX_SOFTMODE
23344+static ctl_table pax_table[] = {
23345+ {
23346+ .ctl_name = PAX_SOFTMODE,
23347+ .procname = "softmode",
23348+ .data = &pax_softmode,
23349+ .maxlen = sizeof(unsigned int),
23350+ .mode = 0600,
23351+ .proc_handler = &proc_dointvec,
23352+ },
23353+
23354+ { .ctl_name = 0 }
23355+};
23356+#endif
23357
23358 /* /proc declarations: */
23359
23360@@ -683,6 +707,24 @@ static ctl_table kern_table[] = {
23361 .proc_handler = &proc_dointvec,
23362 },
23363 #endif
23364+
23365+#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP)
23366+ {
23367+ .ctl_name = KERN_GRSECURITY,
23368+ .procname = "grsecurity",
23369+ .mode = 0500,
23370+ .child = grsecurity_table,
23371+ },
23372+#endif
23373+
23374+#ifdef CONFIG_PAX_SOFTMODE
23375+ {
23376+ .ctl_name = KERN_PAX,
23377+ .procname = "pax",
23378+ .mode = 0500,
23379+ .child = pax_table,
23380+ },
23381+#endif
23382 { .ctl_name = 0 }
23383 };
23384
23385@@ -1180,6 +1222,10 @@ static int test_perm(int mode, int op)
23386 static inline int ctl_perm(ctl_table *table, int op)
23387 {
23388 int error;
23389+ if (table->de && gr_handle_sysctl_mod(table->de->parent->name, table->de->name, op))
23390+ return -EACCES;
23391+ if (gr_handle_chroot_sysctl(op))
23392+ return -EACCES;
23393 error = security_sysctl(table, op);
23394 if (error)
23395 return error;
23396@@ -1216,6 +1262,10 @@ repeat:
23397 table = table->child;
23398 goto repeat;
23399 }
23400+
23401+ if (!gr_handle_sysctl(table, oldval, newval))
23402+ return -EACCES;
23403+
23404 error = do_sysctl_strategy(table, name, nlen,
23405 oldval, oldlenp,
23406 newval, newlen, context);
23407diff -urNp linux-2.6.17.7/kernel/time.c linux-2.6.17.7/kernel/time.c
23408--- linux-2.6.17.7/kernel/time.c 2006-07-24 23:36:01.000000000 -0400
23409+++ linux-2.6.17.7/kernel/time.c 2006-08-01 20:29:48.000000000 -0400
23410@@ -36,6 +36,7 @@
23411 #include <linux/security.h>
23412 #include <linux/fs.h>
23413 #include <linux/module.h>
23414+#include <linux/grsecurity.h>
23415
23416 #include <asm/uaccess.h>
23417 #include <asm/unistd.h>
23418@@ -93,6 +94,9 @@ asmlinkage long sys_stime(time_t __user
23419 return err;
23420
77fa6d7d 23421 vx_settimeofday(&tv);
f1a4f855 23422+
23423+ gr_log_timechange();
23424+
23425 return 0;
23426 }
23427
23428@@ -199,6 +203,8 @@ asmlinkage long sys_settimeofday(struct
23429 return -EFAULT;
23430 }
23431
23432+ gr_log_timechange();
23433+
23434 return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
23435 }
23436
f1a4f855 23437diff -urNp linux-2.6.17.7/mm/filemap.c linux-2.6.17.7/mm/filemap.c
23438--- linux-2.6.17.7/mm/filemap.c 2006-07-24 23:36:01.000000000 -0400
23439+++ linux-2.6.17.7/mm/filemap.c 2006-08-01 20:29:48.000000000 -0400
23440@@ -30,6 +30,7 @@
23441 #include <linux/security.h>
23442 #include <linux/syscalls.h>
23443 #include <linux/cpuset.h>
23444+#include <linux/grsecurity.h>
23445 #include "filemap.h"
23446 #include "internal.h"
23447
23448@@ -1650,7 +1651,13 @@ int generic_file_mmap(struct file * file
23449 struct address_space *mapping = file->f_mapping;
23450
23451 if (!mapping->a_ops->readpage)
23452- return -ENOEXEC;
23453+ return -ENODEV;
23454+
23455+#ifdef CONFIG_PAX_PAGEEXEC
23456+ if (vma->vm_mm->pax_flags & MF_PAX_PAGEEXEC)
23457+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
23458+#endif
23459+
23460 file_accessed(file);
23461 vma->vm_ops = &generic_file_vm_ops;
23462 return 0;
23463@@ -1872,6 +1879,7 @@ inline int generic_write_checks(struct f
23464 *pos = i_size_read(inode);
23465
23466 if (limit != RLIM_INFINITY) {
23467+ gr_learn_resource(current, RLIMIT_FSIZE,*pos, 0);
23468 if (*pos >= limit) {
23469 send_sig(SIGXFSZ, current, 0);
23470 return -EFBIG;
23471diff -urNp linux-2.6.17.7/mm/madvise.c linux-2.6.17.7/mm/madvise.c
23472--- linux-2.6.17.7/mm/madvise.c 2006-07-24 23:36:01.000000000 -0400
23473+++ linux-2.6.17.7/mm/madvise.c 2006-08-01 20:29:48.000000000 -0400
23474@@ -15,9 +15,46 @@
23475 * We can potentially split a vm area into separate
23476 * areas, each area with its own behavior.
23477 */
23478+
23479+#ifdef CONFIG_PAX_SEGMEXEC
23480+static long __madvise_behavior(struct vm_area_struct * vma,
23481+ struct vm_area_struct **prev,
23482+ unsigned long start, unsigned long end, int behavior);
23483+
23484+static long madvise_behavior(struct vm_area_struct * vma,
23485+ struct vm_area_struct **prev,
23486+ unsigned long start, unsigned long end, int behavior)
23487+{
23488+ if (vma->vm_flags & VM_MIRROR) {
23489+ struct vm_area_struct * vma_m, * prev_m;
23490+ unsigned long start_m, end_m;
23491+ int error;
23492+
23493+ start_m = vma->vm_start + vma->vm_mirror;
23494+ vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m);
23495+ if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
23496+ start_m = start + vma->vm_mirror;
23497+ end_m = end + vma->vm_mirror;
23498+ error = __madvise_behavior(vma_m, &prev_m, start_m, end_m, behavior);
23499+ if (error)
23500+ return error;
23501+ } else {
23502+ printk("PAX: VMMIRROR: madvise bug in %s, %08lx\n", current->comm, vma->vm_start);
23503+ return -ENOMEM;
23504+ }
23505+ }
23506+
23507+ return __madvise_behavior(vma, prev, start, end, behavior);
23508+}
23509+
23510+static long __madvise_behavior(struct vm_area_struct * vma,
23511+ struct vm_area_struct **prev,
23512+ unsigned long start, unsigned long end, int behavior)
23513+#else
23514 static long madvise_behavior(struct vm_area_struct * vma,
23515 struct vm_area_struct **prev,
23516 unsigned long start, unsigned long end, int behavior)
23517+#endif
23518 {
23519 struct mm_struct * mm = vma->vm_mm;
23520 int error = 0;
23521diff -urNp linux-2.6.17.7/mm/memory.c linux-2.6.17.7/mm/memory.c
23522--- linux-2.6.17.7/mm/memory.c 2006-07-24 23:36:01.000000000 -0400
23523+++ linux-2.6.17.7/mm/memory.c 2006-08-01 20:29:48.000000000 -0400
23524@@ -48,6 +48,7 @@
23525 #include <linux/rmap.h>
23526 #include <linux/module.h>
23527 #include <linux/init.h>
23528+#include <linux/grsecurity.h>
23529
23530 #include <asm/pgalloc.h>
23531 #include <asm/uaccess.h>
23532@@ -320,6 +321,11 @@ int __pte_alloc(struct mm_struct *mm, pm
23533
23534 int __pte_alloc_kernel(pmd_t *pmd, unsigned long address)
23535 {
23536+
23537+#ifdef CONFIG_PAX_KERNEXEC
23538+ unsigned long cr0;
23539+#endif
23540+
23541 pte_t *new = pte_alloc_one_kernel(&init_mm, address);
23542 if (!new)
23543 return -ENOMEM;
23544@@ -327,8 +333,19 @@ int __pte_alloc_kernel(pmd_t *pmd, unsig
23545 spin_lock(&init_mm.page_table_lock);
23546 if (pmd_present(*pmd)) /* Another has populated it */
23547 pte_free_kernel(new);
23548- else
23549+ else {
23550+
23551+#ifdef CONFIG_PAX_KERNEXEC
23552+ pax_open_kernel(cr0);
23553+#endif
23554+
23555 pmd_populate_kernel(&init_mm, pmd, new);
23556+
23557+#ifdef CONFIG_PAX_KERNEXEC
23558+ pax_close_kernel(cr0);
23559+#endif
23560+
23561+ }
23562 spin_unlock(&init_mm.page_table_lock);
23563 return 0;
23564 }
23565@@ -1421,6 +1438,88 @@ static inline void cow_user_page(struct
23566 copy_user_highpage(dst, src, va);
23567 }
23568
23569+#ifdef CONFIG_PAX_SEGMEXEC
23570+/* PaX: if vma is mirrored, synchronize the mirror's PTE
23571+ *
23572+ * the ptl of the lower mapped page is held on entry and is not released on exit
23573+ * or inside to ensure atomic changes to the PTE states (swapout, mremap, munmap, etc)
23574+ */
23575+static void pax_mirror_fault(struct vm_area_struct *vma, unsigned long address, pte_t *pte)
23576+{
23577+ struct mm_struct *mm = vma->vm_mm;
23578+ unsigned long address_m, pfn_m;
23579+ struct vm_area_struct * vma_m = NULL;
23580+ pte_t * pte_m, entry_m;
23581+ struct page * page_m = NULL;
23582+
23583+ address_m = vma->vm_start + vma->vm_mirror;
23584+ vma_m = find_vma(mm, address_m);
23585+ BUG_ON(!vma_m || vma_m->vm_start != address_m);
23586+
23587+ address_m = address + vma->vm_mirror;
23588+ pte_m = pte_offset_map_nested(pmd_offset(pud_offset(pgd_offset(mm, address_m), address_m), address_m), address_m);
23589+
23590+ if (pte_same(*pte, *pte_m)) {
23591+ pte_unmap_nested(pte_m);
23592+ return;
23593+ }
23594+
23595+ pfn_m = pte_pfn(*pte);
23596+ if (pte_present(*pte_m)) {
23597+ page_m = vm_normal_page(vma_m, address_m, *pte_m);
23598+ if (page_m) {
23599+ flush_cache_page(vma_m, address_m, pfn_m);
23600+ flush_icache_page(vma_m, page_m);
23601+ }
23602+ }
23603+
23604+ if (pte_present(*pte_m))
23605+ entry_m = ptep_clear_flush(vma_m, address_m, pte_m);
23606+ else
23607+ entry_m = ptep_get_and_clear(mm, address_m, pte_m);
23608+
23609+ if (pte_none(entry_m)) {
23610+ } else if (pte_present(entry_m)) {
23611+ if (page_m) {
23612+ page_remove_rmap(page_m);
23613+ if (PageAnon(page_m))
23614+ dec_mm_counter(mm, anon_rss);
23615+ else
23616+ dec_mm_counter(mm, file_rss);
23617+ page_cache_release(page_m);
23618+ }
23619+ } else if (!pte_file(entry_m)) {
23620+ free_swap_and_cache(pte_to_swp_entry(entry_m));
23621+ } else {
23622+ printk(KERN_ERR "PAX: VMMIRROR: bug in mirror_fault: %08lx, %08lx, %08lx, %08lx\n",
23623+ address, vma->vm_start, address_m, vma_m->vm_start);
23624+ }
23625+
23626+ page_m = vm_normal_page(vma, address, *pte);
23627+ entry_m = pfn_pte(pfn_m, vma_m->vm_page_prot);
23628+ if (pte_write(*pte))
23629+ entry_m = maybe_mkwrite(pte_mkdirty(entry_m), vma_m);
23630+ if (page_m) {
23631+ page_cache_get(page_m);
23632+ /*
23633+ * we can test PAGE_MAPPING_ANON without holding page_map_lock because
23634+ * we hold the page table lock and have a reference to page_m
23635+ */
23636+ if (PageAnon(page_m)) {
23637+ page_add_anon_rmap(page_m, vma_m, address_m);
23638+ inc_mm_counter(mm, anon_rss);
23639+ } else {
23640+ page_add_file_rmap(page_m);
23641+ inc_mm_counter(mm, file_rss);
23642+ }
23643+ }
23644+ set_pte_at(mm, address_m, pte_m, entry_m);
23645+ update_mmu_cache(vma_m, address_m, entry_m);
23646+ lazy_mmu_prot_update(entry_m);
23647+ pte_unmap_nested(pte_m);
23648+}
23649+#endif
23650+
23651 /*
23652 * This routine handles present pages, when users try to write
23653 * to a shared page. It is done by copying the page to a new address
23654@@ -1511,6 +1610,12 @@ gotten:
23655 /* Free the old page.. */
23656 new_page = old_page;
23657 ret |= VM_FAULT_WRITE;
23658+
23659+#ifdef CONFIG_PAX_SEGMEXEC
23660+ if (vma->vm_flags & VM_MIRROR)
23661+ pax_mirror_fault(vma, address, page_table);
23662+#endif
23663+
23664 }
23665 if (new_page)
23666 page_cache_release(new_page);
23667@@ -1761,6 +1866,7 @@ int vmtruncate(struct inode * inode, lof
23668
23669 do_expand:
23670 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
23671+ gr_learn_resource(current, RLIMIT_FSIZE, offset, 1);
23672 if (limit != RLIM_INFINITY && offset > limit)
23673 goto out_sig;
23674 if (offset > inode->i_sb->s_maxbytes)
23675@@ -1950,6 +2056,12 @@ again:
23676 /* No need to invalidate - it was non-present before */
23677 update_mmu_cache(vma, address, pte);
23678 lazy_mmu_prot_update(pte);
23679+
23680+#ifdef CONFIG_PAX_SEGMEXEC
23681+ if (vma->vm_flags & VM_MIRROR)
23682+ pax_mirror_fault(vma, address, page_table);
23683+#endif
23684+
23685 unlock:
23686 pte_unmap_unlock(page_table, ptl);
23687 out:
23688@@ -2012,6 +2124,12 @@ static int do_anonymous_page(struct mm_s
23689 /* No need to invalidate - it was non-present before */
23690 update_mmu_cache(vma, address, entry);
23691 lazy_mmu_prot_update(entry);
23692+
23693+#ifdef CONFIG_PAX_SEGMEXEC
23694+ if (vma->vm_flags & VM_MIRROR)
23695+ pax_mirror_fault(vma, address, page_table);
23696+#endif
23697+
23698 unlock:
23699 pte_unmap_unlock(page_table, ptl);
23700 return VM_FAULT_MINOR;
23701@@ -2137,6 +2255,12 @@ retry:
23702 /* no need to invalidate: a not-present page shouldn't be cached */
23703 update_mmu_cache(vma, address, entry);
23704 lazy_mmu_prot_update(entry);
23705+
23706+#ifdef CONFIG_PAX_SEGMEXEC
23707+ if (vma->vm_flags & VM_MIRROR)
23708+ pax_mirror_fault(vma, address, page_table);
23709+#endif
23710+
23711 unlock:
23712 pte_unmap_unlock(page_table, ptl);
23713 return ret;
23714@@ -2246,6 +2370,12 @@ static inline int handle_pte_fault(struc
23715 flush_tlb_page(vma, address);
23716 }
23717 unlock:
23718+
23719+#ifdef CONFIG_PAX_SEGMEXEC
23720+ if (vma->vm_flags & VM_MIRROR)
23721+ pax_mirror_fault(vma, address, pte);
23722+#endif
23723+
23724 pte_unmap_unlock(pte, ptl);
23725 return VM_FAULT_MINOR;
23726 }
23727@@ -2268,6 +2398,49 @@ int __handle_mm_fault(struct mm_struct *
23728 if (unlikely(is_vm_hugetlb_page(vma)))
23729 return hugetlb_fault(mm, vma, address, write_access);
23730
23731+#ifdef CONFIG_PAX_SEGMEXEC
23732+ if (vma->vm_flags & VM_MIRROR) {
23733+ unsigned long address_m;
23734+ struct vm_area_struct * vma_m;
23735+ pgd_t *pgd_m;
23736+ pud_t *pud_m;
23737+ pmd_t *pmd_m;
23738+
23739+ address_m = vma->vm_start + vma->vm_mirror;
23740+ vma_m = find_vma(mm, address_m);
23741+
23742+ /* PaX: sanity checks */
23743+ if (!vma_m) {
23744+ printk(KERN_ERR "PAX: VMMIRROR: fault bug, %08lx, %p, %08lx, %p\n",
23745+ address, vma, address_m, vma_m);
23746+ return VM_FAULT_SIGBUS;
23747+ } else if (!(vma_m->vm_flags & VM_MIRROR) ||
23748+ vma_m->vm_start != address_m ||
23749+ vma->vm_end - vma->vm_start != vma_m->vm_end - vma_m->vm_start)
23750+ {
23751+ printk(KERN_ERR "PAX: VMMIRROR: fault bug2, %08lx, %08lx, %08lx, %08lx, %08lx\n",
23752+ address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
23753+ return VM_FAULT_SIGBUS;
23754+ }
23755+
23756+ if (address_m < address) {
23757+ address += vma->vm_mirror;
23758+ vma = vma_m;
23759+ }
23760+
23761+ address_m = address + vma->vm_mirror;
23762+ pgd_m = pgd_offset(mm, address_m);
23763+ pud_m = pud_alloc(mm, pgd_m, address_m);
23764+ if (!pud_m)
23765+ return VM_FAULT_OOM;
23766+ pmd_m = pmd_alloc(mm, pud_m, address_m);
23767+ if (!pmd_m)
23768+ return VM_FAULT_OOM;
23769+ if (!pmd_present(*pmd_m) && __pte_alloc(mm, pmd_m, address_m))
23770+ return VM_FAULT_OOM;
23771+ }
23772+#endif
23773+
23774 pgd = pgd_offset(mm, address);
23775 pud = pud_alloc(mm, pgd, address);
23776 if (!pud)
23777diff -urNp linux-2.6.17.7/mm/mempolicy.c linux-2.6.17.7/mm/mempolicy.c
23778--- linux-2.6.17.7/mm/mempolicy.c 2006-07-24 23:36:01.000000000 -0400
23779+++ linux-2.6.17.7/mm/mempolicy.c 2006-08-01 20:29:48.000000000 -0400
23780@@ -346,6 +346,12 @@ check_range(struct mm_struct *mm, unsign
23781 if (prev && prev->vm_end < vma->vm_start)
23782 return ERR_PTR(-EFAULT);
23783 }
23784+
23785+#ifdef CONFIG_PAX_SEGMEXEC
23786+ if (vma->vm_flags & VM_MIRROR)
23787+ return ERR_PTR(-EFAULT);
23788+#endif
23789+
23790 if (!is_vm_hugetlb_page(vma) &&
23791 ((flags & MPOL_MF_STRICT) ||
23792 ((flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) &&
23793diff -urNp linux-2.6.17.7/mm/mlock.c linux-2.6.17.7/mm/mlock.c
23794--- linux-2.6.17.7/mm/mlock.c 2006-07-24 23:36:01.000000000 -0400
23795+++ linux-2.6.17.7/mm/mlock.c 2006-08-01 20:29:48.000000000 -0400
23796@@ -10,14 +10,85 @@
f1a4f855 23797 #include <linux/mempolicy.h>
23798 #include <linux/syscalls.h>
68731fcf 23799 #include <linux/vs_memory.h>
f1a4f855 23800+#include <linux/grsecurity.h>
23801
23802+static int __mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
23803+ unsigned long start, unsigned long end, unsigned int newflags);
23804
23805 static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
23806 unsigned long start, unsigned long end, unsigned int newflags)
23807 {
23808 struct mm_struct * mm = vma->vm_mm;
23809- pgoff_t pgoff;
23810 int pages;
23811+ int ret;
23812+
23813+#ifdef CONFIG_PAX_SEGMEXEC
23814+ struct vm_area_struct * vma_m = NULL, *prev_m;
23815+ unsigned long start_m = 0UL, end_m = 0UL, newflags_m = 0UL;
23816+
23817+ if (vma->vm_flags & VM_MIRROR) {
23818+ start_m = vma->vm_start + vma->vm_mirror;
23819+ vma_m = find_vma_prev(mm, start_m, &prev_m);
23820+ if (!vma_m || vma_m->vm_start != start_m || !(vma_m->vm_flags & VM_MIRROR)) {
23821+ printk("PAX: VMMIRROR: mlock bug in %s, %08lx\n", current->comm, vma->vm_start);
23822+ return -ENOMEM;
23823+ }
23824+
23825+ start_m = start + vma->vm_mirror;
23826+ end_m = end + vma->vm_mirror;
23827+ if (newflags & VM_LOCKED)
23828+ newflags_m = vma_m->vm_flags | VM_LOCKED;
23829+ else
23830+ newflags_m = vma_m->vm_flags & ~VM_LOCKED;
23831+ ret = __mlock_fixup(vma_m, &prev_m, start_m, end_m, newflags_m);
23832+ if (ret)
23833+ return ret;
23834+ }
23835+#endif
23836+
23837+ ret = __mlock_fixup(vma, prev, start, end, newflags);
23838+ if (ret)
23839+ return ret;
23840+
23841+ /*
23842+ * vm_flags is protected by the mmap_sem held in write mode.
23843+ * It's okay if try_to_unmap_one unmaps a page just after we
23844+ * set VM_LOCKED, make_pages_present below will bring it back.
23845+ */
23846+ vma->vm_flags = newflags;
23847+
23848+#ifdef CONFIG_PAX_SEGMEXEC
23849+ if (vma->vm_flags & VM_MIRROR)
23850+ vma_m->vm_flags = newflags_m;
23851+#endif
23852+
23853+ /*
23854+ * Keep track of amount of locked VM.
23855+ */
23856+ pages = (end - start) >> PAGE_SHIFT;
23857+ if (newflags & VM_LOCKED) {
23858+ pages = -pages;
23859+ if (!(newflags & VM_IO))
23860+ ret = make_pages_present(start, end);
23861+ }
23862+
23863+ mm->locked_vm -= pages;
23864+
23865+#ifdef CONFIG_PAX_SEGMEXEC
23866+ if (vma->vm_flags & VM_MIRROR)
23867+ mm->locked_vm -= pages;
23868+#endif
23869+
23870+ if (ret == -ENOMEM)
23871+ ret = -EAGAIN;
23872+ return ret;
23873+}
23874+
23875+static int __mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
23876+ unsigned long start, unsigned long end, unsigned int newflags)
23877+{
23878+ struct mm_struct * mm = vma->vm_mm;
23879+ pgoff_t pgoff;
23880 int ret = 0;
23881
23882 if (newflags == vma->vm_flags) {
23883@@ -30,7 +101,7 @@ static int mlock_fixup(struct vm_area_st
23884 vma->vm_file, pgoff, vma_policy(vma));
23885 if (*prev) {
23886 vma = *prev;
23887- goto success;
23888+ goto out;
23889 }
23890
23891 *prev = vma;
23892@@ -41,31 +112,9 @@ static int mlock_fixup(struct vm_area_st
23893 goto out;
23894 }
23895
23896- if (end != vma->vm_end) {
23897+ if (end != vma->vm_end)
23898 ret = split_vma(mm, vma, end, 0);
23899- if (ret)
23900- goto out;
23901- }
23902
23903-success:
23904- /*
23905- * vm_flags is protected by the mmap_sem held in write mode.
23906- * It's okay if try_to_unmap_one unmaps a page just after we
23907- * set VM_LOCKED, make_pages_present below will bring it back.
23908- */
23909- vma->vm_flags = newflags;
23910-
23911- /*
23912- * Keep track of amount of locked VM.
23913- */
23914- pages = (end - start) >> PAGE_SHIFT;
23915- if (newflags & VM_LOCKED) {
23916- pages = -pages;
23917- if (!(newflags & VM_IO))
23918- ret = make_pages_present(start, end);
23919- }
23920-
68731fcf 23921- vx_vmlocked_sub(vma->vm_mm, pages);
f1a4f855 23922 out:
23923 if (ret == -ENOMEM)
23924 ret = -EAGAIN;
23925@@ -84,6 +133,17 @@ static int do_mlock(unsigned long start,
23926 return -EINVAL;
23927 if (end == start)
23928 return 0;
23929+
23930+#ifdef CONFIG_PAX_SEGMEXEC
23931+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
23932+ if (end > SEGMEXEC_TASK_SIZE)
23933+ return -EINVAL;
23934+ } else
23935+#endif
23936+
23937+ if (end > TASK_SIZE)
23938+ return -EINVAL;
23939+
23940 vma = find_vma_prev(current->mm, start, &prev);
23941 if (!vma || vma->vm_start > start)
23942 return -ENOMEM;
23943@@ -141,6 +201,7 @@ asmlinkage long sys_mlock(unsigned long
23944 lock_limit >>= PAGE_SHIFT;
23945
23946 /* check against resource limits */
23947+ gr_learn_resource(current, RLIMIT_MEMLOCK, (current->mm->locked_vm << PAGE_SHIFT) + len, 1);
23948 if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
23949 error = do_mlock(start, len, 1);
68731fcf 23950 out:
f1a4f855 23951@@ -173,6 +234,16 @@ static int do_mlockall(int flags)
23952 for (vma = current->mm->mmap; vma ; vma = prev->vm_next) {
23953 unsigned int newflags;
23954
23955+#ifdef CONFIG_PAX_SEGMEXEC
23956+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
23957+ if (vma->vm_end > SEGMEXEC_TASK_SIZE)
23958+ break;
23959+ } else
23960+#endif
23961+
23962+ if (vma->vm_end > TASK_SIZE)
23963+ break;
23964+
23965 newflags = vma->vm_flags | VM_LOCKED;
23966 if (!(flags & MCL_CURRENT))
23967 newflags &= ~VM_LOCKED;
23968@@ -202,6 +273,7 @@ asmlinkage long sys_mlockall(int flags)
f1a4f855 23969 ret = -ENOMEM;
68731fcf 23970 if (!vx_vmlocked_avail(current->mm, current->mm->total_vm))
23971 goto out;
f1a4f855 23972+ gr_learn_resource(current, RLIMIT_MEMLOCK, current->mm->total_vm, 1);
23973 if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
23974 capable(CAP_IPC_LOCK))
23975 ret = do_mlockall(flags);
23976diff -urNp linux-2.6.17.7/mm/mmap.c linux-2.6.17.7/mm/mmap.c
23977--- linux-2.6.17.7/mm/mmap.c 2006-07-24 23:36:01.000000000 -0400
23978+++ linux-2.6.17.7/mm/mmap.c 2006-08-01 20:29:48.000000000 -0400
23979@@ -25,6 +25,7 @@
23980 #include <linux/mount.h>
23981 #include <linux/mempolicy.h>
23982 #include <linux/rmap.h>
23983+#include <linux/grsecurity.h>
23984
23985 #include <asm/uaccess.h>
23986 #include <asm/cacheflush.h>
23987@@ -60,6 +61,8 @@ pgprot_t protection_map[16] = {
23988 __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
23989 };
23990
23991+EXPORT_SYMBOL(protection_map);
23992+
23993 int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
23994 int sysctl_overcommit_ratio = 50; /* default is 50% */
23995 int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
23996@@ -240,6 +243,7 @@ asmlinkage unsigned long sys_brk(unsigne
23997 * not page aligned -Ram Gupta
23998 */
23999 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
24000+ gr_learn_resource(current, RLIMIT_DATA, brk - mm->start_data, 1);
24001 if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
24002 goto out;
24003
24004@@ -628,11 +632,17 @@ again: remove_next = 1 + (end > next->
24005 * If the vma has a ->close operation then the driver probably needs to release
24006 * per-vma resources, so we don't attempt to merge those.
24007 */
24008+#ifdef CONFIG_PAX_SEGMEXEC
24009+#define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP | VM_MIRROR)
24010+#else
24011 #define VM_SPECIAL (VM_IO | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
24012+#endif
24013
24014 static inline int is_mergeable_vma(struct vm_area_struct *vma,
24015 struct file *file, unsigned long vm_flags)
24016 {
24017+ if ((vma->vm_flags | vm_flags) & VM_SPECIAL)
24018+ return 0;
24019 if (vma->vm_flags != vm_flags)
24020 return 0;
24021 if (vma->vm_file != file)
24022@@ -857,14 +867,11 @@ none:
24023 void vm_stat_account(struct mm_struct *mm, unsigned long flags,
24024 struct file *file, long pages)
24025 {
24026- const unsigned long stack_flags
24027- = VM_STACK_FLAGS & (VM_GROWSUP|VM_GROWSDOWN);
24028-
24029 if (file) {
24030 mm->shared_vm += pages;
24031 if ((flags & (VM_EXEC|VM_WRITE)) == VM_EXEC)
24032 mm->exec_vm += pages;
24033- } else if (flags & stack_flags)
24034+ } else if (flags & (VM_GROWSUP|VM_GROWSDOWN))
24035 mm->stack_vm += pages;
24036 if (flags & (VM_RESERVED|VM_IO))
24037 mm->reserved_vm += pages;
24038@@ -875,10 +882,55 @@ void vm_stat_account(struct mm_struct *m
24039 * The caller must hold down_write(current->mm->mmap_sem).
24040 */
24041
24042+#ifdef CONFIG_PAX_SEGMEXEC
24043+static unsigned long __do_mmap_pgoff(struct file * file, unsigned long addr,
24044+ unsigned long len, unsigned long prot,
24045+ unsigned long flags, unsigned long pgoff);
24046+
24047 unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
24048 unsigned long len, unsigned long prot,
24049 unsigned long flags, unsigned long pgoff)
24050 {
24051+ unsigned long ret = -EINVAL;
24052+
24053+ if (flags & MAP_MIRROR)
24054+ return ret;
24055+
24056+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) &&
24057+ (len > SEGMEXEC_TASK_SIZE || (addr > SEGMEXEC_TASK_SIZE-len)))
24058+ return ret;
24059+
24060+ ret = __do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
24061+
24062+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && ret < TASK_SIZE && ((flags & MAP_TYPE) == MAP_PRIVATE)
24063+
24064+#ifdef CONFIG_PAX_MPROTECT
24065+ && (!(current->mm->pax_flags & MF_PAX_MPROTECT) || ((prot & PROT_EXEC) && file && !(prot & PROT_WRITE)))
24066+#endif
24067+
24068+ )
24069+ {
24070+ unsigned long ret_m;
24071+ prot = prot & PROT_EXEC ? prot & ~PROT_WRITE : PROT_NONE;
24072+ ret_m = __do_mmap_pgoff(NULL, ret + SEGMEXEC_TASK_SIZE, 0UL, prot, flags | MAP_MIRROR | MAP_FIXED, ret);
24073+ if (ret_m >= TASK_SIZE) {
24074+ do_munmap(current->mm, ret, len);
24075+ ret = ret_m;
24076+ }
24077+ }
24078+
24079+ return ret;
24080+}
24081+
24082+static unsigned long __do_mmap_pgoff(struct file * file, unsigned long addr,
24083+ unsigned long len, unsigned long prot,
24084+ unsigned long flags, unsigned long pgoff)
24085+#else
24086+unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
24087+ unsigned long len, unsigned long prot,
24088+ unsigned long flags, unsigned long pgoff)
24089+#endif
24090+{
24091 struct mm_struct * mm = current->mm;
24092 struct vm_area_struct * vma, * prev;
24093 struct inode *inode;
24094@@ -889,6 +941,28 @@ unsigned long do_mmap_pgoff(struct file
24095 int accountable = 1;
24096 unsigned long charged = 0, reqprot = prot;
24097
24098+#ifdef CONFIG_PAX_SEGMEXEC
24099+ struct vm_area_struct * vma_m = NULL;
24100+
24101+ if (flags & MAP_MIRROR) {
24102+ /* PaX: sanity checks, to be removed when proved to be stable */
24103+ if (file || len || ((flags & MAP_TYPE) != MAP_PRIVATE))
24104+ return -EINVAL;
24105+
24106+ vma_m = find_vma(mm, pgoff);
24107+
24108+ if (!vma_m || is_vm_hugetlb_page(vma_m) ||
24109+ vma_m->vm_start != pgoff ||
24110+ (vma_m->vm_flags & VM_SPECIAL) ||
24111+ (prot & PROT_WRITE))
24112+ return -EINVAL;
24113+
24114+ file = vma_m->vm_file;
24115+ pgoff = vma_m->vm_pgoff;
24116+ len = vma_m->vm_end - vma_m->vm_start;
24117+ }
24118+#endif
24119+
24120 if (file) {
24121 if (is_file_hugepages(file))
24122 accountable = 0;
24123@@ -929,7 +1003,7 @@ unsigned long do_mmap_pgoff(struct file
24124 /* Obtain the address to map to. we verify (or select) it and ensure
24125 * that it represents a valid section of the address space.
24126 */
24127- addr = get_unmapped_area(file, addr, len, pgoff, flags);
24128+ addr = get_unmapped_area(file, addr, len, pgoff, flags | ((prot & PROT_EXEC) ? MAP_EXECUTABLE : 0));
24129 if (addr & ~PAGE_MASK)
24130 return addr;
24131
24132@@ -940,6 +1014,24 @@ unsigned long do_mmap_pgoff(struct file
24133 vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) |
24134 mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
24135
24136+ if (file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
24137+ vm_flags &= ~VM_MAYEXEC;
24138+
24139+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
24140+ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
24141+
24142+#ifdef CONFIG_PAX_MPROTECT
24143+ if (mm->pax_flags & MF_PAX_MPROTECT) {
24144+ if ((prot & (PROT_WRITE | PROT_EXEC)) != PROT_EXEC)
24145+ vm_flags &= ~(VM_EXEC | VM_MAYEXEC);
24146+ else
24147+ vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
24148+ }
24149+#endif
24150+
24151+ }
24152+#endif
24153+
24154 if (flags & MAP_LOCKED) {
24155 if (!can_do_mlock())
24156 return -EPERM;
24157@@ -952,6 +1044,7 @@ unsigned long do_mmap_pgoff(struct file
24158 locked += mm->locked_vm;
24159 lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
24160 lock_limit >>= PAGE_SHIFT;
24161+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
24162 if (locked > lock_limit && !capable(CAP_IPC_LOCK))
24163 return -EAGAIN;
24164 }
24165@@ -999,6 +1092,11 @@ unsigned long do_mmap_pgoff(struct file
24166 /*
24167 * Set pgoff according to addr for anon_vma.
24168 */
24169+
24170+#ifdef CONFIG_PAX_SEGMEXEC
24171+ if (!(flags & MAP_MIRROR))
24172+#endif
24173+
24174 pgoff = addr >> PAGE_SHIFT;
24175 break;
24176 default:
24177@@ -1010,14 +1108,17 @@ unsigned long do_mmap_pgoff(struct file
24178 if (error)
24179 return error;
24180
24181+ if (!gr_acl_handle_mmap(file, prot))
24182+ return -EACCES;
24183+
24184 /* Clear old maps */
24185 error = -ENOMEM;
24186-munmap_back:
24187 vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
24188 if (vma && vma->vm_start < addr + len) {
24189 if (do_munmap(mm, addr, len))
24190 return -ENOMEM;
24191- goto munmap_back;
24192+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
24193+ BUG_ON(vma && vma->vm_start < addr + len);
24194 }
24195
24196 /* Check against address space limit. */
24197@@ -1065,6 +1166,13 @@ munmap_back:
24198 vma->vm_start = addr;
24199 vma->vm_end = addr + len;
24200 vma->vm_flags = vm_flags;
24201+
24202+#ifdef CONFIG_PAX_PAGEEXEC
24203+ if ((file || !(mm->pax_flags & MF_PAX_PAGEEXEC)) && (vm_flags & (VM_READ|VM_WRITE)))
24204+ vma->vm_page_prot = protection_map[(vm_flags | VM_EXEC) & 0x0f];
24205+ else
24206+#endif
24207+
24208 vma->vm_page_prot = protection_map[vm_flags & 0x0f];
24209 vma->vm_pgoff = pgoff;
24210
24211@@ -1089,6 +1197,14 @@ munmap_back:
24212 goto free_vma;
24213 }
24214
24215+#ifdef CONFIG_PAX_SEGMEXEC
24216+ if (flags & MAP_MIRROR) {
24217+ vma_m->vm_flags |= VM_MIRROR;
24218+ vma_m->vm_mirror = vma->vm_start - vma_m->vm_start;
24219+ vma->vm_mirror = vma_m->vm_start - vma->vm_start;
24220+ }
24221+#endif
24222+
24223 /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform
24224 * shmem_zero_setup (perhaps called through /dev/zero's ->mmap)
24225 * that memory reservation must be checked; but that reservation
24226@@ -1124,6 +1240,7 @@ munmap_back:
24227 out:
24228 mm->total_vm += len >> PAGE_SHIFT;
24229 vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
24230+ track_exec_limit(mm, addr, addr + len, vm_flags);
24231 if (vm_flags & VM_LOCKED) {
24232 mm->locked_vm += len >> PAGE_SHIFT;
24233 make_pages_present(addr, addr + len);
24234@@ -1178,6 +1295,10 @@ arch_get_unmapped_area(struct file *filp
24235 if (len > TASK_SIZE)
24236 return -ENOMEM;
24237
24238+#ifdef CONFIG_PAX_RANDMMAP
24239+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
24240+#endif
24241+
24242 if (addr) {
24243 addr = PAGE_ALIGN(addr);
24244 vma = find_vma(mm, addr);
24245@@ -1188,7 +1309,7 @@ arch_get_unmapped_area(struct file *filp
24246 if (len > mm->cached_hole_size) {
24247 start_addr = addr = mm->free_area_cache;
24248 } else {
24249- start_addr = addr = TASK_UNMAPPED_BASE;
24250+ start_addr = addr = mm->mmap_base;
24251 mm->cached_hole_size = 0;
24252 }
24253
24254@@ -1200,9 +1321,8 @@ full_search:
24255 * Start a new search - just in case we missed
24256 * some holes.
24257 */
24258- if (start_addr != TASK_UNMAPPED_BASE) {
24259- addr = TASK_UNMAPPED_BASE;
24260- start_addr = addr;
24261+ if (start_addr != mm->mmap_base) {
24262+ start_addr = addr = mm->mmap_base;
24263 mm->cached_hole_size = 0;
24264 goto full_search;
24265 }
24266@@ -1227,7 +1347,7 @@ void arch_unmap_area(struct mm_struct *m
24267 /*
24268 * Is this a new hole at the lowest possible address?
24269 */
24270- if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache) {
24271+ if (addr >= mm->mmap_base && addr < mm->free_area_cache) {
24272 mm->free_area_cache = addr;
24273 mm->cached_hole_size = ~0UL;
24274 }
24275@@ -1245,12 +1365,16 @@ arch_get_unmapped_area_topdown(struct fi
24276 {
24277 struct vm_area_struct *vma;
24278 struct mm_struct *mm = current->mm;
24279- unsigned long addr = addr0;
24280+ unsigned long base = mm->mmap_base, addr = addr0;
24281
24282 /* requested length too big for entire address space */
24283 if (len > TASK_SIZE)
24284 return -ENOMEM;
24285
24286+#ifdef CONFIG_PAX_RANDMMAP
24287+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
24288+#endif
24289+
24290 /* requesting a specific address */
24291 if (addr) {
24292 addr = PAGE_ALIGN(addr);
24293@@ -1308,13 +1432,21 @@ bottomup:
24294 * can happen with large stack limits and large mmap()
24295 * allocations.
24296 */
24297+ mm->mmap_base = TASK_UNMAPPED_BASE;
24298+
24299+#ifdef CONFIG_PAX_RANDMMAP
24300+ if (mm->pax_flags & MF_PAX_RANDMMAP)
24301+ mm->mmap_base += mm->delta_mmap;
24302+#endif
24303+
24304+ mm->free_area_cache = mm->mmap_base;
24305 mm->cached_hole_size = ~0UL;
24306- mm->free_area_cache = TASK_UNMAPPED_BASE;
24307 addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
24308 /*
24309 * Restore the topdown base:
24310 */
24311- mm->free_area_cache = mm->mmap_base;
24312+ mm->mmap_base = base;
24313+ mm->free_area_cache = base;
24314 mm->cached_hole_size = ~0UL;
24315
24316 return addr;
24317@@ -1330,8 +1462,10 @@ void arch_unmap_area_topdown(struct mm_s
24318 mm->free_area_cache = addr;
24319
24320 /* dont allow allocations above current base */
24321- if (mm->free_area_cache > mm->mmap_base)
24322+ if (mm->free_area_cache > mm->mmap_base) {
24323 mm->free_area_cache = mm->mmap_base;
24324+ mm->cached_hole_size = ~0UL;
24325+ }
24326 }
24327
24328 unsigned long
24329@@ -1464,6 +1598,7 @@ static int acct_stack_growth(struct vm_a
24330 return -ENOMEM;
24331
24332 /* Stack limit test */
24333+ gr_learn_resource(current, RLIMIT_STACK, size, 1);
24334 if (size > rlim[RLIMIT_STACK].rlim_cur)
24335 return -ENOMEM;
24336
24337@@ -1473,6 +1608,7 @@ static int acct_stack_growth(struct vm_a
24338 unsigned long limit;
24339 locked = mm->locked_vm + grow;
24340 limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
24341+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
24342 if (locked > limit && !capable(CAP_IPC_LOCK))
24343 return -ENOMEM;
24344 }
24345@@ -1590,13 +1726,49 @@ int expand_stack(struct vm_area_struct *
24346 if (address < vma->vm_start) {
24347 unsigned long size, grow;
24348
24349+#ifdef CONFIG_PAX_SEGMEXEC
24350+ struct vm_area_struct *vma_m = NULL;
24351+ unsigned long address_m = 0UL;
24352+
24353+ if (vma->vm_flags & VM_MIRROR) {
24354+ address_m = vma->vm_start + vma->vm_mirror;
24355+ vma_m = find_vma(vma->vm_mm, address_m);
24356+ if (!vma_m || vma_m->vm_start != address_m ||
24357+ !(vma_m->vm_flags & VM_MIRROR) ||
24358+ vma->vm_end - vma->vm_start !=
24359+ vma_m->vm_end - vma_m->vm_start ||
24360+ vma->anon_vma != vma_m->anon_vma) {
24361+ printk(KERN_ERR "PAX: VMMIRROR: expand bug, %08lx, %08lx, %08lx, %08lx, %08lx\n",
24362+ address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
24363+ anon_vma_unlock(vma);
24364+ return -EFAULT;
24365+ }
24366+ address_m = address + vma->vm_mirror;
24367+ }
24368+#endif
24369+
24370 size = vma->vm_end - address;
24371 grow = (vma->vm_start - address) >> PAGE_SHIFT;
24372
24373+#ifdef CONFIG_PAX_SEGMEXEC
24374+ if (vma_m)
24375+ error = acct_stack_growth(vma, size, 2*grow);
24376+ else
24377+#endif
24378+
24379 error = acct_stack_growth(vma, size, grow);
24380 if (!error) {
24381 vma->vm_start = address;
24382 vma->vm_pgoff -= grow;
24383+ track_exec_limit(vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_flags);
24384+
24385+#ifdef CONFIG_PAX_SEGMEXEC
24386+ if (vma_m) {
24387+ vma_m->vm_start = address_m;
24388+ vma_m->vm_pgoff -= grow;
24389+ }
24390+#endif
24391+
24392 }
24393 }
24394 anon_vma_unlock(vma);
24395@@ -1758,7 +1930,24 @@ int split_vma(struct mm_struct * mm, str
24396 * work. This now handles partial unmappings.
24397 * Jeremy Fitzhardinge <jeremy@goop.org>
24398 */
24399+#ifdef CONFIG_PAX_SEGMEXEC
24400+static int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len);
24401+
24402+int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
24403+{
24404+ if (mm->pax_flags & MF_PAX_SEGMEXEC) {
24405+ int ret = __do_munmap(mm, start + SEGMEXEC_TASK_SIZE, len);
24406+ if (ret)
24407+ return ret;
24408+ }
24409+
24410+ return __do_munmap(mm, start, len);
24411+}
24412+
24413+static int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
24414+#else
24415 int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
24416+#endif
24417 {
24418 unsigned long end;
24419 struct vm_area_struct *vma, *prev, *last;
24420@@ -1812,6 +2001,8 @@ int do_munmap(struct mm_struct *mm, unsi
24421 /* Fix up all other VM information */
24422 remove_vma_list(mm, vma);
24423
24424+ track_exec_limit(mm, start, end, 0UL);
24425+
24426 return 0;
24427 }
24428
24429@@ -1824,6 +2015,12 @@ asmlinkage long sys_munmap(unsigned long
24430
24431 profile_munmap(addr);
24432
24433+#ifdef CONFIG_PAX_SEGMEXEC
24434+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) &&
24435+ (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len))
24436+ return -EINVAL;
24437+#endif
24438+
24439 down_write(&mm->mmap_sem);
24440 ret = do_munmap(mm, addr, len);
24441 up_write(&mm->mmap_sem);
24442@@ -1845,11 +2042,35 @@ static inline void verify_mm_writelocked
24443 * anonymous maps. eventually we may be able to do some
24444 * brk-specific accounting here.
24445 */
24446+#ifdef CONFIG_PAX_SEGMEXEC
24447+static unsigned long __do_brk(unsigned long addr, unsigned long len);
24448+
24449 unsigned long do_brk(unsigned long addr, unsigned long len)
24450 {
24451+ unsigned long ret;
24452+
24453+ ret = __do_brk(addr, len);
24454+ if (ret == addr && (current->mm->pax_flags & (MF_PAX_SEGMEXEC | MF_PAX_MPROTECT)) == MF_PAX_SEGMEXEC) {
24455+ unsigned long ret_m;
24456+
24457+ ret_m = __do_mmap_pgoff(NULL, addr + SEGMEXEC_TASK_SIZE, 0UL, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_MIRROR, addr);
24458+ if (ret_m > TASK_SIZE) {
24459+ do_munmap(current->mm, addr, len);
24460+ ret = ret_m;
24461+ }
24462+ }
24463+
24464+ return ret;
24465+}
24466+
24467+static unsigned long __do_brk(unsigned long addr, unsigned long len)
24468+#else
24469+unsigned long do_brk(unsigned long addr, unsigned long len)
24470+#endif
24471+{
24472 struct mm_struct * mm = current->mm;
24473 struct vm_area_struct * vma, * prev;
24474- unsigned long flags;
24475+ unsigned long flags, task_size = TASK_SIZE;
24476 struct rb_node ** rb_link, * rb_parent;
24477 pgoff_t pgoff = addr >> PAGE_SHIFT;
24478
24479@@ -1857,7 +2078,12 @@ unsigned long do_brk(unsigned long addr,
24480 if (!len)
24481 return addr;
24482
24483- if ((addr + len) > TASK_SIZE || (addr + len) < addr)
24484+#ifdef CONFIG_PAX_SEGMEXEC
24485+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
24486+ task_size = SEGMEXEC_TASK_SIZE;
24487+#endif
24488+
24489+ if ((addr + len) > task_size || (addr + len) < addr)
24490 return -EINVAL;
24491
24492 /*
24493@@ -1869,6 +2095,7 @@ unsigned long do_brk(unsigned long addr,
24494 locked += mm->locked_vm;
24495 lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
24496 lock_limit >>= PAGE_SHIFT;
24497+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
24498 if (locked > lock_limit && !capable(CAP_IPC_LOCK))
24499 return -EAGAIN;
24500 }
24501@@ -1882,12 +2109,12 @@ unsigned long do_brk(unsigned long addr,
24502 /*
24503 * Clear old maps. this also does some error checking for us
24504 */
24505- munmap_back:
24506 vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
24507 if (vma && vma->vm_start < addr + len) {
24508 if (do_munmap(mm, addr, len))
24509 return -ENOMEM;
24510- goto munmap_back;
24511+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
24512+ BUG_ON(vma && vma->vm_start < addr + len);
24513 }
24514
24515 /* Check against address space limits *after* clearing old maps... */
24516@@ -1902,6 +2129,18 @@ unsigned long do_brk(unsigned long addr,
24517
24518 flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
24519
24520+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
24521+ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
24522+ flags &= ~VM_EXEC;
24523+
24524+#ifdef CONFIG_PAX_MPROTECT
24525+ if (mm->pax_flags & MF_PAX_MPROTECT)
24526+ flags &= ~VM_MAYEXEC;
24527+#endif
24528+
24529+ }
24530+#endif
24531+
24532 /* Can we just expand an old private anonymous mapping? */
24533 if (vma_merge(mm, prev, addr, addr + len, flags,
24534 NULL, NULL, pgoff, NULL))
24535@@ -1921,6 +2160,13 @@ unsigned long do_brk(unsigned long addr,
24536 vma->vm_end = addr + len;
24537 vma->vm_pgoff = pgoff;
24538 vma->vm_flags = flags;
24539+
24540+#ifdef CONFIG_PAX_PAGEEXEC
24541+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & (VM_READ|VM_WRITE)))
24542+ vma->vm_page_prot = protection_map[(flags | VM_EXEC) & 0x0f];
24543+ else
24544+#endif
24545+
24546 vma->vm_page_prot = protection_map[flags & 0x0f];
24547 vma_link(mm, vma, prev, rb_link, rb_parent);
24548 out:
24549@@ -1929,6 +2175,7 @@ out:
24550 mm->locked_vm += len >> PAGE_SHIFT;
24551 make_pages_present(addr, addr + len);
24552 }
24553+ track_exec_limit(mm, addr, addr + len, flags);
24554 return addr;
24555 }
24556
24557@@ -2061,7 +2308,7 @@ int may_expand_vm(struct mm_struct *mm,
24558 unsigned long lim;
24559
24560 lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
24561-
24562+ gr_learn_resource(current, RLIMIT_AS, (cur + npages) << PAGE_SHIFT, 1);
24563 if (cur + npages > lim)
24564 return 0;
24565 return 1;
24566diff -urNp linux-2.6.17.7/mm/mprotect.c linux-2.6.17.7/mm/mprotect.c
24567--- linux-2.6.17.7/mm/mprotect.c 2006-07-24 23:36:01.000000000 -0400
24568+++ linux-2.6.17.7/mm/mprotect.c 2006-08-01 20:29:48.000000000 -0400
24569@@ -19,11 +19,18 @@
24570 #include <linux/mempolicy.h>
24571 #include <linux/personality.h>
24572 #include <linux/syscalls.h>
24573+#include <linux/grsecurity.h>
24574+
24575+#ifdef CONFIG_PAX_MPROTECT
24576+#include <linux/elf.h>
24577+#include <linux/fs.h>
24578+#endif
24579
24580 #include <asm/uaccess.h>
24581 #include <asm/pgtable.h>
24582 #include <asm/cacheflush.h>
24583 #include <asm/tlbflush.h>
24584+#include <asm/mmu_context.h>
24585
24586 static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
24587 unsigned long addr, unsigned long end, pgprot_t newprot)
24588@@ -98,6 +105,94 @@ static void change_protection(struct vm_
24589 flush_tlb_range(vma, start, end);
24590 }
24591
24592+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
24593+/* called while holding the mmap semaphor for writing */
24594+static inline void establish_user_cs_limit(struct mm_struct *mm, unsigned long start, unsigned long end)
24595+{
24596+ struct vm_area_struct *vma = find_vma(mm, start);
24597+
24598+ for (; vma && vma->vm_start < end; vma = vma->vm_next)
24599+ change_protection(vma, vma->vm_start, vma->vm_end, vma->vm_page_prot);
24600+
24601+}
24602+
24603+void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot)
24604+{
24605+ unsigned long oldlimit, newlimit = 0UL;
24606+
24607+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC))
24608+ return;
24609+
24610+ spin_lock(&mm->page_table_lock);
24611+ oldlimit = mm->context.user_cs_limit;
24612+ if ((prot & VM_EXEC) && oldlimit < end)
24613+ /* USER_CS limit moved up */
24614+ newlimit = end;
24615+ else if (!(prot & VM_EXEC) && start < oldlimit && oldlimit <= end)
24616+ /* USER_CS limit moved down */
24617+ newlimit = start;
24618+
24619+ if (newlimit) {
24620+ mm->context.user_cs_limit = newlimit;
24621+
24622+#ifdef CONFIG_SMP
24623+ wmb();
24624+ cpus_clear(mm->context.cpu_user_cs_mask);
24625+ cpu_set(smp_processor_id(), mm->context.cpu_user_cs_mask);
24626+#endif
24627+
24628+ set_user_cs(mm, smp_processor_id());
24629+ }
24630+ spin_unlock(&mm->page_table_lock);
24631+ if (newlimit == end)
24632+ establish_user_cs_limit(mm, oldlimit, end);
24633+}
24634+#endif
24635+
24636+#ifdef CONFIG_PAX_SEGMEXEC
24637+static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
24638+ unsigned long start, unsigned long end, unsigned int newflags);
24639+
24640+static int mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
24641+ unsigned long start, unsigned long end, unsigned int newflags)
24642+{
24643+ if (vma->vm_flags & VM_MIRROR) {
24644+ struct vm_area_struct * vma_m, * prev_m;
24645+ unsigned long start_m, end_m;
24646+ int error;
24647+
24648+ start_m = vma->vm_start + vma->vm_mirror;
24649+ vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m);
24650+ if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
24651+ start_m = start + vma->vm_mirror;
24652+ end_m = end + vma->vm_mirror;
24653+
24654+ if (vma_m->vm_start >= SEGMEXEC_TASK_SIZE && !(newflags & VM_EXEC))
24655+ error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, vma_m->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC));
24656+ else
24657+ error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, newflags);
24658+ if (error)
24659+ return error;
24660+ } else {
24661+ printk("PAX: VMMIRROR: mprotect bug in %s, %08lx\n", current->comm, vma->vm_start);
24662+ return -ENOMEM;
24663+ }
24664+ }
24665+
24666+ return __mprotect_fixup(vma, pprev, start, end, newflags);
24667+}
24668+
24669+static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
24670+ unsigned long start, unsigned long end, unsigned int newflags)
24671+{
24672+ struct mm_struct * mm = vma->vm_mm;
24673+ unsigned long oldflags = vma->vm_flags;
24674+ long nrpages = (end - start) >> PAGE_SHIFT;
24675+ unsigned long charged = 0;
24676+ pgprot_t newprot;
24677+ pgoff_t pgoff;
24678+ int error;
24679+#else
24680 static int
24681 mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
24682 unsigned long start, unsigned long end, unsigned long newflags)
24683@@ -114,6 +209,7 @@ mprotect_fixup(struct vm_area_struct *vm
24684 *pprev = vma;
24685 return 0;
24686 }
24687+#endif
24688
24689 /*
24690 * If we make a private mapping writable we increase our commit;
24691@@ -132,6 +228,12 @@ mprotect_fixup(struct vm_area_struct *vm
24692 }
24693 }
24694
24695+#ifdef CONFIG_PAX_PAGEEXEC
24696+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) && (newflags & (VM_READ|VM_WRITE)))
24697+ newprot = protection_map[(newflags | VM_EXEC) & 0xf];
24698+ else
24699+#endif
24700+
24701 newprot = protection_map[newflags & 0xf];
24702
24703 /*
24704@@ -179,6 +281,69 @@ fail:
24705 return error;
24706 }
24707
24708+#ifdef CONFIG_PAX_MPROTECT
24709+/* PaX: non-PIC ELF libraries need relocations on their executable segments
24710+ * therefore we'll grant them VM_MAYWRITE once during their life.
24711+ *
24712+ * The checks favour ld-linux.so behaviour which operates on a per ELF segment
24713+ * basis because we want to allow the common case and not the special ones.
24714+ */
24715+static inline void pax_handle_maywrite(struct vm_area_struct * vma, unsigned long start)
24716+{
24717+ struct elfhdr elf_h;
24718+ struct elf_phdr elf_p, p_dyn;
24719+ elf_dyn dyn;
24720+ unsigned long i, j = 65536UL / sizeof(struct elf_phdr);
24721+
24722+#ifndef CONFIG_PAX_NOELFRELOCS
24723+ if ((vma->vm_start != start) ||
24724+ !vma->vm_file ||
24725+ !(vma->vm_flags & VM_MAYEXEC) ||
24726+ (vma->vm_flags & VM_MAYNOTWRITE))
24727+#endif
24728+
24729+ return;
24730+
24731+ if (sizeof(elf_h) != kernel_read(vma->vm_file, 0UL, (char*)&elf_h, sizeof(elf_h)) ||
24732+ memcmp(elf_h.e_ident, ELFMAG, SELFMAG) ||
24733+
24734+#ifdef CONFIG_PAX_ETEXECRELOCS
24735+ (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC) ||
24736+#else
24737+ elf_h.e_type != ET_DYN ||
24738+#endif
24739+
24740+ !elf_check_arch(&elf_h) ||
24741+ elf_h.e_phentsize != sizeof(struct elf_phdr) ||
24742+ elf_h.e_phnum > j)
24743+ return;
24744+
24745+ for (i = 0UL; i < elf_h.e_phnum; i++) {
24746+ if (sizeof(elf_p) != kernel_read(vma->vm_file, elf_h.e_phoff + i*sizeof(elf_p), (char*)&elf_p, sizeof(elf_p)))
24747+ return;
24748+ if (elf_p.p_type == PT_DYNAMIC) {
24749+ p_dyn = elf_p;
24750+ j = i;
24751+ }
24752+ }
24753+ if (elf_h.e_phnum <= j)
24754+ return;
24755+
24756+ i = 0UL;
24757+ do {
24758+ if (sizeof(dyn) != kernel_read(vma->vm_file, p_dyn.p_offset + i*sizeof(dyn), (char*)&dyn, sizeof(dyn)))
24759+ return;
24760+ if (dyn.d_tag == DT_TEXTREL || (dyn.d_tag == DT_FLAGS && (dyn.d_un.d_val & DF_TEXTREL))) {
24761+ vma->vm_flags |= VM_MAYWRITE | VM_MAYNOTWRITE;
24762+ gr_log_textrel(vma);
24763+ return;
24764+ }
24765+ i++;
24766+ } while (dyn.d_tag != DT_NULL);
24767+ return;
24768+}
24769+#endif
24770+
24771 asmlinkage long
24772 sys_mprotect(unsigned long start, size_t len, unsigned long prot)
24773 {
24774@@ -198,6 +363,17 @@ sys_mprotect(unsigned long start, size_t
24775 end = start + len;
24776 if (end <= start)
24777 return -ENOMEM;
24778+
24779+#ifdef CONFIG_PAX_SEGMEXEC
24780+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
24781+ if (end > SEGMEXEC_TASK_SIZE)
24782+ return -EINVAL;
24783+ } else
24784+#endif
24785+
24786+ if (end > TASK_SIZE)
24787+ return -EINVAL;
24788+
24789 if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM))
24790 return -EINVAL;
24791
24792@@ -238,6 +414,16 @@ sys_mprotect(unsigned long start, size_t
24793 if (start > vma->vm_start)
24794 prev = vma;
24795
24796+#ifdef CONFIG_PAX_MPROTECT
24797+ if ((vma->vm_mm->pax_flags & MF_PAX_MPROTECT) && (prot & PROT_WRITE))
24798+ pax_handle_maywrite(vma, start);
24799+#endif
24800+
24801+ if (!gr_acl_handle_mprotect(vma->vm_file, prot)) {
24802+ error = -EACCES;
24803+ goto out;
24804+ }
24805+
24806 for (nstart = start ; ; ) {
24807 unsigned long newflags;
24808
24809@@ -251,6 +437,12 @@ sys_mprotect(unsigned long start, size_t
24810 goto out;
24811 }
24812
24813+#ifdef CONFIG_PAX_MPROTECT
24814+ /* PaX: disallow write access after relocs are done, hopefully noone else needs it... */
24815+ if ((vma->vm_mm->pax_flags & MF_PAX_MPROTECT) && !(prot & PROT_WRITE) && (vma->vm_flags & VM_MAYNOTWRITE))
24816+ newflags &= ~VM_MAYWRITE;
24817+#endif
24818+
24819 error = security_file_mprotect(vma, reqprot, prot);
24820 if (error)
24821 goto out;
24822@@ -274,6 +466,9 @@ sys_mprotect(unsigned long start, size_t
24823 goto out;
24824 }
24825 }
24826+
24827+ track_exec_limit(current->mm, start, end, vm_flags);
24828+
24829 out:
24830 up_write(&current->mm->mmap_sem);
24831 return error;
24832diff -urNp linux-2.6.17.7/mm/mremap.c linux-2.6.17.7/mm/mremap.c
24833--- linux-2.6.17.7/mm/mremap.c 2006-07-24 23:36:01.000000000 -0400
24834+++ linux-2.6.17.7/mm/mremap.c 2006-08-01 20:29:48.000000000 -0400
24835@@ -106,6 +106,12 @@ static void move_ptes(struct vm_area_str
24836 pte = ptep_clear_flush(vma, old_addr, old_pte);
24837 /* ZERO_PAGE can be dependant on virtual addr */
24838 pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr);
24839+
24840+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
24841+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && !(vma->vm_flags & VM_EXEC))
24842+ pte_exprotect(pte);
24843+#endif
24844+
24845 set_pte_at(mm, new_addr, new_pte, pte);
24846 }
24847
24848@@ -253,6 +259,7 @@ unsigned long do_mremap(unsigned long ad
24849 struct vm_area_struct *vma;
24850 unsigned long ret = -EINVAL;
24851 unsigned long charged = 0;
24852+ unsigned long task_size = TASK_SIZE;
24853
24854 if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
24855 goto out;
24856@@ -271,6 +278,15 @@ unsigned long do_mremap(unsigned long ad
24857 if (!new_len)
24858 goto out;
24859
24860+#ifdef CONFIG_PAX_SEGMEXEC
24861+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
24862+ task_size = SEGMEXEC_TASK_SIZE;
24863+#endif
24864+
24865+ if (new_len > task_size || addr > task_size-new_len ||
24866+ old_len > task_size || addr > task_size-old_len)
24867+ goto out;
24868+
24869 /* new_addr is only valid if MREMAP_FIXED is specified */
24870 if (flags & MREMAP_FIXED) {
24871 if (new_addr & ~PAGE_MASK)
24872@@ -278,16 +294,13 @@ unsigned long do_mremap(unsigned long ad
24873 if (!(flags & MREMAP_MAYMOVE))
24874 goto out;
24875
24876- if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
24877+ if (new_addr > task_size - new_len)
24878 goto out;
24879
24880 /* Check if the location we're moving into overlaps the
24881 * old location at all, and fail if it does.
24882 */
24883- if ((new_addr <= addr) && (new_addr+new_len) > addr)
24884- goto out;
24885-
24886- if ((addr <= new_addr) && (addr+old_len) > new_addr)
24887+ if (addr + old_len > new_addr && new_addr + new_len > addr)
24888 goto out;
24889
24890 ret = do_munmap(mm, new_addr, new_len);
24891@@ -321,6 +334,14 @@ unsigned long do_mremap(unsigned long ad
24892 ret = -EINVAL;
24893 goto out;
24894 }
24895+
24896+#ifdef CONFIG_PAX_SEGMEXEC
24897+ if (vma->vm_flags & VM_MIRROR) {
24898+ ret = -EINVAL;
24899+ goto out;
24900+ }
24901+#endif
24902+
24903 /* We can't remap across vm area boundaries */
24904 if (old_len > vma->vm_end - addr)
24905 goto out;
24906@@ -354,7 +375,7 @@ unsigned long do_mremap(unsigned long ad
24907 if (old_len == vma->vm_end - addr &&
24908 !((flags & MREMAP_FIXED) && (addr != new_addr)) &&
24909 (old_len != new_len || !(flags & MREMAP_MAYMOVE))) {
24910- unsigned long max_addr = TASK_SIZE;
24911+ unsigned long max_addr = task_size;
24912 if (vma->vm_next)
24913 max_addr = vma->vm_next->vm_start;
24914 /* can we just expand the current mapping? */
24915@@ -372,6 +393,7 @@ unsigned long do_mremap(unsigned long ad
24916 addr + new_len);
24917 }
24918 ret = addr;
24919+ track_exec_limit(vma->vm_mm, vma->vm_start, addr + new_len, vma->vm_flags);
24920 goto out;
24921 }
24922 }
24923@@ -382,8 +404,8 @@ unsigned long do_mremap(unsigned long ad
24924 */
24925 ret = -ENOMEM;
24926 if (flags & MREMAP_MAYMOVE) {
24927+ unsigned long map_flags = 0;
24928 if (!(flags & MREMAP_FIXED)) {
24929- unsigned long map_flags = 0;
24930 if (vma->vm_flags & VM_MAYSHARE)
24931 map_flags |= MAP_SHARED;
24932
24933@@ -393,7 +415,12 @@ unsigned long do_mremap(unsigned long ad
24934 if (new_addr & ~PAGE_MASK)
24935 goto out;
24936 }
24937+ map_flags = vma->vm_flags;
24938 ret = move_vma(vma, addr, old_len, new_len, new_addr);
24939+ if (!(ret & ~PAGE_MASK)) {
24940+ track_exec_limit(current->mm, addr, addr + old_len, 0UL);
24941+ track_exec_limit(current->mm, new_addr, new_addr + new_len, map_flags);
24942+ }
24943 }
24944 out:
24945 if (ret & ~PAGE_MASK)
24946diff -urNp linux-2.6.17.7/mm/page_alloc.c linux-2.6.17.7/mm/page_alloc.c
24947--- linux-2.6.17.7/mm/page_alloc.c 2006-07-24 23:36:01.000000000 -0400
24948+++ linux-2.6.17.7/mm/page_alloc.c 2006-08-01 20:29:48.000000000 -0400
24949@@ -334,7 +334,7 @@ static inline int page_is_buddy(struct p
24950 static inline void __free_one_page(struct page *page,
24951 struct zone *zone, unsigned int order)
24952 {
24953- unsigned long page_idx;
24954+ unsigned long page_idx, index;
24955 int order_size = 1 << order;
24956
24957 if (unlikely(PageCompound(page)))
24958@@ -345,6 +345,11 @@ static inline void __free_one_page(struc
24959 BUG_ON(page_idx & (order_size - 1));
24960 BUG_ON(bad_range(zone, page));
24961
24962+#ifdef CONFIG_PAX_MEMORY_SANITIZE
24963+ for (index = order_size; index; --index)
24964+ clear_highpage(page + index - 1);
24965+#endif
24966+
24967 zone->free_pages += order_size;
24968 while (order < MAX_ORDER-1) {
24969 unsigned long combined_idx;
24970diff -urNp linux-2.6.17.7/mm/rmap.c linux-2.6.17.7/mm/rmap.c
24971--- linux-2.6.17.7/mm/rmap.c 2006-07-24 23:36:01.000000000 -0400
24972+++ linux-2.6.17.7/mm/rmap.c 2006-08-01 20:29:48.000000000 -0400
24973@@ -106,6 +106,19 @@ int anon_vma_prepare(struct vm_area_stru
24974 list_add(&vma->anon_vma_node, &anon_vma->head);
24975 allocated = NULL;
24976 }
24977+
24978+#ifdef CONFIG_PAX_SEGMEXEC
24979+ if (vma->vm_flags & VM_MIRROR) {
24980+ struct vm_area_struct *vma_m;
24981+
24982+ vma_m = find_vma(vma->vm_mm, vma->vm_start + vma->vm_mirror);
24983+ BUG_ON(!vma_m || vma_m->vm_start != vma->vm_start + vma->vm_mirror);
24984+ BUG_ON(vma_m->anon_vma || vma->vm_pgoff != vma_m->vm_pgoff);
24985+ vma_m->anon_vma = anon_vma;
24986+ __anon_vma_link(vma_m);
24987+ }
24988+#endif
24989+
24990 spin_unlock(&mm->page_table_lock);
24991
24992 if (locked)
24993diff -urNp linux-2.6.17.7/mm/shmem.c linux-2.6.17.7/mm/shmem.c
24994--- linux-2.6.17.7/mm/shmem.c 2006-07-24 23:36:01.000000000 -0400
24995+++ linux-2.6.17.7/mm/shmem.c 2006-08-01 20:29:48.000000000 -0400
24996@@ -2245,7 +2245,7 @@ static struct file_system_type tmpfs_fs_
24997 .get_sb = shmem_get_sb,
24998 .kill_sb = kill_litter_super,
24999 };
25000-static struct vfsmount *shm_mnt;
25001+struct vfsmount *shm_mnt;
25002
25003 static int __init init_tmpfs(void)
25004 {
25005diff -urNp linux-2.6.17.7/mm/tiny-shmem.c linux-2.6.17.7/mm/tiny-shmem.c
25006--- linux-2.6.17.7/mm/tiny-shmem.c 2006-07-24 23:36:01.000000000 -0400
25007+++ linux-2.6.17.7/mm/tiny-shmem.c 2006-08-01 20:29:48.000000000 -0400
25008@@ -27,7 +27,7 @@ static struct file_system_type tmpfs_fs_
25009 .kill_sb = kill_litter_super,
25010 };
25011
25012-static struct vfsmount *shm_mnt;
25013+struct vfsmount *shm_mnt;
25014
25015 static int __init init_tmpfs(void)
25016 {
25017diff -urNp linux-2.6.17.7/mm/vmalloc.c linux-2.6.17.7/mm/vmalloc.c
25018--- linux-2.6.17.7/mm/vmalloc.c 2006-07-24 23:36:01.000000000 -0400
25019+++ linux-2.6.17.7/mm/vmalloc.c 2006-08-01 20:29:48.000000000 -0400
25020@@ -193,6 +193,8 @@ struct vm_struct *__get_vm_area_node(uns
25021
25022 write_lock(&vmlist_lock);
25023 for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
25024+ if (addr > end - size)
25025+ goto out;
25026 if ((unsigned long)tmp->addr < addr) {
25027 if((unsigned long)tmp->addr + tmp->size >= addr)
25028 addr = ALIGN(tmp->size +
25029@@ -204,8 +206,6 @@ struct vm_struct *__get_vm_area_node(uns
25030 if (size + addr <= (unsigned long)tmp->addr)
25031 goto found;
25032 addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);
25033- if (addr > end - size)
25034- goto out;
25035 }
25036
25037 found:
25038diff -urNp linux-2.6.17.7/net/ipv4/inet_connection_sock.c linux-2.6.17.7/net/ipv4/inet_connection_sock.c
25039--- linux-2.6.17.7/net/ipv4/inet_connection_sock.c 2006-07-24 23:36:01.000000000 -0400
25040+++ linux-2.6.17.7/net/ipv4/inet_connection_sock.c 2006-08-01 20:29:48.000000000 -0400
25041@@ -16,6 +16,7 @@
25042 #include <linux/config.h>
25043 #include <linux/module.h>
25044 #include <linux/jhash.h>
25045+#include <linux/grsecurity.h>
25046
25047 #include <net/inet_connection_sock.h>
25048 #include <net/inet_hashtables.h>
25049diff -urNp linux-2.6.17.7/net/ipv4/inet_hashtables.c linux-2.6.17.7/net/ipv4/inet_hashtables.c
25050--- linux-2.6.17.7/net/ipv4/inet_hashtables.c 2006-07-24 23:36:01.000000000 -0400
25051+++ linux-2.6.17.7/net/ipv4/inet_hashtables.c 2006-08-01 20:29:48.000000000 -0400
25052@@ -19,11 +19,14 @@
25053 #include <linux/sched.h>
25054 #include <linux/slab.h>
25055 #include <linux/wait.h>
25056+#include <linux/grsecurity.h>
25057
25058 #include <net/inet_connection_sock.h>
25059 #include <net/inet_hashtables.h>
25060 #include <net/ip.h>
25061
25062+extern void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet);
25063+
25064 /*
25065 * Allocate and initialize a new local port bind bucket.
25066 * The bindhash mutex for snum's hash chain must be held here.
25067@@ -310,6 +313,8 @@ ok:
25068 }
25069 spin_unlock(&head->lock);
25070
25071+ gr_update_task_in_ip_table(current, inet_sk(sk));
25072+
25073 if (tw) {
25074 inet_twsk_deschedule(tw, death_row);
25075 inet_twsk_put(tw);
25076diff -urNp linux-2.6.17.7/net/ipv4/netfilter/Kconfig linux-2.6.17.7/net/ipv4/netfilter/Kconfig
25077--- linux-2.6.17.7/net/ipv4/netfilter/Kconfig 2006-07-24 23:36:01.000000000 -0400
25078+++ linux-2.6.17.7/net/ipv4/netfilter/Kconfig 2006-08-01 20:29:48.000000000 -0400
25079@@ -314,6 +314,21 @@ config IP_NF_MATCH_HASHLIMIT
25080 destination IP' or `500pps from any given source IP' with a single
25081 IPtables rule.
25082
25083+config IP_NF_MATCH_STEALTH
25084+ tristate "stealth match support"
25085+ depends on IP_NF_IPTABLES
25086+ help
25087+ Enabling this option will drop all syn packets coming to unserved tcp
25088+ ports as well as all packets coming to unserved udp ports. If you
25089+ are using your system to route any type of packets (ie. via NAT)
25090+ you should put this module at the end of your ruleset, since it will
25091+ drop packets that aren't going to ports that are listening on your
25092+ machine itself, it doesn't take into account that the packet might be
25093+ destined for someone on your internal network if you're using NAT for
25094+ instance.
25095+
25096+ To compile it as a module, choose M here. If unsure, say N.
25097+
25098 # `filter', generic and specific targets
25099 config IP_NF_FILTER
25100 tristate "Packet filtering"
25101@@ -614,4 +629,3 @@ config IP_NF_ARP_MANGLE
25102 hardware and network addresses.
25103
25104 endmenu
25105-
25106diff -urNp linux-2.6.17.7/net/ipv4/netfilter/Makefile linux-2.6.17.7/net/ipv4/netfilter/Makefile
25107--- linux-2.6.17.7/net/ipv4/netfilter/Makefile 2006-07-24 23:36:01.000000000 -0400
25108+++ linux-2.6.17.7/net/ipv4/netfilter/Makefile 2006-08-01 20:29:48.000000000 -0400
25109@@ -61,6 +61,7 @@ obj-$(CONFIG_IP_NF_MATCH_DSCP) += ipt_ds
25110 obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o
25111 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
25112 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
25113+obj-$(CONFIG_IP_NF_MATCH_STEALTH) += ipt_stealth.o
25114
25115 # targets
25116 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
25117diff -urNp linux-2.6.17.7/net/ipv4/netfilter/ipt_stealth.c linux-2.6.17.7/net/ipv4/netfilter/ipt_stealth.c
25118--- linux-2.6.17.7/net/ipv4/netfilter/ipt_stealth.c 1969-12-31 19:00:00.000000000 -0500
25119+++ linux-2.6.17.7/net/ipv4/netfilter/ipt_stealth.c 2006-08-01 20:29:48.000000000 -0400
25120@@ -0,0 +1,112 @@
25121+/* Kernel module to add stealth support.
25122+ *
25123+ * Copyright (C) 2002,2005 Brad Spengler <spender@grsecurity.net>
25124+ *
25125+ */
25126+
25127+#include <linux/kernel.h>
25128+#include <linux/module.h>
25129+#include <linux/skbuff.h>
25130+#include <linux/net.h>
25131+#include <linux/sched.h>
25132+#include <linux/inet.h>
25133+#include <linux/stddef.h>
25134+
25135+#include <net/ip.h>
25136+#include <net/sock.h>
25137+#include <net/tcp.h>
25138+#include <net/udp.h>
25139+#include <net/route.h>
25140+#include <net/inet_common.h>
25141+
25142+#include <linux/netfilter_ipv4/ip_tables.h>
25143+
25144+MODULE_LICENSE("GPL");
25145+
25146+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
25147+
25148+static int
25149+match(const struct sk_buff *skb,
25150+ const struct net_device *in,
25151+ const struct net_device *out,
25152+ const void *matchinfo,
25153+ int offset,
25154+ int *hotdrop)
25155+{
25156+ struct iphdr *ip = skb->nh.iph;
25157+ struct tcphdr th;
25158+ struct udphdr uh;
25159+ struct sock *sk = NULL;
25160+
25161+ if (!ip || offset) return 0;
25162+
25163+ switch(ip->protocol) {
25164+ case IPPROTO_TCP:
25165+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &th, sizeof(th)) < 0) {
25166+ *hotdrop = 1;
25167+ return 0;
25168+ }
25169+ if (!(th.syn && !th.ack)) return 0;
25170+ sk = inet_lookup_listener(&tcp_hashinfo, ip->daddr, ntohs(th.dest), ((struct rtable*)skb->dst)->rt_iif);
25171+ break;
25172+ case IPPROTO_UDP:
25173+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &uh, sizeof(uh)) < 0) {
25174+ *hotdrop = 1;
25175+ return 0;
25176+ }
25177+ sk = udp_v4_lookup(ip->saddr, uh.source, ip->daddr, uh.dest, skb->dev->ifindex);
25178+ break;
25179+ default:
25180+ return 0;
25181+ }
25182+
25183+ if(!sk) // port is being listened on, match this
25184+ return 1;
25185+ else {
25186+ sock_put(sk);
25187+ return 0;
25188+ }
25189+}
25190+
25191+/* Called when user tries to insert an entry of this type. */
25192+static int
25193+checkentry(const char *tablename,
25194+ const struct ipt_ip *ip,
25195+ void *matchinfo,
25196+ unsigned int matchsize,
25197+ unsigned int hook_mask)
25198+{
25199+ if (matchsize != IPT_ALIGN(0))
25200+ return 0;
25201+
25202+ if(((ip->proto == IPPROTO_TCP && !(ip->invflags & IPT_INV_PROTO)) ||
25203+ ((ip->proto == IPPROTO_UDP) && !(ip->invflags & IPT_INV_PROTO)))
25204+ && (hook_mask & (1 << NF_IP_LOCAL_IN)))
25205+ return 1;
25206+
25207+ printk("stealth: Only works on TCP and UDP for the INPUT chain.\n");
25208+
25209+ return 0;
25210+}
25211+
25212+
25213+static struct ipt_match stealth_match = {
25214+ .name = "stealth",
25215+ .match = &match,
25216+ .checkentry = &checkentry,
25217+ .destroy = NULL,
25218+ .me = THIS_MODULE
25219+};
25220+
25221+static int __init init(void)
25222+{
25223+ return ipt_register_match(&stealth_match);
25224+}
25225+
25226+static void __exit fini(void)
25227+{
25228+ ipt_unregister_match(&stealth_match);
25229+}
25230+
25231+module_init(init);
25232+module_exit(fini);
25233diff -urNp linux-2.6.17.7/net/ipv4/tcp_ipv4.c linux-2.6.17.7/net/ipv4/tcp_ipv4.c
25234--- linux-2.6.17.7/net/ipv4/tcp_ipv4.c 2006-07-24 23:36:01.000000000 -0400
25235+++ linux-2.6.17.7/net/ipv4/tcp_ipv4.c 2006-08-01 20:29:48.000000000 -0400
25236@@ -62,6 +62,7 @@
25237 #include <linux/jhash.h>
25238 #include <linux/init.h>
25239 #include <linux/times.h>
25240+#include <linux/grsecurity.h>
25241
25242 #include <net/icmp.h>
25243 #include <net/inet_hashtables.h>
25244diff -urNp linux-2.6.17.7/net/ipv4/udp.c linux-2.6.17.7/net/ipv4/udp.c
25245--- linux-2.6.17.7/net/ipv4/udp.c 2006-07-24 23:36:01.000000000 -0400
25246+++ linux-2.6.17.7/net/ipv4/udp.c 2006-08-01 20:29:48.000000000 -0400
25247@@ -102,6 +102,7 @@
25248 #include <linux/skbuff.h>
25249 #include <linux/proc_fs.h>
25250 #include <linux/seq_file.h>
25251+#include <linux/grsecurity.h>
25252 #include <net/sock.h>
25253 #include <net/udp.h>
25254 #include <net/icmp.h>
25255@@ -110,6 +111,12 @@
25256 #include <net/checksum.h>
25257 #include <net/xfrm.h>
25258
25259+extern int gr_search_udp_recvmsg(const struct sock *sk,
25260+ const struct sk_buff *skb);
25261+extern int gr_search_udp_sendmsg(const struct sock *sk,
25262+ const struct sockaddr_in *addr);
25263+
25264+
25265 /*
25266 * Snmp MIB for the UDP layer
25267 */
25268@@ -266,8 +273,7 @@ static struct sock *udp_v4_lookup_longwa
25269 return result;
25270 }
25271
25272-static __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport,
25273- u32 daddr, u16 dport, int dif)
25274+struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
25275 {
25276 struct sock *sk;
25277
25278@@ -542,9 +548,16 @@ int udp_sendmsg(struct kiocb *iocb, stru
25279 dport = usin->sin_port;
25280 if (dport == 0)
25281 return -EINVAL;
25282+
25283+ if (!gr_search_udp_sendmsg(sk, usin))
25284+ return -EPERM;
25285 } else {
25286 if (sk->sk_state != TCP_ESTABLISHED)
25287 return -EDESTADDRREQ;
25288+
25289+ if (!gr_search_udp_sendmsg(sk, NULL))
25290+ return -EPERM;
25291+
25292 daddr = inet->daddr;
25293 dport = inet->dport;
25294 /* Open fast path for connected socket.
25295@@ -798,6 +811,11 @@ try_again:
25296 if (!skb)
25297 goto out;
25298
25299+ if (!gr_search_udp_recvmsg(sk, skb)) {
25300+ err = -EPERM;
25301+ goto out_free;
25302+ }
25303+
25304 copied = skb->len - sizeof(struct udphdr);
25305 if (copied > len) {
25306 copied = len;
25307diff -urNp linux-2.6.17.7/net/socket.c linux-2.6.17.7/net/socket.c
25308--- linux-2.6.17.7/net/socket.c 2006-07-24 23:36:01.000000000 -0400
25309+++ linux-2.6.17.7/net/socket.c 2006-08-01 20:29:48.000000000 -0400
25310@@ -86,6 +86,7 @@
25311 #include <linux/kmod.h>
25312 #include <linux/audit.h>
25313 #include <linux/wireless.h>
25314+#include <linux/in.h>
25315
25316 #include <asm/uaccess.h>
25317 #include <asm/unistd.h>
25318@@ -95,6 +96,21 @@
25319 #include <net/sock.h>
25320 #include <linux/netfilter.h>
25321
25322+extern void gr_attach_curr_ip(const struct sock *sk);
25323+extern int gr_handle_sock_all(const int family, const int type,
25324+ const int protocol);
25325+extern int gr_handle_sock_server(const struct sockaddr *sck);
25326+extern int gr_handle_sock_server_other(const struct socket *sck);
25327+extern int gr_handle_sock_client(const struct sockaddr *sck);
25328+extern int gr_search_connect(const struct socket * sock,
25329+ const struct sockaddr_in * addr);
25330+extern int gr_search_bind(const struct socket * sock,
25331+ const struct sockaddr_in * addr);
25332+extern int gr_search_listen(const struct socket * sock);
25333+extern int gr_search_accept(const struct socket * sock);
25334+extern int gr_search_socket(const int domain, const int type,
25335+ const int protocol);
25336+
25337 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
25338 static ssize_t sock_aio_read(struct kiocb *iocb, char __user *buf,
25339 size_t size, loff_t pos);
25340@@ -341,7 +357,7 @@ static struct super_block *sockfs_get_sb
25341 return get_sb_pseudo(fs_type, "socket:", &sockfs_ops, SOCKFS_MAGIC);
25342 }
25343
25344-static struct vfsmount *sock_mnt __read_mostly;
25345+struct vfsmount *sock_mnt __read_mostly;
25346
25347 static struct file_system_type sock_fs_type = {
25348 .name = "sockfs",
25349@@ -1240,6 +1256,16 @@ asmlinkage long sys_socket(int family, i
25350 int retval;
25351 struct socket *sock;
25352
25353+ if(!gr_search_socket(family, type, protocol)) {
25354+ retval = -EACCES;
25355+ goto out;
25356+ }
25357+
25358+ if (gr_handle_sock_all(family, type, protocol)) {
25359+ retval = -EACCES;
25360+ goto out;
25361+ }
25362+
25363 retval = sock_create(family, type, protocol, &sock);
25364 if (retval < 0)
25365 goto out;
25366@@ -1335,16 +1361,25 @@ asmlinkage long sys_bind(int fd, struct
25367 {
25368 struct socket *sock;
25369 char address[MAX_SOCK_ADDR];
25370+ struct sockaddr *sck;
25371 int err, fput_needed;
25372
25373 if((sock = sockfd_lookup_light(fd, &err, &fput_needed))!=NULL)
25374 {
25375 if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
25376+ sck = (struct sockaddr *)address;
25377+ if (!gr_search_bind(sock, (struct sockaddr_in *)sck) ||
25378+ gr_handle_sock_server(sck)) {
25379+ err = -EACCES;
25380+ goto error;
25381+ }
25382+
25383 err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
25384 if (!err)
25385 err = sock->ops->bind(sock,
25386 (struct sockaddr *)address, addrlen);
25387 }
25388+error:
25389 fput_light(sock->file, fput_needed);
25390 }
25391 return err;
25392@@ -1368,10 +1403,17 @@ asmlinkage long sys_listen(int fd, int b
25393 if ((unsigned) backlog > sysctl_somaxconn)
25394 backlog = sysctl_somaxconn;
25395
25396+ if (gr_handle_sock_server_other(sock) ||
25397+ !gr_search_listen(sock)) {
25398+ err = -EPERM;
25399+ goto error;
25400+ }
25401+
25402 err = security_socket_listen(sock, backlog);
25403 if (!err)
25404 err = sock->ops->listen(sock, backlog);
25405
25406+error:
25407 fput_light(sock->file, fput_needed);
25408 }
25409 return err;
25410@@ -1408,6 +1450,13 @@ asmlinkage long sys_accept(int fd, struc
25411 newsock->type = sock->type;
25412 newsock->ops = sock->ops;
25413
25414+ if (gr_handle_sock_server_other(sock) ||
25415+ !gr_search_accept(sock)) {
25416+ err = -EPERM;
25417+ sock_release(newsock);
25418+ goto out_put;
25419+ }
25420+
25421 /*
25422 * We don't need try_module_get here, as the listening socket (sock)
25423 * has the protocol module (sock->ops->owner) held.
25424@@ -1449,6 +1498,7 @@ asmlinkage long sys_accept(int fd, struc
25425 err = newfd;
25426
25427 security_socket_post_accept(sock, newsock);
25428+ gr_attach_curr_ip(newsock->sk);
25429
25430 out_put:
25431 fput_light(sock->file, fput_needed);
25432@@ -1477,6 +1527,7 @@ asmlinkage long sys_connect(int fd, stru
25433 {
25434 struct socket *sock;
25435 char address[MAX_SOCK_ADDR];
25436+ struct sockaddr *sck;
25437 int err, fput_needed;
25438
25439 sock = sockfd_lookup_light(fd, &err, &fput_needed);
25440@@ -1486,6 +1537,13 @@ asmlinkage long sys_connect(int fd, stru
25441 if (err < 0)
25442 goto out_put;
25443
25444+ sck = (struct sockaddr *)address;
25445+ if (!gr_search_connect(sock, (struct sockaddr_in *)sck) ||
25446+ gr_handle_sock_client(sck)) {
25447+ err = -EACCES;
25448+ goto out_put;
25449+ }
25450+
25451 err = security_socket_connect(sock, (struct sockaddr *)address, addrlen);
25452 if (err)
25453 goto out_put;
25454@@ -1740,6 +1798,7 @@ asmlinkage long sys_shutdown(int fd, int
25455 err = sock->ops->shutdown(sock, how);
25456 fput_light(sock->file, fput_needed);
25457 }
25458+
25459 return err;
25460 }
25461
25462diff -urNp linux-2.6.17.7/net/unix/af_unix.c linux-2.6.17.7/net/unix/af_unix.c
25463--- linux-2.6.17.7/net/unix/af_unix.c 2006-07-24 23:36:01.000000000 -0400
25464+++ linux-2.6.17.7/net/unix/af_unix.c 2006-08-01 20:29:48.000000000 -0400
25465@@ -117,6 +117,7 @@
77fa6d7d 25466 #include <linux/vs_context.h>
25467 #include <linux/vs_network.h>
25468 #include <linux/vs_limit.h>
f1a4f855 25469+#include <linux/grsecurity.h>
25470
25471 int sysctl_unix_max_dgram_qlen = 10;
25472
25473@@ -680,6 +681,11 @@ static struct sock *unix_find_other(stru
25474 if (err)
25475 goto put_fail;
25476
25477+ if (!gr_acl_handle_unix(nd.dentry, nd.mnt)) {
25478+ err = -EACCES;
25479+ goto put_fail;
25480+ }
25481+
25482 err = -ECONNREFUSED;
25483 if (!S_ISSOCK(nd.dentry->d_inode->i_mode))
25484 goto put_fail;
25485@@ -703,6 +709,13 @@ static struct sock *unix_find_other(stru
25486 if (u) {
25487 struct dentry *dentry;
25488 dentry = unix_sk(u)->dentry;
25489+
25490+ if (!gr_handle_chroot_unix(u->sk_peercred.pid)) {
25491+ err = -EPERM;
25492+ sock_put(u);
25493+ goto fail;
25494+ }
25495+
25496 if (dentry)
25497 touch_atime(unix_sk(u)->mnt, dentry);
25498 } else
25499@@ -781,9 +794,18 @@ static int unix_bind(struct socket *sock
25500 */
25501 mode = S_IFSOCK |
25502 (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
25503+
25504+ if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) {
25505+ err = -EACCES;
25506+ goto out_mknod_dput;
25507+ }
25508+
77fa6d7d 25509 err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0, NULL);
f1a4f855 25510 if (err)
25511 goto out_mknod_dput;
25512+
25513+ gr_handle_create(dentry, nd.mnt);
25514+
25515 mutex_unlock(&nd.dentry->d_inode->i_mutex);
25516 dput(nd.dentry);
25517 nd.dentry = dentry;
25518@@ -801,6 +823,10 @@ static int unix_bind(struct socket *sock
25519 goto out_unlock;
25520 }
25521
25522+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
25523+ sk->sk_peercred.pid = current->pid;
25524+#endif
25525+
25526 list = &unix_socket_table[addr->hash];
25527 } else {
25528 list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
25529diff -urNp linux-2.6.17.7/security/Kconfig linux-2.6.17.7/security/Kconfig
25530--- linux-2.6.17.7/security/Kconfig 2006-07-24 23:36:01.000000000 -0400
25531+++ linux-2.6.17.7/security/Kconfig 2006-08-01 20:29:48.000000000 -0400
25532@@ -4,6 +4,453 @@
25533
25534 menu "Security options"
25535
25536+menu "PaX"
25537+
25538+config PAX
25539+ bool "Enable various PaX features"
25540+ depends on GRKERNSEC && (ALPHA || ARM || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || PPC64 || SPARC32 || SPARC64 || X86 || X86_64)
25541+ help
25542+ This allows you to enable various PaX features. PaX adds
25543+ intrusion prevention mechanisms to the kernel that reduce
25544+ the risks posed by exploitable memory corruption bugs.
25545+
25546+menu "PaX Control"
25547+ depends on PAX
25548+
25549+config PAX_SOFTMODE
25550+ bool 'Support soft mode'
25551+ help
25552+ Enabling this option will allow you to run PaX in soft mode, that
25553+ is, PaX features will not be enforced by default, only on executables
25554+ marked explicitly. You must also enable PT_PAX_FLAGS support as it
25555+ is the only way to mark executables for soft mode use.
25556+
25557+ Soft mode can be activated by using the "pax_softmode=1" kernel command
25558+ line option on boot. Furthermore you can control various PaX features
25559+ at runtime via the entries in /proc/sys/kernel/pax.
25560+
25561+config PAX_EI_PAX
25562+ bool 'Use legacy ELF header marking'
25563+ help
25564+ Enabling this option will allow you to control PaX features on
25565+ a per executable basis via the 'chpax' utility available at
25566+ http://pax.grsecurity.net/. The control flags will be read from
25567+ an otherwise reserved part of the ELF header. This marking has
25568+ numerous drawbacks (no support for soft-mode, toolchain does not
25569+ know about the non-standard use of the ELF header) therefore it
25570+ has been deprecated in favour of PT_PAX_FLAGS support.
25571+
25572+ If you have applications not marked by the PT_PAX_FLAGS ELF
25573+ program header then you MUST enable this option otherwise they
25574+ will not get any protection.
25575+
25576+ Note that if you enable PT_PAX_FLAGS marking support as well,
25577+ the PT_PAX_FLAG marks will override the legacy EI_PAX marks.
25578+
25579+config PAX_PT_PAX_FLAGS
25580+ bool 'Use ELF program header marking'
25581+ help
25582+ Enabling this option will allow you to control PaX features on
25583+ a per executable basis via the 'paxctl' utility available at
25584+ http://pax.grsecurity.net/. The control flags will be read from
25585+ a PaX specific ELF program header (PT_PAX_FLAGS). This marking
25586+ has the benefits of supporting both soft mode and being fully
25587+ integrated into the toolchain (the binutils patch is available
25588+ from http://pax.grsecurity.net).
25589+
25590+ If you have applications not marked by the PT_PAX_FLAGS ELF
25591+ program header then you MUST enable the EI_PAX marking support
25592+ otherwise they will not get any protection.
25593+
25594+ Note that if you enable the legacy EI_PAX marking support as well,
25595+ the EI_PAX marks will be overridden by the PT_PAX_FLAGS marks.
25596+
25597+choice
25598+ prompt 'MAC system integration'
25599+ default PAX_HAVE_ACL_FLAGS
25600+ help
25601+ Mandatory Access Control systems have the option of controlling
25602+ PaX flags on a per executable basis, choose the method supported
25603+ by your particular system.
25604+
25605+ - "none": if your MAC system does not interact with PaX,
25606+ - "direct": if your MAC system defines pax_set_flags() itself,
25607+ - "hook": if your MAC system uses the pax_set_flags_func callback.
25608+
25609+ NOTE: this option is for developers/integrators only.
25610+
25611+config PAX_NO_ACL_FLAGS
25612+ bool 'none'
25613+
25614+config PAX_HAVE_ACL_FLAGS
25615+ bool 'direct'
25616+
25617+config PAX_HOOK_ACL_FLAGS
25618+ bool 'hook'
25619+endchoice
25620+
25621+endmenu
25622+
25623+menu "Non-executable pages"
25624+ depends on PAX
25625+
25626+config PAX_NOEXEC
25627+ bool "Enforce non-executable pages"
25628+ 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)
25629+ help
25630+ By design some architectures do not allow for protecting memory
25631+ pages against execution or even if they do, Linux does not make
25632+ use of this feature. In practice this means that if a page is
25633+ readable (such as the stack or heap) it is also executable.
25634+
25635+ There is a well known exploit technique that makes use of this
25636+ fact and a common programming mistake where an attacker can
25637+ introduce code of his choice somewhere in the attacked program's
25638+ memory (typically the stack or the heap) and then execute it.
25639+
25640+ If the attacked program was running with different (typically
25641+ higher) privileges than that of the attacker, then he can elevate
25642+ his own privilege level (e.g. get a root shell, write to files for
25643+ which he does not have write access to, etc).
25644+
25645+ Enabling this option will let you choose from various features
25646+ that prevent the injection and execution of 'foreign' code in
25647+ a program.
25648+
25649+ This will also break programs that rely on the old behaviour and
25650+ expect that dynamically allocated memory via the malloc() family
25651+ of functions is executable (which it is not). Notable examples
25652+ are the XFree86 4.x server, the java runtime and wine.
25653+
25654+config PAX_PAGEEXEC
25655+ bool "Paging based non-executable pages"
25656+ depends on PAX_NOEXEC && (!X86_32 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MPENTIUM4 || MK7 || MK8 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MVIAC3_2)
25657+ select PAX_NOVSYSCALL if X86_32
25658+ help
25659+ This implementation is based on the paging feature of the CPU.
25660+ On i386 and ppc there is a variable but usually low performance
25661+ impact on applications. On alpha, ia64, parisc, sparc, sparc64
25662+ and x86_64 there is no performance impact.
25663+
25664+config PAX_SEGMEXEC
25665+ bool "Segmentation based non-executable pages"
25666+ depends on PAX_NOEXEC && X86_32
25667+ select PAX_NOVSYSCALL
25668+ help
25669+ This implementation is based on the segmentation feature of the
25670+ CPU and has little performance impact, however applications will
25671+ be limited to a 1.5 GB address space instead of the normal 3 GB.
25672+
25673+choice
25674+ prompt "Default non-executable page method"
25675+ depends on PAX_PAGEEXEC && PAX_SEGMEXEC
25676+ default PAX_DEFAULT_SEGMEXEC
25677+ help
25678+ Select the default non-executable page method applied to applications
25679+ that do not select one themselves.
25680+
25681+config PAX_DEFAULT_PAGEEXEC
25682+ bool "PAGEEXEC"
25683+
25684+config PAX_DEFAULT_SEGMEXEC
25685+ bool "SEGMEXEC"
25686+endchoice
25687+
25688+config PAX_EMUTRAMP
25689+ bool "Emulate trampolines" if (PAX_PAGEEXEC || PAX_SEGMEXEC) && (PARISC || PPC32 || X86_32)
25690+ default y if PARISC || PPC32
25691+ help
25692+ There are some programs and libraries that for one reason or
25693+ another attempt to execute special small code snippets from
25694+ non-executable memory pages. Most notable examples are the
25695+ signal handler return code generated by the kernel itself and
25696+ the GCC trampolines.
25697+
25698+ If you enabled CONFIG_PAX_PAGEEXEC or CONFIG_PAX_SEGMEXEC then
25699+ such programs will no longer work under your kernel.
25700+
25701+ As a remedy you can say Y here and use the 'chpax' or 'paxctl'
25702+ utilities to enable trampoline emulation for the affected programs
25703+ yet still have the protection provided by the non-executable pages.
25704+
25705+ On parisc and ppc you MUST enable this option and EMUSIGRT as
25706+ well, otherwise your system will not even boot.
25707+
25708+ Alternatively you can say N here and use the 'chpax' or 'paxctl'
25709+ utilities to disable CONFIG_PAX_PAGEEXEC and CONFIG_PAX_SEGMEXEC
25710+ for the affected files.
25711+
25712+ NOTE: enabling this feature *may* open up a loophole in the
25713+ protection provided by non-executable pages that an attacker
25714+ could abuse. Therefore the best solution is to not have any
25715+ files on your system that would require this option. This can
25716+ be achieved by not using libc5 (which relies on the kernel
25717+ signal handler return code) and not using or rewriting programs
25718+ that make use of the nested function implementation of GCC.
25719+ Skilled users can just fix GCC itself so that it implements
25720+ nested function calls in a way that does not interfere with PaX.
25721+
25722+config PAX_EMUSIGRT
25723+ bool "Automatically emulate sigreturn trampolines"
25724+ depends on PAX_EMUTRAMP && (PARISC || PPC32)
25725+ default y
25726+ help
25727+ Enabling this option will have the kernel automatically detect
25728+ and emulate signal return trampolines executing on the stack
25729+ that would otherwise lead to task termination.
25730+
25731+ This solution is intended as a temporary one for users with
25732+ legacy versions of libc (libc5, glibc 2.0, uClibc before 0.9.17,
25733+ Modula-3 runtime, etc) or executables linked to such, basically
25734+ everything that does not specify its own SA_RESTORER function in
25735+ normal executable memory like glibc 2.1+ does.
25736+
25737+ On parisc and ppc you MUST enable this option, otherwise your
25738+ system will not even boot.
25739+
25740+ NOTE: this feature cannot be disabled on a per executable basis
25741+ and since it *does* open up a loophole in the protection provided
25742+ by non-executable pages, the best solution is to not have any
25743+ files on your system that would require this option.
25744+
25745+config PAX_MPROTECT
25746+ bool "Restrict mprotect()"
25747+ depends on (PAX_PAGEEXEC || PAX_SEGMEXEC) && !PPC64
25748+ help
25749+ Enabling this option will prevent programs from
25750+ - changing the executable status of memory pages that were
25751+ not originally created as executable,
25752+ - making read-only executable pages writable again,
25753+ - creating executable pages from anonymous memory.
25754+
25755+ You should say Y here to complete the protection provided by
25756+ the enforcement of non-executable pages.
25757+
25758+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control
25759+ this feature on a per file basis.
25760+
25761+config PAX_NOELFRELOCS
25762+ bool "Disallow ELF text relocations"
25763+ depends on PAX_MPROTECT && !PAX_ETEXECRELOCS && (IA64 || X86 || X86_64)
25764+ help
25765+ Non-executable pages and mprotect() restrictions are effective
25766+ in preventing the introduction of new executable code into an
25767+ attacked task's address space. There remain only two venues
25768+ for this kind of attack: if the attacker can execute already
25769+ existing code in the attacked task then he can either have it
25770+ create and mmap() a file containing his code or have it mmap()
25771+ an already existing ELF library that does not have position
25772+ independent code in it and use mprotect() on it to make it
25773+ writable and copy his code there. While protecting against
25774+ the former approach is beyond PaX, the latter can be prevented
25775+ by having only PIC ELF libraries on one's system (which do not
25776+ need to relocate their code). If you are sure this is your case,
25777+ then enable this option otherwise be careful as you may not even
25778+ be able to boot or log on your system (for example, some PAM
25779+ modules are erroneously compiled as non-PIC by default).
25780+
25781+ NOTE: if you are using dynamic ELF executables (as suggested
25782+ when using ASLR) then you must have made sure that you linked
25783+ your files using the PIC version of crt1 (the et_dyn.tar.gz package
25784+ referenced there has already been updated to support this).
25785+
25786+config PAX_ETEXECRELOCS
25787+ bool "Allow ELF ET_EXEC text relocations"
25788+ depends on PAX_MPROTECT && (ALPHA || IA64 || PARISC)
25789+ default y
25790+ help
25791+ On some architectures there are incorrectly created applications
25792+ that require text relocations and would not work without enabling
25793+ this option. If you are an alpha, ia64 or parisc user, you should
25794+ enable this option and disable it once you have made sure that
25795+ none of your applications need it.
25796+
25797+config PAX_EMUPLT
25798+ bool "Automatically emulate ELF PLT"
25799+ depends on PAX_MPROTECT && (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64)
25800+ default y
25801+ help
25802+ Enabling this option will have the kernel automatically detect
25803+ and emulate the Procedure Linkage Table entries in ELF files.
25804+ On some architectures such entries are in writable memory, and
25805+ become non-executable leading to task termination. Therefore
25806+ it is mandatory that you enable this option on alpha, parisc, ppc,
25807+ sparc and sparc64, otherwise your system would not even boot.
25808+
25809+ NOTE: this feature *does* open up a loophole in the protection
25810+ provided by the non-executable pages, therefore the proper
25811+ solution is to modify the toolchain to produce a PLT that does
25812+ not need to be writable.
25813+
25814+config PAX_DLRESOLVE
25815+ bool
25816+ depends on PAX_EMUPLT && (SPARC32 || SPARC64)
25817+ default y
25818+
25819+config PAX_SYSCALL
25820+ bool
25821+ depends on PAX_PAGEEXEC && PPC32
25822+ default y
25823+
25824+config PAX_KERNEXEC
25825+ bool "Enforce non-executable kernel pages"
25826+ depends on PAX_NOEXEC && X86_32 && !HOTPLUG_PCI_COMPAQ_NVRAM && !PCI_BIOS && !EFI && !DEBUG_RODATA
25827+ select PAX_NOVSYSCALL
25828+ help
25829+ This is the kernel land equivalent of PAGEEXEC and MPROTECT,
25830+ that is, enabling this option will make it harder to inject
25831+ and execute 'foreign' code in kernel memory itself.
25832+
25833+endmenu
25834+
25835+menu "Address Space Layout Randomization"
25836+ depends on PAX
25837+
25838+config PAX_ASLR
25839+ bool "Address Space Layout Randomization"
25840+ depends on PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS
25841+ help
25842+ Many if not most exploit techniques rely on the knowledge of
25843+ certain addresses in the attacked program. The following options
25844+ will allow the kernel to apply a certain amount of randomization
25845+ to specific parts of the program thereby forcing an attacker to
25846+ guess them in most cases. Any failed guess will most likely crash
25847+ the attacked program which allows the kernel to detect such attempts
25848+ and react on them. PaX itself provides no reaction mechanisms,
25849+ instead it is strongly encouraged that you make use of Nergal's
25850+ segvguard (ftp://ftp.pl.openwall.com/misc/segvguard/) or grsecurity's
25851+ (http://www.grsecurity.net/) built-in crash detection features or
25852+ develop one yourself.
25853+
25854+ By saying Y here you can choose to randomize the following areas:
25855+ - top of the task's kernel stack
25856+ - top of the task's userland stack
25857+ - base address for mmap() requests that do not specify one
25858+ (this includes all libraries)
25859+ - base address of the main executable
25860+
25861+ It is strongly recommended to say Y here as address space layout
25862+ randomization has negligible impact on performance yet it provides
25863+ a very effective protection.
25864+
25865+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control
25866+ this feature on a per file basis.
25867+
25868+config PAX_RANDKSTACK
25869+ bool "Randomize kernel stack base"
25870+ depends on PAX_ASLR && X86_TSC && X86_32
25871+ help
25872+ By saying Y here the kernel will randomize every task's kernel
25873+ stack on every system call. This will not only force an attacker
25874+ to guess it but also prevent him from making use of possible
25875+ leaked information about it.
25876+
25877+ Since the kernel stack is a rather scarce resource, randomization
25878+ may cause unexpected stack overflows, therefore you should very
25879+ carefully test your system. Note that once enabled in the kernel
25880+ configuration, this feature cannot be disabled on a per file basis.
25881+
25882+config PAX_RANDUSTACK
25883+ bool "Randomize user stack base"
25884+ depends on PAX_ASLR
25885+ help
25886+ By saying Y here the kernel will randomize every task's userland
25887+ stack. The randomization is done in two steps where the second
25888+ one may apply a big amount of shift to the top of the stack and
25889+ cause problems for programs that want to use lots of memory (more
25890+ than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is).
25891+ For this reason the second step can be controlled by 'chpax' or
25892+ 'paxctl' on a per file basis.
25893+
25894+config PAX_RANDMMAP
25895+ bool "Randomize mmap() base"
25896+ depends on PAX_ASLR
25897+ help
25898+ By saying Y here the kernel will use a randomized base address for
25899+ mmap() requests that do not specify one themselves. As a result
25900+ all dynamically loaded libraries will appear at random addresses
25901+ and therefore be harder to exploit by a technique where an attacker
25902+ attempts to execute library code for his purposes (e.g. spawn a
25903+ shell from an exploited program that is running at an elevated
25904+ privilege level).
25905+
25906+ Furthermore, if a program is relinked as a dynamic ELF file, its
25907+ base address will be randomized as well, completing the full
25908+ randomization of the address space layout. Attacking such programs
25909+ becomes a guess game. You can find an example of doing this at
25910+ http://pax.grsecurity.net/et_dyn.tar.gz and practical samples at
25911+ http://www.grsecurity.net/grsec-gcc-specs.tar.gz .
25912+
25913+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control this
25914+ feature on a per file basis.
25915+
25916+config PAX_NOVSYSCALL
25917+ bool "Disable the vsyscall page"
25918+ depends on PAX_ASLR && X86_32
25919+ help
25920+ The Linux 2.6 kernel introduced a new feature that speeds up or
25921+ simplifies certain operations, such as system calls or returns
25922+ from signal handlers.
25923+
25924+ Unfortunately the implementation also gives a powerful instrument
25925+ into the hands of exploit writers: the so-called vsyscall page exists
25926+ in every task at the same fixed address and it contains machine code
25927+ that is very useful in performing the return-to-libc style attack.
25928+
25929+ Since this exploit technique cannot in general be protected against
25930+ via kernel solutions, this option will allow you to disable the use
25931+ of the vsyscall page and revert back to the old behaviour.
25932+
25933+endmenu
25934+
25935+menu "Miscellaneous hardening features"
25936+
25937+config PAX_MEMORY_SANITIZE
25938+ bool "Sanitize all freed memory"
25939+ help
25940+ By saying Y here the kernel will erase memory pages as soon as they
25941+ are freed. This in turn reduces the lifetime of data stored in the
25942+ pages, making it less likely that sensitive information such as
25943+ passwords, cryptographic secrets, etc stay in memory for too long.
25944+
25945+ This is especially useful for programs whose runtime is short, long
25946+ lived processes and the kernel itself benefit from this as long as
25947+ they operate on whole memory pages and ensure timely freeing of pages
25948+ that may hold sensitive information.
25949+
25950+ The tradeoff is performance impact, on a single CPU system kernel
25951+ compilation sees a 3% slowdown, other systems and workloads may vary
25952+ and you are advised to test this feature on your expected workload
25953+ before deploying it.
25954+
25955+ Note that this feature does not protect data stored in live pages,
25956+ e.g., process memory swapped to disk may stay there for a long time.
25957+
25958+config PAX_MEMORY_UDEREF
25959+ bool "Prevent invalid userland pointer dereference"
25960+ depends on X86_32
25961+ select PAX_NOVSYSCALL
25962+ help
25963+ By saying Y here the kernel will be prevented from dereferencing
25964+ userland pointers in contexts where the kernel expects only kernel
25965+ pointers. This is both a useful runtime debugging feature and a
25966+ security measure that prevents exploiting a class of kernel bugs.
25967+
25968+ The tradeoff is that some virtualization solutions may experience
25969+ a huge slowdown and therefore you should not enable this feature
25970+ for kernels meant to run in such environments. Whether a given VM
25971+ solution is affected or not is best determined by simply trying it
25972+ out, the performance impact will be obvious right on boot as this
25973+ mechanism engages from very early on. A good rule of thumb is that
25974+ VMs running on CPUs without hardware virtualization support (i.e.,
25975+ the majority of IA-32 CPUs) will likely experience the slowdown.
25976+
25977+endmenu
25978+
25979+endmenu
25980+
25981+source grsecurity/Kconfig
25982+
25983 config KEYS
25984 bool "Enable access key retention support"
25985 help
25986diff -urNp linux-2.6.17.7/security/commoncap.c linux-2.6.17.7/security/commoncap.c
25987--- linux-2.6.17.7/security/commoncap.c 2006-07-24 23:36:01.000000000 -0400
25988+++ linux-2.6.17.7/security/commoncap.c 2006-08-01 20:29:48.000000000 -0400
25989@@ -24,6 +24,7 @@
25990 #include <linux/ptrace.h>
25991 #include <linux/xattr.h>
25992 #include <linux/hugetlb.h>
25993+#include <linux/grsecurity.h>
25994
25995 int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
25996 {
25997@@ -45,7 +46,15 @@ EXPORT_SYMBOL(cap_netlink_recv);
25998 int cap_capable (struct task_struct *tsk, int cap)
25999 {
26000 /* Derived from include/linux/sched.h:capable. */
77fa6d7d 26001- if (vx_cap_raised(tsk->vx_info, tsk->cap_effective, cap))
26002+ if (vx_cap_raised(tsk->vx_info, tsk->cap_effective, cap) && gr_task_is_capable(tsk, cap))
f1a4f855 26003+ return 0;
26004+ return -EPERM;
26005+}
26006+
26007+int cap_capable_nolog (struct task_struct *tsk, int cap)
26008+{
26009+ /* Derived from include/linux/sched.h:capable. */
26010+ if (cap_raised (tsk->cap_effective, cap))
26011 return 0;
26012 return -EPERM;
26013 }
26014@@ -164,8 +173,11 @@ void cap_bprm_apply_creds (struct linux_
26015 }
26016 }
26017
26018- current->suid = current->euid = current->fsuid = bprm->e_uid;
26019- current->sgid = current->egid = current->fsgid = bprm->e_gid;
26020+ if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid))
26021+ current->suid = current->euid = current->fsuid = bprm->e_uid;
26022+
26023+ if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid))
26024+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
26025
26026 /* For init, we want to retain the capabilities set
26027 * in the init_task struct. Thus we skip the usual
26028@@ -176,6 +188,8 @@ void cap_bprm_apply_creds (struct linux_
26029 cap_intersect (new_permitted, bprm->cap_effective);
26030 }
26031
26032+ gr_handle_chroot_caps(current);
26033+
26034 /* AUD: Audit candidate if current->cap_effective is set */
26035
26036 current->keep_capabilities = 0;
26037@@ -321,12 +335,13 @@ int cap_vm_enough_memory(long pages)
26038 {
26039 int cap_sys_admin = 0;
26040
26041- if (cap_capable(current, CAP_SYS_ADMIN) == 0)
26042+ if (cap_capable_nolog(current, CAP_SYS_ADMIN) == 0)
26043 cap_sys_admin = 1;
26044 return __vm_enough_memory(pages, cap_sys_admin);
26045 }
26046
26047 EXPORT_SYMBOL(cap_capable);
26048+EXPORT_SYMBOL(cap_capable_nolog);
26049 EXPORT_SYMBOL(cap_settime);
26050 EXPORT_SYMBOL(cap_ptrace);
26051 EXPORT_SYMBOL(cap_capget);
26052diff -urNp linux-2.6.17.7/security/dummy.c linux-2.6.17.7/security/dummy.c
26053--- linux-2.6.17.7/security/dummy.c 2006-07-24 23:36:01.000000000 -0400
26054+++ linux-2.6.17.7/security/dummy.c 2006-08-01 20:29:48.000000000 -0400
26055@@ -29,6 +29,7 @@
26056 #include <linux/hugetlb.h>
26057 #include <linux/ptrace.h>
26058 #include <linux/file.h>
26059+#include <linux/grsecurity.h>
26060
26061 static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
26062 {
26063@@ -139,8 +140,11 @@ static void dummy_bprm_apply_creds (stru
26064 }
26065 }
26066
26067- current->suid = current->euid = current->fsuid = bprm->e_uid;
26068- current->sgid = current->egid = current->fsgid = bprm->e_gid;
26069+ if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid))
26070+ current->suid = current->euid = current->fsuid = bprm->e_uid;
26071+
26072+ if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid))
26073+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
26074
26075 dummy_capget(current, &current->cap_effective, &current->cap_inheritable, &current->cap_permitted);
26076 }
This page took 3.293422 seconds and 4 git commands to generate.