]> git.pld-linux.org Git - packages/kernel.git/blame - grsecurity-2.1.9-2.6.16.14.patch
- ppc configs updated, rel 0.7
[packages/kernel.git] / grsecurity-2.1.9-2.6.16.14.patch
CommitLineData
89675291 1diff -urNp linux-2.6.16.12/arch/alpha/kernel/module.c linux-2.6.16.12/arch/alpha/kernel/module.c
2--- linux-2.6.16.12/arch/alpha/kernel/module.c 2006-05-01 15:14:26.000000000 -0400
3+++ linux-2.6.16.12/arch/alpha/kernel/module.c 2006-05-01 20:17:33.000000000 -0400
4@@ -177,7 +177,7 @@ apply_relocate_add(Elf64_Shdr *sechdrs,
5
6 /* The small sections were sorted to the end of the segment.
7 The following should definitely cover them. */
8- gp = (u64)me->module_core + me->core_size - 0x8000;
9+ gp = (u64)me->module_core_rw + me->core_size_rw - 0x8000;
10 got = sechdrs[me->arch.gotsecindex].sh_addr;
11
12 for (i = 0; i < n; i++) {
13diff -urNp linux-2.6.16.12/arch/alpha/kernel/osf_sys.c linux-2.6.16.12/arch/alpha/kernel/osf_sys.c
14--- linux-2.6.16.12/arch/alpha/kernel/osf_sys.c 2006-05-01 15:14:26.000000000 -0400
15+++ linux-2.6.16.12/arch/alpha/kernel/osf_sys.c 2006-05-01 20:17:33.000000000 -0400
16@@ -1274,6 +1274,10 @@ arch_get_unmapped_area(struct file *filp
17 merely specific addresses, but regions of memory -- perhaps
18 this feature should be incorporated into all ports? */
19
20+#ifdef CONFIG_PAX_RANDMMAP
21+ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
22+#endif
23+
24 if (addr) {
25 addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit);
26 if (addr != (unsigned long) -ENOMEM)
27@@ -1281,8 +1285,8 @@ arch_get_unmapped_area(struct file *filp
28 }
29
30 /* Next, try allocating at TASK_UNMAPPED_BASE. */
31- addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE),
32- len, limit);
33+ addr = arch_get_unmapped_area_1 (PAGE_ALIGN(current->mm->mmap_base), len, limit);
34+
35 if (addr != (unsigned long) -ENOMEM)
36 return addr;
37
38diff -urNp linux-2.6.16.12/arch/alpha/kernel/ptrace.c linux-2.6.16.12/arch/alpha/kernel/ptrace.c
39--- linux-2.6.16.12/arch/alpha/kernel/ptrace.c 2006-05-01 15:14:26.000000000 -0400
40+++ linux-2.6.16.12/arch/alpha/kernel/ptrace.c 2006-05-01 20:17:33.000000000 -0400
41@@ -15,6 +15,7 @@
42 #include <linux/slab.h>
43 #include <linux/security.h>
44 #include <linux/signal.h>
45+#include <linux/grsecurity.h>
46
47 #include <asm/uaccess.h>
48 #include <asm/pgtable.h>
9a4c6ab7 49@@ -288,6 +289,9 @@ do_sys_ptrace(long request, long pid, lo
50 goto out;
89675291 51 }
52
53+ if (gr_handle_ptrace(child, request))
54+ goto out;
55+
56 if (request == PTRACE_ATTACH) {
57 ret = ptrace_attach(child);
58 goto out;
59diff -urNp linux-2.6.16.12/arch/alpha/mm/fault.c linux-2.6.16.12/arch/alpha/mm/fault.c
60--- linux-2.6.16.12/arch/alpha/mm/fault.c 2006-05-01 15:14:26.000000000 -0400
61+++ linux-2.6.16.12/arch/alpha/mm/fault.c 2006-05-01 20:17:33.000000000 -0400
62@@ -25,6 +25,7 @@
63 #include <linux/smp_lock.h>
64 #include <linux/interrupt.h>
65 #include <linux/module.h>
66+#include <linux/binfmts.h>
67
68 #include <asm/system.h>
69 #include <asm/uaccess.h>
70@@ -56,6 +57,124 @@ __load_new_mm_context(struct mm_struct *
71 __reload_thread(pcb);
72 }
73
74+#ifdef CONFIG_PAX_PAGEEXEC
75+/*
76+ * PaX: decide what to do with offenders (regs->pc = fault address)
77+ *
78+ * returns 1 when task should be killed
79+ * 2 when patched PLT trampoline was detected
80+ * 3 when unpatched PLT trampoline was detected
81+ */
82+static int pax_handle_fetch_fault(struct pt_regs *regs)
83+{
84+
85+#ifdef CONFIG_PAX_EMUPLT
86+ int err;
87+
88+ do { /* PaX: patched PLT emulation #1 */
89+ unsigned int ldah, ldq, jmp;
90+
91+ err = get_user(ldah, (unsigned int *)regs->pc);
92+ err |= get_user(ldq, (unsigned int *)(regs->pc+4));
93+ err |= get_user(jmp, (unsigned int *)(regs->pc+8));
94+
95+ if (err)
96+ break;
97+
98+ if ((ldah & 0xFFFF0000U) == 0x277B0000U &&
99+ (ldq & 0xFFFF0000U) == 0xA77B0000U &&
100+ jmp == 0x6BFB0000U)
101+ {
102+ unsigned long r27, addr;
103+ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
104+ unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL;
105+
106+ addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
107+ err = get_user(r27, (unsigned long*)addr);
108+ if (err)
109+ break;
110+
111+ regs->r27 = r27;
112+ regs->pc = r27;
113+ return 2;
114+ }
115+ } while (0);
116+
117+ do { /* PaX: patched PLT emulation #2 */
118+ unsigned int ldah, lda, br;
119+
120+ err = get_user(ldah, (unsigned int *)regs->pc);
121+ err |= get_user(lda, (unsigned int *)(regs->pc+4));
122+ err |= get_user(br, (unsigned int *)(regs->pc+8));
123+
124+ if (err)
125+ break;
126+
127+ if ((ldah & 0xFFFF0000U)== 0x277B0000U &&
128+ (lda & 0xFFFF0000U) == 0xA77B0000U &&
129+ (br & 0xFFE00000U) == 0xC3E00000U)
130+ {
131+ unsigned long addr = br | 0xFFFFFFFFFFE00000UL;
132+ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
133+ unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL;
134+
135+ regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
136+ regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
137+ return 2;
138+ }
139+ } while (0);
140+
141+ do { /* PaX: unpatched PLT emulation */
142+ unsigned int br;
143+
144+ err = get_user(br, (unsigned int *)regs->pc);
145+
146+ if (!err && (br & 0xFFE00000U) == 0xC3800000U) {
147+ unsigned int br2, ldq, nop, jmp;
148+ unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver;
149+
150+ addr = regs->pc + 4 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
151+ err = get_user(br2, (unsigned int *)addr);
152+ err |= get_user(ldq, (unsigned int *)(addr+4));
153+ err |= get_user(nop, (unsigned int *)(addr+8));
154+ err |= get_user(jmp, (unsigned int *)(addr+12));
155+ err |= get_user(resolver, (unsigned long *)(addr+16));
156+
157+ if (err)
158+ break;
159+
160+ if (br2 == 0xC3600000U &&
161+ ldq == 0xA77B000CU &&
162+ nop == 0x47FF041FU &&
163+ jmp == 0x6B7B0000U)
164+ {
165+ regs->r28 = regs->pc+4;
166+ regs->r27 = addr+16;
167+ regs->pc = resolver;
168+ return 3;
169+ }
170+ }
171+ } while (0);
172+#endif
173+
174+ return 1;
175+}
176+
177+void pax_report_insns(void *pc, void *sp)
178+{
179+ unsigned long i;
180+
181+ printk(KERN_ERR "PAX: bytes at PC: ");
182+ for (i = 0; i < 5; i++) {
183+ unsigned int c;
184+ if (get_user(c, (unsigned int*)pc+i))
185+ printk("???????? ");
186+ else
187+ printk("%08x ", c);
188+ }
189+ printk("\n");
190+}
191+#endif
192
193 /*
194 * This routine handles page faults. It determines the address,
195@@ -133,8 +252,29 @@ do_page_fault(unsigned long address, uns
196 good_area:
197 si_code = SEGV_ACCERR;
198 if (cause < 0) {
199- if (!(vma->vm_flags & VM_EXEC))
200+ if (!(vma->vm_flags & VM_EXEC)) {
201+
202+#ifdef CONFIG_PAX_PAGEEXEC
203+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->pc)
204+ goto bad_area;
205+
206+ up_read(&mm->mmap_sem);
207+ switch(pax_handle_fetch_fault(regs)) {
208+
209+#ifdef CONFIG_PAX_EMUPLT
210+ case 2:
211+ case 3:
212+ return;
213+#endif
214+
215+ }
216+ pax_report_fault(regs, (void*)regs->pc, (void*)rdusp());
217+ do_exit(SIGKILL);
218+#else
219 goto bad_area;
220+#endif
221+
222+ }
223 } else if (!cause) {
224 /* Allow reads even for write-only mappings */
225 if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
226diff -urNp linux-2.6.16.12/arch/arm/mm/mmap.c linux-2.6.16.12/arch/arm/mm/mmap.c
227--- linux-2.6.16.12/arch/arm/mm/mmap.c 2006-05-01 15:14:26.000000000 -0400
228+++ linux-2.6.16.12/arch/arm/mm/mmap.c 2006-05-01 20:17:33.000000000 -0400
229@@ -62,6 +62,10 @@ arch_get_unmapped_area(struct file *filp
230 if (len > TASK_SIZE)
231 return -ENOMEM;
232
233+#ifdef CONFIG_PAX_RANDMMAP
234+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
235+#endif
236+
237 if (addr) {
238 if (do_align)
239 addr = COLOUR_ALIGN(addr, pgoff);
240@@ -76,7 +80,7 @@ arch_get_unmapped_area(struct file *filp
241 if (len > mm->cached_hole_size) {
242 start_addr = addr = mm->free_area_cache;
243 } else {
244- start_addr = addr = TASK_UNMAPPED_BASE;
245+ start_addr = addr = mm->mmap_base;
246 mm->cached_hole_size = 0;
247 }
248
249@@ -93,8 +97,8 @@ full_search:
250 * Start a new search - just in case we missed
251 * some holes.
252 */
253- if (start_addr != TASK_UNMAPPED_BASE) {
254- start_addr = addr = TASK_UNMAPPED_BASE;
255+ if (start_addr != mm->mmap_base) {
256+ start_addr = addr = mm->mmap_base;
257 mm->cached_hole_size = 0;
258 goto full_search;
259 }
260diff -urNp linux-2.6.16.12/arch/i386/boot/compressed/head.S linux-2.6.16.12/arch/i386/boot/compressed/head.S
261--- linux-2.6.16.12/arch/i386/boot/compressed/head.S 2006-05-01 15:14:26.000000000 -0400
262+++ linux-2.6.16.12/arch/i386/boot/compressed/head.S 2006-05-01 20:17:33.000000000 -0400
263@@ -39,11 +39,13 @@ startup_32:
264 movl %eax,%gs
265
266 lss stack_start,%esp
267+ movl 0x000000,%ecx
268 xorl %eax,%eax
269 1: incl %eax # check that A20 really IS enabled
270 movl %eax,0x000000 # loop forever if it isn't
271 cmpl %eax,0x100000
272 je 1b
273+ movl %ecx,0x000000
274
275 /*
276 * Initialize eflags. Some BIOS's leave bits like NT set. This would
277diff -urNp linux-2.6.16.12/arch/i386/Kconfig linux-2.6.16.12/arch/i386/Kconfig
278--- linux-2.6.16.12/arch/i386/Kconfig 2006-05-01 15:14:26.000000000 -0400
279+++ linux-2.6.16.12/arch/i386/Kconfig 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 280@@ -983,7 +983,7 @@ endchoice
89675291 281
282 config PCI_BIOS
283 bool
284- depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
285+ depends on !X86_VISWS && PCI && PCI_GOBIOS
286 default y
287
288 config PCI_DIRECT
289diff -urNp linux-2.6.16.12/arch/i386/Kconfig.cpu linux-2.6.16.12/arch/i386/Kconfig.cpu
290--- linux-2.6.16.12/arch/i386/Kconfig.cpu 2006-05-01 15:14:26.000000000 -0400
291+++ linux-2.6.16.12/arch/i386/Kconfig.cpu 2006-05-01 20:17:33.000000000 -0400
292@@ -251,7 +251,7 @@ config X86_PPRO_FENCE
293
294 config X86_F00F_BUG
295 bool
296- depends on M586MMX || M586TSC || M586 || M486 || M386
297+ depends on (M586MMX || M586TSC || M586 || M486 || M386) && !PAX_KERNEXEC
298 default y
299
300 config X86_WP_WORKS_OK
301@@ -281,7 +281,7 @@ config X86_CMPXCHG64
302
303 config X86_ALIGNMENT_16
304 bool
305- depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
306+ depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 || MGEODEGX1
307 default y
308
309 config X86_GOOD_APIC
310diff -urNp linux-2.6.16.12/arch/i386/Kconfig.debug linux-2.6.16.12/arch/i386/Kconfig.debug
311--- linux-2.6.16.12/arch/i386/Kconfig.debug 2006-05-01 15:14:26.000000000 -0400
312+++ linux-2.6.16.12/arch/i386/Kconfig.debug 2006-05-01 20:17:33.000000000 -0400
313@@ -44,7 +44,7 @@ config DEBUG_PAGEALLOC
314
315 config DEBUG_RODATA
316 bool "Write protect kernel read-only data structures"
317- depends on DEBUG_KERNEL
318+ depends on DEBUG_KERNEL && 0
319 help
320 Mark the kernel read-only data as write-protected in the pagetables,
321 in order to catch accidental (and incorrect) writes to such const
322diff -urNp linux-2.6.16.12/arch/i386/kernel/acpi/sleep.c linux-2.6.16.12/arch/i386/kernel/acpi/sleep.c
323--- linux-2.6.16.12/arch/i386/kernel/acpi/sleep.c 2006-05-01 15:14:26.000000000 -0400
324+++ linux-2.6.16.12/arch/i386/kernel/acpi/sleep.c 2006-05-01 20:17:33.000000000 -0400
325@@ -10,6 +10,7 @@
326 #include <linux/dmi.h>
327 #include <asm/smp.h>
328 #include <asm/tlbflush.h>
329+#include <asm/desc.h>
330
331 /* address in low memory of the wakeup routine. */
332 unsigned long acpi_wakeup_address = 0;
333@@ -24,11 +25,22 @@ static void init_low_mapping(pgd_t * pgd
334 {
335 int pgd_ofs = 0;
336
337+#ifdef CONFIG_PAX_KERNEXEC
338+ unsigned long cr0;
339+
340+ pax_open_kernel(cr0);
341+#endif
342+
343 while ((pgd_ofs < pgd_limit)
344 && (pgd_ofs + USER_PTRS_PER_PGD < PTRS_PER_PGD)) {
345 set_pgd(pgd, *(pgd + USER_PTRS_PER_PGD));
346 pgd_ofs++, pgd++;
347 }
348+
349+#ifdef CONFIG_PAX_KERNEXEC
350+ pax_close_kernel(cr0);
351+#endif
352+
353 flush_tlb_all();
354 }
355
356@@ -55,7 +67,18 @@ int acpi_save_state_mem(void)
357 */
358 void acpi_restore_state_mem(void)
359 {
360+#ifdef CONFIG_PAX_KERNEXEC
361+ unsigned long cr0;
362+
363+ pax_open_kernel(cr0);
364+#endif
365+
366 zap_low_mappings();
367+
368+#ifdef CONFIG_PAX_KERNEXEC
369+ pax_close_kernel(cr0);
370+#endif
371+
372 }
373
374 /**
375diff -urNp linux-2.6.16.12/arch/i386/kernel/apic.c linux-2.6.16.12/arch/i386/kernel/apic.c
376--- linux-2.6.16.12/arch/i386/kernel/apic.c 2006-05-01 15:14:26.000000000 -0400
377+++ linux-2.6.16.12/arch/i386/kernel/apic.c 2006-05-01 20:17:33.000000000 -0400
378@@ -1150,7 +1150,7 @@ inline void smp_local_timer_interrupt(st
379 {
380 profile_tick(CPU_PROFILING, regs);
381 #ifdef CONFIG_SMP
382- update_process_times(user_mode_vm(regs));
383+ update_process_times(user_mode(regs));
384 #endif
385
386 /*
387diff -urNp linux-2.6.16.12/arch/i386/kernel/apm.c linux-2.6.16.12/arch/i386/kernel/apm.c
388--- linux-2.6.16.12/arch/i386/kernel/apm.c 2006-05-01 15:14:26.000000000 -0400
389+++ linux-2.6.16.12/arch/i386/kernel/apm.c 2006-05-01 20:17:33.000000000 -0400
390@@ -589,9 +589,18 @@ static u8 apm_bios_call(u32 func, u32 eb
391 struct desc_struct save_desc_40;
392 struct desc_struct *gdt;
393
394+#ifdef CONFIG_PAX_KERNEXEC
395+ unsigned long cr0;
396+#endif
397+
398 cpus = apm_save_cpus();
399
400 cpu = get_cpu();
401+
402+#ifdef CONFIG_PAX_KERNEXEC
403+ pax_open_kernel(cr0);
404+#endif
405+
406 gdt = get_cpu_gdt_table(cpu);
407 save_desc_40 = gdt[0x40 / 8];
408 gdt[0x40 / 8] = bad_bios_desc;
409@@ -603,6 +612,11 @@ static u8 apm_bios_call(u32 func, u32 eb
410 APM_DO_RESTORE_SEGS;
411 local_irq_restore(flags);
412 gdt[0x40 / 8] = save_desc_40;
413+
414+#ifdef CONFIG_PAX_KERNEXEC
415+ pax_close_kernel(cr0);
416+#endif
417+
418 put_cpu();
419 apm_restore_cpus(cpus);
420
421@@ -633,9 +647,18 @@ static u8 apm_bios_call_simple(u32 func,
422 struct desc_struct save_desc_40;
423 struct desc_struct *gdt;
424
425+#ifdef CONFIG_PAX_KERNEXEC
426+ unsigned long cr0;
427+#endif
428+
429 cpus = apm_save_cpus();
430
431 cpu = get_cpu();
432+
433+#ifdef CONFIG_PAX_KERNEXEC
434+ pax_open_kernel(cr0);
435+#endif
436+
437 gdt = get_cpu_gdt_table(cpu);
438 save_desc_40 = gdt[0x40 / 8];
439 gdt[0x40 / 8] = bad_bios_desc;
440@@ -647,6 +670,11 @@ static u8 apm_bios_call_simple(u32 func,
441 APM_DO_RESTORE_SEGS;
442 local_irq_restore(flags);
443 gdt[0x40 / 8] = save_desc_40;
444+
445+#ifdef CONFIG_PAX_KERNEXEC
446+ pax_close_kernel(cr0);
447+#endif
448+
449 put_cpu();
450 apm_restore_cpus(cpus);
451 return error;
452diff -urNp linux-2.6.16.12/arch/i386/kernel/asm-offsets.c linux-2.6.16.12/arch/i386/kernel/asm-offsets.c
453--- linux-2.6.16.12/arch/i386/kernel/asm-offsets.c 2006-05-01 15:14:26.000000000 -0400
454+++ linux-2.6.16.12/arch/i386/kernel/asm-offsets.c 2006-05-01 20:17:33.000000000 -0400
455@@ -68,5 +68,6 @@ void foo(void)
456 sizeof(struct tss_struct));
457
458 DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
459+ DEFINE(PTRS_PER_PTE_asm, PTRS_PER_PTE);
460 DEFINE(VSYSCALL_BASE, __fix_to_virt(FIX_VSYSCALL));
461 }
462diff -urNp linux-2.6.16.12/arch/i386/kernel/cpu/common.c linux-2.6.16.12/arch/i386/kernel/cpu/common.c
463--- linux-2.6.16.12/arch/i386/kernel/cpu/common.c 2006-05-01 15:14:26.000000000 -0400
464+++ linux-2.6.16.12/arch/i386/kernel/cpu/common.c 2006-05-01 20:17:33.000000000 -0400
465@@ -4,7 +4,6 @@
466 #include <linux/smp.h>
467 #include <linux/module.h>
468 #include <linux/percpu.h>
469-#include <linux/bootmem.h>
470 #include <asm/semaphore.h>
471 #include <asm/processor.h>
472 #include <asm/i387.h>
473@@ -19,9 +18,6 @@
474
475 #include "cpu.h"
476
477-DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
478-EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
479-
480 DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
481 EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
482
483@@ -387,6 +383,10 @@ void __devinit identify_cpu(struct cpuin
484 if (this_cpu->c_init)
485 this_cpu->c_init(c);
486
487+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_NOVSYSCALL)
488+ clear_bit(X86_FEATURE_SEP, c->x86_capability);
489+#endif
490+
491 /* Disable the PN if appropriate */
492 squash_the_stupid_serial_number(c);
493
494@@ -573,11 +573,10 @@ void __init early_cpu_init(void)
495 void __devinit cpu_init(void)
496 {
497 int cpu = smp_processor_id();
498- struct tss_struct * t = &per_cpu(init_tss, cpu);
499+ struct tss_struct * t = init_tss + cpu;
500 struct thread_struct *thread = &current->thread;
501- struct desc_struct *gdt;
502+ struct desc_struct *gdt = get_cpu_gdt_table(cpu);
503 __u32 stk16_off = (__u32)&per_cpu(cpu_16bit_stack, cpu);
504- struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
505
506 if (cpu_test_and_set(cpu, cpu_initialized)) {
507 printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
508@@ -595,29 +594,11 @@ void __devinit cpu_init(void)
509 }
510
511 /*
512- * This is a horrible hack to allocate the GDT. The problem
513- * is that cpu_init() is called really early for the boot CPU
514- * (and hence needs bootmem) but much later for the secondary
515- * CPUs, when bootmem will have gone away
516- */
517- if (NODE_DATA(0)->bdata->node_bootmem_map) {
518- gdt = (struct desc_struct *)alloc_bootmem_pages(PAGE_SIZE);
519- /* alloc_bootmem_pages panics on failure, so no check */
520- memset(gdt, 0, PAGE_SIZE);
521- } else {
522- gdt = (struct desc_struct *)get_zeroed_page(GFP_KERNEL);
523- if (unlikely(!gdt)) {
524- printk(KERN_CRIT "CPU%d failed to allocate GDT\n", cpu);
525- for (;;)
526- local_irq_enable();
527- }
528- }
529-
530- /*
531 * Initialize the per-CPU GDT with the boot GDT,
532 * and set up the GDT descriptor:
533 */
534- memcpy(gdt, cpu_gdt_table, GDT_SIZE);
535+ if (cpu)
536+ memcpy(gdt, cpu_gdt_table, GDT_SIZE);
537
538 /* Set up GDT entry for 16bit stack */
539 *(__u64 *)(&gdt[GDT_ENTRY_ESPFIX_SS]) |=
540@@ -625,10 +606,10 @@ void __devinit cpu_init(void)
541 ((((__u64)stk16_off) << 32) & 0xff00000000000000ULL) |
542 (CPU_16BIT_STACK_SIZE - 1);
543
544- cpu_gdt_descr->size = GDT_SIZE - 1;
545- cpu_gdt_descr->address = (unsigned long)gdt;
546+ cpu_gdt_descr[cpu].size = GDT_SIZE - 1;
547+ cpu_gdt_descr[cpu].address = (unsigned long)gdt;
548
549- load_gdt(cpu_gdt_descr);
550+ load_gdt(&cpu_gdt_descr[cpu]);
551 load_idt(&idt_descr);
552
553 /*
554@@ -643,7 +624,7 @@ void __devinit cpu_init(void)
555 load_esp0(t, thread);
556 set_tss_desc(cpu,t);
557 load_TR_desc();
558- load_LDT(&init_mm.context);
559+ _load_LDT(&init_mm.context);
560
561 #ifdef CONFIG_DOUBLEFAULT
562 /* Set up doublefault TSS pointer in the GDT */
563diff -urNp linux-2.6.16.12/arch/i386/kernel/doublefault.c linux-2.6.16.12/arch/i386/kernel/doublefault.c
564--- linux-2.6.16.12/arch/i386/kernel/doublefault.c 2006-05-01 15:14:26.000000000 -0400
565+++ linux-2.6.16.12/arch/i386/kernel/doublefault.c 2006-05-01 20:17:33.000000000 -0400
566@@ -11,7 +11,7 @@
567
568 #define DOUBLEFAULT_STACKSIZE (1024)
569 static unsigned long doublefault_stack[DOUBLEFAULT_STACKSIZE];
570-#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE)
571+#define STACK_START (unsigned long)(doublefault_stack+DOUBLEFAULT_STACKSIZE-2)
572
573 #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000)
574
575diff -urNp linux-2.6.16.12/arch/i386/kernel/efi.c linux-2.6.16.12/arch/i386/kernel/efi.c
576--- linux-2.6.16.12/arch/i386/kernel/efi.c 2006-05-01 15:14:26.000000000 -0400
577+++ linux-2.6.16.12/arch/i386/kernel/efi.c 2006-05-01 20:17:33.000000000 -0400
578@@ -64,82 +64,58 @@ extern void * boot_ioremap(unsigned long
579
580 static unsigned long efi_rt_eflags;
581 static DEFINE_SPINLOCK(efi_rt_lock);
582-static pgd_t efi_bak_pg_dir_pointer[2];
583+static pgd_t __initdata efi_bak_pg_dir_pointer[4];
584
585-static void efi_call_phys_prelog(void)
586+static void __init efi_call_phys_prelog(void)
587 {
588- unsigned long cr4;
589- unsigned long temp;
590- struct Xgt_desc_struct *cpu_gdt_descr;
591-
592 spin_lock(&efi_rt_lock);
593 local_irq_save(efi_rt_eflags);
594
595- cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
596+ efi_bak_pg_dir_pointer[0] = swapper_pg_dir[0];
597+ swapper_pg_dir[0] = swapper_pg_dir[USER_PTRS_PER_PGD];
598
599- /*
600- * If I don't have PSE, I should just duplicate two entries in page
601- * directory. If I have PSE, I just need to duplicate one entry in
602- * page directory.
603- */
604- cr4 = read_cr4();
605-
606- if (cr4 & X86_CR4_PSE) {
607- efi_bak_pg_dir_pointer[0].pgd =
608- swapper_pg_dir[pgd_index(0)].pgd;
609- swapper_pg_dir[0].pgd =
610- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
611- } else {
612- efi_bak_pg_dir_pointer[0].pgd =
613- swapper_pg_dir[pgd_index(0)].pgd;
614- efi_bak_pg_dir_pointer[1].pgd =
615- swapper_pg_dir[pgd_index(0x400000)].pgd;
616- swapper_pg_dir[pgd_index(0)].pgd =
617- swapper_pg_dir[pgd_index(PAGE_OFFSET)].pgd;
618- temp = PAGE_OFFSET + 0x400000;
619- swapper_pg_dir[pgd_index(0x400000)].pgd =
620- swapper_pg_dir[pgd_index(temp)].pgd;
621- }
622+#ifndef CONFIG_X86_PAE
623+ efi_bak_pg_dir_pointer[1] = swapper_pg_dir[1];
624+ swapper_pg_dir[1] = swapper_pg_dir[USER_PTRS_PER_PGD+1];
625+ efi_bak_pg_dir_pointer[2] = swapper_pg_dir[2];
626+ swapper_pg_dir[2] = swapper_pg_dir[USER_PTRS_PER_PGD+2];
627+ efi_bak_pg_dir_pointer[3] = swapper_pg_dir[3];
628+ swapper_pg_dir[3] = swapper_pg_dir[USER_PTRS_PER_PGD+3];
629+#endif
630
631 /*
632 * After the lock is released, the original page table is restored.
633 */
634- local_flush_tlb();
635+ __flush_tlb_all();
636
637- cpu_gdt_descr->address = __pa(cpu_gdt_descr->address);
638- load_gdt(cpu_gdt_descr);
639+ cpu_gdt_descr[0].address = __pa(cpu_gdt_descr[0].address);
640+ load_gdt((struct Xgt_desc_struct *) __pa(&cpu_gdt_descr[0]));
641 }
642
643-static void efi_call_phys_epilog(void)
644+static void __init efi_call_phys_epilog(void)
645 {
646- unsigned long cr4;
647- struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
648-
649- cpu_gdt_descr->address = __va(cpu_gdt_descr->address);
650- load_gdt(cpu_gdt_descr);
651+ cpu_gdt_descr[0].address =
652+ (unsigned long) __va(cpu_gdt_descr[0].address);
653+ load_gdt(&cpu_gdt_descr[0]);
654
655- cr4 = read_cr4();
656+ swapper_pg_dir[0] = efi_bak_pg_dir_pointer[0];
657
658- if (cr4 & X86_CR4_PSE) {
659- swapper_pg_dir[pgd_index(0)].pgd =
660- efi_bak_pg_dir_pointer[0].pgd;
661- } else {
662- swapper_pg_dir[pgd_index(0)].pgd =
663- efi_bak_pg_dir_pointer[0].pgd;
664- swapper_pg_dir[pgd_index(0x400000)].pgd =
665- efi_bak_pg_dir_pointer[1].pgd;
666- }
667+#ifndef CONFIG_X86_PAE
668+ swapper_pg_dir[1] = efi_bak_pg_dir_pointer[1];
669+ swapper_pg_dir[2] = efi_bak_pg_dir_pointer[2];
670+ swapper_pg_dir[3] = efi_bak_pg_dir_pointer[3];
671+#endif
672
673 /*
674 * After the lock is released, the original page table is restored.
675 */
676- local_flush_tlb();
677+ __flush_tlb_all();
678
679 local_irq_restore(efi_rt_eflags);
680 spin_unlock(&efi_rt_lock);
681 }
682
683-static efi_status_t
684+static efi_status_t __init
685 phys_efi_set_virtual_address_map(unsigned long memory_map_size,
686 unsigned long descriptor_size,
687 u32 descriptor_version,
688@@ -155,7 +131,7 @@ phys_efi_set_virtual_address_map(unsigne
689 return status;
690 }
691
692-static efi_status_t
693+static efi_status_t __init
694 phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
695 {
696 efi_status_t status;
697diff -urNp linux-2.6.16.12/arch/i386/kernel/efi_stub.S linux-2.6.16.12/arch/i386/kernel/efi_stub.S
698--- linux-2.6.16.12/arch/i386/kernel/efi_stub.S 2006-05-01 15:14:26.000000000 -0400
699+++ linux-2.6.16.12/arch/i386/kernel/efi_stub.S 2006-05-01 20:17:33.000000000 -0400
700@@ -7,6 +7,7 @@
701
702 #include <linux/config.h>
703 #include <linux/linkage.h>
704+#include <linux/init.h>
705 #include <asm/page.h>
706 #include <asm/pgtable.h>
707
708@@ -22,7 +23,7 @@
709 * service functions will comply with gcc calling convention, too.
710 */
711
712-.text
713+__INIT
714 ENTRY(efi_call_phys)
715 /*
716 * 0. The function can only be called in Linux kernel. So CS has been
717@@ -38,9 +39,7 @@ ENTRY(efi_call_phys)
718 * The mapping of lower virtual memory has been created in prelog and
719 * epilog.
720 */
721- movl $1f, %edx
722- subl $__PAGE_OFFSET, %edx
723- jmp *%edx
724+ jmp 1f-__PAGE_OFFSET
725 1:
726
727 /*
728@@ -49,14 +48,8 @@ ENTRY(efi_call_phys)
729 * parameter 2, ..., param n. To make things easy, we save the return
730 * address of efi_call_phys in a global variable.
731 */
732- popl %edx
733- movl %edx, saved_return_addr
734- /* get the function pointer into ECX*/
735- popl %ecx
736- movl %ecx, efi_rt_function_ptr
737- movl $2f, %edx
738- subl $__PAGE_OFFSET, %edx
739- pushl %edx
740+ popl (saved_return_addr)
741+ popl (efi_rt_function_ptr)
742
743 /*
744 * 3. Clear PG bit in %CR0.
745@@ -75,9 +68,8 @@ ENTRY(efi_call_phys)
746 /*
747 * 5. Call the physical function.
748 */
749- jmp *%ecx
750+ call *(efi_rt_function_ptr-__PAGE_OFFSET)
751
752-2:
753 /*
754 * 6. After EFI runtime service returns, control will return to
755 * following instruction. We'd better readjust stack pointer first.
756@@ -87,37 +79,29 @@ ENTRY(efi_call_phys)
757 /*
758 * 7. Restore PG bit
759 */
760- movl %cr0, %edx
761- orl $0x80000000, %edx
762- movl %edx, %cr0
763- jmp 1f
764-1:
765 /*
766 * 8. Now restore the virtual mode from flat mode by
767 * adding EIP with PAGE_OFFSET.
768 */
769- movl $1f, %edx
770- jmp *%edx
771+ movl %cr0, %edx
772+ orl $0x80000000, %edx
773+ movl %edx, %cr0
774+ jmp 1f+__PAGE_OFFSET
775 1:
776
777 /*
778 * 9. Balance the stack. And because EAX contain the return value,
779 * we'd better not clobber it.
780 */
781- leal efi_rt_function_ptr, %edx
782- movl (%edx), %ecx
783- pushl %ecx
784+ pushl (efi_rt_function_ptr)
785
786 /*
787- * 10. Push the saved return address onto the stack and return.
788+ * 10. Return to the saved return address.
789 */
790- leal saved_return_addr, %edx
791- movl (%edx), %ecx
792- pushl %ecx
793- ret
794+ jmpl *(saved_return_addr)
795 .previous
796
797-.data
798+__INITDATA
799 saved_return_addr:
800 .long 0
801 efi_rt_function_ptr:
802diff -urNp linux-2.6.16.12/arch/i386/kernel/entry.S linux-2.6.16.12/arch/i386/kernel/entry.S
803--- linux-2.6.16.12/arch/i386/kernel/entry.S 2006-05-01 15:14:26.000000000 -0400
804+++ linux-2.6.16.12/arch/i386/kernel/entry.S 2006-05-01 20:17:33.000000000 -0400
805@@ -82,7 +82,7 @@ VM_MASK = 0x00020000
806 #define resume_kernel restore_nocheck
807 #endif
808
809-#define SAVE_ALL \
810+#define __SAVE_ALL \
811 cld; \
812 pushl %es; \
813 pushl %ds; \
814@@ -97,6 +97,18 @@ VM_MASK = 0x00020000
815 movl %edx, %ds; \
816 movl %edx, %es;
817
818+#ifdef CONFIG_PAX_KERNEXEC
819+#define SAVE_ALL \
820+ __SAVE_ALL \
821+ movl %cr0, %edx; \
822+ movl %edx, %esi; \
823+ orl $0x10000, %edx; \
824+ xorl %edx, %esi; \
825+ movl %edx, %cr0;
826+#else
827+#define SAVE_ALL __SAVE_ALL
828+#endif
829+
830 #define RESTORE_INT_REGS \
831 popl %ebx; \
832 popl %ecx; \
833@@ -146,7 +158,19 @@ ret_from_intr:
834 movl EFLAGS(%esp), %eax # mix EFLAGS and CS
835 movb CS(%esp), %al
836 testl $(VM_MASK | 3), %eax
837+
838+#ifdef CONFIG_PAX_KERNEXEC
839+ jnz resume_userspace
840+
841+ movl %cr0, %edx
842+ xorl %esi, %edx
843+ movl %edx, %cr0
844+ jmp resume_kernel
845+#else
846 jz resume_kernel
847+#endif
848+
849+
850 ENTRY(resume_userspace)
851 cli # make sure we don't miss an interrupt
852 # setting need_resched or sigpending
853@@ -213,6 +237,13 @@ sysenter_past_esp:
854 movl TI_flags(%ebp), %ecx
855 testw $_TIF_ALLWORK_MASK, %cx
856 jne syscall_exit_work
857+
858+#ifdef CONFIG_PAX_RANDKSTACK
859+ pushl %eax
860+ call pax_randomize_kstack
861+ popl %eax
862+#endif
863+
864 /* if something modifies registers it must also disable sysexit */
865 movl EIP(%esp), %edx
866 movl OLDESP(%esp), %ecx
867@@ -243,6 +274,10 @@ syscall_exit:
868 testw $_TIF_ALLWORK_MASK, %cx # current->work
869 jne syscall_exit_work
870
871+#ifdef CONFIG_PAX_RANDKSTACK
872+ call pax_randomize_kstack
873+#endif
874+
875 restore_all:
876 movl EFLAGS(%esp), %eax # mix EFLAGS, SS and CS
877 # Warning: OLDSS(%esp) contains the wrong/random values if we
878@@ -398,7 +433,7 @@ syscall_badsys:
879 * Build the entry stubs and pointer table with
880 * some assembler magic.
881 */
882-.data
883+.section .rodata,"a",@progbits
884 ENTRY(interrupt)
885 .text
886
887@@ -408,7 +443,7 @@ ENTRY(irq_entries_start)
888 ALIGN
889 1: pushl $vector-256
890 jmp common_interrupt
891-.data
892+.section .rodata,"a",@progbits
893 .long 1b
894 .text
895 vector=vector+1
896@@ -459,6 +494,15 @@ error_code:
897 movl %ecx, %ds
898 movl %ecx, %es
899 movl %esp,%eax # pt_regs pointer
900+
901+#ifdef CONFIG_PAX_KERNEXEC
902+ movl %cr0, %ecx
903+ movl %ecx, %esi
904+ orl $0x10000, %ecx
905+ xorl %ecx, %esi
906+ movl %ecx, %cr0
907+#endif
908+
909 call *%edi
910 jmp ret_from_exception
911
912@@ -554,6 +598,13 @@ nmi_stack_correct:
913 xorl %edx,%edx # zero error code
914 movl %esp,%eax # pt_regs pointer
915 call do_nmi
916+
917+#ifdef CONFIG_PAX_KERNEXEC
918+ movl %cr0, %edx
919+ xorl %esi, %edx
920+ movl %edx, %cr0
921+#endif
922+
923 jmp restore_all
924
925 nmi_stack_fixup:
926@@ -584,6 +635,13 @@ nmi_16bit_stack:
927 FIXUP_ESPFIX_STACK # %eax == %esp
928 xorl %edx,%edx # zero error code
929 call do_nmi
930+
931+#ifdef CONFIG_PAX_KERNEXEC
932+ movl %cr0, %edx
933+ xorl %esi, %edx
934+ movl %edx, %cr0
935+#endif
936+
937 RESTORE_REGS
938 lss 12+4(%esp), %esp # back to 16bit stack
939 1: iret
940@@ -659,7 +717,6 @@ ENTRY(spurious_interrupt_bug)
941 pushl $do_spurious_interrupt_bug
942 jmp error_code
943
944-.section .rodata,"a"
945 #include "syscall_table.S"
946
947 syscall_table_size=(.-sys_call_table)
948diff -urNp linux-2.6.16.12/arch/i386/kernel/head.S linux-2.6.16.12/arch/i386/kernel/head.S
949--- linux-2.6.16.12/arch/i386/kernel/head.S 2006-05-01 15:14:26.000000000 -0400
950+++ linux-2.6.16.12/arch/i386/kernel/head.S 2006-05-01 20:17:33.000000000 -0400
951@@ -48,6 +48,12 @@
952
953
954 /*
955+ * Real beginning of normal "text" segment
956+ */
957+ENTRY(stext)
958+ENTRY(_stext)
959+
960+/*
961 * 32-bit kernel entrypoint; only used by the boot CPU. On entry,
962 * %esi points to the real-mode code as a 32-bit pointer.
963 * CS and DS must be 4 GB flat segments, but we don't depend on
964@@ -67,6 +73,19 @@ ENTRY(startup_32)
965 movl %eax,%fs
966 movl %eax,%gs
967
968+#ifdef CONFIG_PAX_KERNEXEC
969+ movl $ __KERNEL_TEXT_OFFSET,%eax
970+ movw %ax,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 2)
971+ rorl $16,%eax
972+ movb %al,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 4)
973+ movb %ah,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 7)
974+
975+ movb %al,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 4)
976+ movb %ah,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 7)
977+ rorl $16,%eax
978+ movw %ax,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 2)
979+#endif
980+
981 /*
982 * Clear BSS first so that there are no surprises...
983 * No need to cld as DF is already clear from cld above...
984@@ -114,24 +133,42 @@ ENTRY(startup_32)
985 * Warning: don't use %esi or the stack in this code. However, %esp
986 * can be used as a GPR if you really need it...
987 */
988-page_pde_offset = (__PAGE_OFFSET >> 20);
989-
990+#ifdef CONFIG_X86_PAE
991+page_pde_offset = ((__PAGE_OFFSET >> 21) * (4096 / PTRS_PER_PTE_asm));
992+#else
993+page_pde_offset = ((__PAGE_OFFSET >> 22) * (4096 / PTRS_PER_PTE_asm));
994+#endif
995 movl $(pg0 - __PAGE_OFFSET), %edi
996+#ifdef CONFIG_X86_PAE
997+ movl $(swapper_pm_dir - __PAGE_OFFSET), %edx
998+#else
999 movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
1000- movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */
1001+#endif
1002+ movl $0x063, %eax /* 0x063 = DIRTY+ACCESSED+PRESENT+RW */
1003 10:
1004- leal 0x007(%edi),%ecx /* Create PDE entry */
1005+ leal 0x063(%edi),%ecx /* Create PDE entry */
1006 movl %ecx,(%edx) /* Store identity PDE entry */
1007 movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */
1008+#ifdef CONFIG_X86_PAE
1009+ movl $0,4(%edx)
1010+ movl $0,page_pde_offset+4(%edx)
1011+ addl $8,%edx
1012+ movl $512, %ecx
1013+#else
1014 addl $4,%edx
1015 movl $1024, %ecx
1016+#endif
1017 11:
1018 stosl
1019+#ifdef CONFIG_X86_PAE
1020+ movl $0,(%edi)
1021+ addl $4,%edi
1022+#endif
1023 addl $0x1000,%eax
1024 loop 11b
1025 /* End condition: we must map up to and including INIT_MAP_BEYOND_END */
1026- /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */
1027- leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp
1028+ /* bytes beyond the end of our own page tables; the +0x063 is the attribute bits */
1029+ leal (INIT_MAP_BEYOND_END+0x063)(%edi),%ebp
1030 cmpl %ebp,%eax
1031 jb 10b
1032 movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
1033@@ -154,6 +191,11 @@ ENTRY(startup_32_smp)
1034 movl %eax,%fs
1035 movl %eax,%gs
1036
1037+ /* This is a secondary processor (AP) */
1038+ xorl %ebx,%ebx
1039+ incl %ebx
1040+#endif /* CONFIG_SMP */
1041+
1042 /*
1043 * New page tables may be in 4Mbyte page mode and may
1044 * be using the global pages.
1045@@ -169,26 +211,27 @@ ENTRY(startup_32_smp)
1046 * not yet offset PAGE_OFFSET..
1047 */
1048 #define cr4_bits mmu_cr4_features-__PAGE_OFFSET
1049+3:
1050 movl cr4_bits,%edx
1051 andl %edx,%edx
1052- jz 6f
1053+ jz 5f
1054 movl %cr4,%eax # Turn on paging options (PSE,PAE,..)
1055 orl %edx,%eax
1056 movl %eax,%cr4
1057
1058- btl $5, %eax # check if PAE is enabled
1059- jnc 6f
1060+#ifdef CONFIG_X86_PAE
1061+ movl %ebx,%edi
1062
1063 /* Check if extended functions are implemented */
1064 movl $0x80000000, %eax
1065 cpuid
1066 cmpl $0x80000000, %eax
1067- jbe 6f
1068+ jbe 4f
1069 mov $0x80000001, %eax
1070 cpuid
1071 /* Execute Disable bit supported? */
1072 btl $20, %edx
1073- jnc 6f
1074+ jnc 4f
1075
1076 /* Setup EFER (Extended Feature Enable Register) */
1077 movl $0xc0000080, %ecx
1078@@ -197,14 +240,12 @@ ENTRY(startup_32_smp)
1079 btsl $11, %eax
1080 /* Make changes effective */
1081 wrmsr
1082+ btsl $63,__supported_pte_mask-__PAGE_OFFSET
1083
1084-6:
1085- /* This is a secondary processor (AP) */
1086- xorl %ebx,%ebx
1087- incl %ebx
1088-
1089-3:
1090-#endif /* CONFIG_SMP */
1091+4:
1092+ movl %edi,%ebx
1093+#endif
1094+5:
1095
1096 /*
1097 * Enable paging
1098@@ -229,9 +270,7 @@ ENTRY(startup_32_smp)
1099
1100 #ifdef CONFIG_SMP
1101 andl %ebx,%ebx
1102- jz 1f /* Initial CPU cleans BSS */
1103- jmp checkCPUtype
1104-1:
1105+ jnz checkCPUtype /* Initial CPU cleans BSS */
1106 #endif /* CONFIG_SMP */
1107
1108 /*
1109@@ -412,32 +451,50 @@ ignore_int:
1110 #endif
1111 iret
1112
1113-/*
1114- * Real beginning of normal "text" segment
1115- */
1116-ENTRY(stext)
1117-ENTRY(_stext)
1118-
1119-/*
1120- * BSS section
1121- */
1122-.section ".bss.page_aligned","w"
1123+.section .swapper_pg_dir,"a",@progbits
1124 ENTRY(swapper_pg_dir)
1125+#ifdef CONFIG_X86_PAE
1126+ .long swapper_pm_dir-__PAGE_OFFSET+1
1127+ .long 0
1128+ .long swapper_pm_dir+512*8-__PAGE_OFFSET+1
1129+ .long 0
1130+ .long swapper_pm_dir+512*16-__PAGE_OFFSET+1
1131+ .long 0
1132+ .long swapper_pm_dir+512*24-__PAGE_OFFSET+1
1133+ .long 0
1134+#else
1135 .fill 1024,4,0
1136+#endif
1137+
1138+#ifdef CONFIG_X86_PAE
1139+.section .swapper_pm_dir,"a",@progbits
1140+ENTRY(swapper_pm_dir)
1141+ .fill 512,8,0
1142+ .fill 512,8,0
1143+ .fill 512,8,0
1144+ .fill 512,8,0
1145+#endif
1146+
1147+.section .empty_zero_page,"a",@progbits
1148 ENTRY(empty_zero_page)
1149 .fill 4096,1,0
1150
1151 /*
1152- * This starts the data section.
1153- */
1154-.data
1155+ * The IDT has to be page-aligned to simplify the Pentium
1156+ * F0 0F bug workaround.. We have a special link segment
1157+ * for this.
1158+ */
1159+.section .idt,"a",@progbits
1160+ENTRY(idt_table)
1161+ .fill 256,8,0
1162+
1163+.section .rodata,"a",@progbits
1164+ready: .byte 0
1165
1166 ENTRY(stack_start)
1167- .long init_thread_union+THREAD_SIZE
1168+ .long init_thread_union+THREAD_SIZE-8
1169 .long __BOOT_DS
1170
1171-ready: .byte 0
1172-
1173 int_msg:
1174 .asciz "Unknown interrupt or fault at EIP %p %p %p\n"
1175
1176@@ -479,8 +536,8 @@ cpu_gdt_descr:
1177 .align L1_CACHE_BYTES
1178 ENTRY(boot_gdt_table)
1179 .fill GDT_ENTRY_BOOT_CS,8,0
1180- .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */
1181- .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */
1182+ .quad 0x00cf9b000000ffff /* kernel 4GB code at 0x00000000 */
1183+ .quad 0x00cf93000000ffff /* kernel 4GB data at 0x00000000 */
1184
1185 /*
1186 * The Global Descriptor Table contains 28 quadwords, per-CPU.
1187@@ -500,10 +557,10 @@ ENTRY(cpu_gdt_table)
1188 .quad 0x0000000000000000 /* 0x53 reserved */
1189 .quad 0x0000000000000000 /* 0x5b reserved */
1190
1191- .quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */
1192- .quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */
1193- .quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */
1194- .quad 0x00cff2000000ffff /* 0x7b user 4GB data at 0x00000000 */
1195+ .quad 0x00cf9b000000ffff /* 0x60 kernel 4GB code at 0x00000000 */
1196+ .quad 0x00cf93000000ffff /* 0x68 kernel 4GB data at 0x00000000 */
1197+ .quad 0x00cffb000000ffff /* 0x73 user 4GB code at 0x00000000 */
1198+ .quad 0x00cff3000000ffff /* 0x7b user 4GB data at 0x00000000 */
1199
1200 .quad 0x0000000000000000 /* 0x80 TSS descriptor */
1201 .quad 0x0000000000000000 /* 0x88 LDT descriptor */
1202@@ -513,24 +570,30 @@ ENTRY(cpu_gdt_table)
1203 * They code segments and data segments have fixed 64k limits,
1204 * the transfer segment sizes are set at run time.
1205 */
1206- .quad 0x00409a000000ffff /* 0x90 32-bit code */
1207- .quad 0x00009a000000ffff /* 0x98 16-bit code */
1208- .quad 0x000092000000ffff /* 0xa0 16-bit data */
1209- .quad 0x0000920000000000 /* 0xa8 16-bit data */
1210- .quad 0x0000920000000000 /* 0xb0 16-bit data */
1211+ .quad 0x00409b000000ffff /* 0x90 32-bit code */
1212+ .quad 0x00009b000000ffff /* 0x98 16-bit code */
1213+ .quad 0x000093000000ffff /* 0xa0 16-bit data */
1214+ .quad 0x0000930000000000 /* 0xa8 16-bit data */
1215+ .quad 0x0000930000000000 /* 0xb0 16-bit data */
1216
1217 /*
1218 * The APM segments have byte granularity and their bases
1219 * are set at run time. All have 64k limits.
1220 */
1221- .quad 0x00409a000000ffff /* 0xb8 APM CS code */
1222- .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */
1223- .quad 0x004092000000ffff /* 0xc8 APM DS data */
1224+ .quad 0x00409b000000ffff /* 0xb8 APM CS code */
1225+ .quad 0x00009b000000ffff /* 0xc0 APM CS 16 code (16 bit) */
1226+ .quad 0x004093000000ffff /* 0xc8 APM DS data */
1227
1228- .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */
1229+ .quad 0x0000930000000000 /* 0xd0 - ESPFIX 16-bit SS */
1230 .quad 0x0000000000000000 /* 0xd8 - unused */
1231 .quad 0x0000000000000000 /* 0xe0 - unused */
1232 .quad 0x0000000000000000 /* 0xe8 - unused */
1233 .quad 0x0000000000000000 /* 0xf0 - unused */
1234 .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */
1235
1236+ /* Be sure this is zeroed to avoid false validations in Xen */
1237+ .fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0
1238+
1239+#ifdef CONFIG_SMP
1240+ .fill (NR_CPUS-1) * (PAGE_SIZE_asm / 8),8,0 /* other CPU's GDT */
1241+#endif
1242diff -urNp linux-2.6.16.12/arch/i386/kernel/i386_ksyms.c linux-2.6.16.12/arch/i386/kernel/i386_ksyms.c
1243--- linux-2.6.16.12/arch/i386/kernel/i386_ksyms.c 2006-05-01 15:14:26.000000000 -0400
1244+++ linux-2.6.16.12/arch/i386/kernel/i386_ksyms.c 2006-05-01 20:17:33.000000000 -0400
1245@@ -3,6 +3,8 @@
1246 #include <asm/checksum.h>
1247 #include <asm/desc.h>
1248
1249+EXPORT_SYMBOL_GPL(cpu_gdt_table);
1250+
1251 EXPORT_SYMBOL(__down_failed);
1252 EXPORT_SYMBOL(__down_failed_interruptible);
1253 EXPORT_SYMBOL(__down_failed_trylock);
1254diff -urNp linux-2.6.16.12/arch/i386/kernel/init_task.c linux-2.6.16.12/arch/i386/kernel/init_task.c
1255--- linux-2.6.16.12/arch/i386/kernel/init_task.c 2006-05-01 15:14:26.000000000 -0400
1256+++ linux-2.6.16.12/arch/i386/kernel/init_task.c 2006-05-01 20:17:33.000000000 -0400
1257@@ -42,5 +42,5 @@ EXPORT_SYMBOL(init_task);
1258 * per-CPU TSS segments. Threads are completely 'soft' on Linux,
1259 * no more per-task TSS's.
1260 */
1261-DEFINE_PER_CPU(struct tss_struct, init_tss) ____cacheline_internodealigned_in_smp = INIT_TSS;
1262+struct tss_struct init_tss[NR_CPUS] ____cacheline_internodealigned_in_smp = { [0 ... NR_CPUS-1] = INIT_TSS };
1263
1264diff -urNp linux-2.6.16.12/arch/i386/kernel/ioport.c linux-2.6.16.12/arch/i386/kernel/ioport.c
1265--- linux-2.6.16.12/arch/i386/kernel/ioport.c 2006-05-01 15:14:26.000000000 -0400
1266+++ linux-2.6.16.12/arch/i386/kernel/ioport.c 2006-05-01 20:17:33.000000000 -0400
1267@@ -16,6 +16,7 @@
1268 #include <linux/stddef.h>
1269 #include <linux/slab.h>
1270 #include <linux/thread_info.h>
1271+#include <linux/grsecurity.h>
1272
1273 /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
1274 static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value)
1275@@ -64,9 +65,16 @@ asmlinkage long sys_ioperm(unsigned long
1276
1277 if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
1278 return -EINVAL;
1279+#ifdef CONFIG_GRKERNSEC_IO
1280+ if (turn_on) {
1281+ gr_handle_ioperm();
1282+#else
1283 if (turn_on && !capable(CAP_SYS_RAWIO))
1284+#endif
1285 return -EPERM;
1286-
1287+#ifdef CONFIG_GRKERNSEC_IO
1288+ }
1289+#endif
1290 /*
1291 * If it's the first ioperm() call in this thread's lifetime, set the
1292 * IO bitmap up. ioperm() is much less timing critical than clone(),
1293@@ -88,7 +96,7 @@ asmlinkage long sys_ioperm(unsigned long
1294 * because the ->io_bitmap_max value must match the bitmap
1295 * contents:
1296 */
1297- tss = &per_cpu(init_tss, get_cpu());
1298+ tss = init_tss + get_cpu();
1299
1300 set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
1301
1302@@ -142,8 +150,13 @@ asmlinkage long sys_iopl(unsigned long u
1303 return -EINVAL;
1304 /* Trying to gain more privileges? */
1305 if (level > old) {
1306+#ifdef CONFIG_GRKERNSEC_IO
1307+ gr_handle_iopl();
1308+ return -EPERM;
1309+#else
1310 if (!capable(CAP_SYS_RAWIO))
1311 return -EPERM;
1312+#endif
1313 }
1314 t->iopl = level << 12;
1315 regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl;
1316diff -urNp linux-2.6.16.12/arch/i386/kernel/irq.c linux-2.6.16.12/arch/i386/kernel/irq.c
1317--- linux-2.6.16.12/arch/i386/kernel/irq.c 2006-05-01 15:14:26.000000000 -0400
1318+++ linux-2.6.16.12/arch/i386/kernel/irq.c 2006-05-01 20:17:33.000000000 -0400
1319@@ -91,7 +91,7 @@ fastcall unsigned int do_IRQ(struct pt_r
1320 int arg1, arg2, ebx;
1321
1322 /* build the stack frame on the IRQ stack */
1323- isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
1324+ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)) - 2;
1325 irqctx->tinfo.task = curctx->tinfo.task;
1326 irqctx->tinfo.previous_esp = current_stack_pointer;
1327
1328@@ -119,10 +119,10 @@ fastcall unsigned int do_IRQ(struct pt_r
1329 * gcc's 3.0 and earlier don't handle that correctly.
1330 */
1331 static char softirq_stack[NR_CPUS * THREAD_SIZE]
1332- __attribute__((__aligned__(THREAD_SIZE)));
1333+ __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
1334
1335 static char hardirq_stack[NR_CPUS * THREAD_SIZE]
1336- __attribute__((__aligned__(THREAD_SIZE)));
1337+ __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
1338
1339 /*
1340 * allocate per-cpu stacks for hardirq and for softirq processing
1341@@ -182,7 +182,7 @@ asmlinkage void do_softirq(void)
1342 irqctx->tinfo.previous_esp = current_stack_pointer;
1343
1344 /* build the stack frame on the softirq stack */
1345- isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
1346+ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)) - 2;
1347
1348 asm volatile(
1349 " xchgl %%ebx,%%esp \n"
1350diff -urNp linux-2.6.16.12/arch/i386/kernel/ldt.c linux-2.6.16.12/arch/i386/kernel/ldt.c
1351--- linux-2.6.16.12/arch/i386/kernel/ldt.c 2006-05-01 15:14:26.000000000 -0400
1352+++ linux-2.6.16.12/arch/i386/kernel/ldt.c 2006-05-01 20:17:33.000000000 -0400
1353@@ -103,6 +103,19 @@ int init_new_context(struct task_struct
1354 retval = copy_ldt(&mm->context, &old_mm->context);
1355 up(&old_mm->context.sem);
1356 }
1357+
1358+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
1359+ if (!mm->context.user_cs_limit) {
1360+ mm->context.user_cs_base = 0UL;
1361+ mm->context.user_cs_limit = ~0UL;
1362+
1363+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
1364+ cpus_clear(mm->context.cpu_user_cs_mask);
1365+#endif
1366+
1367+ }
1368+#endif
1369+
1370 return retval;
1371 }
1372
1373@@ -160,7 +173,7 @@ static int read_default_ldt(void __user
1374 {
1375 int err;
1376 unsigned long size;
1377- void *address;
1378+ const void *address;
1379
1380 err = 0;
1381 address = &default_ldt[0];
1382@@ -215,6 +228,13 @@ static int write_ldt(void __user * ptr,
1383 }
1384 }
1385
1386+#ifdef CONFIG_PAX_SEGMEXEC
1387+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (ldt_info.contents & MODIFY_LDT_CONTENTS_CODE)) {
1388+ error = -EINVAL;
1389+ goto out_unlock;
1390+ }
1391+#endif
1392+
1393 entry_1 = LDT_entry_a(&ldt_info);
1394 entry_2 = LDT_entry_b(&ldt_info);
1395 if (oldmode)
1396diff -urNp linux-2.6.16.12/arch/i386/kernel/module.c linux-2.6.16.12/arch/i386/kernel/module.c
1397--- linux-2.6.16.12/arch/i386/kernel/module.c 2006-05-01 15:14:26.000000000 -0400
1398+++ linux-2.6.16.12/arch/i386/kernel/module.c 2006-05-01 20:17:33.000000000 -0400
1399@@ -21,6 +21,7 @@
1400 #include <linux/fs.h>
1401 #include <linux/string.h>
1402 #include <linux/kernel.h>
1403+#include <asm/desc.h>
1404
1405 #if 0
1406 #define DEBUGP printk
1407@@ -32,9 +33,30 @@ void *module_alloc(unsigned long size)
1408 {
1409 if (size == 0)
1410 return NULL;
1411+
1412+#ifdef CONFIG_PAX_KERNEXEC
1413+ return vmalloc(size);
1414+#else
1415 return vmalloc_exec(size);
1416+#endif
1417+
1418 }
1419
1420+#ifdef CONFIG_PAX_KERNEXEC
1421+void *module_alloc_exec(unsigned long size)
1422+{
1423+ struct vm_struct *area;
1424+
1425+ if (size == 0)
1426+ return NULL;
1427+
1428+ area = __get_vm_area(size, 0, (unsigned long)&MODULES_VADDR, (unsigned long)&MODULES_END);
1429+ if (area)
1430+ return area->addr;
1431+
1432+ return NULL;
1433+}
1434+#endif
1435
1436 /* Free memory returned from module_alloc */
1437 void module_free(struct module *mod, void *module_region)
1438@@ -44,6 +66,45 @@ void module_free(struct module *mod, voi
1439 table entries. */
1440 }
1441
1442+#ifdef CONFIG_PAX_KERNEXEC
1443+void module_free_exec(struct module *mod, void *module_region)
1444+{
1445+ struct vm_struct **p, *tmp;
1446+
1447+ if (!module_region)
1448+ return;
1449+
1450+ if ((PAGE_SIZE-1) & (unsigned long)module_region) {
1451+ printk(KERN_ERR "Trying to module_free_exec() bad address (%p)\n", module_region);
1452+ WARN_ON(1);
1453+ return;
1454+ }
1455+
1456+ write_lock(&vmlist_lock);
1457+ for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next)
1458+ if (tmp->addr == module_region)
1459+ break;
1460+
1461+ if (tmp) {
1462+ unsigned long cr0;
1463+
1464+ pax_open_kernel(cr0);
1465+ memset(tmp->addr, 0xCC, tmp->size);
1466+ pax_close_kernel(cr0);
1467+
1468+ *p = tmp->next;
1469+ kfree(tmp);
1470+ }
1471+ write_unlock(&vmlist_lock);
1472+
1473+ if (!tmp) {
1474+ printk(KERN_ERR "Trying to module_free_exec() nonexistent vm area (%p)\n",
1475+ module_region);
1476+ WARN_ON(1);
1477+ }
1478+}
1479+#endif
1480+
1481 /* We don't need anything special. */
1482 int module_frob_arch_sections(Elf_Ehdr *hdr,
1483 Elf_Shdr *sechdrs,
1484@@ -62,14 +123,16 @@ int apply_relocate(Elf32_Shdr *sechdrs,
1485 unsigned int i;
1486 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
1487 Elf32_Sym *sym;
1488- uint32_t *location;
1489+ uint32_t *plocation, location;
1490
1491 DEBUGP("Applying relocate section %u to %u\n", relsec,
1492 sechdrs[relsec].sh_info);
1493 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
1494 /* This is where to make the change */
1495- location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
1496- + rel[i].r_offset;
1497+ plocation = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr + rel[i].r_offset;
1498+ location = (uint32_t)plocation;
1499+ if (sechdrs[sechdrs[relsec].sh_info].sh_flags & SHF_EXECINSTR)
1500+ plocation = (void *)plocation + __KERNEL_TEXT_OFFSET;
1501 /* This is the symbol it is referring to. Note that all
1502 undefined symbols have been resolved. */
1503 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
1504@@ -78,11 +141,11 @@ int apply_relocate(Elf32_Shdr *sechdrs,
1505 switch (ELF32_R_TYPE(rel[i].r_info)) {
1506 case R_386_32:
1507 /* We add the value into the location given */
1508- *location += sym->st_value;
1509+ *plocation += sym->st_value;
1510 break;
1511 case R_386_PC32:
1512 /* Add the value, subtract its postition */
1513- *location += sym->st_value - (uint32_t)location;
1514+ *plocation += sym->st_value - location;
1515 break;
1516 default:
1517 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
1518diff -urNp linux-2.6.16.12/arch/i386/kernel/process.c linux-2.6.16.12/arch/i386/kernel/process.c
1519--- linux-2.6.16.12/arch/i386/kernel/process.c 2006-05-01 15:14:26.000000000 -0400
1520+++ linux-2.6.16.12/arch/i386/kernel/process.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 1521@@ -377,7 +377,7 @@ void exit_thread(void)
89675291 1522 /* The process may have allocated an io port bitmap... nuke it. */
1523 if (unlikely(NULL != t->io_bitmap_ptr)) {
1524 int cpu = get_cpu();
1525- struct tss_struct *tss = &per_cpu(init_tss, cpu);
1526+ struct tss_struct *tss = init_tss + cpu;
1527
1528 kfree(t->io_bitmap_ptr);
1529 t->io_bitmap_ptr = NULL;
9a4c6ab7 1530@@ -397,6 +397,9 @@ void flush_thread(void)
89675291 1531 {
1532 struct task_struct *tsk = current;
1533
1534+ __asm__("mov %0,%%fs\n"
1535+ "mov %0,%%gs\n"
1536+ : : "r" (0) : "memory");
1537 memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
1538 memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
1539 /*
9a4c6ab7 1540@@ -429,7 +432,7 @@ int copy_thread(int nr, unsigned long cl
89675291 1541 struct task_struct *tsk;
1542 int err;
1543
1544- childregs = task_pt_regs(p);
1545+ childregs = task_stack_page(p) + THREAD_SIZE - sizeof(struct pt_regs) - 8;
1546 *childregs = *regs;
1547 childregs->eax = 0;
1548 childregs->esp = esp;
9a4c6ab7 1549@@ -472,6 +475,11 @@ int copy_thread(int nr, unsigned long cl
89675291 1550 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
1551 goto out;
1552
1553+#ifdef CONFIG_PAX_SEGMEXEC
1554+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
1555+ goto out;
1556+#endif
1557+
1558 desc = p->thread.tls_array + idx - GDT_ENTRY_TLS_MIN;
1559 desc->a = LDT_entry_a(&info);
1560 desc->b = LDT_entry_b(&info);
9a4c6ab7 1561@@ -636,7 +644,11 @@ struct task_struct fastcall * __switch_t
89675291 1562 struct thread_struct *prev = &prev_p->thread,
1563 *next = &next_p->thread;
1564 int cpu = smp_processor_id();
1565- struct tss_struct *tss = &per_cpu(init_tss, cpu);
1566+ struct tss_struct *tss = init_tss + cpu;
1567+
1568+#ifdef CONFIG_PAX_KERNEXEC
1569+ unsigned long cr0;
1570+#endif
1571
1572 /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
1573
9a4c6ab7 1574@@ -659,11 +671,19 @@ struct task_struct fastcall * __switch_t
89675291 1575 savesegment(fs, prev->fs);
1576 savesegment(gs, prev->gs);
1577
1578+#ifdef CONFIG_PAX_KERNEXEC
1579+ pax_open_kernel(cr0);
1580+#endif
1581+
1582 /*
1583 * Load the per-thread Thread-Local Storage descriptor.
1584 */
1585 load_TLS(next, cpu);
1586
1587+#ifdef CONFIG_PAX_KERNEXEC
1588+ pax_close_kernel(cr0);
1589+#endif
1590+
1591 /*
1592 * Restore %fs and %gs if needed.
1593 *
9a4c6ab7 1594@@ -818,8 +838,18 @@ asmlinkage int sys_set_thread_area(struc
89675291 1595 struct desc_struct *desc;
1596 int cpu, idx;
1597
1598+#ifdef CONFIG_PAX_KERNEXEC
1599+ unsigned long cr0;
1600+#endif
1601+
1602 if (copy_from_user(&info, u_info, sizeof(info)))
1603 return -EFAULT;
1604+
1605+#ifdef CONFIG_PAX_SEGMEXEC
1606+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
1607+ return -EINVAL;
1608+#endif
1609+
1610 idx = info.entry_number;
1611
1612 /*
9a4c6ab7 1613@@ -851,8 +881,17 @@ asmlinkage int sys_set_thread_area(struc
89675291 1614 desc->a = LDT_entry_a(&info);
1615 desc->b = LDT_entry_b(&info);
1616 }
1617+
1618+#ifdef CONFIG_PAX_KERNEXEC
1619+ pax_open_kernel(cr0);
1620+#endif
1621+
1622 load_TLS(t, cpu);
1623
1624+#ifdef CONFIG_PAX_KERNEXEC
1625+ pax_close_kernel(cr0);
1626+#endif
1627+
1628 put_cpu();
1629
1630 return 0;
9a4c6ab7 1631@@ -908,9 +947,27 @@ asmlinkage int sys_get_thread_area(struc
89675291 1632 return 0;
1633 }
1634
1635-unsigned long arch_align_stack(unsigned long sp)
1636+#ifdef CONFIG_PAX_RANDKSTACK
1637+asmlinkage void pax_randomize_kstack(void)
1638 {
1639- if (randomize_va_space)
1640- sp -= get_random_int() % 8192;
1641- return sp & ~0xf;
1642+ struct tss_struct *tss = init_tss + smp_processor_id();
1643+ unsigned long time;
1644+
1645+ if (!randomize_va_space)
1646+ return;
1647+
1648+ rdtscl(time);
1649+
1650+ /* P4 seems to return a 0 LSB, ignore it */
1651+#ifdef CONFIG_MPENTIUM4
1652+ time &= 0x1EUL;
1653+ time <<= 2;
1654+#else
1655+ time &= 0xFUL;
1656+ time <<= 3;
1657+#endif
1658+
1659+ tss->esp0 ^= time;
1660+ current->thread.esp0 = tss->esp0;
1661 }
1662+#endif
1663diff -urNp linux-2.6.16.12/arch/i386/kernel/ptrace.c linux-2.6.16.12/arch/i386/kernel/ptrace.c
1664--- linux-2.6.16.12/arch/i386/kernel/ptrace.c 2006-05-01 15:14:26.000000000 -0400
1665+++ linux-2.6.16.12/arch/i386/kernel/ptrace.c 2006-05-01 20:17:33.000000000 -0400
1666@@ -17,6 +17,7 @@
1667 #include <linux/audit.h>
1668 #include <linux/seccomp.h>
1669 #include <linux/signal.h>
1670+#include <linux/grsecurity.h>
1671
1672 #include <asm/uaccess.h>
1673 #include <asm/pgtable.h>
1674@@ -342,6 +343,11 @@ ptrace_set_thread_area(struct task_struc
1675 if (copy_from_user(&info, user_desc, sizeof(info)))
1676 return -EFAULT;
1677
1678+#ifdef CONFIG_PAX_SEGMEXEC
1679+ if ((child->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
1680+ return -EINVAL;
1681+#endif
1682+
1683 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
1684 return -EINVAL;
1685
1686@@ -432,6 +438,17 @@ long arch_ptrace(struct task_struct *chi
1687 if(addr == (long) &dummy->u_debugreg[5]) break;
1688 if(addr < (long) &dummy->u_debugreg[4] &&
1689 ((unsigned long) data) >= TASK_SIZE-3) break;
1690+
1691+#ifdef CONFIG_GRKERNSEC
1692+ if(addr >= (long) &dummy->u_debugreg[0] &&
1693+ addr <= (long) &dummy->u_debugreg[3]){
1694+ long reg = (addr - (long) &dummy->u_debugreg[0]) >> 2;
1695+ long type = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 4*reg)) & 3;
1696+ long align = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 2 + 4*reg)) & 3;
1697+ if((type & 1) && (data & align))
1698+ break;
1699+ }
1700+#endif
1701
1702 /* Sanity-check data. Take one half-byte at once with
1703 * check = (val >> (16 + 4*i)) & 0xf. It contains the
1704@@ -645,7 +662,7 @@ void send_sigtrap(struct task_struct *ts
1705 info.si_code = TRAP_BRKPT;
1706
1707 /* User-mode eip? */
1708- info.si_addr = user_mode_vm(regs) ? (void __user *) regs->eip : NULL;
1709+ info.si_addr = user_mode(regs) ? (void __user *) regs->eip : NULL;
1710
1711 /* Send us the fakey SIGTRAP */
1712 force_sig_info(SIGTRAP, &info, tsk);
1713diff -urNp linux-2.6.16.12/arch/i386/kernel/reboot.c linux-2.6.16.12/arch/i386/kernel/reboot.c
1714--- linux-2.6.16.12/arch/i386/kernel/reboot.c 2006-05-01 15:14:26.000000000 -0400
1715+++ linux-2.6.16.12/arch/i386/kernel/reboot.c 2006-05-01 20:17:33.000000000 -0400
1716@@ -138,18 +138,18 @@ core_initcall(reboot_init);
1717 doesn't work with at least one type of 486 motherboard. It is easy
1718 to stop this code working; hence the copious comments. */
1719
1720-static unsigned long long
1721+static const unsigned long long
1722 real_mode_gdt_entries [3] =
1723 {
1724 0x0000000000000000ULL, /* Null descriptor */
1725- 0x00009a000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */
1726- 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
1727+ 0x00009b000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */
1728+ 0x000093000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */
1729 };
1730
1731 static struct
1732 {
1733 unsigned short size __attribute__ ((packed));
1734- unsigned long long * base __attribute__ ((packed));
1735+ const unsigned long long * base __attribute__ ((packed));
1736 }
1737 real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries },
1738 real_mode_idt = { 0x3ff, NULL },
1739@@ -203,6 +203,10 @@ void machine_real_restart(unsigned char
1740 {
1741 unsigned long flags;
1742
1743+#ifdef CONFIG_PAX_KERNEXEC
1744+ unsigned long cr0;
1745+#endif
1746+
1747 local_irq_disable();
1748
1749 /* Write zero to CMOS register number 0x0f, which the BIOS POST
1750@@ -223,9 +227,17 @@ void machine_real_restart(unsigned char
1751 from the kernel segment. This assumes the kernel segment starts at
1752 virtual address PAGE_OFFSET. */
1753
1754+#ifdef CONFIG_PAX_KERNEXEC
1755+ pax_open_kernel(cr0);
1756+#endif
1757+
1758 memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
1759 sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
1760
1761+#ifdef CONFIG_PAX_KERNEXEC
1762+ pax_close_kernel(cr0);
1763+#endif
1764+
1765 /*
1766 * Use `swapper_pg_dir' as our page directory.
1767 */
1768diff -urNp linux-2.6.16.12/arch/i386/kernel/setup.c linux-2.6.16.12/arch/i386/kernel/setup.c
1769--- linux-2.6.16.12/arch/i386/kernel/setup.c 2006-05-01 15:14:26.000000000 -0400
1770+++ linux-2.6.16.12/arch/i386/kernel/setup.c 2006-05-01 20:17:33.000000000 -0400
1771@@ -60,6 +60,7 @@
1772 #include <asm/io.h>
1773 #include "setup_arch_pre.h"
1774 #include <bios_ebda.h>
1775+#include <asm/desc.h>
1776
1777 /* Forward Declaration. */
1778 void __init find_max_pfn(void);
1779@@ -86,7 +87,11 @@ struct cpuinfo_x86 new_cpu_data __initda
1780 struct cpuinfo_x86 boot_cpu_data __read_mostly = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
1781 EXPORT_SYMBOL(boot_cpu_data);
1782
1783+#ifdef CONFIG_X86_PAE
1784+unsigned long mmu_cr4_features = X86_CR4_PAE;
1785+#else
1786 unsigned long mmu_cr4_features;
1787+#endif
1788
1789 #ifdef CONFIG_ACPI
1790 int acpi_disabled = 0;
1791@@ -1444,12 +1449,22 @@ void apply_alternatives(void *start, voi
1792 struct alt_instr *a;
1793 int diff, i, k;
1794 unsigned char **noptable = intel_nops;
1795+
1796+#ifdef CONFIG_PAX_KERNEXEC
1797+ unsigned long cr0;
1798+#endif
1799+
1800 for (i = 0; noptypes[i].cpuid >= 0; i++) {
1801 if (boot_cpu_has(noptypes[i].cpuid)) {
1802 noptable = noptypes[i].noptable;
1803 break;
1804 }
1805 }
1806+
1807+#ifdef CONFIG_PAX_KERNEXEC
1808+ pax_open_kernel(cr0);
1809+#endif
1810+
1811 for (a = start; (void *)a < end; a++) {
1812 if (!boot_cpu_has(a->cpuid))
1813 continue;
1814@@ -1464,6 +1479,11 @@ void apply_alternatives(void *start, voi
1815 memcpy(a->instr + i, noptable[k], k);
1816 }
1817 }
1818+
1819+#ifdef CONFIG_PAX_KERNEXEC
1820+ pax_close_kernel(cr0);
1821+#endif
1822+
1823 }
1824
1825 void __init alternative_instructions(void)
1826@@ -1542,14 +1562,14 @@ void __init setup_arch(char **cmdline_p)
1827
1828 if (!MOUNT_ROOT_RDONLY)
1829 root_mountflags &= ~MS_RDONLY;
1830- init_mm.start_code = (unsigned long) _text;
1831- init_mm.end_code = (unsigned long) _etext;
1832+ init_mm.start_code = (unsigned long) _text + __KERNEL_TEXT_OFFSET;
1833+ init_mm.end_code = (unsigned long) _etext + __KERNEL_TEXT_OFFSET;
1834 init_mm.end_data = (unsigned long) _edata;
1835 init_mm.brk = init_pg_tables_end + PAGE_OFFSET;
1836
1837- code_resource.start = virt_to_phys(_text);
1838- code_resource.end = virt_to_phys(_etext)-1;
1839- data_resource.start = virt_to_phys(_etext);
1840+ code_resource.start = virt_to_phys(_text + __KERNEL_TEXT_OFFSET);
1841+ code_resource.end = virt_to_phys(_etext + __KERNEL_TEXT_OFFSET)-1;
1842+ data_resource.start = virt_to_phys(_data);
1843 data_resource.end = virt_to_phys(_edata)-1;
1844
1845 parse_cmdline_early(cmdline_p);
1846diff -urNp linux-2.6.16.12/arch/i386/kernel/signal.c linux-2.6.16.12/arch/i386/kernel/signal.c
1847--- linux-2.6.16.12/arch/i386/kernel/signal.c 2006-05-01 15:14:26.000000000 -0400
1848+++ linux-2.6.16.12/arch/i386/kernel/signal.c 2006-05-01 20:17:33.000000000 -0400
1849@@ -350,7 +350,17 @@ static int setup_frame(int sig, struct k
1850 goto give_sigsegv;
1851 }
1852
1853+#ifdef CONFIG_PAX_NOVSYSCALL
1854+ restorer = frame->retcode;
1855+#else
1856 restorer = &__kernel_sigreturn;
1857+
1858+#ifdef CONFIG_PAX_SEGMEXEC
1859+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
1860+ restorer -= SEGMEXEC_TASK_SIZE;
1861+#endif
1862+#endif
1863+
1864 if (ka->sa.sa_flags & SA_RESTORER)
1865 restorer = ka->sa.sa_restorer;
1866
1867@@ -446,7 +456,18 @@ static int setup_rt_frame(int sig, struc
1868 goto give_sigsegv;
1869
1870 /* Set up to return from userspace. */
1871+
1872+#ifdef CONFIG_PAX_NOVSYSCALL
1873+ restorer = frame->retcode;
1874+#else
1875 restorer = &__kernel_rt_sigreturn;
1876+
1877+#ifdef CONFIG_PAX_SEGMEXEC
1878+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
1879+ restorer -= SEGMEXEC_TASK_SIZE;
1880+#endif
1881+#endif
1882+
1883 if (ka->sa.sa_flags & SA_RESTORER)
1884 restorer = ka->sa.sa_restorer;
1885 err |= __put_user(restorer, &frame->pretcode);
1886@@ -579,7 +600,7 @@ static void fastcall do_signal(struct pt
1887 * before reaching here, so testing against kernel
1888 * CS suffices.
1889 */
1890- if (!user_mode(regs))
1891+ if (!user_mode_novm(regs))
1892 return;
1893
1894 if (try_to_freeze())
1895diff -urNp linux-2.6.16.12/arch/i386/kernel/syscall_table.S linux-2.6.16.12/arch/i386/kernel/syscall_table.S
1896--- linux-2.6.16.12/arch/i386/kernel/syscall_table.S 2006-05-01 15:14:26.000000000 -0400
1897+++ linux-2.6.16.12/arch/i386/kernel/syscall_table.S 2006-05-01 20:17:33.000000000 -0400
1898@@ -1,3 +1,4 @@
1899+.section .rodata,"a",@progbits
1900 ENTRY(sys_call_table)
1901 .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
1902 .long sys_exit
1903diff -urNp linux-2.6.16.12/arch/i386/kernel/sysenter.c linux-2.6.16.12/arch/i386/kernel/sysenter.c
1904--- linux-2.6.16.12/arch/i386/kernel/sysenter.c 2006-05-01 15:14:26.000000000 -0400
1905+++ linux-2.6.16.12/arch/i386/kernel/sysenter.c 2006-05-01 20:17:33.000000000 -0400
1906@@ -24,7 +24,7 @@ extern asmlinkage void sysenter_entry(vo
1907 void enable_sep_cpu(void)
1908 {
1909 int cpu = get_cpu();
1910- struct tss_struct *tss = &per_cpu(init_tss, cpu);
1911+ struct tss_struct *tss = init_tss + cpu;
1912
1913 if (!boot_cpu_has(X86_FEATURE_SEP)) {
1914 put_cpu();
1915@@ -48,6 +48,7 @@ extern const char vsyscall_sysenter_star
1916
1917 int __init sysenter_setup(void)
1918 {
1919+#ifndef CONFIG_PAX_NOVSYSCALL
1920 void *page = (void *)get_zeroed_page(GFP_ATOMIC);
1921
1922 __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
1923@@ -62,6 +63,7 @@ int __init sysenter_setup(void)
1924 memcpy(page,
1925 &vsyscall_sysenter_start,
1926 &vsyscall_sysenter_end - &vsyscall_sysenter_start);
1927+#endif
1928
1929 return 0;
1930 }
1931diff -urNp linux-2.6.16.12/arch/i386/kernel/sys_i386.c linux-2.6.16.12/arch/i386/kernel/sys_i386.c
1932--- linux-2.6.16.12/arch/i386/kernel/sys_i386.c 2006-05-01 15:14:26.000000000 -0400
1933+++ linux-2.6.16.12/arch/i386/kernel/sys_i386.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 1934@@ -107,6 +107,191 @@ out:
89675291 1935 return err;
1936 }
1937
1938+unsigned long
1939+arch_get_unmapped_area(struct file *filp, unsigned long addr,
1940+ unsigned long len, unsigned long pgoff, unsigned long flags)
1941+{
1942+ struct mm_struct *mm = current->mm;
1943+ struct vm_area_struct *vma;
1944+ unsigned long start_addr, task_size = TASK_SIZE;
1945+
1946+#ifdef CONFIG_PAX_SEGMEXEC
1947+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
1948+ task_size = SEGMEXEC_TASK_SIZE;
1949+#endif
1950+
1951+ if (len > task_size)
1952+ return -ENOMEM;
1953+
1954+#ifdef CONFIG_PAX_RANDMMAP
1955+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
1956+#endif
1957+
1958+ if (addr) {
1959+ addr = PAGE_ALIGN(addr);
1960+ vma = find_vma(mm, addr);
1961+ if (task_size - len >= addr &&
1962+ (!vma || addr + len <= vma->vm_start))
1963+ return addr;
1964+ }
1965+ if (len > mm->cached_hole_size) {
1966+ start_addr = addr = mm->free_area_cache;
1967+ } else {
1968+ start_addr = addr = mm->mmap_base;
1969+ mm->cached_hole_size = 0;
1970+ }
1971+
1972+#ifdef CONFIG_PAX_PAGEEXEC
1973+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE) && start_addr >= mm->mmap_base) {
1974+ start_addr = 0x00110000UL;
1975+
1976+#ifdef CONFIG_PAX_RANDMMAP
1977+ if (mm->pax_flags & MF_PAX_RANDMMAP)
1978+ start_addr += mm->delta_mmap & 0x03FFFFFFUL;
1979+#endif
1980+
1981+ if (mm->start_brk <= start_addr && start_addr < mm->mmap_base)
1982+ start_addr = addr = mm->mmap_base;
1983+ else
1984+ addr = start_addr;
1985+ }
1986+#endif
1987+
1988+full_search:
1989+ for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
1990+ /* At this point: (!vma || addr < vma->vm_end). */
1991+ if (task_size - len < addr) {
1992+ /*
1993+ * Start a new search - just in case we missed
1994+ * some holes.
1995+ */
1996+ if (start_addr != mm->mmap_base) {
1997+ start_addr = addr = mm->mmap_base;
1998+ mm->cached_hole_size = 0;
1999+ goto full_search;
2000+ }
2001+ return -ENOMEM;
2002+ }
2003+ if (!vma || addr + len <= vma->vm_start) {
2004+ /*
2005+ * Remember the place where we stopped the search:
2006+ */
2007+ mm->free_area_cache = addr + len;
2008+ return addr;
2009+ }
2010+ if (addr + mm->cached_hole_size < vma->vm_start)
2011+ mm->cached_hole_size = vma->vm_start - addr;
2012+ addr = vma->vm_end;
2013+ if (mm->start_brk <= addr && addr < mm->mmap_base) {
2014+ start_addr = addr = mm->mmap_base;
2015+ goto full_search;
2016+ }
2017+ }
2018+}
2019+
2020+unsigned long
2021+arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
2022+ const unsigned long len, const unsigned long pgoff,
2023+ const unsigned long flags)
2024+{
2025+ struct vm_area_struct *vma;
2026+ struct mm_struct *mm = current->mm;
2027+ unsigned long base = mm->mmap_base, addr = addr0, task_size = TASK_SIZE;
2028+
2029+#ifdef CONFIG_PAX_SEGMEXEC
2030+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
2031+ task_size = SEGMEXEC_TASK_SIZE;
2032+#endif
2033+
2034+ /* requested length too big for entire address space */
2035+ if (len > task_size)
2036+ return -ENOMEM;
2037+
2038+#ifdef CONFIG_PAX_PAGEEXEC
2039+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE))
2040+ goto bottomup;
2041+#endif
2042+
2043+#ifdef CONFIG_PAX_RANDMMAP
2044+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
2045+#endif
2046+
2047+ /* requesting a specific address */
2048+ if (addr) {
2049+ addr = PAGE_ALIGN(addr);
2050+ vma = find_vma(mm, addr);
2051+ if (task_size - len >= addr &&
2052+ (!vma || addr + len <= vma->vm_start))
2053+ return addr;
2054+ }
2055+
2056+ /* check if free_area_cache is useful for us */
2057+ if (len <= mm->cached_hole_size) {
2058+ mm->cached_hole_size = 0;
2059+ mm->free_area_cache = mm->mmap_base;
2060+ }
2061+
2062+ /* either no address requested or can't fit in requested address hole */
2063+ addr = mm->free_area_cache;
2064+
2065+ /* make sure it can fit in the remaining address space */
2066+ if (addr > len) {
2067+ vma = find_vma(mm, addr-len);
2068+ if (!vma || addr <= vma->vm_start)
2069+ /* remember the address as a hint for next time */
2070+ return (mm->free_area_cache = addr-len);
2071+ }
2072+
2073+ if (mm->mmap_base < len)
2074+ goto bottomup;
2075+
2076+ addr = mm->mmap_base-len;
2077+
2078+ do {
2079+ /*
2080+ * Lookup failure means no vma is above this address,
2081+ * else if new region fits below vma->vm_start,
2082+ * return with success:
2083+ */
2084+ vma = find_vma(mm, addr);
2085+ if (!vma || addr+len <= vma->vm_start)
2086+ /* remember the address as a hint for next time */
2087+ return (mm->free_area_cache = addr);
2088+
2089+ /* remember the largest hole we saw so far */
2090+ if (addr + mm->cached_hole_size < vma->vm_start)
2091+ mm->cached_hole_size = vma->vm_start - addr;
2092+
2093+ /* try just below the current vma->vm_start */
2094+ addr = vma->vm_start-len;
2095+ } while (len < vma->vm_start);
2096+
2097+bottomup:
2098+ /*
2099+ * A failed mmap() very likely causes application failure,
2100+ * so fall back to the bottom-up function here. This scenario
2101+ * can happen with large stack limits and large mmap()
2102+ * allocations.
2103+ */
2104+ mm->mmap_base = TASK_UNMAPPED_BASE;
2105+
2106+#ifdef CONFIG_PAX_RANDMMAP
2107+ if (mm->pax_flags & MF_PAX_RANDMMAP)
2108+ mm->mmap_base += mm->delta_mmap;
2109+#endif
2110+
2111+ mm->free_area_cache = mm->mmap_base;
2112+ mm->cached_hole_size = ~0UL;
2113+ addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
2114+ /*
2115+ * Restore the topdown base:
2116+ */
2117+ mm->mmap_base = base;
2118+ mm->free_area_cache = base;
2119+ mm->cached_hole_size = ~0UL;
2120+
2121+ return addr;
2122+}
2123
2124 struct sel_arg_struct {
2125 unsigned long n;
2126diff -urNp linux-2.6.16.12/arch/i386/kernel/traps.c linux-2.6.16.12/arch/i386/kernel/traps.c
2127--- linux-2.6.16.12/arch/i386/kernel/traps.c 2006-05-01 15:14:26.000000000 -0400
2128+++ linux-2.6.16.12/arch/i386/kernel/traps.c 2006-05-01 20:17:33.000000000 -0400
2129@@ -28,6 +28,7 @@
2130 #include <linux/utsname.h>
2131 #include <linux/kprobes.h>
2132 #include <linux/kexec.h>
2133+#include <linux/binfmts.h>
2134
2135 #ifdef CONFIG_EISA
2136 #include <linux/ioport.h>
9a4c6ab7 2137@@ -60,18 +60,13 @@
89675291 2138
2139 asmlinkage int system_call(void);
2140
2141-struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
2142+const struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
2143 { 0, 0 }, { 0, 0 } };
2144
2145 /* Do we ignore FPU interrupts ? */
2146 char ignore_fpu_irq = 0;
2147
2148-/*
2149- * The IDT has to be page-aligned to simplify the Pentium
2150- * F0 0F bug workaround.. We have a special link segment
2151- * for this.
2152- */
2153-struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
2154+extern struct desc_struct idt_table[256];
2155
2156 asmlinkage void divide_error(void);
2157 asmlinkage void debug(void);
9a4c6ab7 2158@@ -127,18 +123,22 @@ static inline unsigned long print_contex
89675291 2159 char *log_lvl)
2160 {
2161 unsigned long addr;
2162+ int i = kstack_depth_to_print;
2163
2164 #ifdef CONFIG_FRAME_POINTER
2165 while (valid_stack_ptr(tinfo, (void *)ebp)) {
2166 addr = *(unsigned long *)(ebp + 4);
2167 print_addr_and_symbol(addr, log_lvl);
2168 ebp = *(unsigned long *)ebp;
2169+ --i;
2170 }
2171 #else
2172 while (valid_stack_ptr(tinfo, stack)) {
2173 addr = *stack++;
2174- if (__kernel_text_address(addr))
2175+ if (__kernel_text_address(addr)) {
2176 print_addr_and_symbol(addr, log_lvl);
2177+ --i;
2178+ }
2179 }
2180 #endif
2181 return ebp;
9a4c6ab7 2182@@ -269,7 +269,7 @@ void show_registers(struct pt_regs *regs
89675291 2183
2184 printk(KERN_EMERG "Code: ");
2185
2186- eip = (u8 __user *)regs->eip - 43;
2187+ eip = (u8 __user *)regs->eip - 43 + __KERNEL_TEXT_OFFSET;
2188 for (i = 0; i < 64; i++, eip++) {
2189 unsigned char c;
2190
9a4c6ab7 2191@@ -277,7 +277,7 @@ void show_registers(struct pt_regs *regs
89675291 2192 printk(" Bad EIP value.");
2193 break;
2194 }
2195- if (eip == (u8 __user *)regs->eip)
2196+ if (eip == (u8 __user *)regs->eip + __KERNEL_TEXT_OFFSET)
2197 printk("<%02x> ", c);
2198 else
2199 printk("%02x ", c);
9a4c6ab7 2200@@ -294,7 +294,7 @@ static void handle_BUG(struct pt_regs *r
89675291 2201 char c;
2202 unsigned long eip;
2203
2204- eip = regs->eip;
2205+ eip = regs->eip + __KERNEL_TEXT_OFFSET;
2206
2207 if (eip < PAGE_OFFSET)
2208 goto no_bug;
9a4c6ab7 2209@@ -396,7 +396,7 @@ void die(const char * str, struct pt_reg
89675291 2210
2211 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
2212 {
2213- if (!user_mode_vm(regs))
2214+ if (!user_mode(regs))
2215 die(str, regs, err);
2216 }
2217
9a4c6ab7 2218@@ -414,7 +414,7 @@ static void __kprobes do_trap(int trapnr
89675291 2219 goto trap_signal;
2220 }
2221
2222- if (!user_mode(regs))
2223+ if (!user_mode_novm(regs))
2224 goto kernel_trap;
2225
2226 trap_signal: {
9a4c6ab7 2227@@ -502,7 +502,7 @@ fastcall void __kprobes do_general_prote
89675291 2228 long error_code)
2229 {
2230 int cpu = get_cpu();
2231- struct tss_struct *tss = &per_cpu(init_tss, cpu);
2232+ struct tss_struct *tss = &init_tss[cpu];
2233 struct thread_struct *thread = &current->thread;
2234
2235 /*
9a4c6ab7 2236@@ -538,9 +538,25 @@ fastcall void __kprobes do_general_prote
89675291 2237 if (regs->eflags & VM_MASK)
2238 goto gp_in_vm86;
2239
2240- if (!user_mode(regs))
2241+ if (!user_mode_novm(regs))
2242 goto gp_in_kernel;
2243
2244+#ifdef CONFIG_PAX_PAGEEXEC
2245+ if (current->mm && (current->mm->pax_flags & MF_PAX_PAGEEXEC)) {
2246+ struct mm_struct *mm = current->mm;
2247+ unsigned long limit;
2248+
2249+ down_write(&mm->mmap_sem);
2250+ limit = mm->context.user_cs_limit;
2251+ if (limit < TASK_SIZE) {
2252+ track_exec_limit(mm, limit, TASK_SIZE, PROT_EXEC);
2253+ up_write(&mm->mmap_sem);
2254+ return;
2255+ }
2256+ up_write(&mm->mmap_sem);
2257+ }
2258+#endif
2259+
2260 current->thread.error_code = error_code;
2261 current->thread.trap_no = 13;
2262 force_sig(SIGSEGV, current);
9a4c6ab7 2263@@ -556,6 +572,13 @@ gp_in_kernel:
89675291 2264 if (notify_die(DIE_GPF, "general protection fault", regs,
2265 error_code, 13, SIGSEGV) == NOTIFY_STOP)
2266 return;
2267+
2268+#ifdef CONFIG_PAX_KERNEXEC
2269+ if ((regs->xcs & 0xFFFF) == __KERNEL_CS)
2270+ die("PAX: suspicious general protection fault", regs, error_code);
2271+ else
2272+#endif
2273+
2274 die("general protection fault", regs, error_code);
2275 }
2276 }
9a4c6ab7 2277@@ -781,7 +804,7 @@ fastcall void __kprobes do_debug(struct
89675291 2278 * check for kernel mode by just checking the CPL
2279 * of CS.
2280 */
2281- if (!user_mode(regs))
2282+ if (!user_mode_novm(regs))
2283 goto clear_TF_reenable;
2284 }
2285
9a4c6ab7 2286@@ -1071,7 +1094,19 @@ do { \
89675291 2287 */
2288 void set_intr_gate(unsigned int n, void *addr)
2289 {
2290+
2291+#ifdef CONFIG_PAX_KERNEXEC
2292+ unsigned long cr0;
2293+
2294+ pax_open_kernel(cr0);
2295+#endif
2296+
2297 _set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
2298+
2299+#ifdef CONFIG_PAX_KERNEXEC
2300+ pax_close_kernel(cr0);
2301+#endif
2302+
2303 }
2304
2305 /*
2306diff -urNp linux-2.6.16.12/arch/i386/kernel/vm86.c linux-2.6.16.12/arch/i386/kernel/vm86.c
2307--- linux-2.6.16.12/arch/i386/kernel/vm86.c 2006-05-01 15:14:26.000000000 -0400
2308+++ linux-2.6.16.12/arch/i386/kernel/vm86.c 2006-05-01 20:17:33.000000000 -0400
2309@@ -123,7 +123,7 @@ struct pt_regs * fastcall save_v86_state
2310 do_exit(SIGSEGV);
2311 }
2312
2313- tss = &per_cpu(init_tss, get_cpu());
2314+ tss = init_tss + get_cpu();
2315 current->thread.esp0 = current->thread.saved_esp0;
2316 current->thread.sysenter_cs = __KERNEL_CS;
2317 load_esp0(tss, &current->thread);
2318@@ -297,7 +297,7 @@ static void do_sys_vm86(struct kernel_vm
2319 savesegment(fs, tsk->thread.saved_fs);
2320 savesegment(gs, tsk->thread.saved_gs);
2321
2322- tss = &per_cpu(init_tss, get_cpu());
2323+ tss = init_tss + get_cpu();
2324 tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
2325 if (cpu_has_sep)
2326 tsk->thread.sysenter_cs = 0;
2327diff -urNp linux-2.6.16.12/arch/i386/kernel/vmlinux.lds.S linux-2.6.16.12/arch/i386/kernel/vmlinux.lds.S
2328--- linux-2.6.16.12/arch/i386/kernel/vmlinux.lds.S 2006-05-01 15:14:26.000000000 -0400
2329+++ linux-2.6.16.12/arch/i386/kernel/vmlinux.lds.S 2006-05-01 20:17:33.000000000 -0400
2330@@ -4,9 +4,18 @@
2331
2332 #define LOAD_OFFSET __PAGE_OFFSET
2333
2334+#include <linux/config.h>
2335+
2336 #include <asm-generic/vmlinux.lds.h>
2337 #include <asm/thread_info.h>
2338 #include <asm/page.h>
2339+#include <asm/segment.h>
2340+
2341+#ifdef CONFIG_X86_PAE
2342+#define PMD_SHIFT 21
2343+#else
2344+#define PMD_SHIFT 22
2345+#endif
2346
2347 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
2348 OUTPUT_ARCH(i386)
2349@@ -15,67 +24,17 @@ jiffies = jiffies_64;
2350 SECTIONS
2351 {
2352 . = __KERNEL_START;
2353- phys_startup_32 = startup_32 - LOAD_OFFSET;
2354- /* read-only */
2355- _text = .; /* Text and read-only data */
2356- .text : AT(ADDR(.text) - LOAD_OFFSET) {
2357- *(.text)
2358- SCHED_TEXT
2359- LOCK_TEXT
2360- KPROBES_TEXT
2361- *(.fixup)
2362- *(.gnu.warning)
2363- } = 0x9090
2364-
2365- _etext = .; /* End of text section */
2366-
2367- . = ALIGN(16); /* Exception table */
2368- __start___ex_table = .;
2369- __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
2370- __stop___ex_table = .;
2371-
2372- RODATA
2373+ phys_startup_32 = startup_32 - LOAD_OFFSET + __KERNEL_TEXT_OFFSET;
2374
2375- /* writeable */
2376- .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
2377- *(.data)
2378- CONSTRUCTORS
2379+ .text.startup : AT(ADDR(.text.startup) - LOAD_OFFSET) {
2380+ BYTE(0xEA) /* jmp far */
2381+ LONG(phys_startup_32)
2382+ SHORT(__BOOT_CS)
2383 }
2384
2385- . = ALIGN(4096);
2386- __nosave_begin = .;
2387- .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
2388- . = ALIGN(4096);
2389- __nosave_end = .;
2390-
2391- . = ALIGN(4096);
2392- .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
2393- *(.data.idt)
2394- }
2395-
2396- . = ALIGN(32);
2397- .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
2398- *(.data.cacheline_aligned)
2399- }
2400-
2401- /* rarely changed data like cpu maps */
2402- . = ALIGN(32);
2403- .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
2404- _edata = .; /* End of data section */
2405-
2406- . = ALIGN(THREAD_SIZE); /* init_task */
2407- .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
2408- *(.data.init_task)
2409- }
2410-
2411 /* will be freed after init */
2412 . = ALIGN(4096); /* Init code and data */
2413 __init_begin = .;
2414- .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
2415- _sinittext = .;
2416- *(.init.text)
2417- _einittext = .;
2418- }
2419 .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
2420 . = ALIGN(16);
2421 __setup_start = .;
2422@@ -107,9 +66,7 @@ SECTIONS
2423 .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
2424 *(.altinstr_replacement)
2425 }
2426- /* .exit.text is discard at runtime, not link time, to deal with references
2427- from .altinstructions and .eh_frame */
2428- .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) }
2429+
2430 .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
2431 . = ALIGN(4096);
2432 __initramfs_start = .;
2433@@ -119,10 +76,108 @@ SECTIONS
2434 __per_cpu_start = .;
2435 .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
2436 __per_cpu_end = .;
2437+
2438+ /* read-only */
2439+
2440 . = ALIGN(4096);
2441- __init_end = .;
2442+ .init.text (. - __KERNEL_TEXT_OFFSET) : AT(ADDR(.init.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
2443+ _sinittext = .;
2444+ *(.init.text)
2445+ _einittext = .;
2446+ }
2447+
2448+ /* .exit.text is discard at runtime, not link time, to deal with references
2449+ from .altinstructions and .eh_frame */
2450+ .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) { *(.exit.text) }
2451+
2452+#ifdef CONFIG_PAX_KERNEXEC
2453+ .text.align : AT(ADDR(.text.align) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
2454+ . = ALIGN(__KERNEL_TEXT_OFFSET - LOAD_OFFSET) - 1;
2455+ BYTE(0)
2456+ }
2457+#else
2458+ . = ALIGN(4096);
2459+#endif
2460+
2461+ __init_end = . + __KERNEL_TEXT_OFFSET;
2462 /* freed after init ends here */
2463-
2464+
2465+ _text = .; /* Text and read-only data */
2466+ .text : AT(ADDR(.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
2467+ *(.text)
2468+ SCHED_TEXT
2469+ LOCK_TEXT
2470+ KPROBES_TEXT
2471+ *(.fixup)
2472+ *(.gnu.warning)
2473+ } = 0x9090
2474+
2475+ _etext = .; /* End of text section */
2476+ . += __KERNEL_TEXT_OFFSET;
2477+ . = ALIGN(16); /* Exception table */
2478+ __start___ex_table = .;
2479+ __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
2480+ __stop___ex_table = .;
2481+
2482+ . = ALIGN(4096);
2483+ .rodata.page_aligned : AT(ADDR(.rodata.page_aligned) - LOAD_OFFSET) {
2484+ *(.empty_zero_page)
2485+
2486+#ifdef CONFIG_X86_PAE
2487+ *(.swapper_pm_dir)
2488+#endif
2489+
2490+ *(.swapper_pg_dir)
2491+ *(.idt)
2492+ }
2493+
2494+ RODATA
2495+
2496+#ifdef CONFIG_PAX_KERNEXEC
2497+ . = ALIGN(4096);
2498+ MODULES_VADDR = .;
2499+
2500+ .module.text : AT(ADDR(.module.text) - LOAD_OFFSET) {
2501+ . += (4 * 1024 * 1024);
2502+ . = ALIGN(1 << PMD_SHIFT) - 1;
2503+ BYTE(0)
2504+ }
2505+
2506+ MODULES_END = .;
2507+#else
2508+ . = ALIGN(32);
2509+#endif
2510+
2511+ /* writeable */
2512+ .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
2513+ _data = .;
2514+ *(.data)
2515+ CONSTRUCTORS
2516+ }
2517+
2518+ . = ALIGN(4096);
2519+ __nosave_begin = .;
2520+ .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
2521+ . = ALIGN(4096);
2522+ __nosave_end = .;
2523+
2524+ . = ALIGN(32);
2525+ .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
2526+ *(.data.cacheline_aligned)
2527+ }
2528+
2529+ /* rarely changed data like cpu maps */
2530+ . = ALIGN(32);
2531+ .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
2532+
2533+ . = ALIGN(THREAD_SIZE); /* init_task */
2534+ .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
2535+ *(.data.init_task)
2536+ }
2537+
2538+ _edata = .; /* End of data section */
2539+
2540+ . = ALIGN(4096);
2541 __bss_start = .; /* BSS */
2542 .bss.page_aligned : AT(ADDR(.bss.page_aligned) - LOAD_OFFSET) {
2543 *(.bss.page_aligned)
2544diff -urNp linux-2.6.16.12/arch/i386/mach-voyager/voyager_smp.c linux-2.6.16.12/arch/i386/mach-voyager/voyager_smp.c
2545--- linux-2.6.16.12/arch/i386/mach-voyager/voyager_smp.c 2006-05-01 15:14:26.000000000 -0400
2546+++ linux-2.6.16.12/arch/i386/mach-voyager/voyager_smp.c 2006-05-01 20:17:33.000000000 -0400
2547@@ -1295,7 +1295,7 @@ smp_local_timer_interrupt(struct pt_regs
2548 per_cpu(prof_counter, cpu);
2549 }
2550
2551- update_process_times(user_mode_vm(regs));
2552+ update_process_times(user_mode(regs));
2553 }
2554
2555 if( ((1<<cpu) & voyager_extended_vic_processors) == 0)
2556diff -urNp linux-2.6.16.12/arch/i386/mm/boot_ioremap.c linux-2.6.16.12/arch/i386/mm/boot_ioremap.c
2557--- linux-2.6.16.12/arch/i386/mm/boot_ioremap.c 2006-05-01 15:14:26.000000000 -0400
2558+++ linux-2.6.16.12/arch/i386/mm/boot_ioremap.c 2006-05-01 20:17:33.000000000 -0400
2559@@ -8,53 +8,37 @@
2560 */
2561
2562
2563-/*
2564- * We need to use the 2-level pagetable functions, but CONFIG_X86_PAE
2565- * keeps that from happenning. If anyone has a better way, I'm listening.
2566- *
2567- * boot_pte_t is defined only if this all works correctly
2568- */
2569-
2570 #include <linux/config.h>
2571-#undef CONFIG_X86_PAE
2572 #include <asm/page.h>
2573 #include <asm/pgtable.h>
2574 #include <asm/tlbflush.h>
2575 #include <linux/init.h>
2576 #include <linux/stddef.h>
2577
2578-/*
2579- * I'm cheating here. It is known that the two boot PTE pages are
2580- * allocated next to each other. I'm pretending that they're just
2581- * one big array.
2582- */
2583-
2584-#define BOOT_PTE_PTRS (PTRS_PER_PTE*2)
2585-#define boot_pte_index(address) \
2586- (((address) >> PAGE_SHIFT) & (BOOT_PTE_PTRS - 1))
2587-
2588-static inline boot_pte_t* boot_vaddr_to_pte(void *address)
2589-{
2590- boot_pte_t* boot_pg = (boot_pte_t*)pg0;
2591- return &boot_pg[boot_pte_index((unsigned long)address)];
2592-}
2593
2594 /*
2595 * This is only for a caller who is clever enough to page-align
2596 * phys_addr and virtual_source, and who also has a preference
2597 * about which virtual address from which to steal ptes
2598 */
2599-static void __boot_ioremap(unsigned long phys_addr, unsigned long nrpages,
2600- void* virtual_source)
2601+static void __init __boot_ioremap(unsigned long phys_addr, unsigned int nrpages,
2602+ char* virtual_source)
2603 {
2604- boot_pte_t* pte;
2605- int i;
2606- char *vaddr = virtual_source;
2607+ pgd_t *pgd;
2608+ pud_t *pud;
2609+ pmd_t *pmd;
2610+ pte_t* pte;
2611+ unsigned int i;
2612+ unsigned long vaddr = (unsigned long)virtual_source;
2613+
2614+ pgd = pgd_offset_k(vaddr);
2615+ pud = pud_offset(pgd, vaddr);
2616+ pmd = pmd_offset(pud, vaddr);
2617+ pte = pte_offset_kernel(pmd, vaddr);
2618
2619- pte = boot_vaddr_to_pte(virtual_source);
2620 for (i=0; i < nrpages; i++, phys_addr += PAGE_SIZE, pte++) {
2621 set_pte(pte, pfn_pte(phys_addr>>PAGE_SHIFT, PAGE_KERNEL));
2622- __flush_tlb_one(&vaddr[i*PAGE_SIZE]);
2623+ __flush_tlb_one(&virtual_source[i*PAGE_SIZE]);
2624 }
2625 }
2626
2627diff -urNp linux-2.6.16.12/arch/i386/mm/extable.c linux-2.6.16.12/arch/i386/mm/extable.c
2628--- linux-2.6.16.12/arch/i386/mm/extable.c 2006-05-01 15:14:26.000000000 -0400
2629+++ linux-2.6.16.12/arch/i386/mm/extable.c 2006-05-01 20:17:33.000000000 -0400
2630@@ -12,7 +12,7 @@ int fixup_exception(struct pt_regs *regs
2631 const struct exception_table_entry *fixup;
2632
2633 #ifdef CONFIG_PNPBIOS
2634- if (unlikely((regs->xcs & ~15) == (GDT_ENTRY_PNPBIOS_BASE << 3)))
2635+ if (unlikely(regs->xcs == (GDT_ENTRY_PNPBIOS_BASE << 3)))
2636 {
2637 extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
2638 extern u32 pnp_bios_is_utter_crap;
2639diff -urNp linux-2.6.16.12/arch/i386/mm/fault.c linux-2.6.16.12/arch/i386/mm/fault.c
2640--- linux-2.6.16.12/arch/i386/mm/fault.c 2006-05-01 15:14:26.000000000 -0400
2641+++ linux-2.6.16.12/arch/i386/mm/fault.c 2006-05-01 20:17:33.000000000 -0400
2642@@ -22,6 +22,9 @@
2643 #include <linux/highmem.h>
2644 #include <linux/module.h>
2645 #include <linux/kprobes.h>
2646+#include <linux/unistd.h>
2647+#include <linux/compiler.h>
2648+#include <linux/binfmts.h>
2649
2650 #include <asm/system.h>
2651 #include <asm/uaccess.h>
2652@@ -82,11 +85,13 @@ static inline unsigned long get_segment_
2653
2654 /* Unlikely, but must come before segment checks. */
2655 if (unlikely((regs->eflags & VM_MASK) != 0))
2656- return eip + (seg << 4);
2657+ return (eip & 0xFFFF) + (seg << 4);
2658
2659 /* By far the most common cases. */
2660- if (likely(seg == __USER_CS || seg == __KERNEL_CS))
2661+ if (likely(seg == __USER_CS))
2662 return eip;
2663+ if (likely(seg == __KERNEL_CS))
2664+ return eip + __KERNEL_TEXT_OFFSET;
2665
2666 /* Check the segment exists, is within the current LDT/GDT size,
2667 that kernel/user (ring 0..3) has the appropriate privilege,
2668@@ -108,7 +113,7 @@ static inline unsigned long get_segment_
2669 desc = (void *)desc + (seg & ~7);
2670 } else {
2671 /* Must disable preemption while reading the GDT. */
2672- desc = (u32 *)get_cpu_gdt_table(get_cpu());
2673+ desc = (u32 *)get_cpu_gdt_table(get_cpu());
2674 desc = (void *)desc + (seg & ~7);
2675 }
2676
2677@@ -214,6 +219,30 @@ static noinline void force_sig_info_faul
2678
2679 fastcall void do_invalid_op(struct pt_regs *, unsigned long);
2680
2681+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
2682+static int pax_handle_fetch_fault(struct pt_regs *regs);
2683+#endif
2684+
2685+#ifdef CONFIG_PAX_PAGEEXEC
2686+static inline pmd_t * pax_get_pmd(struct mm_struct *mm, unsigned long address)
2687+{
2688+ pgd_t *pgd;
2689+ pud_t *pud;
2690+ pmd_t *pmd;
2691+
2692+ pgd = pgd_offset(mm, address);
2693+ if (!pgd_present(*pgd))
2694+ return NULL;
2695+ pud = pud_offset(pgd, address);
2696+ if (!pud_present(*pud))
2697+ return NULL;
2698+ pmd = pmd_offset(pud, address);
2699+ if (!pmd_present(*pmd))
2700+ return NULL;
2701+ return pmd;
2702+}
2703+#endif
2704+
2705 /*
2706 * This routine handles page faults. It determines the address,
2707 * and the problem, and then passes it off to one of the appropriate
2708@@ -231,9 +260,15 @@ fastcall void __kprobes do_page_fault(st
2709 struct mm_struct *mm;
2710 struct vm_area_struct * vma;
2711 unsigned long address;
2712- unsigned long page;
2713 int write, si_code;
2714
2715+#ifdef CONFIG_PAX_PAGEEXEC
2716+ pmd_t *pmd;
2717+ pte_t *pte;
2718+ spinlock_t *ptl;
2719+ unsigned char pte_mask;
2720+#endif
2721+
2722 /* get the address */
2723 address = read_cr2();
2724
2725@@ -245,6 +280,7 @@ fastcall void __kprobes do_page_fault(st
2726 local_irq_enable();
2727
2728 tsk = current;
2729+ mm = tsk->mm;
2730
2731 si_code = SEGV_MAPERR;
2732
2733@@ -271,14 +307,12 @@ fastcall void __kprobes do_page_fault(st
2734 goto bad_area_nosemaphore;
2735 }
2736
2737- mm = tsk->mm;
2738-
2739 /*
2740 * If we're in an interrupt, have no user context or are running in an
2741 * atomic region then we must not take the fault..
2742 */
2743 if (in_atomic() || !mm)
2744- goto bad_area_nosemaphore;
2745+ goto bad_area_nopax;
2746
2747 /* When running in the kernel we expect faults to occur only to
2748 * addresses in user space. All other faults represent errors in the
2749@@ -298,10 +332,98 @@ fastcall void __kprobes do_page_fault(st
2750 if (!down_read_trylock(&mm->mmap_sem)) {
2751 if ((error_code & 4) == 0 &&
2752 !search_exception_tables(regs->eip))
2753- goto bad_area_nosemaphore;
2754+ goto bad_area_nopax;
2755 down_read(&mm->mmap_sem);
2756 }
2757
2758+#ifdef CONFIG_PAX_PAGEEXEC
2759+ if (unlikely((error_code & 5) != 5 ||
2760+ (regs->eflags & X86_EFLAGS_VM) ||
2761+ !(mm->pax_flags & MF_PAX_PAGEEXEC)))
2762+ goto not_pax_fault;
2763+
2764+ /* PaX: it's our fault, let's handle it if we can */
2765+
2766+ /* PaX: take a look at read faults before acquiring any locks */
2767+ if (unlikely(!(error_code & 2) && (regs->eip == address))) {
2768+ /* instruction fetch attempt from a protected page in user mode */
2769+ up_read(&mm->mmap_sem);
2770+ switch (pax_handle_fetch_fault(regs)) {
2771+
2772+#ifdef CONFIG_PAX_EMUTRAMP
2773+ case 2:
2774+ return;
2775+#endif
2776+
2777+ }
2778+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
2779+ do_exit(SIGKILL);
2780+ }
2781+
2782+ pmd = pax_get_pmd(mm, address);
2783+ if (unlikely(!pmd))
2784+ goto not_pax_fault;
2785+
2786+ pte = pte_offset_map_lock(mm, pmd, address, &ptl);
2787+ if (unlikely(!(pte_val(*pte) & _PAGE_PRESENT) || pte_user(*pte))) {
2788+ pte_unmap_unlock(pte, ptl);
2789+ goto not_pax_fault;
2790+ }
2791+
2792+ if (unlikely((error_code & 2) && !pte_write(*pte))) {
2793+ /* write attempt to a protected page in user mode */
2794+ pte_unmap_unlock(pte, ptl);
2795+ goto not_pax_fault;
2796+ }
2797+
2798+#ifdef CONFIG_SMP
2799+ if (likely(address > get_limit(regs->xcs) && cpu_isset(smp_processor_id(), mm->context.cpu_user_cs_mask)))
2800+#else
2801+ if (likely(address > get_limit(regs->xcs)))
2802+#endif
2803+ {
2804+ set_pte(pte, pte_mkread(*pte));
2805+ __flush_tlb_one(address);
2806+ pte_unmap_unlock(pte, ptl);
2807+ up_read(&mm->mmap_sem);
2808+ return;
2809+ }
2810+
2811+ pte_mask = _PAGE_ACCESSED | _PAGE_USER | ((error_code & 2) << (_PAGE_BIT_DIRTY-1));
2812+
2813+ /*
2814+ * PaX: fill DTLB with user rights and retry
2815+ */
2816+ __asm__ __volatile__ (
2817+ "orb %2,%1\n"
2818+#if defined(CONFIG_M586) || defined(CONFIG_M586TSC)
2819+/*
2820+ * PaX: let this uncommented 'invlpg' remind us on the behaviour of Intel's
2821+ * (and AMD's) TLBs. namely, they do not cache PTEs that would raise *any*
2822+ * page fault when examined during a TLB load attempt. this is true not only
2823+ * for PTEs holding a non-present entry but also present entries that will
2824+ * raise a page fault (such as those set up by PaX, or the copy-on-write
2825+ * mechanism). in effect it means that we do *not* need to flush the TLBs
2826+ * for our target pages since their PTEs are simply not in the TLBs at all.
2827+
2828+ * the best thing in omitting it is that we gain around 15-20% speed in the
2829+ * fast path of the page fault handler and can get rid of tracing since we
2830+ * can no longer flush unintended entries.
2831+ */
2832+ "invlpg %0\n"
2833+#endif
2834+ "testb $0,%0\n"
2835+ "xorb %3,%1\n"
2836+ :
2837+ : "m" (*(char*)address), "m" (*(char*)pte), "q" (pte_mask), "i" (_PAGE_USER)
2838+ : "memory", "cc");
2839+ pte_unmap_unlock(pte, ptl);
2840+ up_read(&mm->mmap_sem);
2841+ return;
2842+
2843+not_pax_fault:
2844+#endif
2845+
2846 vma = find_vma(mm, address);
2847 if (!vma)
2848 goto bad_area;
2849@@ -387,6 +509,37 @@ bad_area:
2850 up_read(&mm->mmap_sem);
2851
2852 bad_area_nosemaphore:
2853+
2854+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
2855+ if (mm && (error_code & 4) && !(regs->eflags & X86_EFLAGS_VM)) {
2856+
2857+#ifdef CONFIG_PAX_PAGEEXEC
2858+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && !(error_code & 3) && (regs->eip == address)) {
2859+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
2860+ do_exit(SIGKILL);
2861+ }
2862+#endif
2863+
2864+#ifdef CONFIG_PAX_SEGMEXEC
2865+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && !(error_code & 3) && (regs->eip + SEGMEXEC_TASK_SIZE == address)) {
2866+
2867+ switch (pax_handle_fetch_fault(regs)) {
2868+
2869+#ifdef CONFIG_PAX_EMUTRAMP
2870+ case 2:
2871+ return;
2872+#endif
2873+
2874+ }
2875+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
2876+ do_exit(SIGKILL);
2877+ }
2878+#endif
2879+
2880+ }
2881+#endif
2882+
2883+bad_area_nopax:
2884 /* User mode accesses just cause a SIGSEGV */
2885 if (error_code & 4) {
2886 /*
2887@@ -450,28 +603,53 @@ no_context:
2888 #endif
2889 if (address < PAGE_SIZE)
2890 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
2891+
2892+#ifdef CONFIG_PAX_KERNEXEC
2893+#ifdef CONFIG_MODULES
2894+ else if (init_mm.start_code <= address && address < (unsigned long)MODULES_END)
2895+#else
2896+ else if (init_mm.start_code <= address && address < init_mm.end_code)
2897+#endif
2898+ if (tsk->signal->curr_ip)
2899+ printk(KERN_ERR "PAX: From %u.%u.%u.%u: %s:%d, uid/euid: %u/%u, attempted to modify kernel code",
2900+ NIPQUAD(tsk->signal->curr_ip), tsk->comm, tsk->pid, tsk->uid, tsk->euid);
2901+ else
2902+ printk(KERN_ERR "PAX: %s:%d, uid/euid: %u/%u, attempted to modify kernel code",
2903+ tsk->comm, tsk->pid, tsk->uid, tsk->euid);
2904+#endif
2905+
2906 else
2907 printk(KERN_ALERT "Unable to handle kernel paging request");
2908 printk(" at virtual address %08lx\n",address);
2909 printk(KERN_ALERT " printing eip:\n");
2910 printk("%08lx\n", regs->eip);
2911- page = read_cr3();
2912- page = ((unsigned long *) __va(page))[address >> 22];
2913- printk(KERN_ALERT "*pde = %08lx\n", page);
2914- /*
2915- * We must not directly access the pte in the highpte
2916- * case, the page table might be allocated in highmem.
2917- * And lets rather not kmap-atomic the pte, just in case
2918- * it's allocated already.
2919- */
2920+ {
2921+ unsigned long index = pgd_index(address);
2922+ pgd_t *pgd;
2923+ pud_t *pud;
2924+ pmd_t *pmd;
2925+ pte_t *pte;
2926+
2927+ pgd = index + (pgd_t *)__va(read_cr3());
2928+ printk(KERN_ALERT "*pgd = %*llx\n", sizeof(*pgd), (unsigned long long)pgd_val(*pgd));
2929+ if (pgd_present(*pgd)) {
2930+ pud = pud_offset(pgd, address);
2931+ pmd = pmd_offset(pud, address);
2932+ printk(KERN_ALERT "*pmd = %*llx\n", sizeof(*pmd), (unsigned long long)pmd_val(*pmd));
2933+ /*
2934+ * We must not directly access the pte in the highpte
2935+ * case, the page table might be allocated in highmem.
2936+ * And lets rather not kmap-atomic the pte, just in case
2937+ * it's allocated already.
2938+ */
2939 #ifndef CONFIG_HIGHPTE
2940- if (page & 1) {
2941- page &= PAGE_MASK;
2942- address &= 0x003ff000;
2943- page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
2944- printk(KERN_ALERT "*pte = %08lx\n", page);
2945- }
2946+ if (pmd_present(*pmd) && !pmd_large(*pmd)) {
2947+ pte = pte_offset_kernel(pmd, address);
2948+ printk(KERN_ALERT "*pte = %*llx\n", sizeof(*pte), (unsigned long long)pte_val(*pte));
2949+ }
2950 #endif
2951+ }
2952+ }
2953 tsk->thread.cr2 = address;
2954 tsk->thread.trap_no = 14;
2955 tsk->thread.error_code = error_code;
2956@@ -521,7 +699,7 @@ vmalloc_fault:
2957 * Do _not_ use "tsk" here. We might be inside
2958 * an interrupt in the middle of a task switch..
2959 */
2960- int index = pgd_index(address);
2961+ unsigned long index = pgd_index(address);
2962 unsigned long pgd_paddr;
2963 pgd_t *pgd, *pgd_k;
2964 pud_t *pud, *pud_k;
2965@@ -558,3 +736,105 @@ vmalloc_fault:
2966 return;
2967 }
2968 }
2969+
2970+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
2971+/*
2972+ * PaX: decide what to do with offenders (regs->eip = fault address)
2973+ *
2974+ * returns 1 when task should be killed
2975+ * 2 when gcc trampoline was detected
2976+ */
2977+static int pax_handle_fetch_fault(struct pt_regs *regs)
2978+{
2979+
2980+#ifdef CONFIG_PAX_EMUTRAMP
2981+ static const unsigned char trans[8] = {6, 1, 2, 0, 13, 5, 3, 4};
2982+ int err;
2983+#endif
2984+
2985+ if (regs->eflags & X86_EFLAGS_VM)
2986+ return 1;
2987+
2988+#ifdef CONFIG_PAX_EMUTRAMP
2989+ if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
2990+ return 1;
2991+
2992+ do { /* PaX: gcc trampoline emulation #1 */
2993+ unsigned char mov1, mov2;
2994+ unsigned short jmp;
2995+ unsigned long addr1, addr2;
2996+
2997+ err = get_user(mov1, (unsigned char __user *)regs->eip);
2998+ err |= get_user(addr1, (unsigned long __user *)(regs->eip + 1));
2999+ err |= get_user(mov2, (unsigned char __user *)(regs->eip + 5));
3000+ err |= get_user(addr2, (unsigned long __user *)(regs->eip + 6));
3001+ err |= get_user(jmp, (unsigned short __user *)(regs->eip + 10));
3002+
3003+ if (err)
3004+ break;
3005+
3006+ if ((mov1 & 0xF8) == 0xB8 &&
3007+ (mov2 & 0xF8) == 0xB8 &&
3008+ (mov1 & 0x07) != (mov2 & 0x07) &&
3009+ (jmp & 0xF8FF) == 0xE0FF &&
3010+ (mov2 & 0x07) == ((jmp>>8) & 0x07))
3011+ {
3012+ ((unsigned long *)regs)[trans[mov1 & 0x07]] = addr1;
3013+ ((unsigned long *)regs)[trans[mov2 & 0x07]] = addr2;
3014+ regs->eip = addr2;
3015+ return 2;
3016+ }
3017+ } while (0);
3018+
3019+ do { /* PaX: gcc trampoline emulation #2 */
3020+ unsigned char mov, jmp;
3021+ unsigned long addr1, addr2;
3022+
3023+ err = get_user(mov, (unsigned char __user *)regs->eip);
3024+ err |= get_user(addr1, (unsigned long __user *)(regs->eip + 1));
3025+ err |= get_user(jmp, (unsigned char __user *)(regs->eip + 5));
3026+ err |= get_user(addr2, (unsigned long __user *)(regs->eip + 6));
3027+
3028+ if (err)
3029+ break;
3030+
3031+ if ((mov & 0xF8) == 0xB8 &&
3032+ jmp == 0xE9)
3033+ {
3034+ ((unsigned long *)regs)[trans[mov & 0x07]] = addr1;
3035+ regs->eip += addr2 + 10;
3036+ return 2;
3037+ }
3038+ } while (0);
3039+#endif
3040+
3041+ return 1; /* PaX in action */
3042+}
3043+#endif
3044+
3045+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
3046+void pax_report_insns(void *pc, void *sp)
3047+{
3048+ long i;
3049+
3050+ printk(KERN_ERR "PAX: bytes at PC: ");
3051+ for (i = 0; i < 20; i++) {
3052+ unsigned char c;
3053+ if (get_user(c, (unsigned char __user *)pc+i))
3054+ printk("?? ");
3055+ else
3056+ printk("%02x ", c);
3057+ }
3058+ printk("\n");
3059+
3060+ printk(KERN_ERR "PAX: bytes at SP-4: ");
3061+ for (i = -1; i < 20; i++) {
3062+ unsigned long c;
3063+ if (get_user(c, (unsigned long __user *)sp+i))
3064+ printk("???????? ");
3065+ else
3066+ printk("%08lx ", c);
3067+ }
3068+ printk("\n");
3069+}
3070+#endif
3071diff -urNp linux-2.6.16.12/arch/i386/mm/hugetlbpage.c linux-2.6.16.12/arch/i386/mm/hugetlbpage.c
3072--- linux-2.6.16.12/arch/i386/mm/hugetlbpage.c 2006-05-01 15:14:26.000000000 -0400
3073+++ linux-2.6.16.12/arch/i386/mm/hugetlbpage.c 2006-05-01 20:17:33.000000000 -0400
3074@@ -133,7 +133,12 @@ static unsigned long hugetlb_get_unmappe
3075 {
3076 struct mm_struct *mm = current->mm;
3077 struct vm_area_struct *vma;
3078- unsigned long start_addr;
3079+ unsigned long start_addr, task_size = TASK_SIZE;
3080+
3081+#ifdef CONFIG_PAX_SEGMEXEC
3082+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
3083+ task_size = SEGMEXEC_TASK_SIZE;
3084+#endif
3085
3086 if (len > mm->cached_hole_size) {
3087 start_addr = mm->free_area_cache;
3088@@ -147,7 +152,7 @@ full_search:
3089
3090 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
3091 /* At this point: (!vma || addr < vma->vm_end). */
3092- if (TASK_SIZE - len < addr) {
3093+ if (task_size - len < addr) {
3094 /*
3095 * Start a new search - just in case we missed
3096 * some holes.
3097@@ -175,9 +180,8 @@ static unsigned long hugetlb_get_unmappe
3098 {
3099 struct mm_struct *mm = current->mm;
3100 struct vm_area_struct *vma, *prev_vma;
3101- unsigned long base = mm->mmap_base, addr = addr0;
3102+ unsigned long base = mm->mmap_base, addr;
3103 unsigned long largest_hole = mm->cached_hole_size;
3104- int first_time = 1;
3105
3106 /* don't allow allocations above current base */
3107 if (mm->free_area_cache > base)
3108@@ -187,7 +191,7 @@ static unsigned long hugetlb_get_unmappe
3109 largest_hole = 0;
3110 mm->free_area_cache = base;
3111 }
3112-try_again:
3113+
3114 /* make sure it can fit in the remaining address space */
3115 if (mm->free_area_cache < len)
3116 goto fail;
3117@@ -229,16 +233,6 @@ try_again:
3118
3119 fail:
3120 /*
3121- * if hint left us with no space for the requested
3122- * mapping then try again:
3123- */
3124- if (first_time) {
3125- mm->free_area_cache = base;
3126- largest_hole = 0;
3127- first_time = 0;
3128- goto try_again;
3129- }
3130- /*
3131 * A failed mmap() very likely causes application failure,
3132 * so fall back to the bottom-up function here. This scenario
3133 * can happen with large stack limits and large mmap()
3134@@ -264,16 +258,23 @@ hugetlb_get_unmapped_area(struct file *f
3135 {
3136 struct mm_struct *mm = current->mm;
3137 struct vm_area_struct *vma;
3138+ unsigned long task_size = TASK_SIZE;
3139
3140 if (len & ~HPAGE_MASK)
3141 return -EINVAL;
3142- if (len > TASK_SIZE)
3143+
3144+#ifdef CONFIG_PAX_SEGMEXEC
3145+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
3146+ task_size = SEGMEXEC_TASK_SIZE;
3147+#endif
3148+
3149+ if (len > task_size || addr > task_size - len)
3150 return -ENOMEM;
3151
3152 if (addr) {
3153 addr = ALIGN(addr, HPAGE_SIZE);
3154 vma = find_vma(mm, addr);
3155- if (TASK_SIZE - len >= addr &&
3156+ if (task_size - len >= addr &&
3157 (!vma || addr + len <= vma->vm_start))
3158 return addr;
3159 }
3160diff -urNp linux-2.6.16.12/arch/i386/mm/init.c linux-2.6.16.12/arch/i386/mm/init.c
3161--- linux-2.6.16.12/arch/i386/mm/init.c 2006-05-01 15:14:26.000000000 -0400
3162+++ linux-2.6.16.12/arch/i386/mm/init.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 3163@@ -42,6 +42,7 @@
89675291 3164 #include <asm/tlb.h>
3165 #include <asm/tlbflush.h>
3166 #include <asm/sections.h>
3167+#include <asm/desc.h>
3168
3169 unsigned int __VMALLOC_RESERVE = 128 << 20;
3170
9a4c6ab7 3171@@ -52,30 +53,6 @@ unsigned long highstart_pfn, highend_pfn
3172 int bad_ppro;
89675291 3173
3174 /*
3175- * Creates a middle page table and puts a pointer to it in the
3176- * given global directory entry. This only returns the gd entry
3177- * in non-PAE compilation mode, since the middle layer is folded.
3178- */
3179-static pmd_t * __init one_md_table_init(pgd_t *pgd)
3180-{
3181- pud_t *pud;
3182- pmd_t *pmd_table;
3183-
3184-#ifdef CONFIG_X86_PAE
3185- pmd_table = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
3186- set_pgd(pgd, __pgd(__pa(pmd_table) | _PAGE_PRESENT));
3187- pud = pud_offset(pgd, 0);
3188- if (pmd_table != pmd_offset(pud, 0))
3189- BUG();
3190-#else
3191- pud = pud_offset(pgd, 0);
3192- pmd_table = pmd_offset(pud, 0);
3193-#endif
3194-
3195- return pmd_table;
3196-}
3197-
3198-/*
3199 * Create a page table and place a pointer to it in a middle page
3200 * directory entry.
3201 */
9a4c6ab7 3202@@ -83,7 +60,11 @@ static pte_t * __init one_page_table_ini
89675291 3203 {
3204 if (pmd_none(*pmd)) {
3205 pte_t *page_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
3206+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
3207+ set_pmd(pmd, __pmd(__pa(page_table) | _KERNPG_TABLE));
3208+#else
3209 set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
3210+#endif
3211 if (page_table != pte_offset_kernel(pmd, 0))
3212 BUG();
3213
9a4c6ab7 3214@@ -118,8 +99,6 @@ static void __init page_table_range_init
89675291 3215 pgd = pgd_base + pgd_idx;
3216
3217 for ( ; (pgd_idx < PTRS_PER_PGD) && (vaddr != end); pgd++, pgd_idx++) {
3218- if (pgd_none(*pgd))
3219- one_md_table_init(pgd);
3220 pud = pud_offset(pgd, vaddr);
3221 pmd = pmd_offset(pud, vaddr);
3222 for (; (pmd_idx < PTRS_PER_PMD) && (vaddr != end); pmd++, pmd_idx++) {
9a4c6ab7 3223@@ -132,11 +111,22 @@ static void __init page_table_range_init
89675291 3224 }
3225 }
3226
3227-static inline int is_kernel_text(unsigned long addr)
3228+static inline int is_kernel_text(unsigned long start, unsigned long end)
3229 {
3230- if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end)
3231- return 1;
3232- return 0;
3233+ unsigned long etext;
3234+
3235+#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
3236+ etext = (unsigned long)&MODULES_END - __KERNEL_TEXT_OFFSET;
3237+#else
3238+ etext = (unsigned long)&_etext;
3239+#endif
3240+
3241+ if ((start > etext + __KERNEL_TEXT_OFFSET ||
3242+ end <= (unsigned long)_stext + __KERNEL_TEXT_OFFSET) &&
3243+ (start > (unsigned long)_einittext + __KERNEL_TEXT_OFFSET ||
3244+ end <= (unsigned long)_sinittext + __KERNEL_TEXT_OFFSET))
3245+ return 0;
3246+ return 1;
3247 }
3248
3249 /*
9a4c6ab7 3250@@ -148,26 +138,24 @@ static void __init kernel_physical_mappi
89675291 3251 {
3252 unsigned long pfn;
3253 pgd_t *pgd;
3254+ pud_t *pud;
3255 pmd_t *pmd;
3256 pte_t *pte;
3257- int pgd_idx, pmd_idx, pte_ofs;
3258+ unsigned int pgd_idx, pmd_idx, pte_ofs;
3259
3260 pgd_idx = pgd_index(PAGE_OFFSET);
3261 pgd = pgd_base + pgd_idx;
3262 pfn = 0;
3263
3264- for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
3265- pmd = one_md_table_init(pgd);
3266- if (pfn >= max_low_pfn)
3267- continue;
3268+ for (; pgd_idx < PTRS_PER_PGD && pfn < max_low_pfn; pgd++, pgd_idx++) {
3269+ pud = pud_offset(pgd, 0);
3270+ pmd = pmd_offset(pud, 0);
3271 for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD && pfn < max_low_pfn; pmd++, pmd_idx++) {
3272- unsigned int address = pfn * PAGE_SIZE + PAGE_OFFSET;
3273+ unsigned long address = pfn * PAGE_SIZE + PAGE_OFFSET;
3274
3275 /* Map with big pages if possible, otherwise create normal page tables. */
3276 if (cpu_has_pse) {
3277- unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
3278-
3279- if (is_kernel_text(address) || is_kernel_text(address2))
3280+ if (is_kernel_text(address, address + PMD_SIZE))
3281 set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE_EXEC));
3282 else
3283 set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
9a4c6ab7 3284@@ -176,7 +164,7 @@ static void __init kernel_physical_mappi
89675291 3285 pte = one_page_table_init(pmd);
3286
3287 for (pte_ofs = 0; pte_ofs < PTRS_PER_PTE && pfn < max_low_pfn; pte++, pfn++, pte_ofs++) {
3288- if (is_kernel_text(address))
3289+ if (is_kernel_text(address, address + PAGE_SIZE))
3290 set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
3291 else
3292 set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
9a4c6ab7 3293@@ -347,13 +335,6 @@ static void __init pagetable_init (void)
89675291 3294 unsigned long vaddr;
3295 pgd_t *pgd_base = swapper_pg_dir;
3296
3297-#ifdef CONFIG_X86_PAE
3298- int i;
3299- /* Init entries of the first-level page table to the zero page */
3300- for (i = 0; i < PTRS_PER_PGD; i++)
3301- set_pgd(pgd_base + i, __pgd(__pa(empty_zero_page) | _PAGE_PRESENT));
3302-#endif
3303-
3304 /* Enable PSE if available */
3305 if (cpu_has_pse) {
3306 set_in_cr4(X86_CR4_PSE);
9a4c6ab7 3307@@ -377,17 +358,6 @@ static void __init pagetable_init (void)
89675291 3308 page_table_range_init(vaddr, 0, pgd_base);
3309
3310 permanent_kmaps_init(pgd_base);
3311-
3312-#ifdef CONFIG_X86_PAE
3313- /*
3314- * Add low memory identity-mappings - SMP needs it when
3315- * starting up on an AP from real-mode. In the non-PAE
3316- * case we already have these mappings through head.S.
3317- * All user-space mappings are explicitly cleared after
3318- * SMP startup.
3319- */
3320- set_pgd(&pgd_base[0], pgd_base[USER_PTRS_PER_PGD]);
3321-#endif
3322 }
3323
9a4c6ab7 3324 #ifdef CONFIG_PM
3325@@ -429,7 +399,6 @@ void zap_low_mappings (void)
89675291 3326 flush_tlb_all();
3327 }
3328
3329-static int disable_nx __initdata = 0;
3330 u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
3331
3332 /*
9a4c6ab7 3333@@ -443,11 +412,9 @@ u64 __supported_pte_mask __read_mostly =
89675291 3334 void __init noexec_setup(const char *str)
3335 {
3336 if (!strncmp(str, "on",2) && cpu_has_nx) {
3337- __supported_pte_mask |= _PAGE_NX;
3338- disable_nx = 0;
3339+ nx_enabled = 1;
3340 } else if (!strncmp(str,"off",3)) {
3341- disable_nx = 1;
3342- __supported_pte_mask &= ~_PAGE_NX;
3343+ nx_enabled = 0;
3344 }
3345 }
3346
9a4c6ab7 3347@@ -456,17 +423,13 @@ int nx_enabled = 0;
89675291 3348
3349 static void __init set_nx(void)
3350 {
3351- unsigned int v[4], l, h;
3352+ if (!nx_enabled && cpu_has_nx) {
3353+ unsigned l, h;
3354
3355- if (cpu_has_pae && (cpuid_eax(0x80000000) > 0x80000001)) {
3356- cpuid(0x80000001, &v[0], &v[1], &v[2], &v[3]);
3357- if ((v[3] & (1 << 20)) && !disable_nx) {
3358- rdmsr(MSR_EFER, l, h);
3359- l |= EFER_NX;
3360- wrmsr(MSR_EFER, l, h);
3361- nx_enabled = 1;
3362- __supported_pte_mask |= _PAGE_NX;
3363- }
3364+ __supported_pte_mask &= ~_PAGE_NX;
3365+ rdmsr(MSR_EFER, l, h);
3366+ l &= ~EFER_NX;
3367+ wrmsr(MSR_EFER, l, h);
3368 }
3369 }
3370
9a4c6ab7 3371@@ -518,14 +481,6 @@ void __init paging_init(void)
89675291 3372
3373 load_cr3(swapper_pg_dir);
3374
3375-#ifdef CONFIG_X86_PAE
3376- /*
3377- * We will bail out later - printk doesn't work right now so
3378- * the user would just see a hanging kernel.
3379- */
3380- if (cpu_has_pae)
3381- set_in_cr4(X86_CR4_PAE);
3382-#endif
3383 __flush_tlb_all();
3384
3385 kmap_init();
9a4c6ab7 3386@@ -628,7 +583,7 @@ void __init mem_init(void)
89675291 3387 set_highmem_pages_init(bad_ppro);
3388
3389 codesize = (unsigned long) &_etext - (unsigned long) &_text;
3390- datasize = (unsigned long) &_edata - (unsigned long) &_etext;
3391+ datasize = (unsigned long) &_edata - (unsigned long) &_data;
3392 initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
3393
3394 kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
9a4c6ab7 3395@@ -645,10 +600,6 @@ void __init mem_init(void)
89675291 3396 (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
3397 );
3398
3399-#ifdef CONFIG_X86_PAE
3400- if (!cpu_has_pae)
3401- panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
3402-#endif
3403 if (boot_cpu_data.wp_works_ok < 0)
3404 test_wp_bit();
3405
9a4c6ab7 3406@@ -741,6 +692,36 @@ void free_initmem(void)
89675291 3407 {
3408 unsigned long addr;
3409
3410+#ifdef CONFIG_PAX_KERNEXEC
3411+ /* PaX: limit KERNEL_CS to actual size */
3412+ unsigned long limit;
3413+ int cpu;
3414+ pgd_t *pgd;
3415+ pud_t *pud;
3416+ pmd_t *pmd;
3417+
3418+#ifdef CONFIG_MODULES
3419+ limit = (unsigned long)&MODULES_END - __KERNEL_TEXT_OFFSET;
3420+#else
3421+ limit = (unsigned long)&_etext;
3422+#endif
3423+ limit = (limit - 1UL) >> PAGE_SHIFT;
3424+
3425+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
3426+ get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].a = (get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].a & 0xFFFF0000UL) | (limit & 0x0FFFFUL);
3427+ get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].b = (get_cpu_gdt_table(cpu)[GDT_ENTRY_KERNEL_CS].b & 0xFFF0FFFFUL) | (limit & 0xF0000UL);
3428+ }
3429+
3430+ /* PaX: make KERNEL_CS read-only */
3431+ for (addr = __KERNEL_TEXT_OFFSET; addr < (unsigned long)&_data; addr += PMD_SIZE) {
3432+ pgd = pgd_offset_k(addr);
3433+ pud = pud_offset(pgd, addr);
3434+ pmd = pmd_offset(pud, addr);
3435+ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW));
3436+ }
3437+ flush_tlb_all();
3438+#endif
3439+
3440 addr = (unsigned long)(&__init_begin);
3441 for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
3442 ClearPageReserved(virt_to_page(addr));
3443diff -urNp linux-2.6.16.12/arch/i386/mm/mmap.c linux-2.6.16.12/arch/i386/mm/mmap.c
3444--- linux-2.6.16.12/arch/i386/mm/mmap.c 2006-05-01 15:14:26.000000000 -0400
3445+++ linux-2.6.16.12/arch/i386/mm/mmap.c 2006-05-01 20:17:33.000000000 -0400
3446@@ -34,12 +34,18 @@
3447 * Leave an at least ~128 MB hole.
3448 */
3449 #define MIN_GAP (128*1024*1024)
3450-#define MAX_GAP (TASK_SIZE/6*5)
3451+#define MAX_GAP (task_size/6*5)
3452
3453 static inline unsigned long mmap_base(struct mm_struct *mm)
3454 {
3455 unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
3456 unsigned long random_factor = 0;
3457+ unsigned long task_size = TASK_SIZE;
3458+
3459+#ifdef CONFIG_PAX_SEGMEXEC
3460+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
3461+ task_size = SEGMEXEC_TASK_SIZE;
3462+#endif
3463
3464 if (current->flags & PF_RANDOMIZE)
3465 random_factor = get_random_int() % (1024*1024);
3466@@ -49,7 +55,7 @@ static inline unsigned long mmap_base(st
3467 else if (gap > MAX_GAP)
3468 gap = MAX_GAP;
3469
3470- return PAGE_ALIGN(TASK_SIZE - gap - random_factor);
3471+ return PAGE_ALIGN(task_size - gap - random_factor);
3472 }
3473
3474 /*
3475@@ -66,10 +72,22 @@ void arch_pick_mmap_layout(struct mm_str
3476 (current->personality & ADDR_COMPAT_LAYOUT) ||
3477 current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
3478 mm->mmap_base = TASK_UNMAPPED_BASE;
3479+
3480+#ifdef CONFIG_PAX_RANDMMAP
3481+ if (mm->pax_flags & MF_PAX_RANDMMAP)
3482+ mm->mmap_base += mm->delta_mmap;
3483+#endif
3484+
3485 mm->get_unmapped_area = arch_get_unmapped_area;
3486 mm->unmap_area = arch_unmap_area;
3487 } else {
3488 mm->mmap_base = mmap_base(mm);
3489+
3490+#ifdef CONFIG_PAX_RANDMMAP
3491+ if (mm->pax_flags & MF_PAX_RANDMMAP)
3492+ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
3493+#endif
3494+
3495 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
3496 mm->unmap_area = arch_unmap_area_topdown;
3497 }
3498diff -urNp linux-2.6.16.12/arch/i386/mm/pageattr.c linux-2.6.16.12/arch/i386/mm/pageattr.c
3499--- linux-2.6.16.12/arch/i386/mm/pageattr.c 2006-05-01 15:14:26.000000000 -0400
3500+++ linux-2.6.16.12/arch/i386/mm/pageattr.c 2006-05-01 20:17:33.000000000 -0400
3501@@ -14,6 +14,7 @@
3502 #include <asm/tlbflush.h>
3503 #include <asm/pgalloc.h>
3504 #include <asm/sections.h>
3505+#include <asm/desc.h>
3506
3507 static DEFINE_SPINLOCK(cpa_lock);
3508 static struct list_head df_list = LIST_HEAD_INIT(df_list);
3509@@ -77,7 +78,18 @@ static void set_pmd_pte(pte_t *kpte, uns
3510 struct page *page;
3511 unsigned long flags;
3512
3513+#ifdef CONFIG_PAX_KERNEXEC
3514+ unsigned long cr0;
3515+
3516+ pax_open_kernel(cr0);
3517+#endif
3518+
3519 set_pte_atomic(kpte, pte); /* change init_mm */
3520+
3521+#ifdef CONFIG_PAX_KERNEXEC
3522+ pax_close_kernel(cr0);
3523+#endif
3524+
3525 if (PTRS_PER_PMD > 1)
3526 return;
3527
3528@@ -104,7 +116,7 @@ static inline void revert_page(struct pa
3529 pte_t *linear;
3530
3531 ref_prot =
3532- ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
3533+ ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext + __KERNEL_TEXT_OFFSET)
3534 ? PAGE_KERNEL_LARGE_EXEC : PAGE_KERNEL_LARGE;
3535
3536 linear = (pte_t *)
3537@@ -136,7 +148,7 @@ __change_page_attr(struct page *page, pg
3538 struct page *split;
3539
3540 ref_prot =
3541- ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext)
3542+ ((address & LARGE_PAGE_MASK) < (unsigned long)&_etext + __KERNEL_TEXT_OFFSET)
3543 ? PAGE_KERNEL_EXEC : PAGE_KERNEL;
3544 split = split_large_page(address, prot, ref_prot);
3545 if (!split)
3546diff -urNp linux-2.6.16.12/arch/i386/oprofile/backtrace.c linux-2.6.16.12/arch/i386/oprofile/backtrace.c
3547--- linux-2.6.16.12/arch/i386/oprofile/backtrace.c 2006-05-01 15:14:26.000000000 -0400
3548+++ linux-2.6.16.12/arch/i386/oprofile/backtrace.c 2006-05-01 20:17:33.000000000 -0400
3549@@ -116,7 +116,7 @@ x86_backtrace(struct pt_regs * const reg
3550 head = (struct frame_head *)regs->ebp;
3551 #endif
3552
3553- if (!user_mode_vm(regs)) {
3554+ if (!user_mode(regs)) {
3555 while (depth-- && valid_kernel_stack(head, regs))
3556 head = dump_kernel_backtrace(head);
3557 return;
3558diff -urNp linux-2.6.16.12/arch/i386/power/cpu.c linux-2.6.16.12/arch/i386/power/cpu.c
3559--- linux-2.6.16.12/arch/i386/power/cpu.c 2006-05-01 15:14:26.000000000 -0400
3560+++ linux-2.6.16.12/arch/i386/power/cpu.c 2006-05-01 20:17:33.000000000 -0400
3561@@ -62,7 +62,7 @@ static void do_fpu_end(void)
3562 static void fix_processor_context(void)
3563 {
3564 int cpu = smp_processor_id();
3565- struct tss_struct * t = &per_cpu(init_tss, cpu);
3566+ struct tss_struct * t = init_tss + cpu;
3567
3568 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. */
3569
3570@@ -92,7 +92,7 @@ void __restore_processor_state(struct sa
3571 write_cr4(ctxt->cr4);
3572 write_cr3(ctxt->cr3);
3573 write_cr2(ctxt->cr2);
3574- write_cr2(ctxt->cr0);
3575+ write_cr0(ctxt->cr0);
3576
3577 /*
3578 * now restore the descriptor tables to their proper values
3579diff -urNp linux-2.6.16.12/arch/ia64/ia32/binfmt_elf32.c linux-2.6.16.12/arch/ia64/ia32/binfmt_elf32.c
3580--- linux-2.6.16.12/arch/ia64/ia32/binfmt_elf32.c 2006-05-01 15:14:26.000000000 -0400
3581+++ linux-2.6.16.12/arch/ia64/ia32/binfmt_elf32.c 2006-05-01 20:17:33.000000000 -0400
3582@@ -43,6 +43,17 @@ static void elf32_set_personality (void)
3583
3584 #define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack))
3585
3586+#ifdef CONFIG_PAX_ASLR
3587+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
3588+
3589+#define PAX_DELTA_MMAP_LSB(tsk) IA32_PAGE_SHIFT
3590+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - IA32_PAGE_SHIFT)
3591+#define PAX_DELTA_EXEC_LSB(tsk) IA32_PAGE_SHIFT
3592+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - IA32_PAGE_SHIFT)
3593+#define PAX_DELTA_STACK_LSB(tsk) IA32_PAGE_SHIFT
3594+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - IA32_PAGE_SHIFT)
3595+#endif
3596+
3597 /* Ugly but avoids duplication */
3598 #include "../../../fs/binfmt_elf.c"
3599
3600diff -urNp linux-2.6.16.12/arch/ia64/ia32/ia32priv.h linux-2.6.16.12/arch/ia64/ia32/ia32priv.h
3601--- linux-2.6.16.12/arch/ia64/ia32/ia32priv.h 2006-05-01 15:14:26.000000000 -0400
3602+++ linux-2.6.16.12/arch/ia64/ia32/ia32priv.h 2006-05-01 20:17:33.000000000 -0400
3603@@ -305,7 +305,14 @@ struct old_linux32_dirent {
3604 #define ELF_DATA ELFDATA2LSB
3605 #define ELF_ARCH EM_386
3606
3607-#define IA32_STACK_TOP IA32_PAGE_OFFSET
3608+#ifdef CONFIG_PAX_RANDUSTACK
3609+#define __IA32_DELTA_STACK (current->mm->delta_stack)
3610+#else
3611+#define __IA32_DELTA_STACK 0UL
3612+#endif
3613+
3614+#define IA32_STACK_TOP (IA32_PAGE_OFFSET - __IA32_DELTA_STACK)
3615+
3616 #define IA32_GATE_OFFSET IA32_PAGE_OFFSET
3617 #define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE
3618
3619diff -urNp linux-2.6.16.12/arch/ia64/kernel/module.c linux-2.6.16.12/arch/ia64/kernel/module.c
3620--- linux-2.6.16.12/arch/ia64/kernel/module.c 2006-05-01 15:14:26.000000000 -0400
3621+++ linux-2.6.16.12/arch/ia64/kernel/module.c 2006-05-01 20:17:33.000000000 -0400
3622@@ -322,7 +322,7 @@ module_alloc (unsigned long size)
3623 void
3624 module_free (struct module *mod, void *module_region)
3625 {
3626- if (mod->arch.init_unw_table && module_region == mod->module_init) {
3627+ if (mod->arch.init_unw_table && module_region == mod->module_init_rx) {
3628 unw_remove_unwind_table(mod->arch.init_unw_table);
3629 mod->arch.init_unw_table = NULL;
3630 }
3631@@ -500,15 +500,39 @@ module_frob_arch_sections (Elf_Ehdr *ehd
3632 }
3633
3634 static inline int
3635+in_init_rx (const struct module *mod, uint64_t addr)
3636+{
3637+ return addr - (uint64_t) mod->module_init_rx < mod->init_size_rx;
3638+}
3639+
3640+static inline int
3641+in_init_rw (const struct module *mod, uint64_t addr)
3642+{
3643+ return addr - (uint64_t) mod->module_init_rw < mod->init_size_rw;
3644+}
3645+
3646+static inline int
3647 in_init (const struct module *mod, uint64_t addr)
3648 {
3649- return addr - (uint64_t) mod->module_init < mod->init_size;
3650+ return in_init_rx(mod, value) || in_init_rw(mod, value);
3651+}
3652+
3653+static inline int
3654+in_core_rx (const struct module *mod, uint64_t addr)
3655+{
3656+ return addr - (uint64_t) mod->module_core_rx < mod->core_size_rx;
3657+}
3658+
3659+static inline int
3660+in_core_rw (const struct module *mod, uint64_t addr)
3661+{
3662+ return addr - (uint64_t) mod->module_core_rw < mod->core_size_rw;
3663 }
3664
3665 static inline int
3666 in_core (const struct module *mod, uint64_t addr)
3667 {
3668- return addr - (uint64_t) mod->module_core < mod->core_size;
3669+ return in_core_rx(mod, value) || in_core_rw(mod, value);
3670 }
3671
3672 static inline int
3673@@ -692,7 +716,14 @@ do_reloc (struct module *mod, uint8_t r_
3674 break;
3675
3676 case RV_BDREL:
3677- val -= (uint64_t) (in_init(mod, val) ? mod->module_init : mod->module_core);
3678+ if (in_init_rx(mod, val))
3679+ val -= (uint64_t) mod->module_init_rx;
3680+ else if (in_init_rw(mod, val))
3681+ val -= (uint64_t) mod->module_init_rw;
3682+ else if (in_core_rx(mod, val))
3683+ val -= (uint64_t) mod->module_core_rx;
3684+ else if (in_core_rw(mod, val))
3685+ val -= (uint64_t) mod->module_core_rw;
3686 break;
3687
3688 case RV_LTV:
3689@@ -826,15 +857,15 @@ apply_relocate_add (Elf64_Shdr *sechdrs,
3690 * addresses have been selected...
3691 */
3692 uint64_t gp;
3693- if (mod->core_size > MAX_LTOFF)
3694+ if (mod->core_size_rx + mod->core_size_rw > MAX_LTOFF)
3695 /*
3696 * This takes advantage of fact that SHF_ARCH_SMALL gets allocated
3697 * at the end of the module.
3698 */
3699- gp = mod->core_size - MAX_LTOFF / 2;
3700+ gp = mod->core_size_rx + mod->core_size_rw - MAX_LTOFF / 2;
3701 else
3702- gp = mod->core_size / 2;
3703- gp = (uint64_t) mod->module_core + ((gp + 7) & -8);
3704+ gp = (mod->core_size_rx + mod->core_size_rw) / 2;
3705+ gp = (uint64_t) mod->module_core_rx + ((gp + 7) & -8);
3706 mod->arch.gp = gp;
3707 DEBUGP("%s: placing gp at 0x%lx\n", __FUNCTION__, gp);
3708 }
3709diff -urNp linux-2.6.16.12/arch/ia64/kernel/ptrace.c linux-2.6.16.12/arch/ia64/kernel/ptrace.c
3710--- linux-2.6.16.12/arch/ia64/kernel/ptrace.c 2006-05-01 15:14:26.000000000 -0400
3711+++ linux-2.6.16.12/arch/ia64/kernel/ptrace.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 3712@@ -19,6 +19,7 @@
89675291 3713 #include <linux/audit.h>
3714 #include <linux/signal.h>
9a4c6ab7 3715 #include <linux/vs_pid.h>
89675291 3716+#include <linux/grsecurity.h>
3717
3718 #include <asm/pgtable.h>
3719 #include <asm/processor.h>
9a4c6ab7 3720@@ -1451,6 +1452,9 @@ sys_ptrace (long request, pid_t pid, uns
89675291 3721 if (pid == 1) /* no messing around with init! */
3722 goto out_tsk;
3723
3724+ if (gr_handle_ptrace(child, request))
3725+ goto out_tsk;
3726+
3727 if (request == PTRACE_ATTACH) {
3728 ret = ptrace_attach(child);
3729 goto out_tsk;
3730diff -urNp linux-2.6.16.12/arch/ia64/kernel/sys_ia64.c linux-2.6.16.12/arch/ia64/kernel/sys_ia64.c
3731--- linux-2.6.16.12/arch/ia64/kernel/sys_ia64.c 2006-05-01 15:14:26.000000000 -0400
3732+++ linux-2.6.16.12/arch/ia64/kernel/sys_ia64.c 2006-05-01 20:17:33.000000000 -0400
3733@@ -38,6 +38,13 @@ arch_get_unmapped_area (struct file *fil
3734 if (REGION_NUMBER(addr) == RGN_HPAGE)
3735 addr = 0;
3736 #endif
3737+
3738+#ifdef CONFIG_PAX_RANDMMAP
3739+ if ((mm->pax_flags & MF_PAX_RANDMMAP) && addr && filp)
3740+ addr = mm->free_area_cache;
3741+ else
3742+#endif
3743+
3744 if (!addr)
3745 addr = mm->free_area_cache;
3746
3747@@ -56,9 +63,9 @@ arch_get_unmapped_area (struct file *fil
3748 for (vma = find_vma(mm, addr); ; vma = vma->vm_next) {
3749 /* At this point: (!vma || addr < vma->vm_end). */
3750 if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) {
3751- if (start_addr != TASK_UNMAPPED_BASE) {
3752+ if (start_addr != mm->mmap_base) {
3753 /* Start a new search --- just in case we missed some holes. */
3754- addr = TASK_UNMAPPED_BASE;
3755+ addr = mm->mmap_base;
3756 goto full_search;
3757 }
3758 return -ENOMEM;
3759diff -urNp linux-2.6.16.12/arch/ia64/mm/fault.c linux-2.6.16.12/arch/ia64/mm/fault.c
3760--- linux-2.6.16.12/arch/ia64/mm/fault.c 2006-05-01 15:14:26.000000000 -0400
3761+++ linux-2.6.16.12/arch/ia64/mm/fault.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 3762@@ -11,6 +11,7 @@
89675291 3763 #include <linux/interrupt.h>
3764 #include <linux/kprobes.h>
9a4c6ab7 3765 #include <linux/vs_memory.h>
89675291 3766+#include <linux/binfmts.h>
3767
3768 #include <asm/pgtable.h>
3769 #include <asm/processor.h>
9a4c6ab7 3770@@ -52,6 +53,23 @@ mapped_kernel_page_is_present (unsigned
89675291 3771 return pte_present(pte);
3772 }
3773
3774+#ifdef CONFIG_PAX_PAGEEXEC
3775+void pax_report_insns(void *pc, void *sp)
3776+{
3777+ unsigned long i;
3778+
3779+ printk(KERN_ERR "PAX: bytes at PC: ");
3780+ for (i = 0; i < 8; i++) {
3781+ unsigned int c;
3782+ if (get_user(c, (unsigned int*)pc+i))
3783+ printk("???????? ");
3784+ else
3785+ printk("%08x ", c);
3786+ }
3787+ printk("\n");
3788+}
3789+#endif
3790+
3791 void __kprobes
3792 ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
3793 {
9a4c6ab7 3794@@ -114,9 +132,23 @@ ia64_do_page_fault (unsigned long addres
89675291 3795 | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)
3796 | (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_BIT));
3797
3798- if ((vma->vm_flags & mask) != mask)
3799+ if ((vma->vm_flags & mask) != mask) {
3800+
3801+#ifdef CONFIG_PAX_PAGEEXEC
3802+ if (!(vma->vm_flags & VM_EXEC) && (mask & VM_EXEC)) {
3803+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->cr_iip)
3804+ goto bad_area;
3805+
3806+ up_read(&mm->mmap_sem);
3807+ pax_report_fault(regs, (void*)regs->cr_iip, (void*)regs->r12);
3808+ do_exit(SIGKILL);
3809+ }
3810+#endif
3811+
3812 goto bad_area;
3813
3814+ }
3815+
3816 survive:
3817 /*
3818 * If for any reason at all we couldn't handle the fault, make
3819diff -urNp linux-2.6.16.12/arch/ia64/mm/init.c linux-2.6.16.12/arch/ia64/mm/init.c
3820--- linux-2.6.16.12/arch/ia64/mm/init.c 2006-05-01 15:14:26.000000000 -0400
3821+++ linux-2.6.16.12/arch/ia64/mm/init.c 2006-05-01 20:17:33.000000000 -0400
3822@@ -20,8 +20,8 @@
3823 #include <linux/swap.h>
3824 #include <linux/proc_fs.h>
3825 #include <linux/bitops.h>
3826+#include <linux/a.out.h>
3827
3828-#include <asm/a.out.h>
3829 #include <asm/dma.h>
3830 #include <asm/ia32.h>
3831 #include <asm/io.h>
3832diff -urNp linux-2.6.16.12/arch/mips/kernel/binfmt_elfn32.c linux-2.6.16.12/arch/mips/kernel/binfmt_elfn32.c
3833--- linux-2.6.16.12/arch/mips/kernel/binfmt_elfn32.c 2006-05-01 15:14:26.000000000 -0400
3834+++ linux-2.6.16.12/arch/mips/kernel/binfmt_elfn32.c 2006-05-01 20:17:33.000000000 -0400
3835@@ -50,6 +50,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
3836 #undef ELF_ET_DYN_BASE
3837 #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
3838
3839+#ifdef CONFIG_PAX_ASLR
3840+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
3841+
3842+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
3843+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
3844+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
3845+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
3846+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
3847+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
3848+#endif
3849+
3850 #include <asm/processor.h>
3851 #include <linux/module.h>
3852 #include <linux/elfcore.h>
3853diff -urNp linux-2.6.16.12/arch/mips/kernel/binfmt_elfo32.c linux-2.6.16.12/arch/mips/kernel/binfmt_elfo32.c
3854--- linux-2.6.16.12/arch/mips/kernel/binfmt_elfo32.c 2006-05-01 15:14:26.000000000 -0400
3855+++ linux-2.6.16.12/arch/mips/kernel/binfmt_elfo32.c 2006-05-01 20:17:33.000000000 -0400
3856@@ -52,6 +52,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
3857 #undef ELF_ET_DYN_BASE
3858 #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2)
3859
3860+#ifdef CONFIG_PAX_ASLR
3861+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
3862+
3863+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
3864+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
3865+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
3866+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
3867+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
3868+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
3869+#endif
3870+
3871 #include <asm/processor.h>
3872 #include <linux/module.h>
3873 #include <linux/elfcore.h>
3874diff -urNp linux-2.6.16.12/arch/mips/kernel/syscall.c linux-2.6.16.12/arch/mips/kernel/syscall.c
3875--- linux-2.6.16.12/arch/mips/kernel/syscall.c 2006-05-01 15:14:26.000000000 -0400
3876+++ linux-2.6.16.12/arch/mips/kernel/syscall.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 3877@@ -90,6 +90,11 @@ unsigned long arch_get_unmapped_area(str
89675291 3878 do_color_align = 0;
3879 if (filp || (flags & MAP_SHARED))
3880 do_color_align = 1;
3881+
3882+#ifdef CONFIG_PAX_RANDMMAP
3883+ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
3884+#endif
3885+
3886 if (addr) {
3887 if (do_color_align)
3888 addr = COLOUR_ALIGN(addr, pgoff);
9a4c6ab7 3889@@ -100,7 +105,7 @@ unsigned long arch_get_unmapped_area(str
89675291 3890 (!vmm || addr + len <= vmm->vm_start))
3891 return addr;
3892 }
3893- addr = TASK_UNMAPPED_BASE;
3894+ addr = current->mm->mmap_base;
3895 if (do_color_align)
3896 addr = COLOUR_ALIGN(addr, pgoff);
3897 else
3898diff -urNp linux-2.6.16.12/arch/mips/mm/fault.c linux-2.6.16.12/arch/mips/mm/fault.c
3899--- linux-2.6.16.12/arch/mips/mm/fault.c 2006-05-01 15:14:26.000000000 -0400
3900+++ linux-2.6.16.12/arch/mips/mm/fault.c 2006-05-01 20:17:33.000000000 -0400
3901@@ -27,6 +27,23 @@
3902 #include <asm/ptrace.h>
3903 #include <asm/highmem.h> /* For VMALLOC_END */
3904
3905+#ifdef CONFIG_PAX_PAGEEXEC
3906+void pax_report_insns(void *pc)
3907+{
3908+ unsigned long i;
3909+
3910+ printk(KERN_ERR "PAX: bytes at PC: ");
3911+ for (i = 0; i < 5; i++) {
3912+ unsigned int c;
3913+ if (get_user(c, (unsigned int*)pc+i))
3914+ printk("???????? ");
3915+ else
3916+ printk("%08x ", c);
3917+ }
3918+ printk("\n");
3919+}
3920+#endif
3921+
3922 /*
3923 * This routine handles page faults. It determines the address,
3924 * and the problem, and then passes it off to one of the appropriate
3925diff -urNp linux-2.6.16.12/arch/parisc/kernel/module.c linux-2.6.16.12/arch/parisc/kernel/module.c
3926--- linux-2.6.16.12/arch/parisc/kernel/module.c 2006-05-01 15:14:26.000000000 -0400
3927+++ linux-2.6.16.12/arch/parisc/kernel/module.c 2006-05-01 20:17:33.000000000 -0400
3928@@ -72,16 +72,38 @@
3929
3930 /* three functions to determine where in the module core
3931 * or init pieces the location is */
3932+static inline int is_init_rx(struct module *me, void *loc)
3933+{
3934+ return (loc >= me->module_init_rx &&
3935+ loc < (me->module_init_rx + me->init_size_rx));
3936+}
3937+
3938+static inline int is_init_rw(struct module *me, void *loc)
3939+{
3940+ return (loc >= me->module_init_rw &&
3941+ loc < (me->module_init_rw + me->init_size_rw));
3942+}
3943+
3944 static inline int is_init(struct module *me, void *loc)
3945 {
3946- return (loc >= me->module_init &&
3947- loc <= (me->module_init + me->init_size));
3948+ return is_init_rx(me, loc) || is_init_rw(me, loc);
3949+}
3950+
3951+static inline int is_core_rx(struct module *me, void *loc)
3952+{
3953+ return (loc >= me->module_core_rx &&
3954+ loc < (me->module_core_rx + me->core_size_rx));
3955+}
3956+
3957+static inline int is_core_rw(struct module *me, void *loc)
3958+{
3959+ return (loc >= me->module_core_rw &&
3960+ loc < (me->module_core_rw + me->core_size_rw));
3961 }
3962
3963 static inline int is_core(struct module *me, void *loc)
3964 {
3965- return (loc >= me->module_core &&
3966- loc <= (me->module_core + me->core_size));
3967+ return is_core_rx(me, loc) || is_core_rw(me, loc);
3968 }
3969
3970 static inline int is_local(struct module *me, void *loc)
3971@@ -289,21 +311,21 @@ int module_frob_arch_sections(CONST Elf_
3972 }
3973
3974 /* align things a bit */
3975- me->core_size = ALIGN(me->core_size, 16);
3976- me->arch.got_offset = me->core_size;
3977- me->core_size += gots * sizeof(struct got_entry);
3978-
3979- me->core_size = ALIGN(me->core_size, 16);
3980- me->arch.fdesc_offset = me->core_size;
3981- me->core_size += fdescs * sizeof(Elf_Fdesc);
3982-
3983- me->core_size = ALIGN(me->core_size, 16);
3984- me->arch.stub_offset = me->core_size;
3985- me->core_size += stubs * sizeof(struct stub_entry);
3986-
3987- me->init_size = ALIGN(me->init_size, 16);
3988- me->arch.init_stub_offset = me->init_size;
3989- me->init_size += init_stubs * sizeof(struct stub_entry);
3990+ me->core_size_rw = ALIGN(me->core_size_rw, 16);
3991+ me->arch.got_offset = me->core_size_rw;
3992+ me->core_size_rw += gots * sizeof(struct got_entry);
3993+
3994+ me->core_size_rw = ALIGN(me->core_size_rw, 16);
3995+ me->arch.fdesc_offset = me->core_size_rw;
3996+ me->core_size_rw += fdescs * sizeof(Elf_Fdesc);
3997+
3998+ me->core_size_rx = ALIGN(me->core_size_rx, 16);
3999+ me->arch.stub_offset = me->core_size_rx;
4000+ me->core_size_rx += stubs * sizeof(struct stub_entry);
4001+
4002+ me->init_size_rx = ALIGN(me->init_size_rx, 16);
4003+ me->arch.init_stub_offset = me->init_size_rx;
4004+ me->init_size_rx += init_stubs * sizeof(struct stub_entry);
4005
4006 me->arch.got_max = gots;
4007 me->arch.fdesc_max = fdescs;
4008@@ -323,7 +345,7 @@ static Elf64_Word get_got(struct module
4009
4010 BUG_ON(value == 0);
4011
4012- got = me->module_core + me->arch.got_offset;
4013+ got = me->module_core_rw + me->arch.got_offset;
4014 for (i = 0; got[i].addr; i++)
4015 if (got[i].addr == value)
4016 goto out;
4017@@ -341,7 +363,7 @@ static Elf64_Word get_got(struct module
4018 #ifdef __LP64__
4019 static Elf_Addr get_fdesc(struct module *me, unsigned long value)
4020 {
4021- Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
4022+ Elf_Fdesc *fdesc = me->module_core_rw + me->arch.fdesc_offset;
4023
4024 if (!value) {
4025 printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
4026@@ -359,7 +381,7 @@ static Elf_Addr get_fdesc(struct module
4027
4028 /* Create new one */
4029 fdesc->addr = value;
4030- fdesc->gp = (Elf_Addr)me->module_core + me->arch.got_offset;
4031+ fdesc->gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset;
4032 return (Elf_Addr)fdesc;
4033 }
4034 #endif /* __LP64__ */
4035@@ -373,12 +395,12 @@ static Elf_Addr get_stub(struct module *
4036 if(init_section) {
4037 i = me->arch.init_stub_count++;
4038 BUG_ON(me->arch.init_stub_count > me->arch.init_stub_max);
4039- stub = me->module_init + me->arch.init_stub_offset +
4040+ stub = me->module_init_rx + me->arch.init_stub_offset +
4041 i * sizeof(struct stub_entry);
4042 } else {
4043 i = me->arch.stub_count++;
4044 BUG_ON(me->arch.stub_count > me->arch.stub_max);
4045- stub = me->module_core + me->arch.stub_offset +
4046+ stub = me->module_core_rx + me->arch.stub_offset +
4047 i * sizeof(struct stub_entry);
4048 }
4049
4050@@ -721,7 +743,7 @@ register_unwind_table(struct module *me,
4051
4052 table = (unsigned char *)sechdrs[me->arch.unwind_section].sh_addr;
4053 end = table + sechdrs[me->arch.unwind_section].sh_size;
4054- gp = (Elf_Addr)me->module_core + me->arch.got_offset;
4055+ gp = (Elf_Addr)me->module_core_rw + me->arch.got_offset;
4056
4057 DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
4058 me->arch.unwind_section, table, end, gp);
4059diff -urNp linux-2.6.16.12/arch/parisc/kernel/ptrace.c linux-2.6.16.12/arch/parisc/kernel/ptrace.c
4060--- linux-2.6.16.12/arch/parisc/kernel/ptrace.c 2006-05-01 15:14:26.000000000 -0400
4061+++ linux-2.6.16.12/arch/parisc/kernel/ptrace.c 2006-05-01 20:17:33.000000000 -0400
4062@@ -18,6 +18,7 @@
4063 #include <linux/security.h>
4064 #include <linux/compat.h>
4065 #include <linux/signal.h>
4066+#include <linux/grsecurity.h>
4067
4068 #include <asm/uaccess.h>
4069 #include <asm/pgtable.h>
4070diff -urNp linux-2.6.16.12/arch/parisc/kernel/sys_parisc.c linux-2.6.16.12/arch/parisc/kernel/sys_parisc.c
4071--- linux-2.6.16.12/arch/parisc/kernel/sys_parisc.c 2006-05-01 15:14:26.000000000 -0400
4072+++ linux-2.6.16.12/arch/parisc/kernel/sys_parisc.c 2006-05-01 20:17:33.000000000 -0400
4073@@ -105,7 +105,7 @@ unsigned long arch_get_unmapped_area(str
4074 if (len > TASK_SIZE)
4075 return -ENOMEM;
4076 if (!addr)
4077- addr = TASK_UNMAPPED_BASE;
4078+ addr = current->mm->mmap_base;
4079
4080 if (filp) {
4081 addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
4082diff -urNp linux-2.6.16.12/arch/parisc/kernel/traps.c linux-2.6.16.12/arch/parisc/kernel/traps.c
4083--- linux-2.6.16.12/arch/parisc/kernel/traps.c 2006-05-01 15:14:26.000000000 -0400
4084+++ linux-2.6.16.12/arch/parisc/kernel/traps.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 4085@@ -712,9 +712,7 @@ void handle_interruption(int code, struc
89675291 4086
4087 down_read(&current->mm->mmap_sem);
4088 vma = find_vma(current->mm,regs->iaoq[0]);
4089- if (vma && (regs->iaoq[0] >= vma->vm_start)
4090- && (vma->vm_flags & VM_EXEC)) {
4091-
4092+ if (vma && (regs->iaoq[0] >= vma->vm_start)) {
4093 fault_address = regs->iaoq[0];
4094 fault_space = regs->iasq[0];
4095
4096diff -urNp linux-2.6.16.12/arch/parisc/mm/fault.c linux-2.6.16.12/arch/parisc/mm/fault.c
4097--- linux-2.6.16.12/arch/parisc/mm/fault.c 2006-05-01 15:14:26.000000000 -0400
4098+++ linux-2.6.16.12/arch/parisc/mm/fault.c 2006-05-01 20:17:33.000000000 -0400
4099@@ -16,6 +16,8 @@
4100 #include <linux/sched.h>
4101 #include <linux/interrupt.h>
4102 #include <linux/module.h>
4103+#include <linux/unistd.h>
4104+#include <linux/binfmts.h>
4105
4106 #include <asm/uaccess.h>
4107 #include <asm/traps.h>
4108@@ -57,7 +59,7 @@ DEFINE_PER_CPU(struct exception_data, ex
4109 static unsigned long
4110 parisc_acctyp(unsigned long code, unsigned int inst)
4111 {
4112- if (code == 6 || code == 16)
4113+ if (code == 6 || code == 7 || code == 16)
4114 return VM_EXEC;
4115
4116 switch (inst & 0xf0000000) {
4117@@ -143,6 +145,116 @@ parisc_acctyp(unsigned long code, unsign
4118 }
4119 #endif
4120
4121+#ifdef CONFIG_PAX_PAGEEXEC
4122+/*
4123+ * PaX: decide what to do with offenders (instruction_pointer(regs) = fault address)
4124+ *
4125+ * returns 1 when task should be killed
4126+ * 2 when rt_sigreturn trampoline was detected
4127+ * 3 when unpatched PLT trampoline was detected
4128+ */
4129+static int pax_handle_fetch_fault(struct pt_regs *regs)
4130+{
4131+
4132+#ifdef CONFIG_PAX_EMUPLT
4133+ int err;
4134+
4135+ do { /* PaX: unpatched PLT emulation */
4136+ unsigned int bl, depwi;
4137+
4138+ err = get_user(bl, (unsigned int*)instruction_pointer(regs));
4139+ err |= get_user(depwi, (unsigned int*)(instruction_pointer(regs)+4));
4140+
4141+ if (err)
4142+ break;
4143+
4144+ if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) {
4145+ unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12;
4146+
4147+ err = get_user(ldw, (unsigned int*)addr);
4148+ err |= get_user(bv, (unsigned int*)(addr+4));
4149+ err |= get_user(ldw2, (unsigned int*)(addr+8));
4150+
4151+ if (err)
4152+ break;
4153+
4154+ if (ldw == 0x0E801096U &&
4155+ bv == 0xEAC0C000U &&
4156+ ldw2 == 0x0E881095U)
4157+ {
4158+ unsigned int resolver, map;
4159+
4160+ err = get_user(resolver, (unsigned int*)(instruction_pointer(regs)+8));
4161+ err |= get_user(map, (unsigned int*)(instruction_pointer(regs)+12));
4162+ if (err)
4163+ break;
4164+
4165+ regs->gr[20] = instruction_pointer(regs)+8;
4166+ regs->gr[21] = map;
4167+ regs->gr[22] = resolver;
4168+ regs->iaoq[0] = resolver | 3UL;
4169+ regs->iaoq[1] = regs->iaoq[0] + 4;
4170+ return 3;
4171+ }
4172+ }
4173+ } while (0);
4174+#endif
4175+
4176+#ifdef CONFIG_PAX_EMUTRAMP
4177+
4178+#ifndef CONFIG_PAX_EMUSIGRT
4179+ if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
4180+ return 1;
4181+#endif
4182+
4183+ do { /* PaX: rt_sigreturn emulation */
4184+ unsigned int ldi1, ldi2, bel, nop;
4185+
4186+ err = get_user(ldi1, (unsigned int *)instruction_pointer(regs));
4187+ err |= get_user(ldi2, (unsigned int *)(instruction_pointer(regs)+4));
4188+ err |= get_user(bel, (unsigned int *)(instruction_pointer(regs)+8));
4189+ err |= get_user(nop, (unsigned int *)(instruction_pointer(regs)+12));
4190+
4191+ if (err)
4192+ break;
4193+
4194+ if ((ldi1 == 0x34190000U || ldi1 == 0x34190002U) &&
4195+ ldi2 == 0x3414015AU &&
4196+ bel == 0xE4008200U &&
4197+ nop == 0x08000240U)
4198+ {
4199+ regs->gr[25] = (ldi1 & 2) >> 1;
4200+ regs->gr[20] = __NR_rt_sigreturn;
4201+ regs->gr[31] = regs->iaoq[1] + 16;
4202+ regs->sr[0] = regs->iasq[1];
4203+ regs->iaoq[0] = 0x100UL;
4204+ regs->iaoq[1] = regs->iaoq[0] + 4;
4205+ regs->iasq[0] = regs->sr[2];
4206+ regs->iasq[1] = regs->sr[2];
4207+ return 2;
4208+ }
4209+ } while (0);
4210+#endif
4211+
4212+ return 1;
4213+}
4214+
4215+void pax_report_insns(void *pc, void *sp)
4216+{
4217+ unsigned long i;
4218+
4219+ printk(KERN_ERR "PAX: bytes at PC: ");
4220+ for (i = 0; i < 5; i++) {
4221+ unsigned int c;
4222+ if (get_user(c, (unsigned int*)pc+i))
4223+ printk("???????? ");
4224+ else
4225+ printk("%08x ", c);
4226+ }
4227+ printk("\n");
4228+}
4229+#endif
4230+
4231 void do_page_fault(struct pt_regs *regs, unsigned long code,
4232 unsigned long address)
4233 {
4234@@ -168,8 +280,33 @@ good_area:
4235
4236 acc_type = parisc_acctyp(code,regs->iir);
4237
4238- if ((vma->vm_flags & acc_type) != acc_type)
4239+ if ((vma->vm_flags & acc_type) != acc_type) {
4240+
4241+#ifdef CONFIG_PAX_PAGEEXEC
4242+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (acc_type & VM_EXEC) &&
4243+ (address & ~3UL) == instruction_pointer(regs))
4244+ {
4245+ up_read(&mm->mmap_sem);
4246+ switch(pax_handle_fetch_fault(regs)) {
4247+
4248+#ifdef CONFIG_PAX_EMUPLT
4249+ case 3:
4250+ return;
4251+#endif
4252+
4253+#ifdef CONFIG_PAX_EMUTRAMP
4254+ case 2:
4255+ return;
4256+#endif
4257+
4258+ }
4259+ pax_report_fault(regs, (void*)instruction_pointer(regs), (void*)regs->gr[30]);
4260+ do_exit(SIGKILL);
4261+ }
4262+#endif
4263+
4264 goto bad_area;
4265+ }
4266
4267 /*
4268 * If for any reason at all we couldn't handle the fault, make
4269diff -urNp linux-2.6.16.12/arch/powerpc/mm/fault.c linux-2.6.16.12/arch/powerpc/mm/fault.c
4270--- linux-2.6.16.12/arch/powerpc/mm/fault.c 2006-05-01 15:14:26.000000000 -0400
4271+++ linux-2.6.16.12/arch/powerpc/mm/fault.c 2006-05-01 20:17:33.000000000 -0400
4272@@ -31,6 +31,7 @@
4273 #include <linux/highmem.h>
4274 #include <linux/module.h>
4275 #include <linux/kprobes.h>
4276+#include <linux/binfmts.h>
4277
4278 #include <asm/page.h>
4279 #include <asm/pgtable.h>
4280@@ -105,6 +106,38 @@ static void do_dabr(struct pt_regs *regs
4281 }
4282 #endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
4283
4284+#ifdef CONFIG_PAX_PAGEEXEC
4285+/*
4286+ * PaX: decide what to do with offenders (regs->nip = fault address)
4287+ *
4288+ * returns 1 when task should be killed
4289+ */
4290+static int pax_handle_fetch_fault(struct pt_regs *regs)
4291+{
4292+
4293+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT)
4294+ int err;
4295+#endif
4296+
4297+ return 1;
4298+}
4299+
4300+void pax_report_insns(void *pc, void *sp)
4301+{
4302+ unsigned long i;
4303+
4304+ printk(KERN_ERR "PAX: bytes at PC: ");
4305+ for (i = 0; i < 5; i++) {
4306+ unsigned int c;
4307+ if (get_user(c, (unsigned int*)pc+i))
4308+ printk("???????? ");
4309+ else
4310+ printk("%08x ", c);
4311+ }
4312+ printk("\n");
4313+}
4314+#endif
4315+
4316 /*
4317 * For 600- and 800-family processors, the error_code parameter is DSISR
4318 * for a data fault, SRR1 for an instruction fault. For 400-family processors
4319@@ -333,6 +366,19 @@ bad_area:
4320 bad_area_nosemaphore:
4321 /* User mode accesses cause a SIGSEGV */
4322 if (user_mode(regs)) {
4323+
4324+#ifdef CONFIG_PAX_PAGEEXEC
4325+ if (mm->pax_flags & MF_PAX_PAGEEXEC) {
4326+ if (is_exec && (error_code & DSISR_PROTFAULT)) {
4327+ switch (pax_handle_fetch_fault(regs)) {
4328+ }
4329+
4330+ pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]);
4331+ do_exit(SIGKILL);
4332+ }
4333+ }
4334+#endif
4335+
4336 _exception(SIGSEGV, regs, code, address);
4337 return 0;
4338 }
4339diff -urNp linux-2.6.16.12/arch/powerpc/mm/mmap.c linux-2.6.16.12/arch/powerpc/mm/mmap.c
4340--- linux-2.6.16.12/arch/powerpc/mm/mmap.c 2006-05-01 15:14:26.000000000 -0400
4341+++ linux-2.6.16.12/arch/powerpc/mm/mmap.c 2006-05-01 20:17:33.000000000 -0400
4342@@ -76,10 +76,22 @@ void arch_pick_mmap_layout(struct mm_str
4343 */
4344 if (mmap_is_legacy()) {
4345 mm->mmap_base = TASK_UNMAPPED_BASE;
4346+
4347+#ifdef CONFIG_PAX_RANDMMAP
4348+ if (mm->pax_flags & MF_PAX_RANDMMAP)
4349+ mm->mmap_base += mm->delta_mmap;
4350+#endif
4351+
4352 mm->get_unmapped_area = arch_get_unmapped_area;
4353 mm->unmap_area = arch_unmap_area;
4354 } else {
4355 mm->mmap_base = mmap_base();
4356+
4357+#ifdef CONFIG_PAX_RANDMMAP
4358+ if (mm->pax_flags & MF_PAX_RANDMMAP)
4359+ mm->mmap_base -= mm->delta_mmap;
4360+#endif
4361+
4362 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
4363 mm->unmap_area = arch_unmap_area_topdown;
4364 }
4365diff -urNp linux-2.6.16.12/arch/ppc/kernel/module.c linux-2.6.16.12/arch/ppc/kernel/module.c
4366--- linux-2.6.16.12/arch/ppc/kernel/module.c 2006-05-01 15:14:26.000000000 -0400
4367+++ linux-2.6.16.12/arch/ppc/kernel/module.c 2006-05-01 20:17:33.000000000 -0400
4368@@ -164,8 +164,8 @@ static uint32_t do_plt_call(void *locati
4369
4370 DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location);
4371 /* Init, or core PLT? */
4372- if (location >= mod->module_core
4373- && location < mod->module_core + mod->core_size)
4374+ if (location >= mod->module_core_rx
4375+ && location < mod->module_core_rx + mod->core_size_rx)
4376 entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
4377 else
4378 entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
4379diff -urNp linux-2.6.16.12/arch/ppc/mm/fault.c linux-2.6.16.12/arch/ppc/mm/fault.c
4380--- linux-2.6.16.12/arch/ppc/mm/fault.c 2006-05-01 15:14:26.000000000 -0400
4381+++ linux-2.6.16.12/arch/ppc/mm/fault.c 2006-05-01 20:17:33.000000000 -0400
4382@@ -28,6 +28,11 @@
4383 #include <linux/interrupt.h>
4384 #include <linux/highmem.h>
4385 #include <linux/module.h>
4386+#include <linux/slab.h>
4387+#include <linux/pagemap.h>
4388+#include <linux/compiler.h>
4389+#include <linux/binfmts.h>
4390+#include <linux/unistd.h>
4391
4392 #include <asm/page.h>
4393 #include <asm/pgtable.h>
4394@@ -51,6 +56,364 @@ unsigned long pte_misses; /* updated by
4395 unsigned long pte_errors; /* updated by do_page_fault() */
4396 unsigned int probingmem;
4397
4398+#ifdef CONFIG_PAX_EMUSIGRT
4399+void pax_syscall_close(struct vm_area_struct * vma)
4400+{
4401+ vma->vm_mm->call_syscall = 0UL;
4402+}
4403+
4404+static struct page* pax_syscall_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
4405+{
4406+ struct page* page;
4407+ unsigned int *kaddr;
4408+
4409+ page = alloc_page(GFP_HIGHUSER);
4410+ if (!page)
4411+ return NOPAGE_OOM;
4412+
4413+ kaddr = kmap(page);
4414+ memset(kaddr, 0, PAGE_SIZE);
4415+ kaddr[0] = 0x44000002U; /* sc */
4416+ __flush_dcache_icache(kaddr);
4417+ kunmap(page);
4418+ if (type)
4419+ *type = VM_FAULT_MAJOR;
4420+ return page;
4421+}
4422+
4423+static struct vm_operations_struct pax_vm_ops = {
4424+ .close = pax_syscall_close,
4425+ .nopage = pax_syscall_nopage,
4426+};
4427+
4428+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
4429+{
4430+ int ret;
4431+
4432+ memset(vma, 0, sizeof(*vma));
4433+ vma->vm_mm = current->mm;
4434+ vma->vm_start = addr;
4435+ vma->vm_end = addr + PAGE_SIZE;
4436+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
4437+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
4438+ vma->vm_ops = &pax_vm_ops;
4439+
4440+ ret = insert_vm_struct(current->mm, vma);
4441+ if (ret)
4442+ return ret;
4443+
4444+ ++current->mm->total_vm;
4445+ return 0;
4446+}
4447+#endif
4448+
4449+#ifdef CONFIG_PAX_PAGEEXEC
4450+/*
4451+ * PaX: decide what to do with offenders (regs->nip = fault address)
4452+ *
4453+ * returns 1 when task should be killed
4454+ * 2 when patched GOT trampoline was detected
4455+ * 3 when patched PLT trampoline was detected
4456+ * 4 when unpatched PLT trampoline was detected
4457+ * 5 when sigreturn trampoline was detected
4458+ * 7 when rt_sigreturn trampoline was detected
4459+ */
4460+static int pax_handle_fetch_fault(struct pt_regs *regs)
4461+{
4462+
4463+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT)
4464+ int err;
4465+#endif
4466+
4467+#ifdef CONFIG_PAX_EMUPLT
4468+ do { /* PaX: patched GOT emulation */
4469+ unsigned int blrl;
4470+
4471+ err = get_user(blrl, (unsigned int*)regs->nip);
4472+
4473+ if (!err && blrl == 0x4E800021U) {
4474+ unsigned long temp = regs->nip;
4475+
4476+ regs->nip = regs->link & 0xFFFFFFFCUL;
4477+ regs->link = temp + 4UL;
4478+ return 2;
4479+ }
4480+ } while (0);
4481+
4482+ do { /* PaX: patched PLT emulation #1 */
4483+ unsigned int b;
4484+
4485+ err = get_user(b, (unsigned int *)regs->nip);
4486+
4487+ if (!err && (b & 0xFC000003U) == 0x48000000U) {
4488+ regs->nip += (((b | 0xFC000000UL) ^ 0x02000000UL) + 0x02000000UL);
4489+ return 3;
4490+ }
4491+ } while (0);
4492+
4493+ do { /* PaX: unpatched PLT emulation #1 */
4494+ unsigned int li, b;
4495+
4496+ err = get_user(li, (unsigned int *)regs->nip);
4497+ err |= get_user(b, (unsigned int *)(regs->nip+4));
4498+
4499+ if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) {
4500+ unsigned int rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr;
4501+ unsigned long addr = b | 0xFC000000UL;
4502+
4503+ addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL);
4504+ err = get_user(rlwinm, (unsigned int*)addr);
4505+ err |= get_user(add, (unsigned int*)(addr+4));
4506+ err |= get_user(li2, (unsigned int*)(addr+8));
4507+ err |= get_user(addis2, (unsigned int*)(addr+12));
4508+ err |= get_user(mtctr, (unsigned int*)(addr+16));
4509+ err |= get_user(li3, (unsigned int*)(addr+20));
4510+ err |= get_user(addis3, (unsigned int*)(addr+24));
4511+ err |= get_user(bctr, (unsigned int*)(addr+28));
4512+
4513+ if (err)
4514+ break;
4515+
4516+ if (rlwinm == 0x556C083CU &&
4517+ add == 0x7D6C5A14U &&
4518+ (li2 & 0xFFFF0000U) == 0x39800000U &&
4519+ (addis2 & 0xFFFF0000U) == 0x3D8C0000U &&
4520+ mtctr == 0x7D8903A6U &&
4521+ (li3 & 0xFFFF0000U) == 0x39800000U &&
4522+ (addis3 & 0xFFFF0000U) == 0x3D8C0000U &&
4523+ bctr == 0x4E800420U)
4524+ {
4525+ regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
4526+ regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
4527+ regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16;
4528+ regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
4529+ regs->ctr += (addis2 & 0xFFFFU) << 16;
4530+ regs->nip = regs->ctr;
4531+ return 4;
4532+ }
4533+ }
4534+ } while (0);
4535+
4536+#if 0
4537+ do { /* PaX: unpatched PLT emulation #2 */
4538+ unsigned int lis, lwzu, b, bctr;
4539+
4540+ err = get_user(lis, (unsigned int *)regs->nip);
4541+ err |= get_user(lwzu, (unsigned int *)(regs->nip+4));
4542+ err |= get_user(b, (unsigned int *)(regs->nip+8));
4543+ err |= get_user(bctr, (unsigned int *)(regs->nip+12));
4544+
4545+ if (err)
4546+ break;
4547+
4548+ if ((lis & 0xFFFF0000U) == 0x39600000U &&
4549+ (lwzu & 0xU) == 0xU &&
4550+ (b & 0xFC000003U) == 0x48000000U &&
4551+ bctr == 0x4E800420U)
4552+ {
4553+ unsigned int addis, addi, rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr;
4554+ unsigned long addr = b | 0xFC000000UL;
4555+
4556+ addr = regs->nip + 12 + ((addr ^ 0x02000000UL) + 0x02000000UL);
4557+ err = get_user(addis, (unsigned int*)addr);
4558+ err |= get_user(addi, (unsigned int*)(addr+4));
4559+ err |= get_user(rlwinm, (unsigned int*)(addr+8));
4560+ err |= get_user(add, (unsigned int*)(addr+12));
4561+ err |= get_user(li2, (unsigned int*)(addr+16));
4562+ err |= get_user(addis2, (unsigned int*)(addr+20));
4563+ err |= get_user(mtctr, (unsigned int*)(addr+24));
4564+ err |= get_user(li3, (unsigned int*)(addr+28));
4565+ err |= get_user(addis3, (unsigned int*)(addr+32));
4566+ err |= get_user(bctr, (unsigned int*)(addr+36));
4567+
4568+ if (err)
4569+ break;
4570+
4571+ if ((addis & 0xFFFF0000U) == 0x3D6B0000U &&
4572+ (addi & 0xFFFF0000U) == 0x396B0000U &&
4573+ rlwinm == 0x556C083CU &&
4574+ add == 0x7D6C5A14U &&
4575+ (li2 & 0xFFFF0000U) == 0x39800000U &&
4576+ (addis2 & 0xFFFF0000U) == 0x3D8C0000U &&
4577+ mtctr == 0x7D8903A6U &&
4578+ (li3 & 0xFFFF0000U) == 0x39800000U &&
4579+ (addis3 & 0xFFFF0000U) == 0x3D8C0000U &&
4580+ bctr == 0x4E800420U)
4581+ {
4582+ regs->gpr[PT_R11] =
4583+ regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
4584+ regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
4585+ regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16;
4586+ regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
4587+ regs->ctr += (addis2 & 0xFFFFU) << 16;
4588+ regs->nip = regs->ctr;
4589+ return 4;
4590+ }
4591+ }
4592+ } while (0);
4593+#endif
4594+
4595+ do { /* PaX: unpatched PLT emulation #3 */
4596+ unsigned int li, b;
4597+
4598+ err = get_user(li, (unsigned int *)regs->nip);
4599+ err |= get_user(b, (unsigned int *)(regs->nip+4));
4600+
4601+ if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) {
4602+ unsigned int addis, lwz, mtctr, bctr;
4603+ unsigned long addr = b | 0xFC000000UL;
4604+
4605+ addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL);
4606+ err = get_user(addis, (unsigned int*)addr);
4607+ err |= get_user(lwz, (unsigned int*)(addr+4));
4608+ err |= get_user(mtctr, (unsigned int*)(addr+8));
4609+ err |= get_user(bctr, (unsigned int*)(addr+12));
4610+
4611+ if (err)
4612+ break;
4613+
4614+ if ((addis & 0xFFFF0000U) == 0x3D6B0000U &&
4615+ (lwz & 0xFFFF0000U) == 0x816B0000U &&
4616+ mtctr == 0x7D6903A6U &&
4617+ bctr == 0x4E800420U)
4618+ {
4619+ unsigned int r11;
4620+
4621+ addr = (addis << 16) + (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
4622+ addr += (((lwz | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
4623+
4624+ err = get_user(r11, (unsigned int*)addr);
4625+ if (err)
4626+ break;
4627+
4628+ regs->gpr[PT_R11] = r11;
4629+ regs->ctr = r11;
4630+ regs->nip = r11;
4631+ return 4;
4632+ }
4633+ }
4634+ } while (0);
4635+#endif
4636+
4637+#ifdef CONFIG_PAX_EMUSIGRT
4638+ do { /* PaX: sigreturn emulation */
4639+ unsigned int li, sc;
4640+
4641+ err = get_user(li, (unsigned int *)regs->nip);
4642+ err |= get_user(sc, (unsigned int *)(regs->nip+4));
4643+
4644+ if (!err && li == 0x38000000U + __NR_sigreturn && sc == 0x44000002U) {
4645+ struct vm_area_struct *vma;
4646+ unsigned long call_syscall;
4647+
4648+ down_read(&current->mm->mmap_sem);
4649+ call_syscall = current->mm->call_syscall;
4650+ up_read(&current->mm->mmap_sem);
4651+ if (likely(call_syscall))
4652+ goto emulate;
4653+
4654+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
4655+
4656+ down_write(&current->mm->mmap_sem);
4657+ if (current->mm->call_syscall) {
4658+ call_syscall = current->mm->call_syscall;
4659+ up_write(&current->mm->mmap_sem);
4660+ if (vma) kmem_cache_free(vm_area_cachep, vma);
4661+ goto emulate;
4662+ }
4663+
4664+ call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
4665+ if (!vma || (call_syscall & ~PAGE_MASK)) {
4666+ up_write(&current->mm->mmap_sem);
4667+ if (vma) kmem_cache_free(vm_area_cachep, vma);
4668+ return 1;
4669+ }
4670+
4671+ if (pax_insert_vma(vma, call_syscall)) {
4672+ up_write(&current->mm->mmap_sem);
4673+ kmem_cache_free(vm_area_cachep, vma);
4674+ return 1;
4675+ }
4676+
4677+ current->mm->call_syscall = call_syscall;
4678+ up_write(&current->mm->mmap_sem);
4679+
4680+emulate:
4681+ regs->gpr[PT_R0] = __NR_sigreturn;
4682+ regs->nip = call_syscall;
4683+ return 5;
4684+ }
4685+ } while (0);
4686+
4687+ do { /* PaX: rt_sigreturn emulation */
4688+ unsigned int li, sc;
4689+
4690+ err = get_user(li, (unsigned int *)regs->nip);
4691+ err |= get_user(sc, (unsigned int *)(regs->nip+4));
4692+
4693+ if (!err && li == 0x38000000U + __NR_rt_sigreturn && sc == 0x44000002U) {
4694+ struct vm_area_struct *vma;
4695+ unsigned int call_syscall;
4696+
4697+ down_read(&current->mm->mmap_sem);
4698+ call_syscall = current->mm->call_syscall;
4699+ up_read(&current->mm->mmap_sem);
4700+ if (likely(call_syscall))
4701+ goto rt_emulate;
4702+
4703+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
4704+
4705+ down_write(&current->mm->mmap_sem);
4706+ if (current->mm->call_syscall) {
4707+ call_syscall = current->mm->call_syscall;
4708+ up_write(&current->mm->mmap_sem);
4709+ if (vma) kmem_cache_free(vm_area_cachep, vma);
4710+ goto rt_emulate;
4711+ }
4712+
4713+ call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
4714+ if (!vma || (call_syscall & ~PAGE_MASK)) {
4715+ up_write(&current->mm->mmap_sem);
4716+ if (vma) kmem_cache_free(vm_area_cachep, vma);
4717+ return 1;
4718+ }
4719+
4720+ if (pax_insert_vma(vma, call_syscall)) {
4721+ up_write(&current->mm->mmap_sem);
4722+ kmem_cache_free(vm_area_cachep, vma);
4723+ return 1;
4724+ }
4725+
4726+ current->mm->call_syscall = call_syscall;
4727+ up_write(&current->mm->mmap_sem);
4728+
4729+rt_emulate:
4730+ regs->gpr[PT_R0] = __NR_rt_sigreturn;
4731+ regs->nip = call_syscall;
4732+ return 6;
4733+ }
4734+ } while (0);
4735+#endif
4736+
4737+ return 1;
4738+}
4739+
4740+void pax_report_insns(void *pc, void *sp)
4741+{
4742+ unsigned long i;
4743+
4744+ printk(KERN_ERR "PAX: bytes at PC: ");
4745+ for (i = 0; i < 5; i++) {
4746+ unsigned int c;
4747+ if (get_user(c, (unsigned int*)pc+i))
4748+ printk("???????? ");
4749+ else
4750+ printk("%08x ", c);
4751+ }
4752+ printk("\n");
4753+}
4754+#endif
4755+
4756 /*
4757 * Check whether the instruction at regs->nip is a store using
4758 * an update addressing form which will update r1.
4759@@ -111,7 +474,7 @@ int do_page_fault(struct pt_regs *regs,
4760 * indicate errors in DSISR but can validly be set in SRR1.
4761 */
4762 if (TRAP(regs) == 0x400)
4763- error_code &= 0x48200000;
4764+ error_code &= 0x58200000;
4765 else
4766 is_write = error_code & 0x02000000;
4767 #endif /* CONFIG_4xx || CONFIG_BOOKE */
4768@@ -205,15 +568,14 @@ good_area:
4769 } else if (TRAP(regs) == 0x400) {
4770 pte_t *ptep;
4771
4772-#if 0
4773+#if 1
4774 /* It would be nice to actually enforce the VM execute
4775 permission on CPUs which can do so, but far too
4776 much stuff in userspace doesn't get the permissions
4777 right, so we let any page be executed for now. */
4778 if (! (vma->vm_flags & VM_EXEC))
4779 goto bad_area;
4780-#endif
4781-
4782+#else
4783 /* Since 4xx/Book-E supports per-page execute permission,
4784 * we lazily flush dcache to icache. */
4785 ptep = NULL;
4786@@ -233,6 +595,7 @@ good_area:
4787 if (ptep != NULL)
4788 pte_unmap(ptep);
4789 #endif
4790+#endif
4791 /* a read */
4792 } else {
4793 /* protection fault */
4794@@ -278,6 +641,33 @@ bad_area:
4795
4796 /* User mode accesses cause a SIGSEGV */
4797 if (user_mode(regs)) {
4798+
4799+#ifdef CONFIG_PAX_PAGEEXEC
4800+ if (mm->pax_flags & MF_PAX_PAGEEXEC) {
4801+ if ((TRAP(regs) == 0x400) && (regs->nip == address)) {
4802+ switch (pax_handle_fetch_fault(regs)) {
4803+
4804+#ifdef CONFIG_PAX_EMUPLT
4805+ case 2:
4806+ case 3:
4807+ case 4:
4808+ return 0;
4809+#endif
4810+
4811+#ifdef CONFIG_PAX_EMUSIGRT
4812+ case 5:
4813+ case 6:
4814+ return 0;
4815+#endif
4816+
4817+ }
4818+
4819+ pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]);
4820+ do_exit(SIGKILL);
4821+ }
4822+ }
4823+#endif
4824+
4825 _exception(SIGSEGV, regs, code, address);
4826 return 0;
4827 }
4828diff -urNp linux-2.6.16.12/arch/s390/kernel/module.c linux-2.6.16.12/arch/s390/kernel/module.c
4829--- linux-2.6.16.12/arch/s390/kernel/module.c 2006-05-01 15:14:26.000000000 -0400
4830+++ linux-2.6.16.12/arch/s390/kernel/module.c 2006-05-01 20:17:33.000000000 -0400
4831@@ -164,11 +164,11 @@ module_frob_arch_sections(Elf_Ehdr *hdr,
4832
4833 /* Increase core size by size of got & plt and set start
4834 offsets for got and plt. */
4835- me->core_size = ALIGN(me->core_size, 4);
4836- me->arch.got_offset = me->core_size;
4837- me->core_size += me->arch.got_size;
4838- me->arch.plt_offset = me->core_size;
4839- me->core_size += me->arch.plt_size;
4840+ me->core_size_rw = ALIGN(me->core_size_rw, 4);
4841+ me->arch.got_offset = me->core_size_rw;
4842+ me->core_size_rw += me->arch.got_size;
4843+ me->arch.plt_offset = me->core_size_rx;
4844+ me->core_size_rx += me->arch.plt_size;
4845 return 0;
4846 }
4847
4848@@ -254,7 +254,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
4849 if (info->got_initialized == 0) {
4850 Elf_Addr *gotent;
4851
4852- gotent = me->module_core + me->arch.got_offset +
4853+ gotent = me->module_core_rw + me->arch.got_offset +
4854 info->got_offset;
4855 *gotent = val;
4856 info->got_initialized = 1;
4857@@ -278,7 +278,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
4858 else if (r_type == R_390_GOTENT ||
4859 r_type == R_390_GOTPLTENT)
4860 *(unsigned int *) loc =
4861- (val + (Elf_Addr) me->module_core - loc) >> 1;
4862+ (val + (Elf_Addr) me->module_core_rw - loc) >> 1;
4863 else if (r_type == R_390_GOT64 ||
4864 r_type == R_390_GOTPLT64)
4865 *(unsigned long *) loc = val;
4866@@ -292,7 +292,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
4867 case R_390_PLTOFF64: /* 16 bit offset from GOT to PLT. */
4868 if (info->plt_initialized == 0) {
4869 unsigned int *ip;
4870- ip = me->module_core + me->arch.plt_offset +
4871+ ip = me->module_core_rx + me->arch.plt_offset +
4872 info->plt_offset;
4873 #ifndef CONFIG_64BIT
4874 ip[0] = 0x0d105810; /* basr 1,0; l 1,6(1); br 1 */
4875@@ -314,7 +314,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
4876 val = me->arch.plt_offset - me->arch.got_offset +
4877 info->plt_offset + rela->r_addend;
4878 else
4879- val = (Elf_Addr) me->module_core +
4880+ val = (Elf_Addr) me->module_core_rx +
4881 me->arch.plt_offset + info->plt_offset +
4882 rela->r_addend - loc;
4883 if (r_type == R_390_PLT16DBL)
4884@@ -334,7 +334,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
4885 case R_390_GOTOFF32: /* 32 bit offset to GOT. */
4886 case R_390_GOTOFF64: /* 64 bit offset to GOT. */
4887 val = val + rela->r_addend -
4888- ((Elf_Addr) me->module_core + me->arch.got_offset);
4889+ ((Elf_Addr) me->module_core_rw + me->arch.got_offset);
4890 if (r_type == R_390_GOTOFF16)
4891 *(unsigned short *) loc = val;
4892 else if (r_type == R_390_GOTOFF32)
4893@@ -344,7 +344,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
4894 break;
4895 case R_390_GOTPC: /* 32 bit PC relative offset to GOT. */
4896 case R_390_GOTPCDBL: /* 32 bit PC rel. off. to GOT shifted by 1. */
4897- val = (Elf_Addr) me->module_core + me->arch.got_offset +
4898+ val = (Elf_Addr) me->module_core_rw + me->arch.got_offset +
4899 rela->r_addend - loc;
4900 if (r_type == R_390_GOTPC)
4901 *(unsigned int *) loc = val;
4902diff -urNp linux-2.6.16.12/arch/sparc/kernel/ptrace.c linux-2.6.16.12/arch/sparc/kernel/ptrace.c
4903--- linux-2.6.16.12/arch/sparc/kernel/ptrace.c 2006-05-01 15:14:26.000000000 -0400
4904+++ linux-2.6.16.12/arch/sparc/kernel/ptrace.c 2006-05-01 20:17:33.000000000 -0400
4905@@ -19,6 +19,7 @@
4906 #include <linux/smp_lock.h>
4907 #include <linux/security.h>
4908 #include <linux/signal.h>
4909+#include <linux/grsecurity.h>
4910
4911 #include <asm/pgtable.h>
4912 #include <asm/system.h>
9a4c6ab7 4913@@ -304,6 +305,11 @@ asmlinkage void do_ptrace(struct pt_regs
4914 goto out_tsk;
89675291 4915 }
4916
4917+ if (gr_handle_ptrace(child, request)) {
4918+ pt_error_return(regs, EPERM);
4919+ goto out_tsk;
4920+ }
4921+
4922 if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
4923 || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
4924 if (ptrace_attach(child)) {
4925diff -urNp linux-2.6.16.12/arch/sparc/kernel/sys_sparc.c linux-2.6.16.12/arch/sparc/kernel/sys_sparc.c
4926--- linux-2.6.16.12/arch/sparc/kernel/sys_sparc.c 2006-05-01 15:14:26.000000000 -0400
4927+++ linux-2.6.16.12/arch/sparc/kernel/sys_sparc.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 4928@@ -57,7 +57,7 @@ unsigned long arch_get_unmapped_area(str
89675291 4929 if (ARCH_SUN4C_SUN4 && len > 0x20000000)
4930 return -ENOMEM;
4931 if (!addr)
4932- addr = TASK_UNMAPPED_BASE;
4933+ addr = current->mm->mmap_base;
4934
4935 if (flags & MAP_SHARED)
4936 addr = COLOUR_ALIGN(addr);
4937diff -urNp linux-2.6.16.12/arch/sparc/Makefile linux-2.6.16.12/arch/sparc/Makefile
4938--- linux-2.6.16.12/arch/sparc/Makefile 2006-05-01 15:14:26.000000000 -0400
4939+++ linux-2.6.16.12/arch/sparc/Makefile 2006-05-01 20:17:33.000000000 -0400
4940@@ -34,7 +34,7 @@ libs-y += arch/sparc/prom/ arch/sparc/li
4941 # Renaming is done to avoid confusing pattern matching rules in 2.5.45 (multy-)
4942 INIT_Y := $(patsubst %/, %/built-in.o, $(init-y))
4943 CORE_Y := $(core-y)
4944-CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
4945+CORE_Y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
4946 CORE_Y := $(patsubst %/, %/built-in.o, $(CORE_Y))
4947 DRIVERS_Y := $(patsubst %/, %/built-in.o, $(drivers-y))
4948 NET_Y := $(patsubst %/, %/built-in.o, $(net-y))
4949diff -urNp linux-2.6.16.12/arch/sparc/mm/fault.c linux-2.6.16.12/arch/sparc/mm/fault.c
4950--- linux-2.6.16.12/arch/sparc/mm/fault.c 2006-05-01 15:14:26.000000000 -0400
4951+++ linux-2.6.16.12/arch/sparc/mm/fault.c 2006-05-01 20:17:33.000000000 -0400
4952@@ -21,6 +21,10 @@
4953 #include <linux/smp_lock.h>
4954 #include <linux/interrupt.h>
4955 #include <linux/module.h>
4956+#include <linux/slab.h>
4957+#include <linux/pagemap.h>
4958+#include <linux/compiler.h>
4959+#include <linux/binfmts.h>
4960
4961 #include <asm/system.h>
4962 #include <asm/page.h>
4963@@ -217,6 +221,252 @@ static unsigned long compute_si_addr(str
4964 return safe_compute_effective_address(regs, insn);
4965 }
4966
4967+#ifdef CONFIG_PAX_PAGEEXEC
4968+void pax_emuplt_close(struct vm_area_struct * vma)
4969+{
4970+ vma->vm_mm->call_dl_resolve = 0UL;
4971+}
4972+
4973+static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
4974+{
4975+ struct page* page;
4976+ unsigned int *kaddr;
4977+
4978+ page = alloc_page(GFP_HIGHUSER);
4979+ if (!page)
4980+ return NOPAGE_OOM;
4981+
4982+ kaddr = kmap(page);
4983+ memset(kaddr, 0, PAGE_SIZE);
4984+ kaddr[0] = 0x9DE3BFA8U; /* save */
4985+ flush_dcache_page(page);
4986+ kunmap(page);
4987+ if (type)
4988+ *type = VM_FAULT_MAJOR;
4989+
4990+ return page;
4991+}
4992+
4993+static struct vm_operations_struct pax_vm_ops = {
4994+ .close = pax_emuplt_close,
4995+ .nopage = pax_emuplt_nopage,
4996+};
4997+
4998+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
4999+{
5000+ int ret;
5001+
5002+ memset(vma, 0, sizeof(*vma));
5003+ vma->vm_mm = current->mm;
5004+ vma->vm_start = addr;
5005+ vma->vm_end = addr + PAGE_SIZE;
5006+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
5007+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
5008+ vma->vm_ops = &pax_vm_ops;
5009+
5010+ ret = insert_vm_struct(current->mm, vma);
5011+ if (ret)
5012+ return ret;
5013+
5014+ ++current->mm->total_vm;
5015+ return 0;
5016+}
5017+
5018+/*
5019+ * PaX: decide what to do with offenders (regs->pc = fault address)
5020+ *
5021+ * returns 1 when task should be killed
5022+ * 2 when patched PLT trampoline was detected
5023+ * 3 when unpatched PLT trampoline was detected
5024+ */
5025+static int pax_handle_fetch_fault(struct pt_regs *regs)
5026+{
5027+
5028+#ifdef CONFIG_PAX_EMUPLT
5029+ int err;
5030+
5031+ do { /* PaX: patched PLT emulation #1 */
5032+ unsigned int sethi1, sethi2, jmpl;
5033+
5034+ err = get_user(sethi1, (unsigned int*)regs->pc);
5035+ err |= get_user(sethi2, (unsigned int*)(regs->pc+4));
5036+ err |= get_user(jmpl, (unsigned int*)(regs->pc+8));
5037+
5038+ if (err)
5039+ break;
5040+
5041+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
5042+ (sethi2 & 0xFFC00000U) == 0x03000000U &&
5043+ (jmpl & 0xFFFFE000U) == 0x81C06000U)
5044+ {
5045+ unsigned int addr;
5046+
5047+ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
5048+ addr = regs->u_regs[UREG_G1];
5049+ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
5050+ regs->pc = addr;
5051+ regs->npc = addr+4;
5052+ return 2;
5053+ }
5054+ } while (0);
5055+
5056+ { /* PaX: patched PLT emulation #2 */
5057+ unsigned int ba;
5058+
5059+ err = get_user(ba, (unsigned int*)regs->pc);
5060+
5061+ if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
5062+ unsigned int addr;
5063+
5064+ addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
5065+ regs->pc = addr;
5066+ regs->npc = addr+4;
5067+ return 2;
5068+ }
5069+ }
5070+
5071+ do { /* PaX: patched PLT emulation #3 */
5072+ unsigned int sethi, jmpl, nop;
5073+
5074+ err = get_user(sethi, (unsigned int*)regs->pc);
5075+ err |= get_user(jmpl, (unsigned int*)(regs->pc+4));
5076+ err |= get_user(nop, (unsigned int*)(regs->pc+8));
5077+
5078+ if (err)
5079+ break;
5080+
5081+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
5082+ (jmpl & 0xFFFFE000U) == 0x81C06000U &&
5083+ nop == 0x01000000U)
5084+ {
5085+ unsigned int addr;
5086+
5087+ addr = (sethi & 0x003FFFFFU) << 10;
5088+ regs->u_regs[UREG_G1] = addr;
5089+ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
5090+ regs->pc = addr;
5091+ regs->npc = addr+4;
5092+ return 2;
5093+ }
5094+ } while (0);
5095+
5096+ do { /* PaX: unpatched PLT emulation step 1 */
5097+ unsigned int sethi, ba, nop;
5098+
5099+ err = get_user(sethi, (unsigned int*)regs->pc);
5100+ err |= get_user(ba, (unsigned int*)(regs->pc+4));
5101+ err |= get_user(nop, (unsigned int*)(regs->pc+8));
5102+
5103+ if (err)
5104+ break;
5105+
5106+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
5107+ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
5108+ nop == 0x01000000U)
5109+ {
5110+ unsigned int addr, save, call;
5111+
5112+ if ((ba & 0xFFC00000U) == 0x30800000U)
5113+ addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
5114+ else
5115+ addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2);
5116+
5117+ err = get_user(save, (unsigned int*)addr);
5118+ err |= get_user(call, (unsigned int*)(addr+4));
5119+ err |= get_user(nop, (unsigned int*)(addr+8));
5120+ if (err)
5121+ break;
5122+
5123+ if (save == 0x9DE3BFA8U &&
5124+ (call & 0xC0000000U) == 0x40000000U &&
5125+ nop == 0x01000000U)
5126+ {
5127+ struct vm_area_struct *vma;
5128+ unsigned long call_dl_resolve;
5129+
5130+ down_read(&current->mm->mmap_sem);
5131+ call_dl_resolve = current->mm->call_dl_resolve;
5132+ up_read(&current->mm->mmap_sem);
5133+ if (likely(call_dl_resolve))
5134+ goto emulate;
5135+
5136+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
5137+
5138+ down_write(&current->mm->mmap_sem);
5139+ if (current->mm->call_dl_resolve) {
5140+ call_dl_resolve = current->mm->call_dl_resolve;
5141+ up_write(&current->mm->mmap_sem);
5142+ if (vma) kmem_cache_free(vm_area_cachep, vma);
5143+ goto emulate;
5144+ }
5145+
5146+ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
5147+ if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
5148+ up_write(&current->mm->mmap_sem);
5149+ if (vma) kmem_cache_free(vm_area_cachep, vma);
5150+ return 1;
5151+ }
5152+
5153+ if (pax_insert_vma(vma, call_dl_resolve)) {
5154+ up_write(&current->mm->mmap_sem);
5155+ kmem_cache_free(vm_area_cachep, vma);
5156+ return 1;
5157+ }
5158+
5159+ current->mm->call_dl_resolve = call_dl_resolve;
5160+ up_write(&current->mm->mmap_sem);
5161+
5162+emulate:
5163+ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
5164+ regs->pc = call_dl_resolve;
5165+ regs->npc = addr+4;
5166+ return 3;
5167+ }
5168+ }
5169+ } while (0);
5170+
5171+ do { /* PaX: unpatched PLT emulation step 2 */
5172+ unsigned int save, call, nop;
5173+
5174+ err = get_user(save, (unsigned int*)(regs->pc-4));
5175+ err |= get_user(call, (unsigned int*)regs->pc);
5176+ err |= get_user(nop, (unsigned int*)(regs->pc+4));
5177+ if (err)
5178+ break;
5179+
5180+ if (save == 0x9DE3BFA8U &&
5181+ (call & 0xC0000000U) == 0x40000000U &&
5182+ nop == 0x01000000U)
5183+ {
5184+ unsigned int dl_resolve = regs->pc + ((((call | 0xC0000000U) ^ 0x20000000U) + 0x20000000U) << 2);
5185+
5186+ regs->u_regs[UREG_RETPC] = regs->pc;
5187+ regs->pc = dl_resolve;
5188+ regs->npc = dl_resolve+4;
5189+ return 3;
5190+ }
5191+ } while (0);
5192+#endif
5193+
5194+ return 1;
5195+}
5196+
5197+void pax_report_insns(void *pc, void *sp)
5198+{
5199+ unsigned long i;
5200+
5201+ printk(KERN_ERR "PAX: bytes at PC: ");
5202+ for (i = 0; i < 5; i++) {
5203+ unsigned int c;
5204+ if (get_user(c, (unsigned int*)pc+i))
5205+ printk("???????? ");
5206+ else
5207+ printk("%08x ", c);
5208+ }
5209+ printk("\n");
5210+}
5211+#endif
5212+
5213 asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
5214 unsigned long address)
5215 {
5216@@ -280,6 +530,24 @@ good_area:
5217 if(!(vma->vm_flags & VM_WRITE))
5218 goto bad_area;
5219 } else {
5220+
5221+#ifdef CONFIG_PAX_PAGEEXEC
5222+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && text_fault && !(vma->vm_flags & VM_EXEC)) {
5223+ up_read(&mm->mmap_sem);
5224+ switch (pax_handle_fetch_fault(regs)) {
5225+
5226+#ifdef CONFIG_PAX_EMUPLT
5227+ case 2:
5228+ case 3:
5229+ return;
5230+#endif
5231+
5232+ }
5233+ pax_report_fault(regs, (void*)regs->pc, (void*)regs->u_regs[UREG_FP]);
5234+ do_exit(SIGKILL);
5235+ }
5236+#endif
5237+
5238 /* Allow reads even for write-only mappings */
5239 if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
5240 goto bad_area;
5241diff -urNp linux-2.6.16.12/arch/sparc/mm/init.c linux-2.6.16.12/arch/sparc/mm/init.c
5242--- linux-2.6.16.12/arch/sparc/mm/init.c 2006-05-01 15:14:26.000000000 -0400
5243+++ linux-2.6.16.12/arch/sparc/mm/init.c 2006-05-01 20:17:33.000000000 -0400
5244@@ -333,17 +333,17 @@ void __init paging_init(void)
5245
5246 /* Initialize the protection map with non-constant, MMU dependent values. */
5247 protection_map[0] = PAGE_NONE;
5248- protection_map[1] = PAGE_READONLY;
5249- protection_map[2] = PAGE_COPY;
5250- protection_map[3] = PAGE_COPY;
5251+ protection_map[1] = PAGE_READONLY_NOEXEC;
5252+ protection_map[2] = PAGE_COPY_NOEXEC;
5253+ protection_map[3] = PAGE_COPY_NOEXEC;
5254 protection_map[4] = PAGE_READONLY;
5255 protection_map[5] = PAGE_READONLY;
5256 protection_map[6] = PAGE_COPY;
5257 protection_map[7] = PAGE_COPY;
5258 protection_map[8] = PAGE_NONE;
5259- protection_map[9] = PAGE_READONLY;
5260- protection_map[10] = PAGE_SHARED;
5261- protection_map[11] = PAGE_SHARED;
5262+ protection_map[9] = PAGE_READONLY_NOEXEC;
5263+ protection_map[10] = PAGE_SHARED_NOEXEC;
5264+ protection_map[11] = PAGE_SHARED_NOEXEC;
5265 protection_map[12] = PAGE_READONLY;
5266 protection_map[13] = PAGE_READONLY;
5267 protection_map[14] = PAGE_SHARED;
5268diff -urNp linux-2.6.16.12/arch/sparc/mm/srmmu.c linux-2.6.16.12/arch/sparc/mm/srmmu.c
5269--- linux-2.6.16.12/arch/sparc/mm/srmmu.c 2006-05-01 15:14:26.000000000 -0400
5270+++ linux-2.6.16.12/arch/sparc/mm/srmmu.c 2006-05-01 20:17:33.000000000 -0400
5271@@ -2148,6 +2148,13 @@ void __init ld_mmu_srmmu(void)
5272 BTFIXUPSET_INT(page_shared, pgprot_val(SRMMU_PAGE_SHARED));
5273 BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY));
5274 BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY));
5275+
5276+#ifdef CONFIG_PAX_PAGEEXEC
5277+ BTFIXUPSET_INT(page_shared_noexec, pgprot_val(SRMMU_PAGE_SHARED_NOEXEC));
5278+ BTFIXUPSET_INT(page_copy_noexec, pgprot_val(SRMMU_PAGE_COPY_NOEXEC));
5279+ BTFIXUPSET_INT(page_readonly_noexec, pgprot_val(SRMMU_PAGE_RDONLY_NOEXEC));
5280+#endif
5281+
5282 BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL));
5283 page_kernel = pgprot_val(SRMMU_PAGE_KERNEL);
5284 pg_iobits = SRMMU_VALID | SRMMU_WRITE | SRMMU_REF;
5285diff -urNp linux-2.6.16.12/arch/sparc64/kernel/ptrace.c linux-2.6.16.12/arch/sparc64/kernel/ptrace.c
5286--- linux-2.6.16.12/arch/sparc64/kernel/ptrace.c 2006-05-01 15:14:26.000000000 -0400
5287+++ linux-2.6.16.12/arch/sparc64/kernel/ptrace.c 2006-05-01 20:17:33.000000000 -0400
5288@@ -22,6 +22,7 @@
5289 #include <linux/seccomp.h>
5290 #include <linux/audit.h>
5291 #include <linux/signal.h>
5292+#include <linux/grsecurity.h>
5293
5294 #include <asm/asi.h>
5295 #include <asm/pgtable.h>
9a4c6ab7 5296@@ -214,6 +215,11 @@ asmlinkage void do_ptrace(struct pt_regs
5297 goto out_tsk;
89675291 5298 }
5299
5300+ if (gr_handle_ptrace(child, (long)request)) {
5301+ pt_error_return(regs, EPERM);
5302+ goto out_tsk;
5303+ }
5304+
5305 if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
5306 || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
5307 if (ptrace_attach(child)) {
5308diff -urNp linux-2.6.16.12/arch/sparc64/kernel/sys_sparc.c linux-2.6.16.12/arch/sparc64/kernel/sys_sparc.c
5309--- linux-2.6.16.12/arch/sparc64/kernel/sys_sparc.c 2006-05-01 15:14:26.000000000 -0400
5310+++ linux-2.6.16.12/arch/sparc64/kernel/sys_sparc.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 5311@@ -73,6 +73,10 @@ unsigned long arch_get_unmapped_area(str
89675291 5312 if (filp || (flags & MAP_SHARED))
5313 do_color_align = 1;
5314
5315+#ifdef CONFIG_PAX_RANDMMAP
5316+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
5317+#endif
5318+
5319 if (addr) {
5320 if (do_color_align)
5321 addr = COLOUR_ALIGN(addr, pgoff);
9a4c6ab7 5322@@ -87,7 +91,7 @@ unsigned long arch_get_unmapped_area(str
89675291 5323
5324 if (len <= mm->cached_hole_size) {
5325 mm->cached_hole_size = 0;
5326- mm->free_area_cache = TASK_UNMAPPED_BASE;
5327+ mm->free_area_cache = mm->mmap_base;
5328 }
5329 start_addr = addr = mm->free_area_cache;
5330
9a4c6ab7 5331@@ -106,8 +110,8 @@ full_search:
89675291 5332 vma = find_vma(mm, PAGE_OFFSET);
5333 }
5334 if (task_size < addr) {
5335- if (start_addr != TASK_UNMAPPED_BASE) {
5336- start_addr = addr = TASK_UNMAPPED_BASE;
5337+ if (start_addr != mm->mmap_base) {
5338+ start_addr = addr = mm->mmap_base;
5339 mm->cached_hole_size = 0;
5340 goto full_search;
5341 }
5342diff -urNp linux-2.6.16.12/arch/sparc64/mm/fault.c linux-2.6.16.12/arch/sparc64/mm/fault.c
5343--- linux-2.6.16.12/arch/sparc64/mm/fault.c 2006-05-01 15:14:26.000000000 -0400
5344+++ linux-2.6.16.12/arch/sparc64/mm/fault.c 2006-05-01 20:17:33.000000000 -0400
5345@@ -19,6 +19,10 @@
5346 #include <linux/init.h>
5347 #include <linux/interrupt.h>
5348 #include <linux/kprobes.h>
5349+#include <linux/slab.h>
5350+#include <linux/pagemap.h>
5351+#include <linux/compiler.h>
5352+#include <linux/binfmts.h>
5353
5354 #include <asm/page.h>
5355 #include <asm/pgtable.h>
5356@@ -251,6 +255,369 @@ cannot_handle:
5357 unhandled_fault (address, current, regs);
5358 }
5359
5360+#ifdef CONFIG_PAX_PAGEEXEC
5361+#ifdef CONFIG_PAX_EMUPLT
5362+static void pax_emuplt_close(struct vm_area_struct * vma)
5363+{
5364+ vma->vm_mm->call_dl_resolve = 0UL;
5365+}
5366+
5367+static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
5368+{
5369+ struct page* page;
5370+ unsigned int *kaddr;
5371+
5372+ page = alloc_page(GFP_HIGHUSER);
5373+ if (!page)
5374+ return NOPAGE_OOM;
5375+
5376+ kaddr = kmap(page);
5377+ memset(kaddr, 0, PAGE_SIZE);
5378+ kaddr[0] = 0x9DE3BFA8U; /* save */
5379+ flush_dcache_page(page);
5380+ kunmap(page);
5381+ if (type)
5382+ *type = VM_FAULT_MAJOR;
5383+ return page;
5384+}
5385+
5386+static struct vm_operations_struct pax_vm_ops = {
5387+ .close = pax_emuplt_close,
5388+ .nopage = pax_emuplt_nopage,
5389+};
5390+
5391+static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
5392+{
5393+ int ret;
5394+
5395+ memset(vma, 0, sizeof(*vma));
5396+ vma->vm_mm = current->mm;
5397+ vma->vm_start = addr;
5398+ vma->vm_end = addr + PAGE_SIZE;
5399+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC;
5400+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
5401+ vma->vm_ops = &pax_vm_ops;
5402+
5403+ ret = insert_vm_struct(current->mm, vma);
5404+ if (ret)
5405+ return ret;
5406+
5407+ ++current->mm->total_vm;
5408+ return 0;
5409+}
5410+#endif
5411+
5412+/*
5413+ * PaX: decide what to do with offenders (regs->tpc = fault address)
5414+ *
5415+ * returns 1 when task should be killed
5416+ * 2 when patched PLT trampoline was detected
5417+ * 3 when unpatched PLT trampoline was detected
5418+ */
5419+static int pax_handle_fetch_fault(struct pt_regs *regs)
5420+{
5421+
5422+#ifdef CONFIG_PAX_EMUPLT
5423+ int err;
5424+
5425+ do { /* PaX: patched PLT emulation #1 */
5426+ unsigned int sethi1, sethi2, jmpl;
5427+
5428+ err = get_user(sethi1, (unsigned int*)regs->tpc);
5429+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
5430+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+8));
5431+
5432+ if (err)
5433+ break;
5434+
5435+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
5436+ (sethi2 & 0xFFC00000U) == 0x03000000U &&
5437+ (jmpl & 0xFFFFE000U) == 0x81C06000U)
5438+ {
5439+ unsigned long addr;
5440+
5441+ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
5442+ addr = regs->u_regs[UREG_G1];
5443+ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
5444+ regs->tpc = addr;
5445+ regs->tnpc = addr+4;
5446+ return 2;
5447+ }
5448+ } while (0);
5449+
5450+ { /* PaX: patched PLT emulation #2 */
5451+ unsigned int ba;
5452+
5453+ err = get_user(ba, (unsigned int*)regs->tpc);
5454+
5455+ if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
5456+ unsigned long addr;
5457+
5458+ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
5459+ regs->tpc = addr;
5460+ regs->tnpc = addr+4;
5461+ return 2;
5462+ }
5463+ }
5464+
5465+ do { /* PaX: patched PLT emulation #3 */
5466+ unsigned int sethi, jmpl, nop;
5467+
5468+ err = get_user(sethi, (unsigned int*)regs->tpc);
5469+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+4));
5470+ err |= get_user(nop, (unsigned int*)(regs->tpc+8));
5471+
5472+ if (err)
5473+ break;
5474+
5475+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
5476+ (jmpl & 0xFFFFE000U) == 0x81C06000U &&
5477+ nop == 0x01000000U)
5478+ {
5479+ unsigned long addr;
5480+
5481+ addr = (sethi & 0x003FFFFFU) << 10;
5482+ regs->u_regs[UREG_G1] = addr;
5483+ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
5484+ regs->tpc = addr;
5485+ regs->tnpc = addr+4;
5486+ return 2;
5487+ }
5488+ } while (0);
5489+
5490+ do { /* PaX: patched PLT emulation #4 */
5491+ unsigned int mov1, call, mov2;
5492+
5493+ err = get_user(mov1, (unsigned int*)regs->tpc);
5494+ err |= get_user(call, (unsigned int*)(regs->tpc+4));
5495+ err |= get_user(mov2, (unsigned int*)(regs->tpc+8));
5496+
5497+ if (err)
5498+ break;
5499+
5500+ if (mov1 == 0x8210000FU &&
5501+ (call & 0xC0000000U) == 0x40000000U &&
5502+ mov2 == 0x9E100001U)
5503+ {
5504+ unsigned long addr;
5505+
5506+ regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC];
5507+ addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
5508+ regs->tpc = addr;
5509+ regs->tnpc = addr+4;
5510+ return 2;
5511+ }
5512+ } while (0);
5513+
5514+ do { /* PaX: patched PLT emulation #5 */
5515+ unsigned int sethi1, sethi2, or1, or2, sllx, jmpl, nop;
5516+
5517+ err = get_user(sethi1, (unsigned int*)regs->tpc);
5518+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
5519+ err |= get_user(or1, (unsigned int*)(regs->tpc+8));
5520+ err |= get_user(or2, (unsigned int*)(regs->tpc+12));
5521+ err |= get_user(sllx, (unsigned int*)(regs->tpc+16));
5522+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+20));
5523+ err |= get_user(nop, (unsigned int*)(regs->tpc+24));
5524+
5525+ if (err)
5526+ break;
5527+
5528+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
5529+ (sethi2 & 0xFFC00000U) == 0x0B000000U &&
5530+ (or1 & 0xFFFFE000U) == 0x82106000U &&
5531+ (or2 & 0xFFFFE000U) == 0x8A116000U &&
5532+ sllx == 0x83287020 &&
5533+ jmpl == 0x81C04005U &&
5534+ nop == 0x01000000U)
5535+ {
5536+ unsigned long addr;
5537+
5538+ regs->u_regs[UREG_G1] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU);
5539+ regs->u_regs[UREG_G1] <<= 32;
5540+ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU);
5541+ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
5542+ regs->tpc = addr;
5543+ regs->tnpc = addr+4;
5544+ return 2;
5545+ }
5546+ } while (0);
5547+
5548+ do { /* PaX: patched PLT emulation #6 */
5549+ unsigned int sethi1, sethi2, sllx, or, jmpl, nop;
5550+
5551+ err = get_user(sethi1, (unsigned int*)regs->tpc);
5552+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4));
5553+ err |= get_user(sllx, (unsigned int*)(regs->tpc+8));
5554+ err |= get_user(or, (unsigned int*)(regs->tpc+12));
5555+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+16));
5556+ err |= get_user(nop, (unsigned int*)(regs->tpc+20));
5557+
5558+ if (err)
5559+ break;
5560+
5561+ if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
5562+ (sethi2 & 0xFFC00000U) == 0x0B000000U &&
5563+ sllx == 0x83287020 &&
5564+ (or & 0xFFFFE000U) == 0x8A116000U &&
5565+ jmpl == 0x81C04005U &&
5566+ nop == 0x01000000U)
5567+ {
5568+ unsigned long addr;
5569+
5570+ regs->u_regs[UREG_G1] = (sethi1 & 0x003FFFFFU) << 10;
5571+ regs->u_regs[UREG_G1] <<= 32;
5572+ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or & 0x3FFU);
5573+ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5];
5574+ regs->tpc = addr;
5575+ regs->tnpc = addr+4;
5576+ return 2;
5577+ }
5578+ } while (0);
5579+
5580+ do { /* PaX: patched PLT emulation #7 */
5581+ unsigned int sethi, ba, nop;
5582+
5583+ err = get_user(sethi, (unsigned int*)regs->tpc);
5584+ err |= get_user(ba, (unsigned int*)(regs->tpc+4));
5585+ err |= get_user(nop, (unsigned int*)(regs->tpc+8));
5586+
5587+ if (err)
5588+ break;
5589+
5590+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
5591+ (ba & 0xFFF00000U) == 0x30600000U &&
5592+ nop == 0x01000000U)
5593+ {
5594+ unsigned long addr;
5595+
5596+ addr = (sethi & 0x003FFFFFU) << 10;
5597+ regs->u_regs[UREG_G1] = addr;
5598+ addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
5599+ regs->tpc = addr;
5600+ regs->tnpc = addr+4;
5601+ return 2;
5602+ }
5603+ } while (0);
5604+
5605+ do { /* PaX: unpatched PLT emulation step 1 */
5606+ unsigned int sethi, ba, nop;
5607+
5608+ err = get_user(sethi, (unsigned int*)regs->tpc);
5609+ err |= get_user(ba, (unsigned int*)(regs->tpc+4));
5610+ err |= get_user(nop, (unsigned int*)(regs->tpc+8));
5611+
5612+ if (err)
5613+ break;
5614+
5615+ if ((sethi & 0xFFC00000U) == 0x03000000U &&
5616+ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
5617+ nop == 0x01000000U)
5618+ {
5619+ unsigned long addr;
5620+ unsigned int save, call;
5621+
5622+ if ((ba & 0xFFC00000U) == 0x30800000U)
5623+ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
5624+ else
5625+ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
5626+
5627+ err = get_user(save, (unsigned int*)addr);
5628+ err |= get_user(call, (unsigned int*)(addr+4));
5629+ err |= get_user(nop, (unsigned int*)(addr+8));
5630+ if (err)
5631+ break;
5632+
5633+ if (save == 0x9DE3BFA8U &&
5634+ (call & 0xC0000000U) == 0x40000000U &&
5635+ nop == 0x01000000U)
5636+ {
5637+ struct vm_area_struct *vma;
5638+ unsigned long call_dl_resolve;
5639+
5640+ down_read(&current->mm->mmap_sem);
5641+ call_dl_resolve = current->mm->call_dl_resolve;
5642+ up_read(&current->mm->mmap_sem);
5643+ if (likely(call_dl_resolve))
5644+ goto emulate;
5645+
5646+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
5647+
5648+ down_write(&current->mm->mmap_sem);
5649+ if (current->mm->call_dl_resolve) {
5650+ call_dl_resolve = current->mm->call_dl_resolve;
5651+ up_write(&current->mm->mmap_sem);
5652+ if (vma) kmem_cache_free(vm_area_cachep, vma);
5653+ goto emulate;
5654+ }
5655+
5656+ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
5657+ if (!vma || (call_dl_resolve & ~PAGE_MASK)) {
5658+ up_write(&current->mm->mmap_sem);
5659+ if (vma) kmem_cache_free(vm_area_cachep, vma);
5660+ return 1;
5661+ }
5662+
5663+ if (pax_insert_vma(vma, call_dl_resolve)) {
5664+ up_write(&current->mm->mmap_sem);
5665+ kmem_cache_free(vm_area_cachep, vma);
5666+ return 1;
5667+ }
5668+
5669+ current->mm->call_dl_resolve = call_dl_resolve;
5670+ up_write(&current->mm->mmap_sem);
5671+
5672+emulate:
5673+ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
5674+ regs->tpc = call_dl_resolve;
5675+ regs->tnpc = addr+4;
5676+ return 3;
5677+ }
5678+ }
5679+ } while (0);
5680+
5681+ do { /* PaX: unpatched PLT emulation step 2 */
5682+ unsigned int save, call, nop;
5683+
5684+ err = get_user(save, (unsigned int*)(regs->tpc-4));
5685+ err |= get_user(call, (unsigned int*)regs->tpc);
5686+ err |= get_user(nop, (unsigned int*)(regs->tpc+4));
5687+ if (err)
5688+ break;
5689+
5690+ if (save == 0x9DE3BFA8U &&
5691+ (call & 0xC0000000U) == 0x40000000U &&
5692+ nop == 0x01000000U)
5693+ {
5694+ unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
5695+
5696+ regs->u_regs[UREG_RETPC] = regs->tpc;
5697+ regs->tpc = dl_resolve;
5698+ regs->tnpc = dl_resolve+4;
5699+ return 3;
5700+ }
5701+ } while (0);
5702+#endif
5703+
5704+ return 1;
5705+}
5706+
5707+void pax_report_insns(void *pc, void *sp)
5708+{
5709+ unsigned long i;
5710+
5711+ printk(KERN_ERR "PAX: bytes at PC: ");
5712+ for (i = 0; i < 5; i++) {
5713+ unsigned int c;
5714+ if (get_user(c, (unsigned int*)pc+i))
5715+ printk("???????? ");
5716+ else
5717+ printk("%08x ", c);
5718+ }
5719+ printk("\n");
5720+}
5721+#endif
5722+
5723 asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
5724 {
5725 struct mm_struct *mm = current->mm;
5726@@ -293,8 +660,10 @@ asmlinkage void __kprobes do_sparc64_fau
5727 goto intr_or_no_mm;
5728
5729 if (test_thread_flag(TIF_32BIT)) {
5730- if (!(regs->tstate & TSTATE_PRIV))
5731+ if (!(regs->tstate & TSTATE_PRIV)) {
5732 regs->tpc &= 0xffffffff;
5733+ regs->tnpc &= 0xffffffff;
5734+ }
5735 address &= 0xffffffff;
5736 }
5737
5738@@ -311,6 +680,29 @@ asmlinkage void __kprobes do_sparc64_fau
5739 if (!vma)
5740 goto bad_area;
5741
5742+#ifdef CONFIG_PAX_PAGEEXEC
5743+ /* PaX: detect ITLB misses on non-exec pages */
5744+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && vma->vm_start <= address &&
5745+ !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB))
5746+ {
5747+ if (address != regs->tpc)
5748+ goto good_area;
5749+
5750+ up_read(&mm->mmap_sem);
5751+ switch (pax_handle_fetch_fault(regs)) {
5752+
5753+#ifdef CONFIG_PAX_EMUPLT
5754+ case 2:
5755+ case 3:
5756+ return;
5757+#endif
5758+
5759+ }
5760+ pax_report_fault(regs, (void*)regs->tpc, (void*)(regs->u_regs[UREG_FP] + STACK_BIAS));
5761+ do_exit(SIGKILL);
5762+ }
5763+#endif
5764+
5765 /* Pure DTLB misses do not tell us whether the fault causing
5766 * load/store/atomic was a write or not, it only says that there
5767 * was no match. So in such a case we (carefully) read the
5768diff -urNp linux-2.6.16.12/arch/v850/kernel/module.c linux-2.6.16.12/arch/v850/kernel/module.c
5769--- linux-2.6.16.12/arch/v850/kernel/module.c 2006-05-01 15:14:26.000000000 -0400
5770+++ linux-2.6.16.12/arch/v850/kernel/module.c 2006-05-01 20:17:33.000000000 -0400
5771@@ -150,8 +150,8 @@ static uint32_t do_plt_call (void *locat
5772 tramp[1] = ((val >> 16) & 0xffff) + 0x610000; /* ...; jmp r1 */
5773
5774 /* Init, or core PLT? */
5775- if (location >= mod->module_core
5776- && location < mod->module_core + mod->core_size)
5777+ if (location >= mod->module_core_rx
5778+ && location < mod->module_core_rx + mod->core_size_rx)
5779 entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr;
5780 else
5781 entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
5782diff -urNp linux-2.6.16.12/arch/x86_64/boot/compressed/head.S linux-2.6.16.12/arch/x86_64/boot/compressed/head.S
5783--- linux-2.6.16.12/arch/x86_64/boot/compressed/head.S 2006-05-01 15:14:26.000000000 -0400
5784+++ linux-2.6.16.12/arch/x86_64/boot/compressed/head.S 2006-05-01 20:17:33.000000000 -0400
5785@@ -41,11 +41,13 @@ startup_32:
5786 movl %eax,%gs
5787
5788 lss stack_start,%esp
5789+ movl 0x000000,%ecx
5790 xorl %eax,%eax
5791 1: incl %eax # check that A20 really IS enabled
5792 movl %eax,0x000000 # loop forever if it isn't
5793 cmpl %eax,0x100000
5794 je 1b
5795+ movl %ecx,0x000000
5796
5797 /*
5798 * Initialize eflags. Some BIOS's leave bits like NT set. This would
5799diff -urNp linux-2.6.16.12/arch/x86_64/ia32/ia32_binfmt.c linux-2.6.16.12/arch/x86_64/ia32/ia32_binfmt.c
5800--- linux-2.6.16.12/arch/x86_64/ia32/ia32_binfmt.c 2006-05-01 15:14:26.000000000 -0400
5801+++ linux-2.6.16.12/arch/x86_64/ia32/ia32_binfmt.c 2006-05-01 20:17:33.000000000 -0400
5802@@ -186,6 +186,17 @@ struct elf_prpsinfo
5803 //#include <asm/ia32.h>
5804 #include <linux/elf.h>
5805
5806+#ifdef CONFIG_PAX_ASLR
5807+#define PAX_ELF_ET_DYN_BASE(tsk) 0x08048000UL
5808+
5809+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
5810+#define PAX_DELTA_MMAP_LEN(tsk) 16
5811+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
5812+#define PAX_DELTA_EXEC_LEN(tsk) 16
5813+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
5814+#define PAX_DELTA_STACK_LEN(tsk) 16
5815+#endif
5816+
5817 typedef struct user_i387_ia32_struct elf_fpregset_t;
5818 typedef struct user32_fxsr_struct elf_fpxregset_t;
5819
5820diff -urNp linux-2.6.16.12/arch/x86_64/ia32/mmap32.c linux-2.6.16.12/arch/x86_64/ia32/mmap32.c
5821--- linux-2.6.16.12/arch/x86_64/ia32/mmap32.c 2006-05-01 15:14:26.000000000 -0400
5822+++ linux-2.6.16.12/arch/x86_64/ia32/mmap32.c 2006-05-01 20:17:33.000000000 -0400
5823@@ -68,10 +68,22 @@ void ia32_pick_mmap_layout(struct mm_str
5824 (current->personality & ADDR_COMPAT_LAYOUT) ||
5825 current->signal->rlim[RLIMIT_STACK].rlim_cur == RLIM_INFINITY) {
5826 mm->mmap_base = TASK_UNMAPPED_BASE;
5827+
5828+#ifdef CONFIG_PAX_RANDMMAP
5829+ if (mm->pax_flags & MF_PAX_RANDMMAP)
5830+ mm->mmap_base += mm->delta_mmap;
5831+#endif
5832+
5833 mm->get_unmapped_area = arch_get_unmapped_area;
5834 mm->unmap_area = arch_unmap_area;
5835 } else {
5836 mm->mmap_base = mmap_base(mm);
5837+
5838+#ifdef CONFIG_PAX_RANDMMAP
5839+ if (mm->pax_flags & MF_PAX_RANDMMAP)
5840+ mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
5841+#endif
5842+
5843 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
5844 mm->unmap_area = arch_unmap_area_topdown;
5845 }
5846diff -urNp linux-2.6.16.12/arch/x86_64/kernel/process.c linux-2.6.16.12/arch/x86_64/kernel/process.c
5847--- linux-2.6.16.12/arch/x86_64/kernel/process.c 2006-05-01 15:14:26.000000000 -0400
5848+++ linux-2.6.16.12/arch/x86_64/kernel/process.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 5849@@ -840,9 +840,3 @@ int dump_task_regs(struct task_struct *t
89675291 5850 return 1;
5851 }
5852
5853-unsigned long arch_align_stack(unsigned long sp)
5854-{
5855- if (randomize_va_space)
5856- sp -= get_random_int() % 8192;
5857- return sp & ~0xf;
5858-}
5859diff -urNp linux-2.6.16.12/arch/x86_64/kernel/ptrace.c linux-2.6.16.12/arch/x86_64/kernel/ptrace.c
5860--- linux-2.6.16.12/arch/x86_64/kernel/ptrace.c 2006-05-01 15:14:26.000000000 -0400
5861+++ linux-2.6.16.12/arch/x86_64/kernel/ptrace.c 2006-05-01 20:17:33.000000000 -0400
5862@@ -19,6 +19,7 @@
5863 #include <linux/audit.h>
5864 #include <linux/seccomp.h>
5865 #include <linux/signal.h>
5866+#include <linux/grsecurity.h>
5867
5868 #include <asm/uaccess.h>
5869 #include <asm/pgtable.h>
5870diff -urNp linux-2.6.16.12/arch/x86_64/kernel/setup64.c linux-2.6.16.12/arch/x86_64/kernel/setup64.c
5871--- linux-2.6.16.12/arch/x86_64/kernel/setup64.c 2006-05-01 15:14:26.000000000 -0400
5872+++ linux-2.6.16.12/arch/x86_64/kernel/setup64.c 2006-05-01 20:17:33.000000000 -0400
5873@@ -38,7 +38,6 @@ struct desc_ptr idt_descr = { 256 * 16,
5874 char boot_cpu_stack[IRQSTACKSIZE] __attribute__((section(".bss.page_aligned")));
5875
5876 unsigned long __supported_pte_mask __read_mostly = ~0UL;
5877-static int do_not_nx __cpuinitdata = 0;
5878
5879 /* noexec=on|off
5880 Control non executable mappings for 64bit processes.
5881@@ -50,16 +49,14 @@ int __init nonx_setup(char *str)
5882 {
5883 if (!strncmp(str, "on", 2)) {
5884 __supported_pte_mask |= _PAGE_NX;
5885- do_not_nx = 0;
5886 } else if (!strncmp(str, "off", 3)) {
5887- do_not_nx = 1;
5888 __supported_pte_mask &= ~_PAGE_NX;
5889 }
5890 return 0;
5891 }
5892 __setup("noexec=", nonx_setup); /* parsed early actually */
5893
5894-int force_personality32 = READ_IMPLIES_EXEC;
5895+int force_personality32;
5896
5897 /* noexec32=on|off
5898 Control non executable heap for 32bit processes.
5899@@ -173,7 +170,7 @@ void __cpuinit check_efer(void)
5900 unsigned long efer;
5901
5902 rdmsrl(MSR_EFER, efer);
5903- if (!(efer & EFER_NX) || do_not_nx) {
5904+ if (!(efer & EFER_NX)) {
5905 __supported_pte_mask &= ~_PAGE_NX;
5906 }
5907 }
5908diff -urNp linux-2.6.16.12/arch/x86_64/kernel/sys_x86_64.c linux-2.6.16.12/arch/x86_64/kernel/sys_x86_64.c
5909--- linux-2.6.16.12/arch/x86_64/kernel/sys_x86_64.c 2006-05-01 15:14:26.000000000 -0400
5910+++ linux-2.6.16.12/arch/x86_64/kernel/sys_x86_64.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 5911@@ -66,8 +66,8 @@ out:
89675291 5912 return error;
5913 }
5914
5915-static void find_start_end(unsigned long flags, unsigned long *begin,
5916- unsigned long *end)
5917+static void find_start_end(struct mm_struct *mm, unsigned long flags,
5918+ unsigned long *begin, unsigned long *end)
5919 {
5920 if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
5921 /* This is usually used needed to map code in small
9a4c6ab7 5922@@ -80,7 +80,7 @@ static void find_start_end(unsigned long
89675291 5923 *begin = 0x40000000;
5924 *end = 0x80000000;
5925 } else {
5926- *begin = TASK_UNMAPPED_BASE;
5927+ *begin = mm->mmap_base;
5928 *end = TASK_SIZE;
5929 }
5930 }
9a4c6ab7 5931@@ -94,11 +94,15 @@ arch_get_unmapped_area(struct file *filp
89675291 5932 unsigned long start_addr;
5933 unsigned long begin, end;
5934
5935- find_start_end(flags, &begin, &end);
5936+ find_start_end(mm, flags, &begin, &end);
5937
5938 if (len > end)
5939 return -ENOMEM;
5940
5941+#ifdef CONFIG_PAX_RANDMMAP
5942+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
5943+#endif
5944+
5945 if (addr) {
5946 addr = PAGE_ALIGN(addr);
5947 vma = find_vma(mm, addr);
5948diff -urNp linux-2.6.16.12/arch/x86_64/mm/fault.c linux-2.6.16.12/arch/x86_64/mm/fault.c
5949--- linux-2.6.16.12/arch/x86_64/mm/fault.c 2006-05-01 15:14:26.000000000 -0400
5950+++ linux-2.6.16.12/arch/x86_64/mm/fault.c 2006-05-01 20:17:33.000000000 -0400
5951@@ -24,6 +24,7 @@
5952 #include <linux/compiler.h>
5953 #include <linux/module.h>
5954 #include <linux/kprobes.h>
5955+#include <linux/binfmts.h>
5956
5957 #include <asm/system.h>
5958 #include <asm/uaccess.h>
5959@@ -292,6 +293,33 @@ static int vmalloc_fault(unsigned long a
5960 return 0;
5961 }
5962
5963+#ifdef CONFIG_PAX_PAGEEXEC
5964+void pax_report_insns(void *pc, void *sp)
5965+{
5966+ long i;
5967+
5968+ printk(KERN_ERR "PAX: bytes at PC: ");
5969+ for (i = 0; i < 20; i++) {
5970+ unsigned char c;
5971+ if (get_user(c, (unsigned char __user *)pc+i))
5972+ printk("?? ");
5973+ else
5974+ printk("%02x ", c);
5975+ }
5976+ printk("\n");
5977+
5978+ printk(KERN_ERR "PAX: bytes at SP-8: ");
5979+ for (i = -1; i < 10; i++) {
5980+ unsigned long c;
5981+ if (get_user(c, (unsigned long __user *)sp+i))
5982+ printk("???????????????? ");
5983+ else
5984+ printk("%016lx ", c);
5985+ }
5986+ printk("\n");
5987+}
5988+#endif
5989+
5990 int page_fault_trace = 0;
5991 int exception_trace = 1;
5992
5993@@ -416,6 +444,8 @@ asmlinkage void __kprobes do_page_fault(
5994 good_area:
5995 info.si_code = SEGV_ACCERR;
5996 write = 0;
5997+ if ((error_code & PF_INSTR) && !(vma->vm_flags & VM_EXEC))
5998+ goto bad_area;
5999 switch (error_code & (PF_PROT|PF_WRITE)) {
6000 default: /* 3: write, present */
6001 /* fall through */
6002@@ -482,7 +512,14 @@ bad_area_nosemaphore:
6003 tsk->comm, tsk->pid, address, regs->rip,
6004 regs->rsp, error_code);
6005 }
6006-
6007+
6008+#ifdef CONFIG_PAX_PAGEEXEC
6009+ if (mm && (mm->pax_flags & MF_PAX_PAGEEXEC) && (error_code & 16)) {
6010+ pax_report_fault(regs, (void*)regs->rip, (void*)regs->rsp);
6011+ do_exit(SIGKILL);
6012+ }
6013+#endif
6014+
6015 tsk->thread.cr2 = address;
6016 /* Kernel addresses are always protection faults */
6017 tsk->thread.error_code = error_code | (address >= TASK_SIZE);
6018diff -urNp linux-2.6.16.12/arch/x86_64/mm/mmap.c linux-2.6.16.12/arch/x86_64/mm/mmap.c
6019--- linux-2.6.16.12/arch/x86_64/mm/mmap.c 2006-05-01 15:14:26.000000000 -0400
6020+++ linux-2.6.16.12/arch/x86_64/mm/mmap.c 2006-05-01 20:17:33.000000000 -0400
6021@@ -24,6 +24,12 @@ void arch_pick_mmap_layout(struct mm_str
6022 unsigned rnd = get_random_int() & 0xfffffff;
6023 mm->mmap_base += ((unsigned long)rnd) << PAGE_SHIFT;
6024 }
6025+
6026+#ifdef CONFIG_PAX_RANDMMAP
6027+ if (mm->pax_flags & MF_PAX_RANDMMAP)
6028+ mm->mmap_base += mm->delta_mmap;
6029+#endif
6030+
6031 mm->get_unmapped_area = arch_get_unmapped_area;
6032 mm->unmap_area = arch_unmap_area;
6033 }
6034diff -urNp linux-2.6.16.12/drivers/char/agp/frontend.c linux-2.6.16.12/drivers/char/agp/frontend.c
6035--- linux-2.6.16.12/drivers/char/agp/frontend.c 2006-05-01 15:14:26.000000000 -0400
6036+++ linux-2.6.16.12/drivers/char/agp/frontend.c 2006-05-01 20:17:33.000000000 -0400
6037@@ -841,7 +841,7 @@ static int agpioc_reserve_wrap(struct ag
6038 if (copy_from_user(&reserve, arg, sizeof(struct agp_region)))
6039 return -EFAULT;
6040
6041- if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
6042+ if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment_priv))
6043 return -EFAULT;
6044
6045 client = agp_find_client_by_pid(reserve.pid);
6046diff -urNp linux-2.6.16.12/drivers/char/keyboard.c linux-2.6.16.12/drivers/char/keyboard.c
6047--- linux-2.6.16.12/drivers/char/keyboard.c 2006-05-01 15:14:26.000000000 -0400
6048+++ linux-2.6.16.12/drivers/char/keyboard.c 2006-05-01 20:17:33.000000000 -0400
6049@@ -607,6 +607,16 @@ static void k_spec(struct vc_data *vc, u
6050 kbd->kbdmode == VC_MEDIUMRAW) &&
6051 value != KVAL(K_SAK))
6052 return; /* SAK is allowed even in raw mode */
6053+
6054+#if defined(CONFIG_GRKERNSEC_PROC) || defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
6055+ {
6056+ void *func = fn_handler[value];
6057+ if (func == fn_show_state || func == fn_show_ptregs ||
6058+ func == fn_show_mem)
6059+ return;
6060+ }
6061+#endif
6062+
6063 fn_handler[value](vc, regs);
6064 }
6065
6066diff -urNp linux-2.6.16.12/drivers/char/mem.c linux-2.6.16.12/drivers/char/mem.c
6067--- linux-2.6.16.12/drivers/char/mem.c 2006-05-01 15:14:26.000000000 -0400
6068+++ linux-2.6.16.12/drivers/char/mem.c 2006-05-01 20:17:33.000000000 -0400
6069@@ -27,6 +27,7 @@
6070 #include <linux/crash_dump.h>
6071 #include <linux/backing-dev.h>
6072 #include <linux/bootmem.h>
6073+#include <linux/grsecurity.h>
6074
6075 #include <asm/uaccess.h>
6076 #include <asm/io.h>
6077@@ -35,6 +36,10 @@
6078 # include <linux/efi.h>
6079 #endif
6080
6081+#ifdef CONFIG_GRKERNSEC
6082+extern struct file_operations grsec_fops;
6083+#endif
6084+
6085 /*
6086 * Architectures vary in how they handle caching for addresses
6087 * outside of main memory.
6088@@ -180,6 +185,11 @@ static ssize_t write_mem(struct file * f
6089 if (!valid_phys_addr_range(p, &count))
6090 return -EFAULT;
6091
6092+#ifdef CONFIG_GRKERNSEC_KMEM
6093+ gr_handle_mem_write();
6094+ return -EPERM;
6095+#endif
6096+
6097 written = 0;
6098
6099 #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
6100@@ -258,6 +268,11 @@ static int mmap_mem(struct file * file,
6101 size,
6102 vma->vm_page_prot);
6103
6104+#ifdef CONFIG_GRKERNSEC_KMEM
6105+ if (gr_handle_mem_mmap(vma->vm_pgoff << PAGE_SHIFT, vma))
6106+ return -EPERM;
6107+#endif
6108+
6109 /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
6110 if (remap_pfn_range(vma,
6111 vma->vm_start,
6112@@ -487,6 +502,11 @@ static ssize_t write_kmem(struct file *
6113 ssize_t written;
6114 char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
6115
6116+#ifdef CONFIG_GRKERNSEC_KMEM
6117+ gr_handle_kmem_write();
6118+ return -EPERM;
6119+#endif
6120+
6121 if (p < (unsigned long) high_memory) {
6122
6123 wrote = count;
6124@@ -613,7 +633,23 @@ static inline size_t read_zero_pagealign
6125 count = size;
6126
6127 zap_page_range(vma, addr, count, NULL);
6128- zeromap_page_range(vma, addr, count, PAGE_COPY);
6129+ zeromap_page_range(vma, addr, count, vma->vm_page_prot);
6130+
6131+#ifdef CONFIG_PAX_SEGMEXEC
6132+ if (vma->vm_flags & VM_MIRROR) {
6133+ unsigned long addr_m;
6134+ struct vm_area_struct * vma_m;
6135+
6136+ addr_m = vma->vm_start + vma->vm_mirror;
6137+ vma_m = find_vma(mm, addr_m);
6138+ if (vma_m && vma_m->vm_start == addr_m && (vma_m->vm_flags & VM_MIRROR)) {
6139+ addr_m = addr + vma->vm_mirror;
6140+ zap_page_range(vma_m, addr_m, count, NULL);
6141+ } else
6142+ printk(KERN_ERR "PAX: VMMIRROR: read_zero bug, %08lx, %08lx\n",
6143+ addr, vma->vm_start);
6144+ }
6145+#endif
6146
6147 size -= count;
6148 buf += count;
6149@@ -762,6 +798,16 @@ static loff_t memory_lseek(struct file *
6150
6151 static int open_port(struct inode * inode, struct file * filp)
6152 {
6153+#ifdef CONFIG_GRKERNSEC_KMEM
6154+ gr_handle_open_port();
6155+ return -EPERM;
6156+#endif
6157+
6158+ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
6159+}
6160+
6161+static int open_mem(struct inode * inode, struct file * filp)
6162+{
6163 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
6164 }
6165
6166@@ -769,7 +815,6 @@ static int open_port(struct inode * inod
6167 #define full_lseek null_lseek
6168 #define write_zero write_null
6169 #define read_full read_zero
6170-#define open_mem open_port
6171 #define open_kmem open_mem
6172 #define open_oldmem open_mem
6173
6174@@ -891,6 +936,11 @@ static int memory_open(struct inode * in
6175 filp->f_op = &oldmem_fops;
6176 break;
6177 #endif
6178+#ifdef CONFIG_GRKERNSEC
6179+ case 13:
6180+ filp->f_op = &grsec_fops;
6181+ break;
6182+#endif
6183 default:
6184 return -ENXIO;
6185 }
6186@@ -923,6 +973,9 @@ static const struct {
6187 #ifdef CONFIG_CRASH_DUMP
6188 {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
6189 #endif
6190+#ifdef CONFIG_GRKERNSEC
6191+ {13,"grsec", S_IRUSR | S_IWUGO, &grsec_fops},
6192+#endif
6193 };
6194
6195 static struct class *mem_class;
6196diff -urNp linux-2.6.16.12/drivers/char/random.c linux-2.6.16.12/drivers/char/random.c
6197--- linux-2.6.16.12/drivers/char/random.c 2006-05-01 15:14:26.000000000 -0400
6198+++ linux-2.6.16.12/drivers/char/random.c 2006-05-01 20:17:33.000000000 -0400
6199@@ -249,8 +249,13 @@
6200 /*
6201 * Configuration information
6202 */
6203+#ifdef CONFIG_GRKERNSEC_RANDNET
6204+#define INPUT_POOL_WORDS 256
6205+#define OUTPUT_POOL_WORDS 64
6206+#else
6207 #define INPUT_POOL_WORDS 128
6208 #define OUTPUT_POOL_WORDS 32
6209+#endif
6210 #define SEC_XFER_SIZE 512
6211
6212 /*
6213@@ -1659,3 +1664,25 @@ randomize_range(unsigned long start, uns
6214 return 0;
6215 return PAGE_ALIGN(get_random_int() % range + start);
6216 }
6217+
6218+#if defined(CONFIG_PAX_ASLR) || defined(CONFIG_GRKERNSEC)
6219+unsigned long pax_get_random_long(void)
6220+{
6221+ static time_t rekey_time;
6222+ static __u32 secret[12];
6223+ time_t t;
6224+
6225+ /*
6226+ * Pick a random secret every REKEY_INTERVAL seconds.
6227+ */
6228+ t = get_seconds();
6229+ if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) {
6230+ rekey_time = t;
6231+ get_random_bytes(secret, sizeof(secret));
6232+ }
6233+
6234+ secret[1] = half_md4_transform(secret+8, secret);
6235+ secret[0] = half_md4_transform(secret+8, secret);
6236+ return *(unsigned long *)secret;
6237+}
6238+#endif
6239diff -urNp linux-2.6.16.12/drivers/char/vt_ioctl.c linux-2.6.16.12/drivers/char/vt_ioctl.c
6240--- linux-2.6.16.12/drivers/char/vt_ioctl.c 2006-05-01 15:14:26.000000000 -0400
6241+++ linux-2.6.16.12/drivers/char/vt_ioctl.c 2006-05-01 20:17:33.000000000 -0400
6242@@ -96,6 +96,12 @@ do_kdsk_ioctl(int cmd, struct kbentry __
6243 case KDSKBENT:
6244 if (!perm)
6245 return -EPERM;
6246+
6247+#ifdef CONFIG_GRKERNSEC
6248+ if (!capable(CAP_SYS_TTY_CONFIG))
6249+ return -EPERM;
6250+#endif
6251+
6252 if (!i && v == K_NOSUCHMAP) {
6253 /* disallocate map */
6254 key_map = key_maps[s];
6255@@ -236,6 +242,13 @@ do_kdgkb_ioctl(int cmd, struct kbsentry
6256 goto reterr;
6257 }
6258
6259+#ifdef CONFIG_GRKERNSEC
6260+ if (!capable(CAP_SYS_TTY_CONFIG)) {
6261+ ret = -EPERM;
6262+ goto reterr;
6263+ }
6264+#endif
6265+
6266 q = func_table[i];
6267 first_free = funcbufptr + (funcbufsize - funcbufleft);
6268 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
6269diff -urNp linux-2.6.16.12/drivers/ieee1394/ohci1394.c linux-2.6.16.12/drivers/ieee1394/ohci1394.c
6270--- linux-2.6.16.12/drivers/ieee1394/ohci1394.c 2006-05-01 15:14:26.000000000 -0400
6271+++ linux-2.6.16.12/drivers/ieee1394/ohci1394.c 2006-05-01 20:17:33.000000000 -0400
6272@@ -162,9 +162,9 @@ printk(level "%s: " fmt "\n" , OHCI1394_
6273 printk(level "%s: fw-host%d: " fmt "\n" , OHCI1394_DRIVER_NAME, ohci->host->id , ## args)
6274
6275 /* Module Parameters */
6276-static int phys_dma = 1;
6277+static int phys_dma = 0;
6278 module_param(phys_dma, int, 0644);
6279-MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 1).");
6280+MODULE_PARM_DESC(phys_dma, "Enable physical dma (default = 0).");
6281
6282 static void dma_trm_tasklet(unsigned long data);
6283 static void dma_trm_reset(struct dma_trm_ctx *d);
6284diff -urNp linux-2.6.16.12/drivers/mtd/devices/doc2001.c linux-2.6.16.12/drivers/mtd/devices/doc2001.c
6285--- linux-2.6.16.12/drivers/mtd/devices/doc2001.c 2006-05-01 15:14:26.000000000 -0400
6286+++ linux-2.6.16.12/drivers/mtd/devices/doc2001.c 2006-05-01 20:17:33.000000000 -0400
6287@@ -423,6 +423,8 @@ static int doc_read_ecc (struct mtd_info
6288 /* Don't allow read past end of device */
6289 if (from >= this->totlen)
6290 return -EINVAL;
6291+ if (!len)
6292+ return -EINVAL;
6293
6294 /* Don't allow a single read to cross a 512-byte block boundary */
6295 if (from + len > ((from | 0x1ff) + 1))
6296diff -urNp linux-2.6.16.12/drivers/net/wan/sdla_ppp.c linux-2.6.16.12/drivers/net/wan/sdla_ppp.c
6297--- linux-2.6.16.12/drivers/net/wan/sdla_ppp.c 2006-05-01 15:14:26.000000000 -0400
6298+++ linux-2.6.16.12/drivers/net/wan/sdla_ppp.c 2006-05-01 20:17:33.000000000 -0400
6299@@ -451,7 +451,7 @@ static int update(struct wan_device *wan
6300 sdla_t* card = wandev->private;
6301 struct net_device* dev;
6302 volatile ppp_private_area_t *ppp_priv_area;
6303- ppp_flags_t *flags = card->flags;
6304+ ppp_flags_t *flags;
6305 unsigned long timeout;
6306
6307 /* sanity checks */
6308@@ -475,6 +475,7 @@ static int update(struct wan_device *wan
6309
6310 ppp_priv_area->update_comms_stats = 2;
6311 ppp_priv_area->timer_int_enabled |= TMR_INT_ENABLED_UPDATE;
6312+ flags = card->flags;
6313 flags->imask |= PPP_INTR_TIMER;
6314
6315 /* wait a maximum of 1 second for the statistics to be updated */
6316diff -urNp linux-2.6.16.12/drivers/pci/proc.c linux-2.6.16.12/drivers/pci/proc.c
6317--- linux-2.6.16.12/drivers/pci/proc.c 2006-05-01 15:14:26.000000000 -0400
6318+++ linux-2.6.16.12/drivers/pci/proc.c 2006-05-01 20:17:33.000000000 -0400
6319@@ -569,7 +569,15 @@ static struct file_operations proc_pci_o
6320
6321 static void legacy_proc_init(void)
6322 {
6323+#ifdef CONFIG_GRKERNSEC_PROC_ADD
6324+#ifdef CONFIG_GRKERNSEC_PROC_USER
6325+ struct proc_dir_entry * entry = create_proc_entry("pci", S_IRUSR, NULL);
6326+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
6327+ struct proc_dir_entry * entry = create_proc_entry("pci", S_IRUSR | S_IRGRP, NULL);
6328+#endif
6329+#else
6330 struct proc_dir_entry * entry = create_proc_entry("pci", 0, NULL);
6331+#endif
6332 if (entry)
6333 entry->proc_fops = &proc_pci_operations;
6334 }
6335@@ -598,7 +606,15 @@ static int __init pci_proc_init(void)
6336 {
6337 struct proc_dir_entry *entry;
6338 struct pci_dev *dev = NULL;
6339+#ifdef CONFIG_GRKERNSEC_PROC_ADD
6340+#ifdef CONFIG_GRKERNSEC_PROC_USER
6341+ proc_bus_pci_dir = proc_mkdir_mode("pci", S_IRUSR | S_IXUSR, proc_bus);
6342+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
6343+ proc_bus_pci_dir = proc_mkdir_mode("pci", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, proc_bus);
6344+#endif
6345+#else
6346 proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
6347+#endif
6348 entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
6349 if (entry)
6350 entry->proc_fops = &proc_bus_pci_dev_operations;
6351diff -urNp linux-2.6.16.12/drivers/pnp/pnpbios/bioscalls.c linux-2.6.16.12/drivers/pnp/pnpbios/bioscalls.c
6352--- linux-2.6.16.12/drivers/pnp/pnpbios/bioscalls.c 2006-05-01 15:14:26.000000000 -0400
6353+++ linux-2.6.16.12/drivers/pnp/pnpbios/bioscalls.c 2006-05-01 20:17:33.000000000 -0400
6354@@ -65,7 +65,7 @@ set_base(gdt[(selname) >> 3], (u32)(addr
6355 set_limit(gdt[(selname) >> 3], size); \
6356 } while(0)
6357
6358-static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
6359+static struct desc_struct bad_bios_desc = { 0, 0x00409300 };
6360
6361 /*
6362 * At some point we want to use this stack frame pointer to unwind
6363@@ -93,6 +93,10 @@ static inline u16 call_pnp_bios(u16 func
6364 struct desc_struct save_desc_40;
6365 int cpu;
6366
6367+#ifdef CONFIG_PAX_KERNEXEC
6368+ unsigned long cr0;
6369+#endif
6370+
6371 /*
6372 * PnP BIOSes are generally not terribly re-entrant.
6373 * Also, don't rely on them to save everything correctly.
6374@@ -107,6 +111,10 @@ static inline u16 call_pnp_bios(u16 func
6375 /* On some boxes IRQ's during PnP BIOS calls are deadly. */
6376 spin_lock_irqsave(&pnp_bios_lock, flags);
6377
6378+#ifdef CONFIG_PAX_KERNEXEC
6379+ pax_open_kernel(cr0);
6380+#endif
6381+
6382 /* The lock prevents us bouncing CPU here */
6383 if (ts1_size)
6384 Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
6385@@ -142,9 +150,14 @@ static inline u16 call_pnp_bios(u16 func
6386 "i" (0)
6387 : "memory"
6388 );
6389- spin_unlock_irqrestore(&pnp_bios_lock, flags);
6390
6391 get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40;
6392+
6393+#ifdef CONFIG_PAX_KERNEXEC
6394+ pax_close_kernel(cr0);
6395+#endif
6396+
6397+ spin_unlock_irqrestore(&pnp_bios_lock, flags);
6398 put_cpu();
6399
6400 /* If we get here and this is set then the PnP BIOS faulted on us. */
6401diff -urNp linux-2.6.16.12/drivers/scsi/libata-scsi.c linux-2.6.16.12/drivers/scsi/libata-scsi.c
6402--- linux-2.6.16.12/drivers/scsi/libata-scsi.c 2006-05-01 15:14:26.000000000 -0400
6403+++ linux-2.6.16.12/drivers/scsi/libata-scsi.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 6404@@ -1591,7 +1591,7 @@ unsigned int ata_scsiop_inq_80(struct at
89675291 6405 return 0;
6406 }
6407
6408-static const char * const inq_83_str = "Linux ATA-SCSI simulator";
6409+static const char inq_83_str[] = "Linux ATA-SCSI simulator";
6410
6411 /**
6412 * ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity
9a4c6ab7 6413@@ -1610,13 +1610,13 @@ unsigned int ata_scsiop_inq_83(struct at
89675291 6414 unsigned int buflen)
6415 {
6416 rbuf[1] = 0x83; /* this page code */
6417- rbuf[3] = 4 + strlen(inq_83_str); /* page len */
6418+ rbuf[3] = 3 + sizeof(inq_83_str); /* page len */
6419
6420 /* our one and only identification descriptor (vendor-specific) */
6421- if (buflen > (strlen(inq_83_str) + 4 + 4 - 1)) {
6422+ if (buflen >= (sizeof(inq_83_str) + 4 + 4 - 1)) {
6423 rbuf[4 + 0] = 2; /* code set: ASCII */
6424- rbuf[4 + 3] = strlen(inq_83_str);
6425- memcpy(rbuf + 4 + 4, inq_83_str, strlen(inq_83_str));
6426+ rbuf[4 + 3] = sizeof(inq_83_str)-1;
6427+ memcpy(rbuf + 4 + 4, inq_83_str, sizeof(inq_83_str)-1);
6428 }
6429
6430 return 0;
6431diff -urNp linux-2.6.16.12/drivers/video/vesafb.c linux-2.6.16.12/drivers/video/vesafb.c
6432--- linux-2.6.16.12/drivers/video/vesafb.c 2006-05-01 15:14:26.000000000 -0400
6433+++ linux-2.6.16.12/drivers/video/vesafb.c 2006-05-01 20:17:33.000000000 -0400
6434@@ -251,7 +251,7 @@ static int __init vesafb_probe(struct pl
6435 size_remap = size_total;
6436 vesafb_fix.smem_len = size_remap;
6437
6438-#ifndef __i386__
6439+#if !defined(__i386__) || defined(CONFIG_PAX_KERNEXEC)
6440 screen_info.vesapm_seg = 0;
6441 #endif
6442
6443diff -urNp linux-2.6.16.12/fs/binfmt_aout.c linux-2.6.16.12/fs/binfmt_aout.c
6444--- linux-2.6.16.12/fs/binfmt_aout.c 2006-05-01 15:14:26.000000000 -0400
6445+++ linux-2.6.16.12/fs/binfmt_aout.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 6446@@ -25,6 +25,7 @@
89675291 6447 #include <linux/personality.h>
6448 #include <linux/init.h>
9a4c6ab7 6449 #include <linux/vs_memory.h>
89675291 6450+#include <linux/grsecurity.h>
6451
6452 #include <asm/system.h>
6453 #include <asm/uaccess.h>
9a4c6ab7 6454@@ -124,10 +125,12 @@ static int aout_core_dump(long signr, st
89675291 6455 /* If the size of the dump file exceeds the rlimit, then see what would happen
6456 if we wrote the stack, but not the data area. */
6457 #ifdef __sparc__
6458+ gr_learn_resource(current, RLIMIT_CORE, dump.u_dsize+dump.u_ssize, 1);
6459 if ((dump.u_dsize+dump.u_ssize) >
6460 current->signal->rlim[RLIMIT_CORE].rlim_cur)
6461 dump.u_dsize = 0;
6462 #else
6463+ gr_learn_resource(current, RLIMIT_CORE, (dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE, 1);
6464 if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE >
6465 current->signal->rlim[RLIMIT_CORE].rlim_cur)
6466 dump.u_dsize = 0;
9a4c6ab7 6467@@ -135,10 +138,12 @@ static int aout_core_dump(long signr, st
89675291 6468
6469 /* Make sure we have enough room to write the stack and data areas. */
6470 #ifdef __sparc__
6471+ gr_learn_resource(current, RLIMIT_CORE, dump.u_ssize, 1);
6472 if ((dump.u_ssize) >
6473 current->signal->rlim[RLIMIT_CORE].rlim_cur)
6474 dump.u_ssize = 0;
6475 #else
6476+ gr_learn_resource(current, RLIMIT_CORE, (dump.u_ssize+1) * PAGE_SIZE, 1);
6477 if ((dump.u_ssize+1) * PAGE_SIZE >
6478 current->signal->rlim[RLIMIT_CORE].rlim_cur)
6479 dump.u_ssize = 0;
9a4c6ab7 6480@@ -288,6 +293,8 @@ static int load_aout_binary(struct linux
89675291 6481 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
6482 if (rlim >= RLIM_INFINITY)
6483 rlim = ~0;
6484+
6485+ gr_learn_resource(current, RLIMIT_DATA, ex.a_data + ex.a_bss, 1);
6486 if (ex.a_data + ex.a_bss > rlim)
6487 return -ENOMEM;
6488
9a4c6ab7 6489@@ -320,6 +327,28 @@ static int load_aout_binary(struct linux
89675291 6490 current->mm->mmap = NULL;
6491 compute_creds(bprm);
6492 current->flags &= ~PF_FORKNOEXEC;
6493+
6494+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
6495+ current->mm->pax_flags = 0UL;
6496+#endif
6497+
6498+#ifdef CONFIG_PAX_PAGEEXEC
6499+ if (!(N_FLAGS(ex) & F_PAX_PAGEEXEC)) {
6500+ current->mm->pax_flags |= MF_PAX_PAGEEXEC;
6501+
6502+#ifdef CONFIG_PAX_EMUTRAMP
6503+ if (N_FLAGS(ex) & F_PAX_EMUTRAMP)
6504+ current->mm->pax_flags |= MF_PAX_EMUTRAMP;
6505+#endif
6506+
6507+#ifdef CONFIG_PAX_MPROTECT
6508+ if (!(N_FLAGS(ex) & F_PAX_MPROTECT))
6509+ current->mm->pax_flags |= MF_PAX_MPROTECT;
6510+#endif
6511+
6512+ }
6513+#endif
6514+
6515 #ifdef __sparc__
6516 if (N_MAGIC(ex) == NMAGIC) {
6517 loff_t pos = fd_offset;
9a4c6ab7 6518@@ -415,7 +444,7 @@ static int load_aout_binary(struct linux
89675291 6519
6520 down_write(&current->mm->mmap_sem);
6521 error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
6522- PROT_READ | PROT_WRITE | PROT_EXEC,
6523+ PROT_READ | PROT_WRITE,
6524 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
6525 fd_offset + ex.a_text);
6526 up_write(&current->mm->mmap_sem);
6527diff -urNp linux-2.6.16.12/fs/binfmt_elf.c linux-2.6.16.12/fs/binfmt_elf.c
6528--- linux-2.6.16.12/fs/binfmt_elf.c 2006-05-01 15:14:26.000000000 -0400
6529+++ linux-2.6.16.12/fs/binfmt_elf.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 6530@@ -39,11 +39,16 @@
89675291 6531 #include <linux/syscalls.h>
6532 #include <linux/random.h>
9a4c6ab7 6533 #include <linux/vs_memory.h>
89675291 6534+#include <linux/grsecurity.h>
6535
6536 #include <asm/uaccess.h>
6537 #include <asm/param.h>
6538 #include <asm/page.h>
6539
6540+#ifdef CONFIG_PAX_SEGMEXEC
6541+#include <asm/desc.h>
6542+#endif
6543+
6544 #include <linux/elf.h>
6545
6546 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
9a4c6ab7 6547@@ -91,6 +96,8 @@ static struct linux_binfmt elf_format =
89675291 6548
6549 static int set_brk(unsigned long start, unsigned long end)
6550 {
6551+ unsigned long e = end;
6552+
6553 start = ELF_PAGEALIGN(start);
6554 end = ELF_PAGEALIGN(end);
6555 if (end > start) {
9a4c6ab7 6556@@ -101,7 +108,7 @@ static int set_brk(unsigned long start,
89675291 6557 if (BAD_ADDR(addr))
6558 return addr;
6559 }
6560- current->mm->start_brk = current->mm->brk = end;
6561+ current->mm->start_brk = current->mm->brk = e;
6562 return 0;
6563 }
6564
9a4c6ab7 6565@@ -317,10 +324,9 @@ static unsigned long load_elf_interp(str
89675291 6566 {
6567 struct elf_phdr *elf_phdata;
6568 struct elf_phdr *eppnt;
6569- unsigned long load_addr = 0;
6570- int load_addr_set = 0;
6571+ unsigned long load_addr = 0, min_addr, max_addr, task_size = TASK_SIZE;
6572 unsigned long last_bss = 0, elf_bss = 0;
6573- unsigned long error = ~0UL;
6574+ unsigned long error = -EINVAL;
6575 int retval, i, size;
6576
6577 /* First of all, some simple consistency checks */
9a4c6ab7 6578@@ -359,59 +365,80 @@ static unsigned long load_elf_interp(str
89675291 6579 goto out_close;
6580 }
6581
6582+#ifdef CONFIG_PAX_SEGMEXEC
6583+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
6584+ task_size = SEGMEXEC_TASK_SIZE;
6585+#endif
6586+
6587 eppnt = elf_phdata;
6588+ min_addr = task_size;
6589+ max_addr = 0;
6590+ error = -ENOMEM;
6591+
6592 for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
6593- if (eppnt->p_type == PT_LOAD) {
6594- int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
6595- int elf_prot = 0;
6596- unsigned long vaddr = 0;
6597- unsigned long k, map_addr;
6598-
6599- if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
6600- if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
6601- if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
6602- vaddr = eppnt->p_vaddr;
6603- if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)
6604- elf_type |= MAP_FIXED;
6605-
6606- map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
6607- error = map_addr;
6608- if (BAD_ADDR(map_addr))
6609- goto out_close;
6610-
6611- if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
6612- load_addr = map_addr - ELF_PAGESTART(vaddr);
6613- load_addr_set = 1;
6614- }
6615-
6616- /*
6617- * Check to see if the section's size will overflow the
6618- * allowed task size. Note that p_filesz must always be
6619- * <= p_memsize so it is only necessary to check p_memsz.
6620- */
6621- k = load_addr + eppnt->p_vaddr;
6622- if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz ||
6623- eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) {
6624- error = -ENOMEM;
6625+ if (eppnt->p_type != PT_LOAD)
6626+ continue;
6627+
6628+ /*
6629+ * Check to see if the section's size will overflow the
6630+ * allowed task size. Note that p_filesz must always be
6631+ * <= p_memsize so it is only necessary to check p_memsz.
6632+ */
6633+ if (eppnt->p_filesz > eppnt->p_memsz || eppnt->p_vaddr >= eppnt->p_vaddr + eppnt->p_memsz)
6634+ goto out_close;
6635+
6636+ if (min_addr > ELF_PAGESTART(eppnt->p_vaddr))
6637+ min_addr = ELF_PAGESTART(eppnt->p_vaddr);
6638+ if (max_addr < ELF_PAGEALIGN(eppnt->p_vaddr + eppnt->p_memsz))
6639+ max_addr = ELF_PAGEALIGN(eppnt->p_vaddr + eppnt->p_memsz);
6640+ }
6641+ if (min_addr >= max_addr)
6642 goto out_close;
6643- }
6644
6645- /*
6646- * Find the end of the file mapping for this phdr, and keep
6647- * track of the largest address we see for this.
6648- */
6649- k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
6650- if (k > elf_bss)
6651- elf_bss = k;
6652-
6653- /*
6654- * Do the same thing for the memory mapping - between
6655- * elf_bss and last_bss is the bss section.
6656- */
6657- k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
6658- if (k > last_bss)
6659- last_bss = k;
6660- }
6661+ eppnt = elf_phdata;
6662+ for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
6663+ int elf_type = MAP_PRIVATE | MAP_DENYWRITE | MAP_FIXED;
6664+ int elf_prot = 0;
6665+ unsigned long vaddr;
6666+ unsigned long k, map_addr;
6667+
6668+ if (eppnt->p_type != PT_LOAD)
6669+ continue;
6670+
6671+ if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
6672+ if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
6673+ if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
6674+ vaddr = eppnt->p_vaddr;
6675+
6676+ if (!load_addr && interp_elf_ex->e_type == ET_DYN) {
6677+ load_addr = get_unmapped_area(interpreter, 0, max_addr - min_addr, 0, MAP_PRIVATE | MAP_EXECUTABLE);
6678+
6679+ if (load_addr > task_size)
6680+ goto out_close;
6681+
6682+ load_addr -= min_addr;
6683+ }
6684+
6685+ map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
6686+ error = map_addr;
6687+ if (BAD_ADDR(map_addr))
6688+ goto out_close;
6689+
6690+ /*
6691+ * Find the end of the file mapping for this phdr, and keep
6692+ * track of the largest address we see for this.
6693+ */
6694+ k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
6695+ if (k > elf_bss)
6696+ elf_bss = k;
6697+
6698+ /*
6699+ * Do the same thing for the memory mapping - between
6700+ * elf_bss and last_bss is the bss section.
6701+ */
6702+ k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
6703+ if (k > last_bss)
6704+ last_bss = k;
6705 }
6706
6707 /*
9a4c6ab7 6708@@ -448,7 +475,7 @@ out:
89675291 6709 static unsigned long load_aout_interp(struct exec * interp_ex,
6710 struct file * interpreter)
6711 {
6712- unsigned long text_data, elf_entry = ~0UL;
6713+ unsigned long text_data, elf_entry = -EINVAL;
6714 char __user * addr;
6715 loff_t offset;
6716
9a4c6ab7 6717@@ -492,6 +519,180 @@ out:
89675291 6718 return elf_entry;
6719 }
6720
6721+#if (defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)) && defined(CONFIG_PAX_SOFTMODE)
6722+static unsigned long pax_parse_softmode(const struct elf_phdr * const elf_phdata)
6723+{
6724+ unsigned long pax_flags = 0UL;
6725+
6726+#ifdef CONFIG_PAX_PAGEEXEC
6727+ if (elf_phdata->p_flags & PF_PAGEEXEC)
6728+ pax_flags |= MF_PAX_PAGEEXEC;
6729+#endif
6730+
6731+#ifdef CONFIG_PAX_SEGMEXEC
6732+ if (elf_phdata->p_flags & PF_SEGMEXEC)
6733+ pax_flags |= MF_PAX_SEGMEXEC;
6734+#endif
6735+
6736+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
6737+ if (pax_flags & MF_PAX_PAGEEXEC)
6738+ pax_flags &= ~MF_PAX_SEGMEXEC;
6739+#endif
6740+
6741+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
6742+ if (pax_flags & MF_PAX_SEGMEXEC)
6743+ pax_flags &= ~MF_PAX_PAGEEXEC;
6744+#endif
6745+
6746+#ifdef CONFIG_PAX_EMUTRAMP
6747+ if (elf_phdata->p_flags & PF_EMUTRAMP)
6748+ pax_flags |= MF_PAX_EMUTRAMP;
6749+#endif
6750+
6751+#ifdef CONFIG_PAX_MPROTECT
6752+ if (elf_phdata->p_flags & PF_MPROTECT)
6753+ pax_flags |= MF_PAX_MPROTECT;
6754+#endif
6755+
6756+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
6757+ if (randomize_va_space && (elf_phdata->p_flags & PF_RANDMMAP))
6758+ pax_flags |= MF_PAX_RANDMMAP;
6759+#endif
6760+
6761+ return pax_flags;
6762+}
6763+#endif
6764+
6765+#ifdef CONFIG_PAX_PT_PAX_FLAGS
6766+static unsigned long pax_parse_hardmode(const struct elf_phdr * const elf_phdata)
6767+{
6768+ unsigned long pax_flags = 0UL;
6769+
6770+#ifdef CONFIG_PAX_PAGEEXEC
6771+ if (!(elf_phdata->p_flags & PF_NOPAGEEXEC))
6772+ pax_flags |= MF_PAX_PAGEEXEC;
6773+#endif
6774+
6775+#ifdef CONFIG_PAX_SEGMEXEC
6776+ if (!(elf_phdata->p_flags & PF_NOSEGMEXEC))
6777+ pax_flags |= MF_PAX_SEGMEXEC;
6778+#endif
6779+
6780+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
6781+ if (pax_flags & MF_PAX_PAGEEXEC)
6782+ pax_flags &= ~MF_PAX_SEGMEXEC;
6783+#endif
6784+
6785+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
6786+ if (pax_flags & MF_PAX_SEGMEXEC)
6787+ pax_flags &= ~MF_PAX_PAGEEXEC;
6788+#endif
6789+
6790+#ifdef CONFIG_PAX_EMUTRAMP
6791+ if (!(elf_phdata->p_flags & PF_NOEMUTRAMP))
6792+ pax_flags |= MF_PAX_EMUTRAMP;
6793+#endif
6794+
6795+#ifdef CONFIG_PAX_MPROTECT
6796+ if (!(elf_phdata->p_flags & PF_NOMPROTECT))
6797+ pax_flags |= MF_PAX_MPROTECT;
6798+#endif
6799+
6800+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK)
6801+ if (randomize_va_space && !(elf_phdata->p_flags & PF_NORANDMMAP))
6802+ pax_flags |= MF_PAX_RANDMMAP;
6803+#endif
6804+
6805+ return pax_flags;
6806+}
6807+#endif
6808+
6809+#ifdef CONFIG_PAX_EI_PAX
6810+static unsigned long pax_parse_ei_pax(const struct elfhdr * const elf_ex)
6811+{
6812+ unsigned long pax_flags = 0UL;
6813+
6814+#ifdef CONFIG_PAX_PAGEEXEC
6815+ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_PAGEEXEC))
6816+ pax_flags |= MF_PAX_PAGEEXEC;
6817+#endif
6818+
6819+#ifdef CONFIG_PAX_SEGMEXEC
6820+ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_SEGMEXEC))
6821+ pax_flags |= MF_PAX_SEGMEXEC;
6822+#endif
6823+
6824+#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
6825+ if (pax_flags & MF_PAX_PAGEEXEC)
6826+ pax_flags &= ~MF_PAX_SEGMEXEC;
6827+#endif
6828+
6829+#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
6830+ if (pax_flags & MF_PAX_SEGMEXEC)
6831+ pax_flags &= ~MF_PAX_PAGEEXEC;
6832+#endif
6833+
6834+#ifdef CONFIG_PAX_EMUTRAMP
6835+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && (elf_ex->e_ident[EI_PAX] & EF_PAX_EMUTRAMP))
6836+ pax_flags |= MF_PAX_EMUTRAMP;
6837+#endif
6838+
6839+#ifdef CONFIG_PAX_MPROTECT
6840+ if ((pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) && !(elf_ex->e_ident[EI_PAX] & EF_PAX_MPROTECT))
6841+ pax_flags |= MF_PAX_MPROTECT;
6842+#endif
6843+
6844+#ifdef CONFIG_PAX_ASLR
6845+ if (randomize_va_space && !(elf_ex->e_ident[EI_PAX] & EF_PAX_RANDMMAP))
6846+ pax_flags |= MF_PAX_RANDMMAP;
6847+#endif
6848+
6849+ return pax_flags;
6850+}
6851+#endif
6852+
6853+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)
6854+static long pax_parse_elf_flags(const struct elfhdr * const elf_ex, const struct elf_phdr * const elf_phdata)
6855+{
6856+ unsigned long pax_flags = 0UL;
6857+
6858+#ifdef CONFIG_PAX_PT_PAX_FLAGS
6859+ unsigned long i;
6860+#endif
6861+
6862+#ifdef CONFIG_PAX_EI_PAX
6863+ pax_flags = pax_parse_ei_pax(elf_ex);
6864+#endif
6865+
6866+#ifdef CONFIG_PAX_PT_PAX_FLAGS
6867+ for (i = 0UL; i < elf_ex->e_phnum; i++)
6868+ if (elf_phdata[i].p_type == PT_PAX_FLAGS) {
6869+ if (((elf_phdata[i].p_flags & PF_PAGEEXEC) && (elf_phdata[i].p_flags & PF_NOPAGEEXEC)) ||
6870+ ((elf_phdata[i].p_flags & PF_SEGMEXEC) && (elf_phdata[i].p_flags & PF_NOSEGMEXEC)) ||
6871+ ((elf_phdata[i].p_flags & PF_EMUTRAMP) && (elf_phdata[i].p_flags & PF_NOEMUTRAMP)) ||
6872+ ((elf_phdata[i].p_flags & PF_MPROTECT) && (elf_phdata[i].p_flags & PF_NOMPROTECT)) ||
6873+ ((elf_phdata[i].p_flags & PF_RANDMMAP) && (elf_phdata[i].p_flags & PF_NORANDMMAP)))
6874+ return -EINVAL;
6875+
6876+#ifdef CONFIG_PAX_SOFTMODE
6877+ if (pax_softmode)
6878+ pax_flags = pax_parse_softmode(&elf_phdata[i]);
6879+ else
6880+#endif
6881+
6882+ pax_flags = pax_parse_hardmode(&elf_phdata[i]);
6883+ break;
6884+ }
6885+#endif
6886+
6887+ if (0 > pax_check_flags(&pax_flags))
6888+ return -EINVAL;
6889+
6890+ current->mm->pax_flags = pax_flags;
6891+ return 0;
6892+}
6893+#endif
6894+
6895 /*
6896 * These are the functions used to load ELF style executables and shared
6897 * libraries. There is no binary dependent code anywhere else.
9a4c6ab7 6898@@ -523,7 +724,7 @@ static int load_elf_binary(struct linux_
89675291 6899 char * elf_interpreter = NULL;
6900 unsigned int interpreter_type = INTERPRETER_NONE;
6901 unsigned char ibcs2_interpreter = 0;
6902- unsigned long error;
6903+ unsigned long error = 0;
6904 struct elf_phdr * elf_ppnt, *elf_phdata;
6905 unsigned long elf_bss, elf_brk;
6906 int elf_exec_fileno;
9a4c6ab7 6907@@ -541,6 +742,7 @@ static int load_elf_binary(struct linux_
89675291 6908 struct elfhdr interp_elf_ex;
6909 struct exec interp_ex;
6910 } *loc;
6911+ unsigned long task_size = TASK_SIZE;
6912
6913 loc = kmalloc(sizeof(*loc), GFP_KERNEL);
6914 if (!loc) {
9a4c6ab7 6915@@ -766,14 +968,88 @@ static int load_elf_binary(struct linux_
89675291 6916 current->mm->end_code = 0;
6917 current->mm->mmap = NULL;
6918 current->flags &= ~PF_FORKNOEXEC;
6919+
6920+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
6921+ current->mm->pax_flags = 0UL;
6922+#endif
6923+
6924+#ifdef CONFIG_PAX_DLRESOLVE
6925+ current->mm->call_dl_resolve = 0UL;
6926+#endif
6927+
6928+#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
6929+ current->mm->call_syscall = 0UL;
6930+#endif
6931+
6932+#ifdef CONFIG_PAX_ASLR
6933+ current->mm->delta_mmap = 0UL;
6934+ current->mm->delta_exec = 0UL;
6935+ current->mm->delta_stack = 0UL;
6936+#endif
6937+
6938 current->mm->def_flags = def_flags;
6939
6940+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)
6941+ if (0 > pax_parse_elf_flags(&loc->elf_ex, elf_phdata)) {
6942+ send_sig(SIGKILL, current, 0);
6943+ goto out_free_dentry;
6944+ }
6945+#endif
6946+
6947+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
6948+ pax_set_initial_flags(bprm);
6949+#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
6950+ if (pax_set_initial_flags_func)
6951+ (pax_set_initial_flags_func)(bprm);
6952+#endif
6953+
6954+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
6955+ if (current->mm->pax_flags & MF_PAX_PAGEEXEC)
6956+ current->mm->context.user_cs_limit = PAGE_SIZE;
6957+#endif
6958+
6959+#ifdef CONFIG_PAX_SEGMEXEC
6960+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
6961+ int cpu = get_cpu();
6962+
6963+ current->mm->context.user_cs_base = SEGMEXEC_TASK_SIZE;
6964+ current->mm->context.user_cs_limit = -SEGMEXEC_TASK_SIZE;
6965+ set_user_cs(current->mm, cpu);
6966+ put_cpu();
6967+ task_size = SEGMEXEC_TASK_SIZE;
6968+ }
6969+#endif
6970+
6971+#ifdef CONFIG_PAX_ASLR
6972+ if (current->mm->pax_flags & MF_PAX_RANDMMAP) {
6973+#define pax_delta_mask(delta, lsb, len) (((delta) & ((1UL << (len)) - 1)) << (lsb))
6974+
6975+ current->mm->delta_mmap = pax_delta_mask(pax_get_random_long(), PAX_DELTA_MMAP_LSB(current), PAX_DELTA_MMAP_LEN(current));
6976+ current->mm->delta_exec = pax_delta_mask(pax_get_random_long(), PAX_DELTA_EXEC_LSB(current), PAX_DELTA_EXEC_LEN(current));
6977+ current->mm->delta_stack = pax_delta_mask(pax_get_random_long(), PAX_DELTA_STACK_LSB(current), PAX_DELTA_STACK_LEN(current));
6978+ }
6979+#endif
6980+
6981+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
6982+ if (current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
6983+ executable_stack = EXSTACK_DEFAULT;
6984+#endif
6985+
6986 /* Do this immediately, since STACK_TOP as used in setup_arg_pages
6987 may depend on the personality. */
6988 SET_PERSONALITY(loc->elf_ex, ibcs2_interpreter);
6989+
6990+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
6991+ if (!(current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)))
6992+#endif
6993+
6994 if (elf_read_implies_exec(loc->elf_ex, executable_stack))
6995 current->personality |= READ_IMPLIES_EXEC;
6996
6997+#ifdef CONFIG_PAX_ASLR
6998+ if (!(current->mm->pax_flags & MF_PAX_RANDMMAP))
6999+#endif
7000+
7001 if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
7002 current->flags |= PF_RANDOMIZE;
7003 arch_pick_mmap_layout(current->mm);
9a4c6ab7 7004@@ -845,6 +1121,15 @@ static int load_elf_binary(struct linux_
89675291 7005 base, as well as whatever program they might try to exec. This
7006 is because the brk will follow the loader, and is not movable. */
7007 load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr);
7008+
7009+#ifdef CONFIG_PAX_RANDMMAP
7010+ /* PaX: randomize base address at the default exe base if requested */
7011+ if (current->mm->pax_flags & MF_PAX_RANDMMAP) {
7012+ load_bias = ELF_PAGESTART(PAX_ELF_ET_DYN_BASE(current) - vaddr + current->mm->delta_exec);
7013+ elf_flags |= MAP_FIXED;
7014+ }
7015+#endif
7016+
7017 }
7018
7019 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
9a4c6ab7 7020@@ -872,9 +1157,9 @@ static int load_elf_binary(struct linux_
89675291 7021 * allowed task size. Note that p_filesz must always be
7022 * <= p_memsz so it is only necessary to check p_memsz.
7023 */
7024- if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
7025- elf_ppnt->p_memsz > TASK_SIZE ||
7026- TASK_SIZE - elf_ppnt->p_memsz < k) {
7027+ if (k > task_size || elf_ppnt->p_filesz > elf_ppnt->p_memsz ||
7028+ elf_ppnt->p_memsz > task_size ||
7029+ task_size - elf_ppnt->p_memsz < k) {
7030 /* set_brk can never work. Avoid overflows. */
7031 send_sig(SIGKILL, current, 0);
7032 goto out_free_dentry;
9a4c6ab7 7033@@ -901,6 +1186,12 @@ static int load_elf_binary(struct linux_
89675291 7034 start_data += load_bias;
7035 end_data += load_bias;
7036
7037+#ifdef CONFIG_PAX_RANDMMAP
7038+ if (randomize_va_space)
7039+ elf_brk += PAGE_SIZE + pax_delta_mask(pax_get_random_long(), 4, PAGE_SHIFT);
7040+#undef pax_delta_mask
7041+#endif
7042+
7043 /* Calling set_brk effectively mmaps the pages that we need
7044 * for the bss and break sections. We must do this before
7045 * mapping in the interpreter, to make sure it doesn't wind
9a4c6ab7 7046@@ -929,7 +1220,7 @@ static int load_elf_binary(struct linux_
89675291 7047 printk(KERN_ERR "Unable to load interpreter %.128s\n",
7048 elf_interpreter);
7049 force_sig(SIGSEGV, current);
7050- retval = -ENOEXEC; /* Nobody gets to see this, but.. */
7051+ retval = elf_entry; /* Nobody gets to see this, but.. */
7052 goto out_free_dentry;
7053 }
7054 reloc_func_desc = interp_load_addr;
9a4c6ab7 7055@@ -1153,7 +1444,7 @@ static int dump_seek(struct file *file,
89675291 7056 *
7057 * I think we should skip something. But I am not sure how. H.J.
7058 */
7059-static int maydump(struct vm_area_struct *vma)
7060+static int maydump(struct vm_area_struct *vma, long signr)
7061 {
7062 /* Do not dump I/O mapped devices or special mappings */
7063 if (vma->vm_flags & (VM_IO | VM_RESERVED))
9a4c6ab7 7064@@ -1164,7 +1455,7 @@ static int maydump(struct vm_area_struct
89675291 7065 return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
7066
7067 /* If it hasn't been written to, don't write it out */
7068- if (!vma->anon_vma)
7069+ if (signr != SIGKILL && !vma->anon_vma)
7070 return 0;
7071
7072 return 1;
9a4c6ab7 7073@@ -1218,8 +1509,11 @@ static int writenote(struct memelfnote *
89675291 7074 #undef DUMP_SEEK
7075
7076 #define DUMP_WRITE(addr, nr) \
7077+ do { \
7078+ gr_learn_resource(current, RLIMIT_CORE, size + (nr), 1); \
7079 if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \
7080- goto end_coredump;
7081+ goto end_coredump; \
7082+ } while (0);
7083 #define DUMP_SEEK(off) \
7084 if (!dump_seek(file, (off))) \
7085 goto end_coredump;
9a4c6ab7 7086@@ -1570,7 +1864,7 @@ static int elf_core_dump(long signr, str
89675291 7087 phdr.p_offset = offset;
7088 phdr.p_vaddr = vma->vm_start;
7089 phdr.p_paddr = 0;
7090- phdr.p_filesz = maydump(vma) ? sz : 0;
7091+ phdr.p_filesz = maydump(vma, signr) ? sz : 0;
7092 phdr.p_memsz = sz;
7093 offset += phdr.p_filesz;
7094 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
9a4c6ab7 7095@@ -1603,7 +1897,7 @@ static int elf_core_dump(long signr, str
89675291 7096 for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
7097 unsigned long addr;
7098
7099- if (!maydump(vma))
7100+ if (!maydump(vma, signr))
7101 continue;
7102
7103 for (addr = vma->vm_start;
9a4c6ab7 7104@@ -1622,6 +1916,7 @@ static int elf_core_dump(long signr, str
89675291 7105 void *kaddr;
7106 flush_cache_page(vma, addr, page_to_pfn(page));
7107 kaddr = kmap(page);
7108+ gr_learn_resource(current, RLIMIT_CORE, size + PAGE_SIZE, 1);
7109 if ((size += PAGE_SIZE) > limit ||
7110 !dump_write(file, kaddr,
7111 PAGE_SIZE)) {
7112diff -urNp linux-2.6.16.12/fs/binfmt_flat.c linux-2.6.16.12/fs/binfmt_flat.c
7113--- linux-2.6.16.12/fs/binfmt_flat.c 2006-05-01 15:14:26.000000000 -0400
7114+++ linux-2.6.16.12/fs/binfmt_flat.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 7115@@ -542,7 +542,9 @@ static int load_flat_file(struct linux_b
89675291 7116 realdatastart = (unsigned long) -ENOMEM;
7117 printk("Unable to allocate RAM for process data, errno %d\n",
7118 (int)-datapos);
7119+ down_write(&current->mm->mmap_sem);
7120 do_munmap(current->mm, textpos, text_len);
7121+ up_write(&current->mm->mmap_sem);
7122 return realdatastart;
7123 }
7124 datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
9a4c6ab7 7125@@ -563,8 +565,10 @@ static int load_flat_file(struct linux_b
89675291 7126 }
7127 if (result >= (unsigned long)-4096) {
7128 printk("Unable to read data+bss, errno %d\n", (int)-result);
7129+ down_write(&current->mm->mmap_sem);
7130 do_munmap(current->mm, textpos, text_len);
7131 do_munmap(current->mm, realdatastart, data_len + extra);
7132+ up_write(&current->mm->mmap_sem);
7133 return result;
7134 }
7135
9a4c6ab7 7136@@ -626,8 +630,10 @@ static int load_flat_file(struct linux_b
89675291 7137 }
7138 if (result >= (unsigned long)-4096) {
7139 printk("Unable to read code+data+bss, errno %d\n",(int)-result);
7140+ down_write(&current->mm->mmap_sem);
7141 do_munmap(current->mm, textpos, text_len + data_len + extra +
7142 MAX_SHARED_LIBS * sizeof(unsigned long));
7143+ up_write(&current->mm->mmap_sem);
7144 return result;
7145 }
7146 }
7147diff -urNp linux-2.6.16.12/fs/binfmt_misc.c linux-2.6.16.12/fs/binfmt_misc.c
7148--- linux-2.6.16.12/fs/binfmt_misc.c 2006-05-01 15:14:26.000000000 -0400
7149+++ linux-2.6.16.12/fs/binfmt_misc.c 2006-05-01 20:17:33.000000000 -0400
7150@@ -112,9 +112,11 @@ static int load_misc_binary(struct linux
7151 struct files_struct *files = NULL;
7152
7153 retval = -ENOEXEC;
7154- if (!enabled)
7155+ if (!enabled || bprm->misc)
7156 goto _ret;
7157
7158+ bprm->misc++;
7159+
7160 /* to keep locking time low, we copy the interpreter string */
7161 read_lock(&entries_lock);
7162 fmt = check_file(bprm);
7163diff -urNp linux-2.6.16.12/fs/buffer.c linux-2.6.16.12/fs/buffer.c
7164--- linux-2.6.16.12/fs/buffer.c 2006-05-01 15:14:26.000000000 -0400
7165+++ linux-2.6.16.12/fs/buffer.c 2006-05-01 20:17:33.000000000 -0400
7166@@ -42,6 +42,7 @@
7167 #include <linux/bitops.h>
7168 #include <linux/mpage.h>
7169 #include <linux/bit_spinlock.h>
7170+#include <linux/grsecurity.h>
7171
7172 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
7173 static void invalidate_bh_lrus(void);
7174@@ -2166,6 +2167,7 @@ static int __generic_cont_expand(struct
7175
7176 err = -EFBIG;
7177 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
7178+ gr_learn_resource(current, RLIMIT_FSIZE, (unsigned long) size, 1);
7179 if (limit != RLIM_INFINITY && size > (loff_t)limit) {
7180 send_sig(SIGXFSZ, current, 0);
7181 goto out;
7182diff -urNp linux-2.6.16.12/fs/compat.c linux-2.6.16.12/fs/compat.c
7183--- linux-2.6.16.12/fs/compat.c 2006-05-01 15:14:26.000000000 -0400
7184+++ linux-2.6.16.12/fs/compat.c 2006-05-01 20:17:33.000000000 -0400
7185@@ -46,6 +46,7 @@
7186 #include <linux/rwsem.h>
7187 #include <linux/acct.h>
7188 #include <linux/mm.h>
7189+#include <linux/grsecurity.h>
7190
7191 #include <net/sock.h> /* siocdevprivate_ioctl */
7192
7193@@ -1476,6 +1477,11 @@ int compat_do_execve(char * filename,
7194 struct file *file;
7195 int retval;
7196 int i;
7197+#ifdef CONFIG_GRKERNSEC
7198+ struct file *old_exec_file;
7199+ struct acl_subject_label *old_acl;
7200+ struct rlimit old_rlim[RLIM_NLIMITS];
7201+#endif
7202
7203 retval = -ENOMEM;
7204 bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
7205@@ -1494,6 +1500,15 @@ int compat_do_execve(char * filename,
7206 bprm->file = file;
7207 bprm->filename = filename;
7208 bprm->interp = filename;
7209+
7210+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->user->processes), 1);
7211+ retval = -EAGAIN;
7212+ if (gr_handle_nproc())
7213+ goto out_file;
7214+ retval = -EACCES;
7215+ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt))
7216+ goto out_file;
7217+
7218 bprm->mm = mm_alloc();
7219 retval = -ENOMEM;
7220 if (!bprm->mm)
7221@@ -1532,10 +1547,39 @@ int compat_do_execve(char * filename,
7222 if (retval < 0)
7223 goto out;
7224
7225+ if (!gr_tpe_allow(file)) {
7226+ retval = -EACCES;
7227+ goto out;
7228+ }
7229+
7230+ if (gr_check_crash_exec(file)) {
7231+ retval = -EACCES;
7232+ goto out;
7233+ }
7234+
7235+ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
7236+
7237+ gr_handle_exec_args(bprm, (char __user * __user *)argv);
7238+
7239+#ifdef CONFIG_GRKERNSEC
7240+ old_acl = current->acl;
7241+ memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim));
7242+ old_exec_file = current->exec_file;
7243+ get_file(file);
7244+ current->exec_file = file;
7245+#endif
7246+
7247+ gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
7248+
7249 retval = search_binary_handler(bprm, regs);
7250 if (retval >= 0) {
7251 free_arg_pages(bprm);
7252
7253+#ifdef CONFIG_GRKERNSEC
7254+ if (old_exec_file)
7255+ fput(old_exec_file);
7256+#endif
7257+
7258 /* execve success */
7259 security_bprm_free(bprm);
7260 acct_update_integrals(current);
7261@@ -1543,6 +1587,13 @@ int compat_do_execve(char * filename,
7262 return retval;
7263 }
7264
7265+#ifdef CONFIG_GRKERNSEC
7266+ current->acl = old_acl;
7267+ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim));
7268+ fput(current->exec_file);
7269+ current->exec_file = old_exec_file;
7270+#endif
7271+
7272 out:
7273 /* Something went wrong, return the inode and free the argument pages*/
7274 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
7275diff -urNp linux-2.6.16.12/fs/dcache.c linux-2.6.16.12/fs/dcache.c
7276--- linux-2.6.16.12/fs/dcache.c 2006-05-01 15:14:26.000000000 -0400
7277+++ linux-2.6.16.12/fs/dcache.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 7278@@ -1370,7 +1370,7 @@ already_unhashed:
89675291 7279 *
7280 * "buflen" should be positive. Caller holds the dcache_lock.
7281 */
7282-static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
7283+char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt,
7284 struct dentry *root, struct vfsmount *rootmnt,
7285 char *buffer, int buflen)
7286 {
7287diff -urNp linux-2.6.16.12/fs/exec.c linux-2.6.16.12/fs/exec.c
7288--- linux-2.6.16.12/fs/exec.c 2006-05-01 15:14:26.000000000 -0400
7289+++ linux-2.6.16.12/fs/exec.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 7290@@ -51,6 +51,8 @@
89675291 7291 #include <linux/cn_proc.h>
9a4c6ab7 7292 #include <linux/vs_cvirt.h>
7293 #include <linux/vs_memory.h>
89675291 7294+#include <linux/random.h>
7295+#include <linux/grsecurity.h>
7296
7297 #include <asm/uaccess.h>
7298 #include <asm/mmu_context.h>
9a4c6ab7 7299@@ -69,6 +71,15 @@ EXPORT_SYMBOL(suid_dumpable);
89675291 7300 static struct linux_binfmt *formats;
7301 static DEFINE_RWLOCK(binfmt_lock);
7302
7303+#ifdef CONFIG_PAX_SOFTMODE
7304+unsigned int pax_softmode;
7305+#endif
7306+
7307+#ifdef CONFIG_PAX_HOOK_ACL_FLAGS
7308+void (*pax_set_initial_flags_func)(struct linux_binprm * bprm);
7309+EXPORT_SYMBOL(pax_set_initial_flags_func);
7310+#endif
7311+
7312 int register_binfmt(struct linux_binfmt * fmt)
7313 {
7314 struct linux_binfmt ** tmp = &formats;
9a4c6ab7 7315@@ -314,6 +325,10 @@ void install_arg_page(struct vm_area_str
89675291 7316 if (unlikely(anon_vma_prepare(vma)))
7317 goto out;
7318
7319+#ifdef CONFIG_PAX_SEGMEXEC
7320+ if (page_count(page) == 1)
7321+#endif
7322+
7323 flush_dcache_page(page);
7324 pte = get_locked_pte(mm, address, &ptl);
7325 if (!pte)
9a4c6ab7 7326@@ -323,9 +338,21 @@ void install_arg_page(struct vm_area_str
89675291 7327 goto out;
7328 }
7329 inc_mm_counter(mm, anon_rss);
7330+
7331+#ifdef CONFIG_PAX_SEGMEXEC
7332+ if (page_count(page) == 1)
7333+#endif
7334+
7335 lru_cache_add_active(page);
7336 set_pte_at(mm, address, pte, pte_mkdirty(pte_mkwrite(mk_pte(
7337 page, vma->vm_page_prot))));
7338+
7339+#ifdef CONFIG_PAX_SEGMEXEC
7340+ if (page_count(page) != 1)
7341+ page_add_anon_rmap(page, vma, address);
7342+ else
7343+#endif
7344+
7345 page_add_new_anon_rmap(page, vma, address);
7346 pte_unmap_unlock(pte, ptl);
7347
9a4c6ab7 7348@@ -348,6 +375,10 @@ int setup_arg_pages(struct linux_binprm
89675291 7349 int i, ret;
7350 long arg_size;
7351
7352+#ifdef CONFIG_PAX_SEGMEXEC
7353+ struct vm_area_struct *mpnt_m = NULL;
7354+#endif
7355+
7356 #ifdef CONFIG_STACK_GROWSUP
7357 /* Move the argument and environment strings to the bottom of the
7358 * stack space.
9a4c6ab7 7359@@ -412,6 +443,18 @@ int setup_arg_pages(struct linux_binprm
89675291 7360
7361 memset(mpnt, 0, sizeof(*mpnt));
7362
7363+#ifdef CONFIG_PAX_SEGMEXEC
7364+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (VM_STACK_FLAGS & VM_MAYEXEC)) {
7365+ mpnt_m = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
7366+ if (!mpnt_m) {
7367+ kmem_cache_free(vm_area_cachep, mpnt);
7368+ return -ENOMEM;
7369+ }
7370+
7371+ memset(mpnt_m, 0, sizeof(*mpnt_m));
7372+ }
7373+#endif
7374+
7375 down_write(&mm->mmap_sem);
7376 {
7377 mpnt->vm_mm = mm;
9a4c6ab7 7378@@ -432,14 +475,51 @@ int setup_arg_pages(struct linux_binprm
89675291 7379 else
7380 mpnt->vm_flags = VM_STACK_FLAGS;
7381 mpnt->vm_flags |= mm->def_flags;
7382+
7383+#ifdef CONFIG_PAX_PAGEEXEC
7384+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC))
7385+ mpnt->vm_page_prot = protection_map[(mpnt->vm_flags | VM_EXEC) & 0x7];
7386+ else
7387+#endif
7388+
7389 mpnt->vm_page_prot = protection_map[mpnt->vm_flags & 0x7];
7390 if ((ret = insert_vm_struct(mm, mpnt))) {
7391 up_write(&mm->mmap_sem);
7392 kmem_cache_free(vm_area_cachep, mpnt);
7393+
7394+#ifdef CONFIG_PAX_SEGMEXEC
7395+ if (mpnt_m)
7396+ kmem_cache_free(vm_area_cachep, mpnt_m);
7397+#endif
7398+
7399 return ret;
7400 }
9a4c6ab7 7401 vx_vmpages_sub(mm, mm->total_vm - vma_pages(mpnt));
7402 mm->stack_vm = mm->total_vm;
89675291 7403+
7404+#ifdef CONFIG_PAX_SEGMEXEC
7405+ if (mpnt_m) {
7406+ *mpnt_m = *mpnt;
7407+ if (!(mpnt->vm_flags & VM_EXEC)) {
7408+ mpnt_m->vm_flags &= ~(VM_READ | VM_WRITE | VM_EXEC);
7409+ mpnt_m->vm_page_prot = PAGE_NONE;
7410+ }
7411+ mpnt_m->vm_start += SEGMEXEC_TASK_SIZE;
7412+ mpnt_m->vm_end += SEGMEXEC_TASK_SIZE;
7413+ if ((ret = insert_vm_struct(mm, mpnt_m))) {
7414+ up_write(&mm->mmap_sem);
7415+ kmem_cache_free(vm_area_cachep, mpnt_m);
7416+ return ret;
7417+ }
7418+ mpnt_m->vm_flags |= VM_MIRROR;
7419+ mpnt->vm_flags |= VM_MIRROR;
7420+ mpnt_m->vm_mirror = mpnt->vm_start - mpnt_m->vm_start;
7421+ mpnt->vm_mirror = mpnt_m->vm_start - mpnt->vm_start;
7422+ mpnt_m->vm_pgoff = mpnt->vm_pgoff;
7423+ mm->total_vm += vma_pages(mpnt_m);
7424+ }
7425+#endif
7426+
7427 }
7428
7429 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
9a4c6ab7 7430@@ -447,6 +527,14 @@ int setup_arg_pages(struct linux_binprm
89675291 7431 if (page) {
7432 bprm->page[i] = NULL;
7433 install_arg_page(mpnt, page, stack_base);
7434+
7435+#ifdef CONFIG_PAX_SEGMEXEC
7436+ if (mpnt_m) {
7437+ page_cache_get(page);
7438+ install_arg_page(mpnt_m, page, stack_base + SEGMEXEC_TASK_SIZE);
7439+ }
7440+#endif
7441+
7442 }
7443 stack_base += PAGE_SIZE;
7444 }
9a4c6ab7 7445@@ -1144,6 +1232,11 @@ int do_execve(char * filename,
89675291 7446 struct file *file;
7447 int retval;
7448 int i;
7449+#ifdef CONFIG_GRKERNSEC
7450+ struct file *old_exec_file;
7451+ struct acl_subject_label *old_acl;
7452+ struct rlimit old_rlim[RLIM_NLIMITS];
7453+#endif
7454
7455 retval = -ENOMEM;
7456 bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
9a4c6ab7 7457@@ -1156,10 +1249,29 @@ int do_execve(char * filename,
89675291 7458 if (IS_ERR(file))
7459 goto out_kfree;
7460
7461+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(&current->user->processes), 1);
7462+
7463+ if (gr_handle_nproc()) {
7464+ allow_write_access(file);
7465+ fput(file);
7466+ return -EAGAIN;
7467+ }
7468+
7469+ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) {
7470+ allow_write_access(file);
7471+ fput(file);
7472+ return -EACCES;
7473+ }
7474+
7475 sched_exec();
7476
7477 bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
7478
7479+#ifdef CONFIG_PAX_RANDUSTACK
7480+ if (randomize_va_space)
7481+ bprm->p -= (pax_get_random_long() & ~(sizeof(void *)-1)) & ~PAGE_MASK;
7482+#endif
7483+
7484 bprm->file = file;
7485 bprm->filename = filename;
7486 bprm->interp = filename;
9a4c6ab7 7487@@ -1201,8 +1313,38 @@ int do_execve(char * filename,
89675291 7488 if (retval < 0)
7489 goto out;
7490
7491+ if (!gr_tpe_allow(file)) {
7492+ retval = -EACCES;
7493+ goto out;
7494+ }
7495+
7496+ if (gr_check_crash_exec(file)) {
7497+ retval = -EACCES;
7498+ goto out;
7499+ }
7500+
7501+ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
7502+
7503+ gr_handle_exec_args(bprm, argv);
7504+
7505+#ifdef CONFIG_GRKERNSEC
7506+ old_acl = current->acl;
7507+ memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim));
7508+ old_exec_file = current->exec_file;
7509+ get_file(file);
7510+ current->exec_file = file;
7511+#endif
7512+
7513+ retval = gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
7514+ if (retval < 0)
7515+ goto out_fail;
7516+
7517 retval = search_binary_handler(bprm,regs);
7518 if (retval >= 0) {
7519+#ifdef CONFIG_GRKERNSEC
7520+ if (old_exec_file)
7521+ fput(old_exec_file);
7522+#endif
7523 free_arg_pages(bprm);
7524
7525 /* execve success */
9a4c6ab7 7526@@ -1212,6 +1354,14 @@ int do_execve(char * filename,
89675291 7527 return retval;
7528 }
7529
7530+out_fail:
7531+#ifdef CONFIG_GRKERNSEC
7532+ current->acl = old_acl;
7533+ memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim));
7534+ fput(current->exec_file);
7535+ current->exec_file = old_exec_file;
7536+#endif
7537+
7538 out:
7539 /* Something went wrong, return the inode and free the argument pages*/
7540 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
9a4c6ab7 7541@@ -1372,6 +1522,114 @@ static void format_corename(char *corena
89675291 7542 *out_ptr = 0;
7543 }
7544
7545+int pax_check_flags(unsigned long * flags)
7546+{
7547+ int retval = 0;
7548+
7549+#if !defined(__i386__) || !defined(CONFIG_PAX_SEGMEXEC)
7550+ if (*flags & MF_PAX_SEGMEXEC)
7551+ {
7552+ *flags &= ~MF_PAX_SEGMEXEC;
7553+ retval = -EINVAL;
7554+ }
7555+#endif
7556+
7557+ if ((*flags & MF_PAX_PAGEEXEC)
7558+
7559+#ifdef CONFIG_PAX_PAGEEXEC
7560+ && (*flags & MF_PAX_SEGMEXEC)
7561+#endif
7562+
7563+ )
7564+ {
7565+ *flags &= ~MF_PAX_PAGEEXEC;
7566+ retval = -EINVAL;
7567+ }
7568+
7569+ if ((*flags & MF_PAX_MPROTECT)
7570+
7571+#ifdef CONFIG_PAX_MPROTECT
7572+ && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
7573+#endif
7574+
7575+ )
7576+ {
7577+ *flags &= ~MF_PAX_MPROTECT;
7578+ retval = -EINVAL;
7579+ }
7580+
7581+ if ((*flags & MF_PAX_EMUTRAMP)
7582+
7583+#ifdef CONFIG_PAX_EMUTRAMP
7584+ && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
7585+#endif
7586+
7587+ )
7588+ {
7589+ *flags &= ~MF_PAX_EMUTRAMP;
7590+ retval = -EINVAL;
7591+ }
7592+
7593+ return retval;
7594+}
7595+
7596+EXPORT_SYMBOL(pax_check_flags);
7597+
7598+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
7599+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp)
7600+{
7601+ struct task_struct *tsk = current;
7602+ struct mm_struct *mm = current->mm;
7603+ char* buffer_exec = (char*)__get_free_page(GFP_ATOMIC);
7604+ char* buffer_fault = (char*)__get_free_page(GFP_ATOMIC);
7605+ char* path_exec=NULL;
7606+ char* path_fault=NULL;
7607+ unsigned long start=0UL, end=0UL, offset=0UL;
7608+
7609+ if (buffer_exec && buffer_fault) {
7610+ struct vm_area_struct* vma, * vma_exec=NULL, * vma_fault=NULL;
7611+
7612+ down_read(&mm->mmap_sem);
7613+ vma = mm->mmap;
7614+ while (vma && (!vma_exec || !vma_fault)) {
7615+ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
7616+ vma_exec = vma;
7617+ if (vma->vm_start <= (unsigned long)pc && (unsigned long)pc < vma->vm_end)
7618+ vma_fault = vma;
7619+ vma = vma->vm_next;
7620+ }
7621+ if (vma_exec) {
7622+ path_exec = d_path(vma_exec->vm_file->f_dentry, vma_exec->vm_file->f_vfsmnt, buffer_exec, PAGE_SIZE);
7623+ if (IS_ERR(path_exec))
7624+ path_exec = "<path too long>";
7625+ }
7626+ if (vma_fault) {
7627+ start = vma_fault->vm_start;
7628+ end = vma_fault->vm_end;
7629+ offset = vma_fault->vm_pgoff << PAGE_SHIFT;
7630+ if (vma_fault->vm_file) {
7631+ path_fault = d_path(vma_fault->vm_file->f_dentry, vma_fault->vm_file->f_vfsmnt, buffer_fault, PAGE_SIZE);
7632+ if (IS_ERR(path_fault))
7633+ path_fault = "<path too long>";
7634+ } else
7635+ path_fault = "<anonymous mapping>";
7636+ }
7637+ up_read(&mm->mmap_sem);
7638+ }
7639+ if (tsk->signal->curr_ip)
7640+ 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);
7641+ else
7642+ printk(KERN_ERR "PAX: execution attempt in: %s, %08lx-%08lx %08lx\n", path_fault, start, end, offset);
7643+ printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, "
7644+ "PC: %p, SP: %p\n", path_exec, tsk->comm, tsk->pid,
7645+ tsk->uid, tsk->euid, pc, sp);
7646+ free_page((unsigned long)buffer_exec);
7647+ free_page((unsigned long)buffer_fault);
7648+ pax_report_insns(pc, sp);
7649+ do_coredump(SIGKILL, SIGKILL, regs);
7650+}
7651+#endif
7652+
7653 static void zap_threads (struct mm_struct *mm)
7654 {
7655 struct task_struct *g, *p;
9a4c6ab7 7656@@ -1489,6 +1747,10 @@ int do_coredump(long signr, int exit_cod
89675291 7657 */
7658 clear_thread_flag(TIF_SIGPENDING);
7659
7660+ if (signr == SIGKILL || signr == SIGILL)
7661+ gr_handle_brute_attach(current);
7662+
7663+ gr_learn_resource(current, RLIMIT_CORE, binfmt->min_coredump, 1);
7664 if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
7665 goto fail_unlock;
7666
7667diff -urNp linux-2.6.16.12/fs/fcntl.c linux-2.6.16.12/fs/fcntl.c
7668--- linux-2.6.16.12/fs/fcntl.c 2006-05-01 15:14:26.000000000 -0400
7669+++ linux-2.6.16.12/fs/fcntl.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 7670@@ -19,6 +19,7 @@
89675291 7671 #include <linux/signal.h>
7672 #include <linux/rcupdate.h>
9a4c6ab7 7673 #include <linux/vs_limit.h>
89675291 7674+#include <linux/grsecurity.h>
7675
7676 #include <asm/poll.h>
7677 #include <asm/siginfo.h>
9a4c6ab7 7678@@ -64,6 +65,7 @@ static int locate_fd(struct files_struct
89675291 7679 struct fdtable *fdt;
7680
7681 error = -EINVAL;
7682+ gr_learn_resource(current, RLIMIT_NOFILE, orig_start, 0);
7683 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
7684 goto out;
7685
9a4c6ab7 7686@@ -84,6 +86,7 @@ repeat:
89675291 7687 }
7688
7689 error = -EMFILE;
7690+ gr_learn_resource(current, RLIMIT_NOFILE, newfd, 0);
7691 if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
7692 goto out;
9a4c6ab7 7693 if (!vx_files_avail(1))
7694@@ -146,6 +149,8 @@ asmlinkage long sys_dup2(unsigned int ol
89675291 7695 struct files_struct * files = current->files;
7696 struct fdtable *fdt;
7697
7698+ gr_learn_resource(current, RLIMIT_NOFILE, newfd, 0);
7699+
7700 spin_lock(&files->file_lock);
7701 if (!(file = fcheck(oldfd)))
7702 goto out_unlock;
9a4c6ab7 7703@@ -435,7 +440,8 @@ static inline int sigio_perm(struct task
89675291 7704 return (((fown->euid == 0) ||
7705 (fown->euid == p->suid) || (fown->euid == p->uid) ||
7706 (fown->uid == p->suid) || (fown->uid == p->uid)) &&
7707- !security_file_send_sigiotask(p, fown, sig));
7708+ !security_file_send_sigiotask(p, fown, sig) &&
7709+ !gr_check_protected_task(p) && !gr_pid_is_chrooted(p));
7710 }
7711
7712 static void send_sigio_to_task(struct task_struct *p,
7713diff -urNp linux-2.6.16.12/fs/Kconfig linux-2.6.16.12/fs/Kconfig
7714--- linux-2.6.16.12/fs/Kconfig 2006-05-01 15:14:26.000000000 -0400
7715+++ linux-2.6.16.12/fs/Kconfig 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 7716@@ -796,7 +796,7 @@ config PROC_FS
89675291 7717
7718 config PROC_KCORE
7719 bool "/proc/kcore support" if !ARM
7720- depends on PROC_FS && MMU
7721+ depends on PROC_FS && MMU && !GRKERNSEC_PROC_ADD
7722
7723 config PROC_VMCORE
7724 bool "/proc/vmcore support (EXPERIMENTAL)"
7725diff -urNp linux-2.6.16.12/fs/namei.c linux-2.6.16.12/fs/namei.c
7726--- linux-2.6.16.12/fs/namei.c 2006-05-01 15:14:26.000000000 -0400
7727+++ linux-2.6.16.12/fs/namei.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 7728@@ -36,6 +36,7 @@
7729 #include <linux/vserver/inode.h>
7730 #include <linux/vs_tag.h>
7731 #include <linux/vserver/debug.h>
89675291 7732+#include <linux/grsecurity.h>
7733 #include <asm/namei.h>
7734 #include <asm/uaccess.h>
7735
9a4c6ab7 7736@@ -632,6 +633,13 @@ static inline int do_follow_link(struct
89675291 7737 err = security_inode_follow_link(path->dentry, nd);
7738 if (err)
7739 goto loop;
7740+
7741+ if (gr_handle_follow_link(path->dentry->d_parent->d_inode,
7742+ path->dentry->d_inode, path->dentry, nd->mnt)) {
7743+ err = -EACCES;
7744+ goto loop;
7745+ }
7746+
7747 current->link_count++;
7748 current->total_link_count++;
7749 nd->depth++;
9a4c6ab7 7750@@ -994,11 +1002,18 @@ return_reval:
89675291 7751 break;
7752 }
7753 return_base:
7754+ if (!gr_acl_handle_hidden_file(nd->dentry, nd->mnt)) {
7755+ path_release(nd);
7756+ return -ENOENT;
7757+ }
7758 return 0;
7759 out_dput:
7760 dput_path(&next, nd);
7761 break;
7762 }
7763+ if (!gr_acl_handle_hidden_file(nd->dentry, nd->mnt))
7764+ err = -ENOENT;
7765+
7766 path_release(nd);
7767 return_err:
7768 return err;
9a4c6ab7 7769@@ -1652,6 +1667,17 @@ int open_namei(int dfd, const char *path
89675291 7770 nd, flag);
7771 if (error)
7772 return error;
7773+
7774+ if (gr_handle_rawio(nd->dentry->d_inode)) {
7775+ error = -EPERM;
7776+ goto exit;
7777+ }
7778+
7779+ if (!gr_acl_handle_open(nd->dentry, nd->mnt, flag)) {
7780+ error = -EACCES;
7781+ goto exit;
7782+ }
7783+
7784 goto ok;
7785 }
7786
9a4c6ab7 7787@@ -1686,9 +1712,16 @@ do_last:
89675291 7788
7789 /* Negative dentry, just create the file */
7790 if (!path.dentry->d_inode) {
7791+ if (!gr_acl_handle_creat(path.dentry, nd->dentry, nd->mnt, flag, mode)) {
7792+ error = -EACCES;
7793+ mutex_unlock(&dir->d_inode->i_mutex);
7794+ goto exit_dput;
7795+ }
7796 if (!IS_POSIXACL(dir->d_inode))
7797 mode &= ~current->fs->umask;
7798 error = vfs_create(dir->d_inode, path.dentry, mode, nd);
7799+ if (!error)
7800+ gr_handle_create(path.dentry, nd->mnt);
7801 mutex_unlock(&dir->d_inode->i_mutex);
7802 dput(nd->dentry);
7803 nd->dentry = path.dentry;
9a4c6ab7 7804@@ -1703,6 +1736,23 @@ do_last:
89675291 7805 /*
7806 * It already exists.
7807 */
7808+
7809+ if (gr_handle_rawio(path.dentry->d_inode)) {
7810+ mutex_unlock(&dir->d_inode->i_mutex);
7811+ error = -EPERM;
7812+ goto exit_dput;
7813+ }
7814+ if (!gr_acl_handle_open(path.dentry, nd->mnt, flag)) {
7815+ mutex_unlock(&dir->d_inode->i_mutex);
7816+ error = -EACCES;
7817+ goto exit_dput;
7818+ }
7819+ if (gr_handle_fifo(path.dentry, nd->mnt, dir, flag, acc_mode)) {
7820+ mutex_unlock(&dir->d_inode->i_mutex);
7821+ error = -EACCES;
7822+ goto exit_dput;
7823+ }
7824+
7825 mutex_unlock(&dir->d_inode->i_mutex);
7826
7827 error = -EEXIST;
9a4c6ab7 7828@@ -1768,6 +1818,13 @@ do_link:
89675291 7829 error = security_inode_follow_link(path.dentry, nd);
7830 if (error)
7831 goto exit_dput;
7832+
7833+ if (gr_handle_follow_link(path.dentry->d_parent->d_inode, path.dentry->d_inode,
7834+ path.dentry, nd->mnt)) {
7835+ error = -EACCES;
7836+ goto exit_dput;
7837+ }
7838+
7839 error = __do_follow_link(&path, nd);
7840 if (error)
7841 return error;
9a4c6ab7 7842@@ -1889,6 +1946,22 @@ asmlinkage long sys_mknodat(int dfd, con
89675291 7843 if (!IS_POSIXACL(nd.dentry->d_inode))
7844 mode &= ~current->fs->umask;
7845 if (!IS_ERR(dentry)) {
7846+ if (gr_handle_chroot_mknod(dentry, nd.mnt, mode)) {
7847+ error = -EPERM;
7848+ dput(dentry);
7849+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
7850+ path_release(&nd);
7851+ goto out;
7852+ }
7853+
7854+ if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) {
7855+ error = -EACCES;
7856+ dput(dentry);
7857+ mutex_unlock(&nd.dentry->d_inode->i_mutex);
7858+ path_release(&nd);
7859+ goto out;
7860+ }
7861+
7862 switch (mode & S_IFMT) {
7863 case 0: case S_IFREG:
7864 error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
9a4c6ab7 7865@@ -1907,6 +1980,10 @@ asmlinkage long sys_mknodat(int dfd, con
89675291 7866 default:
7867 error = -EINVAL;
7868 }
7869+
7870+ if (!error)
7871+ gr_handle_create(dentry, nd.mnt);
7872+
7873 dput(dentry);
7874 }
7875 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9a4c6ab7 7876@@ -1962,10 +2039,19 @@ asmlinkage long sys_mkdirat(int dfd, con
89675291 7877 dentry = lookup_create(&nd, 1);
7878 error = PTR_ERR(dentry);
7879 if (!IS_ERR(dentry)) {
7880+ error = 0;
7881 if (!IS_POSIXACL(nd.dentry->d_inode))
7882 mode &= ~current->fs->umask;
9a4c6ab7 7883- error = vfs_mkdir(nd.dentry->d_inode, dentry,
7884- mode, &nd);
89675291 7885+
7886+ if (!gr_acl_handle_mkdir(dentry, nd.dentry, nd.mnt))
7887+ error = -EACCES;
7888+
7889+ if (!error)
9a4c6ab7 7890+ error = vfs_mkdir(nd.dentry->d_inode, dentry,
7891+ mode, &nd);
89675291 7892+ if (!error)
7893+ gr_handle_create(dentry, nd.mnt);
7894+
7895 dput(dentry);
7896 }
7897 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9a4c6ab7 7898@@ -2050,6 +2136,8 @@ static long do_rmdir(int dfd, const char
89675291 7899 char * name;
7900 struct dentry *dentry;
7901 struct nameidata nd;
7902+ ino_t saved_ino = 0;
7903+ dev_t saved_dev = 0;
7904
7905 name = getname(pathname);
7906 if(IS_ERR(name))
9a4c6ab7 7907@@ -2074,7 +2162,21 @@ static long do_rmdir(int dfd, const char
89675291 7908 dentry = lookup_hash(&nd);
7909 error = PTR_ERR(dentry);
7910 if (!IS_ERR(dentry)) {
9a4c6ab7 7911- error = vfs_rmdir(nd.dentry->d_inode, dentry, &nd);
89675291 7912+ error = 0;
7913+ if (dentry->d_inode) {
7914+ if (dentry->d_inode->i_nlink <= 1) {
7915+ saved_ino = dentry->d_inode->i_ino;
7916+ saved_dev = dentry->d_inode->i_sb->s_dev;
7917+ }
7918+
7919+ if (!gr_acl_handle_rmdir(dentry, nd.mnt))
7920+ error = -EACCES;
7921+ }
7922+
7923+ if (!error)
9a4c6ab7 7924+ error = vfs_rmdir(nd.dentry->d_inode, dentry, &nd);
89675291 7925+ if (!error && (saved_dev || saved_ino))
7926+ gr_handle_delete(saved_ino, saved_dev);
7927 dput(dentry);
7928 }
7929 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9a4c6ab7 7930@@ -2134,6 +2236,8 @@ static long do_unlinkat(int dfd, const c
89675291 7931 struct dentry *dentry;
7932 struct nameidata nd;
7933 struct inode *inode = NULL;
7934+ ino_t saved_ino = 0;
7935+ dev_t saved_dev = 0;
7936
7937 name = getname(pathname);
7938 if(IS_ERR(name))
9a4c6ab7 7939@@ -2149,13 +2253,26 @@ static long do_unlinkat(int dfd, const c
89675291 7940 dentry = lookup_hash(&nd);
7941 error = PTR_ERR(dentry);
7942 if (!IS_ERR(dentry)) {
7943+ error = 0;
7944 /* Why not before? Because we want correct error value */
7945 if (nd.last.name[nd.last.len])
7946 goto slashes;
7947 inode = dentry->d_inode;
7948- if (inode)
7949+ if (inode) {
7950+ if (inode->i_nlink <= 1) {
7951+ saved_ino = inode->i_ino;
7952+ saved_dev = inode->i_sb->s_dev;
7953+ }
7954+
7955+ if (!gr_acl_handle_unlink(dentry, nd.mnt))
7956+ error = -EACCES;
7957+
7958 atomic_inc(&inode->i_count);
9a4c6ab7 7959- error = vfs_unlink(nd.dentry->d_inode, dentry, &nd);
89675291 7960+ }
7961+ if (!error)
9a4c6ab7 7962+ error = vfs_unlink(nd.dentry->d_inode, dentry, &nd);
89675291 7963+ if (!error && (saved_ino || saved_dev))
7964+ gr_handle_delete(saved_ino, saved_dev);
7965 exit2:
7966 dput(dentry);
7967 }
9a4c6ab7 7968@@ -2234,8 +2351,16 @@ asmlinkage long sys_symlinkat(const char
89675291 7969 dentry = lookup_create(&nd, 0);
7970 error = PTR_ERR(dentry);
7971 if (!IS_ERR(dentry)) {
9a4c6ab7 7972- error = vfs_symlink(nd.dentry->d_inode, dentry,
7973- from, S_IALLUGO, &nd);
89675291 7974+ error = 0;
7975+ if (!gr_acl_handle_symlink(dentry, nd.dentry, nd.mnt, from))
7976+ error = -EACCES;
7977+
7978+ if (!error)
9a4c6ab7 7979+ error = vfs_symlink(nd.dentry->d_inode, dentry,
7980+ from, S_IALLUGO, &nd);
89675291 7981+
7982+ if (!error)
7983+ gr_handle_create(dentry, nd.mnt);
7984 dput(dentry);
7985 }
7986 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9a4c6ab7 7987@@ -2328,8 +2453,21 @@ asmlinkage long sys_linkat(int olddfd, c
89675291 7988 new_dentry = lookup_create(&nd, 0);
7989 error = PTR_ERR(new_dentry);
7990 if (!IS_ERR(new_dentry)) {
9a4c6ab7 7991- error = vfs_link(old_nd.dentry, nd.dentry->d_inode,
7992- new_dentry, &nd);
89675291 7993+ error = 0;
7994+ if (gr_handle_hardlink(old_nd.dentry, old_nd.mnt,
7995+ old_nd.dentry->d_inode,
7996+ old_nd.dentry->d_inode->i_mode, to))
7997+ error = -EPERM;
7998+ if (!gr_acl_handle_link(new_dentry, nd.dentry, nd.mnt,
7999+ old_nd.dentry, old_nd.mnt, to))
8000+ error = -EACCES;
8001+ if (!error)
9a4c6ab7 8002+ error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry,
8003+ &nd);
89675291 8004+
8005+ if (!error)
8006+ gr_handle_create(new_dentry, nd.mnt);
8007+
8008 dput(new_dentry);
8009 }
8010 mutex_unlock(&nd.dentry->d_inode->i_mutex);
9a4c6ab7 8011@@ -2558,8 +2696,16 @@ static int do_rename(int olddfd, const c
89675291 8012 if (new_dentry == trap)
8013 goto exit5;
8014
8015- error = vfs_rename(old_dir->d_inode, old_dentry,
8016+ error = gr_acl_handle_rename(new_dentry, newnd.dentry, newnd.mnt,
8017+ old_dentry, old_dir->d_inode, oldnd.mnt,
8018+ newname);
8019+
8020+ if (!error)
8021+ error = vfs_rename(old_dir->d_inode, old_dentry,
8022 new_dir->d_inode, new_dentry);
8023+ if (!error)
8024+ gr_handle_rename(old_dir->d_inode, newnd.dentry->d_inode, old_dentry,
8025+ new_dentry, oldnd.mnt, new_dentry->d_inode ? 1 : 0);
8026 exit5:
8027 dput(new_dentry);
8028 exit4:
8029diff -urNp linux-2.6.16.12/fs/namespace.c linux-2.6.16.12/fs/namespace.c
8030--- linux-2.6.16.12/fs/namespace.c 2006-05-01 15:14:26.000000000 -0400
8031+++ linux-2.6.16.12/fs/namespace.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 8032@@ -25,6 +25,8 @@
89675291 8033 #include <linux/mount.h>
9a4c6ab7 8034 #include <linux/vserver/namespace.h>
8035 #include <linux/vserver/tag.h>
89675291 8036+#include <linux/sched.h>
8037+#include <linux/grsecurity.h>
8038 #include <asm/uaccess.h>
8039 #include <asm/unistd.h>
8040 #include "pnode.h"
9a4c6ab7 8041@@ -630,6 +632,8 @@ static int do_umount(struct vfsmount *mn
89675291 8042 DQUOT_OFF(sb);
8043 retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
8044 unlock_kernel();
8045+
8046+ gr_log_remount(mnt->mnt_devname, retval);
8047 }
8048 up_write(&sb->s_umount);
8049 return retval;
9a4c6ab7 8050@@ -650,6 +654,9 @@ static int do_umount(struct vfsmount *mn
89675291 8051 security_sb_umount_busy(mnt);
8052 up_write(&namespace_sem);
8053 release_mounts(&umount_list);
8054+
8055+ gr_log_unmount(mnt->mnt_devname, retval);
8056+
8057 return retval;
8058 }
8059
9a4c6ab7 8060@@ -1400,6 +1407,11 @@ long do_mount(char *dev_name, char *dir_
89675291 8061 if (retval)
8062 goto dput_out;
8063
8064+ if (gr_handle_chroot_mount(nd.dentry, nd.mnt, dev_name)) {
8065+ retval = -EPERM;
8066+ goto dput_out;
8067+ }
8068+
8069 if (flags & MS_REMOUNT)
8070 retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
9a4c6ab7 8071 data_page, tag);
8072@@ -1414,6 +1426,9 @@ long do_mount(char *dev_name, char *dir_
89675291 8073 dev_name, data_page);
8074 dput_out:
8075 path_release(&nd);
8076+
8077+ gr_log_mount(dev_name, dir_name, retval);
8078+
8079 return retval;
8080 }
8081
9a4c6ab7 8082@@ -1666,6 +1681,9 @@ asmlinkage long sys_pivot_root(const cha
89675291 8083 if (!capable(CAP_SYS_ADMIN))
8084 return -EPERM;
8085
8086+ if (gr_handle_chroot_pivot())
8087+ return -EPERM;
8088+
8089 lock_kernel();
8090
8091 error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
8092diff -urNp linux-2.6.16.12/fs/open.c linux-2.6.16.12/fs/open.c
8093--- linux-2.6.16.12/fs/open.c 2006-05-01 15:14:26.000000000 -0400
8094+++ linux-2.6.16.12/fs/open.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 8095@@ -30,6 +30,7 @@
8096 #include <linux/vs_limit.h>
8097 #include <linux/vs_dlimit.h>
8098 #include <linux/vserver/tag.h>
89675291 8099+#include <linux/grsecurity.h>
8100
8101 #include <asm/unistd.h>
8102
9a4c6ab7 8103@@ -211,6 +212,9 @@ int do_truncate(struct dentry *dentry, l
89675291 8104 if (length < 0)
8105 return -EINVAL;
8106
8107+ if (filp && !gr_acl_handle_truncate(dentry, filp->f_vfsmnt))
8108+ return -EACCES;
8109+
8110 newattrs.ia_size = length;
8111 newattrs.ia_valid = ATTR_SIZE | time_attrs;
8112 if (filp) {
9a4c6ab7 8113@@ -411,6 +415,12 @@ asmlinkage long sys_utime(char __user *
89675291 8114 (error = vfs_permission(&nd, MAY_WRITE)) != 0)
8115 goto dput_and_out;
8116 }
8117+
8118+ if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) {
8119+ error = -EACCES;
8120+ goto dput_and_out;
8121+ }
8122+
8123 mutex_lock(&inode->i_mutex);
8124 error = notify_change(nd.dentry, &newattrs);
8125 mutex_unlock(&inode->i_mutex);
9a4c6ab7 8126@@ -464,6 +474,12 @@ long do_utimes(int dfd, char __user *fil
89675291 8127 (error = vfs_permission(&nd, MAY_WRITE)) != 0)
8128 goto dput_and_out;
8129 }
8130+
8131+ if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) {
8132+ error = -EACCES;
8133+ goto dput_and_out;
8134+ }
8135+
8136 mutex_lock(&inode->i_mutex);
8137 error = notify_change(nd.dentry, &newattrs);
8138 mutex_unlock(&inode->i_mutex);
9a4c6ab7 8139@@ -531,6 +547,10 @@ asmlinkage long sys_faccessat(int dfd, c
8140 && (IS_RDONLY(nd.dentry->d_inode) || MNT_IS_RDONLY(nd.mnt))
89675291 8141 && !special_file(nd.dentry->d_inode->i_mode))
8142 res = -EROFS;
8143+
8144+ if (!res && !gr_acl_handle_access(nd.dentry, nd.mnt, mode))
8145+ res = -EACCES;
8146+
8147 path_release(&nd);
8148 }
8149
9a4c6ab7 8150@@ -559,6 +579,8 @@ asmlinkage long sys_chdir(const char __u
89675291 8151 if (error)
8152 goto dput_and_out;
8153
8154+ gr_log_chdir(nd.dentry, nd.mnt);
8155+
8156 set_fs_pwd(current->fs, nd.mnt, nd.dentry);
8157
8158 dput_and_out:
9a4c6ab7 8159@@ -589,6 +611,13 @@ asmlinkage long sys_fchdir(unsigned int
89675291 8160 goto out_putf;
8161
8162 error = file_permission(file, MAY_EXEC);
8163+
8164+ if (!error && !gr_chroot_fchdir(dentry, mnt))
8165+ error = -EPERM;
8166+
8167+ if (!error)
8168+ gr_log_chdir(dentry, mnt);
8169+
8170 if (!error)
8171 set_fs_pwd(current->fs, mnt, dentry);
8172 out_putf:
9a4c6ab7 8173@@ -614,8 +643,16 @@ asmlinkage long sys_chroot(const char __
89675291 8174 if (!capable(CAP_SYS_CHROOT))
8175 goto dput_and_out;
8176
8177+ if (gr_handle_chroot_chroot(nd.dentry, nd.mnt))
8178+ goto dput_and_out;
8179+
8180 set_fs_root(current->fs, nd.mnt, nd.dentry);
8181 set_fs_altroot();
8182+
8183+ gr_handle_chroot_caps(current);
8184+
8185+ gr_handle_chroot_chdir(nd.dentry, nd.mnt);
8186+
8187 error = 0;
8188 dput_and_out:
8189 path_release(&nd);
9a4c6ab7 8190@@ -644,9 +681,22 @@ asmlinkage long sys_fchmod(unsigned int
89675291 8191 err = -EPERM;
8192 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
8193 goto out_putf;
8194+
8195+ if (!gr_acl_handle_fchmod(dentry, file->f_vfsmnt, mode)) {
8196+ err = -EACCES;
8197+ goto out_putf;
8198+ }
8199+
8200 mutex_lock(&inode->i_mutex);
8201 if (mode == (mode_t) -1)
8202 mode = inode->i_mode;
8203+
8204+ if (gr_handle_chroot_chmod(dentry, file->f_vfsmnt, mode)) {
8205+ err = -EPERM;
8206+ mutex_unlock(&inode->i_mutex);
8207+ goto out_putf;
8208+ }
8209+
8210 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
8211 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
8212 err = notify_change(dentry, &newattrs);
9a4c6ab7 8213@@ -679,9 +729,21 @@ asmlinkage long sys_fchmodat(int dfd, co
89675291 8214 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
8215 goto dput_and_out;
8216
8217+ if (!gr_acl_handle_chmod(nd.dentry, nd.mnt, mode)) {
8218+ error = -EACCES;
8219+ goto dput_and_out;
8220+ };
8221+
8222 mutex_lock(&inode->i_mutex);
8223 if (mode == (mode_t) -1)
8224 mode = inode->i_mode;
8225+
8226+ if (gr_handle_chroot_chmod(nd.dentry, nd.mnt, mode)) {
8227+ error = -EACCES;
8228+ mutex_unlock(&inode->i_mutex);
8229+ goto dput_and_out;
8230+ }
8231+
8232 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
8233 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
8234 error = notify_change(nd.dentry, &newattrs);
9a4c6ab7 8235@@ -716,6 +778,12 @@ static int chown_common(struct dentry *
89675291 8236 error = -EPERM;
8237 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
8238 goto out;
8239+
8240+ if (!gr_acl_handle_chown(dentry, mnt)) {
8241+ error = -EACCES;
8242+ goto out;
8243+ }
8244+
8245 newattrs.ia_valid = ATTR_CTIME;
8246 if (user != (uid_t) -1) {
8247 newattrs.ia_valid |= ATTR_UID;
9a4c6ab7 8248@@ -992,6 +1061,7 @@ repeat:
89675291 8249 * N.B. For clone tasks sharing a files structure, this test
8250 * will limit the total number of files that can be opened.
8251 */
8252+ gr_learn_resource(current, RLIMIT_NOFILE, fd, 0);
8253 if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
8254 goto out;
8255
8256diff -urNp linux-2.6.16.12/fs/proc/array.c linux-2.6.16.12/fs/proc/array.c
8257--- linux-2.6.16.12/fs/proc/array.c 2006-05-01 15:14:26.000000000 -0400
8258+++ linux-2.6.16.12/fs/proc/array.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 8259@@ -306,6 +306,21 @@ static inline char *task_cap(struct task
8260 (unsigned)vx_info_mbcap(vxi, p->cap_effective));
89675291 8261 }
8262
8263+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
8264+static inline char *task_pax(struct task_struct *p, char *buffer)
8265+{
8266+ if (p->mm)
8267+ return buffer + sprintf(buffer, "PaX:\t%c%c%c%c%c\n",
8268+ p->mm->pax_flags & MF_PAX_PAGEEXEC ? 'P' : 'p',
8269+ p->mm->pax_flags & MF_PAX_EMUTRAMP ? 'E' : 'e',
8270+ p->mm->pax_flags & MF_PAX_MPROTECT ? 'M' : 'm',
8271+ p->mm->pax_flags & MF_PAX_RANDMMAP ? 'R' : 'r',
8272+ p->mm->pax_flags & MF_PAX_SEGMEXEC ? 'S' : 's');
8273+ else
8274+ return buffer + sprintf(buffer, "PaX:\t-----\n");
8275+}
8276+#endif
8277+
8278 int proc_pid_status(struct task_struct *task, char * buffer)
8279 {
8280 char * orig = buffer;
9a4c6ab7 8281@@ -370,9 +385,20 @@ int proc_pid_status(struct task_struct *
89675291 8282 #if defined(CONFIG_S390)
8283 buffer = task_show_regs(task, buffer);
8284 #endif
8285+
8286+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
8287+ buffer = task_pax(task, buffer);
8288+#endif
8289+
8290 return buffer - orig;
8291 }
8292
8293+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8294+#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
8295+ (_mm->pax_flags & MF_PAX_RANDMMAP || \
8296+ _mm->pax_flags & MF_PAX_SEGMEXEC))
8297+#endif
8298+
8299 static int do_task_stat(struct task_struct *task, char * buffer, int whole)
8300 {
8301 unsigned long vsize, eip, esp, wchan = ~0UL;
9a4c6ab7 8302@@ -463,6 +489,19 @@ static int do_task_stat(struct task_stru
89675291 8303 stime = task->stime;
8304 }
8305
8306+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8307+ if (PAX_RAND_FLAGS(mm)) {
8308+ eip = 0;
8309+ esp = 0;
8310+ wchan = 0;
8311+ }
8312+#endif
8313+#ifdef CONFIG_GRKERNSEC_HIDESYM
8314+ wchan = 0;
8315+ eip =0;
8316+ esp =0;
8317+#endif
8318+
8319 /* scale priority and nice values from timeslices to -20..20 */
8320 /* to make it look like a "normal" Unix priority/nice value */
8321 priority = task_prio(task);
9a4c6ab7 8322@@ -514,9 +553,15 @@ static int do_task_stat(struct task_stru
89675291 8323 vsize,
8324 mm ? get_mm_rss(mm) : 0,
8325 rsslim,
8326+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8327+ PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->start_code : 0),
8328+ PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->end_code : 0),
8329+ PAX_RAND_FLAGS(mm) ? 0 : (mm ? mm->start_stack : 0),
8330+#else
8331 mm ? mm->start_code : 0,
8332 mm ? mm->end_code : 0,
8333 mm ? mm->start_stack : 0,
8334+#endif
8335 esp,
8336 eip,
8337 /* The signal information here is obsolete.
9a4c6ab7 8338@@ -562,3 +607,14 @@ int proc_pid_statm(struct task_struct *t
89675291 8339 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
8340 size, resident, shared, text, lib, data, 0);
8341 }
8342+
8343+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
8344+int proc_pid_ipaddr(struct task_struct *task, char * buffer)
8345+{
8346+ int len;
8347+
8348+ len = sprintf(buffer, "%u.%u.%u.%u\n", NIPQUAD(task->signal->curr_ip));
8349+ return len;
8350+}
8351+#endif
8352+
8353diff -urNp linux-2.6.16.12/fs/proc/base.c linux-2.6.16.12/fs/proc/base.c
8354--- linux-2.6.16.12/fs/proc/base.c 2006-05-01 15:14:26.000000000 -0400
8355+++ linux-2.6.16.12/fs/proc/base.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 8356@@ -74,6 +74,7 @@
89675291 8357 #include <linux/poll.h>
9a4c6ab7 8358 #include <linux/vs_network.h>
8359 #include <linux/vs_pid.h>
89675291 8360+#include <linux/grsecurity.h>
8361 #include "internal.h"
8362
8363 /*
9a4c6ab7 8364@@ -128,6 +129,9 @@ enum pid_directory_inos {
89675291 8365 #ifdef CONFIG_AUDITSYSCALL
8366 PROC_TGID_LOGINUID,
8367 #endif
8368+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
8369+ PROC_TGID_IPADDR,
8370+#endif
8371 PROC_TGID_OOM_SCORE,
8372 PROC_TGID_OOM_ADJUST,
8373 PROC_TID_INO,
9a4c6ab7 8374@@ -207,6 +211,9 @@ static struct pid_entry tgid_base_stuff[
89675291 8375 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
8376 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
8377 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
8378+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
8379+ E(PROC_TGID_IPADDR, "ipaddr", S_IFREG|S_IRUSR),
8380+#endif
8381 #ifdef CONFIG_MMU
8382 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
8383 #endif
9a4c6ab7 8384@@ -417,7 +424,7 @@ static int proc_task_root_link(struct in
89675291 8385 (task->parent == current && \
8386 (task->ptrace & PT_PTRACED) && \
8387 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
8388- security_ptrace(current,task) == 0))
8389+ security_ptrace(current,task) == 0 && !gr_handle_proc_ptrace(task)))
8390
8391 static int proc_pid_environ(struct task_struct *task, char * buffer)
8392 {
9a4c6ab7 8393@@ -601,9 +608,25 @@ static int proc_check_root(struct inode
89675291 8394
8395 static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
8396 {
8397+ int ret = -EACCES;
8398+ struct task_struct *task;
8399+
8400 if (generic_permission(inode, mask, NULL) != 0)
8401- return -EACCES;
8402- return proc_check_root(inode);
8403+ goto out;
8404+
8405+ ret = proc_check_root(inode);
8406+ if (ret)
8407+ goto out;
8408+
8409+ task = proc_task(inode);
8410+
8411+ if (!task)
8412+ goto out;
8413+
8414+ ret = gr_acl_handle_procpidmem(task);
8415+
8416+out:
8417+ return ret;
8418 }
8419
8420 static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd)
9a4c6ab7 8421@@ -1361,6 +1384,9 @@ static struct inode *proc_pid_make_inode
89675291 8422 }
9a4c6ab7 8423 /* procfs is xid tagged */
8424 inode->i_tag = (tag_t)vx_task_xid(task);
89675291 8425+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
8426+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
8427+#endif
8428 security_task_to_inode(task, inode);
8429
8430 out:
9a4c6ab7 8431@@ -1394,7 +1420,9 @@ static int pid_revalidate(struct dentry
89675291 8432 if (pid_alive(task)) {
8433 if (proc_type(inode) == PROC_TGID_INO || proc_type(inode) == PROC_TID_INO || task_dumpable(task)) {
8434 inode->i_uid = task->euid;
8435+#ifndef CONFIG_GRKERNSEC_PROC_USERGROUP
8436 inode->i_gid = task->egid;
8437+#endif
8438 } else {
8439 inode->i_uid = 0;
8440 inode->i_gid = 0;
9a4c6ab7 8441@@ -1726,6 +1754,12 @@ static struct dentry *proc_pident_lookup
89675291 8442 inode->i_fop = &proc_info_file_operations;
8443 ei->op.proc_read = proc_pid_status;
8444 break;
8445+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
8446+ case PROC_TGID_IPADDR:
8447+ inode->i_fop = &proc_info_file_operations;
8448+ ei->op.proc_read = proc_pid_ipaddr;
8449+ break;
8450+#endif
8451 case PROC_TID_STAT:
8452 inode->i_fop = &proc_info_file_operations;
8453 ei->op.proc_read = proc_tid_stat;
9a4c6ab7 8454@@ -2066,11 +2100,35 @@ struct dentry *proc_pid_lookup(struct in
8455 if (!proc_pid_visible(task, tgid))
8456 goto out_drop_task;
89675291 8457
8458+ if (gr_check_hidden_task(task)) {
8459+ put_task_struct(task);
8460+ goto out;
8461+ }
8462+
8463+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8464+ if (current->uid && (task->uid != current->uid)
8465+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
8466+ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)
8467+#endif
8468+ ) {
8469+ put_task_struct(task);
8470+ goto out;
8471+ }
8472+#endif
8473+
8474 inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
9a4c6ab7 8475 if (!inode)
8476 goto out_drop_task;
89675291 8477
89675291 8478+
8479+#ifdef CONFIG_GRKERNSEC_PROC_USER
8480+ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR;
8481+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8482+ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP;
8483+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
8484+#else
8485 inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
8486+#endif
8487 inode->i_op = &proc_tgid_base_inode_operations;
8488 inode->i_fop = &proc_tgid_base_operations;
8489 inode->i_flags|=S_IMMUTABLE;
9a4c6ab7 8490@@ -2169,6 +2227,9 @@ out:
89675291 8491 static int get_tgid_list(int index, unsigned long version, unsigned int *tgids)
8492 {
8493 struct task_struct *p;
8494+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8495+ struct task_struct *tmp = current;
8496+#endif
8497 int nr_tgids = 0;
8498
8499 index--;
9a4c6ab7 8500@@ -2193,6 +2254,18 @@ static int get_tgid_list(int index, unsi
8501 /* check for context visibility */
8502 if (!proc_pid_visible(p, tgid))
89675291 8503 continue;
8504+ if (gr_pid_is_chrooted(p))
8505+ continue;
8506+ if (gr_check_hidden_task(p))
8507+ continue;
8508+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8509+ if (tmp->uid && (p->uid != tmp->uid)
8510+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
8511+ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)
8512+#endif
8513+ )
8514+ continue;
8515+#endif
8516 if (--index >= 0)
8517 continue;
9a4c6ab7 8518 tgids[nr_tgids] = vx_map_tgid(tgid);
89675291 8519diff -urNp linux-2.6.16.12/fs/proc/inode.c linux-2.6.16.12/fs/proc/inode.c
8520--- linux-2.6.16.12/fs/proc/inode.c 2006-05-01 15:14:26.000000000 -0400
8521+++ linux-2.6.16.12/fs/proc/inode.c 2006-05-01 20:17:33.000000000 -0400
8522@@ -168,7 +168,11 @@ struct inode *proc_get_inode(struct supe
8523 if (de->mode) {
8524 inode->i_mode = de->mode;
8525 inode->i_uid = de->uid;
8526+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
8527+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
8528+#else
8529 inode->i_gid = de->gid;
8530+#endif
8531 }
9a4c6ab7 8532 if (de->vx_flags)
8533 PROC_I(inode)->vx_flags = de->vx_flags;
89675291 8534diff -urNp linux-2.6.16.12/fs/proc/internal.h linux-2.6.16.12/fs/proc/internal.h
8535--- linux-2.6.16.12/fs/proc/internal.h 2006-05-01 15:14:26.000000000 -0400
8536+++ linux-2.6.16.12/fs/proc/internal.h 2006-05-01 20:17:33.000000000 -0400
8537@@ -36,6 +36,9 @@ extern int proc_tid_stat(struct task_str
8538 extern int proc_tgid_stat(struct task_struct *, char *);
8539 extern int proc_pid_status(struct task_struct *, char *);
8540 extern int proc_pid_statm(struct task_struct *, char *);
8541+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
8542+extern int proc_pid_ipaddr(struct task_struct*,char*);
8543+#endif
8544
8545 void free_proc_entry(struct proc_dir_entry *de);
8546
8547diff -urNp linux-2.6.16.12/fs/proc/proc_misc.c linux-2.6.16.12/fs/proc/proc_misc.c
8548--- linux-2.6.16.12/fs/proc/proc_misc.c 2006-05-01 15:14:26.000000000 -0400
8549+++ linux-2.6.16.12/fs/proc/proc_misc.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 8550@@ -651,6 +651,8 @@ void create_seq_entry(char *name, mode_t
89675291 8551 void __init proc_misc_init(void)
8552 {
8553 struct proc_dir_entry *entry;
8554+ int gr_mode = 0;
8555+
8556 static struct {
8557 char *name;
8558 int (*read_proc)(char*,char**,off_t,int,int*,void*);
9a4c6ab7 8559@@ -666,7 +668,9 @@ void __init proc_misc_init(void)
89675291 8560 {"stram", stram_read_proc},
8561 #endif
8562 {"filesystems", filesystems_read_proc},
8563+#ifndef CONFIG_GRKERNSEC_PROC_ADD
8564 {"cmdline", cmdline_read_proc},
8565+#endif
8566 {"locks", locks_read_proc},
8567 {"execdomains", execdomains_read_proc},
8568 {NULL,}
9a4c6ab7 8569@@ -674,31 +678,49 @@ void __init proc_misc_init(void)
89675291 8570 for (p = simple_ones; p->name; p++)
8571 create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
8572
8573+#ifdef CONFIG_GRKERNSEC_PROC_USER
8574+ gr_mode = S_IRUSR;
8575+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8576+ gr_mode = S_IRUSR | S_IRGRP;
8577+#endif
8578+#ifdef CONFIG_GRKERNSEC_PROC_ADD
8579+ create_proc_read_entry("cmdline", gr_mode, NULL, &cmdline_read_proc, NULL);
8580+#endif
8581+
8582 proc_symlink("mounts", NULL, "self/mounts");
8583
8584 /* And now for trickier ones */
8585 entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
8586 if (entry)
8587 entry->proc_fops = &proc_kmsg_operations;
8588+
8589+#ifdef CONFIG_GRKERNSEC_PROC_ADD
8590+ create_seq_entry("devices", gr_mode, &proc_devinfo_operations);
8591+#else
8592 create_seq_entry("devices", 0, &proc_devinfo_operations);
8593+#endif
8594 create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
8595 create_seq_entry("partitions", 0, &proc_partitions_operations);
8596 create_seq_entry("stat", 0, &proc_stat_operations);
8597 create_seq_entry("interrupts", 0, &proc_interrupts_operations);
8598 #ifdef CONFIG_SLAB
8599+#ifdef CONFIG_GRKERNSEC_PROC_ADD
8600+ create_seq_entry("slabinfo",S_IWUSR|gr_mode,&proc_slabinfo_operations);
8601+#else
8602 create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
8603 #endif
8604+#endif
8605 create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
8606 create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
8607 create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
8608 create_seq_entry("diskstats", 0, &proc_diskstats_operations);
8609 #ifdef CONFIG_MODULES
8610- create_seq_entry("modules", 0, &proc_modules_operations);
8611+ create_seq_entry("modules", gr_mode, &proc_modules_operations);
8612 #endif
8613 #ifdef CONFIG_SCHEDSTATS
8614 create_seq_entry("schedstat", 0, &proc_schedstat_operations);
8615 #endif
8616-#ifdef CONFIG_PROC_KCORE
8617+#if defined(CONFIG_PROC_KCORE) && !defined(CONFIG_GRKERNSEC_PROC_ADD)
8618 proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
8619 if (proc_root_kcore) {
8620 proc_root_kcore->proc_fops = &proc_kcore_operations;
8621diff -urNp linux-2.6.16.12/fs/proc/root.c linux-2.6.16.12/fs/proc/root.c
8622--- linux-2.6.16.12/fs/proc/root.c 2006-05-01 15:14:26.000000000 -0400
8623+++ linux-2.6.16.12/fs/proc/root.c 2006-05-01 20:17:33.000000000 -0400
9a4c6ab7 8624@@ -56,7 +56,13 @@ void __init proc_root_init(void)
89675291 8625 return;
8626 }
8627 proc_misc_init();
8628+#ifdef CONFIG_GRKERNSEC_PROC_USER
8629+ proc_net = proc_mkdir_mode("net", S_IRUSR | S_IXUSR, NULL);
8630+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8631+ proc_net = proc_mkdir_mode("net", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL);
8632+#else
8633 proc_net = proc_mkdir("net", NULL);
8634+#endif
8635 proc_net_stat = proc_mkdir("net/stat", NULL);
8636
8637 #ifdef CONFIG_SYSVIPC
9a4c6ab7 8638@@ -80,7 +86,15 @@ void __init proc_root_init(void)
89675291 8639 #ifdef CONFIG_PROC_DEVICETREE
8640 proc_device_tree_init();
8641 #endif
8642+#ifdef CONFIG_GRKERNSEC_PROC_ADD
8643+#ifdef CONFIG_GRKERNSEC_PROC_USER
8644+ proc_bus = proc_mkdir_mode("bus", S_IRUSR | S_IXUSR, NULL);
8645+#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8646+ proc_bus = proc_mkdir_mode("bus", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL);
8647+#endif
8648+#else
8649 proc_bus = proc_mkdir("bus", NULL);
8650+#endif
9a4c6ab7 8651 proc_vx_init();
89675291 8652 }
8653
89675291 8654diff -urNp linux-2.6.16.12/fs/proc/task_mmu.c linux-2.6.16.12/fs/proc/task_mmu.c
8655--- linux-2.6.16.12/fs/proc/task_mmu.c 2006-05-01 15:14:26.000000000 -0400
8656+++ linux-2.6.16.12/fs/proc/task_mmu.c 2006-05-01 20:17:33.000000000 -0400
8657@@ -43,15 +43,27 @@ char *task_mem(struct mm_struct *mm, cha
8658 "VmStk:\t%8lu kB\n"
8659 "VmExe:\t%8lu kB\n"
8660 "VmLib:\t%8lu kB\n"
8661- "VmPTE:\t%8lu kB\n",
8662- hiwater_vm << (PAGE_SHIFT-10),
8663+ "VmPTE:\t%8lu kB\n"
8664+
8665+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
8666+ "CsBase:\t%8lx\nCsLim:\t%8lx\n"
8667+#endif
8668+
8669+ ,hiwater_vm << (PAGE_SHIFT-10),
8670 (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
8671 mm->locked_vm << (PAGE_SHIFT-10),
8672 hiwater_rss << (PAGE_SHIFT-10),
8673 total_rss << (PAGE_SHIFT-10),
8674 data << (PAGE_SHIFT-10),
8675 mm->stack_vm << (PAGE_SHIFT-10), text, lib,
8676- (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
8677+ (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10
8678+
8679+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
8680+ , mm->context.user_cs_base, mm->context.user_cs_limit
8681+#endif
8682+
8683+ );
8684+
8685 return buffer;
8686 }
8687
8688@@ -118,6 +130,12 @@ struct mem_size_stats
8689 unsigned long private_dirty;
8690 };
8691
8692+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8693+#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
8694+ (_mm->pax_flags & MF_PAX_RANDMMAP || \
8695+ _mm->pax_flags & MF_PAX_SEGMEXEC))
8696+#endif
8697+
8698 static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
8699 {
8700 struct task_struct *task = m->private;
8701@@ -136,13 +154,30 @@ static int show_map_internal(struct seq_
8702 }
8703
8704 seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
8705+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8706+ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_start,
8707+ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_end,
8708+#else
8709 vma->vm_start,
8710 vma->vm_end,
8711+#endif
8712+
8713+#if 0
8714+ flags & VM_MAYREAD ? flags & VM_READ ? 'R' : '+' : flags & VM_READ ? 'r' : '-',
8715+ flags & VM_MAYWRITE ? flags & VM_WRITE ? 'W' : '+' : flags & VM_WRITE ? 'w' : '-',
8716+ flags & VM_MAYEXEC ? flags & VM_EXEC ? 'X' : '+' : flags & VM_EXEC ? 'x' : '-',
8717+#else
8718 flags & VM_READ ? 'r' : '-',
8719 flags & VM_WRITE ? 'w' : '-',
8720 flags & VM_EXEC ? 'x' : '-',
8721+#endif
8722+
8723 flags & VM_MAYSHARE ? 's' : 'p',
8724+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8725+ PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_pgoff << PAGE_SHIFT,
8726+#else
8727 vma->vm_pgoff << PAGE_SHIFT,
8728+#endif
8729 MAJOR(dev), MINOR(dev), ino, &len);
8730
8731 /*
8732@@ -154,13 +189,13 @@ static int show_map_internal(struct seq_
8733 seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
8734 } else {
8735 if (mm) {
8736- if (vma->vm_start <= mm->start_brk &&
8737- vma->vm_end >= mm->brk) {
8738+ if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
8739 pad_len_spaces(m, len);
8740 seq_puts(m, "[heap]");
8741 } else {
8742- if (vma->vm_start <= mm->start_stack &&
8743- vma->vm_end >= mm->start_stack) {
8744+ if ((vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP)) ||
8745+ (vma->vm_start <= mm->start_stack &&
8746+ vma->vm_end >= mm->start_stack)) {
8747
8748 pad_len_spaces(m, len);
8749 seq_puts(m, "[stack]");
8750@@ -173,7 +208,25 @@ static int show_map_internal(struct seq_
8751 }
8752 seq_putc(m, '\n');
8753
8754- if (mss)
8755+
8756+ if (mss) {
8757+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8758+ if (PAX_RAND_FLAGS(mm))
8759+ seq_printf(m,
8760+ "Size: %8lu kB\n"
8761+ "Rss: %8lu kB\n"
8762+ "Shared_Clean: %8lu kB\n"
8763+ "Shared_Dirty: %8lu kB\n"
8764+ "Private_Clean: %8lu kB\n"
8765+ "Private_Dirty: %8lu kB\n",
8766+ 0UL,
8767+ 0UL,
8768+ 0UL,
8769+ 0UL,
8770+ 0UL,
8771+ 0UL);
8772+ else
8773+#endif
8774 seq_printf(m,
8775 "Size: %8lu kB\n"
8776 "Rss: %8lu kB\n"
8777@@ -187,6 +240,7 @@ static int show_map_internal(struct seq_
8778 mss->shared_dirty >> 10,
8779 mss->private_clean >> 10,
8780 mss->private_dirty >> 10);
8781+ }
8782
8783 if (m->count < m->size) /* vma is copied successfully */
8784 m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
8785diff -urNp linux-2.6.16.12/fs/readdir.c linux-2.6.16.12/fs/readdir.c
8786--- linux-2.6.16.12/fs/readdir.c 2006-05-01 15:14:26.000000000 -0400
8787+++ linux-2.6.16.12/fs/readdir.c 2006-05-01 20:17:33.000000000 -0400
8788@@ -16,6 +16,8 @@
8789 #include <linux/security.h>
8790 #include <linux/syscalls.h>
8791 #include <linux/unistd.h>
8792+#include <linux/namei.h>
8793+#include <linux/grsecurity.h>
8794
8795 #include <asm/uaccess.h>
8796
8797@@ -65,6 +67,7 @@ struct old_linux_dirent {
8798
8799 struct readdir_callback {
8800 struct old_linux_dirent __user * dirent;
8801+ struct file * file;
8802 int result;
8803 };
8804
8805@@ -76,6 +79,10 @@ static int fillonedir(void * __buf, cons
8806
8807 if (buf->result)
8808 return -EINVAL;
8809+
8810+ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
8811+ return 0;
8812+
8813 buf->result++;
8814 dirent = buf->dirent;
8815 if (!access_ok(VERIFY_WRITE, dirent,
8816@@ -107,6 +114,7 @@ asmlinkage long old_readdir(unsigned int
8817
8818 buf.result = 0;
8819 buf.dirent = dirent;
8820+ buf.file = file;
8821
8822 error = vfs_readdir(file, fillonedir, &buf);
8823 if (error >= 0)
8824@@ -133,6 +141,7 @@ struct linux_dirent {
8825 struct getdents_callback {
8826 struct linux_dirent __user * current_dir;
8827 struct linux_dirent __user * previous;
8828+ struct file * file;
8829 int count;
8830 int error;
8831 };
8832@@ -147,6 +156,10 @@ static int filldir(void * __buf, const c
8833 buf->error = -EINVAL; /* only used if we fail.. */
8834 if (reclen > buf->count)
8835 return -EINVAL;
8836+
8837+ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
8838+ return 0;
8839+
8840 dirent = buf->previous;
8841 if (dirent) {
8842 if (__put_user(offset, &dirent->d_off))
8843@@ -191,6 +204,7 @@ asmlinkage long sys_getdents(unsigned in
8844
8845 buf.current_dir = dirent;
8846 buf.previous = NULL;
8847+ buf.file = file;
8848 buf.count = count;
8849 buf.error = 0;
8850
8851@@ -217,6 +231,7 @@ out:
8852 struct getdents_callback64 {
8853 struct linux_dirent64 __user * current_dir;
8854 struct linux_dirent64 __user * previous;
8855+ struct file * file;
8856 int count;
8857 int error;
8858 };
8859@@ -231,6 +246,10 @@ static int filldir64(void * __buf, const
8860 buf->error = -EINVAL; /* only used if we fail.. */
8861 if (reclen > buf->count)
8862 return -EINVAL;
8863+
8864+ if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
8865+ return 0;
8866+
8867 dirent = buf->previous;
8868 if (dirent) {
8869 if (__put_user(offset, &dirent->d_off))
8870@@ -277,6 +296,7 @@ asmlinkage long sys_getdents64(unsigned
8871
8872 buf.current_dir = dirent;
8873 buf.previous = NULL;
8874+ buf.file = file;
8875 buf.count = count;
8876 buf.error = 0;
8877
8878diff -urNp linux-2.6.16.12/fs/xfs/linux-2.6/xfs_file.c linux-2.6.16.12/fs/xfs/linux-2.6/xfs_file.c
8879--- linux-2.6.16.12/fs/xfs/linux-2.6/xfs_file.c 2006-05-01 15:14:26.000000000 -0400
8880+++ linux-2.6.16.12/fs/xfs/linux-2.6/xfs_file.c 2006-05-01 20:17:33.000000000 -0400
8881@@ -413,6 +413,11 @@ linvfs_file_mmap(
8882 vattr_t va = { .va_mask = XFS_AT_UPDATIME };
8883 int error;
8884
8885+#ifdef CONFIG_PAX_PAGEEXEC
8886+ if (vma->vm_mm->pax_flags & MF_PAX_PAGEEXEC)
8887+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
8888+#endif
8889+
8890 vma->vm_ops = &linvfs_file_vm_ops;
8891
8892 #ifdef CONFIG_XFS_DMAPI
8893diff -urNp linux-2.6.16.12/grsecurity/gracl_alloc.c linux-2.6.16.12/grsecurity/gracl_alloc.c
8894--- linux-2.6.16.12/grsecurity/gracl_alloc.c 1969-12-31 19:00:00.000000000 -0500
8895+++ linux-2.6.16.12/grsecurity/gracl_alloc.c 2006-05-01 20:17:33.000000000 -0400
8896@@ -0,0 +1,91 @@
8897+#include <linux/kernel.h>
8898+#include <linux/mm.h>
8899+#include <linux/slab.h>
8900+#include <linux/vmalloc.h>
8901+#include <linux/gracl.h>
8902+#include <linux/grsecurity.h>
8903+
8904+static unsigned long alloc_stack_next = 1;
8905+static unsigned long alloc_stack_size = 1;
8906+static void **alloc_stack;
8907+
8908+static __inline__ int
8909+alloc_pop(void)
8910+{
8911+ if (alloc_stack_next == 1)
8912+ return 0;
8913+
8914+ kfree(alloc_stack[alloc_stack_next - 2]);
8915+
8916+ alloc_stack_next--;
8917+
8918+ return 1;
8919+}
8920+
8921+static __inline__ void
8922+alloc_push(void *buf)
8923+{
8924+ if (alloc_stack_next >= alloc_stack_size)
8925+ BUG();
8926+
8927+ alloc_stack[alloc_stack_next - 1] = buf;
8928+
8929+ alloc_stack_next++;
8930+
8931+ return;
8932+}
8933+
8934+void *
8935+acl_alloc(unsigned long len)
8936+{
8937+ void *ret;
8938+
8939+ if (len > PAGE_SIZE)
8940+ BUG();
8941+
8942+ ret = kmalloc(len, GFP_KERNEL);
8943+
8944+ if (ret)
8945+ alloc_push(ret);
8946+
8947+ return ret;
8948+}
8949+
8950+void
8951+acl_free_all(void)
8952+{
8953+ if (gr_acl_is_enabled() || !alloc_stack)
8954+ return;
8955+
8956+ while (alloc_pop()) ;
8957+
8958+ if (alloc_stack) {
8959+ if ((alloc_stack_size * sizeof (void *)) <= PAGE_SIZE)
8960+ kfree(alloc_stack);
8961+ else
8962+ vfree(alloc_stack);
8963+ }
8964+
8965+ alloc_stack = NULL;
8966+ alloc_stack_size = 1;
8967+ alloc_stack_next = 1;
8968+
8969+ return;
8970+}
8971+
8972+int
8973+acl_alloc_stack_init(unsigned long size)
8974+{
8975+ if ((size * sizeof (void *)) <= PAGE_SIZE)
8976+ alloc_stack =
8977+ (void **) kmalloc(size * sizeof (void *), GFP_KERNEL);
8978+ else
8979+ alloc_stack = (void **) vmalloc(size * sizeof (void *));
8980+
8981+ alloc_stack_size = size;
8982+
8983+ if (!alloc_stack)
8984+ return 0;
8985+ else
8986+ return 1;
8987+}
8988diff -urNp linux-2.6.16.12/grsecurity/gracl.c linux-2.6.16.12/grsecurity/gracl.c
8989--- linux-2.6.16.12/grsecurity/gracl.c 1969-12-31 19:00:00.000000000 -0500
8990+++ linux-2.6.16.12/grsecurity/gracl.c 2006-05-01 20:17:33.000000000 -0400
8991@@ -0,0 +1,3533 @@
8992+#include <linux/kernel.h>
8993+#include <linux/module.h>
8994+#include <linux/sched.h>
8995+#include <linux/mm.h>
8996+#include <linux/file.h>
8997+#include <linux/fs.h>
8998+#include <linux/namei.h>
8999+#include <linux/mount.h>
9000+#include <linux/tty.h>
9001+#include <linux/proc_fs.h>
9002+#include <linux/smp_lock.h>
9003+#include <linux/slab.h>
9004+#include <linux/vmalloc.h>
9005+#include <linux/types.h>
9006+#include <linux/capability.h>
9007+#include <linux/sysctl.h>
9008+#include <linux/netdevice.h>
9009+#include <linux/ptrace.h>
9010+#include <linux/gracl.h>
9011+#include <linux/gralloc.h>
9012+#include <linux/grsecurity.h>
9013+#include <linux/grinternal.h>
9014+#include <linux/percpu.h>
9015+
9016+#include <asm/uaccess.h>
9017+#include <asm/errno.h>
9018+#include <asm/mman.h>
9019+
9020+static struct acl_role_db acl_role_set;
9021+static struct name_db name_set;
9022+static struct inodev_db inodev_set;
9023+
9024+/* for keeping track of userspace pointers used for subjects, so we
9025+ can share references in the kernel as well
9026+*/
9027+
9028+static struct dentry *real_root;
9029+static struct vfsmount *real_root_mnt;
9030+
9031+static struct acl_subj_map_db subj_map_set;
9032+
9033+static struct acl_role_label *default_role;
9034+
9035+static u16 acl_sp_role_value;
9036+
9037+extern char *gr_shared_page[4];
9038+static DECLARE_MUTEX(gr_dev_sem);
9039+rwlock_t gr_inode_lock = RW_LOCK_UNLOCKED;
9040+
9041+struct gr_arg *gr_usermode;
9042+
9043+static unsigned int gr_status = GR_STATUS_INIT;
9044+
9045+extern int chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum);
9046+extern void gr_clear_learn_entries(void);
9047+
9048+#ifdef CONFIG_GRKERNSEC_RESLOG
9049+extern void gr_log_resource(const struct task_struct *task,
9050+ const int res, const unsigned long wanted, const int gt);
9051+#endif
9052+
9053+extern char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
9054+ struct dentry *root, struct vfsmount *rootmnt,
9055+ char *buffer, int buflen);
9056+
9057+unsigned char *gr_system_salt;
9058+unsigned char *gr_system_sum;
9059+
9060+static struct sprole_pw **acl_special_roles = NULL;
9061+static __u16 num_sprole_pws = 0;
9062+
9063+static struct acl_role_label *kernel_role = NULL;
9064+
9065+static unsigned int gr_auth_attempts = 0;
9066+static unsigned long gr_auth_expires = 0UL;
9067+
9068+extern int gr_init_uidset(void);
9069+extern void gr_free_uidset(void);
9070+extern void gr_remove_uid(uid_t uid);
9071+extern int gr_find_uid(uid_t uid);
9072+
9073+__inline__ int
9074+gr_acl_is_enabled(void)
9075+{
9076+ return (gr_status & GR_READY);
9077+}
9078+
9079+char gr_roletype_to_char(void)
9080+{
9081+ switch (current->role->roletype &
9082+ (GR_ROLE_DEFAULT | GR_ROLE_USER | GR_ROLE_GROUP |
9083+ GR_ROLE_SPECIAL)) {
9084+ case GR_ROLE_DEFAULT:
9085+ return 'D';
9086+ case GR_ROLE_USER:
9087+ return 'U';
9088+ case GR_ROLE_GROUP:
9089+ return 'G';
9090+ case GR_ROLE_SPECIAL:
9091+ return 'S';
9092+ }
9093+
9094+ return 'X';
9095+}
9096+
9097+__inline__ int
9098+gr_acl_tpe_check(void)
9099+{
9100+ if (unlikely(!(gr_status & GR_READY)))
9101+ return 0;
9102+ if (current->role->roletype & GR_ROLE_TPE)
9103+ return 1;
9104+ else
9105+ return 0;
9106+}
9107+
9108+int
9109+gr_handle_rawio(const struct inode *inode)
9110+{
9111+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
9112+ if (inode && S_ISBLK(inode->i_mode) &&
9113+ grsec_enable_chroot_caps && proc_is_chrooted(current) &&
9114+ !capable(CAP_SYS_RAWIO))
9115+ return 1;
9116+#endif
9117+ return 0;
9118+}
9119+
9120+static int
9121+gr_streq(const char *a, const char *b, const unsigned int lena, const unsigned int lenb)
9122+{
9123+ int i;
9124+ unsigned long *l1;
9125+ unsigned long *l2;
9126+ unsigned char *c1;
9127+ unsigned char *c2;
9128+ int num_longs;
9129+
9130+ if (likely(lena != lenb))
9131+ return 0;
9132+
9133+ l1 = (unsigned long *)a;
9134+ l2 = (unsigned long *)b;
9135+
9136+ num_longs = lena / sizeof(unsigned long);
9137+
9138+ for (i = num_longs; i--; l1++, l2++) {
9139+ if (unlikely(*l1 != *l2))
9140+ return 0;
9141+ }
9142+
9143+ c1 = (unsigned char *) l1;
9144+ c2 = (unsigned char *) l2;
9145+
9146+ i = lena - (num_longs * sizeof(unsigned long));
9147+
9148+ for (; i--; c1++, c2++) {
9149+ if (unlikely(*c1 != *c2))
9150+ return 0;
9151+ }
9152+
9153+ return 1;
9154+}
9155+
9156+static char *
9157+gen_full_path(struct dentry *dentry, struct vfsmount *vfsmnt,
9158+ struct dentry *root, struct vfsmount *rootmnt, char *buf, int buflen)
9159+{
9160+ char *end = buf + buflen;
9161+ char *retval;
9162+ int namelen = 0;
9163+
9164+ *--end = '\0';
9165+
9166+ retval = end - 1;
9167+ *retval = '/';
9168+
9169+ if (dentry == root && vfsmnt == rootmnt)
9170+ return retval;
9171+ if (dentry != vfsmnt->mnt_root && !IS_ROOT(dentry)) {
9172+ namelen = strlen(dentry->d_name.name);
9173+ buflen -= namelen;
9174+ if (buflen < 2)
9175+ goto err;
9176+ if (dentry->d_parent != root || vfsmnt != rootmnt)
9177+ buflen--;
9178+ }
9179+
9180+ retval = __d_path(dentry->d_parent, vfsmnt, root, rootmnt, buf, buflen);
9181+ if (unlikely(IS_ERR(retval)))
9182+err:
9183+ retval = strcpy(buf, "<path too long>");
9184+ else if (namelen != 0) {
9185+ end = buf + buflen - 1; // accounts for null termination
9186+ if (dentry->d_parent != root || vfsmnt != rootmnt)
9187+ *end++ = '/'; // accounted for above with buflen--
9188+ memcpy(end, dentry->d_name.name, namelen);
9189+ }
9190+
9191+ return retval;
9192+}
9193+
9194+static char *
9195+__d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
9196+ char *buf, int buflen)
9197+{
9198+ char *res;
9199+
9200+ /* we can use real_root, real_root_mnt, because this is only called
9201+ by the RBAC system */
9202+ res = gen_full_path((struct dentry *)dentry, (struct vfsmount *)vfsmnt, real_root, real_root_mnt, buf, buflen);
9203+
9204+ return res;
9205+}
9206+
9207+static char *
9208+d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
9209+ char *buf, int buflen)
9210+{
9211+ char *res;
9212+ struct dentry *root;
9213+ struct vfsmount *rootmnt;
9214+
9215+ /* we can't use real_root, real_root_mnt, because they belong only to the RBAC system */
9216+ read_lock(&child_reaper->fs->lock);
9217+ root = dget(child_reaper->fs->root);
9218+ rootmnt = mntget(child_reaper->fs->rootmnt);
9219+ read_unlock(&child_reaper->fs->lock);
9220+
9221+ spin_lock(&dcache_lock);
9222+ res = gen_full_path((struct dentry *)dentry, (struct vfsmount *)vfsmnt, root, rootmnt, buf, buflen);
9223+ spin_unlock(&dcache_lock);
9224+
9225+ dput(root);
9226+ mntput(rootmnt);
9227+ return res;
9228+}
9229+
9230+static char *
9231+gr_to_filename_rbac(const struct dentry *dentry, const struct vfsmount *mnt)
9232+{
9233+ char *ret;
9234+ spin_lock(&dcache_lock);
9235+ ret = __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()),
9236+ PAGE_SIZE);
9237+ spin_unlock(&dcache_lock);
9238+ return ret;
9239+}
9240+
9241+char *
9242+gr_to_filename_nolock(const struct dentry *dentry, const struct vfsmount *mnt)
9243+{
9244+ return __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()),
9245+ PAGE_SIZE);
9246+}
9247+
9248+char *
9249+gr_to_filename(const struct dentry *dentry, const struct vfsmount *mnt)
9250+{
9251+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()),
9252+ PAGE_SIZE);
9253+}
9254+
9255+char *
9256+gr_to_filename1(const struct dentry *dentry, const struct vfsmount *mnt)
9257+{
9258+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[1], smp_processor_id()),
9259+ PAGE_SIZE);
9260+}
9261+
9262+char *
9263+gr_to_filename2(const struct dentry *dentry, const struct vfsmount *mnt)
9264+{
9265+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[2], smp_processor_id()),
9266+ PAGE_SIZE);
9267+}
9268+
9269+char *
9270+gr_to_filename3(const struct dentry *dentry, const struct vfsmount *mnt)
9271+{
9272+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[3], smp_processor_id()),
9273+ PAGE_SIZE);
9274+}
9275+
9276+__inline__ __u32
9277+to_gr_audit(const __u32 reqmode)
9278+{
9279+ /* masks off auditable permission flags, then shifts them to create
9280+ auditing flags, and adds the special case of append auditing if
9281+ we're requesting write */
9282+ return (((reqmode & GR_AUDIT_READ) << 10) | ((reqmode & GR_WRITE) ? GR_AUDIT_APPEND : 0));
9283+}
9284+
9285+struct acl_subject_label *
9286+lookup_subject_map(const struct acl_subject_label *userp)
9287+{
9288+ unsigned int index = shash(userp, subj_map_set.s_size);
9289+ struct subject_map *match;
9290+
9291+ match = subj_map_set.s_hash[index];
9292+
9293+ while (match && match->user != userp)
9294+ match = match->next;
9295+
9296+ if (match != NULL)
9297+ return match->kernel;
9298+ else
9299+ return NULL;
9300+}
9301+
9302+static void
9303+insert_subj_map_entry(struct subject_map *subjmap)
9304+{
9305+ unsigned int index = shash(subjmap->user, subj_map_set.s_size);
9306+ struct subject_map **curr;
9307+
9308+ subjmap->prev = NULL;
9309+
9310+ curr = &subj_map_set.s_hash[index];
9311+ if (*curr != NULL)
9312+ (*curr)->prev = subjmap;
9313+
9314+ subjmap->next = *curr;
9315+ *curr = subjmap;
9316+
9317+ return;
9318+}
9319+
9320+static struct acl_role_label *
9321+lookup_acl_role_label(const struct task_struct *task, const uid_t uid,
9322+ const gid_t gid)
9323+{
9324+ unsigned int index = rhash(uid, GR_ROLE_USER, acl_role_set.r_size);
9325+ struct acl_role_label *match;
9326+ struct role_allowed_ip *ipp;
9327+ unsigned int x;
9328+
9329+ match = acl_role_set.r_hash[index];
9330+
9331+ while (match) {
9332+ if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_USER)) == (GR_ROLE_DOMAIN | GR_ROLE_USER)) {
9333+ for (x = 0; x < match->domain_child_num; x++) {
9334+ if (match->domain_children[x] == uid)
9335+ goto found;
9336+ }
9337+ } else if (match->uidgid == uid && match->roletype & GR_ROLE_USER)
9338+ break;
9339+ match = match->next;
9340+ }
9341+found:
9342+ if (match == NULL) {
9343+ try_group:
9344+ index = rhash(gid, GR_ROLE_GROUP, acl_role_set.r_size);
9345+ match = acl_role_set.r_hash[index];
9346+
9347+ while (match) {
9348+ if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) == (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) {
9349+ for (x = 0; x < match->domain_child_num; x++) {
9350+ if (match->domain_children[x] == gid)
9351+ goto found2;
9352+ }
9353+ } else if (match->uidgid == gid && match->roletype & GR_ROLE_GROUP)
9354+ break;
9355+ match = match->next;
9356+ }
9357+found2:
9358+ if (match == NULL)
9359+ match = default_role;
9360+ if (match->allowed_ips == NULL)
9361+ return match;
9362+ else {
9363+ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
9364+ if (likely
9365+ ((ntohl(task->signal->curr_ip) & ipp->netmask) ==
9366+ (ntohl(ipp->addr) & ipp->netmask)))
9367+ return match;
9368+ }
9369+ match = default_role;
9370+ }
9371+ } else if (match->allowed_ips == NULL) {
9372+ return match;
9373+ } else {
9374+ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
9375+ if (likely
9376+ ((ntohl(task->signal->curr_ip) & ipp->netmask) ==
9377+ (ntohl(ipp->addr) & ipp->netmask)))
9378+ return match;
9379+ }
9380+ goto try_group;
9381+ }
9382+
9383+ return match;
9384+}
9385+
9386+struct acl_subject_label *
9387+lookup_acl_subj_label(const ino_t ino, const dev_t dev,
9388+ const struct acl_role_label *role)
9389+{
9390+ unsigned int index = fhash(ino, dev, role->subj_hash_size);
9391+ struct acl_subject_label *match;
9392+
9393+ match = role->subj_hash[index];
9394+
9395+ while (match && (match->inode != ino || match->device != dev ||
9396+ (match->mode & GR_DELETED))) {
9397+ match = match->next;
9398+ }
9399+
9400+ if (match && !(match->mode & GR_DELETED))
9401+ return match;
9402+ else
9403+ return NULL;
9404+}
9405+
9406+static struct acl_object_label *
9407+lookup_acl_obj_label(const ino_t ino, const dev_t dev,
9408+ const struct acl_subject_label *subj)
9409+{
9410+ unsigned int index = fhash(ino, dev, subj->obj_hash_size);
9411+ struct acl_object_label *match;
9412+
9413+ match = subj->obj_hash[index];
9414+
9415+ while (match && (match->inode != ino || match->device != dev ||
9416+ (match->mode & GR_DELETED))) {
9417+ match = match->next;
9418+ }
9419+
9420+ if (match && !(match->mode & GR_DELETED))
9421+ return match;
9422+ else
9423+ return NULL;
9424+}
9425+
9426+static struct acl_object_label *
9427+lookup_acl_obj_label_create(const ino_t ino, const dev_t dev,
9428+ const struct acl_subject_label *subj)
9429+{
9430+ unsigned int index = fhash(ino, dev, subj->obj_hash_size);
9431+ struct acl_object_label *match;
9432+
9433+ match = subj->obj_hash[index];
9434+
9435+ while (match && (match->inode != ino || match->device != dev ||
9436+ !(match->mode & GR_DELETED))) {
9437+ match = match->next;
9438+ }
9439+
9440+ if (match && (match->mode & GR_DELETED))
9441+ return match;
9442+
9443+ match = subj->obj_hash[index];
9444+
9445+ while (match && (match->inode != ino || match->device != dev ||
9446+ (match->mode & GR_DELETED))) {
9447+ match = match->next;
9448+ }
9449+
9450+ if (match && !(match->mode & GR_DELETED))
9451+ return match;
9452+ else
9453+ return NULL;
9454+}
9455+
9456+static struct name_entry *
9457+lookup_name_entry(const char *name)
9458+{
9459+ unsigned int len = strlen(name);
9460+ unsigned int key = full_name_hash(name, len);
9461+ unsigned int index = key % name_set.n_size;
9462+ struct name_entry *match;
9463+
9464+ match = name_set.n_hash[index];
9465+
9466+ while (match && (match->key != key || !gr_streq(match->name, name, match->len, len)))
9467+ match = match->next;
9468+
9469+ return match;
9470+}
9471+
9472+static struct inodev_entry *
9473+lookup_inodev_entry(const ino_t ino, const dev_t dev)
9474+{
9475+ unsigned int index = fhash(ino, dev, inodev_set.i_size);
9476+ struct inodev_entry *match;
9477+
9478+ match = inodev_set.i_hash[index];
9479+
9480+ while (match && (match->nentry->inode != ino || match->nentry->device != dev))
9481+ match = match->next;
9482+
9483+ return match;
9484+}
9485+
9486+static void
9487+insert_inodev_entry(struct inodev_entry *entry)
9488+{
9489+ unsigned int index = fhash(entry->nentry->inode, entry->nentry->device,
9490+ inodev_set.i_size);
9491+ struct inodev_entry **curr;
9492+
9493+ entry->prev = NULL;
9494+
9495+ curr = &inodev_set.i_hash[index];
9496+ if (*curr != NULL)
9497+ (*curr)->prev = entry;
9498+
9499+ entry->next = *curr;
9500+ *curr = entry;
9501+
9502+ return;
9503+}
9504+
9505+static void
9506+__insert_acl_role_label(struct acl_role_label *role, uid_t uidgid)
9507+{
9508+ unsigned int index =
9509+ rhash(uidgid, role->roletype & (GR_ROLE_USER | GR_ROLE_GROUP), acl_role_set.r_size);
9510+ struct acl_role_label **curr;
9511+
9512+ role->prev = NULL;
9513+
9514+ curr = &acl_role_set.r_hash[index];
9515+ if (*curr != NULL)
9516+ (*curr)->prev = role;
9517+
9518+ role->next = *curr;
9519+ *curr = role;
9520+
9521+ return;
9522+}
9523+
9524+static void
9525+insert_acl_role_label(struct acl_role_label *role)
9526+{
9527+ int i;
9528+
9529+ if (role->roletype & GR_ROLE_DOMAIN) {
9530+ for (i = 0; i < role->domain_child_num; i++)
9531+ __insert_acl_role_label(role, role->domain_children[i]);
9532+ } else
9533+ __insert_acl_role_label(role, role->uidgid);
9534+}
9535+
9536+static int
9537+insert_name_entry(char *name, const ino_t inode, const dev_t device)
9538+{
9539+ struct name_entry **curr, *nentry;
9540+ struct inodev_entry *ientry;
9541+ unsigned int len = strlen(name);
9542+ unsigned int key = full_name_hash(name, len);
9543+ unsigned int index = key % name_set.n_size;
9544+
9545+ curr = &name_set.n_hash[index];
9546+
9547+ while (*curr && ((*curr)->key != key || !gr_streq((*curr)->name, name, (*curr)->len, len)))
9548+ curr = &((*curr)->next);
9549+
9550+ if (*curr != NULL)
9551+ return 1;
9552+
9553+ nentry = acl_alloc(sizeof (struct name_entry));
9554+ if (nentry == NULL)
9555+ return 0;
9556+ ientry = acl_alloc(sizeof (struct inodev_entry));
9557+ if (ientry == NULL)
9558+ return 0;
9559+ ientry->nentry = nentry;
9560+
9561+ nentry->key = key;
9562+ nentry->name = name;
9563+ nentry->inode = inode;
9564+ nentry->device = device;
9565+ nentry->len = len;
9566+
9567+ nentry->prev = NULL;
9568+ curr = &name_set.n_hash[index];
9569+ if (*curr != NULL)
9570+ (*curr)->prev = nentry;
9571+ nentry->next = *curr;
9572+ *curr = nentry;
9573+
9574+ /* insert us into the table searchable by inode/dev */
9575+ insert_inodev_entry(ientry);
9576+
9577+ return 1;
9578+}
9579+
9580+static void
9581+insert_acl_obj_label(struct acl_object_label *obj,
9582+ struct acl_subject_label *subj)
9583+{
9584+ unsigned int index =
9585+ fhash(obj->inode, obj->device, subj->obj_hash_size);
9586+ struct acl_object_label **curr;
9587+
9588+
9589+ obj->prev = NULL;
9590+
9591+ curr = &subj->obj_hash[index];
9592+ if (*curr != NULL)
9593+ (*curr)->prev = obj;
9594+
9595+ obj->next = *curr;
9596+ *curr = obj;
9597+
9598+ return;
9599+}
9600+
9601+static void
9602+insert_acl_subj_label(struct acl_subject_label *obj,
9603+ struct acl_role_label *role)
9604+{
9605+ unsigned int index = fhash(obj->inode, obj->device, role->subj_hash_size);
9606+ struct acl_subject_label **curr;
9607+
9608+ obj->prev = NULL;
9609+
9610+ curr = &role->subj_hash[index];
9611+ if (*curr != NULL)
9612+ (*curr)->prev = obj;
9613+
9614+ obj->next = *curr;
9615+ *curr = obj;
9616+
9617+ return;
9618+}
9619+
9620+/* allocating chained hash tables, so optimal size is where lambda ~ 1 */
9621+
9622+static void *
9623+create_table(__u32 * len, int elementsize)
9624+{
9625+ unsigned int table_sizes[] = {
9626+ 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381,
9627+ 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
9628+ 4194301, 8388593, 16777213, 33554393, 67108859, 134217689,
9629+ 268435399, 536870909, 1073741789, 2147483647
9630+ };
9631+ void *newtable = NULL;
9632+ unsigned int pwr = 0;
9633+
9634+ while ((pwr < ((sizeof (table_sizes) / sizeof (table_sizes[0])) - 1)) &&
9635+ table_sizes[pwr] <= *len)
9636+ pwr++;
9637+
9638+ if (table_sizes[pwr] <= *len)
9639+ return newtable;
9640+
9641+ if ((table_sizes[pwr] * elementsize) <= PAGE_SIZE)
9642+ newtable =
9643+ kmalloc(table_sizes[pwr] * elementsize, GFP_KERNEL);
9644+ else
9645+ newtable = vmalloc(table_sizes[pwr] * elementsize);
9646+
9647+ *len = table_sizes[pwr];
9648+
9649+ return newtable;
9650+}
9651+
9652+static int
9653+init_variables(const struct gr_arg *arg)
9654+{
9655+ unsigned int stacksize;
9656+
9657+ subj_map_set.s_size = arg->role_db.num_subjects;
9658+ acl_role_set.r_size = arg->role_db.num_roles + arg->role_db.num_domain_children;
9659+ name_set.n_size = arg->role_db.num_objects;
9660+ inodev_set.i_size = arg->role_db.num_objects;
9661+
9662+ if (!subj_map_set.s_size || !acl_role_set.r_size ||
9663+ !name_set.n_size || !inodev_set.i_size)
9664+ return 1;
9665+
9666+ if (!gr_init_uidset())
9667+ return 1;
9668+
9669+ /* set up the stack that holds allocation info */
9670+
9671+ stacksize = arg->role_db.num_pointers + 5;
9672+
9673+ if (!acl_alloc_stack_init(stacksize))
9674+ return 1;
9675+
9676+ /* grab reference for the real root dentry and vfsmount */
9677+ read_lock(&child_reaper->fs->lock);
9678+ real_root_mnt = mntget(child_reaper->fs->rootmnt);
9679+ real_root = dget(child_reaper->fs->root);
9680+ read_unlock(&child_reaper->fs->lock);
9681+
9682+
9683+ subj_map_set.s_hash =
9684+ (struct subject_map **) create_table(&subj_map_set.s_size, sizeof(void *));
9685+ acl_role_set.r_hash =
9686+ (struct acl_role_label **) create_table(&acl_role_set.r_size, sizeof(void *));
9687+ name_set.n_hash = (struct name_entry **) create_table(&name_set.n_size, sizeof(void *));
9688+ inodev_set.i_hash =
9689+ (struct inodev_entry **) create_table(&inodev_set.i_size, sizeof(void *));
9690+
9691+ if (!subj_map_set.s_hash || !acl_role_set.r_hash ||
9692+ !name_set.n_hash || !inodev_set.i_hash)
9693+ return 1;
9694+
9695+ memset(subj_map_set.s_hash, 0,
9696+ sizeof(struct subject_map *) * subj_map_set.s_size);
9697+ memset(acl_role_set.r_hash, 0,
9698+ sizeof (struct acl_role_label *) * acl_role_set.r_size);
9699+ memset(name_set.n_hash, 0,
9700+ sizeof (struct name_entry *) * name_set.n_size);
9701+ memset(inodev_set.i_hash, 0,
9702+ sizeof (struct inodev_entry *) * inodev_set.i_size);
9703+
9704+ return 0;
9705+}
9706+
9707+/* free information not needed after startup
9708+ currently contains user->kernel pointer mappings for subjects
9709+*/
9710+
9711+static void
9712+free_init_variables(void)
9713+{
9714+ __u32 i;
9715+
9716+ if (subj_map_set.s_hash) {
9717+ for (i = 0; i < subj_map_set.s_size; i++) {
9718+ if (subj_map_set.s_hash[i]) {
9719+ kfree(subj_map_set.s_hash[i]);
9720+ subj_map_set.s_hash[i] = NULL;
9721+ }
9722+ }
9723+
9724+ if ((subj_map_set.s_size * sizeof (struct subject_map *)) <=
9725+ PAGE_SIZE)
9726+ kfree(subj_map_set.s_hash);
9727+ else
9728+ vfree(subj_map_set.s_hash);
9729+ }
9730+
9731+ return;
9732+}
9733+
9734+static void
9735+free_variables(void)
9736+{
9737+ struct acl_subject_label *s;
9738+ struct acl_role_label *r;
9739+ struct task_struct *task, *task2;
9740+ unsigned int i, x;
9741+
9742+ gr_clear_learn_entries();
9743+
9744+ read_lock(&tasklist_lock);
9745+ do_each_thread(task2, task) {
9746+ task->acl_sp_role = 0;
9747+ task->acl_role_id = 0;
9748+ task->acl = NULL;
9749+ task->role = NULL;
9750+ } while_each_thread(task2, task);
9751+ read_unlock(&tasklist_lock);
9752+
9753+ /* release the reference to the real root dentry and vfsmount */
9754+ if (real_root)
9755+ dput(real_root);
9756+ real_root = NULL;
9757+ if (real_root_mnt)
9758+ mntput(real_root_mnt);
9759+ real_root_mnt = NULL;
9760+
9761+ /* free all object hash tables */
9762+
9763+ FOR_EACH_ROLE_START(r, i)
9764+ if (r->subj_hash == NULL)
9765+ break;
9766+ FOR_EACH_SUBJECT_START(r, s, x)
9767+ if (s->obj_hash == NULL)
9768+ break;
9769+ if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE)
9770+ kfree(s->obj_hash);
9771+ else
9772+ vfree(s->obj_hash);
9773+ FOR_EACH_SUBJECT_END(s, x)
9774+ FOR_EACH_NESTED_SUBJECT_START(r, s)
9775+ if (s->obj_hash == NULL)
9776+ break;
9777+ if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE)
9778+ kfree(s->obj_hash);
9779+ else
9780+ vfree(s->obj_hash);
9781+ FOR_EACH_NESTED_SUBJECT_END(s)
9782+ if ((r->subj_hash_size * sizeof (struct acl_subject_label *)) <= PAGE_SIZE)
9783+ kfree(r->subj_hash);
9784+ else
9785+ vfree(r->subj_hash);
9786+ r->subj_hash = NULL;
9787+ FOR_EACH_ROLE_END(r,i)
9788+
9789+ acl_free_all();
9790+
9791+ if (acl_role_set.r_hash) {
9792+ if ((acl_role_set.r_size * sizeof (struct acl_role_label *)) <=
9793+ PAGE_SIZE)
9794+ kfree(acl_role_set.r_hash);
9795+ else
9796+ vfree(acl_role_set.r_hash);
9797+ }
9798+ if (name_set.n_hash) {
9799+ if ((name_set.n_size * sizeof (struct name_entry *)) <=
9800+ PAGE_SIZE)
9801+ kfree(name_set.n_hash);
9802+ else
9803+ vfree(name_set.n_hash);
9804+ }
9805+
9806+ if (inodev_set.i_hash) {
9807+ if ((inodev_set.i_size * sizeof (struct inodev_entry *)) <=
9808+ PAGE_SIZE)
9809+ kfree(inodev_set.i_hash);
9810+ else
9811+ vfree(inodev_set.i_hash);
9812+ }
9813+
9814+ gr_free_uidset();
9815+
9816+ memset(&name_set, 0, sizeof (struct name_db));
9817+ memset(&inodev_set, 0, sizeof (struct inodev_db));
9818+ memset(&acl_role_set, 0, sizeof (struct acl_role_db));
9819+ memset(&subj_map_set, 0, sizeof (struct acl_subj_map_db));
9820+
9821+ default_role = NULL;
9822+
9823+ return;
9824+}
9825+
9826+static __u32
9827+count_user_objs(struct acl_object_label *userp)
9828+{
9829+ struct acl_object_label o_tmp;
9830+ __u32 num = 0;
9831+
9832+ while (userp) {
9833+ if (copy_from_user(&o_tmp, userp,
9834+ sizeof (struct acl_object_label)))
9835+ break;
9836+
9837+ userp = o_tmp.prev;
9838+ num++;
9839+ }
9840+
9841+ return num;
9842+}
9843+
9844+static struct acl_subject_label *
9845+do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role);
9846+
9847+static int
9848+copy_user_glob(struct acl_object_label *obj)
9849+{
9850+ struct acl_object_label *g_tmp, **guser;
9851+ unsigned int len;
9852+ char *tmp;
9853+
9854+ if (obj->globbed == NULL)
9855+ return 0;
9856+
9857+ guser = &obj->globbed;
9858+ while (*guser) {
9859+ g_tmp = (struct acl_object_label *)
9860+ acl_alloc(sizeof (struct acl_object_label));
9861+ if (g_tmp == NULL)
9862+ return -ENOMEM;
9863+
9864+ if (copy_from_user(g_tmp, *guser,
9865+ sizeof (struct acl_object_label)))
9866+ return -EFAULT;
9867+
9868+ len = strnlen_user(g_tmp->filename, PATH_MAX);
9869+
9870+ if (!len || len >= PATH_MAX)
9871+ return -EINVAL;
9872+
9873+ if ((tmp = (char *) acl_alloc(len)) == NULL)
9874+ return -ENOMEM;
9875+
9876+ if (copy_from_user(tmp, g_tmp->filename, len))
9877+ return -EFAULT;
9878+
9879+ g_tmp->filename = tmp;
9880+
9881+ *guser = g_tmp;
9882+ guser = &(g_tmp->next);
9883+ }
9884+
9885+ return 0;
9886+}
9887+
9888+static int
9889+copy_user_objs(struct acl_object_label *userp, struct acl_subject_label *subj,
9890+ struct acl_role_label *role)
9891+{
9892+ struct acl_object_label *o_tmp;
9893+ unsigned int len;
9894+ int ret;
9895+ char *tmp;
9896+
9897+ while (userp) {
9898+ if ((o_tmp = (struct acl_object_label *)
9899+ acl_alloc(sizeof (struct acl_object_label))) == NULL)
9900+ return -ENOMEM;
9901+
9902+ if (copy_from_user(o_tmp, userp,
9903+ sizeof (struct acl_object_label)))
9904+ return -EFAULT;
9905+
9906+ userp = o_tmp->prev;
9907+
9908+ len = strnlen_user(o_tmp->filename, PATH_MAX);
9909+
9910+ if (!len || len >= PATH_MAX)
9911+ return -EINVAL;
9912+
9913+ if ((tmp = (char *) acl_alloc(len)) == NULL)
9914+ return -ENOMEM;
9915+
9916+ if (copy_from_user(tmp, o_tmp->filename, len))
9917+ return -EFAULT;
9918+
9919+ o_tmp->filename = tmp;
9920+
9921+ insert_acl_obj_label(o_tmp, subj);
9922+ if (!insert_name_entry(o_tmp->filename, o_tmp->inode,
9923+ o_tmp->device))
9924+ return -ENOMEM;
9925+
9926+ ret = copy_user_glob(o_tmp);
9927+ if (ret)
9928+ return ret;
9929+
9930+ if (o_tmp->nested) {
9931+ o_tmp->nested = do_copy_user_subj(o_tmp->nested, role);
9932+ if (IS_ERR(o_tmp->nested))
9933+ return PTR_ERR(o_tmp->nested);
9934+
9935+ /* insert into nested subject list */
9936+ o_tmp->nested->next = role->hash->first;
9937+ role->hash->first = o_tmp->nested;
9938+ }
9939+ }
9940+
9941+ return 0;
9942+}
9943+
9944+static __u32
9945+count_user_subjs(struct acl_subject_label *userp)
9946+{
9947+ struct acl_subject_label s_tmp;
9948+ __u32 num = 0;
9949+
9950+ while (userp) {
9951+ if (copy_from_user(&s_tmp, userp,
9952+ sizeof (struct acl_subject_label)))
9953+ break;
9954+
9955+ userp = s_tmp.prev;
9956+ /* do not count nested subjects against this count, since
9957+ they are not included in the hash table, but are
9958+ attached to objects. We have already counted
9959+ the subjects in userspace for the allocation
9960+ stack
9961+ */
9962+ if (!(s_tmp.mode & GR_NESTED))
9963+ num++;
9964+ }
9965+
9966+ return num;
9967+}
9968+
9969+static int
9970+copy_user_allowedips(struct acl_role_label *rolep)
9971+{
9972+ struct role_allowed_ip *ruserip, *rtmp = NULL, *rlast;
9973+
9974+ ruserip = rolep->allowed_ips;
9975+
9976+ while (ruserip) {
9977+ rlast = rtmp;
9978+
9979+ if ((rtmp = (struct role_allowed_ip *)
9980+ acl_alloc(sizeof (struct role_allowed_ip))) == NULL)
9981+ return -ENOMEM;
9982+
9983+ if (copy_from_user(rtmp, ruserip,
9984+ sizeof (struct role_allowed_ip)))
9985+ return -EFAULT;
9986+
9987+ ruserip = rtmp->prev;
9988+
9989+ if (!rlast) {
9990+ rtmp->prev = NULL;
9991+ rolep->allowed_ips = rtmp;
9992+ } else {
9993+ rlast->next = rtmp;
9994+ rtmp->prev = rlast;
9995+ }
9996+
9997+ if (!ruserip)
9998+ rtmp->next = NULL;
9999+ }
10000+
10001+ return 0;
10002+}
10003+
10004+static int
10005+copy_user_transitions(struct acl_role_label *rolep)
10006+{
10007+ struct role_transition *rusertp, *rtmp = NULL, *rlast;
10008+
10009+ unsigned int len;
10010+ char *tmp;
10011+
10012+ rusertp = rolep->transitions;
10013+
10014+ while (rusertp) {
10015+ rlast = rtmp;
10016+
10017+ if ((rtmp = (struct role_transition *)
10018+ acl_alloc(sizeof (struct role_transition))) == NULL)
10019+ return -ENOMEM;
10020+
10021+ if (copy_from_user(rtmp, rusertp,
10022+ sizeof (struct role_transition)))
10023+ return -EFAULT;
10024+
10025+ rusertp = rtmp->prev;
10026+
10027+ len = strnlen_user(rtmp->rolename, GR_SPROLE_LEN);
10028+
10029+ if (!len || len >= GR_SPROLE_LEN)
10030+ return -EINVAL;
10031+
10032+ if ((tmp = (char *) acl_alloc(len)) == NULL)
10033+ return -ENOMEM;
10034+
10035+ if (copy_from_user(tmp, rtmp->rolename, len))
10036+ return -EFAULT;
10037+
10038+ rtmp->rolename = tmp;
10039+
10040+ if (!rlast) {
10041+ rtmp->prev = NULL;
10042+ rolep->transitions = rtmp;
10043+ } else {
10044+ rlast->next = rtmp;
10045+ rtmp->prev = rlast;
10046+ }
10047+
10048+ if (!rusertp)
10049+ rtmp->next = NULL;
10050+ }
10051+
10052+ return 0;
10053+}
10054+
10055+static struct acl_subject_label *
10056+do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role)
10057+{
10058+ struct acl_subject_label *s_tmp = NULL, *s_tmp2;
10059+ unsigned int len;
10060+ char *tmp;
10061+ __u32 num_objs;
10062+ struct acl_ip_label **i_tmp, *i_utmp2;
10063+ struct gr_hash_struct ghash;
10064+ struct subject_map *subjmap;
10065+ unsigned int i_num;
10066+ int err;
10067+
10068+ s_tmp = lookup_subject_map(userp);
10069+
10070+ /* we've already copied this subject into the kernel, just return
10071+ the reference to it, and don't copy it over again
10072+ */
10073+ if (s_tmp)
10074+ return(s_tmp);
10075+
10076+ if ((s_tmp = (struct acl_subject_label *)
10077+ acl_alloc(sizeof (struct acl_subject_label))) == NULL)
10078+ return ERR_PTR(-ENOMEM);
10079+
10080+ subjmap = (struct subject_map *)kmalloc(sizeof (struct subject_map), GFP_KERNEL);
10081+ if (subjmap == NULL)
10082+ return ERR_PTR(-ENOMEM);
10083+
10084+ subjmap->user = userp;
10085+ subjmap->kernel = s_tmp;
10086+ insert_subj_map_entry(subjmap);
10087+
10088+ if (copy_from_user(s_tmp, userp,
10089+ sizeof (struct acl_subject_label)))
10090+ return ERR_PTR(-EFAULT);
10091+
10092+ len = strnlen_user(s_tmp->filename, PATH_MAX);
10093+
10094+ if (!len || len >= PATH_MAX)
10095+ return ERR_PTR(-EINVAL);
10096+
10097+ if ((tmp = (char *) acl_alloc(len)) == NULL)
10098+ return ERR_PTR(-ENOMEM);
10099+
10100+ if (copy_from_user(tmp, s_tmp->filename, len))
10101+ return ERR_PTR(-EFAULT);
10102+
10103+ s_tmp->filename = tmp;
10104+
10105+ if (!strcmp(s_tmp->filename, "/"))
10106+ role->root_label = s_tmp;
10107+
10108+ if (copy_from_user(&ghash, s_tmp->hash, sizeof(struct gr_hash_struct)))
10109+ return ERR_PTR(-EFAULT);
10110+
10111+ /* copy user and group transition tables */
10112+
10113+ if (s_tmp->user_trans_num) {
10114+ uid_t *uidlist;
10115+
10116+ uidlist = (uid_t *)acl_alloc(s_tmp->user_trans_num * sizeof(uid_t));
10117+ if (uidlist == NULL)
10118+ return ERR_PTR(-ENOMEM);
10119+ if (copy_from_user(uidlist, s_tmp->user_transitions, s_tmp->user_trans_num * sizeof(uid_t)))
10120+ return ERR_PTR(-EFAULT);
10121+
10122+ s_tmp->user_transitions = uidlist;
10123+ }
10124+
10125+ if (s_tmp->group_trans_num) {
10126+ gid_t *gidlist;
10127+
10128+ gidlist = (gid_t *)acl_alloc(s_tmp->group_trans_num * sizeof(gid_t));
10129+ if (gidlist == NULL)
10130+ return ERR_PTR(-ENOMEM);
10131+ if (copy_from_user(gidlist, s_tmp->group_transitions, s_tmp->group_trans_num * sizeof(gid_t)))
10132+ return ERR_PTR(-EFAULT);
10133+
10134+ s_tmp->group_transitions = gidlist;
10135+ }
10136+
10137+ /* set up object hash table */
10138+ num_objs = count_user_objs(ghash.first);
10139+
10140+ s_tmp->obj_hash_size = num_objs;
10141+ s_tmp->obj_hash =
10142+ (struct acl_object_label **)
10143+ create_table(&(s_tmp->obj_hash_size), sizeof(void *));
10144+
10145+ if (!s_tmp->obj_hash)
10146+ return ERR_PTR(-ENOMEM);
10147+
10148+ memset(s_tmp->obj_hash, 0,
10149+ s_tmp->obj_hash_size *
10150+ sizeof (struct acl_object_label *));
10151+
10152+ /* add in objects */
10153+ err = copy_user_objs(ghash.first, s_tmp, role);
10154+
10155+ if (err)
10156+ return ERR_PTR(err);
10157+
10158+ /* set pointer for parent subject */
10159+ if (s_tmp->parent_subject) {
10160+ s_tmp2 = do_copy_user_subj(s_tmp->parent_subject, role);
10161+
10162+ if (IS_ERR(s_tmp2))
10163+ return s_tmp2;
10164+
10165+ s_tmp->parent_subject = s_tmp2;
10166+ }
10167+
10168+ /* add in ip acls */
10169+
10170+ if (!s_tmp->ip_num) {
10171+ s_tmp->ips = NULL;
10172+ goto insert;
10173+ }
10174+
10175+ i_tmp =
10176+ (struct acl_ip_label **) acl_alloc(s_tmp->ip_num *
10177+ sizeof (struct
10178+ acl_ip_label *));
10179+
10180+ if (!i_tmp)
10181+ return ERR_PTR(-ENOMEM);
10182+
10183+ for (i_num = 0; i_num < s_tmp->ip_num; i_num++) {
10184+ *(i_tmp + i_num) =
10185+ (struct acl_ip_label *)
10186+ acl_alloc(sizeof (struct acl_ip_label));
10187+ if (!*(i_tmp + i_num))
10188+ return ERR_PTR(-ENOMEM);
10189+
10190+ if (copy_from_user
10191+ (&i_utmp2, s_tmp->ips + i_num,
10192+ sizeof (struct acl_ip_label *)))
10193+ return ERR_PTR(-EFAULT);
10194+
10195+ if (copy_from_user
10196+ (*(i_tmp + i_num), i_utmp2,
10197+ sizeof (struct acl_ip_label)))
10198+ return ERR_PTR(-EFAULT);
10199+
10200+ if ((*(i_tmp + i_num))->iface == NULL)
10201+ continue;
10202+
10203+ len = strnlen_user((*(i_tmp + i_num))->iface, IFNAMSIZ);
10204+ if (!len || len >= IFNAMSIZ)
10205+ return ERR_PTR(-EINVAL);
10206+ tmp = acl_alloc(len);
10207+ if (tmp == NULL)
10208+ return ERR_PTR(-ENOMEM);
10209+ if (copy_from_user(tmp, (*(i_tmp + i_num))->iface, len))
10210+ return ERR_PTR(-EFAULT);
10211+ (*(i_tmp + i_num))->iface = tmp;
10212+ }
10213+
10214+ s_tmp->ips = i_tmp;
10215+
10216+insert:
10217+ if (!insert_name_entry(s_tmp->filename, s_tmp->inode,
10218+ s_tmp->device))
10219+ return ERR_PTR(-ENOMEM);
10220+
10221+ return s_tmp;
10222+}
10223+
10224+static int
10225+copy_user_subjs(struct acl_subject_label *userp, struct acl_role_label *role)
10226+{
10227+ struct acl_subject_label s_pre;
10228+ struct acl_subject_label * ret;
10229+ int err;
10230+
10231+ while (userp) {
10232+ if (copy_from_user(&s_pre, userp,
10233+ sizeof (struct acl_subject_label)))
10234+ return -EFAULT;
10235+
10236+ /* do not add nested subjects here, add
10237+ while parsing objects
10238+ */
10239+
10240+ if (s_pre.mode & GR_NESTED) {
10241+ userp = s_pre.prev;
10242+ continue;
10243+ }
10244+
10245+ ret = do_copy_user_subj(userp, role);
10246+
10247+ err = PTR_ERR(ret);
10248+ if (IS_ERR(ret))
10249+ return err;
10250+
10251+ insert_acl_subj_label(ret, role);
10252+
10253+ userp = s_pre.prev;
10254+ }
10255+
10256+ return 0;
10257+}
10258+
10259+static int
10260+copy_user_acl(struct gr_arg *arg)
10261+{
10262+ struct acl_role_label *r_tmp = NULL, **r_utmp, *r_utmp2;
10263+ struct sprole_pw *sptmp;
10264+ struct gr_hash_struct *ghash;
10265+ uid_t *domainlist;
10266+ unsigned int r_num;
10267+ unsigned int len;
10268+ char *tmp;
10269+ int err = 0;
10270+ __u16 i;
10271+ __u32 num_subjs;
10272+
10273+ /* we need a default and kernel role */
10274+ if (arg->role_db.num_roles < 2)
10275+ return -EINVAL;
10276+
10277+ /* copy special role authentication info from userspace */
10278+
10279+ num_sprole_pws = arg->num_sprole_pws;
10280+ acl_special_roles = (struct sprole_pw **) acl_alloc(num_sprole_pws * sizeof(struct sprole_pw *));
10281+
10282+ if (!acl_special_roles) {
10283+ err = -ENOMEM;
10284+ goto cleanup;
10285+ }
10286+
10287+ for (i = 0; i < num_sprole_pws; i++) {
10288+ sptmp = (struct sprole_pw *) acl_alloc(sizeof(struct sprole_pw));
10289+ if (!sptmp) {
10290+ err = -ENOMEM;
10291+ goto cleanup;
10292+ }
10293+ if (copy_from_user(sptmp, arg->sprole_pws + i,
10294+ sizeof (struct sprole_pw))) {
10295+ err = -EFAULT;
10296+ goto cleanup;
10297+ }
10298+
10299+ len =
10300+ strnlen_user(sptmp->rolename, GR_SPROLE_LEN);
10301+
10302+ if (!len || len >= GR_SPROLE_LEN) {
10303+ err = -EINVAL;
10304+ goto cleanup;
10305+ }
10306+
10307+ if ((tmp = (char *) acl_alloc(len)) == NULL) {
10308+ err = -ENOMEM;
10309+ goto cleanup;
10310+ }
10311+
10312+ if (copy_from_user(tmp, sptmp->rolename, len)) {
10313+ err = -EFAULT;
10314+ goto cleanup;
10315+ }
10316+
10317+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
10318+ printk(KERN_ALERT "Copying special role %s\n", tmp);
10319+#endif
10320+ sptmp->rolename = tmp;
10321+ acl_special_roles[i] = sptmp;
10322+ }
10323+
10324+ r_utmp = (struct acl_role_label **) arg->role_db.r_table;
10325+
10326+ for (r_num = 0; r_num < arg->role_db.num_roles; r_num++) {
10327+ r_tmp = acl_alloc(sizeof (struct acl_role_label));
10328+
10329+ if (!r_tmp) {
10330+ err = -ENOMEM;
10331+ goto cleanup;
10332+ }
10333+
10334+ if (copy_from_user(&r_utmp2, r_utmp + r_num,
10335+ sizeof (struct acl_role_label *))) {
10336+ err = -EFAULT;
10337+ goto cleanup;
10338+ }
10339+
10340+ if (copy_from_user(r_tmp, r_utmp2,
10341+ sizeof (struct acl_role_label))) {
10342+ err = -EFAULT;
10343+ goto cleanup;
10344+ }
10345+
10346+ len = strnlen_user(r_tmp->rolename, GR_SPROLE_LEN);
10347+
10348+ if (!len || len >= PATH_MAX) {
10349+ err = -EINVAL;
10350+ goto cleanup;
10351+ }
10352+
10353+ if ((tmp = (char *) acl_alloc(len)) == NULL) {
10354+ err = -ENOMEM;
10355+ goto cleanup;
10356+ }
10357+ if (copy_from_user(tmp, r_tmp->rolename, len)) {
10358+ err = -EFAULT;
10359+ goto cleanup;
10360+ }
10361+ r_tmp->rolename = tmp;
10362+
10363+ if (!strcmp(r_tmp->rolename, "default")
10364+ && (r_tmp->roletype & GR_ROLE_DEFAULT)) {
10365+ default_role = r_tmp;
10366+ } else if (!strcmp(r_tmp->rolename, ":::kernel:::")) {
10367+ kernel_role = r_tmp;
10368+ }
10369+
10370+ if ((ghash = (struct gr_hash_struct *) acl_alloc(sizeof(struct gr_hash_struct))) == NULL) {
10371+ err = -ENOMEM;
10372+ goto cleanup;
10373+ }
10374+ if (copy_from_user(ghash, r_tmp->hash, sizeof(struct gr_hash_struct))) {
10375+ err = -EFAULT;
10376+ goto cleanup;
10377+ }
10378+
10379+ r_tmp->hash = ghash;
10380+
10381+ num_subjs = count_user_subjs(r_tmp->hash->first);
10382+
10383+ r_tmp->subj_hash_size = num_subjs;
10384+ r_tmp->subj_hash =
10385+ (struct acl_subject_label **)
10386+ create_table(&(r_tmp->subj_hash_size), sizeof(void *));
10387+
10388+ if (!r_tmp->subj_hash) {
10389+ err = -ENOMEM;
10390+ goto cleanup;
10391+ }
10392+
10393+ err = copy_user_allowedips(r_tmp);
10394+ if (err)
10395+ goto cleanup;
10396+
10397+ /* copy domain info */
10398+ if (r_tmp->domain_children != NULL) {
10399+ domainlist = acl_alloc(r_tmp->domain_child_num * sizeof(uid_t));
10400+ if (domainlist == NULL) {
10401+ err = -ENOMEM;
10402+ goto cleanup;
10403+ }
10404+ if (copy_from_user(domainlist, r_tmp->domain_children, r_tmp->domain_child_num * sizeof(uid_t))) {
10405+ err = -EFAULT;
10406+ goto cleanup;
10407+ }
10408+ r_tmp->domain_children = domainlist;
10409+ }
10410+
10411+ err = copy_user_transitions(r_tmp);
10412+ if (err)
10413+ goto cleanup;
10414+
10415+ memset(r_tmp->subj_hash, 0,
10416+ r_tmp->subj_hash_size *
10417+ sizeof (struct acl_subject_label *));
10418+
10419+ err = copy_user_subjs(r_tmp->hash->first, r_tmp);
10420+
10421+ if (err)
10422+ goto cleanup;
10423+
10424+ /* set nested subject list to null */
10425+ r_tmp->hash->first = NULL;
10426+
10427+ insert_acl_role_label(r_tmp);
10428+ }
10429+
10430+ goto return_err;
10431+ cleanup:
10432+ free_variables();
10433+ return_err:
10434+ return err;
10435+
10436+}
10437+
10438+static int
10439+gracl_init(struct gr_arg *args)
10440+{
10441+ int error = 0;
10442+
10443+ memcpy(gr_system_salt, args->salt, GR_SALT_LEN);
10444+ memcpy(gr_system_sum, args->sum, GR_SHA_LEN);
10445+
10446+ if (init_variables(args)) {
10447+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_INITF_ACL_MSG, GR_VERSION);
10448+ error = -ENOMEM;
10449+ free_variables();
10450+ goto out;
10451+ }
10452+
10453+ error = copy_user_acl(args);
10454+ free_init_variables();
10455+ if (error) {
10456+ free_variables();
10457+ goto out;
10458+ }
10459+
10460+ if ((error = gr_set_acls(0))) {
10461+ free_variables();
10462+ goto out;
10463+ }
10464+
10465+ gr_status |= GR_READY;
10466+ out:
10467+ return error;
10468+}
10469+
10470+/* derived from glibc fnmatch() 0: match, 1: no match*/
10471+
10472+static int
10473+glob_match(const char *p, const char *n)
10474+{
10475+ char c;
10476+
10477+ while ((c = *p++) != '\0') {
10478+ switch (c) {
10479+ case '?':
10480+ if (*n == '\0')
10481+ return 1;
10482+ else if (*n == '/')
10483+ return 1;
10484+ break;
10485+ case '\\':
10486+ if (*n != c)
10487+ return 1;
10488+ break;
10489+ case '*':
10490+ for (c = *p++; c == '?' || c == '*'; c = *p++) {
10491+ if (*n == '/')
10492+ return 1;
10493+ else if (c == '?') {
10494+ if (*n == '\0')
10495+ return 1;
10496+ else
10497+ ++n;
10498+ }
10499+ }
10500+ if (c == '\0') {
10501+ return 0;
10502+ } else {
10503+ const char *endp;
10504+
10505+ if ((endp = strchr(n, '/')) == NULL)
10506+ endp = n + strlen(n);
10507+
10508+ if (c == '[') {
10509+ for (--p; n < endp; ++n)
10510+ if (!glob_match(p, n))
10511+ return 0;
10512+ } else if (c == '/') {
10513+ while (*n != '\0' && *n != '/')
10514+ ++n;
10515+ if (*n == '/' && !glob_match(p, n + 1))
10516+ return 0;
10517+ } else {
10518+ for (--p; n < endp; ++n)
10519+ if (*n == c && !glob_match(p, n))
10520+ return 0;
10521+ }
10522+
10523+ return 1;
10524+ }
10525+ case '[':
10526+ {
10527+ int not;
10528+ char cold;
10529+
10530+ if (*n == '\0' || *n == '/')
10531+ return 1;
10532+
10533+ not = (*p == '!' || *p == '^');
10534+ if (not)
10535+ ++p;
10536+
10537+ c = *p++;
10538+ for (;;) {
10539+ unsigned char fn = (unsigned char)*n;
10540+
10541+ if (c == '\0')
10542+ return 1;
10543+ else {
10544+ if (c == fn)
10545+ goto matched;
10546+ cold = c;
10547+ c = *p++;
10548+
10549+ if (c == '-' && *p != ']') {
10550+ unsigned char cend = *p++;
10551+
10552+ if (cend == '\0')
10553+ return 1;
10554+
10555+ if (cold <= fn && fn <= cend)
10556+ goto matched;
10557+
10558+ c = *p++;
10559+ }
10560+ }
10561+
10562+ if (c == ']')
10563+ break;
10564+ }
10565+ if (!not)
10566+ return 1;
10567+ break;
10568+ matched:
10569+ while (c != ']') {
10570+ if (c == '\0')
10571+ return 1;
10572+
10573+ c = *p++;
10574+ }
10575+ if (not)
10576+ return 1;
10577+ }
10578+ break;
10579+ default:
10580+ if (c != *n)
10581+ return 1;
10582+ }
10583+
10584+ ++n;
10585+ }
10586+
10587+ if (*n == '\0')
10588+ return 0;
10589+
10590+ if (*n == '/')
10591+ return 0;
10592+
10593+ return 1;
10594+}
10595+
10596+static struct acl_object_label *
10597+chk_glob_label(struct acl_object_label *globbed,
10598+ struct dentry *dentry, struct vfsmount *mnt, char **path)
10599+{
10600+ struct acl_object_label *tmp;
10601+
10602+ if (*path == NULL)
10603+ *path = gr_to_filename_nolock(dentry, mnt);
10604+
10605+ tmp = globbed;
10606+
10607+ while (tmp) {
10608+ if (!glob_match(tmp->filename, *path))
10609+ return tmp;
10610+ tmp = tmp->next;
10611+ }
10612+
10613+ return NULL;
10614+}
10615+
10616+static struct acl_object_label *
10617+__full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
10618+ const ino_t curr_ino, const dev_t curr_dev,
10619+ const struct acl_subject_label *subj, char **path)
10620+{
10621+ struct acl_subject_label *tmpsubj;
10622+ struct acl_object_label *retval;
10623+ struct acl_object_label *retval2;
10624+
10625+ tmpsubj = (struct acl_subject_label *) subj;
10626+ read_lock(&gr_inode_lock);
10627+ do {
10628+ retval = lookup_acl_obj_label(curr_ino, curr_dev, tmpsubj);
10629+ if (retval) {
10630+ if (retval->globbed) {
10631+ retval2 = chk_glob_label(retval->globbed, (struct dentry *)orig_dentry,
10632+ (struct vfsmount *)orig_mnt, path);
10633+ if (retval2)
10634+ retval = retval2;
10635+ }
10636+ break;
10637+ }
10638+ } while ((tmpsubj = tmpsubj->parent_subject));
10639+ read_unlock(&gr_inode_lock);
10640+
10641+ return retval;
10642+}
10643+
10644+static __inline__ struct acl_object_label *
10645+full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
10646+ const struct dentry *curr_dentry,
10647+ const struct acl_subject_label *subj, char **path)
10648+{
10649+ return __full_lookup(orig_dentry, orig_mnt,
10650+ curr_dentry->d_inode->i_ino,
10651+ curr_dentry->d_inode->i_sb->s_dev, subj, path);
10652+}
10653+
10654+static struct acl_object_label *
10655+__chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
10656+ const struct acl_subject_label *subj, char *path)
10657+{
10658+ struct dentry *dentry = (struct dentry *) l_dentry;
10659+ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
10660+ struct acl_object_label *retval;
10661+
10662+ spin_lock(&dcache_lock);
10663+
10664+ for (;;) {
10665+ if (dentry == real_root && mnt == real_root_mnt)
10666+ break;
10667+
10668+ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) {
10669+ if (mnt->mnt_parent == mnt)
10670+ break;
10671+
10672+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
10673+ if (retval != NULL)
10674+ goto out;
10675+
10676+ dentry = mnt->mnt_mountpoint;
10677+ mnt = mnt->mnt_parent;
10678+ continue;
10679+ }
10680+
10681+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
10682+ if (retval != NULL)
10683+ goto out;
10684+
10685+ dentry = dentry->d_parent;
10686+ }
10687+
10688+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
10689+
10690+ if (retval == NULL)
10691+ retval = full_lookup(l_dentry, l_mnt, real_root, subj, &path);
10692+out:
10693+ spin_unlock(&dcache_lock);
10694+ return retval;
10695+}
10696+
10697+static __inline__ struct acl_object_label *
10698+chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
10699+ const struct acl_subject_label *subj)
10700+{
10701+ char *path = NULL;
10702+ return __chk_obj_label(l_dentry, l_mnt, subj, path);
10703+}
10704+
10705+static __inline__ struct acl_object_label *
10706+chk_obj_create_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
10707+ const struct acl_subject_label *subj, char *path)
10708+{
10709+ return __chk_obj_label(l_dentry, l_mnt, subj, path);
10710+}
10711+
10712+static struct acl_subject_label *
10713+chk_subj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
10714+ const struct acl_role_label *role)
10715+{
10716+ struct dentry *dentry = (struct dentry *) l_dentry;
10717+ struct vfsmount *mnt = (struct vfsmount *) l_mnt;
10718+ struct acl_subject_label *retval;
10719+
10720+ spin_lock(&dcache_lock);
10721+
10722+ for (;;) {
10723+ if (dentry == real_root && mnt == real_root_mnt)
10724+ break;
10725+ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) {
10726+ if (mnt->mnt_parent == mnt)
10727+ break;
10728+
10729+ read_lock(&gr_inode_lock);
10730+ retval =
10731+ lookup_acl_subj_label(dentry->d_inode->i_ino,
10732+ dentry->d_inode->i_sb->s_dev, role);
10733+ read_unlock(&gr_inode_lock);
10734+ if (retval != NULL)
10735+ goto out;
10736+
10737+ dentry = mnt->mnt_mountpoint;
10738+ mnt = mnt->mnt_parent;
10739+ continue;
10740+ }
10741+
10742+ read_lock(&gr_inode_lock);
10743+ retval = lookup_acl_subj_label(dentry->d_inode->i_ino,
10744+ dentry->d_inode->i_sb->s_dev, role);
10745+ read_unlock(&gr_inode_lock);
10746+ if (retval != NULL)
10747+ goto out;
10748+
10749+ dentry = dentry->d_parent;
10750+ }
10751+
10752+ read_lock(&gr_inode_lock);
10753+ retval = lookup_acl_subj_label(dentry->d_inode->i_ino,
10754+ dentry->d_inode->i_sb->s_dev, role);
10755+ read_unlock(&gr_inode_lock);
10756+
10757+ if (unlikely(retval == NULL)) {
10758+ read_lock(&gr_inode_lock);
10759+ retval = lookup_acl_subj_label(real_root->d_inode->i_ino,
10760+ real_root->d_inode->i_sb->s_dev, role);
10761+ read_unlock(&gr_inode_lock);
10762+ }
10763+out:
10764+ spin_unlock(&dcache_lock);
10765+
10766+ return retval;
10767+}
10768+
10769+static void
10770+gr_log_learn(const struct task_struct *task, const struct dentry *dentry, const struct vfsmount *mnt, const __u32 mode)
10771+{
10772+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, task->role->roletype,
10773+ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_dentry,
10774+ task->exec_file->f_vfsmnt) : task->acl->filename, task->acl->filename,
10775+ 1, 1, gr_to_filename(dentry, mnt), (unsigned long) mode, NIPQUAD(task->signal->curr_ip));
10776+
10777+ return;
10778+}
10779+
10780+static void
10781+gr_log_learn_id_change(const struct task_struct *task, const char type, const unsigned int real,
10782+ const unsigned int effective, const unsigned int fs)
10783+{
10784+ security_learn(GR_ID_LEARN_MSG, task->role->rolename, task->role->roletype,
10785+ task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_dentry,
10786+ task->exec_file->f_vfsmnt) : task->acl->filename, task->acl->filename,
10787+ type, real, effective, fs, NIPQUAD(task->signal->curr_ip));
10788+
10789+ return;
10790+}
10791+
10792+__u32
10793+gr_check_link(const struct dentry * new_dentry,
10794+ const struct dentry * parent_dentry,
10795+ const struct vfsmount * parent_mnt,
10796+ const struct dentry * old_dentry, const struct vfsmount * old_mnt)
10797+{
10798+ struct acl_object_label *obj;
10799+ __u32 oldmode, newmode;
10800+ __u32 needmode;
10801+
10802+ if (unlikely(!(gr_status & GR_READY)))
10803+ return (GR_CREATE | GR_LINK);
10804+
10805+ obj = chk_obj_label(old_dentry, old_mnt, current->acl);
10806+ oldmode = obj->mode;
10807+
10808+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
10809+ oldmode |= (GR_CREATE | GR_LINK);
10810+
10811+ needmode = GR_CREATE | GR_AUDIT_CREATE | GR_SUPPRESS;
10812+ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID))
10813+ needmode |= GR_SETID | GR_AUDIT_SETID;
10814+
10815+ newmode =
10816+ gr_check_create(new_dentry, parent_dentry, parent_mnt,
10817+ oldmode | needmode);
10818+
10819+ needmode = newmode & (GR_FIND | GR_APPEND | GR_WRITE | GR_EXEC |
10820+ GR_SETID | GR_READ | GR_FIND | GR_DELETE |
10821+ GR_INHERIT | GR_AUDIT_INHERIT);
10822+
10823+ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID) && !(newmode & GR_SETID))
10824+ goto bad;
10825+
10826+ if ((oldmode & needmode) != needmode)
10827+ goto bad;
10828+
10829+ needmode = oldmode & (GR_NOPTRACE | GR_PTRACERD | GR_INHERIT | GR_AUDITS);
10830+ if ((newmode & needmode) != needmode)
10831+ goto bad;
10832+
10833+ if ((newmode & (GR_CREATE | GR_LINK)) == (GR_CREATE | GR_LINK))
10834+ return newmode;
10835+bad:
10836+ needmode = oldmode;
10837+ if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID))
10838+ needmode |= GR_SETID;
10839+
10840+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) {
10841+ gr_log_learn(current, old_dentry, old_mnt, needmode);
10842+ return (GR_CREATE | GR_LINK);
10843+ } else if (newmode & GR_SUPPRESS)
10844+ return GR_SUPPRESS;
10845+ else
10846+ return 0;
10847+}
10848+
10849+__u32
10850+gr_search_file(const struct dentry * dentry, const __u32 mode,
10851+ const struct vfsmount * mnt)
10852+{
10853+ __u32 retval = mode;
10854+ struct acl_subject_label *curracl;
10855+ struct acl_object_label *currobj;
10856+
10857+ if (unlikely(!(gr_status & GR_READY)))
10858+ return (mode & ~GR_AUDITS);
10859+
10860+ curracl = current->acl;
10861+
10862+ currobj = chk_obj_label(dentry, mnt, curracl);
10863+ retval = currobj->mode & mode;
10864+
10865+ if (unlikely
10866+ ((curracl->mode & (GR_LEARN | GR_INHERITLEARN)) && !(mode & GR_NOPTRACE)
10867+ && (retval != (mode & ~(GR_AUDITS | GR_SUPPRESS))))) {
10868+ __u32 new_mode = mode;
10869+
10870+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
10871+
10872+ retval = new_mode;
10873+
10874+ if (new_mode & GR_EXEC && curracl->mode & GR_INHERITLEARN)
10875+ new_mode |= GR_INHERIT;
10876+
10877+ if (!(mode & GR_NOLEARN))
10878+ gr_log_learn(current, dentry, mnt, new_mode);
10879+ }
10880+
10881+ return retval;
10882+}
10883+
10884+__u32
10885+gr_check_create(const struct dentry * new_dentry, const struct dentry * parent,
10886+ const struct vfsmount * mnt, const __u32 mode)
10887+{
10888+ struct name_entry *match;
10889+ struct acl_object_label *matchpo;
10890+ struct acl_subject_label *curracl;
10891+ char *path;
10892+ __u32 retval;
10893+
10894+ if (unlikely(!(gr_status & GR_READY)))
10895+ return (mode & ~GR_AUDITS);
10896+
10897+ preempt_disable();
10898+ path = gr_to_filename_rbac(new_dentry, mnt);
10899+ match = lookup_name_entry(path);
10900+
10901+ if (!match)
10902+ goto check_parent;
10903+
10904+ curracl = current->acl;
10905+
10906+ read_lock(&gr_inode_lock);
10907+ matchpo = lookup_acl_obj_label_create(match->inode, match->device, curracl);
10908+ read_unlock(&gr_inode_lock);
10909+
10910+ if (matchpo) {
10911+ if ((matchpo->mode & mode) !=
10912+ (mode & ~(GR_AUDITS | GR_SUPPRESS))
10913+ && curracl->mode & (GR_LEARN | GR_INHERITLEARN)) {
10914+ __u32 new_mode = mode;
10915+
10916+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
10917+
10918+ gr_log_learn(current, new_dentry, mnt, new_mode);
10919+
10920+ preempt_enable();
10921+ return new_mode;
10922+ }
10923+ preempt_enable();
10924+ return (matchpo->mode & mode);
10925+ }
10926+
10927+ check_parent:
10928+ curracl = current->acl;
10929+
10930+ matchpo = chk_obj_create_label(parent, mnt, curracl, path);
10931+ retval = matchpo->mode & mode;
10932+
10933+ if ((retval != (mode & ~(GR_AUDITS | GR_SUPPRESS)))
10934+ && (curracl->mode & (GR_LEARN | GR_INHERITLEARN))) {
10935+ __u32 new_mode = mode;
10936+
10937+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
10938+
10939+ gr_log_learn(current, new_dentry, mnt, new_mode);
10940+ preempt_enable();
10941+ return new_mode;
10942+ }
10943+
10944+ preempt_enable();
10945+ return retval;
10946+}
10947+
10948+int
10949+gr_check_hidden_task(const struct task_struct *task)
10950+{
10951+ if (unlikely(!(gr_status & GR_READY)))
10952+ return 0;
10953+
10954+ if (!(task->acl->mode & GR_PROCFIND) && !(current->acl->mode & GR_VIEW))
10955+ return 1;
10956+
10957+ return 0;
10958+}
10959+
10960+int
10961+gr_check_protected_task(const struct task_struct *task)
10962+{
10963+ if (unlikely(!(gr_status & GR_READY) || !task))
10964+ return 0;
10965+
10966+ if ((task->acl->mode & GR_PROTECTED) && !(current->acl->mode & GR_KILL) &&
10967+ task->acl != current->acl)
10968+ return 1;
10969+
10970+ return 0;
10971+}
10972+
10973+void
10974+gr_copy_label(struct task_struct *tsk)
10975+{
10976+ tsk->signal->used_accept = 0;
10977+ tsk->acl_sp_role = 0;
10978+ tsk->acl_role_id = current->acl_role_id;
10979+ tsk->acl = current->acl;
10980+ tsk->role = current->role;
10981+ tsk->signal->curr_ip = current->signal->curr_ip;
10982+ if (current->exec_file)
10983+ get_file(current->exec_file);
10984+ tsk->exec_file = current->exec_file;
10985+ tsk->is_writable = current->is_writable;
10986+ if (unlikely(current->signal->used_accept))
10987+ current->signal->curr_ip = 0;
10988+
10989+ return;
10990+}
10991+
10992+static void
10993+gr_set_proc_res(struct task_struct *task)
10994+{
10995+ struct acl_subject_label *proc;
10996+ unsigned short i;
10997+
10998+ proc = task->acl;
10999+
11000+ if (proc->mode & (GR_LEARN | GR_INHERITLEARN))
11001+ return;
11002+
11003+ for (i = 0; i < (GR_NLIMITS - 1); i++) {
11004+ if (!(proc->resmask & (1 << i)))
11005+ continue;
11006+
11007+ task->signal->rlim[i].rlim_cur = proc->res[i].rlim_cur;
11008+ task->signal->rlim[i].rlim_max = proc->res[i].rlim_max;
11009+ }
11010+
11011+ return;
11012+}
11013+
11014+int
11015+gr_check_user_change(int real, int effective, int fs)
11016+{
11017+ unsigned int i;
11018+ __u16 num;
11019+ uid_t *uidlist;
11020+ int curuid;
11021+ int realok = 0;
11022+ int effectiveok = 0;
11023+ int fsok = 0;
11024+
11025+ if (unlikely(!(gr_status & GR_READY)))
11026+ return 0;
11027+
11028+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
11029+ gr_log_learn_id_change(current, 'u', real, effective, fs);
11030+
11031+ num = current->acl->user_trans_num;
11032+ uidlist = current->acl->user_transitions;
11033+
11034+ if (uidlist == NULL)
11035+ return 0;
11036+
11037+ if (real == -1)
11038+ realok = 1;
11039+ if (effective == -1)
11040+ effectiveok = 1;
11041+ if (fs == -1)
11042+ fsok = 1;
11043+
11044+ if (current->acl->user_trans_type & GR_ID_ALLOW) {
11045+ for (i = 0; i < num; i++) {
11046+ curuid = (int)uidlist[i];
11047+ if (real == curuid)
11048+ realok = 1;
11049+ if (effective == curuid)
11050+ effectiveok = 1;
11051+ if (fs == curuid)
11052+ fsok = 1;
11053+ }
11054+ } else if (current->acl->user_trans_type & GR_ID_DENY) {
11055+ for (i = 0; i < num; i++) {
11056+ curuid = (int)uidlist[i];
11057+ if (real == curuid)
11058+ break;
11059+ if (effective == curuid)
11060+ break;
11061+ if (fs == curuid)
11062+ break;
11063+ }
11064+ /* not in deny list */
11065+ if (i == num) {
11066+ realok = 1;
11067+ effectiveok = 1;
11068+ fsok = 1;
11069+ }
11070+ }
11071+
11072+ if (realok && effectiveok && fsok)
11073+ return 0;
11074+ else {
11075+ gr_log_int(GR_DONT_AUDIT, GR_USRCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real);
11076+ return 1;
11077+ }
11078+}
11079+
11080+int
11081+gr_check_group_change(int real, int effective, int fs)
11082+{
11083+ unsigned int i;
11084+ __u16 num;
11085+ gid_t *gidlist;
11086+ int curgid;
11087+ int realok = 0;
11088+ int effectiveok = 0;
11089+ int fsok = 0;
11090+
11091+ if (unlikely(!(gr_status & GR_READY)))
11092+ return 0;
11093+
11094+ if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
11095+ gr_log_learn_id_change(current, 'g', real, effective, fs);
11096+
11097+ num = current->acl->group_trans_num;
11098+ gidlist = current->acl->group_transitions;
11099+
11100+ if (gidlist == NULL)
11101+ return 0;
11102+
11103+ if (real == -1)
11104+ realok = 1;
11105+ if (effective == -1)
11106+ effectiveok = 1;
11107+ if (fs == -1)
11108+ fsok = 1;
11109+
11110+ if (current->acl->group_trans_type & GR_ID_ALLOW) {
11111+ for (i = 0; i < num; i++) {
11112+ curgid = (int)gidlist[i];
11113+ if (real == curgid)
11114+ realok = 1;
11115+ if (effective == curgid)
11116+ effectiveok = 1;
11117+ if (fs == curgid)
11118+ fsok = 1;
11119+ }
11120+ } else if (current->acl->group_trans_type & GR_ID_DENY) {
11121+ for (i = 0; i < num; i++) {
11122+ curgid = (int)gidlist[i];
11123+ if (real == curgid)
11124+ break;
11125+ if (effective == curgid)
11126+ break;
11127+ if (fs == curgid)
11128+ break;
11129+ }
11130+ /* not in deny list */
11131+ if (i == num) {
11132+ realok = 1;
11133+ effectiveok = 1;
11134+ fsok = 1;
11135+ }
11136+ }
11137+
11138+ if (realok && effectiveok && fsok)
11139+ return 0;
11140+ else {
11141+ gr_log_int(GR_DONT_AUDIT, GR_GRPCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real);
11142+ return 1;
11143+ }
11144+}
11145+
11146+void
11147+gr_set_role_label(struct task_struct *task, const uid_t uid, const uid_t gid)
11148+{
11149+ struct acl_role_label *role = task->role;
11150+ struct acl_subject_label *subj = NULL;
11151+ struct acl_object_label *obj;
11152+ struct file *filp;
11153+
11154+ if (unlikely(!(gr_status & GR_READY)))
11155+ return;
11156+
11157+ filp = task->exec_file;
11158+
11159+ /* kernel process, we'll give them the kernel role */
11160+ if (unlikely(!filp)) {
11161+ task->role = kernel_role;
11162+ task->acl = kernel_role->root_label;
11163+ return;
11164+ } else if (!task->role || !(task->role->roletype & GR_ROLE_SPECIAL))
11165+ role = lookup_acl_role_label(task, uid, gid);
11166+
11167+ /* perform subject lookup in possibly new role
11168+ we can use this result below in the case where role == task->role
11169+ */
11170+ subj = chk_subj_label(filp->f_dentry, filp->f_vfsmnt, role);
11171+
11172+ /* if we changed uid/gid, but result in the same role
11173+ and are using inheritance, don't lose the inherited subject
11174+ if current subject is other than what normal lookup
11175+ would result in, we arrived via inheritance, don't
11176+ lose subject
11177+ */
11178+ if (role != task->role || (!(task->acl->mode & GR_INHERITLEARN) &&
11179+ (subj == task->acl)))
11180+ task->acl = subj;
11181+
11182+ task->role = role;
11183+
11184+ task->is_writable = 0;
11185+
11186+ /* ignore additional mmap checks for processes that are writable
11187+ by the default ACL */
11188+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
11189+ if (unlikely(obj->mode & GR_WRITE))
11190+ task->is_writable = 1;
11191+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label);
11192+ if (unlikely(obj->mode & GR_WRITE))
11193+ task->is_writable = 1;
11194+
11195+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
11196+ printk(KERN_ALERT "Set role label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
11197+#endif
11198+
11199+ gr_set_proc_res(task);
11200+
11201+ return;
11202+}
11203+
11204+int
11205+gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
11206+{
11207+ struct task_struct *task = current;
11208+ struct acl_subject_label *newacl;
11209+ struct acl_object_label *obj;
11210+ __u32 retmode;
11211+
11212+ if (unlikely(!(gr_status & GR_READY)))
11213+ return 0;
11214+
11215+ newacl = chk_subj_label(dentry, mnt, task->role);
11216+
11217+ task_lock(task);
11218+ if (((task->ptrace & PT_PTRACED) && !(task->acl->mode &
11219+ GR_POVERRIDE) && (task->acl != newacl) &&
11220+ !(task->role->roletype & GR_ROLE_GOD) &&
11221+ !gr_search_file(dentry, GR_PTRACERD, mnt) &&
11222+ !(task->acl->mode & (GR_LEARN | GR_INHERITLEARN))) ||
11223+ (atomic_read(&task->fs->count) > 1 ||
11224+ atomic_read(&task->files->count) > 1 ||
11225+ atomic_read(&task->sighand->count) > 1)) {
11226+ task_unlock(task);
11227+ gr_log_fs_generic(GR_DONT_AUDIT, GR_PTRACE_EXEC_ACL_MSG, dentry, mnt);
11228+ return -EACCES;
11229+ }
11230+ task_unlock(task);
11231+
11232+ obj = chk_obj_label(dentry, mnt, task->acl);
11233+ retmode = obj->mode & (GR_INHERIT | GR_AUDIT_INHERIT);
11234+
11235+ if (!(task->acl->mode & GR_INHERITLEARN) &&
11236+ ((newacl->mode & GR_LEARN) || !(retmode & GR_INHERIT))) {
11237+ if (obj->nested)
11238+ task->acl = obj->nested;
11239+ else
11240+ task->acl = newacl;
11241+ } else if (retmode & GR_INHERIT && retmode & GR_AUDIT_INHERIT)
11242+ gr_log_str_fs(GR_DO_AUDIT, GR_INHERIT_ACL_MSG, task->acl->filename, dentry, mnt);
11243+
11244+ task->is_writable = 0;
11245+
11246+ /* ignore additional mmap checks for processes that are writable
11247+ by the default ACL */
11248+ obj = chk_obj_label(dentry, mnt, default_role->root_label);
11249+ if (unlikely(obj->mode & GR_WRITE))
11250+ task->is_writable = 1;
11251+ obj = chk_obj_label(dentry, mnt, task->role->root_label);
11252+ if (unlikely(obj->mode & GR_WRITE))
11253+ task->is_writable = 1;
11254+
11255+ gr_set_proc_res(task);
11256+
11257+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
11258+ printk(KERN_ALERT "Set subject label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
11259+#endif
11260+ return 0;
11261+}
11262+
11263+static void
11264+do_handle_delete(const ino_t ino, const dev_t dev)
11265+{
11266+ struct acl_object_label *matchpo;
11267+ struct acl_subject_label *matchps;
11268+ struct acl_subject_label *subj;
11269+ struct acl_role_label *role;
11270+ unsigned int i, x;
11271+
11272+ FOR_EACH_ROLE_START(role, i)
11273+ FOR_EACH_SUBJECT_START(role, subj, x)
11274+ if ((matchpo = lookup_acl_obj_label(ino, dev, subj)) != NULL)
11275+ matchpo->mode |= GR_DELETED;
11276+ FOR_EACH_SUBJECT_END(subj,x)
11277+ FOR_EACH_NESTED_SUBJECT_START(role, subj)
11278+ if (subj->inode == ino && subj->device == dev)
11279+ subj->mode |= GR_DELETED;
11280+ FOR_EACH_NESTED_SUBJECT_END(subj)
11281+ if ((matchps = lookup_acl_subj_label(ino, dev, role)) != NULL)
11282+ matchps->mode |= GR_DELETED;
11283+ FOR_EACH_ROLE_END(role,i)
11284+
11285+ return;
11286+}
11287+
11288+void
11289+gr_handle_delete(const ino_t ino, const dev_t dev)
11290+{
11291+ if (unlikely(!(gr_status & GR_READY)))
11292+ return;
11293+
11294+ write_lock(&gr_inode_lock);
11295+ if (unlikely((unsigned long)lookup_inodev_entry(ino, dev)))
11296+ do_handle_delete(ino, dev);
11297+ write_unlock(&gr_inode_lock);
11298+
11299+ return;
11300+}
11301+
11302+static void
11303+update_acl_obj_label(const ino_t oldinode, const dev_t olddevice,
11304+ const ino_t newinode, const dev_t newdevice,
11305+ struct acl_subject_label *subj)
11306+{
11307+ unsigned int index = fhash(oldinode, olddevice, subj->obj_hash_size);
11308+ struct acl_object_label *match;
11309+
11310+ match = subj->obj_hash[index];
11311+
11312+ while (match && (match->inode != oldinode ||
11313+ match->device != olddevice ||
11314+ !(match->mode & GR_DELETED)))
11315+ match = match->next;
11316+
11317+ if (match && (match->inode == oldinode)
11318+ && (match->device == olddevice)
11319+ && (match->mode & GR_DELETED)) {
11320+ if (match->prev == NULL) {
11321+ subj->obj_hash[index] = match->next;
11322+ if (match->next != NULL)
11323+ match->next->prev = NULL;
11324+ } else {
11325+ match->prev->next = match->next;
11326+ if (match->next != NULL)
11327+ match->next->prev = match->prev;
11328+ }
11329+ match->prev = NULL;
11330+ match->next = NULL;
11331+ match->inode = newinode;
11332+ match->device = newdevice;
11333+ match->mode &= ~GR_DELETED;
11334+
11335+ insert_acl_obj_label(match, subj);
11336+ }
11337+
11338+ return;
11339+}
11340+
11341+static void
11342+update_acl_subj_label(const ino_t oldinode, const dev_t olddevice,
11343+ const ino_t newinode, const dev_t newdevice,
11344+ struct acl_role_label *role)
11345+{
11346+ unsigned int index = fhash(oldinode, olddevice, role->subj_hash_size);
11347+ struct acl_subject_label *match;
11348+
11349+ match = role->subj_hash[index];
11350+
11351+ while (match && (match->inode != oldinode ||
11352+ match->device != olddevice ||
11353+ !(match->mode & GR_DELETED)))
11354+ match = match->next;
11355+
11356+ if (match && (match->inode == oldinode)
11357+ && (match->device == olddevice)
11358+ && (match->mode & GR_DELETED)) {
11359+ if (match->prev == NULL) {
11360+ role->subj_hash[index] = match->next;
11361+ if (match->next != NULL)
11362+ match->next->prev = NULL;
11363+ } else {
11364+ match->prev->next = match->next;
11365+ if (match->next != NULL)
11366+ match->next->prev = match->prev;
11367+ }
11368+ match->prev = NULL;
11369+ match->next = NULL;
11370+ match->inode = newinode;
11371+ match->device = newdevice;
11372+ match->mode &= ~GR_DELETED;
11373+
11374+ insert_acl_subj_label(match, role);
11375+ }
11376+
11377+ return;
11378+}
11379+
11380+static void
11381+update_inodev_entry(const ino_t oldinode, const dev_t olddevice,
11382+ const ino_t newinode, const dev_t newdevice)
11383+{
11384+ unsigned int index = fhash(oldinode, olddevice, inodev_set.i_size);
11385+ struct inodev_entry *match;
11386+
11387+ match = inodev_set.i_hash[index];
11388+
11389+ while (match && (match->nentry->inode != oldinode ||
11390+ match->nentry->device != olddevice))
11391+ match = match->next;
11392+
11393+ if (match && (match->nentry->inode == oldinode)
11394+ && (match->nentry->device == olddevice)) {
11395+ if (match->prev == NULL) {
11396+ inodev_set.i_hash[index] = match->next;
11397+ if (match->next != NULL)
11398+ match->next->prev = NULL;
11399+ } else {
11400+ match->prev->next = match->next;
11401+ if (match->next != NULL)
11402+ match->next->prev = match->prev;
11403+ }
11404+ match->prev = NULL;
11405+ match->next = NULL;
11406+ match->nentry->inode = newinode;
11407+ match->nentry->device = newdevice;
11408+
11409+ insert_inodev_entry(match);
11410+ }
11411+
11412+ return;
11413+}
11414+
11415+static void
11416+do_handle_create(const struct name_entry *matchn, const struct dentry *dentry,
11417+ const struct vfsmount *mnt)
11418+{
11419+ struct acl_subject_label *subj;
11420+ struct acl_role_label *role;
11421+ unsigned int i, x;
11422+
11423+ FOR_EACH_ROLE_START(role, i)
11424+ update_acl_subj_label(matchn->inode, matchn->device,
11425+ dentry->d_inode->i_ino,
11426+ dentry->d_inode->i_sb->s_dev, role);
11427+
11428+ FOR_EACH_NESTED_SUBJECT_START(role, subj)
11429+ if ((subj->inode == dentry->d_inode->i_ino) &&
11430+ (subj->device == dentry->d_inode->i_sb->s_dev)) {
11431+ subj->inode = dentry->d_inode->i_ino;
11432+ subj->device = dentry->d_inode->i_sb->s_dev;
11433+ }
11434+ FOR_EACH_NESTED_SUBJECT_END(subj)
11435+ FOR_EACH_SUBJECT_START(role, subj, x)
11436+ update_acl_obj_label(matchn->inode, matchn->device,
11437+ dentry->d_inode->i_ino,
11438+ dentry->d_inode->i_sb->s_dev, subj);
11439+ FOR_EACH_SUBJECT_END(subj,x)
11440+ FOR_EACH_ROLE_END(role,i)
11441+
11442+ update_inodev_entry(matchn->inode, matchn->device,
11443+ dentry->d_inode->i_ino, dentry->d_inode->i_sb->s_dev);
11444+
11445+ return;
11446+}
11447+
11448+void
11449+gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
11450+{
11451+ struct name_entry *matchn;
11452+
11453+ if (unlikely(!(gr_status & GR_READY)))
11454+ return;
11455+
11456+ preempt_disable();
11457+ matchn = lookup_name_entry(gr_to_filename_rbac(dentry, mnt));
11458+
11459+ if (unlikely((unsigned long)matchn)) {
11460+ write_lock(&gr_inode_lock);
11461+ do_handle_create(matchn, dentry, mnt);
11462+ write_unlock(&gr_inode_lock);
11463+ }
11464+ preempt_enable();
11465+
11466+ return;
11467+}
11468+
11469+void
11470+gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
11471+ struct dentry *old_dentry,
11472+ struct dentry *new_dentry,
11473+ struct vfsmount *mnt, const __u8 replace)
11474+{
11475+ struct name_entry *matchn;
11476+
11477+ if (unlikely(!(gr_status & GR_READY)))
11478+ return;
11479+
11480+ preempt_disable();
11481+ matchn = lookup_name_entry(gr_to_filename_rbac(new_dentry, mnt));
11482+
11483+ /* we wouldn't have to check d_inode if it weren't for
11484+ NFS silly-renaming
11485+ */
11486+
11487+ write_lock(&gr_inode_lock);
11488+ if (unlikely(replace && new_dentry->d_inode)) {
11489+ if (unlikely(lookup_inodev_entry(new_dentry->d_inode->i_ino,
11490+ new_dentry->d_inode->i_sb->s_dev) &&
11491+ (old_dentry->d_inode->i_nlink <= 1)))
11492+ do_handle_delete(new_dentry->d_inode->i_ino,
11493+ new_dentry->d_inode->i_sb->s_dev);
11494+ }
11495+
11496+ if (unlikely(lookup_inodev_entry(old_dentry->d_inode->i_ino,
11497+ old_dentry->d_inode->i_sb->s_dev) &&
11498+ (old_dentry->d_inode->i_nlink <= 1)))
11499+ do_handle_delete(old_dentry->d_inode->i_ino,
11500+ old_dentry->d_inode->i_sb->s_dev);
11501+
11502+ if (unlikely((unsigned long)matchn))
11503+ do_handle_create(matchn, old_dentry, mnt);
11504+
11505+ write_unlock(&gr_inode_lock);
11506+ preempt_enable();
11507+
11508+ return;
11509+}
11510+
11511+static int
11512+lookup_special_role_auth(__u16 mode, const char *rolename, unsigned char **salt,
11513+ unsigned char **sum)
11514+{
11515+ struct acl_role_label *r;
11516+ struct role_allowed_ip *ipp;
11517+ struct role_transition *trans;
11518+ unsigned int i;
11519+ int found = 0;
11520+
11521+ /* check transition table */
11522+
11523+ for (trans = current->role->transitions; trans; trans = trans->next) {
11524+ if (!strcmp(rolename, trans->rolename)) {
11525+ found = 1;
11526+ break;
11527+ }
11528+ }
11529+
11530+ if (!found)
11531+ return 0;
11532+
11533+ /* handle special roles that do not require authentication
11534+ and check ip */
11535+
11536+ FOR_EACH_ROLE_START(r, i)
11537+ if (!strcmp(rolename, r->rolename) &&
11538+ (r->roletype & GR_ROLE_SPECIAL)) {
11539+ found = 0;
11540+ if (r->allowed_ips != NULL) {
11541+ for (ipp = r->allowed_ips; ipp; ipp = ipp->next) {
11542+ if ((ntohl(current->signal->curr_ip) & ipp->netmask) ==
11543+ (ntohl(ipp->addr) & ipp->netmask))
11544+ found = 1;
11545+ }
11546+ } else
11547+ found = 2;
11548+ if (!found)
11549+ return 0;
11550+
11551+ if (((mode == SPROLE) && (r->roletype & GR_ROLE_NOPW)) ||
11552+ ((mode == SPROLEPAM) && (r->roletype & GR_ROLE_PAM))) {
11553+ *salt = NULL;
11554+ *sum = NULL;
11555+ return 1;
11556+ }
11557+ }
11558+ FOR_EACH_ROLE_END(r,i)
11559+
11560+ for (i = 0; i < num_sprole_pws; i++) {
11561+ if (!strcmp(rolename, acl_special_roles[i]->rolename)) {
11562+ *salt = acl_special_roles[i]->salt;
11563+ *sum = acl_special_roles[i]->sum;
11564+ return 1;
11565+ }
11566+ }
11567+
11568+ return 0;
11569+}
11570+
11571+static void
11572+assign_special_role(char *rolename)
11573+{
11574+ struct acl_object_label *obj;
11575+ struct acl_role_label *r;
11576+ struct acl_role_label *assigned = NULL;
11577+ struct task_struct *tsk;
11578+ struct file *filp;
11579+ unsigned int i;
11580+
11581+ FOR_EACH_ROLE_START(r, i)
11582+ if (!strcmp(rolename, r->rolename) &&
11583+ (r->roletype & GR_ROLE_SPECIAL))
11584+ assigned = r;
11585+ FOR_EACH_ROLE_END(r,i)
11586+
11587+ if (!assigned)
11588+ return;
11589+
11590+ read_lock(&tasklist_lock);
11591+ read_lock(&grsec_exec_file_lock);
11592+
11593+ tsk = current->parent;
11594+ if (tsk == NULL)
11595+ goto out_unlock;
11596+
11597+ filp = tsk->exec_file;
11598+ if (filp == NULL)
11599+ goto out_unlock;
11600+
11601+ tsk->is_writable = 0;
11602+
11603+ tsk->acl_sp_role = 1;
11604+ tsk->acl_role_id = ++acl_sp_role_value;
11605+ tsk->role = assigned;
11606+ tsk->acl = chk_subj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role);
11607+
11608+ /* ignore additional mmap checks for processes that are writable
11609+ by the default ACL */
11610+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
11611+ if (unlikely(obj->mode & GR_WRITE))
11612+ tsk->is_writable = 1;
11613+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role->root_label);
11614+ if (unlikely(obj->mode & GR_WRITE))
11615+ tsk->is_writable = 1;
11616+
11617+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
11618+ printk(KERN_ALERT "Assigning special role:%s subject:%s to process (%s:%d)\n", tsk->role->rolename, tsk->acl->filename, tsk->comm, tsk->pid);
11619+#endif
11620+
11621+out_unlock:
11622+ read_unlock(&grsec_exec_file_lock);
11623+ read_unlock(&tasklist_lock);
11624+ return;
11625+}
11626+
11627+int gr_check_secure_terminal(struct task_struct *task)
11628+{
11629+ struct task_struct *p, *p2, *p3;
11630+ struct files_struct *files;
11631+ struct fdtable *fdt;
11632+ struct file *our_file = NULL, *file;
11633+ int i;
11634+
11635+ if (task->signal->tty == NULL)
11636+ return 1;
11637+
11638+ files = get_files_struct(task);
11639+ if (files != NULL) {
11640+ rcu_read_lock();
11641+ fdt = files_fdtable(files);
11642+ for (i=0; i < fdt->max_fds; i++) {
11643+ file = fcheck_files(files, i);
11644+ if (file && (our_file == NULL) && (file->private_data == task->signal->tty)) {
11645+ get_file(file);
11646+ our_file = file;
11647+ }
11648+ }
11649+ rcu_read_unlock();
11650+ put_files_struct(files);
11651+ }
11652+
11653+ if (our_file == NULL)
11654+ return 1;
11655+
11656+ read_lock(&tasklist_lock);
11657+ do_each_thread(p2, p) {
11658+ files = get_files_struct(p);
11659+ if (files == NULL ||
11660+ (p->signal && p->signal->tty == task->signal->tty)) {
11661+ if (files != NULL)
11662+ put_files_struct(files);
11663+ continue;
11664+ }
11665+ rcu_read_lock();
11666+ fdt = files_fdtable(files);
11667+ for (i=0; i < fdt->max_fds; i++) {
11668+ file = fcheck_files(files, i);
11669+ if (file && S_ISCHR(file->f_dentry->d_inode->i_mode) &&
11670+ file->f_dentry->d_inode->i_rdev == our_file->f_dentry->d_inode->i_rdev) {
11671+ p3 = task;
11672+ while (p3->pid > 0) {
11673+ if (p3 == p)
11674+ break;
11675+ p3 = p3->parent;
11676+ }
11677+ if (p3 == p)
11678+ break;
11679+ gr_log_ttysniff(GR_DONT_AUDIT_GOOD, GR_TTYSNIFF_ACL_MSG, p);
11680+ gr_handle_alertkill(p);
11681+ rcu_read_unlock();
11682+ put_files_struct(files);
11683+ read_unlock(&tasklist_lock);
11684+ fput(our_file);
11685+ return 0;
11686+ }
11687+ }
11688+ rcu_read_unlock();
11689+ put_files_struct(files);
11690+ } while_each_thread(p2, p);
11691+ read_unlock(&tasklist_lock);
11692+
11693+ fput(our_file);
11694+ return 1;
11695+}
11696+
11697+ssize_t
11698+write_grsec_handler(struct file *file, const char * buf, size_t count, loff_t *ppos)
11699+{
11700+ struct gr_arg_wrapper uwrap;
11701+ unsigned char *sprole_salt;
11702+ unsigned char *sprole_sum;
11703+ int error = sizeof (struct gr_arg_wrapper);
11704+ int error2 = 0;
11705+
11706+ down(&gr_dev_sem);
11707+
11708+ if ((gr_status & GR_READY) && !(current->acl->mode & GR_KERNELAUTH)) {
11709+ error = -EPERM;
11710+ goto out;
11711+ }
11712+
11713+ if (count != sizeof (struct gr_arg_wrapper)) {
11714+ gr_log_int_int(GR_DONT_AUDIT_GOOD, GR_DEV_ACL_MSG, (int)count, (int)sizeof(struct gr_arg_wrapper));
11715+ error = -EINVAL;
11716+ goto out;
11717+ }
11718+
11719+
11720+ if (gr_auth_expires && time_after_eq(get_seconds(), gr_auth_expires)) {
11721+ gr_auth_expires = 0;
11722+ gr_auth_attempts = 0;
11723+ }
11724+
11725+ if (copy_from_user(&uwrap, buf, sizeof (struct gr_arg_wrapper))) {
11726+ error = -EFAULT;
11727+ goto out;
11728+ }
11729+
11730+ if ((uwrap.version != GRSECURITY_VERSION) || (uwrap.size != sizeof(struct gr_arg))) {
11731+ error = -EINVAL;
11732+ goto out;
11733+ }
11734+
11735+ if (copy_from_user(gr_usermode, uwrap.arg, sizeof (struct gr_arg))) {
11736+ error = -EFAULT;
11737+ goto out;
11738+ }
11739+
11740+ if (gr_usermode->mode != SPROLE && gr_usermode->mode != SPROLEPAM &&
11741+ gr_auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES &&
11742+ time_after(gr_auth_expires, get_seconds())) {
11743+ error = -EBUSY;
11744+ goto out;
11745+ }
11746+
11747+ /* if non-root trying to do anything other than use a special role,
11748+ do not attempt authentication, do not count towards authentication
11749+ locking
11750+ */
11751+
11752+ if (gr_usermode->mode != SPROLE && gr_usermode->mode != STATUS &&
11753+ gr_usermode->mode != UNSPROLE && gr_usermode->mode != SPROLEPAM &&
11754+ current->uid) {
11755+ error = -EPERM;
11756+ goto out;
11757+ }
11758+
11759+ /* ensure pw and special role name are null terminated */
11760+
11761+ gr_usermode->pw[GR_PW_LEN - 1] = '\0';
11762+ gr_usermode->sp_role[GR_SPROLE_LEN - 1] = '\0';
11763+
11764+ /* Okay.
11765+ * We have our enough of the argument structure..(we have yet
11766+ * to copy_from_user the tables themselves) . Copy the tables
11767+ * only if we need them, i.e. for loading operations. */
11768+
11769+ switch (gr_usermode->mode) {
11770+ case STATUS:
11771+ if (gr_status & GR_READY) {
11772+ error = 1;
11773+ if (!gr_check_secure_terminal(current))
11774+ error = 3;
11775+ } else
11776+ error = 2;
11777+ goto out;
11778+ case SHUTDOWN:
11779+ if ((gr_status & GR_READY)
11780+ && !(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
11781+ gr_status &= ~GR_READY;
11782+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTS_ACL_MSG);
11783+ free_variables();
11784+ memset(gr_usermode, 0, sizeof (struct gr_arg));
11785+ memset(gr_system_salt, 0, GR_SALT_LEN);
11786+ memset(gr_system_sum, 0, GR_SHA_LEN);
11787+ } else if (gr_status & GR_READY) {
11788+ gr_log_noargs(GR_DONT_AUDIT, GR_SHUTF_ACL_MSG);
11789+ error = -EPERM;
11790+ } else {
11791+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTI_ACL_MSG);
11792+ error = -EAGAIN;
11793+ }
11794+ break;
11795+ case ENABLE:
11796+ if (!(gr_status & GR_READY) && !(error2 = gracl_init(gr_usermode)))
11797+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_ENABLE_ACL_MSG, GR_VERSION);
11798+ else {
11799+ if (gr_status & GR_READY)
11800+ error = -EAGAIN;
11801+ else
11802+ error = error2;
11803+ gr_log_str(GR_DONT_AUDIT, GR_ENABLEF_ACL_MSG, GR_VERSION);
11804+ }
11805+ break;
11806+ case RELOAD:
11807+ if (!(gr_status & GR_READY)) {
11808+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOADI_ACL_MSG, GR_VERSION);
11809+ error = -EAGAIN;
11810+ } else if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
11811+ lock_kernel();
11812+ gr_status &= ~GR_READY;
11813+ free_variables();
11814+ if (!(error2 = gracl_init(gr_usermode))) {
11815+ unlock_kernel();
11816+ gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOAD_ACL_MSG, GR_VERSION);
11817+ } else {
11818+ unlock_kernel();
11819+ error = error2;
11820+ gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION);
11821+ }
11822+ } else {
11823+ gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION);
11824+ error = -EPERM;
11825+ }
11826+ break;
11827+ case SEGVMOD:
11828+ if (unlikely(!(gr_status & GR_READY))) {
11829+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODI_ACL_MSG);
11830+ error = -EAGAIN;
11831+ break;
11832+ }
11833+
11834+ if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
11835+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODS_ACL_MSG);
11836+ if (gr_usermode->segv_device && gr_usermode->segv_inode) {
11837+ struct acl_subject_label *segvacl;
11838+ segvacl =
11839+ lookup_acl_subj_label(gr_usermode->segv_inode,
11840+ gr_usermode->segv_device,
11841+ current->role);
11842+ if (segvacl) {
11843+ segvacl->crashes = 0;
11844+ segvacl->expires = 0;
11845+ }
11846+ } else if (gr_find_uid(gr_usermode->segv_uid) >= 0) {
11847+ gr_remove_uid(gr_usermode->segv_uid);
11848+ }
11849+ } else {
11850+ gr_log_noargs(GR_DONT_AUDIT, GR_SEGVMODF_ACL_MSG);
11851+ error = -EPERM;
11852+ }
11853+ break;
11854+ case SPROLE:
11855+ case SPROLEPAM:
11856+ if (unlikely(!(gr_status & GR_READY))) {
11857+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SPROLEI_ACL_MSG);
11858+ error = -EAGAIN;
11859+ break;
11860+ }
11861+
11862+ if (current->role->expires && time_after_eq(get_seconds(), current->role->expires)) {
11863+ current->role->expires = 0;
11864+ current->role->auth_attempts = 0;
11865+ }
11866+
11867+ if (current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES &&
11868+ time_after(current->role->expires, get_seconds())) {
11869+ error = -EBUSY;
11870+ goto out;
11871+ }
11872+
11873+ if (lookup_special_role_auth
11874+ (gr_usermode->mode, gr_usermode->sp_role, &sprole_salt, &sprole_sum)
11875+ && ((!sprole_salt && !sprole_sum)
11876+ || !(chkpw(gr_usermode, sprole_salt, sprole_sum)))) {
11877+ char *p = "";
11878+ assign_special_role(gr_usermode->sp_role);
11879+ read_lock(&tasklist_lock);
11880+ if (current->parent)
11881+ p = current->parent->role->rolename;
11882+ read_unlock(&tasklist_lock);
11883+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLES_ACL_MSG,
11884+ p, acl_sp_role_value);
11885+ } else {
11886+ gr_log_str(GR_DONT_AUDIT, GR_SPROLEF_ACL_MSG, gr_usermode->sp_role);
11887+ error = -EPERM;
11888+ if(!(current->role->auth_attempts++))
11889+ current->role->expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT;
11890+
11891+ goto out;
11892+ }
11893+ break;
11894+ case UNSPROLE:
11895+ if (unlikely(!(gr_status & GR_READY))) {
11896+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_UNSPROLEI_ACL_MSG);
11897+ error = -EAGAIN;
11898+ break;
11899+ }
11900+
11901+ if (current->role->roletype & GR_ROLE_SPECIAL) {
11902+ char *p = "";
11903+ int i = 0;
11904+
11905+ read_lock(&tasklist_lock);
11906+ if (current->parent) {
11907+ p = current->parent->role->rolename;
11908+ i = current->parent->acl_role_id;
11909+ }
11910+ read_unlock(&tasklist_lock);
11911+
11912+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_UNSPROLES_ACL_MSG, p, i);
11913+ gr_set_acls(1);
11914+ } else {
11915+ gr_log_str(GR_DONT_AUDIT, GR_UNSPROLEF_ACL_MSG, current->role->rolename);
11916+ error = -EPERM;
11917+ goto out;
11918+ }
11919+ break;
11920+ default:
11921+ gr_log_int(GR_DONT_AUDIT, GR_INVMODE_ACL_MSG, gr_usermode->mode);
11922+ error = -EINVAL;
11923+ break;
11924+ }
11925+
11926+ if (error != -EPERM)
11927+ goto out;
11928+
11929+ if(!(gr_auth_attempts++))
11930+ gr_auth_expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT;
11931+
11932+ out:
11933+ up(&gr_dev_sem);
11934+ return error;
11935+}
11936+
11937+int
11938+gr_set_acls(const int type)
11939+{
11940+ struct acl_object_label *obj;
11941+ struct task_struct *task, *task2;
11942+ struct file *filp;
11943+ struct acl_role_label *role = current->role;
11944+ __u16 acl_role_id = current->acl_role_id;
11945+
11946+ read_lock(&tasklist_lock);
11947+ read_lock(&grsec_exec_file_lock);
11948+ do_each_thread(task2, task) {
11949+ /* check to see if we're called from the exit handler,
11950+ if so, only replace ACLs that have inherited the admin
11951+ ACL */
11952+
11953+ if (type && (task->role != role ||
11954+ task->acl_role_id != acl_role_id))
11955+ continue;
11956+
11957+ task->acl_role_id = 0;
11958+ task->acl_sp_role = 0;
11959+
11960+ if ((filp = task->exec_file)) {
11961+ task->role = lookup_acl_role_label(task, task->uid, task->gid);
11962+
11963+ task->acl =
11964+ chk_subj_label(filp->f_dentry, filp->f_vfsmnt,
11965+ task->role);
11966+ if (task->acl) {
11967+ struct acl_subject_label *curr;
11968+ curr = task->acl;
11969+
11970+ task->is_writable = 0;
11971+ /* ignore additional mmap checks for processes that are writable
11972+ by the default ACL */
11973+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
11974+ if (unlikely(obj->mode & GR_WRITE))
11975+ task->is_writable = 1;
11976+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label);
11977+ if (unlikely(obj->mode & GR_WRITE))
11978+ task->is_writable = 1;
11979+
11980+ gr_set_proc_res(task);
11981+
11982+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
11983+ printk(KERN_ALERT "gr_set_acls for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
11984+#endif
11985+ } else {
11986+ read_unlock(&grsec_exec_file_lock);
11987+ read_unlock(&tasklist_lock);
11988+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_DEFACL_MSG, task->comm, task->pid);
11989+ return 1;
11990+ }
11991+ } else {
11992+ // it's a kernel process
11993+ task->role = kernel_role;
11994+ task->acl = kernel_role->root_label;
11995+#ifdef CONFIG_GRKERNSEC_ACL_HIDEKERN
11996+ task->acl->mode &= ~GR_PROCFIND;
11997+#endif
11998+ }
11999+ } while_each_thread(task2, task);
12000+ read_unlock(&grsec_exec_file_lock);
12001+ read_unlock(&tasklist_lock);
12002+ return 0;
12003+}
12004+
12005+void
12006+gr_learn_resource(const struct task_struct *task,
12007+ const int res, const unsigned long wanted, const int gt)
12008+{
12009+ struct acl_subject_label *acl;
12010+
12011+ if (unlikely((gr_status & GR_READY) &&
12012+ task->acl && (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))))
12013+ goto skip_reslog;
12014+
12015+#ifdef CONFIG_GRKERNSEC_RESLOG
12016+ gr_log_resource(task, res, wanted, gt);
12017+#endif
12018+ skip_reslog:
12019+
12020+ if (unlikely(!(gr_status & GR_READY) || !wanted))
12021+ return;
12022+
12023+ acl = task->acl;
12024+
12025+ if (likely(!acl || !(acl->mode & (GR_LEARN | GR_INHERITLEARN)) ||
12026+ !(acl->resmask & (1 << (unsigned short) res))))
12027+ return;
12028+
12029+ if (wanted >= acl->res[res].rlim_cur) {
12030+ unsigned long res_add;
12031+
12032+ res_add = wanted;
12033+ switch (res) {
12034+ case RLIMIT_CPU:
12035+ res_add += GR_RLIM_CPU_BUMP;
12036+ break;
12037+ case RLIMIT_FSIZE:
12038+ res_add += GR_RLIM_FSIZE_BUMP;
12039+ break;
12040+ case RLIMIT_DATA:
12041+ res_add += GR_RLIM_DATA_BUMP;
12042+ break;
12043+ case RLIMIT_STACK:
12044+ res_add += GR_RLIM_STACK_BUMP;
12045+ break;
12046+ case RLIMIT_CORE:
12047+ res_add += GR_RLIM_CORE_BUMP;
12048+ break;
12049+ case RLIMIT_RSS:
12050+ res_add += GR_RLIM_RSS_BUMP;
12051+ break;
12052+ case RLIMIT_NPROC:
12053+ res_add += GR_RLIM_NPROC_BUMP;
12054+ break;
12055+ case RLIMIT_NOFILE:
12056+ res_add += GR_RLIM_NOFILE_BUMP;
12057+ break;
12058+ case RLIMIT_MEMLOCK:
12059+ res_add += GR_RLIM_MEMLOCK_BUMP;
12060+ break;
12061+ case RLIMIT_AS:
12062+ res_add += GR_RLIM_AS_BUMP;
12063+ break;
12064+ case RLIMIT_LOCKS:
12065+ res_add += GR_RLIM_LOCKS_BUMP;
12066+ break;
12067+ }
12068+
12069+ acl->res[res].rlim_cur = res_add;
12070+
12071+ if (wanted > acl->res[res].rlim_max)
12072+ acl->res[res].rlim_max = res_add;
12073+
12074+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
12075+ task->role->roletype, acl->filename,
12076+ acl->res[res].rlim_cur, acl->res[res].rlim_max,
12077+ "", (unsigned long) res);
12078+ }
12079+
12080+ return;
12081+}
12082+
12083+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
12084+void
12085+pax_set_initial_flags(struct linux_binprm *bprm)
12086+{
12087+ struct task_struct *task = current;
12088+ struct acl_subject_label *proc;
12089+ unsigned long flags;
12090+
12091+ if (unlikely(!(gr_status & GR_READY)))
12092+ return;
12093+
12094+ flags = pax_get_flags(task);
12095+
12096+ proc = task->acl;
12097+
12098+ if (proc->pax_flags & GR_PAX_DISABLE_PAGEEXEC)
12099+ flags &= ~MF_PAX_PAGEEXEC;
12100+ if (proc->pax_flags & GR_PAX_DISABLE_SEGMEXEC)
12101+ flags &= ~MF_PAX_SEGMEXEC;
12102+ if (proc->pax_flags & GR_PAX_DISABLE_RANDMMAP)
12103+ flags &= ~MF_PAX_RANDMMAP;
12104+ if (proc->pax_flags & GR_PAX_DISABLE_EMUTRAMP)
12105+ flags &= ~MF_PAX_EMUTRAMP;
12106+ if (proc->pax_flags & GR_PAX_DISABLE_MPROTECT)
12107+ flags &= ~MF_PAX_MPROTECT;
12108+
12109+ if (proc->pax_flags & GR_PAX_ENABLE_PAGEEXEC)
12110+ flags |= MF_PAX_PAGEEXEC;
12111+ if (proc->pax_flags & GR_PAX_ENABLE_SEGMEXEC)
12112+ flags |= MF_PAX_SEGMEXEC;
12113+ if (proc->pax_flags & GR_PAX_ENABLE_RANDMMAP)
12114+ flags |= MF_PAX_RANDMMAP;
12115+ if (proc->pax_flags & GR_PAX_ENABLE_EMUTRAMP)
12116+ flags |= MF_PAX_EMUTRAMP;
12117+ if (proc->pax_flags & GR_PAX_ENABLE_MPROTECT)
12118+ flags |= MF_PAX_MPROTECT;
12119+
12120+ pax_set_flags(task, flags);
12121+
12122+ return;
12123+}
12124+#endif
12125+
12126+#ifdef CONFIG_SYSCTL
12127+extern struct proc_dir_entry *proc_sys_root;
12128+
12129+/* the following function is called under the BKL */
12130+
12131+__u32
12132+gr_handle_sysctl(const struct ctl_table *table, const void *oldval,
12133+ const void *newval)
12134+{
12135+ struct proc_dir_entry *tmp;
12136+ struct nameidata nd;
12137+ const char *proc_sys = "/proc/sys";
12138+ char *path;
12139+ struct acl_object_label *obj;
12140+ unsigned short len = 0, pos = 0, depth = 0, i;
12141+ __u32 err = 0;
12142+ __u32 mode = 0;
12143+
12144+ if (unlikely(!(gr_status & GR_READY)))
12145+ return 1;
12146+
12147+ path = per_cpu_ptr(gr_shared_page[0], smp_processor_id());
12148+
12149+ if (oldval)
12150+ mode |= GR_READ;
12151+ if (newval)
12152+ mode |= GR_WRITE;
12153+
12154+ /* convert the requested sysctl entry into a pathname */
12155+
12156+ for (tmp = table->de; tmp != proc_sys_root; tmp = tmp->parent) {
12157+ len += strlen(tmp->name);
12158+ len++;
12159+ depth++;
12160+ }
12161+
12162+ if ((len + depth + strlen(proc_sys) + 1) > PAGE_SIZE)
12163+ return 0; /* deny */
12164+
12165+ memset(path, 0, PAGE_SIZE);
12166+
12167+ memcpy(path, proc_sys, strlen(proc_sys));
12168+
12169+ pos += strlen(proc_sys);
12170+
12171+ for (; depth > 0; depth--) {
12172+ path[pos] = '/';
12173+ pos++;
12174+ for (i = 1, tmp = table->de; tmp != proc_sys_root;
12175+ tmp = tmp->parent) {
12176+ if (depth == i) {
12177+ memcpy(path + pos, tmp->name,
12178+ strlen(tmp->name));
12179+ pos += strlen(tmp->name);
12180+ }
12181+ i++;
12182+ }
12183+ }
12184+
12185+ err = path_lookup(path, LOOKUP_FOLLOW, &nd);
12186+
12187+ if (err)
12188+ goto out;
12189+
12190+ obj = chk_obj_label(nd.dentry, nd.mnt, current->acl);
12191+ err = obj->mode & (mode | to_gr_audit(mode) | GR_SUPPRESS);
12192+
12193+ if (unlikely((current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) &&
12194+ ((err & mode) != mode))) {
12195+ __u32 new_mode = mode;
12196+
12197+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
12198+
12199+ err = new_mode;
12200+ gr_log_learn(current, nd.dentry, nd.mnt, new_mode);
12201+ } else if ((err & mode) != mode && !(err & GR_SUPPRESS)) {
12202+ gr_log_str4(GR_DONT_AUDIT, GR_SYSCTL_ACL_MSG, "denied",
12203+ path, (mode & GR_READ) ? " reading" : "",
12204+ (mode & GR_WRITE) ? " writing" : "");
12205+ err = 0;
12206+ } else if ((err & mode) != mode) {
12207+ err = 0;
12208+ } else if (((err & mode) == mode) && (err & GR_AUDITS)) {
12209+ gr_log_str4(GR_DO_AUDIT, GR_SYSCTL_ACL_MSG, "successful",
12210+ path, (mode & GR_READ) ? " reading" : "",
12211+ (mode & GR_WRITE) ? " writing" : "");
12212+ }
12213+
12214+ path_release(&nd);
12215+
12216+ out:
12217+ return err;
12218+}
12219+#endif
12220+
12221+int
12222+gr_handle_proc_ptrace(struct task_struct *task)
12223+{
12224+ struct file *filp;
12225+ struct task_struct *tmp = task;
12226+ struct task_struct *curtemp = current;
12227+ __u32 retmode;
12228+
12229+ if (unlikely(!(gr_status & GR_READY)))
12230+ return 0;
12231+
12232+ read_lock(&tasklist_lock);
12233+ read_lock(&grsec_exec_file_lock);
12234+ filp = task->exec_file;
12235+
12236+ while (tmp->pid > 0) {
12237+ if (tmp == curtemp)
12238+ break;
12239+ tmp = tmp->parent;
12240+ }
12241+
12242+ if (!filp || (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE))) {
12243+ read_unlock(&grsec_exec_file_lock);
12244+ read_unlock(&tasklist_lock);
12245+ return 1;
12246+ }
12247+
12248+ retmode = gr_search_file(filp->f_dentry, GR_NOPTRACE, filp->f_vfsmnt);
12249+ read_unlock(&grsec_exec_file_lock);
12250+ read_unlock(&tasklist_lock);
12251+
12252+ if (retmode & GR_NOPTRACE)
12253+ return 1;
12254+
12255+ if (!(current->acl->mode & GR_POVERRIDE) && !(current->role->roletype & GR_ROLE_GOD)
12256+ && (current->acl != task->acl || (current->acl != current->role->root_label
12257+ && current->pid != task->pid)))
12258+ return 1;
12259+
12260+ return 0;
12261+}
12262+
12263+int
12264+gr_handle_ptrace(struct task_struct *task, const long request)
12265+{
12266+ struct task_struct *tmp = task;
12267+ struct task_struct *curtemp = current;
12268+ __u32 retmode;
12269+
12270+ if (unlikely(!(gr_status & GR_READY)))
12271+ return 0;
12272+
12273+ read_lock(&tasklist_lock);
12274+ while (tmp->pid > 0) {
12275+ if (tmp == curtemp)
12276+ break;
12277+ tmp = tmp->parent;
12278+ }
12279+
12280+ if (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE)) {
12281+ read_unlock(&tasklist_lock);
12282+ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
12283+ return 1;
12284+ }
12285+ read_unlock(&tasklist_lock);
12286+
12287+ read_lock(&grsec_exec_file_lock);
12288+ if (unlikely(!task->exec_file)) {
12289+ read_unlock(&grsec_exec_file_lock);
12290+ return 0;
12291+ }
12292+
12293+ retmode = gr_search_file(task->exec_file->f_dentry, GR_PTRACERD | GR_NOPTRACE, task->exec_file->f_vfsmnt);
12294+ read_unlock(&grsec_exec_file_lock);
12295+
12296+ if (retmode & GR_NOPTRACE) {
12297+ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
12298+ return 1;
12299+ }
12300+
12301+ if (retmode & GR_PTRACERD) {
12302+ switch (request) {
12303+ case PTRACE_POKETEXT:
12304+ case PTRACE_POKEDATA:
12305+ case PTRACE_POKEUSR:
12306+#if !defined(CONFIG_PPC32) && !defined(CONFIG_PPC64) && !defined(CONFIG_PARISC) && !defined(CONFIG_ALPHA) && !defined(CONFIG_IA64)
12307+ case PTRACE_SETREGS:
12308+ case PTRACE_SETFPREGS:
12309+#endif
12310+#ifdef CONFIG_X86
12311+ case PTRACE_SETFPXREGS:
12312+#endif
12313+#ifdef CONFIG_ALTIVEC
12314+ case PTRACE_SETVRREGS:
12315+#endif
12316+ return 1;
12317+ default:
12318+ return 0;
12319+ }
12320+ } else if (!(current->acl->mode & GR_POVERRIDE) &&
12321+ !(current->role->roletype & GR_ROLE_GOD) &&
12322+ (current->acl != task->acl)) {
12323+ gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
12324+ return 1;
12325+ }
12326+
12327+ return 0;
12328+}
12329+
12330+static int is_writable_mmap(const struct file *filp)
12331+{
12332+ struct task_struct *task = current;
12333+ struct acl_object_label *obj, *obj2;
12334+
12335+ if (gr_status & GR_READY && !(task->acl->mode & GR_OVERRIDE) &&
12336+ !task->is_writable && S_ISREG(filp->f_dentry->d_inode->i_mode)) {
12337+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
12338+ obj2 = chk_obj_label(filp->f_dentry, filp->f_vfsmnt,
12339+ task->role->root_label);
12340+ if (unlikely((obj->mode & GR_WRITE) || (obj2->mode & GR_WRITE))) {
12341+ gr_log_fs_generic(GR_DONT_AUDIT, GR_WRITLIB_ACL_MSG, filp->f_dentry, filp->f_vfsmnt);
12342+ return 1;
12343+ }
12344+ }
12345+ return 0;
12346+}
12347+
12348+int
12349+gr_acl_handle_mmap(const struct file *file, const unsigned long prot)
12350+{
12351+ __u32 mode;
12352+
12353+ if (unlikely(!file || !(prot & PROT_EXEC)))
12354+ return 1;
12355+
12356+ if (is_writable_mmap(file))
12357+ return 0;
12358+
12359+ mode =
12360+ gr_search_file(file->f_dentry,
12361+ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
12362+ file->f_vfsmnt);
12363+
12364+ if (!gr_tpe_allow(file))
12365+ return 0;
12366+
12367+ if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) {
12368+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MMAP_ACL_MSG, file->f_dentry, file->f_vfsmnt);
12369+ return 0;
12370+ } else if (unlikely(!(mode & GR_EXEC))) {
12371+ return 0;
12372+ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
12373+ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MMAP_ACL_MSG, file->f_dentry, file->f_vfsmnt);
12374+ return 1;
12375+ }
12376+
12377+ return 1;
12378+}
12379+
12380+int
12381+gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
12382+{
12383+ __u32 mode;
12384+
12385+ if (unlikely(!file || !(prot & PROT_EXEC)))
12386+ return 1;
12387+
12388+ if (is_writable_mmap(file))
12389+ return 0;
12390+
12391+ mode =
12392+ gr_search_file(file->f_dentry,
12393+ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
12394+ file->f_vfsmnt);
12395+
12396+ if (!gr_tpe_allow(file))
12397+ return 0;
12398+
12399+ if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) {
12400+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MPROTECT_ACL_MSG, file->f_dentry, file->f_vfsmnt);
12401+ return 0;
12402+ } else if (unlikely(!(mode & GR_EXEC))) {
12403+ return 0;
12404+ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
12405+ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MPROTECT_ACL_MSG, file->f_dentry, file->f_vfsmnt);
12406+ return 1;
12407+ }
12408+
12409+ return 1;
12410+}
12411+
12412+void
12413+gr_acl_handle_psacct(struct task_struct *task, const long code)
12414+{
12415+ unsigned long runtime;
12416+ unsigned long cputime;
12417+ unsigned int wday, cday;
12418+ __u8 whr, chr;
12419+ __u8 wmin, cmin;
12420+ __u8 wsec, csec;
12421+
12422+ if (unlikely(!(gr_status & GR_READY) || !task->acl ||
12423+ !(task->acl->mode & GR_PROCACCT)))
12424+ return;
12425+
12426+ runtime = xtime.tv_sec - task->start_time.tv_sec;
12427+ wday = runtime / (3600 * 24);
12428+ runtime -= wday * (3600 * 24);
12429+ whr = runtime / 3600;
12430+ runtime -= whr * 3600;
12431+ wmin = runtime / 60;
12432+ runtime -= wmin * 60;
12433+ wsec = runtime;
12434+
12435+ cputime = (task->utime + task->stime) / HZ;
12436+ cday = cputime / (3600 * 24);
12437+ cputime -= cday * (3600 * 24);
12438+ chr = cputime / 3600;
12439+ cputime -= chr * 3600;
12440+ cmin = cputime / 60;
12441+ cputime -= cmin * 60;
12442+ csec = cputime;
12443+
12444+ gr_log_procacct(GR_DO_AUDIT, GR_ACL_PROCACCT_MSG, task, wday, whr, wmin, wsec, cday, chr, cmin, csec, code);
12445+
12446+ return;
12447+}
12448+
12449+void gr_set_kernel_label(struct task_struct *task)
12450+{
12451+ if (gr_status & GR_READY) {
12452+ task->role = kernel_role;
12453+ task->acl = kernel_role->root_label;
12454+ }
12455+ return;
12456+}
12457+
12458+int gr_acl_handle_filldir(const struct file *file, const char *name, const unsigned int namelen, const ino_t ino)
12459+{
12460+ struct task_struct *task = current;
12461+ struct dentry *dentry = file->f_dentry;
12462+ struct vfsmount *mnt = file->f_vfsmnt;
12463+ struct acl_object_label *obj, *tmp;
12464+ struct acl_subject_label *subj;
12465+ unsigned int bufsize;
12466+ int is_not_root;
12467+ char *path;
12468+
12469+ if (unlikely(!(gr_status & GR_READY)))
12470+ return 1;
12471+
12472+ if (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))
12473+ return 1;
12474+
12475+ subj = task->acl;
12476+ do {
12477+ obj = lookup_acl_obj_label(ino, dentry->d_inode->i_sb->s_dev, subj);
12478+ if (obj != NULL)
12479+ return (obj->mode & GR_FIND) ? 1 : 0;
12480+ } while ((subj = subj->parent_subject));
12481+
12482+ obj = chk_obj_label(dentry, mnt, task->acl);
12483+ if (obj->globbed == NULL)
12484+ return (obj->mode & GR_FIND) ? 1 : 0;
12485+
12486+ is_not_root = ((obj->filename[0] == '/') &&
12487+ (obj->filename[1] == '\0')) ? 0 : 1;
12488+ bufsize = PAGE_SIZE - namelen - is_not_root;
12489+
12490+ /* check bufsize > PAGE_SIZE || bufsize == 0 */
12491+ if (unlikely((bufsize - 1) > (PAGE_SIZE - 1)))
12492+ return 1;
12493+
12494+ preempt_disable();
12495+ path = d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()),
12496+ bufsize);
12497+
12498+ bufsize = strlen(path);
12499+
12500+ /* if base is "/", don't append an additional slash */
12501+ if (is_not_root)
12502+ *(path + bufsize) = '/';
12503+ memcpy(path + bufsize + is_not_root, name, namelen);
12504+ *(path + bufsize + namelen + is_not_root) = '\0';
12505+
12506+ tmp = obj->globbed;
12507+ while (tmp) {
12508+ if (!glob_match(tmp->filename, path)) {
12509+ preempt_enable();
12510+ return (tmp->mode & GR_FIND) ? 1 : 0;
12511+ }
12512+ tmp = tmp->next;
12513+ }
12514+ preempt_enable();
12515+ return (obj->mode & GR_FIND) ? 1 : 0;
12516+}
12517+
12518+EXPORT_SYMBOL(gr_learn_resource);
12519+EXPORT_SYMBOL(gr_set_kernel_label);
12520+#ifdef CONFIG_SECURITY
12521+EXPORT_SYMBOL(gr_check_user_change);
12522+EXPORT_SYMBOL(gr_check_group_change);
12523+#endif
12524+
12525diff -urNp linux-2.6.16.12/grsecurity/gracl_cap.c linux-2.6.16.12/grsecurity/gracl_cap.c
12526--- linux-2.6.16.12/grsecurity/gracl_cap.c 1969-12-31 19:00:00.000000000 -0500
12527+++ linux-2.6.16.12/grsecurity/gracl_cap.c 2006-05-01 20:17:33.000000000 -0400
12528@@ -0,0 +1,110 @@
12529+#include <linux/kernel.h>
12530+#include <linux/module.h>
12531+#include <linux/sched.h>
12532+#include <linux/capability.h>
12533+#include <linux/gracl.h>
12534+#include <linux/grsecurity.h>
12535+#include <linux/grinternal.h>
12536+
12537+static const char *captab_log[] = {
12538+ "CAP_CHOWN",
12539+ "CAP_DAC_OVERRIDE",
12540+ "CAP_DAC_READ_SEARCH",
12541+ "CAP_FOWNER",
12542+ "CAP_FSETID",
12543+ "CAP_KILL",
12544+ "CAP_SETGID",
12545+ "CAP_SETUID",
12546+ "CAP_SETPCAP",
12547+ "CAP_LINUX_IMMUTABLE",
12548+ "CAP_NET_BIND_SERVICE",
12549+ "CAP_NET_BROADCAST",
12550+ "CAP_NET_ADMIN",
12551+ "CAP_NET_RAW",
12552+ "CAP_IPC_LOCK",
12553+ "CAP_IPC_OWNER",
12554+ "CAP_SYS_MODULE",
12555+ "CAP_SYS_RAWIO",
12556+ "CAP_SYS_CHROOT",
12557+ "CAP_SYS_PTRACE",
12558+ "CAP_SYS_PACCT",
12559+ "CAP_SYS_ADMIN",
12560+ "CAP_SYS_BOOT",
12561+ "CAP_SYS_NICE",
12562+ "CAP_SYS_RESOURCE",
12563+ "CAP_SYS_TIME",
12564+ "CAP_SYS_TTY_CONFIG",
12565+ "CAP_MKNOD",
12566+ "CAP_LEASE"
12567+};
12568+
12569+EXPORT_SYMBOL(gr_task_is_capable);
12570+
12571+int
12572+gr_task_is_capable(struct task_struct *task, const int cap)
12573+{
12574+ struct acl_subject_label *curracl;
12575+ __u32 cap_drop = 0, cap_mask = 0;
12576+
12577+ if (!gr_acl_is_enabled())
12578+ return 1;
12579+
12580+ curracl = task->acl;
12581+
12582+ cap_drop = curracl->cap_lower;
12583+ cap_mask = curracl->cap_mask;
12584+
12585+ while ((curracl = curracl->parent_subject)) {
12586+ if (!(cap_mask & (1 << cap)) && (curracl->cap_mask & (1 << cap)))
12587+ cap_drop |= curracl->cap_lower & (1 << cap);
12588+ cap_mask |= curracl->cap_mask;
12589+ }
12590+
12591+ if (!cap_raised(cap_drop, cap))
12592+ return 1;
12593+
12594+ curracl = task->acl;
12595+
12596+ if ((curracl->mode & (GR_LEARN | GR_INHERITLEARN))
12597+ && cap_raised(task->cap_effective, cap)) {
12598+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
12599+ task->role->roletype, task->uid,
12600+ task->gid, task->exec_file ?
12601+ gr_to_filename(task->exec_file->f_dentry,
12602+ task->exec_file->f_vfsmnt) : curracl->filename,
12603+ curracl->filename, 0UL,
12604+ 0UL, "", (unsigned long) cap, NIPQUAD(task->signal->curr_ip));
12605+ return 1;
12606+ }
12607+
12608+ if ((cap >= 0) && (cap < (sizeof(captab_log)/sizeof(captab_log[0]))) && cap_raised(task->cap_effective, cap))
12609+ gr_log_cap(GR_DONT_AUDIT, GR_CAP_ACL_MSG, task, captab_log[cap]);
12610+
12611+ return 0;
12612+}
12613+
12614+int
12615+gr_is_capable_nolog(const int cap)
12616+{
12617+ struct acl_subject_label *curracl;
12618+ __u32 cap_drop = 0, cap_mask = 0;
12619+
12620+ if (!gr_acl_is_enabled())
12621+ return 1;
12622+
12623+ curracl = current->acl;
12624+
12625+ cap_drop = curracl->cap_lower;
12626+ cap_mask = curracl->cap_mask;
12627+
12628+ while ((curracl = curracl->parent_subject)) {
12629+ cap_drop |= curracl->cap_lower & (cap_mask & ~curracl->cap_mask);
12630+ cap_mask |= curracl->cap_mask;
12631+ }
12632+
12633+ if (!cap_raised(cap_drop, cap))
12634+ return 1;
12635+
12636+ return 0;
12637+}
12638+
12639diff -urNp linux-2.6.16.12/grsecurity/gracl_fs.c linux-2.6.16.12/grsecurity/gracl_fs.c
12640--- linux-2.6.16.12/grsecurity/gracl_fs.c 1969-12-31 19:00:00.000000000 -0500
12641+++ linux-2.6.16.12/grsecurity/gracl_fs.c 2006-05-01 20:17:33.000000000 -0400
12642@@ -0,0 +1,423 @@
12643+#include <linux/kernel.h>
12644+#include <linux/sched.h>
12645+#include <linux/types.h>
12646+#include <linux/fs.h>
12647+#include <linux/file.h>
12648+#include <linux/stat.h>
12649+#include <linux/grsecurity.h>
12650+#include <linux/grinternal.h>
12651+#include <linux/gracl.h>
12652+
12653+__u32
12654+gr_acl_handle_hidden_file(const struct dentry * dentry,
12655+ const struct vfsmount * mnt)
12656+{
12657+ __u32 mode;
12658+
12659+ if (unlikely(!dentry->d_inode))
12660+ return GR_FIND;
12661+
12662+ mode =
12663+ gr_search_file(dentry, GR_FIND | GR_AUDIT_FIND | GR_SUPPRESS, mnt);
12664+
12665+ if (unlikely(mode & GR_FIND && mode & GR_AUDIT_FIND)) {
12666+ gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt);
12667+ return mode;
12668+ } else if (unlikely(!(mode & GR_FIND) && !(mode & GR_SUPPRESS))) {
12669+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt);
12670+ return 0;
12671+ } else if (unlikely(!(mode & GR_FIND)))
12672+ return 0;
12673+
12674+ return GR_FIND;
12675+}
12676+
12677+__u32
12678+gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
12679+ const int fmode)
12680+{
12681+ __u32 reqmode = GR_FIND;
12682+ __u32 mode;
12683+
12684+ if (unlikely(!dentry->d_inode))
12685+ return reqmode;
12686+
12687+ if (unlikely(fmode & O_APPEND))
12688+ reqmode |= GR_APPEND;
12689+ else if (unlikely(fmode & FMODE_WRITE))
12690+ reqmode |= GR_WRITE;
12691+ if (likely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
12692+ reqmode |= GR_READ;
12693+
12694+ mode =
12695+ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
12696+ mnt);
12697+
12698+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
12699+ gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt,
12700+ reqmode & GR_READ ? " reading" : "",
12701+ reqmode & GR_WRITE ? " writing" : reqmode &
12702+ GR_APPEND ? " appending" : "");
12703+ return reqmode;
12704+ } else
12705+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
12706+ {
12707+ gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt,
12708+ reqmode & GR_READ ? " reading" : "",
12709+ reqmode & GR_WRITE ? " writing" : reqmode &
12710+ GR_APPEND ? " appending" : "");
12711+ return 0;
12712+ } else if (unlikely((mode & reqmode) != reqmode))
12713+ return 0;
12714+
12715+ return reqmode;
12716+}
12717+
12718+__u32
12719+gr_acl_handle_creat(const struct dentry * dentry,
12720+ const struct dentry * p_dentry,
12721+ const struct vfsmount * p_mnt, const int fmode,
12722+ const int imode)
12723+{
12724+ __u32 reqmode = GR_WRITE | GR_CREATE;
12725+ __u32 mode;
12726+
12727+ if (unlikely(fmode & O_APPEND))
12728+ reqmode |= GR_APPEND;
12729+ if (unlikely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
12730+ reqmode |= GR_READ;
12731+ if (unlikely((fmode & O_CREAT) && (imode & (S_ISUID | S_ISGID))))
12732+ reqmode |= GR_SETID;
12733+
12734+ mode =
12735+ gr_check_create(dentry, p_dentry, p_mnt,
12736+ reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
12737+
12738+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
12739+ gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt,
12740+ reqmode & GR_READ ? " reading" : "",
12741+ reqmode & GR_WRITE ? " writing" : reqmode &
12742+ GR_APPEND ? " appending" : "");
12743+ return reqmode;
12744+ } else
12745+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
12746+ {
12747+ gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt,
12748+ reqmode & GR_READ ? " reading" : "",
12749+ reqmode & GR_WRITE ? " writing" : reqmode &
12750+ GR_APPEND ? " appending" : "");
12751+ return 0;
12752+ } else if (unlikely((mode & reqmode) != reqmode))
12753+ return 0;
12754+
12755+ return reqmode;
12756+}
12757+
12758+__u32
12759+gr_acl_handle_access(const struct dentry * dentry, const struct vfsmount * mnt,
12760+ const int fmode)
12761+{
12762+ __u32 mode, reqmode = GR_FIND;
12763+
12764+ if ((fmode & S_IXOTH) && !S_ISDIR(dentry->d_inode->i_mode))
12765+ reqmode |= GR_EXEC;
12766+ if (fmode & S_IWOTH)
12767+ reqmode |= GR_WRITE;
12768+ if (fmode & S_IROTH)
12769+ reqmode |= GR_READ;
12770+
12771+ mode =
12772+ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
12773+ mnt);
12774+
12775+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
12776+ gr_log_fs_rbac_mode3(GR_DO_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt,
12777+ reqmode & GR_READ ? " reading" : "",
12778+ reqmode & GR_WRITE ? " writing" : "",
12779+ reqmode & GR_EXEC ? " executing" : "");
12780+ return reqmode;
12781+ } else
12782+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
12783+ {
12784+ gr_log_fs_rbac_mode3(GR_DONT_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt,
12785+ reqmode & GR_READ ? " reading" : "",
12786+ reqmode & GR_WRITE ? " writing" : "",
12787+ reqmode & GR_EXEC ? " executing" : "");
12788+ return 0;
12789+ } else if (unlikely((mode & reqmode) != reqmode))
12790+ return 0;
12791+
12792+ return reqmode;
12793+}
12794+
12795+static __u32 generic_fs_handler(const struct dentry *dentry, const struct vfsmount *mnt, __u32 reqmode, const char *fmt)
12796+{
12797+ __u32 mode;
12798+
12799+ mode = gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, mnt);
12800+
12801+ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) {
12802+ gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, dentry, mnt);
12803+ return mode;
12804+ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) {
12805+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, dentry, mnt);
12806+ return 0;
12807+ } else if (unlikely((mode & (reqmode)) != (reqmode)))
12808+ return 0;
12809+
12810+ return (reqmode);
12811+}
12812+
12813+__u32
12814+gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
12815+{
12816+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_RMDIR_ACL_MSG);
12817+}
12818+
12819+__u32
12820+gr_acl_handle_unlink(const struct dentry *dentry, const struct vfsmount *mnt)
12821+{
12822+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_UNLINK_ACL_MSG);
12823+}
12824+
12825+__u32
12826+gr_acl_handle_truncate(const struct dentry *dentry, const struct vfsmount *mnt)
12827+{
12828+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_TRUNCATE_ACL_MSG);
12829+}
12830+
12831+__u32
12832+gr_acl_handle_utime(const struct dentry *dentry, const struct vfsmount *mnt)
12833+{
12834+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_ATIME_ACL_MSG);
12835+}
12836+
12837+__u32
12838+gr_acl_handle_fchmod(const struct dentry *dentry, const struct vfsmount *mnt,
12839+ mode_t mode)
12840+{
12841+ if (unlikely(dentry->d_inode && S_ISSOCK(dentry->d_inode->i_mode)))
12842+ return 1;
12843+
12844+ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
12845+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
12846+ GR_FCHMOD_ACL_MSG);
12847+ } else {
12848+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_FCHMOD_ACL_MSG);
12849+ }
12850+}
12851+
12852+__u32
12853+gr_acl_handle_chmod(const struct dentry *dentry, const struct vfsmount *mnt,
12854+ mode_t mode)
12855+{
12856+ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
12857+ return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
12858+ GR_CHMOD_ACL_MSG);
12859+ } else {
12860+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHMOD_ACL_MSG);
12861+ }
12862+}
12863+
12864+__u32
12865+gr_acl_handle_chown(const struct dentry *dentry, const struct vfsmount *mnt)
12866+{
12867+ return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHOWN_ACL_MSG);
12868+}
12869+
12870+__u32
12871+gr_acl_handle_execve(const struct dentry *dentry, const struct vfsmount *mnt)
12872+{
12873+ return generic_fs_handler(dentry, mnt, GR_EXEC, GR_EXEC_ACL_MSG);
12874+}
12875+
12876+__u32
12877+gr_acl_handle_unix(const struct dentry *dentry, const struct vfsmount *mnt)
12878+{
12879+ return generic_fs_handler(dentry, mnt, GR_READ | GR_WRITE,
12880+ GR_UNIXCONNECT_ACL_MSG);
12881+}
12882+
12883+/* hardlinks require at minimum create permission,
12884+ any additional privilege required is based on the
12885+ privilege of the file being linked to
12886+*/
12887+__u32
12888+gr_acl_handle_link(const struct dentry * new_dentry,
12889+ const struct dentry * parent_dentry,
12890+ const struct vfsmount * parent_mnt,
12891+ const struct dentry * old_dentry,
12892+ const struct vfsmount * old_mnt, const char *to)
12893+{
12894+ __u32 mode;
12895+ __u32 needmode = GR_CREATE | GR_LINK;
12896+ __u32 needaudit = GR_AUDIT_CREATE | GR_AUDIT_LINK;
12897+
12898+ mode =
12899+ gr_check_link(new_dentry, parent_dentry, parent_mnt, old_dentry,
12900+ old_mnt);
12901+
12902+ if (unlikely(((mode & needmode) == needmode) && (mode & needaudit))) {
12903+ gr_log_fs_rbac_str(GR_DO_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to);
12904+ return mode;
12905+ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
12906+ gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to);
12907+ return 0;
12908+ } else if (unlikely((mode & needmode) != needmode))
12909+ return 0;
12910+
12911+ return 1;
12912+}
12913+
12914+__u32
12915+gr_acl_handle_symlink(const struct dentry * new_dentry,
12916+ const struct dentry * parent_dentry,
12917+ const struct vfsmount * parent_mnt, const char *from)
12918+{
12919+ __u32 needmode = GR_WRITE | GR_CREATE;
12920+ __u32 mode;
12921+
12922+ mode =
12923+ gr_check_create(new_dentry, parent_dentry, parent_mnt,
12924+ GR_CREATE | GR_AUDIT_CREATE |
12925+ GR_WRITE | GR_AUDIT_WRITE | GR_SUPPRESS);
12926+
12927+ if (unlikely(mode & GR_WRITE && mode & GR_AUDITS)) {
12928+ gr_log_fs_str_rbac(GR_DO_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt);
12929+ return mode;
12930+ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
12931+ gr_log_fs_str_rbac(GR_DONT_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt);
12932+ return 0;
12933+ } else if (unlikely((mode & needmode) != needmode))
12934+ return 0;
12935+
12936+ return (GR_WRITE | GR_CREATE);
12937+}
12938+
12939+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)
12940+{
12941+ __u32 mode;
12942+
12943+ mode = gr_check_create(new_dentry, parent_dentry, parent_mnt, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
12944+
12945+ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) {
12946+ gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, new_dentry, parent_mnt);
12947+ return mode;
12948+ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) {
12949+ gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, new_dentry, parent_mnt);
12950+ return 0;
12951+ } else if (unlikely((mode & (reqmode)) != (reqmode)))
12952+ return 0;
12953+
12954+ return (reqmode);
12955+}
12956+
12957+__u32
12958+gr_acl_handle_mknod(const struct dentry * new_dentry,
12959+ const struct dentry * parent_dentry,
12960+ const struct vfsmount * parent_mnt,
12961+ const int mode)
12962+{
12963+ __u32 reqmode = GR_WRITE | GR_CREATE;
12964+ if (unlikely(mode & (S_ISUID | S_ISGID)))
12965+ reqmode |= GR_SETID;
12966+
12967+ return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
12968+ reqmode, GR_MKNOD_ACL_MSG);
12969+}
12970+
12971+__u32
12972+gr_acl_handle_mkdir(const struct dentry *new_dentry,
12973+ const struct dentry *parent_dentry,
12974+ const struct vfsmount *parent_mnt)
12975+{
12976+ return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
12977+ GR_WRITE | GR_CREATE, GR_MKDIR_ACL_MSG);
12978+}
12979+
12980+#define RENAME_CHECK_SUCCESS(old, new) \
12981+ (((old & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)) && \
12982+ ((new & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)))
12983+
12984+int
12985+gr_acl_handle_rename(struct dentry *new_dentry,
12986+ struct dentry *parent_dentry,
12987+ const struct vfsmount *parent_mnt,
12988+ struct dentry *old_dentry,
12989+ struct inode *old_parent_inode,
12990+ struct vfsmount *old_mnt, const char *newname)
12991+{
12992+ __u32 comp1, comp2;
12993+ int error = 0;
12994+
12995+ if (unlikely(!gr_acl_is_enabled()))
12996+ return 0;
12997+
12998+ if (!new_dentry->d_inode) {
12999+ comp1 = gr_check_create(new_dentry, parent_dentry, parent_mnt,
13000+ GR_READ | GR_WRITE | GR_CREATE | GR_AUDIT_READ |
13001+ GR_AUDIT_WRITE | GR_AUDIT_CREATE | GR_SUPPRESS);
13002+ comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE |
13003+ GR_DELETE | GR_AUDIT_DELETE |
13004+ GR_AUDIT_READ | GR_AUDIT_WRITE |
13005+ GR_SUPPRESS, old_mnt);
13006+ } else {
13007+ comp1 = gr_search_file(new_dentry, GR_READ | GR_WRITE |
13008+ GR_CREATE | GR_DELETE |
13009+ GR_AUDIT_CREATE | GR_AUDIT_DELETE |
13010+ GR_AUDIT_READ | GR_AUDIT_WRITE |
13011+ GR_SUPPRESS, parent_mnt);
13012+ comp2 =
13013+ gr_search_file(old_dentry,
13014+ GR_READ | GR_WRITE | GR_AUDIT_READ |
13015+ GR_DELETE | GR_AUDIT_DELETE |
13016+ GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt);
13017+ }
13018+
13019+ if (RENAME_CHECK_SUCCESS(comp1, comp2) &&
13020+ ((comp1 & GR_AUDITS) || (comp2 & GR_AUDITS)))
13021+ gr_log_fs_rbac_str(GR_DO_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname);
13022+ else if (!RENAME_CHECK_SUCCESS(comp1, comp2) && !(comp1 & GR_SUPPRESS)
13023+ && !(comp2 & GR_SUPPRESS)) {
13024+ gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname);
13025+ error = -EACCES;
13026+ } else if (unlikely(!RENAME_CHECK_SUCCESS(comp1, comp2)))
13027+ error = -EACCES;
13028+
13029+ return error;
13030+}
13031+
13032+void
13033+gr_acl_handle_exit(void)
13034+{
13035+ u16 id;
13036+ char *rolename;
13037+ struct file *exec_file;
13038+
13039+ if (unlikely(current->acl_sp_role && gr_acl_is_enabled())) {
13040+ id = current->acl_role_id;
13041+ rolename = current->role->rolename;
13042+ gr_set_acls(1);
13043+ gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLEL_ACL_MSG, rolename, id);
13044+ }
13045+
13046+ write_lock(&grsec_exec_file_lock);
13047+ exec_file = current->exec_file;
13048+ current->exec_file = NULL;
13049+ write_unlock(&grsec_exec_file_lock);
13050+
13051+ if (exec_file)
13052+ fput(exec_file);
13053+}
13054+
13055+int
13056+gr_acl_handle_procpidmem(const struct task_struct *task)
13057+{
13058+ if (unlikely(!gr_acl_is_enabled()))
13059+ return 0;
13060+
13061+ if (task->acl->mode & GR_PROTPROCFD)
13062+ return -EACCES;
13063+
13064+ return 0;
13065+}
13066diff -urNp linux-2.6.16.12/grsecurity/gracl_ip.c linux-2.6.16.12/grsecurity/gracl_ip.c
13067--- linux-2.6.16.12/grsecurity/gracl_ip.c 1969-12-31 19:00:00.000000000 -0500
13068+++ linux-2.6.16.12/grsecurity/gracl_ip.c 2006-05-01 20:17:33.000000000 -0400
13069@@ -0,0 +1,313 @@
13070+#include <linux/kernel.h>
13071+#include <asm/uaccess.h>
13072+#include <asm/errno.h>
13073+#include <net/sock.h>
13074+#include <linux/file.h>
13075+#include <linux/fs.h>
13076+#include <linux/net.h>
13077+#include <linux/in.h>
13078+#include <linux/skbuff.h>
13079+#include <linux/ip.h>
13080+#include <linux/udp.h>
13081+#include <linux/smp_lock.h>
13082+#include <linux/types.h>
13083+#include <linux/sched.h>
13084+#include <linux/netdevice.h>
13085+#include <linux/inetdevice.h>
13086+#include <linux/gracl.h>
13087+#include <linux/grsecurity.h>
13088+#include <linux/grinternal.h>
13089+
13090+#define GR_BIND 0x01
13091+#define GR_CONNECT 0x02
13092+#define GR_INVERT 0x04
13093+
13094+static const char * gr_protocols[256] = {
13095+ "ip", "icmp", "igmp", "ggp", "ipencap", "st", "tcp", "cbt",
13096+ "egp", "igp", "bbn-rcc", "nvp", "pup", "argus", "emcon", "xnet",
13097+ "chaos", "udp", "mux", "dcn", "hmp", "prm", "xns-idp", "trunk-1",
13098+ "trunk-2", "leaf-1", "leaf-2", "rdp", "irtp", "iso-tp4", "netblt", "mfe-nsp",
13099+ "merit-inp", "sep", "3pc", "idpr", "xtp", "ddp", "idpr-cmtp", "tp++",
13100+ "il", "ipv6", "sdrp", "ipv6-route", "ipv6-frag", "idrp", "rsvp", "gre",
13101+ "mhrp", "bna", "ipv6-crypt", "ipv6-auth", "i-nlsp", "swipe", "narp", "mobile",
13102+ "tlsp", "skip", "ipv6-icmp", "ipv6-nonxt", "ipv6-opts", "unknown:61", "cftp", "unknown:63",
13103+ "sat-expak", "kryptolan", "rvd", "ippc", "unknown:68", "sat-mon", "visa", "ipcv",
13104+ "cpnx", "cphb", "wsn", "pvp", "br-sat-mon", "sun-nd", "wb-mon", "wb-expak",
13105+ "iso-ip", "vmtp", "secure-vmtp", "vines", "ttp", "nfsnet-igp", "dgp", "tcf",
13106+ "eigrp", "ospf", "sprite-rpc", "larp", "mtp", "ax.25", "ipip", "micp",
13107+ "scc-sp", "etherip", "encap", "unknown:99", "gmtp", "ifmp", "pnni", "pim",
13108+ "aris", "scps", "qnx", "a/n", "ipcomp", "snp", "compaq-peer", "ipx-in-ip",
13109+ "vrrp", "pgm", "unknown:114", "l2tp", "ddx", "iatp", "stp", "srp",
13110+ "uti", "smp", "sm", "ptp", "isis", "fire", "crtp", "crdup",
13111+ "sscopmce", "iplt", "sps", "pipe", "sctp", "fc", "unkown:134", "unknown:135",
13112+ "unknown:136", "unknown:137", "unknown:138", "unknown:139", "unknown:140", "unknown:141", "unknown:142", "unknown:143",
13113+ "unknown:144", "unknown:145", "unknown:146", "unknown:147", "unknown:148", "unknown:149", "unknown:150", "unknown:151",
13114+ "unknown:152", "unknown:153", "unknown:154", "unknown:155", "unknown:156", "unknown:157", "unknown:158", "unknown:159",
13115+ "unknown:160", "unknown:161", "unknown:162", "unknown:163", "unknown:164", "unknown:165", "unknown:166", "unknown:167",
13116+ "unknown:168", "unknown:169", "unknown:170", "unknown:171", "unknown:172", "unknown:173", "unknown:174", "unknown:175",
13117+ "unknown:176", "unknown:177", "unknown:178", "unknown:179", "unknown:180", "unknown:181", "unknown:182", "unknown:183",
13118+ "unknown:184", "unknown:185", "unknown:186", "unknown:187", "unknown:188", "unknown:189", "unknown:190", "unknown:191",
13119+ "unknown:192", "unknown:193", "unknown:194", "unknown:195", "unknown:196", "unknown:197", "unknown:198", "unknown:199",
13120+ "unknown:200", "unknown:201", "unknown:202", "unknown:203", "unknown:204", "unknown:205", "unknown:206", "unknown:207",
13121+ "unknown:208", "unknown:209", "unknown:210", "unknown:211", "unknown:212", "unknown:213", "unknown:214", "unknown:215",
13122+ "unknown:216", "unknown:217", "unknown:218", "unknown:219", "unknown:220", "unknown:221", "unknown:222", "unknown:223",
13123+ "unknown:224", "unknown:225", "unknown:226", "unknown:227", "unknown:228", "unknown:229", "unknown:230", "unknown:231",
13124+ "unknown:232", "unknown:233", "unknown:234", "unknown:235", "unknown:236", "unknown:237", "unknown:238", "unknown:239",
13125+ "unknown:240", "unknown:241", "unknown:242", "unknown:243", "unknown:244", "unknown:245", "unknown:246", "unknown:247",
13126+ "unknown:248", "unknown:249", "unknown:250", "unknown:251", "unknown:252", "unknown:253", "unknown:254", "unknown:255",
13127+ };
13128+
13129+static const char * gr_socktypes[11] = {
13130+ "unknown:0", "stream", "dgram", "raw", "rdm", "seqpacket", "unknown:6",
13131+ "unknown:7", "unknown:8", "unknown:9", "packet"
13132+ };
13133+
13134+const char *
13135+gr_proto_to_name(unsigned char proto)
13136+{
13137+ return gr_protocols[proto];
13138+}
13139+
13140+const char *
13141+gr_socktype_to_name(unsigned char type)
13142+{
13143+ return gr_socktypes[type];
13144+}
13145+
13146+int
13147+gr_search_socket(const int domain, const int type, const int protocol)
13148+{
13149+ struct acl_subject_label *curr;
13150+
13151+ if (unlikely(!gr_acl_is_enabled()))
13152+ goto exit;
13153+
13154+ if ((domain < 0) || (type < 0) || (protocol < 0) || (domain != PF_INET)
13155+ || (domain >= NPROTO) || (type >= SOCK_MAX) || (protocol > 255))
13156+ goto exit; // let the kernel handle it
13157+
13158+ curr = current->acl;
13159+
13160+ if (!curr->ips)
13161+ goto exit;
13162+
13163+ if ((curr->ip_type & (1 << type)) &&
13164+ (curr->ip_proto[protocol / 32] & (1 << (protocol % 32))))
13165+ goto exit;
13166+
13167+ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
13168+ /* we don't place acls on raw sockets , and sometimes
13169+ dgram/ip sockets are opened for ioctl and not
13170+ bind/connect, so we'll fake a bind learn log */
13171+ if (type == SOCK_RAW || type == SOCK_PACKET) {
13172+ __u32 fakeip = 0;
13173+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
13174+ current->role->roletype, current->uid,
13175+ current->gid, current->exec_file ?
13176+ gr_to_filename(current->exec_file->f_dentry,
13177+ current->exec_file->f_vfsmnt) :
13178+ curr->filename, curr->filename,
13179+ NIPQUAD(fakeip), 0, type,
13180+ protocol, GR_CONNECT,
13181+NIPQUAD(current->signal->curr_ip));
13182+ } else if ((type == SOCK_DGRAM) && (protocol == IPPROTO_IP)) {
13183+ __u32 fakeip = 0;
13184+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
13185+ current->role->roletype, current->uid,
13186+ current->gid, current->exec_file ?
13187+ gr_to_filename(current->exec_file->f_dentry,
13188+ current->exec_file->f_vfsmnt) :
13189+ curr->filename, curr->filename,
13190+ NIPQUAD(fakeip), 0, type,
13191+ protocol, GR_BIND, NIPQUAD(current->signal->curr_ip));
13192+ }
13193+ /* we'll log when they use connect or bind */
13194+ goto exit;
13195+ }
13196+
13197+ gr_log_str3(GR_DONT_AUDIT, GR_SOCK_MSG, "inet",
13198+ gr_socktype_to_name(type), gr_proto_to_name(protocol));
13199+
13200+ return 0;
13201+ exit:
13202+ return 1;
13203+}
13204+
13205+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)
13206+{
13207+ if ((ip->mode & mode) &&
13208+ (ip_port >= ip->low) &&
13209+ (ip_port <= ip->high) &&
13210+ ((ntohl(ip_addr) & our_netmask) ==
13211+ (ntohl(our_addr) & our_netmask))
13212+ && (ip->proto[protocol / 32] & (1 << (protocol % 32)))
13213+ && (ip->type & (1 << type))) {
13214+ if (ip->mode & GR_INVERT)
13215+ return 2; // specifically denied
13216+ else
13217+ return 1; // allowed
13218+ }
13219+
13220+ return 0; // not specifically allowed, may continue parsing
13221+}
13222+
13223+static int
13224+gr_search_connectbind(const int mode, const struct sock *sk,
13225+ const struct sockaddr_in *addr, const int type)
13226+{
13227+ char iface[IFNAMSIZ] = {0};
13228+ struct acl_subject_label *curr;
13229+ struct acl_ip_label *ip;
13230+ struct net_device *dev;
13231+ struct in_device *idev;
13232+ unsigned long i;
13233+ int ret;
13234+ __u32 ip_addr = 0;
13235+ __u32 our_addr;
13236+ __u32 our_netmask;
13237+ char *p;
13238+ __u16 ip_port = 0;
13239+
13240+ if (unlikely(!gr_acl_is_enabled() || sk->sk_family != PF_INET))
13241+ return 1;
13242+
13243+ curr = current->acl;
13244+
13245+ if (!curr->ips)
13246+ return 1;
13247+
13248+ ip_addr = addr->sin_addr.s_addr;
13249+ ip_port = ntohs(addr->sin_port);
13250+
13251+ if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
13252+ security_learn(GR_IP_LEARN_MSG, current->role->rolename,
13253+ current->role->roletype, current->uid,
13254+ current->gid, current->exec_file ?
13255+ gr_to_filename(current->exec_file->f_dentry,
13256+ current->exec_file->f_vfsmnt) :
13257+ curr->filename, curr->filename,
13258+ NIPQUAD(ip_addr), ip_port, type,
13259+ sk->sk_protocol, mode, NIPQUAD(current->signal->curr_ip));
13260+ return 1;
13261+ }
13262+
13263+ for (i = 0; i < curr->ip_num; i++) {
13264+ ip = *(curr->ips + i);
13265+ if (ip->iface != NULL) {
13266+ strncpy(iface, ip->iface, IFNAMSIZ - 1);
13267+ p = strchr(iface, ':');
13268+ if (p != NULL)
13269+ *p = '\0';
13270+ dev = dev_get_by_name(iface);
13271+ if (dev == NULL)
13272+ continue;
13273+ idev = in_dev_get(dev);
13274+ if (idev == NULL) {
13275+ dev_put(dev);
13276+ continue;
13277+ }
13278+ rcu_read_lock();
13279+ for_ifa(idev) {
13280+ if (!strcmp(ip->iface, ifa->ifa_label)) {
13281+ our_addr = ifa->ifa_address;
13282+ our_netmask = 0xffffffff;
13283+ ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask);
13284+ if (ret == 1) {
13285+ rcu_read_unlock();
13286+ in_dev_put(idev);
13287+ dev_put(dev);
13288+ return 1;
13289+ } else if (ret == 2) {
13290+ rcu_read_unlock();
13291+ in_dev_put(idev);
13292+ dev_put(dev);
13293+ goto denied;
13294+ }
13295+ }
13296+ } endfor_ifa(idev);
13297+ rcu_read_unlock();
13298+ in_dev_put(idev);
13299+ dev_put(dev);
13300+ } else {
13301+ our_addr = ip->addr;
13302+ our_netmask = ip->netmask;
13303+ ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask);
13304+ if (ret == 1)
13305+ return 1;
13306+ else if (ret == 2)
13307+ goto denied;
13308+ }
13309+ }
13310+
13311+denied:
13312+ if (mode == GR_BIND)
13313+ 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));
13314+ else if (mode == GR_CONNECT)
13315+ 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));
13316+
13317+ return 0;
13318+}
13319+
13320+int
13321+gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
13322+{
13323+ return gr_search_connectbind(GR_CONNECT, sock->sk, addr, sock->type);
13324+}
13325+
13326+int
13327+gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
13328+{
13329+ return gr_search_connectbind(GR_BIND, sock->sk, addr, sock->type);
13330+}
13331+
13332+int gr_search_listen(const struct socket *sock)
13333+{
13334+ struct sock *sk = sock->sk;
13335+ struct sockaddr_in addr;
13336+
13337+ addr.sin_addr.s_addr = inet_sk(sk)->saddr;
13338+ addr.sin_port = inet_sk(sk)->sport;
13339+
13340+ return gr_search_connectbind(GR_BIND, sock->sk, &addr, sock->type);
13341+}
13342+
13343+int gr_search_accept(const struct socket *sock)
13344+{
13345+ struct sock *sk = sock->sk;
13346+ struct sockaddr_in addr;
13347+
13348+ addr.sin_addr.s_addr = inet_sk(sk)->saddr;
13349+ addr.sin_port = inet_sk(sk)->sport;
13350+
13351+ return gr_search_connectbind(GR_BIND, sock->sk, &addr, sock->type);
13352+}
13353+
13354+int
13355+gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
13356+{
13357+ if (addr)
13358+ return gr_search_connectbind(GR_CONNECT, sk, addr, SOCK_DGRAM);
13359+ else {
13360+ struct sockaddr_in sin;
13361+ const struct inet_sock *inet = inet_sk(sk);
13362+
13363+ sin.sin_addr.s_addr = inet->daddr;
13364+ sin.sin_port = inet->dport;
13365+
13366+ return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM);
13367+ }
13368+}
13369+
13370+int
13371+gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
13372+{
13373+ struct sockaddr_in sin;
13374+
13375+ if (unlikely(skb->len < sizeof (struct udphdr)))
13376+ return 1; // skip this packet
13377+
13378+ sin.sin_addr.s_addr = skb->nh.iph->saddr;
13379+ sin.sin_port = skb->h.uh->source;
13380+
13381+ return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM);
13382+}
13383diff -urNp linux-2.6.16.12/grsecurity/gracl_learn.c linux-2.6.16.12/grsecurity/gracl_learn.c
13384--- linux-2.6.16.12/grsecurity/gracl_learn.c 1969-12-31 19:00:00.000000000 -0500
13385+++ linux-2.6.16.12/grsecurity/gracl_learn.c 2006-05-01 20:17:33.000000000 -0400
13386@@ -0,0 +1,204 @@
13387+#include <linux/kernel.h>
13388+#include <linux/mm.h>
13389+#include <linux/sched.h>
13390+#include <linux/poll.h>
13391+#include <linux/smp_lock.h>
13392+#include <linux/string.h>
13393+#include <linux/file.h>
13394+#include <linux/types.h>
13395+#include <linux/vmalloc.h>
13396+#include <linux/grinternal.h>
13397+
13398+extern ssize_t write_grsec_handler(struct file * file, const char __user * buf,
13399+ size_t count, loff_t *ppos);
13400+extern int gr_acl_is_enabled(void);
13401+
13402+static DECLARE_WAIT_QUEUE_HEAD(learn_wait);
13403+static int gr_learn_attached;
13404+
13405+/* use a 512k buffer */
13406+#define LEARN_BUFFER_SIZE (512 * 1024)
13407+
13408+static spinlock_t gr_learn_lock = SPIN_LOCK_UNLOCKED;
13409+static DECLARE_MUTEX(gr_learn_user_sem);
13410+
13411+/* we need to maintain two buffers, so that the kernel context of grlearn
13412+ uses a semaphore around the userspace copying, and the other kernel contexts
13413+ use a spinlock when copying into the buffer, since they cannot sleep
13414+*/
13415+static char *learn_buffer;
13416+static char *learn_buffer_user;
13417+static int learn_buffer_len;
13418+static int learn_buffer_user_len;
13419+
13420+static ssize_t
13421+read_learn(struct file *file, char __user * buf, size_t count, loff_t * ppos)
13422+{
13423+ DECLARE_WAITQUEUE(wait, current);
13424+ ssize_t retval = 0;
13425+
13426+ add_wait_queue(&learn_wait, &wait);
13427+ set_current_state(TASK_INTERRUPTIBLE);
13428+ do {
13429+ down(&gr_learn_user_sem);
13430+ spin_lock(&gr_learn_lock);
13431+ if (learn_buffer_len)
13432+ break;
13433+ spin_unlock(&gr_learn_lock);
13434+ up(&gr_learn_user_sem);
13435+ if (file->f_flags & O_NONBLOCK) {
13436+ retval = -EAGAIN;
13437+ goto out;
13438+ }
13439+ if (signal_pending(current)) {
13440+ retval = -ERESTARTSYS;
13441+ goto out;
13442+ }
13443+
13444+ schedule();
13445+ } while (1);
13446+
13447+ memcpy(learn_buffer_user, learn_buffer, learn_buffer_len);
13448+ learn_buffer_user_len = learn_buffer_len;
13449+ retval = learn_buffer_len;
13450+ learn_buffer_len = 0;
13451+
13452+ spin_unlock(&gr_learn_lock);
13453+
13454+ if (copy_to_user(buf, learn_buffer_user, learn_buffer_user_len))
13455+ retval = -EFAULT;
13456+
13457+ up(&gr_learn_user_sem);
13458+out:
13459+ set_current_state(TASK_RUNNING);
13460+ remove_wait_queue(&learn_wait, &wait);
13461+ return retval;
13462+}
13463+
13464+static unsigned int
13465+poll_learn(struct file * file, poll_table * wait)
13466+{
13467+ poll_wait(file, &learn_wait, wait);
13468+
13469+ if (learn_buffer_len)
13470+ return (POLLIN | POLLRDNORM);
13471+
13472+ return 0;
13473+}
13474+
13475+void
13476+gr_clear_learn_entries(void)
13477+{
13478+ char *tmp;
13479+
13480+ down(&gr_learn_user_sem);
13481+ if (learn_buffer != NULL) {
13482+ spin_lock(&gr_learn_lock);
13483+ tmp = learn_buffer;
13484+ learn_buffer = NULL;
13485+ spin_unlock(&gr_learn_lock);
13486+ vfree(learn_buffer);
13487+ }
13488+ if (learn_buffer_user != NULL) {
13489+ vfree(learn_buffer_user);
13490+ learn_buffer_user = NULL;
13491+ }
13492+ learn_buffer_len = 0;
13493+ up(&gr_learn_user_sem);
13494+
13495+ return;
13496+}
13497+
13498+void
13499+gr_add_learn_entry(const char *fmt, ...)
13500+{
13501+ va_list args;
13502+ unsigned int len;
13503+
13504+ if (!gr_learn_attached)
13505+ return;
13506+
13507+ spin_lock(&gr_learn_lock);
13508+
13509+ /* leave a gap at the end so we know when it's "full" but don't have to
13510+ compute the exact length of the string we're trying to append
13511+ */
13512+ if (learn_buffer_len > LEARN_BUFFER_SIZE - 16384) {
13513+ spin_unlock(&gr_learn_lock);
13514+ wake_up_interruptible(&learn_wait);
13515+ return;
13516+ }
13517+ if (learn_buffer == NULL) {
13518+ spin_unlock(&gr_learn_lock);
13519+ return;
13520+ }
13521+
13522+ va_start(args, fmt);
13523+ len = vsnprintf(learn_buffer + learn_buffer_len, LEARN_BUFFER_SIZE - learn_buffer_len, fmt, args);
13524+ va_end(args);
13525+
13526+ learn_buffer_len += len + 1;
13527+
13528+ spin_unlock(&gr_learn_lock);
13529+ wake_up_interruptible(&learn_wait);
13530+
13531+ return;
13532+}
13533+
13534+static int
13535+open_learn(struct inode *inode, struct file *file)
13536+{
13537+ if (file->f_mode & FMODE_READ && gr_learn_attached)
13538+ return -EBUSY;
13539+ if (file->f_mode & FMODE_READ) {
13540+ down(&gr_learn_user_sem);
13541+ if (learn_buffer == NULL)
13542+ learn_buffer = vmalloc(LEARN_BUFFER_SIZE);
13543+ if (learn_buffer_user == NULL)
13544+ learn_buffer_user = vmalloc(LEARN_BUFFER_SIZE);
13545+ if (learn_buffer == NULL)
13546+ return -ENOMEM;
13547+ if (learn_buffer_user == NULL)
13548+ return -ENOMEM;
13549+ learn_buffer_len = 0;
13550+ learn_buffer_user_len = 0;
13551+ gr_learn_attached = 1;
13552+ up(&gr_learn_user_sem);
13553+ }
13554+ return 0;
13555+}
13556+
13557+static int
13558+close_learn(struct inode *inode, struct file *file)
13559+{
13560+ char *tmp;
13561+
13562+ if (file->f_mode & FMODE_READ) {
13563+ down(&gr_learn_user_sem);
13564+ if (learn_buffer != NULL) {
13565+ spin_lock(&gr_learn_lock);
13566+ tmp = learn_buffer;
13567+ learn_buffer = NULL;
13568+ spin_unlock(&gr_learn_lock);
13569+ vfree(tmp);
13570+ }
13571+ if (learn_buffer_user != NULL) {
13572+ vfree(learn_buffer_user);
13573+ learn_buffer_user = NULL;
13574+ }
13575+ learn_buffer_len = 0;
13576+ learn_buffer_user_len = 0;
13577+ gr_learn_attached = 0;
13578+ up(&gr_learn_user_sem);
13579+ }
13580+
13581+ return 0;
13582+}
13583+
13584+struct file_operations grsec_fops = {
13585+ .read = read_learn,
13586+ .write = write_grsec_handler,
13587+ .open = open_learn,
13588+ .release = close_learn,
13589+ .poll = poll_learn,
13590+};
13591diff -urNp linux-2.6.16.12/grsecurity/gracl_res.c linux-2.6.16.12/grsecurity/gracl_res.c
13592--- linux-2.6.16.12/grsecurity/gracl_res.c 1969-12-31 19:00:00.000000000 -0500
13593+++ linux-2.6.16.12/grsecurity/gracl_res.c 2006-05-01 20:17:33.000000000 -0400
13594@@ -0,0 +1,42 @@
13595+#include <linux/kernel.h>
13596+#include <linux/sched.h>
13597+#include <linux/gracl.h>
13598+#include <linux/grinternal.h>
13599+
13600+static const char *restab_log[] = {
13601+ [RLIMIT_CPU] = "RLIMIT_CPU",
13602+ [RLIMIT_FSIZE] = "RLIMIT_FSIZE",
13603+ [RLIMIT_DATA] = "RLIMIT_DATA",
13604+ [RLIMIT_STACK] = "RLIMIT_STACK",
13605+ [RLIMIT_CORE] = "RLIMIT_CORE",
13606+ [RLIMIT_RSS] = "RLIMIT_RSS",
13607+ [RLIMIT_NPROC] = "RLIMIT_NPROC",
13608+ [RLIMIT_NOFILE] = "RLIMIT_NOFILE",
13609+ [RLIMIT_MEMLOCK] = "RLIMIT_MEMLOCK",
13610+ [RLIMIT_AS] = "RLIMIT_AS",
13611+ [RLIMIT_LOCKS] = "RLIMIT_LOCKS",
13612+ [RLIMIT_LOCKS + 1] = "RLIMIT_CRASH"
13613+};
13614+
13615+void
13616+gr_log_resource(const struct task_struct *task,
13617+ const int res, const unsigned long wanted, const int gt)
13618+{
13619+ if (res == RLIMIT_NPROC &&
13620+ (cap_raised(task->cap_effective, CAP_SYS_ADMIN) ||
13621+ cap_raised(task->cap_effective, CAP_SYS_RESOURCE)))
13622+ return;
13623+ else if (res == RLIMIT_MEMLOCK &&
13624+ cap_raised(task->cap_effective, CAP_IPC_LOCK))
13625+ return;
13626+
13627+ preempt_disable();
13628+
13629+ if (unlikely(((gt && wanted > task->signal->rlim[res].rlim_cur) ||
13630+ (!gt && wanted >= task->signal->rlim[res].rlim_cur)) &&
13631+ task->signal->rlim[res].rlim_cur != RLIM_INFINITY))
13632+ gr_log_res_ulong2_str(GR_DONT_AUDIT, GR_RESOURCE_MSG, task, wanted, restab_log[res], task->signal->rlim[res].rlim_cur);
13633+ preempt_enable_no_resched();
13634+
13635+ return;
13636+}
13637diff -urNp linux-2.6.16.12/grsecurity/gracl_segv.c linux-2.6.16.12/grsecurity/gracl_segv.c
13638--- linux-2.6.16.12/grsecurity/gracl_segv.c 1969-12-31 19:00:00.000000000 -0500
13639+++ linux-2.6.16.12/grsecurity/gracl_segv.c 2006-05-01 20:17:33.000000000 -0400
13640@@ -0,0 +1,295 @@
13641+#include <linux/kernel.h>
13642+#include <linux/mm.h>
13643+#include <asm/uaccess.h>
13644+#include <asm/errno.h>
13645+#include <asm/mman.h>
13646+#include <net/sock.h>
13647+#include <linux/file.h>
13648+#include <linux/fs.h>
13649+#include <linux/net.h>
13650+#include <linux/in.h>
13651+#include <linux/smp_lock.h>
13652+#include <linux/slab.h>
13653+#include <linux/types.h>
13654+#include <linux/sched.h>
13655+#include <linux/timer.h>
13656+#include <linux/gracl.h>
13657+#include <linux/grsecurity.h>
13658+#include <linux/grinternal.h>
13659+
13660+static struct crash_uid *uid_set;
13661+static unsigned short uid_used;
13662+static spinlock_t gr_uid_lock = SPIN_LOCK_UNLOCKED;
13663+extern rwlock_t gr_inode_lock;
13664+extern struct acl_subject_label *
13665+ lookup_acl_subj_label(const ino_t inode, const dev_t dev,
13666+ struct acl_role_label *role);
13667+extern int specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t);
13668+
13669+int
13670+gr_init_uidset(void)
13671+{
13672+ uid_set =
13673+ kmalloc(GR_UIDTABLE_MAX * sizeof (struct crash_uid), GFP_KERNEL);
13674+ uid_used = 0;
13675+
13676+ return uid_set ? 1 : 0;
13677+}
13678+
13679+void
13680+gr_free_uidset(void)
13681+{
13682+ if (uid_set)
13683+ kfree(uid_set);
13684+
13685+ return;
13686+}
13687+
13688+int
13689+gr_find_uid(const uid_t uid)
13690+{
13691+ struct crash_uid *tmp = uid_set;
13692+ uid_t buid;
13693+ int low = 0, high = uid_used - 1, mid;
13694+
13695+ while (high >= low) {
13696+ mid = (low + high) >> 1;
13697+ buid = tmp[mid].uid;
13698+ if (buid == uid)
13699+ return mid;
13700+ if (buid > uid)
13701+ high = mid - 1;
13702+ if (buid < uid)
13703+ low = mid + 1;
13704+ }
13705+
13706+ return -1;
13707+}
13708+
13709+static __inline__ void
13710+gr_insertsort(void)
13711+{
13712+ unsigned short i, j;
13713+ struct crash_uid index;
13714+
13715+ for (i = 1; i < uid_used; i++) {
13716+ index = uid_set[i];
13717+ j = i;
13718+ while ((j > 0) && uid_set[j - 1].uid > index.uid) {
13719+ uid_set[j] = uid_set[j - 1];
13720+ j--;
13721+ }
13722+ uid_set[j] = index;
13723+ }
13724+
13725+ return;
13726+}
13727+
13728+static __inline__ void
13729+gr_insert_uid(const uid_t uid, const unsigned long expires)
13730+{
13731+ int loc;
13732+
13733+ if (uid_used == GR_UIDTABLE_MAX)
13734+ return;
13735+
13736+ loc = gr_find_uid(uid);
13737+
13738+ if (loc >= 0) {
13739+ uid_set[loc].expires = expires;
13740+ return;
13741+ }
13742+
13743+ uid_set[uid_used].uid = uid;
13744+ uid_set[uid_used].expires = expires;
13745+ uid_used++;
13746+
13747+ gr_insertsort();
13748+
13749+ return;
13750+}
13751+
13752+void
13753+gr_remove_uid(const unsigned short loc)
13754+{
13755+ unsigned short i;
13756+
13757+ for (i = loc + 1; i < uid_used; i++)
13758+ uid_set[i - 1] = uid_set[i];
13759+
13760+ uid_used--;
13761+
13762+ return;
13763+}
13764+
13765+int
13766+gr_check_crash_uid(const uid_t uid)
13767+{
13768+ int loc;
13769+ int ret = 0;
13770+
13771+ if (unlikely(!gr_acl_is_enabled()))
13772+ return 0;
13773+
13774+ spin_lock(&gr_uid_lock);
13775+ loc = gr_find_uid(uid);
13776+
13777+ if (loc < 0)
13778+ goto out_unlock;
13779+
13780+ if (time_before_eq(uid_set[loc].expires, get_seconds()))
13781+ gr_remove_uid(loc);
13782+ else
13783+ ret = 1;
13784+
13785+out_unlock:
13786+ spin_unlock(&gr_uid_lock);
13787+ return ret;
13788+}
13789+
13790+static __inline__ int
13791+proc_is_setxid(const struct task_struct *task)
13792+{
13793+ if (task->uid != task->euid || task->uid != task->suid ||
13794+ task->uid != task->fsuid)
13795+ return 1;
13796+ if (task->gid != task->egid || task->gid != task->sgid ||
13797+ task->gid != task->fsgid)
13798+ return 1;
13799+
13800+ return 0;
13801+}
13802+static __inline__ int
13803+gr_fake_force_sig(int sig, struct task_struct *t)
13804+{
13805+ unsigned long int flags;
13806+ int ret;
13807+
13808+ spin_lock_irqsave(&t->sighand->siglock, flags);
13809+ if (sigismember(&t->blocked, sig) || t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) {
13810+ t->sighand->action[sig-1].sa.sa_handler = SIG_DFL;
13811+ sigdelset(&t->blocked, sig);
13812+ recalc_sigpending_tsk(t);
13813+ }
13814+ ret = specific_send_sig_info(sig, (void*)1L, t);
13815+ spin_unlock_irqrestore(&t->sighand->siglock, flags);
13816+
13817+ return ret;
13818+}
13819+
13820+void
13821+gr_handle_crash(struct task_struct *task, const int sig)
13822+{
13823+ struct acl_subject_label *curr;
13824+ struct acl_subject_label *curr2;
13825+ struct task_struct *tsk, *tsk2;
13826+
13827+ if (sig != SIGSEGV && sig != SIGKILL && sig != SIGBUS && sig != SIGILL)
13828+ return;
13829+
13830+ if (unlikely(!gr_acl_is_enabled()))
13831+ return;
13832+
13833+ curr = task->acl;
13834+
13835+ if (!(curr->resmask & (1 << GR_CRASH_RES)))
13836+ return;
13837+
13838+ if (time_before_eq(curr->expires, get_seconds())) {
13839+ curr->expires = 0;
13840+ curr->crashes = 0;
13841+ }
13842+
13843+ curr->crashes++;
13844+
13845+ if (!curr->expires)
13846+ curr->expires = get_seconds() + curr->res[GR_CRASH_RES].rlim_max;
13847+
13848+ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
13849+ time_after(curr->expires, get_seconds())) {
13850+ if (task->uid && proc_is_setxid(task)) {
13851+ gr_log_crash1(GR_DONT_AUDIT, GR_SEGVSTART_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
13852+ spin_lock(&gr_uid_lock);
13853+ gr_insert_uid(task->uid, curr->expires);
13854+ spin_unlock(&gr_uid_lock);
13855+ curr->expires = 0;
13856+ curr->crashes = 0;
13857+ read_lock(&tasklist_lock);
13858+ do_each_thread(tsk2, tsk) {
13859+ if (tsk != task && tsk->uid == task->uid)
13860+ gr_fake_force_sig(SIGKILL, tsk);
13861+ } while_each_thread(tsk2, tsk);
13862+ read_unlock(&tasklist_lock);
13863+ } else {
13864+ gr_log_crash2(GR_DONT_AUDIT, GR_SEGVNOSUID_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
13865+ read_lock(&tasklist_lock);
13866+ do_each_thread(tsk2, tsk) {
13867+ if (likely(tsk != task)) {
13868+ curr2 = tsk->acl;
13869+
13870+ if (curr2->device == curr->device &&
13871+ curr2->inode == curr->inode)
13872+ gr_fake_force_sig(SIGKILL, tsk);
13873+ }
13874+ } while_each_thread(tsk2, tsk);
13875+ read_unlock(&tasklist_lock);
13876+ }
13877+ }
13878+
13879+ return;
13880+}
13881+
13882+int
13883+gr_check_crash_exec(const struct file *filp)
13884+{
13885+ struct acl_subject_label *curr;
13886+
13887+ if (unlikely(!gr_acl_is_enabled()))
13888+ return 0;
13889+
13890+ read_lock(&gr_inode_lock);
13891+ curr = lookup_acl_subj_label(filp->f_dentry->d_inode->i_ino,
13892+ filp->f_dentry->d_inode->i_sb->s_dev,
13893+ current->role);
13894+ read_unlock(&gr_inode_lock);
13895+
13896+ if (!curr || !(curr->resmask & (1 << GR_CRASH_RES)) ||
13897+ (!curr->crashes && !curr->expires))
13898+ return 0;
13899+
13900+ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
13901+ time_after(curr->expires, get_seconds()))
13902+ return 1;
13903+ else if (time_before_eq(curr->expires, get_seconds())) {
13904+ curr->crashes = 0;
13905+ curr->expires = 0;
13906+ }
13907+
13908+ return 0;
13909+}
13910+
13911+void
13912+gr_handle_alertkill(struct task_struct *task)
13913+{
13914+ struct acl_subject_label *curracl;
13915+ __u32 curr_ip;
13916+ struct task_struct *p, *p2;
13917+
13918+ if (unlikely(!gr_acl_is_enabled()))
13919+ return;
13920+
13921+ curracl = task->acl;
13922+ curr_ip = task->signal->curr_ip;
13923+
13924+ if ((curracl->mode & GR_KILLIPPROC) && curr_ip) {
13925+ read_lock(&tasklist_lock);
13926+ do_each_thread(p2, p) {
13927+ if (p->signal->curr_ip == curr_ip)
13928+ gr_fake_force_sig(SIGKILL, p);
13929+ } while_each_thread(p2, p);
13930+ read_unlock(&tasklist_lock);
13931+ } else if (curracl->mode & GR_KILLPROC)
13932+ gr_fake_force_sig(SIGKILL, task);
13933+
13934+ return;
13935+}
13936diff -urNp linux-2.6.16.12/grsecurity/gracl_shm.c linux-2.6.16.12/grsecurity/gracl_shm.c
13937--- linux-2.6.16.12/grsecurity/gracl_shm.c 1969-12-31 19:00:00.000000000 -0500
13938+++ linux-2.6.16.12/grsecurity/gracl_shm.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 13939@@ -0,0 +1,34 @@
89675291 13940+#include <linux/kernel.h>
13941+#include <linux/mm.h>
13942+#include <linux/sched.h>
13943+#include <linux/file.h>
13944+#include <linux/ipc.h>
13945+#include <linux/gracl.h>
13946+#include <linux/grsecurity.h>
13947+#include <linux/grinternal.h>
9a4c6ab7 13948+#include <linux/vs_pid.h>
89675291 13949+
13950+int
13951+gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
13952+ const time_t shm_createtime, const uid_t cuid, const int shmid)
13953+{
13954+ struct task_struct *task;
13955+
13956+ if (!gr_acl_is_enabled())
13957+ return 1;
13958+
13959+ task = find_task_by_pid(shm_cprid);
13960+
13961+ if (unlikely(!task))
13962+ task = find_task_by_pid(shm_lapid);
13963+
13964+ if (unlikely(task && (time_before((unsigned long)task->start_time.tv_sec, (unsigned long)shm_createtime) ||
13965+ (task->pid == shm_lapid)) &&
13966+ (task->acl->mode & GR_PROTSHM) &&
13967+ (task->acl != current->acl))) {
13968+ gr_log_int3(GR_DONT_AUDIT, GR_SHMAT_ACL_MSG, cuid, shm_cprid, shmid);
13969+ return 0;
13970+ }
13971+
13972+ return 1;
13973+}
13974diff -urNp linux-2.6.16.12/grsecurity/grsec_chdir.c linux-2.6.16.12/grsecurity/grsec_chdir.c
13975--- linux-2.6.16.12/grsecurity/grsec_chdir.c 1969-12-31 19:00:00.000000000 -0500
13976+++ linux-2.6.16.12/grsecurity/grsec_chdir.c 2006-05-01 20:17:34.000000000 -0400
13977@@ -0,0 +1,19 @@
13978+#include <linux/kernel.h>
13979+#include <linux/sched.h>
13980+#include <linux/fs.h>
13981+#include <linux/file.h>
13982+#include <linux/grsecurity.h>
13983+#include <linux/grinternal.h>
13984+
13985+void
13986+gr_log_chdir(const struct dentry *dentry, const struct vfsmount *mnt)
13987+{
13988+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
13989+ if ((grsec_enable_chdir && grsec_enable_group &&
13990+ in_group_p(grsec_audit_gid)) || (grsec_enable_chdir &&
13991+ !grsec_enable_group)) {
13992+ gr_log_fs_generic(GR_DO_AUDIT, GR_CHDIR_AUDIT_MSG, dentry, mnt);
13993+ }
13994+#endif
13995+ return;
13996+}
13997diff -urNp linux-2.6.16.12/grsecurity/grsec_chroot.c linux-2.6.16.12/grsecurity/grsec_chroot.c
13998--- linux-2.6.16.12/grsecurity/grsec_chroot.c 1969-12-31 19:00:00.000000000 -0500
13999+++ linux-2.6.16.12/grsecurity/grsec_chroot.c 2006-05-01 20:17:34.000000000 -0400
14000@@ -0,0 +1,332 @@
14001+#include <linux/kernel.h>
14002+#include <linux/module.h>
14003+#include <linux/sched.h>
14004+#include <linux/file.h>
14005+#include <linux/fs.h>
14006+#include <linux/mount.h>
14007+#include <linux/types.h>
14008+#include <linux/grinternal.h>
14009+
14010+int
14011+gr_handle_chroot_unix(const pid_t pid)
14012+{
14013+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
14014+ struct pid *spid = NULL;
14015+
14016+ if (unlikely(!grsec_enable_chroot_unix))
14017+ return 1;
14018+
14019+ if (likely(!proc_is_chrooted(current)))
14020+ return 1;
14021+
14022+ read_lock(&tasklist_lock);
14023+
14024+ spid = find_pid(PIDTYPE_PID, pid);
14025+ if (spid) {
14026+ struct task_struct *p;
14027+ p = pid_task(&spid->pid_list, PIDTYPE_PID);
14028+ task_lock(p);
14029+ if (unlikely(!have_same_root(current, p))) {
14030+ task_unlock(p);
14031+ read_unlock(&tasklist_lock);
14032+ gr_log_noargs(GR_DONT_AUDIT, GR_UNIX_CHROOT_MSG);
14033+ return 0;
14034+ }
14035+ task_unlock(p);
14036+ }
14037+ read_unlock(&tasklist_lock);
14038+#endif
14039+ return 1;
14040+}
14041+
14042+int
14043+gr_handle_chroot_nice(void)
14044+{
14045+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
14046+ if (grsec_enable_chroot_nice && proc_is_chrooted(current)) {
14047+ gr_log_noargs(GR_DONT_AUDIT, GR_NICE_CHROOT_MSG);
14048+ return -EPERM;
14049+ }
14050+#endif
14051+ return 0;
14052+}
14053+
14054+int
14055+gr_handle_chroot_setpriority(struct task_struct *p, const int niceval)
14056+{
14057+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
14058+ if (grsec_enable_chroot_nice && (niceval < task_nice(p))
14059+ && proc_is_chrooted(current)) {
14060+ gr_log_str_int(GR_DONT_AUDIT, GR_PRIORITY_CHROOT_MSG, p->comm, p->pid);
14061+ return -EACCES;
14062+ }
14063+#endif
14064+ return 0;
14065+}
14066+
14067+int
14068+gr_handle_chroot_rawio(const struct inode *inode)
14069+{
14070+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
14071+ if (grsec_enable_chroot_caps && proc_is_chrooted(current) &&
14072+ inode && S_ISBLK(inode->i_mode) && !capable(CAP_SYS_RAWIO))
14073+ return 1;
14074+#endif
14075+ return 0;
14076+}
14077+
14078+int
14079+gr_pid_is_chrooted(struct task_struct *p)
14080+{
14081+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
14082+ if (!grsec_enable_chroot_findtask || !proc_is_chrooted(current) || !p)
14083+ return 0;
14084+
14085+ task_lock(p);
14086+ if ((p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) ||
14087+ !have_same_root(current, p)) {
14088+ task_unlock(p);
14089+ return 1;
14090+ }
14091+ task_unlock(p);
14092+#endif
14093+ return 0;
14094+}
14095+
14096+EXPORT_SYMBOL(gr_pid_is_chrooted);
14097+
14098+#if defined(CONFIG_GRKERNSEC_CHROOT_DOUBLE) || defined(CONFIG_GRKERNSEC_CHROOT_FCHDIR)
14099+int gr_is_outside_chroot(const struct dentry *u_dentry, const struct vfsmount *u_mnt)
14100+{
14101+ struct dentry *dentry = (struct dentry *)u_dentry;
14102+ struct vfsmount *mnt = (struct vfsmount *)u_mnt;
14103+ struct dentry *realroot;
14104+ struct vfsmount *realrootmnt;
14105+ struct dentry *currentroot;
14106+ struct vfsmount *currentmnt;
14107+ int ret = 1;
14108+
14109+ read_lock(&child_reaper->fs->lock);
14110+ realrootmnt = mntget(child_reaper->fs->rootmnt);
14111+ realroot = dget(child_reaper->fs->root);
14112+ read_unlock(&child_reaper->fs->lock);
14113+
14114+ read_lock(&current->fs->lock);
14115+ currentmnt = mntget(current->fs->rootmnt);
14116+ currentroot = dget(current->fs->root);
14117+ read_unlock(&current->fs->lock);
14118+
14119+ spin_lock(&dcache_lock);
14120+ for (;;) {
14121+ if (unlikely((dentry == realroot && mnt == realrootmnt)
14122+ || (dentry == currentroot && mnt == currentmnt)))
14123+ break;
14124+ if (unlikely(dentry == mnt->mnt_root || IS_ROOT(dentry))) {
14125+ if (mnt->mnt_parent == mnt)
14126+ break;
14127+ dentry = mnt->mnt_mountpoint;
14128+ mnt = mnt->mnt_parent;
14129+ continue;
14130+ }
14131+ dentry = dentry->d_parent;
14132+ }
14133+ spin_unlock(&dcache_lock);
14134+
14135+ dput(currentroot);
14136+ mntput(currentmnt);
14137+
14138+ /* access is outside of chroot */
14139+ if (dentry == realroot && mnt == realrootmnt)
14140+ ret = 0;
14141+
14142+ dput(realroot);
14143+ mntput(realrootmnt);
14144+ return ret;
14145+}
14146+#endif
14147+
14148+int
14149+gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt)
14150+{
14151+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
14152+ if (!grsec_enable_chroot_fchdir)
14153+ return 1;
14154+
14155+ if (!proc_is_chrooted(current))
14156+ return 1;
14157+ else if (!gr_is_outside_chroot(u_dentry, u_mnt)) {
14158+ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_FCHDIR_MSG, u_dentry, u_mnt);
14159+ return 0;
14160+ }
14161+#endif
14162+ return 1;
14163+}
14164+
14165+int
14166+gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
14167+ const time_t shm_createtime)
14168+{
14169+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
14170+ struct pid *pid = NULL;
14171+ time_t starttime;
14172+
14173+ if (unlikely(!grsec_enable_chroot_shmat))
14174+ return 1;
14175+
14176+ if (likely(!proc_is_chrooted(current)))
14177+ return 1;
14178+
14179+ read_lock(&tasklist_lock);
14180+
14181+ pid = find_pid(PIDTYPE_PID, shm_cprid);
14182+ if (pid) {
14183+ struct task_struct *p;
14184+ p = pid_task(&pid->pid_list, PIDTYPE_PID);
14185+ task_lock(p);
14186+ starttime = p->start_time.tv_sec;
14187+ if (unlikely(!have_same_root(current, p) &&
14188+ time_before((unsigned long)starttime, (unsigned long)shm_createtime))) {
14189+ task_unlock(p);
14190+ read_unlock(&tasklist_lock);
14191+ gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG);
14192+ return 0;
14193+ }
14194+ task_unlock(p);
14195+ } else {
14196+ pid = find_pid(PIDTYPE_PID, shm_lapid);
14197+ if (pid) {
14198+ struct task_struct *p;
14199+ p = pid_task(&pid->pid_list, PIDTYPE_PID);
14200+ task_lock(p);
14201+ if (unlikely(!have_same_root(current, p))) {
14202+ task_unlock(p);
14203+ read_unlock(&tasklist_lock);
14204+ gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG);
14205+ return 0;
14206+ }
14207+ task_unlock(p);
14208+ }
14209+ }
14210+
14211+ read_unlock(&tasklist_lock);
14212+#endif
14213+ return 1;
14214+}
14215+
14216+void
14217+gr_log_chroot_exec(const struct dentry *dentry, const struct vfsmount *mnt)
14218+{
14219+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
14220+ if (grsec_enable_chroot_execlog && proc_is_chrooted(current))
14221+ gr_log_fs_generic(GR_DO_AUDIT, GR_EXEC_CHROOT_MSG, dentry, mnt);
14222+#endif
14223+ return;
14224+}
14225+
14226+int
14227+gr_handle_chroot_mknod(const struct dentry *dentry,
14228+ const struct vfsmount *mnt, const int mode)
14229+{
14230+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
14231+ if (grsec_enable_chroot_mknod && !S_ISFIFO(mode) && !S_ISREG(mode) &&
14232+ proc_is_chrooted(current)) {
14233+ gr_log_fs_generic(GR_DONT_AUDIT, GR_MKNOD_CHROOT_MSG, dentry, mnt);
14234+ return -EPERM;
14235+ }
14236+#endif
14237+ return 0;
14238+}
14239+
14240+int
14241+gr_handle_chroot_mount(const struct dentry *dentry,
14242+ const struct vfsmount *mnt, const char *dev_name)
14243+{
14244+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
14245+ if (grsec_enable_chroot_mount && proc_is_chrooted(current)) {
14246+ gr_log_str_fs(GR_DONT_AUDIT, GR_MOUNT_CHROOT_MSG, dev_name, dentry, mnt);
14247+ return -EPERM;
14248+ }
14249+#endif
14250+ return 0;
14251+}
14252+
14253+int
14254+gr_handle_chroot_pivot(void)
14255+{
14256+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
14257+ if (grsec_enable_chroot_pivot && proc_is_chrooted(current)) {
14258+ gr_log_noargs(GR_DONT_AUDIT, GR_PIVOT_CHROOT_MSG);
14259+ return -EPERM;
14260+ }
14261+#endif
14262+ return 0;
14263+}
14264+
14265+int
14266+gr_handle_chroot_chroot(const struct dentry *dentry, const struct vfsmount *mnt)
14267+{
14268+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
14269+ if (grsec_enable_chroot_double && proc_is_chrooted(current) &&
14270+ !gr_is_outside_chroot(dentry, mnt)) {
14271+ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_CHROOT_MSG, dentry, mnt);
14272+ return -EPERM;
14273+ }
14274+#endif
14275+ return 0;
14276+}
14277+
14278+void
14279+gr_handle_chroot_caps(struct task_struct *task)
14280+{
14281+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
14282+ if (grsec_enable_chroot_caps && proc_is_chrooted(task)) {
14283+ task->cap_permitted =
14284+ cap_drop(task->cap_permitted, GR_CHROOT_CAPS);
14285+ task->cap_inheritable =
14286+ cap_drop(task->cap_inheritable, GR_CHROOT_CAPS);
14287+ task->cap_effective =
14288+ cap_drop(task->cap_effective, GR_CHROOT_CAPS);
14289+ }
14290+#endif
14291+ return;
14292+}
14293+
14294+int
14295+gr_handle_chroot_sysctl(const int op)
14296+{
14297+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
14298+ if (grsec_enable_chroot_sysctl && proc_is_chrooted(current)
14299+ && (op & 002))
14300+ return -EACCES;
14301+#endif
14302+ return 0;
14303+}
14304+
14305+void
14306+gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt)
14307+{
14308+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
14309+ if (grsec_enable_chroot_chdir)
14310+ set_fs_pwd(current->fs, mnt, dentry);
14311+#endif
14312+ return;
14313+}
14314+
14315+int
14316+gr_handle_chroot_chmod(const struct dentry *dentry,
14317+ const struct vfsmount *mnt, const int mode)
14318+{
14319+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
14320+ if (grsec_enable_chroot_chmod &&
14321+ ((mode & S_ISUID) || ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) &&
14322+ proc_is_chrooted(current)) {
14323+ gr_log_fs_generic(GR_DONT_AUDIT, GR_CHMOD_CHROOT_MSG, dentry, mnt);
14324+ return -EPERM;
14325+ }
14326+#endif
14327+ return 0;
14328+}
14329+
14330+#ifdef CONFIG_SECURITY
14331+EXPORT_SYMBOL(gr_handle_chroot_caps);
14332+#endif
14333diff -urNp linux-2.6.16.12/grsecurity/grsec_disabled.c linux-2.6.16.12/grsecurity/grsec_disabled.c
14334--- linux-2.6.16.12/grsecurity/grsec_disabled.c 1969-12-31 19:00:00.000000000 -0500
14335+++ linux-2.6.16.12/grsecurity/grsec_disabled.c 2006-05-01 20:17:34.000000000 -0400
14336@@ -0,0 +1,418 @@
14337+#include <linux/kernel.h>
14338+#include <linux/module.h>
14339+#include <linux/config.h>
14340+#include <linux/sched.h>
14341+#include <linux/file.h>
14342+#include <linux/fs.h>
14343+#include <linux/kdev_t.h>
14344+#include <linux/net.h>
14345+#include <linux/in.h>
14346+#include <linux/ip.h>
14347+#include <linux/skbuff.h>
14348+#include <linux/sysctl.h>
14349+
14350+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
14351+void
14352+pax_set_initial_flags(struct linux_binprm *bprm)
14353+{
14354+ return;
14355+}
14356+#endif
14357+
14358+#ifdef CONFIG_SYSCTL
14359+__u32
14360+gr_handle_sysctl(const struct ctl_table * table, __u32 mode)
14361+{
14362+ return mode;
14363+}
14364+#endif
14365+
14366+int
14367+gr_acl_is_enabled(void)
14368+{
14369+ return 0;
14370+}
14371+
14372+int
14373+gr_handle_rawio(const struct inode *inode)
14374+{
14375+ return 0;
14376+}
14377+
14378+void
14379+gr_acl_handle_psacct(struct task_struct *task, const long code)
14380+{
14381+ return;
14382+}
14383+
14384+int
14385+gr_handle_ptrace(struct task_struct *task, const long request)
14386+{
14387+ return 0;
14388+}
14389+
14390+int
14391+gr_handle_proc_ptrace(struct task_struct *task)
14392+{
14393+ return 0;
14394+}
14395+
14396+void
14397+gr_learn_resource(const struct task_struct *task,
14398+ const int res, const unsigned long wanted, const int gt)
14399+{
14400+ return;
14401+}
14402+
14403+int
14404+gr_set_acls(const int type)
14405+{
14406+ return 0;
14407+}
14408+
14409+int
14410+gr_check_hidden_task(const struct task_struct *tsk)
14411+{
14412+ return 0;
14413+}
14414+
14415+int
14416+gr_check_protected_task(const struct task_struct *task)
14417+{
14418+ return 0;
14419+}
14420+
14421+void
14422+gr_copy_label(struct task_struct *tsk)
14423+{
14424+ return;
14425+}
14426+
14427+void
14428+gr_set_pax_flags(struct task_struct *task)
14429+{
14430+ return;
14431+}
14432+
14433+int
14434+gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
14435+{
14436+ return 0;
14437+}
14438+
14439+void
14440+gr_handle_delete(const ino_t ino, const dev_t dev)
14441+{
14442+ return;
14443+}
14444+
14445+void
14446+gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
14447+{
14448+ return;
14449+}
14450+
14451+void
14452+gr_handle_crash(struct task_struct *task, const int sig)
14453+{
14454+ return;
14455+}
14456+
14457+int
14458+gr_check_crash_exec(const struct file *filp)
14459+{
14460+ return 0;
14461+}
14462+
14463+int
14464+gr_check_crash_uid(const uid_t uid)
14465+{
14466+ return 0;
14467+}
14468+
14469+void
14470+gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
14471+ struct dentry *old_dentry,
14472+ struct dentry *new_dentry,
14473+ struct vfsmount *mnt, const __u8 replace)
14474+{
14475+ return;
14476+}
14477+
14478+int
14479+gr_search_socket(const int family, const int type, const int protocol)
14480+{
14481+ return 1;
14482+}
14483+
14484+int
14485+gr_search_connectbind(const int mode, const struct socket *sock,
14486+ const struct sockaddr_in *addr)
14487+{
14488+ return 1;
14489+}
14490+
14491+int
14492+gr_task_is_capable(struct task_struct *task, const int cap)
14493+{
14494+ return 1;
14495+}
14496+
14497+int
14498+gr_is_capable_nolog(const int cap)
14499+{
14500+ return 1;
14501+}
14502+
14503+void
14504+gr_handle_alertkill(struct task_struct *task)
14505+{
14506+ return;
14507+}
14508+
14509+__u32
14510+gr_acl_handle_execve(const struct dentry * dentry, const struct vfsmount * mnt)
14511+{
14512+ return 1;
14513+}
14514+
14515+__u32
14516+gr_acl_handle_hidden_file(const struct dentry * dentry,
14517+ const struct vfsmount * mnt)
14518+{
14519+ return 1;
14520+}
14521+
14522+__u32
14523+gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
14524+ const int fmode)
14525+{
14526+ return 1;
14527+}
14528+
14529+__u32
14530+gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
14531+{
14532+ return 1;
14533+}
14534+
14535+__u32
14536+gr_acl_handle_unlink(const struct dentry * dentry, const struct vfsmount * mnt)
14537+{
14538+ return 1;
14539+}
14540+
14541+int
14542+gr_acl_handle_mmap(const struct file *file, const unsigned long prot,
14543+ unsigned int *vm_flags)
14544+{
14545+ return 1;
14546+}
14547+
14548+__u32
14549+gr_acl_handle_truncate(const struct dentry * dentry,
14550+ const struct vfsmount * mnt)
14551+{
14552+ return 1;
14553+}
14554+
14555+__u32
14556+gr_acl_handle_utime(const struct dentry * dentry, const struct vfsmount * mnt)
14557+{
14558+ return 1;
14559+}
14560+
14561+__u32
14562+gr_acl_handle_access(const struct dentry * dentry,
14563+ const struct vfsmount * mnt, const int fmode)
14564+{
14565+ return 1;
14566+}
14567+
14568+__u32
14569+gr_acl_handle_fchmod(const struct dentry * dentry, const struct vfsmount * mnt,
14570+ mode_t mode)
14571+{
14572+ return 1;
14573+}
14574+
14575+__u32
14576+gr_acl_handle_chmod(const struct dentry * dentry, const struct vfsmount * mnt,
14577+ mode_t mode)
14578+{
14579+ return 1;
14580+}
14581+
14582+__u32
14583+gr_acl_handle_chown(const struct dentry * dentry, const struct vfsmount * mnt)
14584+{
14585+ return 1;
14586+}
14587+
14588+void
14589+grsecurity_init(void)
14590+{
14591+ return;
14592+}
14593+
14594+__u32
14595+gr_acl_handle_mknod(const struct dentry * new_dentry,
14596+ const struct dentry * parent_dentry,
14597+ const struct vfsmount * parent_mnt,
14598+ const int mode)
14599+{
14600+ return 1;
14601+}
14602+
14603+__u32
14604+gr_acl_handle_mkdir(const struct dentry * new_dentry,
14605+ const struct dentry * parent_dentry,
14606+ const struct vfsmount * parent_mnt)
14607+{
14608+ return 1;
14609+}
14610+
14611+__u32
14612+gr_acl_handle_symlink(const struct dentry * new_dentry,
14613+ const struct dentry * parent_dentry,
14614+ const struct vfsmount * parent_mnt, const char *from)
14615+{
14616+ return 1;
14617+}
14618+
14619+__u32
14620+gr_acl_handle_link(const struct dentry * new_dentry,
14621+ const struct dentry * parent_dentry,
14622+ const struct vfsmount * parent_mnt,
14623+ const struct dentry * old_dentry,
14624+ const struct vfsmount * old_mnt, const char *to)
14625+{
14626+ return 1;
14627+}
14628+
14629+int
14630+gr_acl_handle_rename(const struct dentry *new_dentry,
14631+ const struct dentry *parent_dentry,
14632+ const struct vfsmount *parent_mnt,
14633+ const struct dentry *old_dentry,
14634+ const struct inode *old_parent_inode,
14635+ const struct vfsmount *old_mnt, const char *newname)
14636+{
14637+ return 0;
14638+}
14639+
14640+int
14641+gr_acl_handle_filldir(const struct file *file, const char *name,
14642+ const int namelen, const ino_t ino)
14643+{
14644+ return 1;
14645+}
14646+
14647+int
14648+gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
14649+ const time_t shm_createtime, const uid_t cuid, const int shmid)
14650+{
14651+ return 1;
14652+}
14653+
14654+int
14655+gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
14656+{
14657+ return 1;
14658+}
14659+
14660+int
14661+gr_search_accept(const struct socket *sock)
14662+{
14663+ return 1;
14664+}
14665+
14666+int
14667+gr_search_listen(const struct socket *sock)
14668+{
14669+ return 1;
14670+}
14671+
14672+int
14673+gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
14674+{
14675+ return 1;
14676+}
14677+
14678+__u32
14679+gr_acl_handle_unix(const struct dentry * dentry, const struct vfsmount * mnt)
14680+{
14681+ return 1;
14682+}
14683+
14684+__u32
14685+gr_acl_handle_creat(const struct dentry * dentry,
14686+ const struct dentry * p_dentry,
14687+ const struct vfsmount * p_mnt, const int fmode,
14688+ const int imode)
14689+{
14690+ return 1;
14691+}
14692+
14693+void
14694+gr_acl_handle_exit(void)
14695+{
14696+ return;
14697+}
14698+
14699+int
14700+gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
14701+{
14702+ return 1;
14703+}
14704+
14705+void
14706+gr_set_role_label(const uid_t uid, const gid_t gid)
14707+{
14708+ return;
14709+}
14710+
14711+int
14712+gr_acl_handle_procpidmem(const struct task_struct *task)
14713+{
14714+ return 0;
14715+}
14716+
14717+int
14718+gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
14719+{
14720+ return 1;
14721+}
14722+
14723+int
14724+gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
14725+{
14726+ return 1;
14727+}
14728+
14729+void
14730+gr_set_kernel_label(struct task_struct *task)
14731+{
14732+ return;
14733+}
14734+
14735+int
14736+gr_check_user_change(int real, int effective, int fs)
14737+{
14738+ return 0;
14739+}
14740+
14741+int
14742+gr_check_group_change(int real, int effective, int fs)
14743+{
14744+ return 0;
14745+}
14746+
14747+
14748+EXPORT_SYMBOL(gr_task_is_capable);
14749+EXPORT_SYMBOL(gr_learn_resource);
14750+EXPORT_SYMBOL(gr_set_kernel_label);
14751+#ifdef CONFIG_SECURITY
14752+EXPORT_SYMBOL(gr_check_user_change);
14753+EXPORT_SYMBOL(gr_check_group_change);
14754+#endif
14755diff -urNp linux-2.6.16.12/grsecurity/grsec_exec.c linux-2.6.16.12/grsecurity/grsec_exec.c
14756--- linux-2.6.16.12/grsecurity/grsec_exec.c 1969-12-31 19:00:00.000000000 -0500
14757+++ linux-2.6.16.12/grsecurity/grsec_exec.c 2006-05-01 20:17:34.000000000 -0400
14758@@ -0,0 +1,88 @@
14759+#include <linux/kernel.h>
14760+#include <linux/sched.h>
14761+#include <linux/file.h>
14762+#include <linux/binfmts.h>
14763+#include <linux/smp_lock.h>
14764+#include <linux/fs.h>
14765+#include <linux/types.h>
14766+#include <linux/grdefs.h>
14767+#include <linux/grinternal.h>
14768+#include <linux/capability.h>
14769+
14770+#include <asm/uaccess.h>
14771+
14772+#ifdef CONFIG_GRKERNSEC_EXECLOG
14773+static char gr_exec_arg_buf[132];
14774+static DECLARE_MUTEX(gr_exec_arg_sem);
14775+#endif
14776+
14777+int
14778+gr_handle_nproc(void)
14779+{
14780+#ifdef CONFIG_GRKERNSEC_EXECVE
14781+ if (grsec_enable_execve && current->user &&
14782+ (atomic_read(&current->user->processes) >
14783+ current->signal->rlim[RLIMIT_NPROC].rlim_cur) &&
14784+ !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) {
14785+ gr_log_noargs(GR_DONT_AUDIT, GR_NPROC_MSG);
14786+ return -EAGAIN;
14787+ }
14788+#endif
14789+ return 0;
14790+}
14791+
14792+void
14793+gr_handle_exec_args(struct linux_binprm *bprm, const char __user *__user *argv)
14794+{
14795+#ifdef CONFIG_GRKERNSEC_EXECLOG
14796+ char *grarg = gr_exec_arg_buf;
14797+ unsigned int i, x, execlen = 0;
14798+ char c;
14799+
14800+ if (!((grsec_enable_execlog && grsec_enable_group &&
14801+ in_group_p(grsec_audit_gid))
14802+ || (grsec_enable_execlog && !grsec_enable_group)))
14803+ return;
14804+
14805+ down(&gr_exec_arg_sem);
14806+ memset(grarg, 0, sizeof(gr_exec_arg_buf));
14807+
14808+ if (unlikely(argv == NULL))
14809+ goto log;
14810+
14811+ for (i = 0; i < bprm->argc && execlen < 128; i++) {
14812+ const char __user *p;
14813+ unsigned int len;
14814+
14815+ if (copy_from_user(&p, argv + i, sizeof(p)))
14816+ goto log;
14817+ if (!p)
14818+ goto log;
14819+ len = strnlen_user(p, 128 - execlen);
14820+ if (len > 128 - execlen)
14821+ len = 128 - execlen;
14822+ else if (len > 0)
14823+ len--;
14824+ if (copy_from_user(grarg + execlen, p, len))
14825+ goto log;
14826+
14827+ /* rewrite unprintable characters */
14828+ for (x = 0; x < len; x++) {
14829+ c = *(grarg + execlen + x);
14830+ if (c < 32 || c > 126)
14831+ *(grarg + execlen + x) = ' ';
14832+ }
14833+
14834+ execlen += len;
14835+ *(grarg + execlen) = ' ';
14836+ *(grarg + execlen + 1) = '\0';
14837+ execlen++;
14838+ }
14839+
14840+ log:
14841+ gr_log_fs_str(GR_DO_AUDIT, GR_EXEC_AUDIT_MSG, bprm->file->f_dentry,
14842+ bprm->file->f_vfsmnt, grarg);
14843+ up(&gr_exec_arg_sem);
14844+#endif
14845+ return;
14846+}
14847diff -urNp linux-2.6.16.12/grsecurity/grsec_fifo.c linux-2.6.16.12/grsecurity/grsec_fifo.c
14848--- linux-2.6.16.12/grsecurity/grsec_fifo.c 1969-12-31 19:00:00.000000000 -0500
14849+++ linux-2.6.16.12/grsecurity/grsec_fifo.c 2006-05-01 20:17:34.000000000 -0400
14850@@ -0,0 +1,22 @@
14851+#include <linux/kernel.h>
14852+#include <linux/sched.h>
14853+#include <linux/fs.h>
14854+#include <linux/file.h>
14855+#include <linux/grinternal.h>
14856+
14857+int
14858+gr_handle_fifo(const struct dentry *dentry, const struct vfsmount *mnt,
14859+ const struct dentry *dir, const int flag, const int acc_mode)
14860+{
14861+#ifdef CONFIG_GRKERNSEC_FIFO
14862+ if (grsec_enable_fifo && S_ISFIFO(dentry->d_inode->i_mode) &&
14863+ !(flag & O_EXCL) && (dir->d_inode->i_mode & S_ISVTX) &&
14864+ (dentry->d_inode->i_uid != dir->d_inode->i_uid) &&
14865+ (current->fsuid != dentry->d_inode->i_uid)) {
14866+ if (!generic_permission(dentry->d_inode, acc_mode, NULL))
14867+ gr_log_fs_int2(GR_DONT_AUDIT, GR_FIFO_MSG, dentry, mnt, dentry->d_inode->i_uid, dentry->d_inode->i_gid);
14868+ return -EACCES;
14869+ }
14870+#endif
14871+ return 0;
14872+}
14873diff -urNp linux-2.6.16.12/grsecurity/grsec_fork.c linux-2.6.16.12/grsecurity/grsec_fork.c
14874--- linux-2.6.16.12/grsecurity/grsec_fork.c 1969-12-31 19:00:00.000000000 -0500
14875+++ linux-2.6.16.12/grsecurity/grsec_fork.c 2006-05-01 20:17:34.000000000 -0400
14876@@ -0,0 +1,14 @@
14877+#include <linux/kernel.h>
14878+#include <linux/sched.h>
14879+#include <linux/grsecurity.h>
14880+#include <linux/grinternal.h>
14881+
14882+void
14883+gr_log_forkfail(const int retval)
14884+{
14885+#ifdef CONFIG_GRKERNSEC_FORKFAIL
14886+ if (grsec_enable_forkfail)
14887+ gr_log_int(GR_DONT_AUDIT, GR_FAILFORK_MSG, retval);
14888+#endif
14889+ return;
14890+}
14891diff -urNp linux-2.6.16.12/grsecurity/grsec_init.c linux-2.6.16.12/grsecurity/grsec_init.c
14892--- linux-2.6.16.12/grsecurity/grsec_init.c 1969-12-31 19:00:00.000000000 -0500
14893+++ linux-2.6.16.12/grsecurity/grsec_init.c 2006-05-01 20:17:34.000000000 -0400
14894@@ -0,0 +1,232 @@
14895+#include <linux/kernel.h>
14896+#include <linux/sched.h>
14897+#include <linux/mm.h>
14898+#include <linux/smp_lock.h>
14899+#include <linux/gracl.h>
14900+#include <linux/slab.h>
14901+#include <linux/vmalloc.h>
14902+#include <linux/percpu.h>
14903+
14904+int grsec_enable_shm;
14905+int grsec_enable_link;
14906+int grsec_enable_dmesg;
14907+int grsec_enable_fifo;
14908+int grsec_enable_execve;
14909+int grsec_enable_execlog;
14910+int grsec_enable_signal;
14911+int grsec_enable_forkfail;
14912+int grsec_enable_time;
14913+int grsec_enable_audit_textrel;
14914+int grsec_enable_group;
14915+int grsec_audit_gid;
14916+int grsec_enable_chdir;
14917+int grsec_enable_audit_ipc;
14918+int grsec_enable_mount;
14919+int grsec_enable_chroot_findtask;
14920+int grsec_enable_chroot_mount;
14921+int grsec_enable_chroot_shmat;
14922+int grsec_enable_chroot_fchdir;
14923+int grsec_enable_chroot_double;
14924+int grsec_enable_chroot_pivot;
14925+int grsec_enable_chroot_chdir;
14926+int grsec_enable_chroot_chmod;
14927+int grsec_enable_chroot_mknod;
14928+int grsec_enable_chroot_nice;
14929+int grsec_enable_chroot_execlog;
14930+int grsec_enable_chroot_caps;
14931+int grsec_enable_chroot_sysctl;
14932+int grsec_enable_chroot_unix;
14933+int grsec_enable_tpe;
14934+int grsec_tpe_gid;
14935+int grsec_enable_tpe_all;
14936+int grsec_enable_randpid;
14937+int grsec_enable_socket_all;
14938+int grsec_socket_all_gid;
14939+int grsec_enable_socket_client;
14940+int grsec_socket_client_gid;
14941+int grsec_enable_socket_server;
14942+int grsec_socket_server_gid;
14943+int grsec_lock;
14944+
14945+spinlock_t grsec_alert_lock = SPIN_LOCK_UNLOCKED;
14946+unsigned long grsec_alert_wtime = 0;
14947+unsigned long grsec_alert_fyet = 0;
14948+
14949+spinlock_t grsec_audit_lock = SPIN_LOCK_UNLOCKED;
14950+
14951+rwlock_t grsec_exec_file_lock = RW_LOCK_UNLOCKED;
14952+
14953+char *gr_shared_page[4];
14954+
14955+char *gr_alert_log_fmt;
14956+char *gr_audit_log_fmt;
14957+char *gr_alert_log_buf;
14958+char *gr_audit_log_buf;
14959+
14960+extern struct gr_arg *gr_usermode;
14961+extern unsigned char *gr_system_salt;
14962+extern unsigned char *gr_system_sum;
14963+
14964+void
14965+grsecurity_init(void)
14966+{
14967+ int j;
14968+ /* create the per-cpu shared pages */
14969+
14970+ preempt_disable();
14971+ for (j = 0; j < 4; j++) {
14972+ gr_shared_page[j] = (char *)__alloc_percpu(PAGE_SIZE);
14973+ if (gr_shared_page[j] == NULL) {
14974+ panic("Unable to allocate grsecurity shared page");
14975+ return;
14976+ }
14977+ }
14978+ preempt_enable();
14979+
14980+ /* allocate log buffers */
14981+ gr_alert_log_fmt = kmalloc(512, GFP_KERNEL);
14982+ if (!gr_alert_log_fmt) {
14983+ panic("Unable to allocate grsecurity alert log format buffer");
14984+ return;
14985+ }
14986+ gr_audit_log_fmt = kmalloc(512, GFP_KERNEL);
14987+ if (!gr_audit_log_fmt) {
14988+ panic("Unable to allocate grsecurity audit log format buffer");
14989+ return;
14990+ }
14991+ gr_alert_log_buf = (char *) get_zeroed_page(GFP_KERNEL);
14992+ if (!gr_alert_log_buf) {
14993+ panic("Unable to allocate grsecurity alert log buffer");
14994+ return;
14995+ }
14996+ gr_audit_log_buf = (char *) get_zeroed_page(GFP_KERNEL);
14997+ if (!gr_audit_log_buf) {
14998+ panic("Unable to allocate grsecurity audit log buffer");
14999+ return;
15000+ }
15001+
15002+ /* allocate memory for authentication structure */
15003+ gr_usermode = kmalloc(sizeof(struct gr_arg), GFP_KERNEL);
15004+ gr_system_salt = kmalloc(GR_SALT_LEN, GFP_KERNEL);
15005+ gr_system_sum = kmalloc(GR_SHA_LEN, GFP_KERNEL);
15006+
15007+ if (!gr_usermode || !gr_system_salt || !gr_system_sum) {
15008+ panic("Unable to allocate grsecurity authentication structure");
15009+ return;
15010+ }
15011+
15012+#if !defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_SYSCTL_ON)
15013+#ifndef CONFIG_GRKERNSEC_SYSCTL
15014+ grsec_lock = 1;
15015+#endif
15016+#ifdef CONFIG_GRKERNSEC_SHM
15017+ grsec_enable_shm = 1;
15018+#endif
15019+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
15020+ grsec_enable_audit_textrel = 1;
15021+#endif
15022+#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
15023+ grsec_enable_group = 1;
15024+ grsec_audit_gid = CONFIG_GRKERNSEC_AUDIT_GID;
15025+#endif
15026+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
15027+ grsec_enable_chdir = 1;
15028+#endif
15029+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15030+ grsec_enable_audit_ipc = 1;
15031+#endif
15032+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
15033+ grsec_enable_mount = 1;
15034+#endif
15035+#ifdef CONFIG_GRKERNSEC_LINK
15036+ grsec_enable_link = 1;
15037+#endif
15038+#ifdef CONFIG_GRKERNSEC_DMESG
15039+ grsec_enable_dmesg = 1;
15040+#endif
15041+#ifdef CONFIG_GRKERNSEC_FIFO
15042+ grsec_enable_fifo = 1;
15043+#endif
15044+#ifdef CONFIG_GRKERNSEC_EXECVE
15045+ grsec_enable_execve = 1;
15046+#endif
15047+#ifdef CONFIG_GRKERNSEC_EXECLOG
15048+ grsec_enable_execlog = 1;
15049+#endif
15050+#ifdef CONFIG_GRKERNSEC_SIGNAL
15051+ grsec_enable_signal = 1;
15052+#endif
15053+#ifdef CONFIG_GRKERNSEC_FORKFAIL
15054+ grsec_enable_forkfail = 1;
15055+#endif
15056+#ifdef CONFIG_GRKERNSEC_TIME
15057+ grsec_enable_time = 1;
15058+#endif
15059+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
15060+ grsec_enable_chroot_findtask = 1;
15061+#endif
15062+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
15063+ grsec_enable_chroot_unix = 1;
15064+#endif
15065+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
15066+ grsec_enable_chroot_mount = 1;
15067+#endif
15068+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
15069+ grsec_enable_chroot_fchdir = 1;
15070+#endif
15071+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
15072+ grsec_enable_chroot_shmat = 1;
15073+#endif
15074+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
15075+ grsec_enable_chroot_double = 1;
15076+#endif
15077+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
15078+ grsec_enable_chroot_pivot = 1;
15079+#endif
15080+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
15081+ grsec_enable_chroot_chdir = 1;
15082+#endif
15083+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
15084+ grsec_enable_chroot_chmod = 1;
15085+#endif
15086+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
15087+ grsec_enable_chroot_mknod = 1;
15088+#endif
15089+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
15090+ grsec_enable_chroot_nice = 1;
15091+#endif
15092+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
15093+ grsec_enable_chroot_execlog = 1;
15094+#endif
15095+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
15096+ grsec_enable_chroot_caps = 1;
15097+#endif
15098+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
15099+ grsec_enable_chroot_sysctl = 1;
15100+#endif
15101+#ifdef CONFIG_GRKERNSEC_TPE
15102+ grsec_enable_tpe = 1;
15103+ grsec_tpe_gid = CONFIG_GRKERNSEC_TPE_GID;
15104+#ifdef CONFIG_GRKERNSEC_TPE_ALL
15105+ grsec_enable_tpe_all = 1;
15106+#endif
15107+#endif
15108+#ifdef CONFIG_GRKERNSEC_RANDPID
15109+ grsec_enable_randpid = 1;
15110+#endif
15111+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
15112+ grsec_enable_socket_all = 1;
15113+ grsec_socket_all_gid = CONFIG_GRKERNSEC_SOCKET_ALL_GID;
15114+#endif
15115+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
15116+ grsec_enable_socket_client = 1;
15117+ grsec_socket_client_gid = CONFIG_GRKERNSEC_SOCKET_CLIENT_GID;
15118+#endif
15119+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
15120+ grsec_enable_socket_server = 1;
15121+ grsec_socket_server_gid = CONFIG_GRKERNSEC_SOCKET_SERVER_GID;
15122+#endif
15123+#endif
15124+
15125+ return;
15126+}
15127diff -urNp linux-2.6.16.12/grsecurity/grsec_ipc.c linux-2.6.16.12/grsecurity/grsec_ipc.c
15128--- linux-2.6.16.12/grsecurity/grsec_ipc.c 1969-12-31 19:00:00.000000000 -0500
15129+++ linux-2.6.16.12/grsecurity/grsec_ipc.c 2006-05-01 20:17:34.000000000 -0400
15130@@ -0,0 +1,81 @@
15131+#include <linux/kernel.h>
15132+#include <linux/sched.h>
15133+#include <linux/types.h>
15134+#include <linux/ipc.h>
15135+#include <linux/grsecurity.h>
15136+#include <linux/grinternal.h>
15137+
15138+void
15139+gr_log_msgget(const int ret, const int msgflg)
15140+{
15141+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15142+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15143+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
15144+ !grsec_enable_group)) && (ret >= 0)
15145+ && (msgflg & IPC_CREAT))
15146+ gr_log_noargs(GR_DO_AUDIT, GR_MSGQ_AUDIT_MSG);
15147+#endif
15148+ return;
15149+}
15150+
15151+void
15152+gr_log_msgrm(const uid_t uid, const uid_t cuid)
15153+{
15154+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15155+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15156+ grsec_enable_audit_ipc) ||
15157+ (grsec_enable_audit_ipc && !grsec_enable_group))
15158+ gr_log_int_int(GR_DO_AUDIT, GR_MSGQR_AUDIT_MSG, uid, cuid);
15159+#endif
15160+ return;
15161+}
15162+
15163+void
15164+gr_log_semget(const int err, const int semflg)
15165+{
15166+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15167+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15168+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
15169+ !grsec_enable_group)) && (err >= 0)
15170+ && (semflg & IPC_CREAT))
15171+ gr_log_noargs(GR_DO_AUDIT, GR_SEM_AUDIT_MSG);
15172+#endif
15173+ return;
15174+}
15175+
15176+void
15177+gr_log_semrm(const uid_t uid, const uid_t cuid)
15178+{
15179+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15180+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15181+ grsec_enable_audit_ipc) ||
15182+ (grsec_enable_audit_ipc && !grsec_enable_group))
15183+ gr_log_int_int(GR_DO_AUDIT, GR_SEMR_AUDIT_MSG, uid, cuid);
15184+#endif
15185+ return;
15186+}
15187+
15188+void
15189+gr_log_shmget(const int err, const int shmflg, const size_t size)
15190+{
15191+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15192+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15193+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
15194+ !grsec_enable_group)) && (err >= 0)
15195+ && (shmflg & IPC_CREAT))
15196+ gr_log_int(GR_DO_AUDIT, GR_SHM_AUDIT_MSG, size);
15197+#endif
15198+ return;
15199+}
15200+
15201+void
15202+gr_log_shmrm(const uid_t uid, const uid_t cuid)
15203+{
15204+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15205+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15206+ grsec_enable_audit_ipc) ||
15207+ (grsec_enable_audit_ipc && !grsec_enable_group))
15208+ gr_log_int_int(GR_DO_AUDIT, GR_SHMR_AUDIT_MSG, uid, cuid);
15209+#endif
15210+ return;
15211+}
15212diff -urNp linux-2.6.16.12/grsecurity/grsec_link.c linux-2.6.16.12/grsecurity/grsec_link.c
15213--- linux-2.6.16.12/grsecurity/grsec_link.c 1969-12-31 19:00:00.000000000 -0500
15214+++ linux-2.6.16.12/grsecurity/grsec_link.c 2006-05-01 20:17:34.000000000 -0400
15215@@ -0,0 +1,39 @@
15216+#include <linux/kernel.h>
15217+#include <linux/sched.h>
15218+#include <linux/fs.h>
15219+#include <linux/file.h>
15220+#include <linux/grinternal.h>
15221+
15222+int
15223+gr_handle_follow_link(const struct inode *parent,
15224+ const struct inode *inode,
15225+ const struct dentry *dentry, const struct vfsmount *mnt)
15226+{
15227+#ifdef CONFIG_GRKERNSEC_LINK
15228+ if (grsec_enable_link && S_ISLNK(inode->i_mode) &&
15229+ (parent->i_mode & S_ISVTX) && (parent->i_uid != inode->i_uid) &&
15230+ (parent->i_mode & S_IWOTH) && (current->fsuid != inode->i_uid)) {
15231+ gr_log_fs_int2(GR_DONT_AUDIT, GR_SYMLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid);
15232+ return -EACCES;
15233+ }
15234+#endif
15235+ return 0;
15236+}
15237+
15238+int
15239+gr_handle_hardlink(const struct dentry *dentry,
15240+ const struct vfsmount *mnt,
15241+ struct inode *inode, const int mode, const char *to)
15242+{
15243+#ifdef CONFIG_GRKERNSEC_LINK
15244+ if (grsec_enable_link && current->fsuid != inode->i_uid &&
15245+ (!S_ISREG(mode) || (mode & S_ISUID) ||
15246+ ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) ||
15247+ (generic_permission(inode, MAY_READ | MAY_WRITE, NULL))) &&
15248+ !capable(CAP_FOWNER) && current->uid) {
15249+ gr_log_fs_int2_str(GR_DONT_AUDIT, GR_HARDLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid, to);
15250+ return -EPERM;
15251+ }
15252+#endif
15253+ return 0;
15254+}
15255diff -urNp linux-2.6.16.12/grsecurity/grsec_log.c linux-2.6.16.12/grsecurity/grsec_log.c
15256--- linux-2.6.16.12/grsecurity/grsec_log.c 1969-12-31 19:00:00.000000000 -0500
15257+++ linux-2.6.16.12/grsecurity/grsec_log.c 2006-05-01 20:17:34.000000000 -0400
15258@@ -0,0 +1,265 @@
15259+#include <linux/kernel.h>
15260+#include <linux/sched.h>
15261+#include <linux/file.h>
15262+#include <linux/tty.h>
15263+#include <linux/fs.h>
15264+#include <linux/grinternal.h>
15265+
15266+#define BEGIN_LOCKS(x) \
15267+ read_lock(&tasklist_lock); \
15268+ read_lock(&grsec_exec_file_lock); \
15269+ if (x != GR_DO_AUDIT) \
15270+ spin_lock(&grsec_alert_lock); \
15271+ else \
15272+ spin_lock(&grsec_audit_lock)
15273+
15274+#define END_LOCKS(x) \
15275+ if (x != GR_DO_AUDIT) \
15276+ spin_unlock(&grsec_alert_lock); \
15277+ else \
15278+ spin_unlock(&grsec_audit_lock); \
15279+ read_unlock(&grsec_exec_file_lock); \
15280+ read_unlock(&tasklist_lock); \
15281+ if (x == GR_DONT_AUDIT) \
15282+ gr_handle_alertkill(current)
15283+
15284+enum {
15285+ FLOODING,
15286+ NO_FLOODING
15287+};
15288+
15289+extern char *gr_alert_log_fmt;
15290+extern char *gr_audit_log_fmt;
15291+extern char *gr_alert_log_buf;
15292+extern char *gr_audit_log_buf;
15293+
15294+static int gr_log_start(int audit)
15295+{
15296+ char *loglevel = (audit == GR_DO_AUDIT) ? KERN_INFO : KERN_ALERT;
15297+ char *fmt = (audit == GR_DO_AUDIT) ? gr_audit_log_fmt : gr_alert_log_fmt;
15298+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
15299+
15300+ if (audit == GR_DO_AUDIT)
15301+ goto set_fmt;
15302+
15303+ if (!grsec_alert_wtime || jiffies - grsec_alert_wtime > CONFIG_GRKERNSEC_FLOODTIME * HZ) {
15304+ grsec_alert_wtime = jiffies;
15305+ grsec_alert_fyet = 0;
15306+ } else if ((jiffies - grsec_alert_wtime < CONFIG_GRKERNSEC_FLOODTIME * HZ) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) {
15307+ grsec_alert_fyet++;
15308+ } else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) {
15309+ grsec_alert_wtime = jiffies;
15310+ grsec_alert_fyet++;
15311+ printk(KERN_ALERT "grsec: more alerts, logging disabled for %d seconds\n", CONFIG_GRKERNSEC_FLOODTIME);
15312+ return FLOODING;
15313+ } else return FLOODING;
15314+
15315+set_fmt:
15316+ memset(buf, 0, PAGE_SIZE);
15317+ if (current->signal->curr_ip && gr_acl_is_enabled()) {
15318+ sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: (%.64s:%c:%.950s) ");
15319+ snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip), current->role->rolename, gr_roletype_to_char(), current->acl->filename);
15320+ } else if (current->signal->curr_ip) {
15321+ sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: ");
15322+ snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip));
15323+ } else if (gr_acl_is_enabled()) {
15324+ sprintf(fmt, "%s%s", loglevel, "grsec: (%.64s:%c:%.950s) ");
15325+ snprintf(buf, PAGE_SIZE - 1, fmt, current->role->rolename, gr_roletype_to_char(), current->acl->filename);
15326+ } else {
15327+ sprintf(fmt, "%s%s", loglevel, "grsec: ");
15328+ strcpy(buf, fmt);
15329+ }
15330+
15331+ return NO_FLOODING;
15332+}
15333+
15334+static void gr_log_middle(int audit, const char *msg, va_list ap)
15335+{
15336+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
15337+ unsigned int len = strlen(buf);
15338+
15339+ vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap);
15340+
15341+ return;
15342+}
15343+
15344+static void gr_log_middle_varargs(int audit, const char *msg, ...)
15345+{
15346+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
15347+ unsigned int len = strlen(buf);
15348+ va_list ap;
15349+
15350+ va_start(ap, msg);
15351+ vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap);
15352+ va_end(ap);
15353+
15354+ return;
15355+}
15356+
15357+static void gr_log_end(int audit)
15358+{
15359+ char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
15360+ unsigned int len = strlen(buf);
15361+
15362+ snprintf(buf + len, PAGE_SIZE - len - 1, DEFAULTSECMSG, DEFAULTSECARGS(current));
15363+ printk("%s\n", buf);
15364+
15365+ return;
15366+}
15367+
15368+void gr_log_varargs(int audit, const char *msg, int argtypes, ...)
15369+{
15370+ int logtype;
15371+ char *result = (audit == GR_DO_AUDIT) ? "successful" : "denied";
15372+ char *str1, *str2, *str3;
15373+ int num1, num2;
15374+ unsigned long ulong1, ulong2;
15375+ struct dentry *dentry;
15376+ struct vfsmount *mnt;
15377+ struct file *file;
15378+ struct task_struct *task;
15379+ va_list ap;
15380+
15381+ BEGIN_LOCKS(audit);
15382+ logtype = gr_log_start(audit);
15383+ if (logtype == FLOODING) {
15384+ END_LOCKS(audit);
15385+ return;
15386+ }
15387+ va_start(ap, argtypes);
15388+ switch (argtypes) {
15389+ case GR_TTYSNIFF:
15390+ task = va_arg(ap, struct task_struct *);
15391+ 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);
15392+ break;
15393+ case GR_RBAC:
15394+ dentry = va_arg(ap, struct dentry *);
15395+ mnt = va_arg(ap, struct vfsmount *);
15396+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt));
15397+ break;
15398+ case GR_RBAC_STR:
15399+ dentry = va_arg(ap, struct dentry *);
15400+ mnt = va_arg(ap, struct vfsmount *);
15401+ str1 = va_arg(ap, char *);
15402+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1);
15403+ break;
15404+ case GR_STR_RBAC:
15405+ str1 = va_arg(ap, char *);
15406+ dentry = va_arg(ap, struct dentry *);
15407+ mnt = va_arg(ap, struct vfsmount *);
15408+ gr_log_middle_varargs(audit, msg, result, str1, gr_to_filename(dentry, mnt));
15409+ break;
15410+ case GR_RBAC_MODE2:
15411+ dentry = va_arg(ap, struct dentry *);
15412+ mnt = va_arg(ap, struct vfsmount *);
15413+ str1 = va_arg(ap, char *);
15414+ str2 = va_arg(ap, char *);
15415+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2);
15416+ break;
15417+ case GR_RBAC_MODE3:
15418+ dentry = va_arg(ap, struct dentry *);
15419+ mnt = va_arg(ap, struct vfsmount *);
15420+ str1 = va_arg(ap, char *);
15421+ str2 = va_arg(ap, char *);
15422+ str3 = va_arg(ap, char *);
15423+ gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2, str3);
15424+ break;
15425+ case GR_FILENAME:
15426+ dentry = va_arg(ap, struct dentry *);
15427+ mnt = va_arg(ap, struct vfsmount *);
15428+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt));
15429+ break;
15430+ case GR_STR_FILENAME:
15431+ str1 = va_arg(ap, char *);
15432+ dentry = va_arg(ap, struct dentry *);
15433+ mnt = va_arg(ap, struct vfsmount *);
15434+ gr_log_middle_varargs(audit, msg, str1, gr_to_filename(dentry, mnt));
15435+ break;
15436+ case GR_FILENAME_STR:
15437+ dentry = va_arg(ap, struct dentry *);
15438+ mnt = va_arg(ap, struct vfsmount *);
15439+ str1 = va_arg(ap, char *);
15440+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), str1);
15441+ break;
15442+ case GR_FILENAME_TWO_INT:
15443+ dentry = va_arg(ap, struct dentry *);
15444+ mnt = va_arg(ap, struct vfsmount *);
15445+ num1 = va_arg(ap, int);
15446+ num2 = va_arg(ap, int);
15447+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2);
15448+ break;
15449+ case GR_FILENAME_TWO_INT_STR:
15450+ dentry = va_arg(ap, struct dentry *);
15451+ mnt = va_arg(ap, struct vfsmount *);
15452+ num1 = va_arg(ap, int);
15453+ num2 = va_arg(ap, int);
15454+ str1 = va_arg(ap, char *);
15455+ gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2, str1);
15456+ break;
15457+ case GR_TEXTREL:
15458+ file = va_arg(ap, struct file *);
15459+ ulong1 = va_arg(ap, unsigned long);
15460+ ulong2 = va_arg(ap, unsigned long);
15461+ gr_log_middle_varargs(audit, msg, file ? gr_to_filename(file->f_dentry, file->f_vfsmnt) : "<anonymous mapping>", ulong1, ulong2);
15462+ break;
15463+ case GR_PTRACE:
15464+ task = va_arg(ap, struct task_struct *);
15465+ 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);
15466+ break;
15467+ case GR_RESOURCE:
15468+ task = va_arg(ap, struct task_struct *);
15469+ ulong1 = va_arg(ap, unsigned long);
15470+ str1 = va_arg(ap, char *);
15471+ ulong2 = va_arg(ap, unsigned long);
15472+ 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);
15473+ break;
15474+ case GR_CAP:
15475+ task = va_arg(ap, struct task_struct *);
15476+ str1 = va_arg(ap, char *);
15477+ 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);
15478+ break;
15479+ case GR_SIG:
15480+ task = va_arg(ap, struct task_struct *);
15481+ num1 = va_arg(ap, int);
15482+ 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);
15483+ break;
15484+ case GR_CRASH1:
15485+ task = va_arg(ap, struct task_struct *);
15486+ ulong1 = va_arg(ap, unsigned long);
15487+ 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);
15488+ break;
15489+ case GR_CRASH2:
15490+ task = va_arg(ap, struct task_struct *);
15491+ ulong1 = va_arg(ap, unsigned long);
15492+ 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);
15493+ break;
15494+ case GR_PSACCT:
15495+ {
15496+ unsigned int wday, cday;
15497+ __u8 whr, chr;
15498+ __u8 wmin, cmin;
15499+ __u8 wsec, csec;
15500+ char cur_tty[64] = { 0 };
15501+ char parent_tty[64] = { 0 };
15502+
15503+ task = va_arg(ap, struct task_struct *);
15504+ wday = va_arg(ap, unsigned int);
15505+ cday = va_arg(ap, unsigned int);
15506+ whr = va_arg(ap, int);
15507+ chr = va_arg(ap, int);
15508+ wmin = va_arg(ap, int);
15509+ cmin = va_arg(ap, int);
15510+ wsec = va_arg(ap, int);
15511+ csec = va_arg(ap, int);
15512+ ulong1 = va_arg(ap, unsigned long);
15513+
15514+ 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);
15515+ }
15516+ break;
15517+ default:
15518+ gr_log_middle(audit, msg, ap);
15519+ }
15520+ va_end(ap);
15521+ gr_log_end(audit);
15522+ END_LOCKS(audit);
15523+}
15524diff -urNp linux-2.6.16.12/grsecurity/grsec_mem.c linux-2.6.16.12/grsecurity/grsec_mem.c
15525--- linux-2.6.16.12/grsecurity/grsec_mem.c 1969-12-31 19:00:00.000000000 -0500
15526+++ linux-2.6.16.12/grsecurity/grsec_mem.c 2006-05-01 20:17:34.000000000 -0400
15527@@ -0,0 +1,71 @@
15528+#include <linux/kernel.h>
15529+#include <linux/sched.h>
15530+#include <linux/mm.h>
15531+#include <linux/mman.h>
15532+#include <linux/grinternal.h>
15533+
15534+void
15535+gr_handle_ioperm(void)
15536+{
15537+ gr_log_noargs(GR_DONT_AUDIT, GR_IOPERM_MSG);
15538+ return;
15539+}
15540+
15541+void
15542+gr_handle_iopl(void)
15543+{
15544+ gr_log_noargs(GR_DONT_AUDIT, GR_IOPL_MSG);
15545+ return;
15546+}
15547+
15548+void
15549+gr_handle_mem_write(void)
15550+{
15551+ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_WRITE_MSG);
15552+ return;
15553+}
15554+
15555+void
15556+gr_handle_kmem_write(void)
15557+{
15558+ gr_log_noargs(GR_DONT_AUDIT, GR_KMEM_MSG);
15559+ return;
15560+}
15561+
15562+void
15563+gr_handle_open_port(void)
15564+{
15565+ gr_log_noargs(GR_DONT_AUDIT, GR_PORT_OPEN_MSG);
15566+ return;
15567+}
15568+
15569+int
15570+gr_handle_mem_mmap(const unsigned long offset, struct vm_area_struct *vma)
15571+{
15572+ unsigned long start, end;
15573+
15574+ start = offset;
15575+ end = start + vma->vm_end - vma->vm_start;
15576+
15577+ if (start > end) {
15578+ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_MMAP_MSG);
15579+ return -EPERM;
15580+ }
15581+
15582+ /* allowed ranges : ISA I/O BIOS */
15583+ if ((start >= __pa(high_memory))
15584+#ifdef CONFIG_X86
15585+ || (start >= 0x000a0000 && end <= 0x00100000)
15586+ || (start >= 0x00000000 && end <= 0x00001000)
15587+#endif
15588+ )
15589+ return 0;
15590+
15591+ if (vma->vm_flags & VM_WRITE) {
15592+ gr_log_noargs(GR_DONT_AUDIT, GR_MEM_MMAP_MSG);
15593+ return -EPERM;
15594+ } else
15595+ vma->vm_flags &= ~VM_MAYWRITE;
15596+
15597+ return 0;
15598+}
15599diff -urNp linux-2.6.16.12/grsecurity/grsec_mount.c linux-2.6.16.12/grsecurity/grsec_mount.c
15600--- linux-2.6.16.12/grsecurity/grsec_mount.c 1969-12-31 19:00:00.000000000 -0500
15601+++ linux-2.6.16.12/grsecurity/grsec_mount.c 2006-05-01 20:17:34.000000000 -0400
15602@@ -0,0 +1,34 @@
15603+#include <linux/kernel.h>
15604+#include <linux/sched.h>
15605+#include <linux/grsecurity.h>
15606+#include <linux/grinternal.h>
15607+
15608+void
15609+gr_log_remount(const char *devname, const int retval)
15610+{
15611+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
15612+ if (grsec_enable_mount && (retval >= 0))
15613+ gr_log_str(GR_DO_AUDIT, GR_REMOUNT_AUDIT_MSG, devname ? devname : "none");
15614+#endif
15615+ return;
15616+}
15617+
15618+void
15619+gr_log_unmount(const char *devname, const int retval)
15620+{
15621+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
15622+ if (grsec_enable_mount && (retval >= 0))
15623+ gr_log_str(GR_DO_AUDIT, GR_UNMOUNT_AUDIT_MSG, devname ? devname : "none");
15624+#endif
15625+ return;
15626+}
15627+
15628+void
15629+gr_log_mount(const char *from, const char *to, const int retval)
15630+{
15631+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
15632+ if (grsec_enable_mount && (retval >= 0))
15633+ gr_log_str_str(GR_DO_AUDIT, GR_MOUNT_AUDIT_MSG, from, to);
15634+#endif
15635+ return;
15636+}
15637diff -urNp linux-2.6.16.12/grsecurity/grsec_rand.c linux-2.6.16.12/grsecurity/grsec_rand.c
15638--- linux-2.6.16.12/grsecurity/grsec_rand.c 1969-12-31 19:00:00.000000000 -0500
15639+++ linux-2.6.16.12/grsecurity/grsec_rand.c 2006-05-01 20:17:34.000000000 -0400
15640@@ -0,0 +1,26 @@
15641+#include <linux/kernel.h>
15642+#include <linux/sched.h>
15643+#include <linux/smp_lock.h>
15644+#include <linux/grsecurity.h>
15645+#include <linux/grinternal.h>
15646+
15647+extern int pid_max;
15648+
15649+int
15650+gr_random_pid(void)
15651+{
15652+#ifdef CONFIG_GRKERNSEC_RANDPID
15653+ int pid;
15654+
15655+ if (grsec_enable_randpid && current->fs->root) {
15656+ /* return a pid in the range 1 ... pid_max - 1
15657+ optimize this so we don't have to do a real division
15658+ */
15659+ pid = 1 + (get_random_long() % pid_max);
15660+ if (pid == pid_max)
15661+ pid = pid_max - 1;
15662+ return pid;
15663+ }
15664+#endif
15665+ return 0;
15666+}
15667diff -urNp linux-2.6.16.12/grsecurity/grsec_sig.c linux-2.6.16.12/grsecurity/grsec_sig.c
15668--- linux-2.6.16.12/grsecurity/grsec_sig.c 1969-12-31 19:00:00.000000000 -0500
15669+++ linux-2.6.16.12/grsecurity/grsec_sig.c 2006-05-01 20:17:34.000000000 -0400
15670@@ -0,0 +1,59 @@
15671+#include <linux/kernel.h>
15672+#include <linux/sched.h>
15673+#include <linux/grsecurity.h>
15674+#include <linux/grinternal.h>
15675+
15676+void
15677+gr_log_signal(const int sig, const struct task_struct *t)
15678+{
15679+#ifdef CONFIG_GRKERNSEC_SIGNAL
15680+ if (grsec_enable_signal && ((sig == SIGSEGV) || (sig == SIGILL) ||
15681+ (sig == SIGABRT) || (sig == SIGBUS))) {
15682+ if (t->pid == current->pid) {
15683+ gr_log_int(GR_DONT_AUDIT_GOOD, GR_UNISIGLOG_MSG, sig);
15684+ } else {
15685+ gr_log_sig(GR_DONT_AUDIT_GOOD, GR_DUALSIGLOG_MSG, t, sig);
15686+ }
15687+ }
15688+#endif
15689+ return;
15690+}
15691+
15692+int
15693+gr_handle_signal(const struct task_struct *p, const int sig)
15694+{
15695+#ifdef CONFIG_GRKERNSEC
15696+ if (current->pid > 1 && gr_check_protected_task(p)) {
15697+ gr_log_sig(GR_DONT_AUDIT, GR_SIG_ACL_MSG, p, sig);
15698+ return -EPERM;
15699+ } else if (gr_pid_is_chrooted((struct task_struct *)p)) {
15700+ return -EPERM;
15701+ }
15702+#endif
15703+ return 0;
15704+}
15705+
15706+void gr_handle_brute_attach(struct task_struct *p)
15707+{
15708+#ifdef CONFIG_GRKERNSEC_BRUTE
15709+ read_lock(&tasklist_lock);
15710+ read_lock(&grsec_exec_file_lock);
15711+ if (p->parent && p->parent->exec_file == p->exec_file)
15712+ p->parent->brute = 1;
15713+ read_unlock(&grsec_exec_file_lock);
15714+ read_unlock(&tasklist_lock);
15715+#endif
15716+ return;
15717+}
15718+
15719+void gr_handle_brute_check(void)
15720+{
15721+#ifdef CONFIG_GRKERNSEC_BRUTE
15722+ if (current->brute) {
15723+ set_current_state(TASK_UNINTERRUPTIBLE);
15724+ schedule_timeout(30 * HZ);
15725+ }
15726+#endif
15727+ return;
15728+}
15729+
15730diff -urNp linux-2.6.16.12/grsecurity/grsec_sock.c linux-2.6.16.12/grsecurity/grsec_sock.c
15731--- linux-2.6.16.12/grsecurity/grsec_sock.c 1969-12-31 19:00:00.000000000 -0500
15732+++ linux-2.6.16.12/grsecurity/grsec_sock.c 2006-05-01 20:17:34.000000000 -0400
15733@@ -0,0 +1,263 @@
15734+#include <linux/kernel.h>
15735+#include <linux/module.h>
15736+#include <linux/sched.h>
15737+#include <linux/file.h>
15738+#include <linux/net.h>
15739+#include <linux/in.h>
15740+#include <linux/ip.h>
15741+#include <net/sock.h>
15742+#include <net/inet_sock.h>
15743+#include <linux/grsecurity.h>
15744+#include <linux/grinternal.h>
15745+#include <linux/gracl.h>
15746+
15747+#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE)
15748+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
15749+EXPORT_SYMBOL(udp_v4_lookup);
15750+#endif
15751+
15752+EXPORT_SYMBOL(gr_cap_rtnetlink);
15753+
15754+extern int gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb);
15755+extern int gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr);
15756+
15757+EXPORT_SYMBOL(gr_search_udp_recvmsg);
15758+EXPORT_SYMBOL(gr_search_udp_sendmsg);
15759+
15760+#ifdef CONFIG_UNIX_MODULE
15761+EXPORT_SYMBOL(gr_acl_handle_unix);
15762+EXPORT_SYMBOL(gr_acl_handle_mknod);
15763+EXPORT_SYMBOL(gr_handle_chroot_unix);
15764+EXPORT_SYMBOL(gr_handle_create);
15765+#endif
15766+
15767+#ifdef CONFIG_GRKERNSEC
15768+#define gr_conn_table_size 32749
15769+struct conn_table_entry {
15770+ struct conn_table_entry *next;
15771+ struct signal_struct *sig;
15772+};
15773+
15774+struct conn_table_entry *gr_conn_table[gr_conn_table_size];
15775+spinlock_t gr_conn_table_lock = SPIN_LOCK_UNLOCKED;
15776+
15777+extern const char * gr_socktype_to_name(unsigned char type);
15778+extern const char * gr_proto_to_name(unsigned char proto);
15779+
15780+static __inline__ int
15781+conn_hash(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, unsigned int size)
15782+{
15783+ return ((daddr + saddr + (sport << 8) + (dport << 16)) % size);
15784+}
15785+
15786+static __inline__ int
15787+conn_match(const struct signal_struct *sig, __u32 saddr, __u32 daddr,
15788+ __u16 sport, __u16 dport)
15789+{
15790+ if (unlikely(sig->gr_saddr == saddr && sig->gr_daddr == daddr &&
15791+ sig->gr_sport == sport && sig->gr_dport == dport))
15792+ return 1;
15793+ else
15794+ return 0;
15795+}
15796+
15797+static void gr_add_to_task_ip_table_nolock(struct signal_struct *sig, struct conn_table_entry *newent)
15798+{
15799+ struct conn_table_entry **match;
15800+ unsigned int index;
15801+
15802+ index = conn_hash(sig->gr_saddr, sig->gr_daddr,
15803+ sig->gr_sport, sig->gr_dport,
15804+ gr_conn_table_size);
15805+
15806+ newent->sig = sig;
15807+
15808+ match = &gr_conn_table[index];
15809+ newent->next = *match;
15810+ *match = newent;
15811+
15812+ return;
15813+}
15814+
15815+static void gr_del_task_from_ip_table_nolock(struct signal_struct *sig)
15816+{
15817+ struct conn_table_entry *match, *last = NULL;
15818+ unsigned int index;
15819+
15820+ index = conn_hash(sig->gr_saddr, sig->gr_daddr,
15821+ sig->gr_sport, sig->gr_dport,
15822+ gr_conn_table_size);
15823+
15824+ match = gr_conn_table[index];
15825+ while (match && !conn_match(match->sig,
15826+ sig->gr_saddr, sig->gr_daddr, sig->gr_sport,
15827+ sig->gr_dport)) {
15828+ last = match;
15829+ match = match->next;
15830+ }
15831+
15832+ if (match) {
15833+ if (last)
15834+ last->next = match->next;
15835+ else
15836+ gr_conn_table[index] = NULL;
15837+ kfree(match);
15838+ }
15839+
15840+ return;
15841+}
15842+
15843+static struct signal_struct * gr_lookup_task_ip_table(__u32 saddr, __u32 daddr,
15844+ __u16 sport, __u16 dport)
15845+{
15846+ struct conn_table_entry *match;
15847+ unsigned int index;
15848+
15849+ index = conn_hash(saddr, daddr, sport, dport, gr_conn_table_size);
15850+
15851+ match = gr_conn_table[index];
15852+ while (match && !conn_match(match->sig, saddr, daddr, sport, dport))
15853+ match = match->next;
15854+
15855+ if (match)
15856+ return match->sig;
15857+ else
15858+ return NULL;
15859+}
15860+
15861+#endif
15862+
15863+void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet)
15864+{
15865+#ifdef CONFIG_GRKERNSEC
15866+ struct signal_struct *sig = task->signal;
15867+ struct conn_table_entry *newent;
15868+
15869+ newent = kmalloc(sizeof(struct conn_table_entry), GFP_ATOMIC);
15870+ if (newent == NULL)
15871+ return;
15872+ /* no bh lock needed since we are called with bh disabled */
15873+ spin_lock(&gr_conn_table_lock);
15874+ gr_del_task_from_ip_table_nolock(sig);
15875+ sig->gr_saddr = inet->rcv_saddr;
15876+ sig->gr_daddr = inet->daddr;
15877+ sig->gr_sport = inet->sport;
15878+ sig->gr_dport = inet->dport;
15879+ gr_add_to_task_ip_table_nolock(sig, newent);
15880+ spin_unlock(&gr_conn_table_lock);
15881+#endif
15882+ return;
15883+}
15884+
15885+void gr_del_task_from_ip_table(struct task_struct *task)
15886+{
15887+#ifdef CONFIG_GRKERNSEC
dbf6e0c5 15888+ spin_lock(&gr_conn_table_lock);
89675291 15889+ gr_del_task_from_ip_table_nolock(task->signal);
dbf6e0c5 15890+ spin_unlock(&gr_conn_table_lock);
89675291 15891+#endif
15892+ return;
15893+}
15894+
15895+void
15896+gr_attach_curr_ip(const struct sock *sk)
15897+{
15898+#ifdef CONFIG_GRKERNSEC
15899+ struct signal_struct *p, *set;
15900+ const struct inet_sock *inet = inet_sk(sk);
15901+
15902+ if (unlikely(sk->sk_protocol != IPPROTO_TCP))
15903+ return;
15904+
15905+ set = current->signal;
15906+
15907+ spin_lock_bh(&gr_conn_table_lock);
15908+ p = gr_lookup_task_ip_table(inet->daddr, inet->rcv_saddr,
15909+ inet->dport, inet->sport);
15910+ if (unlikely(p != NULL)) {
15911+ set->curr_ip = p->curr_ip;
15912+ set->used_accept = 1;
15913+ gr_del_task_from_ip_table_nolock(p);
15914+ spin_unlock_bh(&gr_conn_table_lock);
15915+ return;
15916+ }
15917+ spin_unlock_bh(&gr_conn_table_lock);
15918+
15919+ set->curr_ip = inet->daddr;
15920+ set->used_accept = 1;
15921+#endif
15922+ return;
15923+}
15924+
15925+int
15926+gr_handle_sock_all(const int family, const int type, const int protocol)
15927+{
15928+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
15929+ if (grsec_enable_socket_all && in_group_p(grsec_socket_all_gid) &&
15930+ (family != AF_UNIX) && (family != AF_LOCAL)) {
15931+ gr_log_int_str2(GR_DONT_AUDIT, GR_SOCK2_MSG, family, gr_socktype_to_name(type), gr_proto_to_name(protocol));
15932+ return -EACCES;
15933+ }
15934+#endif
15935+ return 0;
15936+}
15937+
15938+int
15939+gr_handle_sock_server(const struct sockaddr *sck)
15940+{
15941+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
15942+ if (grsec_enable_socket_server &&
15943+ in_group_p(grsec_socket_server_gid) &&
15944+ sck && (sck->sa_family != AF_UNIX) &&
15945+ (sck->sa_family != AF_LOCAL)) {
15946+ gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
15947+ return -EACCES;
15948+ }
15949+#endif
15950+ return 0;
15951+}
15952+
15953+int
15954+gr_handle_sock_server_other(const struct sock *sck)
15955+{
15956+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
15957+ if (grsec_enable_socket_server &&
15958+ in_group_p(grsec_socket_server_gid) &&
15959+ sck && (sck->sk_family != AF_UNIX) &&
15960+ (sck->sk_family != AF_LOCAL)) {
15961+ gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
15962+ return -EACCES;
15963+ }
15964+#endif
15965+ return 0;
15966+}
15967+
15968+int
15969+gr_handle_sock_client(const struct sockaddr *sck)
15970+{
15971+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
15972+ if (grsec_enable_socket_client && in_group_p(grsec_socket_client_gid) &&
15973+ sck && (sck->sa_family != AF_UNIX) &&
15974+ (sck->sa_family != AF_LOCAL)) {
15975+ gr_log_noargs(GR_DONT_AUDIT, GR_CONNECT_MSG);
15976+ return -EACCES;
15977+ }
15978+#endif
15979+ return 0;
15980+}
15981+
15982+__u32
15983+gr_cap_rtnetlink(void)
15984+{
15985+#ifdef CONFIG_GRKERNSEC
15986+ if (!gr_acl_is_enabled())
15987+ return current->cap_effective;
15988+ else if (cap_raised(current->cap_effective, CAP_NET_ADMIN) &&
15989+ gr_task_is_capable(current, CAP_NET_ADMIN))
15990+ return current->cap_effective;
15991+ else
15992+ return 0;
15993+#else
15994+ return current->cap_effective;
15995+#endif
15996+}
15997diff -urNp linux-2.6.16.12/grsecurity/grsec_sysctl.c linux-2.6.16.12/grsecurity/grsec_sysctl.c
15998--- linux-2.6.16.12/grsecurity/grsec_sysctl.c 1969-12-31 19:00:00.000000000 -0500
15999+++ linux-2.6.16.12/grsecurity/grsec_sysctl.c 2006-05-01 20:17:34.000000000 -0400
16000@@ -0,0 +1,456 @@
16001+#include <linux/kernel.h>
16002+#include <linux/sched.h>
16003+#include <linux/sysctl.h>
16004+#include <linux/grsecurity.h>
16005+#include <linux/grinternal.h>
16006+
16007+#ifdef CONFIG_GRKERNSEC_MODSTOP
16008+int grsec_modstop;
16009+#endif
16010+
16011+int
16012+gr_handle_sysctl_mod(const char *dirname, const char *name, const int op)
16013+{
16014+#ifdef CONFIG_GRKERNSEC_SYSCTL
16015+ if (!strcmp(dirname, "grsecurity") && grsec_lock && (op & 002)) {
16016+ gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name);
16017+ return -EACCES;
16018+ }
16019+#endif
16020+#ifdef CONFIG_GRKERNSEC_MODSTOP
16021+ if (!strcmp(dirname, "grsecurity") && !strcmp(name, "disable_modules") &&
16022+ grsec_modstop && (op & 002)) {
16023+ gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name);
16024+ return -EACCES;
16025+ }
16026+#endif
16027+ return 0;
16028+}
16029+
16030+#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP)
16031+enum {GS_LINK=1, GS_FIFO, GS_EXECVE, GS_EXECLOG, GS_SIGNAL,
16032+GS_FORKFAIL, GS_TIME, GS_CHROOT_SHMAT, GS_CHROOT_UNIX, GS_CHROOT_MNT,
16033+GS_CHROOT_FCHDIR, GS_CHROOT_DBL, GS_CHROOT_PVT, GS_CHROOT_CD, GS_CHROOT_CM,
16034+GS_CHROOT_MK, GS_CHROOT_NI, GS_CHROOT_EXECLOG, GS_CHROOT_CAPS,
16035+GS_CHROOT_SYSCTL, GS_TPE, GS_TPE_GID, GS_TPE_ALL, GS_SIDCAPS,
16036+GS_RANDPID, GS_SOCKET_ALL, GS_SOCKET_ALL_GID, GS_SOCKET_CLIENT,
16037+GS_SOCKET_CLIENT_GID, GS_SOCKET_SERVER, GS_SOCKET_SERVER_GID,
16038+GS_GROUP, GS_GID, GS_ACHDIR, GS_AMOUNT, GS_AIPC, GS_DMSG,
16039+GS_TEXTREL, GS_FINDTASK, GS_SHM, GS_LOCK, GS_MODSTOP};
16040+
16041+
16042+ctl_table grsecurity_table[] = {
16043+#ifdef CONFIG_GRKERNSEC_SYSCTL
16044+#ifdef CONFIG_GRKERNSEC_LINK
16045+ {
16046+ .ctl_name = GS_LINK,
16047+ .procname = "linking_restrictions",
16048+ .data = &grsec_enable_link,
16049+ .maxlen = sizeof(int),
16050+ .mode = 0600,
16051+ .proc_handler = &proc_dointvec,
16052+ },
16053+#endif
16054+#ifdef CONFIG_GRKERNSEC_FIFO
16055+ {
16056+ .ctl_name = GS_FIFO,
16057+ .procname = "fifo_restrictions",
16058+ .data = &grsec_enable_fifo,
16059+ .maxlen = sizeof(int),
16060+ .mode = 0600,
16061+ .proc_handler = &proc_dointvec,
16062+ },
16063+#endif
16064+#ifdef CONFIG_GRKERNSEC_EXECVE
16065+ {
16066+ .ctl_name = GS_EXECVE,
16067+ .procname = "execve_limiting",
16068+ .data = &grsec_enable_execve,
16069+ .maxlen = sizeof(int),
16070+ .mode = 0600,
16071+ .proc_handler = &proc_dointvec,
16072+ },
16073+#endif
16074+#ifdef CONFIG_GRKERNSEC_EXECLOG
16075+ {
16076+ .ctl_name = GS_EXECLOG,
16077+ .procname = "exec_logging",
16078+ .data = &grsec_enable_execlog,
16079+ .maxlen = sizeof(int),
16080+ .mode = 0600,
16081+ .proc_handler = &proc_dointvec,
16082+ },
16083+#endif
16084+#ifdef CONFIG_GRKERNSEC_SIGNAL
16085+ {
16086+ .ctl_name = GS_SIGNAL,
16087+ .procname = "signal_logging",
16088+ .data = &grsec_enable_signal,
16089+ .maxlen = sizeof(int),
16090+ .mode = 0600,
16091+ .proc_handler = &proc_dointvec,
16092+ },
16093+#endif
16094+#ifdef CONFIG_GRKERNSEC_FORKFAIL
16095+ {
16096+ .ctl_name = GS_FORKFAIL,
16097+ .procname = "forkfail_logging",
16098+ .data = &grsec_enable_forkfail,
16099+ .maxlen = sizeof(int),
16100+ .mode = 0600,
16101+ .proc_handler = &proc_dointvec,
16102+ },
16103+#endif
16104+#ifdef CONFIG_GRKERNSEC_TIME
16105+ {
16106+ .ctl_name = GS_TIME,
16107+ .procname = "timechange_logging",
16108+ .data = &grsec_enable_time,
16109+ .maxlen = sizeof(int),
16110+ .mode = 0600,
16111+ .proc_handler = &proc_dointvec,
16112+ },
16113+#endif
16114+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
16115+ {
16116+ .ctl_name = GS_CHROOT_SHMAT,
16117+ .procname = "chroot_deny_shmat",
16118+ .data = &grsec_enable_chroot_shmat,
16119+ .maxlen = sizeof(int),
16120+ .mode = 0600,
16121+ .proc_handler = &proc_dointvec,
16122+ },
16123+#endif
16124+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
16125+ {
16126+ .ctl_name = GS_CHROOT_UNIX,
16127+ .procname = "chroot_deny_unix",
16128+ .data = &grsec_enable_chroot_unix,
16129+ .maxlen = sizeof(int),
16130+ .mode = 0600,
16131+ .proc_handler = &proc_dointvec,
16132+ },
16133+#endif
16134+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
16135+ {
16136+ .ctl_name = GS_CHROOT_MNT,
16137+ .procname = "chroot_deny_mount",
16138+ .data = &grsec_enable_chroot_mount,
16139+ .maxlen = sizeof(int),
16140+ .mode = 0600,
16141+ .proc_handler = &proc_dointvec,
16142+ },
16143+#endif
16144+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
16145+ {
16146+ .ctl_name = GS_CHROOT_FCHDIR,
16147+ .procname = "chroot_deny_fchdir",
16148+ .data = &grsec_enable_chroot_fchdir,
16149+ .maxlen = sizeof(int),
16150+ .mode = 0600,
16151+ .proc_handler = &proc_dointvec,
16152+ },
16153+#endif
16154+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
16155+ {
16156+ .ctl_name = GS_CHROOT_DBL,
16157+ .procname = "chroot_deny_chroot",
16158+ .data = &grsec_enable_chroot_double,
16159+ .maxlen = sizeof(int),
16160+ .mode = 0600,
16161+ .proc_handler = &proc_dointvec,
16162+ },
16163+#endif
16164+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
16165+ {
16166+ .ctl_name = GS_CHROOT_PVT,
16167+ .procname = "chroot_deny_pivot",
16168+ .data = &grsec_enable_chroot_pivot,
16169+ .maxlen = sizeof(int),
16170+ .mode = 0600,
16171+ .proc_handler = &proc_dointvec,
16172+ },
16173+#endif
16174+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
16175+ {
16176+ .ctl_name = GS_CHROOT_CD,
16177+ .procname = "chroot_enforce_chdir",
16178+ .data = &grsec_enable_chroot_chdir,
16179+ .maxlen = sizeof(int),
16180+ .mode = 0600,
16181+ .proc_handler = &proc_dointvec,
16182+ },
16183+#endif
16184+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
16185+ {
16186+ .ctl_name = GS_CHROOT_CM,
16187+ .procname = "chroot_deny_chmod",
16188+ .data = &grsec_enable_chroot_chmod,
16189+ .maxlen = sizeof(int),
16190+ .mode = 0600,
16191+ .proc_handler = &proc_dointvec,
16192+ },
16193+#endif
16194+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
16195+ {
16196+ .ctl_name = GS_CHROOT_MK,
16197+ .procname = "chroot_deny_mknod",
16198+ .data = &grsec_enable_chroot_mknod,
16199+ .maxlen = sizeof(int),
16200+ .mode = 0600,
16201+ .proc_handler = &proc_dointvec,
16202+ },
16203+#endif
16204+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
16205+ {
16206+ .ctl_name = GS_CHROOT_NI,
16207+ .procname = "chroot_restrict_nice",
16208+ .data = &grsec_enable_chroot_nice,
16209+ .maxlen = sizeof(int),
16210+ .mode = 0600,
16211+ .proc_handler = &proc_dointvec,
16212+ },
16213+#endif
16214+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
16215+ {
16216+ .ctl_name = GS_CHROOT_EXECLOG,
16217+ .procname = "chroot_execlog",
16218+ .data = &grsec_enable_chroot_execlog,
16219+ .maxlen = sizeof(int),
16220+ .mode = 0600,
16221+ .proc_handler = &proc_dointvec,
16222+ },
16223+#endif
16224+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
16225+ {
16226+ .ctl_name = GS_CHROOT_CAPS,
16227+ .procname = "chroot_caps",
16228+ .data = &grsec_enable_chroot_caps,
16229+ .maxlen = sizeof(int),
16230+ .mode = 0600,
16231+ .proc_handler = &proc_dointvec,
16232+ },
16233+#endif
16234+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
16235+ {
16236+ .ctl_name = GS_CHROOT_SYSCTL,
16237+ .procname = "chroot_deny_sysctl",
16238+ .data = &grsec_enable_chroot_sysctl,
16239+ .maxlen = sizeof(int),
16240+ .mode = 0600,
16241+ .proc_handler = &proc_dointvec,
16242+ },
16243+#endif
16244+#ifdef CONFIG_GRKERNSEC_TPE
16245+ {
16246+ .ctl_name = GS_TPE,
16247+ .procname = "tpe",
16248+ .data = &grsec_enable_tpe,
16249+ .maxlen = sizeof(int),
16250+ .mode = 0600,
16251+ .proc_handler = &proc_dointvec,
16252+ },
16253+ {
16254+ .ctl_name = GS_TPE_GID,
16255+ .procname = "tpe_gid",
16256+ .data = &grsec_tpe_gid,
16257+ .maxlen = sizeof(int),
16258+ .mode = 0600,
16259+ .proc_handler = &proc_dointvec,
16260+ },
16261+#endif
16262+#ifdef CONFIG_GRKERNSEC_TPE_ALL
16263+ {
16264+ .ctl_name = GS_TPE_ALL,
16265+ .procname = "tpe_restrict_all",
16266+ .data = &grsec_enable_tpe_all,
16267+ .maxlen = sizeof(int),
16268+ .mode = 0600,
16269+ .proc_handler = &proc_dointvec,
16270+ },
16271+#endif
16272+#ifdef CONFIG_GRKERNSEC_RANDPID
16273+ {
16274+ .ctl_name = GS_RANDPID,
16275+ .procname = "rand_pids",
16276+ .data = &grsec_enable_randpid,
16277+ .maxlen = sizeof(int),
16278+ .mode = 0600,
16279+ .proc_handler = &proc_dointvec,
16280+ },
16281+#endif
16282+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
16283+ {
16284+ .ctl_name = GS_SOCKET_ALL,
16285+ .procname = "socket_all",
16286+ .data = &grsec_enable_socket_all,
16287+ .maxlen = sizeof(int),
16288+ .mode = 0600,
16289+ .proc_handler = &proc_dointvec,
16290+ },
16291+ {
16292+ .ctl_name = GS_SOCKET_ALL_GID,
16293+ .procname = "socket_all_gid",
16294+ .data = &grsec_socket_all_gid,
16295+ .maxlen = sizeof(int),
16296+ .mode = 0600,
16297+ .proc_handler = &proc_dointvec,
16298+ },
16299+#endif
16300+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
16301+ {
16302+ .ctl_name = GS_SOCKET_CLIENT,
16303+ .procname = "socket_client",
16304+ .data = &grsec_enable_socket_client,
16305+ .maxlen = sizeof(int),
16306+ .mode = 0600,
16307+ .proc_handler = &proc_dointvec,
16308+ },
16309+ {
16310+ .ctl_name = GS_SOCKET_CLIENT_GID,
16311+ .procname = "socket_client_gid",
16312+ .data = &grsec_socket_client_gid,
16313+ .maxlen = sizeof(int),
16314+ .mode = 0600,
16315+ .proc_handler = &proc_dointvec,
16316+ },
16317+#endif
16318+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
16319+ {
16320+ .ctl_name = GS_SOCKET_SERVER,
16321+ .procname = "socket_server",
16322+ .data = &grsec_enable_socket_server,
16323+ .maxlen = sizeof(int),
16324+ .mode = 0600,
16325+ .proc_handler = &proc_dointvec,
16326+ },
16327+ {
16328+ .ctl_name = GS_SOCKET_SERVER_GID,
16329+ .procname = "socket_server_gid",
16330+ .data = &grsec_socket_server_gid,
16331+ .maxlen = sizeof(int),
16332+ .mode = 0600,
16333+ .proc_handler = &proc_dointvec,
16334+ },
16335+#endif
16336+#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
16337+ {
16338+ .ctl_name = GS_GROUP,
16339+ .procname = "audit_group",
16340+ .data = &grsec_enable_group,
16341+ .maxlen = sizeof(int),
16342+ .mode = 0600,
16343+ .proc_handler = &proc_dointvec,
16344+ },
16345+ {
16346+ .ctl_name = GS_GID,
16347+ .procname = "audit_gid",
16348+ .data = &grsec_audit_gid,
16349+ .maxlen = sizeof(int),
16350+ .mode = 0600,
16351+ .proc_handler = &proc_dointvec,
16352+ },
16353+#endif
16354+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
16355+ {
16356+ .ctl_name = GS_ACHDIR,
16357+ .procname = "audit_chdir",
16358+ .data = &grsec_enable_chdir,
16359+ .maxlen = sizeof(int),
16360+ .mode = 0600,
16361+ .proc_handler = &proc_dointvec,
16362+ },
16363+#endif
16364+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
16365+ {
16366+ .ctl_name = GS_AMOUNT,
16367+ .procname = "audit_mount",
16368+ .data = &grsec_enable_mount,
16369+ .maxlen = sizeof(int),
16370+ .mode = 0600,
16371+ .proc_handler = &proc_dointvec,
16372+ },
16373+#endif
16374+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
16375+ {
16376+ .ctl_name = GS_AIPC,
16377+ .procname = "audit_ipc",
16378+ .data = &grsec_enable_audit_ipc,
16379+ .maxlen = sizeof(int),
16380+ .mode = 0600,
16381+ .proc_handler = &proc_dointvec,
16382+ },
16383+#endif
16384+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
16385+ {
16386+ .ctl_name = GS_TEXTREL,
16387+ .procname = "audit_textrel",
16388+ .data = &grsec_enable_audit_textrel,
16389+ .maxlen = sizeof(int),
16390+ .mode = 0600,
16391+ .proc_handler = &proc_dointvec,
16392+ },
16393+#endif
16394+#ifdef CONFIG_GRKERNSEC_DMESG
16395+ {
16396+ .ctl_name = GS_DMSG,
16397+ .procname = "dmesg",
16398+ .data = &grsec_enable_dmesg,
16399+ .maxlen = sizeof(int),
16400+ .mode = 0600,
16401+ .proc_handler = &proc_dointvec,
16402+ },
16403+#endif
16404+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
16405+ {
16406+ .ctl_name = GS_FINDTASK,
16407+ .procname = "chroot_findtask",
16408+ .data = &grsec_enable_chroot_findtask,
16409+ .maxlen = sizeof(int),
16410+ .mode = 0600,
16411+ .proc_handler = &proc_dointvec,
16412+ },
16413+#endif
16414+#ifdef CONFIG_GRKERNSEC_SHM
16415+ {
16416+ .ctl_name = GS_SHM,
16417+ .procname = "destroy_unused_shm",
16418+ .data = &grsec_enable_shm,
16419+ .maxlen = sizeof(int),
16420+ .mode = 0600,
16421+ .proc_handler = &proc_dointvec,
16422+ },
16423+#endif
16424+ {
16425+ .ctl_name = GS_LOCK,
16426+ .procname = "grsec_lock",
16427+ .data = &grsec_lock,
16428+ .maxlen = sizeof(int),
16429+ .mode = 0600,
16430+ .proc_handler = &proc_dointvec,
16431+ },
16432+#endif
16433+#ifdef CONFIG_GRKERNSEC_MODSTOP
16434+ {
16435+ .ctl_name = GS_MODSTOP,
16436+ .procname = "disable_modules",
16437+ .data = &grsec_modstop,
16438+ .maxlen = sizeof(int),
16439+ .mode = 0600,
16440+ .proc_handler = &proc_dointvec,
16441+ },
16442+#endif
16443+ { .ctl_name = 0 }
16444+};
16445+#endif
16446+
16447+int gr_check_modstop(void)
16448+{
16449+#ifdef CONFIG_GRKERNSEC_MODSTOP
16450+ if (grsec_modstop == 1) {
16451+ gr_log_noargs(GR_DONT_AUDIT, GR_STOPMOD_MSG);
16452+ return 1;
16453+ }
16454+#endif
16455+ return 0;
16456+}
16457diff -urNp linux-2.6.16.12/grsecurity/grsec_textrel.c linux-2.6.16.12/grsecurity/grsec_textrel.c
16458--- linux-2.6.16.12/grsecurity/grsec_textrel.c 1969-12-31 19:00:00.000000000 -0500
16459+++ linux-2.6.16.12/grsecurity/grsec_textrel.c 2006-05-01 20:17:34.000000000 -0400
16460@@ -0,0 +1,16 @@
16461+#include <linux/kernel.h>
16462+#include <linux/sched.h>
16463+#include <linux/mm.h>
16464+#include <linux/file.h>
16465+#include <linux/grinternal.h>
16466+#include <linux/grsecurity.h>
16467+
16468+void
16469+gr_log_textrel(struct vm_area_struct * vma)
16470+{
16471+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
16472+ if (grsec_enable_audit_textrel)
16473+ gr_log_textrel_ulong_ulong(GR_DO_AUDIT, GR_TEXTREL_AUDIT_MSG, vma->vm_file, vma->vm_start, vma->vm_pgoff);
16474+#endif
16475+ return;
16476+}
16477diff -urNp linux-2.6.16.12/grsecurity/grsec_time.c linux-2.6.16.12/grsecurity/grsec_time.c
16478--- linux-2.6.16.12/grsecurity/grsec_time.c 1969-12-31 19:00:00.000000000 -0500
16479+++ linux-2.6.16.12/grsecurity/grsec_time.c 2006-05-01 20:17:34.000000000 -0400
16480@@ -0,0 +1,13 @@
16481+#include <linux/kernel.h>
16482+#include <linux/sched.h>
16483+#include <linux/grinternal.h>
16484+
16485+void
16486+gr_log_timechange(void)
16487+{
16488+#ifdef CONFIG_GRKERNSEC_TIME
16489+ if (grsec_enable_time)
16490+ gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_TIME_MSG);
16491+#endif
16492+ return;
16493+}
16494diff -urNp linux-2.6.16.12/grsecurity/grsec_tpe.c linux-2.6.16.12/grsecurity/grsec_tpe.c
16495--- linux-2.6.16.12/grsecurity/grsec_tpe.c 1969-12-31 19:00:00.000000000 -0500
16496+++ linux-2.6.16.12/grsecurity/grsec_tpe.c 2006-05-01 20:17:34.000000000 -0400
16497@@ -0,0 +1,37 @@
16498+#include <linux/kernel.h>
16499+#include <linux/sched.h>
16500+#include <linux/file.h>
16501+#include <linux/fs.h>
16502+#include <linux/grinternal.h>
16503+
16504+extern int gr_acl_tpe_check(void);
16505+
16506+int
16507+gr_tpe_allow(const struct file *file)
16508+{
16509+#ifdef CONFIG_GRKERNSEC
16510+ struct inode *inode = file->f_dentry->d_parent->d_inode;
16511+
16512+ if (current->uid && ((grsec_enable_tpe &&
16513+#ifdef CONFIG_GRKERNSEC_TPE_INVERT
16514+ !in_group_p(grsec_tpe_gid)
16515+#else
16516+ in_group_p(grsec_tpe_gid)
16517+#endif
16518+ ) || gr_acl_tpe_check()) &&
16519+ (inode->i_uid || (!inode->i_uid && ((inode->i_mode & S_IWGRP) ||
16520+ (inode->i_mode & S_IWOTH))))) {
16521+ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_dentry, file->f_vfsmnt);
16522+ return 0;
16523+ }
16524+#ifdef CONFIG_GRKERNSEC_TPE_ALL
16525+ if (current->uid && grsec_enable_tpe && grsec_enable_tpe_all &&
16526+ ((inode->i_uid && (inode->i_uid != current->uid)) ||
16527+ (inode->i_mode & S_IWGRP) || (inode->i_mode & S_IWOTH))) {
16528+ gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_dentry, file->f_vfsmnt);
16529+ return 0;
16530+ }
16531+#endif
16532+#endif
16533+ return 1;
16534+}
16535diff -urNp linux-2.6.16.12/grsecurity/grsum.c linux-2.6.16.12/grsecurity/grsum.c
16536--- linux-2.6.16.12/grsecurity/grsum.c 1969-12-31 19:00:00.000000000 -0500
16537+++ linux-2.6.16.12/grsecurity/grsum.c 2006-05-01 20:17:34.000000000 -0400
16538@@ -0,0 +1,59 @@
16539+#include <linux/kernel.h>
16540+#include <linux/sched.h>
16541+#include <linux/mm.h>
16542+#include <asm/scatterlist.h>
16543+#include <linux/crypto.h>
16544+#include <linux/gracl.h>
16545+
16546+
16547+#if !defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE) || !defined(CONFIG_CRYPTO_SHA256) || defined(CONFIG_CRYPTO_SHA256_MODULE)
16548+#error "crypto and sha256 must be built into the kernel"
16549+#endif
16550+
16551+int
16552+chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum)
16553+{
16554+ char *p;
16555+ struct crypto_tfm *tfm;
16556+ unsigned char temp_sum[GR_SHA_LEN];
16557+ struct scatterlist sg[2];
16558+ volatile int retval = 0;
16559+ volatile int dummy = 0;
16560+ unsigned int i;
16561+
16562+ tfm = crypto_alloc_tfm("sha256", 0);
16563+ if (tfm == NULL) {
16564+ /* should never happen, since sha256 should be built in */
16565+ return 1;
16566+ }
16567+
16568+ crypto_digest_init(tfm);
16569+
16570+ p = salt;
16571+ sg[0].page = virt_to_page(p);
16572+ sg[0].offset = ((long) p & ~PAGE_MASK);
16573+ sg[0].length = GR_SALT_LEN;
16574+
16575+ crypto_digest_update(tfm, sg, 1);
16576+
16577+ p = entry->pw;
16578+ sg[0].page = virt_to_page(p);
16579+ sg[0].offset = ((long) p & ~PAGE_MASK);
16580+ sg[0].length = strlen(entry->pw);
16581+
16582+ crypto_digest_update(tfm, sg, 1);
16583+
16584+ crypto_digest_final(tfm, temp_sum);
16585+
16586+ memset(entry->pw, 0, GR_PW_LEN);
16587+
16588+ for (i = 0; i < GR_SHA_LEN; i++)
16589+ if (sum[i] != temp_sum[i])
16590+ retval = 1;
16591+ else
16592+ dummy = 1; // waste a cycle
16593+
16594+ crypto_free_tfm(tfm);
16595+
16596+ return retval;
16597+}
16598diff -urNp linux-2.6.16.12/grsecurity/Kconfig linux-2.6.16.12/grsecurity/Kconfig
16599--- linux-2.6.16.12/grsecurity/Kconfig 1969-12-31 19:00:00.000000000 -0500
16600+++ linux-2.6.16.12/grsecurity/Kconfig 2006-05-01 20:17:34.000000000 -0400
16601@@ -0,0 +1,888 @@
16602+#
16603+# grecurity configuration
16604+#
16605+
16606+menu "Grsecurity"
16607+
16608+config GRKERNSEC
16609+ bool "Grsecurity"
16610+ select CRYPTO
16611+ select CRYPTO_SHA256
16612+ help
16613+ If you say Y here, you will be able to configure many features
16614+ that will enhance the security of your system. It is highly
16615+ recommended that you say Y here and read through the help
16616+ for each option so that you fully understand the features and
16617+ can evaluate their usefulness for your machine.
16618+
16619+choice
16620+ prompt "Security Level"
16621+ depends GRKERNSEC
16622+ default GRKERNSEC_CUSTOM
16623+
16624+config GRKERNSEC_LOW
16625+ bool "Low"
16626+ select GRKERNSEC_LINK
16627+ select GRKERNSEC_FIFO
16628+ select GRKERNSEC_RANDPID
16629+ select GRKERNSEC_EXECVE
16630+ select GRKERNSEC_RANDNET
16631+ select GRKERNSEC_DMESG
16632+ select GRKERNSEC_CHROOT_CHDIR
16633+ select GRKERNSEC_MODSTOP if (MODULES)
16634+
16635+ help
16636+ If you choose this option, several of the grsecurity options will
16637+ be enabled that will give you greater protection against a number
16638+ of attacks, while assuring that none of your software will have any
16639+ conflicts with the additional security measures. If you run a lot
16640+ of unusual software, or you are having problems with the higher
16641+ security levels, you should say Y here. With this option, the
16642+ following features are enabled:
16643+
16644+ - Linking restrictions
16645+ - FIFO restrictions
16646+ - Randomized PIDs
16647+ - Enforcing RLIMIT_NPROC on execve
16648+ - Restricted dmesg
16649+ - Enforced chdir("/") on chroot
16650+ - Runtime module disabling
16651+
16652+config GRKERNSEC_MEDIUM
16653+ bool "Medium"
16654+ select PAX
16655+ select PAX_EI_PAX
16656+ select PAX_PT_PAX_FLAGS
16657+ select PAX_HAVE_ACL_FLAGS
16658+ select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR)
16659+ select GRKERNSEC_CHROOT_SYSCTL
16660+ select GRKERNSEC_LINK
16661+ select GRKERNSEC_FIFO
16662+ select GRKERNSEC_RANDPID
16663+ select GRKERNSEC_EXECVE
16664+ select GRKERNSEC_DMESG
16665+ select GRKERNSEC_RANDNET
16666+ select GRKERNSEC_FORKFAIL
16667+ select GRKERNSEC_TIME
16668+ select GRKERNSEC_SIGNAL
16669+ select GRKERNSEC_CHROOT
16670+ select GRKERNSEC_CHROOT_UNIX
16671+ select GRKERNSEC_CHROOT_MOUNT
16672+ select GRKERNSEC_CHROOT_PIVOT
16673+ select GRKERNSEC_CHROOT_DOUBLE
16674+ select GRKERNSEC_CHROOT_CHDIR
16675+ select GRKERNSEC_CHROOT_MKNOD
16676+ select GRKERNSEC_PROC
16677+ select GRKERNSEC_PROC_USERGROUP
16678+ select GRKERNSEC_MODSTOP if (MODULES)
16679+ select PAX_RANDUSTACK
16680+ select PAX_ASLR
16681+ select PAX_RANDMMAP
16682+ select PAX_NOVSYSCALL if (X86 && !X86_64)
16683+
16684+ help
16685+ If you say Y here, several features in addition to those included
16686+ in the low additional security level will be enabled. These
16687+ features provide even more security to your system, though in rare
16688+ cases they may be incompatible with very old or poorly written
16689+ software. If you enable this option, make sure that your auth
16690+ service (identd) is running as gid 1001. With this option,
16691+ the following features (in addition to those provided in the
16692+ low additional security level) will be enabled:
16693+
16694+ - Randomized TCP source ports
16695+ - Failed fork logging
16696+ - Time change logging
16697+ - Signal logging
16698+ - Deny mounts in chroot
16699+ - Deny double chrooting
16700+ - Deny sysctl writes in chroot
16701+ - Deny mknod in chroot
16702+ - Deny access to abstract AF_UNIX sockets out of chroot
16703+ - Deny pivot_root in chroot
16704+ - Denied writes of /dev/kmem, /dev/mem, and /dev/port
16705+ - /proc restrictions with special GID set to 10 (usually wheel)
16706+ - Address Space Layout Randomization (ASLR)
16707+
16708+config GRKERNSEC_HIGH
16709+ bool "High"
16710+ select GRKERNSEC_LINK
16711+ select GRKERNSEC_FIFO
16712+ select GRKERNSEC_RANDPID
16713+ select GRKERNSEC_EXECVE
16714+ select GRKERNSEC_DMESG
16715+ select GRKERNSEC_FORKFAIL
16716+ select GRKERNSEC_TIME
16717+ select GRKERNSEC_SIGNAL
16718+ select GRKERNSEC_CHROOT_SHMAT
16719+ select GRKERNSEC_CHROOT_UNIX
16720+ select GRKERNSEC_CHROOT_MOUNT
16721+ select GRKERNSEC_CHROOT_FCHDIR
16722+ select GRKERNSEC_CHROOT_PIVOT
16723+ select GRKERNSEC_CHROOT_DOUBLE
16724+ select GRKERNSEC_CHROOT_CHDIR
16725+ select GRKERNSEC_CHROOT_MKNOD
16726+ select GRKERNSEC_CHROOT_CAPS
16727+ select GRKERNSEC_CHROOT_SYSCTL
16728+ select GRKERNSEC_CHROOT_FINDTASK
16729+ select GRKERNSEC_PROC
16730+ select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR)
16731+ select GRKERNSEC_HIDESYM
16732+ select GRKERNSEC_BRUTE
16733+ select GRKERNSEC_SHM if (SYSVIPC)
16734+ select GRKERNSEC_PROC_USERGROUP
16735+ select GRKERNSEC_KMEM
16736+ select GRKERNSEC_RESLOG
16737+ select GRKERNSEC_RANDNET
16738+ select GRKERNSEC_PROC_ADD
16739+ select GRKERNSEC_CHROOT_CHMOD
16740+ select GRKERNSEC_CHROOT_NICE
16741+ select GRKERNSEC_AUDIT_MOUNT
16742+ select GRKERNSEC_MODSTOP if (MODULES)
16743+ select PAX
16744+ select PAX_RANDUSTACK
16745+ select PAX_ASLR
16746+ select PAX_RANDMMAP
16747+ select PAX_NOEXEC
16748+ select PAX_MPROTECT
16749+ select PAX_EI_PAX
16750+ select PAX_PT_PAX_FLAGS
16751+ select PAX_HAVE_ACL_FLAGS
16752+ select PAX_KERNEXEC if (!X86_64 && !MODULES && !HOTPLUG_PCI_COMPAQ_NVRAM && !PCI_BIOS)
16753+ select PAX_RANDKSTACK if (X86_TSC && !X86_64)
16754+ select PAX_SEGMEXEC if (X86 && !X86_64)
16755+ select PAX_PAGEEXEC if (!X86)
16756+ select PAX_EMUPLT if (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64)
16757+ select PAX_DLRESOLVE if (SPARC32 || SPARC64)
16758+ select PAX_SYSCALL if (PPC32)
16759+ select PAX_EMUTRAMP if (PARISC)
16760+ select PAX_EMUSIGRT if (PARISC)
16761+ select PAX_NOVSYSCALL if (X86 && !X86_64)
16762+ select PAX_ETEXECRELOCS if (ALPHA || IA64 || PARISC)
16763+ help
16764+ If you say Y here, many of the features of grsecurity will be
16765+ enabled, which will protect you against many kinds of attacks
16766+ against your system. The heightened security comes at a cost
16767+ of an increased chance of incompatibilities with rare software
16768+ on your machine. Since this security level enables PaX, you should
16769+ view <http://pax.grsecurity.net> and read about the PaX
16770+ project. While you are there, download chpax and run it on
16771+ binaries that cause problems with PaX. Also remember that
16772+ since the /proc restrictions are enabled, you must run your
16773+ identd as gid 1001. This security level enables the following
16774+ features in addition to those listed in the low and medium
16775+ security levels:
16776+
16777+ - Additional /proc restrictions
16778+ - Chmod restrictions in chroot
16779+ - No signals, ptrace, or viewing of processes outside of chroot
16780+ - Capability restrictions in chroot
16781+ - Deny fchdir out of chroot
16782+ - Priority restrictions in chroot
16783+ - Segmentation-based implementation of PaX
16784+ - Mprotect restrictions
16785+ - Removal of addresses from /proc/<pid>/[smaps|maps|stat]
16786+ - Kernel stack randomization
16787+ - Mount/unmount/remount logging
16788+ - Kernel symbol hiding
16789+ - Destroy unused shared memory
16790+ - Prevention of memory exhaustion-based exploits
16791+config GRKERNSEC_CUSTOM
16792+ bool "Custom"
16793+ help
16794+ If you say Y here, you will be able to configure every grsecurity
16795+ option, which allows you to enable many more features that aren't
16796+ covered in the basic security levels. These additional features
16797+ include TPE, socket restrictions, and the sysctl system for
16798+ grsecurity. It is advised that you read through the help for
16799+ each option to determine its usefulness in your situation.
16800+
16801+endchoice
16802+
16803+menu "Address Space Protection"
16804+depends on GRKERNSEC
16805+
16806+config GRKERNSEC_KMEM
16807+ bool "Deny writing to /dev/kmem, /dev/mem, and /dev/port"
16808+ help
16809+ If you say Y here, /dev/kmem and /dev/mem won't be allowed to
16810+ be written to via mmap or otherwise to modify the running kernel.
16811+ /dev/port will also not be allowed to be opened. If you have module
16812+ support disabled, enabling this will close up four ways that are
16813+ currently used to insert malicious code into the running kernel.
16814+ Even with all these features enabled, we still highly recommend that
16815+ you use the RBAC system, as it is still possible for an attacker to
16816+ modify the running kernel through privileged I/O granted by ioperm/iopl.
16817+ If you are not using XFree86, you may be able to stop this additional
16818+ case by enabling the 'Disable privileged I/O' option. Though nothing
16819+ legitimately writes to /dev/kmem, XFree86 does need to write to /dev/mem,
16820+ but only to video memory, which is the only writing we allow in this
16821+ case. If /dev/kmem or /dev/mem are mmaped without PROT_WRITE, they will
16822+ not be allowed to mprotect it with PROT_WRITE later.
16823+ It is highly recommended that you say Y here if you meet all the
16824+ conditions above.
16825+
16826+config GRKERNSEC_IO
16827+ bool "Disable privileged I/O"
16828+ depends on X86
16829+ select RTC
16830+ help
16831+ If you say Y here, all ioperm and iopl calls will return an error.
16832+ Ioperm and iopl can be used to modify the running kernel.
16833+ Unfortunately, some programs need this access to operate properly,
16834+ the most notable of which are XFree86 and hwclock. hwclock can be
16835+ remedied by having RTC support in the kernel, so CONFIG_RTC is
16836+ enabled if this option is enabled, to ensure that hwclock operates
16837+ correctly. XFree86 still will not operate correctly with this option
16838+ enabled, so DO NOT CHOOSE Y IF YOU USE XFree86. If you use XFree86
16839+ and you still want to protect your kernel against modification,
16840+ use the RBAC system.
16841+
16842+config GRKERNSEC_PROC_MEMMAP
16843+ bool "Remove addresses from /proc/<pid>/[smaps|maps|stat]"
16844+ depends on PAX_NOEXEC || PAX_ASLR
16845+ help
16846+ If you say Y here, the /proc/<pid>/maps and /proc/<pid>/stat files will
16847+ give no information about the addresses of its mappings if
16848+ PaX features that rely on random addresses are enabled on the task.
16849+ If you use PaX it is greatly recommended that you say Y here as it
16850+ closes up a hole that makes the full ASLR useless for suid
16851+ binaries.
16852+
16853+config GRKERNSEC_BRUTE
16854+ bool "Deter exploit bruteforcing"
16855+ help
16856+ If you say Y here, attempts to bruteforce exploits against forking
16857+ daemons such as apache or sshd will be deterred. When a child of a
16858+ forking daemon is killed by PaX or crashes due to an illegal
16859+ instruction, the parent process will be delayed 30 seconds upon every
16860+ subsequent fork until the administrator is able to assess the
16861+ situation and restart the daemon. It is recommended that you also
16862+ enable signal logging in the auditing section so that logs are
16863+ generated when a process performs an illegal instruction.
16864+
16865+config GRKERNSEC_MODSTOP
16866+ bool "Runtime module disabling"
16867+ depends on MODULES
16868+ help
16869+ If you say Y here, you will be able to disable the ability to (un)load
16870+ modules at runtime. This feature is useful if you need the ability
16871+ to load kernel modules at boot time, but do not want to allow an
16872+ attacker to load a rootkit kernel module into the system, or to remove
16873+ a loaded kernel module important to system functioning. You should
16874+ enable the /dev/mem protection feature as well, since rootkits can be
16875+ inserted into the kernel via other methods than kernel modules. Since
16876+ an untrusted module could still be loaded by modifying init scripts and
16877+ rebooting the system, it is also recommended that you enable the RBAC
16878+ system. If you enable this option, a sysctl option with name
16879+ "disable_modules" will be created. Setting this option to "1" disables
16880+ module loading. After this option is set, no further writes to it are
16881+ allowed until the system is rebooted.
16882+
16883+config GRKERNSEC_HIDESYM
16884+ bool "Hide kernel symbols"
16885+ help
16886+ If you say Y here, getting information on loaded modules, and
16887+ displaying all kernel symbols through a syscall will be restricted
16888+ to users with CAP_SYS_MODULE. This option is only effective
16889+ provided the following conditions are met:
16890+ 1) The kernel using grsecurity is not precompiled by some distribution
16891+ 2) You are using the RBAC system and hiding other files such as your
16892+ kernel image and System.map
16893+ 3) You have the additional /proc restrictions enabled, which removes
16894+ /proc/kcore
16895+ If the above conditions are met, this option will aid to provide a
16896+ useful protection against local and remote kernel exploitation of
16897+ overflows and arbitrary read/write vulnerabilities.
16898+
16899+endmenu
16900+menu "Role Based Access Control Options"
16901+depends on GRKERNSEC
16902+
16903+config GRKERNSEC_ACL_HIDEKERN
16904+ bool "Hide kernel processes"
16905+ help
16906+ If you say Y here, all kernel threads will be hidden to all
16907+ processes but those whose subject has the "view hidden processes"
16908+ flag.
16909+
16910+config GRKERNSEC_ACL_MAXTRIES
16911+ int "Maximum tries before password lockout"
16912+ default 3
16913+ help
16914+ This option enforces the maximum number of times a user can attempt
16915+ to authorize themselves with the grsecurity RBAC system before being
16916+ denied the ability to attempt authorization again for a specified time.
16917+ The lower the number, the harder it will be to brute-force a password.
16918+
16919+config GRKERNSEC_ACL_TIMEOUT
16920+ int "Time to wait after max password tries, in seconds"
16921+ default 30
16922+ help
16923+ This option specifies the time the user must wait after attempting to
16924+ authorize to the RBAC system with the maximum number of invalid
16925+ passwords. The higher the number, the harder it will be to brute-force
16926+ a password.
16927+
16928+endmenu
16929+menu "Filesystem Protections"
16930+depends on GRKERNSEC
16931+
16932+config GRKERNSEC_PROC
16933+ bool "Proc restrictions"
16934+ help
16935+ If you say Y here, the permissions of the /proc filesystem
16936+ will be altered to enhance system security and privacy. You MUST
16937+ choose either a user only restriction or a user and group restriction.
16938+ Depending upon the option you choose, you can either restrict users to
16939+ see only the processes they themselves run, or choose a group that can
16940+ view all processes and files normally restricted to root if you choose
16941+ the "restrict to user only" option. NOTE: If you're running identd as
16942+ a non-root user, you will have to run it as the group you specify here.
16943+
16944+config GRKERNSEC_PROC_USER
16945+ bool "Restrict /proc to user only"
16946+ depends on GRKERNSEC_PROC
16947+ help
16948+ If you say Y here, non-root users will only be able to view their own
16949+ processes, and restricts them from viewing network-related information,
16950+ and viewing kernel symbol and module information.
16951+
16952+config GRKERNSEC_PROC_USERGROUP
16953+ bool "Allow special group"
16954+ depends on GRKERNSEC_PROC && !GRKERNSEC_PROC_USER
16955+ help
16956+ If you say Y here, you will be able to select a group that will be
16957+ able to view all processes, network-related information, and
16958+ kernel and symbol information. This option is useful if you want
16959+ to run identd as a non-root user.
16960+
16961+config GRKERNSEC_PROC_GID
16962+ int "GID for special group"
16963+ depends on GRKERNSEC_PROC_USERGROUP
16964+ default 1001
16965+
16966+config GRKERNSEC_PROC_ADD
16967+ bool "Additional restrictions"
16968+ depends on GRKERNSEC_PROC_USER || GRKERNSEC_PROC_USERGROUP
16969+ help
16970+ If you say Y here, additional restrictions will be placed on
16971+ /proc that keep normal users from viewing device information and
16972+ slabinfo information that could be useful for exploits.
16973+
16974+config GRKERNSEC_LINK
16975+ bool "Linking restrictions"
16976+ help
16977+ If you say Y here, /tmp race exploits will be prevented, since users
16978+ will no longer be able to follow symlinks owned by other users in
16979+ world-writable +t directories (i.e. /tmp), unless the owner of the
16980+ symlink is the owner of the directory. users will also not be
16981+ able to hardlink to files they do not own. If the sysctl option is
16982+ enabled, a sysctl option with name "linking_restrictions" is created.
16983+
16984+config GRKERNSEC_FIFO
16985+ bool "FIFO restrictions"
16986+ help
16987+ If you say Y here, users will not be able to write to FIFOs they don't
16988+ own in world-writable +t directories (i.e. /tmp), unless the owner of
16989+ the FIFO is the same owner of the directory it's held in. If the sysctl
16990+ option is enabled, a sysctl option with name "fifo_restrictions" is
16991+ created.
16992+
16993+config GRKERNSEC_CHROOT
16994+ bool "Chroot jail restrictions"
16995+ help
16996+ If you say Y here, you will be able to choose several options that will
16997+ make breaking out of a chrooted jail much more difficult. If you
16998+ encounter no software incompatibilities with the following options, it
16999+ is recommended that you enable each one.
17000+
17001+config GRKERNSEC_CHROOT_MOUNT
17002+ bool "Deny mounts"
17003+ depends on GRKERNSEC_CHROOT
17004+ help
17005+ If you say Y here, processes inside a chroot will not be able to
17006+ mount or remount filesystems. If the sysctl option is enabled, a
17007+ sysctl option with name "chroot_deny_mount" is created.
17008+
17009+config GRKERNSEC_CHROOT_DOUBLE
17010+ bool "Deny double-chroots"
17011+ depends on GRKERNSEC_CHROOT
17012+ help
17013+ If you say Y here, processes inside a chroot will not be able to chroot
17014+ again outside the chroot. This is a widely used method of breaking
17015+ out of a chroot jail and should not be allowed. If the sysctl
17016+ option is enabled, a sysctl option with name
17017+ "chroot_deny_chroot" is created.
17018+
17019+config GRKERNSEC_CHROOT_PIVOT
17020+ bool "Deny pivot_root in chroot"
17021+ depends on GRKERNSEC_CHROOT
17022+ help
17023+ If you say Y here, processes inside a chroot will not be able to use
17024+ a function called pivot_root() that was introduced in Linux 2.3.41. It
17025+ works similar to chroot in that it changes the root filesystem. This
17026+ function could be misused in a chrooted process to attempt to break out
17027+ of the chroot, and therefore should not be allowed. If the sysctl
17028+ option is enabled, a sysctl option with name "chroot_deny_pivot" is
17029+ created.
17030+
17031+config GRKERNSEC_CHROOT_CHDIR
17032+ bool "Enforce chdir(\"/\") on all chroots"
17033+ depends on GRKERNSEC_CHROOT
17034+ help
17035+ If you say Y here, the current working directory of all newly-chrooted
17036+ applications will be set to the the root directory of the chroot.
17037+ The man page on chroot(2) states:
17038+ Note that this call does not change the current working
17039+ directory, so that `.' can be outside the tree rooted at
17040+ `/'. In particular, the super-user can escape from a
17041+ `chroot jail' by doing `mkdir foo; chroot foo; cd ..'.
17042+
17043+ It is recommended that you say Y here, since it's not known to break
17044+ any software. If the sysctl option is enabled, a sysctl option with
17045+ name "chroot_enforce_chdir" is created.
17046+
17047+config GRKERNSEC_CHROOT_CHMOD
17048+ bool "Deny (f)chmod +s"
17049+ depends on GRKERNSEC_CHROOT
17050+ help
17051+ If you say Y here, processes inside a chroot will not be able to chmod
17052+ or fchmod files to make them have suid or sgid bits. This protects
17053+ against another published method of breaking a chroot. If the sysctl
17054+ option is enabled, a sysctl option with name "chroot_deny_chmod" is
17055+ created.
17056+
17057+config GRKERNSEC_CHROOT_FCHDIR
17058+ bool "Deny fchdir out of chroot"
17059+ depends on GRKERNSEC_CHROOT
17060+ help
17061+ If you say Y here, a well-known method of breaking chroots by fchdir'ing
17062+ to a file descriptor of the chrooting process that points to a directory
17063+ outside the filesystem will be stopped. If the sysctl option
17064+ is enabled, a sysctl option with name "chroot_deny_fchdir" is created.
17065+
17066+config GRKERNSEC_CHROOT_MKNOD
17067+ bool "Deny mknod"
17068+ depends on GRKERNSEC_CHROOT
17069+ help
17070+ If you say Y here, processes inside a chroot will not be allowed to
17071+ mknod. The problem with using mknod inside a chroot is that it
17072+ would allow an attacker to create a device entry that is the same
17073+ as one on the physical root of your system, which could range from
17074+ anything from the console device to a device for your harddrive (which
17075+ they could then use to wipe the drive or steal data). It is recommended
17076+ that you say Y here, unless you run into software incompatibilities.
17077+ If the sysctl option is enabled, a sysctl option with name
17078+ "chroot_deny_mknod" is created.
17079+
17080+config GRKERNSEC_CHROOT_SHMAT
17081+ bool "Deny shmat() out of chroot"
17082+ depends on GRKERNSEC_CHROOT
17083+ help
17084+ If you say Y here, processes inside a chroot will not be able to attach
17085+ to shared memory segments that were created outside of the chroot jail.
17086+ It is recommended that you say Y here. If the sysctl option is enabled,
17087+ a sysctl option with name "chroot_deny_shmat" is created.
17088+
17089+config GRKERNSEC_CHROOT_UNIX
17090+ bool "Deny access to abstract AF_UNIX sockets out of chroot"
17091+ depends on GRKERNSEC_CHROOT
17092+ help
17093+ If you say Y here, processes inside a chroot will not be able to
17094+ connect to abstract (meaning not belonging to a filesystem) Unix
17095+ domain sockets that were bound outside of a chroot. It is recommended
17096+ that you say Y here. If the sysctl option is enabled, a sysctl option
17097+ with name "chroot_deny_unix" is created.
17098+
17099+config GRKERNSEC_CHROOT_FINDTASK
17100+ bool "Protect outside processes"
17101+ depends on GRKERNSEC_CHROOT
17102+ help
17103+ If you say Y here, processes inside a chroot will not be able to
17104+ kill, send signals with fcntl, ptrace, capget, setpgid, getpgid,
17105+ getsid, or view any process outside of the chroot. If the sysctl
17106+ option is enabled, a sysctl option with name "chroot_findtask" is
17107+ created.
17108+
17109+config GRKERNSEC_CHROOT_NICE
17110+ bool "Restrict priority changes"
17111+ depends on GRKERNSEC_CHROOT
17112+ help
17113+ If you say Y here, processes inside a chroot will not be able to raise
17114+ the priority of processes in the chroot, or alter the priority of
17115+ processes outside the chroot. This provides more security than simply
17116+ removing CAP_SYS_NICE from the process' capability set. If the
17117+ sysctl option is enabled, a sysctl option with name "chroot_restrict_nice"
17118+ is created.
17119+
17120+config GRKERNSEC_CHROOT_SYSCTL
17121+ bool "Deny sysctl writes"
17122+ depends on GRKERNSEC_CHROOT
17123+ help
17124+ If you say Y here, an attacker in a chroot will not be able to
17125+ write to sysctl entries, either by sysctl(2) or through a /proc
17126+ interface. It is strongly recommended that you say Y here. If the
17127+ sysctl option is enabled, a sysctl option with name
17128+ "chroot_deny_sysctl" is created.
17129+
17130+config GRKERNSEC_CHROOT_CAPS
17131+ bool "Capability restrictions"
17132+ depends on GRKERNSEC_CHROOT
17133+ help
17134+ If you say Y here, the capabilities on all root processes within a
17135+ chroot jail will be lowered to stop module insertion, raw i/o,
17136+ system and net admin tasks, rebooting the system, modifying immutable
17137+ files, modifying IPC owned by another, and changing the system time.
17138+ This is left an option because it can break some apps. Disable this
17139+ if your chrooted apps are having problems performing those kinds of
17140+ tasks. If the sysctl option is enabled, a sysctl option with
17141+ name "chroot_caps" is created.
17142+
17143+endmenu
17144+menu "Kernel Auditing"
17145+depends on GRKERNSEC
17146+
17147+config GRKERNSEC_AUDIT_GROUP
17148+ bool "Single group for auditing"
17149+ help
17150+ If you say Y here, the exec, chdir, (un)mount, and ipc logging features
17151+ will only operate on a group you specify. This option is recommended
17152+ if you only want to watch certain users instead of having a large
17153+ amount of logs from the entire system. If the sysctl option is enabled,
17154+ a sysctl option with name "audit_group" is created.
17155+
17156+config GRKERNSEC_AUDIT_GID
17157+ int "GID for auditing"
17158+ depends on GRKERNSEC_AUDIT_GROUP
17159+ default 1007
17160+
17161+config GRKERNSEC_EXECLOG
17162+ bool "Exec logging"
17163+ help
17164+ If you say Y here, all execve() calls will be logged (since the
17165+ other exec*() calls are frontends to execve(), all execution
17166+ will be logged). Useful for shell-servers that like to keep track
17167+ of their users. If the sysctl option is enabled, a sysctl option with
17168+ name "exec_logging" is created.
17169+ WARNING: This option when enabled will produce a LOT of logs, especially
17170+ on an active system.
17171+
17172+config GRKERNSEC_RESLOG
17173+ bool "Resource logging"
17174+ help
17175+ If you say Y here, all attempts to overstep resource limits will
17176+ be logged with the resource name, the requested size, and the current
17177+ limit. It is highly recommended that you say Y here.
17178+
17179+config GRKERNSEC_CHROOT_EXECLOG
17180+ bool "Log execs within chroot"
17181+ help
17182+ If you say Y here, all executions inside a chroot jail will be logged
17183+ to syslog. This can cause a large amount of logs if certain
17184+ applications (eg. djb's daemontools) are installed on the system, and
17185+ is therefore left as an option. If the sysctl option is enabled, a
17186+ sysctl option with name "chroot_execlog" is created.
17187+
17188+config GRKERNSEC_AUDIT_CHDIR
17189+ bool "Chdir logging"
17190+ help
17191+ If you say Y here, all chdir() calls will be logged. If the sysctl
17192+ option is enabled, a sysctl option with name "audit_chdir" is created.
17193+
17194+config GRKERNSEC_AUDIT_MOUNT
17195+ bool "(Un)Mount logging"
17196+ help
17197+ If you say Y here, all mounts and unmounts will be logged. If the
17198+ sysctl option is enabled, a sysctl option with name "audit_mount" is
17199+ created.
17200+
17201+config GRKERNSEC_AUDIT_IPC
17202+ bool "IPC logging"
17203+ help
17204+ If you say Y here, creation and removal of message queues, semaphores,
17205+ and shared memory will be logged. If the sysctl option is enabled, a
17206+ sysctl option with name "audit_ipc" is created.
17207+
17208+config GRKERNSEC_SIGNAL
17209+ bool "Signal logging"
17210+ help
17211+ If you say Y here, certain important signals will be logged, such as
17212+ SIGSEGV, which will as a result inform you of when a error in a program
17213+ occurred, which in some cases could mean a possible exploit attempt.
17214+ If the sysctl option is enabled, a sysctl option with name
17215+ "signal_logging" is created.
17216+
17217+config GRKERNSEC_FORKFAIL
17218+ bool "Fork failure logging"
17219+ help
17220+ If you say Y here, all failed fork() attempts will be logged.
17221+ This could suggest a fork bomb, or someone attempting to overstep
17222+ their process limit. If the sysctl option is enabled, a sysctl option
17223+ with name "forkfail_logging" is created.
17224+
17225+config GRKERNSEC_TIME
17226+ bool "Time change logging"
17227+ help
17228+ If you say Y here, any changes of the system clock will be logged.
17229+ If the sysctl option is enabled, a sysctl option with name
17230+ "timechange_logging" is created.
17231+
17232+config GRKERNSEC_PROC_IPADDR
17233+ bool "/proc/<pid>/ipaddr support"
17234+ help
17235+ If you say Y here, a new entry will be added to each /proc/<pid>
17236+ directory that contains the IP address of the person using the task.
17237+ The IP is carried across local TCP and AF_UNIX stream sockets.
17238+ This information can be useful for IDS/IPSes to perform remote response
17239+ to a local attack. The entry is readable by only the owner of the
17240+ process (and root if he has CAP_DAC_OVERRIDE, which can be removed via
17241+ the RBAC system), and thus does not create privacy concerns.
17242+
17243+config GRKERNSEC_AUDIT_TEXTREL
17244+ bool 'ELF text relocations logging (READ HELP)'
17245+ depends on PAX_MPROTECT
17246+ help
17247+ If you say Y here, text relocations will be logged with the filename
17248+ of the offending library or binary. The purpose of the feature is
17249+ to help Linux distribution developers get rid of libraries and
17250+ binaries that need text relocations which hinder the future progress
17251+ of PaX. Only Linux distribution developers should say Y here, and
17252+ never on a production machine, as this option creates an information
17253+ leak that could aid an attacker in defeating the randomization of
17254+ a single memory region. If the sysctl option is enabled, a sysctl
17255+ option with name "audit_textrel" is created.
17256+
17257+endmenu
17258+
17259+menu "Executable Protections"
17260+depends on GRKERNSEC
17261+
17262+config GRKERNSEC_EXECVE
17263+ bool "Enforce RLIMIT_NPROC on execs"
17264+ help
17265+ If you say Y here, users with a resource limit on processes will
17266+ have the value checked during execve() calls. The current system
17267+ only checks the system limit during fork() calls. If the sysctl option
17268+ is enabled, a sysctl option with name "execve_limiting" is created.
17269+
17270+config GRKERNSEC_SHM
17271+ bool "Destroy unused shared memory"
17272+ depends on SYSVIPC
17273+ help
17274+ If you say Y here, shared memory will be destroyed when no one is
17275+ attached to it. Otherwise, resources involved with the shared
17276+ memory can be used up and not be associated with any process (as the
17277+ shared memory still exists, and the creating process has exited). If
17278+ the sysctl option is enabled, a sysctl option with name
17279+ "destroy_unused_shm" is created.
17280+
17281+config GRKERNSEC_DMESG
17282+ bool "Dmesg(8) restriction"
17283+ help
17284+ If you say Y here, non-root users will not be able to use dmesg(8)
17285+ to view up to the last 4kb of messages in the kernel's log buffer.
17286+ If the sysctl option is enabled, a sysctl option with name "dmesg" is
17287+ created.
17288+
17289+config GRKERNSEC_RANDPID
17290+ bool "Randomized PIDs"
17291+ help
17292+ If you say Y here, all PIDs created on the system will be
17293+ pseudo-randomly generated. This is extremely effective along
17294+ with the /proc restrictions to disallow an attacker from guessing
17295+ pids of daemons, etc. PIDs are also used in some cases as part
17296+ of a naming system for temporary files, so this option would keep
17297+ those filenames from being predicted as well. We also use code
17298+ to make sure that PID numbers aren't reused too soon. If the sysctl
17299+ option is enabled, a sysctl option with name "rand_pids" is created.
17300+
17301+config GRKERNSEC_TPE
17302+ bool "Trusted Path Execution (TPE)"
17303+ help
17304+ If you say Y here, you will be able to choose a gid to add to the
17305+ supplementary groups of users you want to mark as "untrusted."
17306+ These users will not be able to execute any files that are not in
17307+ root-owned directories writable only by root. If the sysctl option
17308+ is enabled, a sysctl option with name "tpe" is created.
17309+
17310+config GRKERNSEC_TPE_ALL
17311+ bool "Partially restrict non-root users"
17312+ depends on GRKERNSEC_TPE
17313+ help
17314+ If you say Y here, All non-root users other than the ones in the
17315+ group specified in the main TPE option will only be allowed to
17316+ execute files in directories they own that are not group or
17317+ world-writable, or in directories owned by root and writable only by
17318+ root. If the sysctl option is enabled, a sysctl option with name
17319+ "tpe_restrict_all" is created.
17320+
17321+config GRKERNSEC_TPE_INVERT
17322+ bool "Invert GID option"
17323+ depends on GRKERNSEC_TPE
17324+ help
17325+ If you say Y here, the group you specify in the TPE configuration will
17326+ decide what group TPE restrictions will be *disabled* for. This
17327+ option is useful if you want TPE restrictions to be applied to most
17328+ users on the system.
17329+
17330+config GRKERNSEC_TPE_GID
17331+ int "GID for untrusted users"
17332+ depends on GRKERNSEC_TPE && !GRKERNSEC_TPE_INVERT
17333+ default 1005
17334+ help
17335+ If you have selected the "Invert GID option" above, setting this
17336+ GID determines what group TPE restrictions will be *disabled* for.
17337+ If you have not selected the "Invert GID option" above, setting this
17338+ GID determines what group TPE restrictions will be *enabled* for.
17339+ If the sysctl option is enabled, a sysctl option with name "tpe_gid"
17340+ is created.
17341+
17342+config GRKERNSEC_TPE_GID
17343+ int "GID for trusted users"
17344+ depends on GRKERNSEC_TPE && GRKERNSEC_TPE_INVERT
17345+ default 1005
17346+ help
17347+ If you have selected the "Invert GID option" above, setting this
17348+ GID determines what group TPE restrictions will be *disabled* for.
17349+ If you have not selected the "Invert GID option" above, setting this
17350+ GID determines what group TPE restrictions will be *enabled* for.
17351+ If the sysctl option is enabled, a sysctl option with name "tpe_gid"
17352+ is created.
17353+
17354+endmenu
17355+menu "Network Protections"
17356+depends on GRKERNSEC
17357+
17358+config GRKERNSEC_RANDNET
17359+ bool "Larger entropy pools"
17360+ help
17361+ If you say Y here, the entropy pools used for many features of Linux
17362+ and grsecurity will be doubled in size. Since several grsecurity
17363+ features use additional randomness, it is recommended that you say Y
17364+ here. Saying Y here has a similar effect as modifying
17365+ /proc/sys/kernel/random/poolsize.
17366+
17367+config GRKERNSEC_SOCKET
17368+ bool "Socket restrictions"
17369+ help
17370+ If you say Y here, you will be able to choose from several options.
17371+ If you assign a GID on your system and add it to the supplementary
17372+ groups of users you want to restrict socket access to, this patch
17373+ will perform up to three things, based on the option(s) you choose.
17374+
17375+config GRKERNSEC_SOCKET_ALL
17376+ bool "Deny any sockets to group"
17377+ depends on GRKERNSEC_SOCKET
17378+ help
17379+ If you say Y here, you will be able to choose a GID of whose users will
17380+ be unable to connect to other hosts from your machine or run server
17381+ applications from your machine. If the sysctl option is enabled, a
17382+ sysctl option with name "socket_all" is created.
17383+
17384+config GRKERNSEC_SOCKET_ALL_GID
17385+ int "GID to deny all sockets for"
17386+ depends on GRKERNSEC_SOCKET_ALL
17387+ default 1004
17388+ help
17389+ Here you can choose the GID to disable socket access for. Remember to
17390+ add the users you want socket access disabled for to the GID
17391+ specified here. If the sysctl option is enabled, a sysctl option
17392+ with name "socket_all_gid" is created.
17393+
17394+config GRKERNSEC_SOCKET_CLIENT
17395+ bool "Deny client sockets to group"
17396+ depends on GRKERNSEC_SOCKET
17397+ help
17398+ If you say Y here, you will be able to choose a GID of whose users will
17399+ be unable to connect to other hosts from your machine, but will be
17400+ able to run servers. If this option is enabled, all users in the group
17401+ you specify will have to use passive mode when initiating ftp transfers
17402+ from the shell on your machine. If the sysctl option is enabled, a
17403+ sysctl option with name "socket_client" is created.
17404+
17405+config GRKERNSEC_SOCKET_CLIENT_GID
17406+ int "GID to deny client sockets for"
17407+ depends on GRKERNSEC_SOCKET_CLIENT
17408+ default 1003
17409+ help
17410+ Here you can choose the GID to disable client socket access for.
17411+ Remember to add the users you want client socket access disabled for to
17412+ the GID specified here. If the sysctl option is enabled, a sysctl
17413+ option with name "socket_client_gid" is created.
17414+
17415+config GRKERNSEC_SOCKET_SERVER
17416+ bool "Deny server sockets to group"
17417+ depends on GRKERNSEC_SOCKET
17418+ help
17419+ If you say Y here, you will be able to choose a GID of whose users will
17420+ be unable to run server applications from your machine. If the sysctl
17421+ option is enabled, a sysctl option with name "socket_server" is created.
17422+
17423+config GRKERNSEC_SOCKET_SERVER_GID
17424+ int "GID to deny server sockets for"
17425+ depends on GRKERNSEC_SOCKET_SERVER
17426+ default 1002
17427+ help
17428+ Here you can choose the GID to disable server socket access for.
17429+ Remember to add the users you want server socket access disabled for to
17430+ the GID specified here. If the sysctl option is enabled, a sysctl
17431+ option with name "socket_server_gid" is created.
17432+
17433+endmenu
17434+menu "Sysctl support"
17435+depends on GRKERNSEC && SYSCTL
17436+
17437+config GRKERNSEC_SYSCTL
17438+ bool "Sysctl support"
17439+ help
17440+ If you say Y here, you will be able to change the options that
17441+ grsecurity runs with at bootup, without having to recompile your
17442+ kernel. You can echo values to files in /proc/sys/kernel/grsecurity
17443+ to enable (1) or disable (0) various features. All the sysctl entries
17444+ are mutable until the "grsec_lock" entry is set to a non-zero value.
17445+ All features enabled in the kernel configuration are disabled at boot
17446+ if you do not say Y to the "Turn on features by default" option.
17447+ All options should be set at startup, and the grsec_lock entry should
17448+ be set to a non-zero value after all the options are set.
17449+ *THIS IS EXTREMELY IMPORTANT*
17450+
17451+config GRKERNSEC_SYSCTL_ON
17452+ bool "Turn on features by default"
17453+ depends on GRKERNSEC_SYSCTL
17454+ help
17455+ If you say Y here, instead of having all features enabled in the
17456+ kernel configuration disabled at boot time, the features will be
17457+ enabled at boot time. It is recommended you say Y here unless
17458+ there is some reason you would want all sysctl-tunable features to
17459+ be disabled by default. As mentioned elsewhere, it is important
17460+ to enable the grsec_lock entry once you have finished modifying
17461+ the sysctl entries.
17462+
17463+endmenu
17464+menu "Logging Options"
17465+depends on GRKERNSEC
17466+
17467+config GRKERNSEC_FLOODTIME
17468+ int "Seconds in between log messages (minimum)"
17469+ default 10
17470+ help
17471+ This option allows you to enforce the number of seconds between
17472+ grsecurity log messages. The default should be suitable for most
17473+ people, however, if you choose to change it, choose a value small enough
17474+ to allow informative logs to be produced, but large enough to
17475+ prevent flooding.
17476+
17477+config GRKERNSEC_FLOODBURST
17478+ int "Number of messages in a burst (maximum)"
17479+ default 4
17480+ help
17481+ This option allows you to choose the maximum number of messages allowed
17482+ within the flood time interval you chose in a separate option. The
17483+ default should be suitable for most people, however if you find that
17484+ many of your logs are being interpreted as flooding, you may want to
17485+ raise this value.
17486+
17487+endmenu
17488+
17489+endmenu
17490diff -urNp linux-2.6.16.12/grsecurity/Makefile linux-2.6.16.12/grsecurity/Makefile
17491--- linux-2.6.16.12/grsecurity/Makefile 1969-12-31 19:00:00.000000000 -0500
17492+++ linux-2.6.16.12/grsecurity/Makefile 2006-05-01 20:17:34.000000000 -0400
17493@@ -0,0 +1,20 @@
17494+# grsecurity's ACL system was originally written in 2001 by Michael Dalton
17495+# during 2001-2005 it has been completely redesigned by Brad Spengler
17496+# into an RBAC system
17497+#
17498+# All code in this directory and various hooks inserted throughout the kernel
17499+# are copyright Brad Spengler, and released under the GPL v2 or higher
17500+
17501+obj-y = grsec_chdir.o grsec_chroot.o grsec_exec.o grsec_fifo.o grsec_fork.o \
17502+ grsec_mount.o grsec_rand.o grsec_sig.o grsec_sock.o grsec_sysctl.o \
17503+ grsec_time.o grsec_tpe.o grsec_ipc.o grsec_link.o grsec_textrel.o
17504+
17505+obj-$(CONFIG_GRKERNSEC) += grsec_init.o grsum.o gracl.o gracl_ip.o gracl_segv.o \
17506+ gracl_cap.o gracl_alloc.o gracl_shm.o grsec_mem.o gracl_fs.o \
17507+ gracl_learn.o grsec_log.o
17508+obj-$(CONFIG_GRKERNSEC_RESLOG) += gracl_res.o
17509+
17510+ifndef CONFIG_GRKERNSEC
17511+obj-y += grsec_disabled.o
17512+endif
17513+
17514diff -urNp linux-2.6.16.12/include/asm-alpha/a.out.h linux-2.6.16.12/include/asm-alpha/a.out.h
17515--- linux-2.6.16.12/include/asm-alpha/a.out.h 2006-05-01 15:14:26.000000000 -0400
17516+++ linux-2.6.16.12/include/asm-alpha/a.out.h 2006-05-01 20:17:34.000000000 -0400
17517@@ -98,7 +98,7 @@ struct exec
17518 set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000L \
17519 ? ADDR_LIMIT_32BIT : 0) | PER_OSF4))
17520
17521-#define STACK_TOP \
17522+#define __STACK_TOP \
17523 (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL)
17524
17525 #endif
17526diff -urNp linux-2.6.16.12/include/asm-alpha/elf.h linux-2.6.16.12/include/asm-alpha/elf.h
17527--- linux-2.6.16.12/include/asm-alpha/elf.h 2006-05-01 15:14:26.000000000 -0400
17528+++ linux-2.6.16.12/include/asm-alpha/elf.h 2006-05-01 20:17:34.000000000 -0400
17529@@ -91,6 +91,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
17530
17531 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
17532
17533+#ifdef CONFIG_PAX_ASLR
17534+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 0x10000 : 0x120000000UL)
17535+
17536+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
17537+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28)
17538+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
17539+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28)
17540+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
17541+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 19)
17542+#endif
17543+
17544 /* $0 is set by ld.so to a pointer to a function which might be
17545 registered using atexit. This provides a mean for the dynamic
17546 linker to call DT_FINI functions for shared libraries that have
17547diff -urNp linux-2.6.16.12/include/asm-alpha/page.h linux-2.6.16.12/include/asm-alpha/page.h
17548--- linux-2.6.16.12/include/asm-alpha/page.h 2006-05-01 15:14:26.000000000 -0400
17549+++ linux-2.6.16.12/include/asm-alpha/page.h 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 17550@@ -98,6 +98,15 @@ typedef unsigned long pgprot_t;
89675291 17551 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
17552 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
17553
17554+#ifdef CONFIG_PAX_PAGEEXEC
17555+#ifdef CONFIG_PAX_MPROTECT
17556+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
17557+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
17558+#else
17559+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
17560+#endif
17561+#endif
17562+
17563 #endif /* __KERNEL__ */
17564
17565 #include <asm-generic/page.h>
17566diff -urNp linux-2.6.16.12/include/asm-alpha/pgtable.h linux-2.6.16.12/include/asm-alpha/pgtable.h
17567--- linux-2.6.16.12/include/asm-alpha/pgtable.h 2006-05-01 15:14:26.000000000 -0400
17568+++ linux-2.6.16.12/include/asm-alpha/pgtable.h 2006-05-01 20:17:34.000000000 -0400
17569@@ -102,6 +102,17 @@ struct vm_area_struct;
17570 #define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS)
17571 #define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
17572 #define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
17573+
17574+#ifdef CONFIG_PAX_PAGEEXEC
17575+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOE)
17576+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE)
17577+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE)
17578+#else
17579+# define PAGE_SHARED_NOEXEC PAGE_SHARED
17580+# define PAGE_COPY_NOEXEC PAGE_COPY
17581+# define PAGE_READONLY_NOEXEC PAGE_READONLY
17582+#endif
17583+
17584 #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
17585
17586 #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
17587diff -urNp linux-2.6.16.12/include/asm-arm/a.out.h linux-2.6.16.12/include/asm-arm/a.out.h
17588--- linux-2.6.16.12/include/asm-arm/a.out.h 2006-05-01 15:14:26.000000000 -0400
17589+++ linux-2.6.16.12/include/asm-arm/a.out.h 2006-05-01 20:17:34.000000000 -0400
17590@@ -28,7 +28,7 @@ struct exec
17591 #define M_ARM 103
17592
17593 #ifdef __KERNEL__
17594-#define STACK_TOP ((current->personality == PER_LINUX_32BIT) ? \
17595+#define __STACK_TOP ((current->personality == PER_LINUX_32BIT) ? \
17596 TASK_SIZE : TASK_SIZE_26)
17597 #endif
17598
17599diff -urNp linux-2.6.16.12/include/asm-arm/elf.h linux-2.6.16.12/include/asm-arm/elf.h
17600--- linux-2.6.16.12/include/asm-arm/elf.h 2006-05-01 15:14:26.000000000 -0400
17601+++ linux-2.6.16.12/include/asm-arm/elf.h 2006-05-01 20:17:34.000000000 -0400
17602@@ -56,6 +56,17 @@ typedef struct user_fp elf_fpregset_t;
17603
17604 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
17605
17606+#ifdef CONFIG_PAX_ASLR
17607+#define PAX_ELF_ET_DYN_BASE(tsk) 0x00008000UL
17608+
17609+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
17610+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
17611+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
17612+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
17613+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
17614+#define PAX_DELTA_STACK_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
17615+#endif
17616+
17617 /* When the program starts, a1 contains a pointer to a function to be
17618 registered with atexit, as per the SVR4 ABI. A value of 0 means we
17619 have no such handler. */
17620diff -urNp linux-2.6.16.12/include/asm-i386/a.out.h linux-2.6.16.12/include/asm-i386/a.out.h
17621--- linux-2.6.16.12/include/asm-i386/a.out.h 2006-05-01 15:14:26.000000000 -0400
17622+++ linux-2.6.16.12/include/asm-i386/a.out.h 2006-05-01 20:17:34.000000000 -0400
17623@@ -19,7 +19,11 @@ struct exec
17624
17625 #ifdef __KERNEL__
17626
17627-#define STACK_TOP TASK_SIZE
17628+#ifdef CONFIG_PAX_SEGMEXEC
17629+#define __STACK_TOP ((current->mm->pax_flags & MF_PAX_SEGMEXEC)?TASK_SIZE/2:TASK_SIZE)
17630+#else
17631+#define __STACK_TOP TASK_SIZE
17632+#endif
17633
17634 #endif
17635
17636diff -urNp linux-2.6.16.12/include/asm-i386/auxvec.h linux-2.6.16.12/include/asm-i386/auxvec.h
17637--- linux-2.6.16.12/include/asm-i386/auxvec.h 2006-05-01 15:14:26.000000000 -0400
17638+++ linux-2.6.16.12/include/asm-i386/auxvec.h 2006-05-01 20:17:34.000000000 -0400
17639@@ -5,7 +5,9 @@
17640 * Architecture-neutral AT_ values in 0-17, leave some room
17641 * for more of them, start the x86-specific ones at 32.
17642 */
17643+#ifndef CONFIG_PAX_NOVSYSCALL
17644 #define AT_SYSINFO 32
17645 #define AT_SYSINFO_EHDR 33
17646+#endif
17647
17648 #endif
17649diff -urNp linux-2.6.16.12/include/asm-i386/desc.h linux-2.6.16.12/include/asm-i386/desc.h
17650--- linux-2.6.16.12/include/asm-i386/desc.h 2006-05-01 15:14:26.000000000 -0400
17651+++ linux-2.6.16.12/include/asm-i386/desc.h 2006-05-01 20:17:34.000000000 -0400
17652@@ -10,11 +10,13 @@
17653
17654 #include <linux/preempt.h>
17655 #include <linux/smp.h>
17656-#include <linux/percpu.h>
17657+#include <linux/sched.h>
17658
17659 #include <asm/mmu.h>
17660+#include <asm/pgtable.h>
17661+#include <asm/tlbflush.h>
17662
17663-extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
17664+extern struct desc_struct cpu_gdt_table[NR_CPUS][PAGE_SIZE / sizeof(struct desc_struct)];
17665
17666 DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
17667
17668@@ -24,13 +26,53 @@ struct Xgt_desc_struct {
17669 unsigned short pad;
17670 } __attribute__ ((packed));
17671
17672-extern struct Xgt_desc_struct idt_descr;
17673-DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
17674-
17675+extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
17676
17677 static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
17678 {
17679- return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
17680+ return cpu_gdt_table[cpu];
17681+}
17682+
17683+#define pax_open_kernel(cr0) \
17684+do { \
17685+ typecheck(unsigned long,cr0); \
17686+ preempt_disable(); \
17687+ cr0 = read_cr0(); \
17688+ write_cr0(cr0 & ~0x10000UL); \
17689+} while(0)
17690+
17691+#define pax_close_kernel(cr0) \
17692+do { \
17693+ typecheck(unsigned long,cr0); \
17694+ write_cr0(cr0); \
17695+ preempt_enable_no_resched(); \
17696+} while(0)
17697+
17698+static inline void set_user_cs(struct mm_struct *mm, int cpu)
17699+{
17700+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
17701+ unsigned long base = mm->context.user_cs_base;
17702+ unsigned long limit = mm->context.user_cs_limit;
17703+
17704+#ifdef CONFIG_PAX_KERNEXEC
17705+ unsigned long cr0;
17706+
17707+ pax_open_kernel(cr0);
17708+#endif
17709+
17710+ if (likely(limit)) {
17711+ limit -= 1UL;
17712+ limit >>= 12;
17713+ }
17714+
17715+ get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS].a = (limit & 0xFFFFUL) | (base << 16);
17716+ get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS].b = (limit & 0xF0000UL) | 0xC0FB00UL | (base & 0xFF000000UL) | ((base >> 16) & 0xFFUL);
17717+
17718+#ifdef CONFIG_PAX_KERNEXEC
17719+ pax_close_kernel(cr0);
17720+#endif
17721+
17722+#endif
17723 }
17724
17725 #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
17726@@ -50,7 +92,7 @@ static inline struct desc_struct *get_cp
17727 * This is the ldt that every process will get unless we need
17728 * something other than this.
17729 */
17730-extern struct desc_struct default_ldt[];
17731+extern const struct desc_struct default_ldt[];
17732 extern void set_intr_gate(unsigned int irq, void * addr);
17733
17734 #define _set_tssldt_desc(n,addr,limit,type) \
17735@@ -64,7 +106,7 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\
17736 "rorl $16,%1" \
17737 : "=m"(*(n)) : "q" (addr), "r"(n), "ir"(limit), "i"(type))
17738
17739-static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
17740+static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
17741 {
17742 _set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr,
17743 offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
17744@@ -72,11 +114,28 @@ static inline void __set_tss_desc(unsign
17745
17746 #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
17747
17748-static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
17749+static inline void __set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size)
17750 {
17751 _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
17752 }
17753
17754+static inline void set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size)
17755+{
17756+
17757+#ifdef CONFIG_PAX_KERNEXEC
17758+ unsigned long cr0;
17759+
17760+ pax_open_kernel(cr0);
17761+#endif
17762+
17763+ _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
17764+
17765+#ifdef CONFIG_PAX_KERNEXEC
17766+ pax_close_kernel(cr0);
17767+#endif
17768+
17769+}
17770+
17771 #define LDT_entry_a(info) \
17772 ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
17773
17774@@ -90,7 +149,7 @@ static inline void set_ldt_desc(unsigned
17775 ((info)->seg_32bit << 22) | \
17776 ((info)->limit_in_pages << 23) | \
17777 ((info)->useable << 20) | \
17778- 0x7000)
17779+ 0x7100)
17780
17781 #define LDT_empty(info) (\
17782 (info)->base_addr == 0 && \
17783@@ -134,7 +193,7 @@ static inline void clear_LDT(void)
17784 */
17785 static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
17786 {
17787- void *segments = pc->ldt;
17788+ const void *segments = pc->ldt;
17789 int count = pc->size;
17790
17791 if (likely(!count)) {
17792@@ -162,6 +221,22 @@ static inline unsigned long get_desc_bas
17793 return base;
17794 }
17795
17796+static inline void _load_LDT(mm_context_t *pc)
17797+{
17798+ int cpu = get_cpu();
17799+ const void *segments = pc->ldt;
17800+ int count = pc->size;
17801+
17802+ if (likely(!count)) {
17803+ segments = &default_ldt[0];
17804+ count = 5;
17805+ }
17806+
17807+ __set_ldt_desc(cpu, segments, count);
17808+ load_LDT_desc();
17809+ put_cpu();
17810+}
17811+
17812 #endif /* !__ASSEMBLY__ */
17813
17814 #endif
17815diff -urNp linux-2.6.16.12/include/asm-i386/elf.h linux-2.6.16.12/include/asm-i386/elf.h
17816--- linux-2.6.16.12/include/asm-i386/elf.h 2006-05-01 15:14:26.000000000 -0400
17817+++ linux-2.6.16.12/include/asm-i386/elf.h 2006-05-01 20:17:34.000000000 -0400
17818@@ -71,7 +71,22 @@ typedef struct user_fxsr_struct elf_fpxr
17819 the loader. We need to make sure that it is out of the way of the program
17820 that it will "exec", and that there is sufficient room for the brk. */
17821
17822+#ifdef CONFIG_PAX_SEGMEXEC
9a4c6ab7 17823+#define ELF_ET_DYN_BASE ((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3*2 : TASK_SIZE/3*2)
89675291 17824+#else
9a4c6ab7 17825 #define ELF_ET_DYN_BASE ((TASK_UNMAPPED_BASE) * 2)
89675291 17826+#endif
17827+
17828+#ifdef CONFIG_PAX_ASLR
17829+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000000UL
17830+
17831+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
17832+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
17833+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
17834+#define PAX_DELTA_EXEC_LEN(tsk) 15
17835+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
17836+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
17837+#endif
17838
17839 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
17840 now struct_user_regs, they are different) */
17841@@ -131,7 +146,14 @@ extern int dump_task_extended_fpu (struc
17842
17843 #define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
17844 #define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
17845+
17846+#ifndef CONFIG_PAX_NOVSYSCALL
17847+#ifdef CONFIG_PAX_SEGMEXEC
17848+#define VSYSCALL_ENTRY ((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? (unsigned long) &__kernel_vsyscall - SEGMEXEC_TASK_SIZE : (unsigned long) &__kernel_vsyscall)
17849+#else
17850 #define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall)
17851+#endif
17852+
17853 extern void __kernel_vsyscall;
17854
17855 #define ARCH_DLINFO \
17856@@ -187,3 +209,5 @@ do { \
17857 #endif
17858
17859 #endif
17860+
17861+#endif
17862diff -urNp linux-2.6.16.12/include/asm-i386/i387.h linux-2.6.16.12/include/asm-i386/i387.h
17863--- linux-2.6.16.12/include/asm-i386/i387.h 2006-05-01 15:14:26.000000000 -0400
17864+++ linux-2.6.16.12/include/asm-i386/i387.h 2006-05-01 20:17:34.000000000 -0400
17865@@ -31,8 +31,8 @@ extern void init_fpu(struct task_struct
17866 */
17867 #define restore_fpu(tsk) \
17868 alternative_input( \
17869- "nop ; frstor %1", \
17870- "fxrstor %1", \
17871+ "nop ; frstor %2", \
17872+ "fxrstor %2", \
17873 X86_FEATURE_FXSR, \
17874 "m" ((tsk)->thread.i387.fxsave))
17875
17876diff -urNp linux-2.6.16.12/include/asm-i386/mach-default/apm.h linux-2.6.16.12/include/asm-i386/mach-default/apm.h
17877--- linux-2.6.16.12/include/asm-i386/mach-default/apm.h 2006-05-01 15:14:26.000000000 -0400
17878+++ linux-2.6.16.12/include/asm-i386/mach-default/apm.h 2006-05-01 20:17:34.000000000 -0400
17879@@ -36,7 +36,7 @@ static inline void apm_bios_call_asm(u32
17880 __asm__ __volatile__(APM_DO_ZERO_SEGS
17881 "pushl %%edi\n\t"
17882 "pushl %%ebp\n\t"
17883- "lcall *%%cs:apm_bios_entry\n\t"
17884+ "lcall *%%ss:apm_bios_entry\n\t"
17885 "setc %%al\n\t"
17886 "popl %%ebp\n\t"
17887 "popl %%edi\n\t"
17888@@ -60,7 +60,7 @@ static inline u8 apm_bios_call_simple_as
17889 __asm__ __volatile__(APM_DO_ZERO_SEGS
17890 "pushl %%edi\n\t"
17891 "pushl %%ebp\n\t"
17892- "lcall *%%cs:apm_bios_entry\n\t"
17893+ "lcall *%%ss:apm_bios_entry\n\t"
17894 "setc %%bl\n\t"
17895 "popl %%ebp\n\t"
17896 "popl %%edi\n\t"
17897diff -urNp linux-2.6.16.12/include/asm-i386/mman.h linux-2.6.16.12/include/asm-i386/mman.h
17898--- linux-2.6.16.12/include/asm-i386/mman.h 2006-05-01 15:14:26.000000000 -0400
17899+++ linux-2.6.16.12/include/asm-i386/mman.h 2006-05-01 20:17:34.000000000 -0400
17900@@ -11,6 +11,10 @@
17901 #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
17902 #define MAP_NONBLOCK 0x10000 /* do not block on IO */
17903
17904+#ifdef CONFIG_PAX_SEGMEXEC
17905+#define MAP_MIRROR 0x20000
17906+#endif
17907+
17908 #define MCL_CURRENT 1 /* lock all current mappings */
17909 #define MCL_FUTURE 2 /* lock all future mappings */
17910
17911diff -urNp linux-2.6.16.12/include/asm-i386/mmu_context.h linux-2.6.16.12/include/asm-i386/mmu_context.h
17912--- linux-2.6.16.12/include/asm-i386/mmu_context.h 2006-05-01 15:14:26.000000000 -0400
17913+++ linux-2.6.16.12/include/asm-i386/mmu_context.h 2006-05-01 20:17:34.000000000 -0400
17914@@ -46,6 +46,13 @@ static inline void switch_mm(struct mm_s
17915 */
17916 if (unlikely(prev->context.ldt != next->context.ldt))
17917 load_LDT_nolock(&next->context, cpu);
17918+
17919+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
17920+ cpu_clear(cpu, prev->context.cpu_user_cs_mask);
17921+ cpu_set(cpu, next->context.cpu_user_cs_mask);
17922+#endif
17923+
17924+ set_user_cs(next, cpu);
17925 }
17926 #ifdef CONFIG_SMP
17927 else {
17928@@ -58,6 +65,12 @@ static inline void switch_mm(struct mm_s
17929 */
17930 load_cr3(next->pgd);
17931 load_LDT_nolock(&next->context, cpu);
17932+
17933+#ifdef CONFIG_PAX_PAGEEXEC
17934+ cpu_set(cpu, next->context.cpu_user_cs_mask);
17935+#endif
17936+
17937+ set_user_cs(next, cpu);
17938 }
17939 }
17940 #endif
17941diff -urNp linux-2.6.16.12/include/asm-i386/mmu.h linux-2.6.16.12/include/asm-i386/mmu.h
17942--- linux-2.6.16.12/include/asm-i386/mmu.h 2006-05-01 15:14:26.000000000 -0400
17943+++ linux-2.6.16.12/include/asm-i386/mmu.h 2006-05-01 20:17:34.000000000 -0400
17944@@ -12,6 +12,17 @@ typedef struct {
17945 int size;
17946 struct semaphore sem;
17947 void *ldt;
17948+
17949+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
17950+ unsigned long user_cs_base;
17951+ unsigned long user_cs_limit;
17952+
17953+#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
17954+ cpumask_t cpu_user_cs_mask;
17955+#endif
17956+
17957+#endif
17958+
17959 } mm_context_t;
17960
17961 #endif
17962diff -urNp linux-2.6.16.12/include/asm-i386/module.h linux-2.6.16.12/include/asm-i386/module.h
17963--- linux-2.6.16.12/include/asm-i386/module.h 2006-05-01 15:14:26.000000000 -0400
17964+++ linux-2.6.16.12/include/asm-i386/module.h 2006-05-01 20:17:34.000000000 -0400
17965@@ -72,6 +72,12 @@ struct mod_arch_specific
17966 #define MODULE_STACKSIZE ""
17967 #endif
17968
17969-#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE
17970+#ifdef CONFIG_GRKERNSEC
17971+#define MODULE_GRSEC "GRSECURITY "
17972+#else
17973+#define MODULE_GRSEC ""
17974+#endif
17975+
17976+#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE MODULE_GRSEC
17977
17978 #endif /* _ASM_I386_MODULE_H */
17979diff -urNp linux-2.6.16.12/include/asm-i386/page.h linux-2.6.16.12/include/asm-i386/page.h
17980--- linux-2.6.16.12/include/asm-i386/page.h 2006-05-01 15:14:26.000000000 -0400
17981+++ linux-2.6.16.12/include/asm-i386/page.h 2006-05-01 20:17:34.000000000 -0400
17982@@ -57,7 +57,6 @@ typedef struct { unsigned long long pgpr
17983 typedef struct { unsigned long pte_low; } pte_t;
17984 typedef struct { unsigned long pgd; } pgd_t;
17985 typedef struct { unsigned long pgprot; } pgprot_t;
17986-#define boot_pte_t pte_t /* or would you rather have a typedef */
17987 #define pte_val(x) ((x).pte_low)
17988 #define HPAGE_SHIFT 22
17989 #endif
9a4c6ab7 17990@@ -113,6 +112,15 @@ extern int page_is_ram(unsigned long pag
17991 #define __PHYSICAL_START CONFIG_PHYSICAL_START
89675291 17992 #define __KERNEL_START (__PAGE_OFFSET + __PHYSICAL_START)
9a4c6ab7 17993 #define __MAXMEM (-__PAGE_OFFSET-__VMALLOC_RESERVE)
89675291 17994+#ifdef CONFIG_PAX_KERNEXEC
17995+#define __KERNEL_TEXT_OFFSET (__PAGE_OFFSET + ((__PHYSICAL_START + ~(4*1024*1024)) & (4*1024*1024)))
17996+#ifndef __ASSEMBLY__
17997+extern unsigned char MODULES_VADDR[];
17998+extern unsigned char MODULES_END[];
17999+#endif
18000+#else
18001+#define __KERNEL_TEXT_OFFSET (0)
18002+#endif
18003
18004 #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
9a4c6ab7 18005 #define PHYSICAL_START ((unsigned long)__PHYSICAL_START)
18006@@ -135,6 +143,19 @@ extern int page_is_ram(unsigned long pag
89675291 18007 ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
18008 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18009
18010+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
18011+#ifdef CONFIG_PAX_MPROTECT
18012+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18013+ ((current->mm->pax_flags & (MF_PAX_PAGEEXEC|MF_PAX_SEGMEXEC))?0:VM_EXEC))
18014+#else
18015+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & (MF_PAX_PAGEEXEC|MF_PAX_SEGMEXEC))?0:VM_EXEC))
18016+#endif
18017+#endif
18018+
18019+#ifdef CONFIG_PAX_PAGEEXEC
18020+#define CONFIG_ARCH_TRACK_EXEC_LIMIT 1
18021+#endif
18022+
18023 #endif /* __KERNEL__ */
18024
18025 #include <asm-generic/page.h>
18026diff -urNp linux-2.6.16.12/include/asm-i386/pgalloc.h linux-2.6.16.12/include/asm-i386/pgalloc.h
18027--- linux-2.6.16.12/include/asm-i386/pgalloc.h 2006-05-01 15:14:26.000000000 -0400
18028+++ linux-2.6.16.12/include/asm-i386/pgalloc.h 2006-05-01 20:17:34.000000000 -0400
18029@@ -3,11 +3,12 @@
18030
18031 #include <linux/config.h>
18032 #include <asm/fixmap.h>
18033+#include <asm/desc.h>
18034 #include <linux/threads.h>
18035 #include <linux/mm.h> /* for struct page */
18036
18037 #define pmd_populate_kernel(mm, pmd, pte) \
18038- set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
18039+ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)))
18040
18041 #define pmd_populate(mm, pmd, pte) \
18042 set_pmd(pmd, __pmd(_PAGE_TABLE + \
18043diff -urNp linux-2.6.16.12/include/asm-i386/pgtable.h linux-2.6.16.12/include/asm-i386/pgtable.h
18044--- linux-2.6.16.12/include/asm-i386/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18045+++ linux-2.6.16.12/include/asm-i386/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18046@@ -34,7 +34,6 @@ struct vm_area_struct;
18047 */
18048 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
18049 extern unsigned long empty_zero_page[1024];
18050-extern pgd_t swapper_pg_dir[1024];
18051 extern kmem_cache_t *pgd_cache;
18052 extern kmem_cache_t *pmd_cache;
18053 extern spinlock_t pgd_lock;
18054@@ -59,6 +58,11 @@ void paging_init(void);
18055 # include <asm/pgtable-2level-defs.h>
18056 #endif
18057
18058+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
18059+#ifdef CONFIG_X86_PAE
18060+extern pmd_t swapper_pm_dir[PTRS_PER_PGD][PTRS_PER_PMD];
18061+#endif
18062+
18063 #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
18064 #define PGDIR_MASK (~(PGDIR_SIZE-1))
18065
18066@@ -68,9 +72,11 @@ void paging_init(void);
18067 #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
18068 #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
18069
18070+#ifndef CONFIG_X86_PAE
18071 #define TWOLEVEL_PGDIR_SHIFT 22
18072 #define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
18073 #define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
18074+#endif
18075
18076 /* Just any arbitrary offset to the start of the vmalloc VM area: the
18077 * current 8MB value just means that there will be a 8MB "hole" after the
18078@@ -141,17 +147,26 @@ void paging_init(void);
18079
18080 #define PAGE_SHARED_EXEC \
18081 __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
18082-#define PAGE_COPY_NOEXEC \
18083- __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
18084 #define PAGE_COPY_EXEC \
18085 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
18086-#define PAGE_COPY \
18087- PAGE_COPY_NOEXEC
18088 #define PAGE_READONLY \
18089 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
18090 #define PAGE_READONLY_EXEC \
18091 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
18092
18093+#ifdef CONFIG_PAX_PAGEEXEC
18094+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED)
18095+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
18096+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
18097+#else
18098+# define PAGE_SHARED_NOEXEC PAGE_SHARED
18099+# define PAGE_COPY_NOEXEC \
18100+ __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
18101+# define PAGE_READONLY_NOEXEC PAGE_READONLY
18102+#endif
18103+
18104+#define PAGE_COPY \
18105+ PAGE_COPY_NOEXEC
18106 #define _PAGE_KERNEL \
18107 (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
18108 #define _PAGE_KERNEL_EXEC \
18109@@ -176,18 +191,18 @@ extern unsigned long long __PAGE_KERNEL,
18110 * This is the closest we can get..
18111 */
18112 #define __P000 PAGE_NONE
18113-#define __P001 PAGE_READONLY
18114-#define __P010 PAGE_COPY
18115-#define __P011 PAGE_COPY
18116+#define __P001 PAGE_READONLY_NOEXEC
18117+#define __P010 PAGE_COPY_NOEXEC
18118+#define __P011 PAGE_COPY_NOEXEC
18119 #define __P100 PAGE_READONLY_EXEC
18120 #define __P101 PAGE_READONLY_EXEC
18121 #define __P110 PAGE_COPY_EXEC
18122 #define __P111 PAGE_COPY_EXEC
18123
18124 #define __S000 PAGE_NONE
18125-#define __S001 PAGE_READONLY
18126-#define __S010 PAGE_SHARED
18127-#define __S011 PAGE_SHARED
18128+#define __S001 PAGE_READONLY_NOEXEC
18129+#define __S010 PAGE_SHARED_NOEXEC
18130+#define __S011 PAGE_SHARED_NOEXEC
18131 #define __S100 PAGE_READONLY_EXEC
18132 #define __S101 PAGE_READONLY_EXEC
18133 #define __S110 PAGE_SHARED_EXEC
18134@@ -432,6 +447,9 @@ extern void noexec_setup(const char *str
18135
18136 #endif /* !__ASSEMBLY__ */
18137
18138+#define HAVE_ARCH_UNMAPPED_AREA
18139+#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
18140+
18141 #ifdef CONFIG_FLATMEM
18142 #define kern_addr_valid(addr) (1)
18143 #endif /* CONFIG_FLATMEM */
18144diff -urNp linux-2.6.16.12/include/asm-i386/processor.h linux-2.6.16.12/include/asm-i386/processor.h
18145--- linux-2.6.16.12/include/asm-i386/processor.h 2006-05-01 15:14:26.000000000 -0400
18146+++ linux-2.6.16.12/include/asm-i386/processor.h 2006-05-01 20:17:34.000000000 -0400
18147@@ -19,7 +19,6 @@
18148 #include <linux/cache.h>
18149 #include <linux/config.h>
18150 #include <linux/threads.h>
18151-#include <asm/percpu.h>
18152
18153 /* flag for disabling the tsc */
18154 extern int tsc_disable;
18155@@ -90,8 +89,6 @@ struct cpuinfo_x86 {
18156
18157 extern struct cpuinfo_x86 boot_cpu_data;
18158 extern struct cpuinfo_x86 new_cpu_data;
18159-extern struct tss_struct doublefault_tss;
18160-DECLARE_PER_CPU(struct tss_struct, init_tss);
18161
18162 #ifdef CONFIG_SMP
18163 extern struct cpuinfo_x86 cpu_data[];
9a4c6ab7 18164@@ -321,10 +318,19 @@ extern int bootloader_type;
18165 #define __TASK_SIZE (__PAGE_OFFSET)
18166 #define TASK_SIZE ((unsigned long)__TASK_SIZE)
89675291 18167
18168+#ifdef CONFIG_PAX_SEGMEXEC
18169+#define SEGMEXEC_TASK_SIZE ((PAGE_OFFSET) / 2)
18170+#endif
18171+
18172 /* This decides where the kernel will search for a free chunk of vm
18173 * space during mmap's.
18174 */
18175+
18176+#ifdef CONFIG_PAX_SEGMEXEC
18177+#define TASK_UNMAPPED_BASE (PAGE_ALIGN((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3 : TASK_SIZE/3))
18178+#else
18179 #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
18180+#endif
18181
18182 #define HAVE_ARCH_PICK_MMAP_LAYOUT
18183
9a4c6ab7 18184@@ -440,6 +446,9 @@ struct tss_struct {
89675291 18185
18186 #define ARCH_MIN_TASKALIGN 16
18187
18188+extern struct tss_struct doublefault_tss;
18189+extern struct tss_struct init_tss[NR_CPUS];
18190+
18191 struct thread_struct {
18192 /* cached TLS descriptors. */
18193 struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
9a4c6ab7 18194@@ -468,6 +477,7 @@ struct thread_struct {
89675291 18195 };
18196
18197 #define INIT_THREAD { \
18198+ .esp0 = sizeof(init_stack) + (long)&init_stack - 8, \
18199 .vm86_info = NULL, \
18200 .sysenter_cs = __KERNEL_CS, \
18201 .io_bitmap_ptr = NULL, \
9a4c6ab7 18202@@ -480,7 +490,7 @@ struct thread_struct {
89675291 18203 * be within the limit.
18204 */
18205 #define INIT_TSS { \
18206- .esp0 = sizeof(init_stack) + (long)&init_stack, \
18207+ .esp0 = sizeof(init_stack) + (long)&init_stack - 8, \
18208 .ss0 = __KERNEL_DS, \
18209 .ss1 = __KERNEL_CS, \
18210 .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
9a4c6ab7 18211@@ -556,11 +566,7 @@ void show_trace(struct task_struct *task
89675291 18212 unsigned long get_wchan(struct task_struct *p);
18213
18214 #define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long))
18215-#define KSTK_TOP(info) \
18216-({ \
18217- unsigned long *__ptr = (unsigned long *)(info); \
18218- (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
18219-})
18220+#define KSTK_TOP(info) ((info)->task.thread.esp0)
18221
18222 /*
18223 * The below -8 is to reserve 8 bytes on top of the ring0 stack.
9a4c6ab7 18224@@ -575,7 +581,7 @@ unsigned long get_wchan(struct task_stru
89675291 18225 #define task_pt_regs(task) \
18226 ({ \
18227 struct pt_regs *__regs__; \
18228- __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
18229+ __regs__ = (struct pt_regs *)((task)->thread.esp0); \
18230 __regs__ - 1; \
18231 })
18232
9a4c6ab7 18233@@ -699,7 +705,7 @@ static inline void rep_nop(void)
89675291 18234 static inline void prefetch(const void *x)
18235 {
18236 alternative_input(ASM_NOP4,
18237- "prefetchnta (%1)",
18238+ "prefetchnta (%2)",
18239 X86_FEATURE_XMM,
18240 "r" (x));
18241 }
9a4c6ab7 18242@@ -713,7 +719,7 @@ static inline void prefetch(const void *
89675291 18243 static inline void prefetchw(const void *x)
18244 {
18245 alternative_input(ASM_NOP4,
18246- "prefetchw (%1)",
18247+ "prefetchw (%2)",
18248 X86_FEATURE_3DNOW,
18249 "r" (x));
18250 }
18251diff -urNp linux-2.6.16.12/include/asm-i386/ptrace.h linux-2.6.16.12/include/asm-i386/ptrace.h
18252--- linux-2.6.16.12/include/asm-i386/ptrace.h 2006-05-01 15:14:26.000000000 -0400
18253+++ linux-2.6.16.12/include/asm-i386/ptrace.h 2006-05-01 20:17:34.000000000 -0400
18254@@ -65,17 +65,18 @@ struct task_struct;
18255 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
18256
18257 /*
18258- * user_mode_vm(regs) determines whether a register set came from user mode.
18259+ * user_mode(regs) determines whether a register set came from user mode.
18260 * This is true if V8086 mode was enabled OR if the register set was from
18261 * protected mode with RPL-3 CS value. This tricky test checks that with
18262 * one comparison. Many places in the kernel can bypass this full check
18263- * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
18264+ * if they have already ruled out V8086 mode, so user_mode_novm(regs) can
18265+ * be used.
18266 */
18267-static inline int user_mode(struct pt_regs *regs)
18268+static inline int user_mode_novm(struct pt_regs *regs)
18269 {
18270 return (regs->xcs & 3) != 0;
18271 }
18272-static inline int user_mode_vm(struct pt_regs *regs)
18273+static inline int user_mode(struct pt_regs *regs)
18274 {
18275 return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0;
18276 }
18277diff -urNp linux-2.6.16.12/include/asm-i386/system.h linux-2.6.16.12/include/asm-i386/system.h
18278--- linux-2.6.16.12/include/asm-i386/system.h 2006-05-01 15:14:26.000000000 -0400
18279+++ linux-2.6.16.12/include/asm-i386/system.h 2006-05-01 20:17:34.000000000 -0400
18280@@ -5,6 +5,7 @@
18281 #include <linux/kernel.h>
18282 #include <asm/segment.h>
18283 #include <asm/cpufeature.h>
18284+#include <asm/page.h>
18285 #include <linux/bitops.h> /* for LOCK_PREFIX */
18286
18287 #ifdef __KERNEL__
18288@@ -151,7 +152,7 @@ static inline unsigned long get_limit(un
18289 unsigned long __limit;
18290 __asm__("lsll %1,%0"
18291 :"=r" (__limit):"r" (segment));
18292- return __limit+1;
18293+ return __limit;
18294 }
18295
18296 #define nop() __asm__ __volatile__ ("nop")
18297@@ -379,15 +380,15 @@ struct alt_instr {
18298 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
18299 ".section .altinstructions,\"a\"\n" \
18300 " .align 4\n" \
18301- " .long 661b\n" /* label */ \
18302+ " .long 661b + %c1\n" /* label */ \
18303 " .long 663f\n" /* new instruction */ \
18304 " .byte %c0\n" /* feature bit */ \
18305 " .byte 662b-661b\n" /* sourcelen */ \
18306 " .byte 664f-663f\n" /* replacementlen */ \
18307 ".previous\n" \
18308- ".section .altinstr_replacement,\"ax\"\n" \
18309+ ".section .altinstr_replacement,\"a\"\n" \
18310 "663:\n\t" newinstr "\n664:\n" /* replacement */ \
18311- ".previous" :: "i" (feature) : "memory")
18312+ ".previous" :: "i" (feature), "i" (__KERNEL_TEXT_OFFSET) : "memory")
18313
18314 /*
18315 * Alternative inline assembly with input.
18316@@ -403,15 +404,15 @@ struct alt_instr {
18317 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
18318 ".section .altinstructions,\"a\"\n" \
18319 " .align 4\n" \
18320- " .long 661b\n" /* label */ \
18321+ " .long 661b + %c1\n" /* label */ \
18322 " .long 663f\n" /* new instruction */ \
18323 " .byte %c0\n" /* feature bit */ \
18324 " .byte 662b-661b\n" /* sourcelen */ \
18325 " .byte 664f-663f\n" /* replacementlen */ \
18326 ".previous\n" \
18327- ".section .altinstr_replacement,\"ax\"\n" \
18328+ ".section .altinstr_replacement,\"a\"\n" \
18329 "663:\n\t" newinstr "\n664:\n" /* replacement */ \
18330- ".previous" :: "i" (feature), ##input)
18331+ ".previous" :: "i" (feature), "i" (__KERNEL_TEXT_OFFSET), ##input)
18332
18333 /*
18334 * Force strict CPU ordering.
18335@@ -557,6 +558,6 @@ static inline void sched_cacheflush(void
18336 wbinvd();
18337 }
18338
18339-extern unsigned long arch_align_stack(unsigned long sp);
18340+#define arch_align_stack(x) (x)
18341
18342 #endif
18343diff -urNp linux-2.6.16.12/include/asm-ia64/elf.h linux-2.6.16.12/include/asm-ia64/elf.h
18344--- linux-2.6.16.12/include/asm-ia64/elf.h 2006-05-01 15:14:26.000000000 -0400
18345+++ linux-2.6.16.12/include/asm-ia64/elf.h 2006-05-01 20:17:34.000000000 -0400
18346@@ -163,6 +163,16 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR
18347 typedef struct ia64_fpreg elf_fpreg_t;
18348 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
18349
18350+#ifdef CONFIG_PAX_ASLR
18351+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
18352+
18353+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18354+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
18355+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18356+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
18357+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18358+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
18359+#endif
18360
18361
18362 struct pt_regs; /* forward declaration... */
18363diff -urNp linux-2.6.16.12/include/asm-ia64/page.h linux-2.6.16.12/include/asm-ia64/page.h
18364--- linux-2.6.16.12/include/asm-ia64/page.h 2006-05-01 15:14:26.000000000 -0400
18365+++ linux-2.6.16.12/include/asm-ia64/page.h 2006-05-01 20:17:34.000000000 -0400
18366@@ -219,4 +219,13 @@ get_order (unsigned long size)
18367 (((current->personality & READ_IMPLIES_EXEC) != 0) \
18368 ? VM_EXEC : 0))
18369
18370+#ifdef CONFIG_PAX_PAGEEXEC
18371+#ifdef CONFIG_PAX_MPROTECT
18372+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18373+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18374+#else
18375+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18376+#endif
18377+#endif
18378+
18379 #endif /* _ASM_IA64_PAGE_H */
18380diff -urNp linux-2.6.16.12/include/asm-ia64/pgtable.h linux-2.6.16.12/include/asm-ia64/pgtable.h
18381--- linux-2.6.16.12/include/asm-ia64/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18382+++ linux-2.6.16.12/include/asm-ia64/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18383@@ -144,6 +144,17 @@
18384 #define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
18385 #define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
18386 #define PAGE_COPY_EXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX)
18387+
18388+#ifdef CONFIG_PAX_PAGEEXEC
18389+# define PAGE_SHARED_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW)
18390+# define PAGE_READONLY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
18391+# define PAGE_COPY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
18392+#else
18393+# define PAGE_SHARED_NOEXEC PAGE_SHARED
18394+# define PAGE_READONLY_NOEXEC PAGE_READONLY
18395+# define PAGE_COPY_NOEXEC PAGE_COPY
18396+#endif
18397+
18398 #define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
18399 #define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX)
18400 #define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX)
18401diff -urNp linux-2.6.16.12/include/asm-ia64/processor.h linux-2.6.16.12/include/asm-ia64/processor.h
18402--- linux-2.6.16.12/include/asm-ia64/processor.h 2006-05-01 15:14:26.000000000 -0400
18403+++ linux-2.6.16.12/include/asm-ia64/processor.h 2006-05-01 20:17:34.000000000 -0400
18404@@ -284,7 +284,7 @@ struct thread_struct {
18405 .on_ustack = 0, \
18406 .ksp = 0, \
18407 .map_base = DEFAULT_MAP_BASE, \
18408- .rbs_bot = STACK_TOP - DEFAULT_USER_STACK_SIZE, \
18409+ .rbs_bot = __STACK_TOP - DEFAULT_USER_STACK_SIZE, \
18410 .task_size = DEFAULT_TASK_SIZE, \
18411 .last_fph_cpu = -1, \
18412 INIT_THREAD_IA32 \
18413diff -urNp linux-2.6.16.12/include/asm-ia64/ustack.h linux-2.6.16.12/include/asm-ia64/ustack.h
18414--- linux-2.6.16.12/include/asm-ia64/ustack.h 2006-05-01 15:14:26.000000000 -0400
18415+++ linux-2.6.16.12/include/asm-ia64/ustack.h 2006-05-01 20:17:34.000000000 -0400
18416@@ -11,6 +11,6 @@
18417 #define MAX_USER_STACK_SIZE (RGN_MAP_LIMIT/2)
18418 /* Make a default stack size of 2GB */
18419 #define DEFAULT_USER_STACK_SIZE (1UL << 31)
18420-#define STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT)
18421+#define __STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT)
18422
18423 #endif /* _ASM_IA64_USTACK_H */
18424diff -urNp linux-2.6.16.12/include/asm-mips/a.out.h linux-2.6.16.12/include/asm-mips/a.out.h
18425--- linux-2.6.16.12/include/asm-mips/a.out.h 2006-05-01 15:14:26.000000000 -0400
18426+++ linux-2.6.16.12/include/asm-mips/a.out.h 2006-05-01 20:17:34.000000000 -0400
18427@@ -36,10 +36,10 @@ struct exec
18428 #ifdef __KERNEL__
18429
18430 #ifdef CONFIG_32BIT
18431-#define STACK_TOP TASK_SIZE
18432+#define __STACK_TOP TASK_SIZE
18433 #endif
18434 #ifdef CONFIG_64BIT
18435-#define STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
18436+#define __STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
18437 #endif
18438
18439 #endif
18440diff -urNp linux-2.6.16.12/include/asm-mips/elf.h linux-2.6.16.12/include/asm-mips/elf.h
18441--- linux-2.6.16.12/include/asm-mips/elf.h 2006-05-01 15:14:26.000000000 -0400
18442+++ linux-2.6.16.12/include/asm-mips/elf.h 2006-05-01 20:17:34.000000000 -0400
18443@@ -331,4 +331,15 @@ extern int dump_task_fpu(struct task_str
18444 #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
18445 #endif
18446
18447+#ifdef CONFIG_PAX_ASLR
18448+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
18449+
18450+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18451+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
18452+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18453+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
18454+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18455+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
18456+#endif
18457+
18458 #endif /* _ASM_ELF_H */
18459diff -urNp linux-2.6.16.12/include/asm-mips/page.h linux-2.6.16.12/include/asm-mips/page.h
18460--- linux-2.6.16.12/include/asm-mips/page.h 2006-05-01 15:14:26.000000000 -0400
18461+++ linux-2.6.16.12/include/asm-mips/page.h 2006-05-01 20:17:34.000000000 -0400
18462@@ -151,6 +151,15 @@ typedef struct { unsigned long pgprot; }
18463 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
18464 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18465
18466+#ifdef CONFIG_PAX_PAGEEXEC
18467+#ifdef CONFIG_PAX_MPROTECT
18468+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18469+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18470+#else
18471+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18472+#endif
18473+#endif
18474+
18475 #define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE)
18476 #define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET)
18477
18478diff -urNp linux-2.6.16.12/include/asm-parisc/a.out.h linux-2.6.16.12/include/asm-parisc/a.out.h
18479--- linux-2.6.16.12/include/asm-parisc/a.out.h 2006-05-01 15:14:26.000000000 -0400
18480+++ linux-2.6.16.12/include/asm-parisc/a.out.h 2006-05-01 20:17:34.000000000 -0400
18481@@ -22,7 +22,7 @@ struct exec
18482 /* XXX: STACK_TOP actually should be STACK_BOTTOM for parisc.
18483 * prumpf */
18484
18485-#define STACK_TOP TASK_SIZE
18486+#define __STACK_TOP TASK_SIZE
18487
18488 #endif
18489
18490diff -urNp linux-2.6.16.12/include/asm-parisc/elf.h linux-2.6.16.12/include/asm-parisc/elf.h
18491--- linux-2.6.16.12/include/asm-parisc/elf.h 2006-05-01 15:14:26.000000000 -0400
18492+++ linux-2.6.16.12/include/asm-parisc/elf.h 2006-05-01 20:17:34.000000000 -0400
18493@@ -337,6 +337,17 @@ struct pt_regs; /* forward declaration..
18494
18495 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000)
18496
18497+#ifdef CONFIG_PAX_ASLR
18498+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000UL
18499+
18500+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18501+#define PAX_DELTA_MMAP_LEN(tsk) 16
18502+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18503+#define PAX_DELTA_EXEC_LEN(tsk) 16
18504+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18505+#define PAX_DELTA_STACK_LEN(tsk) 16
18506+#endif
18507+
18508 /* This yields a mask that user programs can use to figure out what
18509 instruction set this CPU supports. This could be done in user space,
18510 but it's not easy, and we've already done it here. */
18511diff -urNp linux-2.6.16.12/include/asm-parisc/page.h linux-2.6.16.12/include/asm-parisc/page.h
18512--- linux-2.6.16.12/include/asm-parisc/page.h 2006-05-01 15:14:26.000000000 -0400
18513+++ linux-2.6.16.12/include/asm-parisc/page.h 2006-05-01 20:17:34.000000000 -0400
18514@@ -150,6 +150,15 @@ extern int npmem_ranges;
18515 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
18516 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18517
18518+#ifdef CONFIG_PAX_PAGEEXEC
18519+#ifdef CONFIG_PAX_MPROTECT
18520+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18521+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18522+#else
18523+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18524+#endif
18525+#endif
18526+
18527 #endif /* __KERNEL__ */
18528
18529 #include <asm-generic/page.h>
18530diff -urNp linux-2.6.16.12/include/asm-parisc/pgtable.h linux-2.6.16.12/include/asm-parisc/pgtable.h
18531--- linux-2.6.16.12/include/asm-parisc/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18532+++ linux-2.6.16.12/include/asm-parisc/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18533@@ -212,6 +212,17 @@ extern void *vmalloc_start;
18534 #define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED)
18535 #define PAGE_COPY PAGE_EXECREAD
18536 #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED)
18537+
18538+#ifdef CONFIG_PAX_PAGEEXEC
18539+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_ACCESSED)
18540+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
18541+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
18542+#else
18543+# define PAGE_SHARED_NOEXEC PAGE_SHARED
18544+# define PAGE_COPY_NOEXEC PAGE_COPY
18545+# define PAGE_READONLY_NOEXEC PAGE_READONLY
18546+#endif
18547+
18548 #define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
18549 #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
18550 #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
18551diff -urNp linux-2.6.16.12/include/asm-powerpc/a.out.h linux-2.6.16.12/include/asm-powerpc/a.out.h
18552--- linux-2.6.16.12/include/asm-powerpc/a.out.h 2006-05-01 15:14:26.000000000 -0400
18553+++ linux-2.6.16.12/include/asm-powerpc/a.out.h 2006-05-01 20:17:34.000000000 -0400
18554@@ -23,12 +23,12 @@ struct exec
18555 #define STACK_TOP_USER64 TASK_SIZE_USER64
18556 #define STACK_TOP_USER32 TASK_SIZE_USER32
18557
18558-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
18559+#define __STACK_TOP (test_thread_flag(TIF_32BIT) ? \
18560 STACK_TOP_USER32 : STACK_TOP_USER64)
18561
18562 #else /* __powerpc64__ */
18563
18564-#define STACK_TOP TASK_SIZE
18565+#define __STACK_TOP TASK_SIZE
18566
18567 #endif /* __powerpc64__ */
18568 #endif /* __KERNEL__ */
18569diff -urNp linux-2.6.16.12/include/asm-powerpc/elf.h linux-2.6.16.12/include/asm-powerpc/elf.h
18570--- linux-2.6.16.12/include/asm-powerpc/elf.h 2006-05-01 15:14:26.000000000 -0400
18571+++ linux-2.6.16.12/include/asm-powerpc/elf.h 2006-05-01 20:17:34.000000000 -0400
18572@@ -176,6 +176,26 @@ typedef elf_vrreg_t elf_vrregset_t32[ELF
18573
18574 #define ELF_ET_DYN_BASE (0x08000000)
18575
18576+#ifdef CONFIG_PAX_ASLR
18577+#define PAX_ELF_ET_DYN_BASE(tsk) (0x10000000UL)
18578+
18579+#ifdef __powerpc64__
18580+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18581+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
18582+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18583+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
18584+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18585+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
18586+#else
18587+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18588+#define PAX_DELTA_MMAP_LEN(tsk) 15
18589+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18590+#define PAX_DELTA_EXEC_LEN(tsk) 15
18591+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18592+#define PAX_DELTA_STACK_LEN(tsk) 15
18593+#endif
18594+#endif
18595+
18596 #ifdef __KERNEL__
18597
18598 /* Common routine for both 32-bit and 64-bit processes */
18599diff -urNp linux-2.6.16.12/include/asm-powerpc/page_64.h linux-2.6.16.12/include/asm-powerpc/page_64.h
18600--- linux-2.6.16.12/include/asm-powerpc/page_64.h 2006-05-01 15:14:26.000000000 -0400
18601+++ linux-2.6.16.12/include/asm-powerpc/page_64.h 2006-05-01 20:17:34.000000000 -0400
18602@@ -169,6 +169,15 @@ extern unsigned int HPAGE_SHIFT;
18603 (test_thread_flag(TIF_32BIT) ? \
18604 VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
18605
18606+#ifdef CONFIG_PAX_PAGEEXEC
18607+#ifdef CONFIG_PAX_MPROTECT
18608+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18609+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18610+#else
18611+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18612+#endif
18613+#endif
18614+
18615 #include <asm-generic/page.h>
18616
18617 #endif /* __KERNEL__ */
18618diff -urNp linux-2.6.16.12/include/asm-ppc/page.h linux-2.6.16.12/include/asm-ppc/page.h
18619--- linux-2.6.16.12/include/asm-ppc/page.h 2006-05-01 15:14:26.000000000 -0400
18620+++ linux-2.6.16.12/include/asm-ppc/page.h 2006-05-01 20:17:34.000000000 -0400
18621@@ -175,5 +175,14 @@ extern __inline__ int get_order(unsigned
18622 /* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */
18623 #define __HAVE_ARCH_GATE_AREA 1
18624
18625+#ifdef CONFIG_PAX_PAGEEXEC
18626+#ifdef CONFIG_PAX_MPROTECT
18627+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18628+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18629+#else
18630+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18631+#endif
18632+#endif
18633+
18634 #endif /* __KERNEL__ */
18635 #endif /* _PPC_PAGE_H */
18636diff -urNp linux-2.6.16.12/include/asm-ppc/pgtable.h linux-2.6.16.12/include/asm-ppc/pgtable.h
18637--- linux-2.6.16.12/include/asm-ppc/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18638+++ linux-2.6.16.12/include/asm-ppc/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18639@@ -441,11 +441,21 @@ extern unsigned long ioremap_bot, iorema
18640
18641 #define PAGE_NONE __pgprot(_PAGE_BASE)
18642 #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
18643-#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
18644+#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC)
18645 #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
18646-#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
18647+#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC | _PAGE_HWEXEC)
18648 #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
18649-#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
18650+#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC)
18651+
18652+#if defined(CONFIG_PAX_PAGEEXEC) && !defined(CONFIG_40x) && !defined(CONFIG_44x)
18653+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_GUARDED)
18654+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
18655+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
18656+#else
18657+# define PAGE_SHARED_NOEXEC PAGE_SHARED
18658+# define PAGE_COPY_NOEXEC PAGE_COPY
18659+# define PAGE_READONLY_NOEXEC PAGE_READONLY
18660+#endif
18661
18662 #define PAGE_KERNEL __pgprot(_PAGE_RAM)
18663 #define PAGE_KERNEL_NOCACHE __pgprot(_PAGE_IO)
18664@@ -457,21 +467,21 @@ extern unsigned long ioremap_bot, iorema
18665 * This is the closest we can get..
18666 */
18667 #define __P000 PAGE_NONE
18668-#define __P001 PAGE_READONLY_X
18669-#define __P010 PAGE_COPY
18670-#define __P011 PAGE_COPY_X
18671-#define __P100 PAGE_READONLY
18672+#define __P001 PAGE_READONLY_NOEXEC
18673+#define __P010 PAGE_COPY_NOEXEC
18674+#define __P011 PAGE_COPY_NOEXEC
18675+#define __P100 PAGE_READONLY_X
18676 #define __P101 PAGE_READONLY_X
18677-#define __P110 PAGE_COPY
18678+#define __P110 PAGE_COPY_X
18679 #define __P111 PAGE_COPY_X
18680
18681 #define __S000 PAGE_NONE
18682-#define __S001 PAGE_READONLY_X
18683-#define __S010 PAGE_SHARED
18684-#define __S011 PAGE_SHARED_X
18685-#define __S100 PAGE_READONLY
18686+#define __S001 PAGE_READONLY_NOEXEC
18687+#define __S010 PAGE_SHARED_NOEXEC
18688+#define __S011 PAGE_SHARED_NOEXEC
18689+#define __S100 PAGE_READONLY_X
18690 #define __S101 PAGE_READONLY_X
18691-#define __S110 PAGE_SHARED
18692+#define __S110 PAGE_SHARED_X
18693 #define __S111 PAGE_SHARED_X
18694
18695 #ifndef __ASSEMBLY__
18696diff -urNp linux-2.6.16.12/include/asm-sparc/a.out.h linux-2.6.16.12/include/asm-sparc/a.out.h
18697--- linux-2.6.16.12/include/asm-sparc/a.out.h 2006-05-01 15:14:26.000000000 -0400
18698+++ linux-2.6.16.12/include/asm-sparc/a.out.h 2006-05-01 20:17:34.000000000 -0400
18699@@ -91,7 +91,7 @@ struct relocation_info /* used when head
18700
18701 #include <asm/page.h>
18702
18703-#define STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
18704+#define __STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
18705
18706 #endif /* __KERNEL__ */
18707
18708diff -urNp linux-2.6.16.12/include/asm-sparc/elf.h linux-2.6.16.12/include/asm-sparc/elf.h
18709--- linux-2.6.16.12/include/asm-sparc/elf.h 2006-05-01 15:14:26.000000000 -0400
18710+++ linux-2.6.16.12/include/asm-sparc/elf.h 2006-05-01 20:17:34.000000000 -0400
18711@@ -145,6 +145,17 @@ typedef struct {
18712
18713 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE)
18714
18715+#ifdef CONFIG_PAX_ASLR
18716+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000UL
18717+
18718+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18719+#define PAX_DELTA_MMAP_LEN(tsk) 16
18720+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18721+#define PAX_DELTA_EXEC_LEN(tsk) 16
18722+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18723+#define PAX_DELTA_STACK_LEN(tsk) 16
18724+#endif
18725+
18726 /* This yields a mask that user programs can use to figure out what
18727 instruction set this cpu supports. This can NOT be done in userspace
18728 on Sparc. */
18729diff -urNp linux-2.6.16.12/include/asm-sparc/page.h linux-2.6.16.12/include/asm-sparc/page.h
18730--- linux-2.6.16.12/include/asm-sparc/page.h 2006-05-01 15:14:26.000000000 -0400
18731+++ linux-2.6.16.12/include/asm-sparc/page.h 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 18732@@ -164,6 +164,15 @@ extern unsigned long pfn_base;
89675291 18733 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
18734 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18735
18736+#ifdef CONFIG_PAX_PAGEEXEC
18737+#ifdef CONFIG_PAX_MPROTECT
18738+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18739+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18740+#else
18741+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18742+#endif
18743+#endif
18744+
18745 #endif /* __KERNEL__ */
18746
18747 #include <asm-generic/page.h>
18748diff -urNp linux-2.6.16.12/include/asm-sparc/pgtable.h linux-2.6.16.12/include/asm-sparc/pgtable.h
18749--- linux-2.6.16.12/include/asm-sparc/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18750+++ linux-2.6.16.12/include/asm-sparc/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18751@@ -50,6 +50,13 @@ BTFIXUPDEF_INT(page_none)
18752 BTFIXUPDEF_INT(page_shared)
18753 BTFIXUPDEF_INT(page_copy)
18754 BTFIXUPDEF_INT(page_readonly)
18755+
18756+#ifdef CONFIG_PAX_PAGEEXEC
18757+BTFIXUPDEF_INT(page_shared_noexec)
18758+BTFIXUPDEF_INT(page_copy_noexec)
18759+BTFIXUPDEF_INT(page_readonly_noexec)
18760+#endif
18761+
18762 BTFIXUPDEF_INT(page_kernel)
18763
18764 #define PMD_SHIFT SUN4C_PMD_SHIFT
18765@@ -71,6 +78,16 @@ BTFIXUPDEF_INT(page_kernel)
18766 #define PAGE_COPY __pgprot(BTFIXUP_INT(page_copy))
18767 #define PAGE_READONLY __pgprot(BTFIXUP_INT(page_readonly))
18768
18769+#ifdef CONFIG_PAX_PAGEEXEC
18770+# define PAGE_SHARED_NOEXEC __pgprot(BTFIXUP_INT(page_shared_noexec))
18771+# define PAGE_COPY_NOEXEC __pgprot(BTFIXUP_INT(page_copy_noexec))
18772+# define PAGE_READONLY_NOEXEC __pgprot(BTFIXUP_INT(page_readonly_noexec))
18773+#else
18774+# define PAGE_SHARED_NOEXEC PAGE_SHARED
18775+# define PAGE_COPY_NOEXEC PAGE_COPY
18776+# define PAGE_READONLY_NOEXEC PAGE_READONLY
18777+#endif
18778+
18779 extern unsigned long page_kernel;
18780
18781 #ifdef MODULE
18782diff -urNp linux-2.6.16.12/include/asm-sparc/pgtsrmmu.h linux-2.6.16.12/include/asm-sparc/pgtsrmmu.h
18783--- linux-2.6.16.12/include/asm-sparc/pgtsrmmu.h 2006-05-01 15:14:26.000000000 -0400
18784+++ linux-2.6.16.12/include/asm-sparc/pgtsrmmu.h 2006-05-01 20:17:34.000000000 -0400
18785@@ -115,6 +115,16 @@
18786 SRMMU_EXEC | SRMMU_REF)
18787 #define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \
18788 SRMMU_EXEC | SRMMU_REF)
18789+
18790+#ifdef CONFIG_PAX_PAGEEXEC
18791+#define SRMMU_PAGE_SHARED_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
18792+ SRMMU_WRITE | SRMMU_REF)
18793+#define SRMMU_PAGE_COPY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
18794+ SRMMU_REF)
18795+#define SRMMU_PAGE_RDONLY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
18796+ SRMMU_REF)
18797+#endif
18798+
18799 #define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \
18800 SRMMU_DIRTY | SRMMU_REF)
18801
18802diff -urNp linux-2.6.16.12/include/asm-sparc/uaccess.h linux-2.6.16.12/include/asm-sparc/uaccess.h
18803--- linux-2.6.16.12/include/asm-sparc/uaccess.h 2006-05-01 15:14:26.000000000 -0400
18804+++ linux-2.6.16.12/include/asm-sparc/uaccess.h 2006-05-01 20:17:34.000000000 -0400
18805@@ -41,7 +41,7 @@
18806 * No one can read/write anything from userland in the kernel space by setting
18807 * large size and address near to PAGE_OFFSET - a fault will break his intentions.
18808 */
18809-#define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; })
18810+#define __user_ok(addr, size) ({ (void)(size); (addr) < __STACK_TOP; })
18811 #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
18812 #define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
18813 #define access_ok(type, addr, size) \
18814diff -urNp linux-2.6.16.12/include/asm-sparc64/a.out.h linux-2.6.16.12/include/asm-sparc64/a.out.h
18815--- linux-2.6.16.12/include/asm-sparc64/a.out.h 2006-05-01 15:14:26.000000000 -0400
18816+++ linux-2.6.16.12/include/asm-sparc64/a.out.h 2006-05-01 20:17:34.000000000 -0400
18817@@ -95,7 +95,7 @@ struct relocation_info /* used when head
18818
18819 #ifdef __KERNEL__
18820
18821-#define STACK_TOP (test_thread_flag(TIF_32BIT) ? 0xf0000000 : 0x80000000000L)
18822+#define __STACK_TOP (test_thread_flag(TIF_32BIT) ? 0xf0000000 : 0x80000000000L)
18823
18824 #endif
18825
18826diff -urNp linux-2.6.16.12/include/asm-sparc64/elf.h linux-2.6.16.12/include/asm-sparc64/elf.h
18827--- linux-2.6.16.12/include/asm-sparc64/elf.h 2006-05-01 15:14:26.000000000 -0400
18828+++ linux-2.6.16.12/include/asm-sparc64/elf.h 2006-05-01 20:17:34.000000000 -0400
18829@@ -140,6 +140,16 @@ typedef struct {
18830 #define ELF_ET_DYN_BASE 0x0000010000000000UL
18831 #endif
18832
18833+#ifdef CONFIG_PAX_ASLR
18834+#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_32BIT) ? 0x10000UL : 0x100000UL)
18835+
18836+#define PAX_DELTA_MMAP_LSB(tsk) (PAGE_SHIFT + 1)
18837+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 14 : 28 )
18838+#define PAX_DELTA_EXEC_LSB(tsk) (PAGE_SHIFT + 1)
18839+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 14 : 28 )
18840+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18841+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 15 : 29 )
18842+#endif
18843
18844 /* This yields a mask that user programs can use to figure out what
18845 instruction set this cpu supports. */
18846diff -urNp linux-2.6.16.12/include/asm-sparc64/page.h linux-2.6.16.12/include/asm-sparc64/page.h
18847--- linux-2.6.16.12/include/asm-sparc64/page.h 2006-05-01 15:14:26.000000000 -0400
18848+++ linux-2.6.16.12/include/asm-sparc64/page.h 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 18849@@ -147,6 +147,15 @@ extern unsigned long page_to_pfn(struct
89675291 18850 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
18851 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18852
18853+#ifdef CONFIG_PAX_PAGEEXEC
18854+#ifdef CONFIG_PAX_MPROTECT
18855+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18856+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18857+#else
18858+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18859+#endif
18860+#endif
18861+
18862 #endif /* !(__KERNEL__) */
18863
18864 #include <asm-generic/page.h>
18865diff -urNp linux-2.6.16.12/include/asm-x86_64/a.out.h linux-2.6.16.12/include/asm-x86_64/a.out.h
18866--- linux-2.6.16.12/include/asm-x86_64/a.out.h 2006-05-01 15:14:26.000000000 -0400
18867+++ linux-2.6.16.12/include/asm-x86_64/a.out.h 2006-05-01 20:17:34.000000000 -0400
18868@@ -21,7 +21,7 @@ struct exec
18869
18870 #ifdef __KERNEL__
18871 #include <linux/thread_info.h>
18872-#define STACK_TOP TASK_SIZE
18873+#define __STACK_TOP TASK_SIZE
18874 #endif
18875
18876 #endif /* __A_OUT_GNU_H__ */
18877diff -urNp linux-2.6.16.12/include/asm-x86_64/elf.h linux-2.6.16.12/include/asm-x86_64/elf.h
18878--- linux-2.6.16.12/include/asm-x86_64/elf.h 2006-05-01 15:14:26.000000000 -0400
18879+++ linux-2.6.16.12/include/asm-x86_64/elf.h 2006-05-01 20:17:34.000000000 -0400
18880@@ -89,6 +89,17 @@ typedef struct user_i387_struct elf_fpre
18881
18882 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
18883
18884+#ifdef CONFIG_PAX_ASLR
18885+#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_IA32) ? 0x08048000UL : 0x400000UL)
18886+
18887+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18888+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
18889+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18890+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
18891+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18892+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
18893+#endif
18894+
18895 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
18896 now struct_user_regs, they are different). Assumes current is the process
18897 getting dumped. */
18898diff -urNp linux-2.6.16.12/include/asm-x86_64/ia32.h linux-2.6.16.12/include/asm-x86_64/ia32.h
18899--- linux-2.6.16.12/include/asm-x86_64/ia32.h 2006-05-01 15:14:26.000000000 -0400
18900+++ linux-2.6.16.12/include/asm-x86_64/ia32.h 2006-05-01 20:17:34.000000000 -0400
18901@@ -157,7 +157,13 @@ struct ustat32 {
18902 char f_fpack[6];
18903 };
18904
18905-#define IA32_STACK_TOP IA32_PAGE_OFFSET
18906+#ifdef CONFIG_PAX_RANDUSTACK
18907+#define IA32_DELTA_STACK (current->mm->delta_stack)
18908+#else
18909+#define IA32_DELTA_STACK 0UL
18910+#endif
18911+
18912+#define IA32_STACK_TOP (IA32_PAGE_OFFSET - IA32_DELTA_STACK)
18913
18914 #ifdef __KERNEL__
18915 struct user_desc;
18916diff -urNp linux-2.6.16.12/include/asm-x86_64/page.h linux-2.6.16.12/include/asm-x86_64/page.h
18917--- linux-2.6.16.12/include/asm-x86_64/page.h 2006-05-01 15:14:26.000000000 -0400
18918+++ linux-2.6.16.12/include/asm-x86_64/page.h 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 18919@@ -138,6 +138,15 @@ typedef struct { unsigned long pgprot; }
89675291 18920 (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
18921 VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18922
18923+#ifdef CONFIG_PAX_PAGEEXEC
18924+#ifdef CONFIG_PAX_MPROTECT
18925+#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18926+ ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18927+#else
18928+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18929+#endif
18930+#endif
18931+
18932 #define __HAVE_ARCH_GATE_AREA 1
18933
18934 #endif /* __KERNEL__ */
18935diff -urNp linux-2.6.16.12/include/asm-x86_64/pgalloc.h linux-2.6.16.12/include/asm-x86_64/pgalloc.h
18936--- linux-2.6.16.12/include/asm-x86_64/pgalloc.h 2006-05-01 15:14:26.000000000 -0400
18937+++ linux-2.6.16.12/include/asm-x86_64/pgalloc.h 2006-05-01 20:17:34.000000000 -0400
18938@@ -7,7 +7,7 @@
18939 #include <linux/mm.h>
18940
18941 #define pmd_populate_kernel(mm, pmd, pte) \
18942- set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
18943+ set_pmd(pmd, __pmd(_KERNPG_TABLE | __pa(pte)))
18944 #define pud_populate(mm, pud, pmd) \
18945 set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)))
18946 #define pgd_populate(mm, pgd, pud) \
18947diff -urNp linux-2.6.16.12/include/asm-x86_64/pgtable.h linux-2.6.16.12/include/asm-x86_64/pgtable.h
18948--- linux-2.6.16.12/include/asm-x86_64/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18949+++ linux-2.6.16.12/include/asm-x86_64/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18950@@ -180,6 +180,10 @@ static inline pte_t ptep_get_and_clear_f
18951 #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
18952 #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
18953 #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
18954+
18955+#define PAGE_READONLY_NOEXEC PAGE_READONLY
18956+#define PAGE_SHARED_NOEXEC PAGE_SHARED
18957+
18958 #define __PAGE_KERNEL \
18959 (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
18960 #define __PAGE_KERNEL_EXEC \
18961@@ -268,7 +272,13 @@ static inline pte_t pfn_pte(unsigned lon
18962 #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
18963 static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
18964 static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
18965-static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
18966+extern inline int pte_exec(pte_t pte)
18967+{
18968+ if (__supported_pte_mask & _PAGE_NX)
18969+ return pte_val(pte) & _PAGE_NX;
18970+ else
18971+ return pte_val(pte) & _PAGE_USER;
18972+}
18973 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
18974 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
18975 static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
18976@@ -276,12 +286,26 @@ static inline int pte_file(pte_t pte) {
18977 static inline int pte_huge(pte_t pte) { return (pte_val(pte) & __LARGE_PTE) == __LARGE_PTE; }
18978
18979 static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
18980-static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
18981+extern inline pte_t pte_exprotect(pte_t pte)
18982+{
18983+ if (__supported_pte_mask & _PAGE_NX)
18984+ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_NX));
18985+ else
18986+ set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER));
18987+ return pte;
18988+}
18989 static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
18990 static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
18991 static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
18992 static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
18993-static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
18994+extern inline pte_t pte_mkexec(pte_t pte)
18995+{
18996+ if (__supported_pte_mask & _PAGE_NX)
18997+ set_pte(&pte, __pte(pte_val(pte) | _PAGE_NX));
18998+ else
18999+ set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER));
19000+ return pte;
19001+}
19002 static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
19003 static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
19004 static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
19005diff -urNp linux-2.6.16.12/include/asm-x86_64/system.h linux-2.6.16.12/include/asm-x86_64/system.h
19006--- linux-2.6.16.12/include/asm-x86_64/system.h 2006-05-01 15:14:26.000000000 -0400
19007+++ linux-2.6.16.12/include/asm-x86_64/system.h 2006-05-01 20:17:34.000000000 -0400
19008@@ -372,6 +372,6 @@ static inline unsigned long __cmpxchg(vo
19009
19010 void cpu_idle_wait(void);
19011
19012-extern unsigned long arch_align_stack(unsigned long sp);
19013+#define arch_align_stack(x) (x)
19014
19015 #endif
19016diff -urNp linux-2.6.16.12/include/linux/a.out.h linux-2.6.16.12/include/linux/a.out.h
19017--- linux-2.6.16.12/include/linux/a.out.h 2006-05-01 15:14:26.000000000 -0400
19018+++ linux-2.6.16.12/include/linux/a.out.h 2006-05-01 20:17:34.000000000 -0400
19019@@ -7,6 +7,16 @@
19020
19021 #include <asm/a.out.h>
19022
19023+#ifdef CONFIG_PAX_RANDUSTACK
19024+#define __DELTA_STACK (current->mm->delta_stack)
19025+#else
19026+#define __DELTA_STACK 0UL
19027+#endif
19028+
19029+#ifndef STACK_TOP
19030+#define STACK_TOP (__STACK_TOP - __DELTA_STACK)
19031+#endif
19032+
19033 #endif /* __STRUCT_EXEC_OVERRIDE__ */
19034
19035 /* these go in the N_MACHTYPE field */
19036@@ -37,6 +47,14 @@ enum machine_type {
19037 M_MIPS2 = 152 /* MIPS R6000/R4000 binary */
19038 };
19039
19040+/* Constants for the N_FLAGS field */
19041+#define F_PAX_PAGEEXEC 1 /* Paging based non-executable pages */
19042+#define F_PAX_EMUTRAMP 2 /* Emulate trampolines */
19043+#define F_PAX_MPROTECT 4 /* Restrict mprotect() */
19044+#define F_PAX_RANDMMAP 8 /* Randomize mmap() base */
19045+/*#define F_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */
19046+#define F_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */
19047+
19048 #if !defined (N_MAGIC)
19049 #define N_MAGIC(exec) ((exec).a_info & 0xffff)
19050 #endif
19051diff -urNp linux-2.6.16.12/include/linux/binfmts.h linux-2.6.16.12/include/linux/binfmts.h
19052--- linux-2.6.16.12/include/linux/binfmts.h 2006-05-01 15:14:26.000000000 -0400
19053+++ linux-2.6.16.12/include/linux/binfmts.h 2006-05-01 20:17:34.000000000 -0400
19054@@ -7,10 +7,10 @@ struct pt_regs;
19055
19056 /*
19057 * MAX_ARG_PAGES defines the number of pages allocated for arguments
19058- * and envelope for the new program. 32 should suffice, this gives
19059- * a maximum env+arg of 128kB w/4KB pages!
19060+ * and envelope for the new program. 33 should suffice, this gives
19061+ * a maximum env+arg of 132kB w/4KB pages!
19062 */
19063-#define MAX_ARG_PAGES 32
19064+#define MAX_ARG_PAGES 33
19065
19066 /* sizeof(linux_binprm->buf) */
19067 #define BINPRM_BUF_SIZE 128
19068@@ -38,6 +38,7 @@ struct linux_binprm{
19069 unsigned interp_flags;
19070 unsigned interp_data;
19071 unsigned long loader, exec;
19072+ int misc;
19073 };
19074
19075 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
19076@@ -87,5 +88,8 @@ extern void compute_creds(struct linux_b
19077 extern int do_coredump(long signr, int exit_code, struct pt_regs * regs);
19078 extern int set_binfmt(struct linux_binfmt *new);
19079
19080+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp);
19081+void pax_report_insns(void *pc, void *sp);
19082+
19083 #endif /* __KERNEL__ */
19084 #endif /* _LINUX_BINFMTS_H */
19085diff -urNp linux-2.6.16.12/include/linux/capability.h linux-2.6.16.12/include/linux/capability.h
19086--- linux-2.6.16.12/include/linux/capability.h 2006-05-01 15:14:26.000000000 -0400
19087+++ linux-2.6.16.12/include/linux/capability.h 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 19088@@ -364,6 +364,7 @@ static inline kernel_cap_t cap_invert(ke
89675291 19089 #define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)
19090
19091 extern int capable(int cap);
19092+extern int capable_nolog(int cap);
19093
19094 #endif /* __KERNEL__ */
19095
19096diff -urNp linux-2.6.16.12/include/linux/elf.h linux-2.6.16.12/include/linux/elf.h
19097--- linux-2.6.16.12/include/linux/elf.h 2006-05-01 15:14:26.000000000 -0400
19098+++ linux-2.6.16.12/include/linux/elf.h 2006-05-01 20:17:34.000000000 -0400
19099@@ -5,6 +5,10 @@
19100 #include <linux/auxvec.h>
19101 #include <asm/elf.h>
19102
19103+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
19104+#undef elf_read_implies_exec
19105+#endif
19106+
19107 #ifndef elf_read_implies_exec
19108 /* Executables for which elf_read_implies_exec() returns TRUE will
19109 have the READ_IMPLIES_EXEC personality flag set automatically.
19110@@ -46,6 +50,16 @@ typedef __s64 Elf64_Sxword;
19111
19112 #define PT_GNU_STACK (PT_LOOS + 0x474e551)
19113
19114+#define PT_PAX_FLAGS (PT_LOOS + 0x5041580)
19115+
19116+/* Constants for the e_flags field */
19117+#define EF_PAX_PAGEEXEC 1 /* Paging based non-executable pages */
19118+#define EF_PAX_EMUTRAMP 2 /* Emulate trampolines */
19119+#define EF_PAX_MPROTECT 4 /* Restrict mprotect() */
19120+#define EF_PAX_RANDMMAP 8 /* Randomize mmap() base */
19121+/*#define EF_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */
19122+#define EF_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */
19123+
19124 /* These constants define the different elf file types */
19125 #define ET_NONE 0
19126 #define ET_REL 1
19127@@ -138,6 +152,8 @@ typedef __s64 Elf64_Sxword;
19128 #define DT_DEBUG 21
19129 #define DT_TEXTREL 22
19130 #define DT_JMPREL 23
19131+#define DT_FLAGS 30
19132+ #define DF_TEXTREL 0x00000004
19133 #define DT_LOPROC 0x70000000
19134 #define DT_HIPROC 0x7fffffff
19135
19136@@ -267,6 +283,19 @@ typedef struct elf64_hdr {
19137 #define PF_W 0x2
19138 #define PF_X 0x1
19139
19140+#define PF_PAGEEXEC (1U << 4) /* Enable PAGEEXEC */
19141+#define PF_NOPAGEEXEC (1U << 5) /* Disable PAGEEXEC */
19142+#define PF_SEGMEXEC (1U << 6) /* Enable SEGMEXEC */
19143+#define PF_NOSEGMEXEC (1U << 7) /* Disable SEGMEXEC */
19144+#define PF_MPROTECT (1U << 8) /* Enable MPROTECT */
19145+#define PF_NOMPROTECT (1U << 9) /* Disable MPROTECT */
19146+/*#define PF_RANDEXEC (1U << 10)*/ /* Enable RANDEXEC */
19147+/*#define PF_NORANDEXEC (1U << 11)*/ /* Disable RANDEXEC */
19148+#define PF_EMUTRAMP (1U << 12) /* Enable EMUTRAMP */
19149+#define PF_NOEMUTRAMP (1U << 13) /* Disable EMUTRAMP */
19150+#define PF_RANDMMAP (1U << 14) /* Enable RANDMMAP */
19151+#define PF_NORANDMMAP (1U << 15) /* Disable RANDMMAP */
19152+
19153 typedef struct elf32_phdr{
19154 Elf32_Word p_type;
19155 Elf32_Off p_offset;
19156@@ -359,6 +388,8 @@ typedef struct elf64_shdr {
19157 #define EI_OSABI 7
19158 #define EI_PAD 8
19159
19160+#define EI_PAX 14
19161+
19162 #define ELFMAG0 0x7f /* EI_MAG */
19163 #define ELFMAG1 'E'
19164 #define ELFMAG2 'L'
19165@@ -415,6 +446,7 @@ extern Elf32_Dyn _DYNAMIC [];
19166 #define elfhdr elf32_hdr
19167 #define elf_phdr elf32_phdr
19168 #define elf_note elf32_note
19169+#define elf_dyn Elf32_Dyn
19170
19171 #else
19172
19173@@ -422,6 +454,7 @@ extern Elf64_Dyn _DYNAMIC [];
19174 #define elfhdr elf64_hdr
19175 #define elf_phdr elf64_phdr
19176 #define elf_note elf64_note
19177+#define elf_dyn Elf64_Dyn
19178
19179 #endif
19180
19181diff -urNp linux-2.6.16.12/include/linux/gracl.h linux-2.6.16.12/include/linux/gracl.h
19182--- linux-2.6.16.12/include/linux/gracl.h 1969-12-31 19:00:00.000000000 -0500
19183+++ linux-2.6.16.12/include/linux/gracl.h 2006-05-01 20:17:34.000000000 -0400
19184@@ -0,0 +1,316 @@
19185+#ifndef GR_ACL_H
19186+#define GR_ACL_H
19187+
19188+#include <linux/grdefs.h>
19189+#include <linux/resource.h>
19190+#include <linux/dcache.h>
19191+#include <asm/resource.h>
19192+
19193+/* Major status information */
19194+
19195+#define GR_VERSION "grsecurity 2.1.9"
19196+#define GRSECURITY_VERSION 0x219
19197+
19198+enum {
19199+
19200+ SHUTDOWN = 0,
19201+ ENABLE = 1,
19202+ SPROLE = 2,
19203+ RELOAD = 3,
19204+ SEGVMOD = 4,
19205+ STATUS = 5,
19206+ UNSPROLE = 6,
19207+ PASSSET = 7,
19208+ SPROLEPAM = 8
19209+};
19210+
19211+/* Password setup definitions
19212+ * kernel/grhash.c */
19213+enum {
19214+ GR_PW_LEN = 128,
19215+ GR_SALT_LEN = 16,
19216+ GR_SHA_LEN = 32,
19217+};
19218+
19219+enum {
19220+ GR_SPROLE_LEN = 64,
19221+};
19222+
19223+#define GR_NLIMITS (RLIMIT_LOCKS + 2)
19224+
19225+/* Begin Data Structures */
19226+
19227+struct sprole_pw {
19228+ unsigned char *rolename;
19229+ unsigned char salt[GR_SALT_LEN];
19230+ unsigned char sum[GR_SHA_LEN]; /* 256-bit SHA hash of the password */
19231+};
19232+
19233+struct name_entry {
19234+ __u32 key;
19235+ ino_t inode;
19236+ dev_t device;
19237+ char *name;
19238+ __u16 len;
19239+ struct name_entry *prev;
19240+ struct name_entry *next;
19241+};
19242+
19243+struct inodev_entry {
19244+ struct name_entry *nentry;
19245+ struct inodev_entry *prev;
19246+ struct inodev_entry *next;
19247+};
19248+
19249+struct acl_role_db {
19250+ struct acl_role_label **r_hash;
19251+ __u32 r_size;
19252+};
19253+
19254+struct inodev_db {
19255+ struct inodev_entry **i_hash;
19256+ __u32 i_size;
19257+};
19258+
19259+struct name_db {
19260+ struct name_entry **n_hash;
19261+ __u32 n_size;
19262+};
19263+
19264+struct crash_uid {
19265+ uid_t uid;
19266+ unsigned long expires;
19267+};
19268+
19269+struct gr_hash_struct {
19270+ void **table;
19271+ void **nametable;
19272+ void *first;
19273+ __u32 table_size;
19274+ __u32 used_size;
19275+ int type;
19276+};
19277+
19278+/* Userspace Grsecurity ACL data structures */
19279+
19280+struct acl_subject_label {
19281+ char *filename;
19282+ ino_t inode;
19283+ dev_t device;
19284+ __u32 mode;
19285+ __u32 cap_mask;
19286+ __u32 cap_lower;
19287+
19288+ struct rlimit res[GR_NLIMITS];
19289+ __u16 resmask;
19290+
19291+ __u8 user_trans_type;
19292+ __u8 group_trans_type;
19293+ uid_t *user_transitions;
19294+ gid_t *group_transitions;
19295+ __u16 user_trans_num;
19296+ __u16 group_trans_num;
19297+
19298+ __u32 ip_proto[8];
19299+ __u32 ip_type;
19300+ struct acl_ip_label **ips;
19301+ __u32 ip_num;
19302+
19303+ __u32 crashes;
19304+ unsigned long expires;
19305+
19306+ struct acl_subject_label *parent_subject;
19307+ struct gr_hash_struct *hash;
19308+ struct acl_subject_label *prev;
19309+ struct acl_subject_label *next;
19310+
19311+ struct acl_object_label **obj_hash;
19312+ __u32 obj_hash_size;
19313+ __u16 pax_flags;
19314+};
19315+
19316+struct role_allowed_ip {
19317+ __u32 addr;
19318+ __u32 netmask;
19319+
19320+ struct role_allowed_ip *prev;
19321+ struct role_allowed_ip *next;
19322+};
19323+
19324+struct role_transition {
19325+ char *rolename;
19326+
19327+ struct role_transition *prev;
19328+ struct role_transition *next;
19329+};
19330+
19331+struct acl_role_label {
19332+ char *rolename;
19333+ uid_t uidgid;
19334+ __u16 roletype;
19335+
19336+ __u16 auth_attempts;
19337+ unsigned long expires;
19338+
19339+ struct acl_subject_label *root_label;
19340+ struct gr_hash_struct *hash;
19341+
19342+ struct acl_role_label *prev;
19343+ struct acl_role_label *next;
19344+
19345+ struct role_transition *transitions;
19346+ struct role_allowed_ip *allowed_ips;
19347+ uid_t *domain_children;
19348+ __u16 domain_child_num;
19349+
19350+ struct acl_subject_label **subj_hash;
19351+ __u32 subj_hash_size;
19352+};
19353+
19354+struct user_acl_role_db {
19355+ struct acl_role_label **r_table;
19356+ __u32 num_pointers; /* Number of allocations to track */
19357+ __u32 num_roles; /* Number of roles */
19358+ __u32 num_domain_children; /* Number of domain children */
19359+ __u32 num_subjects; /* Number of subjects */
19360+ __u32 num_objects; /* Number of objects */
19361+};
19362+
19363+struct acl_object_label {
19364+ char *filename;
19365+ ino_t inode;
19366+ dev_t device;
19367+ __u32 mode;
19368+
19369+ struct acl_subject_label *nested;
19370+ struct acl_object_label *globbed;
19371+
19372+ /* next two structures not used */
19373+
19374+ struct acl_object_label *prev;
19375+ struct acl_object_label *next;
19376+};
19377+
19378+struct acl_ip_label {
19379+ char *iface;
19380+ __u32 addr;
19381+ __u32 netmask;
19382+ __u16 low, high;
19383+ __u8 mode;
19384+ __u32 type;
19385+ __u32 proto[8];
19386+
19387+ /* next two structures not used */
19388+
19389+ struct acl_ip_label *prev;
19390+ struct acl_ip_label *next;
19391+};
19392+
19393+struct gr_arg {
19394+ struct user_acl_role_db role_db;
19395+ unsigned char pw[GR_PW_LEN];
19396+ unsigned char salt[GR_SALT_LEN];
19397+ unsigned char sum[GR_SHA_LEN];
19398+ unsigned char sp_role[GR_SPROLE_LEN];
19399+ struct sprole_pw *sprole_pws;
19400+ dev_t segv_device;
19401+ ino_t segv_inode;
19402+ uid_t segv_uid;
19403+ __u16 num_sprole_pws;
19404+ __u16 mode;
19405+};
19406+
19407+struct gr_arg_wrapper {
19408+ struct gr_arg *arg;
19409+ __u32 version;
19410+ __u32 size;
19411+};
19412+
19413+struct subject_map {
19414+ struct acl_subject_label *user;
19415+ struct acl_subject_label *kernel;
19416+ struct subject_map *prev;
19417+ struct subject_map *next;
19418+};
19419+
19420+struct acl_subj_map_db {
19421+ struct subject_map **s_hash;
19422+ __u32 s_size;
19423+};
19424+
19425+/* End Data Structures Section */
19426+
19427+/* Hash functions generated by empirical testing by Brad Spengler
19428+ Makes good use of the low bits of the inode. Generally 0-1 times
19429+ in loop for successful match. 0-3 for unsuccessful match.
19430+ Shift/add algorithm with modulus of table size and an XOR*/
19431+
19432+static __inline__ unsigned int
19433+rhash(const uid_t uid, const __u16 type, const unsigned int sz)
19434+{
19435+ return (((uid << type) + (uid ^ type)) % sz);
19436+}
19437+
19438+ static __inline__ unsigned int
19439+shash(const struct acl_subject_label *userp, const unsigned int sz)
19440+{
19441+ return ((const unsigned long)userp % sz);
19442+}
19443+
19444+static __inline__ unsigned int
19445+fhash(const ino_t ino, const dev_t dev, const unsigned int sz)
19446+{
19447+ return (((ino + dev) ^ ((ino << 13) + (ino << 23) + (dev << 9))) % sz);
19448+}
19449+
19450+static __inline__ unsigned int
19451+nhash(const char *name, const __u16 len, const unsigned int sz)
19452+{
19453+ return full_name_hash(name, len) % sz;
19454+}
19455+
19456+#define FOR_EACH_ROLE_START(role,iter) \
19457+ role = NULL; \
19458+ iter = 0; \
19459+ while (iter < acl_role_set.r_size) { \
19460+ if (role == NULL) \
19461+ role = acl_role_set.r_hash[iter]; \
19462+ if (role == NULL) { \
19463+ iter++; \
19464+ continue; \
19465+ }
19466+
19467+#define FOR_EACH_ROLE_END(role,iter) \
19468+ role = role->next; \
19469+ if (role == NULL) \
19470+ iter++; \
19471+ }
19472+
19473+#define FOR_EACH_SUBJECT_START(role,subj,iter) \
19474+ subj = NULL; \
19475+ iter = 0; \
19476+ while (iter < role->subj_hash_size) { \
19477+ if (subj == NULL) \
19478+ subj = role->subj_hash[iter]; \
19479+ if (subj == NULL) { \
19480+ iter++; \
19481+ continue; \
19482+ }
19483+
19484+#define FOR_EACH_SUBJECT_END(subj,iter) \
19485+ subj = subj->next; \
19486+ if (subj == NULL) \
19487+ iter++; \
19488+ }
19489+
19490+
19491+#define FOR_EACH_NESTED_SUBJECT_START(role,subj) \
19492+ subj = role->hash->first; \
19493+ while (subj != NULL) {
19494+
19495+#define FOR_EACH_NESTED_SUBJECT_END(subj) \
19496+ subj = subj->next; \
19497+ }
19498+
19499+#endif
19500+
19501diff -urNp linux-2.6.16.12/include/linux/gralloc.h linux-2.6.16.12/include/linux/gralloc.h
19502--- linux-2.6.16.12/include/linux/gralloc.h 1969-12-31 19:00:00.000000000 -0500
19503+++ linux-2.6.16.12/include/linux/gralloc.h 2006-05-01 20:17:34.000000000 -0400
19504@@ -0,0 +1,8 @@
19505+#ifndef __GRALLOC_H
19506+#define __GRALLOC_H
19507+
19508+void acl_free_all(void);
19509+int acl_alloc_stack_init(unsigned long size);
19510+void *acl_alloc(unsigned long len);
19511+
19512+#endif
19513diff -urNp linux-2.6.16.12/include/linux/grdefs.h linux-2.6.16.12/include/linux/grdefs.h
19514--- linux-2.6.16.12/include/linux/grdefs.h 1969-12-31 19:00:00.000000000 -0500
19515+++ linux-2.6.16.12/include/linux/grdefs.h 2006-05-01 20:17:34.000000000 -0400
19516@@ -0,0 +1,131 @@
19517+#ifndef GRDEFS_H
19518+#define GRDEFS_H
19519+
19520+/* Begin grsecurity status declarations */
19521+
19522+enum {
19523+ GR_READY = 0x01,
19524+ GR_STATUS_INIT = 0x00 // disabled state
19525+};
19526+
19527+/* Begin ACL declarations */
19528+
19529+/* Role flags */
19530+
19531+enum {
19532+ GR_ROLE_USER = 0x0001,
19533+ GR_ROLE_GROUP = 0x0002,
19534+ GR_ROLE_DEFAULT = 0x0004,
19535+ GR_ROLE_SPECIAL = 0x0008,
19536+ GR_ROLE_AUTH = 0x0010,
19537+ GR_ROLE_NOPW = 0x0020,
19538+ GR_ROLE_GOD = 0x0040,
19539+ GR_ROLE_LEARN = 0x0080,
19540+ GR_ROLE_TPE = 0x0100,
19541+ GR_ROLE_DOMAIN = 0x0200,
19542+ GR_ROLE_PAM = 0x0400
19543+};
19544+
19545+/* ACL Subject and Object mode flags */
19546+enum {
19547+ GR_DELETED = 0x80000000
19548+};
19549+
19550+/* ACL Object-only mode flags */
19551+enum {
19552+ GR_READ = 0x00000001,
19553+ GR_APPEND = 0x00000002,
19554+ GR_WRITE = 0x00000004,
19555+ GR_EXEC = 0x00000008,
19556+ GR_FIND = 0x00000010,
19557+ GR_INHERIT = 0x00000020,
19558+ GR_SETID = 0x00000040,
19559+ GR_CREATE = 0x00000080,
19560+ GR_DELETE = 0x00000100,
19561+ GR_LINK = 0x00000200,
19562+ GR_AUDIT_READ = 0x00000400,
19563+ GR_AUDIT_APPEND = 0x00000800,
19564+ GR_AUDIT_WRITE = 0x00001000,
19565+ GR_AUDIT_EXEC = 0x00002000,
19566+ GR_AUDIT_FIND = 0x00004000,
19567+ GR_AUDIT_INHERIT= 0x00008000,
19568+ GR_AUDIT_SETID = 0x00010000,
19569+ GR_AUDIT_CREATE = 0x00020000,
19570+ GR_AUDIT_DELETE = 0x00040000,
19571+ GR_AUDIT_LINK = 0x00080000,
19572+ GR_PTRACERD = 0x00100000,
19573+ GR_NOPTRACE = 0x00200000,
19574+ GR_SUPPRESS = 0x00400000,
19575+ GR_NOLEARN = 0x00800000
19576+};
19577+
19578+#define GR_AUDITS (GR_AUDIT_READ | GR_AUDIT_WRITE | GR_AUDIT_APPEND | GR_AUDIT_EXEC | \
19579+ GR_AUDIT_FIND | GR_AUDIT_INHERIT | GR_AUDIT_SETID | \
19580+ GR_AUDIT_CREATE | GR_AUDIT_DELETE | GR_AUDIT_LINK)
19581+
19582+/* ACL subject-only mode flags */
19583+enum {
19584+ GR_KILL = 0x00000001,
19585+ GR_VIEW = 0x00000002,
19586+ GR_PROTECTED = 0x00000004,
19587+ GR_LEARN = 0x00000008,
19588+ GR_OVERRIDE = 0x00000010,
19589+ /* just a placeholder, this mode is only used in userspace */
19590+ GR_DUMMY = 0x00000020,
19591+ GR_PROTSHM = 0x00000040,
19592+ GR_KILLPROC = 0x00000080,
19593+ GR_KILLIPPROC = 0x00000100,
19594+ /* just a placeholder, this mode is only used in userspace */
19595+ GR_NOTROJAN = 0x00000200,
19596+ GR_PROTPROCFD = 0x00000400,
19597+ GR_PROCACCT = 0x00000800,
19598+ GR_RELAXPTRACE = 0x00001000,
19599+ GR_NESTED = 0x00002000,
19600+ GR_INHERITLEARN = 0x00004000,
19601+ GR_PROCFIND = 0x00008000,
19602+ GR_POVERRIDE = 0x00010000,
19603+ GR_KERNELAUTH = 0x00020000,
19604+};
19605+
19606+enum {
19607+ GR_PAX_ENABLE_SEGMEXEC = 0x0001,
19608+ GR_PAX_ENABLE_PAGEEXEC = 0x0002,
19609+ GR_PAX_ENABLE_MPROTECT = 0x0004,
19610+ GR_PAX_ENABLE_RANDMMAP = 0x0008,
19611+ GR_PAX_ENABLE_EMUTRAMP = 0x0010,
19612+ GR_PAX_DISABLE_SEGMEXEC = 0x8001,
19613+ GR_PAX_DISABLE_PAGEEXEC = 0x8002,
19614+ GR_PAX_DISABLE_MPROTECT = 0x8004,
19615+ GR_PAX_DISABLE_RANDMMAP = 0x8008,
19616+ GR_PAX_DISABLE_EMUTRAMP = 0x8010,
19617+};
19618+
19619+enum {
19620+ GR_ID_USER = 0x01,
19621+ GR_ID_GROUP = 0x02,
19622+};
19623+
19624+enum {
19625+ GR_ID_ALLOW = 0x01,
19626+ GR_ID_DENY = 0x02,
19627+};
19628+
19629+#define GR_CRASH_RES 11
19630+#define GR_UIDTABLE_MAX 500
19631+
19632+/* begin resource learning section */
19633+enum {
19634+ GR_RLIM_CPU_BUMP = 60,
19635+ GR_RLIM_FSIZE_BUMP = 50000,
19636+ GR_RLIM_DATA_BUMP = 10000,
19637+ GR_RLIM_STACK_BUMP = 1000,
19638+ GR_RLIM_CORE_BUMP = 10000,
19639+ GR_RLIM_RSS_BUMP = 500000,
19640+ GR_RLIM_NPROC_BUMP = 1,
19641+ GR_RLIM_NOFILE_BUMP = 5,
19642+ GR_RLIM_MEMLOCK_BUMP = 50000,
19643+ GR_RLIM_AS_BUMP = 500000,
19644+ GR_RLIM_LOCKS_BUMP = 2
19645+};
19646+
19647+#endif
19648diff -urNp linux-2.6.16.12/include/linux/grinternal.h linux-2.6.16.12/include/linux/grinternal.h
19649--- linux-2.6.16.12/include/linux/grinternal.h 1969-12-31 19:00:00.000000000 -0500
19650+++ linux-2.6.16.12/include/linux/grinternal.h 2006-05-01 20:17:34.000000000 -0400
19651@@ -0,0 +1,210 @@
19652+#ifndef __GRINTERNAL_H
19653+#define __GRINTERNAL_H
19654+
19655+#ifdef CONFIG_GRKERNSEC
19656+
19657+#include <linux/fs.h>
19658+#include <linux/gracl.h>
19659+#include <linux/grdefs.h>
19660+#include <linux/grmsg.h>
19661+
19662+extern void gr_add_learn_entry(const char *fmt, ...);
19663+extern __u32 gr_search_file(const struct dentry *dentry, const __u32 mode,
19664+ const struct vfsmount *mnt);
19665+extern __u32 gr_check_create(const struct dentry *new_dentry,
19666+ const struct dentry *parent,
19667+ const struct vfsmount *mnt, const __u32 mode);
19668+extern int gr_check_protected_task(const struct task_struct *task);
19669+extern __u32 to_gr_audit(const __u32 reqmode);
19670+extern int gr_set_acls(const int type);
19671+
19672+extern int gr_acl_is_enabled(void);
19673+extern char gr_roletype_to_char(void);
19674+
19675+extern void gr_handle_alertkill(struct task_struct *task);
19676+extern char *gr_to_filename(const struct dentry *dentry,
19677+ const struct vfsmount *mnt);
19678+extern char *gr_to_filename1(const struct dentry *dentry,
19679+ const struct vfsmount *mnt);
19680+extern char *gr_to_filename2(const struct dentry *dentry,
19681+ const struct vfsmount *mnt);
19682+extern char *gr_to_filename3(const struct dentry *dentry,
19683+ const struct vfsmount *mnt);
19684+
19685+extern int grsec_enable_link;
19686+extern int grsec_enable_fifo;
19687+extern int grsec_enable_execve;
19688+extern int grsec_enable_shm;
19689+extern int grsec_enable_execlog;
19690+extern int grsec_enable_signal;
19691+extern int grsec_enable_forkfail;
19692+extern int grsec_enable_time;
19693+extern int grsec_enable_chroot_shmat;
19694+extern int grsec_enable_chroot_findtask;
19695+extern int grsec_enable_chroot_mount;
19696+extern int grsec_enable_chroot_double;
19697+extern int grsec_enable_chroot_pivot;
19698+extern int grsec_enable_chroot_chdir;
19699+extern int grsec_enable_chroot_chmod;
19700+extern int grsec_enable_chroot_mknod;
19701+extern int grsec_enable_chroot_fchdir;
19702+extern int grsec_enable_chroot_nice;
19703+extern int grsec_enable_chroot_execlog;
19704+extern int grsec_enable_chroot_caps;
19705+extern int grsec_enable_chroot_sysctl;
19706+extern int grsec_enable_chroot_unix;
19707+extern int grsec_enable_tpe;
19708+extern int grsec_tpe_gid;
19709+extern int grsec_enable_tpe_all;
19710+extern int grsec_enable_sidcaps;
19711+extern int grsec_enable_randpid;
19712+extern int grsec_enable_socket_all;
19713+extern int grsec_socket_all_gid;
19714+extern int grsec_enable_socket_client;
19715+extern int grsec_socket_client_gid;
19716+extern int grsec_enable_socket_server;
19717+extern int grsec_socket_server_gid;
19718+extern int grsec_audit_gid;
19719+extern int grsec_enable_group;
19720+extern int grsec_enable_audit_ipc;
19721+extern int grsec_enable_audit_textrel;
19722+extern int grsec_enable_mount;
19723+extern int grsec_enable_chdir;
19724+extern int grsec_lock;
19725+
19726+extern struct task_struct *child_reaper;
19727+
19728+extern spinlock_t grsec_alert_lock;
19729+extern unsigned long grsec_alert_wtime;
19730+extern unsigned long grsec_alert_fyet;
19731+
19732+extern spinlock_t grsec_audit_lock;
19733+
19734+extern rwlock_t grsec_exec_file_lock;
19735+
19736+#define gr_task_fullpath(tsk) (tsk->exec_file ? \
19737+ gr_to_filename2(tsk->exec_file->f_dentry, \
19738+ tsk->exec_file->f_vfsmnt) : "/")
19739+
19740+#define gr_parent_task_fullpath(tsk) (tsk->parent->exec_file ? \
19741+ gr_to_filename3(tsk->parent->exec_file->f_dentry, \
19742+ tsk->parent->exec_file->f_vfsmnt) : "/")
19743+
19744+#define gr_task_fullpath0(tsk) (tsk->exec_file ? \
19745+ gr_to_filename(tsk->exec_file->f_dentry, \
19746+ tsk->exec_file->f_vfsmnt) : "/")
19747+
19748+#define gr_parent_task_fullpath0(tsk) (tsk->parent->exec_file ? \
19749+ gr_to_filename1(tsk->parent->exec_file->f_dentry, \
19750+ tsk->parent->exec_file->f_vfsmnt) : "/")
19751+
19752+#define proc_is_chrooted(tsk_a) ((tsk_a->pid > 1) && (tsk_a->fs != NULL) && \
19753+ ((tsk_a->fs->root->d_inode->i_sb->s_dev != \
19754+ child_reaper->fs->root->d_inode->i_sb->s_dev) || \
19755+ (tsk_a->fs->root->d_inode->i_ino != \
19756+ child_reaper->fs->root->d_inode->i_ino)))
19757+
19758+#define have_same_root(tsk_a,tsk_b) ((tsk_a->fs != NULL) && (tsk_b->fs != NULL) && \
19759+ (tsk_a->fs->root->d_inode->i_sb->s_dev == \
19760+ tsk_b->fs->root->d_inode->i_sb->s_dev) && \
19761+ (tsk_a->fs->root->d_inode->i_ino == \
19762+ tsk_b->fs->root->d_inode->i_ino))
19763+
19764+#define DEFAULTSECARGS(task) gr_task_fullpath(task), task->comm, \
19765+ task->pid, task->uid, \
19766+ task->euid, task->gid, task->egid, \
19767+ gr_parent_task_fullpath(task), \
19768+ task->parent->comm, task->parent->pid, \
19769+ task->parent->uid, task->parent->euid, \
19770+ task->parent->gid, task->parent->egid
19771+
19772+#define GR_CHROOT_CAPS ( \
19773+ CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | CAP_TO_MASK(CAP_NET_ADMIN) | \
19774+ CAP_TO_MASK(CAP_SYS_MODULE) | CAP_TO_MASK(CAP_SYS_RAWIO) | \
19775+ CAP_TO_MASK(CAP_SYS_PACCT) | CAP_TO_MASK(CAP_SYS_ADMIN) | \
19776+ CAP_TO_MASK(CAP_SYS_BOOT) | CAP_TO_MASK(CAP_SYS_TIME) | \
19777+ CAP_TO_MASK(CAP_NET_RAW) | CAP_TO_MASK(CAP_SYS_TTY_CONFIG) | \
19778+ CAP_TO_MASK(CAP_IPC_OWNER))
19779+
19780+#define security_learn(normal_msg,args...) \
19781+({ \
19782+ read_lock(&grsec_exec_file_lock); \
19783+ gr_add_learn_entry(normal_msg "\n", ## args); \
19784+ read_unlock(&grsec_exec_file_lock); \
19785+})
19786+
19787+enum {
19788+ GR_DO_AUDIT,
19789+ GR_DONT_AUDIT,
19790+ GR_DONT_AUDIT_GOOD
19791+};
19792+
19793+enum {
19794+ GR_TTYSNIFF,
19795+ GR_RBAC,
19796+ GR_RBAC_STR,
19797+ GR_STR_RBAC,
19798+ GR_RBAC_MODE2,
19799+ GR_RBAC_MODE3,
19800+ GR_FILENAME,
19801+ GR_NOARGS,
19802+ GR_ONE_INT,
19803+ GR_ONE_INT_TWO_STR,
19804+ GR_ONE_STR,
19805+ GR_STR_INT,
19806+ GR_TWO_INT,
19807+ GR_THREE_INT,
19808+ GR_FIVE_INT_TWO_STR,
19809+ GR_TWO_STR,
19810+ GR_THREE_STR,
19811+ GR_FOUR_STR,
19812+ GR_STR_FILENAME,
19813+ GR_FILENAME_STR,
19814+ GR_FILENAME_TWO_INT,
19815+ GR_FILENAME_TWO_INT_STR,
19816+ GR_TEXTREL,
19817+ GR_PTRACE,
19818+ GR_RESOURCE,
19819+ GR_CAP,
19820+ GR_SIG,
19821+ GR_CRASH1,
19822+ GR_CRASH2,
19823+ GR_PSACCT
19824+};
19825+
19826+#define gr_log_ttysniff(audit, msg, task) gr_log_varargs(audit, msg, GR_TTYSNIFF, task)
19827+#define gr_log_fs_rbac_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_RBAC, dentry, mnt)
19828+#define gr_log_fs_rbac_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_RBAC_STR, dentry, mnt, str)
19829+#define gr_log_fs_str_rbac(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_RBAC, str, dentry, mnt)
19830+#define gr_log_fs_rbac_mode2(audit, msg, dentry, mnt, str1, str2) gr_log_varargs(audit, msg, GR_RBAC_MODE2, dentry, mnt, str1, str2)
19831+#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)
19832+#define gr_log_fs_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_FILENAME, dentry, mnt)
19833+#define gr_log_noargs(audit, msg) gr_log_varargs(audit, msg, GR_NOARGS)
19834+#define gr_log_int(audit, msg, num) gr_log_varargs(audit, msg, GR_ONE_INT, num)
19835+#define gr_log_int_str2(audit, msg, num, str1, str2) gr_log_varargs(audit, msg, GR_ONE_INT_TWO_STR, num, str1, str2)
19836+#define gr_log_str(audit, msg, str) gr_log_varargs(audit, msg, GR_ONE_STR, str)
19837+#define gr_log_str_int(audit, msg, str, num) gr_log_varargs(audit, msg, GR_STR_INT, str, num)
19838+#define gr_log_int_int(audit, msg, num1, num2) gr_log_varargs(audit, msg, GR_TWO_INT, num1, num2)
19839+#define gr_log_int3(audit, msg, num1, num2, num3) gr_log_varargs(audit, msg, GR_THREE_INT, num1, num2, num3)
19840+#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)
19841+#define gr_log_str_str(audit, msg, str1, str2) gr_log_varargs(audit, msg, GR_TWO_STR, str1, str2)
19842+#define gr_log_str3(audit, msg, str1, str2, str3) gr_log_varargs(audit, msg, GR_THREE_STR, str1, str2, str3)
19843+#define gr_log_str4(audit, msg, str1, str2, str3, str4) gr_log_varargs(audit, msg, GR_FOUR_STR, str1, str2, str3, str4)
19844+#define gr_log_str_fs(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_FILENAME, str, dentry, mnt)
19845+#define gr_log_fs_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_FILENAME_STR, dentry, mnt, str)
19846+#define gr_log_fs_int2(audit, msg, dentry, mnt, num1, num2) gr_log_varargs(audit, msg, GR_FILENAME_TWO_INT, dentry, mnt, num1, num2)
19847+#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)
19848+#define gr_log_textrel_ulong_ulong(audit, msg, file, ulong1, ulong2) gr_log_varargs(audit, msg, GR_TEXTREL, file, ulong1, ulong2)
19849+#define gr_log_ptrace(audit, msg, task) gr_log_varargs(audit, msg, GR_PTRACE, task)
19850+#define gr_log_res_ulong2_str(audit, msg, task, ulong1, str, ulong2) gr_log_varargs(audit, msg, GR_RESOURCE, task, ulong1, str, ulong2)
19851+#define gr_log_cap(audit, msg, task, str) gr_log_varargs(audit, msg, GR_CAP, task, str)
19852+#define gr_log_sig(audit, msg, task, num) gr_log_varargs(audit, msg, GR_SIG, task, num)
19853+#define gr_log_crash1(audit, msg, task, ulong) gr_log_varargs(audit, msg, GR_CRASH1, task, ulong)
19854+#define gr_log_crash2(audit, msg, task, ulong1) gr_log_varargs(audit, msg, GR_CRASH2, task, ulong1)
19855+#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)
19856+
19857+extern void gr_log_varargs(int audit, const char *msg, int argtypes, ...);
19858+
19859+#endif
19860+
19861+#endif
19862diff -urNp linux-2.6.16.12/include/linux/grmsg.h linux-2.6.16.12/include/linux/grmsg.h
19863--- linux-2.6.16.12/include/linux/grmsg.h 1969-12-31 19:00:00.000000000 -0500
19864+++ linux-2.6.16.12/include/linux/grmsg.h 2006-05-01 20:17:34.000000000 -0400
19865@@ -0,0 +1,108 @@
19866+#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"
19867+#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"
19868+#define GR_PTRACE_ACL_MSG "denied ptrace of %.950s(%.16s:%d) by "
19869+#define GR_STOPMOD_MSG "denied modification of module state by "
19870+#define GR_IOPERM_MSG "denied use of ioperm() by "
19871+#define GR_IOPL_MSG "denied use of iopl() by "
19872+#define GR_SHMAT_ACL_MSG "denied attach of shared memory of UID %u, PID %d, ID %u by "
19873+#define GR_UNIX_CHROOT_MSG "denied connect() to abstract AF_UNIX socket outside of chroot by "
19874+#define GR_SHMAT_CHROOT_MSG "denied attach of shared memory outside of chroot by "
19875+#define GR_KMEM_MSG "denied write of /dev/kmem by "
19876+#define GR_PORT_OPEN_MSG "denied open of /dev/port by "
19877+#define GR_MEM_WRITE_MSG "denied write of /dev/mem by "
19878+#define GR_MEM_MMAP_MSG "denied mmap write of /dev/[k]mem by "
19879+#define GR_SYMLINK_MSG "not following symlink %.950s owned by %d.%d by "
19880+#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"
19881+#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"
19882+#define GR_HIDDEN_ACL_MSG "%s access to hidden file %.950s by "
19883+#define GR_OPEN_ACL_MSG "%s open of %.950s for%s%s by "
19884+#define GR_CREATE_ACL_MSG "%s create of %.950s for%s%s by "
19885+#define GR_FIFO_MSG "denied writing FIFO %.950s of %d.%d by "
19886+#define GR_MKNOD_CHROOT_MSG "denied mknod of %.950s from chroot by "
19887+#define GR_MKNOD_ACL_MSG "%s mknod of %.950s by "
19888+#define GR_UNIXCONNECT_ACL_MSG "%s connect() to the unix domain socket %.950s by "
19889+#define GR_TTYSNIFF_ACL_MSG "terminal being sniffed by IP:%u.%u.%u.%u %.480s[%.16s:%d], parent %.480s[%.16s:%d] against "
19890+#define GR_MKDIR_ACL_MSG "%s mkdir of %.950s by "
19891+#define GR_RMDIR_ACL_MSG "%s rmdir of %.950s by "
19892+#define GR_UNLINK_ACL_MSG "%s unlink of %.950s by "
19893+#define GR_SYMLINK_ACL_MSG "%s symlink from %.480s to %.480s by "
19894+#define GR_HARDLINK_MSG "denied hardlink of %.930s (owned by %d.%d) to %.30s for "
19895+#define GR_LINK_ACL_MSG "%s link of %.480s to %.480s by "
19896+#define GR_INHERIT_ACL_MSG "successful inherit of %.480s's ACL for %.480s by "
19897+#define GR_RENAME_ACL_MSG "%s rename of %.480s to %.480s by "
19898+#define GR_PTRACE_EXEC_ACL_MSG "denied ptrace of %.950s by "
19899+#define GR_NPROC_MSG "denied overstep of process limit by "
19900+#define GR_EXEC_ACL_MSG "%s execution of %.950s by "
19901+#define GR_EXEC_TPE_MSG "denied untrusted exec of %.950s by "
19902+#define GR_SEGVSTART_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning uid %u from login for %lu seconds"
19903+#define GR_SEGVNOSUID_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning execution for %lu seconds"
19904+#define GR_MOUNT_CHROOT_MSG "denied mount of %.30s as %.930s from chroot by "
19905+#define GR_PIVOT_CHROOT_MSG "denied pivot_root from chroot by "
19906+#define GR_TRUNCATE_ACL_MSG "%s truncate of %.950s by "
19907+#define GR_ATIME_ACL_MSG "%s access time change of %.950s by "
19908+#define GR_ACCESS_ACL_MSG "%s access of %.950s for%s%s%s by "
19909+#define GR_CHROOT_CHROOT_MSG "denied double chroot to %.950s by "
19910+#define GR_FCHMOD_ACL_MSG "%s fchmod of %.950s by "
19911+#define GR_CHMOD_CHROOT_MSG "denied chmod +s of %.950s by "
19912+#define GR_CHMOD_ACL_MSG "%s chmod of %.950s by "
19913+#define GR_CHROOT_FCHDIR_MSG "denied fchdir outside of chroot to %.950s by "
19914+#define GR_CHOWN_ACL_MSG "%s chown of %.950s by "
19915+#define GR_WRITLIB_ACL_MSG "denied load of writable library %.950s by "
19916+#define GR_INITF_ACL_MSG "init_variables() failed %s by "
19917+#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"
19918+#define GR_DEV_ACL_MSG "/dev/grsec: %d bytes sent %d required, being fed garbaged by "
19919+#define GR_SHUTS_ACL_MSG "shutdown auth success for "
19920+#define GR_SHUTF_ACL_MSG "shutdown auth failure for "
19921+#define GR_SHUTI_ACL_MSG "ignoring shutdown for disabled RBAC system for "
19922+#define GR_SEGVMODS_ACL_MSG "segvmod auth success for "
19923+#define GR_SEGVMODF_ACL_MSG "segvmod auth failure for "
19924+#define GR_SEGVMODI_ACL_MSG "ignoring segvmod for disabled RBAC system for "
19925+#define GR_ENABLE_ACL_MSG "%s RBAC system loaded by "
19926+#define GR_ENABLEF_ACL_MSG "unable to load %s for "
19927+#define GR_RELOADI_ACL_MSG "ignoring reload request for disabled RBAC system"
19928+#define GR_RELOAD_ACL_MSG "%s RBAC system reloaded by "
19929+#define GR_RELOADF_ACL_MSG "failed reload of %s for "
19930+#define GR_SPROLEI_ACL_MSG "ignoring change to special role for disabled RBAC system for "
19931+#define GR_SPROLES_ACL_MSG "successful change to special role %s (id %d) by "
19932+#define GR_SPROLEL_ACL_MSG "special role %s (id %d) exited by "
19933+#define GR_SPROLEF_ACL_MSG "special role %s failure for "
19934+#define GR_UNSPROLEI_ACL_MSG "ignoring unauth of special role for disabled RBAC system for "
19935+#define GR_UNSPROLES_ACL_MSG "successful unauth of special role %s (id %d) by "
19936+#define GR_UNSPROLEF_ACL_MSG "special role unauth of %s failure for "
19937+#define GR_INVMODE_ACL_MSG "invalid mode %d by "
19938+#define GR_PRIORITY_CHROOT_MSG "denied priority change of process (%.16s:%d) by "
19939+#define GR_FAILFORK_MSG "failed fork with errno %d by "
19940+#define GR_NICE_CHROOT_MSG "denied priority change by "
19941+#define GR_UNISIGLOG_MSG "signal %d sent to "
19942+#define GR_DUALSIGLOG_MSG "signal %d sent to " DEFAULTSECMSG " by "
19943+#define GR_SIG_ACL_MSG "denied send of signal %d to protected task " DEFAULTSECMSG " by "
19944+#define GR_SYSCTL_MSG "denied modification of grsecurity sysctl value : %.32s by "
19945+#define GR_SYSCTL_ACL_MSG "%s sysctl of %.950s for%s%s by "
19946+#define GR_TIME_MSG "time set by "
19947+#define GR_DEFACL_MSG "fatal: unable to find subject for (%.16s:%d), loaded by "
19948+#define GR_MMAP_ACL_MSG "%s executable mmap of %.950s by "
19949+#define GR_MPROTECT_ACL_MSG "%s executable mprotect of %.950s by "
19950+#define GR_SOCK_MSG "denied socket(%.16s,%.16s,%.16s) by "
19951+#define GR_SOCK2_MSG "denied socket(%d,%.16s,%.16s) by "
19952+#define GR_BIND_MSG "denied bind() by "
19953+#define GR_CONNECT_MSG "denied connect() by "
19954+#define GR_BIND_ACL_MSG "denied bind() to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by "
19955+#define GR_CONNECT_ACL_MSG "denied connect() to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by "
19956+#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"
19957+#define GR_EXEC_CHROOT_MSG "exec of %.980s within chroot by process "
19958+#define GR_CAP_ACL_MSG "use of %s denied for "
19959+#define GR_USRCHANGE_ACL_MSG "change to uid %u denied for "
19960+#define GR_GRPCHANGE_ACL_MSG "change to gid %u denied for "
19961+#define GR_REMOUNT_AUDIT_MSG "remount of %.30s by "
19962+#define GR_UNMOUNT_AUDIT_MSG "unmount of %.30s by "
19963+#define GR_MOUNT_AUDIT_MSG "mount of %.30s to %.64s by "
19964+#define GR_CHDIR_AUDIT_MSG "chdir to %.980s by "
19965+#define GR_EXEC_AUDIT_MSG "exec of %.930s (%.128s) by "
19966+#define GR_MSGQ_AUDIT_MSG "message queue created by "
19967+#define GR_MSGQR_AUDIT_MSG "message queue of uid:%u euid:%u removed by "
19968+#define GR_SEM_AUDIT_MSG "semaphore created by "
19969+#define GR_SEMR_AUDIT_MSG "semaphore of uid:%u euid:%u removed by "
19970+#define GR_SHM_AUDIT_MSG "shared memory of size %d created by "
19971+#define GR_SHMR_AUDIT_MSG "shared memory of uid:%u euid:%u removed by "
19972+#define GR_RESOURCE_MSG "denied resource overstep by requesting %lu for %.16s against limit %lu for "
19973+#define GR_TEXTREL_AUDIT_MSG "text relocation in %s, VMA:0x%08lx 0x%08lx by "
19974diff -urNp linux-2.6.16.12/include/linux/grsecurity.h linux-2.6.16.12/include/linux/grsecurity.h
19975--- linux-2.6.16.12/include/linux/grsecurity.h 1969-12-31 19:00:00.000000000 -0500
19976+++ linux-2.6.16.12/include/linux/grsecurity.h 2006-05-01 20:17:34.000000000 -0400
19977@@ -0,0 +1,196 @@
19978+#ifndef GR_SECURITY_H
19979+#define GR_SECURITY_H
19980+#include <linux/fs.h>
19981+#include <linux/binfmts.h>
19982+#include <linux/gracl.h>
19983+
19984+extern void gr_handle_brute_attach(struct task_struct *p);
19985+extern void gr_handle_brute_check(void);
19986+
19987+extern char gr_roletype_to_char(void);
19988+
19989+extern int gr_check_user_change(int real, int effective, int fs);
19990+extern int gr_check_group_change(int real, int effective, int fs);
19991+
19992+extern void gr_del_task_from_ip_table(struct task_struct *p);
19993+
19994+extern int gr_pid_is_chrooted(struct task_struct *p);
19995+extern int gr_handle_chroot_nice(void);
19996+extern int gr_handle_chroot_sysctl(const int op);
19997+extern int gr_handle_chroot_setpriority(struct task_struct *p,
19998+ const int niceval);
19999+extern int gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt);
20000+extern int gr_handle_chroot_chroot(const struct dentry *dentry,
20001+ const struct vfsmount *mnt);
20002+extern void gr_handle_chroot_caps(struct task_struct *task);
20003+extern void gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt);
20004+extern int gr_handle_chroot_chmod(const struct dentry *dentry,
20005+ const struct vfsmount *mnt, const int mode);
20006+extern int gr_handle_chroot_mknod(const struct dentry *dentry,
20007+ const struct vfsmount *mnt, const int mode);
20008+extern int gr_handle_chroot_mount(const struct dentry *dentry,
20009+ const struct vfsmount *mnt,
20010+ const char *dev_name);
20011+extern int gr_handle_chroot_pivot(void);
20012+extern int gr_handle_chroot_unix(const pid_t pid);
20013+
20014+extern int gr_handle_rawio(const struct inode *inode);
20015+extern int gr_handle_nproc(void);
20016+
20017+extern void gr_handle_ioperm(void);
20018+extern void gr_handle_iopl(void);
20019+
20020+extern int gr_tpe_allow(const struct file *file);
20021+
20022+extern int gr_random_pid(void);
20023+
20024+extern void gr_log_forkfail(const int retval);
20025+extern void gr_log_timechange(void);
20026+extern void gr_log_signal(const int sig, const struct task_struct *t);
20027+extern void gr_log_chdir(const struct dentry *dentry,
20028+ const struct vfsmount *mnt);
20029+extern void gr_log_chroot_exec(const struct dentry *dentry,
20030+ const struct vfsmount *mnt);
20031+extern void gr_handle_exec_args(struct linux_binprm *bprm, char **argv);
20032+extern void gr_log_remount(const char *devname, const int retval);
20033+extern void gr_log_unmount(const char *devname, const int retval);
20034+extern void gr_log_mount(const char *from, const char *to, const int retval);
20035+extern void gr_log_msgget(const int ret, const int msgflg);
20036+extern void gr_log_msgrm(const uid_t uid, const uid_t cuid);
20037+extern void gr_log_semget(const int err, const int semflg);
20038+extern void gr_log_semrm(const uid_t uid, const uid_t cuid);
20039+extern void gr_log_shmget(const int err, const int shmflg, const size_t size);
20040+extern void gr_log_shmrm(const uid_t uid, const uid_t cuid);
20041+extern void gr_log_textrel(struct vm_area_struct *vma);
20042+
20043+extern int gr_handle_follow_link(const struct inode *parent,
20044+ const struct inode *inode,
20045+ const struct dentry *dentry,
20046+ const struct vfsmount *mnt);
20047+extern int gr_handle_fifo(const struct dentry *dentry,
20048+ const struct vfsmount *mnt,
20049+ const struct dentry *dir, const int flag,
20050+ const int acc_mode);
20051+extern int gr_handle_hardlink(const struct dentry *dentry,
20052+ const struct vfsmount *mnt,
20053+ struct inode *inode,
20054+ const int mode, const char *to);
20055+
20056+extern int gr_task_is_capable(struct task_struct *task, const int cap);
20057+extern int gr_is_capable_nolog(const int cap);
20058+extern void gr_learn_resource(const struct task_struct *task, const int limit,
20059+ const unsigned long wanted, const int gt);
20060+extern void gr_copy_label(struct task_struct *tsk);
20061+extern void gr_handle_crash(struct task_struct *task, const int sig);
20062+extern int gr_handle_signal(const struct task_struct *p, const int sig);
20063+extern int gr_check_crash_uid(const uid_t uid);
20064+extern int gr_check_protected_task(const struct task_struct *task);
20065+extern int gr_acl_handle_mmap(const struct file *file,
20066+ const unsigned long prot);
20067+extern int gr_acl_handle_mprotect(const struct file *file,
20068+ const unsigned long prot);
20069+extern int gr_check_hidden_task(const struct task_struct *tsk);
20070+extern __u32 gr_acl_handle_truncate(const struct dentry *dentry,
20071+ const struct vfsmount *mnt);
20072+extern __u32 gr_acl_handle_utime(const struct dentry *dentry,
20073+ const struct vfsmount *mnt);
20074+extern __u32 gr_acl_handle_access(const struct dentry *dentry,
20075+ const struct vfsmount *mnt, const int fmode);
20076+extern __u32 gr_acl_handle_fchmod(const struct dentry *dentry,
20077+ const struct vfsmount *mnt, mode_t mode);
20078+extern __u32 gr_acl_handle_chmod(const struct dentry *dentry,
20079+ const struct vfsmount *mnt, mode_t mode);
20080+extern __u32 gr_acl_handle_chown(const struct dentry *dentry,
20081+ const struct vfsmount *mnt);
20082+extern int gr_handle_ptrace(struct task_struct *task, const long request);
20083+extern int gr_handle_proc_ptrace(struct task_struct *task);
20084+extern __u32 gr_acl_handle_execve(const struct dentry *dentry,
20085+ const struct vfsmount *mnt);
20086+extern int gr_check_crash_exec(const struct file *filp);
20087+extern int gr_acl_is_enabled(void);
20088+extern void gr_set_kernel_label(struct task_struct *task);
20089+extern void gr_set_role_label(struct task_struct *task, const uid_t uid,
20090+ const gid_t gid);
20091+extern int gr_set_proc_label(const struct dentry *dentry,
20092+ const struct vfsmount *mnt);
20093+extern __u32 gr_acl_handle_hidden_file(const struct dentry *dentry,
20094+ const struct vfsmount *mnt);
20095+extern __u32 gr_acl_handle_open(const struct dentry *dentry,
20096+ const struct vfsmount *mnt, const int fmode);
20097+extern __u32 gr_acl_handle_creat(const struct dentry *dentry,
20098+ const struct dentry *p_dentry,
20099+ const struct vfsmount *p_mnt, const int fmode,
20100+ const int imode);
20101+extern void gr_handle_create(const struct dentry *dentry,
20102+ const struct vfsmount *mnt);
20103+extern __u32 gr_acl_handle_mknod(const struct dentry *new_dentry,
20104+ const struct dentry *parent_dentry,
20105+ const struct vfsmount *parent_mnt,
20106+ const int mode);
20107+extern __u32 gr_acl_handle_mkdir(const struct dentry *new_dentry,
20108+ const struct dentry *parent_dentry,
20109+ const struct vfsmount *parent_mnt);
20110+extern __u32 gr_acl_handle_rmdir(const struct dentry *dentry,
20111+ const struct vfsmount *mnt);
20112+extern void gr_handle_delete(const ino_t ino, const dev_t dev);
20113+extern __u32 gr_acl_handle_unlink(const struct dentry *dentry,
20114+ const struct vfsmount *mnt);
20115+extern __u32 gr_acl_handle_symlink(const struct dentry *new_dentry,
20116+ const struct dentry *parent_dentry,
20117+ const struct vfsmount *parent_mnt,
20118+ const char *from);
20119+extern __u32 gr_acl_handle_link(const struct dentry *new_dentry,
20120+ const struct dentry *parent_dentry,
20121+ const struct vfsmount *parent_mnt,
20122+ const struct dentry *old_dentry,
20123+ const struct vfsmount *old_mnt, const char *to);
20124+extern int gr_acl_handle_rename(struct dentry *new_dentry,
20125+ struct dentry *parent_dentry,
20126+ const struct vfsmount *parent_mnt,
20127+ struct dentry *old_dentry,
20128+ struct inode *old_parent_inode,
20129+ struct vfsmount *old_mnt, const char *newname);
20130+extern void gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
20131+ struct dentry *old_dentry,
20132+ struct dentry *new_dentry,
20133+ struct vfsmount *mnt, const __u8 replace);
20134+extern __u32 gr_check_link(const struct dentry *new_dentry,
20135+ const struct dentry *parent_dentry,
20136+ const struct vfsmount *parent_mnt,
20137+ const struct dentry *old_dentry,
20138+ const struct vfsmount *old_mnt);
20139+extern int gr_acl_handle_filldir(const struct file *file, const char *name,
20140+ const unsigned int namelen, const ino_t ino);
20141+
20142+extern __u32 gr_acl_handle_unix(const struct dentry *dentry,
20143+ const struct vfsmount *mnt);
20144+extern void gr_acl_handle_exit(void);
20145+extern void gr_acl_handle_psacct(struct task_struct *task, const long code);
20146+extern int gr_acl_handle_procpidmem(const struct task_struct *task);
20147+extern __u32 gr_cap_rtnetlink(void);
20148+
20149+#ifdef CONFIG_SYSVIPC
20150+extern void gr_shm_exit(struct task_struct *task);
20151+#else
20152+static inline void gr_shm_exit(struct task_struct *task)
20153+{
20154+ return;
20155+}
20156+#endif
20157+
20158+#ifdef CONFIG_GRKERNSEC
20159+extern void gr_handle_mem_write(void);
20160+extern void gr_handle_kmem_write(void);
20161+extern void gr_handle_open_port(void);
20162+extern int gr_handle_mem_mmap(const unsigned long offset,
20163+ struct vm_area_struct *vma);
20164+
20165+extern unsigned long pax_get_random_long(void);
20166+#define get_random_long() pax_get_random_long()
20167+
20168+extern int grsec_enable_dmesg;
20169+extern int grsec_enable_randsrc;
20170+extern int grsec_enable_shm;
20171+#endif
20172+
20173+#endif
20174diff -urNp linux-2.6.16.12/include/linux/mman.h linux-2.6.16.12/include/linux/mman.h
20175--- linux-2.6.16.12/include/linux/mman.h 2006-05-01 15:14:26.000000000 -0400
20176+++ linux-2.6.16.12/include/linux/mman.h 2006-05-01 20:17:34.000000000 -0400
20177@@ -59,6 +59,11 @@ static inline unsigned long
20178 calc_vm_flag_bits(unsigned long flags)
20179 {
20180 return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
20181+
20182+#ifdef CONFIG_PAX_SEGMEXEC
20183+ _calc_vm_trans(flags, MAP_MIRROR, VM_MIRROR) |
20184+#endif
20185+
20186 _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) |
20187 _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) |
20188 _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED );
20189diff -urNp linux-2.6.16.12/include/linux/mm.h linux-2.6.16.12/include/linux/mm.h
20190--- linux-2.6.16.12/include/linux/mm.h 2006-05-01 15:14:26.000000000 -0400
20191+++ linux-2.6.16.12/include/linux/mm.h 2006-05-01 20:17:34.000000000 -0400
20192@@ -38,6 +38,7 @@ extern int sysctl_legacy_va_layout;
20193 #include <asm/pgtable.h>
20194 #include <asm/processor.h>
20195 #include <asm/atomic.h>
20196+#include <asm/mman.h>
20197
20198 #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
20199
20200@@ -111,8 +112,43 @@ struct vm_area_struct {
20201 #ifdef CONFIG_NUMA
20202 struct mempolicy *vm_policy; /* NUMA policy for the VMA */
20203 #endif
20204+
20205+ unsigned long vm_mirror; /* PaX: mirror distance */
20206 };
20207
20208+#ifdef CONFIG_PAX_SOFTMODE
20209+extern unsigned int pax_softmode;
20210+#endif
20211+
20212+extern int pax_check_flags(unsigned long *);
20213+
20214+/* if tsk != current then task_lock must be held on it */
20215+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
20216+static inline unsigned long pax_get_flags(struct task_struct *tsk)
20217+{
20218+ if (likely(tsk->mm))
20219+ return tsk->mm->pax_flags;
20220+ else
20221+ return 0UL;
20222+}
20223+
20224+/* if tsk != current then task_lock must be held on it */
20225+static inline long pax_set_flags(struct task_struct *tsk, unsigned long flags)
20226+{
20227+ if (likely(tsk->mm)) {
20228+ tsk->mm->pax_flags = flags;
20229+ return 0;
20230+ }
20231+ return -EINVAL;
20232+}
20233+#endif
20234+
20235+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
20236+extern void pax_set_initial_flags(struct linux_binprm * bprm);
20237+#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
20238+extern void (*pax_set_initial_flags_func)(struct linux_binprm * bprm);
20239+#endif
20240+
20241 /*
20242 * This struct defines the per-mm list of VMAs for uClinux. If CONFIG_MMU is
20243 * disabled, then there's a single shared list of VMAs maintained by the
20244@@ -167,6 +203,18 @@ extern unsigned int kobjsize(const void
20245 #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */
20246 #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */
20247
20248+#ifdef CONFIG_PAX_SEGMEXEC
20249+#define VM_MIRROR 0x04000000 /* vma is mirroring another */
20250+#endif
20251+
20252+#ifdef CONFIG_PAX_MPROTECT
20253+#define VM_MAYNOTWRITE 0x08000000 /* vma cannot be granted VM_WRITE any more */
20254+#endif
20255+
20256+#ifdef __VM_STACK_FLAGS
20257+#define VM_STACK_DEFAULT_FLAGS (0x00000033 | __VM_STACK_FLAGS)
20258+#endif
20259+
20260 #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
20261 #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
20262 #endif
20263@@ -1056,5 +1104,11 @@ void drop_slab(void);
20264 extern int randomize_va_space;
20265 #endif
20266
20267+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
20268+extern void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot);
20269+#else
20270+static inline void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot) {}
20271+#endif
20272+
20273 #endif /* __KERNEL__ */
20274 #endif /* _LINUX_MM_H */
20275diff -urNp linux-2.6.16.12/include/linux/module.h linux-2.6.16.12/include/linux/module.h
20276--- linux-2.6.16.12/include/linux/module.h 2006-05-01 15:14:26.000000000 -0400
20277+++ linux-2.6.16.12/include/linux/module.h 2006-05-01 20:17:34.000000000 -0400
20278@@ -263,16 +263,16 @@ struct module
20279 int (*init)(void);
20280
20281 /* If this is non-NULL, vfree after init() returns */
20282- void *module_init;
20283+ void *module_init_rx, *module_init_rw;
20284
20285 /* Here is the actual code + data, vfree'd on unload. */
20286- void *module_core;
20287+ void *module_core_rx, *module_core_rw;
20288
20289 /* Here are the sizes of the init and core sections */
20290- unsigned long init_size, core_size;
20291+ unsigned long init_size_rw, core_size_rw;
20292
20293 /* The size of the executable code in each section. */
20294- unsigned long init_text_size, core_text_size;
20295+ unsigned long init_size_rx, core_size_rx;
20296
20297 /* Arch-specific module values */
20298 struct mod_arch_specific arch;
20299diff -urNp linux-2.6.16.12/include/linux/moduleloader.h linux-2.6.16.12/include/linux/moduleloader.h
20300--- linux-2.6.16.12/include/linux/moduleloader.h 2006-05-01 15:14:26.000000000 -0400
20301+++ linux-2.6.16.12/include/linux/moduleloader.h 2006-05-01 20:17:34.000000000 -0400
20302@@ -17,9 +17,21 @@ int module_frob_arch_sections(Elf_Ehdr *
20303 sections. Returns NULL on failure. */
20304 void *module_alloc(unsigned long size);
20305
20306+#ifdef CONFIG_PAX_KERNEXEC
20307+void *module_alloc_exec(unsigned long size);
20308+#else
20309+#define module_alloc_exec(x) module_alloc(x)
20310+#endif
20311+
20312 /* Free memory returned from module_alloc. */
20313 void module_free(struct module *mod, void *module_region);
20314
20315+#ifdef CONFIG_PAX_KERNEXEC
20316+void module_free_exec(struct module *mod, void *module_region);
20317+#else
20318+#define module_free_exec(x, y) module_free(x, y)
20319+#endif
20320+
20321 /* Apply the given relocation to the (simplified) ELF. Return -error
20322 or 0. */
20323 int apply_relocate(Elf_Shdr *sechdrs,
20324diff -urNp linux-2.6.16.12/include/linux/random.h linux-2.6.16.12/include/linux/random.h
20325--- linux-2.6.16.12/include/linux/random.h 2006-05-01 15:14:26.000000000 -0400
20326+++ linux-2.6.16.12/include/linux/random.h 2006-05-01 20:17:34.000000000 -0400
20327@@ -62,6 +62,8 @@ extern __u32 secure_tcpv6_sequence_numbe
20328 extern u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr,
20329 __u16 sport, __u16 dport);
20330
20331+extern unsigned long pax_get_random_long(void);
20332+
20333 #ifndef MODULE
20334 extern struct file_operations random_fops, urandom_fops;
20335 #endif
20336diff -urNp linux-2.6.16.12/include/linux/sched.h linux-2.6.16.12/include/linux/sched.h
20337--- linux-2.6.16.12/include/linux/sched.h 2006-05-01 15:14:26.000000000 -0400
20338+++ linux-2.6.16.12/include/linux/sched.h 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 20339@@ -40,6 +40,7 @@
89675291 20340 #include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
20341
20342 struct exec_domain;
20343+struct linux_binprm;
20344
20345 /*
20346 * cloning flags:
9a4c6ab7 20347@@ -355,8 +356,34 @@ struct mm_struct {
89675291 20348 /* aio bits */
20349 rwlock_t ioctx_list_lock;
20350 struct kioctx *ioctx_list;
20351+
20352+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
20353+ unsigned long pax_flags;
20354+#endif
20355+
20356+#ifdef CONFIG_PAX_DLRESOLVE
20357+ unsigned long call_dl_resolve;
20358+#endif
20359+
20360+#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
20361+ unsigned long call_syscall;
20362+#endif
20363+
20364+#ifdef CONFIG_PAX_ASLR
20365+ unsigned long delta_mmap; /* randomized offset */
20366+ unsigned long delta_exec; /* randomized offset */
20367+ unsigned long delta_stack; /* randomized offset */
20368+#endif
20369+
20370 };
20371
20372+#define MF_PAX_PAGEEXEC 0x01000000 /* Paging based non-executable pages */
20373+#define MF_PAX_EMUTRAMP 0x02000000 /* Emulate trampolines */
20374+#define MF_PAX_MPROTECT 0x04000000 /* Restrict mprotect() */
20375+#define MF_PAX_RANDMMAP 0x08000000 /* Randomize mmap() base */
20376+/*#define MF_PAX_RANDEXEC 0x10000000*/ /* Randomize ET_EXEC base */
20377+#define MF_PAX_SEGMEXEC 0x20000000 /* Segmentation based non-executable pages */
20378+
20379 struct sighand_struct {
20380 atomic_t count;
20381 struct k_sigaction action[_NSIG];
9a4c6ab7 20382@@ -461,6 +488,15 @@ struct signal_struct {
89675291 20383 struct key *session_keyring; /* keyring inherited over fork */
20384 struct key *process_keyring; /* keyring private to this process */
20385 #endif
20386+
20387+#ifdef CONFIG_GRKERNSEC
20388+ u32 curr_ip;
20389+ u32 gr_saddr;
20390+ u32 gr_daddr;
20391+ u16 gr_sport;
20392+ u16 gr_dport;
20393+ u8 used_accept:1;
20394+#endif
20395 };
20396
20397 /* Context switch must be unlocked if interrupts are to be enabled */
9a4c6ab7 20398@@ -886,6 +912,16 @@ struct task_struct {
89675291 20399 nodemask_t mems_allowed;
20400 int cpuset_mems_generation;
20401 #endif
20402+#ifdef CONFIG_GRKERNSEC
20403+ /* grsecurity */
20404+ struct acl_subject_label *acl;
20405+ struct acl_role_label *role;
20406+ struct file *exec_file;
20407+ u16 acl_role_id;
20408+ u8 acl_sp_role:1;
20409+ u8 is_writable:1;
20410+ u8 brute:1;
20411+#endif
20412 atomic_t fs_excl; /* holding fs exclusive resources */
20413 struct rcu_head rcu;
20414 };
9a4c6ab7 20415@@ -1402,6 +1442,12 @@ extern void arch_pick_mmap_layout(struct
89675291 20416 static inline void arch_pick_mmap_layout(struct mm_struct *mm)
20417 {
20418 mm->mmap_base = TASK_UNMAPPED_BASE;
20419+
20420+#ifdef CONFIG_PAX_RANDMMAP
20421+ if (mm->pax_flags & MF_PAX_RANDMMAP)
20422+ mm->mmap_base += mm->delta_mmap;
20423+#endif
20424+
20425 mm->get_unmapped_area = arch_get_unmapped_area;
20426 mm->unmap_area = arch_unmap_area;
20427 }
20428diff -urNp linux-2.6.16.12/include/linux/shm.h linux-2.6.16.12/include/linux/shm.h
20429--- linux-2.6.16.12/include/linux/shm.h 2006-05-01 15:14:26.000000000 -0400
20430+++ linux-2.6.16.12/include/linux/shm.h 2006-05-01 20:17:34.000000000 -0400
20431@@ -86,6 +86,10 @@ struct shmid_kernel /* private to the ke
20432 pid_t shm_cprid;
20433 pid_t shm_lprid;
20434 struct user_struct *mlock_user;
20435+#ifdef CONFIG_GRKERNSEC
20436+ time_t shm_createtime;
20437+ pid_t shm_lapid;
20438+#endif
20439 };
20440
20441 /* shm_mode upper byte flags */
20442diff -urNp linux-2.6.16.12/include/linux/sysctl.h linux-2.6.16.12/include/linux/sysctl.h
20443--- linux-2.6.16.12/include/linux/sysctl.h 2006-05-01 15:14:26.000000000 -0400
20444+++ linux-2.6.16.12/include/linux/sysctl.h 2006-05-01 20:17:34.000000000 -0400
b91bd884 20445@@ -78,9 +78,21 @@
20446 INOTIFY_MAX_QUEUED_EVENTS=3 /* max queued events per instance */
89675291 20447 };
20448
20449+#ifdef CONFIG_PAX_SOFTMODE
20450+enum {
20451+ PAX_SOFTMODE=1 /* PaX: disable/enable soft mode */
20452+};
20453+#endif
b91bd884 20454+
20455 /* CTL_KERN names: */
89675291 20456 enum
b91bd884 20457 {
20458+#ifdef CONFIG_GRKERNSEC
20459+ KERN_GRSECURITY=98, /* grsecurity */
20460+#endif
20461+#ifdef CONFIG_PAX_SOFTMODE
20462+ KERN_PAX=99, /* PaX control */
20463+#endif
20464 KERN_OSTYPE=1, /* string: system version */
20465 KERN_OSRELEASE=2, /* string: system release */
20466 KERN_OSREV=3, /* int: system revision */
89675291 20467diff -urNp linux-2.6.16.12/init/Kconfig linux-2.6.16.12/init/Kconfig
20468--- linux-2.6.16.12/init/Kconfig 2006-05-01 15:14:26.000000000 -0400
20469+++ linux-2.6.16.12/init/Kconfig 2006-05-01 20:17:34.000000000 -0400
20470@@ -257,6 +257,7 @@ menuconfig EMBEDDED
20471 config KALLSYMS
20472 bool "Load all symbols for debugging/kksymoops" if EMBEDDED
20473 default y
20474+ depends on !GRKERNSEC_HIDESYM
20475 help
20476 Say Y here to let the kernel print out symbolic crash information and
20477 symbolic stack backtraces. This increases the size of the kernel
20478diff -urNp linux-2.6.16.12/init/main.c linux-2.6.16.12/init/main.c
20479--- linux-2.6.16.12/init/main.c 2006-05-01 15:14:26.000000000 -0400
20480+++ linux-2.6.16.12/init/main.c 2006-05-01 20:17:34.000000000 -0400
20481@@ -100,6 +100,7 @@ static inline void mark_rodata_ro(void)
20482 #ifdef CONFIG_TC
20483 extern void tc_init(void);
20484 #endif
20485+extern void grsecurity_init(void);
20486
20487 enum system_states system_state;
20488 EXPORT_SYMBOL(system_state);
20489@@ -150,6 +151,15 @@ static int __init maxcpus(char *str)
20490
20491 __setup("maxcpus=", maxcpus);
20492
20493+#ifdef CONFIG_PAX_SOFTMODE
20494+static int __init setup_pax_softmode(char *str)
20495+{
20496+ get_option(&str, &pax_softmode);
20497+ return 1;
20498+}
20499+__setup("pax_softmode=", setup_pax_softmode);
20500+#endif
20501+
20502 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
20503 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
20504 static const char *panic_later, *panic_param;
9a4c6ab7 20505@@ -701,6 +711,8 @@ static int init(void * unused)
89675291 20506 prepare_namespace();
20507 }
20508
20509+ grsecurity_init();
20510+
20511 /*
20512 * Ok, we have completed the initial bootup, and
20513 * we're essentially up and running. Get rid of the
20514diff -urNp linux-2.6.16.12/ipc/msg.c linux-2.6.16.12/ipc/msg.c
20515--- linux-2.6.16.12/ipc/msg.c 2006-05-01 15:14:26.000000000 -0400
20516+++ linux-2.6.16.12/ipc/msg.c 2006-05-01 20:17:34.000000000 -0400
20517@@ -28,6 +28,7 @@
20518 #include <linux/syscalls.h>
20519 #include <linux/audit.h>
20520 #include <linux/seq_file.h>
20521+#include <linux/grsecurity.h>
20522 #include <asm/current.h>
20523 #include <asm/uaccess.h>
20524 #include "util.h"
9a4c6ab7 20525@@ -234,6 +235,9 @@ asmlinkage long sys_msgget (key_t key, i
89675291 20526 msg_unlock(msq);
20527 }
20528 up(&msg_ids.sem);
20529+
20530+ gr_log_msgget(ret, msgflg);
20531+
20532 return ret;
20533 }
20534
9a4c6ab7 20535@@ -485,6 +489,8 @@ asmlinkage long sys_msgctl (int msqid, i
89675291 20536 break;
20537 }
20538 case IPC_RMID:
20539+ gr_log_msgrm(ipcp->uid, ipcp->cuid);
20540+
20541 freeque (msq, msqid);
20542 break;
20543 }
20544diff -urNp linux-2.6.16.12/ipc/sem.c linux-2.6.16.12/ipc/sem.c
20545--- linux-2.6.16.12/ipc/sem.c 2006-05-01 15:14:26.000000000 -0400
20546+++ linux-2.6.16.12/ipc/sem.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 20547@@ -76,6 +76,7 @@
89675291 20548 #include <linux/capability.h>
20549 #include <linux/seq_file.h>
9a4c6ab7 20550 #include <linux/vs_limit.h>
89675291 20551+#include <linux/grsecurity.h>
20552 #include <asm/uaccess.h>
20553 #include "util.h"
20554
9a4c6ab7 20555@@ -247,6 +248,9 @@ asmlinkage long sys_semget (key_t key, i
89675291 20556 }
20557
20558 up(&sem_ids.sem);
20559+
20560+ gr_log_semget(err, semflg);
20561+
20562 return err;
20563 }
20564
9a4c6ab7 20565@@ -840,6 +844,8 @@ static int semctl_down(int semid, int se
89675291 20566
20567 switch(cmd){
20568 case IPC_RMID:
20569+ gr_log_semrm(ipcp->uid, ipcp->cuid);
20570+
20571 freeary(sma, semid);
20572 err = 0;
20573 break;
20574diff -urNp linux-2.6.16.12/ipc/shm.c linux-2.6.16.12/ipc/shm.c
20575--- linux-2.6.16.12/ipc/shm.c 2006-05-01 15:14:26.000000000 -0400
20576+++ linux-2.6.16.12/ipc/shm.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 20577@@ -32,6 +32,7 @@
89675291 20578 #include <linux/seq_file.h>
9a4c6ab7 20579 #include <linux/vs_context.h>
20580 #include <linux/vs_limit.h>
89675291 20581+#include <linux/grsecurity.h>
20582
20583 #include <asm/uaccess.h>
20584
9a4c6ab7 20585@@ -55,6 +56,14 @@ static void shm_close (struct vm_area_st
89675291 20586 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
20587 #endif
20588
20589+#ifdef CONFIG_GRKERNSEC
20590+extern int gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
20591+ const time_t shm_createtime, const uid_t cuid,
20592+ const int shmid);
20593+extern int gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
20594+ const time_t shm_createtime);
20595+#endif
20596+
20597 size_t shm_ctlmax = SHMMAX;
20598 size_t shm_ctlall = SHMALL;
20599 int shm_ctlmni = SHMMNI;
9a4c6ab7 20600@@ -154,6 +163,17 @@ static void shm_close (struct vm_area_st
89675291 20601 shp->shm_lprid = current->tgid;
20602 shp->shm_dtim = get_seconds();
20603 shp->shm_nattch--;
20604+#ifdef CONFIG_GRKERNSEC_SHM
20605+ if (grsec_enable_shm) {
20606+ if (shp->shm_nattch == 0) {
20607+ shp->shm_perm.mode |= SHM_DEST;
20608+ shm_destroy(shp);
20609+ } else
20610+ shm_unlock(shp);
20611+ up(&shm_ids.sem);
20612+ return;
20613+ }
20614+#endif
20615 if(shp->shm_nattch == 0 &&
20616 shp->shm_perm.mode & SHM_DEST)
20617 shm_destroy (shp);
9a4c6ab7 20618@@ -256,6 +276,9 @@ static int newseg (key_t key, int shmflg
89675291 20619 shp->shm_lprid = 0;
20620 shp->shm_atim = shp->shm_dtim = 0;
20621 shp->shm_ctim = get_seconds();
20622+#ifdef CONFIG_GRKERNSEC
20623+ shp->shm_createtime = get_seconds();
20624+#endif
20625 shp->shm_segsz = size;
20626 shp->shm_nattch = 0;
20627 shp->id = shm_buildid(id,shp->shm_perm.seq);
9a4c6ab7 20628@@ -312,6 +335,8 @@ asmlinkage long sys_shmget (key_t key, s
89675291 20629 }
20630 up(&shm_ids.sem);
20631
20632+ gr_log_shmget(err, shmflg, size);
20633+
20634 return err;
20635 }
20636
9a4c6ab7 20637@@ -617,6 +642,8 @@ asmlinkage long sys_shmctl (int shmid, i
89675291 20638 if (err)
20639 goto out_unlock_up;
20640
20641+ gr_log_shmrm(shp->shm_perm.uid, shp->shm_perm.cuid);
20642+
20643 if (shp->shm_nattch){
20644 shp->shm_perm.mode |= SHM_DEST;
20645 /* Do not find it any more */
9a4c6ab7 20646@@ -761,9 +788,27 @@ long do_shmat(int shmid, char __user *sh
89675291 20647 return err;
20648 }
20649
20650+#ifdef CONFIG_GRKERNSEC
20651+ if (!gr_handle_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime,
20652+ shp->shm_perm.cuid, shmid)) {
20653+ shm_unlock(shp);
20654+ return -EACCES;
20655+ }
20656+
20657+ if (!gr_chroot_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime)) {
20658+ shm_unlock(shp);
20659+ return -EACCES;
20660+ }
20661+#endif
20662+
20663 file = shp->shm_file;
20664 size = i_size_read(file->f_dentry->d_inode);
20665 shp->shm_nattch++;
20666+
20667+#ifdef CONFIG_GRKERNSEC
20668+ shp->shm_lapid = current->pid;
20669+#endif
20670+
20671 shm_unlock(shp);
20672
20673 down_write(&current->mm->mmap_sem);
9a4c6ab7 20674@@ -933,3 +978,24 @@ static int sysvipc_shm_proc_show(struct
89675291 20675 shp->shm_ctim);
20676 }
20677 #endif
20678+
20679+void gr_shm_exit(struct task_struct *task)
20680+{
20681+#ifdef CONFIG_GRKERNSEC_SHM
20682+ int i;
20683+ struct shmid_kernel *shp;
20684+
20685+ if (!grsec_enable_shm)
20686+ return;
20687+
20688+ for (i = 0; i <= shm_ids.max_id; i++) {
20689+ shp = shm_get(i);
20690+ if (shp && (shp->shm_cprid == task->pid) &&
20691+ (shp->shm_nattch <= 0)) {
20692+ shp->shm_perm.mode |= SHM_DEST;
20693+ shm_destroy(shp);
20694+ }
20695+ }
20696+#endif
20697+ return;
20698+}
20699diff -urNp linux-2.6.16.12/kernel/capability.c linux-2.6.16.12/kernel/capability.c
20700--- linux-2.6.16.12/kernel/capability.c 2006-05-01 15:14:26.000000000 -0400
20701+++ linux-2.6.16.12/kernel/capability.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 20702@@ -13,6 +13,7 @@
89675291 20703 #include <linux/security.h>
20704 #include <linux/syscalls.h>
9a4c6ab7 20705 #include <linux/vs_pid.h>
89675291 20706+#include <linux/grsecurity.h>
20707 #include <asm/uaccess.h>
20708
20709 unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
20710diff -urNp linux-2.6.16.12/kernel/configs.c linux-2.6.16.12/kernel/configs.c
20711--- linux-2.6.16.12/kernel/configs.c 2006-05-01 15:14:26.000000000 -0400
20712+++ linux-2.6.16.12/kernel/configs.c 2006-05-01 20:17:34.000000000 -0400
20713@@ -89,8 +89,16 @@ static int __init ikconfig_init(void)
20714 struct proc_dir_entry *entry;
20715
20716 /* create the current config file */
20717+#ifdef CONFIG_GRKERNSEC_PROC_ADD
20718+#ifdef CONFIG_GRKERNSEC_PROC_USER
20719+ entry = create_proc_entry("config.gz", S_IFREG | S_IRUSR, &proc_root);
20720+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
20721+ entry = create_proc_entry("config.gz", S_IFREG | S_IRUSR | S_IRGRP, &proc_root);
20722+#endif
20723+#else
20724 entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
20725 &proc_root);
20726+#endif
20727 if (!entry)
20728 return -ENOMEM;
20729
20730diff -urNp linux-2.6.16.12/kernel/exit.c linux-2.6.16.12/kernel/exit.c
20731--- linux-2.6.16.12/kernel/exit.c 2006-05-01 15:14:26.000000000 -0400
20732+++ linux-2.6.16.12/kernel/exit.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 20733@@ -35,6 +35,11 @@
20734 #include <linux/vs_context.h>
20735 #include <linux/vs_network.h>
20736 #include <linux/vs_pid.h>
89675291 20737+#include <linux/grsecurity.h>
20738+
20739+#ifdef CONFIG_GRKERNSEC
20740+extern rwlock_t grsec_exec_file_lock;
20741+#endif
20742
20743 #include <asm/uaccess.h>
20744 #include <asm/unistd.h>
9a4c6ab7 20745@@ -238,6 +244,15 @@ static void reparent_to_init(void)
89675291 20746 {
20747 write_lock_irq(&tasklist_lock);
20748
20749+#ifdef CONFIG_GRKERNSEC
20750+ write_lock(&grsec_exec_file_lock);
20751+ if (current->exec_file) {
20752+ fput(current->exec_file);
20753+ current->exec_file = NULL;
20754+ }
20755+ write_unlock(&grsec_exec_file_lock);
20756+#endif
20757+
20758 ptrace_unlink(current);
20759 /* Reparent to init */
20760 REMOVE_LINKS(current);
9a4c6ab7 20761@@ -245,6 +259,8 @@ static void reparent_to_init(void)
89675291 20762 current->real_parent = child_reaper;
20763 SET_LINKS(current);
20764
20765+ gr_set_kernel_label(current);
20766+
20767 /* Set the exit signal to SIGCHLD so we signal init on exit */
20768 current->exit_signal = SIGCHLD;
20769
9a4c6ab7 20770@@ -341,6 +357,17 @@ void daemonize(const char *name, ...)
89675291 20771 vsnprintf(current->comm, sizeof(current->comm), name, args);
20772 va_end(args);
20773
20774+#ifdef CONFIG_GRKERNSEC
20775+ write_lock(&grsec_exec_file_lock);
20776+ if (current->exec_file) {
20777+ fput(current->exec_file);
20778+ current->exec_file = NULL;
20779+ }
20780+ write_unlock(&grsec_exec_file_lock);
20781+#endif
20782+
20783+ gr_set_kernel_label(current);
20784+
20785 /*
20786 * If we were started as result of loading a module, close all of the
20787 * user space pages. We don't need them, and if we didn't close them
9a4c6ab7 20788@@ -863,9 +890,14 @@ fastcall NORET_TYPE void do_exit(long co
89675291 20789 exit_itimers(tsk->signal);
20790 acct_process(code);
20791 }
20792+
20793+ gr_acl_handle_psacct(tsk, code);
20794+ gr_acl_handle_exit();
20795+
20796 exit_mm(tsk);
20797
20798 exit_sem(tsk);
20799+ gr_shm_exit(tsk);
20800 __exit_files(tsk);
20801 __exit_fs(tsk);
20802 exit_namespace(tsk);
20803diff -urNp linux-2.6.16.12/kernel/fork.c linux-2.6.16.12/kernel/fork.c
20804--- linux-2.6.16.12/kernel/fork.c 2006-05-01 15:14:26.000000000 -0400
20805+++ linux-2.6.16.12/kernel/fork.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 20806@@ -48,6 +48,7 @@
20807 #include <linux/vs_network.h>
20808 #include <linux/vs_limit.h>
20809 #include <linux/vs_memory.h>
89675291 20810+#include <linux/grsecurity.h>
20811
20812 #include <asm/pgtable.h>
20813 #include <asm/pgalloc.h>
9a4c6ab7 20814@@ -207,8 +208,8 @@ static inline int dup_mmap(struct mm_str
89675291 20815 mm->locked_vm = 0;
20816 mm->mmap = NULL;
20817 mm->mmap_cache = NULL;
20818- mm->free_area_cache = oldmm->mmap_base;
20819- mm->cached_hole_size = ~0UL;
20820+ mm->free_area_cache = oldmm->free_area_cache;
20821+ mm->cached_hole_size = oldmm->cached_hole_size;
20822 mm->map_count = 0;
9a4c6ab7 20823 __set_mm_counter(mm, file_rss, 0);
20824 __set_mm_counter(mm, anon_rss, 0);
20825@@ -333,7 +334,7 @@ static struct mm_struct * mm_init(struct
89675291 20826 spin_lock_init(&mm->page_table_lock);
20827 rwlock_init(&mm->ioctx_list_lock);
20828 mm->ioctx_list = NULL;
20829- mm->free_area_cache = TASK_UNMAPPED_BASE;
20830+ mm->free_area_cache = ~0UL;
20831 mm->cached_hole_size = ~0UL;
20832
20833 if (likely(!mm_alloc_pgd(mm))) {
9a4c6ab7 20834@@ -1013,6 +1014,9 @@ static task_t *copy_process(unsigned lon
20835 if (!vx_nproc_avail(1))
20836 goto bad_fork_cleanup_vm;
89675291 20837
89675291 20838+
20839+ gr_learn_resource(p, RLIMIT_NPROC, atomic_read(&p->user->processes), 0);
20840+
20841 if (atomic_read(&p->user->processes) >=
20842 p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
20843 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
9a4c6ab7 20844@@ -1122,6 +1126,8 @@ static task_t *copy_process(unsigned lon
89675291 20845 if (retval)
20846 goto bad_fork_cleanup_namespace;
20847
20848+ gr_copy_label(p);
20849+
20850 p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
20851 /*
20852 * Clear TID on mm_release()?
9a4c6ab7 20853@@ -1321,6 +1327,8 @@ bad_fork_cleanup_count:
89675291 20854 bad_fork_free:
20855 free_task(p);
20856 fork_out:
20857+ gr_log_forkfail(retval);
20858+
20859 return ERR_PTR(retval);
20860 }
20861
9a4c6ab7 20862@@ -1387,6 +1395,8 @@ long do_fork(unsigned long clone_flags,
20863 return -EPERM;
20864 }
89675291 20865
89675291 20866+ gr_handle_brute_check();
20867+
20868 if (unlikely(current->ptrace)) {
20869 trace = fork_traceflag (clone_flags);
20870 if (trace)
20871diff -urNp linux-2.6.16.12/kernel/futex.c linux-2.6.16.12/kernel/futex.c
20872--- linux-2.6.16.12/kernel/futex.c 2006-05-01 15:14:26.000000000 -0400
20873+++ linux-2.6.16.12/kernel/futex.c 2006-05-01 20:17:34.000000000 -0400
20874@@ -147,6 +147,11 @@ static int get_futex_key(unsigned long u
20875 struct page *page;
20876 int err;
20877
20878+#ifdef CONFIG_PAX_SEGMEXEC
20879+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (uaddr >= SEGMEXEC_TASK_SIZE))
20880+ return -EFAULT;
20881+#endif
20882+
20883 /*
20884 * The futex address must be "naturally" aligned.
20885 */
20886diff -urNp linux-2.6.16.12/kernel/kallsyms.c linux-2.6.16.12/kernel/kallsyms.c
20887--- linux-2.6.16.12/kernel/kallsyms.c 2006-05-01 15:14:26.000000000 -0400
20888+++ linux-2.6.16.12/kernel/kallsyms.c 2006-05-01 20:17:34.000000000 -0400
20889@@ -301,7 +301,6 @@ static unsigned long get_ksymbol_core(st
20890
20891 static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
20892 {
20893- iter->name[0] = '\0';
20894 iter->nameoff = get_symbol_offset(new_pos);
20895 iter->pos = new_pos;
20896 }
20897@@ -380,7 +379,7 @@ static int kallsyms_open(struct inode *i
20898 struct kallsym_iter *iter;
20899 int ret;
20900
20901- iter = kmalloc(sizeof(*iter), GFP_KERNEL);
20902+ iter = kzalloc(sizeof(*iter), GFP_KERNEL);
20903 if (!iter)
20904 return -ENOMEM;
20905 reset_iter(iter, 0);
20906@@ -411,7 +410,15 @@ static int __init kallsyms_init(void)
20907 {
20908 struct proc_dir_entry *entry;
20909
20910+#ifdef CONFIG_GRKERNSEC_PROC_ADD
20911+#ifdef CONFIG_GRKERNSEC_PROC_USER
20912+ entry = create_proc_entry("kallsyms", S_IFREG | S_IRUSR, NULL);
20913+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
20914+ entry = create_proc_entry("kallsyms", S_IFREG | S_IRUSR | S_IRGRP, NULL);
20915+#endif
20916+#else
20917 entry = create_proc_entry("kallsyms", 0444, NULL);
20918+#endif
20919 if (entry)
20920 entry->proc_fops = &kallsyms_operations;
20921 return 0;
20922diff -urNp linux-2.6.16.12/kernel/kprobes.c linux-2.6.16.12/kernel/kprobes.c
20923--- linux-2.6.16.12/kernel/kprobes.c 2006-05-01 15:14:26.000000000 -0400
20924+++ linux-2.6.16.12/kernel/kprobes.c 2006-05-01 20:17:34.000000000 -0400
20925@@ -106,7 +106,7 @@ kprobe_opcode_t __kprobes *get_insn_slot
20926 * kernel image and loaded module images reside. This is required
20927 * so x86_64 can correctly handle the %rip-relative fixups.
20928 */
20929- kip->insns = module_alloc(PAGE_SIZE);
20930+ kip->insns = module_alloc_exec(PAGE_SIZE);
20931 if (!kip->insns) {
20932 kfree(kip);
20933 return NULL;
20934diff -urNp linux-2.6.16.12/kernel/module.c linux-2.6.16.12/kernel/module.c
20935--- linux-2.6.16.12/kernel/module.c 2006-05-01 15:14:26.000000000 -0400
20936+++ linux-2.6.16.12/kernel/module.c 2006-05-01 20:17:34.000000000 -0400
20937@@ -39,10 +39,15 @@
20938 #include <linux/device.h>
20939 #include <linux/string.h>
20940 #include <linux/sched.h>
20941+#include <linux/kallsyms.h>
20942 #include <asm/uaccess.h>
20943 #include <asm/semaphore.h>
20944 #include <asm/cacheflush.h>
20945
20946+#ifdef CONFIG_PAX_KERNEXEC
20947+#include <asm/desc.h>
20948+#endif
20949+
20950 #if 0
20951 #define DEBUGP printk
20952 #else
20953@@ -66,6 +71,8 @@ static LIST_HEAD(modules);
20954 static DECLARE_MUTEX(notify_mutex);
20955 static struct notifier_block * module_notify_list;
20956
20957+extern int gr_check_modstop(void);
20958+
20959 int register_module_notifier(struct notifier_block * nb)
20960 {
20961 int err;
20962@@ -576,6 +583,9 @@ sys_delete_module(const char __user *nam
20963 char name[MODULE_NAME_LEN];
20964 int ret, forced = 0;
20965
20966+ if (gr_check_modstop())
20967+ return -EPERM;
20968+
20969 if (!capable(CAP_SYS_MODULE))
20970 return -EPERM;
20971
20972@@ -1178,13 +1188,15 @@ static void free_module(struct module *m
20973 module_unload_free(mod);
20974
20975 /* This may be NULL, but that's OK */
20976- module_free(mod, mod->module_init);
20977+ module_free(mod, mod->module_init_rw);
20978+ module_free_exec(mod, mod->module_init_rx);
20979 kfree(mod->args);
20980 if (mod->percpu)
20981 percpu_modfree(mod->percpu);
20982
20983 /* Finally, free the core (containing the module structure) */
20984- module_free(mod, mod->module_core);
20985+ module_free_exec(mod, mod->module_core_rx);
20986+ module_free(mod, mod->module_core_rw);
20987 }
20988
20989 void *__symbol_get(const char *symbol)
20990@@ -1341,11 +1353,14 @@ static void layout_sections(struct modul
20991 || strncmp(secstrings + s->sh_name,
20992 ".init", 5) == 0)
20993 continue;
20994- s->sh_entsize = get_offset(&mod->core_size, s);
20995+ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
20996+ s->sh_entsize = get_offset(&mod->core_size_rw, s);
20997+ else
20998+ s->sh_entsize = get_offset(&mod->core_size_rx, s);
20999 DEBUGP("\t%s\n", secstrings + s->sh_name);
21000 }
21001 if (m == 0)
21002- mod->core_text_size = mod->core_size;
21003+ mod->core_size_rx = mod->core_size_rx;
21004 }
21005
21006 DEBUGP("Init section allocation order:\n");
21007@@ -1359,12 +1374,15 @@ static void layout_sections(struct modul
21008 || strncmp(secstrings + s->sh_name,
21009 ".init", 5) != 0)
21010 continue;
21011- s->sh_entsize = (get_offset(&mod->init_size, s)
21012- | INIT_OFFSET_MASK);
21013+ if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
21014+ s->sh_entsize = get_offset(&mod->init_size_rw, s);
21015+ else
21016+ s->sh_entsize = get_offset(&mod->init_size_rx, s);
21017+ s->sh_entsize |= INIT_OFFSET_MASK;
21018 DEBUGP("\t%s\n", secstrings + s->sh_name);
21019 }
21020 if (m == 0)
21021- mod->init_text_size = mod->init_size;
21022+ mod->init_size_rx = mod->init_size_rx;
21023 }
21024 }
21025
21026@@ -1545,6 +1563,10 @@ static struct module *load_module(void _
21027 struct exception_table_entry *extable;
21028 mm_segment_t old_fs;
21029
21030+#ifdef CONFIG_PAX_KERNEXEC
21031+ unsigned long cr0;
21032+#endif
21033+
21034 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
21035 umod, len, uargs);
21036 if (len < sizeof(*hdr))
21037@@ -1704,21 +1726,57 @@ static struct module *load_module(void _
21038 layout_sections(mod, hdr, sechdrs, secstrings);
21039
21040 /* Do the allocs. */
21041- ptr = module_alloc(mod->core_size);
21042+ ptr = module_alloc(mod->core_size_rw);
21043 if (!ptr) {
21044 err = -ENOMEM;
21045 goto free_percpu;
21046 }
21047- memset(ptr, 0, mod->core_size);
21048- mod->module_core = ptr;
21049+ memset(ptr, 0, mod->core_size_rw);
21050+ mod->module_core_rw = ptr;
21051+
21052+ ptr = module_alloc(mod->init_size_rw);
21053+ if (!ptr && mod->init_size_rw) {
21054+ err = -ENOMEM;
21055+ goto free_core_rw;
21056+ }
21057+ memset(ptr, 0, mod->init_size_rw);
21058+ mod->module_init_rw = ptr;
21059+
21060+ ptr = module_alloc_exec(mod->core_size_rx);
21061+ if (!ptr) {
21062+ err = -ENOMEM;
21063+ goto free_init_rw;
21064+ }
21065+
21066+#ifdef CONFIG_PAX_KERNEXEC
21067+ pax_open_kernel(cr0);
21068+#endif
21069+
21070+ memset(ptr, 0, mod->core_size_rx);
21071+
21072+#ifdef CONFIG_PAX_KERNEXEC
21073+ pax_close_kernel(cr0);
21074+#endif
21075+
21076+ mod->module_core_rx = ptr;
21077
21078- ptr = module_alloc(mod->init_size);
21079- if (!ptr && mod->init_size) {
21080+ ptr = module_alloc_exec(mod->init_size_rx);
21081+ if (!ptr && mod->init_size_rx) {
21082 err = -ENOMEM;
21083- goto free_core;
21084+ goto free_core_rx;
21085 }
21086- memset(ptr, 0, mod->init_size);
21087- mod->module_init = ptr;
21088+
21089+#ifdef CONFIG_PAX_KERNEXEC
21090+ pax_open_kernel(cr0);
21091+#endif
21092+
21093+ memset(ptr, 0, mod->init_size_rx);
21094+
21095+#ifdef CONFIG_PAX_KERNEXEC
21096+ pax_close_kernel(cr0);
21097+#endif
21098+
21099+ mod->module_init_rx = ptr;
21100
21101 /* Transfer each section which specifies SHF_ALLOC */
21102 DEBUGP("final section addresses:\n");
21103@@ -1728,17 +1786,44 @@ static struct module *load_module(void _
21104 if (!(sechdrs[i].sh_flags & SHF_ALLOC))
21105 continue;
21106
21107- if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK)
21108- dest = mod->module_init
21109- + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
21110- else
21111- dest = mod->module_core + sechdrs[i].sh_entsize;
21112+ if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK) {
21113+ if ((sechdrs[i].sh_flags & SHF_WRITE) || !(sechdrs[i].sh_flags & SHF_ALLOC))
21114+ dest = mod->module_init_rw
21115+ + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
21116+ else
21117+ dest = mod->module_init_rx
21118+ + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
21119+ } else {
21120+ if ((sechdrs[i].sh_flags & SHF_WRITE) || !(sechdrs[i].sh_flags & SHF_ALLOC))
21121+ dest = mod->module_core_rw + sechdrs[i].sh_entsize;
21122+ else
21123+ dest = mod->module_core_rx + sechdrs[i].sh_entsize;
21124+ }
21125
21126- if (sechdrs[i].sh_type != SHT_NOBITS)
21127- memcpy(dest, (void *)sechdrs[i].sh_addr,
21128- sechdrs[i].sh_size);
21129+ if (sechdrs[i].sh_type != SHT_NOBITS) {
21130+
21131+#ifdef CONFIG_PAX_KERNEXEC
21132+ if (!(sechdrs[i].sh_flags & SHF_WRITE) && (sechdrs[i].sh_flags & SHF_ALLOC))
21133+ pax_open_kernel(cr0);
21134+#endif
21135+
21136+ memcpy(dest, (void *)sechdrs[i].sh_addr, sechdrs[i].sh_size);
21137+
21138+#ifdef CONFIG_PAX_KERNEXEC
21139+ if (!(sechdrs[i].sh_flags & SHF_WRITE) && (sechdrs[i].sh_flags & SHF_ALLOC))
21140+ pax_close_kernel(cr0);
21141+#endif
21142+
21143+ }
21144 /* Update sh_addr to point to copy in image. */
21145- sechdrs[i].sh_addr = (unsigned long)dest;
21146+
21147+#ifdef CONFIG_PAX_KERNEXEC
21148+ if (sechdrs[i].sh_flags & SHF_EXECINSTR)
21149+ sechdrs[i].sh_addr = (unsigned long)dest - __KERNEL_TEXT_OFFSET;
21150+ else
21151+#endif
21152+
21153+ sechdrs[i].sh_addr = (unsigned long)dest;
21154 DEBUGP("\t0x%lx %s\n", sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name);
21155 }
21156 /* Module has been moved. */
21157@@ -1761,8 +1846,18 @@ static struct module *load_module(void _
21158 #endif
21159
21160 /* Fix up syms, so that st_value is a pointer to location. */
21161+
21162+#ifdef CONFIG_PAX_KERNEXEC
21163+ pax_open_kernel(cr0);
21164+#endif
21165+
21166 err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
21167 mod);
21168+
21169+#ifdef CONFIG_PAX_KERNEXEC
21170+ pax_close_kernel(cr0);
21171+#endif
21172+
21173 if (err < 0)
21174 goto cleanup;
21175
21176@@ -1798,11 +1893,20 @@ static struct module *load_module(void _
21177 if (!(sechdrs[info].sh_flags & SHF_ALLOC))
21178 continue;
21179
21180+#ifdef CONFIG_PAX_KERNEXEC
21181+ pax_open_kernel(cr0);
21182+#endif
21183+
21184 if (sechdrs[i].sh_type == SHT_REL)
21185 err = apply_relocate(sechdrs, strtab, symindex, i,mod);
21186 else if (sechdrs[i].sh_type == SHT_RELA)
21187 err = apply_relocate_add(sechdrs, strtab, symindex, i,
21188 mod);
21189+
21190+#ifdef CONFIG_PAX_KERNEXEC
21191+ pax_close_kernel(cr0);
21192+#endif
21193+
21194 if (err < 0)
21195 goto cleanup;
21196 }
21197@@ -1816,14 +1920,31 @@ static struct module *load_module(void _
21198 /* Set up and sort exception table */
21199 mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
21200 mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
21201+
21202+#ifdef CONFIG_PAX_KERNEXEC
21203+ pax_open_kernel(cr0);
21204+#endif
21205+
21206 sort_extable(extable, extable + mod->num_exentries);
21207
21208+#ifdef CONFIG_PAX_KERNEXEC
21209+ pax_close_kernel(cr0);
21210+#endif
21211+
21212 /* Finally, copy percpu area over. */
21213 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
21214 sechdrs[pcpuindex].sh_size);
21215
21216+#ifdef CONFIG_PAX_KERNEXEC
21217+ pax_open_kernel(cr0);
21218+#endif
21219+
21220 add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
21221
21222+#ifdef CONFIG_PAX_KERNEXEC
21223+ pax_close_kernel(cr0);
21224+#endif
21225+
21226 err = module_finalize(hdr, sechdrs, mod);
21227 if (err < 0)
21228 goto cleanup;
21229@@ -1837,12 +1958,12 @@ static struct module *load_module(void _
21230 * Do it before processing of module parameters, so the module
21231 * can provide parameter accessor functions of its own.
21232 */
21233- if (mod->module_init)
21234- flush_icache_range((unsigned long)mod->module_init,
21235- (unsigned long)mod->module_init
21236- + mod->init_size);
21237- flush_icache_range((unsigned long)mod->module_core,
21238- (unsigned long)mod->module_core + mod->core_size);
21239+ if (mod->module_init_rx)
21240+ flush_icache_range((unsigned long)mod->module_init_rx,
21241+ (unsigned long)mod->module_init_rx
21242+ + mod->init_size_rx);
21243+ flush_icache_range((unsigned long)mod->module_core_rx,
21244+ (unsigned long)mod->module_core_rx + mod->core_size_rx);
21245
21246 set_fs(old_fs);
21247
21248@@ -1890,9 +2011,13 @@ static struct module *load_module(void _
21249 module_arch_cleanup(mod);
21250 cleanup:
21251 module_unload_free(mod);
21252- module_free(mod, mod->module_init);
21253- free_core:
21254- module_free(mod, mod->module_core);
21255+ module_free_exec(mod, mod->module_init_rx);
21256+ free_core_rx:
21257+ module_free_exec(mod, mod->module_core_rx);
21258+ free_init_rw:
21259+ module_free(mod, mod->module_init_rw);
21260+ free_core_rw:
21261+ module_free(mod, mod->module_core_rw);
21262 free_percpu:
21263 if (percpu)
21264 percpu_modfree(percpu);
21265@@ -1928,6 +2053,9 @@ sys_init_module(void __user *umod,
21266 struct module *mod;
21267 int ret = 0;
21268
21269+ if (gr_check_modstop())
21270+ return -EPERM;
21271+
21272 /* Must have permission */
21273 if (!capable(CAP_SYS_MODULE))
21274 return -EPERM;
21275@@ -1979,10 +2107,12 @@ sys_init_module(void __user *umod,
21276 mod->state = MODULE_STATE_LIVE;
21277 /* Drop initial reference. */
21278 module_put(mod);
21279- module_free(mod, mod->module_init);
21280- mod->module_init = NULL;
21281- mod->init_size = 0;
21282- mod->init_text_size = 0;
21283+ module_free(mod, mod->module_init_rw);
21284+ module_free_exec(mod, mod->module_init_rx);
21285+ mod->module_init_rw = NULL;
21286+ mod->module_init_rx = NULL;
21287+ mod->init_size_rw = 0;
21288+ mod->init_size_rx = 0;
21289 up(&module_mutex);
21290
21291 return 0;
21292@@ -2013,10 +2143,14 @@ static const char *get_ksymbol(struct mo
21293 unsigned long nextval;
21294
21295 /* At worse, next value is at end of module */
21296- if (within(addr, mod->module_init, mod->init_size))
21297- nextval = (unsigned long)mod->module_init+mod->init_text_size;
21298- else
21299- nextval = (unsigned long)mod->module_core+mod->core_text_size;
21300+ if (within(addr, mod->module_init_rx, mod->init_size_rx))
21301+ nextval = (unsigned long)mod->module_init_rw;
21302+ else if (within(addr, mod->module_init_rw, mod->init_size_rw))
21303+ nextval = (unsigned long)mod->module_core_rx;
21304+ else if (within(addr, mod->module_core_rx, mod->core_size_rx))
21305+ nextval = (unsigned long)mod->module_core_rw;
21306+ else
21307+ nextval = (unsigned long)mod->module_core_rw+mod->core_size_rw;
21308
21309 /* Scan for closest preceeding symbol, and next symbol. (ELF
21310 starts real symbols at 1). */
21311@@ -2057,8 +2191,10 @@ const char *module_address_lookup(unsign
21312 struct module *mod;
21313
21314 list_for_each_entry(mod, &modules, list) {
21315- if (within(addr, mod->module_init, mod->init_size)
21316- || within(addr, mod->module_core, mod->core_size)) {
21317+ if (within(addr, mod->module_init_rx, mod->init_size_rx)
21318+ || within(addr, mod->module_init_rw, mod->init_size_rw)
21319+ || within(addr, mod->module_core_rx, mod->core_size_rx)
21320+ || within(addr, mod->module_core_rw, mod->core_size_rw)) {
21321 *modname = mod->name;
21322 return get_ksymbol(mod, addr, size, offset);
21323 }
21324@@ -2069,7 +2205,7 @@ const char *module_address_lookup(unsign
21325 struct module *module_get_kallsym(unsigned int symnum,
21326 unsigned long *value,
21327 char *type,
21328- char namebuf[128])
21329+ char namebuf[KSYM_NAME_LEN+1])
21330 {
21331 struct module *mod;
21332
21333@@ -2080,7 +2216,7 @@ struct module *module_get_kallsym(unsign
21334 *type = mod->symtab[symnum].st_info;
21335 strncpy(namebuf,
21336 mod->strtab + mod->symtab[symnum].st_name,
21337- 127);
21338+ KSYM_NAME_LEN);
21339 up(&module_mutex);
21340 return mod;
21341 }
21342@@ -2157,7 +2293,7 @@ static int m_show(struct seq_file *m, vo
21343 {
21344 struct module *mod = list_entry(p, struct module, list);
21345 seq_printf(m, "%s %lu",
21346- mod->name, mod->init_size + mod->core_size);
21347+ mod->name, mod->init_size_rx + mod->init_size_rw + mod->core_size_rx + mod->core_size_rw);
21348 print_unload_info(m, mod);
21349
21350 /* Informative for users. */
21351@@ -2166,7 +2302,7 @@ static int m_show(struct seq_file *m, vo
21352 mod->state == MODULE_STATE_COMING ? "Loading":
21353 "Live");
21354 /* Used by oprofile and other similar tools. */
21355- seq_printf(m, " 0x%p", mod->module_core);
21356+ seq_printf(m, " 0x%p 0x%p", mod->module_core_rx, mod->module_core_rw);
21357
21358 seq_printf(m, "\n");
21359 return 0;
21360@@ -2214,9 +2350,13 @@ struct module *__module_text_address(uns
21361 {
21362 struct module *mod;
21363
21364+#ifdef CONFIG_PAX_KERNEXEC
21365+ addr += __KERNEL_TEXT_OFFSET;
21366+#endif
21367+
21368 list_for_each_entry(mod, &modules, list)
21369- if (within(addr, mod->module_init, mod->init_text_size)
21370- || within(addr, mod->module_core, mod->core_text_size))
21371+ if (within(addr, mod->module_init_rx, mod->init_size_rx)
21372+ || within(addr, mod->module_core_rx, mod->core_size_rx))
21373 return mod;
21374 return NULL;
21375 }
21376diff -urNp linux-2.6.16.12/kernel/pid.c linux-2.6.16.12/kernel/pid.c
21377--- linux-2.6.16.12/kernel/pid.c 2006-05-01 15:14:26.000000000 -0400
21378+++ linux-2.6.16.12/kernel/pid.c 2006-05-01 20:17:34.000000000 -0400
21379@@ -26,6 +26,7 @@
21380 #include <linux/init.h>
21381 #include <linux/bootmem.h>
21382 #include <linux/hash.h>
21383+#include <linux/grsecurity.h>
21384
21385 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
21386 static struct hlist_head *pid_hash[PIDTYPE_MAX];
21387@@ -76,7 +77,9 @@ int alloc_pidmap(void)
21388 int i, offset, max_scan, pid, last = last_pid;
21389 pidmap_t *map;
21390
21391- pid = last + 1;
21392+ pid = gr_random_pid();
21393+ if (!pid)
21394+ pid = last_pid + 1;
21395 if (pid >= pid_max)
21396 pid = RESERVED_PIDS;
21397 offset = pid & BITS_PER_PAGE_MASK;
21398@@ -207,12 +210,18 @@ void fastcall detach_pid(task_t *task, e
21399 task_t *find_task_by_pid_type(int type, int nr)
21400 {
21401 struct pid *pid;
21402+ task_t *task = NULL;
21403
21404 pid = find_pid(type, nr);
21405 if (!pid)
21406 return NULL;
21407
21408- return pid_task(&pid->pid_list, type);
21409+ task = pid_task(&pid->pid_list, type);
21410+
21411+ if (gr_pid_is_chrooted(task))
21412+ return NULL;
21413+
21414+ return task;
21415 }
21416
21417 EXPORT_SYMBOL(find_task_by_pid_type);
21418diff -urNp linux-2.6.16.12/kernel/posix-cpu-timers.c linux-2.6.16.12/kernel/posix-cpu-timers.c
21419--- linux-2.6.16.12/kernel/posix-cpu-timers.c 2006-05-01 15:14:26.000000000 -0400
21420+++ linux-2.6.16.12/kernel/posix-cpu-timers.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 21421@@ -7,6 +7,7 @@
89675291 21422 #include <asm/uaccess.h>
21423 #include <linux/errno.h>
9a4c6ab7 21424 #include <linux/vs_pid.h>
89675291 21425+#include <linux/grsecurity.h>
21426
21427 static int check_clock(const clockid_t which_clock)
21428 {
9a4c6ab7 21429@@ -1129,6 +1130,7 @@ static void check_process_timers(struct
89675291 21430 __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
21431 return;
21432 }
21433+ gr_learn_resource(tsk, RLIMIT_CPU, psecs, 1);
21434 if (psecs >= sig->rlim[RLIMIT_CPU].rlim_cur) {
21435 /*
21436 * At the soft limit, send a SIGXCPU every second.
21437diff -urNp linux-2.6.16.12/kernel/printk.c linux-2.6.16.12/kernel/printk.c
21438--- linux-2.6.16.12/kernel/printk.c 2006-05-01 15:14:26.000000000 -0400
21439+++ linux-2.6.16.12/kernel/printk.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 21440@@ -33,6 +33,7 @@
89675291 21441 #include <linux/syscalls.h>
9a4c6ab7 21442 #include <linux/vs_context.h>
21443 #include <linux/vserver/cvirt.h>
89675291 21444+#include <linux/grsecurity.h>
21445
21446 #include <asm/uaccess.h>
21447
9a4c6ab7 21448@@ -225,6 +226,11 @@ int do_syslog(int type, char __user *buf
89675291 21449 char c;
9a4c6ab7 21450 int error;
89675291 21451
21452+#ifdef CONFIG_GRKERNSEC_DMESG
21453+ if (grsec_enable_dmesg && !capable(CAP_SYS_ADMIN))
21454+ return -EPERM;
21455+#endif
21456+
21457 error = security_syslog(type);
21458 if (error)
21459 return error;
21460diff -urNp linux-2.6.16.12/kernel/ptrace.c linux-2.6.16.12/kernel/ptrace.c
21461--- linux-2.6.16.12/kernel/ptrace.c 2006-05-01 15:14:26.000000000 -0400
21462+++ linux-2.6.16.12/kernel/ptrace.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 21463@@ -19,6 +19,7 @@
89675291 21464 #include <linux/security.h>
21465 #include <linux/signal.h>
9a4c6ab7 21466 #include <linux/vs_pid.h>
89675291 21467+#include <linux/grsecurity.h>
21468
21469 #include <asm/pgtable.h>
21470 #include <asm/uaccess.h>
9a4c6ab7 21471@@ -129,10 +130,10 @@ static int may_attach(struct task_struct
89675291 21472 (current->uid != task->uid) ||
21473 (current->gid != task->egid) ||
21474 (current->gid != task->sgid) ||
21475- (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
21476+ (current->gid != task->gid)) && !capable_nolog(CAP_SYS_PTRACE))
21477 return -EPERM;
21478 smp_rmb();
21479- if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
21480+ if (!task->mm->dumpable && !capable_nolog(CAP_SYS_PTRACE))
21481 return -EPERM;
21482
21483 return security_ptrace(current, task);
9a4c6ab7 21484@@ -500,6 +501,11 @@ asmlinkage long sys_ptrace(long request,
89675291 21485 if (ret < 0)
21486 goto out_put_task_struct;
21487
21488+ if (gr_handle_ptrace(child, request)) {
21489+ ret = -EPERM;
21490+ goto out_put_task_struct;
21491+ }
21492+
21493 ret = arch_ptrace(child, request, addr, data);
21494 if (ret < 0)
21495 goto out_put_task_struct;
21496diff -urNp linux-2.6.16.12/kernel/resource.c linux-2.6.16.12/kernel/resource.c
21497--- linux-2.6.16.12/kernel/resource.c 2006-05-01 15:14:26.000000000 -0400
21498+++ linux-2.6.16.12/kernel/resource.c 2006-05-01 20:17:34.000000000 -0400
21499@@ -136,10 +136,27 @@ static int __init ioresources_init(void)
21500 {
21501 struct proc_dir_entry *entry;
21502
21503+#ifdef CONFIG_GRKERNSEC_PROC_ADD
21504+#ifdef CONFIG_GRKERNSEC_PROC_USER
21505+ entry = create_proc_entry("ioports", S_IRUSR, NULL);
21506+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
21507+ entry = create_proc_entry("ioports", S_IRUSR | S_IRGRP, NULL);
21508+#endif
21509+#else
21510 entry = create_proc_entry("ioports", 0, NULL);
21511+#endif
21512 if (entry)
21513 entry->proc_fops = &proc_ioports_operations;
21514+
21515+#ifdef CONFIG_GRKERNSEC_PROC_ADD
21516+#ifdef CONFIG_GRKERNSEC_PROC_USER
21517+ entry = create_proc_entry("iomem", S_IRUSR, NULL);
21518+#elif CONFIG_GRKERNSEC_PROC_USERGROUP
21519+ entry = create_proc_entry("iomem", S_IRUSR | S_IRGRP, NULL);
21520+#endif
21521+#else
21522 entry = create_proc_entry("iomem", 0, NULL);
21523+#endif
21524 if (entry)
21525 entry->proc_fops = &proc_iomem_operations;
21526 return 0;
21527diff -urNp linux-2.6.16.12/kernel/sched.c linux-2.6.16.12/kernel/sched.c
21528--- linux-2.6.16.12/kernel/sched.c 2006-05-01 15:14:26.000000000 -0400
21529+++ linux-2.6.16.12/kernel/sched.c 2006-05-01 20:17:34.000000000 -0400
21530@@ -49,6 +49,7 @@
21531 #include <linux/syscalls.h>
21532 #include <linux/times.h>
21533 #include <linux/acct.h>
21534+#include <linux/grsecurity.h>
21535 #include <asm/tlb.h>
21536
21537 #include <asm/unistd.h>
9a4c6ab7 21538@@ -3613,7 +3614,8 @@ asmlinkage long sys_nice(int increment)
89675291 21539 if (nice > 19)
21540 nice = 19;
21541
21542- if (increment < 0 && !can_nice(current, nice))
21543+ if (increment < 0 && (!can_nice(current, nice) ||
21544+ gr_handle_chroot_nice()))
9a4c6ab7 21545 return vx_flags(VXF_IGNEG_NICE, 0) ? 0 : -EPERM;
89675291 21546
21547 retval = security_task_setnice(current, nice);
21548diff -urNp linux-2.6.16.12/kernel/signal.c linux-2.6.16.12/kernel/signal.c
21549--- linux-2.6.16.12/kernel/signal.c 2006-05-01 15:14:26.000000000 -0400
21550+++ linux-2.6.16.12/kernel/signal.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 21551@@ -27,6 +27,7 @@
89675291 21552 #include <linux/audit.h>
21553 #include <linux/capability.h>
9a4c6ab7 21554 #include <linux/vs_pid.h>
89675291 21555+#include <linux/grsecurity.h>
21556 #include <asm/param.h>
21557 #include <asm/uaccess.h>
21558 #include <asm/unistd.h>
9a4c6ab7 21559@@ -381,6 +382,7 @@ void __exit_signal(struct task_struct *t
89675291 21560 }
21561 if (tsk == sig->curr_target)
21562 sig->curr_target = next_thread(tsk);
21563+ gr_del_task_from_ip_table(tsk);
21564 tsk->signal = NULL;
21565 /*
21566 * Accumulate here the counters for all threads but the
9a4c6ab7 21567@@ -687,11 +689,11 @@ static int check_kill_permission(int sig
21568 (!is_si_special(info) && SI_FROMUSER(info)));
21569
89675291 21570 error = -EPERM;
9a4c6ab7 21571- if (user && ((sig != SIGCONT) ||
21572+ if (user && ((((sig != SIGCONT) ||
89675291 21573 (current->signal->session != t->signal->session))
21574 && (current->euid ^ t->suid) && (current->euid ^ t->uid)
21575 && (current->uid ^ t->suid) && (current->uid ^ t->uid)
21576- && !capable(CAP_KILL))
21577+ && !capable(CAP_KILL)) || gr_handle_signal(t, sig)))
21578 return error;
21579
9a4c6ab7 21580 error = -ESRCH;
21581@@ -699,8 +701,10 @@ static int check_kill_permission(int sig
21582 return error;
21583
89675291 21584 error = security_task_kill(t, info, sig);
21585- if (!error)
21586+ if (!error) {
21587 audit_signal_info(sig, t); /* Let audit system see the signal */
21588+ gr_log_signal(sig, t);
21589+ }
21590 return error;
21591 }
21592
9a4c6ab7 21593@@ -880,7 +884,7 @@ out_set:
89675291 21594 (((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
21595
21596
21597-static int
21598+int
21599 specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
21600 {
21601 int ret = 0;
9a4c6ab7 21602@@ -926,6 +930,10 @@ force_sig_info(int sig, struct siginfo *
89675291 21603 }
21604 recalc_sigpending_tsk(t);
21605 ret = specific_send_sig_info(sig, info, t);
21606+
21607+ gr_log_signal(sig, t);
21608+ gr_handle_crash(t, sig);
21609+
21610 spin_unlock_irqrestore(&t->sighand->siglock, flags);
21611
21612 return ret;
21613diff -urNp linux-2.6.16.12/kernel/sys.c linux-2.6.16.12/kernel/sys.c
21614--- linux-2.6.16.12/kernel/sys.c 2006-05-01 15:14:26.000000000 -0400
21615+++ linux-2.6.16.12/kernel/sys.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 21616@@ -33,6 +33,7 @@
89675291 21617 #include <linux/cn_proc.h>
9a4c6ab7 21618 #include <linux/vs_cvirt.h>
21619 #include <linux/vs_pid.h>
89675291 21620+#include <linux/grsecurity.h>
21621
21622 #include <linux/compat.h>
21623 #include <linux/syscalls.h>
9a4c6ab7 21624@@ -228,18 +229,37 @@ int unregister_reboot_notifier(struct no
89675291 21625 EXPORT_SYMBOL(unregister_reboot_notifier);
21626
21627 #ifndef CONFIG_SECURITY
21628+extern int gr_task_is_capable(struct task_struct *task, const int cap);
21629+extern int gr_is_capable_nolog(const int cap);
21630 int capable(int cap)
21631 {
9a4c6ab7 21632 if (vx_check_bit(VXC_CAP_MASK, cap) && !vx_mcaps(1L << cap))
21633 return 0;
21634- if (vx_cap_raised(current->vx_info, current->cap_effective, cap)) {
21635+ if (vx_cap_raised(current->vx_info, current->cap_effective, cap)
21636+ && gr_task_is_capable(current, cap)) {
89675291 21637 current->flags |= PF_SUPERPRIV;
21638 return 1;
21639 }
21640 return 0;
21641 }
9a4c6ab7 21642+int capable_nolog(int cap)
21643+{
21644+ if (vx_cap_raised(current->vx_info, current->cap_effective, cap)
21645+ && gr_is_capable_nolog(cap)) {
21646+ current->flags |= PF_SUPERPRIV;
21647+ return 1;
21648+ }
21649+ return 0;
21650+}
89675291 21651 EXPORT_SYMBOL(capable);
21652+#else
21653+int capable_nolog(int cap)
21654+{
21655+ return capable(cap);
21656+}
21657+
21658 #endif
21659+EXPORT_SYMBOL(capable_nolog);
21660
21661 static int set_one_prio(struct task_struct *p, int niceval, int error)
21662 {
9a4c6ab7 21663@@ -257,6 +277,12 @@ static int set_one_prio(struct task_stru
21664 error = -EACCES;
89675291 21665 goto out;
21666 }
21667+
21668+ if (gr_handle_chroot_setpriority(p, niceval)) {
21669+ error = -EACCES;
21670+ goto out;
21671+ }
21672+
21673 no_nice = security_task_setnice(p, niceval);
21674 if (no_nice) {
21675 error = no_nice;
9a4c6ab7 21676@@ -654,6 +680,9 @@ asmlinkage long sys_setregid(gid_t rgid,
89675291 21677 if (rgid != (gid_t) -1 ||
21678 (egid != (gid_t) -1 && egid != old_rgid))
21679 current->sgid = new_egid;
21680+
21681+ gr_set_role_label(current, current->uid, new_rgid);
21682+
21683 current->fsgid = new_egid;
21684 current->egid = new_egid;
21685 current->gid = new_rgid;
9a4c6ab7 21686@@ -683,6 +712,9 @@ asmlinkage long sys_setgid(gid_t gid)
89675291 21687 current->mm->dumpable = suid_dumpable;
21688 smp_wmb();
21689 }
21690+
21691+ gr_set_role_label(current, current->uid, gid);
21692+
21693 current->gid = current->egid = current->sgid = current->fsgid = gid;
21694 }
21695 else if ((gid == current->gid) || (gid == current->sgid))
9a4c6ab7 21696@@ -724,6 +756,9 @@ static int set_user(uid_t new_ruid, int
89675291 21697 current->mm->dumpable = suid_dumpable;
21698 smp_wmb();
21699 }
21700+
21701+ gr_set_role_label(current, new_ruid, current->gid);
21702+
21703 current->uid = new_ruid;
21704 return 0;
21705 }
9a4c6ab7 21706@@ -827,6 +862,9 @@ asmlinkage long sys_setuid(uid_t uid)
89675291 21707 } else if ((uid != current->uid) && (uid != new_suid))
21708 return -EPERM;
21709
21710+ if (gr_check_crash_uid(uid))
21711+ return -EPERM;
21712+
21713 if (old_euid != uid)
21714 {
21715 current->mm->dumpable = suid_dumpable;
9a4c6ab7 21716@@ -932,8 +970,10 @@ asmlinkage long sys_setresgid(gid_t rgid
89675291 21717 current->egid = egid;
21718 }
21719 current->fsgid = current->egid;
21720- if (rgid != (gid_t) -1)
21721+ if (rgid != (gid_t) -1) {
21722+ gr_set_role_label(current, current->uid, rgid);
21723 current->gid = rgid;
21724+ }
21725 if (sgid != (gid_t) -1)
21726 current->sgid = sgid;
21727
21728diff -urNp linux-2.6.16.12/kernel/sysctl.c linux-2.6.16.12/kernel/sysctl.c
21729--- linux-2.6.16.12/kernel/sysctl.c 2006-05-01 15:14:26.000000000 -0400
21730+++ linux-2.6.16.12/kernel/sysctl.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 21731@@ -55,6 +55,14 @@ extern int proc_nr_files(ctl_table *tabl
89675291 21732 void __user *buffer, size_t *lenp, loff_t *ppos);
21733
21734 #if defined(CONFIG_SYSCTL)
21735+#include <linux/grsecurity.h>
21736+#include <linux/grinternal.h>
21737+
21738+extern __u32 gr_handle_sysctl(const ctl_table *table, const void *oldval,
21739+ const void *newval);
21740+extern int gr_handle_sysctl_mod(const char *dirname, const char *name,
21741+ const int op);
21742+extern int gr_handle_chroot_sysctl(const int op);
21743
21744 /* External variables not in a header file. */
21745 extern int C_A_D;
9a4c6ab7 21746@@ -162,6 +170,22 @@ extern ctl_table inotify_table[];
89675291 21747 #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
21748 int sysctl_legacy_va_layout;
21749 #endif
21750+extern ctl_table grsecurity_table[];
21751+
21752+#ifdef CONFIG_PAX_SOFTMODE
21753+static ctl_table pax_table[] = {
21754+ {
21755+ .ctl_name = PAX_SOFTMODE,
21756+ .procname = "softmode",
21757+ .data = &pax_softmode,
21758+ .maxlen = sizeof(unsigned int),
21759+ .mode = 0600,
21760+ .proc_handler = &proc_dointvec,
21761+ },
21762+
21763+ { .ctl_name = 0 }
21764+};
21765+#endif
21766
21767 /* /proc declarations: */
21768
9a4c6ab7 21769@@ -713,6 +737,25 @@ static ctl_table kern_table[] = {
89675291 21770 .proc_handler = &proc_dointvec,
21771 },
21772 #endif
21773+
21774+#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP)
21775+ {
21776+ .ctl_name = KERN_GRSECURITY,
21777+ .procname = "grsecurity",
21778+ .mode = 0500,
21779+ .child = grsecurity_table,
21780+ },
21781+#endif
21782+
21783+#ifdef CONFIG_PAX_SOFTMODE
21784+ {
21785+ .ctl_name = KERN_PAX,
21786+ .procname = "pax",
21787+ .mode = 0500,
21788+ .child = pax_table,
21789+ },
21790+#endif
21791+
21792 { .ctl_name = 0 }
21793 };
21794
9a4c6ab7 21795@@ -1211,6 +1254,10 @@ static int test_perm(int mode, int op)
89675291 21796 static inline int ctl_perm(ctl_table *table, int op)
21797 {
21798 int error;
21799+ if (table->de && gr_handle_sysctl_mod(table->de->parent->name, table->de->name, op))
21800+ return -EACCES;
21801+ if (gr_handle_chroot_sysctl(op))
21802+ return -EACCES;
21803 error = security_sysctl(table, op);
21804 if (error)
21805 return error;
9a4c6ab7 21806@@ -1247,6 +1234,10 @@ repeat:
89675291 21807 table = table->child;
21808 goto repeat;
21809 }
21810+
21811+ if (!gr_handle_sysctl(table, oldval, newval))
21812+ return -EACCES;
21813+
21814 error = do_sysctl_strategy(table, name, nlen,
21815 oldval, oldlenp,
21816 newval, newlen, context);
21817diff -urNp linux-2.6.16.12/kernel/time.c linux-2.6.16.12/kernel/time.c
21818--- linux-2.6.16.12/kernel/time.c 2006-05-01 15:14:26.000000000 -0400
21819+++ linux-2.6.16.12/kernel/time.c 2006-05-01 20:17:34.000000000 -0400
21820@@ -36,6 +36,7 @@
21821 #include <linux/security.h>
21822 #include <linux/fs.h>
21823 #include <linux/module.h>
21824+#include <linux/grsecurity.h>
21825
21826 #include <asm/uaccess.h>
21827 #include <asm/unistd.h>
21828@@ -93,6 +94,9 @@ asmlinkage long sys_stime(time_t __user
21829 return err;
21830
21831 do_settimeofday(&tv);
21832+
21833+ gr_log_timechange();
21834+
21835 return 0;
21836 }
21837
21838@@ -199,6 +203,8 @@ asmlinkage long sys_settimeofday(struct
21839 return -EFAULT;
21840 }
21841
21842+ gr_log_timechange();
21843+
21844 return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
21845 }
21846
89675291 21847diff -urNp linux-2.6.16.12/Makefile linux-2.6.16.12/Makefile
21848--- linux-2.6.16.12/Makefile 2006-05-01 15:14:26.000000000 -0400
21849+++ linux-2.6.16.12/Makefile 2006-05-01 20:17:34.000000000 -0400
21850@@ -556,7 +556,7 @@ export MODLIB
21851
21852
21853 ifeq ($(KBUILD_EXTMOD),)
21854-core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
21855+core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
21856
21857 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
21858 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
21859diff -urNp linux-2.6.16.12/mm/filemap.c linux-2.6.16.12/mm/filemap.c
21860--- linux-2.6.16.12/mm/filemap.c 2006-05-01 15:14:26.000000000 -0400
21861+++ linux-2.6.16.12/mm/filemap.c 2006-05-01 20:17:34.000000000 -0400
21862@@ -29,6 +29,7 @@
21863 #include <linux/blkdev.h>
21864 #include <linux/security.h>
21865 #include <linux/syscalls.h>
21866+#include <linux/grsecurity.h>
21867 #include "filemap.h"
21868 /*
21869 * FIXME: remove all knowledge of the buffer layer from the core VM
9a4c6ab7 21870@@ -1617,7 +1618,13 @@ int generic_file_mmap(struct file * file
89675291 21871 struct address_space *mapping = file->f_mapping;
21872
21873 if (!mapping->a_ops->readpage)
21874- return -ENOEXEC;
21875+ return -ENODEV;
21876+
21877+#ifdef CONFIG_PAX_PAGEEXEC
21878+ if (vma->vm_mm->pax_flags & MF_PAX_PAGEEXEC)
21879+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
21880+#endif
21881+
21882 file_accessed(file);
21883 vma->vm_ops = &generic_file_vm_ops;
21884 return 0;
9a4c6ab7 21885@@ -1852,6 +1859,7 @@ inline int generic_write_checks(struct f
89675291 21886 *pos = i_size_read(inode);
21887
21888 if (limit != RLIM_INFINITY) {
21889+ gr_learn_resource(current, RLIMIT_FSIZE,*pos, 0);
21890 if (*pos >= limit) {
21891 send_sig(SIGXFSZ, current, 0);
21892 return -EFBIG;
21893diff -urNp linux-2.6.16.12/mm/madvise.c linux-2.6.16.12/mm/madvise.c
21894--- linux-2.6.16.12/mm/madvise.c 2006-05-01 15:14:26.000000000 -0400
21895+++ linux-2.6.16.12/mm/madvise.c 2006-05-01 20:17:34.000000000 -0400
21896@@ -15,9 +15,46 @@
21897 * We can potentially split a vm area into separate
21898 * areas, each area with its own behavior.
21899 */
21900+
21901+#ifdef CONFIG_PAX_SEGMEXEC
21902+static long __madvise_behavior(struct vm_area_struct * vma,
21903+ struct vm_area_struct **prev,
21904+ unsigned long start, unsigned long end, int behavior);
21905+
21906+static long madvise_behavior(struct vm_area_struct * vma,
21907+ struct vm_area_struct **prev,
21908+ unsigned long start, unsigned long end, int behavior)
21909+{
21910+ if (vma->vm_flags & VM_MIRROR) {
21911+ struct vm_area_struct * vma_m, * prev_m;
21912+ unsigned long start_m, end_m;
21913+ int error;
21914+
21915+ start_m = vma->vm_start + vma->vm_mirror;
21916+ vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m);
21917+ if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
21918+ start_m = start + vma->vm_mirror;
21919+ end_m = end + vma->vm_mirror;
21920+ error = __madvise_behavior(vma_m, &prev_m, start_m, end_m, behavior);
21921+ if (error)
21922+ return error;
21923+ } else {
21924+ printk("PAX: VMMIRROR: madvise bug in %s, %08lx\n", current->comm, vma->vm_start);
21925+ return -ENOMEM;
21926+ }
21927+ }
21928+
21929+ return __madvise_behavior(vma, prev, start, end, behavior);
21930+}
21931+
21932+static long __madvise_behavior(struct vm_area_struct * vma,
21933+ struct vm_area_struct **prev,
21934+ unsigned long start, unsigned long end, int behavior)
21935+#else
21936 static long madvise_behavior(struct vm_area_struct * vma,
21937 struct vm_area_struct **prev,
21938 unsigned long start, unsigned long end, int behavior)
21939+#endif
21940 {
21941 struct mm_struct * mm = vma->vm_mm;
21942 int error = 0;
21943diff -urNp linux-2.6.16.12/mm/memory.c linux-2.6.16.12/mm/memory.c
21944--- linux-2.6.16.12/mm/memory.c 2006-05-01 15:14:26.000000000 -0400
21945+++ linux-2.6.16.12/mm/memory.c 2006-05-01 20:17:34.000000000 -0400
21946@@ -48,6 +48,7 @@
21947 #include <linux/rmap.h>
21948 #include <linux/module.h>
21949 #include <linux/init.h>
21950+#include <linux/grsecurity.h>
21951
21952 #include <asm/pgalloc.h>
21953 #include <asm/uaccess.h>
21954@@ -321,6 +322,11 @@ int __pte_alloc(struct mm_struct *mm, pm
21955
21956 int __pte_alloc_kernel(pmd_t *pmd, unsigned long address)
21957 {
21958+
21959+#ifdef CONFIG_PAX_KERNEXEC
21960+ unsigned long cr0;
21961+#endif
21962+
21963 pte_t *new = pte_alloc_one_kernel(&init_mm, address);
21964 if (!new)
21965 return -ENOMEM;
21966@@ -328,8 +334,19 @@ int __pte_alloc_kernel(pmd_t *pmd, unsig
21967 spin_lock(&init_mm.page_table_lock);
21968 if (pmd_present(*pmd)) /* Another has populated it */
21969 pte_free_kernel(new);
21970- else
21971+ else {
21972+
21973+#ifdef CONFIG_PAX_KERNEXEC
21974+ pax_open_kernel(cr0);
21975+#endif
21976+
21977 pmd_populate_kernel(&init_mm, pmd, new);
21978+
21979+#ifdef CONFIG_PAX_KERNEXEC
21980+ pax_close_kernel(cr0);
21981+#endif
21982+
21983+ }
21984 spin_unlock(&init_mm.page_table_lock);
21985 return 0;
21986 }
9a4c6ab7 21987@@ -1434,6 +1451,88 @@ static inline void cow_user_page(struct
89675291 21988 copy_user_highpage(dst, src, va);
21989 }
21990
21991+#ifdef CONFIG_PAX_SEGMEXEC
21992+/* PaX: if vma is mirrored, synchronize the mirror's PTE
21993+ *
21994+ * the ptl of the lower mapped page is held on entry and is not released on exit
21995+ * or inside to ensure atomic changes to the PTE states (swapout, mremap, munmap, etc)
21996+ */
21997+static void pax_mirror_fault(struct vm_area_struct *vma, unsigned long address, pte_t *pte)
21998+{
21999+ struct mm_struct *mm = vma->vm_mm;
22000+ unsigned long address_m, pfn_m;
22001+ struct vm_area_struct * vma_m = NULL;
22002+ pte_t * pte_m, entry_m;
22003+ struct page * page_m = NULL;
22004+
22005+ address_m = vma->vm_start + vma->vm_mirror;
22006+ vma_m = find_vma(mm, address_m);
22007+ BUG_ON(!vma_m || vma_m->vm_start != address_m);
22008+
22009+ address_m = address + vma->vm_mirror;
22010+ pte_m = pte_offset_map_nested(pmd_offset(pud_offset(pgd_offset(mm, address_m), address_m), address_m), address_m);
22011+
22012+ if (pte_same(*pte, *pte_m)) {
22013+ pte_unmap_nested(pte_m);
22014+ return;
22015+ }
22016+
22017+ if (pte_present(*pte_m)) {
22018+ page_m = vm_normal_page(vma_m, address_m, *pte_m);
22019+ if (page_m) {
22020+ flush_cache_page(vma_m, address_m, pfn_m);
22021+ flush_icache_page(vma_m, page_m);
22022+ }
22023+ }
22024+
22025+ if (pte_present(*pte_m))
22026+ entry_m = ptep_clear_flush(vma_m, address_m, pte_m);
22027+ else
22028+ entry_m = ptep_get_and_clear(mm, address_m, pte_m);
22029+
22030+ if (pte_none(entry_m)) {
22031+ } else if (pte_present(entry_m)) {
22032+ if (page_m) {
22033+ page_remove_rmap(page_m);
22034+ if (PageAnon(page_m))
22035+ dec_mm_counter(mm, anon_rss);
22036+ else
22037+ dec_mm_counter(mm, file_rss);
22038+ page_cache_release(page_m);
22039+ }
22040+ } else if (!pte_file(entry_m)) {
22041+ free_swap_and_cache(pte_to_swp_entry(entry_m));
22042+ } else {
22043+ printk(KERN_ERR "PAX: VMMIRROR: bug in mirror_fault: %08lx, %08lx, %08lx, %08lx\n",
22044+ address, vma->vm_start, address_m, vma_m->vm_start);
22045+ }
22046+
22047+ pfn_m = pte_pfn(*pte);
22048+ page_m = vm_normal_page(vma, address, *pte);
22049+ entry_m = pfn_pte(pfn_m, vma_m->vm_page_prot);
22050+ if (pte_write(*pte))
22051+ entry_m = maybe_mkwrite(pte_mkdirty(entry_m), vma_m);
22052+ if (page_m) {
22053+ page_cache_get(page_m);
22054+ /*
22055+ * we can test PAGE_MAPPING_ANON without holding page_map_lock because
22056+ * we hold the page table lock and have a reference to page_m
22057+ */
22058+ if (PageAnon(page_m)) {
22059+ page_add_anon_rmap(page_m, vma_m, address_m);
22060+ inc_mm_counter(mm, anon_rss);
22061+ } else {
22062+ page_add_file_rmap(page_m);
22063+ inc_mm_counter(mm, file_rss);
22064+ }
22065+ }
22066+ set_pte_at(mm, address_m, pte_m, entry_m);
22067+ update_mmu_cache(vma_m, address_m, entry_m);
22068+ lazy_mmu_prot_update(entry_m);
22069+ pte_unmap_nested(pte_m);
22070+}
22071+#endif
22072+
22073 /*
22074 * This routine handles present pages, when users try to write
22075 * to a shared page. It is done by copying the page to a new address
9a4c6ab7 22076@@ -1524,6 +1623,12 @@ gotten:
89675291 22077 /* Free the old page.. */
22078 new_page = old_page;
22079 ret |= VM_FAULT_WRITE;
22080+
22081+#ifdef CONFIG_PAX_SEGMEXEC
22082+ if (vma->vm_flags & VM_MIRROR)
22083+ pax_mirror_fault(vma, address, page_table);
22084+#endif
22085+
22086 }
22087 if (new_page)
22088 page_cache_release(new_page);
9a4c6ab7 22089@@ -1774,6 +1879,7 @@ int vmtruncate(struct inode * inode, lof
89675291 22090
22091 do_expand:
22092 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
22093+ gr_learn_resource(current, RLIMIT_FSIZE, offset, 1);
22094 if (limit != RLIM_INFINITY && offset > limit)
22095 goto out_sig;
22096 if (offset > inode->i_sb->s_maxbytes)
9a4c6ab7 22097@@ -1967,6 +2073,12 @@ again:
89675291 22098 /* No need to invalidate - it was non-present before */
22099 update_mmu_cache(vma, address, pte);
22100 lazy_mmu_prot_update(pte);
22101+
22102+#ifdef CONFIG_PAX_SEGMEXEC
22103+ if (vma->vm_flags & VM_MIRROR)
22104+ pax_mirror_fault(vma, address, page_table);
22105+#endif
22106+
22107 unlock:
22108 pte_unmap_unlock(page_table, ptl);
22109 out:
9a4c6ab7 22110@@ -2031,6 +2143,12 @@ static int do_anonymous_page(struct mm_s
89675291 22111 /* No need to invalidate - it was non-present before */
22112 update_mmu_cache(vma, address, entry);
22113 lazy_mmu_prot_update(entry);
22114+
22115+#ifdef CONFIG_PAX_SEGMEXEC
22116+ if (vma->vm_flags & VM_MIRROR)
22117+ pax_mirror_fault(vma, address, page_table);
22118+#endif
22119+
22120 unlock:
22121 pte_unmap_unlock(page_table, ptl);
22122 return VM_FAULT_MINOR;
9a4c6ab7 22123@@ -2159,6 +2277,12 @@ retry:
89675291 22124 /* no need to invalidate: a not-present page shouldn't be cached */
22125 update_mmu_cache(vma, address, entry);
22126 lazy_mmu_prot_update(entry);
22127+
22128+#ifdef CONFIG_PAX_SEGMEXEC
22129+ if (vma->vm_flags & VM_MIRROR)
22130+ pax_mirror_fault(vma, address, page_table);
22131+#endif
22132+
22133 unlock:
22134 pte_unmap_unlock(page_table, ptl);
22135 return ret;
9a4c6ab7 22136@@ -2282,6 +2406,12 @@ static inline int handle_pte_fault(struc
89675291 22137 flush_tlb_page(vma, address);
22138 }
22139 unlock:
22140+
22141+#ifdef CONFIG_PAX_SEGMEXEC
22142+ if (vma->vm_flags & VM_MIRROR)
22143+ pax_mirror_fault(vma, address, pte);
22144+#endif
22145+
22146 pte_unmap_unlock(pte, ptl);
9a4c6ab7 22147 ret = VM_FAULT_MINOR;
22148 out:
22149@@ -2307,6 +2437,49 @@ int __handle_mm_fault(struct mm_struct *
89675291 22150 if (unlikely(is_vm_hugetlb_page(vma)))
22151 return hugetlb_fault(mm, vma, address, write_access);
22152
22153+#ifdef CONFIG_PAX_SEGMEXEC
22154+ if (vma->vm_flags & VM_MIRROR) {
22155+ unsigned long address_m;
22156+ struct vm_area_struct * vma_m;
22157+ pgd_t *pgd_m;
22158+ pud_t *pud_m;
22159+ pmd_t *pmd_m;
22160+
22161+ address_m = vma->vm_start + vma->vm_mirror;
22162+ vma_m = find_vma(mm, address_m);
22163+
22164+ /* PaX: sanity checks */
22165+ if (!vma_m) {
22166+ printk(KERN_ERR "PAX: VMMIRROR: fault bug, %08lx, %p, %08lx, %p\n",
22167+ address, vma, address_m, vma_m);
22168+ return VM_FAULT_SIGBUS;
22169+ } else if (!(vma_m->vm_flags & VM_MIRROR) ||
22170+ vma_m->vm_start != address_m ||
22171+ vma->vm_end - vma->vm_start != vma_m->vm_end - vma_m->vm_start)
22172+ {
22173+ printk(KERN_ERR "PAX: VMMIRROR: fault bug2, %08lx, %08lx, %08lx, %08lx, %08lx\n",
22174+ address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
22175+ return VM_FAULT_SIGBUS;
22176+ }
22177+
22178+ if (address_m < address) {
22179+ address += vma->vm_mirror;
22180+ vma = vma_m;
22181+ }
22182+
22183+ address_m = address + vma->vm_mirror;
22184+ pgd_m = pgd_offset(mm, address_m);
22185+ pud_m = pud_alloc(mm, pgd_m, address_m);
22186+ if (!pud_m)
22187+ return VM_FAULT_OOM;
22188+ pmd_m = pmd_alloc(mm, pud_m, address_m);
22189+ if (!pmd_m)
22190+ return VM_FAULT_OOM;
22191+ if (!pmd_present(*pmd_m) && __pte_alloc(mm, pmd_m, address_m))
22192+ return VM_FAULT_OOM;
22193+ }
22194+#endif
22195+
22196 pgd = pgd_offset(mm, address);
22197 pud = pud_alloc(mm, pgd, address);
22198 if (!pud)
22199diff -urNp linux-2.6.16.12/mm/mempolicy.c linux-2.6.16.12/mm/mempolicy.c
22200--- linux-2.6.16.12/mm/mempolicy.c 2006-05-01 15:14:26.000000000 -0400
22201+++ linux-2.6.16.12/mm/mempolicy.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 22202@@ -356,6 +356,12 @@ check_range(struct mm_struct *mm, unsign
89675291 22203 if (prev && prev->vm_end < vma->vm_start)
22204 return ERR_PTR(-EFAULT);
22205 }
22206+
22207+#ifdef CONFIG_PAX_SEGMEXEC
22208+ if (vma->vm_flags & VM_MIRROR)
22209+ return ERR_PTR(-EFAULT);
22210+#endif
22211+
22212 if (!is_vm_hugetlb_page(vma) &&
22213 ((flags & MPOL_MF_STRICT) ||
22214 ((flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) &&
22215diff -urNp linux-2.6.16.12/mm/mlock.c linux-2.6.16.12/mm/mlock.c
22216--- linux-2.6.16.12/mm/mlock.c 2006-05-01 15:14:26.000000000 -0400
22217+++ linux-2.6.16.12/mm/mlock.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 22218@@ -11,14 +11,85 @@
89675291 22219 #include <linux/mempolicy.h>
22220 #include <linux/syscalls.h>
9a4c6ab7 22221 #include <linux/vs_memory.h>
89675291 22222+#include <linux/grsecurity.h>
22223
22224+static int __mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
22225+ unsigned long start, unsigned long end, unsigned int newflags);
22226
22227 static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
22228 unsigned long start, unsigned long end, unsigned int newflags)
22229 {
22230 struct mm_struct * mm = vma->vm_mm;
22231- pgoff_t pgoff;
22232 int pages;
22233+ int ret;
22234+
22235+#ifdef CONFIG_PAX_SEGMEXEC
22236+ struct vm_area_struct * vma_m = NULL, *prev_m;
22237+ unsigned long start_m = 0UL, end_m = 0UL, newflags_m = 0UL;
22238+
22239+ if (vma->vm_flags & VM_MIRROR) {
22240+ start_m = vma->vm_start + vma->vm_mirror;
22241+ vma_m = find_vma_prev(mm, start_m, &prev_m);
22242+ if (!vma_m || vma_m->vm_start != start_m || !(vma_m->vm_flags & VM_MIRROR)) {
22243+ printk("PAX: VMMIRROR: mlock bug in %s, %08lx\n", current->comm, vma->vm_start);
22244+ return -ENOMEM;
22245+ }
22246+
22247+ start_m = start + vma->vm_mirror;
22248+ end_m = end + vma->vm_mirror;
22249+ if (newflags & VM_LOCKED)
22250+ newflags_m = vma_m->vm_flags | VM_LOCKED;
22251+ else
22252+ newflags_m = vma_m->vm_flags & ~VM_LOCKED;
22253+ ret = __mlock_fixup(vma_m, &prev_m, start_m, end_m, newflags_m);
22254+ if (ret)
22255+ return ret;
22256+ }
22257+#endif
22258+
22259+ ret = __mlock_fixup(vma, prev, start, end, newflags);
22260+ if (ret)
22261+ return ret;
22262+
22263+ /*
22264+ * vm_flags is protected by the mmap_sem held in write mode.
22265+ * It's okay if try_to_unmap_one unmaps a page just after we
22266+ * set VM_LOCKED, make_pages_present below will bring it back.
22267+ */
22268+ vma->vm_flags = newflags;
22269+
22270+#ifdef CONFIG_PAX_SEGMEXEC
22271+ if (vma->vm_flags & VM_MIRROR)
22272+ vma_m->vm_flags = newflags_m;
22273+#endif
22274+
22275+ /*
22276+ * Keep track of amount of locked VM.
22277+ */
22278+ pages = (end - start) >> PAGE_SHIFT;
22279+ if (newflags & VM_LOCKED) {
22280+ pages = -pages;
22281+ if (!(newflags & VM_IO))
22282+ ret = make_pages_present(start, end);
22283+ }
22284+
22285+ mm->locked_vm -= pages;
22286+
22287+#ifdef CONFIG_PAX_SEGMEXEC
22288+ if (vma->vm_flags & VM_MIRROR)
22289+ mm->locked_vm -= pages;
22290+#endif
22291+
22292+ if (ret == -ENOMEM)
22293+ ret = -EAGAIN;
22294+ return ret;
22295+}
22296+
22297+static int __mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
22298+ unsigned long start, unsigned long end, unsigned int newflags)
22299+{
22300+ struct mm_struct * mm = vma->vm_mm;
22301+ pgoff_t pgoff;
22302 int ret = 0;
22303
22304 if (newflags == vma->vm_flags) {
9a4c6ab7 22305@@ -31,7 +102,7 @@ static int mlock_fixup(struct vm_area_st
89675291 22306 vma->vm_file, pgoff, vma_policy(vma));
22307 if (*prev) {
22308 vma = *prev;
22309- goto success;
22310+ goto out;
22311 }
22312
22313 *prev = vma;
9a4c6ab7 22314@@ -42,31 +113,9 @@ static int mlock_fixup(struct vm_area_st
89675291 22315 goto out;
22316 }
22317
22318- if (end != vma->vm_end) {
22319+ if (end != vma->vm_end)
22320 ret = split_vma(mm, vma, end, 0);
22321- if (ret)
22322- goto out;
22323- }
22324
22325-success:
22326- /*
22327- * vm_flags is protected by the mmap_sem held in write mode.
22328- * It's okay if try_to_unmap_one unmaps a page just after we
22329- * set VM_LOCKED, make_pages_present below will bring it back.
22330- */
22331- vma->vm_flags = newflags;
22332-
22333- /*
22334- * Keep track of amount of locked VM.
22335- */
22336- pages = (end - start) >> PAGE_SHIFT;
22337- if (newflags & VM_LOCKED) {
22338- pages = -pages;
22339- if (!(newflags & VM_IO))
22340- ret = make_pages_present(start, end);
22341- }
22342-
9a4c6ab7 22343- vx_vmlocked_sub(vma->vm_mm, pages);
89675291 22344 out:
22345 if (ret == -ENOMEM)
22346 ret = -EAGAIN;
9a4c6ab7 22347@@ -85,6 +134,17 @@ static int do_mlock(unsigned long start,
89675291 22348 return -EINVAL;
22349 if (end == start)
22350 return 0;
22351+
22352+#ifdef CONFIG_PAX_SEGMEXEC
22353+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
22354+ if (end > SEGMEXEC_TASK_SIZE)
22355+ return -EINVAL;
22356+ } else
22357+#endif
22358+
22359+ if (end > TASK_SIZE)
22360+ return -EINVAL;
22361+
22362 vma = find_vma_prev(current->mm, start, &prev);
22363 if (!vma || vma->vm_start > start)
22364 return -ENOMEM;
9a4c6ab7 22365@@ -144,6 +204,7 @@ asmlinkage long sys_mlock(unsigned long
89675291 22366 lock_limit >>= PAGE_SHIFT;
22367
22368 /* check against resource limits */
22369+ gr_learn_resource(current, RLIMIT_MEMLOCK, (current->mm->locked_vm << PAGE_SHIFT) + len, 1);
22370 if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
22371 error = do_mlock(start, len, 1);
9a4c6ab7 22372 out:
22373@@ -177,6 +238,16 @@ static int do_mlockall(int flags)
89675291 22374 for (vma = current->mm->mmap; vma ; vma = prev->vm_next) {
22375 unsigned int newflags;
22376
22377+#ifdef CONFIG_PAX_SEGMEXEC
22378+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
22379+ if (vma->vm_end > SEGMEXEC_TASK_SIZE)
22380+ break;
22381+ } else
22382+#endif
22383+
22384+ if (vma->vm_end > TASK_SIZE)
22385+ break;
22386+
22387 newflags = vma->vm_flags | VM_LOCKED;
22388 if (!(flags & MCL_CURRENT))
22389 newflags &= ~VM_LOCKED;
9a4c6ab7 22390@@ -208,6 +279,7 @@ asmlinkage long sys_mlockall(int flags)
89675291 22391 ret = -ENOMEM;
9a4c6ab7 22392 if (!vx_vmlocked_avail(current->mm, current->mm->total_vm))
22393 goto out;
89675291 22394+ gr_learn_resource(current, RLIMIT_MEMLOCK, current->mm->total_vm, 1);
22395 if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
22396 capable(CAP_IPC_LOCK))
22397 ret = do_mlockall(flags);
22398diff -urNp linux-2.6.16.12/mm/mmap.c linux-2.6.16.12/mm/mmap.c
22399--- linux-2.6.16.12/mm/mmap.c 2006-05-01 15:14:26.000000000 -0400
22400+++ linux-2.6.16.12/mm/mmap.c 2006-05-01 20:17:34.000000000 -0400
22401@@ -25,6 +25,7 @@
22402 #include <linux/mount.h>
22403 #include <linux/mempolicy.h>
22404 #include <linux/rmap.h>
22405+#include <linux/grsecurity.h>
22406
22407 #include <asm/uaccess.h>
22408 #include <asm/cacheflush.h>
22409@@ -60,6 +61,8 @@ pgprot_t protection_map[16] = {
22410 __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
22411 };
22412
22413+EXPORT_SYMBOL(protection_map);
22414+
22415 int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
22416 int sysctl_overcommit_ratio = 50; /* default is 50% */
22417 int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
22418@@ -234,6 +237,7 @@ asmlinkage unsigned long sys_brk(unsigne
22419
22420 /* Check against rlimit.. */
22421 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
22422+ gr_learn_resource(current, RLIMIT_DATA, brk - mm->start_data, 1);
22423 if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
22424 goto out;
22425
22426@@ -612,11 +616,17 @@ again: remove_next = 1 + (end > next->
22427 * If the vma has a ->close operation then the driver probably needs to release
22428 * per-vma resources, so we don't attempt to merge those.
22429 */
22430+#ifdef CONFIG_PAX_SEGMEXEC
22431+#define VM_SPECIAL (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP | VM_MIRROR)
22432+#else
22433 #define VM_SPECIAL (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
22434+#endif
22435
22436 static inline int is_mergeable_vma(struct vm_area_struct *vma,
22437 struct file *file, unsigned long vm_flags)
22438 {
22439+ if ((vma->vm_flags | vm_flags) & VM_SPECIAL)
22440+ return 0;
22441 if (vma->vm_flags != vm_flags)
22442 return 0;
22443 if (vma->vm_file != file)
22444@@ -842,9 +852,6 @@ none:
22445 void vm_stat_account(struct mm_struct *mm, unsigned long flags,
22446 struct file *file, long pages)
22447 {
22448- const unsigned long stack_flags
22449- = VM_STACK_FLAGS & (VM_GROWSUP|VM_GROWSDOWN);
22450-
22451 #ifdef CONFIG_HUGETLB
22452 if (flags & VM_HUGETLB) {
22453 if (!(flags & VM_DONTCOPY))
22454@@ -857,7 +864,7 @@ void vm_stat_account(struct mm_struct *m
22455 mm->shared_vm += pages;
22456 if ((flags & (VM_EXEC|VM_WRITE)) == VM_EXEC)
22457 mm->exec_vm += pages;
22458- } else if (flags & stack_flags)
22459+ } else if (flags & (VM_GROWSUP|VM_GROWSDOWN))
22460 mm->stack_vm += pages;
22461 if (flags & (VM_RESERVED|VM_IO))
22462 mm->reserved_vm += pages;
22463@@ -868,10 +875,55 @@ void vm_stat_account(struct mm_struct *m
22464 * The caller must hold down_write(current->mm->mmap_sem).
22465 */
22466
22467+#ifdef CONFIG_PAX_SEGMEXEC
22468+static unsigned long __do_mmap_pgoff(struct file * file, unsigned long addr,
22469+ unsigned long len, unsigned long prot,
22470+ unsigned long flags, unsigned long pgoff);
22471+
22472 unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
22473 unsigned long len, unsigned long prot,
22474 unsigned long flags, unsigned long pgoff)
22475 {
22476+ unsigned long ret = -EINVAL;
22477+
22478+ if (flags & MAP_MIRROR)
22479+ return ret;
22480+
22481+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) &&
22482+ (len > SEGMEXEC_TASK_SIZE || (addr > SEGMEXEC_TASK_SIZE-len)))
22483+ return ret;
22484+
22485+ ret = __do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
22486+
22487+ if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && ret < TASK_SIZE && ((flags & MAP_TYPE) == MAP_PRIVATE)
22488+
22489+#ifdef CONFIG_PAX_MPROTECT
22490+ && (!(current->mm->pax_flags & MF_PAX_MPROTECT) || ((prot & PROT_EXEC) && file && !(prot & PROT_WRITE)))
22491+#endif
22492+
22493+ )
22494+ {
22495+ unsigned long ret_m;
22496+ prot = prot & PROT_EXEC ? prot & ~PROT_WRITE : PROT_NONE;
22497+ ret_m = __do_mmap_pgoff(NULL, ret + SEGMEXEC_TASK_SIZE, 0UL, prot, flags | MAP_MIRROR | MAP_FIXED, ret);
22498+ if (ret_m >= TASK_SIZE) {
22499+ do_munmap(current->mm, ret, len);
22500+ ret = ret_m;
22501+ }
22502+ }
22503+
22504+ return ret;
22505+}
22506+
22507+static unsigned long __do_mmap_pgoff(struct file * file, unsigned long addr,
22508+ unsigned long len, unsigned long prot,
22509+ unsigned long flags, unsigned long pgoff)
22510+#else
22511+unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
22512+ unsigned long len, unsigned long prot,
22513+ unsigned long flags, unsigned long pgoff)
22514+#endif
22515+{
22516 struct mm_struct * mm = current->mm;
22517 struct vm_area_struct * vma, * prev;
22518 struct inode *inode;
22519@@ -882,6 +934,28 @@ unsigned long do_mmap_pgoff(struct file
22520 int accountable = 1;
22521 unsigned long charged = 0, reqprot = prot;
22522
22523+#ifdef CONFIG_PAX_SEGMEXEC
22524+ struct vm_area_struct * vma_m = NULL;
22525+
22526+ if (flags & MAP_MIRROR) {
22527+ /* PaX: sanity checks, to be removed when proved to be stable */
22528+ if (file || len || ((flags & MAP_TYPE) != MAP_PRIVATE))
22529+ return -EINVAL;
22530+
22531+ vma_m = find_vma(mm, pgoff);
22532+
22533+ if (!vma_m || is_vm_hugetlb_page(vma_m) ||
22534+ vma_m->vm_start != pgoff ||
22535+ (vma_m->vm_flags & VM_SPECIAL) ||
22536+ (prot & PROT_WRITE))
22537+ return -EINVAL;
22538+
22539+ file = vma_m->vm_file;
22540+ pgoff = vma_m->vm_pgoff;
22541+ len = vma_m->vm_end - vma_m->vm_start;
22542+ }
22543+#endif
22544+
22545 if (file) {
22546 if (is_file_hugepages(file))
22547 accountable = 0;
22548@@ -922,7 +996,7 @@ unsigned long do_mmap_pgoff(struct file
22549 /* Obtain the address to map to. we verify (or select) it and ensure
22550 * that it represents a valid section of the address space.
22551 */
22552- addr = get_unmapped_area(file, addr, len, pgoff, flags);
22553+ addr = get_unmapped_area(file, addr, len, pgoff, flags | ((prot & PROT_EXEC) ? MAP_EXECUTABLE : 0));
22554 if (addr & ~PAGE_MASK)
22555 return addr;
22556
22557@@ -933,6 +1007,24 @@ unsigned long do_mmap_pgoff(struct file
22558 vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) |
22559 mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
22560
22561+ if (file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
22562+ vm_flags &= ~VM_MAYEXEC;
22563+
22564+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
22565+ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
22566+
22567+#ifdef CONFIG_PAX_MPROTECT
22568+ if (mm->pax_flags & MF_PAX_MPROTECT) {
22569+ if ((prot & (PROT_WRITE | PROT_EXEC)) != PROT_EXEC)
22570+ vm_flags &= ~(VM_EXEC | VM_MAYEXEC);
22571+ else
22572+ vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
22573+ }
22574+#endif
22575+
22576+ }
22577+#endif
22578+
22579 if (flags & MAP_LOCKED) {
22580 if (!can_do_mlock())
22581 return -EPERM;
22582@@ -945,6 +1037,7 @@ unsigned long do_mmap_pgoff(struct file
22583 locked += mm->locked_vm;
22584 lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
22585 lock_limit >>= PAGE_SHIFT;
22586+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
22587 if (locked > lock_limit && !capable(CAP_IPC_LOCK))
22588 return -EAGAIN;
22589 }
22590@@ -992,6 +1085,11 @@ unsigned long do_mmap_pgoff(struct file
22591 /*
22592 * Set pgoff according to addr for anon_vma.
22593 */
22594+
22595+#ifdef CONFIG_PAX_SEGMEXEC
22596+ if (!(flags & MAP_MIRROR))
22597+#endif
22598+
22599 pgoff = addr >> PAGE_SHIFT;
22600 break;
22601 default:
22602@@ -1003,14 +1101,17 @@ unsigned long do_mmap_pgoff(struct file
22603 if (error)
22604 return error;
22605
22606+ if (!gr_acl_handle_mmap(file, prot))
22607+ return -EACCES;
22608+
22609 /* Clear old maps */
22610 error = -ENOMEM;
22611-munmap_back:
22612 vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
22613 if (vma && vma->vm_start < addr + len) {
22614 if (do_munmap(mm, addr, len))
22615 return -ENOMEM;
22616- goto munmap_back;
22617+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
22618+ BUG_ON(vma && vma->vm_start < addr + len);
22619 }
22620
22621 /* Check against address space limit. */
22622@@ -1059,6 +1160,13 @@ munmap_back:
22623 vma->vm_start = addr;
22624 vma->vm_end = addr + len;
22625 vma->vm_flags = vm_flags;
22626+
22627+#ifdef CONFIG_PAX_PAGEEXEC
22628+ if ((file || !(mm->pax_flags & MF_PAX_PAGEEXEC)) && (vm_flags & (VM_READ|VM_WRITE)))
22629+ vma->vm_page_prot = protection_map[(vm_flags | VM_EXEC) & 0x0f];
22630+ else
22631+#endif
22632+
22633 vma->vm_page_prot = protection_map[vm_flags & 0x0f];
22634 vma->vm_pgoff = pgoff;
22635
22636@@ -1083,6 +1191,14 @@ munmap_back:
22637 goto free_vma;
22638 }
22639
22640+#ifdef CONFIG_PAX_SEGMEXEC
22641+ if (flags & MAP_MIRROR) {
22642+ vma_m->vm_flags |= VM_MIRROR;
22643+ vma_m->vm_mirror = vma->vm_start - vma_m->vm_start;
22644+ vma->vm_mirror = vma_m->vm_start - vma->vm_start;
22645+ }
22646+#endif
22647+
22648 /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform
22649 * shmem_zero_setup (perhaps called through /dev/zero's ->mmap)
22650 * that memory reservation must be checked; but that reservation
22651@@ -1118,6 +1234,7 @@ munmap_back:
22652 out:
9a4c6ab7 22653 vx_vmpages_add(mm, len >> PAGE_SHIFT);
89675291 22654 vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
22655+ track_exec_limit(mm, addr, addr + len, vm_flags);
22656 if (vm_flags & VM_LOCKED) {
9a4c6ab7 22657 vx_vmlocked_add(mm, len >> PAGE_SHIFT);
89675291 22658 make_pages_present(addr, addr + len);
22659@@ -1172,6 +1289,10 @@ arch_get_unmapped_area(struct file *filp
22660 if (len > TASK_SIZE)
22661 return -ENOMEM;
22662
22663+#ifdef CONFIG_PAX_RANDMMAP
22664+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
22665+#endif
22666+
22667 if (addr) {
22668 addr = PAGE_ALIGN(addr);
22669 vma = find_vma(mm, addr);
22670@@ -1182,7 +1303,7 @@ arch_get_unmapped_area(struct file *filp
22671 if (len > mm->cached_hole_size) {
22672 start_addr = addr = mm->free_area_cache;
22673 } else {
22674- start_addr = addr = TASK_UNMAPPED_BASE;
22675+ start_addr = addr = mm->mmap_base;
22676 mm->cached_hole_size = 0;
22677 }
22678
22679@@ -1194,9 +1315,8 @@ full_search:
22680 * Start a new search - just in case we missed
22681 * some holes.
22682 */
22683- if (start_addr != TASK_UNMAPPED_BASE) {
22684- addr = TASK_UNMAPPED_BASE;
22685- start_addr = addr;
22686+ if (start_addr != mm->mmap_base) {
22687+ start_addr = addr = mm->mmap_base;
22688 mm->cached_hole_size = 0;
22689 goto full_search;
22690 }
22691@@ -1221,7 +1341,7 @@ void arch_unmap_area(struct mm_struct *m
22692 /*
22693 * Is this a new hole at the lowest possible address?
22694 */
22695- if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache) {
22696+ if (addr >= mm->mmap_base && addr < mm->free_area_cache) {
22697 mm->free_area_cache = addr;
22698 mm->cached_hole_size = ~0UL;
22699 }
22700@@ -1239,12 +1359,16 @@ arch_get_unmapped_area_topdown(struct fi
22701 {
22702 struct vm_area_struct *vma;
22703 struct mm_struct *mm = current->mm;
22704- unsigned long addr = addr0;
22705+ unsigned long base = mm->mmap_base, addr = addr0;
22706
22707 /* requested length too big for entire address space */
22708 if (len > TASK_SIZE)
22709 return -ENOMEM;
22710
22711+#ifdef CONFIG_PAX_RANDMMAP
22712+ if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
22713+#endif
22714+
22715 /* requesting a specific address */
22716 if (addr) {
22717 addr = PAGE_ALIGN(addr);
22718@@ -1302,13 +1426,21 @@ bottomup:
22719 * can happen with large stack limits and large mmap()
22720 * allocations.
22721 */
22722+ mm->mmap_base = TASK_UNMAPPED_BASE;
22723+
22724+#ifdef CONFIG_PAX_RANDMMAP
22725+ if (mm->pax_flags & MF_PAX_RANDMMAP)
22726+ mm->mmap_base += mm->delta_mmap;
22727+#endif
22728+
22729+ mm->free_area_cache = mm->mmap_base;
22730 mm->cached_hole_size = ~0UL;
22731- mm->free_area_cache = TASK_UNMAPPED_BASE;
22732 addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
22733 /*
22734 * Restore the topdown base:
22735 */
22736- mm->free_area_cache = mm->mmap_base;
22737+ mm->mmap_base = base;
22738+ mm->free_area_cache = base;
22739 mm->cached_hole_size = ~0UL;
22740
22741 return addr;
22742@@ -1324,8 +1456,10 @@ void arch_unmap_area_topdown(struct mm_s
22743 mm->free_area_cache = addr;
22744
22745 /* dont allow allocations above current base */
22746- if (mm->free_area_cache > mm->mmap_base)
22747+ if (mm->free_area_cache > mm->mmap_base) {
22748 mm->free_area_cache = mm->mmap_base;
22749+ mm->cached_hole_size = ~0UL;
22750+ }
22751 }
22752
22753 unsigned long
22754@@ -1458,6 +1592,7 @@ static int acct_stack_growth(struct vm_a
22755 return -ENOMEM;
22756
22757 /* Stack limit test */
22758+ gr_learn_resource(current, RLIMIT_STACK, size, 1);
22759 if (size > rlim[RLIMIT_STACK].rlim_cur)
22760 return -ENOMEM;
22761
22762@@ -1467,6 +1602,7 @@ static int acct_stack_growth(struct vm_a
22763 unsigned long limit;
22764 locked = mm->locked_vm + grow;
22765 limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
22766+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
22767 if (locked > limit && !capable(CAP_IPC_LOCK))
22768 return -ENOMEM;
22769 }
22770@@ -1584,13 +1720,49 @@ int expand_stack(struct vm_area_struct *
22771 if (address < vma->vm_start) {
22772 unsigned long size, grow;
22773
22774+#ifdef CONFIG_PAX_SEGMEXEC
22775+ struct vm_area_struct *vma_m = NULL;
22776+ unsigned long address_m = 0UL;
22777+
22778+ if (vma->vm_flags & VM_MIRROR) {
22779+ address_m = vma->vm_start + vma->vm_mirror;
22780+ vma_m = find_vma(vma->vm_mm, address_m);
22781+ if (!vma_m || vma_m->vm_start != address_m ||
22782+ !(vma_m->vm_flags & VM_MIRROR) ||
22783+ vma->vm_end - vma->vm_start !=
22784+ vma_m->vm_end - vma_m->vm_start ||
22785+ vma->anon_vma != vma_m->anon_vma) {
22786+ printk(KERN_ERR "PAX: VMMIRROR: expand bug, %08lx, %08lx, %08lx, %08lx, %08lx\n",
22787+ address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
22788+ anon_vma_unlock(vma);
22789+ return -EFAULT;
22790+ }
22791+ address_m = address + vma->vm_mirror;
22792+ }
22793+#endif
22794+
22795 size = vma->vm_end - address;
22796 grow = (vma->vm_start - address) >> PAGE_SHIFT;
22797
22798+#ifdef CONFIG_PAX_SEGMEXEC
22799+ if (vma_m)
22800+ error = acct_stack_growth(vma, size, 2*grow);
22801+ else
22802+#endif
22803+
22804 error = acct_stack_growth(vma, size, grow);
22805 if (!error) {
22806 vma->vm_start = address;
22807 vma->vm_pgoff -= grow;
22808+ track_exec_limit(vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_flags);
22809+
22810+#ifdef CONFIG_PAX_SEGMEXEC
22811+ if (vma_m) {
22812+ vma_m->vm_start = address_m;
22813+ vma_m->vm_pgoff -= grow;
22814+ }
22815+#endif
22816+
22817 }
22818 }
22819 anon_vma_unlock(vma);
22820@@ -1752,7 +1924,24 @@ int split_vma(struct mm_struct * mm, str
22821 * work. This now handles partial unmappings.
22822 * Jeremy Fitzhardinge <jeremy@goop.org>
22823 */
22824+#ifdef CONFIG_PAX_SEGMEXEC
22825+static int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len);
22826+
22827+int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
22828+{
22829+ if (mm->pax_flags & MF_PAX_SEGMEXEC) {
22830+ int ret = __do_munmap(mm, start + SEGMEXEC_TASK_SIZE, len);
22831+ if (ret)
22832+ return ret;
22833+ }
22834+
22835+ return __do_munmap(mm, start, len);
22836+}
22837+
22838+static int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
22839+#else
22840 int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
22841+#endif
22842 {
22843 unsigned long end;
22844 struct vm_area_struct *vma, *prev, *last;
22845@@ -1806,6 +1995,8 @@ int do_munmap(struct mm_struct *mm, unsi
22846 /* Fix up all other VM information */
22847 remove_vma_list(mm, vma);
22848
22849+ track_exec_limit(mm, start, end, 0UL);
22850+
22851 return 0;
22852 }
22853
22854@@ -1818,6 +2009,12 @@ asmlinkage long sys_munmap(unsigned long
22855
22856 profile_munmap(addr);
22857
22858+#ifdef CONFIG_PAX_SEGMEXEC
22859+ if ((mm->pax_flags & MF_PAX_SEGMEXEC) &&
22860+ (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len))
22861+ return -EINVAL;
22862+#endif
22863+
22864 down_write(&mm->mmap_sem);
22865 ret = do_munmap(mm, addr, len);
22866 up_write(&mm->mmap_sem);
22867@@ -1839,11 +2036,35 @@ static inline void verify_mm_writelocked
22868 * anonymous maps. eventually we may be able to do some
22869 * brk-specific accounting here.
22870 */
22871+#ifdef CONFIG_PAX_SEGMEXEC
22872+static unsigned long __do_brk(unsigned long addr, unsigned long len);
22873+
22874 unsigned long do_brk(unsigned long addr, unsigned long len)
22875 {
22876+ unsigned long ret;
22877+
22878+ ret = __do_brk(addr, len);
22879+ if (ret == addr && (current->mm->pax_flags & (MF_PAX_SEGMEXEC | MF_PAX_MPROTECT)) == MF_PAX_SEGMEXEC) {
22880+ unsigned long ret_m;
22881+
22882+ ret_m = __do_mmap_pgoff(NULL, addr + SEGMEXEC_TASK_SIZE, 0UL, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_MIRROR, addr);
22883+ if (ret_m > TASK_SIZE) {
22884+ do_munmap(current->mm, addr, len);
22885+ ret = ret_m;
22886+ }
22887+ }
22888+
22889+ return ret;
22890+}
22891+
22892+static unsigned long __do_brk(unsigned long addr, unsigned long len)
22893+#else
22894+unsigned long do_brk(unsigned long addr, unsigned long len)
22895+#endif
22896+{
22897 struct mm_struct * mm = current->mm;
22898 struct vm_area_struct * vma, * prev;
22899- unsigned long flags;
22900+ unsigned long flags, task_size = TASK_SIZE;
22901 struct rb_node ** rb_link, * rb_parent;
22902 pgoff_t pgoff = addr >> PAGE_SHIFT;
22903
22904@@ -1851,7 +2072,12 @@ unsigned long do_brk(unsigned long addr,
22905 if (!len)
22906 return addr;
22907
22908- if ((addr + len) > TASK_SIZE || (addr + len) < addr)
22909+#ifdef CONFIG_PAX_SEGMEXEC
22910+ if (mm->pax_flags & MF_PAX_SEGMEXEC)
22911+ task_size = SEGMEXEC_TASK_SIZE;
22912+#endif
22913+
22914+ if ((addr + len) > task_size || (addr + len) < addr)
22915 return -EINVAL;
22916
22917 /*
22918@@ -1863,6 +2089,7 @@ unsigned long do_brk(unsigned long addr,
22919 locked += mm->locked_vm;
22920 lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
22921 lock_limit >>= PAGE_SHIFT;
22922+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
22923 if (locked > lock_limit && !capable(CAP_IPC_LOCK))
22924 return -EAGAIN;
9a4c6ab7 22925 if (!vx_vmlocked_avail(mm, len >> PAGE_SHIFT))
22926@@ -1878,12 +2105,12 @@ unsigned long do_brk(unsigned long addr,
89675291 22927 /*
22928 * Clear old maps. this also does some error checking for us
22929 */
22930- munmap_back:
22931 vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
22932 if (vma && vma->vm_start < addr + len) {
22933 if (do_munmap(mm, addr, len))
22934 return -ENOMEM;
22935- goto munmap_back;
22936+ vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
22937+ BUG_ON(vma && vma->vm_start < addr + len);
22938 }
22939
22940 /* Check against address space limits *after* clearing old maps... */
9a4c6ab7 22941@@ -1899,6 +2126,18 @@ unsigned long do_brk(unsigned long addr,
89675291 22942
22943 flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
22944
22945+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
22946+ if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
22947+ flags &= ~VM_EXEC;
22948+
22949+#ifdef CONFIG_PAX_MPROTECT
22950+ if (mm->pax_flags & MF_PAX_MPROTECT)
22951+ flags &= ~VM_MAYEXEC;
22952+#endif
22953+
22954+ }
22955+#endif
22956+
22957 /* Can we just expand an old private anonymous mapping? */
22958 if (vma_merge(mm, prev, addr, addr + len, flags,
22959 NULL, NULL, pgoff, NULL))
9a4c6ab7 22960@@ -1919,6 +2158,13 @@ unsigned long do_brk(unsigned long addr,
89675291 22961 vma->vm_end = addr + len;
22962 vma->vm_pgoff = pgoff;
22963 vma->vm_flags = flags;
22964+
22965+#ifdef CONFIG_PAX_PAGEEXEC
22966+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & (VM_READ|VM_WRITE)))
22967+ vma->vm_page_prot = protection_map[(flags | VM_EXEC) & 0x0f];
22968+ else
22969+#endif
22970+
22971 vma->vm_page_prot = protection_map[flags & 0x0f];
22972 vma_link(mm, vma, prev, rb_link, rb_parent);
22973 out:
9a4c6ab7 22974@@ -1927,6 +2173,7 @@ out:
22975 vx_vmlocked_add(mm, len >> PAGE_SHIFT);
89675291 22976 make_pages_present(addr, addr + len);
22977 }
22978+ track_exec_limit(mm, addr, addr + len, flags);
22979 return addr;
22980 }
22981
9a4c6ab7 22982@@ -2066,7 +2313,7 @@ int may_expand_vm(struct mm_struct *mm,
89675291 22983 unsigned long lim;
22984
22985 lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
22986-
22987+ gr_learn_resource(current, RLIMIT_AS, (cur + npages) << PAGE_SHIFT, 1);
22988 if (cur + npages > lim)
22989 return 0;
9a4c6ab7 22990 if (!vx_vmpages_avail(mm, npages))
89675291 22991diff -urNp linux-2.6.16.12/mm/mprotect.c linux-2.6.16.12/mm/mprotect.c
22992--- linux-2.6.16.12/mm/mprotect.c 2006-05-01 15:14:26.000000000 -0400
22993+++ linux-2.6.16.12/mm/mprotect.c 2006-05-01 20:17:34.000000000 -0400
22994@@ -19,11 +19,18 @@
22995 #include <linux/mempolicy.h>
22996 #include <linux/personality.h>
22997 #include <linux/syscalls.h>
22998+#include <linux/grsecurity.h>
22999+
23000+#ifdef CONFIG_PAX_MPROTECT
23001+#include <linux/elf.h>
23002+#include <linux/fs.h>
23003+#endif
23004
23005 #include <asm/uaccess.h>
23006 #include <asm/pgtable.h>
23007 #include <asm/cacheflush.h>
23008 #include <asm/tlbflush.h>
23009+#include <asm/mmu_context.h>
23010
23011 static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
23012 unsigned long addr, unsigned long end, pgprot_t newprot)
23013@@ -98,6 +105,94 @@ static void change_protection(struct vm_
23014 flush_tlb_range(vma, start, end);
23015 }
23016
23017+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
23018+/* called while holding the mmap semaphor for writing */
23019+static inline void establish_user_cs_limit(struct mm_struct *mm, unsigned long start, unsigned long end)
23020+{
23021+ struct vm_area_struct *vma = find_vma(mm, start);
23022+
23023+ for (; vma && vma->vm_start < end; vma = vma->vm_next)
23024+ change_protection(vma, vma->vm_start, vma->vm_end, vma->vm_page_prot);
23025+
23026+}
23027+
23028+void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot)
23029+{
23030+ unsigned long oldlimit, newlimit = 0UL;
23031+
23032+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC))
23033+ return;
23034+
23035+ spin_lock(&mm->page_table_lock);
23036+ oldlimit = mm->context.user_cs_limit;
23037+ if ((prot & VM_EXEC) && oldlimit < end)
23038+ /* USER_CS limit moved up */
23039+ newlimit = end;
23040+ else if (!(prot & VM_EXEC) && start < oldlimit && oldlimit <= end)
23041+ /* USER_CS limit moved down */
23042+ newlimit = start;
23043+
23044+ if (newlimit) {
23045+ mm->context.user_cs_limit = newlimit;
23046+
23047+#ifdef CONFIG_SMP
23048+ wmb();
23049+ cpus_clear(mm->context.cpu_user_cs_mask);
23050+ cpu_set(smp_processor_id(), mm->context.cpu_user_cs_mask);
23051+#endif
23052+
23053+ set_user_cs(mm, smp_processor_id());
23054+ }
23055+ spin_unlock(&mm->page_table_lock);
23056+ if (newlimit == end)
23057+ establish_user_cs_limit(mm, oldlimit, end);
23058+}
23059+#endif
23060+
23061+#ifdef CONFIG_PAX_SEGMEXEC
23062+static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
23063+ unsigned long start, unsigned long end, unsigned int newflags);
23064+
23065+static int mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
23066+ unsigned long start, unsigned long end, unsigned int newflags)
23067+{
23068+ if (vma->vm_flags & VM_MIRROR) {
23069+ struct vm_area_struct * vma_m, * prev_m;
23070+ unsigned long start_m, end_m;
23071+ int error;
23072+
23073+ start_m = vma->vm_start + vma->vm_mirror;
23074+ vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m);
23075+ if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
23076+ start_m = start + vma->vm_mirror;
23077+ end_m = end + vma->vm_mirror;
23078+
23079+ if (vma_m->vm_start >= SEGMEXEC_TASK_SIZE && !(newflags & VM_EXEC))
23080+ error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, vma_m->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC));
23081+ else
23082+ error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, newflags);
23083+ if (error)
23084+ return error;
23085+ } else {
23086+ printk("PAX: VMMIRROR: mprotect bug in %s, %08lx\n", current->comm, vma->vm_start);
23087+ return -ENOMEM;
23088+ }
23089+ }
23090+
23091+ return __mprotect_fixup(vma, pprev, start, end, newflags);
23092+}
23093+
23094+static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
23095+ unsigned long start, unsigned long end, unsigned int newflags)
23096+{
23097+ struct mm_struct * mm = vma->vm_mm;
23098+ unsigned long oldflags = vma->vm_flags;
23099+ long nrpages = (end - start) >> PAGE_SHIFT;
23100+ unsigned long charged = 0;
23101+ pgprot_t newprot;
23102+ pgoff_t pgoff;
23103+ int error;
23104+#else
23105 static int
23106 mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
23107 unsigned long start, unsigned long end, unsigned long newflags)
23108@@ -114,6 +209,7 @@ mprotect_fixup(struct vm_area_struct *vm
23109 *pprev = vma;
23110 return 0;
23111 }
23112+#endif
23113
23114 /*
23115 * If we make a private mapping writable we increase our commit;
23116@@ -132,6 +228,12 @@ mprotect_fixup(struct vm_area_struct *vm
23117 }
23118 }
23119
23120+#ifdef CONFIG_PAX_PAGEEXEC
23121+ if (!(mm->pax_flags & MF_PAX_PAGEEXEC) && (newflags & (VM_READ|VM_WRITE)))
23122+ newprot = protection_map[(newflags | VM_EXEC) & 0xf];
23123+ else
23124+#endif
23125+
23126 newprot = protection_map[newflags & 0xf];
23127
23128 /*
23129@@ -176,6 +278,69 @@ fail:
23130 return error;
23131 }
23132
23133+#ifdef CONFIG_PAX_MPROTECT
23134+/* PaX: non-PIC ELF libraries need relocations on their executable segments
23135+ * therefore we'll grant them VM_MAYWRITE once during their life.
23136+ *
23137+ * The checks favour ld-linux.so behaviour which operates on a per ELF segment
23138+ * basis because we want to allow the common case and not the special ones.
23139+ */
23140+static inline void pax_handle_maywrite(struct vm_area_struct * vma, unsigned long start)
23141+{
23142+ struct elfhdr elf_h;
23143+ struct elf_phdr elf_p, p_dyn;
23144+ elf_dyn dyn;
23145+ unsigned long i, j = 65536UL / sizeof(struct elf_phdr);
23146+
23147+#ifndef CONFIG_PAX_NOELFRELOCS
23148+ if ((vma->vm_start != start) ||
23149+ !vma->vm_file ||
23150+ !(vma->vm_flags & VM_MAYEXEC) ||
23151+ (vma->vm_flags & VM_MAYNOTWRITE))
23152+#endif
23153+
23154+ return;
23155+
23156+ if (sizeof(elf_h) != kernel_read(vma->vm_file, 0UL, (char*)&elf_h, sizeof(elf_h)) ||
23157+ memcmp(elf_h.e_ident, ELFMAG, SELFMAG) ||
23158+
23159+#ifdef CONFIG_PAX_ETEXECRELOCS
23160+ (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC) ||
23161+#else
23162+ elf_h.e_type != ET_DYN ||
23163+#endif
23164+
23165+ !elf_check_arch(&elf_h) ||
23166+ elf_h.e_phentsize != sizeof(struct elf_phdr) ||
23167+ elf_h.e_phnum > j)
23168+ return;
23169+
23170+ for (i = 0UL; i < elf_h.e_phnum; i++) {
23171+ if (sizeof(elf_p) != kernel_read(vma->vm_file, elf_h.e_phoff + i*sizeof(elf_p), (char*)&elf_p, sizeof(elf_p)))
23172+ return;
23173+ if (elf_p.p_type == PT_DYNAMIC) {
23174+ p_dyn = elf_p;
23175+ j = i;
23176+ }
23177+ }
23178+ if (elf_h.e_phnum <= j)
23179+ return;
23180+
23181+ i = 0UL;
23182+ do {
23183+ if (sizeof(dyn) != kernel_read(vma->vm_file, p_dyn.p_offset + i*sizeof(dyn), (char*)&dyn, sizeof(dyn)))
23184+ return;
23185+ if (dyn.d_tag == DT_TEXTREL || (dyn.d_tag == DT_FLAGS && (dyn.d_un.d_val & DF_TEXTREL))) {
23186+ vma->vm_flags |= VM_MAYWRITE | VM_MAYNOTWRITE;
23187+ gr_log_textrel(vma);
23188+ return;
23189+ }
23190+ i++;
23191+ } while (dyn.d_tag != DT_NULL);
23192+ return;
23193+}
23194+#endif
23195+
23196 asmlinkage long
23197 sys_mprotect(unsigned long start, size_t len, unsigned long prot)
23198 {
23199@@ -195,6 +360,17 @@ sys_mprotect(unsigned long start, size_t
23200 end = start + len;
23201 if (end <= start)
23202 return -ENOMEM;
23203+
23204+#ifdef CONFIG_PAX_SEGMEXEC
23205+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
23206+ if (end > SEGMEXEC_TASK_SIZE)
23207+ return -EINVAL;
23208+ } else
23209+#endif
23210+
23211+ if (end > TASK_SIZE)
23212+ return -EINVAL;
23213+
23214 if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM))
23215 return -EINVAL;
23216
23217@@ -235,6 +411,16 @@ sys_mprotect(unsigned long start, size_t
23218 if (start > vma->vm_start)
23219 prev = vma;
23220
23221+#ifdef CONFIG_PAX_MPROTECT
23222+ if ((vma->vm_mm->pax_flags & MF_PAX_MPROTECT) && (prot & PROT_WRITE))
23223+ pax_handle_maywrite(vma, start);
23224+#endif
23225+
23226+ if (!gr_acl_handle_mprotect(vma->vm_file, prot)) {
23227+ error = -EACCES;
23228+ goto out;
23229+ }
23230+
23231 for (nstart = start ; ; ) {
23232 unsigned long newflags;
23233
23234@@ -253,6 +439,12 @@ sys_mprotect(unsigned long start, size_t
23235 goto out;
23236 }
23237
23238+#ifdef CONFIG_PAX_MPROTECT
23239+ /* PaX: disallow write access after relocs are done, hopefully noone else needs it... */
23240+ if ((vma->vm_mm->pax_flags & MF_PAX_MPROTECT) && !(prot & PROT_WRITE) && (vma->vm_flags & VM_MAYNOTWRITE))
23241+ newflags &= ~VM_MAYWRITE;
23242+#endif
23243+
23244 error = security_file_mprotect(vma, reqprot, prot);
23245 if (error)
23246 goto out;
23247@@ -276,6 +468,9 @@ sys_mprotect(unsigned long start, size_t
23248 goto out;
23249 }
23250 }
23251+
23252+ track_exec_limit(current->mm, start, end, vm_flags);
23253+
23254 out:
23255 up_write(&current->mm->mmap_sem);
23256 return error;
23257diff -urNp linux-2.6.16.12/mm/mremap.c linux-2.6.16.12/mm/mremap.c
23258--- linux-2.6.16.12/mm/mremap.c 2006-05-01 15:14:26.000000000 -0400
23259+++ linux-2.6.16.12/mm/mremap.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 23260@@ -107,6 +107,12 @@ static void move_ptes(struct vm_area_str
89675291 23261 pte = ptep_clear_flush(vma, old_addr, old_pte);
23262 /* ZERO_PAGE can be dependant on virtual addr */
23263 pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr);
23264+
23265+#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
23266+ if ((mm->pax_flags & MF_PAX_PAGEEXEC) && !(vma->vm_flags & VM_EXEC))
23267+ pte_exprotect(pte);
23268+#endif
23269+
23270 set_pte_at(mm, new_addr, new_pte, pte);
23271 }
23272
9a4c6ab7 23273@@ -254,6 +260,7 @@ unsigned long do_mremap(unsigned long ad
89675291 23274 struct vm_area_struct *vma;
23275 unsigned long ret = -EINVAL;
23276 unsigned long charged = 0;
23277+ unsigned long task_size = TASK_SIZE;
23278
23279 if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
23280 goto out;
9a4c6ab7 23281@@ -272,6 +279,15 @@ unsigned long do_mremap(unsigned long ad
89675291 23282 if (!new_len)
23283 goto out;
23284
23285+#ifdef CONFIG_PAX_SEGMEXEC
23286+ if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
23287+ task_size = SEGMEXEC_TASK_SIZE;
23288+#endif
23289+
23290+ if (new_len > task_size || addr > task_size-new_len ||
23291+ old_len > task_size || addr > task_size-old_len)
23292+ goto out;
23293+
23294 /* new_addr is only valid if MREMAP_FIXED is specified */
23295 if (flags & MREMAP_FIXED) {
23296 if (new_addr & ~PAGE_MASK)
9a4c6ab7 23297@@ -279,16 +295,13 @@ unsigned long do_mremap(unsigned long ad
89675291 23298 if (!(flags & MREMAP_MAYMOVE))
23299 goto out;
23300
23301- if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
23302+ if (new_addr > task_size - new_len)
23303 goto out;
23304
23305 /* Check if the location we're moving into overlaps the
23306 * old location at all, and fail if it does.
23307 */
23308- if ((new_addr <= addr) && (new_addr+new_len) > addr)
23309- goto out;
23310-
23311- if ((addr <= new_addr) && (addr+old_len) > new_addr)
23312+ if (addr + old_len > new_addr && new_addr + new_len > addr)
23313 goto out;
23314
23315 ret = do_munmap(mm, new_addr, new_len);
9a4c6ab7 23316@@ -322,6 +335,14 @@ unsigned long do_mremap(unsigned long ad
89675291 23317 ret = -EINVAL;
23318 goto out;
23319 }
23320+
23321+#ifdef CONFIG_PAX_SEGMEXEC
23322+ if (vma->vm_flags & VM_MIRROR) {
23323+ ret = -EINVAL;
23324+ goto out;
23325+ }
23326+#endif
23327+
23328 /* We can't remap across vm area boundaries */
23329 if (old_len > vma->vm_end - addr)
23330 goto out;
9a4c6ab7 23331@@ -358,7 +379,7 @@ unsigned long do_mremap(unsigned long ad
89675291 23332 if (old_len == vma->vm_end - addr &&
23333 !((flags & MREMAP_FIXED) && (addr != new_addr)) &&
23334 (old_len != new_len || !(flags & MREMAP_MAYMOVE))) {
23335- unsigned long max_addr = TASK_SIZE;
23336+ unsigned long max_addr = task_size;
23337 if (vma->vm_next)
23338 max_addr = vma->vm_next->vm_start;
23339 /* can we just expand the current mapping? */
9a4c6ab7 23340@@ -376,6 +397,7 @@ unsigned long do_mremap(unsigned long ad
89675291 23341 addr + new_len);
23342 }
23343 ret = addr;
23344+ track_exec_limit(vma->vm_mm, vma->vm_start, addr + new_len, vma->vm_flags);
23345 goto out;
23346 }
23347 }
9a4c6ab7 23348@@ -386,8 +408,8 @@ unsigned long do_mremap(unsigned long ad
89675291 23349 */
23350 ret = -ENOMEM;
23351 if (flags & MREMAP_MAYMOVE) {
23352+ unsigned long map_flags = 0;
23353 if (!(flags & MREMAP_FIXED)) {
23354- unsigned long map_flags = 0;
23355 if (vma->vm_flags & VM_MAYSHARE)
23356 map_flags |= MAP_SHARED;
23357
9a4c6ab7 23358@@ -397,7 +419,12 @@ unsigned long do_mremap(unsigned long ad
89675291 23359 if (new_addr & ~PAGE_MASK)
23360 goto out;
23361 }
23362+ map_flags = vma->vm_flags;
23363 ret = move_vma(vma, addr, old_len, new_len, new_addr);
23364+ if (!(ret & ~PAGE_MASK)) {
23365+ track_exec_limit(current->mm, addr, addr + old_len, 0UL);
23366+ track_exec_limit(current->mm, new_addr, new_addr + new_len, map_flags);
23367+ }
23368 }
23369 out:
23370 if (ret & ~PAGE_MASK)
23371diff -urNp linux-2.6.16.12/mm/rmap.c linux-2.6.16.12/mm/rmap.c
23372--- linux-2.6.16.12/mm/rmap.c 2006-05-01 15:14:26.000000000 -0400
23373+++ linux-2.6.16.12/mm/rmap.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 23374@@ -109,6 +109,19 @@ int anon_vma_prepare(struct vm_area_stru
89675291 23375 list_add(&vma->anon_vma_node, &anon_vma->head);
23376 allocated = NULL;
23377 }
23378+
23379+#ifdef CONFIG_PAX_SEGMEXEC
23380+ if (vma->vm_flags & VM_MIRROR) {
23381+ struct vm_area_struct *vma_m;
23382+
23383+ vma_m = find_vma(vma->vm_mm, vma->vm_start + vma->vm_mirror);
23384+ BUG_ON(!vma_m || vma_m->vm_start != vma->vm_start + vma->vm_mirror);
23385+ BUG_ON(vma_m->anon_vma || vma->vm_pgoff != vma_m->vm_pgoff);
23386+ vma_m->anon_vma = anon_vma;
23387+ __anon_vma_link(vma_m);
23388+ }
23389+#endif
23390+
23391 spin_unlock(&mm->page_table_lock);
23392
23393 if (locked)
23394diff -urNp linux-2.6.16.12/mm/vmalloc.c linux-2.6.16.12/mm/vmalloc.c
23395--- linux-2.6.16.12/mm/vmalloc.c 2006-05-01 15:14:26.000000000 -0400
23396+++ linux-2.6.16.12/mm/vmalloc.c 2006-05-01 20:17:34.000000000 -0400
23397@@ -193,6 +193,8 @@ struct vm_struct *__get_vm_area_node(uns
23398
23399 write_lock(&vmlist_lock);
23400 for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
23401+ if (addr > end - size)
23402+ goto out;
23403 if ((unsigned long)tmp->addr < addr) {
23404 if((unsigned long)tmp->addr + tmp->size >= addr)
23405 addr = ALIGN(tmp->size +
23406@@ -204,8 +206,6 @@ struct vm_struct *__get_vm_area_node(uns
23407 if (size + addr <= (unsigned long)tmp->addr)
23408 goto found;
23409 addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);
23410- if (addr > end - size)
23411- goto out;
23412 }
23413
23414 found:
23415diff -urNp linux-2.6.16.12/net/ipv4/inet_connection_sock.c linux-2.6.16.12/net/ipv4/inet_connection_sock.c
23416--- linux-2.6.16.12/net/ipv4/inet_connection_sock.c 2006-05-01 15:14:26.000000000 -0400
23417+++ linux-2.6.16.12/net/ipv4/inet_connection_sock.c 2006-05-01 20:17:34.000000000 -0400
23418@@ -16,6 +16,7 @@
23419 #include <linux/config.h>
23420 #include <linux/module.h>
23421 #include <linux/jhash.h>
23422+#include <linux/grsecurity.h>
23423
23424 #include <net/inet_connection_sock.h>
23425 #include <net/inet_hashtables.h>
23426diff -urNp linux-2.6.16.12/net/ipv4/inet_hashtables.c linux-2.6.16.12/net/ipv4/inet_hashtables.c
23427--- linux-2.6.16.12/net/ipv4/inet_hashtables.c 2006-05-01 15:14:26.000000000 -0400
23428+++ linux-2.6.16.12/net/ipv4/inet_hashtables.c 2006-05-01 20:17:34.000000000 -0400
23429@@ -19,11 +19,14 @@
23430 #include <linux/sched.h>
23431 #include <linux/slab.h>
23432 #include <linux/wait.h>
23433+#include <linux/grsecurity.h>
23434
23435 #include <net/inet_connection_sock.h>
23436 #include <net/inet_hashtables.h>
23437 #include <net/ip.h>
23438
23439+extern void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet);
23440+
23441 /*
23442 * Allocate and initialize a new local port bind bucket.
23443 * The bindhash mutex for snum's hash chain must be held here.
9a4c6ab7 23444@@ -313,6 +316,8 @@ ok:
89675291 23445 }
23446 spin_unlock(&head->lock);
23447
23448+ gr_update_task_in_ip_table(current, inet_sk(sk));
23449+
23450 if (tw) {
23451 inet_twsk_deschedule(tw, death_row);;
23452 inet_twsk_put(tw);
23453diff -urNp linux-2.6.16.12/net/ipv4/netfilter/ipt_stealth.c linux-2.6.16.12/net/ipv4/netfilter/ipt_stealth.c
23454--- linux-2.6.16.12/net/ipv4/netfilter/ipt_stealth.c 1969-12-31 19:00:00.000000000 -0500
23455+++ linux-2.6.16.12/net/ipv4/netfilter/ipt_stealth.c 2006-05-01 20:17:34.000000000 -0400
23456@@ -0,0 +1,112 @@
23457+/* Kernel module to add stealth support.
23458+ *
23459+ * Copyright (C) 2002,2005 Brad Spengler <spender@grsecurity.net>
23460+ *
23461+ */
23462+
23463+#include <linux/kernel.h>
23464+#include <linux/module.h>
23465+#include <linux/skbuff.h>
23466+#include <linux/net.h>
23467+#include <linux/sched.h>
23468+#include <linux/inet.h>
23469+#include <linux/stddef.h>
23470+
23471+#include <net/ip.h>
23472+#include <net/sock.h>
23473+#include <net/tcp.h>
23474+#include <net/udp.h>
23475+#include <net/route.h>
23476+#include <net/inet_common.h>
23477+
23478+#include <linux/netfilter_ipv4/ip_tables.h>
23479+
23480+MODULE_LICENSE("GPL");
23481+
23482+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
23483+
23484+static int
23485+match(const struct sk_buff *skb,
23486+ const struct net_device *in,
23487+ const struct net_device *out,
23488+ const void *matchinfo,
23489+ int offset,
23490+ int *hotdrop)
23491+{
23492+ struct iphdr *ip = skb->nh.iph;
23493+ struct tcphdr th;
23494+ struct udphdr uh;
23495+ struct sock *sk = NULL;
23496+
23497+ if (!ip || offset) return 0;
23498+
23499+ switch(ip->protocol) {
23500+ case IPPROTO_TCP:
23501+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &th, sizeof(th)) < 0) {
23502+ *hotdrop = 1;
23503+ return 0;
23504+ }
23505+ if (!(th.syn && !th.ack)) return 0;
23506+ sk = inet_lookup_listener(&tcp_hashinfo, ip->daddr, ntohs(th.dest), ((struct rtable*)skb->dst)->rt_iif);
23507+ break;
23508+ case IPPROTO_UDP:
23509+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &uh, sizeof(uh)) < 0) {
23510+ *hotdrop = 1;
23511+ return 0;
23512+ }
23513+ sk = udp_v4_lookup(ip->saddr, uh.source, ip->daddr, uh.dest, skb->dev->ifindex);
23514+ break;
23515+ default:
23516+ return 0;
23517+ }
23518+
23519+ if(!sk) // port is being listened on, match this
23520+ return 1;
23521+ else {
23522+ sock_put(sk);
23523+ return 0;
23524+ }
23525+}
23526+
23527+/* Called when user tries to insert an entry of this type. */
23528+static int
23529+checkentry(const char *tablename,
23530+ const struct ipt_ip *ip,
23531+ void *matchinfo,
23532+ unsigned int matchsize,
23533+ unsigned int hook_mask)
23534+{
23535+ if (matchsize != IPT_ALIGN(0))
23536+ return 0;
23537+
23538+ if(((ip->proto == IPPROTO_TCP && !(ip->invflags & IPT_INV_PROTO)) ||
23539+ ((ip->proto == IPPROTO_UDP) && !(ip->invflags & IPT_INV_PROTO)))
23540+ && (hook_mask & (1 << NF_IP_LOCAL_IN)))
23541+ return 1;
23542+
23543+ printk("stealth: Only works on TCP and UDP for the INPUT chain.\n");
23544+
23545+ return 0;
23546+}
23547+
23548+
23549+static struct ipt_match stealth_match = {
23550+ .name = "stealth",
23551+ .match = &match,
23552+ .checkentry = &checkentry,
23553+ .destroy = NULL,
23554+ .me = THIS_MODULE
23555+};
23556+
23557+static int __init init(void)
23558+{
23559+ return ipt_register_match(&stealth_match);
23560+}
23561+
23562+static void __exit fini(void)
23563+{
23564+ ipt_unregister_match(&stealth_match);
23565+}
23566+
23567+module_init(init);
23568+module_exit(fini);
23569diff -urNp linux-2.6.16.12/net/ipv4/netfilter/Kconfig linux-2.6.16.12/net/ipv4/netfilter/Kconfig
23570--- linux-2.6.16.12/net/ipv4/netfilter/Kconfig 2006-05-01 15:14:26.000000000 -0400
23571+++ linux-2.6.16.12/net/ipv4/netfilter/Kconfig 2006-05-01 20:17:34.000000000 -0400
23572@@ -313,6 +313,21 @@ config IP_NF_MATCH_POLICY
23573
23574 To compile it as a module, choose M here. If unsure, say N.
23575
23576+config IP_NF_MATCH_STEALTH
23577+ tristate "stealth match support"
23578+ depends on IP_NF_IPTABLES
23579+ help
23580+ Enabling this option will drop all syn packets coming to unserved tcp
23581+ ports as well as all packets coming to unserved udp ports. If you
23582+ are using your system to route any type of packets (ie. via NAT)
23583+ you should put this module at the end of your ruleset, since it will
23584+ drop packets that aren't going to ports that are listening on your
23585+ machine itself, it doesn't take into account that the packet might be
23586+ destined for someone on your internal network if you're using NAT for
23587+ instance.
23588+
23589+ To compile it as a module, choose M here. If unsure, say N.
23590+
23591 # `filter', generic and specific targets
23592 config IP_NF_FILTER
23593 tristate "Packet filtering"
89675291 23594diff -urNp linux-2.6.16.12/net/ipv4/netfilter/Makefile linux-2.6.16.12/net/ipv4/netfilter/Makefile
23595--- linux-2.6.16.12/net/ipv4/netfilter/Makefile 2006-05-01 15:14:26.000000000 -0400
23596+++ linux-2.6.16.12/net/ipv4/netfilter/Makefile 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 23597@@ -91,6 +91,7 @@ obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_
89675291 23598 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
23599 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
23600 obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
23601+obj-$(CONFIG_IP_NF_MATCH_STEALTH) += ipt_stealth.o
23602
23603 # targets
23604 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
23605diff -urNp linux-2.6.16.12/net/ipv4/tcp_ipv4.c linux-2.6.16.12/net/ipv4/tcp_ipv4.c
23606--- linux-2.6.16.12/net/ipv4/tcp_ipv4.c 2006-05-01 15:14:26.000000000 -0400
23607+++ linux-2.6.16.12/net/ipv4/tcp_ipv4.c 2006-05-01 20:17:34.000000000 -0400
23608@@ -62,6 +62,7 @@
23609 #include <linux/jhash.h>
23610 #include <linux/init.h>
23611 #include <linux/times.h>
23612+#include <linux/grsecurity.h>
23613
23614 #include <net/icmp.h>
23615 #include <net/inet_hashtables.h>
23616diff -urNp linux-2.6.16.12/net/ipv4/udp.c linux-2.6.16.12/net/ipv4/udp.c
23617--- linux-2.6.16.12/net/ipv4/udp.c 2006-05-01 15:14:26.000000000 -0400
23618+++ linux-2.6.16.12/net/ipv4/udp.c 2006-05-01 20:17:34.000000000 -0400
23619@@ -102,6 +102,7 @@
23620 #include <linux/skbuff.h>
23621 #include <linux/proc_fs.h>
23622 #include <linux/seq_file.h>
23623+#include <linux/grsecurity.h>
23624 #include <net/sock.h>
23625 #include <net/udp.h>
23626 #include <net/icmp.h>
23627@@ -110,6 +111,12 @@
23628 #include <net/checksum.h>
23629 #include <net/xfrm.h>
23630
23631+extern int gr_search_udp_recvmsg(const struct sock *sk,
23632+ const struct sk_buff *skb);
23633+extern int gr_search_udp_sendmsg(const struct sock *sk,
23634+ const struct sockaddr_in *addr);
23635+
23636+
23637 /*
23638 * Snmp MIB for the UDP layer
23639 */
9a4c6ab7 23640@@ -270,8 +277,7 @@ static struct sock *udp_v4_lookup_longwa
89675291 23641 return result;
23642 }
23643
23644-static __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport,
23645- u32 daddr, u16 dport, int dif)
23646+struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
23647 {
23648 struct sock *sk;
23649
9a4c6ab7 23650@@ -547,9 +553,16 @@ int udp_sendmsg(struct kiocb *iocb, stru
89675291 23651 dport = usin->sin_port;
23652 if (dport == 0)
23653 return -EINVAL;
23654+
23655+ if (!gr_search_udp_sendmsg(sk, usin))
23656+ return -EPERM;
23657 } else {
23658 if (sk->sk_state != TCP_ESTABLISHED)
23659 return -EDESTADDRREQ;
23660+
23661+ if (!gr_search_udp_sendmsg(sk, NULL))
23662+ return -EPERM;
23663+
23664 daddr = inet->daddr;
23665 dport = inet->dport;
23666 /* Open fast path for connected socket.
9a4c6ab7 23667@@ -812,6 +825,11 @@ try_again:
89675291 23668 if (!skb)
23669 goto out;
23670
23671+ if (!gr_search_udp_recvmsg(sk, skb)) {
23672+ err = -EPERM;
23673+ goto out_free;
23674+ }
23675+
23676 copied = skb->len - sizeof(struct udphdr);
23677 if (copied > len) {
23678 copied = len;
23679diff -urNp linux-2.6.16.12/net/socket.c linux-2.6.16.12/net/socket.c
23680--- linux-2.6.16.12/net/socket.c 2006-05-01 15:14:26.000000000 -0400
23681+++ linux-2.6.16.12/net/socket.c 2006-05-01 20:17:34.000000000 -0400
23682@@ -84,6 +84,7 @@
23683 #include <linux/compat.h>
23684 #include <linux/kmod.h>
23685 #include <linux/audit.h>
23686+#include <linux/in.h>
23687
23688 #ifdef CONFIG_NET_RADIO
23689 #include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
9a4c6ab7 23690@@ -98,6 +99,21 @@
89675291 23691 #include <linux/netfilter.h>
9a4c6ab7 23692 #include <linux/vs_socket.h>
89675291 23693
23694+extern void gr_attach_curr_ip(const struct sock *sk);
23695+extern int gr_handle_sock_all(const int family, const int type,
23696+ const int protocol);
23697+extern int gr_handle_sock_server(const struct sockaddr *sck);
23698+extern int gr_handle_sock_server_other(const struct socket *sck);
23699+extern int gr_handle_sock_client(const struct sockaddr *sck);
23700+extern int gr_search_connect(const struct socket * sock,
23701+ const struct sockaddr_in * addr);
23702+extern int gr_search_bind(const struct socket * sock,
23703+ const struct sockaddr_in * addr);
23704+extern int gr_search_listen(const struct socket * sock);
23705+extern int gr_search_accept(const struct socket * sock);
23706+extern int gr_search_socket(const int domain, const int type,
23707+ const int protocol);
23708+
23709 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
23710 static ssize_t sock_aio_read(struct kiocb *iocb, char __user *buf,
23711 size_t size, loff_t pos);
9a4c6ab7 23712@@ -1223,6 +1239,16 @@ asmlinkage long sys_socket(int family, i
89675291 23713 int retval;
23714 struct socket *sock;
23715
23716+ if(!gr_search_socket(family, type, protocol)) {
23717+ retval = -EACCES;
23718+ goto out;
23719+ }
23720+
23721+ if (gr_handle_sock_all(family, type, protocol)) {
23722+ retval = -EACCES;
23723+ goto out;
23724+ }
23725+
23726 retval = sock_create(family, type, protocol, &sock);
23727 if (retval < 0)
23728 goto out;
9a4c6ab7 23729@@ -1321,11 +1347,23 @@ asmlinkage long sys_bind(int fd, struct
89675291 23730 {
23731 struct socket *sock;
23732 char address[MAX_SOCK_ADDR];
23733+ struct sockaddr *sck;
23734 int err;
23735
23736 if((sock = sockfd_lookup(fd,&err))!=NULL)
23737 {
23738 if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
23739+ sck = (struct sockaddr *)address;
23740+ if (!gr_search_bind(sock, (struct sockaddr_in *)sck)) {
23741+ sockfd_put(sock);
23742+ return -EACCES;
23743+ }
23744+
23745+ if (gr_handle_sock_server(sck)) {
23746+ sockfd_put(sock);
23747+ return -EACCES;
23748+ }
23749+
23750 err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
23751 if (err) {
23752 sockfd_put(sock);
9a4c6ab7 23753@@ -1362,6 +1400,16 @@ asmlinkage long sys_listen(int fd, int b
89675291 23754 return err;
23755 }
23756
23757+ if (gr_handle_sock_server_other(sock)) {
23758+ sockfd_put(sock);
23759+ return -EPERM;
23760+ }
23761+
23762+ if(!gr_search_listen(sock)) {
23763+ sockfd_put(sock);
23764+ return -EPERM;
23765+ }
23766+
23767 err=sock->ops->listen(sock, backlog);
23768 sockfd_put(sock);
23769 }
9a4c6ab7 23770@@ -1398,6 +1446,16 @@ asmlinkage long sys_accept(int fd, struc
89675291 23771 newsock->type = sock->type;
23772 newsock->ops = sock->ops;
23773
23774+ if (gr_handle_sock_server_other(sock)) {
23775+ err = -EPERM;
23776+ goto out_release;
23777+ }
23778+
23779+ if(!gr_search_accept(sock)) {
23780+ err = -EPERM;
23781+ goto out_release;
23782+ }
23783+
23784 /*
23785 * We don't need try_module_get here, as the listening socket (sock)
23786 * has the protocol module (sock->ops->owner) held.
9a4c6ab7 23787@@ -1428,6 +1486,7 @@ asmlinkage long sys_accept(int fd, struc
89675291 23788 goto out_release;
23789
23790 security_socket_post_accept(sock, newsock);
23791+ gr_attach_curr_ip(newsock->sk);
23792
23793 out_put:
23794 sockfd_put(sock);
9a4c6ab7 23795@@ -1455,6 +1514,7 @@ asmlinkage long sys_connect(int fd, stru
89675291 23796 {
23797 struct socket *sock;
23798 char address[MAX_SOCK_ADDR];
23799+ struct sockaddr *sck;
23800 int err;
23801
23802 sock = sockfd_lookup(fd, &err);
9a4c6ab7 23803@@ -1464,6 +1524,18 @@ asmlinkage long sys_connect(int fd, stru
89675291 23804 if (err < 0)
23805 goto out_put;
23806
23807+ sck = (struct sockaddr *)address;
23808+
23809+ if (!gr_search_connect(sock, (struct sockaddr_in *)sck)) {
23810+ err = -EACCES;
23811+ goto out_put;
23812+ }
23813+
23814+ if (gr_handle_sock_client(sck)) {
23815+ err = -EACCES;
23816+ goto out_put;
23817+ }
23818+
23819 err = security_socket_connect(sock, (struct sockaddr *)address, addrlen);
23820 if (err)
23821 goto out_put;
9a4c6ab7 23822@@ -1717,6 +1789,7 @@ asmlinkage long sys_shutdown(int fd, int
89675291 23823 err=sock->ops->shutdown(sock, how);
23824 sockfd_put(sock);
23825 }
23826+
23827 return err;
23828 }
23829
23830diff -urNp linux-2.6.16.12/net/unix/af_unix.c linux-2.6.16.12/net/unix/af_unix.c
23831--- linux-2.6.16.12/net/unix/af_unix.c 2006-05-01 15:14:26.000000000 -0400
23832+++ linux-2.6.16.12/net/unix/af_unix.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 23833@@ -120,6 +120,7 @@
23834 #include <linux/vs_context.h>
23835 #include <linux/vs_network.h>
23836 #include <linux/vs_limit.h>
89675291 23837+#include <linux/grsecurity.h>
23838
23839 int sysctl_unix_max_dgram_qlen = 10;
23840
9a4c6ab7 23841@@ -685,6 +686,11 @@ static struct sock *unix_find_other(stru
89675291 23842 if (err)
23843 goto put_fail;
23844
23845+ if (!gr_acl_handle_unix(nd.dentry, nd.mnt)) {
23846+ err = -EACCES;
23847+ goto put_fail;
23848+ }
23849+
23850 err = -ECONNREFUSED;
23851 if (!S_ISSOCK(nd.dentry->d_inode->i_mode))
23852 goto put_fail;
9a4c6ab7 23853@@ -708,6 +714,13 @@ static struct sock *unix_find_other(stru
89675291 23854 if (u) {
23855 struct dentry *dentry;
23856 dentry = unix_sk(u)->dentry;
23857+
23858+ if (!gr_handle_chroot_unix(u->sk_peercred.pid)) {
23859+ err = -EPERM;
23860+ sock_put(u);
23861+ goto fail;
23862+ }
23863+
23864 if (dentry)
23865 touch_atime(unix_sk(u)->mnt, dentry);
23866 } else
9a4c6ab7 23867@@ -786,9 +799,18 @@ static int unix_bind(struct socket *sock
89675291 23868 */
23869 mode = S_IFSOCK |
23870 (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
23871+
23872+ if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) {
23873+ err = -EACCES;
23874+ goto out_mknod_dput;
23875+ }
23876+
9a4c6ab7 23877 err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0, NULL);
89675291 23878 if (err)
23879 goto out_mknod_dput;
23880+
23881+ gr_handle_create(dentry, nd.mnt);
23882+
23883 mutex_unlock(&nd.dentry->d_inode->i_mutex);
23884 dput(nd.dentry);
23885 nd.dentry = dentry;
9a4c6ab7 23886@@ -806,6 +828,10 @@ static int unix_bind(struct socket *sock
89675291 23887 goto out_unlock;
23888 }
23889
23890+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
23891+ sk->sk_peercred.pid = current->pid;
23892+#endif
23893+
23894 list = &unix_socket_table[addr->hash];
23895 } else {
23896 list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
23897diff -urNp linux-2.6.16.12/security/commoncap.c linux-2.6.16.12/security/commoncap.c
23898--- linux-2.6.16.12/security/commoncap.c 2006-05-01 15:14:26.000000000 -0400
23899+++ linux-2.6.16.12/security/commoncap.c 2006-05-01 20:17:34.000000000 -0400
23900@@ -24,6 +24,7 @@
23901 #include <linux/ptrace.h>
23902 #include <linux/xattr.h>
23903 #include <linux/hugetlb.h>
23904+#include <linux/grsecurity.h>
23905
23906 int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
23907 {
23908@@ -45,7 +46,15 @@ EXPORT_SYMBOL(cap_netlink_recv);
23909 int cap_capable (struct task_struct *tsk, int cap)
23910 {
23911 /* Derived from include/linux/sched.h:capable. */
9a4c6ab7 23912- if (vx_cap_raised(tsk->vx_info, tsk->cap_effective, cap))
23913+ if (vx_cap_raised(tsk->vx_info, tsk->cap_effective, cap) && gr_task_is_capable(tsk, cap))
89675291 23914+ return 0;
23915+ return -EPERM;
23916+}
23917+
23918+int cap_capable_nolog (struct task_struct *tsk, int cap)
23919+{
23920+ /* Derived from include/linux/sched.h:capable. */
9a4c6ab7 23921+ if (vx_cap_raised(tsk->vx_info, tsk->cap_effective, cap))
89675291 23922 return 0;
23923 return -EPERM;
23924 }
23925@@ -61,7 +70,7 @@ int cap_ptrace (struct task_struct *pare
23926 {
23927 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
23928 if (!cap_issubset (child->cap_permitted, current->cap_permitted) &&
23929- !capable(CAP_SYS_PTRACE))
23930+ !capable_nolog(CAP_SYS_PTRACE))
23931 return -EPERM;
23932 return 0;
23933 }
9a4c6ab7 23934@@ -165,8 +174,11 @@ void cap_bprm_apply_creds (struct linux_
89675291 23935 }
23936 }
23937
23938- current->suid = current->euid = current->fsuid = bprm->e_uid;
23939- current->sgid = current->egid = current->fsgid = bprm->e_gid;
23940+ if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid))
23941+ current->suid = current->euid = current->fsuid = bprm->e_uid;
23942+
23943+ if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid))
23944+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
23945
23946 /* For init, we want to retain the capabilities set
23947 * in the init_task struct. Thus we skip the usual
9a4c6ab7 23948@@ -177,6 +189,8 @@ void cap_bprm_apply_creds (struct linux_
89675291 23949 cap_intersect (new_permitted, bprm->cap_effective);
23950 }
23951
23952+ gr_handle_chroot_caps(current);
23953+
23954 /* AUD: Audit candidate if current->cap_effective is set */
23955
23956 current->keep_capabilities = 0;
9a4c6ab7 23957@@ -323,12 +337,13 @@ int cap_vm_enough_memory(long pages)
89675291 23958 {
23959 int cap_sys_admin = 0;
23960
23961- if (cap_capable(current, CAP_SYS_ADMIN) == 0)
23962+ if (cap_capable_nolog(current, CAP_SYS_ADMIN) == 0)
23963 cap_sys_admin = 1;
23964 return __vm_enough_memory(pages, cap_sys_admin);
23965 }
23966
23967 EXPORT_SYMBOL(cap_capable);
23968+EXPORT_SYMBOL(cap_capable_nolog);
23969 EXPORT_SYMBOL(cap_settime);
23970 EXPORT_SYMBOL(cap_ptrace);
23971 EXPORT_SYMBOL(cap_capget);
23972diff -urNp linux-2.6.16.12/security/dummy.c linux-2.6.16.12/security/dummy.c
23973--- linux-2.6.16.12/security/dummy.c 2006-05-01 15:14:26.000000000 -0400
23974+++ linux-2.6.16.12/security/dummy.c 2006-05-01 20:17:34.000000000 -0400
23975@@ -29,6 +29,7 @@
23976 #include <linux/hugetlb.h>
23977 #include <linux/ptrace.h>
23978 #include <linux/file.h>
23979+#include <linux/grsecurity.h>
23980
23981 static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
23982 {
23983@@ -139,8 +140,11 @@ static void dummy_bprm_apply_creds (stru
23984 }
23985 }
23986
23987- current->suid = current->euid = current->fsuid = bprm->e_uid;
23988- current->sgid = current->egid = current->fsgid = bprm->e_gid;
23989+ if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid))
23990+ current->suid = current->euid = current->fsuid = bprm->e_uid;
23991+
23992+ if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid))
23993+ current->sgid = current->egid = current->fsgid = bprm->e_gid;
23994
23995 dummy_capget(current, &current->cap_effective, &current->cap_inheritable, &current->cap_permitted);
23996 }
23997diff -urNp linux-2.6.16.12/security/Kconfig linux-2.6.16.12/security/Kconfig
23998--- linux-2.6.16.12/security/Kconfig 2006-05-01 15:14:26.000000000 -0400
23999+++ linux-2.6.16.12/security/Kconfig 2006-05-01 20:17:34.000000000 -0400
24000@@ -4,6 +4,408 @@
24001
24002 menu "Security options"
24003
24004+menu "PaX"
24005+
24006+config PAX
24007+ bool "Enable various PaX features"
24008+ depends on GRKERNSEC && (ALPHA || ARM || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || PPC64 || SPARC32 || SPARC64 || X86 || X86_64)
24009+ help
24010+ This allows you to enable various PaX features. PaX adds
24011+ intrusion prevention mechanisms to the kernel that reduce
24012+ the risks posed by exploitable memory corruption bugs.
24013+
24014+menu "PaX Control"
24015+ depends on PAX
24016+
24017+config PAX_SOFTMODE
24018+ bool 'Support soft mode'
24019+ help
24020+ Enabling this option will allow you to run PaX in soft mode, that
24021+ is, PaX features will not be enforced by default, only on executables
24022+ marked explicitly. You must also enable PT_PAX_FLAGS support as it
24023+ is the only way to mark executables for soft mode use.
24024+
24025+ Soft mode can be activated by using the "pax_softmode=1" kernel command
24026+ line option on boot. Furthermore you can control various PaX features
24027+ at runtime via the entries in /proc/sys/kernel/pax.
24028+
24029+config PAX_EI_PAX
24030+ bool 'Use legacy ELF header marking'
24031+ help
24032+ Enabling this option will allow you to control PaX features on
24033+ a per executable basis via the 'chpax' utility available at
24034+ http://pax.grsecurity.net/. The control flags will be read from
24035+ an otherwise reserved part of the ELF header. This marking has
24036+ numerous drawbacks (no support for soft-mode, toolchain does not
24037+ know about the non-standard use of the ELF header) therefore it
24038+ has been deprecated in favour of PT_PAX_FLAGS support.
24039+
24040+ If you have applications not marked by the PT_PAX_FLAGS ELF
24041+ program header then you MUST enable this option otherwise they
24042+ will not get any protection.
24043+
24044+ Note that if you enable PT_PAX_FLAGS marking support as well,
24045+ the PT_PAX_FLAG marks will override the legacy EI_PAX marks.
24046+
24047+config PAX_PT_PAX_FLAGS
24048+ bool 'Use ELF program header marking'
24049+ help
24050+ Enabling this option will allow you to control PaX features on
24051+ a per executable basis via the 'paxctl' utility available at
24052+ http://pax.grsecurity.net/. The control flags will be read from
24053+ a PaX specific ELF program header (PT_PAX_FLAGS). This marking
24054+ has the benefits of supporting both soft mode and being fully
24055+ integrated into the toolchain (the binutils patch is available
24056+ from http://pax.grsecurity.net).
24057+
24058+ If you have applications not marked by the PT_PAX_FLAGS ELF
24059+ program header then you MUST enable the EI_PAX marking support
24060+ otherwise they will not get any protection.
24061+
24062+ Note that if you enable the legacy EI_PAX marking support as well,
24063+ the EI_PAX marks will be overridden by the PT_PAX_FLAGS marks.
24064+
24065+choice
24066+ prompt 'MAC system integration'
24067+ default PAX_HAVE_ACL_FLAGS
24068+ help
24069+ Mandatory Access Control systems have the option of controlling
24070+ PaX flags on a per executable basis, choose the method supported
24071+ by your particular system.
24072+
24073+ - "none": if your MAC system does not interact with PaX,
24074+ - "direct": if your MAC system defines pax_set_flags() itself,
24075+ - "hook": if your MAC system uses the pax_set_flags_func callback.
24076+
24077+ NOTE: this option is for developers/integrators only.
24078+
24079+config PAX_NO_ACL_FLAGS
24080+ bool 'none'
24081+
24082+config PAX_HAVE_ACL_FLAGS
24083+ bool 'direct'
24084+
24085+config PAX_HOOK_ACL_FLAGS
24086+ bool 'hook'
24087+endchoice
24088+
24089+endmenu
24090+
24091+menu "Non-executable pages"
24092+ depends on PAX
24093+
24094+config PAX_NOEXEC
24095+ bool "Enforce non-executable pages"
24096+ 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)
24097+ help
24098+ By design some architectures do not allow for protecting memory
24099+ pages against execution or even if they do, Linux does not make
24100+ use of this feature. In practice this means that if a page is
24101+ readable (such as the stack or heap) it is also executable.
24102+
24103+ There is a well known exploit technique that makes use of this
24104+ fact and a common programming mistake where an attacker can
24105+ introduce code of his choice somewhere in the attacked program's
24106+ memory (typically the stack or the heap) and then execute it.
24107+
24108+ If the attacked program was running with different (typically
24109+ higher) privileges than that of the attacker, then he can elevate
24110+ his own privilege level (e.g. get a root shell, write to files for
24111+ which he does not have write access to, etc).
24112+
24113+ Enabling this option will let you choose from various features
24114+ that prevent the injection and execution of 'foreign' code in
24115+ a program.
24116+
24117+ This will also break programs that rely on the old behaviour and
24118+ expect that dynamically allocated memory via the malloc() family
24119+ of functions is executable (which it is not). Notable examples
24120+ are the XFree86 4.x server, the java runtime and wine.
24121+
24122+config PAX_PAGEEXEC
24123+ bool "Paging based non-executable pages"
24124+ depends on PAX_NOEXEC && (!X86_32 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MPENTIUM4 || MK7 || MK8 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MVIAC3_2)
24125+ select PAX_NOVSYSCALL if X86_32
24126+ help
24127+ This implementation is based on the paging feature of the CPU.
24128+ On i386 and ppc there is a variable but usually low performance
24129+ impact on applications. On alpha, ia64, parisc, sparc, sparc64
24130+ and x86_64 there is no performance impact.
24131+
24132+config PAX_SEGMEXEC
24133+ bool "Segmentation based non-executable pages"
24134+ depends on PAX_NOEXEC && X86_32
24135+ select PAX_NOVSYSCALL if X86_32
24136+ help
24137+ This implementation is based on the segmentation feature of the
24138+ CPU and has little performance impact, however applications will
24139+ be limited to a 1.5 GB address space instead of the normal 3 GB.
24140+
24141+choice
24142+ prompt "Default non-executable page method"
24143+ depends on PAX_PAGEEXEC && PAX_SEGMEXEC
24144+ default PAX_DEFAULT_SEGMEXEC
24145+ help
24146+ Select the default non-executable page method applied to applications
24147+ that do not select one themselves.
24148+
24149+config PAX_DEFAULT_PAGEEXEC
24150+ bool "PAGEEXEC"
24151+
24152+config PAX_DEFAULT_SEGMEXEC
24153+ bool "SEGMEXEC"
24154+endchoice
24155+
24156+config PAX_EMUTRAMP
24157+ bool "Emulate trampolines" if (PAX_PAGEEXEC || PAX_SEGMEXEC) && (PARISC || PPC32 || X86_32)
24158+ default y if PARISC || PPC32
24159+ help
24160+ There are some programs and libraries that for one reason or
24161+ another attempt to execute special small code snippets from
24162+ non-executable memory pages. Most notable examples are the
24163+ signal handler return code generated by the kernel itself and
24164+ the GCC trampolines.
24165+
24166+ If you enabled CONFIG_PAX_PAGEEXEC or CONFIG_PAX_SEGMEXEC then
24167+ such programs will no longer work under your kernel.
24168+
24169+ As a remedy you can say Y here and use the 'chpax' or 'paxctl'
24170+ utilities to enable trampoline emulation for the affected programs
24171+ yet still have the protection provided by the non-executable pages.
24172+
24173+ On parisc and ppc you MUST enable this option and EMUSIGRT as
24174+ well, otherwise your system will not even boot.
24175+
24176+ Alternatively you can say N here and use the 'chpax' or 'paxctl'
24177+ utilities to disable CONFIG_PAX_PAGEEXEC and CONFIG_PAX_SEGMEXEC
24178+ for the affected files.
24179+
24180+ NOTE: enabling this feature *may* open up a loophole in the
24181+ protection provided by non-executable pages that an attacker
24182+ could abuse. Therefore the best solution is to not have any
24183+ files on your system that would require this option. This can
24184+ be achieved by not using libc5 (which relies on the kernel
24185+ signal handler return code) and not using or rewriting programs
24186+ that make use of the nested function implementation of GCC.
24187+ Skilled users can just fix GCC itself so that it implements
24188+ nested function calls in a way that does not interfere with PaX.
24189+
24190+config PAX_EMUSIGRT
24191+ bool "Automatically emulate sigreturn trampolines"
24192+ depends on PAX_EMUTRAMP && (PARISC || PPC32)
24193+ default y
24194+ help
24195+ Enabling this option will have the kernel automatically detect
24196+ and emulate signal return trampolines executing on the stack
24197+ that would otherwise lead to task termination.
24198+
24199+ This solution is intended as a temporary one for users with
24200+ legacy versions of libc (libc5, glibc 2.0, uClibc before 0.9.17,
24201+ Modula-3 runtime, etc) or executables linked to such, basically
24202+ everything that does not specify its own SA_RESTORER function in
24203+ normal executable memory like glibc 2.1+ does.
24204+
24205+ On parisc and ppc you MUST enable this option, otherwise your
24206+ system will not even boot.
24207+
24208+ NOTE: this feature cannot be disabled on a per executable basis
24209+ and since it *does* open up a loophole in the protection provided
24210+ by non-executable pages, the best solution is to not have any
24211+ files on your system that would require this option.
24212+
24213+config PAX_MPROTECT
24214+ bool "Restrict mprotect()"
24215+ depends on (PAX_PAGEEXEC || PAX_SEGMEXEC) && !PPC64
24216+ help
24217+ Enabling this option will prevent programs from
24218+ - changing the executable status of memory pages that were
24219+ not originally created as executable,
24220+ - making read-only executable pages writable again,
24221+ - creating executable pages from anonymous memory.
24222+
24223+ You should say Y here to complete the protection provided by
24224+ the enforcement of non-executable pages.
24225+
24226+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control
24227+ this feature on a per file basis.
24228+
24229+config PAX_NOELFRELOCS
24230+ bool "Disallow ELF text relocations"
24231+ depends on PAX_MPROTECT && !PAX_ETEXECRELOCS && (IA64 || X86 || X86_64)
24232+ help
24233+ Non-executable pages and mprotect() restrictions are effective
24234+ in preventing the introduction of new executable code into an
24235+ attacked task's address space. There remain only two venues
24236+ for this kind of attack: if the attacker can execute already
24237+ existing code in the attacked task then he can either have it
24238+ create and mmap() a file containing his code or have it mmap()
24239+ an already existing ELF library that does not have position
24240+ independent code in it and use mprotect() on it to make it
24241+ writable and copy his code there. While protecting against
24242+ the former approach is beyond PaX, the latter can be prevented
24243+ by having only PIC ELF libraries on one's system (which do not
24244+ need to relocate their code). If you are sure this is your case,
24245+ then enable this option otherwise be careful as you may not even
24246+ be able to boot or log on your system (for example, some PAM
24247+ modules are erroneously compiled as non-PIC by default).
24248+
24249+ NOTE: if you are using dynamic ELF executables (as suggested
24250+ when using ASLR) then you must have made sure that you linked
24251+ your files using the PIC version of crt1 (the et_dyn.tar.gz package
24252+ referenced there has already been updated to support this).
24253+
24254+config PAX_ETEXECRELOCS
24255+ bool "Allow ELF ET_EXEC text relocations"
24256+ depends on PAX_MPROTECT && (ALPHA || IA64 || PARISC)
24257+ default y
24258+ help
24259+ On some architectures there are incorrectly created applications
24260+ that require text relocations and would not work without enabling
24261+ this option. If you are an alpha, ia64 or parisc user, you should
24262+ enable this option and disable it once you have made sure that
24263+ none of your applications need it.
24264+
24265+config PAX_EMUPLT
24266+ bool "Automatically emulate ELF PLT"
24267+ depends on PAX_MPROTECT && (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64)
24268+ default y
24269+ help
24270+ Enabling this option will have the kernel automatically detect
24271+ and emulate the Procedure Linkage Table entries in ELF files.
24272+ On some architectures such entries are in writable memory, and
24273+ become non-executable leading to task termination. Therefore
24274+ it is mandatory that you enable this option on alpha, parisc, ppc,
24275+ sparc and sparc64, otherwise your system would not even boot.
24276+
24277+ NOTE: this feature *does* open up a loophole in the protection
24278+ provided by the non-executable pages, therefore the proper
24279+ solution is to modify the toolchain to produce a PLT that does
24280+ not need to be writable.
24281+
24282+config PAX_DLRESOLVE
24283+ bool
24284+ depends on PAX_EMUPLT && (SPARC32 || SPARC64)
24285+ default y
24286+
24287+config PAX_SYSCALL
24288+ bool
24289+ depends on PAX_PAGEEXEC && PPC32
24290+ default y
24291+
24292+config PAX_KERNEXEC
24293+ bool "Enforce non-executable kernel pages"
24294+ depends on PAX_NOEXEC && X86_32 && !HOTPLUG_PCI_COMPAQ_NVRAM && !PCI_BIOS && !EFI && !DEBUG_RODATA
24295+ help
24296+ This is the kernel land equivalent of PAGEEXEC and MPROTECT,
24297+ that is, enabling this option will make it harder to inject
24298+ and execute 'foreign' code in kernel memory itself.
24299+
24300+endmenu
24301+
24302+menu "Address Space Layout Randomization"
24303+ depends on PAX
24304+
24305+config PAX_ASLR
24306+ bool "Address Space Layout Randomization"
24307+ depends on PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS
24308+ help
24309+ Many if not most exploit techniques rely on the knowledge of
24310+ certain addresses in the attacked program. The following options
24311+ will allow the kernel to apply a certain amount of randomization
24312+ to specific parts of the program thereby forcing an attacker to
24313+ guess them in most cases. Any failed guess will most likely crash
24314+ the attacked program which allows the kernel to detect such attempts
24315+ and react on them. PaX itself provides no reaction mechanisms,
24316+ instead it is strongly encouraged that you make use of Nergal's
24317+ segvguard (ftp://ftp.pl.openwall.com/misc/segvguard/) or grsecurity's
24318+ (http://www.grsecurity.net/) built-in crash detection features or
24319+ develop one yourself.
24320+
24321+ By saying Y here you can choose to randomize the following areas:
24322+ - top of the task's kernel stack
24323+ - top of the task's userland stack
24324+ - base address for mmap() requests that do not specify one
24325+ (this includes all libraries)
24326+ - base address of the main executable
24327+
24328+ It is strongly recommended to say Y here as address space layout
24329+ randomization has negligible impact on performance yet it provides
24330+ a very effective protection.
24331+
24332+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control
24333+ this feature on a per file basis.
24334+
24335+config PAX_RANDKSTACK
24336+ bool "Randomize kernel stack base"
24337+ depends on PAX_ASLR && X86_TSC && X86_32
24338+ help
24339+ By saying Y here the kernel will randomize every task's kernel
24340+ stack on every system call. This will not only force an attacker
24341+ to guess it but also prevent him from making use of possible
24342+ leaked information about it.
24343+
24344+ Since the kernel stack is a rather scarce resource, randomization
24345+ may cause unexpected stack overflows, therefore you should very
24346+ carefully test your system. Note that once enabled in the kernel
24347+ configuration, this feature cannot be disabled on a per file basis.
24348+
24349+config PAX_RANDUSTACK
24350+ bool "Randomize user stack base"
24351+ depends on PAX_ASLR
24352+ help
24353+ By saying Y here the kernel will randomize every task's userland
24354+ stack. The randomization is done in two steps where the second
24355+ one may apply a big amount of shift to the top of the stack and
24356+ cause problems for programs that want to use lots of memory (more
24357+ than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is).
24358+ For this reason the second step can be controlled by 'chpax' or
24359+ 'paxctl' on a per file basis.
24360+
24361+config PAX_RANDMMAP
24362+ bool "Randomize mmap() base"
24363+ depends on PAX_ASLR
24364+ help
24365+ By saying Y here the kernel will use a randomized base address for
24366+ mmap() requests that do not specify one themselves. As a result
24367+ all dynamically loaded libraries will appear at random addresses
24368+ and therefore be harder to exploit by a technique where an attacker
24369+ attempts to execute library code for his purposes (e.g. spawn a
24370+ shell from an exploited program that is running at an elevated
24371+ privilege level).
24372+
24373+ Furthermore, if a program is relinked as a dynamic ELF file, its
24374+ base address will be randomized as well, completing the full
24375+ randomization of the address space layout. Attacking such programs
24376+ becomes a guess game. You can find an example of doing this at
24377+ http://pax.grsecurity.net/et_dyn.tar.gz and practical samples at
24378+ http://www.grsecurity.net/grsec-gcc-specs.tar.gz .
24379+
24380+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control this
24381+ feature on a per file basis.
24382+
24383+config PAX_NOVSYSCALL
24384+ bool "Disable the vsyscall page"
24385+ depends on PAX_ASLR && X86_32
24386+ help
24387+ The Linux 2.6 kernel introduced a new feature that speeds up or
24388+ simplifies certain operations, such as system calls or returns
24389+ from signal handlers.
24390+
24391+ Unfortunately the implementation also gives a powerful instrument
24392+ into the hands of exploit writers: the so-called vsyscall page exists
24393+ in every task at the same fixed address and it contains machine code
24394+ that is very useful in performing the return-to-libc style attack.
24395+
24396+ Since this exploit technique cannot in general be protected against
24397+ via kernel solutions, this option will allow you to disable the use
24398+ of the vsyscall page and revert back to the old behaviour.
24399+
24400+endmenu
24401+
24402+endmenu
24403+
24404+source grsecurity/Kconfig
24405+
24406 config KEYS
24407 bool "Enable access key retention support"
24408 help
24409diff -urNp linux-2.6.16.12/security/security.c linux-2.6.16.12/security/security.c
24410--- linux-2.6.16.12/security/security.c 2006-05-01 15:14:26.000000000 -0400
24411+++ linux-2.6.16.12/security/security.c 2006-05-01 20:17:34.000000000 -0400
9a4c6ab7 24412@@ -204,4 +204,5 @@ EXPORT_SYMBOL_GPL(unregister_security);
89675291 24413 EXPORT_SYMBOL_GPL(mod_reg_security);
24414 EXPORT_SYMBOL_GPL(mod_unreg_security);
24415 EXPORT_SYMBOL(capable);
24416+EXPORT_SYMBOL(capable_nolog);
24417 EXPORT_SYMBOL(security_ops);
This page took 2.724106 seconds and 4 git commands to generate.