1 diff -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,
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;
12 for (i = 0; i < n; i++) {
13 diff -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? */
20 +#ifdef CONFIG_PAX_RANDMMAP
21 + if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
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
30 /* Next, try allocating at TASK_UNMAPPED_BASE. */
31 - addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE),
33 + addr = arch_get_unmapped_area_1 (PAGE_ALIGN(current->mm->mmap_base), len, limit);
35 if (addr != (unsigned long) -ENOMEM)
38 diff -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
42 #include <linux/slab.h>
43 #include <linux/security.h>
44 #include <linux/signal.h>
45 +#include <linux/grsecurity.h>
47 #include <asm/uaccess.h>
48 #include <asm/pgtable.h>
49 @@ -283,6 +284,9 @@ do_sys_ptrace(long request, long pid, lo
53 + if (gr_handle_ptrace(child, request))
56 if (request == PTRACE_ATTACH) {
57 ret = ptrace_attach(child);
59 diff -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
63 #include <linux/smp_lock.h>
64 #include <linux/interrupt.h>
65 #include <linux/module.h>
66 +#include <linux/binfmts.h>
68 #include <asm/system.h>
69 #include <asm/uaccess.h>
70 @@ -56,6 +57,124 @@ __load_new_mm_context(struct mm_struct *
74 +#ifdef CONFIG_PAX_PAGEEXEC
76 + * PaX: decide what to do with offenders (regs->pc = fault address)
78 + * returns 1 when task should be killed
79 + * 2 when patched PLT trampoline was detected
80 + * 3 when unpatched PLT trampoline was detected
82 +static int pax_handle_fetch_fault(struct pt_regs *regs)
85 +#ifdef CONFIG_PAX_EMUPLT
88 + do { /* PaX: patched PLT emulation #1 */
89 + unsigned int ldah, ldq, jmp;
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));
98 + if ((ldah & 0xFFFF0000U) == 0x277B0000U &&
99 + (ldq & 0xFFFF0000U) == 0xA77B0000U &&
100 + jmp == 0x6BFB0000U)
102 + unsigned long r27, addr;
103 + unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
104 + unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL;
106 + addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
107 + err = get_user(r27, (unsigned long*)addr);
117 + do { /* PaX: patched PLT emulation #2 */
118 + unsigned int ldah, lda, br;
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));
127 + if ((ldah & 0xFFFF0000U)== 0x277B0000U &&
128 + (lda & 0xFFFF0000U) == 0xA77B0000U &&
129 + (br & 0xFFE00000U) == 0xC3E00000U)
131 + unsigned long addr = br | 0xFFFFFFFFFFE00000UL;
132 + unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16;
133 + unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL;
135 + regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL);
136 + regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2);
141 + do { /* PaX: unpatched PLT emulation */
144 + err = get_user(br, (unsigned int *)regs->pc);
146 + if (!err && (br & 0xFFE00000U) == 0xC3800000U) {
147 + unsigned int br2, ldq, nop, jmp;
148 + unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver;
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));
160 + if (br2 == 0xC3600000U &&
161 + ldq == 0xA77B000CU &&
162 + nop == 0x47FF041FU &&
163 + jmp == 0x6B7B0000U)
165 + regs->r28 = regs->pc+4;
166 + regs->r27 = addr+16;
167 + regs->pc = resolver;
177 +void pax_report_insns(void *pc, void *sp)
181 + printk(KERN_ERR "PAX: bytes at PC: ");
182 + for (i = 0; i < 5; i++) {
184 + if (get_user(c, (unsigned int*)pc+i))
185 + printk("???????? ");
187 + printk("%08x ", c);
194 * This routine handles page faults. It determines the address,
195 @@ -133,8 +252,29 @@ do_page_fault(unsigned long address, uns
197 si_code = SEGV_ACCERR;
199 - if (!(vma->vm_flags & VM_EXEC))
200 + if (!(vma->vm_flags & VM_EXEC)) {
202 +#ifdef CONFIG_PAX_PAGEEXEC
203 + if (!(mm->pax_flags & MF_PAX_PAGEEXEC) || address != regs->pc)
206 + up_read(&mm->mmap_sem);
207 + switch(pax_handle_fetch_fault(regs)) {
209 +#ifdef CONFIG_PAX_EMUPLT
216 + pax_report_fault(regs, (void*)regs->pc, (void*)rdusp());
224 /* Allow reads even for write-only mappings */
225 if (!(vma->vm_flags & (VM_READ | VM_WRITE)))
226 diff -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
233 +#ifdef CONFIG_PAX_RANDMMAP
234 + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
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;
244 - start_addr = addr = TASK_UNMAPPED_BASE;
245 + start_addr = addr = mm->mmap_base;
246 mm->cached_hole_size = 0;
249 @@ -93,8 +97,8 @@ full_search:
250 * Start a new search - just in case we missed
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;
260 diff -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:
269 1: incl %eax # check that A20 really IS enabled
270 movl %eax,0x000000 # loop forever if it isn't
276 * Initialize eflags. Some BIOS's leave bits like NT set. This would
277 diff -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
280 @@ -963,7 +963,7 @@ endchoice
284 - depends on !X86_VISWS && PCI && (PCI_GOBIOS || PCI_GOANY)
285 + depends on !X86_VISWS && PCI && PCI_GOBIOS
289 diff -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
296 - depends on M586MMX || M586TSC || M586 || M486 || M386
297 + depends on (M586MMX || M586TSC || M586 || M486 || M386) && !PAX_KERNEXEC
300 config X86_WP_WORKS_OK
301 @@ -281,7 +281,7 @@ config X86_CMPXCHG64
303 config X86_ALIGNMENT_16
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
310 diff -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
316 bool "Write protect kernel read-only data structures"
317 - depends on DEBUG_KERNEL
318 + depends on DEBUG_KERNEL && 0
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
322 diff -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
326 #include <linux/dmi.h>
328 #include <asm/tlbflush.h>
329 +#include <asm/desc.h>
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
337 +#ifdef CONFIG_PAX_KERNEXEC
340 + pax_open_kernel(cr0);
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));
349 +#ifdef CONFIG_PAX_KERNEXEC
350 + pax_close_kernel(cr0);
356 @@ -55,7 +67,18 @@ int acpi_save_state_mem(void)
358 void acpi_restore_state_mem(void)
360 +#ifdef CONFIG_PAX_KERNEXEC
363 + pax_open_kernel(cr0);
368 +#ifdef CONFIG_PAX_KERNEXEC
369 + pax_close_kernel(cr0);
375 diff -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
380 profile_tick(CPU_PROFILING, regs);
382 - update_process_times(user_mode_vm(regs));
383 + update_process_times(user_mode(regs));
387 diff -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;
394 +#ifdef CONFIG_PAX_KERNEXEC
398 cpus = apm_save_cpus();
402 +#ifdef CONFIG_PAX_KERNEXEC
403 + pax_open_kernel(cr0);
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
411 local_irq_restore(flags);
412 gdt[0x40 / 8] = save_desc_40;
414 +#ifdef CONFIG_PAX_KERNEXEC
415 + pax_close_kernel(cr0);
419 apm_restore_cpus(cpus);
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;
425 +#ifdef CONFIG_PAX_KERNEXEC
429 cpus = apm_save_cpus();
433 +#ifdef CONFIG_PAX_KERNEXEC
434 + pax_open_kernel(cr0);
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,
442 local_irq_restore(flags);
443 gdt[0x40 / 8] = save_desc_40;
445 +#ifdef CONFIG_PAX_KERNEXEC
446 + pax_close_kernel(cr0);
450 apm_restore_cpus(cpus);
452 diff -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));
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));
462 diff -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
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>
477 -DEFINE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
478 -EXPORT_PER_CPU_SYMBOL(cpu_gdt_descr);
480 DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
481 EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack);
483 @@ -387,6 +383,10 @@ void __devinit identify_cpu(struct cpuin
484 if (this_cpu->c_init)
487 +#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_NOVSYSCALL)
488 + clear_bit(X86_FEATURE_SEP, c->x86_capability);
491 /* Disable the PN if appropriate */
492 squash_the_stupid_serial_number(c);
494 @@ -573,11 +573,10 @@ void __init early_cpu_init(void)
495 void __devinit cpu_init(void)
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 = ¤t->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);
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)
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
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);
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);
526 - local_irq_enable();
531 * Initialize the per-CPU GDT with the boot GDT,
532 * and set up the GDT descriptor:
534 - memcpy(gdt, cpu_gdt_table, GDT_SIZE);
536 + memcpy(gdt, cpu_gdt_table, GDT_SIZE);
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);
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;
549 - load_gdt(cpu_gdt_descr);
550 + load_gdt(&cpu_gdt_descr[cpu]);
551 load_idt(&idt_descr);
554 @@ -643,7 +624,7 @@ void __devinit cpu_init(void)
555 load_esp0(t, thread);
558 - load_LDT(&init_mm.context);
559 + _load_LDT(&init_mm.context);
561 #ifdef CONFIG_DOUBLEFAULT
562 /* Set up doublefault TSS pointer in the GDT */
563 diff -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
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)
573 #define ptr_ok(x) ((x) > PAGE_OFFSET && (x) < PAGE_OFFSET + 0x1000000)
575 diff -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
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];
585 -static void efi_call_phys_prelog(void)
586 +static void __init efi_call_phys_prelog(void)
589 - unsigned long temp;
590 - struct Xgt_desc_struct *cpu_gdt_descr;
592 spin_lock(&efi_rt_lock);
593 local_irq_save(efi_rt_eflags);
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];
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
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;
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;
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];
632 * After the lock is released, the original page table is restored.
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]));
643 -static void efi_call_phys_epilog(void)
644 +static void __init efi_call_phys_epilog(void)
647 - struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, 0);
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]);
656 + swapper_pg_dir[0] = efi_bak_pg_dir_pointer[0];
658 - if (cr4 & X86_CR4_PSE) {
659 - swapper_pg_dir[pgd_index(0)].pgd =
660 - efi_bak_pg_dir_pointer[0].pgd;
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;
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];
674 * After the lock is released, the original page table is restored.
679 local_irq_restore(efi_rt_eflags);
680 spin_unlock(&efi_rt_lock);
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
693 +static efi_status_t __init
694 phys_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
697 diff -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
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>
709 * service functions will comply with gcc calling convention, too.
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
722 - subl $__PAGE_OFFSET, %edx
724 + jmp 1f-__PAGE_OFFSET
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.
733 - movl %edx, saved_return_addr
734 - /* get the function pointer into ECX*/
736 - movl %ecx, efi_rt_function_ptr
738 - subl $__PAGE_OFFSET, %edx
740 + popl (saved_return_addr)
741 + popl (efi_rt_function_ptr)
744 * 3. Clear PG bit in %CR0.
745 @@ -75,9 +68,8 @@ ENTRY(efi_call_phys)
747 * 5. Call the physical function.
750 + call *(efi_rt_function_ptr-__PAGE_OFFSET)
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)
761 - orl $0x80000000, %edx
766 * 8. Now restore the virtual mode from flat mode by
767 * adding EIP with PAGE_OFFSET.
772 + orl $0x80000000, %edx
774 + jmp 1f+__PAGE_OFFSET
778 * 9. Balance the stack. And because EAX contain the return value,
779 * we'd better not clobber it.
781 - leal efi_rt_function_ptr, %edx
784 + pushl (efi_rt_function_ptr)
787 - * 10. Push the saved return address onto the stack and return.
788 + * 10. Return to the saved return address.
790 - leal saved_return_addr, %edx
794 + jmpl *(saved_return_addr)
802 diff -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
810 +#define __SAVE_ALL \
814 @@ -97,6 +97,18 @@ VM_MASK = 0x00020000
818 +#ifdef CONFIG_PAX_KERNEXEC
823 + orl $0x10000, %edx; \
827 +#define SAVE_ALL __SAVE_ALL
830 #define RESTORE_INT_REGS \
833 @@ -146,7 +158,19 @@ ret_from_intr:
834 movl EFLAGS(%esp), %eax # mix EFLAGS and CS
836 testl $(VM_MASK | 3), %eax
838 +#ifdef CONFIG_PAX_KERNEXEC
839 + jnz resume_userspace
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
858 +#ifdef CONFIG_PAX_RANDKSTACK
860 + call pax_randomize_kstack
864 /* if something modifies registers it must also disable sysexit */
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
871 +#ifdef CONFIG_PAX_RANDKSTACK
872 + call pax_randomize_kstack
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.
883 +.section .rodata,"a",@progbits
887 @@ -408,7 +443,7 @@ ENTRY(irq_entries_start)
892 +.section .rodata,"a",@progbits
896 @@ -459,6 +494,15 @@ error_code:
899 movl %esp,%eax # pt_regs pointer
901 +#ifdef CONFIG_PAX_KERNEXEC
910 jmp ret_from_exception
912 @@ -554,6 +598,13 @@ nmi_stack_correct:
913 xorl %edx,%edx # zero error code
914 movl %esp,%eax # pt_regs pointer
917 +#ifdef CONFIG_PAX_KERNEXEC
926 @@ -584,6 +635,13 @@ nmi_16bit_stack:
927 FIXUP_ESPFIX_STACK # %eax == %esp
928 xorl %edx,%edx # zero error code
931 +#ifdef CONFIG_PAX_KERNEXEC
938 lss 12+4(%esp), %esp # back to 16bit stack
940 @@ -659,7 +717,6 @@ ENTRY(spurious_interrupt_bug)
941 pushl $do_spurious_interrupt_bug
944 -.section .rodata,"a"
945 #include "syscall_table.S"
947 syscall_table_size=(.-sys_call_table)
948 diff -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
955 + * Real beginning of normal "text" segment
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)
968 +#ifdef CONFIG_PAX_KERNEXEC
969 + movl $ __KERNEL_TEXT_OFFSET,%eax
970 + movw %ax,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 2)
972 + movb %al,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 4)
973 + movb %ah,(cpu_gdt_table - __PAGE_OFFSET + __KERNEL_CS + 7)
975 + movb %al,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 4)
976 + movb %ah,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 7)
978 + movw %ax,(boot_gdt_table - __PAGE_OFFSET + __BOOT_CS + 2)
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...
988 -page_pde_offset = (__PAGE_OFFSET >> 20);
990 +#ifdef CONFIG_X86_PAE
991 +page_pde_offset = ((__PAGE_OFFSET >> 21) * (4096 / PTRS_PER_PTE_asm));
993 +page_pde_offset = ((__PAGE_OFFSET >> 22) * (4096 / PTRS_PER_PTE_asm));
995 movl $(pg0 - __PAGE_OFFSET), %edi
996 +#ifdef CONFIG_X86_PAE
997 + movl $(swapper_pm_dir - __PAGE_OFFSET), %edx
999 movl $(swapper_pg_dir - __PAGE_OFFSET), %edx
1000 - movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */
1002 + movl $0x063, %eax /* 0x063 = DIRTY+ACCESSED+PRESENT+RW */
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
1010 + movl $0,page_pde_offset+4(%edx)
1019 +#ifdef CONFIG_X86_PAE
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
1032 movl %edi,(init_pg_tables_end - __PAGE_OFFSET)
1033 @@ -154,6 +191,11 @@ ENTRY(startup_32_smp)
1037 + /* This is a secondary processor (AP) */
1040 +#endif /* CONFIG_SMP */
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..
1048 #define cr4_bits mmu_cr4_features-__PAGE_OFFSET
1054 movl %cr4,%eax # Turn on paging options (PSE,PAE,..)
1058 - btl $5, %eax # check if PAE is enabled
1060 +#ifdef CONFIG_X86_PAE
1063 /* Check if extended functions are implemented */
1064 movl $0x80000000, %eax
1066 cmpl $0x80000000, %eax
1069 mov $0x80000001, %eax
1071 /* Execute Disable bit supported? */
1076 /* Setup EFER (Extended Feature Enable Register) */
1077 movl $0xc0000080, %ecx
1078 @@ -197,14 +240,12 @@ ENTRY(startup_32_smp)
1080 /* Make changes effective */
1082 + btsl $63,__supported_pte_mask-__PAGE_OFFSET
1085 - /* This is a secondary processor (AP) */
1090 -#endif /* CONFIG_SMP */
1098 @@ -229,9 +270,7 @@ ENTRY(startup_32_smp)
1102 - jz 1f /* Initial CPU cleans BSS */
1105 + jnz checkCPUtype /* Initial CPU cleans BSS */
1106 #endif /* CONFIG_SMP */
1109 @@ -412,32 +451,50 @@ ignore_int:
1114 - * Real beginning of normal "text" segment
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
1128 + .long swapper_pm_dir+512*8-__PAGE_OFFSET+1
1130 + .long swapper_pm_dir+512*16-__PAGE_OFFSET+1
1132 + .long swapper_pm_dir+512*24-__PAGE_OFFSET+1
1138 +#ifdef CONFIG_X86_PAE
1139 +.section .swapper_pm_dir,"a",@progbits
1140 +ENTRY(swapper_pm_dir)
1147 +.section .empty_zero_page,"a",@progbits
1148 ENTRY(empty_zero_page)
1152 - * This starts the data section.
1155 + * The IDT has to be page-aligned to simplify the Pentium
1156 + * F0 0F bug workaround.. We have a special link segment
1159 +.section .idt,"a",@progbits
1163 +.section .rodata,"a",@progbits
1167 - .long init_thread_union+THREAD_SIZE
1168 + .long init_thread_union+THREAD_SIZE-8
1174 .asciz "Unknown interrupt or fault at EIP %p %p %p\n"
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 */
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 */
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 */
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.
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 */
1218 * The APM segments have byte granularity and their bases
1219 * are set at run time. All have 64k limits.
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 */
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 */
1236 + /* Be sure this is zeroed to avoid false validations in Xen */
1237 + .fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0
1240 + .fill (NR_CPUS-1) * (PAGE_SIZE_asm / 8),8,0 /* other CPU's GDT */
1242 diff -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
1246 #include <asm/checksum.h>
1247 #include <asm/desc.h>
1249 +EXPORT_SYMBOL_GPL(cpu_gdt_table);
1251 EXPORT_SYMBOL(__down_failed);
1252 EXPORT_SYMBOL(__down_failed_interruptible);
1253 EXPORT_SYMBOL(__down_failed_trylock);
1254 diff -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.
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 };
1264 diff -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
1268 #include <linux/stddef.h>
1269 #include <linux/slab.h>
1270 #include <linux/thread_info.h>
1271 +#include <linux/grsecurity.h>
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
1277 if ((from + num <= from) || (from + num > IO_BITMAP_BITS))
1279 +#ifdef CONFIG_GRKERNSEC_IO
1281 + gr_handle_ioperm();
1283 if (turn_on && !capable(CAP_SYS_RAWIO))
1287 +#ifdef CONFIG_GRKERNSEC_IO
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
1297 - tss = &per_cpu(init_tss, get_cpu());
1298 + tss = init_tss + get_cpu();
1300 set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
1302 @@ -142,8 +150,13 @@ asmlinkage long sys_iopl(unsigned long u
1304 /* Trying to gain more privileges? */
1306 +#ifdef CONFIG_GRKERNSEC_IO
1310 if (!capable(CAP_SYS_RAWIO))
1314 t->iopl = level << 12;
1315 regs->eflags = (regs->eflags & ~X86_EFLAGS_IOPL) | t->iopl;
1316 diff -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;
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;
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.
1331 static char softirq_stack[NR_CPUS * THREAD_SIZE]
1332 - __attribute__((__aligned__(THREAD_SIZE)));
1333 + __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
1335 static char hardirq_stack[NR_CPUS * THREAD_SIZE]
1336 - __attribute__((__aligned__(THREAD_SIZE)));
1337 + __attribute__((__aligned__(THREAD_SIZE), __section__(".bss.page_aligned")));
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;
1344 /* build the stack frame on the softirq stack */
1345 - isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
1346 + isp = (u32*) ((char*)irqctx + sizeof(*irqctx)) - 2;
1349 " xchgl %%ebx,%%esp \n"
1350 diff -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);
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;
1363 +#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
1364 + cpus_clear(mm->context.cpu_user_cs_mask);
1373 @@ -160,7 +173,7 @@ static int read_default_ldt(void __user
1378 + const void *address;
1381 address = &default_ldt[0];
1382 @@ -215,6 +228,13 @@ static int write_ldt(void __user * ptr,
1386 +#ifdef CONFIG_PAX_SEGMEXEC
1387 + if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (ldt_info.contents & MODIFY_LDT_CONTENTS_CODE)) {
1393 entry_1 = LDT_entry_a(&ldt_info);
1394 entry_2 = LDT_entry_b(&ldt_info);
1396 diff -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
1400 #include <linux/fs.h>
1401 #include <linux/string.h>
1402 #include <linux/kernel.h>
1403 +#include <asm/desc.h>
1406 #define DEBUGP printk
1407 @@ -32,9 +33,30 @@ void *module_alloc(unsigned long size)
1412 +#ifdef CONFIG_PAX_KERNEXEC
1413 + return vmalloc(size);
1415 return vmalloc_exec(size);
1420 +#ifdef CONFIG_PAX_KERNEXEC
1421 +void *module_alloc_exec(unsigned long size)
1423 + struct vm_struct *area;
1428 + area = __get_vm_area(size, 0, (unsigned long)&MODULES_VADDR, (unsigned long)&MODULES_END);
1430 + return area->addr;
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
1442 +#ifdef CONFIG_PAX_KERNEXEC
1443 +void module_free_exec(struct module *mod, void *module_region)
1445 + struct vm_struct **p, *tmp;
1447 + if (!module_region)
1450 + if ((PAGE_SIZE-1) & (unsigned long)module_region) {
1451 + printk(KERN_ERR "Trying to module_free_exec() bad address (%p)\n", module_region);
1456 + write_lock(&vmlist_lock);
1457 + for (p = &vmlist ; (tmp = *p) != NULL ;p = &tmp->next)
1458 + if (tmp->addr == module_region)
1462 + unsigned long cr0;
1464 + pax_open_kernel(cr0);
1465 + memset(tmp->addr, 0xCC, tmp->size);
1466 + pax_close_kernel(cr0);
1471 + write_unlock(&vmlist_lock);
1474 + printk(KERN_ERR "Trying to module_free_exec() nonexistent vm area (%p)\n",
1481 /* We don't need anything special. */
1482 int module_frob_arch_sections(Elf_Ehdr *hdr,
1484 @@ -62,14 +123,16 @@ int apply_relocate(Elf32_Shdr *sechdrs,
1486 Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
1488 - uint32_t *location;
1489 + uint32_t *plocation, location;
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)) {
1507 /* We add the value into the location given */
1508 - *location += sym->st_value;
1509 + *plocation += sym->st_value;
1512 /* Add the value, subtract its postition */
1513 - *location += sym->st_value - (uint32_t)location;
1514 + *plocation += sym->st_value - location;
1517 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
1518 diff -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
1521 @@ -374,7 +374,7 @@ void exit_thread(void)
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;
1528 kfree(t->io_bitmap_ptr);
1529 t->io_bitmap_ptr = NULL;
1530 @@ -394,6 +394,9 @@ void flush_thread(void)
1532 struct task_struct *tsk = current;
1534 + __asm__("mov %0,%%fs\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));
1540 @@ -426,7 +429,7 @@ int copy_thread(int nr, unsigned long cl
1541 struct task_struct *tsk;
1544 - childregs = task_pt_regs(p);
1545 + childregs = task_stack_page(p) + THREAD_SIZE - sizeof(struct pt_regs) - 8;
1548 childregs->esp = esp;
1549 @@ -469,6 +472,11 @@ int copy_thread(int nr, unsigned long cl
1550 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
1553 +#ifdef CONFIG_PAX_SEGMEXEC
1554 + if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
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);
1561 @@ -633,7 +641,11 @@ struct task_struct fastcall * __switch_t
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;
1568 +#ifdef CONFIG_PAX_KERNEXEC
1569 + unsigned long cr0;
1572 /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */
1574 @@ -656,11 +668,19 @@ struct task_struct fastcall * __switch_t
1575 savesegment(fs, prev->fs);
1576 savesegment(gs, prev->gs);
1578 +#ifdef CONFIG_PAX_KERNEXEC
1579 + pax_open_kernel(cr0);
1583 * Load the per-thread Thread-Local Storage descriptor.
1585 load_TLS(next, cpu);
1587 +#ifdef CONFIG_PAX_KERNEXEC
1588 + pax_close_kernel(cr0);
1592 * Restore %fs and %gs if needed.
1594 @@ -815,8 +835,18 @@ asmlinkage int sys_set_thread_area(struc
1595 struct desc_struct *desc;
1598 +#ifdef CONFIG_PAX_KERNEXEC
1599 + unsigned long cr0;
1602 if (copy_from_user(&info, u_info, sizeof(info)))
1605 +#ifdef CONFIG_PAX_SEGMEXEC
1606 + if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
1610 idx = info.entry_number;
1613 @@ -848,8 +878,17 @@ asmlinkage int sys_set_thread_area(struc
1614 desc->a = LDT_entry_a(&info);
1615 desc->b = LDT_entry_b(&info);
1618 +#ifdef CONFIG_PAX_KERNEXEC
1619 + pax_open_kernel(cr0);
1624 +#ifdef CONFIG_PAX_KERNEXEC
1625 + pax_close_kernel(cr0);
1631 @@ -905,9 +944,27 @@ asmlinkage int sys_get_thread_area(struc
1635 -unsigned long arch_align_stack(unsigned long sp)
1636 +#ifdef CONFIG_PAX_RANDKSTACK
1637 +asmlinkage void pax_randomize_kstack(void)
1639 - if (randomize_va_space)
1640 - sp -= get_random_int() % 8192;
1642 + struct tss_struct *tss = init_tss + smp_processor_id();
1643 + unsigned long time;
1645 + if (!randomize_va_space)
1650 + /* P4 seems to return a 0 LSB, ignore it */
1651 +#ifdef CONFIG_MPENTIUM4
1659 + tss->esp0 ^= time;
1660 + current->thread.esp0 = tss->esp0;
1663 diff -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
1667 #include <linux/audit.h>
1668 #include <linux/seccomp.h>
1669 #include <linux/signal.h>
1670 +#include <linux/grsecurity.h>
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)))
1678 +#ifdef CONFIG_PAX_SEGMEXEC
1679 + if ((child->mm->pax_flags & MF_PAX_SEGMEXEC) && (info.contents & MODIFY_LDT_CONTENTS_CODE))
1683 if (idx < GDT_ENTRY_TLS_MIN || idx > GDT_ENTRY_TLS_MAX)
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;
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))
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;
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;
1711 /* Send us the fakey SIGTRAP */
1712 force_sig_info(SIGTRAP, &info, tsk);
1713 diff -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. */
1720 -static unsigned long long
1721 +static const unsigned long long
1722 real_mode_gdt_entries [3] =
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 */
1733 unsigned short size __attribute__ ((packed));
1734 - unsigned long long * base __attribute__ ((packed));
1735 + const unsigned long long * base __attribute__ ((packed));
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
1741 unsigned long flags;
1743 +#ifdef CONFIG_PAX_KERNEXEC
1744 + unsigned long cr0;
1747 local_irq_disable();
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. */
1754 +#ifdef CONFIG_PAX_KERNEXEC
1755 + pax_open_kernel(cr0);
1758 memcpy (swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
1759 sizeof (swapper_pg_dir [0]) * KERNEL_PGD_PTRS);
1761 +#ifdef CONFIG_PAX_KERNEXEC
1762 + pax_close_kernel(cr0);
1766 * Use `swapper_pg_dir' as our page directory.
1768 diff -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
1773 #include "setup_arch_pre.h"
1774 #include <bios_ebda.h>
1775 +#include <asm/desc.h>
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);
1783 +#ifdef CONFIG_X86_PAE
1784 +unsigned long mmu_cr4_features = X86_CR4_PAE;
1786 unsigned long mmu_cr4_features;
1790 int acpi_disabled = 0;
1791 @@ -1444,12 +1449,22 @@ void apply_alternatives(void *start, voi
1792 struct alt_instr *a;
1794 unsigned char **noptable = intel_nops;
1796 +#ifdef CONFIG_PAX_KERNEXEC
1797 + unsigned long cr0;
1800 for (i = 0; noptypes[i].cpuid >= 0; i++) {
1801 if (boot_cpu_has(noptypes[i].cpuid)) {
1802 noptable = noptypes[i].noptable;
1807 +#ifdef CONFIG_PAX_KERNEXEC
1808 + pax_open_kernel(cr0);
1811 for (a = start; (void *)a < end; a++) {
1812 if (!boot_cpu_has(a->cpuid))
1814 @@ -1464,6 +1479,11 @@ void apply_alternatives(void *start, voi
1815 memcpy(a->instr + i, noptable[k], k);
1819 +#ifdef CONFIG_PAX_KERNEXEC
1820 + pax_close_kernel(cr0);
1825 void __init alternative_instructions(void)
1826 @@ -1542,14 +1562,14 @@ void __init setup_arch(char **cmdline_p)
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;
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;
1845 parse_cmdline_early(cmdline_p);
1846 diff -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
1853 +#ifdef CONFIG_PAX_NOVSYSCALL
1854 + restorer = frame->retcode;
1856 restorer = &__kernel_sigreturn;
1858 +#ifdef CONFIG_PAX_SEGMEXEC
1859 + if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
1860 + restorer -= SEGMEXEC_TASK_SIZE;
1864 if (ka->sa.sa_flags & SA_RESTORER)
1865 restorer = ka->sa.sa_restorer;
1867 @@ -446,7 +456,18 @@ static int setup_rt_frame(int sig, struc
1870 /* Set up to return from userspace. */
1872 +#ifdef CONFIG_PAX_NOVSYSCALL
1873 + restorer = frame->retcode;
1875 restorer = &__kernel_rt_sigreturn;
1877 +#ifdef CONFIG_PAX_SEGMEXEC
1878 + if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
1879 + restorer -= SEGMEXEC_TASK_SIZE;
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
1890 - if (!user_mode(regs))
1891 + if (!user_mode_novm(regs))
1894 if (try_to_freeze())
1895 diff -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
1899 +.section .rodata,"a",@progbits
1900 ENTRY(sys_call_table)
1901 .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
1903 diff -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)
1909 int cpu = get_cpu();
1910 - struct tss_struct *tss = &per_cpu(init_tss, cpu);
1911 + struct tss_struct *tss = init_tss + cpu;
1913 if (!boot_cpu_has(X86_FEATURE_SEP)) {
1915 @@ -48,6 +48,7 @@ extern const char vsyscall_sysenter_star
1917 int __init sysenter_setup(void)
1919 +#ifndef CONFIG_PAX_NOVSYSCALL
1920 void *page = (void *)get_zeroed_page(GFP_ATOMIC);
1922 __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY_EXEC);
1923 @@ -62,6 +63,7 @@ int __init sysenter_setup(void)
1925 &vsyscall_sysenter_start,
1926 &vsyscall_sysenter_end - &vsyscall_sysenter_start);
1931 diff -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
1934 @@ -106,6 +106,191 @@ out:
1939 +arch_get_unmapped_area(struct file *filp, unsigned long addr,
1940 + unsigned long len, unsigned long pgoff, unsigned long flags)
1942 + struct mm_struct *mm = current->mm;
1943 + struct vm_area_struct *vma;
1944 + unsigned long start_addr, task_size = TASK_SIZE;
1946 +#ifdef CONFIG_PAX_SEGMEXEC
1947 + if (mm->pax_flags & MF_PAX_SEGMEXEC)
1948 + task_size = SEGMEXEC_TASK_SIZE;
1951 + if (len > task_size)
1954 +#ifdef CONFIG_PAX_RANDMMAP
1955 + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
1959 + addr = PAGE_ALIGN(addr);
1960 + vma = find_vma(mm, addr);
1961 + if (task_size - len >= addr &&
1962 + (!vma || addr + len <= vma->vm_start))
1965 + if (len > mm->cached_hole_size) {
1966 + start_addr = addr = mm->free_area_cache;
1968 + start_addr = addr = mm->mmap_base;
1969 + mm->cached_hole_size = 0;
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;
1976 +#ifdef CONFIG_PAX_RANDMMAP
1977 + if (mm->pax_flags & MF_PAX_RANDMMAP)
1978 + start_addr += mm->delta_mmap & 0x03FFFFFFUL;
1981 + if (mm->start_brk <= start_addr && start_addr < mm->mmap_base)
1982 + start_addr = addr = mm->mmap_base;
1984 + addr = start_addr;
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) {
1993 + * Start a new search - just in case we missed
1996 + if (start_addr != mm->mmap_base) {
1997 + start_addr = addr = mm->mmap_base;
1998 + mm->cached_hole_size = 0;
2003 + if (!vma || addr + len <= vma->vm_start) {
2005 + * Remember the place where we stopped the search:
2007 + mm->free_area_cache = addr + len;
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;
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)
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;
2029 +#ifdef CONFIG_PAX_SEGMEXEC
2030 + if (mm->pax_flags & MF_PAX_SEGMEXEC)
2031 + task_size = SEGMEXEC_TASK_SIZE;
2034 + /* requested length too big for entire address space */
2035 + if (len > task_size)
2038 +#ifdef CONFIG_PAX_PAGEEXEC
2039 + if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & MAP_EXECUTABLE))
2043 +#ifdef CONFIG_PAX_RANDMMAP
2044 + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
2047 + /* requesting a specific address */
2049 + addr = PAGE_ALIGN(addr);
2050 + vma = find_vma(mm, addr);
2051 + if (task_size - len >= addr &&
2052 + (!vma || addr + len <= vma->vm_start))
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;
2062 + /* either no address requested or can't fit in requested address hole */
2063 + addr = mm->free_area_cache;
2065 + /* make sure it can fit in the remaining address space */
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);
2073 + if (mm->mmap_base < len)
2076 + addr = mm->mmap_base-len;
2080 + * Lookup failure means no vma is above this address,
2081 + * else if new region fits below vma->vm_start,
2082 + * return with success:
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);
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;
2093 + /* try just below the current vma->vm_start */
2094 + addr = vma->vm_start-len;
2095 + } while (len < vma->vm_start);
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()
2104 + mm->mmap_base = TASK_UNMAPPED_BASE;
2106 +#ifdef CONFIG_PAX_RANDMMAP
2107 + if (mm->pax_flags & MF_PAX_RANDMMAP)
2108 + mm->mmap_base += mm->delta_mmap;
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);
2115 + * Restore the topdown base:
2117 + mm->mmap_base = base;
2118 + mm->free_area_cache = base;
2119 + mm->cached_hole_size = ~0UL;
2124 struct sel_arg_struct {
2126 diff -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
2130 #include <linux/utsname.h>
2131 #include <linux/kprobes.h>
2132 #include <linux/kexec.h>
2133 +#include <linux/binfmts.h>
2136 #include <linux/ioport.h>
2139 asmlinkage int system_call(void);
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 } };
2145 /* Do we ignore FPU interrupts ? */
2146 char ignore_fpu_irq = 0;
2149 - * The IDT has to be page-aligned to simplify the Pentium
2150 - * F0 0F bug workaround.. We have a special link segment
2153 -struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, };
2154 +extern struct desc_struct idt_table[256];
2156 asmlinkage void divide_error(void);
2157 asmlinkage void debug(void);
2158 @@ -125,18 +121,22 @@ static inline unsigned long print_contex
2162 + int i = kstack_depth_to_print;
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;
2172 while (valid_stack_ptr(tinfo, stack)) {
2174 - if (__kernel_text_address(addr))
2175 + if (__kernel_text_address(addr)) {
2176 print_addr_and_symbol(addr, log_lvl);
2182 @@ -266,7 +266,7 @@ void show_registers(struct pt_regs *regs
2184 printk(KERN_EMERG "Code: ");
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++) {
2191 @@ -274,7 +274,7 @@ void show_registers(struct pt_regs *regs
2192 printk(" Bad EIP value.");
2195 - if (eip == (u8 __user *)regs->eip)
2196 + if (eip == (u8 __user *)regs->eip + __KERNEL_TEXT_OFFSET)
2197 printk("<%02x> ", c);
2200 @@ -291,7 +291,7 @@ static void handle_BUG(struct pt_regs *r
2205 + eip = regs->eip + __KERNEL_TEXT_OFFSET;
2207 if (eip < PAGE_OFFSET)
2209 @@ -390,7 +390,7 @@ void die(const char * str, struct pt_reg
2211 static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
2213 - if (!user_mode_vm(regs))
2214 + if (!user_mode(regs))
2215 die(str, regs, err);
2218 @@ -408,7 +408,7 @@ static void __kprobes do_trap(int trapnr
2222 - if (!user_mode(regs))
2223 + if (!user_mode_novm(regs))
2227 @@ -496,7 +496,7 @@ fastcall void __kprobes do_general_prote
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 = ¤t->thread;
2236 @@ -532,9 +532,25 @@ fastcall void __kprobes do_general_prote
2237 if (regs->eflags & VM_MASK)
2240 - if (!user_mode(regs))
2241 + if (!user_mode_novm(regs))
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;
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);
2256 + up_write(&mm->mmap_sem);
2260 current->thread.error_code = error_code;
2261 current->thread.trap_no = 13;
2262 force_sig(SIGSEGV, current);
2263 @@ -550,6 +566,13 @@ gp_in_kernel:
2264 if (notify_die(DIE_GPF, "general protection fault", regs,
2265 error_code, 13, SIGSEGV) == NOTIFY_STOP)
2268 +#ifdef CONFIG_PAX_KERNEXEC
2269 + if ((regs->xcs & 0xFFFF) == __KERNEL_CS)
2270 + die("PAX: suspicious general protection fault", regs, error_code);
2274 die("general protection fault", regs, error_code);
2277 @@ -775,7 +798,7 @@ fastcall void __kprobes do_debug(struct
2278 * check for kernel mode by just checking the CPL
2281 - if (!user_mode(regs))
2282 + if (!user_mode_novm(regs))
2283 goto clear_TF_reenable;
2286 @@ -1065,7 +1088,19 @@ do { \
2288 void set_intr_gate(unsigned int n, void *addr)
2291 +#ifdef CONFIG_PAX_KERNEXEC
2292 + unsigned long cr0;
2294 + pax_open_kernel(cr0);
2297 _set_gate(idt_table+n,14,0,addr,__KERNEL_CS);
2299 +#ifdef CONFIG_PAX_KERNEXEC
2300 + pax_close_kernel(cr0);
2306 diff -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
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, ¤t->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);
2322 - tss = &per_cpu(init_tss, get_cpu());
2323 + tss = init_tss + get_cpu();
2324 tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0;
2326 tsk->thread.sysenter_cs = 0;
2327 diff -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
2332 #define LOAD_OFFSET __PAGE_OFFSET
2334 +#include <linux/config.h>
2336 #include <asm-generic/vmlinux.lds.h>
2337 #include <asm/thread_info.h>
2338 #include <asm/page.h>
2339 +#include <asm/segment.h>
2341 +#ifdef CONFIG_X86_PAE
2342 +#define PMD_SHIFT 21
2344 +#define PMD_SHIFT 22
2347 OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
2349 @@ -15,67 +24,17 @@ jiffies = jiffies_64;
2353 - phys_startup_32 = startup_32 - LOAD_OFFSET;
2355 - _text = .; /* Text and read-only data */
2356 - .text : AT(ADDR(.text) - LOAD_OFFSET) {
2365 - _etext = .; /* End of text section */
2367 - . = ALIGN(16); /* Exception table */
2368 - __start___ex_table = .;
2369 - __ex_table : AT(ADDR(__ex_table) - LOAD_OFFSET) { *(__ex_table) }
2370 - __stop___ex_table = .;
2373 + phys_startup_32 = startup_32 - LOAD_OFFSET + __KERNEL_TEXT_OFFSET;
2376 - .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
2379 + .text.startup : AT(ADDR(.text.startup) - LOAD_OFFSET) {
2380 + BYTE(0xEA) /* jmp far */
2381 + LONG(phys_startup_32)
2386 - __nosave_begin = .;
2387 - .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
2392 - .data.page_aligned : AT(ADDR(.data.page_aligned) - LOAD_OFFSET) {
2397 - .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
2398 - *(.data.cacheline_aligned)
2401 - /* rarely changed data like cpu maps */
2403 - .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
2404 - _edata = .; /* End of data section */
2406 - . = ALIGN(THREAD_SIZE); /* init_task */
2407 - .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
2408 - *(.data.init_task)
2411 /* will be freed after init */
2412 . = ALIGN(4096); /* Init code and data */
2414 - .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) {
2419 .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) { *(.init.data) }
2422 @@ -107,9 +66,7 @@ SECTIONS
2423 .altinstr_replacement : AT(ADDR(.altinstr_replacement) - LOAD_OFFSET) {
2424 *(.altinstr_replacement)
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) }
2430 .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) }
2432 __initramfs_start = .;
2433 @@ -119,10 +76,108 @@ SECTIONS
2434 __per_cpu_start = .;
2435 .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) }
2442 + .init.text (. - __KERNEL_TEXT_OFFSET) : AT(ADDR(.init.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
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) }
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;
2461 + __init_end = . + __KERNEL_TEXT_OFFSET;
2462 /* freed after init ends here */
2465 + _text = .; /* Text and read-only data */
2466 + .text : AT(ADDR(.text) - LOAD_OFFSET + __KERNEL_TEXT_OFFSET) {
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 = .;
2483 + .rodata.page_aligned : AT(ADDR(.rodata.page_aligned) - LOAD_OFFSET) {
2484 + *(.empty_zero_page)
2486 +#ifdef CONFIG_X86_PAE
2487 + *(.swapper_pm_dir)
2490 + *(.swapper_pg_dir)
2496 +#ifdef CONFIG_PAX_KERNEXEC
2498 + MODULES_VADDR = .;
2500 + .module.text : AT(ADDR(.module.text) - LOAD_OFFSET) {
2501 + . += (4 * 1024 * 1024);
2502 + . = ALIGN(1 << PMD_SHIFT) - 1;
2512 + .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */
2519 + __nosave_begin = .;
2520 + .data_nosave : AT(ADDR(.data_nosave) - LOAD_OFFSET) { *(.data.nosave) }
2525 + .data.cacheline_aligned : AT(ADDR(.data.cacheline_aligned) - LOAD_OFFSET) {
2526 + *(.data.cacheline_aligned)
2529 + /* rarely changed data like cpu maps */
2531 + .data.read_mostly : AT(ADDR(.data.read_mostly) - LOAD_OFFSET) { *(.data.read_mostly) }
2533 + . = ALIGN(THREAD_SIZE); /* init_task */
2534 + .data.init_task : AT(ADDR(.data.init_task) - LOAD_OFFSET) {
2535 + *(.data.init_task)
2538 + _edata = .; /* End of data section */
2541 __bss_start = .; /* BSS */
2542 .bss.page_aligned : AT(ADDR(.bss.page_aligned) - LOAD_OFFSET) {
2543 *(.bss.page_aligned)
2544 diff -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);
2551 - update_process_times(user_mode_vm(regs));
2552 + update_process_times(user_mode(regs));
2555 if( ((1<<cpu) & voyager_extended_vic_processors) == 0)
2556 diff -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
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.
2567 - * boot_pte_t is defined only if this all works correctly
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>
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
2584 -#define BOOT_PTE_PTRS (PTRS_PER_PTE*2)
2585 -#define boot_pte_index(address) \
2586 - (((address) >> PAGE_SHIFT) & (BOOT_PTE_PTRS - 1))
2588 -static inline boot_pte_t* boot_vaddr_to_pte(void *address)
2590 - boot_pte_t* boot_pg = (boot_pte_t*)pg0;
2591 - return &boot_pg[boot_pte_index((unsigned long)address)];
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
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)
2606 - char *vaddr = virtual_source;
2612 + unsigned long vaddr = (unsigned long)virtual_source;
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);
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]);
2627 diff -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;
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)))
2637 extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
2638 extern u32 pnp_bios_is_utter_crap;
2639 diff -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
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>
2650 #include <asm/system.h>
2651 #include <asm/uaccess.h>
2652 @@ -82,11 +85,13 @@ static inline unsigned long get_segment_
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);
2659 /* By far the most common cases. */
2660 - if (likely(seg == __USER_CS || seg == __KERNEL_CS))
2661 + if (likely(seg == __USER_CS))
2663 + if (likely(seg == __KERNEL_CS))
2664 + return eip + __KERNEL_TEXT_OFFSET;
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);
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);
2677 @@ -214,6 +219,30 @@ static noinline void force_sig_info_faul
2679 fastcall void do_invalid_op(struct pt_regs *, unsigned long);
2681 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
2682 +static int pax_handle_fetch_fault(struct pt_regs *regs);
2685 +#ifdef CONFIG_PAX_PAGEEXEC
2686 +static inline pmd_t * pax_get_pmd(struct mm_struct *mm, unsigned long address)
2692 + pgd = pgd_offset(mm, address);
2693 + if (!pgd_present(*pgd))
2695 + pud = pud_offset(pgd, address);
2696 + if (!pud_present(*pud))
2698 + pmd = pmd_offset(pud, address);
2699 + if (!pmd_present(*pmd))
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;
2715 +#ifdef CONFIG_PAX_PAGEEXEC
2719 + unsigned char pte_mask;
2722 /* get the address */
2723 address = read_cr2();
2725 @@ -245,6 +280,7 @@ fastcall void __kprobes do_page_fault(st
2731 si_code = SEGV_MAPERR;
2733 @@ -271,14 +307,12 @@ fastcall void __kprobes do_page_fault(st
2734 goto bad_area_nosemaphore;
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..
2743 if (in_atomic() || !mm)
2744 - goto bad_area_nosemaphore;
2745 + goto bad_area_nopax;
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);
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;
2764 + /* PaX: it's our fault, let's handle it if we can */
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)) {
2772 +#ifdef CONFIG_PAX_EMUTRAMP
2778 + pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
2782 + pmd = pax_get_pmd(mm, address);
2783 + if (unlikely(!pmd))
2784 + goto not_pax_fault;
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;
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;
2799 + if (likely(address > get_limit(regs->xcs) && cpu_isset(smp_processor_id(), mm->context.cpu_user_cs_mask)))
2801 + if (likely(address > get_limit(regs->xcs)))
2804 + set_pte(pte, pte_mkread(*pte));
2805 + __flush_tlb_one(address);
2806 + pte_unmap_unlock(pte, ptl);
2807 + up_read(&mm->mmap_sem);
2811 + pte_mask = _PAGE_ACCESSED | _PAGE_USER | ((error_code & 2) << (_PAGE_BIT_DIRTY-1));
2814 + * PaX: fill DTLB with user rights and retry
2816 + __asm__ __volatile__ (
2818 +#if defined(CONFIG_M586) || defined(CONFIG_M586TSC)
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.
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.
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);
2846 vma = find_vma(mm, address);
2849 @@ -387,6 +509,37 @@ bad_area:
2850 up_read(&mm->mmap_sem);
2852 bad_area_nosemaphore:
2854 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
2855 + if (mm && (error_code & 4) && !(regs->eflags & X86_EFLAGS_VM)) {
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);
2864 +#ifdef CONFIG_PAX_SEGMEXEC
2865 + if ((mm->pax_flags & MF_PAX_SEGMEXEC) && !(error_code & 3) && (regs->eip + SEGMEXEC_TASK_SIZE == address)) {
2867 + switch (pax_handle_fetch_fault(regs)) {
2869 +#ifdef CONFIG_PAX_EMUTRAMP
2875 + pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp);
2884 /* User mode accesses just cause a SIGSEGV */
2885 if (error_code & 4) {
2887 @@ -450,28 +603,53 @@ no_context:
2889 if (address < PAGE_SIZE)
2890 printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
2892 +#ifdef CONFIG_PAX_KERNEXEC
2893 +#ifdef CONFIG_MODULES
2894 + else if (init_mm.start_code <= address && address < (unsigned long)MODULES_END)
2896 + else if (init_mm.start_code <= address && address < init_mm.end_code)
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);
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);
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);
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.
2921 + unsigned long index = pgd_index(address);
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));
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.
2939 #ifndef CONFIG_HIGHPTE
2941 - page &= PAGE_MASK;
2942 - address &= 0x003ff000;
2943 - page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
2944 - printk(KERN_ALERT "*pte = %08lx\n", page);
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));
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..
2960 - int index = pgd_index(address);
2961 + unsigned long index = pgd_index(address);
2962 unsigned long pgd_paddr;
2965 @@ -558,3 +736,105 @@ vmalloc_fault:
2970 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
2972 + * PaX: decide what to do with offenders (regs->eip = fault address)
2974 + * returns 1 when task should be killed
2975 + * 2 when gcc trampoline was detected
2977 +static int pax_handle_fetch_fault(struct pt_regs *regs)
2980 +#ifdef CONFIG_PAX_EMUTRAMP
2981 + static const unsigned char trans[8] = {6, 1, 2, 0, 13, 5, 3, 4};
2985 + if (regs->eflags & X86_EFLAGS_VM)
2988 +#ifdef CONFIG_PAX_EMUTRAMP
2989 + if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
2992 + do { /* PaX: gcc trampoline emulation #1 */
2993 + unsigned char mov1, mov2;
2994 + unsigned short jmp;
2995 + unsigned long addr1, addr2;
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));
3006 + if ((mov1 & 0xF8) == 0xB8 &&
3007 + (mov2 & 0xF8) == 0xB8 &&
3008 + (mov1 & 0x07) != (mov2 & 0x07) &&
3009 + (jmp & 0xF8FF) == 0xE0FF &&
3010 + (mov2 & 0x07) == ((jmp>>8) & 0x07))
3012 + ((unsigned long *)regs)[trans[mov1 & 0x07]] = addr1;
3013 + ((unsigned long *)regs)[trans[mov2 & 0x07]] = addr2;
3014 + regs->eip = addr2;
3019 + do { /* PaX: gcc trampoline emulation #2 */
3020 + unsigned char mov, jmp;
3021 + unsigned long addr1, addr2;
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));
3031 + if ((mov & 0xF8) == 0xB8 &&
3034 + ((unsigned long *)regs)[trans[mov & 0x07]] = addr1;
3035 + regs->eip += addr2 + 10;
3041 + return 1; /* PaX in action */
3045 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
3046 +void pax_report_insns(void *pc, void *sp)
3050 + printk(KERN_ERR "PAX: bytes at PC: ");
3051 + for (i = 0; i < 20; i++) {
3053 + if (get_user(c, (unsigned char __user *)pc+i))
3056 + printk("%02x ", c);
3060 + printk(KERN_ERR "PAX: bytes at SP-4: ");
3061 + for (i = -1; i < 20; i++) {
3063 + if (get_user(c, (unsigned long __user *)sp+i))
3064 + printk("???????? ");
3066 + printk("%08lx ", c);
3071 diff -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
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;
3081 +#ifdef CONFIG_PAX_SEGMEXEC
3082 + if (mm->pax_flags & MF_PAX_SEGMEXEC)
3083 + task_size = SEGMEXEC_TASK_SIZE;
3086 if (len > mm->cached_hole_size) {
3087 start_addr = mm->free_area_cache;
3088 @@ -147,7 +152,7 @@ full_search:
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) {
3095 * Start a new search - just in case we missed
3097 @@ -175,9 +180,8 @@ static unsigned long hugetlb_get_unmappe
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;
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
3110 mm->free_area_cache = base;
3114 /* make sure it can fit in the remaining address space */
3115 if (mm->free_area_cache < len)
3117 @@ -229,16 +233,6 @@ try_again:
3121 - * if hint left us with no space for the requested
3122 - * mapping then try again:
3125 - mm->free_area_cache = base;
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
3136 struct mm_struct *mm = current->mm;
3137 struct vm_area_struct *vma;
3138 + unsigned long task_size = TASK_SIZE;
3140 if (len & ~HPAGE_MASK)
3142 - if (len > TASK_SIZE)
3144 +#ifdef CONFIG_PAX_SEGMEXEC
3145 + if (mm->pax_flags & MF_PAX_SEGMEXEC)
3146 + task_size = SEGMEXEC_TASK_SIZE;
3149 + if (len > task_size || addr > task_size - len)
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))
3160 diff -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
3164 #include <asm/tlb.h>
3165 #include <asm/tlbflush.h>
3166 #include <asm/sections.h>
3167 +#include <asm/desc.h>
3169 unsigned int __VMALLOC_RESERVE = 128 << 20;
3171 @@ -50,30 +51,6 @@ unsigned long highstart_pfn, highend_pfn
3172 static int noinline do_test_wp_bit(void);
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.
3179 -static pmd_t * __init one_md_table_init(pgd_t *pgd)
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))
3191 - pud = pud_offset(pgd, 0);
3192 - pmd_table = pmd_offset(pud, 0);
3199 * Create a page table and place a pointer to it in a middle page
3202 @@ -81,7 +58,11 @@ static pte_t * __init one_page_table_ini
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));
3209 set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_TABLE));
3211 if (page_table != pte_offset_kernel(pmd, 0))
3214 @@ -116,8 +97,6 @@ static void __init page_table_range_init
3215 pgd = pgd_base + pgd_idx;
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++) {
3223 @@ -130,11 +109,22 @@ static void __init page_table_range_init
3227 -static inline int is_kernel_text(unsigned long addr)
3228 +static inline int is_kernel_text(unsigned long start, unsigned long end)
3230 - if (addr >= PAGE_OFFSET && addr <= (unsigned long)__init_end)
3233 + unsigned long etext;
3235 +#if defined(CONFIG_MODULES) && defined(CONFIG_PAX_KERNEXEC)
3236 + etext = (unsigned long)&MODULES_END - __KERNEL_TEXT_OFFSET;
3238 + etext = (unsigned long)&_etext;
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))
3250 @@ -146,26 +136,24 @@ static void __init kernel_physical_mappi
3257 - int pgd_idx, pmd_idx, pte_ofs;
3258 + unsigned int pgd_idx, pmd_idx, pte_ofs;
3260 pgd_idx = pgd_index(PAGE_OFFSET);
3261 pgd = pgd_base + pgd_idx;
3264 - for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
3265 - pmd = one_md_table_init(pgd);
3266 - if (pfn >= max_low_pfn)
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;
3275 /* Map with big pages if possible, otherwise create normal page tables. */
3277 - unsigned int address2 = (pfn + PTRS_PER_PTE - 1) * PAGE_SIZE + PAGE_OFFSET + PAGE_SIZE-1;
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));
3283 set_pmd(pmd, pfn_pmd(pfn, PAGE_KERNEL_LARGE));
3284 @@ -174,7 +162,7 @@ static void __init kernel_physical_mappi
3285 pte = one_page_table_init(pmd);
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));
3292 set_pte(pte, pfn_pte(pfn, PAGE_KERNEL));
3293 @@ -341,13 +329,6 @@ static void __init pagetable_init (void)
3294 unsigned long vaddr;
3295 pgd_t *pgd_base = swapper_pg_dir;
3297 -#ifdef CONFIG_X86_PAE
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));
3304 /* Enable PSE if available */
3306 set_in_cr4(X86_CR4_PSE);
3307 @@ -371,17 +352,6 @@ static void __init pagetable_init (void)
3308 page_table_range_init(vaddr, 0, pgd_base);
3310 permanent_kmaps_init(pgd_base);
3312 -#ifdef CONFIG_X86_PAE
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
3320 - set_pgd(&pgd_base[0], pgd_base[USER_PTRS_PER_PGD]);
3324 #ifdef CONFIG_SOFTWARE_SUSPEND
3325 @@ -423,7 +393,6 @@ void zap_low_mappings (void)
3329 -static int disable_nx __initdata = 0;
3330 u64 __supported_pte_mask __read_mostly = ~_PAGE_NX;
3333 @@ -437,11 +406,9 @@ u64 __supported_pte_mask __read_mostly =
3334 void __init noexec_setup(const char *str)
3336 if (!strncmp(str, "on",2) && cpu_has_nx) {
3337 - __supported_pte_mask |= _PAGE_NX;
3340 } else if (!strncmp(str,"off",3)) {
3342 - __supported_pte_mask &= ~_PAGE_NX;
3347 @@ -450,17 +417,13 @@ int nx_enabled = 0;
3349 static void __init set_nx(void)
3351 - unsigned int v[4], l, h;
3352 + if (!nx_enabled && cpu_has_nx) {
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);
3360 - wrmsr(MSR_EFER, l, h);
3362 - __supported_pte_mask |= _PAGE_NX;
3364 + __supported_pte_mask &= ~_PAGE_NX;
3365 + rdmsr(MSR_EFER, l, h);
3367 + wrmsr(MSR_EFER, l, h);
3371 @@ -512,14 +475,6 @@ void __init paging_init(void)
3373 load_cr3(swapper_pg_dir);
3375 -#ifdef CONFIG_X86_PAE
3377 - * We will bail out later - printk doesn't work right now so
3378 - * the user would just see a hanging kernel.
3381 - set_in_cr4(X86_CR4_PAE);
3386 @@ -611,7 +566,7 @@ void __init mem_init(void)
3387 set_highmem_pages_init(bad_ppro);
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;
3394 kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT);
3395 @@ -628,10 +583,6 @@ void __init mem_init(void)
3396 (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
3399 -#ifdef CONFIG_X86_PAE
3401 - panic("cannot execute a PAE-enabled kernel on a PAE-less CPU!");
3403 if (boot_cpu_data.wp_works_ok < 0)
3406 @@ -724,6 +675,36 @@ void free_initmem(void)
3410 +#ifdef CONFIG_PAX_KERNEXEC
3411 + /* PaX: limit KERNEL_CS to actual size */
3412 + unsigned long limit;
3418 +#ifdef CONFIG_MODULES
3419 + limit = (unsigned long)&MODULES_END - __KERNEL_TEXT_OFFSET;
3421 + limit = (unsigned long)&_etext;
3423 + limit = (limit - 1UL) >> PAGE_SHIFT;
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);
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));
3440 addr = (unsigned long)(&__init_begin);
3441 for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
3442 ClearPageReserved(virt_to_page(addr));
3443 diff -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
3447 * Leave an at least ~128 MB hole.
3449 #define MIN_GAP (128*1024*1024)
3450 -#define MAX_GAP (TASK_SIZE/6*5)
3451 +#define MAX_GAP (task_size/6*5)
3453 static inline unsigned long mmap_base(struct mm_struct *mm)
3455 unsigned long gap = current->signal->rlim[RLIMIT_STACK].rlim_cur;
3456 unsigned long random_factor = 0;
3457 + unsigned long task_size = TASK_SIZE;
3459 +#ifdef CONFIG_PAX_SEGMEXEC
3460 + if (mm->pax_flags & MF_PAX_SEGMEXEC)
3461 + task_size = SEGMEXEC_TASK_SIZE;
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)
3470 - return PAGE_ALIGN(TASK_SIZE - gap - random_factor);
3471 + return PAGE_ALIGN(task_size - gap - random_factor);
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;
3480 +#ifdef CONFIG_PAX_RANDMMAP
3481 + if (mm->pax_flags & MF_PAX_RANDMMAP)
3482 + mm->mmap_base += mm->delta_mmap;
3485 mm->get_unmapped_area = arch_get_unmapped_area;
3486 mm->unmap_area = arch_unmap_area;
3488 mm->mmap_base = mmap_base(mm);
3490 +#ifdef CONFIG_PAX_RANDMMAP
3491 + if (mm->pax_flags & MF_PAX_RANDMMAP)
3492 + mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
3495 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
3496 mm->unmap_area = arch_unmap_area_topdown;
3498 diff -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
3502 #include <asm/tlbflush.h>
3503 #include <asm/pgalloc.h>
3504 #include <asm/sections.h>
3505 +#include <asm/desc.h>
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
3511 unsigned long flags;
3513 +#ifdef CONFIG_PAX_KERNEXEC
3514 + unsigned long cr0;
3516 + pax_open_kernel(cr0);
3519 set_pte_atomic(kpte, pte); /* change init_mm */
3521 +#ifdef CONFIG_PAX_KERNEXEC
3522 + pax_close_kernel(cr0);
3525 if (PTRS_PER_PMD > 1)
3528 @@ -104,7 +116,7 @@ static inline void revert_page(struct pa
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;
3537 @@ -136,7 +148,7 @@ __change_page_attr(struct page *page, pg
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);
3546 diff -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;
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);
3558 diff -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)
3564 int cpu = smp_processor_id();
3565 - struct tss_struct * t = &per_cpu(init_tss, cpu);
3566 + struct tss_struct * t = init_tss + cpu;
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. */
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);
3578 * now restore the descriptor tables to their proper values
3579 diff -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)
3584 #define elf_read_implies_exec(ex, have_pt_gnu_stack) (!(have_pt_gnu_stack))
3586 +#ifdef CONFIG_PAX_ASLR
3587 +#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
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)
3597 /* Ugly but avoids duplication */
3598 #include "../../../fs/binfmt_elf.c"
3600 diff -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
3607 -#define IA32_STACK_TOP IA32_PAGE_OFFSET
3608 +#ifdef CONFIG_PAX_RANDUSTACK
3609 +#define __IA32_DELTA_STACK (current->mm->delta_stack)
3611 +#define __IA32_DELTA_STACK 0UL
3614 +#define IA32_STACK_TOP (IA32_PAGE_OFFSET - __IA32_DELTA_STACK)
3616 #define IA32_GATE_OFFSET IA32_PAGE_OFFSET
3617 #define IA32_GATE_END IA32_PAGE_OFFSET + PAGE_SIZE
3619 diff -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)
3624 module_free (struct module *mod, void *module_region)
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;
3631 @@ -500,15 +500,39 @@ module_frob_arch_sections (Elf_Ehdr *ehd
3635 +in_init_rx (const struct module *mod, uint64_t addr)
3637 + return addr - (uint64_t) mod->module_init_rx < mod->init_size_rx;
3641 +in_init_rw (const struct module *mod, uint64_t addr)
3643 + return addr - (uint64_t) mod->module_init_rw < mod->init_size_rw;
3647 in_init (const struct module *mod, uint64_t addr)
3649 - return addr - (uint64_t) mod->module_init < mod->init_size;
3650 + return in_init_rx(mod, value) || in_init_rw(mod, value);
3654 +in_core_rx (const struct module *mod, uint64_t addr)
3656 + return addr - (uint64_t) mod->module_core_rx < mod->core_size_rx;
3660 +in_core_rw (const struct module *mod, uint64_t addr)
3662 + return addr - (uint64_t) mod->module_core_rw < mod->core_size_rw;
3666 in_core (const struct module *mod, uint64_t addr)
3668 - return addr - (uint64_t) mod->module_core < mod->core_size;
3669 + return in_core_rx(mod, value) || in_core_rw(mod, value);
3673 @@ -692,7 +716,14 @@ do_reloc (struct module *mod, uint8_t r_
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;
3689 @@ -826,15 +857,15 @@ apply_relocate_add (Elf64_Shdr *sechdrs,
3690 * addresses have been selected...
3693 - if (mod->core_size > MAX_LTOFF)
3694 + if (mod->core_size_rx + mod->core_size_rw > MAX_LTOFF)
3696 * This takes advantage of fact that SHF_ARCH_SMALL gets allocated
3697 * at the end of the module.
3699 - gp = mod->core_size - MAX_LTOFF / 2;
3700 + gp = mod->core_size_rx + mod->core_size_rw - MAX_LTOFF / 2;
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);
3707 DEBUGP("%s: placing gp at 0x%lx\n", __FUNCTION__, gp);
3709 diff -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
3713 #include <linux/security.h>
3714 #include <linux/audit.h>
3715 #include <linux/signal.h>
3716 +#include <linux/grsecurity.h>
3718 #include <asm/pgtable.h>
3719 #include <asm/processor.h>
3720 @@ -1447,6 +1448,9 @@ sys_ptrace (long request, pid_t pid, uns
3721 if (pid == 1) /* no messing around with init! */
3724 + if (gr_handle_ptrace(child, request))
3727 if (request == PTRACE_ATTACH) {
3728 ret = ptrace_attach(child);
3730 diff -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)
3738 +#ifdef CONFIG_PAX_RANDMMAP
3739 + if ((mm->pax_flags & MF_PAX_RANDMMAP) && addr && filp)
3740 + addr = mm->free_area_cache;
3745 addr = mm->free_area_cache;
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;
3759 diff -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
3763 #include <linux/smp_lock.h>
3764 #include <linux/interrupt.h>
3765 #include <linux/kprobes.h>
3766 +#include <linux/binfmts.h>
3768 #include <asm/pgtable.h>
3769 #include <asm/processor.h>
3770 @@ -51,6 +52,23 @@ mapped_kernel_page_is_present (unsigned
3771 return pte_present(pte);
3774 +#ifdef CONFIG_PAX_PAGEEXEC
3775 +void pax_report_insns(void *pc, void *sp)
3779 + printk(KERN_ERR "PAX: bytes at PC: ");
3780 + for (i = 0; i < 8; i++) {
3782 + if (get_user(c, (unsigned int*)pc+i))
3783 + printk("???????? ");
3785 + printk("%08x ", c);
3792 ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs)
3794 @@ -113,9 +131,23 @@ ia64_do_page_fault (unsigned long addres
3795 | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT)
3796 | (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_BIT));
3798 - if ((vma->vm_flags & mask) != mask)
3799 + if ((vma->vm_flags & mask) != mask) {
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)
3806 + up_read(&mm->mmap_sem);
3807 + pax_report_fault(regs, (void*)regs->cr_iip, (void*)regs->r12);
3818 * If for any reason at all we couldn't handle the fault, make
3819 diff -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
3823 #include <linux/swap.h>
3824 #include <linux/proc_fs.h>
3825 #include <linux/bitops.h>
3826 +#include <linux/a.out.h>
3828 -#include <asm/a.out.h>
3829 #include <asm/dma.h>
3830 #include <asm/ia32.h>
3832 diff -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)
3839 +#ifdef CONFIG_PAX_ASLR
3840 +#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
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)
3850 #include <asm/processor.h>
3851 #include <linux/module.h>
3852 #include <linux/elfcore.h>
3853 diff -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)
3860 +#ifdef CONFIG_PAX_ASLR
3861 +#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
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)
3871 #include <asm/processor.h>
3872 #include <linux/module.h>
3873 #include <linux/elfcore.h>
3874 diff -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
3877 @@ -89,6 +89,11 @@ unsigned long arch_get_unmapped_area(str
3879 if (filp || (flags & MAP_SHARED))
3882 +#ifdef CONFIG_PAX_RANDMMAP
3883 + if (!(current->mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
3888 addr = COLOUR_ALIGN(addr, pgoff);
3889 @@ -99,7 +104,7 @@ unsigned long arch_get_unmapped_area(str
3890 (!vmm || addr + len <= vmm->vm_start))
3893 - addr = TASK_UNMAPPED_BASE;
3894 + addr = current->mm->mmap_base;
3896 addr = COLOUR_ALIGN(addr, pgoff);
3898 diff -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
3902 #include <asm/ptrace.h>
3903 #include <asm/highmem.h> /* For VMALLOC_END */
3905 +#ifdef CONFIG_PAX_PAGEEXEC
3906 +void pax_report_insns(void *pc)
3910 + printk(KERN_ERR "PAX: bytes at PC: ");
3911 + for (i = 0; i < 5; i++) {
3913 + if (get_user(c, (unsigned int*)pc+i))
3914 + printk("???????? ");
3916 + printk("%08x ", c);
3923 * This routine handles page faults. It determines the address,
3924 * and the problem, and then passes it off to one of the appropriate
3925 diff -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
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)
3934 + return (loc >= me->module_init_rx &&
3935 + loc < (me->module_init_rx + me->init_size_rx));
3938 +static inline int is_init_rw(struct module *me, void *loc)
3940 + return (loc >= me->module_init_rw &&
3941 + loc < (me->module_init_rw + me->init_size_rw));
3944 static inline int is_init(struct module *me, void *loc)
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);
3951 +static inline int is_core_rx(struct module *me, void *loc)
3953 + return (loc >= me->module_core_rx &&
3954 + loc < (me->module_core_rx + me->core_size_rx));
3957 +static inline int is_core_rw(struct module *me, void *loc)
3959 + return (loc >= me->module_core_rw &&
3960 + loc < (me->module_core_rw + me->core_size_rw));
3963 static inline int is_core(struct module *me, void *loc)
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);
3970 static inline int is_local(struct module *me, void *loc)
3971 @@ -289,21 +311,21 @@ int module_frob_arch_sections(CONST Elf_
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);
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);
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);
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);
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);
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);
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);
4006 me->arch.got_max = gots;
4007 me->arch.fdesc_max = fdescs;
4008 @@ -323,7 +345,7 @@ static Elf64_Word get_got(struct module
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)
4017 @@ -341,7 +363,7 @@ static Elf64_Word get_got(struct module
4019 static Elf_Addr get_fdesc(struct module *me, unsigned long value)
4021 - Elf_Fdesc *fdesc = me->module_core + me->arch.fdesc_offset;
4022 + Elf_Fdesc *fdesc = me->module_core_rw + me->arch.fdesc_offset;
4025 printk(KERN_ERR "%s: zero OPD requested!\n", me->name);
4026 @@ -359,7 +381,7 @@ static Elf_Addr get_fdesc(struct module
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;
4034 #endif /* __LP64__ */
4035 @@ -373,12 +395,12 @@ static Elf_Addr get_stub(struct module *
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);
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);
4050 @@ -721,7 +743,7 @@ register_unwind_table(struct module *me,
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;
4057 DEBUGP("register_unwind_table(), sect = %d at 0x%p - 0x%p (gp=0x%lx)\n",
4058 me->arch.unwind_section, table, end, gp);
4059 diff -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
4063 #include <linux/security.h>
4064 #include <linux/compat.h>
4065 #include <linux/signal.h>
4066 +#include <linux/grsecurity.h>
4068 #include <asm/uaccess.h>
4069 #include <asm/pgtable.h>
4070 diff -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)
4077 - addr = TASK_UNMAPPED_BASE;
4078 + addr = current->mm->mmap_base;
4081 addr = get_shared_area(filp->f_mapping, addr, len, pgoff);
4082 diff -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
4085 @@ -711,9 +711,7 @@ void handle_interruption(int code, struc
4087 down_read(¤t->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)) {
4092 + if (vma && (regs->iaoq[0] >= vma->vm_start)) {
4093 fault_address = regs->iaoq[0];
4094 fault_space = regs->iasq[0];
4096 diff -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
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>
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)
4112 - if (code == 6 || code == 16)
4113 + if (code == 6 || code == 7 || code == 16)
4116 switch (inst & 0xf0000000) {
4117 @@ -143,6 +145,116 @@ parisc_acctyp(unsigned long code, unsign
4121 +#ifdef CONFIG_PAX_PAGEEXEC
4123 + * PaX: decide what to do with offenders (instruction_pointer(regs) = fault address)
4125 + * returns 1 when task should be killed
4126 + * 2 when rt_sigreturn trampoline was detected
4127 + * 3 when unpatched PLT trampoline was detected
4129 +static int pax_handle_fetch_fault(struct pt_regs *regs)
4132 +#ifdef CONFIG_PAX_EMUPLT
4135 + do { /* PaX: unpatched PLT emulation */
4136 + unsigned int bl, depwi;
4138 + err = get_user(bl, (unsigned int*)instruction_pointer(regs));
4139 + err |= get_user(depwi, (unsigned int*)(instruction_pointer(regs)+4));
4144 + if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) {
4145 + unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12;
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));
4154 + if (ldw == 0x0E801096U &&
4155 + bv == 0xEAC0C000U &&
4156 + ldw2 == 0x0E881095U)
4158 + unsigned int resolver, map;
4160 + err = get_user(resolver, (unsigned int*)(instruction_pointer(regs)+8));
4161 + err |= get_user(map, (unsigned int*)(instruction_pointer(regs)+12));
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;
4176 +#ifdef CONFIG_PAX_EMUTRAMP
4178 +#ifndef CONFIG_PAX_EMUSIGRT
4179 + if (!(current->mm->pax_flags & MF_PAX_EMUTRAMP))
4183 + do { /* PaX: rt_sigreturn emulation */
4184 + unsigned int ldi1, ldi2, bel, nop;
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));
4194 + if ((ldi1 == 0x34190000U || ldi1 == 0x34190002U) &&
4195 + ldi2 == 0x3414015AU &&
4196 + bel == 0xE4008200U &&
4197 + nop == 0x08000240U)
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];
4215 +void pax_report_insns(void *pc, void *sp)
4219 + printk(KERN_ERR "PAX: bytes at PC: ");
4220 + for (i = 0; i < 5; i++) {
4222 + if (get_user(c, (unsigned int*)pc+i))
4223 + printk("???????? ");
4225 + printk("%08x ", c);
4231 void do_page_fault(struct pt_regs *regs, unsigned long code,
4232 unsigned long address)
4234 @@ -168,8 +280,33 @@ good_area:
4236 acc_type = parisc_acctyp(code,regs->iir);
4238 - if ((vma->vm_flags & acc_type) != acc_type)
4239 + if ((vma->vm_flags & acc_type) != acc_type) {
4241 +#ifdef CONFIG_PAX_PAGEEXEC
4242 + if ((mm->pax_flags & MF_PAX_PAGEEXEC) && (acc_type & VM_EXEC) &&
4243 + (address & ~3UL) == instruction_pointer(regs))
4245 + up_read(&mm->mmap_sem);
4246 + switch(pax_handle_fetch_fault(regs)) {
4248 +#ifdef CONFIG_PAX_EMUPLT
4253 +#ifdef CONFIG_PAX_EMUTRAMP
4259 + pax_report_fault(regs, (void*)instruction_pointer(regs), (void*)regs->gr[30]);
4268 * If for any reason at all we couldn't handle the fault, make
4269 diff -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
4273 #include <linux/highmem.h>
4274 #include <linux/module.h>
4275 #include <linux/kprobes.h>
4276 +#include <linux/binfmts.h>
4278 #include <asm/page.h>
4279 #include <asm/pgtable.h>
4280 @@ -105,6 +106,38 @@ static void do_dabr(struct pt_regs *regs
4282 #endif /* !(CONFIG_4xx || CONFIG_BOOKE)*/
4284 +#ifdef CONFIG_PAX_PAGEEXEC
4286 + * PaX: decide what to do with offenders (regs->nip = fault address)
4288 + * returns 1 when task should be killed
4290 +static int pax_handle_fetch_fault(struct pt_regs *regs)
4293 +#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT)
4300 +void pax_report_insns(void *pc, void *sp)
4304 + printk(KERN_ERR "PAX: bytes at PC: ");
4305 + for (i = 0; i < 5; i++) {
4307 + if (get_user(c, (unsigned int*)pc+i))
4308 + printk("???????? ");
4310 + printk("%08x ", c);
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)) {
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)) {
4330 + pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]);
4336 _exception(SIGSEGV, regs, code, address);
4339 diff -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
4344 if (mmap_is_legacy()) {
4345 mm->mmap_base = TASK_UNMAPPED_BASE;
4347 +#ifdef CONFIG_PAX_RANDMMAP
4348 + if (mm->pax_flags & MF_PAX_RANDMMAP)
4349 + mm->mmap_base += mm->delta_mmap;
4352 mm->get_unmapped_area = arch_get_unmapped_area;
4353 mm->unmap_area = arch_unmap_area;
4355 mm->mmap_base = mmap_base();
4357 +#ifdef CONFIG_PAX_RANDMMAP
4358 + if (mm->pax_flags & MF_PAX_RANDMMAP)
4359 + mm->mmap_base -= mm->delta_mmap;
4362 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
4363 mm->unmap_area = arch_unmap_area_topdown;
4365 diff -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
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;
4378 entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
4379 diff -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
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>
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;
4398 +#ifdef CONFIG_PAX_EMUSIGRT
4399 +void pax_syscall_close(struct vm_area_struct * vma)
4401 + vma->vm_mm->call_syscall = 0UL;
4404 +static struct page* pax_syscall_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
4406 + struct page* page;
4407 + unsigned int *kaddr;
4409 + page = alloc_page(GFP_HIGHUSER);
4411 + return NOPAGE_OOM;
4413 + kaddr = kmap(page);
4414 + memset(kaddr, 0, PAGE_SIZE);
4415 + kaddr[0] = 0x44000002U; /* sc */
4416 + __flush_dcache_icache(kaddr);
4419 + *type = VM_FAULT_MAJOR;
4423 +static struct vm_operations_struct pax_vm_ops = {
4424 + .close = pax_syscall_close,
4425 + .nopage = pax_syscall_nopage,
4428 +static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
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;
4440 + ret = insert_vm_struct(current->mm, vma);
4444 + ++current->mm->total_vm;
4449 +#ifdef CONFIG_PAX_PAGEEXEC
4451 + * PaX: decide what to do with offenders (regs->nip = fault address)
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
4460 +static int pax_handle_fetch_fault(struct pt_regs *regs)
4463 +#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT)
4467 +#ifdef CONFIG_PAX_EMUPLT
4468 + do { /* PaX: patched GOT emulation */
4469 + unsigned int blrl;
4471 + err = get_user(blrl, (unsigned int*)regs->nip);
4473 + if (!err && blrl == 0x4E800021U) {
4474 + unsigned long temp = regs->nip;
4476 + regs->nip = regs->link & 0xFFFFFFFCUL;
4477 + regs->link = temp + 4UL;
4482 + do { /* PaX: patched PLT emulation #1 */
4485 + err = get_user(b, (unsigned int *)regs->nip);
4487 + if (!err && (b & 0xFC000003U) == 0x48000000U) {
4488 + regs->nip += (((b | 0xFC000000UL) ^ 0x02000000UL) + 0x02000000UL);
4493 + do { /* PaX: unpatched PLT emulation #1 */
4494 + unsigned int li, b;
4496 + err = get_user(li, (unsigned int *)regs->nip);
4497 + err |= get_user(b, (unsigned int *)(regs->nip+4));
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;
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));
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)
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;
4537 + do { /* PaX: unpatched PLT emulation #2 */
4538 + unsigned int lis, lwzu, b, bctr;
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));
4548 + if ((lis & 0xFFFF0000U) == 0x39600000U &&
4549 + (lwzu & 0xU) == 0xU &&
4550 + (b & 0xFC000003U) == 0x48000000U &&
4551 + bctr == 0x4E800420U)
4553 + unsigned int addis, addi, rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr;
4554 + unsigned long addr = b | 0xFC000000UL;
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));
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)
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;
4595 + do { /* PaX: unpatched PLT emulation #3 */
4596 + unsigned int li, b;
4598 + err = get_user(li, (unsigned int *)regs->nip);
4599 + err |= get_user(b, (unsigned int *)(regs->nip+4));
4601 + if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) {
4602 + unsigned int addis, lwz, mtctr, bctr;
4603 + unsigned long addr = b | 0xFC000000UL;
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));
4614 + if ((addis & 0xFFFF0000U) == 0x3D6B0000U &&
4615 + (lwz & 0xFFFF0000U) == 0x816B0000U &&
4616 + mtctr == 0x7D6903A6U &&
4617 + bctr == 0x4E800420U)
4621 + addr = (addis << 16) + (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
4622 + addr += (((lwz | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL);
4624 + err = get_user(r11, (unsigned int*)addr);
4628 + regs->gpr[PT_R11] = r11;
4637 +#ifdef CONFIG_PAX_EMUSIGRT
4638 + do { /* PaX: sigreturn emulation */
4639 + unsigned int li, sc;
4641 + err = get_user(li, (unsigned int *)regs->nip);
4642 + err |= get_user(sc, (unsigned int *)(regs->nip+4));
4644 + if (!err && li == 0x38000000U + __NR_sigreturn && sc == 0x44000002U) {
4645 + struct vm_area_struct *vma;
4646 + unsigned long call_syscall;
4648 + down_read(¤t->mm->mmap_sem);
4649 + call_syscall = current->mm->call_syscall;
4650 + up_read(¤t->mm->mmap_sem);
4651 + if (likely(call_syscall))
4654 + vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
4656 + down_write(¤t->mm->mmap_sem);
4657 + if (current->mm->call_syscall) {
4658 + call_syscall = current->mm->call_syscall;
4659 + up_write(¤t->mm->mmap_sem);
4660 + if (vma) kmem_cache_free(vm_area_cachep, vma);
4664 + call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
4665 + if (!vma || (call_syscall & ~PAGE_MASK)) {
4666 + up_write(¤t->mm->mmap_sem);
4667 + if (vma) kmem_cache_free(vm_area_cachep, vma);
4671 + if (pax_insert_vma(vma, call_syscall)) {
4672 + up_write(¤t->mm->mmap_sem);
4673 + kmem_cache_free(vm_area_cachep, vma);
4677 + current->mm->call_syscall = call_syscall;
4678 + up_write(¤t->mm->mmap_sem);
4681 + regs->gpr[PT_R0] = __NR_sigreturn;
4682 + regs->nip = call_syscall;
4687 + do { /* PaX: rt_sigreturn emulation */
4688 + unsigned int li, sc;
4690 + err = get_user(li, (unsigned int *)regs->nip);
4691 + err |= get_user(sc, (unsigned int *)(regs->nip+4));
4693 + if (!err && li == 0x38000000U + __NR_rt_sigreturn && sc == 0x44000002U) {
4694 + struct vm_area_struct *vma;
4695 + unsigned int call_syscall;
4697 + down_read(¤t->mm->mmap_sem);
4698 + call_syscall = current->mm->call_syscall;
4699 + up_read(¤t->mm->mmap_sem);
4700 + if (likely(call_syscall))
4703 + vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
4705 + down_write(¤t->mm->mmap_sem);
4706 + if (current->mm->call_syscall) {
4707 + call_syscall = current->mm->call_syscall;
4708 + up_write(¤t->mm->mmap_sem);
4709 + if (vma) kmem_cache_free(vm_area_cachep, vma);
4713 + call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE);
4714 + if (!vma || (call_syscall & ~PAGE_MASK)) {
4715 + up_write(¤t->mm->mmap_sem);
4716 + if (vma) kmem_cache_free(vm_area_cachep, vma);
4720 + if (pax_insert_vma(vma, call_syscall)) {
4721 + up_write(¤t->mm->mmap_sem);
4722 + kmem_cache_free(vm_area_cachep, vma);
4726 + current->mm->call_syscall = call_syscall;
4727 + up_write(¤t->mm->mmap_sem);
4730 + regs->gpr[PT_R0] = __NR_rt_sigreturn;
4731 + regs->nip = call_syscall;
4740 +void pax_report_insns(void *pc, void *sp)
4744 + printk(KERN_ERR "PAX: bytes at PC: ");
4745 + for (i = 0; i < 5; i++) {
4747 + if (get_user(c, (unsigned int*)pc+i))
4748 + printk("???????? ");
4750 + printk("%08x ", c);
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.
4762 if (TRAP(regs) == 0x400)
4763 - error_code &= 0x48200000;
4764 + error_code &= 0x58200000;
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) {
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))
4783 /* Since 4xx/Book-E supports per-page execute permission,
4784 * we lazily flush dcache to icache. */
4786 @@ -233,6 +595,7 @@ good_area:
4793 /* protection fault */
4794 @@ -278,6 +641,33 @@ bad_area:
4796 /* User mode accesses cause a SIGSEGV */
4797 if (user_mode(regs)) {
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)) {
4804 +#ifdef CONFIG_PAX_EMUPLT
4811 +#ifdef CONFIG_PAX_EMUSIGRT
4819 + pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]);
4825 _exception(SIGSEGV, regs, code, address);
4828 diff -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,
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;
4848 @@ -254,7 +254,7 @@ apply_rela(Elf_Rela *rela, Elf_Addr base
4849 if (info->got_initialized == 0) {
4852 - gotent = me->module_core + me->arch.got_offset +
4853 + gotent = me->module_core_rw + me->arch.got_offset +
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) {
4870 - ip = me->module_core + me->arch.plt_offset +
4871 + ip = me->module_core_rx + me->arch.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;
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
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;
4902 diff -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
4906 #include <linux/smp_lock.h>
4907 #include <linux/security.h>
4908 #include <linux/signal.h>
4909 +#include <linux/grsecurity.h>
4911 #include <asm/pgtable.h>
4912 #include <asm/system.h>
4913 @@ -300,6 +301,11 @@ asmlinkage void do_ptrace(struct pt_regs
4917 + if (gr_handle_ptrace(child, request)) {
4918 + pt_error_return(regs, EPERM);
4922 if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
4923 || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
4924 if (ptrace_attach(child)) {
4925 diff -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
4928 @@ -56,7 +56,7 @@ unsigned long arch_get_unmapped_area(str
4929 if (ARCH_SUN4C_SUN4 && len > 0x20000000)
4932 - addr = TASK_UNMAPPED_BASE;
4933 + addr = current->mm->mmap_base;
4935 if (flags & MAP_SHARED)
4936 addr = COLOUR_ALIGN(addr);
4937 diff -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))
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))
4949 diff -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
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>
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);
4967 +#ifdef CONFIG_PAX_PAGEEXEC
4968 +void pax_emuplt_close(struct vm_area_struct * vma)
4970 + vma->vm_mm->call_dl_resolve = 0UL;
4973 +static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
4975 + struct page* page;
4976 + unsigned int *kaddr;
4978 + page = alloc_page(GFP_HIGHUSER);
4980 + return NOPAGE_OOM;
4982 + kaddr = kmap(page);
4983 + memset(kaddr, 0, PAGE_SIZE);
4984 + kaddr[0] = 0x9DE3BFA8U; /* save */
4985 + flush_dcache_page(page);
4988 + *type = VM_FAULT_MAJOR;
4993 +static struct vm_operations_struct pax_vm_ops = {
4994 + .close = pax_emuplt_close,
4995 + .nopage = pax_emuplt_nopage,
4998 +static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
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;
5010 + ret = insert_vm_struct(current->mm, vma);
5014 + ++current->mm->total_vm;
5019 + * PaX: decide what to do with offenders (regs->pc = fault address)
5021 + * returns 1 when task should be killed
5022 + * 2 when patched PLT trampoline was detected
5023 + * 3 when unpatched PLT trampoline was detected
5025 +static int pax_handle_fetch_fault(struct pt_regs *regs)
5028 +#ifdef CONFIG_PAX_EMUPLT
5031 + do { /* PaX: patched PLT emulation #1 */
5032 + unsigned int sethi1, sethi2, jmpl;
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));
5041 + if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
5042 + (sethi2 & 0xFFC00000U) == 0x03000000U &&
5043 + (jmpl & 0xFFFFE000U) == 0x81C06000U)
5045 + unsigned int addr;
5047 + regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
5048 + addr = regs->u_regs[UREG_G1];
5049 + addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
5051 + regs->npc = addr+4;
5056 + { /* PaX: patched PLT emulation #2 */
5059 + err = get_user(ba, (unsigned int*)regs->pc);
5061 + if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
5062 + unsigned int addr;
5064 + addr = regs->pc + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
5066 + regs->npc = addr+4;
5071 + do { /* PaX: patched PLT emulation #3 */
5072 + unsigned int sethi, jmpl, nop;
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));
5081 + if ((sethi & 0xFFC00000U) == 0x03000000U &&
5082 + (jmpl & 0xFFFFE000U) == 0x81C06000U &&
5083 + nop == 0x01000000U)
5085 + unsigned int addr;
5087 + addr = (sethi & 0x003FFFFFU) << 10;
5088 + regs->u_regs[UREG_G1] = addr;
5089 + addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U);
5091 + regs->npc = addr+4;
5096 + do { /* PaX: unpatched PLT emulation step 1 */
5097 + unsigned int sethi, ba, nop;
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));
5106 + if ((sethi & 0xFFC00000U) == 0x03000000U &&
5107 + ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
5108 + nop == 0x01000000U)
5110 + unsigned int addr, save, call;
5112 + if ((ba & 0xFFC00000U) == 0x30800000U)
5113 + addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2);
5115 + addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2);
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));
5123 + if (save == 0x9DE3BFA8U &&
5124 + (call & 0xC0000000U) == 0x40000000U &&
5125 + nop == 0x01000000U)
5127 + struct vm_area_struct *vma;
5128 + unsigned long call_dl_resolve;
5130 + down_read(¤t->mm->mmap_sem);
5131 + call_dl_resolve = current->mm->call_dl_resolve;
5132 + up_read(¤t->mm->mmap_sem);
5133 + if (likely(call_dl_resolve))
5136 + vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
5138 + down_write(¤t->mm->mmap_sem);
5139 + if (current->mm->call_dl_resolve) {
5140 + call_dl_resolve = current->mm->call_dl_resolve;
5141 + up_write(¤t->mm->mmap_sem);
5142 + if (vma) kmem_cache_free(vm_area_cachep, vma);
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(¤t->mm->mmap_sem);
5149 + if (vma) kmem_cache_free(vm_area_cachep, vma);
5153 + if (pax_insert_vma(vma, call_dl_resolve)) {
5154 + up_write(¤t->mm->mmap_sem);
5155 + kmem_cache_free(vm_area_cachep, vma);
5159 + current->mm->call_dl_resolve = call_dl_resolve;
5160 + up_write(¤t->mm->mmap_sem);
5163 + regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
5164 + regs->pc = call_dl_resolve;
5165 + regs->npc = addr+4;
5171 + do { /* PaX: unpatched PLT emulation step 2 */
5172 + unsigned int save, call, nop;
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));
5180 + if (save == 0x9DE3BFA8U &&
5181 + (call & 0xC0000000U) == 0x40000000U &&
5182 + nop == 0x01000000U)
5184 + unsigned int dl_resolve = regs->pc + ((((call | 0xC0000000U) ^ 0x20000000U) + 0x20000000U) << 2);
5186 + regs->u_regs[UREG_RETPC] = regs->pc;
5187 + regs->pc = dl_resolve;
5188 + regs->npc = dl_resolve+4;
5197 +void pax_report_insns(void *pc, void *sp)
5201 + printk(KERN_ERR "PAX: bytes at PC: ");
5202 + for (i = 0; i < 5; i++) {
5204 + if (get_user(c, (unsigned int*)pc+i))
5205 + printk("???????? ");
5207 + printk("%08x ", c);
5213 asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write,
5214 unsigned long address)
5216 @@ -280,6 +530,24 @@ good_area:
5217 if(!(vma->vm_flags & VM_WRITE))
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)) {
5226 +#ifdef CONFIG_PAX_EMUPLT
5233 + pax_report_fault(regs, (void*)regs->pc, (void*)regs->u_regs[UREG_FP]);
5238 /* Allow reads even for write-only mappings */
5239 if(!(vma->vm_flags & (VM_READ | VM_EXEC)))
5241 diff -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)
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;
5268 diff -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));
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));
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;
5285 diff -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
5289 #include <linux/seccomp.h>
5290 #include <linux/audit.h>
5291 #include <linux/signal.h>
5292 +#include <linux/grsecurity.h>
5294 #include <asm/asi.h>
5295 #include <asm/pgtable.h>
5296 @@ -210,6 +211,11 @@ asmlinkage void do_ptrace(struct pt_regs
5300 + if (gr_handle_ptrace(child, (long)request)) {
5301 + pt_error_return(regs, EPERM);
5305 if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH)
5306 || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) {
5307 if (ptrace_attach(child)) {
5308 diff -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
5311 @@ -72,6 +72,10 @@ unsigned long arch_get_unmapped_area(str
5312 if (filp || (flags & MAP_SHARED))
5315 +#ifdef CONFIG_PAX_RANDMMAP
5316 + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
5321 addr = COLOUR_ALIGN(addr, pgoff);
5322 @@ -86,7 +90,7 @@ unsigned long arch_get_unmapped_area(str
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;
5329 start_addr = addr = mm->free_area_cache;
5331 @@ -105,8 +109,8 @@ full_search:
5332 vma = find_vma(mm, PAGE_OFFSET);
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;
5342 diff -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
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>
5354 #include <asm/page.h>
5355 #include <asm/pgtable.h>
5356 @@ -251,6 +255,369 @@ cannot_handle:
5357 unhandled_fault (address, current, regs);
5360 +#ifdef CONFIG_PAX_PAGEEXEC
5361 +#ifdef CONFIG_PAX_EMUPLT
5362 +static void pax_emuplt_close(struct vm_area_struct * vma)
5364 + vma->vm_mm->call_dl_resolve = 0UL;
5367 +static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type)
5369 + struct page* page;
5370 + unsigned int *kaddr;
5372 + page = alloc_page(GFP_HIGHUSER);
5374 + return NOPAGE_OOM;
5376 + kaddr = kmap(page);
5377 + memset(kaddr, 0, PAGE_SIZE);
5378 + kaddr[0] = 0x9DE3BFA8U; /* save */
5379 + flush_dcache_page(page);
5382 + *type = VM_FAULT_MAJOR;
5386 +static struct vm_operations_struct pax_vm_ops = {
5387 + .close = pax_emuplt_close,
5388 + .nopage = pax_emuplt_nopage,
5391 +static int pax_insert_vma(struct vm_area_struct *vma, unsigned long addr)
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;
5403 + ret = insert_vm_struct(current->mm, vma);
5407 + ++current->mm->total_vm;
5413 + * PaX: decide what to do with offenders (regs->tpc = fault address)
5415 + * returns 1 when task should be killed
5416 + * 2 when patched PLT trampoline was detected
5417 + * 3 when unpatched PLT trampoline was detected
5419 +static int pax_handle_fetch_fault(struct pt_regs *regs)
5422 +#ifdef CONFIG_PAX_EMUPLT
5425 + do { /* PaX: patched PLT emulation #1 */
5426 + unsigned int sethi1, sethi2, jmpl;
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));
5435 + if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
5436 + (sethi2 & 0xFFC00000U) == 0x03000000U &&
5437 + (jmpl & 0xFFFFE000U) == 0x81C06000U)
5439 + unsigned long addr;
5441 + regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10;
5442 + addr = regs->u_regs[UREG_G1];
5443 + addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
5445 + regs->tnpc = addr+4;
5450 + { /* PaX: patched PLT emulation #2 */
5453 + err = get_user(ba, (unsigned int*)regs->tpc);
5455 + if (!err && (ba & 0xFFC00000U) == 0x30800000U) {
5456 + unsigned long addr;
5458 + addr = regs->tpc + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
5460 + regs->tnpc = addr+4;
5465 + do { /* PaX: patched PLT emulation #3 */
5466 + unsigned int sethi, jmpl, nop;
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));
5475 + if ((sethi & 0xFFC00000U) == 0x03000000U &&
5476 + (jmpl & 0xFFFFE000U) == 0x81C06000U &&
5477 + nop == 0x01000000U)
5479 + unsigned long addr;
5481 + addr = (sethi & 0x003FFFFFU) << 10;
5482 + regs->u_regs[UREG_G1] = addr;
5483 + addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL);
5485 + regs->tnpc = addr+4;
5490 + do { /* PaX: patched PLT emulation #4 */
5491 + unsigned int mov1, call, mov2;
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));
5500 + if (mov1 == 0x8210000FU &&
5501 + (call & 0xC0000000U) == 0x40000000U &&
5502 + mov2 == 0x9E100001U)
5504 + unsigned long addr;
5506 + regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC];
5507 + addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
5509 + regs->tnpc = addr+4;
5514 + do { /* PaX: patched PLT emulation #5 */
5515 + unsigned int sethi1, sethi2, or1, or2, sllx, jmpl, nop;
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));
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)
5536 + unsigned long addr;
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];
5543 + regs->tnpc = addr+4;
5548 + do { /* PaX: patched PLT emulation #6 */
5549 + unsigned int sethi1, sethi2, sllx, or, jmpl, nop;
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));
5561 + if ((sethi1 & 0xFFC00000U) == 0x03000000U &&
5562 + (sethi2 & 0xFFC00000U) == 0x0B000000U &&
5563 + sllx == 0x83287020 &&
5564 + (or & 0xFFFFE000U) == 0x8A116000U &&
5565 + jmpl == 0x81C04005U &&
5566 + nop == 0x01000000U)
5568 + unsigned long addr;
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];
5575 + regs->tnpc = addr+4;
5580 + do { /* PaX: patched PLT emulation #7 */
5581 + unsigned int sethi, ba, nop;
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));
5590 + if ((sethi & 0xFFC00000U) == 0x03000000U &&
5591 + (ba & 0xFFF00000U) == 0x30600000U &&
5592 + nop == 0x01000000U)
5594 + unsigned long addr;
5596 + addr = (sethi & 0x003FFFFFU) << 10;
5597 + regs->u_regs[UREG_G1] = addr;
5598 + addr = regs->tpc + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
5600 + regs->tnpc = addr+4;
5605 + do { /* PaX: unpatched PLT emulation step 1 */
5606 + unsigned int sethi, ba, nop;
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));
5615 + if ((sethi & 0xFFC00000U) == 0x03000000U &&
5616 + ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) &&
5617 + nop == 0x01000000U)
5619 + unsigned long addr;
5620 + unsigned int save, call;
5622 + if ((ba & 0xFFC00000U) == 0x30800000U)
5623 + addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2);
5625 + addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2);
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));
5633 + if (save == 0x9DE3BFA8U &&
5634 + (call & 0xC0000000U) == 0x40000000U &&
5635 + nop == 0x01000000U)
5637 + struct vm_area_struct *vma;
5638 + unsigned long call_dl_resolve;
5640 + down_read(¤t->mm->mmap_sem);
5641 + call_dl_resolve = current->mm->call_dl_resolve;
5642 + up_read(¤t->mm->mmap_sem);
5643 + if (likely(call_dl_resolve))
5646 + vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
5648 + down_write(¤t->mm->mmap_sem);
5649 + if (current->mm->call_dl_resolve) {
5650 + call_dl_resolve = current->mm->call_dl_resolve;
5651 + up_write(¤t->mm->mmap_sem);
5652 + if (vma) kmem_cache_free(vm_area_cachep, vma);
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(¤t->mm->mmap_sem);
5659 + if (vma) kmem_cache_free(vm_area_cachep, vma);
5663 + if (pax_insert_vma(vma, call_dl_resolve)) {
5664 + up_write(¤t->mm->mmap_sem);
5665 + kmem_cache_free(vm_area_cachep, vma);
5669 + current->mm->call_dl_resolve = call_dl_resolve;
5670 + up_write(¤t->mm->mmap_sem);
5673 + regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10;
5674 + regs->tpc = call_dl_resolve;
5675 + regs->tnpc = addr+4;
5681 + do { /* PaX: unpatched PLT emulation step 2 */
5682 + unsigned int save, call, nop;
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));
5690 + if (save == 0x9DE3BFA8U &&
5691 + (call & 0xC0000000U) == 0x40000000U &&
5692 + nop == 0x01000000U)
5694 + unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2);
5696 + regs->u_regs[UREG_RETPC] = regs->tpc;
5697 + regs->tpc = dl_resolve;
5698 + regs->tnpc = dl_resolve+4;
5707 +void pax_report_insns(void *pc, void *sp)
5711 + printk(KERN_ERR "PAX: bytes at PC: ");
5712 + for (i = 0; i < 5; i++) {
5714 + if (get_user(c, (unsigned int*)pc+i))
5715 + printk("???????? ");
5717 + printk("%08x ", c);
5723 asmlinkage void __kprobes do_sparc64_fault(struct pt_regs *regs)
5725 struct mm_struct *mm = current->mm;
5726 @@ -293,8 +660,10 @@ asmlinkage void __kprobes do_sparc64_fau
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;
5735 address &= 0xffffffff;
5738 @@ -311,6 +680,29 @@ asmlinkage void __kprobes do_sparc64_fau
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))
5747 + if (address != regs->tpc)
5750 + up_read(&mm->mmap_sem);
5751 + switch (pax_handle_fetch_fault(regs)) {
5753 +#ifdef CONFIG_PAX_EMUPLT
5760 + pax_report_fault(regs, (void*)regs->tpc, (void*)(regs->u_regs[UREG_FP] + STACK_BIAS));
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
5768 diff -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 */
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;
5781 entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr;
5782 diff -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:
5788 lss stack_start,%esp
5789 + movl 0x000000,%ecx
5791 1: incl %eax # check that A20 really IS enabled
5792 movl %eax,0x000000 # loop forever if it isn't
5795 + movl %ecx,0x000000
5798 * Initialize eflags. Some BIOS's leave bits like NT set. This would
5799 diff -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>
5806 +#ifdef CONFIG_PAX_ASLR
5807 +#define PAX_ELF_ET_DYN_BASE(tsk) 0x08048000UL
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
5817 typedef struct user_i387_ia32_struct elf_fpregset_t;
5818 typedef struct user32_fxsr_struct elf_fpxregset_t;
5820 diff -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;
5828 +#ifdef CONFIG_PAX_RANDMMAP
5829 + if (mm->pax_flags & MF_PAX_RANDMMAP)
5830 + mm->mmap_base += mm->delta_mmap;
5833 mm->get_unmapped_area = arch_get_unmapped_area;
5834 mm->unmap_area = arch_unmap_area;
5836 mm->mmap_base = mmap_base(mm);
5838 +#ifdef CONFIG_PAX_RANDMMAP
5839 + if (mm->pax_flags & MF_PAX_RANDMMAP)
5840 + mm->mmap_base -= mm->delta_mmap + mm->delta_stack;
5843 mm->get_unmapped_area = arch_get_unmapped_area_topdown;
5844 mm->unmap_area = arch_unmap_area_topdown;
5846 diff -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
5849 @@ -839,9 +839,3 @@ int dump_task_regs(struct task_struct *t
5853 -unsigned long arch_align_stack(unsigned long sp)
5855 - if (randomize_va_space)
5856 - sp -= get_random_int() % 8192;
5859 diff -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
5863 #include <linux/audit.h>
5864 #include <linux/seccomp.h>
5865 #include <linux/signal.h>
5866 +#include <linux/grsecurity.h>
5868 #include <asm/uaccess.h>
5869 #include <asm/pgtable.h>
5870 diff -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")));
5876 unsigned long __supported_pte_mask __read_mostly = ~0UL;
5877 -static int do_not_nx __cpuinitdata = 0;
5880 Control non executable mappings for 64bit processes.
5881 @@ -50,16 +49,14 @@ int __init nonx_setup(char *str)
5883 if (!strncmp(str, "on", 2)) {
5884 __supported_pte_mask |= _PAGE_NX;
5886 } else if (!strncmp(str, "off", 3)) {
5888 __supported_pte_mask &= ~_PAGE_NX;
5892 __setup("noexec=", nonx_setup); /* parsed early actually */
5894 -int force_personality32 = READ_IMPLIES_EXEC;
5895 +int force_personality32;
5898 Control non executable heap for 32bit processes.
5899 @@ -173,7 +170,7 @@ void __cpuinit check_efer(void)
5902 rdmsrl(MSR_EFER, efer);
5903 - if (!(efer & EFER_NX) || do_not_nx) {
5904 + if (!(efer & EFER_NX)) {
5905 __supported_pte_mask &= ~_PAGE_NX;
5908 diff -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
5911 @@ -65,8 +65,8 @@ out:
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)
5920 if (!test_thread_flag(TIF_IA32) && (flags & MAP_32BIT)) {
5921 /* This is usually used needed to map code in small
5922 @@ -79,7 +79,7 @@ static void find_start_end(unsigned long
5923 *begin = 0x40000000;
5926 - *begin = TASK_UNMAPPED_BASE;
5927 + *begin = mm->mmap_base;
5931 @@ -93,11 +93,15 @@ arch_get_unmapped_area(struct file *filp
5932 unsigned long start_addr;
5933 unsigned long begin, end;
5935 - find_start_end(flags, &begin, &end);
5936 + find_start_end(mm, flags, &begin, &end);
5941 +#ifdef CONFIG_PAX_RANDMMAP
5942 + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
5946 addr = PAGE_ALIGN(addr);
5947 vma = find_vma(mm, addr);
5948 diff -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
5952 #include <linux/compiler.h>
5953 #include <linux/module.h>
5954 #include <linux/kprobes.h>
5955 +#include <linux/binfmts.h>
5957 #include <asm/system.h>
5958 #include <asm/uaccess.h>
5959 @@ -292,6 +293,33 @@ static int vmalloc_fault(unsigned long a
5963 +#ifdef CONFIG_PAX_PAGEEXEC
5964 +void pax_report_insns(void *pc, void *sp)
5968 + printk(KERN_ERR "PAX: bytes at PC: ");
5969 + for (i = 0; i < 20; i++) {
5971 + if (get_user(c, (unsigned char __user *)pc+i))
5974 + printk("%02x ", c);
5978 + printk(KERN_ERR "PAX: bytes at SP-8: ");
5979 + for (i = -1; i < 10; i++) {
5981 + if (get_user(c, (unsigned long __user *)sp+i))
5982 + printk("???????????????? ");
5984 + printk("%016lx ", c);
5990 int page_fault_trace = 0;
5991 int exception_trace = 1;
5993 @@ -416,6 +444,8 @@ asmlinkage void __kprobes do_page_fault(
5995 info.si_code = SEGV_ACCERR;
5997 + if ((error_code & PF_INSTR) && !(vma->vm_flags & VM_EXEC))
5999 switch (error_code & (PF_PROT|PF_WRITE)) {
6000 default: /* 3: write, present */
6002 @@ -482,7 +512,14 @@ bad_area_nosemaphore:
6003 tsk->comm, tsk->pid, address, regs->rip,
6004 regs->rsp, error_code);
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);
6015 tsk->thread.cr2 = address;
6016 /* Kernel addresses are always protection faults */
6017 tsk->thread.error_code = error_code | (address >= TASK_SIZE);
6018 diff -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;
6026 +#ifdef CONFIG_PAX_RANDMMAP
6027 + if (mm->pax_flags & MF_PAX_RANDMMAP)
6028 + mm->mmap_base += mm->delta_mmap;
6031 mm->get_unmapped_area = arch_get_unmapped_area;
6032 mm->unmap_area = arch_unmap_area;
6034 diff -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)))
6041 - if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment))
6042 + if ((unsigned) reserve.seg_count >= ~0U/sizeof(struct agp_segment_priv))
6045 client = agp_find_client_by_pid(reserve.pid);
6046 diff -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 */
6054 +#if defined(CONFIG_GRKERNSEC_PROC) || defined(CONFIG_GRKERNSEC_PROC_MEMMAP)
6056 + void *func = fn_handler[value];
6057 + if (func == fn_show_state || func == fn_show_ptregs ||
6058 + func == fn_show_mem)
6063 fn_handler[value](vc, regs);
6066 diff -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
6070 #include <linux/crash_dump.h>
6071 #include <linux/backing-dev.h>
6072 #include <linux/bootmem.h>
6073 +#include <linux/grsecurity.h>
6075 #include <asm/uaccess.h>
6078 # include <linux/efi.h>
6081 +#ifdef CONFIG_GRKERNSEC
6082 +extern struct file_operations grsec_fops;
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))
6092 +#ifdef CONFIG_GRKERNSEC_KMEM
6093 + gr_handle_mem_write();
6099 #ifdef __ARCH_HAS_NO_PAGE_ZERO_MAPPED
6100 @@ -258,6 +268,11 @@ static int mmap_mem(struct file * file,
6104 +#ifdef CONFIG_GRKERNSEC_KMEM
6105 + if (gr_handle_mem_mmap(vma->vm_pgoff << PAGE_SHIFT, vma))
6109 /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */
6110 if (remap_pfn_range(vma,
6112 @@ -487,6 +502,11 @@ static ssize_t write_kmem(struct file *
6114 char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */
6116 +#ifdef CONFIG_GRKERNSEC_KMEM
6117 + gr_handle_kmem_write();
6121 if (p < (unsigned long) high_memory) {
6124 @@ -613,7 +633,23 @@ static inline size_t read_zero_pagealign
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);
6131 +#ifdef CONFIG_PAX_SEGMEXEC
6132 + if (vma->vm_flags & VM_MIRROR) {
6133 + unsigned long addr_m;
6134 + struct vm_area_struct * vma_m;
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);
6142 + printk(KERN_ERR "PAX: VMMIRROR: read_zero bug, %08lx, %08lx\n",
6143 + addr, vma->vm_start);
6149 @@ -762,6 +798,16 @@ static loff_t memory_lseek(struct file *
6151 static int open_port(struct inode * inode, struct file * filp)
6153 +#ifdef CONFIG_GRKERNSEC_KMEM
6154 + gr_handle_open_port();
6158 + return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
6161 +static int open_mem(struct inode * inode, struct file * filp)
6163 return capable(CAP_SYS_RAWIO) ? 0 : -EPERM;
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
6174 @@ -891,6 +936,11 @@ static int memory_open(struct inode * in
6175 filp->f_op = &oldmem_fops;
6178 +#ifdef CONFIG_GRKERNSEC
6180 + filp->f_op = &grsec_fops;
6186 @@ -923,6 +973,9 @@ static const struct {
6187 #ifdef CONFIG_CRASH_DUMP
6188 {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
6190 +#ifdef CONFIG_GRKERNSEC
6191 + {13,"grsec", S_IRUSR | S_IWUGO, &grsec_fops},
6195 static struct class *mem_class;
6196 diff -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 @@
6201 * Configuration information
6203 +#ifdef CONFIG_GRKERNSEC_RANDNET
6204 +#define INPUT_POOL_WORDS 256
6205 +#define OUTPUT_POOL_WORDS 64
6207 #define INPUT_POOL_WORDS 128
6208 #define OUTPUT_POOL_WORDS 32
6210 #define SEC_XFER_SIZE 512
6213 @@ -1659,3 +1664,25 @@ randomize_range(unsigned long start, uns
6215 return PAGE_ALIGN(get_random_int() % range + start);
6218 +#if defined(CONFIG_PAX_ASLR) || defined(CONFIG_GRKERNSEC)
6219 +unsigned long pax_get_random_long(void)
6221 + static time_t rekey_time;
6222 + static __u32 secret[12];
6226 + * Pick a random secret every REKEY_INTERVAL seconds.
6228 + t = get_seconds();
6229 + if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) {
6231 + get_random_bytes(secret, sizeof(secret));
6234 + secret[1] = half_md4_transform(secret+8, secret);
6235 + secret[0] = half_md4_transform(secret+8, secret);
6236 + return *(unsigned long *)secret;
6239 diff -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 __
6247 +#ifdef CONFIG_GRKERNSEC
6248 + if (!capable(CAP_SYS_TTY_CONFIG))
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
6259 +#ifdef CONFIG_GRKERNSEC
6260 + if (!capable(CAP_SYS_TTY_CONFIG)) {
6267 first_free = funcbufptr + (funcbufsize - funcbufleft);
6268 for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++)
6269 diff -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)
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).");
6282 static void dma_trm_tasklet(unsigned long data);
6283 static void dma_trm_reset(struct dma_trm_ctx *d);
6284 diff -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)
6294 /* Don't allow a single read to cross a 512-byte block boundary */
6295 if (from + len > ((from | 0x1ff) + 1))
6296 diff -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;
6308 @@ -475,6 +475,7 @@ static int update(struct wan_device *wan
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;
6315 /* wait a maximum of 1 second for the statistics to be updated */
6316 diff -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
6321 static void legacy_proc_init(void)
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);
6330 struct proc_dir_entry * entry = create_proc_entry("pci", 0, NULL);
6333 entry->proc_fops = &proc_pci_operations;
6335 @@ -598,7 +606,15 @@ static int __init pci_proc_init(void)
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);
6346 proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
6348 entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
6350 entry->proc_fops = &proc_bus_pci_dev_operations;
6351 diff -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); \
6358 -static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
6359 +static struct desc_struct bad_bios_desc = { 0, 0x00409300 };
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;
6367 +#ifdef CONFIG_PAX_KERNEXEC
6368 + unsigned long cr0;
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);
6378 +#ifdef CONFIG_PAX_KERNEXEC
6379 + pax_open_kernel(cr0);
6382 /* The lock prevents us bouncing CPU here */
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
6389 - spin_unlock_irqrestore(&pnp_bios_lock, flags);
6391 get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40;
6393 +#ifdef CONFIG_PAX_KERNEXEC
6394 + pax_close_kernel(cr0);
6397 + spin_unlock_irqrestore(&pnp_bios_lock, flags);
6400 /* If we get here and this is set then the PnP BIOS faulted on us. */
6401 diff -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
6404 @@ -1553,7 +1553,7 @@ unsigned int ata_scsiop_inq_80(struct at
6408 -static const char * const inq_83_str = "Linux ATA-SCSI simulator";
6409 +static const char inq_83_str[] = "Linux ATA-SCSI simulator";
6412 * ata_scsiop_inq_83 - Simulate INQUIRY EVPD page 83, device identity
6413 @@ -1572,13 +1572,13 @@ unsigned int ata_scsiop_inq_83(struct at
6414 unsigned int buflen)
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 */
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);
6431 diff -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;
6439 +#if !defined(__i386__) || defined(CONFIG_PAX_KERNEXEC)
6440 screen_info.vesapm_seg = 0;
6443 diff -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
6447 #include <linux/binfmts.h>
6448 #include <linux/personality.h>
6449 #include <linux/init.h>
6450 +#include <linux/grsecurity.h>
6452 #include <asm/system.h>
6453 #include <asm/uaccess.h>
6454 @@ -123,10 +124,12 @@ static int aout_core_dump(long signr, st
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. */
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)
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)
6467 @@ -134,10 +137,12 @@ static int aout_core_dump(long signr, st
6469 /* Make sure we have enough room to write the stack and data areas. */
6471 + gr_learn_resource(current, RLIMIT_CORE, dump.u_ssize, 1);
6472 if ((dump.u_ssize) >
6473 current->signal->rlim[RLIMIT_CORE].rlim_cur)
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)
6480 @@ -287,6 +292,8 @@ static int load_aout_binary(struct linux
6481 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
6482 if (rlim >= RLIM_INFINITY)
6485 + gr_learn_resource(current, RLIMIT_DATA, ex.a_data + ex.a_bss, 1);
6486 if (ex.a_data + ex.a_bss > rlim)
6489 @@ -319,6 +326,28 @@ static int load_aout_binary(struct linux
6490 current->mm->mmap = NULL;
6491 compute_creds(bprm);
6492 current->flags &= ~PF_FORKNOEXEC;
6494 +#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
6495 + current->mm->pax_flags = 0UL;
6498 +#ifdef CONFIG_PAX_PAGEEXEC
6499 + if (!(N_FLAGS(ex) & F_PAX_PAGEEXEC)) {
6500 + current->mm->pax_flags |= MF_PAX_PAGEEXEC;
6502 +#ifdef CONFIG_PAX_EMUTRAMP
6503 + if (N_FLAGS(ex) & F_PAX_EMUTRAMP)
6504 + current->mm->pax_flags |= MF_PAX_EMUTRAMP;
6507 +#ifdef CONFIG_PAX_MPROTECT
6508 + if (!(N_FLAGS(ex) & F_PAX_MPROTECT))
6509 + current->mm->pax_flags |= MF_PAX_MPROTECT;
6516 if (N_MAGIC(ex) == NMAGIC) {
6517 loff_t pos = fd_offset;
6518 @@ -414,7 +443,7 @@ static int load_aout_binary(struct linux
6520 down_write(¤t->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(¤t->mm->mmap_sem);
6527 diff -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
6531 #include <linux/security.h>
6532 #include <linux/syscalls.h>
6533 #include <linux/random.h>
6534 +#include <linux/grsecurity.h>
6536 #include <asm/uaccess.h>
6537 #include <asm/param.h>
6538 #include <asm/page.h>
6540 +#ifdef CONFIG_PAX_SEGMEXEC
6541 +#include <asm/desc.h>
6544 #include <linux/elf.h>
6546 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
6547 @@ -90,6 +95,8 @@ static struct linux_binfmt elf_format =
6549 static int set_brk(unsigned long start, unsigned long end)
6551 + unsigned long e = end;
6553 start = ELF_PAGEALIGN(start);
6554 end = ELF_PAGEALIGN(end);
6556 @@ -100,7 +107,7 @@ static int set_brk(unsigned long start,
6560 - current->mm->start_brk = current->mm->brk = end;
6561 + current->mm->start_brk = current->mm->brk = e;
6565 @@ -316,10 +323,9 @@ static unsigned long load_elf_interp(str
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;
6577 /* First of all, some simple consistency checks */
6578 @@ -358,59 +364,80 @@ static unsigned long load_elf_interp(str
6582 +#ifdef CONFIG_PAX_SEGMEXEC
6583 + if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
6584 + task_size = SEGMEXEC_TASK_SIZE;
6588 + min_addr = task_size;
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;
6596 - unsigned long vaddr = 0;
6597 - unsigned long k, map_addr;
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;
6606 - map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
6608 - if (BAD_ADDR(map_addr))
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;
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.
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) {
6625 + if (eppnt->p_type != PT_LOAD)
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.
6633 + if (eppnt->p_filesz > eppnt->p_memsz || eppnt->p_vaddr >= eppnt->p_vaddr + eppnt->p_memsz)
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);
6641 + if (min_addr >= max_addr)
6646 - * Find the end of the file mapping for this phdr, and keep
6647 - * track of the largest address we see for this.
6649 - k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
6654 - * Do the same thing for the memory mapping - between
6655 - * elf_bss and last_bss is the bss section.
6657 - k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
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;
6665 + unsigned long vaddr;
6666 + unsigned long k, map_addr;
6668 + if (eppnt->p_type != PT_LOAD)
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;
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);
6679 + if (load_addr > task_size)
6682 + load_addr -= min_addr;
6685 + map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);
6687 + if (BAD_ADDR(map_addr))
6691 + * Find the end of the file mapping for this phdr, and keep
6692 + * track of the largest address we see for this.
6694 + k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
6699 + * Do the same thing for the memory mapping - between
6700 + * elf_bss and last_bss is the bss section.
6702 + k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
6708 @@ -447,7 +474,7 @@ out:
6709 static unsigned long load_aout_interp(struct exec * interp_ex,
6710 struct file * interpreter)
6712 - unsigned long text_data, elf_entry = ~0UL;
6713 + unsigned long text_data, elf_entry = -EINVAL;
6717 @@ -491,6 +518,180 @@ out:
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)
6724 + unsigned long pax_flags = 0UL;
6726 +#ifdef CONFIG_PAX_PAGEEXEC
6727 + if (elf_phdata->p_flags & PF_PAGEEXEC)
6728 + pax_flags |= MF_PAX_PAGEEXEC;
6731 +#ifdef CONFIG_PAX_SEGMEXEC
6732 + if (elf_phdata->p_flags & PF_SEGMEXEC)
6733 + pax_flags |= MF_PAX_SEGMEXEC;
6736 +#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
6737 + if (pax_flags & MF_PAX_PAGEEXEC)
6738 + pax_flags &= ~MF_PAX_SEGMEXEC;
6741 +#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
6742 + if (pax_flags & MF_PAX_SEGMEXEC)
6743 + pax_flags &= ~MF_PAX_PAGEEXEC;
6746 +#ifdef CONFIG_PAX_EMUTRAMP
6747 + if (elf_phdata->p_flags & PF_EMUTRAMP)
6748 + pax_flags |= MF_PAX_EMUTRAMP;
6751 +#ifdef CONFIG_PAX_MPROTECT
6752 + if (elf_phdata->p_flags & PF_MPROTECT)
6753 + pax_flags |= MF_PAX_MPROTECT;
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;
6765 +#ifdef CONFIG_PAX_PT_PAX_FLAGS
6766 +static unsigned long pax_parse_hardmode(const struct elf_phdr * const elf_phdata)
6768 + unsigned long pax_flags = 0UL;
6770 +#ifdef CONFIG_PAX_PAGEEXEC
6771 + if (!(elf_phdata->p_flags & PF_NOPAGEEXEC))
6772 + pax_flags |= MF_PAX_PAGEEXEC;
6775 +#ifdef CONFIG_PAX_SEGMEXEC
6776 + if (!(elf_phdata->p_flags & PF_NOSEGMEXEC))
6777 + pax_flags |= MF_PAX_SEGMEXEC;
6780 +#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
6781 + if (pax_flags & MF_PAX_PAGEEXEC)
6782 + pax_flags &= ~MF_PAX_SEGMEXEC;
6785 +#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
6786 + if (pax_flags & MF_PAX_SEGMEXEC)
6787 + pax_flags &= ~MF_PAX_PAGEEXEC;
6790 +#ifdef CONFIG_PAX_EMUTRAMP
6791 + if (!(elf_phdata->p_flags & PF_NOEMUTRAMP))
6792 + pax_flags |= MF_PAX_EMUTRAMP;
6795 +#ifdef CONFIG_PAX_MPROTECT
6796 + if (!(elf_phdata->p_flags & PF_NOMPROTECT))
6797 + pax_flags |= MF_PAX_MPROTECT;
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;
6809 +#ifdef CONFIG_PAX_EI_PAX
6810 +static unsigned long pax_parse_ei_pax(const struct elfhdr * const elf_ex)
6812 + unsigned long pax_flags = 0UL;
6814 +#ifdef CONFIG_PAX_PAGEEXEC
6815 + if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_PAGEEXEC))
6816 + pax_flags |= MF_PAX_PAGEEXEC;
6819 +#ifdef CONFIG_PAX_SEGMEXEC
6820 + if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_SEGMEXEC))
6821 + pax_flags |= MF_PAX_SEGMEXEC;
6824 +#ifdef CONFIG_PAX_DEFAULT_PAGEEXEC
6825 + if (pax_flags & MF_PAX_PAGEEXEC)
6826 + pax_flags &= ~MF_PAX_SEGMEXEC;
6829 +#ifdef CONFIG_PAX_DEFAULT_SEGMEXEC
6830 + if (pax_flags & MF_PAX_SEGMEXEC)
6831 + pax_flags &= ~MF_PAX_PAGEEXEC;
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;
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;
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;
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)
6856 + unsigned long pax_flags = 0UL;
6858 +#ifdef CONFIG_PAX_PT_PAX_FLAGS
6862 +#ifdef CONFIG_PAX_EI_PAX
6863 + pax_flags = pax_parse_ei_pax(elf_ex);
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)))
6876 +#ifdef CONFIG_PAX_SOFTMODE
6878 + pax_flags = pax_parse_softmode(&elf_phdata[i]);
6882 + pax_flags = pax_parse_hardmode(&elf_phdata[i]);
6887 + if (0 > pax_check_flags(&pax_flags))
6890 + current->mm->pax_flags = pax_flags;
6896 * These are the functions used to load ELF style executables and shared
6897 * libraries. There is no binary dependent code anywhere else.
6898 @@ -522,7 +723,7 @@ static int load_elf_binary(struct linux_
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;
6907 @@ -540,6 +741,7 @@ static int load_elf_binary(struct linux_
6908 struct elfhdr interp_elf_ex;
6909 struct exec interp_ex;
6911 + unsigned long task_size = TASK_SIZE;
6913 loc = kmalloc(sizeof(*loc), GFP_KERNEL);
6915 @@ -765,14 +967,88 @@ static int load_elf_binary(struct linux_
6916 current->mm->end_code = 0;
6917 current->mm->mmap = NULL;
6918 current->flags &= ~PF_FORKNOEXEC;
6920 +#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
6921 + current->mm->pax_flags = 0UL;
6924 +#ifdef CONFIG_PAX_DLRESOLVE
6925 + current->mm->call_dl_resolve = 0UL;
6928 +#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
6929 + current->mm->call_syscall = 0UL;
6932 +#ifdef CONFIG_PAX_ASLR
6933 + current->mm->delta_mmap = 0UL;
6934 + current->mm->delta_exec = 0UL;
6935 + current->mm->delta_stack = 0UL;
6938 current->mm->def_flags = def_flags;
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;
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);
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;
6959 +#ifdef CONFIG_PAX_SEGMEXEC
6960 + if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
6961 + int cpu = get_cpu();
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);
6967 + task_size = SEGMEXEC_TASK_SIZE;
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))
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));
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;
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);
6990 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
6991 + if (!(current->mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)))
6994 if (elf_read_implies_exec(loc->elf_ex, executable_stack))
6995 current->personality |= READ_IMPLIES_EXEC;
6997 +#ifdef CONFIG_PAX_ASLR
6998 + if (!(current->mm->pax_flags & MF_PAX_RANDMMAP))
7001 if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
7002 current->flags |= PF_RANDOMIZE;
7003 arch_pick_mmap_layout(current->mm);
7004 @@ -844,6 +1120,15 @@ static int load_elf_binary(struct linux_
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);
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;
7019 error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags);
7020 @@ -871,9 +1156,9 @@ static int load_elf_binary(struct linux_
7021 * allowed task size. Note that p_filesz must always be
7022 * <= p_memsz so it is only necessary to check p_memsz.
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;
7033 @@ -900,6 +1185,12 @@ static int load_elf_binary(struct linux_
7034 start_data += load_bias;
7035 end_data += load_bias;
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
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
7046 @@ -928,7 +1219,7 @@ static int load_elf_binary(struct linux_
7047 printk(KERN_ERR "Unable to load interpreter %.128s\n",
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;
7054 reloc_func_desc = interp_load_addr;
7055 @@ -1152,7 +1443,7 @@ static int dump_seek(struct file *file,
7057 * I think we should skip something. But I am not sure how. H.J.
7059 -static int maydump(struct vm_area_struct *vma)
7060 +static int maydump(struct vm_area_struct *vma, long signr)
7062 /* Do not dump I/O mapped devices or special mappings */
7063 if (vma->vm_flags & (VM_IO | VM_RESERVED))
7064 @@ -1163,7 +1454,7 @@ static int maydump(struct vm_area_struct
7065 return vma->vm_file->f_dentry->d_inode->i_nlink == 0;
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)
7073 @@ -1217,8 +1508,11 @@ static int writenote(struct memelfnote *
7076 #define DUMP_WRITE(addr, nr) \
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; \
7083 #define DUMP_SEEK(off) \
7084 if (!dump_seek(file, (off))) \
7086 @@ -1569,7 +1863,7 @@ static int elf_core_dump(long signr, str
7087 phdr.p_offset = offset;
7088 phdr.p_vaddr = vma->vm_start;
7090 - phdr.p_filesz = maydump(vma) ? sz : 0;
7091 + phdr.p_filesz = maydump(vma, signr) ? sz : 0;
7093 offset += phdr.p_filesz;
7094 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
7095 @@ -1602,7 +1896,7 @@ static int elf_core_dump(long signr, str
7096 for (vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
7099 - if (!maydump(vma))
7100 + if (!maydump(vma, signr))
7103 for (addr = vma->vm_start;
7104 @@ -1621,6 +1915,7 @@ static int elf_core_dump(long signr, str
7106 flush_cache_page(vma, addr, page_to_pfn(page));
7108 + gr_learn_resource(current, RLIMIT_CORE, size + PAGE_SIZE, 1);
7109 if ((size += PAGE_SIZE) > limit ||
7110 !dump_write(file, kaddr,
7112 diff -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
7115 @@ -541,7 +541,9 @@ static int load_flat_file(struct linux_b
7116 realdatastart = (unsigned long) -ENOMEM;
7117 printk("Unable to allocate RAM for process data, errno %d\n",
7119 + down_write(¤t->mm->mmap_sem);
7120 do_munmap(current->mm, textpos, text_len);
7121 + up_write(¤t->mm->mmap_sem);
7122 return realdatastart;
7124 datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long);
7125 @@ -562,8 +564,10 @@ static int load_flat_file(struct linux_b
7127 if (result >= (unsigned long)-4096) {
7128 printk("Unable to read data+bss, errno %d\n", (int)-result);
7129 + down_write(¤t->mm->mmap_sem);
7130 do_munmap(current->mm, textpos, text_len);
7131 do_munmap(current->mm, realdatastart, data_len + extra);
7132 + up_write(¤t->mm->mmap_sem);
7136 @@ -625,8 +629,10 @@ static int load_flat_file(struct linux_b
7138 if (result >= (unsigned long)-4096) {
7139 printk("Unable to read code+data+bss, errno %d\n",(int)-result);
7140 + down_write(¤t->mm->mmap_sem);
7141 do_munmap(current->mm, textpos, text_len + data_len + extra +
7142 MAX_SHARED_LIBS * sizeof(unsigned long));
7143 + up_write(¤t->mm->mmap_sem);
7147 diff -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;
7155 + if (!enabled || bprm->misc)
7160 /* to keep locking time low, we copy the interpreter string */
7161 read_lock(&entries_lock);
7162 fmt = check_file(bprm);
7163 diff -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
7167 #include <linux/bitops.h>
7168 #include <linux/mpage.h>
7169 #include <linux/bit_spinlock.h>
7170 +#include <linux/grsecurity.h>
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
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);
7182 diff -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
7186 #include <linux/rwsem.h>
7187 #include <linux/acct.h>
7188 #include <linux/mm.h>
7189 +#include <linux/grsecurity.h>
7191 #include <net/sock.h> /* siocdevprivate_ioctl */
7193 @@ -1476,6 +1477,11 @@ int compat_do_execve(char * filename,
7197 +#ifdef CONFIG_GRKERNSEC
7198 + struct file *old_exec_file;
7199 + struct acl_subject_label *old_acl;
7200 + struct rlimit old_rlim[RLIM_NLIMITS];
7204 bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
7205 @@ -1494,6 +1500,15 @@ int compat_do_execve(char * filename,
7207 bprm->filename = filename;
7208 bprm->interp = filename;
7210 + gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes), 1);
7212 + if (gr_handle_nproc())
7215 + if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt))
7218 bprm->mm = mm_alloc();
7221 @@ -1532,10 +1547,39 @@ int compat_do_execve(char * filename,
7225 + if (!gr_tpe_allow(file)) {
7230 + if (gr_check_crash_exec(file)) {
7235 + gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
7237 + gr_handle_exec_args(bprm, (char __user * __user *)argv);
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;
7244 + current->exec_file = file;
7247 + gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
7249 retval = search_binary_handler(bprm, regs);
7251 free_arg_pages(bprm);
7253 +#ifdef CONFIG_GRKERNSEC
7254 + if (old_exec_file)
7255 + fput(old_exec_file);
7258 /* execve success */
7259 security_bprm_free(bprm);
7260 acct_update_integrals(current);
7261 @@ -1543,6 +1587,13 @@ int compat_do_execve(char * filename,
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;
7273 /* Something went wrong, return the inode and free the argument pages*/
7274 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
7275 diff -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
7278 @@ -1360,7 +1360,7 @@ already_unhashed:
7280 * "buflen" should be positive. Caller holds the dcache_lock.
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)
7287 diff -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
7291 #include <linux/rmap.h>
7292 #include <linux/acct.h>
7293 #include <linux/cn_proc.h>
7294 +#include <linux/random.h>
7295 +#include <linux/grsecurity.h>
7297 #include <asm/uaccess.h>
7298 #include <asm/mmu_context.h>
7299 @@ -67,6 +69,15 @@ EXPORT_SYMBOL(suid_dumpable);
7300 static struct linux_binfmt *formats;
7301 static DEFINE_RWLOCK(binfmt_lock);
7303 +#ifdef CONFIG_PAX_SOFTMODE
7304 +unsigned int pax_softmode;
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);
7312 int register_binfmt(struct linux_binfmt * fmt)
7314 struct linux_binfmt ** tmp = &formats;
7315 @@ -312,6 +323,10 @@ void install_arg_page(struct vm_area_str
7316 if (unlikely(anon_vma_prepare(vma)))
7319 +#ifdef CONFIG_PAX_SEGMEXEC
7320 + if (page_count(page) == 1)
7323 flush_dcache_page(page);
7324 pte = get_locked_pte(mm, address, &ptl);
7326 @@ -321,9 +336,21 @@ void install_arg_page(struct vm_area_str
7329 inc_mm_counter(mm, anon_rss);
7331 +#ifdef CONFIG_PAX_SEGMEXEC
7332 + if (page_count(page) == 1)
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))));
7339 +#ifdef CONFIG_PAX_SEGMEXEC
7340 + if (page_count(page) != 1)
7341 + page_add_anon_rmap(page, vma, address);
7345 page_add_new_anon_rmap(page, vma, address);
7346 pte_unmap_unlock(pte, ptl);
7348 @@ -346,6 +373,10 @@ int setup_arg_pages(struct linux_binprm
7352 +#ifdef CONFIG_PAX_SEGMEXEC
7353 + struct vm_area_struct *mpnt_m = NULL;
7356 #ifdef CONFIG_STACK_GROWSUP
7357 /* Move the argument and environment strings to the bottom of the
7359 @@ -410,6 +441,18 @@ int setup_arg_pages(struct linux_binprm
7361 memset(mpnt, 0, sizeof(*mpnt));
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);
7367 + kmem_cache_free(vm_area_cachep, mpnt);
7371 + memset(mpnt_m, 0, sizeof(*mpnt_m));
7375 down_write(&mm->mmap_sem);
7378 @@ -430,13 +473,50 @@ int setup_arg_pages(struct linux_binprm
7380 mpnt->vm_flags = VM_STACK_FLAGS;
7381 mpnt->vm_flags |= mm->def_flags;
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];
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);
7394 +#ifdef CONFIG_PAX_SEGMEXEC
7396 + kmem_cache_free(vm_area_cachep, mpnt_m);
7401 mm->stack_vm = mm->total_vm = vma_pages(mpnt);
7403 +#ifdef CONFIG_PAX_SEGMEXEC
7406 + if (!(mpnt->vm_flags & VM_EXEC)) {
7407 + mpnt_m->vm_flags &= ~(VM_READ | VM_WRITE | VM_EXEC);
7408 + mpnt_m->vm_page_prot = PAGE_NONE;
7410 + mpnt_m->vm_start += SEGMEXEC_TASK_SIZE;
7411 + mpnt_m->vm_end += SEGMEXEC_TASK_SIZE;
7412 + if ((ret = insert_vm_struct(mm, mpnt_m))) {
7413 + up_write(&mm->mmap_sem);
7414 + kmem_cache_free(vm_area_cachep, mpnt_m);
7417 + mpnt_m->vm_flags |= VM_MIRROR;
7418 + mpnt->vm_flags |= VM_MIRROR;
7419 + mpnt_m->vm_mirror = mpnt->vm_start - mpnt_m->vm_start;
7420 + mpnt->vm_mirror = mpnt_m->vm_start - mpnt->vm_start;
7421 + mpnt_m->vm_pgoff = mpnt->vm_pgoff;
7422 + mm->total_vm += vma_pages(mpnt_m);
7428 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
7429 @@ -444,6 +524,14 @@ int setup_arg_pages(struct linux_binprm
7431 bprm->page[i] = NULL;
7432 install_arg_page(mpnt, page, stack_base);
7434 +#ifdef CONFIG_PAX_SEGMEXEC
7436 + page_cache_get(page);
7437 + install_arg_page(mpnt_m, page, stack_base + SEGMEXEC_TASK_SIZE);
7442 stack_base += PAGE_SIZE;
7444 @@ -1141,6 +1229,11 @@ int do_execve(char * filename,
7448 +#ifdef CONFIG_GRKERNSEC
7449 + struct file *old_exec_file;
7450 + struct acl_subject_label *old_acl;
7451 + struct rlimit old_rlim[RLIM_NLIMITS];
7455 bprm = kmalloc(sizeof(*bprm), GFP_KERNEL);
7456 @@ -1153,10 +1246,29 @@ int do_execve(char * filename,
7460 + gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes), 1);
7462 + if (gr_handle_nproc()) {
7463 + allow_write_access(file);
7468 + if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) {
7469 + allow_write_access(file);
7476 bprm->p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
7478 +#ifdef CONFIG_PAX_RANDUSTACK
7479 + if (randomize_va_space)
7480 + bprm->p -= (pax_get_random_long() & ~(sizeof(void *)-1)) & ~PAGE_MASK;
7484 bprm->filename = filename;
7485 bprm->interp = filename;
7486 @@ -1198,8 +1310,38 @@ int do_execve(char * filename,
7490 + if (!gr_tpe_allow(file)) {
7495 + if (gr_check_crash_exec(file)) {
7500 + gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt);
7502 + gr_handle_exec_args(bprm, argv);
7504 +#ifdef CONFIG_GRKERNSEC
7505 + old_acl = current->acl;
7506 + memcpy(old_rlim, current->signal->rlim, sizeof(old_rlim));
7507 + old_exec_file = current->exec_file;
7509 + current->exec_file = file;
7512 + retval = gr_set_proc_label(file->f_dentry, file->f_vfsmnt);
7516 retval = search_binary_handler(bprm,regs);
7518 +#ifdef CONFIG_GRKERNSEC
7519 + if (old_exec_file)
7520 + fput(old_exec_file);
7522 free_arg_pages(bprm);
7524 /* execve success */
7525 @@ -1209,6 +1351,14 @@ int do_execve(char * filename,
7530 +#ifdef CONFIG_GRKERNSEC
7531 + current->acl = old_acl;
7532 + memcpy(current->signal->rlim, old_rlim, sizeof(old_rlim));
7533 + fput(current->exec_file);
7534 + current->exec_file = old_exec_file;
7538 /* Something went wrong, return the inode and free the argument pages*/
7539 for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
7540 @@ -1369,6 +1519,114 @@ static void format_corename(char *corena
7544 +int pax_check_flags(unsigned long * flags)
7548 +#if !defined(__i386__) || !defined(CONFIG_PAX_SEGMEXEC)
7549 + if (*flags & MF_PAX_SEGMEXEC)
7551 + *flags &= ~MF_PAX_SEGMEXEC;
7556 + if ((*flags & MF_PAX_PAGEEXEC)
7558 +#ifdef CONFIG_PAX_PAGEEXEC
7559 + && (*flags & MF_PAX_SEGMEXEC)
7564 + *flags &= ~MF_PAX_PAGEEXEC;
7568 + if ((*flags & MF_PAX_MPROTECT)
7570 +#ifdef CONFIG_PAX_MPROTECT
7571 + && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
7576 + *flags &= ~MF_PAX_MPROTECT;
7580 + if ((*flags & MF_PAX_EMUTRAMP)
7582 +#ifdef CONFIG_PAX_EMUTRAMP
7583 + && !(*flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC))
7588 + *flags &= ~MF_PAX_EMUTRAMP;
7595 +EXPORT_SYMBOL(pax_check_flags);
7597 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
7598 +void pax_report_fault(struct pt_regs *regs, void *pc, void *sp)
7600 + struct task_struct *tsk = current;
7601 + struct mm_struct *mm = current->mm;
7602 + char* buffer_exec = (char*)__get_free_page(GFP_ATOMIC);
7603 + char* buffer_fault = (char*)__get_free_page(GFP_ATOMIC);
7604 + char* path_exec=NULL;
7605 + char* path_fault=NULL;
7606 + unsigned long start=0UL, end=0UL, offset=0UL;
7608 + if (buffer_exec && buffer_fault) {
7609 + struct vm_area_struct* vma, * vma_exec=NULL, * vma_fault=NULL;
7611 + down_read(&mm->mmap_sem);
7613 + while (vma && (!vma_exec || !vma_fault)) {
7614 + if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file)
7616 + if (vma->vm_start <= (unsigned long)pc && (unsigned long)pc < vma->vm_end)
7618 + vma = vma->vm_next;
7621 + path_exec = d_path(vma_exec->vm_file->f_dentry, vma_exec->vm_file->f_vfsmnt, buffer_exec, PAGE_SIZE);
7622 + if (IS_ERR(path_exec))
7623 + path_exec = "<path too long>";
7626 + start = vma_fault->vm_start;
7627 + end = vma_fault->vm_end;
7628 + offset = vma_fault->vm_pgoff << PAGE_SHIFT;
7629 + if (vma_fault->vm_file) {
7630 + path_fault = d_path(vma_fault->vm_file->f_dentry, vma_fault->vm_file->f_vfsmnt, buffer_fault, PAGE_SIZE);
7631 + if (IS_ERR(path_fault))
7632 + path_fault = "<path too long>";
7634 + path_fault = "<anonymous mapping>";
7636 + up_read(&mm->mmap_sem);
7638 + if (tsk->signal->curr_ip)
7639 + 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 + printk(KERN_ERR "PAX: execution attempt in: %s, %08lx-%08lx %08lx\n", path_fault, start, end, offset);
7642 + printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, "
7643 + "PC: %p, SP: %p\n", path_exec, tsk->comm, tsk->pid,
7644 + tsk->uid, tsk->euid, pc, sp);
7645 + free_page((unsigned long)buffer_exec);
7646 + free_page((unsigned long)buffer_fault);
7647 + pax_report_insns(pc, sp);
7648 + do_coredump(SIGKILL, SIGKILL, regs);
7652 static void zap_threads (struct mm_struct *mm)
7654 struct task_struct *g, *p;
7655 @@ -1486,6 +1744,10 @@ int do_coredump(long signr, int exit_cod
7657 clear_thread_flag(TIF_SIGPENDING);
7659 + if (signr == SIGKILL || signr == SIGILL)
7660 + gr_handle_brute_attach(current);
7662 + gr_learn_resource(current, RLIMIT_CORE, binfmt->min_coredump, 1);
7663 if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump)
7666 diff -urNp linux-2.6.16.12/fs/fcntl.c linux-2.6.16.12/fs/fcntl.c
7667 --- linux-2.6.16.12/fs/fcntl.c 2006-05-01 15:14:26.000000000 -0400
7668 +++ linux-2.6.16.12/fs/fcntl.c 2006-05-01 20:17:33.000000000 -0400
7670 #include <linux/ptrace.h>
7671 #include <linux/signal.h>
7672 #include <linux/rcupdate.h>
7673 +#include <linux/grsecurity.h>
7675 #include <asm/poll.h>
7676 #include <asm/siginfo.h>
7677 @@ -63,6 +64,7 @@ static int locate_fd(struct files_struct
7678 struct fdtable *fdt;
7681 + gr_learn_resource(current, RLIMIT_NOFILE, orig_start, 0);
7682 if (orig_start >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
7685 @@ -83,6 +85,7 @@ repeat:
7689 + gr_learn_resource(current, RLIMIT_NOFILE, newfd, 0);
7690 if (newfd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
7693 @@ -142,6 +145,8 @@ asmlinkage long sys_dup2(unsigned int ol
7694 struct files_struct * files = current->files;
7695 struct fdtable *fdt;
7697 + gr_learn_resource(current, RLIMIT_NOFILE, newfd, 0);
7699 spin_lock(&files->file_lock);
7700 if (!(file = fcheck(oldfd)))
7702 @@ -428,7 +433,8 @@ static inline int sigio_perm(struct task
7703 return (((fown->euid == 0) ||
7704 (fown->euid == p->suid) || (fown->euid == p->uid) ||
7705 (fown->uid == p->suid) || (fown->uid == p->uid)) &&
7706 - !security_file_send_sigiotask(p, fown, sig));
7707 + !security_file_send_sigiotask(p, fown, sig) &&
7708 + !gr_check_protected_task(p) && !gr_pid_is_chrooted(p));
7711 static void send_sigio_to_task(struct task_struct *p,
7712 diff -urNp linux-2.6.16.12/fs/Kconfig linux-2.6.16.12/fs/Kconfig
7713 --- linux-2.6.16.12/fs/Kconfig 2006-05-01 15:14:26.000000000 -0400
7714 +++ linux-2.6.16.12/fs/Kconfig 2006-05-01 20:17:33.000000000 -0400
7715 @@ -794,7 +794,7 @@ config PROC_FS
7718 bool "/proc/kcore support" if !ARM
7719 - depends on PROC_FS && MMU
7720 + depends on PROC_FS && MMU && !GRKERNSEC_PROC_ADD
7723 bool "/proc/vmcore support (EXPERIMENTAL)"
7724 diff -urNp linux-2.6.16.12/fs/namei.c linux-2.6.16.12/fs/namei.c
7725 --- linux-2.6.16.12/fs/namei.c 2006-05-01 15:14:26.000000000 -0400
7726 +++ linux-2.6.16.12/fs/namei.c 2006-05-01 20:17:33.000000000 -0400
7728 #include <linux/file.h>
7729 #include <linux/fcntl.h>
7730 #include <linux/namei.h>
7731 +#include <linux/grsecurity.h>
7732 #include <asm/namei.h>
7733 #include <asm/uaccess.h>
7735 @@ -608,6 +609,13 @@ static inline int do_follow_link(struct
7736 err = security_inode_follow_link(path->dentry, nd);
7740 + if (gr_handle_follow_link(path->dentry->d_parent->d_inode,
7741 + path->dentry->d_inode, path->dentry, nd->mnt)) {
7746 current->link_count++;
7747 current->total_link_count++;
7749 @@ -951,11 +959,18 @@ return_reval:
7753 + if (!gr_acl_handle_hidden_file(nd->dentry, nd->mnt)) {
7759 dput_path(&next, nd);
7762 + if (!gr_acl_handle_hidden_file(nd->dentry, nd->mnt))
7768 @@ -1596,6 +1611,17 @@ int open_namei(int dfd, const char *path
7773 + if (gr_handle_rawio(nd->dentry->d_inode)) {
7778 + if (!gr_acl_handle_open(nd->dentry, nd->mnt, flag)) {
7786 @@ -1630,9 +1656,16 @@ do_last:
7788 /* Negative dentry, just create the file */
7789 if (!path.dentry->d_inode) {
7790 + if (!gr_acl_handle_creat(path.dentry, nd->dentry, nd->mnt, flag, mode)) {
7792 + mutex_unlock(&dir->d_inode->i_mutex);
7795 if (!IS_POSIXACL(dir->d_inode))
7796 mode &= ~current->fs->umask;
7797 error = vfs_create(dir->d_inode, path.dentry, mode, nd);
7799 + gr_handle_create(path.dentry, nd->mnt);
7800 mutex_unlock(&dir->d_inode->i_mutex);
7802 nd->dentry = path.dentry;
7803 @@ -1647,6 +1680,23 @@ do_last:
7805 * It already exists.
7808 + if (gr_handle_rawio(path.dentry->d_inode)) {
7809 + mutex_unlock(&dir->d_inode->i_mutex);
7813 + if (!gr_acl_handle_open(path.dentry, nd->mnt, flag)) {
7814 + mutex_unlock(&dir->d_inode->i_mutex);
7818 + if (gr_handle_fifo(path.dentry, nd->mnt, dir, flag, acc_mode)) {
7819 + mutex_unlock(&dir->d_inode->i_mutex);
7824 mutex_unlock(&dir->d_inode->i_mutex);
7827 @@ -1700,6 +1750,13 @@ do_link:
7828 error = security_inode_follow_link(path.dentry, nd);
7832 + if (gr_handle_follow_link(path.dentry->d_parent->d_inode, path.dentry->d_inode,
7833 + path.dentry, nd->mnt)) {
7838 error = __do_follow_link(&path, nd);
7841 @@ -1820,6 +1877,22 @@ asmlinkage long sys_mknodat(int dfd, con
7842 if (!IS_POSIXACL(nd.dentry->d_inode))
7843 mode &= ~current->fs->umask;
7844 if (!IS_ERR(dentry)) {
7845 + if (gr_handle_chroot_mknod(dentry, nd.mnt, mode)) {
7848 + mutex_unlock(&nd.dentry->d_inode->i_mutex);
7849 + path_release(&nd);
7853 + if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) {
7856 + mutex_unlock(&nd.dentry->d_inode->i_mutex);
7857 + path_release(&nd);
7861 switch (mode & S_IFMT) {
7862 case 0: case S_IFREG:
7863 error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd);
7864 @@ -1837,6 +1910,10 @@ asmlinkage long sys_mknodat(int dfd, con
7870 + gr_handle_create(dentry, nd.mnt);
7874 mutex_unlock(&nd.dentry->d_inode->i_mutex);
7875 @@ -1891,9 +1968,19 @@ asmlinkage long sys_mkdirat(int dfd, con
7876 dentry = lookup_create(&nd, 1);
7877 error = PTR_ERR(dentry);
7878 if (!IS_ERR(dentry)) {
7880 if (!IS_POSIXACL(nd.dentry->d_inode))
7881 mode &= ~current->fs->umask;
7882 - error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
7884 + if (!gr_acl_handle_mkdir(dentry, nd.dentry, nd.mnt))
7888 + error = vfs_mkdir(nd.dentry->d_inode, dentry, mode);
7891 + gr_handle_create(dentry, nd.mnt);
7895 mutex_unlock(&nd.dentry->d_inode->i_mutex);
7896 @@ -1977,6 +2064,8 @@ static long do_rmdir(int dfd, const char
7898 struct dentry *dentry;
7899 struct nameidata nd;
7900 + ino_t saved_ino = 0;
7901 + dev_t saved_dev = 0;
7903 name = getname(pathname);
7905 @@ -2001,7 +2090,21 @@ static long do_rmdir(int dfd, const char
7906 dentry = lookup_hash(&nd);
7907 error = PTR_ERR(dentry);
7908 if (!IS_ERR(dentry)) {
7909 - error = vfs_rmdir(nd.dentry->d_inode, dentry);
7911 + if (dentry->d_inode) {
7912 + if (dentry->d_inode->i_nlink <= 1) {
7913 + saved_ino = dentry->d_inode->i_ino;
7914 + saved_dev = dentry->d_inode->i_sb->s_dev;
7917 + if (!gr_acl_handle_rmdir(dentry, nd.mnt))
7922 + error = vfs_rmdir(nd.dentry->d_inode, dentry);
7923 + if (!error && (saved_dev || saved_ino))
7924 + gr_handle_delete(saved_ino, saved_dev);
7927 mutex_unlock(&nd.dentry->d_inode->i_mutex);
7928 @@ -2060,6 +2163,8 @@ static long do_unlinkat(int dfd, const c
7929 struct dentry *dentry;
7930 struct nameidata nd;
7931 struct inode *inode = NULL;
7932 + ino_t saved_ino = 0;
7933 + dev_t saved_dev = 0;
7935 name = getname(pathname);
7937 @@ -2075,13 +2180,26 @@ static long do_unlinkat(int dfd, const c
7938 dentry = lookup_hash(&nd);
7939 error = PTR_ERR(dentry);
7940 if (!IS_ERR(dentry)) {
7942 /* Why not before? Because we want correct error value */
7943 if (nd.last.name[nd.last.len])
7945 inode = dentry->d_inode;
7948 + if (inode->i_nlink <= 1) {
7949 + saved_ino = inode->i_ino;
7950 + saved_dev = inode->i_sb->s_dev;
7953 + if (!gr_acl_handle_unlink(dentry, nd.mnt))
7956 atomic_inc(&inode->i_count);
7957 - error = vfs_unlink(nd.dentry->d_inode, dentry);
7960 + error = vfs_unlink(nd.dentry->d_inode, dentry);
7961 + if (!error && (saved_ino || saved_dev))
7962 + gr_handle_delete(saved_ino, saved_dev);
7966 @@ -2159,7 +2277,15 @@ asmlinkage long sys_symlinkat(const char
7967 dentry = lookup_create(&nd, 0);
7968 error = PTR_ERR(dentry);
7969 if (!IS_ERR(dentry)) {
7970 - error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
7972 + if (!gr_acl_handle_symlink(dentry, nd.dentry, nd.mnt, from))
7976 + error = vfs_symlink(nd.dentry->d_inode, dentry, from, S_IALLUGO);
7979 + gr_handle_create(dentry, nd.mnt);
7982 mutex_unlock(&nd.dentry->d_inode->i_mutex);
7983 @@ -2251,7 +2377,20 @@ asmlinkage long sys_linkat(int olddfd, c
7984 new_dentry = lookup_create(&nd, 0);
7985 error = PTR_ERR(new_dentry);
7986 if (!IS_ERR(new_dentry)) {
7987 - error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
7989 + if (gr_handle_hardlink(old_nd.dentry, old_nd.mnt,
7990 + old_nd.dentry->d_inode,
7991 + old_nd.dentry->d_inode->i_mode, to))
7993 + if (!gr_acl_handle_link(new_dentry, nd.dentry, nd.mnt,
7994 + old_nd.dentry, old_nd.mnt, to))
7997 + error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry);
8000 + gr_handle_create(new_dentry, nd.mnt);
8004 mutex_unlock(&nd.dentry->d_inode->i_mutex);
8005 @@ -2477,8 +2616,16 @@ static int do_rename(int olddfd, const c
8006 if (new_dentry == trap)
8009 - error = vfs_rename(old_dir->d_inode, old_dentry,
8010 + error = gr_acl_handle_rename(new_dentry, newnd.dentry, newnd.mnt,
8011 + old_dentry, old_dir->d_inode, oldnd.mnt,
8015 + error = vfs_rename(old_dir->d_inode, old_dentry,
8016 new_dir->d_inode, new_dentry);
8018 + gr_handle_rename(old_dir->d_inode, newnd.dentry->d_inode, old_dentry,
8019 + new_dentry, oldnd.mnt, new_dentry->d_inode ? 1 : 0);
8023 diff -urNp linux-2.6.16.12/fs/namespace.c linux-2.6.16.12/fs/namespace.c
8024 --- linux-2.6.16.12/fs/namespace.c 2006-05-01 15:14:26.000000000 -0400
8025 +++ linux-2.6.16.12/fs/namespace.c 2006-05-01 20:17:33.000000000 -0400
8027 #include <linux/namei.h>
8028 #include <linux/security.h>
8029 #include <linux/mount.h>
8030 +#include <linux/sched.h>
8031 +#include <linux/grsecurity.h>
8032 #include <asm/uaccess.h>
8033 #include <asm/unistd.h>
8035 @@ -562,6 +564,8 @@ static int do_umount(struct vfsmount *mn
8037 retval = do_remount_sb(sb, MS_RDONLY, NULL, 0);
8040 + gr_log_remount(mnt->mnt_devname, retval);
8042 up_write(&sb->s_umount);
8044 @@ -582,6 +586,9 @@ static int do_umount(struct vfsmount *mn
8045 security_sb_umount_busy(mnt);
8046 up_write(&namespace_sem);
8047 release_mounts(&umount_list);
8049 + gr_log_unmount(mnt->mnt_devname, retval);
8054 @@ -1308,6 +1315,11 @@ long do_mount(char *dev_name, char *dir_
8058 + if (gr_handle_chroot_mount(nd.dentry, nd.mnt, dev_name)) {
8063 if (flags & MS_REMOUNT)
8064 retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags,
8066 @@ -1322,6 +1334,9 @@ long do_mount(char *dev_name, char *dir_
8067 dev_name, data_page);
8071 + gr_log_mount(dev_name, dir_name, retval);
8076 @@ -1574,6 +1589,9 @@ asmlinkage long sys_pivot_root(const cha
8077 if (!capable(CAP_SYS_ADMIN))
8080 + if (gr_handle_chroot_pivot())
8085 error = __user_walk(new_root, LOOKUP_FOLLOW | LOOKUP_DIRECTORY,
8086 diff -urNp linux-2.6.16.12/fs/open.c linux-2.6.16.12/fs/open.c
8087 --- linux-2.6.16.12/fs/open.c 2006-05-01 15:14:26.000000000 -0400
8088 +++ linux-2.6.16.12/fs/open.c 2006-05-01 20:17:33.000000000 -0400
8090 #include <linux/pagemap.h>
8091 #include <linux/syscalls.h>
8092 #include <linux/rcupdate.h>
8093 +#include <linux/grsecurity.h>
8095 #include <asm/unistd.h>
8097 @@ -206,6 +207,9 @@ int do_truncate(struct dentry *dentry, l
8101 + if (filp && !gr_acl_handle_truncate(dentry, filp->f_vfsmnt))
8104 newattrs.ia_size = length;
8105 newattrs.ia_valid = ATTR_SIZE | time_attrs;
8107 @@ -406,6 +410,12 @@ asmlinkage long sys_utime(char __user *
8108 (error = vfs_permission(&nd, MAY_WRITE)) != 0)
8112 + if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) {
8114 + goto dput_and_out;
8117 mutex_lock(&inode->i_mutex);
8118 error = notify_change(nd.dentry, &newattrs);
8119 mutex_unlock(&inode->i_mutex);
8120 @@ -459,6 +469,12 @@ long do_utimes(int dfd, char __user *fil
8121 (error = vfs_permission(&nd, MAY_WRITE)) != 0)
8125 + if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) {
8127 + goto dput_and_out;
8130 mutex_lock(&inode->i_mutex);
8131 error = notify_change(nd.dentry, &newattrs);
8132 mutex_unlock(&inode->i_mutex);
8133 @@ -525,6 +541,10 @@ asmlinkage long sys_faccessat(int dfd, c
8134 if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode)
8135 && !special_file(nd.dentry->d_inode->i_mode))
8138 + if (!res && !gr_acl_handle_access(nd.dentry, nd.mnt, mode))
8144 @@ -553,6 +573,8 @@ asmlinkage long sys_chdir(const char __u
8148 + gr_log_chdir(nd.dentry, nd.mnt);
8150 set_fs_pwd(current->fs, nd.mnt, nd.dentry);
8153 @@ -583,6 +605,13 @@ asmlinkage long sys_fchdir(unsigned int
8156 error = file_permission(file, MAY_EXEC);
8158 + if (!error && !gr_chroot_fchdir(dentry, mnt))
8162 + gr_log_chdir(dentry, mnt);
8165 set_fs_pwd(current->fs, mnt, dentry);
8167 @@ -608,8 +637,16 @@ asmlinkage long sys_chroot(const char __
8168 if (!capable(CAP_SYS_CHROOT))
8171 + if (gr_handle_chroot_chroot(nd.dentry, nd.mnt))
8172 + goto dput_and_out;
8174 set_fs_root(current->fs, nd.mnt, nd.dentry);
8177 + gr_handle_chroot_caps(current);
8179 + gr_handle_chroot_chdir(nd.dentry, nd.mnt);
8184 @@ -638,9 +675,22 @@ asmlinkage long sys_fchmod(unsigned int
8186 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
8189 + if (!gr_acl_handle_fchmod(dentry, file->f_vfsmnt, mode)) {
8194 mutex_lock(&inode->i_mutex);
8195 if (mode == (mode_t) -1)
8196 mode = inode->i_mode;
8198 + if (gr_handle_chroot_chmod(dentry, file->f_vfsmnt, mode)) {
8200 + mutex_unlock(&inode->i_mutex);
8204 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
8205 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
8206 err = notify_change(dentry, &newattrs);
8207 @@ -673,9 +723,21 @@ asmlinkage long sys_fchmodat(int dfd, co
8208 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
8211 + if (!gr_acl_handle_chmod(nd.dentry, nd.mnt, mode)) {
8213 + goto dput_and_out;
8216 mutex_lock(&inode->i_mutex);
8217 if (mode == (mode_t) -1)
8218 mode = inode->i_mode;
8220 + if (gr_handle_chroot_chmod(nd.dentry, nd.mnt, mode)) {
8222 + mutex_unlock(&inode->i_mutex);
8223 + goto dput_and_out;
8226 newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO);
8227 newattrs.ia_valid = ATTR_MODE | ATTR_CTIME;
8228 error = notify_change(nd.dentry, &newattrs);
8229 @@ -692,7 +754,7 @@ asmlinkage long sys_chmod(const char __u
8230 return sys_fchmodat(AT_FDCWD, filename, mode);
8233 -static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
8234 +static int chown_common(struct dentry * dentry, uid_t user, gid_t group, struct vfsmount *mnt)
8236 struct inode * inode;
8238 @@ -709,6 +771,12 @@ static int chown_common(struct dentry *
8240 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
8243 + if (!gr_acl_handle_chown(dentry, mnt)) {
8248 newattrs.ia_valid = ATTR_CTIME;
8249 if (user != (uid_t) -1) {
8250 newattrs.ia_valid |= ATTR_UID;
8251 @@ -734,7 +802,7 @@ asmlinkage long sys_chown(const char __u
8253 error = user_path_walk(filename, &nd);
8255 - error = chown_common(nd.dentry, user, group);
8256 + error = chown_common(nd.dentry, user, group, nd.mnt);
8260 @@ -753,7 +821,7 @@ asmlinkage long sys_fchownat(int dfd, co
8261 follow = (flag & AT_SYMLINK_NOFOLLOW) ? 0 : LOOKUP_FOLLOW;
8262 error = __user_walk_fd(dfd, filename, follow, &nd);
8264 - error = chown_common(nd.dentry, user, group);
8265 + error = chown_common(nd.dentry, user, group, nd.mnt);
8269 @@ -767,7 +835,7 @@ asmlinkage long sys_lchown(const char __
8271 error = user_path_walk_link(filename, &nd);
8273 - error = chown_common(nd.dentry, user, group);
8274 + error = chown_common(nd.dentry, user, group, nd.mnt);
8278 @@ -781,7 +849,8 @@ asmlinkage long sys_fchown(unsigned int
8282 - error = chown_common(file->f_dentry, user, group);
8283 + error = chown_common(file->f_dentry, user,
8284 + group, file->f_vfsmnt);
8288 @@ -985,6 +1054,7 @@ repeat:
8289 * N.B. For clone tasks sharing a files structure, this test
8290 * will limit the total number of files that can be opened.
8292 + gr_learn_resource(current, RLIMIT_NOFILE, fd, 0);
8293 if (fd >= current->signal->rlim[RLIMIT_NOFILE].rlim_cur)
8296 diff -urNp linux-2.6.16.12/fs/proc/array.c linux-2.6.16.12/fs/proc/array.c
8297 --- linux-2.6.16.12/fs/proc/array.c 2006-05-01 15:14:26.000000000 -0400
8298 +++ linux-2.6.16.12/fs/proc/array.c 2006-05-01 20:17:33.000000000 -0400
8299 @@ -293,6 +293,21 @@ static inline char *task_cap(struct task
8300 cap_t(p->cap_effective));
8303 +#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
8304 +static inline char *task_pax(struct task_struct *p, char *buffer)
8307 + return buffer + sprintf(buffer, "PaX:\t%c%c%c%c%c\n",
8308 + p->mm->pax_flags & MF_PAX_PAGEEXEC ? 'P' : 'p',
8309 + p->mm->pax_flags & MF_PAX_EMUTRAMP ? 'E' : 'e',
8310 + p->mm->pax_flags & MF_PAX_MPROTECT ? 'M' : 'm',
8311 + p->mm->pax_flags & MF_PAX_RANDMMAP ? 'R' : 'r',
8312 + p->mm->pax_flags & MF_PAX_SEGMEXEC ? 'S' : 's');
8314 + return buffer + sprintf(buffer, "PaX:\t-----\n");
8318 int proc_pid_status(struct task_struct *task, char * buffer)
8320 char * orig = buffer;
8321 @@ -311,9 +326,20 @@ int proc_pid_status(struct task_struct *
8322 #if defined(CONFIG_S390)
8323 buffer = task_show_regs(task, buffer);
8326 +#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
8327 + buffer = task_pax(task, buffer);
8330 return buffer - orig;
8333 +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8334 +#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
8335 + (_mm->pax_flags & MF_PAX_RANDMMAP || \
8336 + _mm->pax_flags & MF_PAX_SEGMEXEC))
8339 static int do_task_stat(struct task_struct *task, char * buffer, int whole)
8341 unsigned long vsize, eip, esp, wchan = ~0UL;
8342 @@ -400,6 +426,19 @@ static int do_task_stat(struct task_stru
8343 stime = task->stime;
8346 +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8347 + if (PAX_RAND_FLAGS(mm)) {
8353 +#ifdef CONFIG_GRKERNSEC_HIDESYM
8359 /* scale priority and nice values from timeslices to -20..20 */
8360 /* to make it look like a "normal" Unix priority/nice value */
8361 priority = task_prio(task);
8362 @@ -440,9 +479,15 @@ static int do_task_stat(struct task_stru
8364 mm ? get_mm_rss(mm) : 0,
8366 +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8367 + PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->start_code : 0),
8368 + PAX_RAND_FLAGS(mm) ? 1 : (mm ? mm->end_code : 0),
8369 + PAX_RAND_FLAGS(mm) ? 0 : (mm ? mm->start_stack : 0),
8371 mm ? mm->start_code : 0,
8372 mm ? mm->end_code : 0,
8373 mm ? mm->start_stack : 0,
8377 /* The signal information here is obsolete.
8378 @@ -488,3 +533,14 @@ int proc_pid_statm(struct task_struct *t
8379 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
8380 size, resident, shared, text, lib, data, 0);
8383 +#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
8384 +int proc_pid_ipaddr(struct task_struct *task, char * buffer)
8388 + len = sprintf(buffer, "%u.%u.%u.%u\n", NIPQUAD(task->signal->curr_ip));
8393 diff -urNp linux-2.6.16.12/fs/proc/base.c linux-2.6.16.12/fs/proc/base.c
8394 --- linux-2.6.16.12/fs/proc/base.c 2006-05-01 15:14:26.000000000 -0400
8395 +++ linux-2.6.16.12/fs/proc/base.c 2006-05-01 20:17:33.000000000 -0400
8397 #include <linux/cpuset.h>
8398 #include <linux/audit.h>
8399 #include <linux/poll.h>
8400 +#include <linux/grsecurity.h>
8401 #include "internal.h"
8404 @@ -124,6 +125,9 @@ enum pid_directory_inos {
8405 #ifdef CONFIG_AUDITSYSCALL
8408 +#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
8411 PROC_TGID_OOM_SCORE,
8412 PROC_TGID_OOM_ADJUST,
8414 @@ -201,6 +205,9 @@ static struct pid_entry tgid_base_stuff[
8415 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
8416 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
8417 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
8418 +#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
8419 + E(PROC_TGID_IPADDR, "ipaddr", S_IFREG|S_IRUSR),
8422 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
8424 @@ -407,7 +414,7 @@ static int proc_task_root_link(struct in
8425 (task->parent == current && \
8426 (task->ptrace & PT_PTRACED) && \
8427 (task->state == TASK_STOPPED || task->state == TASK_TRACED) && \
8428 - security_ptrace(current,task) == 0))
8429 + security_ptrace(current,task) == 0 && !gr_handle_proc_ptrace(task)))
8431 static int proc_pid_environ(struct task_struct *task, char * buffer)
8433 @@ -585,9 +592,25 @@ static int proc_check_root(struct inode
8435 static int proc_permission(struct inode *inode, int mask, struct nameidata *nd)
8437 + int ret = -EACCES;
8438 + struct task_struct *task;
8440 if (generic_permission(inode, mask, NULL) != 0)
8442 - return proc_check_root(inode);
8445 + ret = proc_check_root(inode);
8449 + task = proc_task(inode);
8454 + ret = gr_acl_handle_procpidmem(task);
8460 static int proc_task_permission(struct inode *inode, int mask, struct nameidata *nd)
8461 @@ -1334,6 +1357,9 @@ static struct inode *proc_pid_make_inode
8462 inode->i_uid = task->euid;
8463 inode->i_gid = task->egid;
8465 +#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
8466 + inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
8468 security_task_to_inode(task, inode);
8471 @@ -1362,7 +1388,9 @@ static int pid_revalidate(struct dentry
8472 if (pid_alive(task)) {
8473 if (proc_type(inode) == PROC_TGID_INO || proc_type(inode) == PROC_TID_INO || task_dumpable(task)) {
8474 inode->i_uid = task->euid;
8475 +#ifndef CONFIG_GRKERNSEC_PROC_USERGROUP
8476 inode->i_gid = task->egid;
8481 @@ -1690,6 +1718,12 @@ static struct dentry *proc_pident_lookup
8482 inode->i_fop = &proc_info_file_operations;
8483 ei->op.proc_read = proc_pid_status;
8485 +#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
8486 + case PROC_TGID_IPADDR:
8487 + inode->i_fop = &proc_info_file_operations;
8488 + ei->op.proc_read = proc_pid_ipaddr;
8492 inode->i_fop = &proc_info_file_operations;
8493 ei->op.proc_read = proc_tid_stat;
8494 @@ -1994,6 +2028,22 @@ struct dentry *proc_pid_lookup(struct in
8498 + if (gr_check_hidden_task(task)) {
8499 + put_task_struct(task);
8503 +#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8504 + if (current->uid && (task->uid != current->uid)
8505 +#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
8506 + && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)
8509 + put_task_struct(task);
8514 inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
8517 @@ -2001,7 +2051,15 @@ struct dentry *proc_pid_lookup(struct in
8518 put_task_struct(task);
8522 +#ifdef CONFIG_GRKERNSEC_PROC_USER
8523 + inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR;
8524 +#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8525 + inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP;
8526 + inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
8528 inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
8530 inode->i_op = &proc_tgid_base_inode_operations;
8531 inode->i_fop = &proc_tgid_base_operations;
8532 inode->i_flags|=S_IMMUTABLE;
8533 @@ -2093,6 +2151,9 @@ out:
8534 static int get_tgid_list(int index, unsigned long version, unsigned int *tgids)
8536 struct task_struct *p;
8537 +#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8538 + struct task_struct *tmp = current;
8543 @@ -2113,6 +2174,18 @@ static int get_tgid_list(int index, unsi
8547 + if (gr_pid_is_chrooted(p))
8549 + if (gr_check_hidden_task(p))
8551 +#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8552 + if (tmp->uid && (p->uid != tmp->uid)
8553 +#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
8554 + && !in_group_p(CONFIG_GRKERNSEC_PROC_GID)
8561 tgids[nr_tgids] = tgid;
8562 diff -urNp linux-2.6.16.12/fs/proc/inode.c linux-2.6.16.12/fs/proc/inode.c
8563 --- linux-2.6.16.12/fs/proc/inode.c 2006-05-01 15:14:26.000000000 -0400
8564 +++ linux-2.6.16.12/fs/proc/inode.c 2006-05-01 20:17:33.000000000 -0400
8565 @@ -168,7 +168,11 @@ struct inode *proc_get_inode(struct supe
8567 inode->i_mode = de->mode;
8568 inode->i_uid = de->uid;
8569 +#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP
8570 + inode->i_gid = CONFIG_GRKERNSEC_PROC_GID;
8572 inode->i_gid = de->gid;
8576 inode->i_size = de->size;
8577 diff -urNp linux-2.6.16.12/fs/proc/internal.h linux-2.6.16.12/fs/proc/internal.h
8578 --- linux-2.6.16.12/fs/proc/internal.h 2006-05-01 15:14:26.000000000 -0400
8579 +++ linux-2.6.16.12/fs/proc/internal.h 2006-05-01 20:17:33.000000000 -0400
8580 @@ -36,6 +36,9 @@ extern int proc_tid_stat(struct task_str
8581 extern int proc_tgid_stat(struct task_struct *, char *);
8582 extern int proc_pid_status(struct task_struct *, char *);
8583 extern int proc_pid_statm(struct task_struct *, char *);
8584 +#ifdef CONFIG_GRKERNSEC_PROC_IPADDR
8585 +extern int proc_pid_ipaddr(struct task_struct*,char*);
8588 void free_proc_entry(struct proc_dir_entry *de);
8590 diff -urNp linux-2.6.16.12/fs/proc/proc_misc.c linux-2.6.16.12/fs/proc/proc_misc.c
8591 --- linux-2.6.16.12/fs/proc/proc_misc.c 2006-05-01 15:14:26.000000000 -0400
8592 +++ linux-2.6.16.12/fs/proc/proc_misc.c 2006-05-01 20:17:33.000000000 -0400
8593 @@ -617,6 +617,8 @@ void create_seq_entry(char *name, mode_t
8594 void __init proc_misc_init(void)
8596 struct proc_dir_entry *entry;
8601 int (*read_proc)(char*,char**,off_t,int,int*,void*);
8602 @@ -632,7 +634,9 @@ void __init proc_misc_init(void)
8603 {"stram", stram_read_proc},
8605 {"filesystems", filesystems_read_proc},
8606 +#ifndef CONFIG_GRKERNSEC_PROC_ADD
8607 {"cmdline", cmdline_read_proc},
8609 {"locks", locks_read_proc},
8610 {"execdomains", execdomains_read_proc},
8612 @@ -640,31 +644,49 @@ void __init proc_misc_init(void)
8613 for (p = simple_ones; p->name; p++)
8614 create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL);
8616 +#ifdef CONFIG_GRKERNSEC_PROC_USER
8617 + gr_mode = S_IRUSR;
8618 +#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8619 + gr_mode = S_IRUSR | S_IRGRP;
8621 +#ifdef CONFIG_GRKERNSEC_PROC_ADD
8622 + create_proc_read_entry("cmdline", gr_mode, NULL, &cmdline_read_proc, NULL);
8625 proc_symlink("mounts", NULL, "self/mounts");
8627 /* And now for trickier ones */
8628 entry = create_proc_entry("kmsg", S_IRUSR, &proc_root);
8630 entry->proc_fops = &proc_kmsg_operations;
8632 +#ifdef CONFIG_GRKERNSEC_PROC_ADD
8633 + create_seq_entry("devices", gr_mode, &proc_devinfo_operations);
8635 create_seq_entry("devices", 0, &proc_devinfo_operations);
8637 create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations);
8638 create_seq_entry("partitions", 0, &proc_partitions_operations);
8639 create_seq_entry("stat", 0, &proc_stat_operations);
8640 create_seq_entry("interrupts", 0, &proc_interrupts_operations);
8642 +#ifdef CONFIG_GRKERNSEC_PROC_ADD
8643 + create_seq_entry("slabinfo",S_IWUSR|gr_mode,&proc_slabinfo_operations);
8645 create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations);
8648 create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations);
8649 create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations);
8650 create_seq_entry("zoneinfo",S_IRUGO, &proc_zoneinfo_file_operations);
8651 create_seq_entry("diskstats", 0, &proc_diskstats_operations);
8652 #ifdef CONFIG_MODULES
8653 - create_seq_entry("modules", 0, &proc_modules_operations);
8654 + create_seq_entry("modules", gr_mode, &proc_modules_operations);
8656 #ifdef CONFIG_SCHEDSTATS
8657 create_seq_entry("schedstat", 0, &proc_schedstat_operations);
8659 -#ifdef CONFIG_PROC_KCORE
8660 +#if defined(CONFIG_PROC_KCORE) && !defined(CONFIG_GRKERNSEC_PROC_ADD)
8661 proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL);
8662 if (proc_root_kcore) {
8663 proc_root_kcore->proc_fops = &proc_kcore_operations;
8664 diff -urNp linux-2.6.16.12/fs/proc/root.c linux-2.6.16.12/fs/proc/root.c
8665 --- linux-2.6.16.12/fs/proc/root.c 2006-05-01 15:14:26.000000000 -0400
8666 +++ linux-2.6.16.12/fs/proc/root.c 2006-05-01 20:17:33.000000000 -0400
8667 @@ -53,7 +53,13 @@ void __init proc_root_init(void)
8671 +#ifdef CONFIG_GRKERNSEC_PROC_USER
8672 + proc_net = proc_mkdir_mode("net", S_IRUSR | S_IXUSR, NULL);
8673 +#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8674 + proc_net = proc_mkdir_mode("net", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL);
8676 proc_net = proc_mkdir("net", NULL);
8678 proc_net_stat = proc_mkdir("net/stat", NULL);
8680 #ifdef CONFIG_SYSVIPC
8681 @@ -77,7 +83,15 @@ void __init proc_root_init(void)
8682 #ifdef CONFIG_PROC_DEVICETREE
8683 proc_device_tree_init();
8685 +#ifdef CONFIG_GRKERNSEC_PROC_ADD
8686 +#ifdef CONFIG_GRKERNSEC_PROC_USER
8687 + proc_bus = proc_mkdir_mode("bus", S_IRUSR | S_IXUSR, NULL);
8688 +#elif defined(CONFIG_GRKERNSEC_PROC_USERGROUP)
8689 + proc_bus = proc_mkdir_mode("bus", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, NULL);
8692 proc_bus = proc_mkdir("bus", NULL);
8696 static int proc_root_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat
8697 diff -urNp linux-2.6.16.12/fs/proc/task_mmu.c linux-2.6.16.12/fs/proc/task_mmu.c
8698 --- linux-2.6.16.12/fs/proc/task_mmu.c 2006-05-01 15:14:26.000000000 -0400
8699 +++ linux-2.6.16.12/fs/proc/task_mmu.c 2006-05-01 20:17:33.000000000 -0400
8700 @@ -43,15 +43,27 @@ char *task_mem(struct mm_struct *mm, cha
8704 - "VmPTE:\t%8lu kB\n",
8705 - hiwater_vm << (PAGE_SHIFT-10),
8706 + "VmPTE:\t%8lu kB\n"
8708 +#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
8709 + "CsBase:\t%8lx\nCsLim:\t%8lx\n"
8712 + ,hiwater_vm << (PAGE_SHIFT-10),
8713 (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
8714 mm->locked_vm << (PAGE_SHIFT-10),
8715 hiwater_rss << (PAGE_SHIFT-10),
8716 total_rss << (PAGE_SHIFT-10),
8717 data << (PAGE_SHIFT-10),
8718 mm->stack_vm << (PAGE_SHIFT-10), text, lib,
8719 - (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
8720 + (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10
8722 +#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
8723 + , mm->context.user_cs_base, mm->context.user_cs_limit
8731 @@ -118,6 +130,12 @@ struct mem_size_stats
8732 unsigned long private_dirty;
8735 +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8736 +#define PAX_RAND_FLAGS(_mm) (_mm != NULL && _mm != current->mm && \
8737 + (_mm->pax_flags & MF_PAX_RANDMMAP || \
8738 + _mm->pax_flags & MF_PAX_SEGMEXEC))
8741 static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats *mss)
8743 struct task_struct *task = m->private;
8744 @@ -136,13 +154,30 @@ static int show_map_internal(struct seq_
8747 seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
8748 +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8749 + PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_start,
8750 + PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_end,
8757 + flags & VM_MAYREAD ? flags & VM_READ ? 'R' : '+' : flags & VM_READ ? 'r' : '-',
8758 + flags & VM_MAYWRITE ? flags & VM_WRITE ? 'W' : '+' : flags & VM_WRITE ? 'w' : '-',
8759 + flags & VM_MAYEXEC ? flags & VM_EXEC ? 'X' : '+' : flags & VM_EXEC ? 'x' : '-',
8761 flags & VM_READ ? 'r' : '-',
8762 flags & VM_WRITE ? 'w' : '-',
8763 flags & VM_EXEC ? 'x' : '-',
8766 flags & VM_MAYSHARE ? 's' : 'p',
8767 +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8768 + PAX_RAND_FLAGS(mm) ? 0UL : vma->vm_pgoff << PAGE_SHIFT,
8770 vma->vm_pgoff << PAGE_SHIFT,
8772 MAJOR(dev), MINOR(dev), ino, &len);
8775 @@ -154,13 +189,13 @@ static int show_map_internal(struct seq_
8776 seq_path(m, file->f_vfsmnt, file->f_dentry, "\n");
8779 - if (vma->vm_start <= mm->start_brk &&
8780 - vma->vm_end >= mm->brk) {
8781 + if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
8782 pad_len_spaces(m, len);
8783 seq_puts(m, "[heap]");
8785 - if (vma->vm_start <= mm->start_stack &&
8786 - vma->vm_end >= mm->start_stack) {
8787 + if ((vma->vm_flags & (VM_GROWSDOWN | VM_GROWSUP)) ||
8788 + (vma->vm_start <= mm->start_stack &&
8789 + vma->vm_end >= mm->start_stack)) {
8791 pad_len_spaces(m, len);
8792 seq_puts(m, "[stack]");
8793 @@ -173,7 +208,25 @@ static int show_map_internal(struct seq_
8800 +#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP
8801 + if (PAX_RAND_FLAGS(mm))
8805 + "Shared_Clean: %8lu kB\n"
8806 + "Shared_Dirty: %8lu kB\n"
8807 + "Private_Clean: %8lu kB\n"
8808 + "Private_Dirty: %8lu kB\n",
8820 @@ -187,6 +240,7 @@ static int show_map_internal(struct seq_
8821 mss->shared_dirty >> 10,
8822 mss->private_clean >> 10,
8823 mss->private_dirty >> 10);
8826 if (m->count < m->size) /* vma is copied successfully */
8827 m->version = (vma != get_gate_vma(task))? vma->vm_start: 0;
8828 diff -urNp linux-2.6.16.12/fs/readdir.c linux-2.6.16.12/fs/readdir.c
8829 --- linux-2.6.16.12/fs/readdir.c 2006-05-01 15:14:26.000000000 -0400
8830 +++ linux-2.6.16.12/fs/readdir.c 2006-05-01 20:17:33.000000000 -0400
8832 #include <linux/security.h>
8833 #include <linux/syscalls.h>
8834 #include <linux/unistd.h>
8835 +#include <linux/namei.h>
8836 +#include <linux/grsecurity.h>
8838 #include <asm/uaccess.h>
8840 @@ -65,6 +67,7 @@ struct old_linux_dirent {
8842 struct readdir_callback {
8843 struct old_linux_dirent __user * dirent;
8844 + struct file * file;
8848 @@ -76,6 +79,10 @@ static int fillonedir(void * __buf, cons
8853 + if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
8857 dirent = buf->dirent;
8858 if (!access_ok(VERIFY_WRITE, dirent,
8859 @@ -107,6 +114,7 @@ asmlinkage long old_readdir(unsigned int
8862 buf.dirent = dirent;
8865 error = vfs_readdir(file, fillonedir, &buf);
8867 @@ -133,6 +141,7 @@ struct linux_dirent {
8868 struct getdents_callback {
8869 struct linux_dirent __user * current_dir;
8870 struct linux_dirent __user * previous;
8871 + struct file * file;
8875 @@ -147,6 +156,10 @@ static int filldir(void * __buf, const c
8876 buf->error = -EINVAL; /* only used if we fail.. */
8877 if (reclen > buf->count)
8880 + if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
8883 dirent = buf->previous;
8885 if (__put_user(offset, &dirent->d_off))
8886 @@ -191,6 +204,7 @@ asmlinkage long sys_getdents(unsigned in
8888 buf.current_dir = dirent;
8889 buf.previous = NULL;
8894 @@ -217,6 +231,7 @@ out:
8895 struct getdents_callback64 {
8896 struct linux_dirent64 __user * current_dir;
8897 struct linux_dirent64 __user * previous;
8898 + struct file * file;
8902 @@ -231,6 +246,10 @@ static int filldir64(void * __buf, const
8903 buf->error = -EINVAL; /* only used if we fail.. */
8904 if (reclen > buf->count)
8907 + if (!gr_acl_handle_filldir(buf->file, name, namlen, ino))
8910 dirent = buf->previous;
8912 if (__put_user(offset, &dirent->d_off))
8913 @@ -277,6 +296,7 @@ asmlinkage long sys_getdents64(unsigned
8915 buf.current_dir = dirent;
8916 buf.previous = NULL;
8921 diff -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
8922 --- linux-2.6.16.12/fs/xfs/linux-2.6/xfs_file.c 2006-05-01 15:14:26.000000000 -0400
8923 +++ linux-2.6.16.12/fs/xfs/linux-2.6/xfs_file.c 2006-05-01 20:17:33.000000000 -0400
8924 @@ -413,6 +413,11 @@ linvfs_file_mmap(
8925 vattr_t va = { .va_mask = XFS_AT_UPDATIME };
8928 +#ifdef CONFIG_PAX_PAGEEXEC
8929 + if (vma->vm_mm->pax_flags & MF_PAX_PAGEEXEC)
8930 + vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
8933 vma->vm_ops = &linvfs_file_vm_ops;
8935 #ifdef CONFIG_XFS_DMAPI
8936 diff -urNp linux-2.6.16.12/grsecurity/gracl_alloc.c linux-2.6.16.12/grsecurity/gracl_alloc.c
8937 --- linux-2.6.16.12/grsecurity/gracl_alloc.c 1969-12-31 19:00:00.000000000 -0500
8938 +++ linux-2.6.16.12/grsecurity/gracl_alloc.c 2006-05-01 20:17:33.000000000 -0400
8940 +#include <linux/kernel.h>
8941 +#include <linux/mm.h>
8942 +#include <linux/slab.h>
8943 +#include <linux/vmalloc.h>
8944 +#include <linux/gracl.h>
8945 +#include <linux/grsecurity.h>
8947 +static unsigned long alloc_stack_next = 1;
8948 +static unsigned long alloc_stack_size = 1;
8949 +static void **alloc_stack;
8951 +static __inline__ int
8954 + if (alloc_stack_next == 1)
8957 + kfree(alloc_stack[alloc_stack_next - 2]);
8959 + alloc_stack_next--;
8964 +static __inline__ void
8965 +alloc_push(void *buf)
8967 + if (alloc_stack_next >= alloc_stack_size)
8970 + alloc_stack[alloc_stack_next - 1] = buf;
8972 + alloc_stack_next++;
8978 +acl_alloc(unsigned long len)
8982 + if (len > PAGE_SIZE)
8985 + ret = kmalloc(len, GFP_KERNEL);
8996 + if (gr_acl_is_enabled() || !alloc_stack)
8999 + while (alloc_pop()) ;
9001 + if (alloc_stack) {
9002 + if ((alloc_stack_size * sizeof (void *)) <= PAGE_SIZE)
9003 + kfree(alloc_stack);
9005 + vfree(alloc_stack);
9008 + alloc_stack = NULL;
9009 + alloc_stack_size = 1;
9010 + alloc_stack_next = 1;
9016 +acl_alloc_stack_init(unsigned long size)
9018 + if ((size * sizeof (void *)) <= PAGE_SIZE)
9020 + (void **) kmalloc(size * sizeof (void *), GFP_KERNEL);
9022 + alloc_stack = (void **) vmalloc(size * sizeof (void *));
9024 + alloc_stack_size = size;
9031 diff -urNp linux-2.6.16.12/grsecurity/gracl.c linux-2.6.16.12/grsecurity/gracl.c
9032 --- linux-2.6.16.12/grsecurity/gracl.c 1969-12-31 19:00:00.000000000 -0500
9033 +++ linux-2.6.16.12/grsecurity/gracl.c 2006-05-01 20:17:33.000000000 -0400
9035 +#include <linux/kernel.h>
9036 +#include <linux/module.h>
9037 +#include <linux/sched.h>
9038 +#include <linux/mm.h>
9039 +#include <linux/file.h>
9040 +#include <linux/fs.h>
9041 +#include <linux/namei.h>
9042 +#include <linux/mount.h>
9043 +#include <linux/tty.h>
9044 +#include <linux/proc_fs.h>
9045 +#include <linux/smp_lock.h>
9046 +#include <linux/slab.h>
9047 +#include <linux/vmalloc.h>
9048 +#include <linux/types.h>
9049 +#include <linux/capability.h>
9050 +#include <linux/sysctl.h>
9051 +#include <linux/netdevice.h>
9052 +#include <linux/ptrace.h>
9053 +#include <linux/gracl.h>
9054 +#include <linux/gralloc.h>
9055 +#include <linux/grsecurity.h>
9056 +#include <linux/grinternal.h>
9057 +#include <linux/percpu.h>
9059 +#include <asm/uaccess.h>
9060 +#include <asm/errno.h>
9061 +#include <asm/mman.h>
9063 +static struct acl_role_db acl_role_set;
9064 +static struct name_db name_set;
9065 +static struct inodev_db inodev_set;
9067 +/* for keeping track of userspace pointers used for subjects, so we
9068 + can share references in the kernel as well
9071 +static struct dentry *real_root;
9072 +static struct vfsmount *real_root_mnt;
9074 +static struct acl_subj_map_db subj_map_set;
9076 +static struct acl_role_label *default_role;
9078 +static u16 acl_sp_role_value;
9080 +extern char *gr_shared_page[4];
9081 +static DECLARE_MUTEX(gr_dev_sem);
9082 +rwlock_t gr_inode_lock = RW_LOCK_UNLOCKED;
9084 +struct gr_arg *gr_usermode;
9086 +static unsigned int gr_status = GR_STATUS_INIT;
9088 +extern int chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum);
9089 +extern void gr_clear_learn_entries(void);
9091 +#ifdef CONFIG_GRKERNSEC_RESLOG
9092 +extern void gr_log_resource(const struct task_struct *task,
9093 + const int res, const unsigned long wanted, const int gt);
9096 +extern char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt,
9097 + struct dentry *root, struct vfsmount *rootmnt,
9098 + char *buffer, int buflen);
9100 +unsigned char *gr_system_salt;
9101 +unsigned char *gr_system_sum;
9103 +static struct sprole_pw **acl_special_roles = NULL;
9104 +static __u16 num_sprole_pws = 0;
9106 +static struct acl_role_label *kernel_role = NULL;
9108 +static unsigned int gr_auth_attempts = 0;
9109 +static unsigned long gr_auth_expires = 0UL;
9111 +extern int gr_init_uidset(void);
9112 +extern void gr_free_uidset(void);
9113 +extern void gr_remove_uid(uid_t uid);
9114 +extern int gr_find_uid(uid_t uid);
9117 +gr_acl_is_enabled(void)
9119 + return (gr_status & GR_READY);
9122 +char gr_roletype_to_char(void)
9124 + switch (current->role->roletype &
9125 + (GR_ROLE_DEFAULT | GR_ROLE_USER | GR_ROLE_GROUP |
9126 + GR_ROLE_SPECIAL)) {
9127 + case GR_ROLE_DEFAULT:
9129 + case GR_ROLE_USER:
9131 + case GR_ROLE_GROUP:
9133 + case GR_ROLE_SPECIAL:
9141 +gr_acl_tpe_check(void)
9143 + if (unlikely(!(gr_status & GR_READY)))
9145 + if (current->role->roletype & GR_ROLE_TPE)
9152 +gr_handle_rawio(const struct inode *inode)
9154 +#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
9155 + if (inode && S_ISBLK(inode->i_mode) &&
9156 + grsec_enable_chroot_caps && proc_is_chrooted(current) &&
9157 + !capable(CAP_SYS_RAWIO))
9164 +gr_streq(const char *a, const char *b, const unsigned int lena, const unsigned int lenb)
9167 + unsigned long *l1;
9168 + unsigned long *l2;
9169 + unsigned char *c1;
9170 + unsigned char *c2;
9173 + if (likely(lena != lenb))
9176 + l1 = (unsigned long *)a;
9177 + l2 = (unsigned long *)b;
9179 + num_longs = lena / sizeof(unsigned long);
9181 + for (i = num_longs; i--; l1++, l2++) {
9182 + if (unlikely(*l1 != *l2))
9186 + c1 = (unsigned char *) l1;
9187 + c2 = (unsigned char *) l2;
9189 + i = lena - (num_longs * sizeof(unsigned long));
9191 + for (; i--; c1++, c2++) {
9192 + if (unlikely(*c1 != *c2))
9200 +gen_full_path(struct dentry *dentry, struct vfsmount *vfsmnt,
9201 + struct dentry *root, struct vfsmount *rootmnt, char *buf, int buflen)
9203 + char *end = buf + buflen;
9212 + if (dentry == root && vfsmnt == rootmnt)
9214 + if (dentry != vfsmnt->mnt_root && !IS_ROOT(dentry)) {
9215 + namelen = strlen(dentry->d_name.name);
9216 + buflen -= namelen;
9219 + if (dentry->d_parent != root || vfsmnt != rootmnt)
9223 + retval = __d_path(dentry->d_parent, vfsmnt, root, rootmnt, buf, buflen);
9224 + if (unlikely(IS_ERR(retval)))
9226 + retval = strcpy(buf, "<path too long>");
9227 + else if (namelen != 0) {
9228 + end = buf + buflen - 1; // accounts for null termination
9229 + if (dentry->d_parent != root || vfsmnt != rootmnt)
9230 + *end++ = '/'; // accounted for above with buflen--
9231 + memcpy(end, dentry->d_name.name, namelen);
9238 +__d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
9239 + char *buf, int buflen)
9243 + /* we can use real_root, real_root_mnt, because this is only called
9244 + by the RBAC system */
9245 + res = gen_full_path((struct dentry *)dentry, (struct vfsmount *)vfsmnt, real_root, real_root_mnt, buf, buflen);
9251 +d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt,
9252 + char *buf, int buflen)
9255 + struct dentry *root;
9256 + struct vfsmount *rootmnt;
9258 + /* we can't use real_root, real_root_mnt, because they belong only to the RBAC system */
9259 + read_lock(&child_reaper->fs->lock);
9260 + root = dget(child_reaper->fs->root);
9261 + rootmnt = mntget(child_reaper->fs->rootmnt);
9262 + read_unlock(&child_reaper->fs->lock);
9264 + spin_lock(&dcache_lock);
9265 + res = gen_full_path((struct dentry *)dentry, (struct vfsmount *)vfsmnt, root, rootmnt, buf, buflen);
9266 + spin_unlock(&dcache_lock);
9274 +gr_to_filename_rbac(const struct dentry *dentry, const struct vfsmount *mnt)
9277 + spin_lock(&dcache_lock);
9278 + ret = __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()),
9280 + spin_unlock(&dcache_lock);
9285 +gr_to_filename_nolock(const struct dentry *dentry, const struct vfsmount *mnt)
9287 + return __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0],smp_processor_id()),
9292 +gr_to_filename(const struct dentry *dentry, const struct vfsmount *mnt)
9294 + return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()),
9299 +gr_to_filename1(const struct dentry *dentry, const struct vfsmount *mnt)
9301 + return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[1], smp_processor_id()),
9306 +gr_to_filename2(const struct dentry *dentry, const struct vfsmount *mnt)
9308 + return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[2], smp_processor_id()),
9313 +gr_to_filename3(const struct dentry *dentry, const struct vfsmount *mnt)
9315 + return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[3], smp_processor_id()),
9320 +to_gr_audit(const __u32 reqmode)
9322 + /* masks off auditable permission flags, then shifts them to create
9323 + auditing flags, and adds the special case of append auditing if
9324 + we're requesting write */
9325 + return (((reqmode & GR_AUDIT_READ) << 10) | ((reqmode & GR_WRITE) ? GR_AUDIT_APPEND : 0));
9328 +struct acl_subject_label *
9329 +lookup_subject_map(const struct acl_subject_label *userp)
9331 + unsigned int index = shash(userp, subj_map_set.s_size);
9332 + struct subject_map *match;
9334 + match = subj_map_set.s_hash[index];
9336 + while (match && match->user != userp)
9337 + match = match->next;
9339 + if (match != NULL)
9340 + return match->kernel;
9346 +insert_subj_map_entry(struct subject_map *subjmap)
9348 + unsigned int index = shash(subjmap->user, subj_map_set.s_size);
9349 + struct subject_map **curr;
9351 + subjmap->prev = NULL;
9353 + curr = &subj_map_set.s_hash[index];
9354 + if (*curr != NULL)
9355 + (*curr)->prev = subjmap;
9357 + subjmap->next = *curr;
9363 +static struct acl_role_label *
9364 +lookup_acl_role_label(const struct task_struct *task, const uid_t uid,
9367 + unsigned int index = rhash(uid, GR_ROLE_USER, acl_role_set.r_size);
9368 + struct acl_role_label *match;
9369 + struct role_allowed_ip *ipp;
9372 + match = acl_role_set.r_hash[index];
9375 + if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_USER)) == (GR_ROLE_DOMAIN | GR_ROLE_USER)) {
9376 + for (x = 0; x < match->domain_child_num; x++) {
9377 + if (match->domain_children[x] == uid)
9380 + } else if (match->uidgid == uid && match->roletype & GR_ROLE_USER)
9382 + match = match->next;
9385 + if (match == NULL) {
9387 + index = rhash(gid, GR_ROLE_GROUP, acl_role_set.r_size);
9388 + match = acl_role_set.r_hash[index];
9391 + if ((match->roletype & (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) == (GR_ROLE_DOMAIN | GR_ROLE_GROUP)) {
9392 + for (x = 0; x < match->domain_child_num; x++) {
9393 + if (match->domain_children[x] == gid)
9396 + } else if (match->uidgid == gid && match->roletype & GR_ROLE_GROUP)
9398 + match = match->next;
9401 + if (match == NULL)
9402 + match = default_role;
9403 + if (match->allowed_ips == NULL)
9406 + for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
9408 + ((ntohl(task->signal->curr_ip) & ipp->netmask) ==
9409 + (ntohl(ipp->addr) & ipp->netmask)))
9412 + match = default_role;
9414 + } else if (match->allowed_ips == NULL) {
9417 + for (ipp = match->allowed_ips; ipp; ipp = ipp->next) {
9419 + ((ntohl(task->signal->curr_ip) & ipp->netmask) ==
9420 + (ntohl(ipp->addr) & ipp->netmask)))
9429 +struct acl_subject_label *
9430 +lookup_acl_subj_label(const ino_t ino, const dev_t dev,
9431 + const struct acl_role_label *role)
9433 + unsigned int index = fhash(ino, dev, role->subj_hash_size);
9434 + struct acl_subject_label *match;
9436 + match = role->subj_hash[index];
9438 + while (match && (match->inode != ino || match->device != dev ||
9439 + (match->mode & GR_DELETED))) {
9440 + match = match->next;
9443 + if (match && !(match->mode & GR_DELETED))
9449 +static struct acl_object_label *
9450 +lookup_acl_obj_label(const ino_t ino, const dev_t dev,
9451 + const struct acl_subject_label *subj)
9453 + unsigned int index = fhash(ino, dev, subj->obj_hash_size);
9454 + struct acl_object_label *match;
9456 + match = subj->obj_hash[index];
9458 + while (match && (match->inode != ino || match->device != dev ||
9459 + (match->mode & GR_DELETED))) {
9460 + match = match->next;
9463 + if (match && !(match->mode & GR_DELETED))
9469 +static struct acl_object_label *
9470 +lookup_acl_obj_label_create(const ino_t ino, const dev_t dev,
9471 + const struct acl_subject_label *subj)
9473 + unsigned int index = fhash(ino, dev, subj->obj_hash_size);
9474 + struct acl_object_label *match;
9476 + match = subj->obj_hash[index];
9478 + while (match && (match->inode != ino || match->device != dev ||
9479 + !(match->mode & GR_DELETED))) {
9480 + match = match->next;
9483 + if (match && (match->mode & GR_DELETED))
9486 + match = subj->obj_hash[index];
9488 + while (match && (match->inode != ino || match->device != dev ||
9489 + (match->mode & GR_DELETED))) {
9490 + match = match->next;
9493 + if (match && !(match->mode & GR_DELETED))
9499 +static struct name_entry *
9500 +lookup_name_entry(const char *name)
9502 + unsigned int len = strlen(name);
9503 + unsigned int key = full_name_hash(name, len);
9504 + unsigned int index = key % name_set.n_size;
9505 + struct name_entry *match;
9507 + match = name_set.n_hash[index];
9509 + while (match && (match->key != key || !gr_streq(match->name, name, match->len, len)))
9510 + match = match->next;
9515 +static struct inodev_entry *
9516 +lookup_inodev_entry(const ino_t ino, const dev_t dev)
9518 + unsigned int index = fhash(ino, dev, inodev_set.i_size);
9519 + struct inodev_entry *match;
9521 + match = inodev_set.i_hash[index];
9523 + while (match && (match->nentry->inode != ino || match->nentry->device != dev))
9524 + match = match->next;
9530 +insert_inodev_entry(struct inodev_entry *entry)
9532 + unsigned int index = fhash(entry->nentry->inode, entry->nentry->device,
9533 + inodev_set.i_size);
9534 + struct inodev_entry **curr;
9536 + entry->prev = NULL;
9538 + curr = &inodev_set.i_hash[index];
9539 + if (*curr != NULL)
9540 + (*curr)->prev = entry;
9542 + entry->next = *curr;
9549 +__insert_acl_role_label(struct acl_role_label *role, uid_t uidgid)
9551 + unsigned int index =
9552 + rhash(uidgid, role->roletype & (GR_ROLE_USER | GR_ROLE_GROUP), acl_role_set.r_size);
9553 + struct acl_role_label **curr;
9555 + role->prev = NULL;
9557 + curr = &acl_role_set.r_hash[index];
9558 + if (*curr != NULL)
9559 + (*curr)->prev = role;
9561 + role->next = *curr;
9568 +insert_acl_role_label(struct acl_role_label *role)
9572 + if (role->roletype & GR_ROLE_DOMAIN) {
9573 + for (i = 0; i < role->domain_child_num; i++)
9574 + __insert_acl_role_label(role, role->domain_children[i]);
9576 + __insert_acl_role_label(role, role->uidgid);
9580 +insert_name_entry(char *name, const ino_t inode, const dev_t device)
9582 + struct name_entry **curr, *nentry;
9583 + struct inodev_entry *ientry;
9584 + unsigned int len = strlen(name);
9585 + unsigned int key = full_name_hash(name, len);
9586 + unsigned int index = key % name_set.n_size;
9588 + curr = &name_set.n_hash[index];
9590 + while (*curr && ((*curr)->key != key || !gr_streq((*curr)->name, name, (*curr)->len, len)))
9591 + curr = &((*curr)->next);
9593 + if (*curr != NULL)
9596 + nentry = acl_alloc(sizeof (struct name_entry));
9597 + if (nentry == NULL)
9599 + ientry = acl_alloc(sizeof (struct inodev_entry));
9600 + if (ientry == NULL)
9602 + ientry->nentry = nentry;
9604 + nentry->key = key;
9605 + nentry->name = name;
9606 + nentry->inode = inode;
9607 + nentry->device = device;
9608 + nentry->len = len;
9610 + nentry->prev = NULL;
9611 + curr = &name_set.n_hash[index];
9612 + if (*curr != NULL)
9613 + (*curr)->prev = nentry;
9614 + nentry->next = *curr;
9617 + /* insert us into the table searchable by inode/dev */
9618 + insert_inodev_entry(ientry);
9624 +insert_acl_obj_label(struct acl_object_label *obj,
9625 + struct acl_subject_label *subj)
9627 + unsigned int index =
9628 + fhash(obj->inode, obj->device, subj->obj_hash_size);
9629 + struct acl_object_label **curr;
9634 + curr = &subj->obj_hash[index];
9635 + if (*curr != NULL)
9636 + (*curr)->prev = obj;
9638 + obj->next = *curr;
9645 +insert_acl_subj_label(struct acl_subject_label *obj,
9646 + struct acl_role_label *role)
9648 + unsigned int index = fhash(obj->inode, obj->device, role->subj_hash_size);
9649 + struct acl_subject_label **curr;
9653 + curr = &role->subj_hash[index];
9654 + if (*curr != NULL)
9655 + (*curr)->prev = obj;
9657 + obj->next = *curr;
9663 +/* allocating chained hash tables, so optimal size is where lambda ~ 1 */
9666 +create_table(__u32 * len, int elementsize)
9668 + unsigned int table_sizes[] = {
9669 + 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381,
9670 + 32749, 65521, 131071, 262139, 524287, 1048573, 2097143,
9671 + 4194301, 8388593, 16777213, 33554393, 67108859, 134217689,
9672 + 268435399, 536870909, 1073741789, 2147483647
9674 + void *newtable = NULL;
9675 + unsigned int pwr = 0;
9677 + while ((pwr < ((sizeof (table_sizes) / sizeof (table_sizes[0])) - 1)) &&
9678 + table_sizes[pwr] <= *len)
9681 + if (table_sizes[pwr] <= *len)
9684 + if ((table_sizes[pwr] * elementsize) <= PAGE_SIZE)
9686 + kmalloc(table_sizes[pwr] * elementsize, GFP_KERNEL);
9688 + newtable = vmalloc(table_sizes[pwr] * elementsize);
9690 + *len = table_sizes[pwr];
9696 +init_variables(const struct gr_arg *arg)
9698 + unsigned int stacksize;
9700 + subj_map_set.s_size = arg->role_db.num_subjects;
9701 + acl_role_set.r_size = arg->role_db.num_roles + arg->role_db.num_domain_children;
9702 + name_set.n_size = arg->role_db.num_objects;
9703 + inodev_set.i_size = arg->role_db.num_objects;
9705 + if (!subj_map_set.s_size || !acl_role_set.r_size ||
9706 + !name_set.n_size || !inodev_set.i_size)
9709 + if (!gr_init_uidset())
9712 + /* set up the stack that holds allocation info */
9714 + stacksize = arg->role_db.num_pointers + 5;
9716 + if (!acl_alloc_stack_init(stacksize))
9719 + /* grab reference for the real root dentry and vfsmount */
9720 + read_lock(&child_reaper->fs->lock);
9721 + real_root_mnt = mntget(child_reaper->fs->rootmnt);
9722 + real_root = dget(child_reaper->fs->root);
9723 + read_unlock(&child_reaper->fs->lock);
9726 + subj_map_set.s_hash =
9727 + (struct subject_map **) create_table(&subj_map_set.s_size, sizeof(void *));
9728 + acl_role_set.r_hash =
9729 + (struct acl_role_label **) create_table(&acl_role_set.r_size, sizeof(void *));
9730 + name_set.n_hash = (struct name_entry **) create_table(&name_set.n_size, sizeof(void *));
9731 + inodev_set.i_hash =
9732 + (struct inodev_entry **) create_table(&inodev_set.i_size, sizeof(void *));
9734 + if (!subj_map_set.s_hash || !acl_role_set.r_hash ||
9735 + !name_set.n_hash || !inodev_set.i_hash)
9738 + memset(subj_map_set.s_hash, 0,
9739 + sizeof(struct subject_map *) * subj_map_set.s_size);
9740 + memset(acl_role_set.r_hash, 0,
9741 + sizeof (struct acl_role_label *) * acl_role_set.r_size);
9742 + memset(name_set.n_hash, 0,
9743 + sizeof (struct name_entry *) * name_set.n_size);
9744 + memset(inodev_set.i_hash, 0,
9745 + sizeof (struct inodev_entry *) * inodev_set.i_size);
9750 +/* free information not needed after startup
9751 + currently contains user->kernel pointer mappings for subjects
9755 +free_init_variables(void)
9759 + if (subj_map_set.s_hash) {
9760 + for (i = 0; i < subj_map_set.s_size; i++) {
9761 + if (subj_map_set.s_hash[i]) {
9762 + kfree(subj_map_set.s_hash[i]);
9763 + subj_map_set.s_hash[i] = NULL;
9767 + if ((subj_map_set.s_size * sizeof (struct subject_map *)) <=
9769 + kfree(subj_map_set.s_hash);
9771 + vfree(subj_map_set.s_hash);
9778 +free_variables(void)
9780 + struct acl_subject_label *s;
9781 + struct acl_role_label *r;
9782 + struct task_struct *task, *task2;
9783 + unsigned int i, x;
9785 + gr_clear_learn_entries();
9787 + read_lock(&tasklist_lock);
9788 + do_each_thread(task2, task) {
9789 + task->acl_sp_role = 0;
9790 + task->acl_role_id = 0;
9792 + task->role = NULL;
9793 + } while_each_thread(task2, task);
9794 + read_unlock(&tasklist_lock);
9796 + /* release the reference to the real root dentry and vfsmount */
9800 + if (real_root_mnt)
9801 + mntput(real_root_mnt);
9802 + real_root_mnt = NULL;
9804 + /* free all object hash tables */
9806 + FOR_EACH_ROLE_START(r, i)
9807 + if (r->subj_hash == NULL)
9809 + FOR_EACH_SUBJECT_START(r, s, x)
9810 + if (s->obj_hash == NULL)
9812 + if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE)
9813 + kfree(s->obj_hash);
9815 + vfree(s->obj_hash);
9816 + FOR_EACH_SUBJECT_END(s, x)
9817 + FOR_EACH_NESTED_SUBJECT_START(r, s)
9818 + if (s->obj_hash == NULL)
9820 + if ((s->obj_hash_size * sizeof (struct acl_object_label *)) <= PAGE_SIZE)
9821 + kfree(s->obj_hash);
9823 + vfree(s->obj_hash);
9824 + FOR_EACH_NESTED_SUBJECT_END(s)
9825 + if ((r->subj_hash_size * sizeof (struct acl_subject_label *)) <= PAGE_SIZE)
9826 + kfree(r->subj_hash);
9828 + vfree(r->subj_hash);
9829 + r->subj_hash = NULL;
9830 + FOR_EACH_ROLE_END(r,i)
9834 + if (acl_role_set.r_hash) {
9835 + if ((acl_role_set.r_size * sizeof (struct acl_role_label *)) <=
9837 + kfree(acl_role_set.r_hash);
9839 + vfree(acl_role_set.r_hash);
9841 + if (name_set.n_hash) {
9842 + if ((name_set.n_size * sizeof (struct name_entry *)) <=
9844 + kfree(name_set.n_hash);
9846 + vfree(name_set.n_hash);
9849 + if (inodev_set.i_hash) {
9850 + if ((inodev_set.i_size * sizeof (struct inodev_entry *)) <=
9852 + kfree(inodev_set.i_hash);
9854 + vfree(inodev_set.i_hash);
9859 + memset(&name_set, 0, sizeof (struct name_db));
9860 + memset(&inodev_set, 0, sizeof (struct inodev_db));
9861 + memset(&acl_role_set, 0, sizeof (struct acl_role_db));
9862 + memset(&subj_map_set, 0, sizeof (struct acl_subj_map_db));
9864 + default_role = NULL;
9870 +count_user_objs(struct acl_object_label *userp)
9872 + struct acl_object_label o_tmp;
9876 + if (copy_from_user(&o_tmp, userp,
9877 + sizeof (struct acl_object_label)))
9880 + userp = o_tmp.prev;
9887 +static struct acl_subject_label *
9888 +do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role);
9891 +copy_user_glob(struct acl_object_label *obj)
9893 + struct acl_object_label *g_tmp, **guser;
9897 + if (obj->globbed == NULL)
9900 + guser = &obj->globbed;
9902 + g_tmp = (struct acl_object_label *)
9903 + acl_alloc(sizeof (struct acl_object_label));
9904 + if (g_tmp == NULL)
9907 + if (copy_from_user(g_tmp, *guser,
9908 + sizeof (struct acl_object_label)))
9911 + len = strnlen_user(g_tmp->filename, PATH_MAX);
9913 + if (!len || len >= PATH_MAX)
9916 + if ((tmp = (char *) acl_alloc(len)) == NULL)
9919 + if (copy_from_user(tmp, g_tmp->filename, len))
9922 + g_tmp->filename = tmp;
9925 + guser = &(g_tmp->next);
9932 +copy_user_objs(struct acl_object_label *userp, struct acl_subject_label *subj,
9933 + struct acl_role_label *role)
9935 + struct acl_object_label *o_tmp;
9941 + if ((o_tmp = (struct acl_object_label *)
9942 + acl_alloc(sizeof (struct acl_object_label))) == NULL)
9945 + if (copy_from_user(o_tmp, userp,
9946 + sizeof (struct acl_object_label)))
9949 + userp = o_tmp->prev;
9951 + len = strnlen_user(o_tmp->filename, PATH_MAX);
9953 + if (!len || len >= PATH_MAX)
9956 + if ((tmp = (char *) acl_alloc(len)) == NULL)
9959 + if (copy_from_user(tmp, o_tmp->filename, len))
9962 + o_tmp->filename = tmp;
9964 + insert_acl_obj_label(o_tmp, subj);
9965 + if (!insert_name_entry(o_tmp->filename, o_tmp->inode,
9969 + ret = copy_user_glob(o_tmp);
9973 + if (o_tmp->nested) {
9974 + o_tmp->nested = do_copy_user_subj(o_tmp->nested, role);
9975 + if (IS_ERR(o_tmp->nested))
9976 + return PTR_ERR(o_tmp->nested);
9978 + /* insert into nested subject list */
9979 + o_tmp->nested->next = role->hash->first;
9980 + role->hash->first = o_tmp->nested;
9988 +count_user_subjs(struct acl_subject_label *userp)
9990 + struct acl_subject_label s_tmp;
9994 + if (copy_from_user(&s_tmp, userp,
9995 + sizeof (struct acl_subject_label)))
9998 + userp = s_tmp.prev;
9999 + /* do not count nested subjects against this count, since
10000 + they are not included in the hash table, but are
10001 + attached to objects. We have already counted
10002 + the subjects in userspace for the allocation
10005 + if (!(s_tmp.mode & GR_NESTED))
10013 +copy_user_allowedips(struct acl_role_label *rolep)
10015 + struct role_allowed_ip *ruserip, *rtmp = NULL, *rlast;
10017 + ruserip = rolep->allowed_ips;
10019 + while (ruserip) {
10022 + if ((rtmp = (struct role_allowed_ip *)
10023 + acl_alloc(sizeof (struct role_allowed_ip))) == NULL)
10026 + if (copy_from_user(rtmp, ruserip,
10027 + sizeof (struct role_allowed_ip)))
10030 + ruserip = rtmp->prev;
10033 + rtmp->prev = NULL;
10034 + rolep->allowed_ips = rtmp;
10036 + rlast->next = rtmp;
10037 + rtmp->prev = rlast;
10041 + rtmp->next = NULL;
10048 +copy_user_transitions(struct acl_role_label *rolep)
10050 + struct role_transition *rusertp, *rtmp = NULL, *rlast;
10052 + unsigned int len;
10055 + rusertp = rolep->transitions;
10057 + while (rusertp) {
10060 + if ((rtmp = (struct role_transition *)
10061 + acl_alloc(sizeof (struct role_transition))) == NULL)
10064 + if (copy_from_user(rtmp, rusertp,
10065 + sizeof (struct role_transition)))
10068 + rusertp = rtmp->prev;
10070 + len = strnlen_user(rtmp->rolename, GR_SPROLE_LEN);
10072 + if (!len || len >= GR_SPROLE_LEN)
10075 + if ((tmp = (char *) acl_alloc(len)) == NULL)
10078 + if (copy_from_user(tmp, rtmp->rolename, len))
10081 + rtmp->rolename = tmp;
10084 + rtmp->prev = NULL;
10085 + rolep->transitions = rtmp;
10087 + rlast->next = rtmp;
10088 + rtmp->prev = rlast;
10092 + rtmp->next = NULL;
10098 +static struct acl_subject_label *
10099 +do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role)
10101 + struct acl_subject_label *s_tmp = NULL, *s_tmp2;
10102 + unsigned int len;
10105 + struct acl_ip_label **i_tmp, *i_utmp2;
10106 + struct gr_hash_struct ghash;
10107 + struct subject_map *subjmap;
10108 + unsigned int i_num;
10111 + s_tmp = lookup_subject_map(userp);
10113 + /* we've already copied this subject into the kernel, just return
10114 + the reference to it, and don't copy it over again
10119 + if ((s_tmp = (struct acl_subject_label *)
10120 + acl_alloc(sizeof (struct acl_subject_label))) == NULL)
10121 + return ERR_PTR(-ENOMEM);
10123 + subjmap = (struct subject_map *)kmalloc(sizeof (struct subject_map), GFP_KERNEL);
10124 + if (subjmap == NULL)
10125 + return ERR_PTR(-ENOMEM);
10127 + subjmap->user = userp;
10128 + subjmap->kernel = s_tmp;
10129 + insert_subj_map_entry(subjmap);
10131 + if (copy_from_user(s_tmp, userp,
10132 + sizeof (struct acl_subject_label)))
10133 + return ERR_PTR(-EFAULT);
10135 + len = strnlen_user(s_tmp->filename, PATH_MAX);
10137 + if (!len || len >= PATH_MAX)
10138 + return ERR_PTR(-EINVAL);
10140 + if ((tmp = (char *) acl_alloc(len)) == NULL)
10141 + return ERR_PTR(-ENOMEM);
10143 + if (copy_from_user(tmp, s_tmp->filename, len))
10144 + return ERR_PTR(-EFAULT);
10146 + s_tmp->filename = tmp;
10148 + if (!strcmp(s_tmp->filename, "/"))
10149 + role->root_label = s_tmp;
10151 + if (copy_from_user(&ghash, s_tmp->hash, sizeof(struct gr_hash_struct)))
10152 + return ERR_PTR(-EFAULT);
10154 + /* copy user and group transition tables */
10156 + if (s_tmp->user_trans_num) {
10159 + uidlist = (uid_t *)acl_alloc(s_tmp->user_trans_num * sizeof(uid_t));
10160 + if (uidlist == NULL)
10161 + return ERR_PTR(-ENOMEM);
10162 + if (copy_from_user(uidlist, s_tmp->user_transitions, s_tmp->user_trans_num * sizeof(uid_t)))
10163 + return ERR_PTR(-EFAULT);
10165 + s_tmp->user_transitions = uidlist;
10168 + if (s_tmp->group_trans_num) {
10171 + gidlist = (gid_t *)acl_alloc(s_tmp->group_trans_num * sizeof(gid_t));
10172 + if (gidlist == NULL)
10173 + return ERR_PTR(-ENOMEM);
10174 + if (copy_from_user(gidlist, s_tmp->group_transitions, s_tmp->group_trans_num * sizeof(gid_t)))
10175 + return ERR_PTR(-EFAULT);
10177 + s_tmp->group_transitions = gidlist;
10180 + /* set up object hash table */
10181 + num_objs = count_user_objs(ghash.first);
10183 + s_tmp->obj_hash_size = num_objs;
10184 + s_tmp->obj_hash =
10185 + (struct acl_object_label **)
10186 + create_table(&(s_tmp->obj_hash_size), sizeof(void *));
10188 + if (!s_tmp->obj_hash)
10189 + return ERR_PTR(-ENOMEM);
10191 + memset(s_tmp->obj_hash, 0,
10192 + s_tmp->obj_hash_size *
10193 + sizeof (struct acl_object_label *));
10195 + /* add in objects */
10196 + err = copy_user_objs(ghash.first, s_tmp, role);
10199 + return ERR_PTR(err);
10201 + /* set pointer for parent subject */
10202 + if (s_tmp->parent_subject) {
10203 + s_tmp2 = do_copy_user_subj(s_tmp->parent_subject, role);
10205 + if (IS_ERR(s_tmp2))
10208 + s_tmp->parent_subject = s_tmp2;
10211 + /* add in ip acls */
10213 + if (!s_tmp->ip_num) {
10214 + s_tmp->ips = NULL;
10219 + (struct acl_ip_label **) acl_alloc(s_tmp->ip_num *
10221 + acl_ip_label *));
10224 + return ERR_PTR(-ENOMEM);
10226 + for (i_num = 0; i_num < s_tmp->ip_num; i_num++) {
10227 + *(i_tmp + i_num) =
10228 + (struct acl_ip_label *)
10229 + acl_alloc(sizeof (struct acl_ip_label));
10230 + if (!*(i_tmp + i_num))
10231 + return ERR_PTR(-ENOMEM);
10233 + if (copy_from_user
10234 + (&i_utmp2, s_tmp->ips + i_num,
10235 + sizeof (struct acl_ip_label *)))
10236 + return ERR_PTR(-EFAULT);
10238 + if (copy_from_user
10239 + (*(i_tmp + i_num), i_utmp2,
10240 + sizeof (struct acl_ip_label)))
10241 + return ERR_PTR(-EFAULT);
10243 + if ((*(i_tmp + i_num))->iface == NULL)
10246 + len = strnlen_user((*(i_tmp + i_num))->iface, IFNAMSIZ);
10247 + if (!len || len >= IFNAMSIZ)
10248 + return ERR_PTR(-EINVAL);
10249 + tmp = acl_alloc(len);
10251 + return ERR_PTR(-ENOMEM);
10252 + if (copy_from_user(tmp, (*(i_tmp + i_num))->iface, len))
10253 + return ERR_PTR(-EFAULT);
10254 + (*(i_tmp + i_num))->iface = tmp;
10257 + s_tmp->ips = i_tmp;
10260 + if (!insert_name_entry(s_tmp->filename, s_tmp->inode,
10262 + return ERR_PTR(-ENOMEM);
10268 +copy_user_subjs(struct acl_subject_label *userp, struct acl_role_label *role)
10270 + struct acl_subject_label s_pre;
10271 + struct acl_subject_label * ret;
10275 + if (copy_from_user(&s_pre, userp,
10276 + sizeof (struct acl_subject_label)))
10279 + /* do not add nested subjects here, add
10280 + while parsing objects
10283 + if (s_pre.mode & GR_NESTED) {
10284 + userp = s_pre.prev;
10288 + ret = do_copy_user_subj(userp, role);
10290 + err = PTR_ERR(ret);
10294 + insert_acl_subj_label(ret, role);
10296 + userp = s_pre.prev;
10303 +copy_user_acl(struct gr_arg *arg)
10305 + struct acl_role_label *r_tmp = NULL, **r_utmp, *r_utmp2;
10306 + struct sprole_pw *sptmp;
10307 + struct gr_hash_struct *ghash;
10308 + uid_t *domainlist;
10309 + unsigned int r_num;
10310 + unsigned int len;
10316 + /* we need a default and kernel role */
10317 + if (arg->role_db.num_roles < 2)
10320 + /* copy special role authentication info from userspace */
10322 + num_sprole_pws = arg->num_sprole_pws;
10323 + acl_special_roles = (struct sprole_pw **) acl_alloc(num_sprole_pws * sizeof(struct sprole_pw *));
10325 + if (!acl_special_roles) {
10330 + for (i = 0; i < num_sprole_pws; i++) {
10331 + sptmp = (struct sprole_pw *) acl_alloc(sizeof(struct sprole_pw));
10336 + if (copy_from_user(sptmp, arg->sprole_pws + i,
10337 + sizeof (struct sprole_pw))) {
10343 + strnlen_user(sptmp->rolename, GR_SPROLE_LEN);
10345 + if (!len || len >= GR_SPROLE_LEN) {
10350 + if ((tmp = (char *) acl_alloc(len)) == NULL) {
10355 + if (copy_from_user(tmp, sptmp->rolename, len)) {
10360 +#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
10361 + printk(KERN_ALERT "Copying special role %s\n", tmp);
10363 + sptmp->rolename = tmp;
10364 + acl_special_roles[i] = sptmp;
10367 + r_utmp = (struct acl_role_label **) arg->role_db.r_table;
10369 + for (r_num = 0; r_num < arg->role_db.num_roles; r_num++) {
10370 + r_tmp = acl_alloc(sizeof (struct acl_role_label));
10377 + if (copy_from_user(&r_utmp2, r_utmp + r_num,
10378 + sizeof (struct acl_role_label *))) {
10383 + if (copy_from_user(r_tmp, r_utmp2,
10384 + sizeof (struct acl_role_label))) {
10389 + len = strnlen_user(r_tmp->rolename, GR_SPROLE_LEN);
10391 + if (!len || len >= PATH_MAX) {
10396 + if ((tmp = (char *) acl_alloc(len)) == NULL) {
10400 + if (copy_from_user(tmp, r_tmp->rolename, len)) {
10404 + r_tmp->rolename = tmp;
10406 + if (!strcmp(r_tmp->rolename, "default")
10407 + && (r_tmp->roletype & GR_ROLE_DEFAULT)) {
10408 + default_role = r_tmp;
10409 + } else if (!strcmp(r_tmp->rolename, ":::kernel:::")) {
10410 + kernel_role = r_tmp;
10413 + if ((ghash = (struct gr_hash_struct *) acl_alloc(sizeof(struct gr_hash_struct))) == NULL) {
10417 + if (copy_from_user(ghash, r_tmp->hash, sizeof(struct gr_hash_struct))) {
10422 + r_tmp->hash = ghash;
10424 + num_subjs = count_user_subjs(r_tmp->hash->first);
10426 + r_tmp->subj_hash_size = num_subjs;
10427 + r_tmp->subj_hash =
10428 + (struct acl_subject_label **)
10429 + create_table(&(r_tmp->subj_hash_size), sizeof(void *));
10431 + if (!r_tmp->subj_hash) {
10436 + err = copy_user_allowedips(r_tmp);
10440 + /* copy domain info */
10441 + if (r_tmp->domain_children != NULL) {
10442 + domainlist = acl_alloc(r_tmp->domain_child_num * sizeof(uid_t));
10443 + if (domainlist == NULL) {
10447 + if (copy_from_user(domainlist, r_tmp->domain_children, r_tmp->domain_child_num * sizeof(uid_t))) {
10451 + r_tmp->domain_children = domainlist;
10454 + err = copy_user_transitions(r_tmp);
10458 + memset(r_tmp->subj_hash, 0,
10459 + r_tmp->subj_hash_size *
10460 + sizeof (struct acl_subject_label *));
10462 + err = copy_user_subjs(r_tmp->hash->first, r_tmp);
10467 + /* set nested subject list to null */
10468 + r_tmp->hash->first = NULL;
10470 + insert_acl_role_label(r_tmp);
10475 + free_variables();
10482 +gracl_init(struct gr_arg *args)
10486 + memcpy(gr_system_salt, args->salt, GR_SALT_LEN);
10487 + memcpy(gr_system_sum, args->sum, GR_SHA_LEN);
10489 + if (init_variables(args)) {
10490 + gr_log_str(GR_DONT_AUDIT_GOOD, GR_INITF_ACL_MSG, GR_VERSION);
10492 + free_variables();
10496 + error = copy_user_acl(args);
10497 + free_init_variables();
10499 + free_variables();
10503 + if ((error = gr_set_acls(0))) {
10504 + free_variables();
10508 + gr_status |= GR_READY;
10513 +/* derived from glibc fnmatch() 0: match, 1: no match*/
10516 +glob_match(const char *p, const char *n)
10520 + while ((c = *p++) != '\0') {
10525 + else if (*n == '/')
10533 + for (c = *p++; c == '?' || c == '*'; c = *p++) {
10536 + else if (c == '?') {
10546 + const char *endp;
10548 + if ((endp = strchr(n, '/')) == NULL)
10549 + endp = n + strlen(n);
10552 + for (--p; n < endp; ++n)
10553 + if (!glob_match(p, n))
10555 + } else if (c == '/') {
10556 + while (*n != '\0' && *n != '/')
10558 + if (*n == '/' && !glob_match(p, n + 1))
10561 + for (--p; n < endp; ++n)
10562 + if (*n == c && !glob_match(p, n))
10573 + if (*n == '\0' || *n == '/')
10576 + not = (*p == '!' || *p == '^');
10582 + unsigned char fn = (unsigned char)*n;
10592 + if (c == '-' && *p != ']') {
10593 + unsigned char cend = *p++;
10595 + if (cend == '\0')
10598 + if (cold <= fn && fn <= cend)
10612 + while (c != ']') {
10639 +static struct acl_object_label *
10640 +chk_glob_label(struct acl_object_label *globbed,
10641 + struct dentry *dentry, struct vfsmount *mnt, char **path)
10643 + struct acl_object_label *tmp;
10645 + if (*path == NULL)
10646 + *path = gr_to_filename_nolock(dentry, mnt);
10651 + if (!glob_match(tmp->filename, *path))
10659 +static struct acl_object_label *
10660 +__full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
10661 + const ino_t curr_ino, const dev_t curr_dev,
10662 + const struct acl_subject_label *subj, char **path)
10664 + struct acl_subject_label *tmpsubj;
10665 + struct acl_object_label *retval;
10666 + struct acl_object_label *retval2;
10668 + tmpsubj = (struct acl_subject_label *) subj;
10669 + read_lock(&gr_inode_lock);
10671 + retval = lookup_acl_obj_label(curr_ino, curr_dev, tmpsubj);
10673 + if (retval->globbed) {
10674 + retval2 = chk_glob_label(retval->globbed, (struct dentry *)orig_dentry,
10675 + (struct vfsmount *)orig_mnt, path);
10677 + retval = retval2;
10681 + } while ((tmpsubj = tmpsubj->parent_subject));
10682 + read_unlock(&gr_inode_lock);
10687 +static __inline__ struct acl_object_label *
10688 +full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt,
10689 + const struct dentry *curr_dentry,
10690 + const struct acl_subject_label *subj, char **path)
10692 + return __full_lookup(orig_dentry, orig_mnt,
10693 + curr_dentry->d_inode->i_ino,
10694 + curr_dentry->d_inode->i_sb->s_dev, subj, path);
10697 +static 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, char *path)
10701 + struct dentry *dentry = (struct dentry *) l_dentry;
10702 + struct vfsmount *mnt = (struct vfsmount *) l_mnt;
10703 + struct acl_object_label *retval;
10705 + spin_lock(&dcache_lock);
10708 + if (dentry == real_root && mnt == real_root_mnt)
10711 + if (dentry == mnt->mnt_root || IS_ROOT(dentry)) {
10712 + if (mnt->mnt_parent == mnt)
10715 + retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
10716 + if (retval != NULL)
10719 + dentry = mnt->mnt_mountpoint;
10720 + mnt = mnt->mnt_parent;
10724 + retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
10725 + if (retval != NULL)
10728 + dentry = dentry->d_parent;
10731 + retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path);
10733 + if (retval == NULL)
10734 + retval = full_lookup(l_dentry, l_mnt, real_root, subj, &path);
10736 + spin_unlock(&dcache_lock);
10740 +static __inline__ struct acl_object_label *
10741 +chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
10742 + const struct acl_subject_label *subj)
10744 + char *path = NULL;
10745 + return __chk_obj_label(l_dentry, l_mnt, subj, path);
10748 +static __inline__ struct acl_object_label *
10749 +chk_obj_create_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
10750 + const struct acl_subject_label *subj, char *path)
10752 + return __chk_obj_label(l_dentry, l_mnt, subj, path);
10755 +static struct acl_subject_label *
10756 +chk_subj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt,
10757 + const struct acl_role_label *role)
10759 + struct dentry *dentry = (struct dentry *) l_dentry;
10760 + struct vfsmount *mnt = (struct vfsmount *) l_mnt;
10761 + struct acl_subject_label *retval;
10763 + spin_lock(&dcache_lock);
10766 + if (dentry == real_root && mnt == real_root_mnt)
10768 + if (dentry == mnt->mnt_root || IS_ROOT(dentry)) {
10769 + if (mnt->mnt_parent == mnt)
10772 + read_lock(&gr_inode_lock);
10774 + lookup_acl_subj_label(dentry->d_inode->i_ino,
10775 + dentry->d_inode->i_sb->s_dev, role);
10776 + read_unlock(&gr_inode_lock);
10777 + if (retval != NULL)
10780 + dentry = mnt->mnt_mountpoint;
10781 + mnt = mnt->mnt_parent;
10785 + read_lock(&gr_inode_lock);
10786 + retval = lookup_acl_subj_label(dentry->d_inode->i_ino,
10787 + dentry->d_inode->i_sb->s_dev, role);
10788 + read_unlock(&gr_inode_lock);
10789 + if (retval != NULL)
10792 + dentry = dentry->d_parent;
10795 + read_lock(&gr_inode_lock);
10796 + retval = lookup_acl_subj_label(dentry->d_inode->i_ino,
10797 + dentry->d_inode->i_sb->s_dev, role);
10798 + read_unlock(&gr_inode_lock);
10800 + if (unlikely(retval == NULL)) {
10801 + read_lock(&gr_inode_lock);
10802 + retval = lookup_acl_subj_label(real_root->d_inode->i_ino,
10803 + real_root->d_inode->i_sb->s_dev, role);
10804 + read_unlock(&gr_inode_lock);
10807 + spin_unlock(&dcache_lock);
10813 +gr_log_learn(const struct task_struct *task, const struct dentry *dentry, const struct vfsmount *mnt, const __u32 mode)
10815 + security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, task->role->roletype,
10816 + task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_dentry,
10817 + task->exec_file->f_vfsmnt) : task->acl->filename, task->acl->filename,
10818 + 1, 1, gr_to_filename(dentry, mnt), (unsigned long) mode, NIPQUAD(task->signal->curr_ip));
10824 +gr_log_learn_id_change(const struct task_struct *task, const char type, const unsigned int real,
10825 + const unsigned int effective, const unsigned int fs)
10827 + security_learn(GR_ID_LEARN_MSG, task->role->rolename, task->role->roletype,
10828 + task->uid, task->gid, task->exec_file ? gr_to_filename1(task->exec_file->f_dentry,
10829 + task->exec_file->f_vfsmnt) : task->acl->filename, task->acl->filename,
10830 + type, real, effective, fs, NIPQUAD(task->signal->curr_ip));
10836 +gr_check_link(const struct dentry * new_dentry,
10837 + const struct dentry * parent_dentry,
10838 + const struct vfsmount * parent_mnt,
10839 + const struct dentry * old_dentry, const struct vfsmount * old_mnt)
10841 + struct acl_object_label *obj;
10842 + __u32 oldmode, newmode;
10845 + if (unlikely(!(gr_status & GR_READY)))
10846 + return (GR_CREATE | GR_LINK);
10848 + obj = chk_obj_label(old_dentry, old_mnt, current->acl);
10849 + oldmode = obj->mode;
10851 + if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
10852 + oldmode |= (GR_CREATE | GR_LINK);
10854 + needmode = GR_CREATE | GR_AUDIT_CREATE | GR_SUPPRESS;
10855 + if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID))
10856 + needmode |= GR_SETID | GR_AUDIT_SETID;
10859 + gr_check_create(new_dentry, parent_dentry, parent_mnt,
10860 + oldmode | needmode);
10862 + needmode = newmode & (GR_FIND | GR_APPEND | GR_WRITE | GR_EXEC |
10863 + GR_SETID | GR_READ | GR_FIND | GR_DELETE |
10864 + GR_INHERIT | GR_AUDIT_INHERIT);
10866 + if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID) && !(newmode & GR_SETID))
10869 + if ((oldmode & needmode) != needmode)
10872 + needmode = oldmode & (GR_NOPTRACE | GR_PTRACERD | GR_INHERIT | GR_AUDITS);
10873 + if ((newmode & needmode) != needmode)
10876 + if ((newmode & (GR_CREATE | GR_LINK)) == (GR_CREATE | GR_LINK))
10879 + needmode = oldmode;
10880 + if (old_dentry->d_inode->i_mode & (S_ISUID | S_ISGID))
10881 + needmode |= GR_SETID;
10883 + if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) {
10884 + gr_log_learn(current, old_dentry, old_mnt, needmode);
10885 + return (GR_CREATE | GR_LINK);
10886 + } else if (newmode & GR_SUPPRESS)
10887 + return GR_SUPPRESS;
10893 +gr_search_file(const struct dentry * dentry, const __u32 mode,
10894 + const struct vfsmount * mnt)
10896 + __u32 retval = mode;
10897 + struct acl_subject_label *curracl;
10898 + struct acl_object_label *currobj;
10900 + if (unlikely(!(gr_status & GR_READY)))
10901 + return (mode & ~GR_AUDITS);
10903 + curracl = current->acl;
10905 + currobj = chk_obj_label(dentry, mnt, curracl);
10906 + retval = currobj->mode & mode;
10909 + ((curracl->mode & (GR_LEARN | GR_INHERITLEARN)) && !(mode & GR_NOPTRACE)
10910 + && (retval != (mode & ~(GR_AUDITS | GR_SUPPRESS))))) {
10911 + __u32 new_mode = mode;
10913 + new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
10915 + retval = new_mode;
10917 + if (new_mode & GR_EXEC && curracl->mode & GR_INHERITLEARN)
10918 + new_mode |= GR_INHERIT;
10920 + if (!(mode & GR_NOLEARN))
10921 + gr_log_learn(current, dentry, mnt, new_mode);
10928 +gr_check_create(const struct dentry * new_dentry, const struct dentry * parent,
10929 + const struct vfsmount * mnt, const __u32 mode)
10931 + struct name_entry *match;
10932 + struct acl_object_label *matchpo;
10933 + struct acl_subject_label *curracl;
10937 + if (unlikely(!(gr_status & GR_READY)))
10938 + return (mode & ~GR_AUDITS);
10940 + preempt_disable();
10941 + path = gr_to_filename_rbac(new_dentry, mnt);
10942 + match = lookup_name_entry(path);
10945 + goto check_parent;
10947 + curracl = current->acl;
10949 + read_lock(&gr_inode_lock);
10950 + matchpo = lookup_acl_obj_label_create(match->inode, match->device, curracl);
10951 + read_unlock(&gr_inode_lock);
10954 + if ((matchpo->mode & mode) !=
10955 + (mode & ~(GR_AUDITS | GR_SUPPRESS))
10956 + && curracl->mode & (GR_LEARN | GR_INHERITLEARN)) {
10957 + __u32 new_mode = mode;
10959 + new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
10961 + gr_log_learn(current, new_dentry, mnt, new_mode);
10963 + preempt_enable();
10966 + preempt_enable();
10967 + return (matchpo->mode & mode);
10971 + curracl = current->acl;
10973 + matchpo = chk_obj_create_label(parent, mnt, curracl, path);
10974 + retval = matchpo->mode & mode;
10976 + if ((retval != (mode & ~(GR_AUDITS | GR_SUPPRESS)))
10977 + && (curracl->mode & (GR_LEARN | GR_INHERITLEARN))) {
10978 + __u32 new_mode = mode;
10980 + new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
10982 + gr_log_learn(current, new_dentry, mnt, new_mode);
10983 + preempt_enable();
10987 + preempt_enable();
10992 +gr_check_hidden_task(const struct task_struct *task)
10994 + if (unlikely(!(gr_status & GR_READY)))
10997 + if (!(task->acl->mode & GR_PROCFIND) && !(current->acl->mode & GR_VIEW))
11004 +gr_check_protected_task(const struct task_struct *task)
11006 + if (unlikely(!(gr_status & GR_READY) || !task))
11009 + if ((task->acl->mode & GR_PROTECTED) && !(current->acl->mode & GR_KILL) &&
11010 + task->acl != current->acl)
11017 +gr_copy_label(struct task_struct *tsk)
11019 + tsk->signal->used_accept = 0;
11020 + tsk->acl_sp_role = 0;
11021 + tsk->acl_role_id = current->acl_role_id;
11022 + tsk->acl = current->acl;
11023 + tsk->role = current->role;
11024 + tsk->signal->curr_ip = current->signal->curr_ip;
11025 + if (current->exec_file)
11026 + get_file(current->exec_file);
11027 + tsk->exec_file = current->exec_file;
11028 + tsk->is_writable = current->is_writable;
11029 + if (unlikely(current->signal->used_accept))
11030 + current->signal->curr_ip = 0;
11036 +gr_set_proc_res(struct task_struct *task)
11038 + struct acl_subject_label *proc;
11039 + unsigned short i;
11041 + proc = task->acl;
11043 + if (proc->mode & (GR_LEARN | GR_INHERITLEARN))
11046 + for (i = 0; i < (GR_NLIMITS - 1); i++) {
11047 + if (!(proc->resmask & (1 << i)))
11050 + task->signal->rlim[i].rlim_cur = proc->res[i].rlim_cur;
11051 + task->signal->rlim[i].rlim_max = proc->res[i].rlim_max;
11058 +gr_check_user_change(int real, int effective, int fs)
11065 + int effectiveok = 0;
11068 + if (unlikely(!(gr_status & GR_READY)))
11071 + if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
11072 + gr_log_learn_id_change(current, 'u', real, effective, fs);
11074 + num = current->acl->user_trans_num;
11075 + uidlist = current->acl->user_transitions;
11077 + if (uidlist == NULL)
11082 + if (effective == -1)
11087 + if (current->acl->user_trans_type & GR_ID_ALLOW) {
11088 + for (i = 0; i < num; i++) {
11089 + curuid = (int)uidlist[i];
11090 + if (real == curuid)
11092 + if (effective == curuid)
11094 + if (fs == curuid)
11097 + } else if (current->acl->user_trans_type & GR_ID_DENY) {
11098 + for (i = 0; i < num; i++) {
11099 + curuid = (int)uidlist[i];
11100 + if (real == curuid)
11102 + if (effective == curuid)
11104 + if (fs == curuid)
11107 + /* not in deny list */
11115 + if (realok && effectiveok && fsok)
11118 + gr_log_int(GR_DONT_AUDIT, GR_USRCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real);
11124 +gr_check_group_change(int real, int effective, int fs)
11131 + int effectiveok = 0;
11134 + if (unlikely(!(gr_status & GR_READY)))
11137 + if (current->acl->mode & (GR_LEARN | GR_INHERITLEARN))
11138 + gr_log_learn_id_change(current, 'g', real, effective, fs);
11140 + num = current->acl->group_trans_num;
11141 + gidlist = current->acl->group_transitions;
11143 + if (gidlist == NULL)
11148 + if (effective == -1)
11153 + if (current->acl->group_trans_type & GR_ID_ALLOW) {
11154 + for (i = 0; i < num; i++) {
11155 + curgid = (int)gidlist[i];
11156 + if (real == curgid)
11158 + if (effective == curgid)
11160 + if (fs == curgid)
11163 + } else if (current->acl->group_trans_type & GR_ID_DENY) {
11164 + for (i = 0; i < num; i++) {
11165 + curgid = (int)gidlist[i];
11166 + if (real == curgid)
11168 + if (effective == curgid)
11170 + if (fs == curgid)
11173 + /* not in deny list */
11181 + if (realok && effectiveok && fsok)
11184 + gr_log_int(GR_DONT_AUDIT, GR_GRPCHANGE_ACL_MSG, realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real);
11190 +gr_set_role_label(struct task_struct *task, const uid_t uid, const uid_t gid)
11192 + struct acl_role_label *role = task->role;
11193 + struct acl_subject_label *subj = NULL;
11194 + struct acl_object_label *obj;
11195 + struct file *filp;
11197 + if (unlikely(!(gr_status & GR_READY)))
11200 + filp = task->exec_file;
11202 + /* kernel process, we'll give them the kernel role */
11203 + if (unlikely(!filp)) {
11204 + task->role = kernel_role;
11205 + task->acl = kernel_role->root_label;
11207 + } else if (!task->role || !(task->role->roletype & GR_ROLE_SPECIAL))
11208 + role = lookup_acl_role_label(task, uid, gid);
11210 + /* perform subject lookup in possibly new role
11211 + we can use this result below in the case where role == task->role
11213 + subj = chk_subj_label(filp->f_dentry, filp->f_vfsmnt, role);
11215 + /* if we changed uid/gid, but result in the same role
11216 + and are using inheritance, don't lose the inherited subject
11217 + if current subject is other than what normal lookup
11218 + would result in, we arrived via inheritance, don't
11221 + if (role != task->role || (!(task->acl->mode & GR_INHERITLEARN) &&
11222 + (subj == task->acl)))
11223 + task->acl = subj;
11225 + task->role = role;
11227 + task->is_writable = 0;
11229 + /* ignore additional mmap checks for processes that are writable
11230 + by the default ACL */
11231 + obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
11232 + if (unlikely(obj->mode & GR_WRITE))
11233 + task->is_writable = 1;
11234 + obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label);
11235 + if (unlikely(obj->mode & GR_WRITE))
11236 + task->is_writable = 1;
11238 +#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
11239 + printk(KERN_ALERT "Set role label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
11242 + gr_set_proc_res(task);
11248 +gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
11250 + struct task_struct *task = current;
11251 + struct acl_subject_label *newacl;
11252 + struct acl_object_label *obj;
11255 + if (unlikely(!(gr_status & GR_READY)))
11258 + newacl = chk_subj_label(dentry, mnt, task->role);
11261 + if (((task->ptrace & PT_PTRACED) && !(task->acl->mode &
11262 + GR_POVERRIDE) && (task->acl != newacl) &&
11263 + !(task->role->roletype & GR_ROLE_GOD) &&
11264 + !gr_search_file(dentry, GR_PTRACERD, mnt) &&
11265 + !(task->acl->mode & (GR_LEARN | GR_INHERITLEARN))) ||
11266 + (atomic_read(&task->fs->count) > 1 ||
11267 + atomic_read(&task->files->count) > 1 ||
11268 + atomic_read(&task->sighand->count) > 1)) {
11269 + task_unlock(task);
11270 + gr_log_fs_generic(GR_DONT_AUDIT, GR_PTRACE_EXEC_ACL_MSG, dentry, mnt);
11273 + task_unlock(task);
11275 + obj = chk_obj_label(dentry, mnt, task->acl);
11276 + retmode = obj->mode & (GR_INHERIT | GR_AUDIT_INHERIT);
11278 + if (!(task->acl->mode & GR_INHERITLEARN) &&
11279 + ((newacl->mode & GR_LEARN) || !(retmode & GR_INHERIT))) {
11281 + task->acl = obj->nested;
11283 + task->acl = newacl;
11284 + } else if (retmode & GR_INHERIT && retmode & GR_AUDIT_INHERIT)
11285 + gr_log_str_fs(GR_DO_AUDIT, GR_INHERIT_ACL_MSG, task->acl->filename, dentry, mnt);
11287 + task->is_writable = 0;
11289 + /* ignore additional mmap checks for processes that are writable
11290 + by the default ACL */
11291 + obj = chk_obj_label(dentry, mnt, default_role->root_label);
11292 + if (unlikely(obj->mode & GR_WRITE))
11293 + task->is_writable = 1;
11294 + obj = chk_obj_label(dentry, mnt, task->role->root_label);
11295 + if (unlikely(obj->mode & GR_WRITE))
11296 + task->is_writable = 1;
11298 + gr_set_proc_res(task);
11300 +#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
11301 + printk(KERN_ALERT "Set subject label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
11307 +do_handle_delete(const ino_t ino, const dev_t dev)
11309 + struct acl_object_label *matchpo;
11310 + struct acl_subject_label *matchps;
11311 + struct acl_subject_label *subj;
11312 + struct acl_role_label *role;
11313 + unsigned int i, x;
11315 + FOR_EACH_ROLE_START(role, i)
11316 + FOR_EACH_SUBJECT_START(role, subj, x)
11317 + if ((matchpo = lookup_acl_obj_label(ino, dev, subj)) != NULL)
11318 + matchpo->mode |= GR_DELETED;
11319 + FOR_EACH_SUBJECT_END(subj,x)
11320 + FOR_EACH_NESTED_SUBJECT_START(role, subj)
11321 + if (subj->inode == ino && subj->device == dev)
11322 + subj->mode |= GR_DELETED;
11323 + FOR_EACH_NESTED_SUBJECT_END(subj)
11324 + if ((matchps = lookup_acl_subj_label(ino, dev, role)) != NULL)
11325 + matchps->mode |= GR_DELETED;
11326 + FOR_EACH_ROLE_END(role,i)
11332 +gr_handle_delete(const ino_t ino, const dev_t dev)
11334 + if (unlikely(!(gr_status & GR_READY)))
11337 + write_lock(&gr_inode_lock);
11338 + if (unlikely((unsigned long)lookup_inodev_entry(ino, dev)))
11339 + do_handle_delete(ino, dev);
11340 + write_unlock(&gr_inode_lock);
11346 +update_acl_obj_label(const ino_t oldinode, const dev_t olddevice,
11347 + const ino_t newinode, const dev_t newdevice,
11348 + struct acl_subject_label *subj)
11350 + unsigned int index = fhash(oldinode, olddevice, subj->obj_hash_size);
11351 + struct acl_object_label *match;
11353 + match = subj->obj_hash[index];
11355 + while (match && (match->inode != oldinode ||
11356 + match->device != olddevice ||
11357 + !(match->mode & GR_DELETED)))
11358 + match = match->next;
11360 + if (match && (match->inode == oldinode)
11361 + && (match->device == olddevice)
11362 + && (match->mode & GR_DELETED)) {
11363 + if (match->prev == NULL) {
11364 + subj->obj_hash[index] = match->next;
11365 + if (match->next != NULL)
11366 + match->next->prev = NULL;
11368 + match->prev->next = match->next;
11369 + if (match->next != NULL)
11370 + match->next->prev = match->prev;
11372 + match->prev = NULL;
11373 + match->next = NULL;
11374 + match->inode = newinode;
11375 + match->device = newdevice;
11376 + match->mode &= ~GR_DELETED;
11378 + insert_acl_obj_label(match, subj);
11385 +update_acl_subj_label(const ino_t oldinode, const dev_t olddevice,
11386 + const ino_t newinode, const dev_t newdevice,
11387 + struct acl_role_label *role)
11389 + unsigned int index = fhash(oldinode, olddevice, role->subj_hash_size);
11390 + struct acl_subject_label *match;
11392 + match = role->subj_hash[index];
11394 + while (match && (match->inode != oldinode ||
11395 + match->device != olddevice ||
11396 + !(match->mode & GR_DELETED)))
11397 + match = match->next;
11399 + if (match && (match->inode == oldinode)
11400 + && (match->device == olddevice)
11401 + && (match->mode & GR_DELETED)) {
11402 + if (match->prev == NULL) {
11403 + role->subj_hash[index] = match->next;
11404 + if (match->next != NULL)
11405 + match->next->prev = NULL;
11407 + match->prev->next = match->next;
11408 + if (match->next != NULL)
11409 + match->next->prev = match->prev;
11411 + match->prev = NULL;
11412 + match->next = NULL;
11413 + match->inode = newinode;
11414 + match->device = newdevice;
11415 + match->mode &= ~GR_DELETED;
11417 + insert_acl_subj_label(match, role);
11424 +update_inodev_entry(const ino_t oldinode, const dev_t olddevice,
11425 + const ino_t newinode, const dev_t newdevice)
11427 + unsigned int index = fhash(oldinode, olddevice, inodev_set.i_size);
11428 + struct inodev_entry *match;
11430 + match = inodev_set.i_hash[index];
11432 + while (match && (match->nentry->inode != oldinode ||
11433 + match->nentry->device != olddevice))
11434 + match = match->next;
11436 + if (match && (match->nentry->inode == oldinode)
11437 + && (match->nentry->device == olddevice)) {
11438 + if (match->prev == NULL) {
11439 + inodev_set.i_hash[index] = match->next;
11440 + if (match->next != NULL)
11441 + match->next->prev = NULL;
11443 + match->prev->next = match->next;
11444 + if (match->next != NULL)
11445 + match->next->prev = match->prev;
11447 + match->prev = NULL;
11448 + match->next = NULL;
11449 + match->nentry->inode = newinode;
11450 + match->nentry->device = newdevice;
11452 + insert_inodev_entry(match);
11459 +do_handle_create(const struct name_entry *matchn, const struct dentry *dentry,
11460 + const struct vfsmount *mnt)
11462 + struct acl_subject_label *subj;
11463 + struct acl_role_label *role;
11464 + unsigned int i, x;
11466 + FOR_EACH_ROLE_START(role, i)
11467 + update_acl_subj_label(matchn->inode, matchn->device,
11468 + dentry->d_inode->i_ino,
11469 + dentry->d_inode->i_sb->s_dev, role);
11471 + FOR_EACH_NESTED_SUBJECT_START(role, subj)
11472 + if ((subj->inode == dentry->d_inode->i_ino) &&
11473 + (subj->device == dentry->d_inode->i_sb->s_dev)) {
11474 + subj->inode = dentry->d_inode->i_ino;
11475 + subj->device = dentry->d_inode->i_sb->s_dev;
11477 + FOR_EACH_NESTED_SUBJECT_END(subj)
11478 + FOR_EACH_SUBJECT_START(role, subj, x)
11479 + update_acl_obj_label(matchn->inode, matchn->device,
11480 + dentry->d_inode->i_ino,
11481 + dentry->d_inode->i_sb->s_dev, subj);
11482 + FOR_EACH_SUBJECT_END(subj,x)
11483 + FOR_EACH_ROLE_END(role,i)
11485 + update_inodev_entry(matchn->inode, matchn->device,
11486 + dentry->d_inode->i_ino, dentry->d_inode->i_sb->s_dev);
11492 +gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
11494 + struct name_entry *matchn;
11496 + if (unlikely(!(gr_status & GR_READY)))
11499 + preempt_disable();
11500 + matchn = lookup_name_entry(gr_to_filename_rbac(dentry, mnt));
11502 + if (unlikely((unsigned long)matchn)) {
11503 + write_lock(&gr_inode_lock);
11504 + do_handle_create(matchn, dentry, mnt);
11505 + write_unlock(&gr_inode_lock);
11507 + preempt_enable();
11513 +gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
11514 + struct dentry *old_dentry,
11515 + struct dentry *new_dentry,
11516 + struct vfsmount *mnt, const __u8 replace)
11518 + struct name_entry *matchn;
11520 + if (unlikely(!(gr_status & GR_READY)))
11523 + preempt_disable();
11524 + matchn = lookup_name_entry(gr_to_filename_rbac(new_dentry, mnt));
11526 + /* we wouldn't have to check d_inode if it weren't for
11527 + NFS silly-renaming
11530 + write_lock(&gr_inode_lock);
11531 + if (unlikely(replace && new_dentry->d_inode)) {
11532 + if (unlikely(lookup_inodev_entry(new_dentry->d_inode->i_ino,
11533 + new_dentry->d_inode->i_sb->s_dev) &&
11534 + (old_dentry->d_inode->i_nlink <= 1)))
11535 + do_handle_delete(new_dentry->d_inode->i_ino,
11536 + new_dentry->d_inode->i_sb->s_dev);
11539 + if (unlikely(lookup_inodev_entry(old_dentry->d_inode->i_ino,
11540 + old_dentry->d_inode->i_sb->s_dev) &&
11541 + (old_dentry->d_inode->i_nlink <= 1)))
11542 + do_handle_delete(old_dentry->d_inode->i_ino,
11543 + old_dentry->d_inode->i_sb->s_dev);
11545 + if (unlikely((unsigned long)matchn))
11546 + do_handle_create(matchn, old_dentry, mnt);
11548 + write_unlock(&gr_inode_lock);
11549 + preempt_enable();
11555 +lookup_special_role_auth(__u16 mode, const char *rolename, unsigned char **salt,
11556 + unsigned char **sum)
11558 + struct acl_role_label *r;
11559 + struct role_allowed_ip *ipp;
11560 + struct role_transition *trans;
11564 + /* check transition table */
11566 + for (trans = current->role->transitions; trans; trans = trans->next) {
11567 + if (!strcmp(rolename, trans->rolename)) {
11576 + /* handle special roles that do not require authentication
11579 + FOR_EACH_ROLE_START(r, i)
11580 + if (!strcmp(rolename, r->rolename) &&
11581 + (r->roletype & GR_ROLE_SPECIAL)) {
11583 + if (r->allowed_ips != NULL) {
11584 + for (ipp = r->allowed_ips; ipp; ipp = ipp->next) {
11585 + if ((ntohl(current->signal->curr_ip) & ipp->netmask) ==
11586 + (ntohl(ipp->addr) & ipp->netmask))
11594 + if (((mode == SPROLE) && (r->roletype & GR_ROLE_NOPW)) ||
11595 + ((mode == SPROLEPAM) && (r->roletype & GR_ROLE_PAM))) {
11601 + FOR_EACH_ROLE_END(r,i)
11603 + for (i = 0; i < num_sprole_pws; i++) {
11604 + if (!strcmp(rolename, acl_special_roles[i]->rolename)) {
11605 + *salt = acl_special_roles[i]->salt;
11606 + *sum = acl_special_roles[i]->sum;
11615 +assign_special_role(char *rolename)
11617 + struct acl_object_label *obj;
11618 + struct acl_role_label *r;
11619 + struct acl_role_label *assigned = NULL;
11620 + struct task_struct *tsk;
11621 + struct file *filp;
11624 + FOR_EACH_ROLE_START(r, i)
11625 + if (!strcmp(rolename, r->rolename) &&
11626 + (r->roletype & GR_ROLE_SPECIAL))
11628 + FOR_EACH_ROLE_END(r,i)
11633 + read_lock(&tasklist_lock);
11634 + read_lock(&grsec_exec_file_lock);
11636 + tsk = current->parent;
11640 + filp = tsk->exec_file;
11641 + if (filp == NULL)
11644 + tsk->is_writable = 0;
11646 + tsk->acl_sp_role = 1;
11647 + tsk->acl_role_id = ++acl_sp_role_value;
11648 + tsk->role = assigned;
11649 + tsk->acl = chk_subj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role);
11651 + /* ignore additional mmap checks for processes that are writable
11652 + by the default ACL */
11653 + obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
11654 + if (unlikely(obj->mode & GR_WRITE))
11655 + tsk->is_writable = 1;
11656 + obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role->root_label);
11657 + if (unlikely(obj->mode & GR_WRITE))
11658 + tsk->is_writable = 1;
11660 +#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
11661 + printk(KERN_ALERT "Assigning special role:%s subject:%s to process (%s:%d)\n", tsk->role->rolename, tsk->acl->filename, tsk->comm, tsk->pid);
11665 + read_unlock(&grsec_exec_file_lock);
11666 + read_unlock(&tasklist_lock);
11670 +int gr_check_secure_terminal(struct task_struct *task)
11672 + struct task_struct *p, *p2, *p3;
11673 + struct files_struct *files;
11674 + struct fdtable *fdt;
11675 + struct file *our_file = NULL, *file;
11678 + if (task->signal->tty == NULL)
11681 + files = get_files_struct(task);
11682 + if (files != NULL) {
11684 + fdt = files_fdtable(files);
11685 + for (i=0; i < fdt->max_fds; i++) {
11686 + file = fcheck_files(files, i);
11687 + if (file && (our_file == NULL) && (file->private_data == task->signal->tty)) {
11692 + rcu_read_unlock();
11693 + put_files_struct(files);
11696 + if (our_file == NULL)
11699 + read_lock(&tasklist_lock);
11700 + do_each_thread(p2, p) {
11701 + files = get_files_struct(p);
11702 + if (files == NULL ||
11703 + (p->signal && p->signal->tty == task->signal->tty)) {
11704 + if (files != NULL)
11705 + put_files_struct(files);
11709 + fdt = files_fdtable(files);
11710 + for (i=0; i < fdt->max_fds; i++) {
11711 + file = fcheck_files(files, i);
11712 + if (file && S_ISCHR(file->f_dentry->d_inode->i_mode) &&
11713 + file->f_dentry->d_inode->i_rdev == our_file->f_dentry->d_inode->i_rdev) {
11715 + while (p3->pid > 0) {
11722 + gr_log_ttysniff(GR_DONT_AUDIT_GOOD, GR_TTYSNIFF_ACL_MSG, p);
11723 + gr_handle_alertkill(p);
11724 + rcu_read_unlock();
11725 + put_files_struct(files);
11726 + read_unlock(&tasklist_lock);
11731 + rcu_read_unlock();
11732 + put_files_struct(files);
11733 + } while_each_thread(p2, p);
11734 + read_unlock(&tasklist_lock);
11741 +write_grsec_handler(struct file *file, const char * buf, size_t count, loff_t *ppos)
11743 + struct gr_arg_wrapper uwrap;
11744 + unsigned char *sprole_salt;
11745 + unsigned char *sprole_sum;
11746 + int error = sizeof (struct gr_arg_wrapper);
11749 + down(&gr_dev_sem);
11751 + if ((gr_status & GR_READY) && !(current->acl->mode & GR_KERNELAUTH)) {
11756 + if (count != sizeof (struct gr_arg_wrapper)) {
11757 + gr_log_int_int(GR_DONT_AUDIT_GOOD, GR_DEV_ACL_MSG, (int)count, (int)sizeof(struct gr_arg_wrapper));
11763 + if (gr_auth_expires && time_after_eq(get_seconds(), gr_auth_expires)) {
11764 + gr_auth_expires = 0;
11765 + gr_auth_attempts = 0;
11768 + if (copy_from_user(&uwrap, buf, sizeof (struct gr_arg_wrapper))) {
11773 + if ((uwrap.version != GRSECURITY_VERSION) || (uwrap.size != sizeof(struct gr_arg))) {
11778 + if (copy_from_user(gr_usermode, uwrap.arg, sizeof (struct gr_arg))) {
11783 + if (gr_usermode->mode != SPROLE && gr_usermode->mode != SPROLEPAM &&
11784 + gr_auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES &&
11785 + time_after(gr_auth_expires, get_seconds())) {
11790 + /* if non-root trying to do anything other than use a special role,
11791 + do not attempt authentication, do not count towards authentication
11795 + if (gr_usermode->mode != SPROLE && gr_usermode->mode != STATUS &&
11796 + gr_usermode->mode != UNSPROLE && gr_usermode->mode != SPROLEPAM &&
11802 + /* ensure pw and special role name are null terminated */
11804 + gr_usermode->pw[GR_PW_LEN - 1] = '\0';
11805 + gr_usermode->sp_role[GR_SPROLE_LEN - 1] = '\0';
11808 + * We have our enough of the argument structure..(we have yet
11809 + * to copy_from_user the tables themselves) . Copy the tables
11810 + * only if we need them, i.e. for loading operations. */
11812 + switch (gr_usermode->mode) {
11814 + if (gr_status & GR_READY) {
11816 + if (!gr_check_secure_terminal(current))
11822 + if ((gr_status & GR_READY)
11823 + && !(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
11824 + gr_status &= ~GR_READY;
11825 + gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTS_ACL_MSG);
11826 + free_variables();
11827 + memset(gr_usermode, 0, sizeof (struct gr_arg));
11828 + memset(gr_system_salt, 0, GR_SALT_LEN);
11829 + memset(gr_system_sum, 0, GR_SHA_LEN);
11830 + } else if (gr_status & GR_READY) {
11831 + gr_log_noargs(GR_DONT_AUDIT, GR_SHUTF_ACL_MSG);
11834 + gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SHUTI_ACL_MSG);
11839 + if (!(gr_status & GR_READY) && !(error2 = gracl_init(gr_usermode)))
11840 + gr_log_str(GR_DONT_AUDIT_GOOD, GR_ENABLE_ACL_MSG, GR_VERSION);
11842 + if (gr_status & GR_READY)
11846 + gr_log_str(GR_DONT_AUDIT, GR_ENABLEF_ACL_MSG, GR_VERSION);
11850 + if (!(gr_status & GR_READY)) {
11851 + gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOADI_ACL_MSG, GR_VERSION);
11853 + } else if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
11855 + gr_status &= ~GR_READY;
11856 + free_variables();
11857 + if (!(error2 = gracl_init(gr_usermode))) {
11859 + gr_log_str(GR_DONT_AUDIT_GOOD, GR_RELOAD_ACL_MSG, GR_VERSION);
11863 + gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION);
11866 + gr_log_str(GR_DONT_AUDIT, GR_RELOADF_ACL_MSG, GR_VERSION);
11871 + if (unlikely(!(gr_status & GR_READY))) {
11872 + gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODI_ACL_MSG);
11877 + if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) {
11878 + gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SEGVMODS_ACL_MSG);
11879 + if (gr_usermode->segv_device && gr_usermode->segv_inode) {
11880 + struct acl_subject_label *segvacl;
11882 + lookup_acl_subj_label(gr_usermode->segv_inode,
11883 + gr_usermode->segv_device,
11886 + segvacl->crashes = 0;
11887 + segvacl->expires = 0;
11889 + } else if (gr_find_uid(gr_usermode->segv_uid) >= 0) {
11890 + gr_remove_uid(gr_usermode->segv_uid);
11893 + gr_log_noargs(GR_DONT_AUDIT, GR_SEGVMODF_ACL_MSG);
11899 + if (unlikely(!(gr_status & GR_READY))) {
11900 + gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_SPROLEI_ACL_MSG);
11905 + if (current->role->expires && time_after_eq(get_seconds(), current->role->expires)) {
11906 + current->role->expires = 0;
11907 + current->role->auth_attempts = 0;
11910 + if (current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES &&
11911 + time_after(current->role->expires, get_seconds())) {
11916 + if (lookup_special_role_auth
11917 + (gr_usermode->mode, gr_usermode->sp_role, &sprole_salt, &sprole_sum)
11918 + && ((!sprole_salt && !sprole_sum)
11919 + || !(chkpw(gr_usermode, sprole_salt, sprole_sum)))) {
11921 + assign_special_role(gr_usermode->sp_role);
11922 + read_lock(&tasklist_lock);
11923 + if (current->parent)
11924 + p = current->parent->role->rolename;
11925 + read_unlock(&tasklist_lock);
11926 + gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLES_ACL_MSG,
11927 + p, acl_sp_role_value);
11929 + gr_log_str(GR_DONT_AUDIT, GR_SPROLEF_ACL_MSG, gr_usermode->sp_role);
11931 + if(!(current->role->auth_attempts++))
11932 + current->role->expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT;
11938 + if (unlikely(!(gr_status & GR_READY))) {
11939 + gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_UNSPROLEI_ACL_MSG);
11944 + if (current->role->roletype & GR_ROLE_SPECIAL) {
11948 + read_lock(&tasklist_lock);
11949 + if (current->parent) {
11950 + p = current->parent->role->rolename;
11951 + i = current->parent->acl_role_id;
11953 + read_unlock(&tasklist_lock);
11955 + gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_UNSPROLES_ACL_MSG, p, i);
11958 + gr_log_str(GR_DONT_AUDIT, GR_UNSPROLEF_ACL_MSG, current->role->rolename);
11964 + gr_log_int(GR_DONT_AUDIT, GR_INVMODE_ACL_MSG, gr_usermode->mode);
11969 + if (error != -EPERM)
11972 + if(!(gr_auth_attempts++))
11973 + gr_auth_expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT;
11981 +gr_set_acls(const int type)
11983 + struct acl_object_label *obj;
11984 + struct task_struct *task, *task2;
11985 + struct file *filp;
11986 + struct acl_role_label *role = current->role;
11987 + __u16 acl_role_id = current->acl_role_id;
11989 + read_lock(&tasklist_lock);
11990 + read_lock(&grsec_exec_file_lock);
11991 + do_each_thread(task2, task) {
11992 + /* check to see if we're called from the exit handler,
11993 + if so, only replace ACLs that have inherited the admin
11996 + if (type && (task->role != role ||
11997 + task->acl_role_id != acl_role_id))
12000 + task->acl_role_id = 0;
12001 + task->acl_sp_role = 0;
12003 + if ((filp = task->exec_file)) {
12004 + task->role = lookup_acl_role_label(task, task->uid, task->gid);
12007 + chk_subj_label(filp->f_dentry, filp->f_vfsmnt,
12010 + struct acl_subject_label *curr;
12011 + curr = task->acl;
12013 + task->is_writable = 0;
12014 + /* ignore additional mmap checks for processes that are writable
12015 + by the default ACL */
12016 + obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
12017 + if (unlikely(obj->mode & GR_WRITE))
12018 + task->is_writable = 1;
12019 + obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label);
12020 + if (unlikely(obj->mode & GR_WRITE))
12021 + task->is_writable = 1;
12023 + gr_set_proc_res(task);
12025 +#ifdef CONFIG_GRKERNSEC_ACL_DEBUG
12026 + printk(KERN_ALERT "gr_set_acls for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename);
12029 + read_unlock(&grsec_exec_file_lock);
12030 + read_unlock(&tasklist_lock);
12031 + gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_DEFACL_MSG, task->comm, task->pid);
12035 + // it's a kernel process
12036 + task->role = kernel_role;
12037 + task->acl = kernel_role->root_label;
12038 +#ifdef CONFIG_GRKERNSEC_ACL_HIDEKERN
12039 + task->acl->mode &= ~GR_PROCFIND;
12042 + } while_each_thread(task2, task);
12043 + read_unlock(&grsec_exec_file_lock);
12044 + read_unlock(&tasklist_lock);
12049 +gr_learn_resource(const struct task_struct *task,
12050 + const int res, const unsigned long wanted, const int gt)
12052 + struct acl_subject_label *acl;
12054 + if (unlikely((gr_status & GR_READY) &&
12055 + task->acl && (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))))
12056 + goto skip_reslog;
12058 +#ifdef CONFIG_GRKERNSEC_RESLOG
12059 + gr_log_resource(task, res, wanted, gt);
12063 + if (unlikely(!(gr_status & GR_READY) || !wanted))
12068 + if (likely(!acl || !(acl->mode & (GR_LEARN | GR_INHERITLEARN)) ||
12069 + !(acl->resmask & (1 << (unsigned short) res))))
12072 + if (wanted >= acl->res[res].rlim_cur) {
12073 + unsigned long res_add;
12075 + res_add = wanted;
12078 + res_add += GR_RLIM_CPU_BUMP;
12080 + case RLIMIT_FSIZE:
12081 + res_add += GR_RLIM_FSIZE_BUMP;
12083 + case RLIMIT_DATA:
12084 + res_add += GR_RLIM_DATA_BUMP;
12086 + case RLIMIT_STACK:
12087 + res_add += GR_RLIM_STACK_BUMP;
12089 + case RLIMIT_CORE:
12090 + res_add += GR_RLIM_CORE_BUMP;
12093 + res_add += GR_RLIM_RSS_BUMP;
12095 + case RLIMIT_NPROC:
12096 + res_add += GR_RLIM_NPROC_BUMP;
12098 + case RLIMIT_NOFILE:
12099 + res_add += GR_RLIM_NOFILE_BUMP;
12101 + case RLIMIT_MEMLOCK:
12102 + res_add += GR_RLIM_MEMLOCK_BUMP;
12105 + res_add += GR_RLIM_AS_BUMP;
12107 + case RLIMIT_LOCKS:
12108 + res_add += GR_RLIM_LOCKS_BUMP;
12112 + acl->res[res].rlim_cur = res_add;
12114 + if (wanted > acl->res[res].rlim_max)
12115 + acl->res[res].rlim_max = res_add;
12117 + security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
12118 + task->role->roletype, acl->filename,
12119 + acl->res[res].rlim_cur, acl->res[res].rlim_max,
12120 + "", (unsigned long) res);
12126 +#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
12128 +pax_set_initial_flags(struct linux_binprm *bprm)
12130 + struct task_struct *task = current;
12131 + struct acl_subject_label *proc;
12132 + unsigned long flags;
12134 + if (unlikely(!(gr_status & GR_READY)))
12137 + flags = pax_get_flags(task);
12139 + proc = task->acl;
12141 + if (proc->pax_flags & GR_PAX_DISABLE_PAGEEXEC)
12142 + flags &= ~MF_PAX_PAGEEXEC;
12143 + if (proc->pax_flags & GR_PAX_DISABLE_SEGMEXEC)
12144 + flags &= ~MF_PAX_SEGMEXEC;
12145 + if (proc->pax_flags & GR_PAX_DISABLE_RANDMMAP)
12146 + flags &= ~MF_PAX_RANDMMAP;
12147 + if (proc->pax_flags & GR_PAX_DISABLE_EMUTRAMP)
12148 + flags &= ~MF_PAX_EMUTRAMP;
12149 + if (proc->pax_flags & GR_PAX_DISABLE_MPROTECT)
12150 + flags &= ~MF_PAX_MPROTECT;
12152 + if (proc->pax_flags & GR_PAX_ENABLE_PAGEEXEC)
12153 + flags |= MF_PAX_PAGEEXEC;
12154 + if (proc->pax_flags & GR_PAX_ENABLE_SEGMEXEC)
12155 + flags |= MF_PAX_SEGMEXEC;
12156 + if (proc->pax_flags & GR_PAX_ENABLE_RANDMMAP)
12157 + flags |= MF_PAX_RANDMMAP;
12158 + if (proc->pax_flags & GR_PAX_ENABLE_EMUTRAMP)
12159 + flags |= MF_PAX_EMUTRAMP;
12160 + if (proc->pax_flags & GR_PAX_ENABLE_MPROTECT)
12161 + flags |= MF_PAX_MPROTECT;
12163 + pax_set_flags(task, flags);
12169 +#ifdef CONFIG_SYSCTL
12170 +extern struct proc_dir_entry *proc_sys_root;
12172 +/* the following function is called under the BKL */
12175 +gr_handle_sysctl(const struct ctl_table *table, const void *oldval,
12176 + const void *newval)
12178 + struct proc_dir_entry *tmp;
12179 + struct nameidata nd;
12180 + const char *proc_sys = "/proc/sys";
12182 + struct acl_object_label *obj;
12183 + unsigned short len = 0, pos = 0, depth = 0, i;
12187 + if (unlikely(!(gr_status & GR_READY)))
12190 + path = per_cpu_ptr(gr_shared_page[0], smp_processor_id());
12195 + mode |= GR_WRITE;
12197 + /* convert the requested sysctl entry into a pathname */
12199 + for (tmp = table->de; tmp != proc_sys_root; tmp = tmp->parent) {
12200 + len += strlen(tmp->name);
12205 + if ((len + depth + strlen(proc_sys) + 1) > PAGE_SIZE)
12206 + return 0; /* deny */
12208 + memset(path, 0, PAGE_SIZE);
12210 + memcpy(path, proc_sys, strlen(proc_sys));
12212 + pos += strlen(proc_sys);
12214 + for (; depth > 0; depth--) {
12217 + for (i = 1, tmp = table->de; tmp != proc_sys_root;
12218 + tmp = tmp->parent) {
12219 + if (depth == i) {
12220 + memcpy(path + pos, tmp->name,
12221 + strlen(tmp->name));
12222 + pos += strlen(tmp->name);
12228 + err = path_lookup(path, LOOKUP_FOLLOW, &nd);
12233 + obj = chk_obj_label(nd.dentry, nd.mnt, current->acl);
12234 + err = obj->mode & (mode | to_gr_audit(mode) | GR_SUPPRESS);
12236 + if (unlikely((current->acl->mode & (GR_LEARN | GR_INHERITLEARN)) &&
12237 + ((err & mode) != mode))) {
12238 + __u32 new_mode = mode;
12240 + new_mode &= ~(GR_AUDITS | GR_SUPPRESS);
12243 + gr_log_learn(current, nd.dentry, nd.mnt, new_mode);
12244 + } else if ((err & mode) != mode && !(err & GR_SUPPRESS)) {
12245 + gr_log_str4(GR_DONT_AUDIT, GR_SYSCTL_ACL_MSG, "denied",
12246 + path, (mode & GR_READ) ? " reading" : "",
12247 + (mode & GR_WRITE) ? " writing" : "");
12249 + } else if ((err & mode) != mode) {
12251 + } else if (((err & mode) == mode) && (err & GR_AUDITS)) {
12252 + gr_log_str4(GR_DO_AUDIT, GR_SYSCTL_ACL_MSG, "successful",
12253 + path, (mode & GR_READ) ? " reading" : "",
12254 + (mode & GR_WRITE) ? " writing" : "");
12257 + path_release(&nd);
12265 +gr_handle_proc_ptrace(struct task_struct *task)
12267 + struct file *filp;
12268 + struct task_struct *tmp = task;
12269 + struct task_struct *curtemp = current;
12272 + if (unlikely(!(gr_status & GR_READY)))
12275 + read_lock(&tasklist_lock);
12276 + read_lock(&grsec_exec_file_lock);
12277 + filp = task->exec_file;
12279 + while (tmp->pid > 0) {
12280 + if (tmp == curtemp)
12282 + tmp = tmp->parent;
12285 + if (!filp || (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE))) {
12286 + read_unlock(&grsec_exec_file_lock);
12287 + read_unlock(&tasklist_lock);
12291 + retmode = gr_search_file(filp->f_dentry, GR_NOPTRACE, filp->f_vfsmnt);
12292 + read_unlock(&grsec_exec_file_lock);
12293 + read_unlock(&tasklist_lock);
12295 + if (retmode & GR_NOPTRACE)
12298 + if (!(current->acl->mode & GR_POVERRIDE) && !(current->role->roletype & GR_ROLE_GOD)
12299 + && (current->acl != task->acl || (current->acl != current->role->root_label
12300 + && current->pid != task->pid)))
12307 +gr_handle_ptrace(struct task_struct *task, const long request)
12309 + struct task_struct *tmp = task;
12310 + struct task_struct *curtemp = current;
12313 + if (unlikely(!(gr_status & GR_READY)))
12316 + read_lock(&tasklist_lock);
12317 + while (tmp->pid > 0) {
12318 + if (tmp == curtemp)
12320 + tmp = tmp->parent;
12323 + if (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE)) {
12324 + read_unlock(&tasklist_lock);
12325 + gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
12328 + read_unlock(&tasklist_lock);
12330 + read_lock(&grsec_exec_file_lock);
12331 + if (unlikely(!task->exec_file)) {
12332 + read_unlock(&grsec_exec_file_lock);
12336 + retmode = gr_search_file(task->exec_file->f_dentry, GR_PTRACERD | GR_NOPTRACE, task->exec_file->f_vfsmnt);
12337 + read_unlock(&grsec_exec_file_lock);
12339 + if (retmode & GR_NOPTRACE) {
12340 + gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
12344 + if (retmode & GR_PTRACERD) {
12345 + switch (request) {
12346 + case PTRACE_POKETEXT:
12347 + case PTRACE_POKEDATA:
12348 + case PTRACE_POKEUSR:
12349 +#if !defined(CONFIG_PPC32) && !defined(CONFIG_PPC64) && !defined(CONFIG_PARISC) && !defined(CONFIG_ALPHA) && !defined(CONFIG_IA64)
12350 + case PTRACE_SETREGS:
12351 + case PTRACE_SETFPREGS:
12354 + case PTRACE_SETFPXREGS:
12356 +#ifdef CONFIG_ALTIVEC
12357 + case PTRACE_SETVRREGS:
12363 + } else if (!(current->acl->mode & GR_POVERRIDE) &&
12364 + !(current->role->roletype & GR_ROLE_GOD) &&
12365 + (current->acl != task->acl)) {
12366 + gr_log_ptrace(GR_DONT_AUDIT, GR_PTRACE_ACL_MSG, task);
12373 +static int is_writable_mmap(const struct file *filp)
12375 + struct task_struct *task = current;
12376 + struct acl_object_label *obj, *obj2;
12378 + if (gr_status & GR_READY && !(task->acl->mode & GR_OVERRIDE) &&
12379 + !task->is_writable && S_ISREG(filp->f_dentry->d_inode->i_mode)) {
12380 + obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label);
12381 + obj2 = chk_obj_label(filp->f_dentry, filp->f_vfsmnt,
12382 + task->role->root_label);
12383 + if (unlikely((obj->mode & GR_WRITE) || (obj2->mode & GR_WRITE))) {
12384 + gr_log_fs_generic(GR_DONT_AUDIT, GR_WRITLIB_ACL_MSG, filp->f_dentry, filp->f_vfsmnt);
12392 +gr_acl_handle_mmap(const struct file *file, const unsigned long prot)
12396 + if (unlikely(!file || !(prot & PROT_EXEC)))
12399 + if (is_writable_mmap(file))
12403 + gr_search_file(file->f_dentry,
12404 + GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
12407 + if (!gr_tpe_allow(file))
12410 + if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) {
12411 + gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MMAP_ACL_MSG, file->f_dentry, file->f_vfsmnt);
12413 + } else if (unlikely(!(mode & GR_EXEC))) {
12415 + } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
12416 + gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MMAP_ACL_MSG, file->f_dentry, file->f_vfsmnt);
12424 +gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
12428 + if (unlikely(!file || !(prot & PROT_EXEC)))
12431 + if (is_writable_mmap(file))
12435 + gr_search_file(file->f_dentry,
12436 + GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS,
12439 + if (!gr_tpe_allow(file))
12442 + if (unlikely(!(mode & GR_EXEC) && !(mode & GR_SUPPRESS))) {
12443 + gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_MPROTECT_ACL_MSG, file->f_dentry, file->f_vfsmnt);
12445 + } else if (unlikely(!(mode & GR_EXEC))) {
12447 + } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) {
12448 + gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_MPROTECT_ACL_MSG, file->f_dentry, file->f_vfsmnt);
12456 +gr_acl_handle_psacct(struct task_struct *task, const long code)
12458 + unsigned long runtime;
12459 + unsigned long cputime;
12460 + unsigned int wday, cday;
12465 + if (unlikely(!(gr_status & GR_READY) || !task->acl ||
12466 + !(task->acl->mode & GR_PROCACCT)))
12469 + runtime = xtime.tv_sec - task->start_time.tv_sec;
12470 + wday = runtime / (3600 * 24);
12471 + runtime -= wday * (3600 * 24);
12472 + whr = runtime / 3600;
12473 + runtime -= whr * 3600;
12474 + wmin = runtime / 60;
12475 + runtime -= wmin * 60;
12478 + cputime = (task->utime + task->stime) / HZ;
12479 + cday = cputime / (3600 * 24);
12480 + cputime -= cday * (3600 * 24);
12481 + chr = cputime / 3600;
12482 + cputime -= chr * 3600;
12483 + cmin = cputime / 60;
12484 + cputime -= cmin * 60;
12487 + gr_log_procacct(GR_DO_AUDIT, GR_ACL_PROCACCT_MSG, task, wday, whr, wmin, wsec, cday, chr, cmin, csec, code);
12492 +void gr_set_kernel_label(struct task_struct *task)
12494 + if (gr_status & GR_READY) {
12495 + task->role = kernel_role;
12496 + task->acl = kernel_role->root_label;
12501 +int gr_acl_handle_filldir(const struct file *file, const char *name, const unsigned int namelen, const ino_t ino)
12503 + struct task_struct *task = current;
12504 + struct dentry *dentry = file->f_dentry;
12505 + struct vfsmount *mnt = file->f_vfsmnt;
12506 + struct acl_object_label *obj, *tmp;
12507 + struct acl_subject_label *subj;
12508 + unsigned int bufsize;
12512 + if (unlikely(!(gr_status & GR_READY)))
12515 + if (task->acl->mode & (GR_LEARN | GR_INHERITLEARN))
12518 + subj = task->acl;
12520 + obj = lookup_acl_obj_label(ino, dentry->d_inode->i_sb->s_dev, subj);
12522 + return (obj->mode & GR_FIND) ? 1 : 0;
12523 + } while ((subj = subj->parent_subject));
12525 + obj = chk_obj_label(dentry, mnt, task->acl);
12526 + if (obj->globbed == NULL)
12527 + return (obj->mode & GR_FIND) ? 1 : 0;
12529 + is_not_root = ((obj->filename[0] == '/') &&
12530 + (obj->filename[1] == '\0')) ? 0 : 1;
12531 + bufsize = PAGE_SIZE - namelen - is_not_root;
12533 + /* check bufsize > PAGE_SIZE || bufsize == 0 */
12534 + if (unlikely((bufsize - 1) > (PAGE_SIZE - 1)))
12537 + preempt_disable();
12538 + path = d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()),
12541 + bufsize = strlen(path);
12543 + /* if base is "/", don't append an additional slash */
12545 + *(path + bufsize) = '/';
12546 + memcpy(path + bufsize + is_not_root, name, namelen);
12547 + *(path + bufsize + namelen + is_not_root) = '\0';
12549 + tmp = obj->globbed;
12551 + if (!glob_match(tmp->filename, path)) {
12552 + preempt_enable();
12553 + return (tmp->mode & GR_FIND) ? 1 : 0;
12557 + preempt_enable();
12558 + return (obj->mode & GR_FIND) ? 1 : 0;
12561 +EXPORT_SYMBOL(gr_learn_resource);
12562 +EXPORT_SYMBOL(gr_set_kernel_label);
12563 +#ifdef CONFIG_SECURITY
12564 +EXPORT_SYMBOL(gr_check_user_change);
12565 +EXPORT_SYMBOL(gr_check_group_change);
12568 diff -urNp linux-2.6.16.12/grsecurity/gracl_cap.c linux-2.6.16.12/grsecurity/gracl_cap.c
12569 --- linux-2.6.16.12/grsecurity/gracl_cap.c 1969-12-31 19:00:00.000000000 -0500
12570 +++ linux-2.6.16.12/grsecurity/gracl_cap.c 2006-05-01 20:17:33.000000000 -0400
12572 +#include <linux/kernel.h>
12573 +#include <linux/module.h>
12574 +#include <linux/sched.h>
12575 +#include <linux/capability.h>
12576 +#include <linux/gracl.h>
12577 +#include <linux/grsecurity.h>
12578 +#include <linux/grinternal.h>
12580 +static const char *captab_log[] = {
12582 + "CAP_DAC_OVERRIDE",
12583 + "CAP_DAC_READ_SEARCH",
12590 + "CAP_LINUX_IMMUTABLE",
12591 + "CAP_NET_BIND_SERVICE",
12592 + "CAP_NET_BROADCAST",
12597 + "CAP_SYS_MODULE",
12599 + "CAP_SYS_CHROOT",
12600 + "CAP_SYS_PTRACE",
12605 + "CAP_SYS_RESOURCE",
12607 + "CAP_SYS_TTY_CONFIG",
12612 +EXPORT_SYMBOL(gr_task_is_capable);
12615 +gr_task_is_capable(struct task_struct *task, const int cap)
12617 + struct acl_subject_label *curracl;
12618 + __u32 cap_drop = 0, cap_mask = 0;
12620 + if (!gr_acl_is_enabled())
12623 + curracl = task->acl;
12625 + cap_drop = curracl->cap_lower;
12626 + cap_mask = curracl->cap_mask;
12628 + while ((curracl = curracl->parent_subject)) {
12629 + if (!(cap_mask & (1 << cap)) && (curracl->cap_mask & (1 << cap)))
12630 + cap_drop |= curracl->cap_lower & (1 << cap);
12631 + cap_mask |= curracl->cap_mask;
12634 + if (!cap_raised(cap_drop, cap))
12637 + curracl = task->acl;
12639 + if ((curracl->mode & (GR_LEARN | GR_INHERITLEARN))
12640 + && cap_raised(task->cap_effective, cap)) {
12641 + security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename,
12642 + task->role->roletype, task->uid,
12643 + task->gid, task->exec_file ?
12644 + gr_to_filename(task->exec_file->f_dentry,
12645 + task->exec_file->f_vfsmnt) : curracl->filename,
12646 + curracl->filename, 0UL,
12647 + 0UL, "", (unsigned long) cap, NIPQUAD(task->signal->curr_ip));
12651 + if ((cap >= 0) && (cap < (sizeof(captab_log)/sizeof(captab_log[0]))) && cap_raised(task->cap_effective, cap))
12652 + gr_log_cap(GR_DONT_AUDIT, GR_CAP_ACL_MSG, task, captab_log[cap]);
12658 +gr_is_capable_nolog(const int cap)
12660 + struct acl_subject_label *curracl;
12661 + __u32 cap_drop = 0, cap_mask = 0;
12663 + if (!gr_acl_is_enabled())
12666 + curracl = current->acl;
12668 + cap_drop = curracl->cap_lower;
12669 + cap_mask = curracl->cap_mask;
12671 + while ((curracl = curracl->parent_subject)) {
12672 + cap_drop |= curracl->cap_lower & (cap_mask & ~curracl->cap_mask);
12673 + cap_mask |= curracl->cap_mask;
12676 + if (!cap_raised(cap_drop, cap))
12682 diff -urNp linux-2.6.16.12/grsecurity/gracl_fs.c linux-2.6.16.12/grsecurity/gracl_fs.c
12683 --- linux-2.6.16.12/grsecurity/gracl_fs.c 1969-12-31 19:00:00.000000000 -0500
12684 +++ linux-2.6.16.12/grsecurity/gracl_fs.c 2006-05-01 20:17:33.000000000 -0400
12686 +#include <linux/kernel.h>
12687 +#include <linux/sched.h>
12688 +#include <linux/types.h>
12689 +#include <linux/fs.h>
12690 +#include <linux/file.h>
12691 +#include <linux/stat.h>
12692 +#include <linux/grsecurity.h>
12693 +#include <linux/grinternal.h>
12694 +#include <linux/gracl.h>
12697 +gr_acl_handle_hidden_file(const struct dentry * dentry,
12698 + const struct vfsmount * mnt)
12702 + if (unlikely(!dentry->d_inode))
12706 + gr_search_file(dentry, GR_FIND | GR_AUDIT_FIND | GR_SUPPRESS, mnt);
12708 + if (unlikely(mode & GR_FIND && mode & GR_AUDIT_FIND)) {
12709 + gr_log_fs_rbac_generic(GR_DO_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt);
12711 + } else if (unlikely(!(mode & GR_FIND) && !(mode & GR_SUPPRESS))) {
12712 + gr_log_fs_rbac_generic(GR_DONT_AUDIT, GR_HIDDEN_ACL_MSG, dentry, mnt);
12714 + } else if (unlikely(!(mode & GR_FIND)))
12721 +gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
12724 + __u32 reqmode = GR_FIND;
12727 + if (unlikely(!dentry->d_inode))
12730 + if (unlikely(fmode & O_APPEND))
12731 + reqmode |= GR_APPEND;
12732 + else if (unlikely(fmode & FMODE_WRITE))
12733 + reqmode |= GR_WRITE;
12734 + if (likely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
12735 + reqmode |= GR_READ;
12738 + gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
12741 + if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
12742 + gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt,
12743 + reqmode & GR_READ ? " reading" : "",
12744 + reqmode & GR_WRITE ? " writing" : reqmode &
12745 + GR_APPEND ? " appending" : "");
12748 + if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
12750 + gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_OPEN_ACL_MSG, dentry, mnt,
12751 + reqmode & GR_READ ? " reading" : "",
12752 + reqmode & GR_WRITE ? " writing" : reqmode &
12753 + GR_APPEND ? " appending" : "");
12755 + } else if (unlikely((mode & reqmode) != reqmode))
12762 +gr_acl_handle_creat(const struct dentry * dentry,
12763 + const struct dentry * p_dentry,
12764 + const struct vfsmount * p_mnt, const int fmode,
12767 + __u32 reqmode = GR_WRITE | GR_CREATE;
12770 + if (unlikely(fmode & O_APPEND))
12771 + reqmode |= GR_APPEND;
12772 + if (unlikely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY)))
12773 + reqmode |= GR_READ;
12774 + if (unlikely((fmode & O_CREAT) && (imode & (S_ISUID | S_ISGID))))
12775 + reqmode |= GR_SETID;
12778 + gr_check_create(dentry, p_dentry, p_mnt,
12779 + reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
12781 + if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
12782 + gr_log_fs_rbac_mode2(GR_DO_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt,
12783 + reqmode & GR_READ ? " reading" : "",
12784 + reqmode & GR_WRITE ? " writing" : reqmode &
12785 + GR_APPEND ? " appending" : "");
12788 + if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
12790 + gr_log_fs_rbac_mode2(GR_DONT_AUDIT, GR_CREATE_ACL_MSG, dentry, p_mnt,
12791 + reqmode & GR_READ ? " reading" : "",
12792 + reqmode & GR_WRITE ? " writing" : reqmode &
12793 + GR_APPEND ? " appending" : "");
12795 + } else if (unlikely((mode & reqmode) != reqmode))
12802 +gr_acl_handle_access(const struct dentry * dentry, const struct vfsmount * mnt,
12805 + __u32 mode, reqmode = GR_FIND;
12807 + if ((fmode & S_IXOTH) && !S_ISDIR(dentry->d_inode->i_mode))
12808 + reqmode |= GR_EXEC;
12809 + if (fmode & S_IWOTH)
12810 + reqmode |= GR_WRITE;
12811 + if (fmode & S_IROTH)
12812 + reqmode |= GR_READ;
12815 + gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS,
12818 + if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) {
12819 + gr_log_fs_rbac_mode3(GR_DO_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt,
12820 + reqmode & GR_READ ? " reading" : "",
12821 + reqmode & GR_WRITE ? " writing" : "",
12822 + reqmode & GR_EXEC ? " executing" : "");
12825 + if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS)))
12827 + gr_log_fs_rbac_mode3(GR_DONT_AUDIT, GR_ACCESS_ACL_MSG, dentry, mnt,
12828 + reqmode & GR_READ ? " reading" : "",
12829 + reqmode & GR_WRITE ? " writing" : "",
12830 + reqmode & GR_EXEC ? " executing" : "");
12832 + } else if (unlikely((mode & reqmode) != reqmode))
12838 +static __u32 generic_fs_handler(const struct dentry *dentry, const struct vfsmount *mnt, __u32 reqmode, const char *fmt)
12842 + mode = gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, mnt);
12844 + if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) {
12845 + gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, dentry, mnt);
12847 + } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) {
12848 + gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, dentry, mnt);
12850 + } else if (unlikely((mode & (reqmode)) != (reqmode)))
12853 + return (reqmode);
12857 +gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
12859 + return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_RMDIR_ACL_MSG);
12863 +gr_acl_handle_unlink(const struct dentry *dentry, const struct vfsmount *mnt)
12865 + return generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_UNLINK_ACL_MSG);
12869 +gr_acl_handle_truncate(const struct dentry *dentry, const struct vfsmount *mnt)
12871 + return generic_fs_handler(dentry, mnt, GR_WRITE, GR_TRUNCATE_ACL_MSG);
12875 +gr_acl_handle_utime(const struct dentry *dentry, const struct vfsmount *mnt)
12877 + return generic_fs_handler(dentry, mnt, GR_WRITE, GR_ATIME_ACL_MSG);
12881 +gr_acl_handle_fchmod(const struct dentry *dentry, const struct vfsmount *mnt,
12884 + if (unlikely(dentry->d_inode && S_ISSOCK(dentry->d_inode->i_mode)))
12887 + if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
12888 + return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
12889 + GR_FCHMOD_ACL_MSG);
12891 + return generic_fs_handler(dentry, mnt, GR_WRITE, GR_FCHMOD_ACL_MSG);
12896 +gr_acl_handle_chmod(const struct dentry *dentry, const struct vfsmount *mnt,
12899 + if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) {
12900 + return generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID,
12901 + GR_CHMOD_ACL_MSG);
12903 + return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHMOD_ACL_MSG);
12908 +gr_acl_handle_chown(const struct dentry *dentry, const struct vfsmount *mnt)
12910 + return generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHOWN_ACL_MSG);
12914 +gr_acl_handle_execve(const struct dentry *dentry, const struct vfsmount *mnt)
12916 + return generic_fs_handler(dentry, mnt, GR_EXEC, GR_EXEC_ACL_MSG);
12920 +gr_acl_handle_unix(const struct dentry *dentry, const struct vfsmount *mnt)
12922 + return generic_fs_handler(dentry, mnt, GR_READ | GR_WRITE,
12923 + GR_UNIXCONNECT_ACL_MSG);
12926 +/* hardlinks require at minimum create permission,
12927 + any additional privilege required is based on the
12928 + privilege of the file being linked to
12931 +gr_acl_handle_link(const struct dentry * new_dentry,
12932 + const struct dentry * parent_dentry,
12933 + const struct vfsmount * parent_mnt,
12934 + const struct dentry * old_dentry,
12935 + const struct vfsmount * old_mnt, const char *to)
12938 + __u32 needmode = GR_CREATE | GR_LINK;
12939 + __u32 needaudit = GR_AUDIT_CREATE | GR_AUDIT_LINK;
12942 + gr_check_link(new_dentry, parent_dentry, parent_mnt, old_dentry,
12945 + if (unlikely(((mode & needmode) == needmode) && (mode & needaudit))) {
12946 + gr_log_fs_rbac_str(GR_DO_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to);
12948 + } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
12949 + gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_LINK_ACL_MSG, old_dentry, old_mnt, to);
12951 + } else if (unlikely((mode & needmode) != needmode))
12958 +gr_acl_handle_symlink(const struct dentry * new_dentry,
12959 + const struct dentry * parent_dentry,
12960 + const struct vfsmount * parent_mnt, const char *from)
12962 + __u32 needmode = GR_WRITE | GR_CREATE;
12966 + gr_check_create(new_dentry, parent_dentry, parent_mnt,
12967 + GR_CREATE | GR_AUDIT_CREATE |
12968 + GR_WRITE | GR_AUDIT_WRITE | GR_SUPPRESS);
12970 + if (unlikely(mode & GR_WRITE && mode & GR_AUDITS)) {
12971 + gr_log_fs_str_rbac(GR_DO_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt);
12973 + } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) {
12974 + gr_log_fs_str_rbac(GR_DONT_AUDIT, GR_SYMLINK_ACL_MSG, from, new_dentry, parent_mnt);
12976 + } else if (unlikely((mode & needmode) != needmode))
12979 + return (GR_WRITE | GR_CREATE);
12982 +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)
12986 + mode = gr_check_create(new_dentry, parent_dentry, parent_mnt, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS);
12988 + if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) {
12989 + gr_log_fs_rbac_generic(GR_DO_AUDIT, fmt, new_dentry, parent_mnt);
12991 + } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) {
12992 + gr_log_fs_rbac_generic(GR_DONT_AUDIT, fmt, new_dentry, parent_mnt);
12994 + } else if (unlikely((mode & (reqmode)) != (reqmode)))
12997 + return (reqmode);
13001 +gr_acl_handle_mknod(const struct dentry * new_dentry,
13002 + const struct dentry * parent_dentry,
13003 + const struct vfsmount * parent_mnt,
13006 + __u32 reqmode = GR_WRITE | GR_CREATE;
13007 + if (unlikely(mode & (S_ISUID | S_ISGID)))
13008 + reqmode |= GR_SETID;
13010 + return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
13011 + reqmode, GR_MKNOD_ACL_MSG);
13015 +gr_acl_handle_mkdir(const struct dentry *new_dentry,
13016 + const struct dentry *parent_dentry,
13017 + const struct vfsmount *parent_mnt)
13019 + return generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt,
13020 + GR_WRITE | GR_CREATE, GR_MKDIR_ACL_MSG);
13023 +#define RENAME_CHECK_SUCCESS(old, new) \
13024 + (((old & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)) && \
13025 + ((new & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)))
13028 +gr_acl_handle_rename(struct dentry *new_dentry,
13029 + struct dentry *parent_dentry,
13030 + const struct vfsmount *parent_mnt,
13031 + struct dentry *old_dentry,
13032 + struct inode *old_parent_inode,
13033 + struct vfsmount *old_mnt, const char *newname)
13035 + __u32 comp1, comp2;
13038 + if (unlikely(!gr_acl_is_enabled()))
13041 + if (!new_dentry->d_inode) {
13042 + comp1 = gr_check_create(new_dentry, parent_dentry, parent_mnt,
13043 + GR_READ | GR_WRITE | GR_CREATE | GR_AUDIT_READ |
13044 + GR_AUDIT_WRITE | GR_AUDIT_CREATE | GR_SUPPRESS);
13045 + comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE |
13046 + GR_DELETE | GR_AUDIT_DELETE |
13047 + GR_AUDIT_READ | GR_AUDIT_WRITE |
13048 + GR_SUPPRESS, old_mnt);
13050 + comp1 = gr_search_file(new_dentry, GR_READ | GR_WRITE |
13051 + GR_CREATE | GR_DELETE |
13052 + GR_AUDIT_CREATE | GR_AUDIT_DELETE |
13053 + GR_AUDIT_READ | GR_AUDIT_WRITE |
13054 + GR_SUPPRESS, parent_mnt);
13056 + gr_search_file(old_dentry,
13057 + GR_READ | GR_WRITE | GR_AUDIT_READ |
13058 + GR_DELETE | GR_AUDIT_DELETE |
13059 + GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt);
13062 + if (RENAME_CHECK_SUCCESS(comp1, comp2) &&
13063 + ((comp1 & GR_AUDITS) || (comp2 & GR_AUDITS)))
13064 + gr_log_fs_rbac_str(GR_DO_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname);
13065 + else if (!RENAME_CHECK_SUCCESS(comp1, comp2) && !(comp1 & GR_SUPPRESS)
13066 + && !(comp2 & GR_SUPPRESS)) {
13067 + gr_log_fs_rbac_str(GR_DONT_AUDIT, GR_RENAME_ACL_MSG, old_dentry, old_mnt, newname);
13069 + } else if (unlikely(!RENAME_CHECK_SUCCESS(comp1, comp2)))
13076 +gr_acl_handle_exit(void)
13080 + struct file *exec_file;
13082 + if (unlikely(current->acl_sp_role && gr_acl_is_enabled())) {
13083 + id = current->acl_role_id;
13084 + rolename = current->role->rolename;
13086 + gr_log_str_int(GR_DONT_AUDIT_GOOD, GR_SPROLEL_ACL_MSG, rolename, id);
13089 + write_lock(&grsec_exec_file_lock);
13090 + exec_file = current->exec_file;
13091 + current->exec_file = NULL;
13092 + write_unlock(&grsec_exec_file_lock);
13099 +gr_acl_handle_procpidmem(const struct task_struct *task)
13101 + if (unlikely(!gr_acl_is_enabled()))
13104 + if (task->acl->mode & GR_PROTPROCFD)
13109 diff -urNp linux-2.6.16.12/grsecurity/gracl_ip.c linux-2.6.16.12/grsecurity/gracl_ip.c
13110 --- linux-2.6.16.12/grsecurity/gracl_ip.c 1969-12-31 19:00:00.000000000 -0500
13111 +++ linux-2.6.16.12/grsecurity/gracl_ip.c 2006-05-01 20:17:33.000000000 -0400
13113 +#include <linux/kernel.h>
13114 +#include <asm/uaccess.h>
13115 +#include <asm/errno.h>
13116 +#include <net/sock.h>
13117 +#include <linux/file.h>
13118 +#include <linux/fs.h>
13119 +#include <linux/net.h>
13120 +#include <linux/in.h>
13121 +#include <linux/skbuff.h>
13122 +#include <linux/ip.h>
13123 +#include <linux/udp.h>
13124 +#include <linux/smp_lock.h>
13125 +#include <linux/types.h>
13126 +#include <linux/sched.h>
13127 +#include <linux/netdevice.h>
13128 +#include <linux/inetdevice.h>
13129 +#include <linux/gracl.h>
13130 +#include <linux/grsecurity.h>
13131 +#include <linux/grinternal.h>
13133 +#define GR_BIND 0x01
13134 +#define GR_CONNECT 0x02
13135 +#define GR_INVERT 0x04
13137 +static const char * gr_protocols[256] = {
13138 + "ip", "icmp", "igmp", "ggp", "ipencap", "st", "tcp", "cbt",
13139 + "egp", "igp", "bbn-rcc", "nvp", "pup", "argus", "emcon", "xnet",
13140 + "chaos", "udp", "mux", "dcn", "hmp", "prm", "xns-idp", "trunk-1",
13141 + "trunk-2", "leaf-1", "leaf-2", "rdp", "irtp", "iso-tp4", "netblt", "mfe-nsp",
13142 + "merit-inp", "sep", "3pc", "idpr", "xtp", "ddp", "idpr-cmtp", "tp++",
13143 + "il", "ipv6", "sdrp", "ipv6-route", "ipv6-frag", "idrp", "rsvp", "gre",
13144 + "mhrp", "bna", "ipv6-crypt", "ipv6-auth", "i-nlsp", "swipe", "narp", "mobile",
13145 + "tlsp", "skip", "ipv6-icmp", "ipv6-nonxt", "ipv6-opts", "unknown:61", "cftp", "unknown:63",
13146 + "sat-expak", "kryptolan", "rvd", "ippc", "unknown:68", "sat-mon", "visa", "ipcv",
13147 + "cpnx", "cphb", "wsn", "pvp", "br-sat-mon", "sun-nd", "wb-mon", "wb-expak",
13148 + "iso-ip", "vmtp", "secure-vmtp", "vines", "ttp", "nfsnet-igp", "dgp", "tcf",
13149 + "eigrp", "ospf", "sprite-rpc", "larp", "mtp", "ax.25", "ipip", "micp",
13150 + "scc-sp", "etherip", "encap", "unknown:99", "gmtp", "ifmp", "pnni", "pim",
13151 + "aris", "scps", "qnx", "a/n", "ipcomp", "snp", "compaq-peer", "ipx-in-ip",
13152 + "vrrp", "pgm", "unknown:114", "l2tp", "ddx", "iatp", "stp", "srp",
13153 + "uti", "smp", "sm", "ptp", "isis", "fire", "crtp", "crdup",
13154 + "sscopmce", "iplt", "sps", "pipe", "sctp", "fc", "unkown:134", "unknown:135",
13155 + "unknown:136", "unknown:137", "unknown:138", "unknown:139", "unknown:140", "unknown:141", "unknown:142", "unknown:143",
13156 + "unknown:144", "unknown:145", "unknown:146", "unknown:147", "unknown:148", "unknown:149", "unknown:150", "unknown:151",
13157 + "unknown:152", "unknown:153", "unknown:154", "unknown:155", "unknown:156", "unknown:157", "unknown:158", "unknown:159",
13158 + "unknown:160", "unknown:161", "unknown:162", "unknown:163", "unknown:164", "unknown:165", "unknown:166", "unknown:167",
13159 + "unknown:168", "unknown:169", "unknown:170", "unknown:171", "unknown:172", "unknown:173", "unknown:174", "unknown:175",
13160 + "unknown:176", "unknown:177", "unknown:178", "unknown:179", "unknown:180", "unknown:181", "unknown:182", "unknown:183",
13161 + "unknown:184", "unknown:185", "unknown:186", "unknown:187", "unknown:188", "unknown:189", "unknown:190", "unknown:191",
13162 + "unknown:192", "unknown:193", "unknown:194", "unknown:195", "unknown:196", "unknown:197", "unknown:198", "unknown:199",
13163 + "unknown:200", "unknown:201", "unknown:202", "unknown:203", "unknown:204", "unknown:205", "unknown:206", "unknown:207",
13164 + "unknown:208", "unknown:209", "unknown:210", "unknown:211", "unknown:212", "unknown:213", "unknown:214", "unknown:215",
13165 + "unknown:216", "unknown:217", "unknown:218", "unknown:219", "unknown:220", "unknown:221", "unknown:222", "unknown:223",
13166 + "unknown:224", "unknown:225", "unknown:226", "unknown:227", "unknown:228", "unknown:229", "unknown:230", "unknown:231",
13167 + "unknown:232", "unknown:233", "unknown:234", "unknown:235", "unknown:236", "unknown:237", "unknown:238", "unknown:239",
13168 + "unknown:240", "unknown:241", "unknown:242", "unknown:243", "unknown:244", "unknown:245", "unknown:246", "unknown:247",
13169 + "unknown:248", "unknown:249", "unknown:250", "unknown:251", "unknown:252", "unknown:253", "unknown:254", "unknown:255",
13172 +static const char * gr_socktypes[11] = {
13173 + "unknown:0", "stream", "dgram", "raw", "rdm", "seqpacket", "unknown:6",
13174 + "unknown:7", "unknown:8", "unknown:9", "packet"
13178 +gr_proto_to_name(unsigned char proto)
13180 + return gr_protocols[proto];
13184 +gr_socktype_to_name(unsigned char type)
13186 + return gr_socktypes[type];
13190 +gr_search_socket(const int domain, const int type, const int protocol)
13192 + struct acl_subject_label *curr;
13194 + if (unlikely(!gr_acl_is_enabled()))
13197 + if ((domain < 0) || (type < 0) || (protocol < 0) || (domain != PF_INET)
13198 + || (domain >= NPROTO) || (type >= SOCK_MAX) || (protocol > 255))
13199 + goto exit; // let the kernel handle it
13201 + curr = current->acl;
13206 + if ((curr->ip_type & (1 << type)) &&
13207 + (curr->ip_proto[protocol / 32] & (1 << (protocol % 32))))
13210 + if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
13211 + /* we don't place acls on raw sockets , and sometimes
13212 + dgram/ip sockets are opened for ioctl and not
13213 + bind/connect, so we'll fake a bind learn log */
13214 + if (type == SOCK_RAW || type == SOCK_PACKET) {
13215 + __u32 fakeip = 0;
13216 + security_learn(GR_IP_LEARN_MSG, current->role->rolename,
13217 + current->role->roletype, current->uid,
13218 + current->gid, current->exec_file ?
13219 + gr_to_filename(current->exec_file->f_dentry,
13220 + current->exec_file->f_vfsmnt) :
13221 + curr->filename, curr->filename,
13222 + NIPQUAD(fakeip), 0, type,
13223 + protocol, GR_CONNECT,
13224 +NIPQUAD(current->signal->curr_ip));
13225 + } else if ((type == SOCK_DGRAM) && (protocol == IPPROTO_IP)) {
13226 + __u32 fakeip = 0;
13227 + security_learn(GR_IP_LEARN_MSG, current->role->rolename,
13228 + current->role->roletype, current->uid,
13229 + current->gid, current->exec_file ?
13230 + gr_to_filename(current->exec_file->f_dentry,
13231 + current->exec_file->f_vfsmnt) :
13232 + curr->filename, curr->filename,
13233 + NIPQUAD(fakeip), 0, type,
13234 + protocol, GR_BIND, NIPQUAD(current->signal->curr_ip));
13236 + /* we'll log when they use connect or bind */
13240 + gr_log_str3(GR_DONT_AUDIT, GR_SOCK_MSG, "inet",
13241 + gr_socktype_to_name(type), gr_proto_to_name(protocol));
13248 +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)
13250 + if ((ip->mode & mode) &&
13251 + (ip_port >= ip->low) &&
13252 + (ip_port <= ip->high) &&
13253 + ((ntohl(ip_addr) & our_netmask) ==
13254 + (ntohl(our_addr) & our_netmask))
13255 + && (ip->proto[protocol / 32] & (1 << (protocol % 32)))
13256 + && (ip->type & (1 << type))) {
13257 + if (ip->mode & GR_INVERT)
13258 + return 2; // specifically denied
13260 + return 1; // allowed
13263 + return 0; // not specifically allowed, may continue parsing
13267 +gr_search_connectbind(const int mode, const struct sock *sk,
13268 + const struct sockaddr_in *addr, const int type)
13270 + char iface[IFNAMSIZ] = {0};
13271 + struct acl_subject_label *curr;
13272 + struct acl_ip_label *ip;
13273 + struct net_device *dev;
13274 + struct in_device *idev;
13277 + __u32 ip_addr = 0;
13279 + __u32 our_netmask;
13281 + __u16 ip_port = 0;
13283 + if (unlikely(!gr_acl_is_enabled() || sk->sk_family != PF_INET))
13286 + curr = current->acl;
13291 + ip_addr = addr->sin_addr.s_addr;
13292 + ip_port = ntohs(addr->sin_port);
13294 + if (curr->mode & (GR_LEARN | GR_INHERITLEARN)) {
13295 + security_learn(GR_IP_LEARN_MSG, current->role->rolename,
13296 + current->role->roletype, current->uid,
13297 + current->gid, current->exec_file ?
13298 + gr_to_filename(current->exec_file->f_dentry,
13299 + current->exec_file->f_vfsmnt) :
13300 + curr->filename, curr->filename,
13301 + NIPQUAD(ip_addr), ip_port, type,
13302 + sk->sk_protocol, mode, NIPQUAD(current->signal->curr_ip));
13306 + for (i = 0; i < curr->ip_num; i++) {
13307 + ip = *(curr->ips + i);
13308 + if (ip->iface != NULL) {
13309 + strncpy(iface, ip->iface, IFNAMSIZ - 1);
13310 + p = strchr(iface, ':');
13313 + dev = dev_get_by_name(iface);
13316 + idev = in_dev_get(dev);
13317 + if (idev == NULL) {
13323 + if (!strcmp(ip->iface, ifa->ifa_label)) {
13324 + our_addr = ifa->ifa_address;
13325 + our_netmask = 0xffffffff;
13326 + ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask);
13328 + rcu_read_unlock();
13329 + in_dev_put(idev);
13332 + } else if (ret == 2) {
13333 + rcu_read_unlock();
13334 + in_dev_put(idev);
13339 + } endfor_ifa(idev);
13340 + rcu_read_unlock();
13341 + in_dev_put(idev);
13344 + our_addr = ip->addr;
13345 + our_netmask = ip->netmask;
13346 + ret = check_ip_policy(ip, ip_addr, ip_port, sk->sk_protocol, mode, type, our_addr, our_netmask);
13349 + else if (ret == 2)
13355 + if (mode == GR_BIND)
13356 + 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));
13357 + else if (mode == GR_CONNECT)
13358 + 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));
13364 +gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
13366 + return gr_search_connectbind(GR_CONNECT, sock->sk, addr, sock->type);
13370 +gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
13372 + return gr_search_connectbind(GR_BIND, sock->sk, addr, sock->type);
13375 +int gr_search_listen(const struct socket *sock)
13377 + struct sock *sk = sock->sk;
13378 + struct sockaddr_in addr;
13380 + addr.sin_addr.s_addr = inet_sk(sk)->saddr;
13381 + addr.sin_port = inet_sk(sk)->sport;
13383 + return gr_search_connectbind(GR_BIND, sock->sk, &addr, sock->type);
13386 +int gr_search_accept(const struct socket *sock)
13388 + struct sock *sk = sock->sk;
13389 + struct sockaddr_in addr;
13391 + addr.sin_addr.s_addr = inet_sk(sk)->saddr;
13392 + addr.sin_port = inet_sk(sk)->sport;
13394 + return gr_search_connectbind(GR_BIND, sock->sk, &addr, sock->type);
13398 +gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
13401 + return gr_search_connectbind(GR_CONNECT, sk, addr, SOCK_DGRAM);
13403 + struct sockaddr_in sin;
13404 + const struct inet_sock *inet = inet_sk(sk);
13406 + sin.sin_addr.s_addr = inet->daddr;
13407 + sin.sin_port = inet->dport;
13409 + return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM);
13414 +gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
13416 + struct sockaddr_in sin;
13418 + if (unlikely(skb->len < sizeof (struct udphdr)))
13419 + return 1; // skip this packet
13421 + sin.sin_addr.s_addr = skb->nh.iph->saddr;
13422 + sin.sin_port = skb->h.uh->source;
13424 + return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM);
13426 diff -urNp linux-2.6.16.12/grsecurity/gracl_learn.c linux-2.6.16.12/grsecurity/gracl_learn.c
13427 --- linux-2.6.16.12/grsecurity/gracl_learn.c 1969-12-31 19:00:00.000000000 -0500
13428 +++ linux-2.6.16.12/grsecurity/gracl_learn.c 2006-05-01 20:17:33.000000000 -0400
13430 +#include <linux/kernel.h>
13431 +#include <linux/mm.h>
13432 +#include <linux/sched.h>
13433 +#include <linux/poll.h>
13434 +#include <linux/smp_lock.h>
13435 +#include <linux/string.h>
13436 +#include <linux/file.h>
13437 +#include <linux/types.h>
13438 +#include <linux/vmalloc.h>
13439 +#include <linux/grinternal.h>
13441 +extern ssize_t write_grsec_handler(struct file * file, const char __user * buf,
13442 + size_t count, loff_t *ppos);
13443 +extern int gr_acl_is_enabled(void);
13445 +static DECLARE_WAIT_QUEUE_HEAD(learn_wait);
13446 +static int gr_learn_attached;
13448 +/* use a 512k buffer */
13449 +#define LEARN_BUFFER_SIZE (512 * 1024)
13451 +static spinlock_t gr_learn_lock = SPIN_LOCK_UNLOCKED;
13452 +static DECLARE_MUTEX(gr_learn_user_sem);
13454 +/* we need to maintain two buffers, so that the kernel context of grlearn
13455 + uses a semaphore around the userspace copying, and the other kernel contexts
13456 + use a spinlock when copying into the buffer, since they cannot sleep
13458 +static char *learn_buffer;
13459 +static char *learn_buffer_user;
13460 +static int learn_buffer_len;
13461 +static int learn_buffer_user_len;
13464 +read_learn(struct file *file, char __user * buf, size_t count, loff_t * ppos)
13466 + DECLARE_WAITQUEUE(wait, current);
13467 + ssize_t retval = 0;
13469 + add_wait_queue(&learn_wait, &wait);
13470 + set_current_state(TASK_INTERRUPTIBLE);
13472 + down(&gr_learn_user_sem);
13473 + spin_lock(&gr_learn_lock);
13474 + if (learn_buffer_len)
13476 + spin_unlock(&gr_learn_lock);
13477 + up(&gr_learn_user_sem);
13478 + if (file->f_flags & O_NONBLOCK) {
13479 + retval = -EAGAIN;
13482 + if (signal_pending(current)) {
13483 + retval = -ERESTARTSYS;
13490 + memcpy(learn_buffer_user, learn_buffer, learn_buffer_len);
13491 + learn_buffer_user_len = learn_buffer_len;
13492 + retval = learn_buffer_len;
13493 + learn_buffer_len = 0;
13495 + spin_unlock(&gr_learn_lock);
13497 + if (copy_to_user(buf, learn_buffer_user, learn_buffer_user_len))
13498 + retval = -EFAULT;
13500 + up(&gr_learn_user_sem);
13502 + set_current_state(TASK_RUNNING);
13503 + remove_wait_queue(&learn_wait, &wait);
13507 +static unsigned int
13508 +poll_learn(struct file * file, poll_table * wait)
13510 + poll_wait(file, &learn_wait, wait);
13512 + if (learn_buffer_len)
13513 + return (POLLIN | POLLRDNORM);
13519 +gr_clear_learn_entries(void)
13523 + down(&gr_learn_user_sem);
13524 + if (learn_buffer != NULL) {
13525 + spin_lock(&gr_learn_lock);
13526 + tmp = learn_buffer;
13527 + learn_buffer = NULL;
13528 + spin_unlock(&gr_learn_lock);
13529 + vfree(learn_buffer);
13531 + if (learn_buffer_user != NULL) {
13532 + vfree(learn_buffer_user);
13533 + learn_buffer_user = NULL;
13535 + learn_buffer_len = 0;
13536 + up(&gr_learn_user_sem);
13542 +gr_add_learn_entry(const char *fmt, ...)
13545 + unsigned int len;
13547 + if (!gr_learn_attached)
13550 + spin_lock(&gr_learn_lock);
13552 + /* leave a gap at the end so we know when it's "full" but don't have to
13553 + compute the exact length of the string we're trying to append
13555 + if (learn_buffer_len > LEARN_BUFFER_SIZE - 16384) {
13556 + spin_unlock(&gr_learn_lock);
13557 + wake_up_interruptible(&learn_wait);
13560 + if (learn_buffer == NULL) {
13561 + spin_unlock(&gr_learn_lock);
13565 + va_start(args, fmt);
13566 + len = vsnprintf(learn_buffer + learn_buffer_len, LEARN_BUFFER_SIZE - learn_buffer_len, fmt, args);
13569 + learn_buffer_len += len + 1;
13571 + spin_unlock(&gr_learn_lock);
13572 + wake_up_interruptible(&learn_wait);
13578 +open_learn(struct inode *inode, struct file *file)
13580 + if (file->f_mode & FMODE_READ && gr_learn_attached)
13582 + if (file->f_mode & FMODE_READ) {
13583 + down(&gr_learn_user_sem);
13584 + if (learn_buffer == NULL)
13585 + learn_buffer = vmalloc(LEARN_BUFFER_SIZE);
13586 + if (learn_buffer_user == NULL)
13587 + learn_buffer_user = vmalloc(LEARN_BUFFER_SIZE);
13588 + if (learn_buffer == NULL)
13590 + if (learn_buffer_user == NULL)
13592 + learn_buffer_len = 0;
13593 + learn_buffer_user_len = 0;
13594 + gr_learn_attached = 1;
13595 + up(&gr_learn_user_sem);
13601 +close_learn(struct inode *inode, struct file *file)
13605 + if (file->f_mode & FMODE_READ) {
13606 + down(&gr_learn_user_sem);
13607 + if (learn_buffer != NULL) {
13608 + spin_lock(&gr_learn_lock);
13609 + tmp = learn_buffer;
13610 + learn_buffer = NULL;
13611 + spin_unlock(&gr_learn_lock);
13614 + if (learn_buffer_user != NULL) {
13615 + vfree(learn_buffer_user);
13616 + learn_buffer_user = NULL;
13618 + learn_buffer_len = 0;
13619 + learn_buffer_user_len = 0;
13620 + gr_learn_attached = 0;
13621 + up(&gr_learn_user_sem);
13627 +struct file_operations grsec_fops = {
13628 + .read = read_learn,
13629 + .write = write_grsec_handler,
13630 + .open = open_learn,
13631 + .release = close_learn,
13632 + .poll = poll_learn,
13634 diff -urNp linux-2.6.16.12/grsecurity/gracl_res.c linux-2.6.16.12/grsecurity/gracl_res.c
13635 --- linux-2.6.16.12/grsecurity/gracl_res.c 1969-12-31 19:00:00.000000000 -0500
13636 +++ linux-2.6.16.12/grsecurity/gracl_res.c 2006-05-01 20:17:33.000000000 -0400
13638 +#include <linux/kernel.h>
13639 +#include <linux/sched.h>
13640 +#include <linux/gracl.h>
13641 +#include <linux/grinternal.h>
13643 +static const char *restab_log[] = {
13644 + [RLIMIT_CPU] = "RLIMIT_CPU",
13645 + [RLIMIT_FSIZE] = "RLIMIT_FSIZE",
13646 + [RLIMIT_DATA] = "RLIMIT_DATA",
13647 + [RLIMIT_STACK] = "RLIMIT_STACK",
13648 + [RLIMIT_CORE] = "RLIMIT_CORE",
13649 + [RLIMIT_RSS] = "RLIMIT_RSS",
13650 + [RLIMIT_NPROC] = "RLIMIT_NPROC",
13651 + [RLIMIT_NOFILE] = "RLIMIT_NOFILE",
13652 + [RLIMIT_MEMLOCK] = "RLIMIT_MEMLOCK",
13653 + [RLIMIT_AS] = "RLIMIT_AS",
13654 + [RLIMIT_LOCKS] = "RLIMIT_LOCKS",
13655 + [RLIMIT_LOCKS + 1] = "RLIMIT_CRASH"
13659 +gr_log_resource(const struct task_struct *task,
13660 + const int res, const unsigned long wanted, const int gt)
13662 + if (res == RLIMIT_NPROC &&
13663 + (cap_raised(task->cap_effective, CAP_SYS_ADMIN) ||
13664 + cap_raised(task->cap_effective, CAP_SYS_RESOURCE)))
13666 + else if (res == RLIMIT_MEMLOCK &&
13667 + cap_raised(task->cap_effective, CAP_IPC_LOCK))
13670 + preempt_disable();
13672 + if (unlikely(((gt && wanted > task->signal->rlim[res].rlim_cur) ||
13673 + (!gt && wanted >= task->signal->rlim[res].rlim_cur)) &&
13674 + task->signal->rlim[res].rlim_cur != RLIM_INFINITY))
13675 + gr_log_res_ulong2_str(GR_DONT_AUDIT, GR_RESOURCE_MSG, task, wanted, restab_log[res], task->signal->rlim[res].rlim_cur);
13676 + preempt_enable_no_resched();
13680 diff -urNp linux-2.6.16.12/grsecurity/gracl_segv.c linux-2.6.16.12/grsecurity/gracl_segv.c
13681 --- linux-2.6.16.12/grsecurity/gracl_segv.c 1969-12-31 19:00:00.000000000 -0500
13682 +++ linux-2.6.16.12/grsecurity/gracl_segv.c 2006-05-01 20:17:33.000000000 -0400
13684 +#include <linux/kernel.h>
13685 +#include <linux/mm.h>
13686 +#include <asm/uaccess.h>
13687 +#include <asm/errno.h>
13688 +#include <asm/mman.h>
13689 +#include <net/sock.h>
13690 +#include <linux/file.h>
13691 +#include <linux/fs.h>
13692 +#include <linux/net.h>
13693 +#include <linux/in.h>
13694 +#include <linux/smp_lock.h>
13695 +#include <linux/slab.h>
13696 +#include <linux/types.h>
13697 +#include <linux/sched.h>
13698 +#include <linux/timer.h>
13699 +#include <linux/gracl.h>
13700 +#include <linux/grsecurity.h>
13701 +#include <linux/grinternal.h>
13703 +static struct crash_uid *uid_set;
13704 +static unsigned short uid_used;
13705 +static spinlock_t gr_uid_lock = SPIN_LOCK_UNLOCKED;
13706 +extern rwlock_t gr_inode_lock;
13707 +extern struct acl_subject_label *
13708 + lookup_acl_subj_label(const ino_t inode, const dev_t dev,
13709 + struct acl_role_label *role);
13710 +extern int specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t);
13713 +gr_init_uidset(void)
13716 + kmalloc(GR_UIDTABLE_MAX * sizeof (struct crash_uid), GFP_KERNEL);
13719 + return uid_set ? 1 : 0;
13723 +gr_free_uidset(void)
13732 +gr_find_uid(const uid_t uid)
13734 + struct crash_uid *tmp = uid_set;
13736 + int low = 0, high = uid_used - 1, mid;
13738 + while (high >= low) {
13739 + mid = (low + high) >> 1;
13740 + buid = tmp[mid].uid;
13752 +static __inline__ void
13753 +gr_insertsort(void)
13755 + unsigned short i, j;
13756 + struct crash_uid index;
13758 + for (i = 1; i < uid_used; i++) {
13759 + index = uid_set[i];
13761 + while ((j > 0) && uid_set[j - 1].uid > index.uid) {
13762 + uid_set[j] = uid_set[j - 1];
13765 + uid_set[j] = index;
13771 +static __inline__ void
13772 +gr_insert_uid(const uid_t uid, const unsigned long expires)
13776 + if (uid_used == GR_UIDTABLE_MAX)
13779 + loc = gr_find_uid(uid);
13782 + uid_set[loc].expires = expires;
13786 + uid_set[uid_used].uid = uid;
13787 + uid_set[uid_used].expires = expires;
13796 +gr_remove_uid(const unsigned short loc)
13798 + unsigned short i;
13800 + for (i = loc + 1; i < uid_used; i++)
13801 + uid_set[i - 1] = uid_set[i];
13809 +gr_check_crash_uid(const uid_t uid)
13814 + if (unlikely(!gr_acl_is_enabled()))
13817 + spin_lock(&gr_uid_lock);
13818 + loc = gr_find_uid(uid);
13823 + if (time_before_eq(uid_set[loc].expires, get_seconds()))
13824 + gr_remove_uid(loc);
13829 + spin_unlock(&gr_uid_lock);
13833 +static __inline__ int
13834 +proc_is_setxid(const struct task_struct *task)
13836 + if (task->uid != task->euid || task->uid != task->suid ||
13837 + task->uid != task->fsuid)
13839 + if (task->gid != task->egid || task->gid != task->sgid ||
13840 + task->gid != task->fsgid)
13845 +static __inline__ int
13846 +gr_fake_force_sig(int sig, struct task_struct *t)
13848 + unsigned long int flags;
13851 + spin_lock_irqsave(&t->sighand->siglock, flags);
13852 + if (sigismember(&t->blocked, sig) || t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) {
13853 + t->sighand->action[sig-1].sa.sa_handler = SIG_DFL;
13854 + sigdelset(&t->blocked, sig);
13855 + recalc_sigpending_tsk(t);
13857 + ret = specific_send_sig_info(sig, (void*)1L, t);
13858 + spin_unlock_irqrestore(&t->sighand->siglock, flags);
13864 +gr_handle_crash(struct task_struct *task, const int sig)
13866 + struct acl_subject_label *curr;
13867 + struct acl_subject_label *curr2;
13868 + struct task_struct *tsk, *tsk2;
13870 + if (sig != SIGSEGV && sig != SIGKILL && sig != SIGBUS && sig != SIGILL)
13873 + if (unlikely(!gr_acl_is_enabled()))
13876 + curr = task->acl;
13878 + if (!(curr->resmask & (1 << GR_CRASH_RES)))
13881 + if (time_before_eq(curr->expires, get_seconds())) {
13882 + curr->expires = 0;
13883 + curr->crashes = 0;
13888 + if (!curr->expires)
13889 + curr->expires = get_seconds() + curr->res[GR_CRASH_RES].rlim_max;
13891 + if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
13892 + time_after(curr->expires, get_seconds())) {
13893 + if (task->uid && proc_is_setxid(task)) {
13894 + gr_log_crash1(GR_DONT_AUDIT, GR_SEGVSTART_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
13895 + spin_lock(&gr_uid_lock);
13896 + gr_insert_uid(task->uid, curr->expires);
13897 + spin_unlock(&gr_uid_lock);
13898 + curr->expires = 0;
13899 + curr->crashes = 0;
13900 + read_lock(&tasklist_lock);
13901 + do_each_thread(tsk2, tsk) {
13902 + if (tsk != task && tsk->uid == task->uid)
13903 + gr_fake_force_sig(SIGKILL, tsk);
13904 + } while_each_thread(tsk2, tsk);
13905 + read_unlock(&tasklist_lock);
13907 + gr_log_crash2(GR_DONT_AUDIT, GR_SEGVNOSUID_ACL_MSG, task, curr->res[GR_CRASH_RES].rlim_max);
13908 + read_lock(&tasklist_lock);
13909 + do_each_thread(tsk2, tsk) {
13910 + if (likely(tsk != task)) {
13911 + curr2 = tsk->acl;
13913 + if (curr2->device == curr->device &&
13914 + curr2->inode == curr->inode)
13915 + gr_fake_force_sig(SIGKILL, tsk);
13917 + } while_each_thread(tsk2, tsk);
13918 + read_unlock(&tasklist_lock);
13926 +gr_check_crash_exec(const struct file *filp)
13928 + struct acl_subject_label *curr;
13930 + if (unlikely(!gr_acl_is_enabled()))
13933 + read_lock(&gr_inode_lock);
13934 + curr = lookup_acl_subj_label(filp->f_dentry->d_inode->i_ino,
13935 + filp->f_dentry->d_inode->i_sb->s_dev,
13937 + read_unlock(&gr_inode_lock);
13939 + if (!curr || !(curr->resmask & (1 << GR_CRASH_RES)) ||
13940 + (!curr->crashes && !curr->expires))
13943 + if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) &&
13944 + time_after(curr->expires, get_seconds()))
13946 + else if (time_before_eq(curr->expires, get_seconds())) {
13947 + curr->crashes = 0;
13948 + curr->expires = 0;
13955 +gr_handle_alertkill(struct task_struct *task)
13957 + struct acl_subject_label *curracl;
13959 + struct task_struct *p, *p2;
13961 + if (unlikely(!gr_acl_is_enabled()))
13964 + curracl = task->acl;
13965 + curr_ip = task->signal->curr_ip;
13967 + if ((curracl->mode & GR_KILLIPPROC) && curr_ip) {
13968 + read_lock(&tasklist_lock);
13969 + do_each_thread(p2, p) {
13970 + if (p->signal->curr_ip == curr_ip)
13971 + gr_fake_force_sig(SIGKILL, p);
13972 + } while_each_thread(p2, p);
13973 + read_unlock(&tasklist_lock);
13974 + } else if (curracl->mode & GR_KILLPROC)
13975 + gr_fake_force_sig(SIGKILL, task);
13979 diff -urNp linux-2.6.16.12/grsecurity/gracl_shm.c linux-2.6.16.12/grsecurity/gracl_shm.c
13980 --- linux-2.6.16.12/grsecurity/gracl_shm.c 1969-12-31 19:00:00.000000000 -0500
13981 +++ linux-2.6.16.12/grsecurity/gracl_shm.c 2006-05-01 20:17:34.000000000 -0400
13983 +#include <linux/kernel.h>
13984 +#include <linux/mm.h>
13985 +#include <linux/sched.h>
13986 +#include <linux/file.h>
13987 +#include <linux/ipc.h>
13988 +#include <linux/gracl.h>
13989 +#include <linux/grsecurity.h>
13990 +#include <linux/grinternal.h>
13993 +gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
13994 + const time_t shm_createtime, const uid_t cuid, const int shmid)
13996 + struct task_struct *task;
13998 + if (!gr_acl_is_enabled())
14001 + task = find_task_by_pid(shm_cprid);
14003 + if (unlikely(!task))
14004 + task = find_task_by_pid(shm_lapid);
14006 + if (unlikely(task && (time_before((unsigned long)task->start_time.tv_sec, (unsigned long)shm_createtime) ||
14007 + (task->pid == shm_lapid)) &&
14008 + (task->acl->mode & GR_PROTSHM) &&
14009 + (task->acl != current->acl))) {
14010 + gr_log_int3(GR_DONT_AUDIT, GR_SHMAT_ACL_MSG, cuid, shm_cprid, shmid);
14016 diff -urNp linux-2.6.16.12/grsecurity/grsec_chdir.c linux-2.6.16.12/grsecurity/grsec_chdir.c
14017 --- linux-2.6.16.12/grsecurity/grsec_chdir.c 1969-12-31 19:00:00.000000000 -0500
14018 +++ linux-2.6.16.12/grsecurity/grsec_chdir.c 2006-05-01 20:17:34.000000000 -0400
14020 +#include <linux/kernel.h>
14021 +#include <linux/sched.h>
14022 +#include <linux/fs.h>
14023 +#include <linux/file.h>
14024 +#include <linux/grsecurity.h>
14025 +#include <linux/grinternal.h>
14028 +gr_log_chdir(const struct dentry *dentry, const struct vfsmount *mnt)
14030 +#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
14031 + if ((grsec_enable_chdir && grsec_enable_group &&
14032 + in_group_p(grsec_audit_gid)) || (grsec_enable_chdir &&
14033 + !grsec_enable_group)) {
14034 + gr_log_fs_generic(GR_DO_AUDIT, GR_CHDIR_AUDIT_MSG, dentry, mnt);
14039 diff -urNp linux-2.6.16.12/grsecurity/grsec_chroot.c linux-2.6.16.12/grsecurity/grsec_chroot.c
14040 --- linux-2.6.16.12/grsecurity/grsec_chroot.c 1969-12-31 19:00:00.000000000 -0500
14041 +++ linux-2.6.16.12/grsecurity/grsec_chroot.c 2006-05-01 20:17:34.000000000 -0400
14043 +#include <linux/kernel.h>
14044 +#include <linux/module.h>
14045 +#include <linux/sched.h>
14046 +#include <linux/file.h>
14047 +#include <linux/fs.h>
14048 +#include <linux/mount.h>
14049 +#include <linux/types.h>
14050 +#include <linux/grinternal.h>
14053 +gr_handle_chroot_unix(const pid_t pid)
14055 +#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
14056 + struct pid *spid = NULL;
14058 + if (unlikely(!grsec_enable_chroot_unix))
14061 + if (likely(!proc_is_chrooted(current)))
14064 + read_lock(&tasklist_lock);
14066 + spid = find_pid(PIDTYPE_PID, pid);
14068 + struct task_struct *p;
14069 + p = pid_task(&spid->pid_list, PIDTYPE_PID);
14071 + if (unlikely(!have_same_root(current, p))) {
14073 + read_unlock(&tasklist_lock);
14074 + gr_log_noargs(GR_DONT_AUDIT, GR_UNIX_CHROOT_MSG);
14079 + read_unlock(&tasklist_lock);
14085 +gr_handle_chroot_nice(void)
14087 +#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
14088 + if (grsec_enable_chroot_nice && proc_is_chrooted(current)) {
14089 + gr_log_noargs(GR_DONT_AUDIT, GR_NICE_CHROOT_MSG);
14097 +gr_handle_chroot_setpriority(struct task_struct *p, const int niceval)
14099 +#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
14100 + if (grsec_enable_chroot_nice && (niceval < task_nice(p))
14101 + && proc_is_chrooted(current)) {
14102 + gr_log_str_int(GR_DONT_AUDIT, GR_PRIORITY_CHROOT_MSG, p->comm, p->pid);
14110 +gr_handle_chroot_rawio(const struct inode *inode)
14112 +#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
14113 + if (grsec_enable_chroot_caps && proc_is_chrooted(current) &&
14114 + inode && S_ISBLK(inode->i_mode) && !capable(CAP_SYS_RAWIO))
14121 +gr_pid_is_chrooted(struct task_struct *p)
14123 +#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
14124 + if (!grsec_enable_chroot_findtask || !proc_is_chrooted(current) || !p)
14128 + if ((p->exit_state & (EXIT_ZOMBIE | EXIT_DEAD)) ||
14129 + !have_same_root(current, p)) {
14138 +EXPORT_SYMBOL(gr_pid_is_chrooted);
14140 +#if defined(CONFIG_GRKERNSEC_CHROOT_DOUBLE) || defined(CONFIG_GRKERNSEC_CHROOT_FCHDIR)
14141 +int gr_is_outside_chroot(const struct dentry *u_dentry, const struct vfsmount *u_mnt)
14143 + struct dentry *dentry = (struct dentry *)u_dentry;
14144 + struct vfsmount *mnt = (struct vfsmount *)u_mnt;
14145 + struct dentry *realroot;
14146 + struct vfsmount *realrootmnt;
14147 + struct dentry *currentroot;
14148 + struct vfsmount *currentmnt;
14151 + read_lock(&child_reaper->fs->lock);
14152 + realrootmnt = mntget(child_reaper->fs->rootmnt);
14153 + realroot = dget(child_reaper->fs->root);
14154 + read_unlock(&child_reaper->fs->lock);
14156 + read_lock(¤t->fs->lock);
14157 + currentmnt = mntget(current->fs->rootmnt);
14158 + currentroot = dget(current->fs->root);
14159 + read_unlock(¤t->fs->lock);
14161 + spin_lock(&dcache_lock);
14163 + if (unlikely((dentry == realroot && mnt == realrootmnt)
14164 + || (dentry == currentroot && mnt == currentmnt)))
14166 + if (unlikely(dentry == mnt->mnt_root || IS_ROOT(dentry))) {
14167 + if (mnt->mnt_parent == mnt)
14169 + dentry = mnt->mnt_mountpoint;
14170 + mnt = mnt->mnt_parent;
14173 + dentry = dentry->d_parent;
14175 + spin_unlock(&dcache_lock);
14177 + dput(currentroot);
14178 + mntput(currentmnt);
14180 + /* access is outside of chroot */
14181 + if (dentry == realroot && mnt == realrootmnt)
14185 + mntput(realrootmnt);
14191 +gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt)
14193 +#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
14194 + if (!grsec_enable_chroot_fchdir)
14197 + if (!proc_is_chrooted(current))
14199 + else if (!gr_is_outside_chroot(u_dentry, u_mnt)) {
14200 + gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_FCHDIR_MSG, u_dentry, u_mnt);
14208 +gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
14209 + const time_t shm_createtime)
14211 +#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
14212 + struct pid *pid = NULL;
14213 + time_t starttime;
14215 + if (unlikely(!grsec_enable_chroot_shmat))
14218 + if (likely(!proc_is_chrooted(current)))
14221 + read_lock(&tasklist_lock);
14223 + pid = find_pid(PIDTYPE_PID, shm_cprid);
14225 + struct task_struct *p;
14226 + p = pid_task(&pid->pid_list, PIDTYPE_PID);
14228 + starttime = p->start_time.tv_sec;
14229 + if (unlikely(!have_same_root(current, p) &&
14230 + time_before((unsigned long)starttime, (unsigned long)shm_createtime))) {
14232 + read_unlock(&tasklist_lock);
14233 + gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG);
14238 + pid = find_pid(PIDTYPE_PID, shm_lapid);
14240 + struct task_struct *p;
14241 + p = pid_task(&pid->pid_list, PIDTYPE_PID);
14243 + if (unlikely(!have_same_root(current, p))) {
14245 + read_unlock(&tasklist_lock);
14246 + gr_log_noargs(GR_DONT_AUDIT, GR_SHMAT_CHROOT_MSG);
14253 + read_unlock(&tasklist_lock);
14259 +gr_log_chroot_exec(const struct dentry *dentry, const struct vfsmount *mnt)
14261 +#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
14262 + if (grsec_enable_chroot_execlog && proc_is_chrooted(current))
14263 + gr_log_fs_generic(GR_DO_AUDIT, GR_EXEC_CHROOT_MSG, dentry, mnt);
14269 +gr_handle_chroot_mknod(const struct dentry *dentry,
14270 + const struct vfsmount *mnt, const int mode)
14272 +#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
14273 + if (grsec_enable_chroot_mknod && !S_ISFIFO(mode) && !S_ISREG(mode) &&
14274 + proc_is_chrooted(current)) {
14275 + gr_log_fs_generic(GR_DONT_AUDIT, GR_MKNOD_CHROOT_MSG, dentry, mnt);
14283 +gr_handle_chroot_mount(const struct dentry *dentry,
14284 + const struct vfsmount *mnt, const char *dev_name)
14286 +#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
14287 + if (grsec_enable_chroot_mount && proc_is_chrooted(current)) {
14288 + gr_log_str_fs(GR_DONT_AUDIT, GR_MOUNT_CHROOT_MSG, dev_name, dentry, mnt);
14296 +gr_handle_chroot_pivot(void)
14298 +#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
14299 + if (grsec_enable_chroot_pivot && proc_is_chrooted(current)) {
14300 + gr_log_noargs(GR_DONT_AUDIT, GR_PIVOT_CHROOT_MSG);
14308 +gr_handle_chroot_chroot(const struct dentry *dentry, const struct vfsmount *mnt)
14310 +#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
14311 + if (grsec_enable_chroot_double && proc_is_chrooted(current) &&
14312 + !gr_is_outside_chroot(dentry, mnt)) {
14313 + gr_log_fs_generic(GR_DONT_AUDIT, GR_CHROOT_CHROOT_MSG, dentry, mnt);
14321 +gr_handle_chroot_caps(struct task_struct *task)
14323 +#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
14324 + if (grsec_enable_chroot_caps && proc_is_chrooted(task)) {
14325 + task->cap_permitted =
14326 + cap_drop(task->cap_permitted, GR_CHROOT_CAPS);
14327 + task->cap_inheritable =
14328 + cap_drop(task->cap_inheritable, GR_CHROOT_CAPS);
14329 + task->cap_effective =
14330 + cap_drop(task->cap_effective, GR_CHROOT_CAPS);
14337 +gr_handle_chroot_sysctl(const int op)
14339 +#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
14340 + if (grsec_enable_chroot_sysctl && proc_is_chrooted(current)
14348 +gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt)
14350 +#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
14351 + if (grsec_enable_chroot_chdir)
14352 + set_fs_pwd(current->fs, mnt, dentry);
14358 +gr_handle_chroot_chmod(const struct dentry *dentry,
14359 + const struct vfsmount *mnt, const int mode)
14361 +#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
14362 + if (grsec_enable_chroot_chmod &&
14363 + ((mode & S_ISUID) || ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))) &&
14364 + proc_is_chrooted(current)) {
14365 + gr_log_fs_generic(GR_DONT_AUDIT, GR_CHMOD_CHROOT_MSG, dentry, mnt);
14372 +#ifdef CONFIG_SECURITY
14373 +EXPORT_SYMBOL(gr_handle_chroot_caps);
14375 diff -urNp linux-2.6.16.12/grsecurity/grsec_disabled.c linux-2.6.16.12/grsecurity/grsec_disabled.c
14376 --- linux-2.6.16.12/grsecurity/grsec_disabled.c 1969-12-31 19:00:00.000000000 -0500
14377 +++ linux-2.6.16.12/grsecurity/grsec_disabled.c 2006-05-01 20:17:34.000000000 -0400
14379 +#include <linux/kernel.h>
14380 +#include <linux/module.h>
14381 +#include <linux/config.h>
14382 +#include <linux/sched.h>
14383 +#include <linux/file.h>
14384 +#include <linux/fs.h>
14385 +#include <linux/kdev_t.h>
14386 +#include <linux/net.h>
14387 +#include <linux/in.h>
14388 +#include <linux/ip.h>
14389 +#include <linux/skbuff.h>
14390 +#include <linux/sysctl.h>
14392 +#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
14394 +pax_set_initial_flags(struct linux_binprm *bprm)
14400 +#ifdef CONFIG_SYSCTL
14402 +gr_handle_sysctl(const struct ctl_table * table, __u32 mode)
14409 +gr_acl_is_enabled(void)
14415 +gr_handle_rawio(const struct inode *inode)
14421 +gr_acl_handle_psacct(struct task_struct *task, const long code)
14427 +gr_handle_ptrace(struct task_struct *task, const long request)
14433 +gr_handle_proc_ptrace(struct task_struct *task)
14439 +gr_learn_resource(const struct task_struct *task,
14440 + const int res, const unsigned long wanted, const int gt)
14446 +gr_set_acls(const int type)
14452 +gr_check_hidden_task(const struct task_struct *tsk)
14458 +gr_check_protected_task(const struct task_struct *task)
14464 +gr_copy_label(struct task_struct *tsk)
14470 +gr_set_pax_flags(struct task_struct *task)
14476 +gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt)
14482 +gr_handle_delete(const ino_t ino, const dev_t dev)
14488 +gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt)
14494 +gr_handle_crash(struct task_struct *task, const int sig)
14500 +gr_check_crash_exec(const struct file *filp)
14506 +gr_check_crash_uid(const uid_t uid)
14512 +gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
14513 + struct dentry *old_dentry,
14514 + struct dentry *new_dentry,
14515 + struct vfsmount *mnt, const __u8 replace)
14521 +gr_search_socket(const int family, const int type, const int protocol)
14527 +gr_search_connectbind(const int mode, const struct socket *sock,
14528 + const struct sockaddr_in *addr)
14534 +gr_task_is_capable(struct task_struct *task, const int cap)
14540 +gr_is_capable_nolog(const int cap)
14546 +gr_handle_alertkill(struct task_struct *task)
14552 +gr_acl_handle_execve(const struct dentry * dentry, const struct vfsmount * mnt)
14558 +gr_acl_handle_hidden_file(const struct dentry * dentry,
14559 + const struct vfsmount * mnt)
14565 +gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt,
14572 +gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt)
14578 +gr_acl_handle_unlink(const struct dentry * dentry, const struct vfsmount * mnt)
14584 +gr_acl_handle_mmap(const struct file *file, const unsigned long prot,
14585 + unsigned int *vm_flags)
14591 +gr_acl_handle_truncate(const struct dentry * dentry,
14592 + const struct vfsmount * mnt)
14598 +gr_acl_handle_utime(const struct dentry * dentry, const struct vfsmount * mnt)
14604 +gr_acl_handle_access(const struct dentry * dentry,
14605 + const struct vfsmount * mnt, const int fmode)
14611 +gr_acl_handle_fchmod(const struct dentry * dentry, const struct vfsmount * mnt,
14618 +gr_acl_handle_chmod(const struct dentry * dentry, const struct vfsmount * mnt,
14625 +gr_acl_handle_chown(const struct dentry * dentry, const struct vfsmount * mnt)
14631 +grsecurity_init(void)
14637 +gr_acl_handle_mknod(const struct dentry * new_dentry,
14638 + const struct dentry * parent_dentry,
14639 + const struct vfsmount * parent_mnt,
14646 +gr_acl_handle_mkdir(const struct dentry * new_dentry,
14647 + const struct dentry * parent_dentry,
14648 + const struct vfsmount * parent_mnt)
14654 +gr_acl_handle_symlink(const struct dentry * new_dentry,
14655 + const struct dentry * parent_dentry,
14656 + const struct vfsmount * parent_mnt, const char *from)
14662 +gr_acl_handle_link(const struct dentry * new_dentry,
14663 + const struct dentry * parent_dentry,
14664 + const struct vfsmount * parent_mnt,
14665 + const struct dentry * old_dentry,
14666 + const struct vfsmount * old_mnt, const char *to)
14672 +gr_acl_handle_rename(const struct dentry *new_dentry,
14673 + const struct dentry *parent_dentry,
14674 + const struct vfsmount *parent_mnt,
14675 + const struct dentry *old_dentry,
14676 + const struct inode *old_parent_inode,
14677 + const struct vfsmount *old_mnt, const char *newname)
14683 +gr_acl_handle_filldir(const struct file *file, const char *name,
14684 + const int namelen, const ino_t ino)
14690 +gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
14691 + const time_t shm_createtime, const uid_t cuid, const int shmid)
14697 +gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr)
14703 +gr_search_accept(const struct socket *sock)
14709 +gr_search_listen(const struct socket *sock)
14715 +gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr)
14721 +gr_acl_handle_unix(const struct dentry * dentry, const struct vfsmount * mnt)
14727 +gr_acl_handle_creat(const struct dentry * dentry,
14728 + const struct dentry * p_dentry,
14729 + const struct vfsmount * p_mnt, const int fmode,
14736 +gr_acl_handle_exit(void)
14742 +gr_acl_handle_mprotect(const struct file *file, const unsigned long prot)
14748 +gr_set_role_label(const uid_t uid, const gid_t gid)
14754 +gr_acl_handle_procpidmem(const struct task_struct *task)
14760 +gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb)
14766 +gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr)
14772 +gr_set_kernel_label(struct task_struct *task)
14778 +gr_check_user_change(int real, int effective, int fs)
14784 +gr_check_group_change(int real, int effective, int fs)
14790 +EXPORT_SYMBOL(gr_task_is_capable);
14791 +EXPORT_SYMBOL(gr_learn_resource);
14792 +EXPORT_SYMBOL(gr_set_kernel_label);
14793 +#ifdef CONFIG_SECURITY
14794 +EXPORT_SYMBOL(gr_check_user_change);
14795 +EXPORT_SYMBOL(gr_check_group_change);
14797 diff -urNp linux-2.6.16.12/grsecurity/grsec_exec.c linux-2.6.16.12/grsecurity/grsec_exec.c
14798 --- linux-2.6.16.12/grsecurity/grsec_exec.c 1969-12-31 19:00:00.000000000 -0500
14799 +++ linux-2.6.16.12/grsecurity/grsec_exec.c 2006-05-01 20:17:34.000000000 -0400
14801 +#include <linux/kernel.h>
14802 +#include <linux/sched.h>
14803 +#include <linux/file.h>
14804 +#include <linux/binfmts.h>
14805 +#include <linux/smp_lock.h>
14806 +#include <linux/fs.h>
14807 +#include <linux/types.h>
14808 +#include <linux/grdefs.h>
14809 +#include <linux/grinternal.h>
14810 +#include <linux/capability.h>
14812 +#include <asm/uaccess.h>
14814 +#ifdef CONFIG_GRKERNSEC_EXECLOG
14815 +static char gr_exec_arg_buf[132];
14816 +static DECLARE_MUTEX(gr_exec_arg_sem);
14820 +gr_handle_nproc(void)
14822 +#ifdef CONFIG_GRKERNSEC_EXECVE
14823 + if (grsec_enable_execve && current->user &&
14824 + (atomic_read(¤t->user->processes) >
14825 + current->signal->rlim[RLIMIT_NPROC].rlim_cur) &&
14826 + !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) {
14827 + gr_log_noargs(GR_DONT_AUDIT, GR_NPROC_MSG);
14835 +gr_handle_exec_args(struct linux_binprm *bprm, const char __user *__user *argv)
14837 +#ifdef CONFIG_GRKERNSEC_EXECLOG
14838 + char *grarg = gr_exec_arg_buf;
14839 + unsigned int i, x, execlen = 0;
14842 + if (!((grsec_enable_execlog && grsec_enable_group &&
14843 + in_group_p(grsec_audit_gid))
14844 + || (grsec_enable_execlog && !grsec_enable_group)))
14847 + down(&gr_exec_arg_sem);
14848 + memset(grarg, 0, sizeof(gr_exec_arg_buf));
14850 + if (unlikely(argv == NULL))
14853 + for (i = 0; i < bprm->argc && execlen < 128; i++) {
14854 + const char __user *p;
14855 + unsigned int len;
14857 + if (copy_from_user(&p, argv + i, sizeof(p)))
14861 + len = strnlen_user(p, 128 - execlen);
14862 + if (len > 128 - execlen)
14863 + len = 128 - execlen;
14864 + else if (len > 0)
14866 + if (copy_from_user(grarg + execlen, p, len))
14869 + /* rewrite unprintable characters */
14870 + for (x = 0; x < len; x++) {
14871 + c = *(grarg + execlen + x);
14872 + if (c < 32 || c > 126)
14873 + *(grarg + execlen + x) = ' ';
14877 + *(grarg + execlen) = ' ';
14878 + *(grarg + execlen + 1) = '\0';
14883 + gr_log_fs_str(GR_DO_AUDIT, GR_EXEC_AUDIT_MSG, bprm->file->f_dentry,
14884 + bprm->file->f_vfsmnt, grarg);
14885 + up(&gr_exec_arg_sem);
14889 diff -urNp linux-2.6.16.12/grsecurity/grsec_fifo.c linux-2.6.16.12/grsecurity/grsec_fifo.c
14890 --- linux-2.6.16.12/grsecurity/grsec_fifo.c 1969-12-31 19:00:00.000000000 -0500
14891 +++ linux-2.6.16.12/grsecurity/grsec_fifo.c 2006-05-01 20:17:34.000000000 -0400
14893 +#include <linux/kernel.h>
14894 +#include <linux/sched.h>
14895 +#include <linux/fs.h>
14896 +#include <linux/file.h>
14897 +#include <linux/grinternal.h>
14900 +gr_handle_fifo(const struct dentry *dentry, const struct vfsmount *mnt,
14901 + const struct dentry *dir, const int flag, const int acc_mode)
14903 +#ifdef CONFIG_GRKERNSEC_FIFO
14904 + if (grsec_enable_fifo && S_ISFIFO(dentry->d_inode->i_mode) &&
14905 + !(flag & O_EXCL) && (dir->d_inode->i_mode & S_ISVTX) &&
14906 + (dentry->d_inode->i_uid != dir->d_inode->i_uid) &&
14907 + (current->fsuid != dentry->d_inode->i_uid)) {
14908 + if (!generic_permission(dentry->d_inode, acc_mode, NULL))
14909 + gr_log_fs_int2(GR_DONT_AUDIT, GR_FIFO_MSG, dentry, mnt, dentry->d_inode->i_uid, dentry->d_inode->i_gid);
14915 diff -urNp linux-2.6.16.12/grsecurity/grsec_fork.c linux-2.6.16.12/grsecurity/grsec_fork.c
14916 --- linux-2.6.16.12/grsecurity/grsec_fork.c 1969-12-31 19:00:00.000000000 -0500
14917 +++ linux-2.6.16.12/grsecurity/grsec_fork.c 2006-05-01 20:17:34.000000000 -0400
14919 +#include <linux/kernel.h>
14920 +#include <linux/sched.h>
14921 +#include <linux/grsecurity.h>
14922 +#include <linux/grinternal.h>
14925 +gr_log_forkfail(const int retval)
14927 +#ifdef CONFIG_GRKERNSEC_FORKFAIL
14928 + if (grsec_enable_forkfail)
14929 + gr_log_int(GR_DONT_AUDIT, GR_FAILFORK_MSG, retval);
14933 diff -urNp linux-2.6.16.12/grsecurity/grsec_init.c linux-2.6.16.12/grsecurity/grsec_init.c
14934 --- linux-2.6.16.12/grsecurity/grsec_init.c 1969-12-31 19:00:00.000000000 -0500
14935 +++ linux-2.6.16.12/grsecurity/grsec_init.c 2006-05-01 20:17:34.000000000 -0400
14937 +#include <linux/kernel.h>
14938 +#include <linux/sched.h>
14939 +#include <linux/mm.h>
14940 +#include <linux/smp_lock.h>
14941 +#include <linux/gracl.h>
14942 +#include <linux/slab.h>
14943 +#include <linux/vmalloc.h>
14944 +#include <linux/percpu.h>
14946 +int grsec_enable_shm;
14947 +int grsec_enable_link;
14948 +int grsec_enable_dmesg;
14949 +int grsec_enable_fifo;
14950 +int grsec_enable_execve;
14951 +int grsec_enable_execlog;
14952 +int grsec_enable_signal;
14953 +int grsec_enable_forkfail;
14954 +int grsec_enable_time;
14955 +int grsec_enable_audit_textrel;
14956 +int grsec_enable_group;
14957 +int grsec_audit_gid;
14958 +int grsec_enable_chdir;
14959 +int grsec_enable_audit_ipc;
14960 +int grsec_enable_mount;
14961 +int grsec_enable_chroot_findtask;
14962 +int grsec_enable_chroot_mount;
14963 +int grsec_enable_chroot_shmat;
14964 +int grsec_enable_chroot_fchdir;
14965 +int grsec_enable_chroot_double;
14966 +int grsec_enable_chroot_pivot;
14967 +int grsec_enable_chroot_chdir;
14968 +int grsec_enable_chroot_chmod;
14969 +int grsec_enable_chroot_mknod;
14970 +int grsec_enable_chroot_nice;
14971 +int grsec_enable_chroot_execlog;
14972 +int grsec_enable_chroot_caps;
14973 +int grsec_enable_chroot_sysctl;
14974 +int grsec_enable_chroot_unix;
14975 +int grsec_enable_tpe;
14976 +int grsec_tpe_gid;
14977 +int grsec_enable_tpe_all;
14978 +int grsec_enable_randpid;
14979 +int grsec_enable_socket_all;
14980 +int grsec_socket_all_gid;
14981 +int grsec_enable_socket_client;
14982 +int grsec_socket_client_gid;
14983 +int grsec_enable_socket_server;
14984 +int grsec_socket_server_gid;
14987 +spinlock_t grsec_alert_lock = SPIN_LOCK_UNLOCKED;
14988 +unsigned long grsec_alert_wtime = 0;
14989 +unsigned long grsec_alert_fyet = 0;
14991 +spinlock_t grsec_audit_lock = SPIN_LOCK_UNLOCKED;
14993 +rwlock_t grsec_exec_file_lock = RW_LOCK_UNLOCKED;
14995 +char *gr_shared_page[4];
14997 +char *gr_alert_log_fmt;
14998 +char *gr_audit_log_fmt;
14999 +char *gr_alert_log_buf;
15000 +char *gr_audit_log_buf;
15002 +extern struct gr_arg *gr_usermode;
15003 +extern unsigned char *gr_system_salt;
15004 +extern unsigned char *gr_system_sum;
15007 +grsecurity_init(void)
15010 + /* create the per-cpu shared pages */
15012 + preempt_disable();
15013 + for (j = 0; j < 4; j++) {
15014 + gr_shared_page[j] = (char *)__alloc_percpu(PAGE_SIZE);
15015 + if (gr_shared_page[j] == NULL) {
15016 + panic("Unable to allocate grsecurity shared page");
15020 + preempt_enable();
15022 + /* allocate log buffers */
15023 + gr_alert_log_fmt = kmalloc(512, GFP_KERNEL);
15024 + if (!gr_alert_log_fmt) {
15025 + panic("Unable to allocate grsecurity alert log format buffer");
15028 + gr_audit_log_fmt = kmalloc(512, GFP_KERNEL);
15029 + if (!gr_audit_log_fmt) {
15030 + panic("Unable to allocate grsecurity audit log format buffer");
15033 + gr_alert_log_buf = (char *) get_zeroed_page(GFP_KERNEL);
15034 + if (!gr_alert_log_buf) {
15035 + panic("Unable to allocate grsecurity alert log buffer");
15038 + gr_audit_log_buf = (char *) get_zeroed_page(GFP_KERNEL);
15039 + if (!gr_audit_log_buf) {
15040 + panic("Unable to allocate grsecurity audit log buffer");
15044 + /* allocate memory for authentication structure */
15045 + gr_usermode = kmalloc(sizeof(struct gr_arg), GFP_KERNEL);
15046 + gr_system_salt = kmalloc(GR_SALT_LEN, GFP_KERNEL);
15047 + gr_system_sum = kmalloc(GR_SHA_LEN, GFP_KERNEL);
15049 + if (!gr_usermode || !gr_system_salt || !gr_system_sum) {
15050 + panic("Unable to allocate grsecurity authentication structure");
15054 +#if !defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_SYSCTL_ON)
15055 +#ifndef CONFIG_GRKERNSEC_SYSCTL
15058 +#ifdef CONFIG_GRKERNSEC_SHM
15059 + grsec_enable_shm = 1;
15061 +#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
15062 + grsec_enable_audit_textrel = 1;
15064 +#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
15065 + grsec_enable_group = 1;
15066 + grsec_audit_gid = CONFIG_GRKERNSEC_AUDIT_GID;
15068 +#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
15069 + grsec_enable_chdir = 1;
15071 +#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15072 + grsec_enable_audit_ipc = 1;
15074 +#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
15075 + grsec_enable_mount = 1;
15077 +#ifdef CONFIG_GRKERNSEC_LINK
15078 + grsec_enable_link = 1;
15080 +#ifdef CONFIG_GRKERNSEC_DMESG
15081 + grsec_enable_dmesg = 1;
15083 +#ifdef CONFIG_GRKERNSEC_FIFO
15084 + grsec_enable_fifo = 1;
15086 +#ifdef CONFIG_GRKERNSEC_EXECVE
15087 + grsec_enable_execve = 1;
15089 +#ifdef CONFIG_GRKERNSEC_EXECLOG
15090 + grsec_enable_execlog = 1;
15092 +#ifdef CONFIG_GRKERNSEC_SIGNAL
15093 + grsec_enable_signal = 1;
15095 +#ifdef CONFIG_GRKERNSEC_FORKFAIL
15096 + grsec_enable_forkfail = 1;
15098 +#ifdef CONFIG_GRKERNSEC_TIME
15099 + grsec_enable_time = 1;
15101 +#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
15102 + grsec_enable_chroot_findtask = 1;
15104 +#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
15105 + grsec_enable_chroot_unix = 1;
15107 +#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
15108 + grsec_enable_chroot_mount = 1;
15110 +#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
15111 + grsec_enable_chroot_fchdir = 1;
15113 +#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
15114 + grsec_enable_chroot_shmat = 1;
15116 +#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
15117 + grsec_enable_chroot_double = 1;
15119 +#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
15120 + grsec_enable_chroot_pivot = 1;
15122 +#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
15123 + grsec_enable_chroot_chdir = 1;
15125 +#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
15126 + grsec_enable_chroot_chmod = 1;
15128 +#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
15129 + grsec_enable_chroot_mknod = 1;
15131 +#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
15132 + grsec_enable_chroot_nice = 1;
15134 +#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
15135 + grsec_enable_chroot_execlog = 1;
15137 +#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
15138 + grsec_enable_chroot_caps = 1;
15140 +#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
15141 + grsec_enable_chroot_sysctl = 1;
15143 +#ifdef CONFIG_GRKERNSEC_TPE
15144 + grsec_enable_tpe = 1;
15145 + grsec_tpe_gid = CONFIG_GRKERNSEC_TPE_GID;
15146 +#ifdef CONFIG_GRKERNSEC_TPE_ALL
15147 + grsec_enable_tpe_all = 1;
15150 +#ifdef CONFIG_GRKERNSEC_RANDPID
15151 + grsec_enable_randpid = 1;
15153 +#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
15154 + grsec_enable_socket_all = 1;
15155 + grsec_socket_all_gid = CONFIG_GRKERNSEC_SOCKET_ALL_GID;
15157 +#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
15158 + grsec_enable_socket_client = 1;
15159 + grsec_socket_client_gid = CONFIG_GRKERNSEC_SOCKET_CLIENT_GID;
15161 +#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
15162 + grsec_enable_socket_server = 1;
15163 + grsec_socket_server_gid = CONFIG_GRKERNSEC_SOCKET_SERVER_GID;
15169 diff -urNp linux-2.6.16.12/grsecurity/grsec_ipc.c linux-2.6.16.12/grsecurity/grsec_ipc.c
15170 --- linux-2.6.16.12/grsecurity/grsec_ipc.c 1969-12-31 19:00:00.000000000 -0500
15171 +++ linux-2.6.16.12/grsecurity/grsec_ipc.c 2006-05-01 20:17:34.000000000 -0400
15173 +#include <linux/kernel.h>
15174 +#include <linux/sched.h>
15175 +#include <linux/types.h>
15176 +#include <linux/ipc.h>
15177 +#include <linux/grsecurity.h>
15178 +#include <linux/grinternal.h>
15181 +gr_log_msgget(const int ret, const int msgflg)
15183 +#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15184 + if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15185 + grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
15186 + !grsec_enable_group)) && (ret >= 0)
15187 + && (msgflg & IPC_CREAT))
15188 + gr_log_noargs(GR_DO_AUDIT, GR_MSGQ_AUDIT_MSG);
15194 +gr_log_msgrm(const uid_t uid, const uid_t cuid)
15196 +#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15197 + if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15198 + grsec_enable_audit_ipc) ||
15199 + (grsec_enable_audit_ipc && !grsec_enable_group))
15200 + gr_log_int_int(GR_DO_AUDIT, GR_MSGQR_AUDIT_MSG, uid, cuid);
15206 +gr_log_semget(const int err, const int semflg)
15208 +#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15209 + if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15210 + grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
15211 + !grsec_enable_group)) && (err >= 0)
15212 + && (semflg & IPC_CREAT))
15213 + gr_log_noargs(GR_DO_AUDIT, GR_SEM_AUDIT_MSG);
15219 +gr_log_semrm(const uid_t uid, const uid_t cuid)
15221 +#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15222 + if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15223 + grsec_enable_audit_ipc) ||
15224 + (grsec_enable_audit_ipc && !grsec_enable_group))
15225 + gr_log_int_int(GR_DO_AUDIT, GR_SEMR_AUDIT_MSG, uid, cuid);
15231 +gr_log_shmget(const int err, const int shmflg, const size_t size)
15233 +#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15234 + if (((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15235 + grsec_enable_audit_ipc) || (grsec_enable_audit_ipc &&
15236 + !grsec_enable_group)) && (err >= 0)
15237 + && (shmflg & IPC_CREAT))
15238 + gr_log_int(GR_DO_AUDIT, GR_SHM_AUDIT_MSG, size);
15244 +gr_log_shmrm(const uid_t uid, const uid_t cuid)
15246 +#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
15247 + if ((grsec_enable_group && in_group_p(grsec_audit_gid) &&
15248 + grsec_enable_audit_ipc) ||
15249 + (grsec_enable_audit_ipc && !grsec_enable_group))
15250 + gr_log_int_int(GR_DO_AUDIT, GR_SHMR_AUDIT_MSG, uid, cuid);
15254 diff -urNp linux-2.6.16.12/grsecurity/grsec_link.c linux-2.6.16.12/grsecurity/grsec_link.c
15255 --- linux-2.6.16.12/grsecurity/grsec_link.c 1969-12-31 19:00:00.000000000 -0500
15256 +++ linux-2.6.16.12/grsecurity/grsec_link.c 2006-05-01 20:17:34.000000000 -0400
15258 +#include <linux/kernel.h>
15259 +#include <linux/sched.h>
15260 +#include <linux/fs.h>
15261 +#include <linux/file.h>
15262 +#include <linux/grinternal.h>
15265 +gr_handle_follow_link(const struct inode *parent,
15266 + const struct inode *inode,
15267 + const struct dentry *dentry, const struct vfsmount *mnt)
15269 +#ifdef CONFIG_GRKERNSEC_LINK
15270 + if (grsec_enable_link && S_ISLNK(inode->i_mode) &&
15271 + (parent->i_mode & S_ISVTX) && (parent->i_uid != inode->i_uid) &&
15272 + (parent->i_mode & S_IWOTH) && (current->fsuid != inode->i_uid)) {
15273 + gr_log_fs_int2(GR_DONT_AUDIT, GR_SYMLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid);
15281 +gr_handle_hardlink(const struct dentry *dentry,
15282 + const struct vfsmount *mnt,
15283 + struct inode *inode, const int mode, const char *to)
15285 +#ifdef CONFIG_GRKERNSEC_LINK
15286 + if (grsec_enable_link && current->fsuid != inode->i_uid &&
15287 + (!S_ISREG(mode) || (mode & S_ISUID) ||
15288 + ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) ||
15289 + (generic_permission(inode, MAY_READ | MAY_WRITE, NULL))) &&
15290 + !capable(CAP_FOWNER) && current->uid) {
15291 + gr_log_fs_int2_str(GR_DONT_AUDIT, GR_HARDLINK_MSG, dentry, mnt, inode->i_uid, inode->i_gid, to);
15297 diff -urNp linux-2.6.16.12/grsecurity/grsec_log.c linux-2.6.16.12/grsecurity/grsec_log.c
15298 --- linux-2.6.16.12/grsecurity/grsec_log.c 1969-12-31 19:00:00.000000000 -0500
15299 +++ linux-2.6.16.12/grsecurity/grsec_log.c 2006-05-01 20:17:34.000000000 -0400
15301 +#include <linux/kernel.h>
15302 +#include <linux/sched.h>
15303 +#include <linux/file.h>
15304 +#include <linux/tty.h>
15305 +#include <linux/fs.h>
15306 +#include <linux/grinternal.h>
15308 +#define BEGIN_LOCKS(x) \
15309 + read_lock(&tasklist_lock); \
15310 + read_lock(&grsec_exec_file_lock); \
15311 + if (x != GR_DO_AUDIT) \
15312 + spin_lock(&grsec_alert_lock); \
15314 + spin_lock(&grsec_audit_lock)
15316 +#define END_LOCKS(x) \
15317 + if (x != GR_DO_AUDIT) \
15318 + spin_unlock(&grsec_alert_lock); \
15320 + spin_unlock(&grsec_audit_lock); \
15321 + read_unlock(&grsec_exec_file_lock); \
15322 + read_unlock(&tasklist_lock); \
15323 + if (x == GR_DONT_AUDIT) \
15324 + gr_handle_alertkill(current)
15331 +extern char *gr_alert_log_fmt;
15332 +extern char *gr_audit_log_fmt;
15333 +extern char *gr_alert_log_buf;
15334 +extern char *gr_audit_log_buf;
15336 +static int gr_log_start(int audit)
15338 + char *loglevel = (audit == GR_DO_AUDIT) ? KERN_INFO : KERN_ALERT;
15339 + char *fmt = (audit == GR_DO_AUDIT) ? gr_audit_log_fmt : gr_alert_log_fmt;
15340 + char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
15342 + if (audit == GR_DO_AUDIT)
15345 + if (!grsec_alert_wtime || jiffies - grsec_alert_wtime > CONFIG_GRKERNSEC_FLOODTIME * HZ) {
15346 + grsec_alert_wtime = jiffies;
15347 + grsec_alert_fyet = 0;
15348 + } else if ((jiffies - grsec_alert_wtime < CONFIG_GRKERNSEC_FLOODTIME * HZ) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) {
15349 + grsec_alert_fyet++;
15350 + } else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) {
15351 + grsec_alert_wtime = jiffies;
15352 + grsec_alert_fyet++;
15353 + printk(KERN_ALERT "grsec: more alerts, logging disabled for %d seconds\n", CONFIG_GRKERNSEC_FLOODTIME);
15355 + } else return FLOODING;
15358 + memset(buf, 0, PAGE_SIZE);
15359 + if (current->signal->curr_ip && gr_acl_is_enabled()) {
15360 + sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: (%.64s:%c:%.950s) ");
15361 + snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip), current->role->rolename, gr_roletype_to_char(), current->acl->filename);
15362 + } else if (current->signal->curr_ip) {
15363 + sprintf(fmt, "%s%s", loglevel, "grsec: From %u.%u.%u.%u: ");
15364 + snprintf(buf, PAGE_SIZE - 1, fmt, NIPQUAD(current->signal->curr_ip));
15365 + } else if (gr_acl_is_enabled()) {
15366 + sprintf(fmt, "%s%s", loglevel, "grsec: (%.64s:%c:%.950s) ");
15367 + snprintf(buf, PAGE_SIZE - 1, fmt, current->role->rolename, gr_roletype_to_char(), current->acl->filename);
15369 + sprintf(fmt, "%s%s", loglevel, "grsec: ");
15370 + strcpy(buf, fmt);
15373 + return NO_FLOODING;
15376 +static void gr_log_middle(int audit, const char *msg, va_list ap)
15378 + char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
15379 + unsigned int len = strlen(buf);
15381 + vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap);
15386 +static void gr_log_middle_varargs(int audit, const char *msg, ...)
15388 + char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
15389 + unsigned int len = strlen(buf);
15392 + va_start(ap, msg);
15393 + vsnprintf(buf + len, PAGE_SIZE - len - 1, msg, ap);
15399 +static void gr_log_end(int audit)
15401 + char *buf = (audit == GR_DO_AUDIT) ? gr_audit_log_buf : gr_alert_log_buf;
15402 + unsigned int len = strlen(buf);
15404 + snprintf(buf + len, PAGE_SIZE - len - 1, DEFAULTSECMSG, DEFAULTSECARGS(current));
15405 + printk("%s\n", buf);
15410 +void gr_log_varargs(int audit, const char *msg, int argtypes, ...)
15413 + char *result = (audit == GR_DO_AUDIT) ? "successful" : "denied";
15414 + char *str1, *str2, *str3;
15416 + unsigned long ulong1, ulong2;
15417 + struct dentry *dentry;
15418 + struct vfsmount *mnt;
15419 + struct file *file;
15420 + struct task_struct *task;
15423 + BEGIN_LOCKS(audit);
15424 + logtype = gr_log_start(audit);
15425 + if (logtype == FLOODING) {
15426 + END_LOCKS(audit);
15429 + va_start(ap, argtypes);
15430 + switch (argtypes) {
15431 + case GR_TTYSNIFF:
15432 + task = va_arg(ap, struct task_struct *);
15433 + 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);
15436 + dentry = va_arg(ap, struct dentry *);
15437 + mnt = va_arg(ap, struct vfsmount *);
15438 + gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt));
15440 + case GR_RBAC_STR:
15441 + dentry = va_arg(ap, struct dentry *);
15442 + mnt = va_arg(ap, struct vfsmount *);
15443 + str1 = va_arg(ap, char *);
15444 + gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1);
15446 + case GR_STR_RBAC:
15447 + str1 = va_arg(ap, char *);
15448 + dentry = va_arg(ap, struct dentry *);
15449 + mnt = va_arg(ap, struct vfsmount *);
15450 + gr_log_middle_varargs(audit, msg, result, str1, gr_to_filename(dentry, mnt));
15452 + case GR_RBAC_MODE2:
15453 + dentry = va_arg(ap, struct dentry *);
15454 + mnt = va_arg(ap, struct vfsmount *);
15455 + str1 = va_arg(ap, char *);
15456 + str2 = va_arg(ap, char *);
15457 + gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2);
15459 + case GR_RBAC_MODE3:
15460 + dentry = va_arg(ap, struct dentry *);
15461 + mnt = va_arg(ap, struct vfsmount *);
15462 + str1 = va_arg(ap, char *);
15463 + str2 = va_arg(ap, char *);
15464 + str3 = va_arg(ap, char *);
15465 + gr_log_middle_varargs(audit, msg, result, gr_to_filename(dentry, mnt), str1, str2, str3);
15467 + case GR_FILENAME:
15468 + dentry = va_arg(ap, struct dentry *);
15469 + mnt = va_arg(ap, struct vfsmount *);
15470 + gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt));
15472 + case GR_STR_FILENAME:
15473 + str1 = va_arg(ap, char *);
15474 + dentry = va_arg(ap, struct dentry *);
15475 + mnt = va_arg(ap, struct vfsmount *);
15476 + gr_log_middle_varargs(audit, msg, str1, gr_to_filename(dentry, mnt));
15478 + case GR_FILENAME_STR:
15479 + dentry = va_arg(ap, struct dentry *);
15480 + mnt = va_arg(ap, struct vfsmount *);
15481 + str1 = va_arg(ap, char *);
15482 + gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), str1);
15484 + case GR_FILENAME_TWO_INT:
15485 + dentry = va_arg(ap, struct dentry *);
15486 + mnt = va_arg(ap, struct vfsmount *);
15487 + num1 = va_arg(ap, int);
15488 + num2 = va_arg(ap, int);
15489 + gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2);
15491 + case GR_FILENAME_TWO_INT_STR:
15492 + dentry = va_arg(ap, struct dentry *);
15493 + mnt = va_arg(ap, struct vfsmount *);
15494 + num1 = va_arg(ap, int);
15495 + num2 = va_arg(ap, int);
15496 + str1 = va_arg(ap, char *);
15497 + gr_log_middle_varargs(audit, msg, gr_to_filename(dentry, mnt), num1, num2, str1);
15500 + file = va_arg(ap, struct file *);
15501 + ulong1 = va_arg(ap, unsigned long);
15502 + ulong2 = va_arg(ap, unsigned long);
15503 + gr_log_middle_varargs(audit, msg, file ? gr_to_filename(file->f_dentry, file->f_vfsmnt) : "<anonymous mapping>", ulong1, ulong2);
15506 + task = va_arg(ap, struct task_struct *);
15507 + 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);
15509 + case GR_RESOURCE:
15510 + task = va_arg(ap, struct task_struct *);
15511 + ulong1 = va_arg(ap, unsigned long);
15512 + str1 = va_arg(ap, char *);
15513 + ulong2 = va_arg(ap, unsigned long);
15514 + 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);
15517 + task = va_arg(ap, struct task_struct *);
15518 + str1 = va_arg(ap, char *);
15519 + 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);
15522 + task = va_arg(ap, struct task_struct *);
15523 + num1 = va_arg(ap, int);
15524 + 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);
15527 + task = va_arg(ap, struct task_struct *);
15528 + ulong1 = va_arg(ap, unsigned long);
15529 + 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);
15532 + task = va_arg(ap, struct task_struct *);
15533 + ulong1 = va_arg(ap, unsigned long);
15534 + 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);
15538 + unsigned int wday, cday;
15542 + char cur_tty[64] = { 0 };
15543 + char parent_tty[64] = { 0 };
15545 + task = va_arg(ap, struct task_struct *);
15546 + wday = va_arg(ap, unsigned int);
15547 + cday = va_arg(ap, unsigned int);
15548 + whr = va_arg(ap, int);
15549 + chr = va_arg(ap, int);
15550 + wmin = va_arg(ap, int);
15551 + cmin = va_arg(ap, int);
15552 + wsec = va_arg(ap, int);
15553 + csec = va_arg(ap, int);
15554 + ulong1 = va_arg(ap, unsigned long);
15556 + 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);
15560 + gr_log_middle(audit, msg, ap);
15563 + gr_log_end(audit);
15564 + END_LOCKS(audit);
15566 diff -urNp linux-2.6.16.12/grsecurity/grsec_mem.c linux-2.6.16.12/grsecurity/grsec_mem.c
15567 --- linux-2.6.16.12/grsecurity/grsec_mem.c 1969-12-31 19:00:00.000000000 -0500
15568 +++ linux-2.6.16.12/grsecurity/grsec_mem.c 2006-05-01 20:17:34.000000000 -0400
15570 +#include <linux/kernel.h>
15571 +#include <linux/sched.h>
15572 +#include <linux/mm.h>
15573 +#include <linux/mman.h>
15574 +#include <linux/grinternal.h>
15577 +gr_handle_ioperm(void)
15579 + gr_log_noargs(GR_DONT_AUDIT, GR_IOPERM_MSG);
15584 +gr_handle_iopl(void)
15586 + gr_log_noargs(GR_DONT_AUDIT, GR_IOPL_MSG);
15591 +gr_handle_mem_write(void)
15593 + gr_log_noargs(GR_DONT_AUDIT, GR_MEM_WRITE_MSG);
15598 +gr_handle_kmem_write(void)
15600 + gr_log_noargs(GR_DONT_AUDIT, GR_KMEM_MSG);
15605 +gr_handle_open_port(void)
15607 + gr_log_noargs(GR_DONT_AUDIT, GR_PORT_OPEN_MSG);
15612 +gr_handle_mem_mmap(const unsigned long offset, struct vm_area_struct *vma)
15614 + unsigned long start, end;
15617 + end = start + vma->vm_end - vma->vm_start;
15619 + if (start > end) {
15620 + gr_log_noargs(GR_DONT_AUDIT, GR_MEM_MMAP_MSG);
15624 + /* allowed ranges : ISA I/O BIOS */
15625 + if ((start >= __pa(high_memory))
15627 + || (start >= 0x000a0000 && end <= 0x00100000)
15628 + || (start >= 0x00000000 && end <= 0x00001000)
15633 + if (vma->vm_flags & VM_WRITE) {
15634 + gr_log_noargs(GR_DONT_AUDIT, GR_MEM_MMAP_MSG);
15637 + vma->vm_flags &= ~VM_MAYWRITE;
15641 diff -urNp linux-2.6.16.12/grsecurity/grsec_mount.c linux-2.6.16.12/grsecurity/grsec_mount.c
15642 --- linux-2.6.16.12/grsecurity/grsec_mount.c 1969-12-31 19:00:00.000000000 -0500
15643 +++ linux-2.6.16.12/grsecurity/grsec_mount.c 2006-05-01 20:17:34.000000000 -0400
15645 +#include <linux/kernel.h>
15646 +#include <linux/sched.h>
15647 +#include <linux/grsecurity.h>
15648 +#include <linux/grinternal.h>
15651 +gr_log_remount(const char *devname, const int retval)
15653 +#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
15654 + if (grsec_enable_mount && (retval >= 0))
15655 + gr_log_str(GR_DO_AUDIT, GR_REMOUNT_AUDIT_MSG, devname ? devname : "none");
15661 +gr_log_unmount(const char *devname, const int retval)
15663 +#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
15664 + if (grsec_enable_mount && (retval >= 0))
15665 + gr_log_str(GR_DO_AUDIT, GR_UNMOUNT_AUDIT_MSG, devname ? devname : "none");
15671 +gr_log_mount(const char *from, const char *to, const int retval)
15673 +#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
15674 + if (grsec_enable_mount && (retval >= 0))
15675 + gr_log_str_str(GR_DO_AUDIT, GR_MOUNT_AUDIT_MSG, from, to);
15679 diff -urNp linux-2.6.16.12/grsecurity/grsec_rand.c linux-2.6.16.12/grsecurity/grsec_rand.c
15680 --- linux-2.6.16.12/grsecurity/grsec_rand.c 1969-12-31 19:00:00.000000000 -0500
15681 +++ linux-2.6.16.12/grsecurity/grsec_rand.c 2006-05-01 20:17:34.000000000 -0400
15683 +#include <linux/kernel.h>
15684 +#include <linux/sched.h>
15685 +#include <linux/smp_lock.h>
15686 +#include <linux/grsecurity.h>
15687 +#include <linux/grinternal.h>
15689 +extern int pid_max;
15692 +gr_random_pid(void)
15694 +#ifdef CONFIG_GRKERNSEC_RANDPID
15697 + if (grsec_enable_randpid && current->fs->root) {
15698 + /* return a pid in the range 1 ... pid_max - 1
15699 + optimize this so we don't have to do a real division
15701 + pid = 1 + (get_random_long() % pid_max);
15702 + if (pid == pid_max)
15703 + pid = pid_max - 1;
15709 diff -urNp linux-2.6.16.12/grsecurity/grsec_sig.c linux-2.6.16.12/grsecurity/grsec_sig.c
15710 --- linux-2.6.16.12/grsecurity/grsec_sig.c 1969-12-31 19:00:00.000000000 -0500
15711 +++ linux-2.6.16.12/grsecurity/grsec_sig.c 2006-05-01 20:17:34.000000000 -0400
15713 +#include <linux/kernel.h>
15714 +#include <linux/sched.h>
15715 +#include <linux/grsecurity.h>
15716 +#include <linux/grinternal.h>
15719 +gr_log_signal(const int sig, const struct task_struct *t)
15721 +#ifdef CONFIG_GRKERNSEC_SIGNAL
15722 + if (grsec_enable_signal && ((sig == SIGSEGV) || (sig == SIGILL) ||
15723 + (sig == SIGABRT) || (sig == SIGBUS))) {
15724 + if (t->pid == current->pid) {
15725 + gr_log_int(GR_DONT_AUDIT_GOOD, GR_UNISIGLOG_MSG, sig);
15727 + gr_log_sig(GR_DONT_AUDIT_GOOD, GR_DUALSIGLOG_MSG, t, sig);
15735 +gr_handle_signal(const struct task_struct *p, const int sig)
15737 +#ifdef CONFIG_GRKERNSEC
15738 + if (current->pid > 1 && gr_check_protected_task(p)) {
15739 + gr_log_sig(GR_DONT_AUDIT, GR_SIG_ACL_MSG, p, sig);
15741 + } else if (gr_pid_is_chrooted((struct task_struct *)p)) {
15748 +void gr_handle_brute_attach(struct task_struct *p)
15750 +#ifdef CONFIG_GRKERNSEC_BRUTE
15751 + read_lock(&tasklist_lock);
15752 + read_lock(&grsec_exec_file_lock);
15753 + if (p->parent && p->parent->exec_file == p->exec_file)
15754 + p->parent->brute = 1;
15755 + read_unlock(&grsec_exec_file_lock);
15756 + read_unlock(&tasklist_lock);
15761 +void gr_handle_brute_check(void)
15763 +#ifdef CONFIG_GRKERNSEC_BRUTE
15764 + if (current->brute) {
15765 + set_current_state(TASK_UNINTERRUPTIBLE);
15766 + schedule_timeout(30 * HZ);
15772 diff -urNp linux-2.6.16.12/grsecurity/grsec_sock.c linux-2.6.16.12/grsecurity/grsec_sock.c
15773 --- linux-2.6.16.12/grsecurity/grsec_sock.c 1969-12-31 19:00:00.000000000 -0500
15774 +++ linux-2.6.16.12/grsecurity/grsec_sock.c 2006-05-01 20:17:34.000000000 -0400
15776 +#include <linux/kernel.h>
15777 +#include <linux/module.h>
15778 +#include <linux/sched.h>
15779 +#include <linux/file.h>
15780 +#include <linux/net.h>
15781 +#include <linux/in.h>
15782 +#include <linux/ip.h>
15783 +#include <net/sock.h>
15784 +#include <net/inet_sock.h>
15785 +#include <linux/grsecurity.h>
15786 +#include <linux/grinternal.h>
15787 +#include <linux/gracl.h>
15789 +#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE)
15790 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
15791 +EXPORT_SYMBOL(udp_v4_lookup);
15794 +EXPORT_SYMBOL(gr_cap_rtnetlink);
15796 +extern int gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb);
15797 +extern int gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr);
15799 +EXPORT_SYMBOL(gr_search_udp_recvmsg);
15800 +EXPORT_SYMBOL(gr_search_udp_sendmsg);
15802 +#ifdef CONFIG_UNIX_MODULE
15803 +EXPORT_SYMBOL(gr_acl_handle_unix);
15804 +EXPORT_SYMBOL(gr_acl_handle_mknod);
15805 +EXPORT_SYMBOL(gr_handle_chroot_unix);
15806 +EXPORT_SYMBOL(gr_handle_create);
15809 +#ifdef CONFIG_GRKERNSEC
15810 +#define gr_conn_table_size 32749
15811 +struct conn_table_entry {
15812 + struct conn_table_entry *next;
15813 + struct signal_struct *sig;
15816 +struct conn_table_entry *gr_conn_table[gr_conn_table_size];
15817 +spinlock_t gr_conn_table_lock = SPIN_LOCK_UNLOCKED;
15819 +extern const char * gr_socktype_to_name(unsigned char type);
15820 +extern const char * gr_proto_to_name(unsigned char proto);
15822 +static __inline__ int
15823 +conn_hash(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, unsigned int size)
15825 + return ((daddr + saddr + (sport << 8) + (dport << 16)) % size);
15828 +static __inline__ int
15829 +conn_match(const struct signal_struct *sig, __u32 saddr, __u32 daddr,
15830 + __u16 sport, __u16 dport)
15832 + if (unlikely(sig->gr_saddr == saddr && sig->gr_daddr == daddr &&
15833 + sig->gr_sport == sport && sig->gr_dport == dport))
15839 +static void gr_add_to_task_ip_table_nolock(struct signal_struct *sig, struct conn_table_entry *newent)
15841 + struct conn_table_entry **match;
15842 + unsigned int index;
15844 + index = conn_hash(sig->gr_saddr, sig->gr_daddr,
15845 + sig->gr_sport, sig->gr_dport,
15846 + gr_conn_table_size);
15848 + newent->sig = sig;
15850 + match = &gr_conn_table[index];
15851 + newent->next = *match;
15857 +static void gr_del_task_from_ip_table_nolock(struct signal_struct *sig)
15859 + struct conn_table_entry *match, *last = NULL;
15860 + unsigned int index;
15862 + index = conn_hash(sig->gr_saddr, sig->gr_daddr,
15863 + sig->gr_sport, sig->gr_dport,
15864 + gr_conn_table_size);
15866 + match = gr_conn_table[index];
15867 + while (match && !conn_match(match->sig,
15868 + sig->gr_saddr, sig->gr_daddr, sig->gr_sport,
15869 + sig->gr_dport)) {
15871 + match = match->next;
15876 + last->next = match->next;
15878 + gr_conn_table[index] = NULL;
15885 +static struct signal_struct * gr_lookup_task_ip_table(__u32 saddr, __u32 daddr,
15886 + __u16 sport, __u16 dport)
15888 + struct conn_table_entry *match;
15889 + unsigned int index;
15891 + index = conn_hash(saddr, daddr, sport, dport, gr_conn_table_size);
15893 + match = gr_conn_table[index];
15894 + while (match && !conn_match(match->sig, saddr, daddr, sport, dport))
15895 + match = match->next;
15898 + return match->sig;
15905 +void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet)
15907 +#ifdef CONFIG_GRKERNSEC
15908 + struct signal_struct *sig = task->signal;
15909 + struct conn_table_entry *newent;
15911 + newent = kmalloc(sizeof(struct conn_table_entry), GFP_ATOMIC);
15912 + if (newent == NULL)
15914 + /* no bh lock needed since we are called with bh disabled */
15915 + spin_lock(&gr_conn_table_lock);
15916 + gr_del_task_from_ip_table_nolock(sig);
15917 + sig->gr_saddr = inet->rcv_saddr;
15918 + sig->gr_daddr = inet->daddr;
15919 + sig->gr_sport = inet->sport;
15920 + sig->gr_dport = inet->dport;
15921 + gr_add_to_task_ip_table_nolock(sig, newent);
15922 + spin_unlock(&gr_conn_table_lock);
15927 +void gr_del_task_from_ip_table(struct task_struct *task)
15929 +#ifdef CONFIG_GRKERNSEC
15930 + spin_lock_bh(&gr_conn_table_lock);
15931 + gr_del_task_from_ip_table_nolock(task->signal);
15932 + spin_unlock_bh(&gr_conn_table_lock);
15938 +gr_attach_curr_ip(const struct sock *sk)
15940 +#ifdef CONFIG_GRKERNSEC
15941 + struct signal_struct *p, *set;
15942 + const struct inet_sock *inet = inet_sk(sk);
15944 + if (unlikely(sk->sk_protocol != IPPROTO_TCP))
15947 + set = current->signal;
15949 + spin_lock_bh(&gr_conn_table_lock);
15950 + p = gr_lookup_task_ip_table(inet->daddr, inet->rcv_saddr,
15951 + inet->dport, inet->sport);
15952 + if (unlikely(p != NULL)) {
15953 + set->curr_ip = p->curr_ip;
15954 + set->used_accept = 1;
15955 + gr_del_task_from_ip_table_nolock(p);
15956 + spin_unlock_bh(&gr_conn_table_lock);
15959 + spin_unlock_bh(&gr_conn_table_lock);
15961 + set->curr_ip = inet->daddr;
15962 + set->used_accept = 1;
15968 +gr_handle_sock_all(const int family, const int type, const int protocol)
15970 +#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
15971 + if (grsec_enable_socket_all && in_group_p(grsec_socket_all_gid) &&
15972 + (family != AF_UNIX) && (family != AF_LOCAL)) {
15973 + gr_log_int_str2(GR_DONT_AUDIT, GR_SOCK2_MSG, family, gr_socktype_to_name(type), gr_proto_to_name(protocol));
15981 +gr_handle_sock_server(const struct sockaddr *sck)
15983 +#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
15984 + if (grsec_enable_socket_server &&
15985 + in_group_p(grsec_socket_server_gid) &&
15986 + sck && (sck->sa_family != AF_UNIX) &&
15987 + (sck->sa_family != AF_LOCAL)) {
15988 + gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
15996 +gr_handle_sock_server_other(const struct sock *sck)
15998 +#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
15999 + if (grsec_enable_socket_server &&
16000 + in_group_p(grsec_socket_server_gid) &&
16001 + sck && (sck->sk_family != AF_UNIX) &&
16002 + (sck->sk_family != AF_LOCAL)) {
16003 + gr_log_noargs(GR_DONT_AUDIT, GR_BIND_MSG);
16011 +gr_handle_sock_client(const struct sockaddr *sck)
16013 +#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
16014 + if (grsec_enable_socket_client && in_group_p(grsec_socket_client_gid) &&
16015 + sck && (sck->sa_family != AF_UNIX) &&
16016 + (sck->sa_family != AF_LOCAL)) {
16017 + gr_log_noargs(GR_DONT_AUDIT, GR_CONNECT_MSG);
16025 +gr_cap_rtnetlink(void)
16027 +#ifdef CONFIG_GRKERNSEC
16028 + if (!gr_acl_is_enabled())
16029 + return current->cap_effective;
16030 + else if (cap_raised(current->cap_effective, CAP_NET_ADMIN) &&
16031 + gr_task_is_capable(current, CAP_NET_ADMIN))
16032 + return current->cap_effective;
16036 + return current->cap_effective;
16039 diff -urNp linux-2.6.16.12/grsecurity/grsec_sysctl.c linux-2.6.16.12/grsecurity/grsec_sysctl.c
16040 --- linux-2.6.16.12/grsecurity/grsec_sysctl.c 1969-12-31 19:00:00.000000000 -0500
16041 +++ linux-2.6.16.12/grsecurity/grsec_sysctl.c 2006-05-01 20:17:34.000000000 -0400
16043 +#include <linux/kernel.h>
16044 +#include <linux/sched.h>
16045 +#include <linux/sysctl.h>
16046 +#include <linux/grsecurity.h>
16047 +#include <linux/grinternal.h>
16049 +#ifdef CONFIG_GRKERNSEC_MODSTOP
16050 +int grsec_modstop;
16054 +gr_handle_sysctl_mod(const char *dirname, const char *name, const int op)
16056 +#ifdef CONFIG_GRKERNSEC_SYSCTL
16057 + if (!strcmp(dirname, "grsecurity") && grsec_lock && (op & 002)) {
16058 + gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name);
16062 +#ifdef CONFIG_GRKERNSEC_MODSTOP
16063 + if (!strcmp(dirname, "grsecurity") && !strcmp(name, "disable_modules") &&
16064 + grsec_modstop && (op & 002)) {
16065 + gr_log_str(GR_DONT_AUDIT, GR_SYSCTL_MSG, name);
16072 +#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP)
16073 +enum {GS_LINK=1, GS_FIFO, GS_EXECVE, GS_EXECLOG, GS_SIGNAL,
16074 +GS_FORKFAIL, GS_TIME, GS_CHROOT_SHMAT, GS_CHROOT_UNIX, GS_CHROOT_MNT,
16075 +GS_CHROOT_FCHDIR, GS_CHROOT_DBL, GS_CHROOT_PVT, GS_CHROOT_CD, GS_CHROOT_CM,
16076 +GS_CHROOT_MK, GS_CHROOT_NI, GS_CHROOT_EXECLOG, GS_CHROOT_CAPS,
16077 +GS_CHROOT_SYSCTL, GS_TPE, GS_TPE_GID, GS_TPE_ALL, GS_SIDCAPS,
16078 +GS_RANDPID, GS_SOCKET_ALL, GS_SOCKET_ALL_GID, GS_SOCKET_CLIENT,
16079 +GS_SOCKET_CLIENT_GID, GS_SOCKET_SERVER, GS_SOCKET_SERVER_GID,
16080 +GS_GROUP, GS_GID, GS_ACHDIR, GS_AMOUNT, GS_AIPC, GS_DMSG,
16081 +GS_TEXTREL, GS_FINDTASK, GS_SHM, GS_LOCK, GS_MODSTOP};
16084 +ctl_table grsecurity_table[] = {
16085 +#ifdef CONFIG_GRKERNSEC_SYSCTL
16086 +#ifdef CONFIG_GRKERNSEC_LINK
16088 + .ctl_name = GS_LINK,
16089 + .procname = "linking_restrictions",
16090 + .data = &grsec_enable_link,
16091 + .maxlen = sizeof(int),
16093 + .proc_handler = &proc_dointvec,
16096 +#ifdef CONFIG_GRKERNSEC_FIFO
16098 + .ctl_name = GS_FIFO,
16099 + .procname = "fifo_restrictions",
16100 + .data = &grsec_enable_fifo,
16101 + .maxlen = sizeof(int),
16103 + .proc_handler = &proc_dointvec,
16106 +#ifdef CONFIG_GRKERNSEC_EXECVE
16108 + .ctl_name = GS_EXECVE,
16109 + .procname = "execve_limiting",
16110 + .data = &grsec_enable_execve,
16111 + .maxlen = sizeof(int),
16113 + .proc_handler = &proc_dointvec,
16116 +#ifdef CONFIG_GRKERNSEC_EXECLOG
16118 + .ctl_name = GS_EXECLOG,
16119 + .procname = "exec_logging",
16120 + .data = &grsec_enable_execlog,
16121 + .maxlen = sizeof(int),
16123 + .proc_handler = &proc_dointvec,
16126 +#ifdef CONFIG_GRKERNSEC_SIGNAL
16128 + .ctl_name = GS_SIGNAL,
16129 + .procname = "signal_logging",
16130 + .data = &grsec_enable_signal,
16131 + .maxlen = sizeof(int),
16133 + .proc_handler = &proc_dointvec,
16136 +#ifdef CONFIG_GRKERNSEC_FORKFAIL
16138 + .ctl_name = GS_FORKFAIL,
16139 + .procname = "forkfail_logging",
16140 + .data = &grsec_enable_forkfail,
16141 + .maxlen = sizeof(int),
16143 + .proc_handler = &proc_dointvec,
16146 +#ifdef CONFIG_GRKERNSEC_TIME
16148 + .ctl_name = GS_TIME,
16149 + .procname = "timechange_logging",
16150 + .data = &grsec_enable_time,
16151 + .maxlen = sizeof(int),
16153 + .proc_handler = &proc_dointvec,
16156 +#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT
16158 + .ctl_name = GS_CHROOT_SHMAT,
16159 + .procname = "chroot_deny_shmat",
16160 + .data = &grsec_enable_chroot_shmat,
16161 + .maxlen = sizeof(int),
16163 + .proc_handler = &proc_dointvec,
16166 +#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
16168 + .ctl_name = GS_CHROOT_UNIX,
16169 + .procname = "chroot_deny_unix",
16170 + .data = &grsec_enable_chroot_unix,
16171 + .maxlen = sizeof(int),
16173 + .proc_handler = &proc_dointvec,
16176 +#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT
16178 + .ctl_name = GS_CHROOT_MNT,
16179 + .procname = "chroot_deny_mount",
16180 + .data = &grsec_enable_chroot_mount,
16181 + .maxlen = sizeof(int),
16183 + .proc_handler = &proc_dointvec,
16186 +#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR
16188 + .ctl_name = GS_CHROOT_FCHDIR,
16189 + .procname = "chroot_deny_fchdir",
16190 + .data = &grsec_enable_chroot_fchdir,
16191 + .maxlen = sizeof(int),
16193 + .proc_handler = &proc_dointvec,
16196 +#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE
16198 + .ctl_name = GS_CHROOT_DBL,
16199 + .procname = "chroot_deny_chroot",
16200 + .data = &grsec_enable_chroot_double,
16201 + .maxlen = sizeof(int),
16203 + .proc_handler = &proc_dointvec,
16206 +#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT
16208 + .ctl_name = GS_CHROOT_PVT,
16209 + .procname = "chroot_deny_pivot",
16210 + .data = &grsec_enable_chroot_pivot,
16211 + .maxlen = sizeof(int),
16213 + .proc_handler = &proc_dointvec,
16216 +#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR
16218 + .ctl_name = GS_CHROOT_CD,
16219 + .procname = "chroot_enforce_chdir",
16220 + .data = &grsec_enable_chroot_chdir,
16221 + .maxlen = sizeof(int),
16223 + .proc_handler = &proc_dointvec,
16226 +#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD
16228 + .ctl_name = GS_CHROOT_CM,
16229 + .procname = "chroot_deny_chmod",
16230 + .data = &grsec_enable_chroot_chmod,
16231 + .maxlen = sizeof(int),
16233 + .proc_handler = &proc_dointvec,
16236 +#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD
16238 + .ctl_name = GS_CHROOT_MK,
16239 + .procname = "chroot_deny_mknod",
16240 + .data = &grsec_enable_chroot_mknod,
16241 + .maxlen = sizeof(int),
16243 + .proc_handler = &proc_dointvec,
16246 +#ifdef CONFIG_GRKERNSEC_CHROOT_NICE
16248 + .ctl_name = GS_CHROOT_NI,
16249 + .procname = "chroot_restrict_nice",
16250 + .data = &grsec_enable_chroot_nice,
16251 + .maxlen = sizeof(int),
16253 + .proc_handler = &proc_dointvec,
16256 +#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG
16258 + .ctl_name = GS_CHROOT_EXECLOG,
16259 + .procname = "chroot_execlog",
16260 + .data = &grsec_enable_chroot_execlog,
16261 + .maxlen = sizeof(int),
16263 + .proc_handler = &proc_dointvec,
16266 +#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS
16268 + .ctl_name = GS_CHROOT_CAPS,
16269 + .procname = "chroot_caps",
16270 + .data = &grsec_enable_chroot_caps,
16271 + .maxlen = sizeof(int),
16273 + .proc_handler = &proc_dointvec,
16276 +#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL
16278 + .ctl_name = GS_CHROOT_SYSCTL,
16279 + .procname = "chroot_deny_sysctl",
16280 + .data = &grsec_enable_chroot_sysctl,
16281 + .maxlen = sizeof(int),
16283 + .proc_handler = &proc_dointvec,
16286 +#ifdef CONFIG_GRKERNSEC_TPE
16288 + .ctl_name = GS_TPE,
16289 + .procname = "tpe",
16290 + .data = &grsec_enable_tpe,
16291 + .maxlen = sizeof(int),
16293 + .proc_handler = &proc_dointvec,
16296 + .ctl_name = GS_TPE_GID,
16297 + .procname = "tpe_gid",
16298 + .data = &grsec_tpe_gid,
16299 + .maxlen = sizeof(int),
16301 + .proc_handler = &proc_dointvec,
16304 +#ifdef CONFIG_GRKERNSEC_TPE_ALL
16306 + .ctl_name = GS_TPE_ALL,
16307 + .procname = "tpe_restrict_all",
16308 + .data = &grsec_enable_tpe_all,
16309 + .maxlen = sizeof(int),
16311 + .proc_handler = &proc_dointvec,
16314 +#ifdef CONFIG_GRKERNSEC_RANDPID
16316 + .ctl_name = GS_RANDPID,
16317 + .procname = "rand_pids",
16318 + .data = &grsec_enable_randpid,
16319 + .maxlen = sizeof(int),
16321 + .proc_handler = &proc_dointvec,
16324 +#ifdef CONFIG_GRKERNSEC_SOCKET_ALL
16326 + .ctl_name = GS_SOCKET_ALL,
16327 + .procname = "socket_all",
16328 + .data = &grsec_enable_socket_all,
16329 + .maxlen = sizeof(int),
16331 + .proc_handler = &proc_dointvec,
16334 + .ctl_name = GS_SOCKET_ALL_GID,
16335 + .procname = "socket_all_gid",
16336 + .data = &grsec_socket_all_gid,
16337 + .maxlen = sizeof(int),
16339 + .proc_handler = &proc_dointvec,
16342 +#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT
16344 + .ctl_name = GS_SOCKET_CLIENT,
16345 + .procname = "socket_client",
16346 + .data = &grsec_enable_socket_client,
16347 + .maxlen = sizeof(int),
16349 + .proc_handler = &proc_dointvec,
16352 + .ctl_name = GS_SOCKET_CLIENT_GID,
16353 + .procname = "socket_client_gid",
16354 + .data = &grsec_socket_client_gid,
16355 + .maxlen = sizeof(int),
16357 + .proc_handler = &proc_dointvec,
16360 +#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER
16362 + .ctl_name = GS_SOCKET_SERVER,
16363 + .procname = "socket_server",
16364 + .data = &grsec_enable_socket_server,
16365 + .maxlen = sizeof(int),
16367 + .proc_handler = &proc_dointvec,
16370 + .ctl_name = GS_SOCKET_SERVER_GID,
16371 + .procname = "socket_server_gid",
16372 + .data = &grsec_socket_server_gid,
16373 + .maxlen = sizeof(int),
16375 + .proc_handler = &proc_dointvec,
16378 +#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP
16380 + .ctl_name = GS_GROUP,
16381 + .procname = "audit_group",
16382 + .data = &grsec_enable_group,
16383 + .maxlen = sizeof(int),
16385 + .proc_handler = &proc_dointvec,
16388 + .ctl_name = GS_GID,
16389 + .procname = "audit_gid",
16390 + .data = &grsec_audit_gid,
16391 + .maxlen = sizeof(int),
16393 + .proc_handler = &proc_dointvec,
16396 +#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR
16398 + .ctl_name = GS_ACHDIR,
16399 + .procname = "audit_chdir",
16400 + .data = &grsec_enable_chdir,
16401 + .maxlen = sizeof(int),
16403 + .proc_handler = &proc_dointvec,
16406 +#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT
16408 + .ctl_name = GS_AMOUNT,
16409 + .procname = "audit_mount",
16410 + .data = &grsec_enable_mount,
16411 + .maxlen = sizeof(int),
16413 + .proc_handler = &proc_dointvec,
16416 +#ifdef CONFIG_GRKERNSEC_AUDIT_IPC
16418 + .ctl_name = GS_AIPC,
16419 + .procname = "audit_ipc",
16420 + .data = &grsec_enable_audit_ipc,
16421 + .maxlen = sizeof(int),
16423 + .proc_handler = &proc_dointvec,
16426 +#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
16428 + .ctl_name = GS_TEXTREL,
16429 + .procname = "audit_textrel",
16430 + .data = &grsec_enable_audit_textrel,
16431 + .maxlen = sizeof(int),
16433 + .proc_handler = &proc_dointvec,
16436 +#ifdef CONFIG_GRKERNSEC_DMESG
16438 + .ctl_name = GS_DMSG,
16439 + .procname = "dmesg",
16440 + .data = &grsec_enable_dmesg,
16441 + .maxlen = sizeof(int),
16443 + .proc_handler = &proc_dointvec,
16446 +#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK
16448 + .ctl_name = GS_FINDTASK,
16449 + .procname = "chroot_findtask",
16450 + .data = &grsec_enable_chroot_findtask,
16451 + .maxlen = sizeof(int),
16453 + .proc_handler = &proc_dointvec,
16456 +#ifdef CONFIG_GRKERNSEC_SHM
16458 + .ctl_name = GS_SHM,
16459 + .procname = "destroy_unused_shm",
16460 + .data = &grsec_enable_shm,
16461 + .maxlen = sizeof(int),
16463 + .proc_handler = &proc_dointvec,
16467 + .ctl_name = GS_LOCK,
16468 + .procname = "grsec_lock",
16469 + .data = &grsec_lock,
16470 + .maxlen = sizeof(int),
16472 + .proc_handler = &proc_dointvec,
16475 +#ifdef CONFIG_GRKERNSEC_MODSTOP
16477 + .ctl_name = GS_MODSTOP,
16478 + .procname = "disable_modules",
16479 + .data = &grsec_modstop,
16480 + .maxlen = sizeof(int),
16482 + .proc_handler = &proc_dointvec,
16485 + { .ctl_name = 0 }
16489 +int gr_check_modstop(void)
16491 +#ifdef CONFIG_GRKERNSEC_MODSTOP
16492 + if (grsec_modstop == 1) {
16493 + gr_log_noargs(GR_DONT_AUDIT, GR_STOPMOD_MSG);
16499 diff -urNp linux-2.6.16.12/grsecurity/grsec_textrel.c linux-2.6.16.12/grsecurity/grsec_textrel.c
16500 --- linux-2.6.16.12/grsecurity/grsec_textrel.c 1969-12-31 19:00:00.000000000 -0500
16501 +++ linux-2.6.16.12/grsecurity/grsec_textrel.c 2006-05-01 20:17:34.000000000 -0400
16503 +#include <linux/kernel.h>
16504 +#include <linux/sched.h>
16505 +#include <linux/mm.h>
16506 +#include <linux/file.h>
16507 +#include <linux/grinternal.h>
16508 +#include <linux/grsecurity.h>
16511 +gr_log_textrel(struct vm_area_struct * vma)
16513 +#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL
16514 + if (grsec_enable_audit_textrel)
16515 + gr_log_textrel_ulong_ulong(GR_DO_AUDIT, GR_TEXTREL_AUDIT_MSG, vma->vm_file, vma->vm_start, vma->vm_pgoff);
16519 diff -urNp linux-2.6.16.12/grsecurity/grsec_time.c linux-2.6.16.12/grsecurity/grsec_time.c
16520 --- linux-2.6.16.12/grsecurity/grsec_time.c 1969-12-31 19:00:00.000000000 -0500
16521 +++ linux-2.6.16.12/grsecurity/grsec_time.c 2006-05-01 20:17:34.000000000 -0400
16523 +#include <linux/kernel.h>
16524 +#include <linux/sched.h>
16525 +#include <linux/grinternal.h>
16528 +gr_log_timechange(void)
16530 +#ifdef CONFIG_GRKERNSEC_TIME
16531 + if (grsec_enable_time)
16532 + gr_log_noargs(GR_DONT_AUDIT_GOOD, GR_TIME_MSG);
16536 diff -urNp linux-2.6.16.12/grsecurity/grsec_tpe.c linux-2.6.16.12/grsecurity/grsec_tpe.c
16537 --- linux-2.6.16.12/grsecurity/grsec_tpe.c 1969-12-31 19:00:00.000000000 -0500
16538 +++ linux-2.6.16.12/grsecurity/grsec_tpe.c 2006-05-01 20:17:34.000000000 -0400
16540 +#include <linux/kernel.h>
16541 +#include <linux/sched.h>
16542 +#include <linux/file.h>
16543 +#include <linux/fs.h>
16544 +#include <linux/grinternal.h>
16546 +extern int gr_acl_tpe_check(void);
16549 +gr_tpe_allow(const struct file *file)
16551 +#ifdef CONFIG_GRKERNSEC
16552 + struct inode *inode = file->f_dentry->d_parent->d_inode;
16554 + if (current->uid && ((grsec_enable_tpe &&
16555 +#ifdef CONFIG_GRKERNSEC_TPE_INVERT
16556 + !in_group_p(grsec_tpe_gid)
16558 + in_group_p(grsec_tpe_gid)
16560 + ) || gr_acl_tpe_check()) &&
16561 + (inode->i_uid || (!inode->i_uid && ((inode->i_mode & S_IWGRP) ||
16562 + (inode->i_mode & S_IWOTH))))) {
16563 + gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_dentry, file->f_vfsmnt);
16566 +#ifdef CONFIG_GRKERNSEC_TPE_ALL
16567 + if (current->uid && grsec_enable_tpe && grsec_enable_tpe_all &&
16568 + ((inode->i_uid && (inode->i_uid != current->uid)) ||
16569 + (inode->i_mode & S_IWGRP) || (inode->i_mode & S_IWOTH))) {
16570 + gr_log_fs_generic(GR_DONT_AUDIT, GR_EXEC_TPE_MSG, file->f_dentry, file->f_vfsmnt);
16577 diff -urNp linux-2.6.16.12/grsecurity/grsum.c linux-2.6.16.12/grsecurity/grsum.c
16578 --- linux-2.6.16.12/grsecurity/grsum.c 1969-12-31 19:00:00.000000000 -0500
16579 +++ linux-2.6.16.12/grsecurity/grsum.c 2006-05-01 20:17:34.000000000 -0400
16581 +#include <linux/kernel.h>
16582 +#include <linux/sched.h>
16583 +#include <linux/mm.h>
16584 +#include <asm/scatterlist.h>
16585 +#include <linux/crypto.h>
16586 +#include <linux/gracl.h>
16589 +#if !defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE) || !defined(CONFIG_CRYPTO_SHA256) || defined(CONFIG_CRYPTO_SHA256_MODULE)
16590 +#error "crypto and sha256 must be built into the kernel"
16594 +chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum)
16597 + struct crypto_tfm *tfm;
16598 + unsigned char temp_sum[GR_SHA_LEN];
16599 + struct scatterlist sg[2];
16600 + volatile int retval = 0;
16601 + volatile int dummy = 0;
16604 + tfm = crypto_alloc_tfm("sha256", 0);
16605 + if (tfm == NULL) {
16606 + /* should never happen, since sha256 should be built in */
16610 + crypto_digest_init(tfm);
16613 + sg[0].page = virt_to_page(p);
16614 + sg[0].offset = ((long) p & ~PAGE_MASK);
16615 + sg[0].length = GR_SALT_LEN;
16617 + crypto_digest_update(tfm, sg, 1);
16620 + sg[0].page = virt_to_page(p);
16621 + sg[0].offset = ((long) p & ~PAGE_MASK);
16622 + sg[0].length = strlen(entry->pw);
16624 + crypto_digest_update(tfm, sg, 1);
16626 + crypto_digest_final(tfm, temp_sum);
16628 + memset(entry->pw, 0, GR_PW_LEN);
16630 + for (i = 0; i < GR_SHA_LEN; i++)
16631 + if (sum[i] != temp_sum[i])
16634 + dummy = 1; // waste a cycle
16636 + crypto_free_tfm(tfm);
16640 diff -urNp linux-2.6.16.12/grsecurity/Kconfig linux-2.6.16.12/grsecurity/Kconfig
16641 --- linux-2.6.16.12/grsecurity/Kconfig 1969-12-31 19:00:00.000000000 -0500
16642 +++ linux-2.6.16.12/grsecurity/Kconfig 2006-05-01 20:17:34.000000000 -0400
16645 +# grecurity configuration
16651 + bool "Grsecurity"
16653 + select CRYPTO_SHA256
16655 + If you say Y here, you will be able to configure many features
16656 + that will enhance the security of your system. It is highly
16657 + recommended that you say Y here and read through the help
16658 + for each option so that you fully understand the features and
16659 + can evaluate their usefulness for your machine.
16662 + prompt "Security Level"
16663 + depends GRKERNSEC
16664 + default GRKERNSEC_CUSTOM
16666 +config GRKERNSEC_LOW
16668 + select GRKERNSEC_LINK
16669 + select GRKERNSEC_FIFO
16670 + select GRKERNSEC_RANDPID
16671 + select GRKERNSEC_EXECVE
16672 + select GRKERNSEC_RANDNET
16673 + select GRKERNSEC_DMESG
16674 + select GRKERNSEC_CHROOT_CHDIR
16675 + select GRKERNSEC_MODSTOP if (MODULES)
16678 + If you choose this option, several of the grsecurity options will
16679 + be enabled that will give you greater protection against a number
16680 + of attacks, while assuring that none of your software will have any
16681 + conflicts with the additional security measures. If you run a lot
16682 + of unusual software, or you are having problems with the higher
16683 + security levels, you should say Y here. With this option, the
16684 + following features are enabled:
16686 + - Linking restrictions
16687 + - FIFO restrictions
16688 + - Randomized PIDs
16689 + - Enforcing RLIMIT_NPROC on execve
16690 + - Restricted dmesg
16691 + - Enforced chdir("/") on chroot
16692 + - Runtime module disabling
16694 +config GRKERNSEC_MEDIUM
16697 + select PAX_EI_PAX
16698 + select PAX_PT_PAX_FLAGS
16699 + select PAX_HAVE_ACL_FLAGS
16700 + select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR)
16701 + select GRKERNSEC_CHROOT_SYSCTL
16702 + select GRKERNSEC_LINK
16703 + select GRKERNSEC_FIFO
16704 + select GRKERNSEC_RANDPID
16705 + select GRKERNSEC_EXECVE
16706 + select GRKERNSEC_DMESG
16707 + select GRKERNSEC_RANDNET
16708 + select GRKERNSEC_FORKFAIL
16709 + select GRKERNSEC_TIME
16710 + select GRKERNSEC_SIGNAL
16711 + select GRKERNSEC_CHROOT
16712 + select GRKERNSEC_CHROOT_UNIX
16713 + select GRKERNSEC_CHROOT_MOUNT
16714 + select GRKERNSEC_CHROOT_PIVOT
16715 + select GRKERNSEC_CHROOT_DOUBLE
16716 + select GRKERNSEC_CHROOT_CHDIR
16717 + select GRKERNSEC_CHROOT_MKNOD
16718 + select GRKERNSEC_PROC
16719 + select GRKERNSEC_PROC_USERGROUP
16720 + select GRKERNSEC_MODSTOP if (MODULES)
16721 + select PAX_RANDUSTACK
16723 + select PAX_RANDMMAP
16724 + select PAX_NOVSYSCALL if (X86 && !X86_64)
16727 + If you say Y here, several features in addition to those included
16728 + in the low additional security level will be enabled. These
16729 + features provide even more security to your system, though in rare
16730 + cases they may be incompatible with very old or poorly written
16731 + software. If you enable this option, make sure that your auth
16732 + service (identd) is running as gid 1001. With this option,
16733 + the following features (in addition to those provided in the
16734 + low additional security level) will be enabled:
16736 + - Randomized TCP source ports
16737 + - Failed fork logging
16738 + - Time change logging
16740 + - Deny mounts in chroot
16741 + - Deny double chrooting
16742 + - Deny sysctl writes in chroot
16743 + - Deny mknod in chroot
16744 + - Deny access to abstract AF_UNIX sockets out of chroot
16745 + - Deny pivot_root in chroot
16746 + - Denied writes of /dev/kmem, /dev/mem, and /dev/port
16747 + - /proc restrictions with special GID set to 10 (usually wheel)
16748 + - Address Space Layout Randomization (ASLR)
16750 +config GRKERNSEC_HIGH
16752 + select GRKERNSEC_LINK
16753 + select GRKERNSEC_FIFO
16754 + select GRKERNSEC_RANDPID
16755 + select GRKERNSEC_EXECVE
16756 + select GRKERNSEC_DMESG
16757 + select GRKERNSEC_FORKFAIL
16758 + select GRKERNSEC_TIME
16759 + select GRKERNSEC_SIGNAL
16760 + select GRKERNSEC_CHROOT_SHMAT
16761 + select GRKERNSEC_CHROOT_UNIX
16762 + select GRKERNSEC_CHROOT_MOUNT
16763 + select GRKERNSEC_CHROOT_FCHDIR
16764 + select GRKERNSEC_CHROOT_PIVOT
16765 + select GRKERNSEC_CHROOT_DOUBLE
16766 + select GRKERNSEC_CHROOT_CHDIR
16767 + select GRKERNSEC_CHROOT_MKNOD
16768 + select GRKERNSEC_CHROOT_CAPS
16769 + select GRKERNSEC_CHROOT_SYSCTL
16770 + select GRKERNSEC_CHROOT_FINDTASK
16771 + select GRKERNSEC_PROC
16772 + select GRKERNSEC_PROC_MEMMAP if (PAX_NOEXEC || PAX_ASLR)
16773 + select GRKERNSEC_HIDESYM
16774 + select GRKERNSEC_BRUTE
16775 + select GRKERNSEC_SHM if (SYSVIPC)
16776 + select GRKERNSEC_PROC_USERGROUP
16777 + select GRKERNSEC_KMEM
16778 + select GRKERNSEC_RESLOG
16779 + select GRKERNSEC_RANDNET
16780 + select GRKERNSEC_PROC_ADD
16781 + select GRKERNSEC_CHROOT_CHMOD
16782 + select GRKERNSEC_CHROOT_NICE
16783 + select GRKERNSEC_AUDIT_MOUNT
16784 + select GRKERNSEC_MODSTOP if (MODULES)
16786 + select PAX_RANDUSTACK
16788 + select PAX_RANDMMAP
16789 + select PAX_NOEXEC
16790 + select PAX_MPROTECT
16791 + select PAX_EI_PAX
16792 + select PAX_PT_PAX_FLAGS
16793 + select PAX_HAVE_ACL_FLAGS
16794 + select PAX_KERNEXEC if (!X86_64 && !MODULES && !HOTPLUG_PCI_COMPAQ_NVRAM && !PCI_BIOS)
16795 + select PAX_RANDKSTACK if (X86_TSC && !X86_64)
16796 + select PAX_SEGMEXEC if (X86 && !X86_64)
16797 + select PAX_PAGEEXEC if (!X86)
16798 + select PAX_EMUPLT if (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64)
16799 + select PAX_DLRESOLVE if (SPARC32 || SPARC64)
16800 + select PAX_SYSCALL if (PPC32)
16801 + select PAX_EMUTRAMP if (PARISC)
16802 + select PAX_EMUSIGRT if (PARISC)
16803 + select PAX_NOVSYSCALL if (X86 && !X86_64)
16804 + select PAX_ETEXECRELOCS if (ALPHA || IA64 || PARISC)
16806 + If you say Y here, many of the features of grsecurity will be
16807 + enabled, which will protect you against many kinds of attacks
16808 + against your system. The heightened security comes at a cost
16809 + of an increased chance of incompatibilities with rare software
16810 + on your machine. Since this security level enables PaX, you should
16811 + view <http://pax.grsecurity.net> and read about the PaX
16812 + project. While you are there, download chpax and run it on
16813 + binaries that cause problems with PaX. Also remember that
16814 + since the /proc restrictions are enabled, you must run your
16815 + identd as gid 1001. This security level enables the following
16816 + features in addition to those listed in the low and medium
16819 + - Additional /proc restrictions
16820 + - Chmod restrictions in chroot
16821 + - No signals, ptrace, or viewing of processes outside of chroot
16822 + - Capability restrictions in chroot
16823 + - Deny fchdir out of chroot
16824 + - Priority restrictions in chroot
16825 + - Segmentation-based implementation of PaX
16826 + - Mprotect restrictions
16827 + - Removal of addresses from /proc/<pid>/[smaps|maps|stat]
16828 + - Kernel stack randomization
16829 + - Mount/unmount/remount logging
16830 + - Kernel symbol hiding
16831 + - Destroy unused shared memory
16832 + - Prevention of memory exhaustion-based exploits
16833 +config GRKERNSEC_CUSTOM
16836 + If you say Y here, you will be able to configure every grsecurity
16837 + option, which allows you to enable many more features that aren't
16838 + covered in the basic security levels. These additional features
16839 + include TPE, socket restrictions, and the sysctl system for
16840 + grsecurity. It is advised that you read through the help for
16841 + each option to determine its usefulness in your situation.
16845 +menu "Address Space Protection"
16846 +depends on GRKERNSEC
16848 +config GRKERNSEC_KMEM
16849 + bool "Deny writing to /dev/kmem, /dev/mem, and /dev/port"
16851 + If you say Y here, /dev/kmem and /dev/mem won't be allowed to
16852 + be written to via mmap or otherwise to modify the running kernel.
16853 + /dev/port will also not be allowed to be opened. If you have module
16854 + support disabled, enabling this will close up four ways that are
16855 + currently used to insert malicious code into the running kernel.
16856 + Even with all these features enabled, we still highly recommend that
16857 + you use the RBAC system, as it is still possible for an attacker to
16858 + modify the running kernel through privileged I/O granted by ioperm/iopl.
16859 + If you are not using XFree86, you may be able to stop this additional
16860 + case by enabling the 'Disable privileged I/O' option. Though nothing
16861 + legitimately writes to /dev/kmem, XFree86 does need to write to /dev/mem,
16862 + but only to video memory, which is the only writing we allow in this
16863 + case. If /dev/kmem or /dev/mem are mmaped without PROT_WRITE, they will
16864 + not be allowed to mprotect it with PROT_WRITE later.
16865 + It is highly recommended that you say Y here if you meet all the
16866 + conditions above.
16868 +config GRKERNSEC_IO
16869 + bool "Disable privileged I/O"
16873 + If you say Y here, all ioperm and iopl calls will return an error.
16874 + Ioperm and iopl can be used to modify the running kernel.
16875 + Unfortunately, some programs need this access to operate properly,
16876 + the most notable of which are XFree86 and hwclock. hwclock can be
16877 + remedied by having RTC support in the kernel, so CONFIG_RTC is
16878 + enabled if this option is enabled, to ensure that hwclock operates
16879 + correctly. XFree86 still will not operate correctly with this option
16880 + enabled, so DO NOT CHOOSE Y IF YOU USE XFree86. If you use XFree86
16881 + and you still want to protect your kernel against modification,
16882 + use the RBAC system.
16884 +config GRKERNSEC_PROC_MEMMAP
16885 + bool "Remove addresses from /proc/<pid>/[smaps|maps|stat]"
16886 + depends on PAX_NOEXEC || PAX_ASLR
16888 + If you say Y here, the /proc/<pid>/maps and /proc/<pid>/stat files will
16889 + give no information about the addresses of its mappings if
16890 + PaX features that rely on random addresses are enabled on the task.
16891 + If you use PaX it is greatly recommended that you say Y here as it
16892 + closes up a hole that makes the full ASLR useless for suid
16895 +config GRKERNSEC_BRUTE
16896 + bool "Deter exploit bruteforcing"
16898 + If you say Y here, attempts to bruteforce exploits against forking
16899 + daemons such as apache or sshd will be deterred. When a child of a
16900 + forking daemon is killed by PaX or crashes due to an illegal
16901 + instruction, the parent process will be delayed 30 seconds upon every
16902 + subsequent fork until the administrator is able to assess the
16903 + situation and restart the daemon. It is recommended that you also
16904 + enable signal logging in the auditing section so that logs are
16905 + generated when a process performs an illegal instruction.
16907 +config GRKERNSEC_MODSTOP
16908 + bool "Runtime module disabling"
16909 + depends on MODULES
16911 + If you say Y here, you will be able to disable the ability to (un)load
16912 + modules at runtime. This feature is useful if you need the ability
16913 + to load kernel modules at boot time, but do not want to allow an
16914 + attacker to load a rootkit kernel module into the system, or to remove
16915 + a loaded kernel module important to system functioning. You should
16916 + enable the /dev/mem protection feature as well, since rootkits can be
16917 + inserted into the kernel via other methods than kernel modules. Since
16918 + an untrusted module could still be loaded by modifying init scripts and
16919 + rebooting the system, it is also recommended that you enable the RBAC
16920 + system. If you enable this option, a sysctl option with name
16921 + "disable_modules" will be created. Setting this option to "1" disables
16922 + module loading. After this option is set, no further writes to it are
16923 + allowed until the system is rebooted.
16925 +config GRKERNSEC_HIDESYM
16926 + bool "Hide kernel symbols"
16928 + If you say Y here, getting information on loaded modules, and
16929 + displaying all kernel symbols through a syscall will be restricted
16930 + to users with CAP_SYS_MODULE. This option is only effective
16931 + provided the following conditions are met:
16932 + 1) The kernel using grsecurity is not precompiled by some distribution
16933 + 2) You are using the RBAC system and hiding other files such as your
16934 + kernel image and System.map
16935 + 3) You have the additional /proc restrictions enabled, which removes
16937 + If the above conditions are met, this option will aid to provide a
16938 + useful protection against local and remote kernel exploitation of
16939 + overflows and arbitrary read/write vulnerabilities.
16942 +menu "Role Based Access Control Options"
16943 +depends on GRKERNSEC
16945 +config GRKERNSEC_ACL_HIDEKERN
16946 + bool "Hide kernel processes"
16948 + If you say Y here, all kernel threads will be hidden to all
16949 + processes but those whose subject has the "view hidden processes"
16952 +config GRKERNSEC_ACL_MAXTRIES
16953 + int "Maximum tries before password lockout"
16956 + This option enforces the maximum number of times a user can attempt
16957 + to authorize themselves with the grsecurity RBAC system before being
16958 + denied the ability to attempt authorization again for a specified time.
16959 + The lower the number, the harder it will be to brute-force a password.
16961 +config GRKERNSEC_ACL_TIMEOUT
16962 + int "Time to wait after max password tries, in seconds"
16965 + This option specifies the time the user must wait after attempting to
16966 + authorize to the RBAC system with the maximum number of invalid
16967 + passwords. The higher the number, the harder it will be to brute-force
16971 +menu "Filesystem Protections"
16972 +depends on GRKERNSEC
16974 +config GRKERNSEC_PROC
16975 + bool "Proc restrictions"
16977 + If you say Y here, the permissions of the /proc filesystem
16978 + will be altered to enhance system security and privacy. You MUST
16979 + choose either a user only restriction or a user and group restriction.
16980 + Depending upon the option you choose, you can either restrict users to
16981 + see only the processes they themselves run, or choose a group that can
16982 + view all processes and files normally restricted to root if you choose
16983 + the "restrict to user only" option. NOTE: If you're running identd as
16984 + a non-root user, you will have to run it as the group you specify here.
16986 +config GRKERNSEC_PROC_USER
16987 + bool "Restrict /proc to user only"
16988 + depends on GRKERNSEC_PROC
16990 + If you say Y here, non-root users will only be able to view their own
16991 + processes, and restricts them from viewing network-related information,
16992 + and viewing kernel symbol and module information.
16994 +config GRKERNSEC_PROC_USERGROUP
16995 + bool "Allow special group"
16996 + depends on GRKERNSEC_PROC && !GRKERNSEC_PROC_USER
16998 + If you say Y here, you will be able to select a group that will be
16999 + able to view all processes, network-related information, and
17000 + kernel and symbol information. This option is useful if you want
17001 + to run identd as a non-root user.
17003 +config GRKERNSEC_PROC_GID
17004 + int "GID for special group"
17005 + depends on GRKERNSEC_PROC_USERGROUP
17008 +config GRKERNSEC_PROC_ADD
17009 + bool "Additional restrictions"
17010 + depends on GRKERNSEC_PROC_USER || GRKERNSEC_PROC_USERGROUP
17012 + If you say Y here, additional restrictions will be placed on
17013 + /proc that keep normal users from viewing device information and
17014 + slabinfo information that could be useful for exploits.
17016 +config GRKERNSEC_LINK
17017 + bool "Linking restrictions"
17019 + If you say Y here, /tmp race exploits will be prevented, since users
17020 + will no longer be able to follow symlinks owned by other users in
17021 + world-writable +t directories (i.e. /tmp), unless the owner of the
17022 + symlink is the owner of the directory. users will also not be
17023 + able to hardlink to files they do not own. If the sysctl option is
17024 + enabled, a sysctl option with name "linking_restrictions" is created.
17026 +config GRKERNSEC_FIFO
17027 + bool "FIFO restrictions"
17029 + If you say Y here, users will not be able to write to FIFOs they don't
17030 + own in world-writable +t directories (i.e. /tmp), unless the owner of
17031 + the FIFO is the same owner of the directory it's held in. If the sysctl
17032 + option is enabled, a sysctl option with name "fifo_restrictions" is
17035 +config GRKERNSEC_CHROOT
17036 + bool "Chroot jail restrictions"
17038 + If you say Y here, you will be able to choose several options that will
17039 + make breaking out of a chrooted jail much more difficult. If you
17040 + encounter no software incompatibilities with the following options, it
17041 + is recommended that you enable each one.
17043 +config GRKERNSEC_CHROOT_MOUNT
17044 + bool "Deny mounts"
17045 + depends on GRKERNSEC_CHROOT
17047 + If you say Y here, processes inside a chroot will not be able to
17048 + mount or remount filesystems. If the sysctl option is enabled, a
17049 + sysctl option with name "chroot_deny_mount" is created.
17051 +config GRKERNSEC_CHROOT_DOUBLE
17052 + bool "Deny double-chroots"
17053 + depends on GRKERNSEC_CHROOT
17055 + If you say Y here, processes inside a chroot will not be able to chroot
17056 + again outside the chroot. This is a widely used method of breaking
17057 + out of a chroot jail and should not be allowed. If the sysctl
17058 + option is enabled, a sysctl option with name
17059 + "chroot_deny_chroot" is created.
17061 +config GRKERNSEC_CHROOT_PIVOT
17062 + bool "Deny pivot_root in chroot"
17063 + depends on GRKERNSEC_CHROOT
17065 + If you say Y here, processes inside a chroot will not be able to use
17066 + a function called pivot_root() that was introduced in Linux 2.3.41. It
17067 + works similar to chroot in that it changes the root filesystem. This
17068 + function could be misused in a chrooted process to attempt to break out
17069 + of the chroot, and therefore should not be allowed. If the sysctl
17070 + option is enabled, a sysctl option with name "chroot_deny_pivot" is
17073 +config GRKERNSEC_CHROOT_CHDIR
17074 + bool "Enforce chdir(\"/\") on all chroots"
17075 + depends on GRKERNSEC_CHROOT
17077 + If you say Y here, the current working directory of all newly-chrooted
17078 + applications will be set to the the root directory of the chroot.
17079 + The man page on chroot(2) states:
17080 + Note that this call does not change the current working
17081 + directory, so that `.' can be outside the tree rooted at
17082 + `/'. In particular, the super-user can escape from a
17083 + `chroot jail' by doing `mkdir foo; chroot foo; cd ..'.
17085 + It is recommended that you say Y here, since it's not known to break
17086 + any software. If the sysctl option is enabled, a sysctl option with
17087 + name "chroot_enforce_chdir" is created.
17089 +config GRKERNSEC_CHROOT_CHMOD
17090 + bool "Deny (f)chmod +s"
17091 + depends on GRKERNSEC_CHROOT
17093 + If you say Y here, processes inside a chroot will not be able to chmod
17094 + or fchmod files to make them have suid or sgid bits. This protects
17095 + against another published method of breaking a chroot. If the sysctl
17096 + option is enabled, a sysctl option with name "chroot_deny_chmod" is
17099 +config GRKERNSEC_CHROOT_FCHDIR
17100 + bool "Deny fchdir out of chroot"
17101 + depends on GRKERNSEC_CHROOT
17103 + If you say Y here, a well-known method of breaking chroots by fchdir'ing
17104 + to a file descriptor of the chrooting process that points to a directory
17105 + outside the filesystem will be stopped. If the sysctl option
17106 + is enabled, a sysctl option with name "chroot_deny_fchdir" is created.
17108 +config GRKERNSEC_CHROOT_MKNOD
17109 + bool "Deny mknod"
17110 + depends on GRKERNSEC_CHROOT
17112 + If you say Y here, processes inside a chroot will not be allowed to
17113 + mknod. The problem with using mknod inside a chroot is that it
17114 + would allow an attacker to create a device entry that is the same
17115 + as one on the physical root of your system, which could range from
17116 + anything from the console device to a device for your harddrive (which
17117 + they could then use to wipe the drive or steal data). It is recommended
17118 + that you say Y here, unless you run into software incompatibilities.
17119 + If the sysctl option is enabled, a sysctl option with name
17120 + "chroot_deny_mknod" is created.
17122 +config GRKERNSEC_CHROOT_SHMAT
17123 + bool "Deny shmat() out of chroot"
17124 + depends on GRKERNSEC_CHROOT
17126 + If you say Y here, processes inside a chroot will not be able to attach
17127 + to shared memory segments that were created outside of the chroot jail.
17128 + It is recommended that you say Y here. If the sysctl option is enabled,
17129 + a sysctl option with name "chroot_deny_shmat" is created.
17131 +config GRKERNSEC_CHROOT_UNIX
17132 + bool "Deny access to abstract AF_UNIX sockets out of chroot"
17133 + depends on GRKERNSEC_CHROOT
17135 + If you say Y here, processes inside a chroot will not be able to
17136 + connect to abstract (meaning not belonging to a filesystem) Unix
17137 + domain sockets that were bound outside of a chroot. It is recommended
17138 + that you say Y here. If the sysctl option is enabled, a sysctl option
17139 + with name "chroot_deny_unix" is created.
17141 +config GRKERNSEC_CHROOT_FINDTASK
17142 + bool "Protect outside processes"
17143 + depends on GRKERNSEC_CHROOT
17145 + If you say Y here, processes inside a chroot will not be able to
17146 + kill, send signals with fcntl, ptrace, capget, setpgid, getpgid,
17147 + getsid, or view any process outside of the chroot. If the sysctl
17148 + option is enabled, a sysctl option with name "chroot_findtask" is
17151 +config GRKERNSEC_CHROOT_NICE
17152 + bool "Restrict priority changes"
17153 + depends on GRKERNSEC_CHROOT
17155 + If you say Y here, processes inside a chroot will not be able to raise
17156 + the priority of processes in the chroot, or alter the priority of
17157 + processes outside the chroot. This provides more security than simply
17158 + removing CAP_SYS_NICE from the process' capability set. If the
17159 + sysctl option is enabled, a sysctl option with name "chroot_restrict_nice"
17162 +config GRKERNSEC_CHROOT_SYSCTL
17163 + bool "Deny sysctl writes"
17164 + depends on GRKERNSEC_CHROOT
17166 + If you say Y here, an attacker in a chroot will not be able to
17167 + write to sysctl entries, either by sysctl(2) or through a /proc
17168 + interface. It is strongly recommended that you say Y here. If the
17169 + sysctl option is enabled, a sysctl option with name
17170 + "chroot_deny_sysctl" is created.
17172 +config GRKERNSEC_CHROOT_CAPS
17173 + bool "Capability restrictions"
17174 + depends on GRKERNSEC_CHROOT
17176 + If you say Y here, the capabilities on all root processes within a
17177 + chroot jail will be lowered to stop module insertion, raw i/o,
17178 + system and net admin tasks, rebooting the system, modifying immutable
17179 + files, modifying IPC owned by another, and changing the system time.
17180 + This is left an option because it can break some apps. Disable this
17181 + if your chrooted apps are having problems performing those kinds of
17182 + tasks. If the sysctl option is enabled, a sysctl option with
17183 + name "chroot_caps" is created.
17186 +menu "Kernel Auditing"
17187 +depends on GRKERNSEC
17189 +config GRKERNSEC_AUDIT_GROUP
17190 + bool "Single group for auditing"
17192 + If you say Y here, the exec, chdir, (un)mount, and ipc logging features
17193 + will only operate on a group you specify. This option is recommended
17194 + if you only want to watch certain users instead of having a large
17195 + amount of logs from the entire system. If the sysctl option is enabled,
17196 + a sysctl option with name "audit_group" is created.
17198 +config GRKERNSEC_AUDIT_GID
17199 + int "GID for auditing"
17200 + depends on GRKERNSEC_AUDIT_GROUP
17203 +config GRKERNSEC_EXECLOG
17204 + bool "Exec logging"
17206 + If you say Y here, all execve() calls will be logged (since the
17207 + other exec*() calls are frontends to execve(), all execution
17208 + will be logged). Useful for shell-servers that like to keep track
17209 + of their users. If the sysctl option is enabled, a sysctl option with
17210 + name "exec_logging" is created.
17211 + WARNING: This option when enabled will produce a LOT of logs, especially
17212 + on an active system.
17214 +config GRKERNSEC_RESLOG
17215 + bool "Resource logging"
17217 + If you say Y here, all attempts to overstep resource limits will
17218 + be logged with the resource name, the requested size, and the current
17219 + limit. It is highly recommended that you say Y here.
17221 +config GRKERNSEC_CHROOT_EXECLOG
17222 + bool "Log execs within chroot"
17224 + If you say Y here, all executions inside a chroot jail will be logged
17225 + to syslog. This can cause a large amount of logs if certain
17226 + applications (eg. djb's daemontools) are installed on the system, and
17227 + is therefore left as an option. If the sysctl option is enabled, a
17228 + sysctl option with name "chroot_execlog" is created.
17230 +config GRKERNSEC_AUDIT_CHDIR
17231 + bool "Chdir logging"
17233 + If you say Y here, all chdir() calls will be logged. If the sysctl
17234 + option is enabled, a sysctl option with name "audit_chdir" is created.
17236 +config GRKERNSEC_AUDIT_MOUNT
17237 + bool "(Un)Mount logging"
17239 + If you say Y here, all mounts and unmounts will be logged. If the
17240 + sysctl option is enabled, a sysctl option with name "audit_mount" is
17243 +config GRKERNSEC_AUDIT_IPC
17244 + bool "IPC logging"
17246 + If you say Y here, creation and removal of message queues, semaphores,
17247 + and shared memory will be logged. If the sysctl option is enabled, a
17248 + sysctl option with name "audit_ipc" is created.
17250 +config GRKERNSEC_SIGNAL
17251 + bool "Signal logging"
17253 + If you say Y here, certain important signals will be logged, such as
17254 + SIGSEGV, which will as a result inform you of when a error in a program
17255 + occurred, which in some cases could mean a possible exploit attempt.
17256 + If the sysctl option is enabled, a sysctl option with name
17257 + "signal_logging" is created.
17259 +config GRKERNSEC_FORKFAIL
17260 + bool "Fork failure logging"
17262 + If you say Y here, all failed fork() attempts will be logged.
17263 + This could suggest a fork bomb, or someone attempting to overstep
17264 + their process limit. If the sysctl option is enabled, a sysctl option
17265 + with name "forkfail_logging" is created.
17267 +config GRKERNSEC_TIME
17268 + bool "Time change logging"
17270 + If you say Y here, any changes of the system clock will be logged.
17271 + If the sysctl option is enabled, a sysctl option with name
17272 + "timechange_logging" is created.
17274 +config GRKERNSEC_PROC_IPADDR
17275 + bool "/proc/<pid>/ipaddr support"
17277 + If you say Y here, a new entry will be added to each /proc/<pid>
17278 + directory that contains the IP address of the person using the task.
17279 + The IP is carried across local TCP and AF_UNIX stream sockets.
17280 + This information can be useful for IDS/IPSes to perform remote response
17281 + to a local attack. The entry is readable by only the owner of the
17282 + process (and root if he has CAP_DAC_OVERRIDE, which can be removed via
17283 + the RBAC system), and thus does not create privacy concerns.
17285 +config GRKERNSEC_AUDIT_TEXTREL
17286 + bool 'ELF text relocations logging (READ HELP)'
17287 + depends on PAX_MPROTECT
17289 + If you say Y here, text relocations will be logged with the filename
17290 + of the offending library or binary. The purpose of the feature is
17291 + to help Linux distribution developers get rid of libraries and
17292 + binaries that need text relocations which hinder the future progress
17293 + of PaX. Only Linux distribution developers should say Y here, and
17294 + never on a production machine, as this option creates an information
17295 + leak that could aid an attacker in defeating the randomization of
17296 + a single memory region. If the sysctl option is enabled, a sysctl
17297 + option with name "audit_textrel" is created.
17301 +menu "Executable Protections"
17302 +depends on GRKERNSEC
17304 +config GRKERNSEC_EXECVE
17305 + bool "Enforce RLIMIT_NPROC on execs"
17307 + If you say Y here, users with a resource limit on processes will
17308 + have the value checked during execve() calls. The current system
17309 + only checks the system limit during fork() calls. If the sysctl option
17310 + is enabled, a sysctl option with name "execve_limiting" is created.
17312 +config GRKERNSEC_SHM
17313 + bool "Destroy unused shared memory"
17314 + depends on SYSVIPC
17316 + If you say Y here, shared memory will be destroyed when no one is
17317 + attached to it. Otherwise, resources involved with the shared
17318 + memory can be used up and not be associated with any process (as the
17319 + shared memory still exists, and the creating process has exited). If
17320 + the sysctl option is enabled, a sysctl option with name
17321 + "destroy_unused_shm" is created.
17323 +config GRKERNSEC_DMESG
17324 + bool "Dmesg(8) restriction"
17326 + If you say Y here, non-root users will not be able to use dmesg(8)
17327 + to view up to the last 4kb of messages in the kernel's log buffer.
17328 + If the sysctl option is enabled, a sysctl option with name "dmesg" is
17331 +config GRKERNSEC_RANDPID
17332 + bool "Randomized PIDs"
17334 + If you say Y here, all PIDs created on the system will be
17335 + pseudo-randomly generated. This is extremely effective along
17336 + with the /proc restrictions to disallow an attacker from guessing
17337 + pids of daemons, etc. PIDs are also used in some cases as part
17338 + of a naming system for temporary files, so this option would keep
17339 + those filenames from being predicted as well. We also use code
17340 + to make sure that PID numbers aren't reused too soon. If the sysctl
17341 + option is enabled, a sysctl option with name "rand_pids" is created.
17343 +config GRKERNSEC_TPE
17344 + bool "Trusted Path Execution (TPE)"
17346 + If you say Y here, you will be able to choose a gid to add to the
17347 + supplementary groups of users you want to mark as "untrusted."
17348 + These users will not be able to execute any files that are not in
17349 + root-owned directories writable only by root. If the sysctl option
17350 + is enabled, a sysctl option with name "tpe" is created.
17352 +config GRKERNSEC_TPE_ALL
17353 + bool "Partially restrict non-root users"
17354 + depends on GRKERNSEC_TPE
17356 + If you say Y here, All non-root users other than the ones in the
17357 + group specified in the main TPE option will only be allowed to
17358 + execute files in directories they own that are not group or
17359 + world-writable, or in directories owned by root and writable only by
17360 + root. If the sysctl option is enabled, a sysctl option with name
17361 + "tpe_restrict_all" is created.
17363 +config GRKERNSEC_TPE_INVERT
17364 + bool "Invert GID option"
17365 + depends on GRKERNSEC_TPE
17367 + If you say Y here, the group you specify in the TPE configuration will
17368 + decide what group TPE restrictions will be *disabled* for. This
17369 + option is useful if you want TPE restrictions to be applied to most
17370 + users on the system.
17372 +config GRKERNSEC_TPE_GID
17373 + int "GID for untrusted users"
17374 + depends on GRKERNSEC_TPE && !GRKERNSEC_TPE_INVERT
17377 + If you have selected the "Invert GID option" above, setting this
17378 + GID determines what group TPE restrictions will be *disabled* for.
17379 + If you have not selected the "Invert GID option" above, setting this
17380 + GID determines what group TPE restrictions will be *enabled* for.
17381 + If the sysctl option is enabled, a sysctl option with name "tpe_gid"
17384 +config GRKERNSEC_TPE_GID
17385 + int "GID for trusted users"
17386 + depends on GRKERNSEC_TPE && GRKERNSEC_TPE_INVERT
17389 + If you have selected the "Invert GID option" above, setting this
17390 + GID determines what group TPE restrictions will be *disabled* for.
17391 + If you have not selected the "Invert GID option" above, setting this
17392 + GID determines what group TPE restrictions will be *enabled* for.
17393 + If the sysctl option is enabled, a sysctl option with name "tpe_gid"
17397 +menu "Network Protections"
17398 +depends on GRKERNSEC
17400 +config GRKERNSEC_RANDNET
17401 + bool "Larger entropy pools"
17403 + If you say Y here, the entropy pools used for many features of Linux
17404 + and grsecurity will be doubled in size. Since several grsecurity
17405 + features use additional randomness, it is recommended that you say Y
17406 + here. Saying Y here has a similar effect as modifying
17407 + /proc/sys/kernel/random/poolsize.
17409 +config GRKERNSEC_SOCKET
17410 + bool "Socket restrictions"
17412 + If you say Y here, you will be able to choose from several options.
17413 + If you assign a GID on your system and add it to the supplementary
17414 + groups of users you want to restrict socket access to, this patch
17415 + will perform up to three things, based on the option(s) you choose.
17417 +config GRKERNSEC_SOCKET_ALL
17418 + bool "Deny any sockets to group"
17419 + depends on GRKERNSEC_SOCKET
17421 + If you say Y here, you will be able to choose a GID of whose users will
17422 + be unable to connect to other hosts from your machine or run server
17423 + applications from your machine. If the sysctl option is enabled, a
17424 + sysctl option with name "socket_all" is created.
17426 +config GRKERNSEC_SOCKET_ALL_GID
17427 + int "GID to deny all sockets for"
17428 + depends on GRKERNSEC_SOCKET_ALL
17431 + Here you can choose the GID to disable socket access for. Remember to
17432 + add the users you want socket access disabled for to the GID
17433 + specified here. If the sysctl option is enabled, a sysctl option
17434 + with name "socket_all_gid" is created.
17436 +config GRKERNSEC_SOCKET_CLIENT
17437 + bool "Deny client sockets to group"
17438 + depends on GRKERNSEC_SOCKET
17440 + If you say Y here, you will be able to choose a GID of whose users will
17441 + be unable to connect to other hosts from your machine, but will be
17442 + able to run servers. If this option is enabled, all users in the group
17443 + you specify will have to use passive mode when initiating ftp transfers
17444 + from the shell on your machine. If the sysctl option is enabled, a
17445 + sysctl option with name "socket_client" is created.
17447 +config GRKERNSEC_SOCKET_CLIENT_GID
17448 + int "GID to deny client sockets for"
17449 + depends on GRKERNSEC_SOCKET_CLIENT
17452 + Here you can choose the GID to disable client socket access for.
17453 + Remember to add the users you want client socket access disabled for to
17454 + the GID specified here. If the sysctl option is enabled, a sysctl
17455 + option with name "socket_client_gid" is created.
17457 +config GRKERNSEC_SOCKET_SERVER
17458 + bool "Deny server sockets to group"
17459 + depends on GRKERNSEC_SOCKET
17461 + If you say Y here, you will be able to choose a GID of whose users will
17462 + be unable to run server applications from your machine. If the sysctl
17463 + option is enabled, a sysctl option with name "socket_server" is created.
17465 +config GRKERNSEC_SOCKET_SERVER_GID
17466 + int "GID to deny server sockets for"
17467 + depends on GRKERNSEC_SOCKET_SERVER
17470 + Here you can choose the GID to disable server socket access for.
17471 + Remember to add the users you want server socket access disabled for to
17472 + the GID specified here. If the sysctl option is enabled, a sysctl
17473 + option with name "socket_server_gid" is created.
17476 +menu "Sysctl support"
17477 +depends on GRKERNSEC && SYSCTL
17479 +config GRKERNSEC_SYSCTL
17480 + bool "Sysctl support"
17482 + If you say Y here, you will be able to change the options that
17483 + grsecurity runs with at bootup, without having to recompile your
17484 + kernel. You can echo values to files in /proc/sys/kernel/grsecurity
17485 + to enable (1) or disable (0) various features. All the sysctl entries
17486 + are mutable until the "grsec_lock" entry is set to a non-zero value.
17487 + All features enabled in the kernel configuration are disabled at boot
17488 + if you do not say Y to the "Turn on features by default" option.
17489 + All options should be set at startup, and the grsec_lock entry should
17490 + be set to a non-zero value after all the options are set.
17491 + *THIS IS EXTREMELY IMPORTANT*
17493 +config GRKERNSEC_SYSCTL_ON
17494 + bool "Turn on features by default"
17495 + depends on GRKERNSEC_SYSCTL
17497 + If you say Y here, instead of having all features enabled in the
17498 + kernel configuration disabled at boot time, the features will be
17499 + enabled at boot time. It is recommended you say Y here unless
17500 + there is some reason you would want all sysctl-tunable features to
17501 + be disabled by default. As mentioned elsewhere, it is important
17502 + to enable the grsec_lock entry once you have finished modifying
17503 + the sysctl entries.
17506 +menu "Logging Options"
17507 +depends on GRKERNSEC
17509 +config GRKERNSEC_FLOODTIME
17510 + int "Seconds in between log messages (minimum)"
17513 + This option allows you to enforce the number of seconds between
17514 + grsecurity log messages. The default should be suitable for most
17515 + people, however, if you choose to change it, choose a value small enough
17516 + to allow informative logs to be produced, but large enough to
17517 + prevent flooding.
17519 +config GRKERNSEC_FLOODBURST
17520 + int "Number of messages in a burst (maximum)"
17523 + This option allows you to choose the maximum number of messages allowed
17524 + within the flood time interval you chose in a separate option. The
17525 + default should be suitable for most people, however if you find that
17526 + many of your logs are being interpreted as flooding, you may want to
17527 + raise this value.
17532 diff -urNp linux-2.6.16.12/grsecurity/Makefile linux-2.6.16.12/grsecurity/Makefile
17533 --- linux-2.6.16.12/grsecurity/Makefile 1969-12-31 19:00:00.000000000 -0500
17534 +++ linux-2.6.16.12/grsecurity/Makefile 2006-05-01 20:17:34.000000000 -0400
17536 +# grsecurity's ACL system was originally written in 2001 by Michael Dalton
17537 +# during 2001-2005 it has been completely redesigned by Brad Spengler
17538 +# into an RBAC system
17540 +# All code in this directory and various hooks inserted throughout the kernel
17541 +# are copyright Brad Spengler, and released under the GPL v2 or higher
17543 +obj-y = grsec_chdir.o grsec_chroot.o grsec_exec.o grsec_fifo.o grsec_fork.o \
17544 + grsec_mount.o grsec_rand.o grsec_sig.o grsec_sock.o grsec_sysctl.o \
17545 + grsec_time.o grsec_tpe.o grsec_ipc.o grsec_link.o grsec_textrel.o
17547 +obj-$(CONFIG_GRKERNSEC) += grsec_init.o grsum.o gracl.o gracl_ip.o gracl_segv.o \
17548 + gracl_cap.o gracl_alloc.o gracl_shm.o grsec_mem.o gracl_fs.o \
17549 + gracl_learn.o grsec_log.o
17550 +obj-$(CONFIG_GRKERNSEC_RESLOG) += gracl_res.o
17552 +ifndef CONFIG_GRKERNSEC
17553 +obj-y += grsec_disabled.o
17556 diff -urNp linux-2.6.16.12/include/asm-alpha/a.out.h linux-2.6.16.12/include/asm-alpha/a.out.h
17557 --- linux-2.6.16.12/include/asm-alpha/a.out.h 2006-05-01 15:14:26.000000000 -0400
17558 +++ linux-2.6.16.12/include/asm-alpha/a.out.h 2006-05-01 20:17:34.000000000 -0400
17559 @@ -98,7 +98,7 @@ struct exec
17560 set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000L \
17561 ? ADDR_LIMIT_32BIT : 0) | PER_OSF4))
17563 -#define STACK_TOP \
17564 +#define __STACK_TOP \
17565 (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL)
17568 diff -urNp linux-2.6.16.12/include/asm-alpha/elf.h linux-2.6.16.12/include/asm-alpha/elf.h
17569 --- linux-2.6.16.12/include/asm-alpha/elf.h 2006-05-01 15:14:26.000000000 -0400
17570 +++ linux-2.6.16.12/include/asm-alpha/elf.h 2006-05-01 20:17:34.000000000 -0400
17571 @@ -91,6 +91,17 @@ typedef elf_fpreg_t elf_fpregset_t[ELF_N
17573 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000)
17575 +#ifdef CONFIG_PAX_ASLR
17576 +#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 0x10000 : 0x120000000UL)
17578 +#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
17579 +#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28)
17580 +#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
17581 +#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28)
17582 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
17583 +#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 19)
17586 /* $0 is set by ld.so to a pointer to a function which might be
17587 registered using atexit. This provides a mean for the dynamic
17588 linker to call DT_FINI functions for shared libraries that have
17589 diff -urNp linux-2.6.16.12/include/asm-alpha/page.h linux-2.6.16.12/include/asm-alpha/page.h
17590 --- linux-2.6.16.12/include/asm-alpha/page.h 2006-05-01 15:14:26.000000000 -0400
17591 +++ linux-2.6.16.12/include/asm-alpha/page.h 2006-05-01 20:17:34.000000000 -0400
17592 @@ -96,6 +96,15 @@ typedef unsigned long pgprot_t;
17593 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
17594 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
17596 +#ifdef CONFIG_PAX_PAGEEXEC
17597 +#ifdef CONFIG_PAX_MPROTECT
17598 +#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
17599 + ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
17601 +#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
17605 #endif /* __KERNEL__ */
17607 #include <asm-generic/page.h>
17608 diff -urNp linux-2.6.16.12/include/asm-alpha/pgtable.h linux-2.6.16.12/include/asm-alpha/pgtable.h
17609 --- linux-2.6.16.12/include/asm-alpha/pgtable.h 2006-05-01 15:14:26.000000000 -0400
17610 +++ linux-2.6.16.12/include/asm-alpha/pgtable.h 2006-05-01 20:17:34.000000000 -0400
17611 @@ -102,6 +102,17 @@ struct vm_area_struct;
17612 #define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS)
17613 #define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
17614 #define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW)
17616 +#ifdef CONFIG_PAX_PAGEEXEC
17617 +# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOE)
17618 +# define PAGE_COPY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE)
17619 +# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE)
17621 +# define PAGE_SHARED_NOEXEC PAGE_SHARED
17622 +# define PAGE_COPY_NOEXEC PAGE_COPY
17623 +# define PAGE_READONLY_NOEXEC PAGE_READONLY
17626 #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE)
17628 #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x))
17629 diff -urNp linux-2.6.16.12/include/asm-arm/a.out.h linux-2.6.16.12/include/asm-arm/a.out.h
17630 --- linux-2.6.16.12/include/asm-arm/a.out.h 2006-05-01 15:14:26.000000000 -0400
17631 +++ linux-2.6.16.12/include/asm-arm/a.out.h 2006-05-01 20:17:34.000000000 -0400
17632 @@ -28,7 +28,7 @@ struct exec
17636 -#define STACK_TOP ((current->personality == PER_LINUX_32BIT) ? \
17637 +#define __STACK_TOP ((current->personality == PER_LINUX_32BIT) ? \
17638 TASK_SIZE : TASK_SIZE_26)
17641 diff -urNp linux-2.6.16.12/include/asm-arm/elf.h linux-2.6.16.12/include/asm-arm/elf.h
17642 --- linux-2.6.16.12/include/asm-arm/elf.h 2006-05-01 15:14:26.000000000 -0400
17643 +++ linux-2.6.16.12/include/asm-arm/elf.h 2006-05-01 20:17:34.000000000 -0400
17644 @@ -56,6 +56,17 @@ typedef struct user_fp elf_fpregset_t;
17646 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
17648 +#ifdef CONFIG_PAX_ASLR
17649 +#define PAX_ELF_ET_DYN_BASE(tsk) 0x00008000UL
17651 +#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
17652 +#define PAX_DELTA_MMAP_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
17653 +#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
17654 +#define PAX_DELTA_EXEC_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
17655 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
17656 +#define PAX_DELTA_STACK_LEN(tsk) ((tsk->personality == PER_LINUX_32BIT) ? 16 : 10)
17659 /* When the program starts, a1 contains a pointer to a function to be
17660 registered with atexit, as per the SVR4 ABI. A value of 0 means we
17661 have no such handler. */
17662 diff -urNp linux-2.6.16.12/include/asm-i386/a.out.h linux-2.6.16.12/include/asm-i386/a.out.h
17663 --- linux-2.6.16.12/include/asm-i386/a.out.h 2006-05-01 15:14:26.000000000 -0400
17664 +++ linux-2.6.16.12/include/asm-i386/a.out.h 2006-05-01 20:17:34.000000000 -0400
17665 @@ -19,7 +19,11 @@ struct exec
17669 -#define STACK_TOP TASK_SIZE
17670 +#ifdef CONFIG_PAX_SEGMEXEC
17671 +#define __STACK_TOP ((current->mm->pax_flags & MF_PAX_SEGMEXEC)?TASK_SIZE/2:TASK_SIZE)
17673 +#define __STACK_TOP TASK_SIZE
17678 diff -urNp linux-2.6.16.12/include/asm-i386/auxvec.h linux-2.6.16.12/include/asm-i386/auxvec.h
17679 --- linux-2.6.16.12/include/asm-i386/auxvec.h 2006-05-01 15:14:26.000000000 -0400
17680 +++ linux-2.6.16.12/include/asm-i386/auxvec.h 2006-05-01 20:17:34.000000000 -0400
17682 * Architecture-neutral AT_ values in 0-17, leave some room
17683 * for more of them, start the x86-specific ones at 32.
17685 +#ifndef CONFIG_PAX_NOVSYSCALL
17686 #define AT_SYSINFO 32
17687 #define AT_SYSINFO_EHDR 33
17691 diff -urNp linux-2.6.16.12/include/asm-i386/desc.h linux-2.6.16.12/include/asm-i386/desc.h
17692 --- linux-2.6.16.12/include/asm-i386/desc.h 2006-05-01 15:14:26.000000000 -0400
17693 +++ linux-2.6.16.12/include/asm-i386/desc.h 2006-05-01 20:17:34.000000000 -0400
17694 @@ -10,11 +10,13 @@
17696 #include <linux/preempt.h>
17697 #include <linux/smp.h>
17698 -#include <linux/percpu.h>
17699 +#include <linux/sched.h>
17701 #include <asm/mmu.h>
17702 +#include <asm/pgtable.h>
17703 +#include <asm/tlbflush.h>
17705 -extern struct desc_struct cpu_gdt_table[GDT_ENTRIES];
17706 +extern struct desc_struct cpu_gdt_table[NR_CPUS][PAGE_SIZE / sizeof(struct desc_struct)];
17708 DECLARE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]);
17710 @@ -24,13 +26,53 @@ struct Xgt_desc_struct {
17711 unsigned short pad;
17712 } __attribute__ ((packed));
17714 -extern struct Xgt_desc_struct idt_descr;
17715 -DECLARE_PER_CPU(struct Xgt_desc_struct, cpu_gdt_descr);
17717 +extern struct Xgt_desc_struct idt_descr, cpu_gdt_descr[NR_CPUS];
17719 static inline struct desc_struct *get_cpu_gdt_table(unsigned int cpu)
17721 - return (struct desc_struct *)per_cpu(cpu_gdt_descr, cpu).address;
17722 + return cpu_gdt_table[cpu];
17725 +#define pax_open_kernel(cr0) \
17727 + typecheck(unsigned long,cr0); \
17728 + preempt_disable(); \
17729 + cr0 = read_cr0(); \
17730 + write_cr0(cr0 & ~0x10000UL); \
17733 +#define pax_close_kernel(cr0) \
17735 + typecheck(unsigned long,cr0); \
17736 + write_cr0(cr0); \
17737 + preempt_enable_no_resched(); \
17740 +static inline void set_user_cs(struct mm_struct *mm, int cpu)
17742 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
17743 + unsigned long base = mm->context.user_cs_base;
17744 + unsigned long limit = mm->context.user_cs_limit;
17746 +#ifdef CONFIG_PAX_KERNEXEC
17747 + unsigned long cr0;
17749 + pax_open_kernel(cr0);
17752 + if (likely(limit)) {
17757 + get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS].a = (limit & 0xFFFFUL) | (base << 16);
17758 + get_cpu_gdt_table(cpu)[GDT_ENTRY_DEFAULT_USER_CS].b = (limit & 0xF0000UL) | 0xC0FB00UL | (base & 0xFF000000UL) | ((base >> 16) & 0xFFUL);
17760 +#ifdef CONFIG_PAX_KERNEXEC
17761 + pax_close_kernel(cr0);
17767 #define load_TR_desc() __asm__ __volatile__("ltr %w0"::"q" (GDT_ENTRY_TSS*8))
17768 @@ -50,7 +92,7 @@ static inline struct desc_struct *get_cp
17769 * This is the ldt that every process will get unless we need
17770 * something other than this.
17772 -extern struct desc_struct default_ldt[];
17773 +extern const struct desc_struct default_ldt[];
17774 extern void set_intr_gate(unsigned int irq, void * addr);
17776 #define _set_tssldt_desc(n,addr,limit,type) \
17777 @@ -64,7 +106,7 @@ __asm__ __volatile__ ("movw %w3,0(%2)\n\
17779 : "=m"(*(n)) : "q" (addr), "r"(n), "ir"(limit), "i"(type))
17781 -static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr)
17782 +static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr)
17784 _set_tssldt_desc(&get_cpu_gdt_table(cpu)[entry], (int)addr,
17785 offsetof(struct tss_struct, __cacheline_filler) - 1, 0x89);
17786 @@ -72,11 +114,28 @@ static inline void __set_tss_desc(unsign
17788 #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr)
17790 -static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size)
17791 +static inline void __set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size)
17793 _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
17796 +static inline void set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size)
17799 +#ifdef CONFIG_PAX_KERNEXEC
17800 + unsigned long cr0;
17802 + pax_open_kernel(cr0);
17805 + _set_tssldt_desc(&get_cpu_gdt_table(cpu)[GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82);
17807 +#ifdef CONFIG_PAX_KERNEXEC
17808 + pax_close_kernel(cr0);
17813 #define LDT_entry_a(info) \
17814 ((((info)->base_addr & 0x0000ffff) << 16) | ((info)->limit & 0x0ffff))
17816 @@ -90,7 +149,7 @@ static inline void set_ldt_desc(unsigned
17817 ((info)->seg_32bit << 22) | \
17818 ((info)->limit_in_pages << 23) | \
17819 ((info)->useable << 20) | \
17823 #define LDT_empty(info) (\
17824 (info)->base_addr == 0 && \
17825 @@ -134,7 +193,7 @@ static inline void clear_LDT(void)
17827 static inline void load_LDT_nolock(mm_context_t *pc, int cpu)
17829 - void *segments = pc->ldt;
17830 + const void *segments = pc->ldt;
17831 int count = pc->size;
17833 if (likely(!count)) {
17834 @@ -162,6 +221,22 @@ static inline unsigned long get_desc_bas
17838 +static inline void _load_LDT(mm_context_t *pc)
17840 + int cpu = get_cpu();
17841 + const void *segments = pc->ldt;
17842 + int count = pc->size;
17844 + if (likely(!count)) {
17845 + segments = &default_ldt[0];
17849 + __set_ldt_desc(cpu, segments, count);
17854 #endif /* !__ASSEMBLY__ */
17857 diff -urNp linux-2.6.16.12/include/asm-i386/elf.h linux-2.6.16.12/include/asm-i386/elf.h
17858 --- linux-2.6.16.12/include/asm-i386/elf.h 2006-05-01 15:14:26.000000000 -0400
17859 +++ linux-2.6.16.12/include/asm-i386/elf.h 2006-05-01 20:17:34.000000000 -0400
17860 @@ -71,7 +71,22 @@ typedef struct user_fxsr_struct elf_fpxr
17861 the loader. We need to make sure that it is out of the way of the program
17862 that it will "exec", and that there is sufficient room for the brk. */
17864 +#ifdef CONFIG_PAX_SEGMEXEC
17865 +#define ELF_ET_DYN_BASE ((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3*2 : TASK_SIZE/3*2)
17867 #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
17870 +#ifdef CONFIG_PAX_ASLR
17871 +#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000000UL
17873 +#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
17874 +#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
17875 +#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
17876 +#define PAX_DELTA_EXEC_LEN(tsk) 15
17877 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
17878 +#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->mm->pax_flags & MF_PAX_SEGMEXEC ? 15 : 16)
17881 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
17882 now struct_user_regs, they are different) */
17883 @@ -131,7 +146,14 @@ extern int dump_task_extended_fpu (struc
17885 #define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL))
17886 #define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE)
17888 +#ifndef CONFIG_PAX_NOVSYSCALL
17889 +#ifdef CONFIG_PAX_SEGMEXEC
17890 +#define VSYSCALL_ENTRY ((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? (unsigned long) &__kernel_vsyscall - SEGMEXEC_TASK_SIZE : (unsigned long) &__kernel_vsyscall)
17892 #define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall)
17895 extern void __kernel_vsyscall;
17897 #define ARCH_DLINFO \
17898 @@ -187,3 +209,5 @@ do { \
17904 diff -urNp linux-2.6.16.12/include/asm-i386/i387.h linux-2.6.16.12/include/asm-i386/i387.h
17905 --- linux-2.6.16.12/include/asm-i386/i387.h 2006-05-01 15:14:26.000000000 -0400
17906 +++ linux-2.6.16.12/include/asm-i386/i387.h 2006-05-01 20:17:34.000000000 -0400
17907 @@ -31,8 +31,8 @@ extern void init_fpu(struct task_struct
17909 #define restore_fpu(tsk) \
17910 alternative_input( \
17911 - "nop ; frstor %1", \
17913 + "nop ; frstor %2", \
17915 X86_FEATURE_FXSR, \
17916 "m" ((tsk)->thread.i387.fxsave))
17918 diff -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
17919 --- linux-2.6.16.12/include/asm-i386/mach-default/apm.h 2006-05-01 15:14:26.000000000 -0400
17920 +++ linux-2.6.16.12/include/asm-i386/mach-default/apm.h 2006-05-01 20:17:34.000000000 -0400
17921 @@ -36,7 +36,7 @@ static inline void apm_bios_call_asm(u32
17922 __asm__ __volatile__(APM_DO_ZERO_SEGS
17925 - "lcall *%%cs:apm_bios_entry\n\t"
17926 + "lcall *%%ss:apm_bios_entry\n\t"
17930 @@ -60,7 +60,7 @@ static inline u8 apm_bios_call_simple_as
17931 __asm__ __volatile__(APM_DO_ZERO_SEGS
17934 - "lcall *%%cs:apm_bios_entry\n\t"
17935 + "lcall *%%ss:apm_bios_entry\n\t"
17939 diff -urNp linux-2.6.16.12/include/asm-i386/mman.h linux-2.6.16.12/include/asm-i386/mman.h
17940 --- linux-2.6.16.12/include/asm-i386/mman.h 2006-05-01 15:14:26.000000000 -0400
17941 +++ linux-2.6.16.12/include/asm-i386/mman.h 2006-05-01 20:17:34.000000000 -0400
17943 #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
17944 #define MAP_NONBLOCK 0x10000 /* do not block on IO */
17946 +#ifdef CONFIG_PAX_SEGMEXEC
17947 +#define MAP_MIRROR 0x20000
17950 #define MCL_CURRENT 1 /* lock all current mappings */
17951 #define MCL_FUTURE 2 /* lock all future mappings */
17953 diff -urNp linux-2.6.16.12/include/asm-i386/mmu_context.h linux-2.6.16.12/include/asm-i386/mmu_context.h
17954 --- linux-2.6.16.12/include/asm-i386/mmu_context.h 2006-05-01 15:14:26.000000000 -0400
17955 +++ linux-2.6.16.12/include/asm-i386/mmu_context.h 2006-05-01 20:17:34.000000000 -0400
17956 @@ -46,6 +46,13 @@ static inline void switch_mm(struct mm_s
17958 if (unlikely(prev->context.ldt != next->context.ldt))
17959 load_LDT_nolock(&next->context, cpu);
17961 +#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
17962 + cpu_clear(cpu, prev->context.cpu_user_cs_mask);
17963 + cpu_set(cpu, next->context.cpu_user_cs_mask);
17966 + set_user_cs(next, cpu);
17970 @@ -58,6 +65,12 @@ static inline void switch_mm(struct mm_s
17972 load_cr3(next->pgd);
17973 load_LDT_nolock(&next->context, cpu);
17975 +#ifdef CONFIG_PAX_PAGEEXEC
17976 + cpu_set(cpu, next->context.cpu_user_cs_mask);
17979 + set_user_cs(next, cpu);
17983 diff -urNp linux-2.6.16.12/include/asm-i386/mmu.h linux-2.6.16.12/include/asm-i386/mmu.h
17984 --- linux-2.6.16.12/include/asm-i386/mmu.h 2006-05-01 15:14:26.000000000 -0400
17985 +++ linux-2.6.16.12/include/asm-i386/mmu.h 2006-05-01 20:17:34.000000000 -0400
17986 @@ -12,6 +12,17 @@ typedef struct {
17988 struct semaphore sem;
17991 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
17992 + unsigned long user_cs_base;
17993 + unsigned long user_cs_limit;
17995 +#if defined(CONFIG_PAX_PAGEEXEC) && defined(CONFIG_SMP)
17996 + cpumask_t cpu_user_cs_mask;
18004 diff -urNp linux-2.6.16.12/include/asm-i386/module.h linux-2.6.16.12/include/asm-i386/module.h
18005 --- linux-2.6.16.12/include/asm-i386/module.h 2006-05-01 15:14:26.000000000 -0400
18006 +++ linux-2.6.16.12/include/asm-i386/module.h 2006-05-01 20:17:34.000000000 -0400
18007 @@ -72,6 +72,12 @@ struct mod_arch_specific
18008 #define MODULE_STACKSIZE ""
18011 -#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE
18012 +#ifdef CONFIG_GRKERNSEC
18013 +#define MODULE_GRSEC "GRSECURITY "
18015 +#define MODULE_GRSEC ""
18018 +#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_STACKSIZE MODULE_GRSEC
18020 #endif /* _ASM_I386_MODULE_H */
18021 diff -urNp linux-2.6.16.12/include/asm-i386/page.h linux-2.6.16.12/include/asm-i386/page.h
18022 --- linux-2.6.16.12/include/asm-i386/page.h 2006-05-01 15:14:26.000000000 -0400
18023 +++ linux-2.6.16.12/include/asm-i386/page.h 2006-05-01 20:17:34.000000000 -0400
18024 @@ -57,7 +57,6 @@ typedef struct { unsigned long long pgpr
18025 typedef struct { unsigned long pte_low; } pte_t;
18026 typedef struct { unsigned long pgd; } pgd_t;
18027 typedef struct { unsigned long pgprot; } pgprot_t;
18028 -#define boot_pte_t pte_t /* or would you rather have a typedef */
18029 #define pte_val(x) ((x).pte_low)
18030 #define HPAGE_SHIFT 22
18032 @@ -118,6 +117,15 @@ extern int page_is_ram(unsigned long pag
18034 #define __KERNEL_START (__PAGE_OFFSET + __PHYSICAL_START)
18036 +#ifdef CONFIG_PAX_KERNEXEC
18037 +#define __KERNEL_TEXT_OFFSET (__PAGE_OFFSET + ((__PHYSICAL_START + ~(4*1024*1024)) & (4*1024*1024)))
18038 +#ifndef __ASSEMBLY__
18039 +extern unsigned char MODULES_VADDR[];
18040 +extern unsigned char MODULES_END[];
18043 +#define __KERNEL_TEXT_OFFSET (0)
18046 #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
18047 #define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE)
18048 @@ -139,6 +147,19 @@ extern int page_is_ram(unsigned long pag
18049 ((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
18050 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18052 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
18053 +#ifdef CONFIG_PAX_MPROTECT
18054 +#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18055 + ((current->mm->pax_flags & (MF_PAX_PAGEEXEC|MF_PAX_SEGMEXEC))?0:VM_EXEC))
18057 +#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & (MF_PAX_PAGEEXEC|MF_PAX_SEGMEXEC))?0:VM_EXEC))
18061 +#ifdef CONFIG_PAX_PAGEEXEC
18062 +#define CONFIG_ARCH_TRACK_EXEC_LIMIT 1
18065 #endif /* __KERNEL__ */
18067 #include <asm-generic/page.h>
18068 diff -urNp linux-2.6.16.12/include/asm-i386/pgalloc.h linux-2.6.16.12/include/asm-i386/pgalloc.h
18069 --- linux-2.6.16.12/include/asm-i386/pgalloc.h 2006-05-01 15:14:26.000000000 -0400
18070 +++ linux-2.6.16.12/include/asm-i386/pgalloc.h 2006-05-01 20:17:34.000000000 -0400
18073 #include <linux/config.h>
18074 #include <asm/fixmap.h>
18075 +#include <asm/desc.h>
18076 #include <linux/threads.h>
18077 #include <linux/mm.h> /* for struct page */
18079 #define pmd_populate_kernel(mm, pmd, pte) \
18080 - set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte)))
18081 + set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)))
18083 #define pmd_populate(mm, pmd, pte) \
18084 set_pmd(pmd, __pmd(_PAGE_TABLE + \
18085 diff -urNp linux-2.6.16.12/include/asm-i386/pgtable.h linux-2.6.16.12/include/asm-i386/pgtable.h
18086 --- linux-2.6.16.12/include/asm-i386/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18087 +++ linux-2.6.16.12/include/asm-i386/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18088 @@ -34,7 +34,6 @@ struct vm_area_struct;
18090 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
18091 extern unsigned long empty_zero_page[1024];
18092 -extern pgd_t swapper_pg_dir[1024];
18093 extern kmem_cache_t *pgd_cache;
18094 extern kmem_cache_t *pmd_cache;
18095 extern spinlock_t pgd_lock;
18096 @@ -59,6 +58,11 @@ void paging_init(void);
18097 # include <asm/pgtable-2level-defs.h>
18100 +extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
18101 +#ifdef CONFIG_X86_PAE
18102 +extern pmd_t swapper_pm_dir[PTRS_PER_PGD][PTRS_PER_PMD];
18105 #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
18106 #define PGDIR_MASK (~(PGDIR_SIZE-1))
18108 @@ -68,9 +72,11 @@ void paging_init(void);
18109 #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
18110 #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
18112 +#ifndef CONFIG_X86_PAE
18113 #define TWOLEVEL_PGDIR_SHIFT 22
18114 #define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
18115 #define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
18118 /* Just any arbitrary offset to the start of the vmalloc VM area: the
18119 * current 8MB value just means that there will be a 8MB "hole" after the
18120 @@ -141,17 +147,26 @@ void paging_init(void);
18122 #define PAGE_SHARED_EXEC \
18123 __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
18124 -#define PAGE_COPY_NOEXEC \
18125 - __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
18126 #define PAGE_COPY_EXEC \
18127 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
18128 -#define PAGE_COPY \
18130 #define PAGE_READONLY \
18131 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
18132 #define PAGE_READONLY_EXEC \
18133 __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
18135 +#ifdef CONFIG_PAX_PAGEEXEC
18136 +# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED)
18137 +# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
18138 +# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED)
18140 +# define PAGE_SHARED_NOEXEC PAGE_SHARED
18141 +# define PAGE_COPY_NOEXEC \
18142 + __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
18143 +# define PAGE_READONLY_NOEXEC PAGE_READONLY
18146 +#define PAGE_COPY \
18148 #define _PAGE_KERNEL \
18149 (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
18150 #define _PAGE_KERNEL_EXEC \
18151 @@ -176,18 +191,18 @@ extern unsigned long long __PAGE_KERNEL,
18152 * This is the closest we can get..
18154 #define __P000 PAGE_NONE
18155 -#define __P001 PAGE_READONLY
18156 -#define __P010 PAGE_COPY
18157 -#define __P011 PAGE_COPY
18158 +#define __P001 PAGE_READONLY_NOEXEC
18159 +#define __P010 PAGE_COPY_NOEXEC
18160 +#define __P011 PAGE_COPY_NOEXEC
18161 #define __P100 PAGE_READONLY_EXEC
18162 #define __P101 PAGE_READONLY_EXEC
18163 #define __P110 PAGE_COPY_EXEC
18164 #define __P111 PAGE_COPY_EXEC
18166 #define __S000 PAGE_NONE
18167 -#define __S001 PAGE_READONLY
18168 -#define __S010 PAGE_SHARED
18169 -#define __S011 PAGE_SHARED
18170 +#define __S001 PAGE_READONLY_NOEXEC
18171 +#define __S010 PAGE_SHARED_NOEXEC
18172 +#define __S011 PAGE_SHARED_NOEXEC
18173 #define __S100 PAGE_READONLY_EXEC
18174 #define __S101 PAGE_READONLY_EXEC
18175 #define __S110 PAGE_SHARED_EXEC
18176 @@ -432,6 +447,9 @@ extern void noexec_setup(const char *str
18178 #endif /* !__ASSEMBLY__ */
18180 +#define HAVE_ARCH_UNMAPPED_AREA
18181 +#define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
18183 #ifdef CONFIG_FLATMEM
18184 #define kern_addr_valid(addr) (1)
18185 #endif /* CONFIG_FLATMEM */
18186 diff -urNp linux-2.6.16.12/include/asm-i386/processor.h linux-2.6.16.12/include/asm-i386/processor.h
18187 --- linux-2.6.16.12/include/asm-i386/processor.h 2006-05-01 15:14:26.000000000 -0400
18188 +++ linux-2.6.16.12/include/asm-i386/processor.h 2006-05-01 20:17:34.000000000 -0400
18190 #include <linux/cache.h>
18191 #include <linux/config.h>
18192 #include <linux/threads.h>
18193 -#include <asm/percpu.h>
18195 /* flag for disabling the tsc */
18196 extern int tsc_disable;
18197 @@ -90,8 +89,6 @@ struct cpuinfo_x86 {
18199 extern struct cpuinfo_x86 boot_cpu_data;
18200 extern struct cpuinfo_x86 new_cpu_data;
18201 -extern struct tss_struct doublefault_tss;
18202 -DECLARE_PER_CPU(struct tss_struct, init_tss);
18205 extern struct cpuinfo_x86 cpu_data[];
18206 @@ -320,10 +317,19 @@ extern int bootloader_type;
18208 #define TASK_SIZE (PAGE_OFFSET)
18210 +#ifdef CONFIG_PAX_SEGMEXEC
18211 +#define SEGMEXEC_TASK_SIZE ((PAGE_OFFSET) / 2)
18214 /* This decides where the kernel will search for a free chunk of vm
18215 * space during mmap's.
18218 +#ifdef CONFIG_PAX_SEGMEXEC
18219 +#define TASK_UNMAPPED_BASE (PAGE_ALIGN((current->mm->pax_flags & MF_PAX_SEGMEXEC) ? SEGMEXEC_TASK_SIZE/3 : TASK_SIZE/3))
18221 #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3))
18224 #define HAVE_ARCH_PICK_MMAP_LAYOUT
18226 @@ -439,6 +445,9 @@ struct tss_struct {
18228 #define ARCH_MIN_TASKALIGN 16
18230 +extern struct tss_struct doublefault_tss;
18231 +extern struct tss_struct init_tss[NR_CPUS];
18233 struct thread_struct {
18234 /* cached TLS descriptors. */
18235 struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
18236 @@ -467,6 +476,7 @@ struct thread_struct {
18239 #define INIT_THREAD { \
18240 + .esp0 = sizeof(init_stack) + (long)&init_stack - 8, \
18241 .vm86_info = NULL, \
18242 .sysenter_cs = __KERNEL_CS, \
18243 .io_bitmap_ptr = NULL, \
18244 @@ -479,7 +489,7 @@ struct thread_struct {
18245 * be within the limit.
18247 #define INIT_TSS { \
18248 - .esp0 = sizeof(init_stack) + (long)&init_stack, \
18249 + .esp0 = sizeof(init_stack) + (long)&init_stack - 8, \
18250 .ss0 = __KERNEL_DS, \
18251 .ss1 = __KERNEL_CS, \
18252 .io_bitmap_base = INVALID_IO_BITMAP_OFFSET, \
18253 @@ -555,11 +565,7 @@ void show_trace(struct task_struct *task
18254 unsigned long get_wchan(struct task_struct *p);
18256 #define THREAD_SIZE_LONGS (THREAD_SIZE/sizeof(unsigned long))
18257 -#define KSTK_TOP(info) \
18259 - unsigned long *__ptr = (unsigned long *)(info); \
18260 - (unsigned long)(&__ptr[THREAD_SIZE_LONGS]); \
18262 +#define KSTK_TOP(info) ((info)->task.thread.esp0)
18265 * The below -8 is to reserve 8 bytes on top of the ring0 stack.
18266 @@ -574,7 +580,7 @@ unsigned long get_wchan(struct task_stru
18267 #define task_pt_regs(task) \
18269 struct pt_regs *__regs__; \
18270 - __regs__ = (struct pt_regs *)(KSTK_TOP(task_stack_page(task))-8); \
18271 + __regs__ = (struct pt_regs *)((task)->thread.esp0); \
18275 @@ -698,7 +704,7 @@ static inline void rep_nop(void)
18276 static inline void prefetch(const void *x)
18278 alternative_input(ASM_NOP4,
18279 - "prefetchnta (%1)",
18280 + "prefetchnta (%2)",
18284 @@ -712,7 +718,7 @@ static inline void prefetch(const void *
18285 static inline void prefetchw(const void *x)
18287 alternative_input(ASM_NOP4,
18288 - "prefetchw (%1)",
18289 + "prefetchw (%2)",
18293 diff -urNp linux-2.6.16.12/include/asm-i386/ptrace.h linux-2.6.16.12/include/asm-i386/ptrace.h
18294 --- linux-2.6.16.12/include/asm-i386/ptrace.h 2006-05-01 15:14:26.000000000 -0400
18295 +++ linux-2.6.16.12/include/asm-i386/ptrace.h 2006-05-01 20:17:34.000000000 -0400
18296 @@ -65,17 +65,18 @@ struct task_struct;
18297 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, int error_code);
18300 - * user_mode_vm(regs) determines whether a register set came from user mode.
18301 + * user_mode(regs) determines whether a register set came from user mode.
18302 * This is true if V8086 mode was enabled OR if the register set was from
18303 * protected mode with RPL-3 CS value. This tricky test checks that with
18304 * one comparison. Many places in the kernel can bypass this full check
18305 - * if they have already ruled out V8086 mode, so user_mode(regs) can be used.
18306 + * if they have already ruled out V8086 mode, so user_mode_novm(regs) can
18309 -static inline int user_mode(struct pt_regs *regs)
18310 +static inline int user_mode_novm(struct pt_regs *regs)
18312 return (regs->xcs & 3) != 0;
18314 -static inline int user_mode_vm(struct pt_regs *regs)
18315 +static inline int user_mode(struct pt_regs *regs)
18317 return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0;
18319 diff -urNp linux-2.6.16.12/include/asm-i386/system.h linux-2.6.16.12/include/asm-i386/system.h
18320 --- linux-2.6.16.12/include/asm-i386/system.h 2006-05-01 15:14:26.000000000 -0400
18321 +++ linux-2.6.16.12/include/asm-i386/system.h 2006-05-01 20:17:34.000000000 -0400
18323 #include <linux/kernel.h>
18324 #include <asm/segment.h>
18325 #include <asm/cpufeature.h>
18326 +#include <asm/page.h>
18327 #include <linux/bitops.h> /* for LOCK_PREFIX */
18330 @@ -151,7 +152,7 @@ static inline unsigned long get_limit(un
18331 unsigned long __limit;
18332 __asm__("lsll %1,%0"
18333 :"=r" (__limit):"r" (segment));
18334 - return __limit+1;
18338 #define nop() __asm__ __volatile__ ("nop")
18339 @@ -379,15 +380,15 @@ struct alt_instr {
18340 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
18341 ".section .altinstructions,\"a\"\n" \
18343 - " .long 661b\n" /* label */ \
18344 + " .long 661b + %c1\n" /* label */ \
18345 " .long 663f\n" /* new instruction */ \
18346 " .byte %c0\n" /* feature bit */ \
18347 " .byte 662b-661b\n" /* sourcelen */ \
18348 " .byte 664f-663f\n" /* replacementlen */ \
18350 - ".section .altinstr_replacement,\"ax\"\n" \
18351 + ".section .altinstr_replacement,\"a\"\n" \
18352 "663:\n\t" newinstr "\n664:\n" /* replacement */ \
18353 - ".previous" :: "i" (feature) : "memory")
18354 + ".previous" :: "i" (feature), "i" (__KERNEL_TEXT_OFFSET) : "memory")
18357 * Alternative inline assembly with input.
18358 @@ -403,15 +404,15 @@ struct alt_instr {
18359 asm volatile ("661:\n\t" oldinstr "\n662:\n" \
18360 ".section .altinstructions,\"a\"\n" \
18362 - " .long 661b\n" /* label */ \
18363 + " .long 661b + %c1\n" /* label */ \
18364 " .long 663f\n" /* new instruction */ \
18365 " .byte %c0\n" /* feature bit */ \
18366 " .byte 662b-661b\n" /* sourcelen */ \
18367 " .byte 664f-663f\n" /* replacementlen */ \
18369 - ".section .altinstr_replacement,\"ax\"\n" \
18370 + ".section .altinstr_replacement,\"a\"\n" \
18371 "663:\n\t" newinstr "\n664:\n" /* replacement */ \
18372 - ".previous" :: "i" (feature), ##input)
18373 + ".previous" :: "i" (feature), "i" (__KERNEL_TEXT_OFFSET), ##input)
18376 * Force strict CPU ordering.
18377 @@ -557,6 +558,6 @@ static inline void sched_cacheflush(void
18381 -extern unsigned long arch_align_stack(unsigned long sp);
18382 +#define arch_align_stack(x) (x)
18385 diff -urNp linux-2.6.16.12/include/asm-ia64/elf.h linux-2.6.16.12/include/asm-ia64/elf.h
18386 --- linux-2.6.16.12/include/asm-ia64/elf.h 2006-05-01 15:14:26.000000000 -0400
18387 +++ linux-2.6.16.12/include/asm-ia64/elf.h 2006-05-01 20:17:34.000000000 -0400
18388 @@ -163,6 +163,16 @@ typedef elf_greg_t elf_gregset_t[ELF_NGR
18389 typedef struct ia64_fpreg elf_fpreg_t;
18390 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
18392 +#ifdef CONFIG_PAX_ASLR
18393 +#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL)
18395 +#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18396 +#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
18397 +#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18398 +#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
18399 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18400 +#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 3*PAGE_SHIFT - 13)
18404 struct pt_regs; /* forward declaration... */
18405 diff -urNp linux-2.6.16.12/include/asm-ia64/page.h linux-2.6.16.12/include/asm-ia64/page.h
18406 --- linux-2.6.16.12/include/asm-ia64/page.h 2006-05-01 15:14:26.000000000 -0400
18407 +++ linux-2.6.16.12/include/asm-ia64/page.h 2006-05-01 20:17:34.000000000 -0400
18408 @@ -219,4 +219,13 @@ get_order (unsigned long size)
18409 (((current->personality & READ_IMPLIES_EXEC) != 0) \
18412 +#ifdef CONFIG_PAX_PAGEEXEC
18413 +#ifdef CONFIG_PAX_MPROTECT
18414 +#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18415 + ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18417 +#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18421 #endif /* _ASM_IA64_PAGE_H */
18422 diff -urNp linux-2.6.16.12/include/asm-ia64/pgtable.h linux-2.6.16.12/include/asm-ia64/pgtable.h
18423 --- linux-2.6.16.12/include/asm-ia64/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18424 +++ linux-2.6.16.12/include/asm-ia64/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18425 @@ -144,6 +144,17 @@
18426 #define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
18427 #define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
18428 #define PAGE_COPY_EXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX)
18430 +#ifdef CONFIG_PAX_PAGEEXEC
18431 +# define PAGE_SHARED_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW)
18432 +# define PAGE_READONLY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
18433 +# define PAGE_COPY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R)
18435 +# define PAGE_SHARED_NOEXEC PAGE_SHARED
18436 +# define PAGE_READONLY_NOEXEC PAGE_READONLY
18437 +# define PAGE_COPY_NOEXEC PAGE_COPY
18440 #define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX)
18441 #define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX)
18442 #define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX)
18443 diff -urNp linux-2.6.16.12/include/asm-ia64/processor.h linux-2.6.16.12/include/asm-ia64/processor.h
18444 --- linux-2.6.16.12/include/asm-ia64/processor.h 2006-05-01 15:14:26.000000000 -0400
18445 +++ linux-2.6.16.12/include/asm-ia64/processor.h 2006-05-01 20:17:34.000000000 -0400
18446 @@ -284,7 +284,7 @@ struct thread_struct {
18449 .map_base = DEFAULT_MAP_BASE, \
18450 - .rbs_bot = STACK_TOP - DEFAULT_USER_STACK_SIZE, \
18451 + .rbs_bot = __STACK_TOP - DEFAULT_USER_STACK_SIZE, \
18452 .task_size = DEFAULT_TASK_SIZE, \
18453 .last_fph_cpu = -1, \
18455 diff -urNp linux-2.6.16.12/include/asm-ia64/ustack.h linux-2.6.16.12/include/asm-ia64/ustack.h
18456 --- linux-2.6.16.12/include/asm-ia64/ustack.h 2006-05-01 15:14:26.000000000 -0400
18457 +++ linux-2.6.16.12/include/asm-ia64/ustack.h 2006-05-01 20:17:34.000000000 -0400
18459 #define MAX_USER_STACK_SIZE (RGN_MAP_LIMIT/2)
18460 /* Make a default stack size of 2GB */
18461 #define DEFAULT_USER_STACK_SIZE (1UL << 31)
18462 -#define STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT)
18463 +#define __STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT)
18465 #endif /* _ASM_IA64_USTACK_H */
18466 diff -urNp linux-2.6.16.12/include/asm-mips/a.out.h linux-2.6.16.12/include/asm-mips/a.out.h
18467 --- linux-2.6.16.12/include/asm-mips/a.out.h 2006-05-01 15:14:26.000000000 -0400
18468 +++ linux-2.6.16.12/include/asm-mips/a.out.h 2006-05-01 20:17:34.000000000 -0400
18469 @@ -36,10 +36,10 @@ struct exec
18472 #ifdef CONFIG_32BIT
18473 -#define STACK_TOP TASK_SIZE
18474 +#define __STACK_TOP TASK_SIZE
18476 #ifdef CONFIG_64BIT
18477 -#define STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
18478 +#define __STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE)
18482 diff -urNp linux-2.6.16.12/include/asm-mips/elf.h linux-2.6.16.12/include/asm-mips/elf.h
18483 --- linux-2.6.16.12/include/asm-mips/elf.h 2006-05-01 15:14:26.000000000 -0400
18484 +++ linux-2.6.16.12/include/asm-mips/elf.h 2006-05-01 20:17:34.000000000 -0400
18485 @@ -331,4 +331,15 @@ extern int dump_task_fpu(struct task_str
18486 #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2)
18489 +#ifdef CONFIG_PAX_ASLR
18490 +#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL)
18492 +#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18493 +#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
18494 +#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18495 +#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
18496 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18497 +#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT)
18500 #endif /* _ASM_ELF_H */
18501 diff -urNp linux-2.6.16.12/include/asm-mips/page.h linux-2.6.16.12/include/asm-mips/page.h
18502 --- linux-2.6.16.12/include/asm-mips/page.h 2006-05-01 15:14:26.000000000 -0400
18503 +++ linux-2.6.16.12/include/asm-mips/page.h 2006-05-01 20:17:34.000000000 -0400
18504 @@ -151,6 +151,15 @@ typedef struct { unsigned long pgprot; }
18505 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
18506 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18508 +#ifdef CONFIG_PAX_PAGEEXEC
18509 +#ifdef CONFIG_PAX_MPROTECT
18510 +#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18511 + ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18513 +#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18517 #define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE)
18518 #define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET)
18520 diff -urNp linux-2.6.16.12/include/asm-parisc/a.out.h linux-2.6.16.12/include/asm-parisc/a.out.h
18521 --- linux-2.6.16.12/include/asm-parisc/a.out.h 2006-05-01 15:14:26.000000000 -0400
18522 +++ linux-2.6.16.12/include/asm-parisc/a.out.h 2006-05-01 20:17:34.000000000 -0400
18523 @@ -22,7 +22,7 @@ struct exec
18524 /* XXX: STACK_TOP actually should be STACK_BOTTOM for parisc.
18527 -#define STACK_TOP TASK_SIZE
18528 +#define __STACK_TOP TASK_SIZE
18532 diff -urNp linux-2.6.16.12/include/asm-parisc/elf.h linux-2.6.16.12/include/asm-parisc/elf.h
18533 --- linux-2.6.16.12/include/asm-parisc/elf.h 2006-05-01 15:14:26.000000000 -0400
18534 +++ linux-2.6.16.12/include/asm-parisc/elf.h 2006-05-01 20:17:34.000000000 -0400
18535 @@ -337,6 +337,17 @@ struct pt_regs; /* forward declaration..
18537 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000)
18539 +#ifdef CONFIG_PAX_ASLR
18540 +#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000UL
18542 +#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18543 +#define PAX_DELTA_MMAP_LEN(tsk) 16
18544 +#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18545 +#define PAX_DELTA_EXEC_LEN(tsk) 16
18546 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18547 +#define PAX_DELTA_STACK_LEN(tsk) 16
18550 /* This yields a mask that user programs can use to figure out what
18551 instruction set this CPU supports. This could be done in user space,
18552 but it's not easy, and we've already done it here. */
18553 diff -urNp linux-2.6.16.12/include/asm-parisc/page.h linux-2.6.16.12/include/asm-parisc/page.h
18554 --- linux-2.6.16.12/include/asm-parisc/page.h 2006-05-01 15:14:26.000000000 -0400
18555 +++ linux-2.6.16.12/include/asm-parisc/page.h 2006-05-01 20:17:34.000000000 -0400
18556 @@ -150,6 +150,15 @@ extern int npmem_ranges;
18557 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
18558 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18560 +#ifdef CONFIG_PAX_PAGEEXEC
18561 +#ifdef CONFIG_PAX_MPROTECT
18562 +#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18563 + ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18565 +#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18569 #endif /* __KERNEL__ */
18571 #include <asm-generic/page.h>
18572 diff -urNp linux-2.6.16.12/include/asm-parisc/pgtable.h linux-2.6.16.12/include/asm-parisc/pgtable.h
18573 --- linux-2.6.16.12/include/asm-parisc/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18574 +++ linux-2.6.16.12/include/asm-parisc/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18575 @@ -212,6 +212,17 @@ extern void *vmalloc_start;
18576 #define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED)
18577 #define PAGE_COPY PAGE_EXECREAD
18578 #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED)
18580 +#ifdef CONFIG_PAX_PAGEEXEC
18581 +# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_ACCESSED)
18582 +# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
18583 +# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED)
18585 +# define PAGE_SHARED_NOEXEC PAGE_SHARED
18586 +# define PAGE_COPY_NOEXEC PAGE_COPY
18587 +# define PAGE_READONLY_NOEXEC PAGE_READONLY
18590 #define PAGE_KERNEL __pgprot(_PAGE_KERNEL)
18591 #define PAGE_KERNEL_RO __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
18592 #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
18593 diff -urNp linux-2.6.16.12/include/asm-powerpc/a.out.h linux-2.6.16.12/include/asm-powerpc/a.out.h
18594 --- linux-2.6.16.12/include/asm-powerpc/a.out.h 2006-05-01 15:14:26.000000000 -0400
18595 +++ linux-2.6.16.12/include/asm-powerpc/a.out.h 2006-05-01 20:17:34.000000000 -0400
18596 @@ -23,12 +23,12 @@ struct exec
18597 #define STACK_TOP_USER64 TASK_SIZE_USER64
18598 #define STACK_TOP_USER32 TASK_SIZE_USER32
18600 -#define STACK_TOP (test_thread_flag(TIF_32BIT) ? \
18601 +#define __STACK_TOP (test_thread_flag(TIF_32BIT) ? \
18602 STACK_TOP_USER32 : STACK_TOP_USER64)
18604 #else /* __powerpc64__ */
18606 -#define STACK_TOP TASK_SIZE
18607 +#define __STACK_TOP TASK_SIZE
18609 #endif /* __powerpc64__ */
18610 #endif /* __KERNEL__ */
18611 diff -urNp linux-2.6.16.12/include/asm-powerpc/elf.h linux-2.6.16.12/include/asm-powerpc/elf.h
18612 --- linux-2.6.16.12/include/asm-powerpc/elf.h 2006-05-01 15:14:26.000000000 -0400
18613 +++ linux-2.6.16.12/include/asm-powerpc/elf.h 2006-05-01 20:17:34.000000000 -0400
18614 @@ -176,6 +176,26 @@ typedef elf_vrreg_t elf_vrregset_t32[ELF
18616 #define ELF_ET_DYN_BASE (0x08000000)
18618 +#ifdef CONFIG_PAX_ASLR
18619 +#define PAX_ELF_ET_DYN_BASE(tsk) (0x10000000UL)
18621 +#ifdef __powerpc64__
18622 +#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18623 +#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
18624 +#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18625 +#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
18626 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18627 +#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 16 : 28)
18629 +#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18630 +#define PAX_DELTA_MMAP_LEN(tsk) 15
18631 +#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18632 +#define PAX_DELTA_EXEC_LEN(tsk) 15
18633 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18634 +#define PAX_DELTA_STACK_LEN(tsk) 15
18640 /* Common routine for both 32-bit and 64-bit processes */
18641 diff -urNp linux-2.6.16.12/include/asm-powerpc/page_64.h linux-2.6.16.12/include/asm-powerpc/page_64.h
18642 --- linux-2.6.16.12/include/asm-powerpc/page_64.h 2006-05-01 15:14:26.000000000 -0400
18643 +++ linux-2.6.16.12/include/asm-powerpc/page_64.h 2006-05-01 20:17:34.000000000 -0400
18644 @@ -169,6 +169,15 @@ extern unsigned int HPAGE_SHIFT;
18645 (test_thread_flag(TIF_32BIT) ? \
18646 VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64)
18648 +#ifdef CONFIG_PAX_PAGEEXEC
18649 +#ifdef CONFIG_PAX_MPROTECT
18650 +#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18651 + ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18653 +#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18657 #include <asm-generic/page.h>
18659 #endif /* __KERNEL__ */
18660 diff -urNp linux-2.6.16.12/include/asm-ppc/page.h linux-2.6.16.12/include/asm-ppc/page.h
18661 --- linux-2.6.16.12/include/asm-ppc/page.h 2006-05-01 15:14:26.000000000 -0400
18662 +++ linux-2.6.16.12/include/asm-ppc/page.h 2006-05-01 20:17:34.000000000 -0400
18663 @@ -175,5 +175,14 @@ extern __inline__ int get_order(unsigned
18664 /* We do define AT_SYSINFO_EHDR but don't use the gate mecanism */
18665 #define __HAVE_ARCH_GATE_AREA 1
18667 +#ifdef CONFIG_PAX_PAGEEXEC
18668 +#ifdef CONFIG_PAX_MPROTECT
18669 +#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18670 + ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18672 +#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18676 #endif /* __KERNEL__ */
18677 #endif /* _PPC_PAGE_H */
18678 diff -urNp linux-2.6.16.12/include/asm-ppc/pgtable.h linux-2.6.16.12/include/asm-ppc/pgtable.h
18679 --- linux-2.6.16.12/include/asm-ppc/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18680 +++ linux-2.6.16.12/include/asm-ppc/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18681 @@ -441,11 +441,21 @@ extern unsigned long ioremap_bot, iorema
18683 #define PAGE_NONE __pgprot(_PAGE_BASE)
18684 #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER)
18685 -#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
18686 +#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC)
18687 #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW)
18688 -#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC)
18689 +#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC | _PAGE_HWEXEC)
18690 #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER)
18691 -#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC)
18692 +#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC)
18694 +#if defined(CONFIG_PAX_PAGEEXEC) && !defined(CONFIG_40x) && !defined(CONFIG_44x)
18695 +# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_GUARDED)
18696 +# define PAGE_COPY_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
18697 +# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED)
18699 +# define PAGE_SHARED_NOEXEC PAGE_SHARED
18700 +# define PAGE_COPY_NOEXEC PAGE_COPY
18701 +# define PAGE_READONLY_NOEXEC PAGE_READONLY
18704 #define PAGE_KERNEL __pgprot(_PAGE_RAM)
18705 #define PAGE_KERNEL_NOCACHE __pgprot(_PAGE_IO)
18706 @@ -457,21 +467,21 @@ extern unsigned long ioremap_bot, iorema
18707 * This is the closest we can get..
18709 #define __P000 PAGE_NONE
18710 -#define __P001 PAGE_READONLY_X
18711 -#define __P010 PAGE_COPY
18712 -#define __P011 PAGE_COPY_X
18713 -#define __P100 PAGE_READONLY
18714 +#define __P001 PAGE_READONLY_NOEXEC
18715 +#define __P010 PAGE_COPY_NOEXEC
18716 +#define __P011 PAGE_COPY_NOEXEC
18717 +#define __P100 PAGE_READONLY_X
18718 #define __P101 PAGE_READONLY_X
18719 -#define __P110 PAGE_COPY
18720 +#define __P110 PAGE_COPY_X
18721 #define __P111 PAGE_COPY_X
18723 #define __S000 PAGE_NONE
18724 -#define __S001 PAGE_READONLY_X
18725 -#define __S010 PAGE_SHARED
18726 -#define __S011 PAGE_SHARED_X
18727 -#define __S100 PAGE_READONLY
18728 +#define __S001 PAGE_READONLY_NOEXEC
18729 +#define __S010 PAGE_SHARED_NOEXEC
18730 +#define __S011 PAGE_SHARED_NOEXEC
18731 +#define __S100 PAGE_READONLY_X
18732 #define __S101 PAGE_READONLY_X
18733 -#define __S110 PAGE_SHARED
18734 +#define __S110 PAGE_SHARED_X
18735 #define __S111 PAGE_SHARED_X
18737 #ifndef __ASSEMBLY__
18738 diff -urNp linux-2.6.16.12/include/asm-sparc/a.out.h linux-2.6.16.12/include/asm-sparc/a.out.h
18739 --- linux-2.6.16.12/include/asm-sparc/a.out.h 2006-05-01 15:14:26.000000000 -0400
18740 +++ linux-2.6.16.12/include/asm-sparc/a.out.h 2006-05-01 20:17:34.000000000 -0400
18741 @@ -91,7 +91,7 @@ struct relocation_info /* used when head
18743 #include <asm/page.h>
18745 -#define STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
18746 +#define __STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
18748 #endif /* __KERNEL__ */
18750 diff -urNp linux-2.6.16.12/include/asm-sparc/elf.h linux-2.6.16.12/include/asm-sparc/elf.h
18751 --- linux-2.6.16.12/include/asm-sparc/elf.h 2006-05-01 15:14:26.000000000 -0400
18752 +++ linux-2.6.16.12/include/asm-sparc/elf.h 2006-05-01 20:17:34.000000000 -0400
18753 @@ -145,6 +145,17 @@ typedef struct {
18755 #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE)
18757 +#ifdef CONFIG_PAX_ASLR
18758 +#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000UL
18760 +#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18761 +#define PAX_DELTA_MMAP_LEN(tsk) 16
18762 +#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18763 +#define PAX_DELTA_EXEC_LEN(tsk) 16
18764 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18765 +#define PAX_DELTA_STACK_LEN(tsk) 16
18768 /* This yields a mask that user programs can use to figure out what
18769 instruction set this cpu supports. This can NOT be done in userspace
18771 diff -urNp linux-2.6.16.12/include/asm-sparc/page.h linux-2.6.16.12/include/asm-sparc/page.h
18772 --- linux-2.6.16.12/include/asm-sparc/page.h 2006-05-01 15:14:26.000000000 -0400
18773 +++ linux-2.6.16.12/include/asm-sparc/page.h 2006-05-01 20:17:34.000000000 -0400
18774 @@ -162,6 +162,15 @@ extern unsigned long pfn_base;
18775 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
18776 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18778 +#ifdef CONFIG_PAX_PAGEEXEC
18779 +#ifdef CONFIG_PAX_MPROTECT
18780 +#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18781 + ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18783 +#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18787 #endif /* __KERNEL__ */
18789 #include <asm-generic/page.h>
18790 diff -urNp linux-2.6.16.12/include/asm-sparc/pgtable.h linux-2.6.16.12/include/asm-sparc/pgtable.h
18791 --- linux-2.6.16.12/include/asm-sparc/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18792 +++ linux-2.6.16.12/include/asm-sparc/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18793 @@ -50,6 +50,13 @@ BTFIXUPDEF_INT(page_none)
18794 BTFIXUPDEF_INT(page_shared)
18795 BTFIXUPDEF_INT(page_copy)
18796 BTFIXUPDEF_INT(page_readonly)
18798 +#ifdef CONFIG_PAX_PAGEEXEC
18799 +BTFIXUPDEF_INT(page_shared_noexec)
18800 +BTFIXUPDEF_INT(page_copy_noexec)
18801 +BTFIXUPDEF_INT(page_readonly_noexec)
18804 BTFIXUPDEF_INT(page_kernel)
18806 #define PMD_SHIFT SUN4C_PMD_SHIFT
18807 @@ -71,6 +78,16 @@ BTFIXUPDEF_INT(page_kernel)
18808 #define PAGE_COPY __pgprot(BTFIXUP_INT(page_copy))
18809 #define PAGE_READONLY __pgprot(BTFIXUP_INT(page_readonly))
18811 +#ifdef CONFIG_PAX_PAGEEXEC
18812 +# define PAGE_SHARED_NOEXEC __pgprot(BTFIXUP_INT(page_shared_noexec))
18813 +# define PAGE_COPY_NOEXEC __pgprot(BTFIXUP_INT(page_copy_noexec))
18814 +# define PAGE_READONLY_NOEXEC __pgprot(BTFIXUP_INT(page_readonly_noexec))
18816 +# define PAGE_SHARED_NOEXEC PAGE_SHARED
18817 +# define PAGE_COPY_NOEXEC PAGE_COPY
18818 +# define PAGE_READONLY_NOEXEC PAGE_READONLY
18821 extern unsigned long page_kernel;
18824 diff -urNp linux-2.6.16.12/include/asm-sparc/pgtsrmmu.h linux-2.6.16.12/include/asm-sparc/pgtsrmmu.h
18825 --- linux-2.6.16.12/include/asm-sparc/pgtsrmmu.h 2006-05-01 15:14:26.000000000 -0400
18826 +++ linux-2.6.16.12/include/asm-sparc/pgtsrmmu.h 2006-05-01 20:17:34.000000000 -0400
18827 @@ -115,6 +115,16 @@
18828 SRMMU_EXEC | SRMMU_REF)
18829 #define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \
18830 SRMMU_EXEC | SRMMU_REF)
18832 +#ifdef CONFIG_PAX_PAGEEXEC
18833 +#define SRMMU_PAGE_SHARED_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
18834 + SRMMU_WRITE | SRMMU_REF)
18835 +#define SRMMU_PAGE_COPY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
18837 +#define SRMMU_PAGE_RDONLY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \
18841 #define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \
18842 SRMMU_DIRTY | SRMMU_REF)
18844 diff -urNp linux-2.6.16.12/include/asm-sparc/uaccess.h linux-2.6.16.12/include/asm-sparc/uaccess.h
18845 --- linux-2.6.16.12/include/asm-sparc/uaccess.h 2006-05-01 15:14:26.000000000 -0400
18846 +++ linux-2.6.16.12/include/asm-sparc/uaccess.h 2006-05-01 20:17:34.000000000 -0400
18848 * No one can read/write anything from userland in the kernel space by setting
18849 * large size and address near to PAGE_OFFSET - a fault will break his intentions.
18851 -#define __user_ok(addr, size) ({ (void)(size); (addr) < STACK_TOP; })
18852 +#define __user_ok(addr, size) ({ (void)(size); (addr) < __STACK_TOP; })
18853 #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
18854 #define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size)))
18855 #define access_ok(type, addr, size) \
18856 diff -urNp linux-2.6.16.12/include/asm-sparc64/a.out.h linux-2.6.16.12/include/asm-sparc64/a.out.h
18857 --- linux-2.6.16.12/include/asm-sparc64/a.out.h 2006-05-01 15:14:26.000000000 -0400
18858 +++ linux-2.6.16.12/include/asm-sparc64/a.out.h 2006-05-01 20:17:34.000000000 -0400
18859 @@ -95,7 +95,7 @@ struct relocation_info /* used when head
18863 -#define STACK_TOP (test_thread_flag(TIF_32BIT) ? 0xf0000000 : 0x80000000000L)
18864 +#define __STACK_TOP (test_thread_flag(TIF_32BIT) ? 0xf0000000 : 0x80000000000L)
18868 diff -urNp linux-2.6.16.12/include/asm-sparc64/elf.h linux-2.6.16.12/include/asm-sparc64/elf.h
18869 --- linux-2.6.16.12/include/asm-sparc64/elf.h 2006-05-01 15:14:26.000000000 -0400
18870 +++ linux-2.6.16.12/include/asm-sparc64/elf.h 2006-05-01 20:17:34.000000000 -0400
18871 @@ -140,6 +140,16 @@ typedef struct {
18872 #define ELF_ET_DYN_BASE 0x0000010000000000UL
18875 +#ifdef CONFIG_PAX_ASLR
18876 +#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_32BIT) ? 0x10000UL : 0x100000UL)
18878 +#define PAX_DELTA_MMAP_LSB(tsk) (PAGE_SHIFT + 1)
18879 +#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 14 : 28 )
18880 +#define PAX_DELTA_EXEC_LSB(tsk) (PAGE_SHIFT + 1)
18881 +#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 14 : 28 )
18882 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18883 +#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 15 : 29 )
18886 /* This yields a mask that user programs can use to figure out what
18887 instruction set this cpu supports. */
18888 diff -urNp linux-2.6.16.12/include/asm-sparc64/page.h linux-2.6.16.12/include/asm-sparc64/page.h
18889 --- linux-2.6.16.12/include/asm-sparc64/page.h 2006-05-01 15:14:26.000000000 -0400
18890 +++ linux-2.6.16.12/include/asm-sparc64/page.h 2006-05-01 20:17:34.000000000 -0400
18891 @@ -145,6 +145,15 @@ extern unsigned long page_to_pfn(struct
18892 #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
18893 VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18895 +#ifdef CONFIG_PAX_PAGEEXEC
18896 +#ifdef CONFIG_PAX_MPROTECT
18897 +#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18898 + ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18900 +#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18904 #endif /* !(__KERNEL__) */
18906 #include <asm-generic/page.h>
18907 diff -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
18908 --- linux-2.6.16.12/include/asm-x86_64/a.out.h 2006-05-01 15:14:26.000000000 -0400
18909 +++ linux-2.6.16.12/include/asm-x86_64/a.out.h 2006-05-01 20:17:34.000000000 -0400
18910 @@ -21,7 +21,7 @@ struct exec
18913 #include <linux/thread_info.h>
18914 -#define STACK_TOP TASK_SIZE
18915 +#define __STACK_TOP TASK_SIZE
18918 #endif /* __A_OUT_GNU_H__ */
18919 diff -urNp linux-2.6.16.12/include/asm-x86_64/elf.h linux-2.6.16.12/include/asm-x86_64/elf.h
18920 --- linux-2.6.16.12/include/asm-x86_64/elf.h 2006-05-01 15:14:26.000000000 -0400
18921 +++ linux-2.6.16.12/include/asm-x86_64/elf.h 2006-05-01 20:17:34.000000000 -0400
18922 @@ -89,6 +89,17 @@ typedef struct user_i387_struct elf_fpre
18924 #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
18926 +#ifdef CONFIG_PAX_ASLR
18927 +#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_IA32) ? 0x08048000UL : 0x400000UL)
18929 +#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT
18930 +#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
18931 +#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT
18932 +#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
18933 +#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT
18934 +#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 32)
18937 /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is
18938 now struct_user_regs, they are different). Assumes current is the process
18940 diff -urNp linux-2.6.16.12/include/asm-x86_64/ia32.h linux-2.6.16.12/include/asm-x86_64/ia32.h
18941 --- linux-2.6.16.12/include/asm-x86_64/ia32.h 2006-05-01 15:14:26.000000000 -0400
18942 +++ linux-2.6.16.12/include/asm-x86_64/ia32.h 2006-05-01 20:17:34.000000000 -0400
18943 @@ -157,7 +157,13 @@ struct ustat32 {
18947 -#define IA32_STACK_TOP IA32_PAGE_OFFSET
18948 +#ifdef CONFIG_PAX_RANDUSTACK
18949 +#define IA32_DELTA_STACK (current->mm->delta_stack)
18951 +#define IA32_DELTA_STACK 0UL
18954 +#define IA32_STACK_TOP (IA32_PAGE_OFFSET - IA32_DELTA_STACK)
18958 diff -urNp linux-2.6.16.12/include/asm-x86_64/page.h linux-2.6.16.12/include/asm-x86_64/page.h
18959 --- linux-2.6.16.12/include/asm-x86_64/page.h 2006-05-01 15:14:26.000000000 -0400
18960 +++ linux-2.6.16.12/include/asm-x86_64/page.h 2006-05-01 20:17:34.000000000 -0400
18961 @@ -136,6 +136,15 @@ typedef struct { unsigned long pgprot; }
18962 (((current->personality & READ_IMPLIES_EXEC) ? VM_EXEC : 0 ) | \
18963 VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
18965 +#ifdef CONFIG_PAX_PAGEEXEC
18966 +#ifdef CONFIG_PAX_MPROTECT
18967 +#define __VM_STACK_FLAGS (((current->mm->pax_flags & MF_PAX_MPROTECT)?0:VM_MAYEXEC) | \
18968 + ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18970 +#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->mm->pax_flags & MF_PAX_PAGEEXEC)?0:VM_EXEC))
18974 #define __HAVE_ARCH_GATE_AREA 1
18976 #endif /* __KERNEL__ */
18977 diff -urNp linux-2.6.16.12/include/asm-x86_64/pgalloc.h linux-2.6.16.12/include/asm-x86_64/pgalloc.h
18978 --- linux-2.6.16.12/include/asm-x86_64/pgalloc.h 2006-05-01 15:14:26.000000000 -0400
18979 +++ linux-2.6.16.12/include/asm-x86_64/pgalloc.h 2006-05-01 20:17:34.000000000 -0400
18981 #include <linux/mm.h>
18983 #define pmd_populate_kernel(mm, pmd, pte) \
18984 - set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte)))
18985 + set_pmd(pmd, __pmd(_KERNPG_TABLE | __pa(pte)))
18986 #define pud_populate(mm, pud, pmd) \
18987 set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd)))
18988 #define pgd_populate(mm, pgd, pud) \
18989 diff -urNp linux-2.6.16.12/include/asm-x86_64/pgtable.h linux-2.6.16.12/include/asm-x86_64/pgtable.h
18990 --- linux-2.6.16.12/include/asm-x86_64/pgtable.h 2006-05-01 15:14:26.000000000 -0400
18991 +++ linux-2.6.16.12/include/asm-x86_64/pgtable.h 2006-05-01 20:17:34.000000000 -0400
18992 @@ -180,6 +180,10 @@ static inline pte_t ptep_get_and_clear_f
18993 #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
18994 #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX)
18995 #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
18997 +#define PAGE_READONLY_NOEXEC PAGE_READONLY
18998 +#define PAGE_SHARED_NOEXEC PAGE_SHARED
19000 #define __PAGE_KERNEL \
19001 (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
19002 #define __PAGE_KERNEL_EXEC \
19003 @@ -268,7 +272,13 @@ static inline pte_t pfn_pte(unsigned lon
19004 #define __LARGE_PTE (_PAGE_PSE|_PAGE_PRESENT)
19005 static inline int pte_user(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
19006 static inline int pte_read(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
19007 -static inline int pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_USER; }
19008 +extern inline int pte_exec(pte_t pte)
19010 + if (__supported_pte_mask & _PAGE_NX)
19011 + return pte_val(pte) & _PAGE_NX;
19013 + return pte_val(pte) & _PAGE_USER;
19015 static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; }
19016 static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; }
19017 static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; }
19018 @@ -276,12 +286,26 @@ static inline int pte_file(pte_t pte) {
19019 static inline int pte_huge(pte_t pte) { return (pte_val(pte) & __LARGE_PTE) == __LARGE_PTE; }
19021 static inline pte_t pte_rdprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
19022 -static inline pte_t pte_exprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER)); return pte; }
19023 +extern inline pte_t pte_exprotect(pte_t pte)
19025 + if (__supported_pte_mask & _PAGE_NX)
19026 + set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_NX));
19028 + set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_USER));
19031 static inline pte_t pte_mkclean(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_DIRTY)); return pte; }
19032 static inline pte_t pte_mkold(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_ACCESSED)); return pte; }
19033 static inline pte_t pte_wrprotect(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) & ~_PAGE_RW)); return pte; }
19034 static inline pte_t pte_mkread(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
19035 -static inline pte_t pte_mkexec(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER)); return pte; }
19036 +extern inline pte_t pte_mkexec(pte_t pte)
19038 + if (__supported_pte_mask & _PAGE_NX)
19039 + set_pte(&pte, __pte(pte_val(pte) | _PAGE_NX));
19041 + set_pte(&pte, __pte(pte_val(pte) | _PAGE_USER));
19044 static inline pte_t pte_mkdirty(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_DIRTY)); return pte; }
19045 static inline pte_t pte_mkyoung(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_ACCESSED)); return pte; }
19046 static inline pte_t pte_mkwrite(pte_t pte) { set_pte(&pte, __pte(pte_val(pte) | _PAGE_RW)); return pte; }
19047 diff -urNp linux-2.6.16.12/include/asm-x86_64/system.h linux-2.6.16.12/include/asm-x86_64/system.h
19048 --- linux-2.6.16.12/include/asm-x86_64/system.h 2006-05-01 15:14:26.000000000 -0400
19049 +++ linux-2.6.16.12/include/asm-x86_64/system.h 2006-05-01 20:17:34.000000000 -0400
19050 @@ -372,6 +372,6 @@ static inline unsigned long __cmpxchg(vo
19052 void cpu_idle_wait(void);
19054 -extern unsigned long arch_align_stack(unsigned long sp);
19055 +#define arch_align_stack(x) (x)
19058 diff -urNp linux-2.6.16.12/include/linux/a.out.h linux-2.6.16.12/include/linux/a.out.h
19059 --- linux-2.6.16.12/include/linux/a.out.h 2006-05-01 15:14:26.000000000 -0400
19060 +++ linux-2.6.16.12/include/linux/a.out.h 2006-05-01 20:17:34.000000000 -0400
19063 #include <asm/a.out.h>
19065 +#ifdef CONFIG_PAX_RANDUSTACK
19066 +#define __DELTA_STACK (current->mm->delta_stack)
19068 +#define __DELTA_STACK 0UL
19072 +#define STACK_TOP (__STACK_TOP - __DELTA_STACK)
19075 #endif /* __STRUCT_EXEC_OVERRIDE__ */
19077 /* these go in the N_MACHTYPE field */
19078 @@ -37,6 +47,14 @@ enum machine_type {
19079 M_MIPS2 = 152 /* MIPS R6000/R4000 binary */
19082 +/* Constants for the N_FLAGS field */
19083 +#define F_PAX_PAGEEXEC 1 /* Paging based non-executable pages */
19084 +#define F_PAX_EMUTRAMP 2 /* Emulate trampolines */
19085 +#define F_PAX_MPROTECT 4 /* Restrict mprotect() */
19086 +#define F_PAX_RANDMMAP 8 /* Randomize mmap() base */
19087 +/*#define F_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */
19088 +#define F_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */
19090 #if !defined (N_MAGIC)
19091 #define N_MAGIC(exec) ((exec).a_info & 0xffff)
19093 diff -urNp linux-2.6.16.12/include/linux/binfmts.h linux-2.6.16.12/include/linux/binfmts.h
19094 --- linux-2.6.16.12/include/linux/binfmts.h 2006-05-01 15:14:26.000000000 -0400
19095 +++ linux-2.6.16.12/include/linux/binfmts.h 2006-05-01 20:17:34.000000000 -0400
19096 @@ -7,10 +7,10 @@ struct pt_regs;
19099 * MAX_ARG_PAGES defines the number of pages allocated for arguments
19100 - * and envelope for the new program. 32 should suffice, this gives
19101 - * a maximum env+arg of 128kB w/4KB pages!
19102 + * and envelope for the new program. 33 should suffice, this gives
19103 + * a maximum env+arg of 132kB w/4KB pages!
19105 -#define MAX_ARG_PAGES 32
19106 +#define MAX_ARG_PAGES 33
19108 /* sizeof(linux_binprm->buf) */
19109 #define BINPRM_BUF_SIZE 128
19110 @@ -38,6 +38,7 @@ struct linux_binprm{
19111 unsigned interp_flags;
19112 unsigned interp_data;
19113 unsigned long loader, exec;
19117 #define BINPRM_FLAGS_ENFORCE_NONDUMP_BIT 0
19118 @@ -87,5 +88,8 @@ extern void compute_creds(struct linux_b
19119 extern int do_coredump(long signr, int exit_code, struct pt_regs * regs);
19120 extern int set_binfmt(struct linux_binfmt *new);
19122 +void pax_report_fault(struct pt_regs *regs, void *pc, void *sp);
19123 +void pax_report_insns(void *pc, void *sp);
19125 #endif /* __KERNEL__ */
19126 #endif /* _LINUX_BINFMTS_H */
19127 diff -urNp linux-2.6.16.12/include/linux/capability.h linux-2.6.16.12/include/linux/capability.h
19128 --- linux-2.6.16.12/include/linux/capability.h 2006-05-01 15:14:26.000000000 -0400
19129 +++ linux-2.6.16.12/include/linux/capability.h 2006-05-01 20:17:34.000000000 -0400
19130 @@ -358,6 +358,7 @@ static inline kernel_cap_t cap_invert(ke
19131 #define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)
19133 extern int capable(int cap);
19134 +extern int capable_nolog(int cap);
19136 #endif /* __KERNEL__ */
19138 diff -urNp linux-2.6.16.12/include/linux/elf.h linux-2.6.16.12/include/linux/elf.h
19139 --- linux-2.6.16.12/include/linux/elf.h 2006-05-01 15:14:26.000000000 -0400
19140 +++ linux-2.6.16.12/include/linux/elf.h 2006-05-01 20:17:34.000000000 -0400
19142 #include <linux/auxvec.h>
19143 #include <asm/elf.h>
19145 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
19146 +#undef elf_read_implies_exec
19149 #ifndef elf_read_implies_exec
19150 /* Executables for which elf_read_implies_exec() returns TRUE will
19151 have the READ_IMPLIES_EXEC personality flag set automatically.
19152 @@ -46,6 +50,16 @@ typedef __s64 Elf64_Sxword;
19154 #define PT_GNU_STACK (PT_LOOS + 0x474e551)
19156 +#define PT_PAX_FLAGS (PT_LOOS + 0x5041580)
19158 +/* Constants for the e_flags field */
19159 +#define EF_PAX_PAGEEXEC 1 /* Paging based non-executable pages */
19160 +#define EF_PAX_EMUTRAMP 2 /* Emulate trampolines */
19161 +#define EF_PAX_MPROTECT 4 /* Restrict mprotect() */
19162 +#define EF_PAX_RANDMMAP 8 /* Randomize mmap() base */
19163 +/*#define EF_PAX_RANDEXEC 16*/ /* Randomize ET_EXEC base */
19164 +#define EF_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */
19166 /* These constants define the different elf file types */
19169 @@ -138,6 +152,8 @@ typedef __s64 Elf64_Sxword;
19170 #define DT_DEBUG 21
19171 #define DT_TEXTREL 22
19172 #define DT_JMPREL 23
19173 +#define DT_FLAGS 30
19174 + #define DF_TEXTREL 0x00000004
19175 #define DT_LOPROC 0x70000000
19176 #define DT_HIPROC 0x7fffffff
19178 @@ -267,6 +283,19 @@ typedef struct elf64_hdr {
19182 +#define PF_PAGEEXEC (1U << 4) /* Enable PAGEEXEC */
19183 +#define PF_NOPAGEEXEC (1U << 5) /* Disable PAGEEXEC */
19184 +#define PF_SEGMEXEC (1U << 6) /* Enable SEGMEXEC */
19185 +#define PF_NOSEGMEXEC (1U << 7) /* Disable SEGMEXEC */
19186 +#define PF_MPROTECT (1U << 8) /* Enable MPROTECT */
19187 +#define PF_NOMPROTECT (1U << 9) /* Disable MPROTECT */
19188 +/*#define PF_RANDEXEC (1U << 10)*/ /* Enable RANDEXEC */
19189 +/*#define PF_NORANDEXEC (1U << 11)*/ /* Disable RANDEXEC */
19190 +#define PF_EMUTRAMP (1U << 12) /* Enable EMUTRAMP */
19191 +#define PF_NOEMUTRAMP (1U << 13) /* Disable EMUTRAMP */
19192 +#define PF_RANDMMAP (1U << 14) /* Enable RANDMMAP */
19193 +#define PF_NORANDMMAP (1U << 15) /* Disable RANDMMAP */
19195 typedef struct elf32_phdr{
19197 Elf32_Off p_offset;
19198 @@ -359,6 +388,8 @@ typedef struct elf64_shdr {
19204 #define ELFMAG0 0x7f /* EI_MAG */
19205 #define ELFMAG1 'E'
19206 #define ELFMAG2 'L'
19207 @@ -415,6 +446,7 @@ extern Elf32_Dyn _DYNAMIC [];
19208 #define elfhdr elf32_hdr
19209 #define elf_phdr elf32_phdr
19210 #define elf_note elf32_note
19211 +#define elf_dyn Elf32_Dyn
19215 @@ -422,6 +454,7 @@ extern Elf64_Dyn _DYNAMIC [];
19216 #define elfhdr elf64_hdr
19217 #define elf_phdr elf64_phdr
19218 #define elf_note elf64_note
19219 +#define elf_dyn Elf64_Dyn
19223 diff -urNp linux-2.6.16.12/include/linux/gracl.h linux-2.6.16.12/include/linux/gracl.h
19224 --- linux-2.6.16.12/include/linux/gracl.h 1969-12-31 19:00:00.000000000 -0500
19225 +++ linux-2.6.16.12/include/linux/gracl.h 2006-05-01 20:17:34.000000000 -0400
19230 +#include <linux/grdefs.h>
19231 +#include <linux/resource.h>
19232 +#include <linux/dcache.h>
19233 +#include <asm/resource.h>
19235 +/* Major status information */
19237 +#define GR_VERSION "grsecurity 2.1.9"
19238 +#define GRSECURITY_VERSION 0x219
19253 +/* Password setup definitions
19254 + * kernel/grhash.c */
19257 + GR_SALT_LEN = 16,
19262 + GR_SPROLE_LEN = 64,
19265 +#define GR_NLIMITS (RLIMIT_LOCKS + 2)
19267 +/* Begin Data Structures */
19269 +struct sprole_pw {
19270 + unsigned char *rolename;
19271 + unsigned char salt[GR_SALT_LEN];
19272 + unsigned char sum[GR_SHA_LEN]; /* 256-bit SHA hash of the password */
19275 +struct name_entry {
19281 + struct name_entry *prev;
19282 + struct name_entry *next;
19285 +struct inodev_entry {
19286 + struct name_entry *nentry;
19287 + struct inodev_entry *prev;
19288 + struct inodev_entry *next;
19291 +struct acl_role_db {
19292 + struct acl_role_label **r_hash;
19296 +struct inodev_db {
19297 + struct inodev_entry **i_hash;
19302 + struct name_entry **n_hash;
19306 +struct crash_uid {
19308 + unsigned long expires;
19311 +struct gr_hash_struct {
19313 + void **nametable;
19315 + __u32 table_size;
19320 +/* Userspace Grsecurity ACL data structures */
19322 +struct acl_subject_label {
19330 + struct rlimit res[GR_NLIMITS];
19333 + __u8 user_trans_type;
19334 + __u8 group_trans_type;
19335 + uid_t *user_transitions;
19336 + gid_t *group_transitions;
19337 + __u16 user_trans_num;
19338 + __u16 group_trans_num;
19340 + __u32 ip_proto[8];
19342 + struct acl_ip_label **ips;
19346 + unsigned long expires;
19348 + struct acl_subject_label *parent_subject;
19349 + struct gr_hash_struct *hash;
19350 + struct acl_subject_label *prev;
19351 + struct acl_subject_label *next;
19353 + struct acl_object_label **obj_hash;
19354 + __u32 obj_hash_size;
19358 +struct role_allowed_ip {
19362 + struct role_allowed_ip *prev;
19363 + struct role_allowed_ip *next;
19366 +struct role_transition {
19369 + struct role_transition *prev;
19370 + struct role_transition *next;
19373 +struct acl_role_label {
19378 + __u16 auth_attempts;
19379 + unsigned long expires;
19381 + struct acl_subject_label *root_label;
19382 + struct gr_hash_struct *hash;
19384 + struct acl_role_label *prev;
19385 + struct acl_role_label *next;
19387 + struct role_transition *transitions;
19388 + struct role_allowed_ip *allowed_ips;
19389 + uid_t *domain_children;
19390 + __u16 domain_child_num;
19392 + struct acl_subject_label **subj_hash;
19393 + __u32 subj_hash_size;
19396 +struct user_acl_role_db {
19397 + struct acl_role_label **r_table;
19398 + __u32 num_pointers; /* Number of allocations to track */
19399 + __u32 num_roles; /* Number of roles */
19400 + __u32 num_domain_children; /* Number of domain children */
19401 + __u32 num_subjects; /* Number of subjects */
19402 + __u32 num_objects; /* Number of objects */
19405 +struct acl_object_label {
19411 + struct acl_subject_label *nested;
19412 + struct acl_object_label *globbed;
19414 + /* next two structures not used */
19416 + struct acl_object_label *prev;
19417 + struct acl_object_label *next;
19420 +struct acl_ip_label {
19429 + /* next two structures not used */
19431 + struct acl_ip_label *prev;
19432 + struct acl_ip_label *next;
19436 + struct user_acl_role_db role_db;
19437 + unsigned char pw[GR_PW_LEN];
19438 + unsigned char salt[GR_SALT_LEN];
19439 + unsigned char sum[GR_SHA_LEN];
19440 + unsigned char sp_role[GR_SPROLE_LEN];
19441 + struct sprole_pw *sprole_pws;
19442 + dev_t segv_device;
19443 + ino_t segv_inode;
19445 + __u16 num_sprole_pws;
19449 +struct gr_arg_wrapper {
19450 + struct gr_arg *arg;
19455 +struct subject_map {
19456 + struct acl_subject_label *user;
19457 + struct acl_subject_label *kernel;
19458 + struct subject_map *prev;
19459 + struct subject_map *next;
19462 +struct acl_subj_map_db {
19463 + struct subject_map **s_hash;
19467 +/* End Data Structures Section */
19469 +/* Hash functions generated by empirical testing by Brad Spengler
19470 + Makes good use of the low bits of the inode. Generally 0-1 times
19471 + in loop for successful match. 0-3 for unsuccessful match.
19472 + Shift/add algorithm with modulus of table size and an XOR*/
19474 +static __inline__ unsigned int
19475 +rhash(const uid_t uid, const __u16 type, const unsigned int sz)
19477 + return (((uid << type) + (uid ^ type)) % sz);
19480 + static __inline__ unsigned int
19481 +shash(const struct acl_subject_label *userp, const unsigned int sz)
19483 + return ((const unsigned long)userp % sz);
19486 +static __inline__ unsigned int
19487 +fhash(const ino_t ino, const dev_t dev, const unsigned int sz)
19489 + return (((ino + dev) ^ ((ino << 13) + (ino << 23) + (dev << 9))) % sz);
19492 +static __inline__ unsigned int
19493 +nhash(const char *name, const __u16 len, const unsigned int sz)
19495 + return full_name_hash(name, len) % sz;
19498 +#define FOR_EACH_ROLE_START(role,iter) \
19501 + while (iter < acl_role_set.r_size) { \
19502 + if (role == NULL) \
19503 + role = acl_role_set.r_hash[iter]; \
19504 + if (role == NULL) { \
19509 +#define FOR_EACH_ROLE_END(role,iter) \
19510 + role = role->next; \
19511 + if (role == NULL) \
19515 +#define FOR_EACH_SUBJECT_START(role,subj,iter) \
19518 + while (iter < role->subj_hash_size) { \
19519 + if (subj == NULL) \
19520 + subj = role->subj_hash[iter]; \
19521 + if (subj == NULL) { \
19526 +#define FOR_EACH_SUBJECT_END(subj,iter) \
19527 + subj = subj->next; \
19528 + if (subj == NULL) \
19533 +#define FOR_EACH_NESTED_SUBJECT_START(role,subj) \
19534 + subj = role->hash->first; \
19535 + while (subj != NULL) {
19537 +#define FOR_EACH_NESTED_SUBJECT_END(subj) \
19538 + subj = subj->next; \
19543 diff -urNp linux-2.6.16.12/include/linux/gralloc.h linux-2.6.16.12/include/linux/gralloc.h
19544 --- linux-2.6.16.12/include/linux/gralloc.h 1969-12-31 19:00:00.000000000 -0500
19545 +++ linux-2.6.16.12/include/linux/gralloc.h 2006-05-01 20:17:34.000000000 -0400
19547 +#ifndef __GRALLOC_H
19548 +#define __GRALLOC_H
19550 +void acl_free_all(void);
19551 +int acl_alloc_stack_init(unsigned long size);
19552 +void *acl_alloc(unsigned long len);
19555 diff -urNp linux-2.6.16.12/include/linux/grdefs.h linux-2.6.16.12/include/linux/grdefs.h
19556 --- linux-2.6.16.12/include/linux/grdefs.h 1969-12-31 19:00:00.000000000 -0500
19557 +++ linux-2.6.16.12/include/linux/grdefs.h 2006-05-01 20:17:34.000000000 -0400
19562 +/* Begin grsecurity status declarations */
19566 + GR_STATUS_INIT = 0x00 // disabled state
19569 +/* Begin ACL declarations */
19574 + GR_ROLE_USER = 0x0001,
19575 + GR_ROLE_GROUP = 0x0002,
19576 + GR_ROLE_DEFAULT = 0x0004,
19577 + GR_ROLE_SPECIAL = 0x0008,
19578 + GR_ROLE_AUTH = 0x0010,
19579 + GR_ROLE_NOPW = 0x0020,
19580 + GR_ROLE_GOD = 0x0040,
19581 + GR_ROLE_LEARN = 0x0080,
19582 + GR_ROLE_TPE = 0x0100,
19583 + GR_ROLE_DOMAIN = 0x0200,
19584 + GR_ROLE_PAM = 0x0400
19587 +/* ACL Subject and Object mode flags */
19589 + GR_DELETED = 0x80000000
19592 +/* ACL Object-only mode flags */
19594 + GR_READ = 0x00000001,
19595 + GR_APPEND = 0x00000002,
19596 + GR_WRITE = 0x00000004,
19597 + GR_EXEC = 0x00000008,
19598 + GR_FIND = 0x00000010,
19599 + GR_INHERIT = 0x00000020,
19600 + GR_SETID = 0x00000040,
19601 + GR_CREATE = 0x00000080,
19602 + GR_DELETE = 0x00000100,
19603 + GR_LINK = 0x00000200,
19604 + GR_AUDIT_READ = 0x00000400,
19605 + GR_AUDIT_APPEND = 0x00000800,
19606 + GR_AUDIT_WRITE = 0x00001000,
19607 + GR_AUDIT_EXEC = 0x00002000,
19608 + GR_AUDIT_FIND = 0x00004000,
19609 + GR_AUDIT_INHERIT= 0x00008000,
19610 + GR_AUDIT_SETID = 0x00010000,
19611 + GR_AUDIT_CREATE = 0x00020000,
19612 + GR_AUDIT_DELETE = 0x00040000,
19613 + GR_AUDIT_LINK = 0x00080000,
19614 + GR_PTRACERD = 0x00100000,
19615 + GR_NOPTRACE = 0x00200000,
19616 + GR_SUPPRESS = 0x00400000,
19617 + GR_NOLEARN = 0x00800000
19620 +#define GR_AUDITS (GR_AUDIT_READ | GR_AUDIT_WRITE | GR_AUDIT_APPEND | GR_AUDIT_EXEC | \
19621 + GR_AUDIT_FIND | GR_AUDIT_INHERIT | GR_AUDIT_SETID | \
19622 + GR_AUDIT_CREATE | GR_AUDIT_DELETE | GR_AUDIT_LINK)
19624 +/* ACL subject-only mode flags */
19626 + GR_KILL = 0x00000001,
19627 + GR_VIEW = 0x00000002,
19628 + GR_PROTECTED = 0x00000004,
19629 + GR_LEARN = 0x00000008,
19630 + GR_OVERRIDE = 0x00000010,
19631 + /* just a placeholder, this mode is only used in userspace */
19632 + GR_DUMMY = 0x00000020,
19633 + GR_PROTSHM = 0x00000040,
19634 + GR_KILLPROC = 0x00000080,
19635 + GR_KILLIPPROC = 0x00000100,
19636 + /* just a placeholder, this mode is only used in userspace */
19637 + GR_NOTROJAN = 0x00000200,
19638 + GR_PROTPROCFD = 0x00000400,
19639 + GR_PROCACCT = 0x00000800,
19640 + GR_RELAXPTRACE = 0x00001000,
19641 + GR_NESTED = 0x00002000,
19642 + GR_INHERITLEARN = 0x00004000,
19643 + GR_PROCFIND = 0x00008000,
19644 + GR_POVERRIDE = 0x00010000,
19645 + GR_KERNELAUTH = 0x00020000,
19649 + GR_PAX_ENABLE_SEGMEXEC = 0x0001,
19650 + GR_PAX_ENABLE_PAGEEXEC = 0x0002,
19651 + GR_PAX_ENABLE_MPROTECT = 0x0004,
19652 + GR_PAX_ENABLE_RANDMMAP = 0x0008,
19653 + GR_PAX_ENABLE_EMUTRAMP = 0x0010,
19654 + GR_PAX_DISABLE_SEGMEXEC = 0x8001,
19655 + GR_PAX_DISABLE_PAGEEXEC = 0x8002,
19656 + GR_PAX_DISABLE_MPROTECT = 0x8004,
19657 + GR_PAX_DISABLE_RANDMMAP = 0x8008,
19658 + GR_PAX_DISABLE_EMUTRAMP = 0x8010,
19662 + GR_ID_USER = 0x01,
19663 + GR_ID_GROUP = 0x02,
19667 + GR_ID_ALLOW = 0x01,
19668 + GR_ID_DENY = 0x02,
19671 +#define GR_CRASH_RES 11
19672 +#define GR_UIDTABLE_MAX 500
19674 +/* begin resource learning section */
19676 + GR_RLIM_CPU_BUMP = 60,
19677 + GR_RLIM_FSIZE_BUMP = 50000,
19678 + GR_RLIM_DATA_BUMP = 10000,
19679 + GR_RLIM_STACK_BUMP = 1000,
19680 + GR_RLIM_CORE_BUMP = 10000,
19681 + GR_RLIM_RSS_BUMP = 500000,
19682 + GR_RLIM_NPROC_BUMP = 1,
19683 + GR_RLIM_NOFILE_BUMP = 5,
19684 + GR_RLIM_MEMLOCK_BUMP = 50000,
19685 + GR_RLIM_AS_BUMP = 500000,
19686 + GR_RLIM_LOCKS_BUMP = 2
19690 diff -urNp linux-2.6.16.12/include/linux/grinternal.h linux-2.6.16.12/include/linux/grinternal.h
19691 --- linux-2.6.16.12/include/linux/grinternal.h 1969-12-31 19:00:00.000000000 -0500
19692 +++ linux-2.6.16.12/include/linux/grinternal.h 2006-05-01 20:17:34.000000000 -0400
19694 +#ifndef __GRINTERNAL_H
19695 +#define __GRINTERNAL_H
19697 +#ifdef CONFIG_GRKERNSEC
19699 +#include <linux/fs.h>
19700 +#include <linux/gracl.h>
19701 +#include <linux/grdefs.h>
19702 +#include <linux/grmsg.h>
19704 +extern void gr_add_learn_entry(const char *fmt, ...);
19705 +extern __u32 gr_search_file(const struct dentry *dentry, const __u32 mode,
19706 + const struct vfsmount *mnt);
19707 +extern __u32 gr_check_create(const struct dentry *new_dentry,
19708 + const struct dentry *parent,
19709 + const struct vfsmount *mnt, const __u32 mode);
19710 +extern int gr_check_protected_task(const struct task_struct *task);
19711 +extern __u32 to_gr_audit(const __u32 reqmode);
19712 +extern int gr_set_acls(const int type);
19714 +extern int gr_acl_is_enabled(void);
19715 +extern char gr_roletype_to_char(void);
19717 +extern void gr_handle_alertkill(struct task_struct *task);
19718 +extern char *gr_to_filename(const struct dentry *dentry,
19719 + const struct vfsmount *mnt);
19720 +extern char *gr_to_filename1(const struct dentry *dentry,
19721 + const struct vfsmount *mnt);
19722 +extern char *gr_to_filename2(const struct dentry *dentry,
19723 + const struct vfsmount *mnt);
19724 +extern char *gr_to_filename3(const struct dentry *dentry,
19725 + const struct vfsmount *mnt);
19727 +extern int grsec_enable_link;
19728 +extern int grsec_enable_fifo;
19729 +extern int grsec_enable_execve;
19730 +extern int grsec_enable_shm;
19731 +extern int grsec_enable_execlog;
19732 +extern int grsec_enable_signal;
19733 +extern int grsec_enable_forkfail;
19734 +extern int grsec_enable_time;
19735 +extern int grsec_enable_chroot_shmat;
19736 +extern int grsec_enable_chroot_findtask;
19737 +extern int grsec_enable_chroot_mount;
19738 +extern int grsec_enable_chroot_double;
19739 +extern int grsec_enable_chroot_pivot;
19740 +extern int grsec_enable_chroot_chdir;
19741 +extern int grsec_enable_chroot_chmod;
19742 +extern int grsec_enable_chroot_mknod;
19743 +extern int grsec_enable_chroot_fchdir;
19744 +extern int grsec_enable_chroot_nice;
19745 +extern int grsec_enable_chroot_execlog;
19746 +extern int grsec_enable_chroot_caps;
19747 +extern int grsec_enable_chroot_sysctl;
19748 +extern int grsec_enable_chroot_unix;
19749 +extern int grsec_enable_tpe;
19750 +extern int grsec_tpe_gid;
19751 +extern int grsec_enable_tpe_all;
19752 +extern int grsec_enable_sidcaps;
19753 +extern int grsec_enable_randpid;
19754 +extern int grsec_enable_socket_all;
19755 +extern int grsec_socket_all_gid;
19756 +extern int grsec_enable_socket_client;
19757 +extern int grsec_socket_client_gid;
19758 +extern int grsec_enable_socket_server;
19759 +extern int grsec_socket_server_gid;
19760 +extern int grsec_audit_gid;
19761 +extern int grsec_enable_group;
19762 +extern int grsec_enable_audit_ipc;
19763 +extern int grsec_enable_audit_textrel;
19764 +extern int grsec_enable_mount;
19765 +extern int grsec_enable_chdir;
19766 +extern int grsec_lock;
19768 +extern struct task_struct *child_reaper;
19770 +extern spinlock_t grsec_alert_lock;
19771 +extern unsigned long grsec_alert_wtime;
19772 +extern unsigned long grsec_alert_fyet;
19774 +extern spinlock_t grsec_audit_lock;
19776 +extern rwlock_t grsec_exec_file_lock;
19778 +#define gr_task_fullpath(tsk) (tsk->exec_file ? \
19779 + gr_to_filename2(tsk->exec_file->f_dentry, \
19780 + tsk->exec_file->f_vfsmnt) : "/")
19782 +#define gr_parent_task_fullpath(tsk) (tsk->parent->exec_file ? \
19783 + gr_to_filename3(tsk->parent->exec_file->f_dentry, \
19784 + tsk->parent->exec_file->f_vfsmnt) : "/")
19786 +#define gr_task_fullpath0(tsk) (tsk->exec_file ? \
19787 + gr_to_filename(tsk->exec_file->f_dentry, \
19788 + tsk->exec_file->f_vfsmnt) : "/")
19790 +#define gr_parent_task_fullpath0(tsk) (tsk->parent->exec_file ? \
19791 + gr_to_filename1(tsk->parent->exec_file->f_dentry, \
19792 + tsk->parent->exec_file->f_vfsmnt) : "/")
19794 +#define proc_is_chrooted(tsk_a) ((tsk_a->pid > 1) && (tsk_a->fs != NULL) && \
19795 + ((tsk_a->fs->root->d_inode->i_sb->s_dev != \
19796 + child_reaper->fs->root->d_inode->i_sb->s_dev) || \
19797 + (tsk_a->fs->root->d_inode->i_ino != \
19798 + child_reaper->fs->root->d_inode->i_ino)))
19800 +#define have_same_root(tsk_a,tsk_b) ((tsk_a->fs != NULL) && (tsk_b->fs != NULL) && \
19801 + (tsk_a->fs->root->d_inode->i_sb->s_dev == \
19802 + tsk_b->fs->root->d_inode->i_sb->s_dev) && \
19803 + (tsk_a->fs->root->d_inode->i_ino == \
19804 + tsk_b->fs->root->d_inode->i_ino))
19806 +#define DEFAULTSECARGS(task) gr_task_fullpath(task), task->comm, \
19807 + task->pid, task->uid, \
19808 + task->euid, task->gid, task->egid, \
19809 + gr_parent_task_fullpath(task), \
19810 + task->parent->comm, task->parent->pid, \
19811 + task->parent->uid, task->parent->euid, \
19812 + task->parent->gid, task->parent->egid
19814 +#define GR_CHROOT_CAPS ( \
19815 + CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | CAP_TO_MASK(CAP_NET_ADMIN) | \
19816 + CAP_TO_MASK(CAP_SYS_MODULE) | CAP_TO_MASK(CAP_SYS_RAWIO) | \
19817 + CAP_TO_MASK(CAP_SYS_PACCT) | CAP_TO_MASK(CAP_SYS_ADMIN) | \
19818 + CAP_TO_MASK(CAP_SYS_BOOT) | CAP_TO_MASK(CAP_SYS_TIME) | \
19819 + CAP_TO_MASK(CAP_NET_RAW) | CAP_TO_MASK(CAP_SYS_TTY_CONFIG) | \
19820 + CAP_TO_MASK(CAP_IPC_OWNER))
19822 +#define security_learn(normal_msg,args...) \
19824 + read_lock(&grsec_exec_file_lock); \
19825 + gr_add_learn_entry(normal_msg "\n", ## args); \
19826 + read_unlock(&grsec_exec_file_lock); \
19832 + GR_DONT_AUDIT_GOOD
19845 + GR_ONE_INT_TWO_STR,
19850 + GR_FIVE_INT_TWO_STR,
19856 + GR_FILENAME_TWO_INT,
19857 + GR_FILENAME_TWO_INT_STR,
19868 +#define gr_log_ttysniff(audit, msg, task) gr_log_varargs(audit, msg, GR_TTYSNIFF, task)
19869 +#define gr_log_fs_rbac_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_RBAC, dentry, mnt)
19870 +#define gr_log_fs_rbac_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_RBAC_STR, dentry, mnt, str)
19871 +#define gr_log_fs_str_rbac(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_RBAC, str, dentry, mnt)
19872 +#define gr_log_fs_rbac_mode2(audit, msg, dentry, mnt, str1, str2) gr_log_varargs(audit, msg, GR_RBAC_MODE2, dentry, mnt, str1, str2)
19873 +#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)
19874 +#define gr_log_fs_generic(audit, msg, dentry, mnt) gr_log_varargs(audit, msg, GR_FILENAME, dentry, mnt)
19875 +#define gr_log_noargs(audit, msg) gr_log_varargs(audit, msg, GR_NOARGS)
19876 +#define gr_log_int(audit, msg, num) gr_log_varargs(audit, msg, GR_ONE_INT, num)
19877 +#define gr_log_int_str2(audit, msg, num, str1, str2) gr_log_varargs(audit, msg, GR_ONE_INT_TWO_STR, num, str1, str2)
19878 +#define gr_log_str(audit, msg, str) gr_log_varargs(audit, msg, GR_ONE_STR, str)
19879 +#define gr_log_str_int(audit, msg, str, num) gr_log_varargs(audit, msg, GR_STR_INT, str, num)
19880 +#define gr_log_int_int(audit, msg, num1, num2) gr_log_varargs(audit, msg, GR_TWO_INT, num1, num2)
19881 +#define gr_log_int3(audit, msg, num1, num2, num3) gr_log_varargs(audit, msg, GR_THREE_INT, num1, num2, num3)
19882 +#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)
19883 +#define gr_log_str_str(audit, msg, str1, str2) gr_log_varargs(audit, msg, GR_TWO_STR, str1, str2)
19884 +#define gr_log_str3(audit, msg, str1, str2, str3) gr_log_varargs(audit, msg, GR_THREE_STR, str1, str2, str3)
19885 +#define gr_log_str4(audit, msg, str1, str2, str3, str4) gr_log_varargs(audit, msg, GR_FOUR_STR, str1, str2, str3, str4)
19886 +#define gr_log_str_fs(audit, msg, str, dentry, mnt) gr_log_varargs(audit, msg, GR_STR_FILENAME, str, dentry, mnt)
19887 +#define gr_log_fs_str(audit, msg, dentry, mnt, str) gr_log_varargs(audit, msg, GR_FILENAME_STR, dentry, mnt, str)
19888 +#define gr_log_fs_int2(audit, msg, dentry, mnt, num1, num2) gr_log_varargs(audit, msg, GR_FILENAME_TWO_INT, dentry, mnt, num1, num2)
19889 +#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)
19890 +#define gr_log_textrel_ulong_ulong(audit, msg, file, ulong1, ulong2) gr_log_varargs(audit, msg, GR_TEXTREL, file, ulong1, ulong2)
19891 +#define gr_log_ptrace(audit, msg, task) gr_log_varargs(audit, msg, GR_PTRACE, task)
19892 +#define gr_log_res_ulong2_str(audit, msg, task, ulong1, str, ulong2) gr_log_varargs(audit, msg, GR_RESOURCE, task, ulong1, str, ulong2)
19893 +#define gr_log_cap(audit, msg, task, str) gr_log_varargs(audit, msg, GR_CAP, task, str)
19894 +#define gr_log_sig(audit, msg, task, num) gr_log_varargs(audit, msg, GR_SIG, task, num)
19895 +#define gr_log_crash1(audit, msg, task, ulong) gr_log_varargs(audit, msg, GR_CRASH1, task, ulong)
19896 +#define gr_log_crash2(audit, msg, task, ulong1) gr_log_varargs(audit, msg, GR_CRASH2, task, ulong1)
19897 +#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)
19899 +extern void gr_log_varargs(int audit, const char *msg, int argtypes, ...);
19904 diff -urNp linux-2.6.16.12/include/linux/grmsg.h linux-2.6.16.12/include/linux/grmsg.h
19905 --- linux-2.6.16.12/include/linux/grmsg.h 1969-12-31 19:00:00.000000000 -0500
19906 +++ linux-2.6.16.12/include/linux/grmsg.h 2006-05-01 20:17:34.000000000 -0400
19908 +#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"
19909 +#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"
19910 +#define GR_PTRACE_ACL_MSG "denied ptrace of %.950s(%.16s:%d) by "
19911 +#define GR_STOPMOD_MSG "denied modification of module state by "
19912 +#define GR_IOPERM_MSG "denied use of ioperm() by "
19913 +#define GR_IOPL_MSG "denied use of iopl() by "
19914 +#define GR_SHMAT_ACL_MSG "denied attach of shared memory of UID %u, PID %d, ID %u by "
19915 +#define GR_UNIX_CHROOT_MSG "denied connect() to abstract AF_UNIX socket outside of chroot by "
19916 +#define GR_SHMAT_CHROOT_MSG "denied attach of shared memory outside of chroot by "
19917 +#define GR_KMEM_MSG "denied write of /dev/kmem by "
19918 +#define GR_PORT_OPEN_MSG "denied open of /dev/port by "
19919 +#define GR_MEM_WRITE_MSG "denied write of /dev/mem by "
19920 +#define GR_MEM_MMAP_MSG "denied mmap write of /dev/[k]mem by "
19921 +#define GR_SYMLINK_MSG "not following symlink %.950s owned by %d.%d by "
19922 +#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"
19923 +#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"
19924 +#define GR_HIDDEN_ACL_MSG "%s access to hidden file %.950s by "
19925 +#define GR_OPEN_ACL_MSG "%s open of %.950s for%s%s by "
19926 +#define GR_CREATE_ACL_MSG "%s create of %.950s for%s%s by "
19927 +#define GR_FIFO_MSG "denied writing FIFO %.950s of %d.%d by "
19928 +#define GR_MKNOD_CHROOT_MSG "denied mknod of %.950s from chroot by "
19929 +#define GR_MKNOD_ACL_MSG "%s mknod of %.950s by "
19930 +#define GR_UNIXCONNECT_ACL_MSG "%s connect() to the unix domain socket %.950s by "
19931 +#define GR_TTYSNIFF_ACL_MSG "terminal being sniffed by IP:%u.%u.%u.%u %.480s[%.16s:%d], parent %.480s[%.16s:%d] against "
19932 +#define GR_MKDIR_ACL_MSG "%s mkdir of %.950s by "
19933 +#define GR_RMDIR_ACL_MSG "%s rmdir of %.950s by "
19934 +#define GR_UNLINK_ACL_MSG "%s unlink of %.950s by "
19935 +#define GR_SYMLINK_ACL_MSG "%s symlink from %.480s to %.480s by "
19936 +#define GR_HARDLINK_MSG "denied hardlink of %.930s (owned by %d.%d) to %.30s for "
19937 +#define GR_LINK_ACL_MSG "%s link of %.480s to %.480s by "
19938 +#define GR_INHERIT_ACL_MSG "successful inherit of %.480s's ACL for %.480s by "
19939 +#define GR_RENAME_ACL_MSG "%s rename of %.480s to %.480s by "
19940 +#define GR_PTRACE_EXEC_ACL_MSG "denied ptrace of %.950s by "
19941 +#define GR_NPROC_MSG "denied overstep of process limit by "
19942 +#define GR_EXEC_ACL_MSG "%s execution of %.950s by "
19943 +#define GR_EXEC_TPE_MSG "denied untrusted exec of %.950s by "
19944 +#define GR_SEGVSTART_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning uid %u from login for %lu seconds"
19945 +#define GR_SEGVNOSUID_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " banning execution for %lu seconds"
19946 +#define GR_MOUNT_CHROOT_MSG "denied mount of %.30s as %.930s from chroot by "
19947 +#define GR_PIVOT_CHROOT_MSG "denied pivot_root from chroot by "
19948 +#define GR_TRUNCATE_ACL_MSG "%s truncate of %.950s by "
19949 +#define GR_ATIME_ACL_MSG "%s access time change of %.950s by "
19950 +#define GR_ACCESS_ACL_MSG "%s access of %.950s for%s%s%s by "
19951 +#define GR_CHROOT_CHROOT_MSG "denied double chroot to %.950s by "
19952 +#define GR_FCHMOD_ACL_MSG "%s fchmod of %.950s by "
19953 +#define GR_CHMOD_CHROOT_MSG "denied chmod +s of %.950s by "
19954 +#define GR_CHMOD_ACL_MSG "%s chmod of %.950s by "
19955 +#define GR_CHROOT_FCHDIR_MSG "denied fchdir outside of chroot to %.950s by "
19956 +#define GR_CHOWN_ACL_MSG "%s chown of %.950s by "
19957 +#define GR_WRITLIB_ACL_MSG "denied load of writable library %.950s by "
19958 +#define GR_INITF_ACL_MSG "init_variables() failed %s by "
19959 +#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"
19960 +#define GR_DEV_ACL_MSG "/dev/grsec: %d bytes sent %d required, being fed garbaged by "
19961 +#define GR_SHUTS_ACL_MSG "shutdown auth success for "
19962 +#define GR_SHUTF_ACL_MSG "shutdown auth failure for "
19963 +#define GR_SHUTI_ACL_MSG "ignoring shutdown for disabled RBAC system for "
19964 +#define GR_SEGVMODS_ACL_MSG "segvmod auth success for "
19965 +#define GR_SEGVMODF_ACL_MSG "segvmod auth failure for "
19966 +#define GR_SEGVMODI_ACL_MSG "ignoring segvmod for disabled RBAC system for "
19967 +#define GR_ENABLE_ACL_MSG "%s RBAC system loaded by "
19968 +#define GR_ENABLEF_ACL_MSG "unable to load %s for "
19969 +#define GR_RELOADI_ACL_MSG "ignoring reload request for disabled RBAC system"
19970 +#define GR_RELOAD_ACL_MSG "%s RBAC system reloaded by "
19971 +#define GR_RELOADF_ACL_MSG "failed reload of %s for "
19972 +#define GR_SPROLEI_ACL_MSG "ignoring change to special role for disabled RBAC system for "
19973 +#define GR_SPROLES_ACL_MSG "successful change to special role %s (id %d) by "
19974 +#define GR_SPROLEL_ACL_MSG "special role %s (id %d) exited by "
19975 +#define GR_SPROLEF_ACL_MSG "special role %s failure for "
19976 +#define GR_UNSPROLEI_ACL_MSG "ignoring unauth of special role for disabled RBAC system for "
19977 +#define GR_UNSPROLES_ACL_MSG "successful unauth of special role %s (id %d) by "
19978 +#define GR_UNSPROLEF_ACL_MSG "special role unauth of %s failure for "
19979 +#define GR_INVMODE_ACL_MSG "invalid mode %d by "
19980 +#define GR_PRIORITY_CHROOT_MSG "denied priority change of process (%.16s:%d) by "
19981 +#define GR_FAILFORK_MSG "failed fork with errno %d by "
19982 +#define GR_NICE_CHROOT_MSG "denied priority change by "
19983 +#define GR_UNISIGLOG_MSG "signal %d sent to "
19984 +#define GR_DUALSIGLOG_MSG "signal %d sent to " DEFAULTSECMSG " by "
19985 +#define GR_SIG_ACL_MSG "denied send of signal %d to protected task " DEFAULTSECMSG " by "
19986 +#define GR_SYSCTL_MSG "denied modification of grsecurity sysctl value : %.32s by "
19987 +#define GR_SYSCTL_ACL_MSG "%s sysctl of %.950s for%s%s by "
19988 +#define GR_TIME_MSG "time set by "
19989 +#define GR_DEFACL_MSG "fatal: unable to find subject for (%.16s:%d), loaded by "
19990 +#define GR_MMAP_ACL_MSG "%s executable mmap of %.950s by "
19991 +#define GR_MPROTECT_ACL_MSG "%s executable mprotect of %.950s by "
19992 +#define GR_SOCK_MSG "denied socket(%.16s,%.16s,%.16s) by "
19993 +#define GR_SOCK2_MSG "denied socket(%d,%.16s,%.16s) by "
19994 +#define GR_BIND_MSG "denied bind() by "
19995 +#define GR_CONNECT_MSG "denied connect() by "
19996 +#define GR_BIND_ACL_MSG "denied bind() to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by "
19997 +#define GR_CONNECT_ACL_MSG "denied connect() to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by "
19998 +#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"
19999 +#define GR_EXEC_CHROOT_MSG "exec of %.980s within chroot by process "
20000 +#define GR_CAP_ACL_MSG "use of %s denied for "
20001 +#define GR_USRCHANGE_ACL_MSG "change to uid %u denied for "
20002 +#define GR_GRPCHANGE_ACL_MSG "change to gid %u denied for "
20003 +#define GR_REMOUNT_AUDIT_MSG "remount of %.30s by "
20004 +#define GR_UNMOUNT_AUDIT_MSG "unmount of %.30s by "
20005 +#define GR_MOUNT_AUDIT_MSG "mount of %.30s to %.64s by "
20006 +#define GR_CHDIR_AUDIT_MSG "chdir to %.980s by "
20007 +#define GR_EXEC_AUDIT_MSG "exec of %.930s (%.128s) by "
20008 +#define GR_MSGQ_AUDIT_MSG "message queue created by "
20009 +#define GR_MSGQR_AUDIT_MSG "message queue of uid:%u euid:%u removed by "
20010 +#define GR_SEM_AUDIT_MSG "semaphore created by "
20011 +#define GR_SEMR_AUDIT_MSG "semaphore of uid:%u euid:%u removed by "
20012 +#define GR_SHM_AUDIT_MSG "shared memory of size %d created by "
20013 +#define GR_SHMR_AUDIT_MSG "shared memory of uid:%u euid:%u removed by "
20014 +#define GR_RESOURCE_MSG "denied resource overstep by requesting %lu for %.16s against limit %lu for "
20015 +#define GR_TEXTREL_AUDIT_MSG "text relocation in %s, VMA:0x%08lx 0x%08lx by "
20016 diff -urNp linux-2.6.16.12/include/linux/grsecurity.h linux-2.6.16.12/include/linux/grsecurity.h
20017 --- linux-2.6.16.12/include/linux/grsecurity.h 1969-12-31 19:00:00.000000000 -0500
20018 +++ linux-2.6.16.12/include/linux/grsecurity.h 2006-05-01 20:17:34.000000000 -0400
20020 +#ifndef GR_SECURITY_H
20021 +#define GR_SECURITY_H
20022 +#include <linux/fs.h>
20023 +#include <linux/binfmts.h>
20024 +#include <linux/gracl.h>
20026 +extern void gr_handle_brute_attach(struct task_struct *p);
20027 +extern void gr_handle_brute_check(void);
20029 +extern char gr_roletype_to_char(void);
20031 +extern int gr_check_user_change(int real, int effective, int fs);
20032 +extern int gr_check_group_change(int real, int effective, int fs);
20034 +extern void gr_del_task_from_ip_table(struct task_struct *p);
20036 +extern int gr_pid_is_chrooted(struct task_struct *p);
20037 +extern int gr_handle_chroot_nice(void);
20038 +extern int gr_handle_chroot_sysctl(const int op);
20039 +extern int gr_handle_chroot_setpriority(struct task_struct *p,
20040 + const int niceval);
20041 +extern int gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt);
20042 +extern int gr_handle_chroot_chroot(const struct dentry *dentry,
20043 + const struct vfsmount *mnt);
20044 +extern void gr_handle_chroot_caps(struct task_struct *task);
20045 +extern void gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt);
20046 +extern int gr_handle_chroot_chmod(const struct dentry *dentry,
20047 + const struct vfsmount *mnt, const int mode);
20048 +extern int gr_handle_chroot_mknod(const struct dentry *dentry,
20049 + const struct vfsmount *mnt, const int mode);
20050 +extern int gr_handle_chroot_mount(const struct dentry *dentry,
20051 + const struct vfsmount *mnt,
20052 + const char *dev_name);
20053 +extern int gr_handle_chroot_pivot(void);
20054 +extern int gr_handle_chroot_unix(const pid_t pid);
20056 +extern int gr_handle_rawio(const struct inode *inode);
20057 +extern int gr_handle_nproc(void);
20059 +extern void gr_handle_ioperm(void);
20060 +extern void gr_handle_iopl(void);
20062 +extern int gr_tpe_allow(const struct file *file);
20064 +extern int gr_random_pid(void);
20066 +extern void gr_log_forkfail(const int retval);
20067 +extern void gr_log_timechange(void);
20068 +extern void gr_log_signal(const int sig, const struct task_struct *t);
20069 +extern void gr_log_chdir(const struct dentry *dentry,
20070 + const struct vfsmount *mnt);
20071 +extern void gr_log_chroot_exec(const struct dentry *dentry,
20072 + const struct vfsmount *mnt);
20073 +extern void gr_handle_exec_args(struct linux_binprm *bprm, char **argv);
20074 +extern void gr_log_remount(const char *devname, const int retval);
20075 +extern void gr_log_unmount(const char *devname, const int retval);
20076 +extern void gr_log_mount(const char *from, const char *to, const int retval);
20077 +extern void gr_log_msgget(const int ret, const int msgflg);
20078 +extern void gr_log_msgrm(const uid_t uid, const uid_t cuid);
20079 +extern void gr_log_semget(const int err, const int semflg);
20080 +extern void gr_log_semrm(const uid_t uid, const uid_t cuid);
20081 +extern void gr_log_shmget(const int err, const int shmflg, const size_t size);
20082 +extern void gr_log_shmrm(const uid_t uid, const uid_t cuid);
20083 +extern void gr_log_textrel(struct vm_area_struct *vma);
20085 +extern int gr_handle_follow_link(const struct inode *parent,
20086 + const struct inode *inode,
20087 + const struct dentry *dentry,
20088 + const struct vfsmount *mnt);
20089 +extern int gr_handle_fifo(const struct dentry *dentry,
20090 + const struct vfsmount *mnt,
20091 + const struct dentry *dir, const int flag,
20092 + const int acc_mode);
20093 +extern int gr_handle_hardlink(const struct dentry *dentry,
20094 + const struct vfsmount *mnt,
20095 + struct inode *inode,
20096 + const int mode, const char *to);
20098 +extern int gr_task_is_capable(struct task_struct *task, const int cap);
20099 +extern int gr_is_capable_nolog(const int cap);
20100 +extern void gr_learn_resource(const struct task_struct *task, const int limit,
20101 + const unsigned long wanted, const int gt);
20102 +extern void gr_copy_label(struct task_struct *tsk);
20103 +extern void gr_handle_crash(struct task_struct *task, const int sig);
20104 +extern int gr_handle_signal(const struct task_struct *p, const int sig);
20105 +extern int gr_check_crash_uid(const uid_t uid);
20106 +extern int gr_check_protected_task(const struct task_struct *task);
20107 +extern int gr_acl_handle_mmap(const struct file *file,
20108 + const unsigned long prot);
20109 +extern int gr_acl_handle_mprotect(const struct file *file,
20110 + const unsigned long prot);
20111 +extern int gr_check_hidden_task(const struct task_struct *tsk);
20112 +extern __u32 gr_acl_handle_truncate(const struct dentry *dentry,
20113 + const struct vfsmount *mnt);
20114 +extern __u32 gr_acl_handle_utime(const struct dentry *dentry,
20115 + const struct vfsmount *mnt);
20116 +extern __u32 gr_acl_handle_access(const struct dentry *dentry,
20117 + const struct vfsmount *mnt, const int fmode);
20118 +extern __u32 gr_acl_handle_fchmod(const struct dentry *dentry,
20119 + const struct vfsmount *mnt, mode_t mode);
20120 +extern __u32 gr_acl_handle_chmod(const struct dentry *dentry,
20121 + const struct vfsmount *mnt, mode_t mode);
20122 +extern __u32 gr_acl_handle_chown(const struct dentry *dentry,
20123 + const struct vfsmount *mnt);
20124 +extern int gr_handle_ptrace(struct task_struct *task, const long request);
20125 +extern int gr_handle_proc_ptrace(struct task_struct *task);
20126 +extern __u32 gr_acl_handle_execve(const struct dentry *dentry,
20127 + const struct vfsmount *mnt);
20128 +extern int gr_check_crash_exec(const struct file *filp);
20129 +extern int gr_acl_is_enabled(void);
20130 +extern void gr_set_kernel_label(struct task_struct *task);
20131 +extern void gr_set_role_label(struct task_struct *task, const uid_t uid,
20132 + const gid_t gid);
20133 +extern int gr_set_proc_label(const struct dentry *dentry,
20134 + const struct vfsmount *mnt);
20135 +extern __u32 gr_acl_handle_hidden_file(const struct dentry *dentry,
20136 + const struct vfsmount *mnt);
20137 +extern __u32 gr_acl_handle_open(const struct dentry *dentry,
20138 + const struct vfsmount *mnt, const int fmode);
20139 +extern __u32 gr_acl_handle_creat(const struct dentry *dentry,
20140 + const struct dentry *p_dentry,
20141 + const struct vfsmount *p_mnt, const int fmode,
20142 + const int imode);
20143 +extern void gr_handle_create(const struct dentry *dentry,
20144 + const struct vfsmount *mnt);
20145 +extern __u32 gr_acl_handle_mknod(const struct dentry *new_dentry,
20146 + const struct dentry *parent_dentry,
20147 + const struct vfsmount *parent_mnt,
20149 +extern __u32 gr_acl_handle_mkdir(const struct dentry *new_dentry,
20150 + const struct dentry *parent_dentry,
20151 + const struct vfsmount *parent_mnt);
20152 +extern __u32 gr_acl_handle_rmdir(const struct dentry *dentry,
20153 + const struct vfsmount *mnt);
20154 +extern void gr_handle_delete(const ino_t ino, const dev_t dev);
20155 +extern __u32 gr_acl_handle_unlink(const struct dentry *dentry,
20156 + const struct vfsmount *mnt);
20157 +extern __u32 gr_acl_handle_symlink(const struct dentry *new_dentry,
20158 + const struct dentry *parent_dentry,
20159 + const struct vfsmount *parent_mnt,
20160 + const char *from);
20161 +extern __u32 gr_acl_handle_link(const struct dentry *new_dentry,
20162 + const struct dentry *parent_dentry,
20163 + const struct vfsmount *parent_mnt,
20164 + const struct dentry *old_dentry,
20165 + const struct vfsmount *old_mnt, const char *to);
20166 +extern int gr_acl_handle_rename(struct dentry *new_dentry,
20167 + struct dentry *parent_dentry,
20168 + const struct vfsmount *parent_mnt,
20169 + struct dentry *old_dentry,
20170 + struct inode *old_parent_inode,
20171 + struct vfsmount *old_mnt, const char *newname);
20172 +extern void gr_handle_rename(struct inode *old_dir, struct inode *new_dir,
20173 + struct dentry *old_dentry,
20174 + struct dentry *new_dentry,
20175 + struct vfsmount *mnt, const __u8 replace);
20176 +extern __u32 gr_check_link(const struct dentry *new_dentry,
20177 + const struct dentry *parent_dentry,
20178 + const struct vfsmount *parent_mnt,
20179 + const struct dentry *old_dentry,
20180 + const struct vfsmount *old_mnt);
20181 +extern int gr_acl_handle_filldir(const struct file *file, const char *name,
20182 + const unsigned int namelen, const ino_t ino);
20184 +extern __u32 gr_acl_handle_unix(const struct dentry *dentry,
20185 + const struct vfsmount *mnt);
20186 +extern void gr_acl_handle_exit(void);
20187 +extern void gr_acl_handle_psacct(struct task_struct *task, const long code);
20188 +extern int gr_acl_handle_procpidmem(const struct task_struct *task);
20189 +extern __u32 gr_cap_rtnetlink(void);
20191 +#ifdef CONFIG_SYSVIPC
20192 +extern void gr_shm_exit(struct task_struct *task);
20194 +static inline void gr_shm_exit(struct task_struct *task)
20200 +#ifdef CONFIG_GRKERNSEC
20201 +extern void gr_handle_mem_write(void);
20202 +extern void gr_handle_kmem_write(void);
20203 +extern void gr_handle_open_port(void);
20204 +extern int gr_handle_mem_mmap(const unsigned long offset,
20205 + struct vm_area_struct *vma);
20207 +extern unsigned long pax_get_random_long(void);
20208 +#define get_random_long() pax_get_random_long()
20210 +extern int grsec_enable_dmesg;
20211 +extern int grsec_enable_randsrc;
20212 +extern int grsec_enable_shm;
20216 diff -urNp linux-2.6.16.12/include/linux/mman.h linux-2.6.16.12/include/linux/mman.h
20217 --- linux-2.6.16.12/include/linux/mman.h 2006-05-01 15:14:26.000000000 -0400
20218 +++ linux-2.6.16.12/include/linux/mman.h 2006-05-01 20:17:34.000000000 -0400
20219 @@ -59,6 +59,11 @@ static inline unsigned long
20220 calc_vm_flag_bits(unsigned long flags)
20222 return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) |
20224 +#ifdef CONFIG_PAX_SEGMEXEC
20225 + _calc_vm_trans(flags, MAP_MIRROR, VM_MIRROR) |
20228 _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) |
20229 _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) |
20230 _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED );
20231 diff -urNp linux-2.6.16.12/include/linux/mm.h linux-2.6.16.12/include/linux/mm.h
20232 --- linux-2.6.16.12/include/linux/mm.h 2006-05-01 15:14:26.000000000 -0400
20233 +++ linux-2.6.16.12/include/linux/mm.h 2006-05-01 20:17:34.000000000 -0400
20234 @@ -38,6 +38,7 @@ extern int sysctl_legacy_va_layout;
20235 #include <asm/pgtable.h>
20236 #include <asm/processor.h>
20237 #include <asm/atomic.h>
20238 +#include <asm/mman.h>
20240 #define nth_page(page,n) pfn_to_page(page_to_pfn((page)) + (n))
20242 @@ -111,8 +112,43 @@ struct vm_area_struct {
20244 struct mempolicy *vm_policy; /* NUMA policy for the VMA */
20247 + unsigned long vm_mirror; /* PaX: mirror distance */
20250 +#ifdef CONFIG_PAX_SOFTMODE
20251 +extern unsigned int pax_softmode;
20254 +extern int pax_check_flags(unsigned long *);
20256 +/* if tsk != current then task_lock must be held on it */
20257 +#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
20258 +static inline unsigned long pax_get_flags(struct task_struct *tsk)
20260 + if (likely(tsk->mm))
20261 + return tsk->mm->pax_flags;
20266 +/* if tsk != current then task_lock must be held on it */
20267 +static inline long pax_set_flags(struct task_struct *tsk, unsigned long flags)
20269 + if (likely(tsk->mm)) {
20270 + tsk->mm->pax_flags = flags;
20277 +#ifdef CONFIG_PAX_HAVE_ACL_FLAGS
20278 +extern void pax_set_initial_flags(struct linux_binprm * bprm);
20279 +#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS)
20280 +extern void (*pax_set_initial_flags_func)(struct linux_binprm * bprm);
20284 * This struct defines the per-mm list of VMAs for uClinux. If CONFIG_MMU is
20285 * disabled, then there's a single shared list of VMAs maintained by the
20286 @@ -167,6 +203,18 @@ extern unsigned int kobjsize(const void
20287 #define VM_MAPPED_COPY 0x01000000 /* T if mapped copy of data (nommu mmap) */
20288 #define VM_INSERTPAGE 0x02000000 /* The vma has had "vm_insert_page()" done on it */
20290 +#ifdef CONFIG_PAX_SEGMEXEC
20291 +#define VM_MIRROR 0x04000000 /* vma is mirroring another */
20294 +#ifdef CONFIG_PAX_MPROTECT
20295 +#define VM_MAYNOTWRITE 0x08000000 /* vma cannot be granted VM_WRITE any more */
20298 +#ifdef __VM_STACK_FLAGS
20299 +#define VM_STACK_DEFAULT_FLAGS (0x00000033 | __VM_STACK_FLAGS)
20302 #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */
20303 #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS
20305 @@ -1056,5 +1104,11 @@ void drop_slab(void);
20306 extern int randomize_va_space;
20309 +#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
20310 +extern void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot);
20312 +static inline void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot) {}
20315 #endif /* __KERNEL__ */
20316 #endif /* _LINUX_MM_H */
20317 diff -urNp linux-2.6.16.12/include/linux/module.h linux-2.6.16.12/include/linux/module.h
20318 --- linux-2.6.16.12/include/linux/module.h 2006-05-01 15:14:26.000000000 -0400
20319 +++ linux-2.6.16.12/include/linux/module.h 2006-05-01 20:17:34.000000000 -0400
20320 @@ -263,16 +263,16 @@ struct module
20323 /* If this is non-NULL, vfree after init() returns */
20324 - void *module_init;
20325 + void *module_init_rx, *module_init_rw;
20327 /* Here is the actual code + data, vfree'd on unload. */
20328 - void *module_core;
20329 + void *module_core_rx, *module_core_rw;
20331 /* Here are the sizes of the init and core sections */
20332 - unsigned long init_size, core_size;
20333 + unsigned long init_size_rw, core_size_rw;
20335 /* The size of the executable code in each section. */
20336 - unsigned long init_text_size, core_text_size;
20337 + unsigned long init_size_rx, core_size_rx;
20339 /* Arch-specific module values */
20340 struct mod_arch_specific arch;
20341 diff -urNp linux-2.6.16.12/include/linux/moduleloader.h linux-2.6.16.12/include/linux/moduleloader.h
20342 --- linux-2.6.16.12/include/linux/moduleloader.h 2006-05-01 15:14:26.000000000 -0400
20343 +++ linux-2.6.16.12/include/linux/moduleloader.h 2006-05-01 20:17:34.000000000 -0400
20344 @@ -17,9 +17,21 @@ int module_frob_arch_sections(Elf_Ehdr *
20345 sections. Returns NULL on failure. */
20346 void *module_alloc(unsigned long size);
20348 +#ifdef CONFIG_PAX_KERNEXEC
20349 +void *module_alloc_exec(unsigned long size);
20351 +#define module_alloc_exec(x) module_alloc(x)
20354 /* Free memory returned from module_alloc. */
20355 void module_free(struct module *mod, void *module_region);
20357 +#ifdef CONFIG_PAX_KERNEXEC
20358 +void module_free_exec(struct module *mod, void *module_region);
20360 +#define module_free_exec(x, y) module_free(x, y)
20363 /* Apply the given relocation to the (simplified) ELF. Return -error
20365 int apply_relocate(Elf_Shdr *sechdrs,
20366 diff -urNp linux-2.6.16.12/include/linux/random.h linux-2.6.16.12/include/linux/random.h
20367 --- linux-2.6.16.12/include/linux/random.h 2006-05-01 15:14:26.000000000 -0400
20368 +++ linux-2.6.16.12/include/linux/random.h 2006-05-01 20:17:34.000000000 -0400
20369 @@ -62,6 +62,8 @@ extern __u32 secure_tcpv6_sequence_numbe
20370 extern u64 secure_dccp_sequence_number(__u32 saddr, __u32 daddr,
20371 __u16 sport, __u16 dport);
20373 +extern unsigned long pax_get_random_long(void);
20376 extern struct file_operations random_fops, urandom_fops;
20378 diff -urNp linux-2.6.16.12/include/linux/sched.h linux-2.6.16.12/include/linux/sched.h
20379 --- linux-2.6.16.12/include/linux/sched.h 2006-05-01 15:14:26.000000000 -0400
20380 +++ linux-2.6.16.12/include/linux/sched.h 2006-05-01 20:17:34.000000000 -0400
20382 #include <linux/auxvec.h> /* For AT_VECTOR_SIZE */
20384 struct exec_domain;
20385 +struct linux_binprm;
20389 @@ -348,8 +349,34 @@ struct mm_struct {
20391 rwlock_t ioctx_list_lock;
20392 struct kioctx *ioctx_list;
20394 +#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR)
20395 + unsigned long pax_flags;
20398 +#ifdef CONFIG_PAX_DLRESOLVE
20399 + unsigned long call_dl_resolve;
20402 +#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT)
20403 + unsigned long call_syscall;
20406 +#ifdef CONFIG_PAX_ASLR
20407 + unsigned long delta_mmap; /* randomized offset */
20408 + unsigned long delta_exec; /* randomized offset */
20409 + unsigned long delta_stack; /* randomized offset */
20414 +#define MF_PAX_PAGEEXEC 0x01000000 /* Paging based non-executable pages */
20415 +#define MF_PAX_EMUTRAMP 0x02000000 /* Emulate trampolines */
20416 +#define MF_PAX_MPROTECT 0x04000000 /* Restrict mprotect() */
20417 +#define MF_PAX_RANDMMAP 0x08000000 /* Randomize mmap() base */
20418 +/*#define MF_PAX_RANDEXEC 0x10000000*/ /* Randomize ET_EXEC base */
20419 +#define MF_PAX_SEGMEXEC 0x20000000 /* Segmentation based non-executable pages */
20421 struct sighand_struct {
20423 struct k_sigaction action[_NSIG];
20424 @@ -454,6 +481,15 @@ struct signal_struct {
20425 struct key *session_keyring; /* keyring inherited over fork */
20426 struct key *process_keyring; /* keyring private to this process */
20429 +#ifdef CONFIG_GRKERNSEC
20435 + u8 used_accept:1;
20439 /* Context switch must be unlocked if interrupts are to be enabled */
20440 @@ -869,6 +905,16 @@ struct task_struct {
20441 nodemask_t mems_allowed;
20442 int cpuset_mems_generation;
20444 +#ifdef CONFIG_GRKERNSEC
20446 + struct acl_subject_label *acl;
20447 + struct acl_role_label *role;
20448 + struct file *exec_file;
20450 + u8 acl_sp_role:1;
20451 + u8 is_writable:1;
20454 atomic_t fs_excl; /* holding fs exclusive resources */
20455 struct rcu_head rcu;
20457 @@ -1377,6 +1423,12 @@ extern void arch_pick_mmap_layout(struct
20458 static inline void arch_pick_mmap_layout(struct mm_struct *mm)
20460 mm->mmap_base = TASK_UNMAPPED_BASE;
20462 +#ifdef CONFIG_PAX_RANDMMAP
20463 + if (mm->pax_flags & MF_PAX_RANDMMAP)
20464 + mm->mmap_base += mm->delta_mmap;
20467 mm->get_unmapped_area = arch_get_unmapped_area;
20468 mm->unmap_area = arch_unmap_area;
20470 diff -urNp linux-2.6.16.12/include/linux/shm.h linux-2.6.16.12/include/linux/shm.h
20471 --- linux-2.6.16.12/include/linux/shm.h 2006-05-01 15:14:26.000000000 -0400
20472 +++ linux-2.6.16.12/include/linux/shm.h 2006-05-01 20:17:34.000000000 -0400
20473 @@ -86,6 +86,10 @@ struct shmid_kernel /* private to the ke
20476 struct user_struct *mlock_user;
20477 +#ifdef CONFIG_GRKERNSEC
20478 + time_t shm_createtime;
20483 /* shm_mode upper byte flags */
20484 diff -urNp linux-2.6.16.12/include/linux/sysctl.h linux-2.6.16.12/include/linux/sysctl.h
20485 --- linux-2.6.16.12/include/linux/sysctl.h 2006-05-01 15:14:26.000000000 -0400
20486 +++ linux-2.6.16.12/include/linux/sysctl.h 2006-05-01 20:17:34.000000000 -0400
20487 @@ -148,8 +148,20 @@ enum
20488 KERN_SPIN_RETRY=70, /* int: number of spinlock retries */
20489 KERN_ACPI_VIDEO_FLAGS=71, /* int: flags for setting up video after ACPI sleep */
20490 KERN_IA64_UNALIGNED=72, /* int: ia64 unaligned userland trap enable */
20491 +#ifdef CONFIG_GRKERNSEC
20492 + KERN_GRSECURITY=98, /* grsecurity */
20494 +#ifdef CONFIG_PAX_SOFTMODE
20495 + KERN_PAX=99, /* PaX control */
20500 +#ifdef CONFIG_PAX_SOFTMODE
20502 + PAX_SOFTMODE=1 /* PaX: disable/enable soft mode */
20506 /* CTL_VM names: */
20508 diff -urNp linux-2.6.16.12/init/Kconfig linux-2.6.16.12/init/Kconfig
20509 --- linux-2.6.16.12/init/Kconfig 2006-05-01 15:14:26.000000000 -0400
20510 +++ linux-2.6.16.12/init/Kconfig 2006-05-01 20:17:34.000000000 -0400
20511 @@ -257,6 +257,7 @@ menuconfig EMBEDDED
20513 bool "Load all symbols for debugging/kksymoops" if EMBEDDED
20515 + depends on !GRKERNSEC_HIDESYM
20517 Say Y here to let the kernel print out symbolic crash information and
20518 symbolic stack backtraces. This increases the size of the kernel
20519 diff -urNp linux-2.6.16.12/init/main.c linux-2.6.16.12/init/main.c
20520 --- linux-2.6.16.12/init/main.c 2006-05-01 15:14:26.000000000 -0400
20521 +++ linux-2.6.16.12/init/main.c 2006-05-01 20:17:34.000000000 -0400
20522 @@ -100,6 +100,7 @@ static inline void mark_rodata_ro(void)
20524 extern void tc_init(void);
20526 +extern void grsecurity_init(void);
20528 enum system_states system_state;
20529 EXPORT_SYMBOL(system_state);
20530 @@ -150,6 +151,15 @@ static int __init maxcpus(char *str)
20532 __setup("maxcpus=", maxcpus);
20534 +#ifdef CONFIG_PAX_SOFTMODE
20535 +static int __init setup_pax_softmode(char *str)
20537 + get_option(&str, &pax_softmode);
20540 +__setup("pax_softmode=", setup_pax_softmode);
20543 static char * argv_init[MAX_INIT_ARGS+2] = { "init", NULL, };
20544 char * envp_init[MAX_INIT_ENVS+2] = { "HOME=/", "TERM=linux", NULL, };
20545 static const char *panic_later, *panic_param;
20546 @@ -699,6 +709,8 @@ static int init(void * unused)
20547 prepare_namespace();
20550 + grsecurity_init();
20553 * Ok, we have completed the initial bootup, and
20554 * we're essentially up and running. Get rid of the
20555 diff -urNp linux-2.6.16.12/ipc/msg.c linux-2.6.16.12/ipc/msg.c
20556 --- linux-2.6.16.12/ipc/msg.c 2006-05-01 15:14:26.000000000 -0400
20557 +++ linux-2.6.16.12/ipc/msg.c 2006-05-01 20:17:34.000000000 -0400
20559 #include <linux/syscalls.h>
20560 #include <linux/audit.h>
20561 #include <linux/seq_file.h>
20562 +#include <linux/grsecurity.h>
20563 #include <asm/current.h>
20564 #include <asm/uaccess.h>
20566 @@ -233,6 +234,9 @@ asmlinkage long sys_msgget (key_t key, i
20571 + gr_log_msgget(ret, msgflg);
20576 @@ -484,6 +488,8 @@ asmlinkage long sys_msgctl (int msqid, i
20580 + gr_log_msgrm(ipcp->uid, ipcp->cuid);
20582 freeque (msq, msqid);
20585 diff -urNp linux-2.6.16.12/ipc/sem.c linux-2.6.16.12/ipc/sem.c
20586 --- linux-2.6.16.12/ipc/sem.c 2006-05-01 15:14:26.000000000 -0400
20587 +++ linux-2.6.16.12/ipc/sem.c 2006-05-01 20:17:34.000000000 -0400
20589 #include <linux/audit.h>
20590 #include <linux/capability.h>
20591 #include <linux/seq_file.h>
20592 +#include <linux/grsecurity.h>
20593 #include <asm/uaccess.h>
20596 @@ -243,6 +244,9 @@ asmlinkage long sys_semget (key_t key, i
20601 + gr_log_semget(err, semflg);
20606 @@ -834,6 +838,8 @@ static int semctl_down(int semid, int se
20610 + gr_log_semrm(ipcp->uid, ipcp->cuid);
20612 freeary(sma, semid);
20615 diff -urNp linux-2.6.16.12/ipc/shm.c linux-2.6.16.12/ipc/shm.c
20616 --- linux-2.6.16.12/ipc/shm.c 2006-05-01 15:14:26.000000000 -0400
20617 +++ linux-2.6.16.12/ipc/shm.c 2006-05-01 20:17:34.000000000 -0400
20619 #include <linux/capability.h>
20620 #include <linux/ptrace.h>
20621 #include <linux/seq_file.h>
20622 +#include <linux/grsecurity.h>
20624 #include <asm/uaccess.h>
20626 @@ -53,6 +54,14 @@ static void shm_close (struct vm_area_st
20627 static int sysvipc_shm_proc_show(struct seq_file *s, void *it);
20630 +#ifdef CONFIG_GRKERNSEC
20631 +extern int gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
20632 + const time_t shm_createtime, const uid_t cuid,
20633 + const int shmid);
20634 +extern int gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid,
20635 + const time_t shm_createtime);
20638 size_t shm_ctlmax = SHMMAX;
20639 size_t shm_ctlall = SHMALL;
20640 int shm_ctlmni = SHMMNI;
20641 @@ -146,6 +155,17 @@ static void shm_close (struct vm_area_st
20642 shp->shm_lprid = current->tgid;
20643 shp->shm_dtim = get_seconds();
20645 +#ifdef CONFIG_GRKERNSEC_SHM
20646 + if (grsec_enable_shm) {
20647 + if (shp->shm_nattch == 0) {
20648 + shp->shm_perm.mode |= SHM_DEST;
20649 + shm_destroy(shp);
20652 + up(&shm_ids.sem);
20656 if(shp->shm_nattch == 0 &&
20657 shp->shm_perm.mode & SHM_DEST)
20659 @@ -245,6 +265,9 @@ static int newseg (key_t key, int shmflg
20660 shp->shm_lprid = 0;
20661 shp->shm_atim = shp->shm_dtim = 0;
20662 shp->shm_ctim = get_seconds();
20663 +#ifdef CONFIG_GRKERNSEC
20664 + shp->shm_createtime = get_seconds();
20666 shp->shm_segsz = size;
20667 shp->shm_nattch = 0;
20668 shp->id = shm_buildid(id,shp->shm_perm.seq);
20669 @@ -300,6 +323,8 @@ asmlinkage long sys_shmget (key_t key, s
20673 + gr_log_shmget(err, shmflg, size);
20678 @@ -605,6 +630,8 @@ asmlinkage long sys_shmctl (int shmid, i
20680 goto out_unlock_up;
20682 + gr_log_shmrm(shp->shm_perm.uid, shp->shm_perm.cuid);
20684 if (shp->shm_nattch){
20685 shp->shm_perm.mode |= SHM_DEST;
20686 /* Do not find it any more */
20687 @@ -749,9 +776,27 @@ long do_shmat(int shmid, char __user *sh
20691 +#ifdef CONFIG_GRKERNSEC
20692 + if (!gr_handle_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime,
20693 + shp->shm_perm.cuid, shmid)) {
20698 + if (!gr_chroot_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime)) {
20704 file = shp->shm_file;
20705 size = i_size_read(file->f_dentry->d_inode);
20708 +#ifdef CONFIG_GRKERNSEC
20709 + shp->shm_lapid = current->pid;
20714 down_write(¤t->mm->mmap_sem);
20715 @@ -918,3 +963,24 @@ static int sysvipc_shm_proc_show(struct
20720 +void gr_shm_exit(struct task_struct *task)
20722 +#ifdef CONFIG_GRKERNSEC_SHM
20724 + struct shmid_kernel *shp;
20726 + if (!grsec_enable_shm)
20729 + for (i = 0; i <= shm_ids.max_id; i++) {
20730 + shp = shm_get(i);
20731 + if (shp && (shp->shm_cprid == task->pid) &&
20732 + (shp->shm_nattch <= 0)) {
20733 + shp->shm_perm.mode |= SHM_DEST;
20734 + shm_destroy(shp);
20740 diff -urNp linux-2.6.16.12/kernel/capability.c linux-2.6.16.12/kernel/capability.c
20741 --- linux-2.6.16.12/kernel/capability.c 2006-05-01 15:14:26.000000000 -0400
20742 +++ linux-2.6.16.12/kernel/capability.c 2006-05-01 20:17:34.000000000 -0400
20744 #include <linux/module.h>
20745 #include <linux/security.h>
20746 #include <linux/syscalls.h>
20747 +#include <linux/grsecurity.h>
20748 #include <asm/uaccess.h>
20750 unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
20751 diff -urNp linux-2.6.16.12/kernel/configs.c linux-2.6.16.12/kernel/configs.c
20752 --- linux-2.6.16.12/kernel/configs.c 2006-05-01 15:14:26.000000000 -0400
20753 +++ linux-2.6.16.12/kernel/configs.c 2006-05-01 20:17:34.000000000 -0400
20754 @@ -89,8 +89,16 @@ static int __init ikconfig_init(void)
20755 struct proc_dir_entry *entry;
20757 /* create the current config file */
20758 +#ifdef CONFIG_GRKERNSEC_PROC_ADD
20759 +#ifdef CONFIG_GRKERNSEC_PROC_USER
20760 + entry = create_proc_entry("config.gz", S_IFREG | S_IRUSR, &proc_root);
20761 +#elif CONFIG_GRKERNSEC_PROC_USERGROUP
20762 + entry = create_proc_entry("config.gz", S_IFREG | S_IRUSR | S_IRGRP, &proc_root);
20765 entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO,
20771 diff -urNp linux-2.6.16.12/kernel/exit.c linux-2.6.16.12/kernel/exit.c
20772 --- linux-2.6.16.12/kernel/exit.c 2006-05-01 15:14:26.000000000 -0400
20773 +++ linux-2.6.16.12/kernel/exit.c 2006-05-01 20:17:34.000000000 -0400
20775 #include <linux/signal.h>
20776 #include <linux/cn_proc.h>
20777 #include <linux/mutex.h>
20778 +#include <linux/grsecurity.h>
20780 +#ifdef CONFIG_GRKERNSEC
20781 +extern rwlock_t grsec_exec_file_lock;
20784 #include <asm/uaccess.h>
20785 #include <asm/unistd.h>
20786 @@ -234,6 +239,15 @@ static void reparent_to_init(void)
20788 write_lock_irq(&tasklist_lock);
20790 +#ifdef CONFIG_GRKERNSEC
20791 + write_lock(&grsec_exec_file_lock);
20792 + if (current->exec_file) {
20793 + fput(current->exec_file);
20794 + current->exec_file = NULL;
20796 + write_unlock(&grsec_exec_file_lock);
20799 ptrace_unlink(current);
20800 /* Reparent to init */
20801 REMOVE_LINKS(current);
20802 @@ -241,6 +255,8 @@ static void reparent_to_init(void)
20803 current->real_parent = child_reaper;
20804 SET_LINKS(current);
20806 + gr_set_kernel_label(current);
20808 /* Set the exit signal to SIGCHLD so we signal init on exit */
20809 current->exit_signal = SIGCHLD;
20811 @@ -337,6 +353,17 @@ void daemonize(const char *name, ...)
20812 vsnprintf(current->comm, sizeof(current->comm), name, args);
20815 +#ifdef CONFIG_GRKERNSEC
20816 + write_lock(&grsec_exec_file_lock);
20817 + if (current->exec_file) {
20818 + fput(current->exec_file);
20819 + current->exec_file = NULL;
20821 + write_unlock(&grsec_exec_file_lock);
20824 + gr_set_kernel_label(current);
20827 * If we were started as result of loading a module, close all of the
20828 * user space pages. We don't need them, and if we didn't close them
20829 @@ -852,9 +879,14 @@ fastcall NORET_TYPE void do_exit(long co
20830 exit_itimers(tsk->signal);
20831 acct_process(code);
20834 + gr_acl_handle_psacct(tsk, code);
20835 + gr_acl_handle_exit();
20840 + gr_shm_exit(tsk);
20843 exit_namespace(tsk);
20844 diff -urNp linux-2.6.16.12/kernel/fork.c linux-2.6.16.12/kernel/fork.c
20845 --- linux-2.6.16.12/kernel/fork.c 2006-05-01 15:14:26.000000000 -0400
20846 +++ linux-2.6.16.12/kernel/fork.c 2006-05-01 20:17:34.000000000 -0400
20848 #include <linux/rmap.h>
20849 #include <linux/acct.h>
20850 #include <linux/cn_proc.h>
20851 +#include <linux/grsecurity.h>
20853 #include <asm/pgtable.h>
20854 #include <asm/pgalloc.h>
20855 @@ -200,8 +201,8 @@ static inline int dup_mmap(struct mm_str
20858 mm->mmap_cache = NULL;
20859 - mm->free_area_cache = oldmm->mmap_base;
20860 - mm->cached_hole_size = ~0UL;
20861 + mm->free_area_cache = oldmm->free_area_cache;
20862 + mm->cached_hole_size = oldmm->cached_hole_size;
20864 cpus_clear(mm->cpu_vm_mask);
20865 mm->mm_rb = RB_ROOT;
20866 @@ -326,7 +327,7 @@ static struct mm_struct * mm_init(struct
20867 spin_lock_init(&mm->page_table_lock);
20868 rwlock_init(&mm->ioctx_list_lock);
20869 mm->ioctx_list = NULL;
20870 - mm->free_area_cache = TASK_UNMAPPED_BASE;
20871 + mm->free_area_cache = ~0UL;
20872 mm->cached_hole_size = ~0UL;
20874 if (likely(!mm_alloc_pgd(mm))) {
20875 @@ -946,6 +947,9 @@ static task_t *copy_process(unsigned lon
20880 + gr_learn_resource(p, RLIMIT_NPROC, atomic_read(&p->user->processes), 0);
20882 if (atomic_read(&p->user->processes) >=
20883 p->signal->rlim[RLIMIT_NPROC].rlim_cur) {
20884 if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) &&
20885 @@ -1055,6 +1059,8 @@ static task_t *copy_process(unsigned lon
20887 goto bad_fork_cleanup_namespace;
20889 + gr_copy_label(p);
20891 p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL;
20893 * Clear TID on mm_release()?
20894 @@ -1239,6 +1245,8 @@ bad_fork_cleanup_count:
20898 + gr_log_forkfail(retval);
20900 return ERR_PTR(retval);
20903 @@ -1296,6 +1304,9 @@ long do_fork(unsigned long clone_flags,
20908 + gr_handle_brute_check();
20910 if (unlikely(current->ptrace)) {
20911 trace = fork_traceflag (clone_flags);
20913 diff -urNp linux-2.6.16.12/kernel/futex.c linux-2.6.16.12/kernel/futex.c
20914 --- linux-2.6.16.12/kernel/futex.c 2006-05-01 15:14:26.000000000 -0400
20915 +++ linux-2.6.16.12/kernel/futex.c 2006-05-01 20:17:34.000000000 -0400
20916 @@ -147,6 +147,11 @@ static int get_futex_key(unsigned long u
20920 +#ifdef CONFIG_PAX_SEGMEXEC
20921 + if ((mm->pax_flags & MF_PAX_SEGMEXEC) && (uaddr >= SEGMEXEC_TASK_SIZE))
20926 * The futex address must be "naturally" aligned.
20928 diff -urNp linux-2.6.16.12/kernel/kallsyms.c linux-2.6.16.12/kernel/kallsyms.c
20929 --- linux-2.6.16.12/kernel/kallsyms.c 2006-05-01 15:14:26.000000000 -0400
20930 +++ linux-2.6.16.12/kernel/kallsyms.c 2006-05-01 20:17:34.000000000 -0400
20931 @@ -301,7 +301,6 @@ static unsigned long get_ksymbol_core(st
20933 static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
20935 - iter->name[0] = '\0';
20936 iter->nameoff = get_symbol_offset(new_pos);
20937 iter->pos = new_pos;
20939 @@ -380,7 +379,7 @@ static int kallsyms_open(struct inode *i
20940 struct kallsym_iter *iter;
20943 - iter = kmalloc(sizeof(*iter), GFP_KERNEL);
20944 + iter = kzalloc(sizeof(*iter), GFP_KERNEL);
20947 reset_iter(iter, 0);
20948 @@ -411,7 +410,15 @@ static int __init kallsyms_init(void)
20950 struct proc_dir_entry *entry;
20952 +#ifdef CONFIG_GRKERNSEC_PROC_ADD
20953 +#ifdef CONFIG_GRKERNSEC_PROC_USER
20954 + entry = create_proc_entry("kallsyms", S_IFREG | S_IRUSR, NULL);
20955 +#elif CONFIG_GRKERNSEC_PROC_USERGROUP
20956 + entry = create_proc_entry("kallsyms", S_IFREG | S_IRUSR | S_IRGRP, NULL);
20959 entry = create_proc_entry("kallsyms", 0444, NULL);
20962 entry->proc_fops = &kallsyms_operations;
20964 diff -urNp linux-2.6.16.12/kernel/kprobes.c linux-2.6.16.12/kernel/kprobes.c
20965 --- linux-2.6.16.12/kernel/kprobes.c 2006-05-01 15:14:26.000000000 -0400
20966 +++ linux-2.6.16.12/kernel/kprobes.c 2006-05-01 20:17:34.000000000 -0400
20967 @@ -106,7 +106,7 @@ kprobe_opcode_t __kprobes *get_insn_slot
20968 * kernel image and loaded module images reside. This is required
20969 * so x86_64 can correctly handle the %rip-relative fixups.
20971 - kip->insns = module_alloc(PAGE_SIZE);
20972 + kip->insns = module_alloc_exec(PAGE_SIZE);
20976 diff -urNp linux-2.6.16.12/kernel/module.c linux-2.6.16.12/kernel/module.c
20977 --- linux-2.6.16.12/kernel/module.c 2006-05-01 15:14:26.000000000 -0400
20978 +++ linux-2.6.16.12/kernel/module.c 2006-05-01 20:17:34.000000000 -0400
20979 @@ -39,10 +39,15 @@
20980 #include <linux/device.h>
20981 #include <linux/string.h>
20982 #include <linux/sched.h>
20983 +#include <linux/kallsyms.h>
20984 #include <asm/uaccess.h>
20985 #include <asm/semaphore.h>
20986 #include <asm/cacheflush.h>
20988 +#ifdef CONFIG_PAX_KERNEXEC
20989 +#include <asm/desc.h>
20993 #define DEBUGP printk
20995 @@ -66,6 +71,8 @@ static LIST_HEAD(modules);
20996 static DECLARE_MUTEX(notify_mutex);
20997 static struct notifier_block * module_notify_list;
20999 +extern int gr_check_modstop(void);
21001 int register_module_notifier(struct notifier_block * nb)
21004 @@ -576,6 +583,9 @@ sys_delete_module(const char __user *nam
21005 char name[MODULE_NAME_LEN];
21006 int ret, forced = 0;
21008 + if (gr_check_modstop())
21011 if (!capable(CAP_SYS_MODULE))
21014 @@ -1178,13 +1188,15 @@ static void free_module(struct module *m
21015 module_unload_free(mod);
21017 /* This may be NULL, but that's OK */
21018 - module_free(mod, mod->module_init);
21019 + module_free(mod, mod->module_init_rw);
21020 + module_free_exec(mod, mod->module_init_rx);
21023 percpu_modfree(mod->percpu);
21025 /* Finally, free the core (containing the module structure) */
21026 - module_free(mod, mod->module_core);
21027 + module_free_exec(mod, mod->module_core_rx);
21028 + module_free(mod, mod->module_core_rw);
21031 void *__symbol_get(const char *symbol)
21032 @@ -1341,11 +1353,14 @@ static void layout_sections(struct modul
21033 || strncmp(secstrings + s->sh_name,
21036 - s->sh_entsize = get_offset(&mod->core_size, s);
21037 + if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
21038 + s->sh_entsize = get_offset(&mod->core_size_rw, s);
21040 + s->sh_entsize = get_offset(&mod->core_size_rx, s);
21041 DEBUGP("\t%s\n", secstrings + s->sh_name);
21044 - mod->core_text_size = mod->core_size;
21045 + mod->core_size_rx = mod->core_size_rx;
21048 DEBUGP("Init section allocation order:\n");
21049 @@ -1359,12 +1374,15 @@ static void layout_sections(struct modul
21050 || strncmp(secstrings + s->sh_name,
21053 - s->sh_entsize = (get_offset(&mod->init_size, s)
21054 - | INIT_OFFSET_MASK);
21055 + if ((s->sh_flags & SHF_WRITE) || !(s->sh_flags & SHF_ALLOC))
21056 + s->sh_entsize = get_offset(&mod->init_size_rw, s);
21058 + s->sh_entsize = get_offset(&mod->init_size_rx, s);
21059 + s->sh_entsize |= INIT_OFFSET_MASK;
21060 DEBUGP("\t%s\n", secstrings + s->sh_name);
21063 - mod->init_text_size = mod->init_size;
21064 + mod->init_size_rx = mod->init_size_rx;
21068 @@ -1545,6 +1563,10 @@ static struct module *load_module(void _
21069 struct exception_table_entry *extable;
21070 mm_segment_t old_fs;
21072 +#ifdef CONFIG_PAX_KERNEXEC
21073 + unsigned long cr0;
21076 DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
21078 if (len < sizeof(*hdr))
21079 @@ -1704,21 +1726,57 @@ static struct module *load_module(void _
21080 layout_sections(mod, hdr, sechdrs, secstrings);
21082 /* Do the allocs. */
21083 - ptr = module_alloc(mod->core_size);
21084 + ptr = module_alloc(mod->core_size_rw);
21089 - memset(ptr, 0, mod->core_size);
21090 - mod->module_core = ptr;
21091 + memset(ptr, 0, mod->core_size_rw);
21092 + mod->module_core_rw = ptr;
21094 + ptr = module_alloc(mod->init_size_rw);
21095 + if (!ptr && mod->init_size_rw) {
21097 + goto free_core_rw;
21099 + memset(ptr, 0, mod->init_size_rw);
21100 + mod->module_init_rw = ptr;
21102 + ptr = module_alloc_exec(mod->core_size_rx);
21105 + goto free_init_rw;
21108 +#ifdef CONFIG_PAX_KERNEXEC
21109 + pax_open_kernel(cr0);
21112 + memset(ptr, 0, mod->core_size_rx);
21114 +#ifdef CONFIG_PAX_KERNEXEC
21115 + pax_close_kernel(cr0);
21118 + mod->module_core_rx = ptr;
21120 - ptr = module_alloc(mod->init_size);
21121 - if (!ptr && mod->init_size) {
21122 + ptr = module_alloc_exec(mod->init_size_rx);
21123 + if (!ptr && mod->init_size_rx) {
21126 + goto free_core_rx;
21128 - memset(ptr, 0, mod->init_size);
21129 - mod->module_init = ptr;
21131 +#ifdef CONFIG_PAX_KERNEXEC
21132 + pax_open_kernel(cr0);
21135 + memset(ptr, 0, mod->init_size_rx);
21137 +#ifdef CONFIG_PAX_KERNEXEC
21138 + pax_close_kernel(cr0);
21141 + mod->module_init_rx = ptr;
21143 /* Transfer each section which specifies SHF_ALLOC */
21144 DEBUGP("final section addresses:\n");
21145 @@ -1728,17 +1786,44 @@ static struct module *load_module(void _
21146 if (!(sechdrs[i].sh_flags & SHF_ALLOC))
21149 - if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK)
21150 - dest = mod->module_init
21151 - + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
21153 - dest = mod->module_core + sechdrs[i].sh_entsize;
21154 + if (sechdrs[i].sh_entsize & INIT_OFFSET_MASK) {
21155 + if ((sechdrs[i].sh_flags & SHF_WRITE) || !(sechdrs[i].sh_flags & SHF_ALLOC))
21156 + dest = mod->module_init_rw
21157 + + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
21159 + dest = mod->module_init_rx
21160 + + (sechdrs[i].sh_entsize & ~INIT_OFFSET_MASK);
21162 + if ((sechdrs[i].sh_flags & SHF_WRITE) || !(sechdrs[i].sh_flags & SHF_ALLOC))
21163 + dest = mod->module_core_rw + sechdrs[i].sh_entsize;
21165 + dest = mod->module_core_rx + sechdrs[i].sh_entsize;
21168 - if (sechdrs[i].sh_type != SHT_NOBITS)
21169 - memcpy(dest, (void *)sechdrs[i].sh_addr,
21170 - sechdrs[i].sh_size);
21171 + if (sechdrs[i].sh_type != SHT_NOBITS) {
21173 +#ifdef CONFIG_PAX_KERNEXEC
21174 + if (!(sechdrs[i].sh_flags & SHF_WRITE) && (sechdrs[i].sh_flags & SHF_ALLOC))
21175 + pax_open_kernel(cr0);
21178 + memcpy(dest, (void *)sechdrs[i].sh_addr, sechdrs[i].sh_size);
21180 +#ifdef CONFIG_PAX_KERNEXEC
21181 + if (!(sechdrs[i].sh_flags & SHF_WRITE) && (sechdrs[i].sh_flags & SHF_ALLOC))
21182 + pax_close_kernel(cr0);
21186 /* Update sh_addr to point to copy in image. */
21187 - sechdrs[i].sh_addr = (unsigned long)dest;
21189 +#ifdef CONFIG_PAX_KERNEXEC
21190 + if (sechdrs[i].sh_flags & SHF_EXECINSTR)
21191 + sechdrs[i].sh_addr = (unsigned long)dest - __KERNEL_TEXT_OFFSET;
21195 + sechdrs[i].sh_addr = (unsigned long)dest;
21196 DEBUGP("\t0x%lx %s\n", sechdrs[i].sh_addr, secstrings + sechdrs[i].sh_name);
21198 /* Module has been moved. */
21199 @@ -1761,8 +1846,18 @@ static struct module *load_module(void _
21202 /* Fix up syms, so that st_value is a pointer to location. */
21204 +#ifdef CONFIG_PAX_KERNEXEC
21205 + pax_open_kernel(cr0);
21208 err = simplify_symbols(sechdrs, symindex, strtab, versindex, pcpuindex,
21211 +#ifdef CONFIG_PAX_KERNEXEC
21212 + pax_close_kernel(cr0);
21218 @@ -1798,11 +1893,20 @@ static struct module *load_module(void _
21219 if (!(sechdrs[info].sh_flags & SHF_ALLOC))
21222 +#ifdef CONFIG_PAX_KERNEXEC
21223 + pax_open_kernel(cr0);
21226 if (sechdrs[i].sh_type == SHT_REL)
21227 err = apply_relocate(sechdrs, strtab, symindex, i,mod);
21228 else if (sechdrs[i].sh_type == SHT_RELA)
21229 err = apply_relocate_add(sechdrs, strtab, symindex, i,
21232 +#ifdef CONFIG_PAX_KERNEXEC
21233 + pax_close_kernel(cr0);
21239 @@ -1816,14 +1920,31 @@ static struct module *load_module(void _
21240 /* Set up and sort exception table */
21241 mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
21242 mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
21244 +#ifdef CONFIG_PAX_KERNEXEC
21245 + pax_open_kernel(cr0);
21248 sort_extable(extable, extable + mod->num_exentries);
21250 +#ifdef CONFIG_PAX_KERNEXEC
21251 + pax_close_kernel(cr0);
21254 /* Finally, copy percpu area over. */
21255 percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
21256 sechdrs[pcpuindex].sh_size);
21258 +#ifdef CONFIG_PAX_KERNEXEC
21259 + pax_open_kernel(cr0);
21262 add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
21264 +#ifdef CONFIG_PAX_KERNEXEC
21265 + pax_close_kernel(cr0);
21268 err = module_finalize(hdr, sechdrs, mod);
21271 @@ -1837,12 +1958,12 @@ static struct module *load_module(void _
21272 * Do it before processing of module parameters, so the module
21273 * can provide parameter accessor functions of its own.
21275 - if (mod->module_init)
21276 - flush_icache_range((unsigned long)mod->module_init,
21277 - (unsigned long)mod->module_init
21278 - + mod->init_size);
21279 - flush_icache_range((unsigned long)mod->module_core,
21280 - (unsigned long)mod->module_core + mod->core_size);
21281 + if (mod->module_init_rx)
21282 + flush_icache_range((unsigned long)mod->module_init_rx,
21283 + (unsigned long)mod->module_init_rx
21284 + + mod->init_size_rx);
21285 + flush_icache_range((unsigned long)mod->module_core_rx,
21286 + (unsigned long)mod->module_core_rx + mod->core_size_rx);
21290 @@ -1890,9 +2011,13 @@ static struct module *load_module(void _
21291 module_arch_cleanup(mod);
21293 module_unload_free(mod);
21294 - module_free(mod, mod->module_init);
21296 - module_free(mod, mod->module_core);
21297 + module_free_exec(mod, mod->module_init_rx);
21299 + module_free_exec(mod, mod->module_core_rx);
21301 + module_free(mod, mod->module_init_rw);
21303 + module_free(mod, mod->module_core_rw);
21306 percpu_modfree(percpu);
21307 @@ -1928,6 +2053,9 @@ sys_init_module(void __user *umod,
21308 struct module *mod;
21311 + if (gr_check_modstop())
21314 /* Must have permission */
21315 if (!capable(CAP_SYS_MODULE))
21317 @@ -1979,10 +2107,12 @@ sys_init_module(void __user *umod,
21318 mod->state = MODULE_STATE_LIVE;
21319 /* Drop initial reference. */
21321 - module_free(mod, mod->module_init);
21322 - mod->module_init = NULL;
21323 - mod->init_size = 0;
21324 - mod->init_text_size = 0;
21325 + module_free(mod, mod->module_init_rw);
21326 + module_free_exec(mod, mod->module_init_rx);
21327 + mod->module_init_rw = NULL;
21328 + mod->module_init_rx = NULL;
21329 + mod->init_size_rw = 0;
21330 + mod->init_size_rx = 0;
21334 @@ -2013,10 +2143,14 @@ static const char *get_ksymbol(struct mo
21335 unsigned long nextval;
21337 /* At worse, next value is at end of module */
21338 - if (within(addr, mod->module_init, mod->init_size))
21339 - nextval = (unsigned long)mod->module_init+mod->init_text_size;
21341 - nextval = (unsigned long)mod->module_core+mod->core_text_size;
21342 + if (within(addr, mod->module_init_rx, mod->init_size_rx))
21343 + nextval = (unsigned long)mod->module_init_rw;
21344 + else if (within(addr, mod->module_init_rw, mod->init_size_rw))
21345 + nextval = (unsigned long)mod->module_core_rx;
21346 + else if (within(addr, mod->module_core_rx, mod->core_size_rx))
21347 + nextval = (unsigned long)mod->module_core_rw;
21349 + nextval = (unsigned long)mod->module_core_rw+mod->core_size_rw;
21351 /* Scan for closest preceeding symbol, and next symbol. (ELF
21352 starts real symbols at 1). */
21353 @@ -2057,8 +2191,10 @@ const char *module_address_lookup(unsign
21354 struct module *mod;
21356 list_for_each_entry(mod, &modules, list) {
21357 - if (within(addr, mod->module_init, mod->init_size)
21358 - || within(addr, mod->module_core, mod->core_size)) {
21359 + if (within(addr, mod->module_init_rx, mod->init_size_rx)
21360 + || within(addr, mod->module_init_rw, mod->init_size_rw)
21361 + || within(addr, mod->module_core_rx, mod->core_size_rx)
21362 + || within(addr, mod->module_core_rw, mod->core_size_rw)) {
21363 *modname = mod->name;
21364 return get_ksymbol(mod, addr, size, offset);
21366 @@ -2069,7 +2205,7 @@ const char *module_address_lookup(unsign
21367 struct module *module_get_kallsym(unsigned int symnum,
21368 unsigned long *value,
21370 - char namebuf[128])
21371 + char namebuf[KSYM_NAME_LEN+1])
21373 struct module *mod;
21375 @@ -2080,7 +2216,7 @@ struct module *module_get_kallsym(unsign
21376 *type = mod->symtab[symnum].st_info;
21378 mod->strtab + mod->symtab[symnum].st_name,
21384 @@ -2157,7 +2293,7 @@ static int m_show(struct seq_file *m, vo
21386 struct module *mod = list_entry(p, struct module, list);
21387 seq_printf(m, "%s %lu",
21388 - mod->name, mod->init_size + mod->core_size);
21389 + mod->name, mod->init_size_rx + mod->init_size_rw + mod->core_size_rx + mod->core_size_rw);
21390 print_unload_info(m, mod);
21392 /* Informative for users. */
21393 @@ -2166,7 +2302,7 @@ static int m_show(struct seq_file *m, vo
21394 mod->state == MODULE_STATE_COMING ? "Loading":
21396 /* Used by oprofile and other similar tools. */
21397 - seq_printf(m, " 0x%p", mod->module_core);
21398 + seq_printf(m, " 0x%p 0x%p", mod->module_core_rx, mod->module_core_rw);
21400 seq_printf(m, "\n");
21402 @@ -2214,9 +2350,13 @@ struct module *__module_text_address(uns
21404 struct module *mod;
21406 +#ifdef CONFIG_PAX_KERNEXEC
21407 + addr += __KERNEL_TEXT_OFFSET;
21410 list_for_each_entry(mod, &modules, list)
21411 - if (within(addr, mod->module_init, mod->init_text_size)
21412 - || within(addr, mod->module_core, mod->core_text_size))
21413 + if (within(addr, mod->module_init_rx, mod->init_size_rx)
21414 + || within(addr, mod->module_core_rx, mod->core_size_rx))
21418 diff -urNp linux-2.6.16.12/kernel/pid.c linux-2.6.16.12/kernel/pid.c
21419 --- linux-2.6.16.12/kernel/pid.c 2006-05-01 15:14:26.000000000 -0400
21420 +++ linux-2.6.16.12/kernel/pid.c 2006-05-01 20:17:34.000000000 -0400
21422 #include <linux/init.h>
21423 #include <linux/bootmem.h>
21424 #include <linux/hash.h>
21425 +#include <linux/grsecurity.h>
21427 #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift)
21428 static struct hlist_head *pid_hash[PIDTYPE_MAX];
21429 @@ -76,7 +77,9 @@ int alloc_pidmap(void)
21430 int i, offset, max_scan, pid, last = last_pid;
21434 + pid = gr_random_pid();
21436 + pid = last_pid + 1;
21437 if (pid >= pid_max)
21438 pid = RESERVED_PIDS;
21439 offset = pid & BITS_PER_PAGE_MASK;
21440 @@ -207,12 +210,18 @@ void fastcall detach_pid(task_t *task, e
21441 task_t *find_task_by_pid_type(int type, int nr)
21444 + task_t *task = NULL;
21446 pid = find_pid(type, nr);
21450 - return pid_task(&pid->pid_list, type);
21451 + task = pid_task(&pid->pid_list, type);
21453 + if (gr_pid_is_chrooted(task))
21459 EXPORT_SYMBOL(find_task_by_pid_type);
21460 diff -urNp linux-2.6.16.12/kernel/posix-cpu-timers.c linux-2.6.16.12/kernel/posix-cpu-timers.c
21461 --- linux-2.6.16.12/kernel/posix-cpu-timers.c 2006-05-01 15:14:26.000000000 -0400
21462 +++ linux-2.6.16.12/kernel/posix-cpu-timers.c 2006-05-01 20:17:34.000000000 -0400
21464 #include <linux/posix-timers.h>
21465 #include <asm/uaccess.h>
21466 #include <linux/errno.h>
21467 +#include <linux/grsecurity.h>
21469 static int check_clock(const clockid_t which_clock)
21471 @@ -1128,6 +1129,7 @@ static void check_process_timers(struct
21472 __group_send_sig_info(SIGKILL, SEND_SIG_PRIV, tsk);
21475 + gr_learn_resource(tsk, RLIMIT_CPU, psecs, 1);
21476 if (psecs >= sig->rlim[RLIMIT_CPU].rlim_cur) {
21478 * At the soft limit, send a SIGXCPU every second.
21479 diff -urNp linux-2.6.16.12/kernel/printk.c linux-2.6.16.12/kernel/printk.c
21480 --- linux-2.6.16.12/kernel/printk.c 2006-05-01 15:14:26.000000000 -0400
21481 +++ linux-2.6.16.12/kernel/printk.c 2006-05-01 20:17:34.000000000 -0400
21483 #include <linux/security.h>
21484 #include <linux/bootmem.h>
21485 #include <linux/syscalls.h>
21486 +#include <linux/grsecurity.h>
21488 #include <asm/uaccess.h>
21490 @@ -223,6 +224,11 @@ int do_syslog(int type, char __user *buf
21494 +#ifdef CONFIG_GRKERNSEC_DMESG
21495 + if (grsec_enable_dmesg && !capable(CAP_SYS_ADMIN))
21499 error = security_syslog(type);
21502 diff -urNp linux-2.6.16.12/kernel/ptrace.c linux-2.6.16.12/kernel/ptrace.c
21503 --- linux-2.6.16.12/kernel/ptrace.c 2006-05-01 15:14:26.000000000 -0400
21504 +++ linux-2.6.16.12/kernel/ptrace.c 2006-05-01 20:17:34.000000000 -0400
21506 #include <linux/ptrace.h>
21507 #include <linux/security.h>
21508 #include <linux/signal.h>
21509 +#include <linux/grsecurity.h>
21511 #include <asm/pgtable.h>
21512 #include <asm/uaccess.h>
21513 @@ -128,10 +129,10 @@ static int may_attach(struct task_struct
21514 (current->uid != task->uid) ||
21515 (current->gid != task->egid) ||
21516 (current->gid != task->sgid) ||
21517 - (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
21518 + (current->gid != task->gid)) && !capable_nolog(CAP_SYS_PTRACE))
21521 - if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
21522 + if (!task->mm->dumpable && !capable_nolog(CAP_SYS_PTRACE))
21525 return security_ptrace(current, task);
21526 @@ -495,6 +496,11 @@ asmlinkage long sys_ptrace(long request,
21528 goto out_put_task_struct;
21530 + if (gr_handle_ptrace(child, request)) {
21532 + goto out_put_task_struct;
21535 ret = arch_ptrace(child, request, addr, data);
21537 goto out_put_task_struct;
21538 diff -urNp linux-2.6.16.12/kernel/resource.c linux-2.6.16.12/kernel/resource.c
21539 --- linux-2.6.16.12/kernel/resource.c 2006-05-01 15:14:26.000000000 -0400
21540 +++ linux-2.6.16.12/kernel/resource.c 2006-05-01 20:17:34.000000000 -0400
21541 @@ -136,10 +136,27 @@ static int __init ioresources_init(void)
21543 struct proc_dir_entry *entry;
21545 +#ifdef CONFIG_GRKERNSEC_PROC_ADD
21546 +#ifdef CONFIG_GRKERNSEC_PROC_USER
21547 + entry = create_proc_entry("ioports", S_IRUSR, NULL);
21548 +#elif CONFIG_GRKERNSEC_PROC_USERGROUP
21549 + entry = create_proc_entry("ioports", S_IRUSR | S_IRGRP, NULL);
21552 entry = create_proc_entry("ioports", 0, NULL);
21555 entry->proc_fops = &proc_ioports_operations;
21557 +#ifdef CONFIG_GRKERNSEC_PROC_ADD
21558 +#ifdef CONFIG_GRKERNSEC_PROC_USER
21559 + entry = create_proc_entry("iomem", S_IRUSR, NULL);
21560 +#elif CONFIG_GRKERNSEC_PROC_USERGROUP
21561 + entry = create_proc_entry("iomem", S_IRUSR | S_IRGRP, NULL);
21564 entry = create_proc_entry("iomem", 0, NULL);
21567 entry->proc_fops = &proc_iomem_operations;
21569 diff -urNp linux-2.6.16.12/kernel/sched.c linux-2.6.16.12/kernel/sched.c
21570 --- linux-2.6.16.12/kernel/sched.c 2006-05-01 15:14:26.000000000 -0400
21571 +++ linux-2.6.16.12/kernel/sched.c 2006-05-01 20:17:34.000000000 -0400
21573 #include <linux/syscalls.h>
21574 #include <linux/times.h>
21575 #include <linux/acct.h>
21576 +#include <linux/grsecurity.h>
21577 #include <asm/tlb.h>
21579 #include <asm/unistd.h>
21580 @@ -3537,7 +3538,8 @@ asmlinkage long sys_nice(int increment)
21584 - if (increment < 0 && !can_nice(current, nice))
21585 + if (increment < 0 && (!can_nice(current, nice) ||
21586 + gr_handle_chroot_nice()))
21589 retval = security_task_setnice(current, nice);
21590 diff -urNp linux-2.6.16.12/kernel/signal.c linux-2.6.16.12/kernel/signal.c
21591 --- linux-2.6.16.12/kernel/signal.c 2006-05-01 15:14:26.000000000 -0400
21592 +++ linux-2.6.16.12/kernel/signal.c 2006-05-01 20:17:34.000000000 -0400
21594 #include <linux/signal.h>
21595 #include <linux/audit.h>
21596 #include <linux/capability.h>
21597 +#include <linux/grsecurity.h>
21598 #include <asm/param.h>
21599 #include <asm/uaccess.h>
21600 #include <asm/unistd.h>
21601 @@ -380,6 +381,7 @@ void __exit_signal(struct task_struct *t
21603 if (tsk == sig->curr_target)
21604 sig->curr_target = next_thread(tsk);
21605 + gr_del_task_from_ip_table(tsk);
21606 tsk->signal = NULL;
21608 * Accumulate here the counters for all threads but the
21609 @@ -681,16 +683,18 @@ static int check_kill_permission(int sig
21612 if ((info == SEND_SIG_NOINFO || (!is_si_special(info) && SI_FROMUSER(info)))
21613 - && ((sig != SIGCONT) ||
21614 + && ((((sig != SIGCONT) ||
21615 (current->signal->session != t->signal->session))
21616 && (current->euid ^ t->suid) && (current->euid ^ t->uid)
21617 && (current->uid ^ t->suid) && (current->uid ^ t->uid)
21618 - && !capable(CAP_KILL))
21619 + && !capable(CAP_KILL)) || gr_handle_signal(t, sig)))
21622 error = security_task_kill(t, info, sig);
21625 audit_signal_info(sig, t); /* Let audit system see the signal */
21626 + gr_log_signal(sig, t);
21631 @@ -870,7 +874,7 @@ out_set:
21632 (((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig)))
21637 specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
21640 @@ -916,6 +920,10 @@ force_sig_info(int sig, struct siginfo *
21642 recalc_sigpending_tsk(t);
21643 ret = specific_send_sig_info(sig, info, t);
21645 + gr_log_signal(sig, t);
21646 + gr_handle_crash(t, sig);
21648 spin_unlock_irqrestore(&t->sighand->siglock, flags);
21651 diff -urNp linux-2.6.16.12/kernel/sys.c linux-2.6.16.12/kernel/sys.c
21652 --- linux-2.6.16.12/kernel/sys.c 2006-05-01 15:14:26.000000000 -0400
21653 +++ linux-2.6.16.12/kernel/sys.c 2006-05-01 20:17:34.000000000 -0400
21655 #include <linux/tty.h>
21656 #include <linux/signal.h>
21657 #include <linux/cn_proc.h>
21658 +#include <linux/grsecurity.h>
21660 #include <linux/compat.h>
21661 #include <linux/syscalls.h>
21662 @@ -225,16 +226,33 @@ int unregister_reboot_notifier(struct no
21663 EXPORT_SYMBOL(unregister_reboot_notifier);
21665 #ifndef CONFIG_SECURITY
21666 +extern int gr_task_is_capable(struct task_struct *task, const int cap);
21667 +extern int gr_is_capable_nolog(const int cap);
21668 int capable(int cap)
21670 - if (cap_raised(current->cap_effective, cap)) {
21671 + if (cap_raised(current->cap_effective, cap) && gr_task_is_capable(current, cap)) {
21672 + current->flags |= PF_SUPERPRIV;
21677 +int capable_nolog(int cap)
21679 + if (cap_raised(current->cap_effective, cap) && gr_is_capable_nolog(cap)) {
21680 current->flags |= PF_SUPERPRIV;
21685 EXPORT_SYMBOL(capable);
21687 +int capable_nolog(int cap)
21689 + return capable(cap);
21693 +EXPORT_SYMBOL(capable_nolog);
21695 static int set_one_prio(struct task_struct *p, int niceval, int error)
21697 @@ -249,6 +267,12 @@ static int set_one_prio(struct task_stru
21702 + if (gr_handle_chroot_setpriority(p, niceval)) {
21707 no_nice = security_task_setnice(p, niceval);
21710 @@ -638,6 +662,9 @@ asmlinkage long sys_setregid(gid_t rgid,
21711 if (rgid != (gid_t) -1 ||
21712 (egid != (gid_t) -1 && egid != old_rgid))
21713 current->sgid = new_egid;
21715 + gr_set_role_label(current, current->uid, new_rgid);
21717 current->fsgid = new_egid;
21718 current->egid = new_egid;
21719 current->gid = new_rgid;
21720 @@ -667,6 +694,9 @@ asmlinkage long sys_setgid(gid_t gid)
21721 current->mm->dumpable = suid_dumpable;
21725 + gr_set_role_label(current, current->uid, gid);
21727 current->gid = current->egid = current->sgid = current->fsgid = gid;
21729 else if ((gid == current->gid) || (gid == current->sgid))
21730 @@ -708,6 +738,9 @@ static int set_user(uid_t new_ruid, int
21731 current->mm->dumpable = suid_dumpable;
21735 + gr_set_role_label(current, new_ruid, current->gid);
21737 current->uid = new_ruid;
21740 @@ -811,6 +844,9 @@ asmlinkage long sys_setuid(uid_t uid)
21741 } else if ((uid != current->uid) && (uid != new_suid))
21744 + if (gr_check_crash_uid(uid))
21747 if (old_euid != uid)
21749 current->mm->dumpable = suid_dumpable;
21750 @@ -916,8 +952,10 @@ asmlinkage long sys_setresgid(gid_t rgid
21751 current->egid = egid;
21753 current->fsgid = current->egid;
21754 - if (rgid != (gid_t) -1)
21755 + if (rgid != (gid_t) -1) {
21756 + gr_set_role_label(current, current->uid, rgid);
21757 current->gid = rgid;
21759 if (sgid != (gid_t) -1)
21760 current->sgid = sgid;
21762 diff -urNp linux-2.6.16.12/kernel/sysctl.c linux-2.6.16.12/kernel/sysctl.c
21763 --- linux-2.6.16.12/kernel/sysctl.c 2006-05-01 15:14:26.000000000 -0400
21764 +++ linux-2.6.16.12/kernel/sysctl.c 2006-05-01 20:17:34.000000000 -0400
21765 @@ -54,6 +54,14 @@ extern int proc_nr_files(ctl_table *tabl
21766 void __user *buffer, size_t *lenp, loff_t *ppos);
21768 #if defined(CONFIG_SYSCTL)
21769 +#include <linux/grsecurity.h>
21770 +#include <linux/grinternal.h>
21772 +extern __u32 gr_handle_sysctl(const ctl_table *table, const void *oldval,
21773 + const void *newval);
21774 +extern int gr_handle_sysctl_mod(const char *dirname, const char *name,
21776 +extern int gr_handle_chroot_sysctl(const int op);
21778 /* External variables not in a header file. */
21780 @@ -157,6 +165,22 @@ extern ctl_table inotify_table[];
21781 #ifdef HAVE_ARCH_PICK_MMAP_LAYOUT
21782 int sysctl_legacy_va_layout;
21784 +extern ctl_table grsecurity_table[];
21786 +#ifdef CONFIG_PAX_SOFTMODE
21787 +static ctl_table pax_table[] = {
21789 + .ctl_name = PAX_SOFTMODE,
21790 + .procname = "softmode",
21791 + .data = &pax_softmode,
21792 + .maxlen = sizeof(unsigned int),
21794 + .proc_handler = &proc_dointvec,
21797 + { .ctl_name = 0 }
21801 /* /proc declarations: */
21803 @@ -683,6 +707,25 @@ static ctl_table kern_table[] = {
21804 .proc_handler = &proc_dointvec,
21808 +#if defined(CONFIG_GRKERNSEC_SYSCTL) || defined(CONFIG_GRKERNSEC_MODSTOP)
21810 + .ctl_name = KERN_GRSECURITY,
21811 + .procname = "grsecurity",
21813 + .child = grsecurity_table,
21817 +#ifdef CONFIG_PAX_SOFTMODE
21819 + .ctl_name = KERN_PAX,
21820 + .procname = "pax",
21822 + .child = pax_table,
21829 @@ -1181,6 +1224,10 @@ static int test_perm(int mode, int op)
21830 static inline int ctl_perm(ctl_table *table, int op)
21833 + if (table->de && gr_handle_sysctl_mod(table->de->parent->name, table->de->name, op))
21835 + if (gr_handle_chroot_sysctl(op))
21837 error = security_sysctl(table, op);
21840 @@ -1217,6 +1264,10 @@ repeat:
21841 table = table->child;
21845 + if (!gr_handle_sysctl(table, oldval, newval))
21848 error = do_sysctl_strategy(table, name, nlen,
21850 newval, newlen, context);
21851 diff -urNp linux-2.6.16.12/kernel/time.c linux-2.6.16.12/kernel/time.c
21852 --- linux-2.6.16.12/kernel/time.c 2006-05-01 15:14:26.000000000 -0400
21853 +++ linux-2.6.16.12/kernel/time.c 2006-05-01 20:17:34.000000000 -0400
21855 #include <linux/security.h>
21856 #include <linux/fs.h>
21857 #include <linux/module.h>
21858 +#include <linux/grsecurity.h>
21860 #include <asm/uaccess.h>
21861 #include <asm/unistd.h>
21862 @@ -93,6 +94,9 @@ asmlinkage long sys_stime(time_t __user
21865 do_settimeofday(&tv);
21867 + gr_log_timechange();
21872 @@ -199,6 +203,8 @@ asmlinkage long sys_settimeofday(struct
21876 + gr_log_timechange();
21878 return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL);
21881 diff -urNp linux-2.6.16.12/localversion-grsec linux-2.6.16.12/localversion-grsec
21882 --- linux-2.6.16.12/localversion-grsec 1969-12-31 19:00:00.000000000 -0500
21883 +++ linux-2.6.16.12/localversion-grsec 2006-05-01 20:17:34.000000000 -0400
21886 diff -urNp linux-2.6.16.12/Makefile linux-2.6.16.12/Makefile
21887 --- linux-2.6.16.12/Makefile 2006-05-01 15:14:26.000000000 -0400
21888 +++ linux-2.6.16.12/Makefile 2006-05-01 20:17:34.000000000 -0400
21889 @@ -556,7 +556,7 @@ export MODLIB
21892 ifeq ($(KBUILD_EXTMOD),)
21893 -core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/
21894 +core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ block/ grsecurity/
21896 vmlinux-dirs := $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \
21897 $(core-y) $(core-m) $(drivers-y) $(drivers-m) \
21898 diff -urNp linux-2.6.16.12/mm/filemap.c linux-2.6.16.12/mm/filemap.c
21899 --- linux-2.6.16.12/mm/filemap.c 2006-05-01 15:14:26.000000000 -0400
21900 +++ linux-2.6.16.12/mm/filemap.c 2006-05-01 20:17:34.000000000 -0400
21902 #include <linux/blkdev.h>
21903 #include <linux/security.h>
21904 #include <linux/syscalls.h>
21905 +#include <linux/grsecurity.h>
21906 #include "filemap.h"
21908 * FIXME: remove all knowledge of the buffer layer from the core VM
21909 @@ -1587,7 +1588,13 @@ int generic_file_mmap(struct file * file
21910 struct address_space *mapping = file->f_mapping;
21912 if (!mapping->a_ops->readpage)
21916 +#ifdef CONFIG_PAX_PAGEEXEC
21917 + if (vma->vm_mm->pax_flags & MF_PAX_PAGEEXEC)
21918 + vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f];
21921 file_accessed(file);
21922 vma->vm_ops = &generic_file_vm_ops;
21924 @@ -1809,6 +1816,7 @@ inline int generic_write_checks(struct f
21925 *pos = i_size_read(inode);
21927 if (limit != RLIM_INFINITY) {
21928 + gr_learn_resource(current, RLIMIT_FSIZE,*pos, 0);
21929 if (*pos >= limit) {
21930 send_sig(SIGXFSZ, current, 0);
21932 diff -urNp linux-2.6.16.12/mm/madvise.c linux-2.6.16.12/mm/madvise.c
21933 --- linux-2.6.16.12/mm/madvise.c 2006-05-01 15:14:26.000000000 -0400
21934 +++ linux-2.6.16.12/mm/madvise.c 2006-05-01 20:17:34.000000000 -0400
21936 * We can potentially split a vm area into separate
21937 * areas, each area with its own behavior.
21940 +#ifdef CONFIG_PAX_SEGMEXEC
21941 +static long __madvise_behavior(struct vm_area_struct * vma,
21942 + struct vm_area_struct **prev,
21943 + unsigned long start, unsigned long end, int behavior);
21945 +static long madvise_behavior(struct vm_area_struct * vma,
21946 + struct vm_area_struct **prev,
21947 + unsigned long start, unsigned long end, int behavior)
21949 + if (vma->vm_flags & VM_MIRROR) {
21950 + struct vm_area_struct * vma_m, * prev_m;
21951 + unsigned long start_m, end_m;
21954 + start_m = vma->vm_start + vma->vm_mirror;
21955 + vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m);
21956 + if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
21957 + start_m = start + vma->vm_mirror;
21958 + end_m = end + vma->vm_mirror;
21959 + error = __madvise_behavior(vma_m, &prev_m, start_m, end_m, behavior);
21963 + printk("PAX: VMMIRROR: madvise bug in %s, %08lx\n", current->comm, vma->vm_start);
21968 + return __madvise_behavior(vma, prev, start, end, behavior);
21971 +static long __madvise_behavior(struct vm_area_struct * vma,
21972 + struct vm_area_struct **prev,
21973 + unsigned long start, unsigned long end, int behavior)
21975 static long madvise_behavior(struct vm_area_struct * vma,
21976 struct vm_area_struct **prev,
21977 unsigned long start, unsigned long end, int behavior)
21980 struct mm_struct * mm = vma->vm_mm;
21982 diff -urNp linux-2.6.16.12/mm/memory.c linux-2.6.16.12/mm/memory.c
21983 --- linux-2.6.16.12/mm/memory.c 2006-05-01 15:14:26.000000000 -0400
21984 +++ linux-2.6.16.12/mm/memory.c 2006-05-01 20:17:34.000000000 -0400
21986 #include <linux/rmap.h>
21987 #include <linux/module.h>
21988 #include <linux/init.h>
21989 +#include <linux/grsecurity.h>
21991 #include <asm/pgalloc.h>
21992 #include <asm/uaccess.h>
21993 @@ -321,6 +322,11 @@ int __pte_alloc(struct mm_struct *mm, pm
21995 int __pte_alloc_kernel(pmd_t *pmd, unsigned long address)
21998 +#ifdef CONFIG_PAX_KERNEXEC
21999 + unsigned long cr0;
22002 pte_t *new = pte_alloc_one_kernel(&init_mm, address);
22005 @@ -328,8 +334,19 @@ int __pte_alloc_kernel(pmd_t *pmd, unsig
22006 spin_lock(&init_mm.page_table_lock);
22007 if (pmd_present(*pmd)) /* Another has populated it */
22008 pte_free_kernel(new);
22012 +#ifdef CONFIG_PAX_KERNEXEC
22013 + pax_open_kernel(cr0);
22016 pmd_populate_kernel(&init_mm, pmd, new);
22018 +#ifdef CONFIG_PAX_KERNEXEC
22019 + pax_close_kernel(cr0);
22023 spin_unlock(&init_mm.page_table_lock);
22026 @@ -1424,6 +1441,88 @@ static inline void cow_user_page(struct
22027 copy_user_highpage(dst, src, va);
22030 +#ifdef CONFIG_PAX_SEGMEXEC
22031 +/* PaX: if vma is mirrored, synchronize the mirror's PTE
22033 + * the ptl of the lower mapped page is held on entry and is not released on exit
22034 + * or inside to ensure atomic changes to the PTE states (swapout, mremap, munmap, etc)
22036 +static void pax_mirror_fault(struct vm_area_struct *vma, unsigned long address, pte_t *pte)
22038 + struct mm_struct *mm = vma->vm_mm;
22039 + unsigned long address_m, pfn_m;
22040 + struct vm_area_struct * vma_m = NULL;
22041 + pte_t * pte_m, entry_m;
22042 + struct page * page_m = NULL;
22044 + address_m = vma->vm_start + vma->vm_mirror;
22045 + vma_m = find_vma(mm, address_m);
22046 + BUG_ON(!vma_m || vma_m->vm_start != address_m);
22048 + address_m = address + vma->vm_mirror;
22049 + pte_m = pte_offset_map_nested(pmd_offset(pud_offset(pgd_offset(mm, address_m), address_m), address_m), address_m);
22051 + if (pte_same(*pte, *pte_m)) {
22052 + pte_unmap_nested(pte_m);
22056 + if (pte_present(*pte_m)) {
22057 + page_m = vm_normal_page(vma_m, address_m, *pte_m);
22059 + flush_cache_page(vma_m, address_m, pfn_m);
22060 + flush_icache_page(vma_m, page_m);
22064 + if (pte_present(*pte_m))
22065 + entry_m = ptep_clear_flush(vma_m, address_m, pte_m);
22067 + entry_m = ptep_get_and_clear(mm, address_m, pte_m);
22069 + if (pte_none(entry_m)) {
22070 + } else if (pte_present(entry_m)) {
22072 + page_remove_rmap(page_m);
22073 + if (PageAnon(page_m))
22074 + dec_mm_counter(mm, anon_rss);
22076 + dec_mm_counter(mm, file_rss);
22077 + page_cache_release(page_m);
22079 + } else if (!pte_file(entry_m)) {
22080 + free_swap_and_cache(pte_to_swp_entry(entry_m));
22082 + printk(KERN_ERR "PAX: VMMIRROR: bug in mirror_fault: %08lx, %08lx, %08lx, %08lx\n",
22083 + address, vma->vm_start, address_m, vma_m->vm_start);
22086 + pfn_m = pte_pfn(*pte);
22087 + page_m = vm_normal_page(vma, address, *pte);
22088 + entry_m = pfn_pte(pfn_m, vma_m->vm_page_prot);
22089 + if (pte_write(*pte))
22090 + entry_m = maybe_mkwrite(pte_mkdirty(entry_m), vma_m);
22092 + page_cache_get(page_m);
22094 + * we can test PAGE_MAPPING_ANON without holding page_map_lock because
22095 + * we hold the page table lock and have a reference to page_m
22097 + if (PageAnon(page_m)) {
22098 + page_add_anon_rmap(page_m, vma_m, address_m);
22099 + inc_mm_counter(mm, anon_rss);
22101 + page_add_file_rmap(page_m);
22102 + inc_mm_counter(mm, file_rss);
22105 + set_pte_at(mm, address_m, pte_m, entry_m);
22106 + update_mmu_cache(vma_m, address_m, entry_m);
22107 + lazy_mmu_prot_update(entry_m);
22108 + pte_unmap_nested(pte_m);
22113 * This routine handles present pages, when users try to write
22114 * to a shared page. It is done by copying the page to a new address
22115 @@ -1514,6 +1613,12 @@ gotten:
22116 /* Free the old page.. */
22117 new_page = old_page;
22118 ret |= VM_FAULT_WRITE;
22120 +#ifdef CONFIG_PAX_SEGMEXEC
22121 + if (vma->vm_flags & VM_MIRROR)
22122 + pax_mirror_fault(vma, address, page_table);
22127 page_cache_release(new_page);
22128 @@ -1764,6 +1869,7 @@ int vmtruncate(struct inode * inode, lof
22131 limit = current->signal->rlim[RLIMIT_FSIZE].rlim_cur;
22132 + gr_learn_resource(current, RLIMIT_FSIZE, offset, 1);
22133 if (limit != RLIM_INFINITY && offset > limit)
22135 if (offset > inode->i_sb->s_maxbytes)
22136 @@ -1953,6 +2059,12 @@ again:
22137 /* No need to invalidate - it was non-present before */
22138 update_mmu_cache(vma, address, pte);
22139 lazy_mmu_prot_update(pte);
22141 +#ifdef CONFIG_PAX_SEGMEXEC
22142 + if (vma->vm_flags & VM_MIRROR)
22143 + pax_mirror_fault(vma, address, page_table);
22147 pte_unmap_unlock(page_table, ptl);
22149 @@ -2015,6 +2127,12 @@ static int do_anonymous_page(struct mm_s
22150 /* No need to invalidate - it was non-present before */
22151 update_mmu_cache(vma, address, entry);
22152 lazy_mmu_prot_update(entry);
22154 +#ifdef CONFIG_PAX_SEGMEXEC
22155 + if (vma->vm_flags & VM_MIRROR)
22156 + pax_mirror_fault(vma, address, page_table);
22160 pte_unmap_unlock(page_table, ptl);
22161 return VM_FAULT_MINOR;
22162 @@ -2140,6 +2258,12 @@ retry:
22163 /* no need to invalidate: a not-present page shouldn't be cached */
22164 update_mmu_cache(vma, address, entry);
22165 lazy_mmu_prot_update(entry);
22167 +#ifdef CONFIG_PAX_SEGMEXEC
22168 + if (vma->vm_flags & VM_MIRROR)
22169 + pax_mirror_fault(vma, address, page_table);
22173 pte_unmap_unlock(page_table, ptl);
22175 @@ -2249,6 +2373,12 @@ static inline int handle_pte_fault(struc
22176 flush_tlb_page(vma, address);
22180 +#ifdef CONFIG_PAX_SEGMEXEC
22181 + if (vma->vm_flags & VM_MIRROR)
22182 + pax_mirror_fault(vma, address, pte);
22185 pte_unmap_unlock(pte, ptl);
22186 return VM_FAULT_MINOR;
22188 @@ -2271,6 +2401,49 @@ int __handle_mm_fault(struct mm_struct *
22189 if (unlikely(is_vm_hugetlb_page(vma)))
22190 return hugetlb_fault(mm, vma, address, write_access);
22192 +#ifdef CONFIG_PAX_SEGMEXEC
22193 + if (vma->vm_flags & VM_MIRROR) {
22194 + unsigned long address_m;
22195 + struct vm_area_struct * vma_m;
22200 + address_m = vma->vm_start + vma->vm_mirror;
22201 + vma_m = find_vma(mm, address_m);
22203 + /* PaX: sanity checks */
22205 + printk(KERN_ERR "PAX: VMMIRROR: fault bug, %08lx, %p, %08lx, %p\n",
22206 + address, vma, address_m, vma_m);
22207 + return VM_FAULT_SIGBUS;
22208 + } else if (!(vma_m->vm_flags & VM_MIRROR) ||
22209 + vma_m->vm_start != address_m ||
22210 + vma->vm_end - vma->vm_start != vma_m->vm_end - vma_m->vm_start)
22212 + printk(KERN_ERR "PAX: VMMIRROR: fault bug2, %08lx, %08lx, %08lx, %08lx, %08lx\n",
22213 + address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
22214 + return VM_FAULT_SIGBUS;
22217 + if (address_m < address) {
22218 + address += vma->vm_mirror;
22222 + address_m = address + vma->vm_mirror;
22223 + pgd_m = pgd_offset(mm, address_m);
22224 + pud_m = pud_alloc(mm, pgd_m, address_m);
22226 + return VM_FAULT_OOM;
22227 + pmd_m = pmd_alloc(mm, pud_m, address_m);
22229 + return VM_FAULT_OOM;
22230 + if (!pmd_present(*pmd_m) && __pte_alloc(mm, pmd_m, address_m))
22231 + return VM_FAULT_OOM;
22235 pgd = pgd_offset(mm, address);
22236 pud = pud_alloc(mm, pgd, address);
22238 diff -urNp linux-2.6.16.12/mm/mempolicy.c linux-2.6.16.12/mm/mempolicy.c
22239 --- linux-2.6.16.12/mm/mempolicy.c 2006-05-01 15:14:26.000000000 -0400
22240 +++ linux-2.6.16.12/mm/mempolicy.c 2006-05-01 20:17:34.000000000 -0400
22241 @@ -355,6 +355,12 @@ check_range(struct mm_struct *mm, unsign
22242 if (prev && prev->vm_end < vma->vm_start)
22243 return ERR_PTR(-EFAULT);
22246 +#ifdef CONFIG_PAX_SEGMEXEC
22247 + if (vma->vm_flags & VM_MIRROR)
22248 + return ERR_PTR(-EFAULT);
22251 if (!is_vm_hugetlb_page(vma) &&
22252 ((flags & MPOL_MF_STRICT) ||
22253 ((flags & (MPOL_MF_MOVE | MPOL_MF_MOVE_ALL)) &&
22254 diff -urNp linux-2.6.16.12/mm/mlock.c linux-2.6.16.12/mm/mlock.c
22255 --- linux-2.6.16.12/mm/mlock.c 2006-05-01 15:14:26.000000000 -0400
22256 +++ linux-2.6.16.12/mm/mlock.c 2006-05-01 20:17:34.000000000 -0400
22257 @@ -10,14 +10,85 @@
22258 #include <linux/mm.h>
22259 #include <linux/mempolicy.h>
22260 #include <linux/syscalls.h>
22261 +#include <linux/grsecurity.h>
22263 +static int __mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
22264 + unsigned long start, unsigned long end, unsigned int newflags);
22266 static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
22267 unsigned long start, unsigned long end, unsigned int newflags)
22269 struct mm_struct * mm = vma->vm_mm;
22274 +#ifdef CONFIG_PAX_SEGMEXEC
22275 + struct vm_area_struct * vma_m = NULL, *prev_m;
22276 + unsigned long start_m = 0UL, end_m = 0UL, newflags_m = 0UL;
22278 + if (vma->vm_flags & VM_MIRROR) {
22279 + start_m = vma->vm_start + vma->vm_mirror;
22280 + vma_m = find_vma_prev(mm, start_m, &prev_m);
22281 + if (!vma_m || vma_m->vm_start != start_m || !(vma_m->vm_flags & VM_MIRROR)) {
22282 + printk("PAX: VMMIRROR: mlock bug in %s, %08lx\n", current->comm, vma->vm_start);
22286 + start_m = start + vma->vm_mirror;
22287 + end_m = end + vma->vm_mirror;
22288 + if (newflags & VM_LOCKED)
22289 + newflags_m = vma_m->vm_flags | VM_LOCKED;
22291 + newflags_m = vma_m->vm_flags & ~VM_LOCKED;
22292 + ret = __mlock_fixup(vma_m, &prev_m, start_m, end_m, newflags_m);
22298 + ret = __mlock_fixup(vma, prev, start, end, newflags);
22303 + * vm_flags is protected by the mmap_sem held in write mode.
22304 + * It's okay if try_to_unmap_one unmaps a page just after we
22305 + * set VM_LOCKED, make_pages_present below will bring it back.
22307 + vma->vm_flags = newflags;
22309 +#ifdef CONFIG_PAX_SEGMEXEC
22310 + if (vma->vm_flags & VM_MIRROR)
22311 + vma_m->vm_flags = newflags_m;
22315 + * Keep track of amount of locked VM.
22317 + pages = (end - start) >> PAGE_SHIFT;
22318 + if (newflags & VM_LOCKED) {
22320 + if (!(newflags & VM_IO))
22321 + ret = make_pages_present(start, end);
22324 + mm->locked_vm -= pages;
22326 +#ifdef CONFIG_PAX_SEGMEXEC
22327 + if (vma->vm_flags & VM_MIRROR)
22328 + mm->locked_vm -= pages;
22331 + if (ret == -ENOMEM)
22336 +static int __mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev,
22337 + unsigned long start, unsigned long end, unsigned int newflags)
22339 + struct mm_struct * mm = vma->vm_mm;
22343 if (newflags == vma->vm_flags) {
22344 @@ -30,7 +101,7 @@ static int mlock_fixup(struct vm_area_st
22345 vma->vm_file, pgoff, vma_policy(vma));
22353 @@ -41,31 +112,9 @@ static int mlock_fixup(struct vm_area_st
22357 - if (end != vma->vm_end) {
22358 + if (end != vma->vm_end)
22359 ret = split_vma(mm, vma, end, 0);
22366 - * vm_flags is protected by the mmap_sem held in write mode.
22367 - * It's okay if try_to_unmap_one unmaps a page just after we
22368 - * set VM_LOCKED, make_pages_present below will bring it back.
22370 - vma->vm_flags = newflags;
22373 - * Keep track of amount of locked VM.
22375 - pages = (end - start) >> PAGE_SHIFT;
22376 - if (newflags & VM_LOCKED) {
22378 - if (!(newflags & VM_IO))
22379 - ret = make_pages_present(start, end);
22382 - vma->vm_mm->locked_vm -= pages;
22384 if (ret == -ENOMEM)
22386 @@ -84,6 +133,17 @@ static int do_mlock(unsigned long start,
22391 +#ifdef CONFIG_PAX_SEGMEXEC
22392 + if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
22393 + if (end > SEGMEXEC_TASK_SIZE)
22398 + if (end > TASK_SIZE)
22401 vma = find_vma_prev(current->mm, start, &prev);
22402 if (!vma || vma->vm_start > start)
22404 @@ -141,6 +201,7 @@ asmlinkage long sys_mlock(unsigned long
22405 lock_limit >>= PAGE_SHIFT;
22407 /* check against resource limits */
22408 + gr_learn_resource(current, RLIMIT_MEMLOCK, (current->mm->locked_vm << PAGE_SHIFT) + len, 1);
22409 if ((locked <= lock_limit) || capable(CAP_IPC_LOCK))
22410 error = do_mlock(start, len, 1);
22411 up_write(¤t->mm->mmap_sem);
22412 @@ -173,6 +234,16 @@ static int do_mlockall(int flags)
22413 for (vma = current->mm->mmap; vma ; vma = prev->vm_next) {
22414 unsigned int newflags;
22416 +#ifdef CONFIG_PAX_SEGMEXEC
22417 + if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
22418 + if (vma->vm_end > SEGMEXEC_TASK_SIZE)
22423 + if (vma->vm_end > TASK_SIZE)
22426 newflags = vma->vm_flags | VM_LOCKED;
22427 if (!(flags & MCL_CURRENT))
22428 newflags &= ~VM_LOCKED;
22429 @@ -202,6 +273,7 @@ asmlinkage long sys_mlockall(int flags)
22430 lock_limit >>= PAGE_SHIFT;
22433 + gr_learn_resource(current, RLIMIT_MEMLOCK, current->mm->total_vm, 1);
22434 if (!(flags & MCL_CURRENT) || (current->mm->total_vm <= lock_limit) ||
22435 capable(CAP_IPC_LOCK))
22436 ret = do_mlockall(flags);
22437 diff -urNp linux-2.6.16.12/mm/mmap.c linux-2.6.16.12/mm/mmap.c
22438 --- linux-2.6.16.12/mm/mmap.c 2006-05-01 15:14:26.000000000 -0400
22439 +++ linux-2.6.16.12/mm/mmap.c 2006-05-01 20:17:34.000000000 -0400
22441 #include <linux/mount.h>
22442 #include <linux/mempolicy.h>
22443 #include <linux/rmap.h>
22444 +#include <linux/grsecurity.h>
22446 #include <asm/uaccess.h>
22447 #include <asm/cacheflush.h>
22448 @@ -60,6 +61,8 @@ pgprot_t protection_map[16] = {
22449 __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111
22452 +EXPORT_SYMBOL(protection_map);
22454 int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
22455 int sysctl_overcommit_ratio = 50; /* default is 50% */
22456 int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
22457 @@ -234,6 +237,7 @@ asmlinkage unsigned long sys_brk(unsigne
22459 /* Check against rlimit.. */
22460 rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur;
22461 + gr_learn_resource(current, RLIMIT_DATA, brk - mm->start_data, 1);
22462 if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim)
22465 @@ -612,11 +616,17 @@ again: remove_next = 1 + (end > next->
22466 * If the vma has a ->close operation then the driver probably needs to release
22467 * per-vma resources, so we don't attempt to merge those.
22469 +#ifdef CONFIG_PAX_SEGMEXEC
22470 +#define VM_SPECIAL (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP | VM_MIRROR)
22472 #define VM_SPECIAL (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED | VM_PFNMAP)
22475 static inline int is_mergeable_vma(struct vm_area_struct *vma,
22476 struct file *file, unsigned long vm_flags)
22478 + if ((vma->vm_flags | vm_flags) & VM_SPECIAL)
22480 if (vma->vm_flags != vm_flags)
22482 if (vma->vm_file != file)
22483 @@ -842,9 +852,6 @@ none:
22484 void vm_stat_account(struct mm_struct *mm, unsigned long flags,
22485 struct file *file, long pages)
22487 - const unsigned long stack_flags
22488 - = VM_STACK_FLAGS & (VM_GROWSUP|VM_GROWSDOWN);
22490 #ifdef CONFIG_HUGETLB
22491 if (flags & VM_HUGETLB) {
22492 if (!(flags & VM_DONTCOPY))
22493 @@ -857,7 +864,7 @@ void vm_stat_account(struct mm_struct *m
22494 mm->shared_vm += pages;
22495 if ((flags & (VM_EXEC|VM_WRITE)) == VM_EXEC)
22496 mm->exec_vm += pages;
22497 - } else if (flags & stack_flags)
22498 + } else if (flags & (VM_GROWSUP|VM_GROWSDOWN))
22499 mm->stack_vm += pages;
22500 if (flags & (VM_RESERVED|VM_IO))
22501 mm->reserved_vm += pages;
22502 @@ -868,10 +875,55 @@ void vm_stat_account(struct mm_struct *m
22503 * The caller must hold down_write(current->mm->mmap_sem).
22506 +#ifdef CONFIG_PAX_SEGMEXEC
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);
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)
22515 + unsigned long ret = -EINVAL;
22517 + if (flags & MAP_MIRROR)
22520 + if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) &&
22521 + (len > SEGMEXEC_TASK_SIZE || (addr > SEGMEXEC_TASK_SIZE-len)))
22524 + ret = __do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
22526 + if ((current->mm->pax_flags & MF_PAX_SEGMEXEC) && ret < TASK_SIZE && ((flags & MAP_TYPE) == MAP_PRIVATE)
22528 +#ifdef CONFIG_PAX_MPROTECT
22529 + && (!(current->mm->pax_flags & MF_PAX_MPROTECT) || ((prot & PROT_EXEC) && file && !(prot & PROT_WRITE)))
22534 + unsigned long ret_m;
22535 + prot = prot & PROT_EXEC ? prot & ~PROT_WRITE : PROT_NONE;
22536 + ret_m = __do_mmap_pgoff(NULL, ret + SEGMEXEC_TASK_SIZE, 0UL, prot, flags | MAP_MIRROR | MAP_FIXED, ret);
22537 + if (ret_m >= TASK_SIZE) {
22538 + do_munmap(current->mm, ret, len);
22546 +static unsigned long __do_mmap_pgoff(struct file * file, unsigned long addr,
22547 + unsigned long len, unsigned long prot,
22548 + unsigned long flags, unsigned long pgoff)
22550 +unsigned long do_mmap_pgoff(struct file * file, unsigned long addr,
22551 + unsigned long len, unsigned long prot,
22552 + unsigned long flags, unsigned long pgoff)
22555 struct mm_struct * mm = current->mm;
22556 struct vm_area_struct * vma, * prev;
22557 struct inode *inode;
22558 @@ -882,6 +934,28 @@ unsigned long do_mmap_pgoff(struct file
22559 int accountable = 1;
22560 unsigned long charged = 0, reqprot = prot;
22562 +#ifdef CONFIG_PAX_SEGMEXEC
22563 + struct vm_area_struct * vma_m = NULL;
22565 + if (flags & MAP_MIRROR) {
22566 + /* PaX: sanity checks, to be removed when proved to be stable */
22567 + if (file || len || ((flags & MAP_TYPE) != MAP_PRIVATE))
22570 + vma_m = find_vma(mm, pgoff);
22572 + if (!vma_m || is_vm_hugetlb_page(vma_m) ||
22573 + vma_m->vm_start != pgoff ||
22574 + (vma_m->vm_flags & VM_SPECIAL) ||
22575 + (prot & PROT_WRITE))
22578 + file = vma_m->vm_file;
22579 + pgoff = vma_m->vm_pgoff;
22580 + len = vma_m->vm_end - vma_m->vm_start;
22585 if (is_file_hugepages(file))
22587 @@ -922,7 +996,7 @@ unsigned long do_mmap_pgoff(struct file
22588 /* Obtain the address to map to. we verify (or select) it and ensure
22589 * that it represents a valid section of the address space.
22591 - addr = get_unmapped_area(file, addr, len, pgoff, flags);
22592 + addr = get_unmapped_area(file, addr, len, pgoff, flags | ((prot & PROT_EXEC) ? MAP_EXECUTABLE : 0));
22593 if (addr & ~PAGE_MASK)
22596 @@ -933,6 +1007,24 @@ unsigned long do_mmap_pgoff(struct file
22597 vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) |
22598 mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
22600 + if (file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC))
22601 + vm_flags &= ~VM_MAYEXEC;
22603 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
22604 + if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
22606 +#ifdef CONFIG_PAX_MPROTECT
22607 + if (mm->pax_flags & MF_PAX_MPROTECT) {
22608 + if ((prot & (PROT_WRITE | PROT_EXEC)) != PROT_EXEC)
22609 + vm_flags &= ~(VM_EXEC | VM_MAYEXEC);
22611 + vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
22618 if (flags & MAP_LOCKED) {
22619 if (!can_do_mlock())
22621 @@ -945,6 +1037,7 @@ unsigned long do_mmap_pgoff(struct file
22622 locked += mm->locked_vm;
22623 lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
22624 lock_limit >>= PAGE_SHIFT;
22625 + gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
22626 if (locked > lock_limit && !capable(CAP_IPC_LOCK))
22629 @@ -992,6 +1085,11 @@ unsigned long do_mmap_pgoff(struct file
22631 * Set pgoff according to addr for anon_vma.
22634 +#ifdef CONFIG_PAX_SEGMEXEC
22635 + if (!(flags & MAP_MIRROR))
22638 pgoff = addr >> PAGE_SHIFT;
22641 @@ -1003,14 +1101,17 @@ unsigned long do_mmap_pgoff(struct file
22645 + if (!gr_acl_handle_mmap(file, prot))
22648 /* Clear old maps */
22651 vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
22652 if (vma && vma->vm_start < addr + len) {
22653 if (do_munmap(mm, addr, len))
22655 - goto munmap_back;
22656 + vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
22657 + BUG_ON(vma && vma->vm_start < addr + len);
22660 /* Check against address space limit. */
22661 @@ -1059,6 +1160,13 @@ munmap_back:
22662 vma->vm_start = addr;
22663 vma->vm_end = addr + len;
22664 vma->vm_flags = vm_flags;
22666 +#ifdef CONFIG_PAX_PAGEEXEC
22667 + if ((file || !(mm->pax_flags & MF_PAX_PAGEEXEC)) && (vm_flags & (VM_READ|VM_WRITE)))
22668 + vma->vm_page_prot = protection_map[(vm_flags | VM_EXEC) & 0x0f];
22672 vma->vm_page_prot = protection_map[vm_flags & 0x0f];
22673 vma->vm_pgoff = pgoff;
22675 @@ -1083,6 +1191,14 @@ munmap_back:
22679 +#ifdef CONFIG_PAX_SEGMEXEC
22680 + if (flags & MAP_MIRROR) {
22681 + vma_m->vm_flags |= VM_MIRROR;
22682 + vma_m->vm_mirror = vma->vm_start - vma_m->vm_start;
22683 + vma->vm_mirror = vma_m->vm_start - vma->vm_start;
22687 /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform
22688 * shmem_zero_setup (perhaps called through /dev/zero's ->mmap)
22689 * that memory reservation must be checked; but that reservation
22690 @@ -1118,6 +1234,7 @@ munmap_back:
22692 mm->total_vm += len >> PAGE_SHIFT;
22693 vm_stat_account(mm, vm_flags, file, len >> PAGE_SHIFT);
22694 + track_exec_limit(mm, addr, addr + len, vm_flags);
22695 if (vm_flags & VM_LOCKED) {
22696 mm->locked_vm += len >> PAGE_SHIFT;
22697 make_pages_present(addr, addr + len);
22698 @@ -1172,6 +1289,10 @@ arch_get_unmapped_area(struct file *filp
22699 if (len > TASK_SIZE)
22702 +#ifdef CONFIG_PAX_RANDMMAP
22703 + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
22707 addr = PAGE_ALIGN(addr);
22708 vma = find_vma(mm, addr);
22709 @@ -1182,7 +1303,7 @@ arch_get_unmapped_area(struct file *filp
22710 if (len > mm->cached_hole_size) {
22711 start_addr = addr = mm->free_area_cache;
22713 - start_addr = addr = TASK_UNMAPPED_BASE;
22714 + start_addr = addr = mm->mmap_base;
22715 mm->cached_hole_size = 0;
22718 @@ -1194,9 +1315,8 @@ full_search:
22719 * Start a new search - just in case we missed
22722 - if (start_addr != TASK_UNMAPPED_BASE) {
22723 - addr = TASK_UNMAPPED_BASE;
22724 - start_addr = addr;
22725 + if (start_addr != mm->mmap_base) {
22726 + start_addr = addr = mm->mmap_base;
22727 mm->cached_hole_size = 0;
22730 @@ -1221,7 +1341,7 @@ void arch_unmap_area(struct mm_struct *m
22732 * Is this a new hole at the lowest possible address?
22734 - if (addr >= TASK_UNMAPPED_BASE && addr < mm->free_area_cache) {
22735 + if (addr >= mm->mmap_base && addr < mm->free_area_cache) {
22736 mm->free_area_cache = addr;
22737 mm->cached_hole_size = ~0UL;
22739 @@ -1239,12 +1359,16 @@ arch_get_unmapped_area_topdown(struct fi
22741 struct vm_area_struct *vma;
22742 struct mm_struct *mm = current->mm;
22743 - unsigned long addr = addr0;
22744 + unsigned long base = mm->mmap_base, addr = addr0;
22746 /* requested length too big for entire address space */
22747 if (len > TASK_SIZE)
22750 +#ifdef CONFIG_PAX_RANDMMAP
22751 + if (!(mm->pax_flags & MF_PAX_RANDMMAP) || !filp)
22754 /* requesting a specific address */
22756 addr = PAGE_ALIGN(addr);
22757 @@ -1302,13 +1426,21 @@ bottomup:
22758 * can happen with large stack limits and large mmap()
22761 + mm->mmap_base = TASK_UNMAPPED_BASE;
22763 +#ifdef CONFIG_PAX_RANDMMAP
22764 + if (mm->pax_flags & MF_PAX_RANDMMAP)
22765 + mm->mmap_base += mm->delta_mmap;
22768 + mm->free_area_cache = mm->mmap_base;
22769 mm->cached_hole_size = ~0UL;
22770 - mm->free_area_cache = TASK_UNMAPPED_BASE;
22771 addr = arch_get_unmapped_area(filp, addr0, len, pgoff, flags);
22773 * Restore the topdown base:
22775 - mm->free_area_cache = mm->mmap_base;
22776 + mm->mmap_base = base;
22777 + mm->free_area_cache = base;
22778 mm->cached_hole_size = ~0UL;
22781 @@ -1324,8 +1456,10 @@ void arch_unmap_area_topdown(struct mm_s
22782 mm->free_area_cache = addr;
22784 /* dont allow allocations above current base */
22785 - if (mm->free_area_cache > mm->mmap_base)
22786 + if (mm->free_area_cache > mm->mmap_base) {
22787 mm->free_area_cache = mm->mmap_base;
22788 + mm->cached_hole_size = ~0UL;
22793 @@ -1458,6 +1592,7 @@ static int acct_stack_growth(struct vm_a
22796 /* Stack limit test */
22797 + gr_learn_resource(current, RLIMIT_STACK, size, 1);
22798 if (size > rlim[RLIMIT_STACK].rlim_cur)
22801 @@ -1467,6 +1602,7 @@ static int acct_stack_growth(struct vm_a
22802 unsigned long limit;
22803 locked = mm->locked_vm + grow;
22804 limit = rlim[RLIMIT_MEMLOCK].rlim_cur >> PAGE_SHIFT;
22805 + gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
22806 if (locked > limit && !capable(CAP_IPC_LOCK))
22809 @@ -1584,13 +1720,49 @@ int expand_stack(struct vm_area_struct *
22810 if (address < vma->vm_start) {
22811 unsigned long size, grow;
22813 +#ifdef CONFIG_PAX_SEGMEXEC
22814 + struct vm_area_struct *vma_m = NULL;
22815 + unsigned long address_m = 0UL;
22817 + if (vma->vm_flags & VM_MIRROR) {
22818 + address_m = vma->vm_start + vma->vm_mirror;
22819 + vma_m = find_vma(vma->vm_mm, address_m);
22820 + if (!vma_m || vma_m->vm_start != address_m ||
22821 + !(vma_m->vm_flags & VM_MIRROR) ||
22822 + vma->vm_end - vma->vm_start !=
22823 + vma_m->vm_end - vma_m->vm_start ||
22824 + vma->anon_vma != vma_m->anon_vma) {
22825 + printk(KERN_ERR "PAX: VMMIRROR: expand bug, %08lx, %08lx, %08lx, %08lx, %08lx\n",
22826 + address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end);
22827 + anon_vma_unlock(vma);
22830 + address_m = address + vma->vm_mirror;
22834 size = vma->vm_end - address;
22835 grow = (vma->vm_start - address) >> PAGE_SHIFT;
22837 +#ifdef CONFIG_PAX_SEGMEXEC
22839 + error = acct_stack_growth(vma, size, 2*grow);
22843 error = acct_stack_growth(vma, size, grow);
22845 vma->vm_start = address;
22846 vma->vm_pgoff -= grow;
22847 + track_exec_limit(vma->vm_mm, vma->vm_start, vma->vm_end, vma->vm_flags);
22849 +#ifdef CONFIG_PAX_SEGMEXEC
22851 + vma_m->vm_start = address_m;
22852 + vma_m->vm_pgoff -= grow;
22858 anon_vma_unlock(vma);
22859 @@ -1752,7 +1924,24 @@ int split_vma(struct mm_struct * mm, str
22860 * work. This now handles partial unmappings.
22861 * Jeremy Fitzhardinge <jeremy@goop.org>
22863 +#ifdef CONFIG_PAX_SEGMEXEC
22864 +static int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len);
22866 +int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
22868 + if (mm->pax_flags & MF_PAX_SEGMEXEC) {
22869 + int ret = __do_munmap(mm, start + SEGMEXEC_TASK_SIZE, len);
22874 + return __do_munmap(mm, start, len);
22877 +static int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
22879 int do_munmap(struct mm_struct *mm, unsigned long start, size_t len)
22883 struct vm_area_struct *vma, *prev, *last;
22884 @@ -1806,6 +1995,8 @@ int do_munmap(struct mm_struct *mm, unsi
22885 /* Fix up all other VM information */
22886 remove_vma_list(mm, vma);
22888 + track_exec_limit(mm, start, end, 0UL);
22893 @@ -1818,6 +2009,12 @@ asmlinkage long sys_munmap(unsigned long
22895 profile_munmap(addr);
22897 +#ifdef CONFIG_PAX_SEGMEXEC
22898 + if ((mm->pax_flags & MF_PAX_SEGMEXEC) &&
22899 + (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len))
22903 down_write(&mm->mmap_sem);
22904 ret = do_munmap(mm, addr, len);
22905 up_write(&mm->mmap_sem);
22906 @@ -1839,11 +2036,35 @@ static inline void verify_mm_writelocked
22907 * anonymous maps. eventually we may be able to do some
22908 * brk-specific accounting here.
22910 +#ifdef CONFIG_PAX_SEGMEXEC
22911 +static unsigned long __do_brk(unsigned long addr, unsigned long len);
22913 unsigned long do_brk(unsigned long addr, unsigned long len)
22915 + unsigned long ret;
22917 + ret = __do_brk(addr, len);
22918 + if (ret == addr && (current->mm->pax_flags & (MF_PAX_SEGMEXEC | MF_PAX_MPROTECT)) == MF_PAX_SEGMEXEC) {
22919 + unsigned long ret_m;
22921 + ret_m = __do_mmap_pgoff(NULL, addr + SEGMEXEC_TASK_SIZE, 0UL, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_MIRROR, addr);
22922 + if (ret_m > TASK_SIZE) {
22923 + do_munmap(current->mm, addr, len);
22931 +static unsigned long __do_brk(unsigned long addr, unsigned long len)
22933 +unsigned long do_brk(unsigned long addr, unsigned long len)
22936 struct mm_struct * mm = current->mm;
22937 struct vm_area_struct * vma, * prev;
22938 - unsigned long flags;
22939 + unsigned long flags, task_size = TASK_SIZE;
22940 struct rb_node ** rb_link, * rb_parent;
22941 pgoff_t pgoff = addr >> PAGE_SHIFT;
22943 @@ -1851,7 +2072,12 @@ unsigned long do_brk(unsigned long addr,
22947 - if ((addr + len) > TASK_SIZE || (addr + len) < addr)
22948 +#ifdef CONFIG_PAX_SEGMEXEC
22949 + if (mm->pax_flags & MF_PAX_SEGMEXEC)
22950 + task_size = SEGMEXEC_TASK_SIZE;
22953 + if ((addr + len) > task_size || (addr + len) < addr)
22957 @@ -1863,6 +2089,7 @@ unsigned long do_brk(unsigned long addr,
22958 locked += mm->locked_vm;
22959 lock_limit = current->signal->rlim[RLIMIT_MEMLOCK].rlim_cur;
22960 lock_limit >>= PAGE_SHIFT;
22961 + gr_learn_resource(current, RLIMIT_MEMLOCK, locked << PAGE_SHIFT, 1);
22962 if (locked > lock_limit && !capable(CAP_IPC_LOCK))
22965 @@ -1876,12 +2103,12 @@ unsigned long do_brk(unsigned long addr,
22967 * Clear old maps. this also does some error checking for us
22970 vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
22971 if (vma && vma->vm_start < addr + len) {
22972 if (do_munmap(mm, addr, len))
22974 - goto munmap_back;
22975 + vma = find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent);
22976 + BUG_ON(vma && vma->vm_start < addr + len);
22979 /* Check against address space limits *after* clearing old maps... */
22980 @@ -1896,6 +2123,18 @@ unsigned long do_brk(unsigned long addr,
22982 flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags;
22984 +#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC)
22985 + if (mm->pax_flags & (MF_PAX_PAGEEXEC | MF_PAX_SEGMEXEC)) {
22986 + flags &= ~VM_EXEC;
22988 +#ifdef CONFIG_PAX_MPROTECT
22989 + if (mm->pax_flags & MF_PAX_MPROTECT)
22990 + flags &= ~VM_MAYEXEC;
22996 /* Can we just expand an old private anonymous mapping? */
22997 if (vma_merge(mm, prev, addr, addr + len, flags,
22998 NULL, NULL, pgoff, NULL))
22999 @@ -1916,6 +2155,13 @@ unsigned long do_brk(unsigned long addr,
23000 vma->vm_end = addr + len;
23001 vma->vm_pgoff = pgoff;
23002 vma->vm_flags = flags;
23004 +#ifdef CONFIG_PAX_PAGEEXEC
23005 + if (!(mm->pax_flags & MF_PAX_PAGEEXEC) && (flags & (VM_READ|VM_WRITE)))
23006 + vma->vm_page_prot = protection_map[(flags | VM_EXEC) & 0x0f];
23010 vma->vm_page_prot = protection_map[flags & 0x0f];
23011 vma_link(mm, vma, prev, rb_link, rb_parent);
23013 @@ -1924,6 +2170,7 @@ out:
23014 mm->locked_vm += len >> PAGE_SHIFT;
23015 make_pages_present(addr, addr + len);
23017 + track_exec_limit(mm, addr, addr + len, flags);
23021 @@ -2056,7 +2303,7 @@ int may_expand_vm(struct mm_struct *mm,
23024 lim = current->signal->rlim[RLIMIT_AS].rlim_cur >> PAGE_SHIFT;
23026 + gr_learn_resource(current, RLIMIT_AS, (cur + npages) << PAGE_SHIFT, 1);
23027 if (cur + npages > lim)
23030 diff -urNp linux-2.6.16.12/mm/mprotect.c linux-2.6.16.12/mm/mprotect.c
23031 --- linux-2.6.16.12/mm/mprotect.c 2006-05-01 15:14:26.000000000 -0400
23032 +++ linux-2.6.16.12/mm/mprotect.c 2006-05-01 20:17:34.000000000 -0400
23033 @@ -19,11 +19,18 @@
23034 #include <linux/mempolicy.h>
23035 #include <linux/personality.h>
23036 #include <linux/syscalls.h>
23037 +#include <linux/grsecurity.h>
23039 +#ifdef CONFIG_PAX_MPROTECT
23040 +#include <linux/elf.h>
23041 +#include <linux/fs.h>
23044 #include <asm/uaccess.h>
23045 #include <asm/pgtable.h>
23046 #include <asm/cacheflush.h>
23047 #include <asm/tlbflush.h>
23048 +#include <asm/mmu_context.h>
23050 static void change_pte_range(struct mm_struct *mm, pmd_t *pmd,
23051 unsigned long addr, unsigned long end, pgprot_t newprot)
23052 @@ -98,6 +105,94 @@ static void change_protection(struct vm_
23053 flush_tlb_range(vma, start, end);
23056 +#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
23057 +/* called while holding the mmap semaphor for writing */
23058 +static inline void establish_user_cs_limit(struct mm_struct *mm, unsigned long start, unsigned long end)
23060 + struct vm_area_struct *vma = find_vma(mm, start);
23062 + for (; vma && vma->vm_start < end; vma = vma->vm_next)
23063 + change_protection(vma, vma->vm_start, vma->vm_end, vma->vm_page_prot);
23067 +void track_exec_limit(struct mm_struct *mm, unsigned long start, unsigned long end, unsigned long prot)
23069 + unsigned long oldlimit, newlimit = 0UL;
23071 + if (!(mm->pax_flags & MF_PAX_PAGEEXEC))
23074 + spin_lock(&mm->page_table_lock);
23075 + oldlimit = mm->context.user_cs_limit;
23076 + if ((prot & VM_EXEC) && oldlimit < end)
23077 + /* USER_CS limit moved up */
23079 + else if (!(prot & VM_EXEC) && start < oldlimit && oldlimit <= end)
23080 + /* USER_CS limit moved down */
23081 + newlimit = start;
23084 + mm->context.user_cs_limit = newlimit;
23088 + cpus_clear(mm->context.cpu_user_cs_mask);
23089 + cpu_set(smp_processor_id(), mm->context.cpu_user_cs_mask);
23092 + set_user_cs(mm, smp_processor_id());
23094 + spin_unlock(&mm->page_table_lock);
23095 + if (newlimit == end)
23096 + establish_user_cs_limit(mm, oldlimit, end);
23100 +#ifdef CONFIG_PAX_SEGMEXEC
23101 +static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
23102 + unsigned long start, unsigned long end, unsigned int newflags);
23104 +static int mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
23105 + unsigned long start, unsigned long end, unsigned int newflags)
23107 + if (vma->vm_flags & VM_MIRROR) {
23108 + struct vm_area_struct * vma_m, * prev_m;
23109 + unsigned long start_m, end_m;
23112 + start_m = vma->vm_start + vma->vm_mirror;
23113 + vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m);
23114 + if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) {
23115 + start_m = start + vma->vm_mirror;
23116 + end_m = end + vma->vm_mirror;
23118 + if (vma_m->vm_start >= SEGMEXEC_TASK_SIZE && !(newflags & VM_EXEC))
23119 + error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, vma_m->vm_flags & ~(VM_READ | VM_WRITE | VM_EXEC));
23121 + error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, newflags);
23125 + printk("PAX: VMMIRROR: mprotect bug in %s, %08lx\n", current->comm, vma->vm_start);
23130 + return __mprotect_fixup(vma, pprev, start, end, newflags);
23133 +static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
23134 + unsigned long start, unsigned long end, unsigned int newflags)
23136 + struct mm_struct * mm = vma->vm_mm;
23137 + unsigned long oldflags = vma->vm_flags;
23138 + long nrpages = (end - start) >> PAGE_SHIFT;
23139 + unsigned long charged = 0;
23140 + pgprot_t newprot;
23145 mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev,
23146 unsigned long start, unsigned long end, unsigned long newflags)
23147 @@ -114,6 +209,7 @@ mprotect_fixup(struct vm_area_struct *vm
23154 * If we make a private mapping writable we increase our commit;
23155 @@ -132,6 +228,12 @@ mprotect_fixup(struct vm_area_struct *vm
23159 +#ifdef CONFIG_PAX_PAGEEXEC
23160 + if (!(mm->pax_flags & MF_PAX_PAGEEXEC) && (newflags & (VM_READ|VM_WRITE)))
23161 + newprot = protection_map[(newflags | VM_EXEC) & 0xf];
23165 newprot = protection_map[newflags & 0xf];
23168 @@ -176,6 +278,69 @@ fail:
23172 +#ifdef CONFIG_PAX_MPROTECT
23173 +/* PaX: non-PIC ELF libraries need relocations on their executable segments
23174 + * therefore we'll grant them VM_MAYWRITE once during their life.
23176 + * The checks favour ld-linux.so behaviour which operates on a per ELF segment
23177 + * basis because we want to allow the common case and not the special ones.
23179 +static inline void pax_handle_maywrite(struct vm_area_struct * vma, unsigned long start)
23181 + struct elfhdr elf_h;
23182 + struct elf_phdr elf_p, p_dyn;
23184 + unsigned long i, j = 65536UL / sizeof(struct elf_phdr);
23186 +#ifndef CONFIG_PAX_NOELFRELOCS
23187 + if ((vma->vm_start != start) ||
23189 + !(vma->vm_flags & VM_MAYEXEC) ||
23190 + (vma->vm_flags & VM_MAYNOTWRITE))
23195 + if (sizeof(elf_h) != kernel_read(vma->vm_file, 0UL, (char*)&elf_h, sizeof(elf_h)) ||
23196 + memcmp(elf_h.e_ident, ELFMAG, SELFMAG) ||
23198 +#ifdef CONFIG_PAX_ETEXECRELOCS
23199 + (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC) ||
23201 + elf_h.e_type != ET_DYN ||
23204 + !elf_check_arch(&elf_h) ||
23205 + elf_h.e_phentsize != sizeof(struct elf_phdr) ||
23206 + elf_h.e_phnum > j)
23209 + for (i = 0UL; i < elf_h.e_phnum; i++) {
23210 + if (sizeof(elf_p) != kernel_read(vma->vm_file, elf_h.e_phoff + i*sizeof(elf_p), (char*)&elf_p, sizeof(elf_p)))
23212 + if (elf_p.p_type == PT_DYNAMIC) {
23217 + if (elf_h.e_phnum <= j)
23222 + if (sizeof(dyn) != kernel_read(vma->vm_file, p_dyn.p_offset + i*sizeof(dyn), (char*)&dyn, sizeof(dyn)))
23224 + if (dyn.d_tag == DT_TEXTREL || (dyn.d_tag == DT_FLAGS && (dyn.d_un.d_val & DF_TEXTREL))) {
23225 + vma->vm_flags |= VM_MAYWRITE | VM_MAYNOTWRITE;
23226 + gr_log_textrel(vma);
23230 + } while (dyn.d_tag != DT_NULL);
23236 sys_mprotect(unsigned long start, size_t len, unsigned long prot)
23238 @@ -195,6 +360,17 @@ sys_mprotect(unsigned long start, size_t
23243 +#ifdef CONFIG_PAX_SEGMEXEC
23244 + if (current->mm->pax_flags & MF_PAX_SEGMEXEC) {
23245 + if (end > SEGMEXEC_TASK_SIZE)
23250 + if (end > TASK_SIZE)
23253 if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM))
23256 @@ -235,6 +411,16 @@ sys_mprotect(unsigned long start, size_t
23257 if (start > vma->vm_start)
23260 +#ifdef CONFIG_PAX_MPROTECT
23261 + if ((vma->vm_mm->pax_flags & MF_PAX_MPROTECT) && (prot & PROT_WRITE))
23262 + pax_handle_maywrite(vma, start);
23265 + if (!gr_acl_handle_mprotect(vma->vm_file, prot)) {
23270 for (nstart = start ; ; ) {
23271 unsigned long newflags;
23273 @@ -253,6 +439,12 @@ sys_mprotect(unsigned long start, size_t
23277 +#ifdef CONFIG_PAX_MPROTECT
23278 + /* PaX: disallow write access after relocs are done, hopefully noone else needs it... */
23279 + if ((vma->vm_mm->pax_flags & MF_PAX_MPROTECT) && !(prot & PROT_WRITE) && (vma->vm_flags & VM_MAYNOTWRITE))
23280 + newflags &= ~VM_MAYWRITE;
23283 error = security_file_mprotect(vma, reqprot, prot);
23286 @@ -276,6 +468,9 @@ sys_mprotect(unsigned long start, size_t
23291 + track_exec_limit(current->mm, start, end, vm_flags);
23294 up_write(¤t->mm->mmap_sem);
23296 diff -urNp linux-2.6.16.12/mm/mremap.c linux-2.6.16.12/mm/mremap.c
23297 --- linux-2.6.16.12/mm/mremap.c 2006-05-01 15:14:26.000000000 -0400
23298 +++ linux-2.6.16.12/mm/mremap.c 2006-05-01 20:17:34.000000000 -0400
23299 @@ -106,6 +106,12 @@ static void move_ptes(struct vm_area_str
23300 pte = ptep_clear_flush(vma, old_addr, old_pte);
23301 /* ZERO_PAGE can be dependant on virtual addr */
23302 pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr);
23304 +#ifdef CONFIG_ARCH_TRACK_EXEC_LIMIT
23305 + if ((mm->pax_flags & MF_PAX_PAGEEXEC) && !(vma->vm_flags & VM_EXEC))
23306 + pte_exprotect(pte);
23309 set_pte_at(mm, new_addr, new_pte, pte);
23312 @@ -253,6 +259,7 @@ unsigned long do_mremap(unsigned long ad
23313 struct vm_area_struct *vma;
23314 unsigned long ret = -EINVAL;
23315 unsigned long charged = 0;
23316 + unsigned long task_size = TASK_SIZE;
23318 if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
23320 @@ -271,6 +278,15 @@ unsigned long do_mremap(unsigned long ad
23324 +#ifdef CONFIG_PAX_SEGMEXEC
23325 + if (current->mm->pax_flags & MF_PAX_SEGMEXEC)
23326 + task_size = SEGMEXEC_TASK_SIZE;
23329 + if (new_len > task_size || addr > task_size-new_len ||
23330 + old_len > task_size || addr > task_size-old_len)
23333 /* new_addr is only valid if MREMAP_FIXED is specified */
23334 if (flags & MREMAP_FIXED) {
23335 if (new_addr & ~PAGE_MASK)
23336 @@ -278,16 +294,13 @@ unsigned long do_mremap(unsigned long ad
23337 if (!(flags & MREMAP_MAYMOVE))
23340 - if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
23341 + if (new_addr > task_size - new_len)
23344 /* Check if the location we're moving into overlaps the
23345 * old location at all, and fail if it does.
23347 - if ((new_addr <= addr) && (new_addr+new_len) > addr)
23350 - if ((addr <= new_addr) && (addr+old_len) > new_addr)
23351 + if (addr + old_len > new_addr && new_addr + new_len > addr)
23354 ret = do_munmap(mm, new_addr, new_len);
23355 @@ -321,6 +334,14 @@ unsigned long do_mremap(unsigned long ad
23360 +#ifdef CONFIG_PAX_SEGMEXEC
23361 + if (vma->vm_flags & VM_MIRROR) {
23367 /* We can't remap across vm area boundaries */
23368 if (old_len > vma->vm_end - addr)
23370 @@ -354,7 +375,7 @@ unsigned long do_mremap(unsigned long ad
23371 if (old_len == vma->vm_end - addr &&
23372 !((flags & MREMAP_FIXED) && (addr != new_addr)) &&
23373 (old_len != new_len || !(flags & MREMAP_MAYMOVE))) {
23374 - unsigned long max_addr = TASK_SIZE;
23375 + unsigned long max_addr = task_size;
23377 max_addr = vma->vm_next->vm_start;
23378 /* can we just expand the current mapping? */
23379 @@ -372,6 +393,7 @@ unsigned long do_mremap(unsigned long ad
23383 + track_exec_limit(vma->vm_mm, vma->vm_start, addr + new_len, vma->vm_flags);
23387 @@ -382,8 +404,8 @@ unsigned long do_mremap(unsigned long ad
23390 if (flags & MREMAP_MAYMOVE) {
23391 + unsigned long map_flags = 0;
23392 if (!(flags & MREMAP_FIXED)) {
23393 - unsigned long map_flags = 0;
23394 if (vma->vm_flags & VM_MAYSHARE)
23395 map_flags |= MAP_SHARED;
23397 @@ -393,7 +415,12 @@ unsigned long do_mremap(unsigned long ad
23398 if (new_addr & ~PAGE_MASK)
23401 + map_flags = vma->vm_flags;
23402 ret = move_vma(vma, addr, old_len, new_len, new_addr);
23403 + if (!(ret & ~PAGE_MASK)) {
23404 + track_exec_limit(current->mm, addr, addr + old_len, 0UL);
23405 + track_exec_limit(current->mm, new_addr, new_addr + new_len, map_flags);
23409 if (ret & ~PAGE_MASK)
23410 diff -urNp linux-2.6.16.12/mm/rmap.c linux-2.6.16.12/mm/rmap.c
23411 --- linux-2.6.16.12/mm/rmap.c 2006-05-01 15:14:26.000000000 -0400
23412 +++ linux-2.6.16.12/mm/rmap.c 2006-05-01 20:17:34.000000000 -0400
23413 @@ -108,6 +108,19 @@ int anon_vma_prepare(struct vm_area_stru
23414 list_add(&vma->anon_vma_node, &anon_vma->head);
23418 +#ifdef CONFIG_PAX_SEGMEXEC
23419 + if (vma->vm_flags & VM_MIRROR) {
23420 + struct vm_area_struct *vma_m;
23422 + vma_m = find_vma(vma->vm_mm, vma->vm_start + vma->vm_mirror);
23423 + BUG_ON(!vma_m || vma_m->vm_start != vma->vm_start + vma->vm_mirror);
23424 + BUG_ON(vma_m->anon_vma || vma->vm_pgoff != vma_m->vm_pgoff);
23425 + vma_m->anon_vma = anon_vma;
23426 + __anon_vma_link(vma_m);
23430 spin_unlock(&mm->page_table_lock);
23433 diff -urNp linux-2.6.16.12/mm/vmalloc.c linux-2.6.16.12/mm/vmalloc.c
23434 --- linux-2.6.16.12/mm/vmalloc.c 2006-05-01 15:14:26.000000000 -0400
23435 +++ linux-2.6.16.12/mm/vmalloc.c 2006-05-01 20:17:34.000000000 -0400
23436 @@ -193,6 +193,8 @@ struct vm_struct *__get_vm_area_node(uns
23438 write_lock(&vmlist_lock);
23439 for (p = &vmlist; (tmp = *p) != NULL ;p = &tmp->next) {
23440 + if (addr > end - size)
23442 if ((unsigned long)tmp->addr < addr) {
23443 if((unsigned long)tmp->addr + tmp->size >= addr)
23444 addr = ALIGN(tmp->size +
23445 @@ -204,8 +206,6 @@ struct vm_struct *__get_vm_area_node(uns
23446 if (size + addr <= (unsigned long)tmp->addr)
23448 addr = ALIGN(tmp->size + (unsigned long)tmp->addr, align);
23449 - if (addr > end - size)
23454 diff -urNp linux-2.6.16.12/net/ipv4/inet_connection_sock.c linux-2.6.16.12/net/ipv4/inet_connection_sock.c
23455 --- linux-2.6.16.12/net/ipv4/inet_connection_sock.c 2006-05-01 15:14:26.000000000 -0400
23456 +++ linux-2.6.16.12/net/ipv4/inet_connection_sock.c 2006-05-01 20:17:34.000000000 -0400
23458 #include <linux/config.h>
23459 #include <linux/module.h>
23460 #include <linux/jhash.h>
23461 +#include <linux/grsecurity.h>
23463 #include <net/inet_connection_sock.h>
23464 #include <net/inet_hashtables.h>
23465 diff -urNp linux-2.6.16.12/net/ipv4/inet_hashtables.c linux-2.6.16.12/net/ipv4/inet_hashtables.c
23466 --- linux-2.6.16.12/net/ipv4/inet_hashtables.c 2006-05-01 15:14:26.000000000 -0400
23467 +++ linux-2.6.16.12/net/ipv4/inet_hashtables.c 2006-05-01 20:17:34.000000000 -0400
23468 @@ -19,11 +19,14 @@
23469 #include <linux/sched.h>
23470 #include <linux/slab.h>
23471 #include <linux/wait.h>
23472 +#include <linux/grsecurity.h>
23474 #include <net/inet_connection_sock.h>
23475 #include <net/inet_hashtables.h>
23476 #include <net/ip.h>
23478 +extern void gr_update_task_in_ip_table(struct task_struct *task, const struct inet_sock *inet);
23481 * Allocate and initialize a new local port bind bucket.
23482 * The bindhash mutex for snum's hash chain must be held here.
23483 @@ -314,6 +317,8 @@ ok:
23485 spin_unlock(&head->lock);
23487 + gr_update_task_in_ip_table(current, inet_sk(sk));
23490 inet_twsk_deschedule(tw, death_row);;
23492 diff -urNp linux-2.6.16.12/net/ipv4/netfilter/ipt_stealth.c linux-2.6.16.12/net/ipv4/netfilter/ipt_stealth.c
23493 --- linux-2.6.16.12/net/ipv4/netfilter/ipt_stealth.c 1969-12-31 19:00:00.000000000 -0500
23494 +++ linux-2.6.16.12/net/ipv4/netfilter/ipt_stealth.c 2006-05-01 20:17:34.000000000 -0400
23496 +/* Kernel module to add stealth support.
23498 + * Copyright (C) 2002,2005 Brad Spengler <spender@grsecurity.net>
23502 +#include <linux/kernel.h>
23503 +#include <linux/module.h>
23504 +#include <linux/skbuff.h>
23505 +#include <linux/net.h>
23506 +#include <linux/sched.h>
23507 +#include <linux/inet.h>
23508 +#include <linux/stddef.h>
23510 +#include <net/ip.h>
23511 +#include <net/sock.h>
23512 +#include <net/tcp.h>
23513 +#include <net/udp.h>
23514 +#include <net/route.h>
23515 +#include <net/inet_common.h>
23517 +#include <linux/netfilter_ipv4/ip_tables.h>
23519 +MODULE_LICENSE("GPL");
23521 +extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif);
23524 +match(const struct sk_buff *skb,
23525 + const struct net_device *in,
23526 + const struct net_device *out,
23527 + const void *matchinfo,
23531 + struct iphdr *ip = skb->nh.iph;
23532 + struct tcphdr th;
23533 + struct udphdr uh;
23534 + struct sock *sk = NULL;
23536 + if (!ip || offset) return 0;
23538 + switch(ip->protocol) {
23539 + case IPPROTO_TCP:
23540 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &th, sizeof(th)) < 0) {
23544 + if (!(th.syn && !th.ack)) return 0;
23545 + sk = inet_lookup_listener(&tcp_hashinfo, ip->daddr, ntohs(th.dest), ((struct rtable*)skb->dst)->rt_iif);
23547 + case IPPROTO_UDP:
23548 + if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &uh, sizeof(uh)) < 0) {
23552 + sk = udp_v4_lookup(ip->saddr, uh.source, ip->daddr, uh.dest, skb->dev->ifindex);
23558 + if(!sk) // port is being listened on, match this
23566 +/* Called when user tries to insert an entry of this type. */
23568 +checkentry(const char *tablename,
23569 + const struct ipt_ip *ip,
23571 + unsigned int matchsize,
23572 + unsigned int hook_mask)
23574 + if (matchsize != IPT_ALIGN(0))
23577 + if(((ip->proto == IPPROTO_TCP && !(ip->invflags & IPT_INV_PROTO)) ||
23578 + ((ip->proto == IPPROTO_UDP) && !(ip->invflags & IPT_INV_PROTO)))
23579 + && (hook_mask & (1 << NF_IP_LOCAL_IN)))
23582 + printk("stealth: Only works on TCP and UDP for the INPUT chain.\n");
23588 +static struct ipt_match stealth_match = {
23589 + .name = "stealth",
23591 + .checkentry = &checkentry,
23593 + .me = THIS_MODULE
23596 +static int __init init(void)
23598 + return ipt_register_match(&stealth_match);
23601 +static void __exit fini(void)
23603 + ipt_unregister_match(&stealth_match);
23606 +module_init(init);
23607 +module_exit(fini);
23608 diff -urNp linux-2.6.16.12/net/ipv4/netfilter/Kconfig linux-2.6.16.12/net/ipv4/netfilter/Kconfig
23609 --- linux-2.6.16.12/net/ipv4/netfilter/Kconfig 2006-05-01 15:14:26.000000000 -0400
23610 +++ linux-2.6.16.12/net/ipv4/netfilter/Kconfig 2006-05-01 20:17:34.000000000 -0400
23611 @@ -313,6 +313,21 @@ config IP_NF_MATCH_POLICY
23613 To compile it as a module, choose M here. If unsure, say N.
23615 +config IP_NF_MATCH_STEALTH
23616 + tristate "stealth match support"
23617 + depends on IP_NF_IPTABLES
23619 + Enabling this option will drop all syn packets coming to unserved tcp
23620 + ports as well as all packets coming to unserved udp ports. If you
23621 + are using your system to route any type of packets (ie. via NAT)
23622 + you should put this module at the end of your ruleset, since it will
23623 + drop packets that aren't going to ports that are listening on your
23624 + machine itself, it doesn't take into account that the packet might be
23625 + destined for someone on your internal network if you're using NAT for
23628 + To compile it as a module, choose M here. If unsure, say N.
23630 # `filter', generic and specific targets
23631 config IP_NF_FILTER
23632 tristate "Packet filtering"
23633 @@ -607,4 +622,3 @@ config IP_NF_ARP_MANGLE
23634 hardware and network addresses.
23638 diff -urNp linux-2.6.16.12/net/ipv4/netfilter/Makefile linux-2.6.16.12/net/ipv4/netfilter/Makefile
23639 --- linux-2.6.16.12/net/ipv4/netfilter/Makefile 2006-05-01 15:14:26.000000000 -0400
23640 +++ linux-2.6.16.12/net/ipv4/netfilter/Makefile 2006-05-01 20:17:34.000000000 -0400
23641 @@ -58,6 +58,7 @@ obj-$(CONFIG_IP_NF_MATCH_AH_ESP) += ipt_
23642 obj-$(CONFIG_IP_NF_MATCH_TTL) += ipt_ttl.o
23643 obj-$(CONFIG_IP_NF_MATCH_ADDRTYPE) += ipt_addrtype.o
23644 obj-$(CONFIG_IP_NF_MATCH_POLICY) += ipt_policy.o
23645 +obj-$(CONFIG_IP_NF_MATCH_STEALTH) += ipt_stealth.o
23648 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
23649 diff -urNp linux-2.6.16.12/net/ipv4/tcp_ipv4.c linux-2.6.16.12/net/ipv4/tcp_ipv4.c
23650 --- linux-2.6.16.12/net/ipv4/tcp_ipv4.c 2006-05-01 15:14:26.000000000 -0400
23651 +++ linux-2.6.16.12/net/ipv4/tcp_ipv4.c 2006-05-01 20:17:34.000000000 -0400
23653 #include <linux/jhash.h>
23654 #include <linux/init.h>
23655 #include <linux/times.h>
23656 +#include <linux/grsecurity.h>
23658 #include <net/icmp.h>
23659 #include <net/inet_hashtables.h>
23660 diff -urNp linux-2.6.16.12/net/ipv4/udp.c linux-2.6.16.12/net/ipv4/udp.c
23661 --- linux-2.6.16.12/net/ipv4/udp.c 2006-05-01 15:14:26.000000000 -0400
23662 +++ linux-2.6.16.12/net/ipv4/udp.c 2006-05-01 20:17:34.000000000 -0400
23663 @@ -102,6 +102,7 @@
23664 #include <linux/skbuff.h>
23665 #include <linux/proc_fs.h>
23666 #include <linux/seq_file.h>
23667 +#include <linux/grsecurity.h>
23668 #include <net/sock.h>
23669 #include <net/udp.h>
23670 #include <net/icmp.h>
23671 @@ -110,6 +111,12 @@
23672 #include <net/checksum.h>
23673 #include <net/xfrm.h>
23675 +extern int gr_search_udp_recvmsg(const struct sock *sk,
23676 + const struct sk_buff *skb);
23677 +extern int gr_search_udp_sendmsg(const struct sock *sk,
23678 + const struct sockaddr_in *addr);
23682 * Snmp MIB for the UDP layer
23684 @@ -266,8 +273,7 @@ static struct sock *udp_v4_lookup_longwa
23688 -static __inline__ struct sock *udp_v4_lookup(u32 saddr, u16 sport,
23689 - u32 daddr, u16 dport, int dif)
23690 +struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif)
23694 @@ -542,9 +548,16 @@ int udp_sendmsg(struct kiocb *iocb, stru
23695 dport = usin->sin_port;
23699 + if (!gr_search_udp_sendmsg(sk, usin))
23702 if (sk->sk_state != TCP_ESTABLISHED)
23703 return -EDESTADDRREQ;
23705 + if (!gr_search_udp_sendmsg(sk, NULL))
23708 daddr = inet->daddr;
23709 dport = inet->dport;
23710 /* Open fast path for connected socket.
23711 @@ -798,6 +811,11 @@ try_again:
23715 + if (!gr_search_udp_recvmsg(sk, skb)) {
23720 copied = skb->len - sizeof(struct udphdr);
23721 if (copied > len) {
23723 diff -urNp linux-2.6.16.12/net/socket.c linux-2.6.16.12/net/socket.c
23724 --- linux-2.6.16.12/net/socket.c 2006-05-01 15:14:26.000000000 -0400
23725 +++ linux-2.6.16.12/net/socket.c 2006-05-01 20:17:34.000000000 -0400
23727 #include <linux/compat.h>
23728 #include <linux/kmod.h>
23729 #include <linux/audit.h>
23730 +#include <linux/in.h>
23732 #ifdef CONFIG_NET_RADIO
23733 #include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
23735 #include <net/sock.h>
23736 #include <linux/netfilter.h>
23738 +extern void gr_attach_curr_ip(const struct sock *sk);
23739 +extern int gr_handle_sock_all(const int family, const int type,
23740 + const int protocol);
23741 +extern int gr_handle_sock_server(const struct sockaddr *sck);
23742 +extern int gr_handle_sock_server_other(const struct socket *sck);
23743 +extern int gr_handle_sock_client(const struct sockaddr *sck);
23744 +extern int gr_search_connect(const struct socket * sock,
23745 + const struct sockaddr_in * addr);
23746 +extern int gr_search_bind(const struct socket * sock,
23747 + const struct sockaddr_in * addr);
23748 +extern int gr_search_listen(const struct socket * sock);
23749 +extern int gr_search_accept(const struct socket * sock);
23750 +extern int gr_search_socket(const int domain, const int type,
23751 + const int protocol);
23753 static int sock_no_open(struct inode *irrelevant, struct file *dontcare);
23754 static ssize_t sock_aio_read(struct kiocb *iocb, char __user *buf,
23755 size_t size, loff_t pos);
23756 @@ -1194,6 +1210,16 @@ asmlinkage long sys_socket(int family, i
23758 struct socket *sock;
23760 + if(!gr_search_socket(family, type, protocol)) {
23761 + retval = -EACCES;
23765 + if (gr_handle_sock_all(family, type, protocol)) {
23766 + retval = -EACCES;
23770 retval = sock_create(family, type, protocol, &sock);
23773 @@ -1289,11 +1315,23 @@ asmlinkage long sys_bind(int fd, struct
23775 struct socket *sock;
23776 char address[MAX_SOCK_ADDR];
23777 + struct sockaddr *sck;
23780 if((sock = sockfd_lookup(fd,&err))!=NULL)
23782 if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) {
23783 + sck = (struct sockaddr *)address;
23784 + if (!gr_search_bind(sock, (struct sockaddr_in *)sck)) {
23785 + sockfd_put(sock);
23789 + if (gr_handle_sock_server(sck)) {
23790 + sockfd_put(sock);
23794 err = security_socket_bind(sock, (struct sockaddr *)address, addrlen);
23797 @@ -1330,6 +1368,16 @@ asmlinkage long sys_listen(int fd, int b
23801 + if (gr_handle_sock_server_other(sock)) {
23802 + sockfd_put(sock);
23806 + if(!gr_search_listen(sock)) {
23807 + sockfd_put(sock);
23811 err=sock->ops->listen(sock, backlog);
23814 @@ -1366,6 +1414,16 @@ asmlinkage long sys_accept(int fd, struc
23815 newsock->type = sock->type;
23816 newsock->ops = sock->ops;
23818 + if (gr_handle_sock_server_other(sock)) {
23820 + goto out_release;
23823 + if(!gr_search_accept(sock)) {
23825 + goto out_release;
23829 * We don't need try_module_get here, as the listening socket (sock)
23830 * has the protocol module (sock->ops->owner) held.
23831 @@ -1396,6 +1454,7 @@ asmlinkage long sys_accept(int fd, struc
23834 security_socket_post_accept(sock, newsock);
23835 + gr_attach_curr_ip(newsock->sk);
23839 @@ -1423,6 +1482,7 @@ asmlinkage long sys_connect(int fd, stru
23841 struct socket *sock;
23842 char address[MAX_SOCK_ADDR];
23843 + struct sockaddr *sck;
23846 sock = sockfd_lookup(fd, &err);
23847 @@ -1432,6 +1492,18 @@ asmlinkage long sys_connect(int fd, stru
23851 + sck = (struct sockaddr *)address;
23853 + if (!gr_search_connect(sock, (struct sockaddr_in *)sck)) {
23858 + if (gr_handle_sock_client(sck)) {
23863 err = security_socket_connect(sock, (struct sockaddr *)address, addrlen);
23866 @@ -1685,6 +1757,7 @@ asmlinkage long sys_shutdown(int fd, int
23867 err=sock->ops->shutdown(sock, how);
23874 diff -urNp linux-2.6.16.12/net/unix/af_unix.c linux-2.6.16.12/net/unix/af_unix.c
23875 --- linux-2.6.16.12/net/unix/af_unix.c 2006-05-01 15:14:26.000000000 -0400
23876 +++ linux-2.6.16.12/net/unix/af_unix.c 2006-05-01 20:17:34.000000000 -0400
23877 @@ -117,6 +117,7 @@
23878 #include <linux/mount.h>
23879 #include <net/checksum.h>
23880 #include <linux/security.h>
23881 +#include <linux/grsecurity.h>
23883 int sysctl_unix_max_dgram_qlen = 10;
23885 @@ -680,6 +681,11 @@ static struct sock *unix_find_other(stru
23889 + if (!gr_acl_handle_unix(nd.dentry, nd.mnt)) {
23894 err = -ECONNREFUSED;
23895 if (!S_ISSOCK(nd.dentry->d_inode->i_mode))
23897 @@ -703,6 +709,13 @@ static struct sock *unix_find_other(stru
23899 struct dentry *dentry;
23900 dentry = unix_sk(u)->dentry;
23902 + if (!gr_handle_chroot_unix(u->sk_peercred.pid)) {
23909 touch_atime(unix_sk(u)->mnt, dentry);
23911 @@ -781,9 +794,18 @@ static int unix_bind(struct socket *sock
23914 (SOCK_INODE(sock)->i_mode & ~current->fs->umask);
23916 + if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) {
23918 + goto out_mknod_dput;
23921 err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0);
23923 goto out_mknod_dput;
23925 + gr_handle_create(dentry, nd.mnt);
23927 mutex_unlock(&nd.dentry->d_inode->i_mutex);
23929 nd.dentry = dentry;
23930 @@ -801,6 +823,10 @@ static int unix_bind(struct socket *sock
23934 +#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX
23935 + sk->sk_peercred.pid = current->pid;
23938 list = &unix_socket_table[addr->hash];
23940 list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)];
23941 diff -urNp linux-2.6.16.12/security/commoncap.c linux-2.6.16.12/security/commoncap.c
23942 --- linux-2.6.16.12/security/commoncap.c 2006-05-01 15:14:26.000000000 -0400
23943 +++ linux-2.6.16.12/security/commoncap.c 2006-05-01 20:17:34.000000000 -0400
23945 #include <linux/ptrace.h>
23946 #include <linux/xattr.h>
23947 #include <linux/hugetlb.h>
23948 +#include <linux/grsecurity.h>
23950 int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
23952 @@ -45,7 +46,15 @@ EXPORT_SYMBOL(cap_netlink_recv);
23953 int cap_capable (struct task_struct *tsk, int cap)
23955 /* Derived from include/linux/sched.h:capable. */
23956 - if (cap_raised(tsk->cap_effective, cap))
23957 + if (cap_raised (tsk->cap_effective, cap) && gr_task_is_capable(tsk, cap))
23962 +int cap_capable_nolog (struct task_struct *tsk, int cap)
23964 + /* Derived from include/linux/sched.h:capable. */
23965 + if (cap_raised (tsk->cap_effective, cap))
23969 @@ -61,7 +70,7 @@ int cap_ptrace (struct task_struct *pare
23971 /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
23972 if (!cap_issubset (child->cap_permitted, current->cap_permitted) &&
23973 - !capable(CAP_SYS_PTRACE))
23974 + !capable_nolog(CAP_SYS_PTRACE))
23978 @@ -164,8 +173,11 @@ void cap_bprm_apply_creds (struct linux_
23982 - current->suid = current->euid = current->fsuid = bprm->e_uid;
23983 - current->sgid = current->egid = current->fsgid = bprm->e_gid;
23984 + if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid))
23985 + current->suid = current->euid = current->fsuid = bprm->e_uid;
23987 + if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid))
23988 + current->sgid = current->egid = current->fsgid = bprm->e_gid;
23990 /* For init, we want to retain the capabilities set
23991 * in the init_task struct. Thus we skip the usual
23992 @@ -176,6 +188,8 @@ void cap_bprm_apply_creds (struct linux_
23993 cap_intersect (new_permitted, bprm->cap_effective);
23996 + gr_handle_chroot_caps(current);
23998 /* AUD: Audit candidate if current->cap_effective is set */
24000 current->keep_capabilities = 0;
24001 @@ -321,12 +335,13 @@ int cap_vm_enough_memory(long pages)
24003 int cap_sys_admin = 0;
24005 - if (cap_capable(current, CAP_SYS_ADMIN) == 0)
24006 + if (cap_capable_nolog(current, CAP_SYS_ADMIN) == 0)
24008 return __vm_enough_memory(pages, cap_sys_admin);
24011 EXPORT_SYMBOL(cap_capable);
24012 +EXPORT_SYMBOL(cap_capable_nolog);
24013 EXPORT_SYMBOL(cap_settime);
24014 EXPORT_SYMBOL(cap_ptrace);
24015 EXPORT_SYMBOL(cap_capget);
24016 diff -urNp linux-2.6.16.12/security/dummy.c linux-2.6.16.12/security/dummy.c
24017 --- linux-2.6.16.12/security/dummy.c 2006-05-01 15:14:26.000000000 -0400
24018 +++ linux-2.6.16.12/security/dummy.c 2006-05-01 20:17:34.000000000 -0400
24020 #include <linux/hugetlb.h>
24021 #include <linux/ptrace.h>
24022 #include <linux/file.h>
24023 +#include <linux/grsecurity.h>
24025 static int dummy_ptrace (struct task_struct *parent, struct task_struct *child)
24027 @@ -139,8 +140,11 @@ static void dummy_bprm_apply_creds (stru
24031 - current->suid = current->euid = current->fsuid = bprm->e_uid;
24032 - current->sgid = current->egid = current->fsgid = bprm->e_gid;
24033 + if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid))
24034 + current->suid = current->euid = current->fsuid = bprm->e_uid;
24036 + if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid))
24037 + current->sgid = current->egid = current->fsgid = bprm->e_gid;
24039 dummy_capget(current, ¤t->cap_effective, ¤t->cap_inheritable, ¤t->cap_permitted);
24041 diff -urNp linux-2.6.16.12/security/Kconfig linux-2.6.16.12/security/Kconfig
24042 --- linux-2.6.16.12/security/Kconfig 2006-05-01 15:14:26.000000000 -0400
24043 +++ linux-2.6.16.12/security/Kconfig 2006-05-01 20:17:34.000000000 -0400
24046 menu "Security options"
24051 + bool "Enable various PaX features"
24052 + depends on GRKERNSEC && (ALPHA || ARM || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || PPC64 || SPARC32 || SPARC64 || X86 || X86_64)
24054 + This allows you to enable various PaX features. PaX adds
24055 + intrusion prevention mechanisms to the kernel that reduce
24056 + the risks posed by exploitable memory corruption bugs.
24058 +menu "PaX Control"
24061 +config PAX_SOFTMODE
24062 + bool 'Support soft mode'
24064 + Enabling this option will allow you to run PaX in soft mode, that
24065 + is, PaX features will not be enforced by default, only on executables
24066 + marked explicitly. You must also enable PT_PAX_FLAGS support as it
24067 + is the only way to mark executables for soft mode use.
24069 + Soft mode can be activated by using the "pax_softmode=1" kernel command
24070 + line option on boot. Furthermore you can control various PaX features
24071 + at runtime via the entries in /proc/sys/kernel/pax.
24074 + bool 'Use legacy ELF header marking'
24076 + Enabling this option will allow you to control PaX features on
24077 + a per executable basis via the 'chpax' utility available at
24078 + http://pax.grsecurity.net/. The control flags will be read from
24079 + an otherwise reserved part of the ELF header. This marking has
24080 + numerous drawbacks (no support for soft-mode, toolchain does not
24081 + know about the non-standard use of the ELF header) therefore it
24082 + has been deprecated in favour of PT_PAX_FLAGS support.
24084 + If you have applications not marked by the PT_PAX_FLAGS ELF
24085 + program header then you MUST enable this option otherwise they
24086 + will not get any protection.
24088 + Note that if you enable PT_PAX_FLAGS marking support as well,
24089 + the PT_PAX_FLAG marks will override the legacy EI_PAX marks.
24091 +config PAX_PT_PAX_FLAGS
24092 + bool 'Use ELF program header marking'
24094 + Enabling this option will allow you to control PaX features on
24095 + a per executable basis via the 'paxctl' utility available at
24096 + http://pax.grsecurity.net/. The control flags will be read from
24097 + a PaX specific ELF program header (PT_PAX_FLAGS). This marking
24098 + has the benefits of supporting both soft mode and being fully
24099 + integrated into the toolchain (the binutils patch is available
24100 + from http://pax.grsecurity.net).
24102 + If you have applications not marked by the PT_PAX_FLAGS ELF
24103 + program header then you MUST enable the EI_PAX marking support
24104 + otherwise they will not get any protection.
24106 + Note that if you enable the legacy EI_PAX marking support as well,
24107 + the EI_PAX marks will be overridden by the PT_PAX_FLAGS marks.
24110 + prompt 'MAC system integration'
24111 + default PAX_HAVE_ACL_FLAGS
24113 + Mandatory Access Control systems have the option of controlling
24114 + PaX flags on a per executable basis, choose the method supported
24115 + by your particular system.
24117 + - "none": if your MAC system does not interact with PaX,
24118 + - "direct": if your MAC system defines pax_set_flags() itself,
24119 + - "hook": if your MAC system uses the pax_set_flags_func callback.
24121 + NOTE: this option is for developers/integrators only.
24123 +config PAX_NO_ACL_FLAGS
24126 +config PAX_HAVE_ACL_FLAGS
24129 +config PAX_HOOK_ACL_FLAGS
24135 +menu "Non-executable pages"
24139 + bool "Enforce non-executable pages"
24140 + 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)
24142 + By design some architectures do not allow for protecting memory
24143 + pages against execution or even if they do, Linux does not make
24144 + use of this feature. In practice this means that if a page is
24145 + readable (such as the stack or heap) it is also executable.
24147 + There is a well known exploit technique that makes use of this
24148 + fact and a common programming mistake where an attacker can
24149 + introduce code of his choice somewhere in the attacked program's
24150 + memory (typically the stack or the heap) and then execute it.
24152 + If the attacked program was running with different (typically
24153 + higher) privileges than that of the attacker, then he can elevate
24154 + his own privilege level (e.g. get a root shell, write to files for
24155 + which he does not have write access to, etc).
24157 + Enabling this option will let you choose from various features
24158 + that prevent the injection and execution of 'foreign' code in
24161 + This will also break programs that rely on the old behaviour and
24162 + expect that dynamically allocated memory via the malloc() family
24163 + of functions is executable (which it is not). Notable examples
24164 + are the XFree86 4.x server, the java runtime and wine.
24166 +config PAX_PAGEEXEC
24167 + bool "Paging based non-executable pages"
24168 + depends on PAX_NOEXEC && (!X86_32 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUMM || MPENTIUM4 || MK7 || MK8 || MWINCHIPC6 || MWINCHIP2 || MWINCHIP3D || MVIAC3_2)
24169 + select PAX_NOVSYSCALL if X86_32
24171 + This implementation is based on the paging feature of the CPU.
24172 + On i386 and ppc there is a variable but usually low performance
24173 + impact on applications. On alpha, ia64, parisc, sparc, sparc64
24174 + and x86_64 there is no performance impact.
24176 +config PAX_SEGMEXEC
24177 + bool "Segmentation based non-executable pages"
24178 + depends on PAX_NOEXEC && X86_32
24179 + select PAX_NOVSYSCALL if X86_32
24181 + This implementation is based on the segmentation feature of the
24182 + CPU and has little performance impact, however applications will
24183 + be limited to a 1.5 GB address space instead of the normal 3 GB.
24186 + prompt "Default non-executable page method"
24187 + depends on PAX_PAGEEXEC && PAX_SEGMEXEC
24188 + default PAX_DEFAULT_SEGMEXEC
24190 + Select the default non-executable page method applied to applications
24191 + that do not select one themselves.
24193 +config PAX_DEFAULT_PAGEEXEC
24196 +config PAX_DEFAULT_SEGMEXEC
24200 +config PAX_EMUTRAMP
24201 + bool "Emulate trampolines" if (PAX_PAGEEXEC || PAX_SEGMEXEC) && (PARISC || PPC32 || X86_32)
24202 + default y if PARISC || PPC32
24204 + There are some programs and libraries that for one reason or
24205 + another attempt to execute special small code snippets from
24206 + non-executable memory pages. Most notable examples are the
24207 + signal handler return code generated by the kernel itself and
24208 + the GCC trampolines.
24210 + If you enabled CONFIG_PAX_PAGEEXEC or CONFIG_PAX_SEGMEXEC then
24211 + such programs will no longer work under your kernel.
24213 + As a remedy you can say Y here and use the 'chpax' or 'paxctl'
24214 + utilities to enable trampoline emulation for the affected programs
24215 + yet still have the protection provided by the non-executable pages.
24217 + On parisc and ppc you MUST enable this option and EMUSIGRT as
24218 + well, otherwise your system will not even boot.
24220 + Alternatively you can say N here and use the 'chpax' or 'paxctl'
24221 + utilities to disable CONFIG_PAX_PAGEEXEC and CONFIG_PAX_SEGMEXEC
24222 + for the affected files.
24224 + NOTE: enabling this feature *may* open up a loophole in the
24225 + protection provided by non-executable pages that an attacker
24226 + could abuse. Therefore the best solution is to not have any
24227 + files on your system that would require this option. This can
24228 + be achieved by not using libc5 (which relies on the kernel
24229 + signal handler return code) and not using or rewriting programs
24230 + that make use of the nested function implementation of GCC.
24231 + Skilled users can just fix GCC itself so that it implements
24232 + nested function calls in a way that does not interfere with PaX.
24234 +config PAX_EMUSIGRT
24235 + bool "Automatically emulate sigreturn trampolines"
24236 + depends on PAX_EMUTRAMP && (PARISC || PPC32)
24239 + Enabling this option will have the kernel automatically detect
24240 + and emulate signal return trampolines executing on the stack
24241 + that would otherwise lead to task termination.
24243 + This solution is intended as a temporary one for users with
24244 + legacy versions of libc (libc5, glibc 2.0, uClibc before 0.9.17,
24245 + Modula-3 runtime, etc) or executables linked to such, basically
24246 + everything that does not specify its own SA_RESTORER function in
24247 + normal executable memory like glibc 2.1+ does.
24249 + On parisc and ppc you MUST enable this option, otherwise your
24250 + system will not even boot.
24252 + NOTE: this feature cannot be disabled on a per executable basis
24253 + and since it *does* open up a loophole in the protection provided
24254 + by non-executable pages, the best solution is to not have any
24255 + files on your system that would require this option.
24257 +config PAX_MPROTECT
24258 + bool "Restrict mprotect()"
24259 + depends on (PAX_PAGEEXEC || PAX_SEGMEXEC) && !PPC64
24261 + Enabling this option will prevent programs from
24262 + - changing the executable status of memory pages that were
24263 + not originally created as executable,
24264 + - making read-only executable pages writable again,
24265 + - creating executable pages from anonymous memory.
24267 + You should say Y here to complete the protection provided by
24268 + the enforcement of non-executable pages.
24270 + NOTE: you can use the 'chpax' or 'paxctl' utilities to control
24271 + this feature on a per file basis.
24273 +config PAX_NOELFRELOCS
24274 + bool "Disallow ELF text relocations"
24275 + depends on PAX_MPROTECT && !PAX_ETEXECRELOCS && (IA64 || X86 || X86_64)
24277 + Non-executable pages and mprotect() restrictions are effective
24278 + in preventing the introduction of new executable code into an
24279 + attacked task's address space. There remain only two venues
24280 + for this kind of attack: if the attacker can execute already
24281 + existing code in the attacked task then he can either have it
24282 + create and mmap() a file containing his code or have it mmap()
24283 + an already existing ELF library that does not have position
24284 + independent code in it and use mprotect() on it to make it
24285 + writable and copy his code there. While protecting against
24286 + the former approach is beyond PaX, the latter can be prevented
24287 + by having only PIC ELF libraries on one's system (which do not
24288 + need to relocate their code). If you are sure this is your case,
24289 + then enable this option otherwise be careful as you may not even
24290 + be able to boot or log on your system (for example, some PAM
24291 + modules are erroneously compiled as non-PIC by default).
24293 + NOTE: if you are using dynamic ELF executables (as suggested
24294 + when using ASLR) then you must have made sure that you linked
24295 + your files using the PIC version of crt1 (the et_dyn.tar.gz package
24296 + referenced there has already been updated to support this).
24298 +config PAX_ETEXECRELOCS
24299 + bool "Allow ELF ET_EXEC text relocations"
24300 + depends on PAX_MPROTECT && (ALPHA || IA64 || PARISC)
24303 + On some architectures there are incorrectly created applications
24304 + that require text relocations and would not work without enabling
24305 + this option. If you are an alpha, ia64 or parisc user, you should
24306 + enable this option and disable it once you have made sure that
24307 + none of your applications need it.
24310 + bool "Automatically emulate ELF PLT"
24311 + depends on PAX_MPROTECT && (ALPHA || PARISC || PPC32 || SPARC32 || SPARC64)
24314 + Enabling this option will have the kernel automatically detect
24315 + and emulate the Procedure Linkage Table entries in ELF files.
24316 + On some architectures such entries are in writable memory, and
24317 + become non-executable leading to task termination. Therefore
24318 + it is mandatory that you enable this option on alpha, parisc, ppc,
24319 + sparc and sparc64, otherwise your system would not even boot.
24321 + NOTE: this feature *does* open up a loophole in the protection
24322 + provided by the non-executable pages, therefore the proper
24323 + solution is to modify the toolchain to produce a PLT that does
24324 + not need to be writable.
24326 +config PAX_DLRESOLVE
24328 + depends on PAX_EMUPLT && (SPARC32 || SPARC64)
24331 +config PAX_SYSCALL
24333 + depends on PAX_PAGEEXEC && PPC32
24336 +config PAX_KERNEXEC
24337 + bool "Enforce non-executable kernel pages"
24338 + depends on PAX_NOEXEC && X86_32 && !HOTPLUG_PCI_COMPAQ_NVRAM && !PCI_BIOS && !EFI && !DEBUG_RODATA
24340 + This is the kernel land equivalent of PAGEEXEC and MPROTECT,
24341 + that is, enabling this option will make it harder to inject
24342 + and execute 'foreign' code in kernel memory itself.
24346 +menu "Address Space Layout Randomization"
24350 + bool "Address Space Layout Randomization"
24351 + depends on PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS
24353 + Many if not most exploit techniques rely on the knowledge of
24354 + certain addresses in the attacked program. The following options
24355 + will allow the kernel to apply a certain amount of randomization
24356 + to specific parts of the program thereby forcing an attacker to
24357 + guess them in most cases. Any failed guess will most likely crash
24358 + the attacked program which allows the kernel to detect such attempts
24359 + and react on them. PaX itself provides no reaction mechanisms,
24360 + instead it is strongly encouraged that you make use of Nergal's
24361 + segvguard (ftp://ftp.pl.openwall.com/misc/segvguard/) or grsecurity's
24362 + (http://www.grsecurity.net/) built-in crash detection features or
24363 + develop one yourself.
24365 + By saying Y here you can choose to randomize the following areas:
24366 + - top of the task's kernel stack
24367 + - top of the task's userland stack
24368 + - base address for mmap() requests that do not specify one
24369 + (this includes all libraries)
24370 + - base address of the main executable
24372 + It is strongly recommended to say Y here as address space layout
24373 + randomization has negligible impact on performance yet it provides
24374 + a very effective protection.
24376 + NOTE: you can use the 'chpax' or 'paxctl' utilities to control
24377 + this feature on a per file basis.
24379 +config PAX_RANDKSTACK
24380 + bool "Randomize kernel stack base"
24381 + depends on PAX_ASLR && X86_TSC && X86_32
24383 + By saying Y here the kernel will randomize every task's kernel
24384 + stack on every system call. This will not only force an attacker
24385 + to guess it but also prevent him from making use of possible
24386 + leaked information about it.
24388 + Since the kernel stack is a rather scarce resource, randomization
24389 + may cause unexpected stack overflows, therefore you should very
24390 + carefully test your system. Note that once enabled in the kernel
24391 + configuration, this feature cannot be disabled on a per file basis.
24393 +config PAX_RANDUSTACK
24394 + bool "Randomize user stack base"
24395 + depends on PAX_ASLR
24397 + By saying Y here the kernel will randomize every task's userland
24398 + stack. The randomization is done in two steps where the second
24399 + one may apply a big amount of shift to the top of the stack and
24400 + cause problems for programs that want to use lots of memory (more
24401 + than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is).
24402 + For this reason the second step can be controlled by 'chpax' or
24403 + 'paxctl' on a per file basis.
24405 +config PAX_RANDMMAP
24406 + bool "Randomize mmap() base"
24407 + depends on PAX_ASLR
24409 + By saying Y here the kernel will use a randomized base address for
24410 + mmap() requests that do not specify one themselves. As a result
24411 + all dynamically loaded libraries will appear at random addresses
24412 + and therefore be harder to exploit by a technique where an attacker
24413 + attempts to execute library code for his purposes (e.g. spawn a
24414 + shell from an exploited program that is running at an elevated
24415 + privilege level).
24417 + Furthermore, if a program is relinked as a dynamic ELF file, its
24418 + base address will be randomized as well, completing the full
24419 + randomization of the address space layout. Attacking such programs
24420 + becomes a guess game. You can find an example of doing this at
24421 + http://pax.grsecurity.net/et_dyn.tar.gz and practical samples at
24422 + http://www.grsecurity.net/grsec-gcc-specs.tar.gz .
24424 + NOTE: you can use the 'chpax' or 'paxctl' utilities to control this
24425 + feature on a per file basis.
24427 +config PAX_NOVSYSCALL
24428 + bool "Disable the vsyscall page"
24429 + depends on PAX_ASLR && X86_32
24431 + The Linux 2.6 kernel introduced a new feature that speeds up or
24432 + simplifies certain operations, such as system calls or returns
24433 + from signal handlers.
24435 + Unfortunately the implementation also gives a powerful instrument
24436 + into the hands of exploit writers: the so-called vsyscall page exists
24437 + in every task at the same fixed address and it contains machine code
24438 + that is very useful in performing the return-to-libc style attack.
24440 + Since this exploit technique cannot in general be protected against
24441 + via kernel solutions, this option will allow you to disable the use
24442 + of the vsyscall page and revert back to the old behaviour.
24448 +source grsecurity/Kconfig
24451 bool "Enable access key retention support"
24453 diff -urNp linux-2.6.16.12/security/security.c linux-2.6.16.12/security/security.c
24454 --- linux-2.6.16.12/security/security.c 2006-05-01 15:14:26.000000000 -0400
24455 +++ linux-2.6.16.12/security/security.c 2006-05-01 20:17:34.000000000 -0400
24456 @@ -201,4 +201,5 @@ EXPORT_SYMBOL_GPL(unregister_security);
24457 EXPORT_SYMBOL_GPL(mod_reg_security);
24458 EXPORT_SYMBOL_GPL(mod_unreg_security);
24459 EXPORT_SYMBOL(capable);
24460 +EXPORT_SYMBOL(capable_nolog);
24461 EXPORT_SYMBOL(security_ops);