diff options
author | Brandon Hale <tseng@gentoo.org> | 2004-06-16 03:43:01 +0000 |
---|---|---|
committer | Brandon Hale <tseng@gentoo.org> | 2004-06-16 03:43:01 +0000 |
commit | d6dfef208d31b656f17b6efcc4afd45a12bf0fab (patch) | |
tree | 9ef005d0d17ea11f94caab3a7853d676c3689248 /src/kernel | |
parent | Add security fixes (diff) | |
download | gentoo-d6dfef208d31b656f17b6efcc4afd45a12bf0fab.tar.gz gentoo-d6dfef208d31b656f17b6efcc4afd45a12bf0fab.tar.bz2 gentoo-d6dfef208d31b656f17b6efcc4afd45a12bf0fab.zip |
remove
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/hardened-patches/hardened-patches-2.6-5.5/1000_grsecurity-2.0-2.6.5.patch | 21403 |
1 files changed, 0 insertions, 21403 deletions
diff --git a/src/kernel/hardened-patches/hardened-patches-2.6-5.5/1000_grsecurity-2.0-2.6.5.patch b/src/kernel/hardened-patches/hardened-patches-2.6-5.5/1000_grsecurity-2.0-2.6.5.patch deleted file mode 100644 index a569b46926..0000000000 --- a/src/kernel/hardened-patches/hardened-patches-2.6-5.5/1000_grsecurity-2.0-2.6.5.patch +++ /dev/null @@ -1,21403 +0,0 @@ -diff -urN linux-2.6.5/Makefile linux-2.6.5/Makefile ---- linux-2.6.5/Makefile 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/Makefile 2004-04-18 11:05:50.000000000 -0400 -@@ -1,7 +1,7 @@ - VERSION = 2 - PATCHLEVEL = 6 - SUBLEVEL = 5 --EXTRAVERSION = -+EXTRAVERSION = -grsec - NAME=Zonked Quokka - - # *DOCUMENTATION* -@@ -424,7 +424,7 @@ - CFLAGS := $(CPPFLAGS) $(CFLAGS) - AFLAGS := $(CPPFLAGS) $(AFLAGS) - --core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ -+core-y += kernel/ mm/ fs/ ipc/ security/ crypto/ grsecurity/ - - SUBDIRS += $(patsubst %/,%,$(filter %/, $(init-y) $(init-m) \ - $(core-y) $(core-m) $(drivers-y) $(drivers-m) \ -diff -urN linux-2.6.5/arch/alpha/kernel/osf_sys.c linux-2.6.5/arch/alpha/kernel/osf_sys.c ---- linux-2.6.5/arch/alpha/kernel/osf_sys.c 2004-04-03 22:36:11.000000000 -0500 -+++ linux-2.6.5/arch/alpha/kernel/osf_sys.c 2004-04-18 11:05:50.000000000 -0400 -@@ -37,6 +37,7 @@ - #include <linux/namei.h> - #include <linux/uio.h> - #include <linux/vfs.h> -+#include <linux/grsecurity.h> - - #include <asm/fpu.h> - #include <asm/io.h> -@@ -179,6 +180,11 @@ - struct file *file = NULL; - unsigned long ret = -EBADF; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - #if 0 - if (flags & (_MAP_HASSEMAPHORE | _MAP_INHERIT | _MAP_UNALIGNED)) - printk("%s: unimplemented OSF mmap flags %04lx\n", -@@ -189,6 +195,13 @@ - if (!file) - goto out; - } -+ -+ if (gr_handle_mmap(file, prot)) { -+ fput(file); -+ ret = -EACCES; -+ goto out; -+ } -+ - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); - ret = do_mmap(file, addr, len, prot, flags, off); -@@ -1295,6 +1308,10 @@ - merely specific addresses, but regions of memory -- perhaps - this feature should be incorporated into all ports? */ - -+#ifdef CONFIG_PAX_RANDMMAP -+ if (!(current->flags & PF_PAX_RANDMMAP) || !filp) -+#endif -+ - if (addr) { - addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit); - if (addr != (unsigned long) -ENOMEM) -@@ -1302,8 +1319,16 @@ - } - - /* Next, try allocating at TASK_UNMAPPED_BASE. */ -- addr = arch_get_unmapped_area_1 (PAGE_ALIGN(TASK_UNMAPPED_BASE), -- len, limit); -+ -+ addr = TASK_UNMAPPED_BASE; -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if (current->flags & PF_PAX_RANDMMAP) -+ addr += current->mm->delta_mmap; -+#endif -+ -+ addr = arch_get_unmapped_area_1 (PAGE_ALIGN(addr), len, limit); -+ - if (addr != (unsigned long) -ENOMEM) - return addr; - -diff -urN linux-2.6.5/arch/alpha/kernel/ptrace.c linux-2.6.5/arch/alpha/kernel/ptrace.c ---- linux-2.6.5/arch/alpha/kernel/ptrace.c 2004-04-03 22:38:13.000000000 -0500 -+++ linux-2.6.5/arch/alpha/kernel/ptrace.c 2004-04-18 11:05:50.000000000 -0400 -@@ -14,6 +14,7 @@ - #include <linux/user.h> - #include <linux/slab.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/pgtable.h> -@@ -288,6 +289,9 @@ - if (!child) - goto out_notsk; - -+ if (gr_handle_ptrace(child, request)) -+ goto out; -+ - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out; -diff -urN linux-2.6.5/arch/alpha/mm/fault.c linux-2.6.5/arch/alpha/mm/fault.c ---- linux-2.6.5/arch/alpha/mm/fault.c 2004-04-03 22:36:54.000000000 -0500 -+++ linux-2.6.5/arch/alpha/mm/fault.c 2004-04-18 11:05:50.000000000 -0400 -@@ -25,6 +25,7 @@ - #include <linux/smp_lock.h> - #include <linux/interrupt.h> - #include <linux/module.h> -+#include <linux/binfmts.h> - - #include <asm/system.h> - #include <asm/uaccess.h> -@@ -56,6 +57,142 @@ - __reload_thread(pcb); - } - -+#ifdef CONFIG_PAX_PAGEEXEC -+/* -+ * PaX: decide what to do with offenders (regs->pc = fault address) -+ * -+ * returns 1 when task should be killed -+ * 2 when patched PLT trampoline was detected -+ * 3 when unpatched PLT trampoline was detected -+ * 4 when legitimate ET_EXEC was detected -+ */ -+static int pax_handle_fetch_fault(struct pt_regs *regs) -+{ -+ -+#ifdef CONFIG_PAX_EMUPLT -+ int err; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ if (current->flags & PF_PAX_RANDEXEC) { -+ if (regs->pc >= current->mm->start_code && -+ regs->pc < current->mm->end_code) -+ { -+ if (regs->r26 == regs->pc) -+ return 1; -+ -+ regs->pc += current->mm->delta_exec; -+ return 4; -+ } -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUPLT -+ do { /* PaX: patched PLT emulation #1 */ -+ unsigned int ldah, ldq, jmp; -+ -+ err = get_user(ldah, (unsigned int *)regs->pc); -+ err |= get_user(ldq, (unsigned int *)(regs->pc+4)); -+ err |= get_user(jmp, (unsigned int *)(regs->pc+8)); -+ -+ if (err) -+ break; -+ -+ if ((ldah & 0xFFFF0000U) == 0x277B0000U && -+ (ldq & 0xFFFF0000U) == 0xA77B0000U && -+ jmp == 0x6BFB0000U) -+ { -+ unsigned long r27, addr; -+ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16; -+ unsigned long addrl = ldq | 0xFFFFFFFFFFFF0000UL; -+ -+ addr = regs->r27 + ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL); -+ err = get_user(r27, (unsigned long*)addr); -+ if (err) -+ break; -+ -+ regs->r27 = r27; -+ regs->pc = r27; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: patched PLT emulation #2 */ -+ unsigned int ldah, lda, br; -+ -+ err = get_user(ldah, (unsigned int *)regs->pc); -+ err |= get_user(lda, (unsigned int *)(regs->pc+4)); -+ err |= get_user(br, (unsigned int *)(regs->pc+8)); -+ -+ if (err) -+ break; -+ -+ if ((ldah & 0xFFFF0000U)== 0x277B0000U && -+ (lda & 0xFFFF0000U) == 0xA77B0000U && -+ (br & 0xFFE00000U) == 0xC3E00000U) -+ { -+ unsigned long addr = br | 0xFFFFFFFFFFE00000UL; -+ unsigned long addrh = (ldah | 0xFFFFFFFFFFFF0000UL) << 16; -+ unsigned long addrl = lda | 0xFFFFFFFFFFFF0000UL; -+ -+ regs->r27 += ((addrh ^ 0x80000000UL) + 0x80000000UL) + ((addrl ^ 0x8000UL) + 0x8000UL); -+ regs->pc += 12 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2); -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: unpatched PLT emulation */ -+ unsigned int br; -+ -+ err = get_user(br, (unsigned int *)regs->pc); -+ -+ if (!err && (br & 0xFFE00000U) == 0xC3800000U) { -+ unsigned int br2, ldq, nop, jmp; -+ unsigned long addr = br | 0xFFFFFFFFFFE00000UL, resolver; -+ -+ addr = regs->pc + 4 + (((addr ^ 0x00100000UL) + 0x00100000UL) << 2); -+ err = get_user(br2, (unsigned int *)addr); -+ err |= get_user(ldq, (unsigned int *)(addr+4)); -+ err |= get_user(nop, (unsigned int *)(addr+8)); -+ err |= get_user(jmp, (unsigned int *)(addr+12)); -+ err |= get_user(resolver, (unsigned long *)(addr+16)); -+ -+ if (err) -+ break; -+ -+ if (br2 == 0xC3600000U && -+ ldq == 0xA77B000CU && -+ nop == 0x47FF041FU && -+ jmp == 0x6B7B0000U) -+ { -+ regs->r28 = regs->pc+4; -+ regs->r27 = addr+16; -+ regs->pc = resolver; -+ return 3; -+ } -+ } -+ } while (0); -+#endif -+ -+ return 1; -+} -+ -+void pax_report_insns(void *pc, void *sp) -+{ -+ unsigned long i; -+ -+ printk(KERN_ERR "PAX: bytes at PC: "); -+ for (i = 0; i < 5; i++) { -+ unsigned int c; -+ if (get_user(c, (unsigned int*)pc+i)) { -+ printk("<invalid address>."); -+ break; -+ } -+ printk("%08x ", c); -+ } -+ printk("\n"); -+} -+#endif - - /* - * This routine handles page faults. It determines the address, -@@ -133,8 +270,34 @@ - good_area: - si_code = SEGV_ACCERR; - if (cause < 0) { -- if (!(vma->vm_flags & VM_EXEC)) -+ if (!(vma->vm_flags & VM_EXEC)) { -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (!(current->flags & PF_PAX_PAGEEXEC) || address != regs->pc) -+ goto bad_area; -+ -+ up_read(&mm->mmap_sem); -+ switch(pax_handle_fetch_fault(regs)) { -+ -+#ifdef CONFIG_PAX_EMUPLT -+ case 2: -+ case 3: -+ return; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ case 4: -+ return; -+#endif -+ -+ } -+ pax_report_fault(regs, (void*)regs->pc, (void*)rdusp()); -+ do_exit(SIGKILL); -+#else - goto bad_area; -+#endif -+ -+ } - } else if (!cause) { - /* Allow reads even for write-only mappings */ - if (!(vma->vm_flags & (VM_READ | VM_WRITE))) -diff -urN linux-2.6.5/arch/i386/Kconfig linux-2.6.5/arch/i386/Kconfig ---- linux-2.6.5/arch/i386/Kconfig 2004-04-03 22:36:25.000000000 -0500 -+++ linux-2.6.5/arch/i386/Kconfig 2004-04-18 11:05:50.000000000 -0400 -@@ -390,7 +390,7 @@ - - config X86_ALIGNMENT_16 - bool -- depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK6 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 -+ depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || X86_ELAN || MK8 || MK7 || MK6 || MPENTIUM4 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || M486 || MVIAC3_2 - default y - - config X86_GOOD_APIC -diff -urN linux-2.6.5/arch/i386/kernel/apm.c linux-2.6.5/arch/i386/kernel/apm.c ---- linux-2.6.5/arch/i386/kernel/apm.c 2004-04-03 22:36:16.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/apm.c 2004-04-18 11:05:50.000000000 -0400 -@@ -597,19 +597,40 @@ - int cpu; - struct desc_struct save_desc_40; - -+#ifdef CONFIG_PAX_KERNEXEC -+ unsigned long cr3; -+#endif -+ - cpus = apm_save_cpus(); - - cpu = get_cpu(); -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_open_kernel(flags, cr3); -+#endif -+ - save_desc_40 = cpu_gdt_table[cpu][0x40 / 8]; - cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc; - -+#ifndef CONFIG_PAX_KERNEXEC - local_save_flags(flags); - APM_DO_CLI; -+#endif -+ - APM_DO_SAVE_SEGS; - apm_bios_call_asm(func, ebx_in, ecx_in, eax, ebx, ecx, edx, esi); - APM_DO_RESTORE_SEGS; -+ -+#ifndef CONFIG_PAX_KERNEXEC - local_irq_restore(flags); -+#endif -+ - cpu_gdt_table[cpu][0x40 / 8] = save_desc_40; -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_close_kernel(flags, cr3); -+#endif -+ - put_cpu(); - apm_restore_cpus(cpus); - -@@ -639,20 +660,40 @@ - int cpu; - struct desc_struct save_desc_40; - -+#ifdef CONFIG_PAX_KERNEXEC -+ unsigned long cr3; -+#endif - - cpus = apm_save_cpus(); - - cpu = get_cpu(); -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_open_kernel(flags, cr3); -+#endif -+ - save_desc_40 = cpu_gdt_table[cpu][0x40 / 8]; - cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc; - -+#ifndef CONFIG_PAX_KERNEXEC - local_save_flags(flags); - APM_DO_CLI; -+#endif -+ - APM_DO_SAVE_SEGS; - error = apm_bios_call_simple_asm(func, ebx_in, ecx_in, eax); - APM_DO_RESTORE_SEGS; -+ -+#ifndef CONFIG_PAX_KERNEXEC - local_irq_restore(flags); -+#endif -+ - cpu_gdt_table[smp_processor_id()][0x40 / 8] = save_desc_40; -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_close_kernel(flags, cr3); -+#endif -+ - put_cpu(); - apm_restore_cpus(cpus); - return error; -diff -urN linux-2.6.5/arch/i386/kernel/cpu/common.c linux-2.6.5/arch/i386/kernel/cpu/common.c ---- linux-2.6.5/arch/i386/kernel/cpu/common.c 2004-04-03 22:36:16.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/cpu/common.c 2004-04-18 11:05:50.000000000 -0400 -@@ -319,6 +319,10 @@ - if (this_cpu->c_init) - this_cpu->c_init(c); - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_KERNEXEC) || defined(CONFIG_PAX_NOVSYSCALL) -+ clear_bit(X86_FEATURE_SEP, c->x86_capability); -+#endif -+ - /* Disable the PN if appropriate */ - squash_the_stupid_serial_number(c); - -@@ -514,7 +518,7 @@ - set_tss_desc(cpu,t); - cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff; - load_TR_desc(); -- load_LDT(&init_mm.context); -+ _load_LDT(&init_mm.context); - - /* Set up doublefault TSS pointer in the GDT */ - __set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss); -diff -urN linux-2.6.5/arch/i386/kernel/entry.S linux-2.6.5/arch/i386/kernel/entry.S ---- linux-2.6.5/arch/i386/kernel/entry.S 2004-04-03 22:36:52.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/entry.S 2004-04-18 11:05:50.000000000 -0400 -@@ -272,6 +272,11 @@ - movl TI_FLAGS(%ebp), %ecx - testw $_TIF_ALLWORK_MASK, %cx - jne syscall_exit_work -+ -+#ifdef CONFIG_PAX_RANDKSTACK -+ call pax_randomize_kstack -+#endif -+ - /* if something modifies registers it must also disable sysexit */ - movl EIP(%esp), %edx - movl OLDESP(%esp), %ecx -@@ -299,6 +304,11 @@ - movl TI_FLAGS(%ebp), %ecx - testw $_TIF_ALLWORK_MASK, %cx # current->work - jne syscall_exit_work -+ -+#ifdef CONFIG_PAX_RANDKSTACK -+ call pax_randomize_kstack -+#endif -+ - restore_all: - RESTORE_ALL - -@@ -591,7 +601,13 @@ - jmp error_code - - ENTRY(page_fault) -+#ifdef CONFIG_PAX_PAGEEXEC -+ ALIGN -+ pushl $pax_do_page_fault -+#else - pushl $do_page_fault -+#endif -+ - jmp error_code - - #ifdef CONFIG_X86_MCE -@@ -606,7 +622,7 @@ - pushl $do_spurious_interrupt_bug - jmp error_code - --.data -+.section .rodata,"a",@progbits - ENTRY(sys_call_table) - .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ - .long sys_exit -diff -urN linux-2.6.5/arch/i386/kernel/head.S linux-2.6.5/arch/i386/kernel/head.S ---- linux-2.6.5/arch/i386/kernel/head.S 2004-04-03 22:36:18.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/head.S 2004-04-18 11:05:50.000000000 -0400 -@@ -49,6 +49,12 @@ - - - /* -+ * Real beginning of normal "text" segment -+ */ -+ENTRY(stext) -+ENTRY(_stext) -+ -+/* - * 32-bit kernel entrypoint; only used by the boot CPU. On entry, - * %esi points to the real-mode code as a 32-bit pointer. - * CS and DS must be 4 GB flat segments, but we don't depend on -@@ -80,9 +86,9 @@ - - movl $(pg0 - __PAGE_OFFSET), %edi - movl $(swapper_pg_dir - __PAGE_OFFSET), %edx -- movl $0x007, %eax /* 0x007 = PRESENT+RW+USER */ -+ movl $0x067, %eax /* 0x067 = DIRTY+ACCESSED+PRESENT+RW+USER */ - 10: -- leal 0x007(%edi),%ecx /* Create PDE entry */ -+ leal 0x067(%edi),%ecx /* Create PDE entry */ - movl %ecx,(%edx) /* Store identity PDE entry */ - movl %ecx,page_pde_offset(%edx) /* Store kernel PDE entry */ - addl $4,%edx -@@ -92,8 +98,8 @@ - addl $0x1000,%eax - loop 11b - /* End condition: we must map up to and including INIT_MAP_BEYOND_END */ -- /* bytes beyond the end of our own page tables; the +0x007 is the attribute bits */ -- leal (INIT_MAP_BEYOND_END+0x007)(%edi),%ebp -+ /* bytes beyond the end of our own page tables; the +0x067 is the attribute bits */ -+ leal (INIT_MAP_BEYOND_END+0x067)(%edi),%ebp - cmpl %ebp,%eax - jb 10b - movl %edi,(init_pg_tables_end - __PAGE_OFFSET) -@@ -152,7 +158,7 @@ - movl %cr0,%eax - orl $0x80000000,%eax - movl %eax,%cr0 /* ..and set paging (PG) bit */ -- ljmp $__BOOT_CS,$1f /* Clear prefetch and normalize %eip */ -+ ljmp $__BOOT_CS,$1f + __KERNEL_TEXT_OFFSET /* Clear prefetch and normalize %eip */ - 1: - /* Set up the stack pointer */ - lss stack_start,%esp -@@ -304,8 +310,6 @@ - jmp L6 # main should never return here, but - # just in case, we know what happens. - --ready: .byte 0 -- - /* - * We depend on ET to be correct. This checks for 287/387. - */ -@@ -353,13 +357,6 @@ - jne rp_sidt - ret - --ENTRY(stack_start) -- .long init_thread_union+THREAD_SIZE -- .long __BOOT_DS -- --/* This is the default interrupt "handler" :-) */ --int_msg: -- .asciz "Unknown interrupt or fault at EIP %p %p %p\n" - ALIGN - ignore_int: - cld -@@ -386,6 +383,56 @@ - iret - - /* -+ * This starts the data section. Note that the above is all -+ * in the text section because it has alignment requirements -+ * that we cannot fulfill any other way except for PaX ;-). -+ */ -+.data -+ready: .byte 0 -+ -+/* -+ * swapper_pg_dir is the main page directory, address 0x00101000 -+ * -+ * This is initialized to create an identity-mapping at 0 (for bootup -+ * purposes) and another mapping at virtual address PAGE_OFFSET. The -+ * values put here should be all invalid (zero); the valid -+ * entries are created dynamically at boot time. -+ * -+ * The code creates enough page tables to map 0-_end, the page tables -+ * themselves, plus INIT_MAP_BEYOND_END bytes; see comment at beginning. -+ */ -+.section .data.swapper_pg_dir,"a",@progbits -+ENTRY(swapper_pg_dir) -+ .fill 1024,4,0 -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ENTRY(kernexec_pg_dir) -+ .fill 1024,4,0 -+#endif -+ -+.section .rodata.empty_zero_page,"a",@progbits -+ENTRY(empty_zero_page) -+ .fill 4096,1,0 -+ -+/* -+ * The IDT has to be page-aligned to simplify the Pentium -+ * F0 0F bug workaround.. We have a special link segment -+ * for this. -+ */ -+.section .rodata.idt,"a",@progbits -+ENTRY(idt_table) -+ .fill 256,8,0 -+ -+.section .rodata,"a",@progbits -+ENTRY(stack_start) -+ .long init_thread_union+THREAD_SIZE -+ .long __BOOT_DS -+ -+/* This is the default interrupt "handler" :-) */ -+int_msg: -+ .asciz "Unknown interrupt or fault at EIP %p %p %p\n" -+ -+/* - * The IDT and GDT 'descriptors' are a strange 48-bit object - * only used by the lidt and lgdt instructions. They are not - * like usual segment descriptors - they consist of a 16-bit -@@ -417,47 +464,14 @@ - .fill NR_CPUS-1,8,0 # space for the other GDT descriptors - - /* -- * swapper_pg_dir is the main page directory, address 0x00101000 -- * -- * This is initialized to create an identity-mapping at 0 (for bootup -- * purposes) and another mapping at virtual address PAGE_OFFSET. The -- * values put here should be all invalid (zero); the valid -- * entries are created dynamically at boot time. -- * -- * The code creates enough page tables to map 0-_end, the page tables -- * themselves, plus INIT_MAP_BEYOND_END bytes; see comment at beginning. -- */ --.org 0x1000 --ENTRY(swapper_pg_dir) -- .fill 1024,4,0 -- --.org 0x2000 --ENTRY(empty_zero_page) -- .fill 4096,1,0 -- --.org 0x3000 --/* -- * Real beginning of normal "text" segment -- */ --ENTRY(stext) --ENTRY(_stext) -- --/* -- * This starts the data section. Note that the above is all -- * in the text section because it has alignment requirements -- * that we cannot fulfill any other way. -- */ --.data -- --/* - * The boot_gdt_table must mirror the equivalent in setup.S and is - * used only for booting. - */ - .align L1_CACHE_BYTES - ENTRY(boot_gdt_table) - .fill GDT_ENTRY_BOOT_CS,8,0 -- .quad 0x00cf9a000000ffff /* kernel 4GB code at 0x00000000 */ -- .quad 0x00cf92000000ffff /* kernel 4GB data at 0x00000000 */ -+ .quad 0x00cf9b000000ffff /* kernel 4GB code at 0x00000000 */ -+ .quad 0x00cf93000000ffff /* kernel 4GB data at 0x00000000 */ - - /* - * The Global Descriptor Table contains 28 quadwords, per-CPU. -@@ -468,7 +482,13 @@ - .quad 0x0000000000000000 /* 0x0b reserved */ - .quad 0x0000000000000000 /* 0x13 reserved */ - .quad 0x0000000000000000 /* 0x1b reserved */ -+ -+#if defined(CONFIG_PAX_KERNEXEC) && defined(CONFIG_PCI_BIOS) -+ .quad 0x00cf9b000000ffff /* 0x20 kernel 4GB code at 0x00000000 */ -+#else - .quad 0x0000000000000000 /* 0x20 unused */ -+#endif -+ - .quad 0x0000000000000000 /* 0x28 unused */ - .quad 0x0000000000000000 /* 0x33 TLS entry 1 */ - .quad 0x0000000000000000 /* 0x3b TLS entry 2 */ -@@ -477,27 +497,32 @@ - .quad 0x0000000000000000 /* 0x53 reserved */ - .quad 0x0000000000000000 /* 0x5b reserved */ - -- .quad 0x00cf9a000000ffff /* 0x60 kernel 4GB code at 0x00000000 */ -- .quad 0x00cf92000000ffff /* 0x68 kernel 4GB data at 0x00000000 */ -- .quad 0x00cffa000000ffff /* 0x73 user 4GB code at 0x00000000 */ -- .quad 0x00cff2000000ffff /* 0x7b user 4GB data at 0x00000000 */ -+#ifdef CONFIG_PAX_KERNEXEC -+ .quad 0xc0cf9b400000ffff /* 0x60 kernel 4GB code at 0xc0400000 */ -+#else -+ .quad 0x00cf9b000000ffff /* 0x60 kernel 4GB code at 0x00000000 */ -+#endif -+ -+ .quad 0x00cf93000000ffff /* 0x68 kernel 4GB data at 0x00000000 */ -+ .quad 0x00cffb000000ffff /* 0x73 user 4GB code at 0x00000000 */ -+ .quad 0x00cff3000000ffff /* 0x7b user 4GB data at 0x00000000 */ - - .quad 0x0000000000000000 /* 0x80 TSS descriptor */ - .quad 0x0000000000000000 /* 0x88 LDT descriptor */ - - /* Segments used for calling PnP BIOS */ -- .quad 0x00c09a0000000000 /* 0x90 32-bit code */ -- .quad 0x00809a0000000000 /* 0x98 16-bit code */ -- .quad 0x0080920000000000 /* 0xa0 16-bit data */ -- .quad 0x0080920000000000 /* 0xa8 16-bit data */ -- .quad 0x0080920000000000 /* 0xb0 16-bit data */ -+ .quad 0x00c09b0000000000 /* 0x90 32-bit code */ -+ .quad 0x00809b0000000000 /* 0x98 16-bit code */ -+ .quad 0x0080930000000000 /* 0xa0 16-bit data */ -+ .quad 0x0080930000000000 /* 0xa8 16-bit data */ -+ .quad 0x0080930000000000 /* 0xb0 16-bit data */ - /* - * The APM segments have byte granularity and their bases - * and limits are set at run time. - */ -- .quad 0x00409a0000000000 /* 0xb8 APM CS code */ -- .quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */ -- .quad 0x0040920000000000 /* 0xc8 APM DS data */ -+ .quad 0x00409b0000000000 /* 0xb8 APM CS code */ -+ .quad 0x00009b0000000000 /* 0xc0 APM CS 16 code (16 bit) */ -+ .quad 0x0040930000000000 /* 0xc8 APM DS data */ - - .quad 0x0000000000000000 /* 0xd0 - unused */ - .quad 0x0000000000000000 /* 0xd8 - unused */ -diff -urN linux-2.6.5/arch/i386/kernel/ioport.c linux-2.6.5/arch/i386/kernel/ioport.c ---- linux-2.6.5/arch/i386/kernel/ioport.c 2004-04-03 22:37:06.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/ioport.c 2004-04-18 11:05:50.000000000 -0400 -@@ -15,6 +15,7 @@ - #include <linux/stddef.h> - #include <linux/slab.h> - #include <linux/thread_info.h> -+#include <linux/grsecurity.h> - - /* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */ - static void set_bitmap(unsigned long *bitmap, unsigned int base, unsigned int extent, int new_value) -@@ -62,9 +63,16 @@ - - if ((from + num <= from) || (from + num > IO_BITMAP_BITS)) - return -EINVAL; -+#ifdef CONFIG_GRKERNSEC_IO -+ if (turn_on) { -+ gr_handle_ioperm(); -+#else - if (turn_on && !capable(CAP_SYS_RAWIO)) -+#endif - return -EPERM; -- -+#ifdef CONFIG_GRKERNSEC_IO -+ } -+#endif - /* - * If it's the first ioperm() call in this thread's lifetime, set the - * IO bitmap up. ioperm() is much less timing critical than clone(), -@@ -115,8 +123,13 @@ - return -EINVAL; - /* Trying to gain more privileges? */ - if (level > old) { -+#ifdef CONFIG_GRKERNSEC_IO -+ gr_handle_iopl(); -+ return -EPERM; -+#else - if (!capable(CAP_SYS_RAWIO)) - return -EPERM; -+#endif - } - regs->eflags = (regs->eflags &~ 0x3000UL) | (level << 12); - /* Make sure we return the long way (not sysenter) */ -diff -urN linux-2.6.5/arch/i386/kernel/ldt.c linux-2.6.5/arch/i386/kernel/ldt.c ---- linux-2.6.5/arch/i386/kernel/ldt.c 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/ldt.c 2004-04-18 11:05:50.000000000 -0400 -@@ -154,7 +154,7 @@ - { - int err; - unsigned long size; -- void *address; -+ const void *address; - - err = 0; - address = &default_ldt[0]; -@@ -211,6 +211,13 @@ - } - } - -+#ifdef CONFIG_PAX_SEGMEXEC -+ if ((current->flags & PF_PAX_SEGMEXEC) && (ldt_info.contents & 2)) { -+ error = -EINVAL; -+ goto out_unlock; -+ } -+#endif -+ - entry_1 = LDT_entry_a(&ldt_info); - entry_2 = LDT_entry_b(&ldt_info); - if (oldmode) -diff -urN linux-2.6.5/arch/i386/kernel/process.c linux-2.6.5/arch/i386/kernel/process.c ---- linux-2.6.5/arch/i386/kernel/process.c 2004-04-03 22:36:10.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/process.c 2004-04-18 11:05:50.000000000 -0400 -@@ -344,7 +344,7 @@ - struct task_struct *tsk; - int err; - -- childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info)) - 1; -+ childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p->thread_info - sizeof(unsigned long))) - 1; - struct_cpy(childregs, regs); - childregs->eax = 0; - childregs->esp = esp; -@@ -446,9 +446,8 @@ - int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) - { - struct pt_regs ptregs; -- -- ptregs = *(struct pt_regs *) -- ((unsigned long)tsk->thread_info+THREAD_SIZE - sizeof(ptregs)); -+ -+ ptregs = *(struct pt_regs *)(tsk->thread.esp0 - sizeof(ptregs)); - ptregs.xcs &= 0xffff; - ptregs.xds &= 0xffff; - ptregs.xes &= 0xffff; -@@ -501,10 +500,22 @@ - int cpu = smp_processor_id(); - struct tss_struct *tss = init_tss + cpu; - -+#ifdef CONFIG_PAX_KERNEXEC -+ unsigned long flags, cr3; -+#endif -+ - /* never put a printk in __switch_to... printk() calls wake_up*() indirectly */ - - __unlazy_fpu(prev_p); - -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_open_kernel(flags, cr3); -+#endif -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ pax_switch_segments(next_p, cpu); -+#endif -+ - /* - * Reload esp0, LDT and the page table pointer: - */ -@@ -515,6 +526,10 @@ - */ - load_TLS(next, cpu); - -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_close_kernel(flags, cr3); -+#endif -+ - /* - * Save away %fs and %gs. No need to save %es and %ds, as - * those are always kernel segments while inside the kernel. -@@ -689,6 +704,10 @@ - struct desc_struct *desc; - int cpu, idx; - -+#ifdef CONFIG_PAX_KERNEXEC -+ unsigned long flags, cr3; -+#endif -+ - if (copy_from_user(&info, u_info, sizeof(info))) - return -EFAULT; - idx = info.entry_number; -@@ -722,8 +741,17 @@ - desc->a = LDT_entry_a(&info); - desc->b = LDT_entry_b(&info); - } -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_open_kernel(flags, cr3); -+#endif -+ - load_TLS(t, cpu); - -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_close_kernel(flags, cr3); -+#endif -+ - put_cpu(); - - return 0; -@@ -777,3 +805,29 @@ - return 0; - } - -+#ifdef CONFIG_PAX_RANDKSTACK -+asmlinkage void pax_randomize_kstack(void) -+{ -+ struct tss_struct *tss = init_tss + smp_processor_id(); -+ unsigned long time; -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ if (!pax_aslr) -+ return; -+#endif -+ -+ rdtscl(time); -+ -+ /* P4 seems to return a 0 LSB, ignore it */ -+#ifdef CONFIG_MPENTIUM4 -+ time &= 0x3EUL; -+ time <<= 1; -+#else -+ time &= 0x1FUL; -+ time <<= 2; -+#endif -+ -+ tss->esp0 ^= time; -+ current->thread.esp0 = tss->esp0; -+} -+#endif -diff -urN linux-2.6.5/arch/i386/kernel/ptrace.c linux-2.6.5/arch/i386/kernel/ptrace.c ---- linux-2.6.5/arch/i386/kernel/ptrace.c 2004-04-03 22:36:54.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/ptrace.c 2004-04-18 11:05:50.000000000 -0400 -@@ -14,6 +14,7 @@ - #include <linux/ptrace.h> - #include <linux/user.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/pgtable.h> -@@ -262,6 +263,9 @@ - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - -+ if (gr_handle_ptrace(child, request)) -+ goto out_tsk; -+ - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; -@@ -340,6 +344,17 @@ - if(addr == (long) &dummy->u_debugreg[5]) break; - if(addr < (long) &dummy->u_debugreg[4] && - ((unsigned long) data) >= TASK_SIZE-3) break; -+ -+#ifdef CONFIG_GRKERNSEC -+ if(addr >= (long) &dummy->u_debugreg[0] && -+ addr <= (long) &dummy->u_debugreg[3]){ -+ long reg = (addr - (long) &dummy->u_debugreg[0]) >> 2; -+ long type = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 4*reg)) & 3; -+ long align = (child->thread.debugreg[7] >> (DR_CONTROL_SHIFT + 2 + 4*reg)) & 3; -+ if((type & 1) && (data & align)) -+ break; -+ } -+#endif - - if(addr == (long) &dummy->u_debugreg[7]) { - data &= ~DR_CONTROL_RESERVED; -diff -urN linux-2.6.5/arch/i386/kernel/reboot.c linux-2.6.5/arch/i386/kernel/reboot.c ---- linux-2.6.5/arch/i386/kernel/reboot.c 2004-04-03 22:36:54.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/reboot.c 2004-04-18 11:05:50.000000000 -0400 -@@ -74,18 +74,18 @@ - doesn't work with at least one type of 486 motherboard. It is easy - to stop this code working; hence the copious comments. */ - --static unsigned long long -+static const unsigned long long - real_mode_gdt_entries [3] = - { - 0x0000000000000000ULL, /* Null descriptor */ -- 0x00009a000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */ -- 0x000092000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ -+ 0x00009b000000ffffULL, /* 16-bit real-mode 64k code at 0x00000000 */ -+ 0x000093000100ffffULL /* 16-bit real-mode 64k data at 0x00000100 */ - }; - - static struct - { - unsigned short size __attribute__ ((packed)); -- unsigned long long * base __attribute__ ((packed)); -+ const unsigned long long * base __attribute__ ((packed)); - } - real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, real_mode_gdt_entries }, - real_mode_idt = { 0x3ff, 0 }, -diff -urN linux-2.6.5/arch/i386/kernel/setup.c linux-2.6.5/arch/i386/kernel/setup.c ---- linux-2.6.5/arch/i386/kernel/setup.c 2004-04-03 22:37:06.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/setup.c 2004-04-18 11:05:50.000000000 -0400 -@@ -1202,6 +1202,15 @@ - #endif - } - -+#ifdef CONFIG_PAX_SOFTMODE -+static int __init setup_pax_softmode(char *str) -+{ -+ get_option (&str, &pax_softmode); -+ return 1; -+} -+__setup("pax_softmode=", setup_pax_softmode); -+#endif -+ - #include "setup_arch_post.h" - /* - * Local Variables: -diff -urN linux-2.6.5/arch/i386/kernel/signal.c linux-2.6.5/arch/i386/kernel/signal.c ---- linux-2.6.5/arch/i386/kernel/signal.c 2004-04-03 22:36:58.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/signal.c 2004-04-18 11:05:50.000000000 -0400 -@@ -371,7 +371,17 @@ - if (err) - goto give_sigsegv; - -+#ifdef CONFIG_PAX_NOVSYSCALL -+ restorer = frame->retcode; -+#else - restorer = &__kernel_sigreturn; -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) -+ restorer -= SEGMEXEC_TASK_SIZE; -+#endif -+#endif -+ - if (ka->sa.sa_flags & SA_RESTORER) - restorer = ka->sa.sa_restorer; - -@@ -454,7 +464,18 @@ - goto give_sigsegv; - - /* Set up to return from userspace. */ -+ -+#ifdef CONFIG_PAX_NOVSYSCALL -+ restorer = frame->retcode; -+#else - restorer = &__kernel_rt_sigreturn; -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) -+ restorer -= SEGMEXEC_TASK_SIZE; -+#endif -+#endif -+ - if (ka->sa.sa_flags & SA_RESTORER) - restorer = ka->sa.sa_restorer; - err |= __put_user(restorer, &frame->pretcode); -diff -urN linux-2.6.5/arch/i386/kernel/sys_i386.c linux-2.6.5/arch/i386/kernel/sys_i386.c ---- linux-2.6.5/arch/i386/kernel/sys_i386.c 2004-04-03 22:38:21.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/sys_i386.c 2004-04-18 11:05:50.000000000 -0400 -@@ -19,6 +19,7 @@ - #include <linux/mman.h> - #include <linux/file.h> - #include <linux/utsname.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/ipc.h> -@@ -49,6 +50,11 @@ - int error = -EBADF; - struct file * file = NULL; - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); -@@ -56,8 +62,14 @@ - goto out; - } - -+ if (gr_handle_mmap(file, prot)) { -+ fput(file); -+ error = -EACCES; -+ goto out; -+ } -+ - down_write(¤t->mm->mmap_sem); -- error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); -+ error = do_mmap(file, addr, len, prot, flags, pgoff << PAGE_SHIFT); - up_write(¤t->mm->mmap_sem); - - if (file) -diff -urN linux-2.6.5/arch/i386/kernel/sysenter.c linux-2.6.5/arch/i386/kernel/sysenter.c ---- linux-2.6.5/arch/i386/kernel/sysenter.c 2004-04-03 22:38:24.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/sysenter.c 2004-04-18 11:05:50.000000000 -0400 -@@ -41,13 +41,15 @@ - extern const char vsyscall_int80_start, vsyscall_int80_end; - extern const char vsyscall_sysenter_start, vsyscall_sysenter_end; - -+#ifndef CONFIG_PAX_NOVSYSCALL - static int __init sysenter_setup(void) - { - unsigned long page = get_zeroed_page(GFP_ATOMIC); - - __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY); - -- if (!boot_cpu_has(X86_FEATURE_SEP)) { -+ if (!boot_cpu_has(X86_FEATURE_SEP)) -+ { - memcpy((void *) page, - &vsyscall_int80_start, - &vsyscall_int80_end - &vsyscall_int80_start); -@@ -63,3 +65,4 @@ - } - - __initcall(sysenter_setup); -+#endif -diff -urN linux-2.6.5/arch/i386/kernel/trampoline.S linux-2.6.5/arch/i386/kernel/trampoline.S ---- linux-2.6.5/arch/i386/kernel/trampoline.S 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/trampoline.S 2004-04-18 11:05:50.000000000 -0400 -@@ -58,7 +58,7 @@ - inc %ax # protected mode (PE) bit - lmsw %ax # into protected mode - # flush prefetch and jump to startup_32_smp in arch/i386/kernel/head.S -- ljmpl $__BOOT_CS, $(startup_32_smp-__PAGE_OFFSET) -+ ljmpl $__BOOT_CS, $(startup_32_smp+__KERNEL_TEXT_OFFSET-__PAGE_OFFSET) - - # These need to be in the same 64K segment as the above; - # hence we don't use the boot_gdt_descr defined in head.S -diff -urN linux-2.6.5/arch/i386/kernel/traps.c linux-2.6.5/arch/i386/kernel/traps.c ---- linux-2.6.5/arch/i386/kernel/traps.c 2004-04-03 22:36:25.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/traps.c 2004-04-18 11:05:50.000000000 -0400 -@@ -59,18 +59,13 @@ - asmlinkage void lcall7(void); - asmlinkage void lcall27(void); - --struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, -+const struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 0, 0 }, { 0, 0 } }; - - /* Do we ignore FPU interrupts ? */ - char ignore_fpu_irq = 0; - --/* -- * The IDT has to be page-aligned to simplify the Pentium -- * F0 0F bug workaround.. We have a special link segment -- * for this. -- */ --struct desc_struct idt_table[256] __attribute__((__section__(".data.idt"))) = { {0, 0}, }; -+extern struct desc_struct idt_table[256]; - - asmlinkage void divide_error(void); - asmlinkage void debug(void); -@@ -97,6 +92,7 @@ - void show_trace(struct task_struct *task, unsigned long * stack) - { - unsigned long addr; -+ int i = kstack_depth_to_print; - - if (!stack) - stack = (unsigned long*)&stack; -@@ -105,11 +101,12 @@ - #ifdef CONFIG_KALLSYMS - printk("\n"); - #endif -- while (!kstack_end(stack)) { -+ while (i && !kstack_end(stack)) { - addr = *stack++; - if (kernel_text_address(addr)) { - printk(" [<%08lx>] ", addr); - print_symbol("%s\n", addr); -+ --i; - } - } - printk("\n"); -@@ -199,14 +196,23 @@ - show_stack(NULL, (unsigned long*)esp); - - printk("Code: "); -+ -+#ifndef CONFIG_PAX_KERNEXEC - if(regs->eip < PAGE_OFFSET) - goto bad; -+#endif - - for(i=0;i<20;i++) - { - unsigned char c; -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ if(__get_user(c, &((unsigned char*)regs->eip)[i+__KERNEL_TEXT_OFFSET])) { -+#else - if(__get_user(c, &((unsigned char*)regs->eip)[i])) { - bad: -+#endif -+ - printk(" Bad EIP value."); - break; - } -@@ -229,8 +235,13 @@ - - eip = regs->eip; - -+#ifdef CONFIG_PAX_KERNEXEC -+ eip += __KERNEL_TEXT_OFFSET; -+#else - if (eip < PAGE_OFFSET) - goto no_bug; -+#endif -+ - if (__get_user(ud2, (unsigned short *)eip)) - goto no_bug; - if (ud2 != 0x0b0f) -@@ -238,7 +249,13 @@ - if (__get_user(line, (unsigned short *)(eip + 2))) - goto bug; - if (__get_user(file, (char **)(eip + 4)) || -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ __get_user(c, file + __KERNEL_TEXT_OFFSET)) -+#else - (unsigned long)file < PAGE_OFFSET || __get_user(c, file)) -+#endif -+ - file = "<bad filename>"; - - printk("------------[ cut here ]------------\n"); -@@ -411,8 +428,16 @@ - return; - - gp_in_kernel: -- if (!fixup_exception(regs)) -+ if (!fixup_exception(regs)) { -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ if ((regs->xcs & 0xFFFF) == __KERNEL_CS) -+ die("PAX: suspicious general protection fault", regs, error_code); -+ else -+#endif -+ - die("general protection fault", regs, error_code); -+ } - } - - static void mem_parity_error(unsigned char reason, struct pt_regs * regs) -@@ -845,7 +870,7 @@ - _set_gate(idt_table+n,15,3,addr,__KERNEL_CS); - } - --static void __init set_call_gate(void *a, void *addr) -+static void __init set_call_gate(const void *a, void *addr) - { - _set_gate(a,12,3,addr,__KERNEL_CS); - } -diff -urN linux-2.6.5/arch/i386/kernel/vmlinux.lds.S linux-2.6.5/arch/i386/kernel/vmlinux.lds.S ---- linux-2.6.5/arch/i386/kernel/vmlinux.lds.S 2004-04-03 22:36:26.000000000 -0500 -+++ linux-2.6.5/arch/i386/kernel/vmlinux.lds.S 2004-04-18 11:05:50.000000000 -0400 -@@ -2,7 +2,12 @@ - * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>; - */ - -+#include <linux/config.h> -+ - #include <asm-generic/vmlinux.lds.h> -+#include <asm-i386/page.h> -+#include <asm-i386/segment.h> -+ - #include <asm/thread_info.h> - - OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") -@@ -11,25 +16,16 @@ - jiffies = jiffies_64; - SECTIONS - { -- . = 0xC0000000 + 0x100000; -- /* read-only */ -- _text = .; /* Text and read-only data */ -- .text : { -- *(.text) -- *(.fixup) -- *(.gnu.warning) -- } = 0x9090 -- -- _etext = .; /* End of text section */ -- -- . = ALIGN(16); /* Exception table */ -- __start___ex_table = .; -- __ex_table : { *(__ex_table) } -- __stop___ex_table = .; -- -- RODATA -+ . = __PAGE_OFFSET + 0x100000; -+ .text.startup : { -+ BYTE(0xEA) /* jmp far */ -+ LONG(startup_32 + __KERNEL_TEXT_OFFSET - __PAGE_OFFSET) -+ SHORT(__BOOT_CS) -+ } - - /* writeable */ -+ . = ALIGN(32); -+ _data = .; - .data : { /* Data */ - *(.data) - CONSTRUCTORS -@@ -41,25 +37,28 @@ - . = ALIGN(4096); - __nosave_end = .; - -- . = ALIGN(4096); -- .data.page_aligned : { *(.data.idt) } -- - . = ALIGN(32); - .data.cacheline_aligned : { *(.data.cacheline_aligned) } - -- _edata = .; /* End of data section */ -- - . = ALIGN(THREAD_SIZE); /* init_task */ - .data.init_task : { *(.data.init_task) } - -+ . = ALIGN(4096); -+ .data.page_aligned : { *(.data.swapper_pg_dir) } -+ -+ _edata = .; /* End of data section */ -+ -+ __bss_start = .; /* BSS */ -+ .bss : { -+ *(.bss) -+ LONG(0) -+ } -+ . = ALIGN(4); -+ __bss_stop = .; -+ - /* will be freed after init */ - . = ALIGN(4096); /* Init code and data */ - __init_begin = .; -- .init.text : { -- _sinittext = .; -- *(.init.text) -- _einittext = .; -- } - .init.data : { *(.init.data) } - . = ALIGN(16); - __setup_start = .; -@@ -100,16 +99,68 @@ - __per_cpu_start = .; - .data.percpu : { *(.data.percpu) } - __per_cpu_end = .; -+ -+ /* read-only */ -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ __init_text_start = .; -+ .init.text (. - __KERNEL_TEXT_OFFSET) : AT (__init_text_start) { -+ _sinittext = .; -+ *(.init.text) -+ _einittext = .; -+ . = ALIGN(4*1024*1024) - 1; -+ BYTE(0) -+ } -+ . = ALIGN(4096); -+ __init_end = . + __KERNEL_TEXT_OFFSET; -+ /* freed after init ends here */ -+ -+/* -+ * PaX: this must be kept in synch with the KERNEL_CS base -+ * in the GDTs in arch/i386/kernel/head.S -+ */ -+ _text = .; /* Text and read-only data */ -+ .text : AT (. + __KERNEL_TEXT_OFFSET) { -+#else -+ .init.text : { -+ _sinittext = .; -+ *(.init.text) -+ _einittext = .; -+ } - . = ALIGN(4096); - __init_end = .; - /* freed after init ends here */ -- -- __bss_start = .; /* BSS */ -- .bss : { *(.bss) } -- . = ALIGN(4); -- __bss_stop = .; - -+ _text = .; /* Text and read-only data */ -+ .text : { -+#endif -+ -+ *(.text) -+ *(.fixup) -+ *(.gnu.warning) -+ } = 0x9090 -+ -+ _etext = .; /* End of text section */ -+ . += __KERNEL_TEXT_OFFSET; -+ . = ALIGN(16); /* Exception table */ -+ __start___ex_table = .; -+ __ex_table : { *(__ex_table) } -+ __stop___ex_table = .; -+ -+ . = ALIGN(4096); -+ .rodata.page_aligned : { -+ *(.rodata.empty_zero_page) -+ *(.rodata.idt) -+ } -+ -+ RODATA -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ _end = ALIGN(4*1024*1024); -+ . = _end ; -+#else - _end = . ; -+#endif - - /* This is where the kernel creates the early boot page tables */ - . = ALIGN(4096); -diff -urN linux-2.6.5/arch/i386/mm/fault.c linux-2.6.5/arch/i386/mm/fault.c ---- linux-2.6.5/arch/i386/mm/fault.c 2004-04-03 22:36:13.000000000 -0500 -+++ linux-2.6.5/arch/i386/mm/fault.c 2004-04-18 11:05:50.000000000 -0400 -@@ -21,6 +21,9 @@ - #include <linux/vt_kern.h> /* For unblank_screen() */ - #include <linux/highmem.h> - #include <linux/module.h> -+#include <linux/unistd.h> -+#include <linux/compiler.h> -+#include <linux/binfmts.h> - - #include <asm/system.h> - #include <asm/uaccess.h> -@@ -199,6 +202,10 @@ - - asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); - -+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) -+static int pax_handle_fetch_fault(struct pt_regs *regs); -+#endif -+ - /* - * This routine handles page faults. It determines the address, - * and the problem, and then passes it off to one of the appropriate -@@ -209,22 +216,31 @@ - * bit 1 == 0 means read, 1 means write - * bit 2 == 0 means kernel, 1 means user-mode - */ -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+static void do_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address) -+#else - asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) -+#endif - { - struct task_struct *tsk; - struct mm_struct *mm; - struct vm_area_struct * vma; -+#ifndef CONFIG_PAX_PAGEEXEC - unsigned long address; -+#endif - unsigned long page; - int write; - siginfo_t info; - -+#ifndef CONFIG_PAX_PAGEEXEC - /* get the address */ - __asm__("movl %%cr2,%0":"=r" (address)); - - /* It's safe to allow irq's after cr2 has been saved */ - if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) - local_irq_enable(); -+#endif - - tsk = current; - -@@ -358,6 +374,34 @@ - if (is_prefetch(regs, address)) - return; - -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) { -+ -+#if defined(CONFIG_PAX_EMUTRAMP) || defined(CONFIG_PAX_RANDEXEC) -+ if ((error_code == 4) && (regs->eip + SEGMEXEC_TASK_SIZE == address)) { -+ switch (pax_handle_fetch_fault(regs)) { -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ case 3: -+ return; -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ case 2: -+ return; -+#endif -+ -+ } -+ } -+#endif -+ -+ if (address >= SEGMEXEC_TASK_SIZE) { -+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp); -+ do_exit(SIGKILL); -+ } -+ } -+#endif -+ - tsk->thread.cr2 = address; - /* Kernel addresses are always protection faults */ - tsk->thread.error_code = error_code | (address >= TASK_SIZE); -@@ -408,6 +452,13 @@ - - if (address < PAGE_SIZE) - printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ else if (init_mm.start_code + __KERNEL_TEXT_OFFSET <= address && address < init_mm.end_code + __KERNEL_TEXT_OFFSET) -+ printk(KERN_ERR "PAX: %s:%d, uid/euid: %u/%u, attempted to modify kernel code", -+ tsk->comm, tsk->pid, tsk->uid, tsk->euid); -+#endif -+ - else - printk(KERN_ALERT "Unable to handle kernel paging request"); - printk(" at virtual address %08lx\n",address); -@@ -509,3 +560,361 @@ - return; - } - } -+ -+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) -+/* -+ * PaX: decide what to do with offenders (regs->eip = fault address) -+ * -+ * returns 1 when task should be killed -+ * 2 when gcc trampoline was detected -+ * 3 when legitimate ET_EXEC was detected -+ */ -+static int pax_handle_fetch_fault(struct pt_regs *regs) -+{ -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ static const unsigned char trans[8] = {6, 1, 2, 0, 13, 5, 3, 4}; -+#endif -+ -+#if defined(CONFIG_PAX_RANDEXEC) || defined(CONFIG_PAX_EMUTRAMP) -+ int err; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ if (current->flags & PF_PAX_RANDEXEC) { -+ unsigned long esp_4; -+ -+ if (regs->eip >= current->mm->start_code && -+ regs->eip < current->mm->end_code) -+ { -+ err = get_user(esp_4, (unsigned long*)(regs->esp-4UL)); -+ if (err || esp_4 == regs->eip) -+ return 1; -+ -+ regs->eip += current->mm->delta_exec; -+ return 3; -+ } -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ do { /* PaX: gcc trampoline emulation #1 */ -+ unsigned char mov1, mov2; -+ unsigned short jmp; -+ unsigned long addr1, addr2, ret; -+ unsigned short call; -+ -+ err = get_user(mov1, (unsigned char *)regs->eip); -+ err |= get_user(addr1, (unsigned long *)(regs->eip + 1)); -+ err |= get_user(mov2, (unsigned char *)(regs->eip + 5)); -+ err |= get_user(addr2, (unsigned long *)(regs->eip + 6)); -+ err |= get_user(jmp, (unsigned short *)(regs->eip + 10)); -+ err |= get_user(ret, (unsigned long *)regs->esp); -+ -+ if (err) -+ break; -+ -+ err = get_user(call, (unsigned short *)(ret-2)); -+ if (err) -+ break; -+ -+ if ((mov1 & 0xF8) == 0xB8 && -+ (mov2 & 0xF8) == 0xB8 && -+ (mov1 & 0x07) != (mov2 & 0x07) && -+ (jmp & 0xF8FF) == 0xE0FF && -+ (mov2 & 0x07) == ((jmp>>8) & 0x07) && -+ (call & 0xF8FF) == 0xD0FF && -+ regs->eip == ((unsigned long*)regs)[trans[(call>>8) & 0x07]]) -+ { -+ ((unsigned long *)regs)[trans[mov1 & 0x07]] = addr1; -+ ((unsigned long *)regs)[trans[mov2 & 0x07]] = addr2; -+ regs->eip = addr2; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: gcc trampoline emulation #2 */ -+ unsigned char mov, jmp; -+ unsigned long addr1, addr2, ret; -+ unsigned short call; -+ -+ err = get_user(mov, (unsigned char *)regs->eip); -+ err |= get_user(addr1, (unsigned long *)(regs->eip + 1)); -+ err |= get_user(jmp, (unsigned char *)(regs->eip + 5)); -+ err |= get_user(addr2, (unsigned long *)(regs->eip + 6)); -+ err |= get_user(ret, (unsigned long *)regs->esp); -+ -+ if (err) -+ break; -+ -+ err = get_user(call, (unsigned short *)(ret-2)); -+ if (err) -+ break; -+ -+ if ((mov & 0xF8) == 0xB8 && -+ jmp == 0xE9 && -+ (call & 0xF8FF) == 0xD0FF && -+ regs->eip == ((unsigned long*)regs)[trans[(call>>8) & 0x07]]) -+ { -+ ((unsigned long *)regs)[trans[mov & 0x07]] = addr1; -+ regs->eip += addr2 + 10; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: gcc trampoline emulation #3 */ -+ unsigned char mov, jmp; -+ char offset; -+ unsigned long addr1, addr2, ret; -+ unsigned short call; -+ -+ err = get_user(mov, (unsigned char *)regs->eip); -+ err |= get_user(addr1, (unsigned long *)(regs->eip + 1)); -+ err |= get_user(jmp, (unsigned char *)(regs->eip + 5)); -+ err |= get_user(addr2, (unsigned long *)(regs->eip + 6)); -+ err |= get_user(ret, (unsigned long *)regs->esp); -+ -+ if (err) -+ break; -+ -+ err = get_user(call, (unsigned short *)(ret-3)); -+ err |= get_user(offset, (char *)(ret-1)); -+ if (err) -+ break; -+ -+ if ((mov & 0xF8) == 0xB8 && -+ jmp == 0xE9 && -+ call == 0x55FF) -+ { -+ unsigned long addr; -+ -+ err = get_user(addr, (unsigned long*)(regs->ebp + (unsigned long)(long)offset)); -+ if (err || regs->eip != addr) -+ break; -+ -+ ((unsigned long *)regs)[trans[mov & 0x07]] = addr1; -+ regs->eip += addr2 + 10; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: gcc trampoline emulation #4 */ -+ unsigned char mov, jmp, sib; -+ char offset; -+ unsigned long addr1, addr2, ret; -+ unsigned short call; -+ -+ err = get_user(mov, (unsigned char *)regs->eip); -+ err |= get_user(addr1, (unsigned long *)(regs->eip + 1)); -+ err |= get_user(jmp, (unsigned char *)(regs->eip + 5)); -+ err |= get_user(addr2, (unsigned long *)(regs->eip + 6)); -+ err |= get_user(ret, (unsigned long *)regs->esp); -+ -+ if (err) -+ break; -+ -+ err = get_user(call, (unsigned short *)(ret-4)); -+ err |= get_user(sib, (unsigned char *)(ret-2)); -+ err |= get_user(offset, (char *)(ret-1)); -+ if (err) -+ break; -+ -+ if ((mov & 0xF8) == 0xB8 && -+ jmp == 0xE9 && -+ call == 0x54FF && -+ sib == 0x24) -+ { -+ unsigned long addr; -+ -+ err = get_user(addr, (unsigned long*)(regs->esp + 4 + (unsigned long)(long)offset)); -+ if (err || regs->eip != addr) -+ break; -+ -+ ((unsigned long *)regs)[trans[mov & 0x07]] = addr1; -+ regs->eip += addr2 + 10; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: gcc trampoline emulation #5 */ -+ unsigned char mov, jmp, sib; -+ unsigned long addr1, addr2, ret, offset; -+ unsigned short call; -+ -+ err = get_user(mov, (unsigned char *)regs->eip); -+ err |= get_user(addr1, (unsigned long *)(regs->eip + 1)); -+ err |= get_user(jmp, (unsigned char *)(regs->eip + 5)); -+ err |= get_user(addr2, (unsigned long *)(regs->eip + 6)); -+ err |= get_user(ret, (unsigned long *)regs->esp); -+ -+ if (err) -+ break; -+ -+ err = get_user(call, (unsigned short *)(ret-7)); -+ err |= get_user(sib, (unsigned char *)(ret-5)); -+ err |= get_user(offset, (unsigned long *)(ret-4)); -+ if (err) -+ break; -+ -+ if ((mov & 0xF8) == 0xB8 && -+ jmp == 0xE9 && -+ call == 0x94FF && -+ sib == 0x24) -+ { -+ unsigned long addr; -+ -+ err = get_user(addr, (unsigned long*)(regs->esp + 4 + offset)); -+ if (err || regs->eip != addr) -+ break; -+ -+ ((unsigned long *)regs)[trans[mov & 0x07]] = addr1; -+ regs->eip += addr2 + 10; -+ return 2; -+ } -+ } while (0); -+#endif -+ -+ return 1; /* PaX in action */ -+} -+ -+void pax_report_insns(void *pc, void *sp) -+{ -+ unsigned long i; -+ -+ printk(KERN_ERR "PAX: bytes at PC: "); -+ for (i = 0; i < 20; i++) { -+ unsigned char c; -+ if (get_user(c, (unsigned char*)pc+i)) { -+ printk("<invalid address>."); -+ break; -+ } -+ printk("%02x ", c); -+ } -+ printk("\n"); -+ -+ printk(KERN_ERR "PAX: bytes at SP: "); -+ for (i = 0; i < 20; i++) { -+ unsigned long c; -+ if (get_user(c, (unsigned long*)sp+i)) { -+ printk("<invalid address>."); -+ break; -+ } -+ printk("%08lx ", c); -+ } -+ printk("\n"); -+} -+#endif -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+/* PaX: called with the page_table_lock spinlock held */ -+static inline pte_t * pax_get_pte(struct mm_struct *mm, unsigned long address) -+{ -+ pgd_t *pgd; -+ pmd_t *pmd; -+ -+ pgd = pgd_offset(mm, address); -+ if (!pgd || !pgd_present(*pgd)) -+ return 0; -+ pmd = pmd_offset(pgd, address); -+ if (!pmd || !pmd_present(*pmd)) -+ return 0; -+ return pte_offset_map(pmd, address); -+} -+ -+/* -+ * PaX: handle the extra page faults or pass it down to the original handler -+ */ -+asmlinkage void pax_do_page_fault(struct pt_regs *regs, unsigned long error_code) -+{ -+ struct mm_struct *mm = current->mm; -+ unsigned long address; -+ pte_t *pte; -+ unsigned char pte_mask; -+ int ret; -+ -+ __asm__("movl %%cr2,%0":"=r" (address)); -+ -+ /* It's safe to allow irq's after cr2 has been saved */ -+ if (regs->eflags & (X86_EFLAGS_IF|VM_MASK)) -+ local_irq_enable(); -+ -+ if (unlikely((error_code & 5) != 5 || -+ address >= TASK_SIZE || -+ !(current->flags & PF_PAX_PAGEEXEC))) -+ return do_page_fault(regs, error_code, address); -+ -+ /* PaX: it's our fault, let's handle it if we can */ -+ -+ /* PaX: take a look at read faults before acquiring any locks */ -+ if (unlikely((error_code == 5) && (regs->eip == address))) { -+ /* instruction fetch attempt from a protected page in user mode */ -+ ret = pax_handle_fetch_fault(regs); -+ switch (ret) { -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ case 3: -+ return; -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ case 2: -+ return; -+#endif -+ -+ case 1: -+ default: -+ pax_report_fault(regs, (void*)regs->eip, (void*)regs->esp); -+ do_exit(SIGKILL); -+ } -+ } -+ -+ pte_mask = _PAGE_ACCESSED | _PAGE_USER | ((error_code & 2) << (_PAGE_BIT_DIRTY-1)); -+ -+ spin_lock(&mm->page_table_lock); -+ pte = pax_get_pte(mm, address); -+ if (unlikely(!pte || !(pte_val(*pte) & _PAGE_PRESENT) || pte_exec(*pte))) { -+ pte_unmap(pte); -+ spin_unlock(&mm->page_table_lock); -+ do_page_fault(regs, error_code, address); -+ return; -+ } -+ -+ if (unlikely((error_code == 7) && !pte_write(*pte))) { -+ /* write attempt to a protected page in user mode */ -+ pte_unmap(pte); -+ spin_unlock(&mm->page_table_lock); -+ do_page_fault(regs, error_code, address); -+ return; -+ } -+ -+ /* -+ * PaX: fill DTLB with user rights and retry -+ */ -+ __asm__ __volatile__ ( -+ "orb %2,%1\n" -+#if defined(CONFIG_M586) || defined(CONFIG_M586TSC) -+/* -+ * PaX: let this uncommented 'invlpg' remind us on the behaviour of Intel's -+ * (and AMD's) TLBs. namely, they do not cache PTEs that would raise *any* -+ * page fault when examined during a TLB load attempt. this is true not only -+ * for PTEs holding a non-present entry but also present entries that will -+ * raise a page fault (such as those set up by PaX, or the copy-on-write -+ * mechanism). in effect it means that we do *not* need to flush the TLBs -+ * for our target pages since their PTEs are simply not in the TLBs at all. -+ -+ * the best thing in omitting it is that we gain around 15-20% speed in the -+ * fast path of the page fault handler and can get rid of tracing since we -+ * can no longer flush unintended entries. -+ */ -+ "invlpg %0\n" -+#endif -+ "testb $0,%0\n" -+ "xorb %3,%1\n" -+ : -+ : "m" (*(char*)address), "m" (*(char*)pte), "q" (pte_mask), "i" (_PAGE_USER) -+ : "memory", "cc"); -+ pte_unmap(pte); -+ spin_unlock(&mm->page_table_lock); -+ return; -+} -+#endif -diff -urN linux-2.6.5/arch/i386/mm/init.c linux-2.6.5/arch/i386/mm/init.c ---- linux-2.6.5/arch/i386/mm/init.c 2004-04-03 22:37:39.000000000 -0500 -+++ linux-2.6.5/arch/i386/mm/init.c 2004-04-18 11:05:50.000000000 -0400 -@@ -40,6 +40,7 @@ - #include <asm/tlb.h> - #include <asm/tlbflush.h> - #include <asm/sections.h> -+#include <asm/desc.h> - - DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); - unsigned long highstart_pfn, highend_pfn; -@@ -394,6 +395,10 @@ - #endif - __flush_tlb_all(); - -+#ifdef CONFIG_PAX_KERNEXEC -+ memcpy(kernexec_pg_dir, swapper_pg_dir, sizeof(kernexec_pg_dir)); -+#endif -+ - kmap_init(); - zone_sizes_init(); - } -@@ -488,7 +493,7 @@ - set_highmem_pages_init(bad_ppro); - - codesize = (unsigned long) &_etext - (unsigned long) &_text; -- datasize = (unsigned long) &_edata - (unsigned long) &_etext; -+ datasize = (unsigned long) &_edata - (unsigned long) &_data; - initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; - - kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); -@@ -587,6 +592,42 @@ - totalram_pages++; - } - printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (__init_end - __init_begin) >> 10); -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ /* PaX: limit KERNEL_CS to actual size */ -+ { -+ unsigned long limit; -+ int cpu; -+ pgd_t *pgd; -+ pmd_t *pmd; -+ -+ limit = (unsigned long)&_etext >> PAGE_SHIFT; -+ for (cpu = 0; cpu < NR_CPUS; cpu++) { -+ cpu_gdt_table[cpu][GDT_ENTRY_KERNEL_CS].a = (cpu_gdt_table[cpu][GDT_ENTRY_KERNEL_CS].a & 0xFFFF0000UL) | (limit & 0x0FFFFUL); -+ cpu_gdt_table[cpu][GDT_ENTRY_KERNEL_CS].b = (cpu_gdt_table[cpu][GDT_ENTRY_KERNEL_CS].b & 0xFFF0FFFFUL) | (limit & 0xF0000UL); -+ -+#ifdef CONFIG_PCI_BIOS -+ printk(KERN_INFO "PAX: warning, PCI BIOS might still be in use, keeping flat KERNEL_CS.\n"); -+#endif -+ -+ } -+ -+ /* PaX: make KERNEL_CS read-only */ -+ for (addr = __KERNEL_TEXT_OFFSET; addr < __KERNEL_TEXT_OFFSET + 0x00400000UL; addr += (1UL << PMD_SHIFT)) { -+ pgd = pgd_offset_k(addr); -+ pmd = pmd_offset(pgd, addr); -+ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_GLOBAL)); -+ } -+ memcpy(kernexec_pg_dir, swapper_pg_dir, sizeof(kernexec_pg_dir)); -+ for (addr = __KERNEL_TEXT_OFFSET; addr < __KERNEL_TEXT_OFFSET + 0x00400000UL; addr += (1UL << PMD_SHIFT)) { -+ pgd = pgd_offset_k(addr); -+ pmd = pmd_offset(pgd, addr); -+ set_pmd(pmd, __pmd(pmd_val(*pmd) & ~_PAGE_RW)); -+ } -+ flush_tlb_all(); -+ } -+#endif -+ - } - - #ifdef CONFIG_BLK_DEV_INITRD -diff -urN linux-2.6.5/arch/i386/pci/pcbios.c linux-2.6.5/arch/i386/pci/pcbios.c ---- linux-2.6.5/arch/i386/pci/pcbios.c 2004-04-03 22:36:17.000000000 -0500 -+++ linux-2.6.5/arch/i386/pci/pcbios.c 2004-04-18 11:05:50.000000000 -0400 -@@ -6,7 +6,7 @@ - #include <linux/init.h> - #include "pci.h" - #include "pci-functions.h" -- -+#include <asm/desc.h> - - /* BIOS32 signature: "_32_" */ - #define BIOS32_SIGNATURE (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24)) -@@ -33,6 +33,12 @@ - * and the PCI BIOS specification. - */ - -+#if defined(CONFIG_PAX_KERNEXEC) && defined(CONFIG_PCI_BIOS) -+#define __FLAT_KERNEL_CS 0x20 -+#else -+#define __FLAT_KERNEL_CS __KERNEL_CS -+#endif -+ - union bios32 { - struct { - unsigned long signature; /* _32_ */ -@@ -55,7 +61,7 @@ - static struct { - unsigned long address; - unsigned short segment; --} bios32_indirect = { 0, __KERNEL_CS }; -+} bios32_indirect = { 0, __FLAT_KERNEL_CS }; - - /* - * Returns the entry point for the given service, NULL on error -@@ -96,7 +102,9 @@ - static struct { - unsigned long address; - unsigned short segment; --} pci_indirect = { 0, __KERNEL_CS }; -+} pci_indirect = { 0, __FLAT_KERNEL_CS }; -+ -+#undef __FLAT_KERNEL_CS - - static int pci_bios_present; - -diff -urN linux-2.6.5/arch/ia64/ia32/binfmt_elf32.c linux-2.6.5/arch/ia64/ia32/binfmt_elf32.c ---- linux-2.6.5/arch/ia64/ia32/binfmt_elf32.c 2004-04-03 22:38:16.000000000 -0500 -+++ linux-2.6.5/arch/ia64/ia32/binfmt_elf32.c 2004-04-18 11:05:50.000000000 -0400 -@@ -41,6 +41,17 @@ - #undef SET_PERSONALITY - #define SET_PERSONALITY(ex, ibcs2) elf32_set_personality() - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL) -+ -+#define PAX_DELTA_MMAP_LSB(tsk) IA32_PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 43 - IA32_PAGE_SHIFT) -+#define PAX_DELTA_EXEC_LSB(tsk) IA32_PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 43 - IA32_PAGE_SHIFT) -+#define PAX_DELTA_STACK_LSB(tsk) IA32_PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 43 - IA32_PAGE_SHIFT) -+#endif -+ - /* Ugly but avoids duplication */ - #include "../../../fs/binfmt_elf.c" - -@@ -178,7 +189,7 @@ - mpnt->vm_mm = current->mm; - mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; - mpnt->vm_end = IA32_STACK_TOP; -- mpnt->vm_page_prot = PAGE_COPY; -+ mpnt->vm_page_prot = protection_map[VM_STACK_FLAGS & 0x7]; - mpnt->vm_flags = VM_STACK_FLAGS; - mpnt->vm_ops = NULL; - mpnt->vm_pgoff = 0; -diff -urN linux-2.6.5/arch/ia64/ia32/ia32priv.h linux-2.6.5/arch/ia64/ia32/ia32priv.h ---- linux-2.6.5/arch/ia64/ia32/ia32priv.h 2004-04-03 22:38:22.000000000 -0500 -+++ linux-2.6.5/arch/ia64/ia32/ia32priv.h 2004-04-18 11:05:50.000000000 -0400 -@@ -295,7 +295,14 @@ - #define ELF_ARCH EM_386 - - #define IA32_PAGE_OFFSET 0xc0000000 --#define IA32_STACK_TOP IA32_PAGE_OFFSET -+ -+#ifdef CONFIG_PAX_RANDUSTACK -+#define __IA32_DELTA_STACK (current->mm->delta_stack) -+#else -+#define __IA32_DELTA_STACK 0UL -+#endif -+ -+#define IA32_STACK_TOP (IA32_PAGE_OFFSET - __IA32_DELTA_STACK) - - /* - * The system segments (GDT, TSS, LDT) have to be mapped below 4GB so the IA-32 engine can -diff -urN linux-2.6.5/arch/ia64/ia32/sys_ia32.c linux-2.6.5/arch/ia64/ia32/sys_ia32.c ---- linux-2.6.5/arch/ia64/ia32/sys_ia32.c 2004-04-03 22:37:24.000000000 -0500 -+++ linux-2.6.5/arch/ia64/ia32/sys_ia32.c 2004-04-18 11:05:50.000000000 -0400 -@@ -475,6 +475,11 @@ - - flags = a.flags; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(a.fd); -@@ -496,6 +501,11 @@ - struct file *file = NULL; - unsigned long retval; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); -diff -urN linux-2.6.5/arch/ia64/kernel/ptrace.c linux-2.6.5/arch/ia64/kernel/ptrace.c ---- linux-2.6.5/arch/ia64/kernel/ptrace.c 2004-04-03 22:38:22.000000000 -0500 -+++ linux-2.6.5/arch/ia64/kernel/ptrace.c 2004-04-18 11:05:50.000000000 -0400 -@@ -17,6 +17,7 @@ - #include <linux/smp_lock.h> - #include <linux/user.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - - #include <asm/pgtable.h> - #include <asm/processor.h> -@@ -1314,6 +1315,9 @@ - if (pid == 1) /* no messing around with init! */ - goto out_tsk; - -+ if (gr_handle_ptrace(child, request)) -+ goto out_tsk; -+ - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; -diff -urN linux-2.6.5/arch/ia64/kernel/sys_ia64.c linux-2.6.5/arch/ia64/kernel/sys_ia64.c ---- linux-2.6.5/arch/ia64/kernel/sys_ia64.c 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/arch/ia64/kernel/sys_ia64.c 2004-04-18 11:05:50.000000000 -0400 -@@ -18,6 +18,7 @@ - #include <linux/syscalls.h> - #include <linux/highuid.h> - #include <linux/hugetlb.h> -+#include <linux/grsecurity.h> - - #include <asm/shmparam.h> - #include <asm/uaccess.h> -@@ -38,6 +39,13 @@ - if (REGION_NUMBER(addr) == REGION_HPAGE) - addr = 0; - #endif -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if ((current->flags & PF_PAX_RANDMMAP) && addr && filp) -+ addr = mm->free_area_cache; -+ else -+#endif -+ - if (!addr) - addr = mm->free_area_cache; - -@@ -58,6 +66,13 @@ - if (TASK_SIZE - len < addr || RGN_MAP_LIMIT - len < REGION_OFFSET(addr)) { - if (start_addr != TASK_UNMAPPED_BASE) { - /* Start a new search --- just in case we missed some holes. */ -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if (current->flags & PF_PAX_RANDMMAP) -+ addr = TASK_UNMAPPED_BASE + mm->delta_mmap; -+ else -+#endif -+ - addr = TASK_UNMAPPED_BASE; - goto full_search; - } -@@ -185,6 +200,11 @@ - unsigned long roff; - struct file *file = 0; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); -@@ -216,6 +236,11 @@ - goto out; - } - -+ if (gr_handle_mmap(file, prot)) { -+ addr = -EACCES; -+ goto out; -+ } -+ - down_write(¤t->mm->mmap_sem); - addr = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); -diff -urN linux-2.6.5/arch/ia64/mm/fault.c linux-2.6.5/arch/ia64/mm/fault.c ---- linux-2.6.5/arch/ia64/mm/fault.c 2004-04-03 22:38:20.000000000 -0500 -+++ linux-2.6.5/arch/ia64/mm/fault.c 2004-04-18 11:05:50.000000000 -0400 -@@ -9,6 +9,7 @@ - #include <linux/mm.h> - #include <linux/smp_lock.h> - #include <linux/interrupt.h> -+#include <linux/binfmts.h> - - #include <asm/pgtable.h> - #include <asm/processor.h> -@@ -70,6 +71,54 @@ - return pte_present(pte); - } - -+#ifdef CONFIG_PAX_PAGEEXEC -+/* -+ * PaX: decide what to do with offenders (regs->cr_iip = fault address) -+ * -+ * returns 1 when task should be killed -+ * 2 when legitimate ET_EXEC was detected -+ */ -+static int pax_handle_fetch_fault(struct pt_regs *regs) -+{ -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ int err; -+ -+ if (current->flags & PF_PAX_RANDEXEC) { -+ if (regs->cr_iip >= current->mm->start_code && -+ regs->cr_iip < current->mm->end_code) -+ { -+#if 0 -+ /* PaX: this needs fixing */ -+ if (regs->b0 == regs->cr_iip) -+ return 1; -+#endif -+ regs->cr_iip += current->mm->delta_exec; -+ return 2; -+ } -+ } -+#endif -+ -+ return 1; -+} -+ -+void pax_report_insns(void *pc, void *sp) -+{ -+ unsigned long i; -+ -+ printk(KERN_ERR "PAX: bytes at PC: "); -+ for (i = 0; i < 8; i++) { -+ unsigned int c; -+ if (get_user(c, (unsigned int*)pc+i)) { -+ printk("<invalid address>."); -+ break; -+ } -+ printk("%08x ", c); -+ } -+ printk("\n"); -+} -+#endif -+ - void - ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *regs) - { -@@ -125,9 +174,31 @@ - | (((isr >> IA64_ISR_W_BIT) & 1UL) << VM_WRITE_BIT) - | (((isr >> IA64_ISR_R_BIT) & 1UL) << VM_READ_BIT)); - -- if ((vma->vm_flags & mask) != mask) -+ if ((vma->vm_flags & mask) != mask) { -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (!(vma->vm_flags & VM_EXEC) && (mask & VM_EXEC)) { -+ if (!(current->flags & PF_PAX_PAGEEXEC) || address != regs->cr_iip) -+ goto bad_area; -+ -+ up_read(&mm->mmap_sem); -+ switch(pax_handle_fetch_fault(regs)) { -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ case 2: -+ return; -+#endif -+ -+ } -+ pax_report_fault(regs, (void*)regs->cr_iip, (void*)regs->r12); -+ do_exit(SIGKILL); -+ } -+#endif -+ - goto bad_area; - -+ } -+ - survive: - /* - * If for any reason at all we couldn't handle the fault, make -diff -urN linux-2.6.5/arch/mips/kernel/binfmt_elfn32.c linux-2.6.5/arch/mips/kernel/binfmt_elfn32.c ---- linux-2.6.5/arch/mips/kernel/binfmt_elfn32.c 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/arch/mips/kernel/binfmt_elfn32.c 2004-04-18 11:05:50.000000000 -0400 -@@ -50,6 +50,17 @@ - #undef ELF_ET_DYN_BASE - #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) -+#endif -+ - #include <asm/processor.h> - #include <linux/module.h> - #include <linux/config.h> -diff -urN linux-2.6.5/arch/mips/kernel/binfmt_elfo32.c linux-2.6.5/arch/mips/kernel/binfmt_elfo32.c ---- linux-2.6.5/arch/mips/kernel/binfmt_elfo32.c 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/arch/mips/kernel/binfmt_elfo32.c 2004-04-18 11:05:50.000000000 -0400 -@@ -52,6 +52,17 @@ - #undef ELF_ET_DYN_BASE - #define ELF_ET_DYN_BASE (TASK32_SIZE / 3 * 2) - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) -+#endif -+ - #include <asm/processor.h> - #include <linux/module.h> - #include <linux/config.h> -diff -urN linux-2.6.5/arch/mips/kernel/syscall.c linux-2.6.5/arch/mips/kernel/syscall.c ---- linux-2.6.5/arch/mips/kernel/syscall.c 2004-04-03 22:37:41.000000000 -0500 -+++ linux-2.6.5/arch/mips/kernel/syscall.c 2004-04-18 11:05:50.000000000 -0400 -@@ -79,6 +79,11 @@ - do_color_align = 0; - if (filp || (flags & MAP_SHARED)) - do_color_align = 1; -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if (!(current->flags & PF_PAX_RANDMMAP) || !filp) -+#endif -+ - if (addr) { - if (do_color_align) - addr = COLOUR_ALIGN(addr, pgoff); -@@ -89,6 +94,13 @@ - (!vmm || addr + len <= vmm->vm_start)) - return addr; - } -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if ((current->flags & PF_PAX_RANDMMAP) && (!addr || filp)) -+ addr = TASK_UNMAPPED_BASE + current->mm->delta_mmap; -+ else -+#endif -+ - addr = TASK_UNMAPPED_BASE; - if (do_color_align) - addr = COLOUR_ALIGN(addr, pgoff); -diff -urN linux-2.6.5/arch/mips/mm/fault.c linux-2.6.5/arch/mips/mm/fault.c ---- linux-2.6.5/arch/mips/mm/fault.c 2004-04-03 22:36:53.000000000 -0500 -+++ linux-2.6.5/arch/mips/mm/fault.c 2004-04-18 11:05:50.000000000 -0400 -@@ -28,6 +28,24 @@ - #include <asm/uaccess.h> - #include <asm/ptrace.h> - -+#ifdef CONFIG_PAX_PAGEEXEC -+void pax_report_insns(void *pc) -+{ -+ unsigned long i; -+ -+ printk(KERN_ERR "PAX: bytes at PC: "); -+ for (i = 0; i < 5; i++) { -+ unsigned int c; -+ if (get_user(c, (unsigned int*)pc+i)) { -+ printk("<invalid address>."); -+ break; -+ } -+ printk("%08x ", c); -+ } -+ printk("\n"); -+} -+#endif -+ - /* - * This routine handles page faults. It determines the address, - * and the problem, and then passes it off to one of the appropriate -diff -urN linux-2.6.5/arch/parisc/kernel/ptrace.c linux-2.6.5/arch/parisc/kernel/ptrace.c ---- linux-2.6.5/arch/parisc/kernel/ptrace.c 2004-04-03 22:36:19.000000000 -0500 -+++ linux-2.6.5/arch/parisc/kernel/ptrace.c 2004-04-18 11:05:50.000000000 -0400 -@@ -17,6 +17,7 @@ - #include <linux/personality.h> - #include <linux/security.h> - #include <linux/compat.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/pgtable.h> -@@ -114,6 +115,9 @@ - if (pid == 1) /* no messing around with init! */ - goto out_tsk; - -+ if (gr_handle_ptrace(child, request)) -+ goto out_tsk; -+ - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; -diff -urN linux-2.6.5/arch/parisc/kernel/sys_parisc.c linux-2.6.5/arch/parisc/kernel/sys_parisc.c ---- linux-2.6.5/arch/parisc/kernel/sys_parisc.c 2004-04-03 22:38:12.000000000 -0500 -+++ linux-2.6.5/arch/parisc/kernel/sys_parisc.c 2004-04-18 11:05:50.000000000 -0400 -@@ -31,6 +31,7 @@ - #include <linux/shm.h> - #include <linux/smp_lock.h> - #include <linux/syscalls.h> -+#include <linux/grsecurity.h> - - int sys_pipe(int *fildes) - { -@@ -114,6 +115,13 @@ - { - if (len > TASK_SIZE) - return -ENOMEM; -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if ((current->flags & PF_PAX_RANDMMAP) && (!addr || filp)) -+ addr = TASK_UNMAPPED_BASE + current->mm->delta_mmap; -+ else -+#endif -+ - if (!addr) - addr = TASK_UNMAPPED_BASE; - -@@ -131,12 +139,23 @@ - { - struct file * file = NULL; - unsigned long error = -EBADF; -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - -+ if (gr_handle_mmap(file, prot)) { -+ fput(file); -+ return -EACCES; -+ } -+ - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); -diff -urN linux-2.6.5/arch/parisc/kernel/sys_parisc32.c linux-2.6.5/arch/parisc/kernel/sys_parisc32.c ---- linux-2.6.5/arch/parisc/kernel/sys_parisc32.c 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/arch/parisc/kernel/sys_parisc32.c 2004-04-18 11:05:50.000000000 -0400 -@@ -48,6 +48,8 @@ - #include <linux/ptrace.h> - #include <linux/swap.h> - #include <linux/syscalls.h> -+#include <linux/random.h> -+#include <linux/grsecurity.h> - - #include <asm/types.h> - #include <asm/uaccess.h> -@@ -171,6 +173,11 @@ - struct file *file; - int retval; - int i; -+#ifdef CONFIG_GRKERNSEC -+ struct file *old_exec_file; -+ struct acl_subject_label *old_acl; -+ struct rlimit old_rlim[RLIM_NLIMITS]; -+#endif - - file = open_exec(filename); - -@@ -178,7 +185,26 @@ - if (IS_ERR(file)) - return retval; - -+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes, 1); -+ -+ if (gr_handle_nproc()) { -+ allow_write_access(file); -+ fput(file); -+ return -EAGAIN; -+ } -+ -+ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) { -+ allow_write_access(file); -+ fput(file); -+ return -EACCES; -+ } -+ - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); -+ -+#ifdef CONFIG_PAX_RANDUSTACK -+ bprm.p -= (pax_get_random_long() & ~(sizeof(void *)-1)) & ~PAGE_MASK; -+#endif -+ - memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); - - DBG(("do_execve32(%s, %p, %p, %p)\n", filename, argv, envp, regs)); -@@ -209,11 +235,24 @@ - if (retval < 0) - goto out; - -+ if (!gr_tpe_allow(file)) { -+ retval = -EACCES; -+ goto out; -+ } -+ -+ if (gr_check_crash_exec(file)) { -+ retval = -EACCES; -+ goto out; -+ } -+ - retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; - - bprm.exec = bprm.p; -+ -+ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt); -+ - retval = copy_strings32(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; -@@ -222,10 +261,32 @@ - if (retval < 0) - goto out; - -+#ifdef CONFIG_GRKERNSEC -+ old_acl = current->acl; -+ memcpy(old_rlim, current->rlim, sizeof(old_rlim)); -+ old_exec_file = current->exec_file; -+ get_file(file); -+ current->exec_file = file; -+#endif -+ -+ gr_set_proc_label(file->f_dentry, file->f_vfsmnt); -+ - retval = search_binary_handler(&bprm,regs); -- if (retval >= 0) -+ if (retval >= 0) { -+#ifdef CONFIG_GRKERNSEC -+ if (old_exec_file) -+ fput(old_exec_file); -+#endif - /* execve success */ - return retval; -+ } -+ -+#ifdef CONFIG_GRKERNSEC -+ current->acl = old_acl; -+ memcpy(current->rlim, old_rlim, sizeof(old_rlim)); -+ fput(current->exec_file); -+ current->exec_file = old_exec_file; -+#endif - - out: - /* Something went wrong, return the inode and free the argument pages*/ -diff -urN linux-2.6.5/arch/parisc/kernel/traps.c linux-2.6.5/arch/parisc/kernel/traps.c ---- linux-2.6.5/arch/parisc/kernel/traps.c 2004-04-03 22:38:27.000000000 -0500 -+++ linux-2.6.5/arch/parisc/kernel/traps.c 2004-04-18 11:05:50.000000000 -0400 -@@ -661,9 +661,7 @@ - - down_read(¤t->mm->mmap_sem); - vma = find_vma(current->mm,regs->iaoq[0]); -- if (vma && (regs->iaoq[0] >= vma->vm_start) -- && (vma->vm_flags & VM_EXEC)) { -- -+ if (vma && (regs->iaoq[0] >= vma->vm_start)) { - fault_address = regs->iaoq[0]; - fault_space = regs->iasq[0]; - -diff -urN linux-2.6.5/arch/parisc/mm/fault.c linux-2.6.5/arch/parisc/mm/fault.c ---- linux-2.6.5/arch/parisc/mm/fault.c 2004-04-03 22:38:13.000000000 -0500 -+++ linux-2.6.5/arch/parisc/mm/fault.c 2004-04-18 11:05:50.000000000 -0400 -@@ -16,6 +16,8 @@ - #include <linux/sched.h> - #include <linux/interrupt.h> - #include <linux/module.h> -+#include <linux/unistd.h> -+#include <linux/binfmts.h> - - #include <asm/uaccess.h> - #include <asm/traps.h> -@@ -54,7 +56,7 @@ - static unsigned long - parisc_acctyp(unsigned long code, unsigned int inst) - { -- if (code == 6 || code == 16) -+ if (code == 6 || code == 7 || code == 16) - return VM_EXEC; - - switch (inst & 0xf0000000) { -@@ -140,6 +142,139 @@ - } - #endif - -+#ifdef CONFIG_PAX_PAGEEXEC -+/* -+ * PaX: decide what to do with offenders (instruction_pointer(regs) = fault address) -+ * -+ * returns 1 when task should be killed -+ * 2 when rt_sigreturn trampoline was detected -+ * 3 when unpatched PLT trampoline was detected -+ * 4 when legitimate ET_EXEC was detected -+ */ -+static int pax_handle_fetch_fault(struct pt_regs *regs) -+{ -+ -+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUTRAMP) -+ int err; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ if (current->flags & PF_PAX_RANDEXEC) { -+ if (instruction_pointer(regs) >= current->mm->start_code && -+ instruction_pointer(regs) < current->mm->end_code) -+ { -+#if 0 -+ /* PaX: this needs fixing */ -+ if ((regs->gr[2] & ~3UL) == instruction_pointer(regs)) -+ return 1; -+#endif -+ regs->iaoq[0] += current->mm->delta_exec; -+ if ((regs->iaoq[1] & ~3UL) >= current->mm->start_code && -+ (regs->iaoq[1] & ~3UL) < current->mm->end_code) -+ regs->iaoq[1] += current->mm->delta_exec; -+ return 4; -+ } -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUPLT -+ do { /* PaX: unpatched PLT emulation */ -+ unsigned int bl, depwi; -+ -+ err = get_user(bl, (unsigned int*)instruction_pointer(regs)); -+ err |= get_user(depwi, (unsigned int*)(instruction_pointer(regs)+4)); -+ -+ if (err) -+ break; -+ -+ if (bl == 0xEA9F1FDDU && depwi == 0xD6801C1EU) { -+ unsigned int ldw, bv, ldw2, addr = instruction_pointer(regs)-12; -+ -+ err = get_user(ldw, (unsigned int*)addr); -+ err |= get_user(bv, (unsigned int*)(addr+4)); -+ err |= get_user(ldw2, (unsigned int*)(addr+8)); -+ -+ if (err) -+ break; -+ -+ if (ldw == 0x0E801096U && -+ bv == 0xEAC0C000U && -+ ldw2 == 0x0E881095U) -+ { -+ unsigned int resolver, map; -+ -+ err = get_user(resolver, (unsigned int*)(instruction_pointer(regs)+8)); -+ err |= get_user(map, (unsigned int*)(instruction_pointer(regs)+12)); -+ if (err) -+ break; -+ -+ regs->gr[20] = instruction_pointer(regs)+8; -+ regs->gr[21] = map; -+ regs->gr[22] = resolver; -+ regs->iaoq[0] = resolver | 3UL; -+ regs->iaoq[1] = regs->iaoq[0] + 4; -+ return 3; -+ } -+ } -+ } while (0); -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ -+#ifndef CONFIG_PAX_EMUSIGRT -+ if (!(current->flags & PF_PAX_EMUTRAMP)) -+ return 1; -+#endif -+ -+ do { /* PaX: rt_sigreturn emulation */ -+ unsigned int ldi1, ldi2, bel, nop; -+ -+ err = get_user(ldi1, (unsigned int *)instruction_pointer(regs)); -+ err |= get_user(ldi2, (unsigned int *)(instruction_pointer(regs)+4)); -+ err |= get_user(bel, (unsigned int *)(instruction_pointer(regs)+8)); -+ err |= get_user(nop, (unsigned int *)(instruction_pointer(regs)+12)); -+ -+ if (err) -+ break; -+ -+ if ((ldi1 == 0x34190000U || ldi1 == 0x34190002U) && -+ ldi2 == 0x3414015AU && -+ bel == 0xE4008200U && -+ nop == 0x08000240U) -+ { -+ regs->gr[25] = (ldi1 & 2) >> 1; -+ regs->gr[20] = __NR_rt_sigreturn; -+ regs->gr[31] = regs->iaoq[1] + 16; -+ regs->sr[0] = regs->iasq[1]; -+ regs->iaoq[0] = 0x100UL; -+ regs->iaoq[1] = regs->iaoq[0] + 4; -+ regs->iasq[0] = regs->sr[2]; -+ regs->iasq[1] = regs->sr[2]; -+ return 2; -+ } -+ } while (0); -+#endif -+ -+ return 1; -+} -+ -+void pax_report_insns(void *pc, void *sp) -+{ -+ unsigned long i; -+ -+ printk(KERN_ERR "PAX: bytes at PC: "); -+ for (i = 0; i < 5; i++) { -+ unsigned int c; -+ if (get_user(c, (unsigned int*)pc+i)) { -+ printk("<invalid address>."); -+ break; -+ } -+ printk("%08x ", c); -+ } -+ printk("\n"); -+} -+#endif -+ - void do_page_fault(struct pt_regs *regs, unsigned long code, - unsigned long address) - { -@@ -165,8 +300,38 @@ - - acc_type = parisc_acctyp(code,regs->iir); - -- if ((vma->vm_flags & acc_type) != acc_type) -+ if ((vma->vm_flags & acc_type) != acc_type) { -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if ((current->flags & PF_PAX_PAGEEXEC) && (acc_type & VM_EXEC) && -+ (address & ~3UL) == instruction_pointer(regs)) -+ { -+ up_read(&mm->mmap_sem); -+ switch(pax_handle_fetch_fault(regs)) { -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ case 4: -+ return; -+#endif -+ -+#ifdef CONFIG_PAX_EMUPLT -+ case 3: -+ return; -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ case 2: -+ return; -+#endif -+ -+ } -+ pax_report_fault(regs, (void*)instruction_pointer(regs), (void*)regs->gr[30]); -+ do_exit(SIGKILL); -+ } -+#endif -+ - goto bad_area; -+ } - - /* - * If for any reason at all we couldn't handle the fault, make -diff -urN linux-2.6.5/arch/ppc/kernel/ptrace.c linux-2.6.5/arch/ppc/kernel/ptrace.c ---- linux-2.6.5/arch/ppc/kernel/ptrace.c 2004-04-03 22:36:52.000000000 -0500 -+++ linux-2.6.5/arch/ppc/kernel/ptrace.c 2004-04-18 11:05:50.000000000 -0400 -@@ -26,6 +26,7 @@ - #include <linux/ptrace.h> - #include <linux/user.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/page.h> -@@ -202,6 +203,9 @@ - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - -+ if (gr_handle_ptrace(child, request)) -+ goto out_tsk; -+ - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; -diff -urN linux-2.6.5/arch/ppc/kernel/syscalls.c linux-2.6.5/arch/ppc/kernel/syscalls.c ---- linux-2.6.5/arch/ppc/kernel/syscalls.c 2004-04-03 22:38:18.000000000 -0500 -+++ linux-2.6.5/arch/ppc/kernel/syscalls.c 2004-04-18 11:05:50.000000000 -0400 -@@ -36,6 +36,7 @@ - #include <linux/utsname.h> - #include <linux/file.h> - #include <linux/unistd.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/ipc.h> -@@ -165,14 +166,25 @@ - struct file * file = NULL; - int ret = -EBADF; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - if (!(file = fget(fd))) - goto out; - } - -+ if (gr_handle_mmap(file, prot)) { -+ fput(file); -+ ret = -EACCES; -+ goto out; -+ } -+ - down_write(¤t->mm->mmap_sem); -- ret = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); -+ ret = do_mmap(file, addr, len, prot, flags, pgoff << PAGE_SHIFT); - up_write(¤t->mm->mmap_sem); - if (file) - fput(file); -diff -urN linux-2.6.5/arch/ppc/mm/fault.c linux-2.6.5/arch/ppc/mm/fault.c ---- linux-2.6.5/arch/ppc/mm/fault.c 2004-04-03 22:36:54.000000000 -0500 -+++ linux-2.6.5/arch/ppc/mm/fault.c 2004-04-18 11:05:50.000000000 -0400 -@@ -28,6 +28,11 @@ - #include <linux/interrupt.h> - #include <linux/highmem.h> - #include <linux/module.h> -+#include <linux/slab.h> -+#include <linux/pagemap.h> -+#include <linux/compiler.h> -+#include <linux/binfmts.h> -+#include <linux/unistd.h> - - #include <asm/page.h> - #include <asm/pgtable.h> -@@ -56,6 +61,366 @@ - void do_page_fault(struct pt_regs *, unsigned long, unsigned long); - extern int get_pteptr(struct mm_struct *mm, unsigned long addr, pte_t **ptep); - -+#ifdef CONFIG_PAX_EMUSIGRT -+void pax_syscall_close(struct vm_area_struct * vma) -+{ -+ vma->vm_mm->call_syscall = 0UL; -+} -+ -+static struct page* pax_syscall_nopage(struct vm_area_struct *vma, unsigned long address, int *type) -+{ -+ struct page* page; -+ unsigned int *kaddr; -+ -+ page = alloc_page(GFP_HIGHUSER); -+ if (!page) -+ return NOPAGE_OOM; -+ -+ kaddr = kmap(page); -+ memset(kaddr, 0, PAGE_SIZE); -+ kaddr[0] = 0x44000002U; /* sc */ -+ __flush_dcache_icache(kaddr); -+ kunmap(page); -+ if (type) -+ *type = VM_FAULT_MAJOR; -+ return page; -+} -+ -+static struct vm_operations_struct pax_vm_ops = { -+ close: pax_syscall_close, -+ nopage: pax_syscall_nopage, -+}; -+ -+static void pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) -+{ -+ vma->vm_mm = current->mm; -+ vma->vm_start = addr; -+ vma->vm_end = addr + PAGE_SIZE; -+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC; -+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f]; -+ vma->vm_ops = &pax_vm_ops; -+ vma->vm_pgoff = 0UL; -+ vma->vm_file = NULL; -+ vma->vm_private_data = NULL; -+ INIT_LIST_HEAD(&vma->shared); -+ insert_vm_struct(current->mm, vma); -+ ++current->mm->total_vm; -+} -+#endif -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+/* -+ * PaX: decide what to do with offenders (regs->nip = fault address) -+ * -+ * returns 1 when task should be killed -+ * 2 when patched GOT trampoline was detected -+ * 3 when patched PLT trampoline was detected -+ * 4 when unpatched PLT trampoline was detected -+ * 5 when legitimate ET_EXEC was detected -+ * 6 when sigreturn trampoline was detected -+ * 7 when rt_sigreturn trampoline was detected -+ */ -+static int pax_handle_fetch_fault(struct pt_regs *regs) -+{ -+ -+#if defined(CONFIG_PAX_EMUPLT) || defined(CONFIG_PAX_EMUSIGRT) -+ int err; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ if (current->flags & PF_PAX_RANDEXEC) { -+ if (regs->nip >= current->mm->start_code && -+ regs->nip < current->mm->end_code) -+ { -+ if (regs->link == regs->nip) -+ return 1; -+ -+ regs->nip += current->mm->delta_exec; -+ return 5; -+ } -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUPLT -+ do { /* PaX: patched GOT emulation */ -+ unsigned int blrl; -+ -+ err = get_user(blrl, (unsigned int*)regs->nip); -+ -+ if (!err && blrl == 0x4E800021U) { -+ unsigned long temp = regs->nip; -+ -+ regs->nip = regs->link & 0xFFFFFFFCUL; -+ regs->link = temp + 4UL; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: patched PLT emulation #1 */ -+ unsigned int b; -+ -+ err = get_user(b, (unsigned int *)regs->nip); -+ -+ if (!err && (b & 0xFC000003U) == 0x48000000U) { -+ regs->nip += (((b | 0xFC000000UL) ^ 0x02000000UL) + 0x02000000UL); -+ return 3; -+ } -+ } while (0); -+ -+ do { /* PaX: unpatched PLT emulation #1 */ -+ unsigned int li, b; -+ -+ err = get_user(li, (unsigned int *)regs->nip); -+ err |= get_user(b, (unsigned int *)(regs->nip+4)); -+ -+ if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) { -+ unsigned int rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr; -+ unsigned long addr = b | 0xFC000000UL; -+ -+ addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL); -+ err = get_user(rlwinm, (unsigned int*)addr); -+ err |= get_user(add, (unsigned int*)(addr+4)); -+ err |= get_user(li2, (unsigned int*)(addr+8)); -+ err |= get_user(addis2, (unsigned int*)(addr+12)); -+ err |= get_user(mtctr, (unsigned int*)(addr+16)); -+ err |= get_user(li3, (unsigned int*)(addr+20)); -+ err |= get_user(addis3, (unsigned int*)(addr+24)); -+ err |= get_user(bctr, (unsigned int*)(addr+28)); -+ -+ if (err) -+ break; -+ -+ if (rlwinm == 0x556C083CU && -+ add == 0x7D6C5A14U && -+ (li2 & 0xFFFF0000U) == 0x39800000U && -+ (addis2 & 0xFFFF0000U) == 0x3D8C0000U && -+ mtctr == 0x7D8903A6U && -+ (li3 & 0xFFFF0000U) == 0x39800000U && -+ (addis3 & 0xFFFF0000U) == 0x3D8C0000U && -+ bctr == 0x4E800420U) -+ { -+ regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); -+ regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); -+ regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16; -+ regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); -+ regs->ctr += (addis2 & 0xFFFFU) << 16; -+ regs->nip = regs->ctr; -+ return 4; -+ } -+ } -+ } while (0); -+ -+#if 0 -+ do { /* PaX: unpatched PLT emulation #2 */ -+ unsigned int lis, lwzu, b, bctr; -+ -+ err = get_user(lis, (unsigned int *)regs->nip); -+ err |= get_user(lwzu, (unsigned int *)(regs->nip+4)); -+ err |= get_user(b, (unsigned int *)(regs->nip+8)); -+ err |= get_user(bctr, (unsigned int *)(regs->nip+12)); -+ -+ if (err) -+ break; -+ -+ if ((lis & 0xFFFF0000U) == 0x39600000U && -+ (lwzu & 0xU) == 0xU && -+ (b & 0xFC000003U) == 0x48000000U && -+ bctr == 0x4E800420U) -+ { -+ unsigned int addis, addi, rlwinm, add, li2, addis2, mtctr, li3, addis3, bctr; -+ unsigned long addr = b | 0xFC000000UL; -+ -+ addr = regs->nip + 12 + ((addr ^ 0x02000000UL) + 0x02000000UL); -+ err = get_user(addis, (unsigned int*)addr); -+ err |= get_user(addi, (unsigned int*)(addr+4)); -+ err |= get_user(rlwinm, (unsigned int*)(addr+8)); -+ err |= get_user(add, (unsigned int*)(addr+12)); -+ err |= get_user(li2, (unsigned int*)(addr+16)); -+ err |= get_user(addis2, (unsigned int*)(addr+20)); -+ err |= get_user(mtctr, (unsigned int*)(addr+24)); -+ err |= get_user(li3, (unsigned int*)(addr+28)); -+ err |= get_user(addis3, (unsigned int*)(addr+32)); -+ err |= get_user(bctr, (unsigned int*)(addr+36)); -+ -+ if (err) -+ break; -+ -+ if ((addis & 0xFFFF0000U) == 0x3D6B0000U && -+ (addi & 0xFFFF0000U) == 0x396B0000U && -+ rlwinm == 0x556C083CU && -+ add == 0x7D6C5A14U && -+ (li2 & 0xFFFF0000U) == 0x39800000U && -+ (addis2 & 0xFFFF0000U) == 0x3D8C0000U && -+ mtctr == 0x7D8903A6U && -+ (li3 & 0xFFFF0000U) == 0x39800000U && -+ (addis3 & 0xFFFF0000U) == 0x3D8C0000U && -+ bctr == 0x4E800420U) -+ { -+ regs->gpr[PT_R11] = -+ regs->gpr[PT_R11] = 3 * (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); -+ regs->gpr[PT_R12] = (((li3 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); -+ regs->gpr[PT_R12] += (addis3 & 0xFFFFU) << 16; -+ regs->ctr = (((li2 | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); -+ regs->ctr += (addis2 & 0xFFFFU) << 16; -+ regs->nip = regs->ctr; -+ return 4; -+ } -+ } -+ } while (0); -+#endif -+ -+ do { /* PaX: unpatched PLT emulation #3 */ -+ unsigned int li, b; -+ -+ err = get_user(li, (unsigned int *)regs->nip); -+ err |= get_user(b, (unsigned int *)(regs->nip+4)); -+ -+ if (!err && (li & 0xFFFF0000U) == 0x39600000U && (b & 0xFC000003U) == 0x48000000U) { -+ unsigned int addis, lwz, mtctr, bctr; -+ unsigned long addr = b | 0xFC000000UL; -+ -+ addr = regs->nip + 4 + ((addr ^ 0x02000000UL) + 0x02000000UL); -+ err = get_user(addis, (unsigned int*)addr); -+ err |= get_user(lwz, (unsigned int*)(addr+4)); -+ err |= get_user(mtctr, (unsigned int*)(addr+8)); -+ err |= get_user(bctr, (unsigned int*)(addr+12)); -+ -+ if (err) -+ break; -+ -+ if ((addis & 0xFFFF0000U) == 0x3D6B0000U && -+ (lwz & 0xFFFF0000U) == 0x816B0000U && -+ mtctr == 0x7D6903A6U && -+ bctr == 0x4E800420U) -+ { -+ unsigned int r11; -+ -+ addr = (addis << 16) + (((li | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); -+ addr += (((lwz | 0xFFFF0000UL) ^ 0x00008000UL) + 0x00008000UL); -+ -+ err = get_user(r11, (unsigned int*)addr); -+ if (err) -+ break; -+ -+ regs->gpr[PT_R11] = r11; -+ regs->ctr = r11; -+ regs->nip = r11; -+ return 4; -+ } -+ } -+ } while (0); -+#endif -+ -+#ifdef CONFIG_PAX_EMUSIGRT -+ do { /* PaX: sigreturn emulation */ -+ unsigned int li, sc; -+ -+ err = get_user(li, (unsigned int *)regs->nip); -+ err |= get_user(sc, (unsigned int *)(regs->nip+4)); -+ -+ if (!err && li == 0x38000000U + __NR_sigreturn && sc == 0x44000002U) { -+ struct vm_area_struct *vma; -+ unsigned long call_syscall; -+ -+ down_read(¤t->mm->mmap_sem); -+ call_syscall = current->mm->call_syscall; -+ up_read(¤t->mm->mmap_sem); -+ if (likely(call_syscall)) -+ goto emulate; -+ -+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); -+ -+ down_write(¤t->mm->mmap_sem); -+ if (current->mm->call_syscall) { -+ call_syscall = current->mm->call_syscall; -+ up_write(¤t->mm->mmap_sem); -+ if (vma) kmem_cache_free(vm_area_cachep, vma); -+ goto emulate; -+ } -+ -+ call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE); -+ if (!vma || (call_syscall & ~PAGE_MASK)) { -+ up_write(¤t->mm->mmap_sem); -+ if (vma) kmem_cache_free(vm_area_cachep, vma); -+ return 1; -+ } -+ -+ pax_insert_vma(vma, call_syscall); -+ current->mm->call_syscall = call_syscall; -+ up_write(¤t->mm->mmap_sem); -+ -+emulate: -+ regs->gpr[PT_R0] = __NR_sigreturn; -+ regs->nip = call_syscall; -+ return 6; -+ } -+ } while (0); -+ -+ do { /* PaX: rt_sigreturn emulation */ -+ unsigned int li, sc; -+ -+ err = get_user(li, (unsigned int *)regs->nip); -+ err |= get_user(sc, (unsigned int *)(regs->nip+4)); -+ -+ if (!err && li == 0x38000000U + __NR_rt_sigreturn && sc == 0x44000002U) { -+ struct vm_area_struct *vma; -+ unsigned int call_syscall; -+ -+ down_read(¤t->mm->mmap_sem); -+ call_syscall = current->mm->call_syscall; -+ up_read(¤t->mm->mmap_sem); -+ if (likely(call_syscall)) -+ goto rt_emulate; -+ -+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); -+ -+ down_write(¤t->mm->mmap_sem); -+ if (current->mm->call_syscall) { -+ call_syscall = current->mm->call_syscall; -+ up_write(¤t->mm->mmap_sem); -+ if (vma) kmem_cache_free(vm_area_cachep, vma); -+ goto rt_emulate; -+ } -+ -+ call_syscall = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE); -+ if (!vma || (call_syscall & ~PAGE_MASK)) { -+ up_write(¤t->mm->mmap_sem); -+ if (vma) kmem_cache_free(vm_area_cachep, vma); -+ return 1; -+ } -+ -+ pax_insert_vma(vma, call_syscall); -+ current->mm->call_syscall = call_syscall; -+ up_write(¤t->mm->mmap_sem); -+ -+rt_emulate: -+ regs->gpr[PT_R0] = __NR_rt_sigreturn; -+ regs->nip = call_syscall; -+ return 7; -+ } -+ } while (0); -+#endif -+ -+ return 1; -+} -+ -+void pax_report_insns(void *pc, void *sp) -+{ -+ unsigned long i; -+ -+ printk(KERN_ERR "PAX: bytes at PC: "); -+ for (i = 0; i < 5; i++) { -+ unsigned int c; -+ if (get_user(c, (unsigned int*)pc+i)) { -+ printk("<invalid address>."); -+ break; -+ } -+ printk("%08x ", c); -+ } -+ printk("\n"); -+} -+#endif -+ - /* - * Check whether the instruction at regs->nip is a store using - * an update addressing form which will update r1. -@@ -116,7 +481,7 @@ - * indicate errors in DSISR but can validly be set in SRR1. - */ - if (TRAP(regs) == 0x400) -- error_code &= 0x48200000; -+ error_code &= 0x58200000; - else - is_write = error_code & 0x02000000; - #endif /* CONFIG_4xx */ -@@ -211,15 +576,14 @@ - } else if (TRAP(regs) == 0x400) { - pte_t *ptep; - --#if 0 -+#if 1 - /* It would be nice to actually enforce the VM execute - permission on CPUs which can do so, but far too - much stuff in userspace doesn't get the permissions - right, so we let any page be executed for now. */ - if (! (vma->vm_flags & VM_EXEC)) - goto bad_area; --#endif -- -+#else - /* Since 4xx supports per-page execute permission, - * we lazily flush dcache to icache. */ - ptep = NULL; -@@ -240,6 +604,7 @@ - if (ptep != NULL) - pte_unmap(ptep); - #endif -+#endif - /* a read */ - } else { - /* protection fault */ -@@ -285,6 +650,38 @@ - - /* User mode accesses cause a SIGSEGV */ - if (user_mode(regs)) { -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (current->flags & PF_PAX_PAGEEXEC) { -+ if ((TRAP(regs) == 0x400) && (regs->nip == address)) { -+ switch (pax_handle_fetch_fault(regs)) { -+ -+#ifdef CONFIG_PAX_EMUPLT -+ case 2: -+ case 3: -+ case 4: -+ return; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ case 5: -+ return; -+#endif -+ -+#ifdef CONFIG_PAX_EMUSIGRT -+ case 6: -+ case 7: -+ return; -+#endif -+ -+ } -+ -+ pax_report_fault(regs, (void*)regs->nip, (void*)regs->gpr[1]); -+ do_exit(SIGKILL); -+ } -+ } -+#endif -+ - info.si_signo = SIGSEGV; - info.si_errno = 0; - info.si_code = code; -diff -urN linux-2.6.5/arch/sparc/kernel/ptrace.c linux-2.6.5/arch/sparc/kernel/ptrace.c ---- linux-2.6.5/arch/sparc/kernel/ptrace.c 2004-04-03 22:38:24.000000000 -0500 -+++ linux-2.6.5/arch/sparc/kernel/ptrace.c 2004-04-18 11:05:50.000000000 -0400 -@@ -18,6 +18,7 @@ - #include <linux/smp.h> - #include <linux/smp_lock.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - - #include <asm/pgtable.h> - #include <asm/system.h> -@@ -320,6 +321,11 @@ - goto out; - } - -+ if (gr_handle_ptrace(child, request)) { -+ pt_error_return(regs, EPERM); -+ goto out_tsk; -+ } -+ - if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH) - || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { - if (ptrace_attach(child)) { -diff -urN linux-2.6.5/arch/sparc/kernel/sys_sparc.c linux-2.6.5/arch/sparc/kernel/sys_sparc.c ---- linux-2.6.5/arch/sparc/kernel/sys_sparc.c 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/arch/sparc/kernel/sys_sparc.c 2004-04-18 11:05:50.000000000 -0400 -@@ -21,6 +21,7 @@ - #include <linux/utsname.h> - #include <linux/smp.h> - #include <linux/smp_lock.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/ipc.h> -@@ -55,6 +56,13 @@ - return -ENOMEM; - if (ARCH_SUN4C_SUN4 && len > 0x20000000) - return -ENOMEM; -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if ((current->flags & PF_PAX_RANDMMAP) && (!addr || filp)) -+ addr = TASK_UNMAPPED_BASE + current->mm->delta_mmap; -+ else -+#endif -+ - if (!addr) - addr = TASK_UNMAPPED_BASE; - -@@ -224,6 +232,11 @@ - struct file * file = NULL; - unsigned long retval = -EBADF; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) -@@ -242,6 +255,12 @@ - if (len > TASK_SIZE - PAGE_SIZE || addr + len > TASK_SIZE - PAGE_SIZE) - goto out_putf; - -+ if (gr_handle_mmap(file, prot)) { -+ fput(file); -+ retval = -EACCES; -+ goto out; -+ } -+ - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - - down_write(¤t->mm->mmap_sem); -diff -urN linux-2.6.5/arch/sparc/kernel/sys_sunos.c linux-2.6.5/arch/sparc/kernel/sys_sunos.c ---- linux-2.6.5/arch/sparc/kernel/sys_sunos.c 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/arch/sparc/kernel/sys_sunos.c 2004-04-18 11:05:50.000000000 -0400 -@@ -71,6 +71,11 @@ - struct file * file = NULL; - unsigned long retval, ret_type; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - if(flags & MAP_NORESERVE) { - static int cnt; - if (cnt++ < 10) -diff -urN linux-2.6.5/arch/sparc/mm/fault.c linux-2.6.5/arch/sparc/mm/fault.c ---- linux-2.6.5/arch/sparc/mm/fault.c 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/arch/sparc/mm/fault.c 2004-04-18 11:05:50.000000000 -0400 -@@ -21,6 +21,10 @@ - #include <linux/smp_lock.h> - #include <linux/interrupt.h> - #include <linux/module.h> -+#include <linux/slab.h> -+#include <linux/pagemap.h> -+#include <linux/compiler.h> -+#include <linux/binfmts.h> - - #include <asm/system.h> - #include <asm/segment.h> -@@ -201,6 +205,272 @@ - return 0; - } - -+#ifdef CONFIG_PAX_PAGEEXEC -+void pax_emuplt_close(struct vm_area_struct * vma) -+{ -+ vma->vm_mm->call_dl_resolve = 0UL; -+} -+ -+static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type) -+{ -+ struct page* page; -+ unsigned int *kaddr; -+ -+ page = alloc_page(GFP_HIGHUSER); -+ if (!page) -+ return NOPAGE_OOM; -+ -+ kaddr = kmap(page); -+ memset(kaddr, 0, PAGE_SIZE); -+ kaddr[0] = 0x9DE3BFA8U; /* save */ -+ flush_dcache_page(page); -+ kunmap(page); -+ if (type) -+ *type = VM_FAULT_MAJOR; -+ -+ return page; -+} -+ -+static struct vm_operations_struct pax_vm_ops = { -+ close: pax_emuplt_close, -+ nopage: pax_emuplt_nopage, -+}; -+ -+static void pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) -+{ -+ vma->vm_mm = current->mm; -+ vma->vm_start = addr; -+ vma->vm_end = addr + PAGE_SIZE; -+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC; -+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f]; -+ vma->vm_ops = &pax_vm_ops; -+ vma->vm_pgoff = 0UL; -+ vma->vm_file = NULL; -+ vma->vm_private_data = NULL; -+ INIT_LIST_HEAD(&vma->shared); -+ insert_vm_struct(current->mm, vma); -+ ++current->mm->total_vm; -+} -+ -+/* -+ * PaX: decide what to do with offenders (regs->pc = fault address) -+ * -+ * returns 1 when task should be killed -+ * 2 when patched PLT trampoline was detected -+ * 3 when unpatched PLT trampoline was detected -+ * 4 when legitimate ET_EXEC was detected -+ */ -+static int pax_handle_fetch_fault(struct pt_regs *regs) -+{ -+ -+#ifdef CONFIG_PAX_EMUPLT -+ int err; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ if (current->flags & PF_PAX_RANDEXEC) { -+ if (regs->pc >= current->mm->start_code && -+ regs->pc < current->mm->end_code) -+ { -+ if (regs->u_regs[UREG_RETPC] + 8UL == regs->pc) -+ return 1; -+ -+ regs->pc += current->mm->delta_exec; -+ if (regs->npc >= current->mm->start_code && -+ regs->npc < current->mm->end_code) -+ regs->npc += current->mm->delta_exec; -+ return 4; -+ } -+ if (regs->pc >= current->mm->start_code + current->mm->delta_exec && -+ regs->pc < current->mm->end_code + current->mm->delta_exec) -+ { -+ regs->pc -= current->mm->delta_exec; -+ if (regs->npc >= current->mm->start_code + current->mm->delta_exec && -+ regs->npc < current->mm->end_code + current->mm->delta_exec) -+ regs->npc -= current->mm->delta_exec; -+ } -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUPLT -+ do { /* PaX: patched PLT emulation #1 */ -+ unsigned int sethi1, sethi2, jmpl; -+ -+ err = get_user(sethi1, (unsigned int*)regs->pc); -+ err |= get_user(sethi2, (unsigned int*)(regs->pc+4)); -+ err |= get_user(jmpl, (unsigned int*)(regs->pc+8)); -+ -+ if (err) -+ break; -+ -+ if ((sethi1 & 0xFFC00000U) == 0x03000000U && -+ (sethi2 & 0xFFC00000U) == 0x03000000U && -+ (jmpl & 0xFFFFE000U) == 0x81C06000U) -+ { -+ unsigned int addr; -+ -+ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10; -+ addr = regs->u_regs[UREG_G1]; -+ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); -+ regs->pc = addr; -+ regs->npc = addr+4; -+ return 2; -+ } -+ } while (0); -+ -+ { /* PaX: patched PLT emulation #2 */ -+ unsigned int ba; -+ -+ err = get_user(ba, (unsigned int*)regs->pc); -+ -+ if (!err && (ba & 0xFFC00000U) == 0x30800000U) { -+ unsigned int addr; -+ -+ addr = regs->pc + 4 + (((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U); -+ regs->pc = addr; -+ regs->npc = addr+4; -+ return 2; -+ } -+ } -+ -+ do { /* PaX: patched PLT emulation #3 */ -+ unsigned int sethi, jmpl, nop; -+ -+ err = get_user(sethi, (unsigned int*)regs->pc); -+ err |= get_user(jmpl, (unsigned int*)(regs->pc+4)); -+ err |= get_user(nop, (unsigned int*)(regs->pc+8)); -+ -+ if (err) -+ break; -+ -+ if ((sethi & 0xFFC00000U) == 0x03000000U && -+ (jmpl & 0xFFFFE000U) == 0x81C06000U && -+ nop == 0x01000000U) -+ { -+ unsigned int addr; -+ -+ addr = (sethi & 0x003FFFFFU) << 10; -+ regs->u_regs[UREG_G1] = addr; -+ addr += (((jmpl | 0xFFFFE000U) ^ 0x00001000U) + 0x00001000U); -+ regs->pc = addr; -+ regs->npc = addr+4; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: unpatched PLT emulation step 1 */ -+ unsigned int sethi, ba, nop; -+ -+ err = get_user(sethi, (unsigned int*)regs->pc); -+ err |= get_user(ba, (unsigned int*)(regs->pc+4)); -+ err |= get_user(nop, (unsigned int*)(regs->pc+8)); -+ -+ if (err) -+ break; -+ -+ if ((sethi & 0xFFC00000U) == 0x03000000U && -+ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) && -+ nop == 0x01000000U) -+ { -+ unsigned int addr, save, call; -+ -+ if ((ba & 0xFFC00000U) == 0x30800000U) -+ addr = regs->pc + 4 + ((((ba | 0xFFC00000U) ^ 0x00200000U) + 0x00200000U) << 2); -+ else -+ addr = regs->pc + 4 + ((((ba | 0xFFF80000U) ^ 0x00040000U) + 0x00040000U) << 2); -+ -+ err = get_user(save, (unsigned int*)addr); -+ err |= get_user(call, (unsigned int*)(addr+4)); -+ err |= get_user(nop, (unsigned int*)(addr+8)); -+ if (err) -+ break; -+ -+ if (save == 0x9DE3BFA8U && -+ (call & 0xC0000000U) == 0x40000000U && -+ nop == 0x01000000U) -+ { -+ struct vm_area_struct *vma; -+ unsigned long call_dl_resolve; -+ -+ down_read(¤t->mm->mmap_sem); -+ call_dl_resolve = current->mm->call_dl_resolve; -+ up_read(¤t->mm->mmap_sem); -+ if (likely(call_dl_resolve)) -+ goto emulate; -+ -+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); -+ -+ down_write(¤t->mm->mmap_sem); -+ if (current->mm->call_dl_resolve) { -+ call_dl_resolve = current->mm->call_dl_resolve; -+ up_write(¤t->mm->mmap_sem); -+ if (vma) kmem_cache_free(vm_area_cachep, vma); -+ goto emulate; -+ } -+ -+ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE); -+ if (!vma || (call_dl_resolve & ~PAGE_MASK)) { -+ up_write(¤t->mm->mmap_sem); -+ if (vma) kmem_cache_free(vm_area_cachep, vma); -+ return 1; -+ } -+ -+ pax_insert_vma(vma, call_dl_resolve); -+ current->mm->call_dl_resolve = call_dl_resolve; -+ up_write(¤t->mm->mmap_sem); -+ -+emulate: -+ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10; -+ regs->pc = call_dl_resolve; -+ regs->npc = addr+4; -+ return 3; -+ } -+ } -+ } while (0); -+ -+ do { /* PaX: unpatched PLT emulation step 2 */ -+ unsigned int save, call, nop; -+ -+ err = get_user(save, (unsigned int*)(regs->pc-4)); -+ err |= get_user(call, (unsigned int*)regs->pc); -+ err |= get_user(nop, (unsigned int*)(regs->pc+4)); -+ if (err) -+ break; -+ -+ if (save == 0x9DE3BFA8U && -+ (call & 0xC0000000U) == 0x40000000U && -+ nop == 0x01000000U) -+ { -+ unsigned int dl_resolve = regs->pc + ((((call | 0xC0000000U) ^ 0x20000000U) + 0x20000000U) << 2); -+ -+ regs->u_regs[UREG_RETPC] = regs->pc; -+ regs->pc = dl_resolve; -+ regs->npc = dl_resolve+4; -+ return 3; -+ } -+ } while (0); -+#endif -+ -+ return 1; -+} -+ -+void pax_report_insns(void *pc, void *sp) -+{ -+ unsigned long i; -+ -+ printk(KERN_ERR "PAX: bytes at PC: "); -+ for (i = 0; i < 5; i++) { -+ unsigned int c; -+ if (get_user(c, (unsigned int*)pc+i)) { -+ printk("<invalid address>."); -+ break; -+ } -+ printk("%08x ", c); -+ } -+ printk("\n"); -+} -+#endif -+ - asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, - unsigned long address) - { -@@ -264,6 +534,29 @@ - if(!(vma->vm_flags & VM_WRITE)) - goto bad_area; - } else { -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if ((current->flags & PF_PAX_PAGEEXEC) && text_fault && !(vma->vm_flags & VM_EXEC)) { -+ up_read(&mm->mmap_sem); -+ switch (pax_handle_fetch_fault(regs)) { -+ -+#ifdef CONFIG_PAX_EMUPLT -+ case 2: -+ case 3: -+ return; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ case 4: -+ return; -+#endif -+ -+ } -+ pax_report_fault(regs, (void*)regs->pc, (void*)regs->u_regs[UREG_FP]); -+ do_exit(SIGKILL); -+ } -+#endif -+ - /* Allow reads even for write-only mappings */ - if(!(vma->vm_flags & (VM_READ | VM_EXEC))) - goto bad_area; -diff -urN linux-2.6.5/arch/sparc/mm/init.c linux-2.6.5/arch/sparc/mm/init.c ---- linux-2.6.5/arch/sparc/mm/init.c 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/arch/sparc/mm/init.c 2004-04-18 11:05:50.000000000 -0400 -@@ -337,17 +337,17 @@ - - /* Initialize the protection map with non-constant, MMU dependent values. */ - protection_map[0] = PAGE_NONE; -- protection_map[1] = PAGE_READONLY; -- protection_map[2] = PAGE_COPY; -- protection_map[3] = PAGE_COPY; -+ protection_map[1] = PAGE_READONLY_NOEXEC; -+ protection_map[2] = PAGE_COPY_NOEXEC; -+ protection_map[3] = PAGE_COPY_NOEXEC; - protection_map[4] = PAGE_READONLY; - protection_map[5] = PAGE_READONLY; - protection_map[6] = PAGE_COPY; - protection_map[7] = PAGE_COPY; - protection_map[8] = PAGE_NONE; -- protection_map[9] = PAGE_READONLY; -- protection_map[10] = PAGE_SHARED; -- protection_map[11] = PAGE_SHARED; -+ protection_map[9] = PAGE_READONLY_NOEXEC; -+ protection_map[10] = PAGE_SHARED_NOEXEC; -+ protection_map[11] = PAGE_SHARED_NOEXEC; - protection_map[12] = PAGE_READONLY; - protection_map[13] = PAGE_READONLY; - protection_map[14] = PAGE_SHARED; -diff -urN linux-2.6.5/arch/sparc/mm/srmmu.c linux-2.6.5/arch/sparc/mm/srmmu.c ---- linux-2.6.5/arch/sparc/mm/srmmu.c 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/arch/sparc/mm/srmmu.c 2004-04-18 11:05:50.000000000 -0400 -@@ -2138,6 +2138,13 @@ - BTFIXUPSET_INT(page_shared, pgprot_val(SRMMU_PAGE_SHARED)); - BTFIXUPSET_INT(page_copy, pgprot_val(SRMMU_PAGE_COPY)); - BTFIXUPSET_INT(page_readonly, pgprot_val(SRMMU_PAGE_RDONLY)); -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ BTFIXUPSET_INT(page_shared_noexec, pgprot_val(SRMMU_PAGE_SHARED_NOEXEC)); -+ BTFIXUPSET_INT(page_copy_noexec, pgprot_val(SRMMU_PAGE_COPY_NOEXEC)); -+ BTFIXUPSET_INT(page_readonly_noexec, pgprot_val(SRMMU_PAGE_RDONLY_NOEXEC)); -+#endif -+ - BTFIXUPSET_INT(page_kernel, pgprot_val(SRMMU_PAGE_KERNEL)); - page_kernel = pgprot_val(SRMMU_PAGE_KERNEL); - pg_iobits = SRMMU_VALID | SRMMU_WRITE | SRMMU_REF; -diff -urN linux-2.6.5/arch/sparc64/kernel/itlb_base.S linux-2.6.5/arch/sparc64/kernel/itlb_base.S ---- linux-2.6.5/arch/sparc64/kernel/itlb_base.S 2004-04-03 22:36:18.000000000 -0500 -+++ linux-2.6.5/arch/sparc64/kernel/itlb_base.S 2004-04-18 11:05:50.000000000 -0400 -@@ -41,7 +41,9 @@ - CREATE_VPTE_OFFSET2(%g4, %g6) ! Create VPTE offset - ldxa [%g3 + %g6] ASI_P, %g5 ! Load VPTE - 1: brgez,pn %g5, 3f ! Not valid, branch out -- nop ! Delay-slot -+ and %g5, _PAGE_EXEC, %g4 -+ brz,pn %g4, 3f ! Not executable, branch out -+ nop ! Delay-slot - 2: stxa %g5, [%g0] ASI_ITLB_DATA_IN ! Load PTE into TLB - retry ! Trap return - 3: rdpr %pstate, %g4 ! Move into alternate globals -@@ -74,8 +76,6 @@ - nop - nop - nop -- nop -- nop - CREATE_VPTE_NOP - - #undef CREATE_VPTE_OFFSET1 -diff -urN linux-2.6.5/arch/sparc64/kernel/ptrace.c linux-2.6.5/arch/sparc64/kernel/ptrace.c ---- linux-2.6.5/arch/sparc64/kernel/ptrace.c 2004-04-03 22:38:22.000000000 -0500 -+++ linux-2.6.5/arch/sparc64/kernel/ptrace.c 2004-04-18 11:05:50.000000000 -0400 -@@ -19,6 +19,7 @@ - #include <linux/smp.h> - #include <linux/smp_lock.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - - #include <asm/asi.h> - #include <asm/pgtable.h> -@@ -169,6 +170,11 @@ - goto out; - } - -+ if (gr_handle_ptrace(child, (long)request)) { -+ pt_error_return(regs, EPERM); -+ goto out_tsk; -+ } -+ - if ((current->personality == PER_SUNOS && request == PTRACE_SUNATTACH) - || (current->personality != PER_SUNOS && request == PTRACE_ATTACH)) { - if (ptrace_attach(child)) { -diff -urN linux-2.6.5/arch/sparc64/kernel/sys_sparc.c linux-2.6.5/arch/sparc64/kernel/sys_sparc.c ---- linux-2.6.5/arch/sparc64/kernel/sys_sparc.c 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/arch/sparc64/kernel/sys_sparc.c 2004-04-18 11:05:50.000000000 -0400 -@@ -25,6 +25,7 @@ - #include <linux/syscalls.h> - #include <linux/ipc.h> - #include <linux/personality.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/ipc.h> -@@ -71,6 +72,10 @@ - if (filp || (flags & MAP_SHARED)) - do_color_align = 1; - -+#ifdef CONFIG_PAX_RANDMMAP -+ if (!(current->flags & PF_PAX_RANDMMAP) || !filp) -+#endif -+ - if (addr) { - if (do_color_align) - addr = COLOUR_ALIGN(addr, pgoff); -@@ -101,6 +106,13 @@ - } - if (task_size < addr) { - if (start_addr != TASK_UNMAPPED_BASE) { -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if (current->flags & PF_PAX_RANDMMAP) -+ start_addr = addr = TASK_UNMAPPED_BASE + mm->delta_mmap; -+ else -+#endif -+ - start_addr = addr = TASK_UNMAPPED_BASE; - goto full_search; - } -@@ -310,11 +322,22 @@ - struct file * file = NULL; - unsigned long retval = -EBADF; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } -+ -+ if (gr_handle_mmap(file, prot)) { -+ retval = -EACCES; -+ goto out_putf; -+ } -+ - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - len = PAGE_ALIGN(len); - retval = -EINVAL; -diff -urN linux-2.6.5/arch/sparc64/kernel/sys_sparc32.c linux-2.6.5/arch/sparc64/kernel/sys_sparc32.c ---- linux-2.6.5/arch/sparc64/kernel/sys_sparc32.c 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/arch/sparc64/kernel/sys_sparc32.c 2004-04-18 11:05:50.000000000 -0400 -@@ -54,6 +54,8 @@ - #include <linux/netfilter_ipv4/ip_tables.h> - #include <linux/ptrace.h> - #include <linux/highuid.h> -+#include <linux/random.h> -+#include <linux/grsecurity.h> - - #include <asm/types.h> - #include <asm/ipc.h> -@@ -1759,6 +1761,11 @@ - struct file * file; - int retval; - int i; -+#ifdef CONFIG_GRKERNSEC -+ struct file *old_exec_file; -+ struct acl_subject_label *old_acl; -+ struct rlimit old_rlim[RLIM_NLIMITS]; -+#endif - - sched_balance_exec(); - -@@ -1768,7 +1775,26 @@ - if (IS_ERR(file)) - return retval; - -+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes), 1); -+ -+ if (gr_handle_nproc()) { -+ allow_write_access(file); -+ fput(file); -+ return -EAGAIN; -+ } -+ -+ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) { -+ allow_write_access(file); -+ fput(file); -+ return -EACCES; -+ } -+ - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); -+ -+#ifdef CONFIG_PAX_RANDUSTACK -+ bprm.p -= (pax_get_random_long() & ~(sizeof(void *)-1)) & ~PAGE_MASK; -+#endif -+ - memset(bprm.page, 0, MAX_ARG_PAGES * sizeof(bprm.page[0])); - - bprm.file = file; -@@ -1803,11 +1829,24 @@ - if (retval < 0) - goto out; - -+ if (!gr_tpe_allow(file)) { -+ retval = -EACCES; -+ goto out; -+ } -+ -+ if (gr_check_crash_exec(file)) { -+ retval = -EACCES; -+ goto out; -+ } -+ - retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; - - bprm.exec = bprm.p; -+ -+ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt); -+ - retval = copy_strings32(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; -@@ -1816,13 +1855,34 @@ - if (retval < 0) - goto out; - -+#ifdef CONFIG_GRKERNSEC -+ old_acl = current->acl; -+ memcpy(old_rlim, current->rlim, sizeof(old_rlim)); -+ old_exec_file = current->exec_file; -+ get_file(file); -+ current->exec_file = file; -+#endif -+ -+ gr_set_proc_label(file->f_dentry, file->f_vfsmnt); -+ - retval = search_binary_handler(&bprm, regs); - if (retval >= 0) { - /* execve success */ -+#ifdef CONFIG_GRKERNSEC -+ if (old_exec_file) -+ fput(old_exec_file); -+#endif - security_bprm_free(&bprm); - return retval; - } - -+#ifdef CONFIG_GRKERNSEC -+ current->acl = old_acl; -+ memcpy(current->rlim, old_rlim, sizeof(old_rlim)); -+ fput(current->exec_file); -+ current->exec_file = old_exec_file; -+#endif -+ - out: - /* Something went wrong, return the inode and free the argument pages*/ - for (i = 0 ; i < MAX_ARG_PAGES ; i++) { -diff -urN linux-2.6.5/arch/sparc64/kernel/sys_sunos32.c linux-2.6.5/arch/sparc64/kernel/sys_sunos32.c ---- linux-2.6.5/arch/sparc64/kernel/sys_sunos32.c 2004-04-03 22:37:24.000000000 -0500 -+++ linux-2.6.5/arch/sparc64/kernel/sys_sunos32.c 2004-04-18 11:05:50.000000000 -0400 -@@ -75,6 +75,11 @@ - struct file *file = NULL; - unsigned long retval, ret_type; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - if (flags & MAP_NORESERVE) { - static int cnt; - if (cnt++ < 10) -diff -urN linux-2.6.5/arch/sparc64/mm/fault.c linux-2.6.5/arch/sparc64/mm/fault.c ---- linux-2.6.5/arch/sparc64/mm/fault.c 2004-04-03 22:38:20.000000000 -0500 -+++ linux-2.6.5/arch/sparc64/mm/fault.c 2004-04-18 11:05:50.000000000 -0400 -@@ -18,6 +18,10 @@ - #include <linux/smp_lock.h> - #include <linux/init.h> - #include <linux/interrupt.h> -+#include <linux/slab.h> -+#include <linux/pagemap.h> -+#include <linux/compiler.h> -+#include <linux/binfmts.h> - - #include <asm/page.h> - #include <asm/pgtable.h> -@@ -303,6 +307,364 @@ - unhandled_fault (address, current, regs); - } - -+#ifdef CONFIG_PAX_PAGEEXEC -+#ifdef CONFIG_PAX_EMUPLT -+static void pax_emuplt_close(struct vm_area_struct * vma) -+{ -+ vma->vm_mm->call_dl_resolve = 0UL; -+} -+ -+static struct page* pax_emuplt_nopage(struct vm_area_struct *vma, unsigned long address, int *type) -+{ -+ struct page* page; -+ unsigned int *kaddr; -+ -+ page = alloc_page(GFP_HIGHUSER); -+ if (!page) -+ return NOPAGE_OOM; -+ -+ kaddr = kmap(page); -+ memset(kaddr, 0, PAGE_SIZE); -+ kaddr[0] = 0x9DE3BFA8U; /* save */ -+ flush_dcache_page(page); -+ kunmap(page); -+ if (type) -+ *type = VM_FAULT_MAJOR; -+ return page; -+} -+ -+static struct vm_operations_struct pax_vm_ops = { -+ close: pax_emuplt_close, -+ nopage: pax_emuplt_nopage, -+}; -+ -+static void pax_insert_vma(struct vm_area_struct *vma, unsigned long addr) -+{ -+ vma->vm_mm = current->mm; -+ vma->vm_start = addr; -+ vma->vm_end = addr + PAGE_SIZE; -+ vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYEXEC; -+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f]; -+ vma->vm_ops = &pax_vm_ops; -+ vma->vm_pgoff = 0UL; -+ vma->vm_file = NULL; -+ vma->vm_private_data = NULL; -+ INIT_LIST_HEAD(&vma->shared); -+ insert_vm_struct(current->mm, vma); -+ ++current->mm->total_vm; -+} -+#endif -+ -+/* -+ * PaX: decide what to do with offenders (regs->tpc = fault address) -+ * -+ * returns 1 when task should be killed -+ * 2 when patched PLT trampoline was detected -+ * 3 when unpatched PLT trampoline was detected -+ * 4 when legitimate ET_EXEC was detected -+ */ -+static int pax_handle_fetch_fault(struct pt_regs *regs) -+{ -+ -+#ifdef CONFIG_PAX_EMUPLT -+ int err; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ if (current->flags & PF_PAX_RANDEXEC) { -+ if (regs->tpc >= current->mm->start_code && -+ regs->tpc < current->mm->end_code) -+ { -+ if (regs->u_regs[UREG_RETPC] + 8UL == regs->tpc) -+ return 1; -+ -+ regs->tpc += current->mm->delta_exec; -+ if (regs->tnpc >= current->mm->start_code && -+ regs->tnpc < current->mm->end_code) -+ regs->tnpc += current->mm->delta_exec; -+ return 4; -+ } -+ if (regs->tpc >= current->mm->start_code + current->mm->delta_exec && -+ regs->tpc < current->mm->end_code + current->mm->delta_exec) -+ { -+ regs->tpc -= current->mm->delta_exec; -+ if (regs->tnpc >= current->mm->start_code + current->mm->delta_exec && -+ regs->tnpc < current->mm->end_code + current->mm->delta_exec) -+ regs->tnpc -= current->mm->delta_exec; -+ } -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUPLT -+ do { /* PaX: patched PLT emulation #1 */ -+ unsigned int sethi1, sethi2, jmpl; -+ -+ err = get_user(sethi1, (unsigned int*)regs->tpc); -+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4)); -+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+8)); -+ -+ if (err) -+ break; -+ -+ if ((sethi1 & 0xFFC00000U) == 0x03000000U && -+ (sethi2 & 0xFFC00000U) == 0x03000000U && -+ (jmpl & 0xFFFFE000U) == 0x81C06000U) -+ { -+ unsigned long addr; -+ -+ regs->u_regs[UREG_G1] = (sethi2 & 0x003FFFFFU) << 10; -+ addr = regs->u_regs[UREG_G1]; -+ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); -+ regs->tpc = addr; -+ regs->tnpc = addr+4; -+ return 2; -+ } -+ } while (0); -+ -+ { /* PaX: patched PLT emulation #2 */ -+ unsigned int ba; -+ -+ err = get_user(ba, (unsigned int*)regs->tpc); -+ -+ if (!err && (ba & 0xFFC00000U) == 0x30800000U) { -+ unsigned long addr; -+ -+ addr = regs->tpc + 4 + (((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL); -+ regs->tpc = addr; -+ regs->tnpc = addr+4; -+ return 2; -+ } -+ } -+ -+ do { /* PaX: patched PLT emulation #3 */ -+ unsigned int sethi, jmpl, nop; -+ -+ err = get_user(sethi, (unsigned int*)regs->tpc); -+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+4)); -+ err |= get_user(nop, (unsigned int*)(regs->tpc+8)); -+ -+ if (err) -+ break; -+ -+ if ((sethi & 0xFFC00000U) == 0x03000000U && -+ (jmpl & 0xFFFFE000U) == 0x81C06000U && -+ nop == 0x01000000U) -+ { -+ unsigned long addr; -+ -+ addr = (sethi & 0x003FFFFFU) << 10; -+ regs->u_regs[UREG_G1] = addr; -+ addr += (((jmpl | 0xFFFFFFFFFFFFE000UL) ^ 0x00001000UL) + 0x00001000UL); -+ regs->tpc = addr; -+ regs->tnpc = addr+4; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: patched PLT emulation #4 */ -+ unsigned int mov1, call, mov2; -+ -+ err = get_user(mov1, (unsigned int*)regs->tpc); -+ err |= get_user(call, (unsigned int*)(regs->tpc+4)); -+ err |= get_user(mov2, (unsigned int*)(regs->tpc+8)); -+ -+ if (err) -+ break; -+ -+ if (mov1 == 0x8210000FU && -+ (call & 0xC0000000U) == 0x40000000U && -+ mov2 == 0x9E100001U) -+ { -+ unsigned long addr; -+ -+ regs->u_regs[UREG_G1] = regs->u_regs[UREG_RETPC]; -+ addr = regs->tpc + 4 + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2); -+ regs->tpc = addr; -+ regs->tnpc = addr+4; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: patched PLT emulation #5 */ -+ unsigned int sethi1, sethi2, or1, or2, sllx, jmpl, nop; -+ -+ err = get_user(sethi1, (unsigned int*)regs->tpc); -+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4)); -+ err |= get_user(or1, (unsigned int*)(regs->tpc+8)); -+ err |= get_user(or2, (unsigned int*)(regs->tpc+12)); -+ err |= get_user(sllx, (unsigned int*)(regs->tpc+16)); -+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+20)); -+ err |= get_user(nop, (unsigned int*)(regs->tpc+24)); -+ -+ if (err) -+ break; -+ -+ if ((sethi1 & 0xFFC00000U) == 0x03000000U && -+ (sethi2 & 0xFFC00000U) == 0x0B000000U && -+ (or1 & 0xFFFFE000U) == 0x82106000U && -+ (or2 & 0xFFFFE000U) == 0x8A116000U && -+ sllx == 0x83287020 && -+ jmpl == 0x81C04005U && -+ nop == 0x01000000U) -+ { -+ unsigned long addr; -+ -+ regs->u_regs[UREG_G1] = ((sethi1 & 0x003FFFFFU) << 10) | (or1 & 0x000003FFU); -+ regs->u_regs[UREG_G1] <<= 32; -+ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or2 & 0x000003FFU); -+ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5]; -+ regs->tpc = addr; -+ regs->tnpc = addr+4; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: patched PLT emulation #6 */ -+ unsigned int sethi1, sethi2, sllx, or, jmpl, nop; -+ -+ err = get_user(sethi1, (unsigned int*)regs->tpc); -+ err |= get_user(sethi2, (unsigned int*)(regs->tpc+4)); -+ err |= get_user(sllx, (unsigned int*)(regs->tpc+8)); -+ err |= get_user(or, (unsigned int*)(regs->tpc+12)); -+ err |= get_user(jmpl, (unsigned int*)(regs->tpc+16)); -+ err |= get_user(nop, (unsigned int*)(regs->tpc+20)); -+ -+ if (err) -+ break; -+ -+ if ((sethi1 & 0xFFC00000U) == 0x03000000U && -+ (sethi2 & 0xFFC00000U) == 0x0B000000U && -+ sllx == 0x83287020 && -+ (or & 0xFFFFE000U) == 0x8A116000U && -+ jmpl == 0x81C04005U && -+ nop == 0x01000000U) -+ { -+ unsigned long addr; -+ -+ regs->u_regs[UREG_G1] = (sethi1 & 0x003FFFFFU) << 10; -+ regs->u_regs[UREG_G1] <<= 32; -+ regs->u_regs[UREG_G5] = ((sethi2 & 0x003FFFFFU) << 10) | (or & 0x3FFU); -+ addr = regs->u_regs[UREG_G1] + regs->u_regs[UREG_G5]; -+ regs->tpc = addr; -+ regs->tnpc = addr+4; -+ return 2; -+ } -+ } while (0); -+ -+ do { /* PaX: unpatched PLT emulation step 1 */ -+ unsigned int sethi, ba, nop; -+ -+ err = get_user(sethi, (unsigned int*)regs->tpc); -+ err |= get_user(ba, (unsigned int*)(regs->tpc+4)); -+ err |= get_user(nop, (unsigned int*)(regs->tpc+8)); -+ -+ if (err) -+ break; -+ -+ if ((sethi & 0xFFC00000U) == 0x03000000U && -+ ((ba & 0xFFC00000U) == 0x30800000U || (ba & 0xFFF80000U) == 0x30680000U) && -+ nop == 0x01000000U) -+ { -+ unsigned long addr; -+ unsigned int save, call; -+ -+ if ((ba & 0xFFC00000U) == 0x30800000U) -+ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFC00000UL) ^ 0x00200000UL) + 0x00200000UL) << 2); -+ else -+ addr = regs->tpc + 4 + ((((ba | 0xFFFFFFFFFFF80000UL) ^ 0x00040000UL) + 0x00040000UL) << 2); -+ -+ err = get_user(save, (unsigned int*)addr); -+ err |= get_user(call, (unsigned int*)(addr+4)); -+ err |= get_user(nop, (unsigned int*)(addr+8)); -+ if (err) -+ break; -+ -+ if (save == 0x9DE3BFA8U && -+ (call & 0xC0000000U) == 0x40000000U && -+ nop == 0x01000000U) -+ { -+ struct vm_area_struct *vma; -+ unsigned long call_dl_resolve; -+ -+ down_read(¤t->mm->mmap_sem); -+ call_dl_resolve = current->mm->call_dl_resolve; -+ up_read(¤t->mm->mmap_sem); -+ if (likely(call_dl_resolve)) -+ goto emulate; -+ -+ vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); -+ -+ down_write(¤t->mm->mmap_sem); -+ if (current->mm->call_dl_resolve) { -+ call_dl_resolve = current->mm->call_dl_resolve; -+ up_write(¤t->mm->mmap_sem); -+ if (vma) kmem_cache_free(vm_area_cachep, vma); -+ goto emulate; -+ } -+ -+ call_dl_resolve = get_unmapped_area(NULL, 0UL, PAGE_SIZE, 0UL, MAP_PRIVATE); -+ if (!vma || (call_dl_resolve & ~PAGE_MASK)) { -+ up_write(¤t->mm->mmap_sem); -+ if (vma) kmem_cache_free(vm_area_cachep, vma); -+ return 1; -+ } -+ -+ pax_insert_vma(vma, call_dl_resolve); -+ current->mm->call_dl_resolve = call_dl_resolve; -+ up_write(¤t->mm->mmap_sem); -+ -+emulate: -+ regs->u_regs[UREG_G1] = (sethi & 0x003FFFFFU) << 10; -+ regs->tpc = call_dl_resolve; -+ regs->tnpc = addr+4; -+ return 3; -+ } -+ } -+ } while (0); -+ -+ do { /* PaX: unpatched PLT emulation step 2 */ -+ unsigned int save, call, nop; -+ -+ err = get_user(save, (unsigned int*)(regs->tpc-4)); -+ err |= get_user(call, (unsigned int*)regs->tpc); -+ err |= get_user(nop, (unsigned int*)(regs->tpc+4)); -+ if (err) -+ break; -+ -+ if (save == 0x9DE3BFA8U && -+ (call & 0xC0000000U) == 0x40000000U && -+ nop == 0x01000000U) -+ { -+ unsigned long dl_resolve = regs->tpc + ((((call | 0xFFFFFFFFC0000000UL) ^ 0x20000000UL) + 0x20000000UL) << 2); -+ -+ regs->u_regs[UREG_RETPC] = regs->tpc; -+ regs->tpc = dl_resolve; -+ regs->tnpc = dl_resolve+4; -+ return 3; -+ } -+ } while (0); -+#endif -+ -+ return 1; -+} -+ -+void pax_report_insns(void *pc, void *sp) -+{ -+ unsigned long i; -+ -+ printk(KERN_ERR "PAX: bytes at PC: "); -+ for (i = 0; i < 5; i++) { -+ unsigned int c; -+ if (get_user(c, (unsigned int*)pc+i)) { -+ printk("<invalid address>."); -+ break; -+ } -+ printk("%08x ", c); -+ } -+ printk("\n"); -+} -+#endif -+ - asmlinkage void do_sparc64_fault(struct pt_regs *regs) - { - struct mm_struct *mm = current->mm; -@@ -340,8 +702,10 @@ - goto intr_or_no_mm; - - if (test_thread_flag(TIF_32BIT)) { -- if (!(regs->tstate & TSTATE_PRIV)) -+ if (!(regs->tstate & TSTATE_PRIV)) { - regs->tpc &= 0xffffffff; -+ regs->tnpc &= 0xffffffff; -+ } - address &= 0xffffffff; - } - -@@ -350,6 +714,34 @@ - if (!vma) - goto bad_area; - -+#ifdef CONFIG_PAX_PAGEEXEC -+ /* PaX: detect ITLB misses on non-exec pages */ -+ if ((current->flags & PF_PAX_PAGEEXEC) && vma->vm_start <= address && -+ !(vma->vm_flags & VM_EXEC) && (fault_code & FAULT_CODE_ITLB)) -+ { -+ if (address != regs->tpc) -+ goto good_area; -+ -+ up_read(&mm->mmap_sem); -+ switch (pax_handle_fetch_fault(regs)) { -+ -+#ifdef CONFIG_PAX_EMUPLT -+ case 2: -+ case 3: -+ goto fault_done; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ case 4: -+ goto fault_done; -+#endif -+ -+ } -+ pax_report_fault(regs, (void*)regs->tpc, (void*)(regs->u_regs[UREG_FP] + STACK_BIAS)); -+ do_exit(SIGKILL); -+ } -+#endif -+ - /* Pure DTLB misses do not tell us whether the fault causing - * load/store/atomic was a write or not, it only says that there - * was no match. So in such a case we (carefully) read the -diff -urN linux-2.6.5/arch/sparc64/solaris/misc.c linux-2.6.5/arch/sparc64/solaris/misc.c ---- linux-2.6.5/arch/sparc64/solaris/misc.c 2004-04-03 22:38:19.000000000 -0500 -+++ linux-2.6.5/arch/sparc64/solaris/misc.c 2004-04-18 11:05:50.000000000 -0400 -@@ -56,6 +56,11 @@ - struct file *file = NULL; - unsigned long retval, ret_type; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - /* Do we need it here? */ - set_personality(PER_SVR4); - if (flags & MAP_NORESERVE) { -diff -urN linux-2.6.5/arch/x86_64/ia32/ia32_binfmt.c linux-2.6.5/arch/x86_64/ia32/ia32_binfmt.c ---- linux-2.6.5/arch/x86_64/ia32/ia32_binfmt.c 2004-04-03 22:36:15.000000000 -0500 -+++ linux-2.6.5/arch/x86_64/ia32/ia32_binfmt.c 2004-04-18 11:05:50.000000000 -0400 -@@ -185,6 +185,17 @@ - //#include <asm/ia32.h> - #include <linux/elf.h> - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_IA32) ? 0x08048000UL : 0x400000UL) -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 24) -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 24) -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 24) -+#endif -+ - typedef struct user_i387_ia32_struct elf_fpregset_t; - typedef struct user32_fxsr_struct elf_fpxregset_t; - -@@ -354,7 +365,13 @@ - mpnt->vm_mm = mm; - mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; - mpnt->vm_end = IA32_STACK_TOP; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ mpnt->vm_flags = VM_STACK_FLAGS; -+#else - mpnt->vm_flags = vm_stack_flags32; -+#endif -+ - mpnt->vm_page_prot = (mpnt->vm_flags & VM_EXEC) ? - PAGE_COPY_EXEC : PAGE_COPY; - mpnt->vm_ops = NULL; -diff -urN linux-2.6.5/arch/x86_64/ia32/sys_ia32.c linux-2.6.5/arch/x86_64/ia32/sys_ia32.c ---- linux-2.6.5/arch/x86_64/ia32/sys_ia32.c 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/arch/x86_64/ia32/sys_ia32.c 2004-04-18 11:05:50.000000000 -0400 -@@ -1235,6 +1235,11 @@ - unsigned long error; - struct file * file = NULL; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ return -EINVAL; -+#endif -+ - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); -diff -urN linux-2.6.5/arch/x86_64/kernel/ptrace.c linux-2.6.5/arch/x86_64/kernel/ptrace.c ---- linux-2.6.5/arch/x86_64/kernel/ptrace.c 2004-04-03 22:36:54.000000000 -0500 -+++ linux-2.6.5/arch/x86_64/kernel/ptrace.c 2004-04-18 11:05:50.000000000 -0400 -@@ -16,6 +16,7 @@ - #include <linux/ptrace.h> - #include <linux/user.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/pgtable.h> -@@ -212,6 +213,9 @@ - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - -+ if (gr_handle_ptrace(child, request)) -+ goto out_tsk; -+ - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; -diff -urN linux-2.6.5/arch/x86_64/kernel/setup64.c linux-2.6.5/arch/x86_64/kernel/setup64.c ---- linux-2.6.5/arch/x86_64/kernel/setup64.c 2004-04-03 22:36:54.000000000 -0500 -+++ linux-2.6.5/arch/x86_64/kernel/setup64.c 2004-04-18 11:05:50.000000000 -0400 -@@ -42,8 +42,15 @@ - - unsigned long __supported_pte_mask = ~0UL; - static int do_not_nx __initdata = 0; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+unsigned long vm_stack_flags = VM_GROWSDOWN | __VM_DATA_DEFAULT_FLAGS; -+unsigned long vm_stack_flags32 = VM_GROWSDOWN | __VM_DATA_DEFAULT_FLAGS; -+#else - unsigned long vm_stack_flags = __VM_STACK_FLAGS; - unsigned long vm_stack_flags32 = __VM_STACK_FLAGS; -+#endif -+ - unsigned long vm_data_default_flags = __VM_DATA_DEFAULT_FLAGS; - unsigned long vm_data_default_flags32 = __VM_DATA_DEFAULT_FLAGS; - unsigned long vm_force_exec32 = PROT_EXEC; -diff -urN linux-2.6.5/arch/x86_64/kernel/sys_x86_64.c linux-2.6.5/arch/x86_64/kernel/sys_x86_64.c ---- linux-2.6.5/arch/x86_64/kernel/sys_x86_64.c 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/arch/x86_64/kernel/sys_x86_64.c 2004-04-18 11:05:50.000000000 -0400 -@@ -48,6 +48,11 @@ - if (off & ~PAGE_MASK) - goto out; - -+#ifdef CONFIG_PAX_RANDEXEC -+ if (flags & MAP_MIRROR) -+ goto out; -+#endif -+ - error = -EBADF; - file = NULL; - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); -@@ -102,6 +107,15 @@ - - find_start_end(flags, &begin, &end); - -+#ifdef CONFIG_PAX_RANDMMAP -+ if ((current->flags & PF_PAX_RANDMMAP) && (!addr || filp)) { -+ if (begin == 0x40000000) -+ begin += current->mm->delta_mmap & 0x0FFFFFFFU; -+ else -+ begin += current->mm->delta_mmap; -+ } -+#endif -+ - if (len > end) - return -ENOMEM; - -diff -urN linux-2.6.5/arch/x86_64/mm/fault.c linux-2.6.5/arch/x86_64/mm/fault.c ---- linux-2.6.5/arch/x86_64/mm/fault.c 2004-04-03 22:36:14.000000000 -0500 -+++ linux-2.6.5/arch/x86_64/mm/fault.c 2004-04-18 11:05:50.000000000 -0400 -@@ -23,6 +23,7 @@ - #include <linux/vt_kern.h> /* For unblank_screen() */ - #include <linux/compiler.h> - #include <linux/module.h> -+#include <linux/binfmts.h> - - #include <asm/system.h> - #include <asm/uaccess.h> -@@ -217,6 +218,63 @@ - (tsk->sighand->action[sig-1].sa.sa_handler == SIG_DFL); - } - -+#ifdef CONFIG_PAX_PAGEEXEC -+/* -+ * PaX: decide what to do with offenders (regs->rip = fault address) -+ * -+ * returns 1 when task should be killed -+ * 2 when legitimate ET_EXEC was detected -+ */ -+static int pax_handle_fetch_fault(struct pt_regs *regs) -+{ -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ int err; -+ -+ if (current->flags & PF_PAX_RANDEXEC) { -+ if (regs->rip >= current->mm->start_code && -+ regs->rip < current->mm->end_code) -+ { -+ if (test_thread_flag(TIF_IA32)) { -+ unsigned int esp_4; -+ -+ err = get_user(esp_4, (unsigned int*)(regs->rsp-4UL)); -+ if (err || esp_4 == regs->rip) -+ return 1; -+ } else { -+ unsigned long esp_8; -+ -+ err = get_user(esp_8, (unsigned long*)(regs->rsp-8UL)); -+ if (err || esp_8 == regs->rip) -+ return 1; -+ } -+ -+ regs->rip += current->mm->delta_exec; -+ return 2; -+ } -+ } -+#endif -+ -+ return 1; -+} -+ -+void pax_report_insns(void *pc, void *sp) -+{ -+ unsigned long i; -+ -+ printk(KERN_ERR "PAX: bytes at PC: "); -+ for (i = 0; i < 20; i++) { -+ unsigned int c; -+ if (get_user(c, (unsigned char*)pc+i)) { -+ printk("<invalid address>."); -+ break; -+ } -+ printk("%08x ", c); -+ } -+ printk("\n"); -+} -+#endif -+ - int page_fault_trace; - int exception_trace = 1; - -@@ -302,6 +360,23 @@ - * we can handle it.. - */ - good_area: -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if ((current->flags & PF_PAX_PAGEEXEC) && (error_code & 16) && !(vma->vm_flags & VM_EXEC)) { -+ up_read(&mm->mmap_sem); -+ switch(pax_handle_fetch_fault(regs)) { -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ case 2: -+ return; -+#endif -+ -+ } -+ pax_report_fault(regs, (void*)regs->rip, (void*)regs->rsp); -+ do_exit(SIGKILL); -+ } -+#endif -+ - info.si_code = SEGV_ACCERR; - write = 0; - switch (error_code & 3) { -diff -urN linux-2.6.5/drivers/char/keyboard.c linux-2.6.5/drivers/char/keyboard.c ---- linux-2.6.5/drivers/char/keyboard.c 2004-04-03 22:38:28.000000000 -0500 -+++ linux-2.6.5/drivers/char/keyboard.c 2004-04-18 11:05:50.000000000 -0400 -@@ -606,6 +606,16 @@ - kbd->kbdmode == VC_MEDIUMRAW) && - value != KVAL(K_SAK)) - return; /* SAK is allowed even in raw mode */ -+ -+#if defined(CONFIG_GRKERNSEC_PROC) || defined(CONFIG_GRKERNSEC_PROC_MEMMAP) -+ { -+ void *func = fn_handler[value]; -+ if (func == fn_show_state || func == fn_show_ptregs || -+ func == fn_show_mem) -+ return; -+ } -+#endif -+ - fn_handler[value](vc, regs); - } - -diff -urN linux-2.6.5/drivers/char/mem.c linux-2.6.5/drivers/char/mem.c ---- linux-2.6.5/drivers/char/mem.c 2004-04-03 22:37:07.000000000 -0500 -+++ linux-2.6.5/drivers/char/mem.c 2004-04-18 11:05:50.000000000 -0400 -@@ -23,6 +23,7 @@ - #include <linux/devfs_fs_kernel.h> - #include <linux/ptrace.h> - #include <linux/device.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/io.h> -@@ -39,6 +40,10 @@ - extern void tapechar_init(void); - #endif - -+#ifdef CONFIG_GRKERNSEC -+extern struct file_operations grsec_fops; -+#endif -+ - /* - * Architectures vary in how they handle caching for addresses - * outside of main memory. -@@ -178,6 +183,12 @@ - - if (!valid_phys_addr_range(p, &count)) - return -EFAULT; -+ -+#ifdef CONFIG_GRKERNSEC_KMEM -+ gr_handle_mem_write(); -+ return -EPERM; -+#endif -+ - return do_write_mem(__va(p), p, buf, count, ppos); - } - -@@ -192,6 +203,11 @@ - vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); - #endif - -+#ifdef CONFIG_GRKERNSEC_KMEM -+ if (gr_handle_mem_mmap(offset, vma)) -+ return -EPERM; -+#endif -+ - /* Don't try to swap out physical pages.. */ - vma->vm_flags |= VM_RESERVED; - -@@ -285,6 +301,11 @@ - ssize_t written; - char * kbuf; /* k-addr because vwrite() takes vmlist_lock rwlock */ - -+#ifdef CONFIG_GRKERNSEC_KMEM -+ gr_handle_kmem_write(); -+ return -EPERM; -+#endif -+ - if (p < (unsigned long) high_memory) { - - wrote = count; -@@ -411,7 +432,23 @@ - count = size; - - zap_page_range(vma, addr, count); -- zeromap_page_range(vma, addr, count, PAGE_COPY); -+ zeromap_page_range(vma, addr, count, vma->vm_page_prot); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (vma->vm_flags & VM_MIRROR) { -+ unsigned long addr_m; -+ struct vm_area_struct * vma_m; -+ -+ addr_m = vma->vm_start + (unsigned long)vma->vm_private_data; -+ vma_m = find_vma(mm, addr_m); -+ if (vma_m && vma_m->vm_start == addr_m && (vma_m->vm_flags & VM_MIRROR)) { -+ addr_m = addr + (unsigned long)vma->vm_private_data; -+ zap_page_range(vma_m, addr_m, count); -+ } else -+ printk(KERN_ERR "PAX: VMMIRROR: read_zero bug, %08lx, %08lx\n", -+ addr, vma->vm_start); -+ } -+#endif - - size -= count; - buf += count; -@@ -560,6 +597,16 @@ - - static int open_port(struct inode * inode, struct file * filp) - { -+#ifdef CONFIG_GRKERNSEC_KMEM -+ gr_handle_open_port(); -+ return -EPERM; -+#endif -+ -+ return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; -+} -+ -+static int open_mem(struct inode * inode, struct file * filp) -+{ - return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; - } - -@@ -568,7 +615,6 @@ - #define full_lseek null_lseek - #define write_zero write_null - #define read_full read_zero --#define open_mem open_port - #define open_kmem open_mem - - static struct file_operations mem_fops = { -@@ -666,6 +712,11 @@ - case 9: - filp->f_op = &urandom_fops; - break; -+#ifdef CONFIG_GRKERNSEC -+ case 10: -+ filp->f_op = &grsec_fops; -+ break; -+#endif - case 11: - filp->f_op = &kmsg_fops; - break; -@@ -697,6 +748,9 @@ - {7, "full", S_IRUGO | S_IWUGO, &full_fops}, - {8, "random", S_IRUGO | S_IWUSR, &random_fops}, - {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, -+#ifdef CONFIG_GRKERNSEC -+ {10,"grsec", S_IRUSR | S_IWUGO, &grsec_fops}, -+#endif - {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops}, - }; - -diff -urN linux-2.6.5/drivers/char/random.c linux-2.6.5/drivers/char/random.c ---- linux-2.6.5/drivers/char/random.c 2004-04-03 22:36:17.000000000 -0500 -+++ linux-2.6.5/drivers/char/random.c 2004-04-18 11:05:50.000000000 -0400 -@@ -263,9 +263,15 @@ - /* - * Configuration information - */ -+#ifdef CONFIG_GRKERNSEC_RANDNET -+#define DEFAULT_POOL_SIZE 1024 -+#define SECONDARY_POOL_SIZE 256 -+#define BATCH_ENTROPY_SIZE 512 -+#else - #define DEFAULT_POOL_SIZE 512 - #define SECONDARY_POOL_SIZE 128 - #define BATCH_ENTROPY_SIZE 256 -+#endif - #define USE_SHA - - /* -@@ -2361,6 +2367,29 @@ - return halfMD4Transform(hash, keyptr->secret); - } - -+#ifdef CONFIG_GRKERNSEC -+/* the following function is provided by PaX under the GPL */ -+unsigned long get_random_long(void) -+{ -+ static time_t rekey_time; -+ static __u32 secret[12]; -+ time_t t; -+ -+ /* -+ * Pick a random secret every REKEY_INTERVAL seconds -+ */ -+ t = get_seconds(); -+ if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) { -+ rekey_time = t; -+ get_random_bytes(secret, sizeof(secret)); -+ } -+ -+ secret[1] = halfMD4Transform(secret+8, secret); -+ secret[0] = halfMD4Transform(secret+8, secret); -+ return *(unsigned long *)secret; -+} -+#endif -+ - #ifdef CONFIG_SYN_COOKIES - /* - * Secure SYN cookie computation. This is the algorithm worked out by -@@ -2460,3 +2489,25 @@ - return (cookie - tmp[17]) & COOKIEMASK; /* Leaving the data behind */ - } - #endif -+ -+#ifdef CONFIG_PAX_ASLR -+unsigned long pax_get_random_long(void) -+{ -+ static time_t rekey_time; -+ static __u32 secret[12]; -+ time_t t; -+ -+ /* -+ * Pick a random secret every REKEY_INTERVAL seconds. -+ */ -+ t = get_seconds(); -+ if (!rekey_time || (t - rekey_time) > REKEY_INTERVAL) { -+ rekey_time = t; -+ get_random_bytes(secret, sizeof(secret)); -+ } -+ -+ secret[1] = halfMD4Transform(secret+8, secret); -+ secret[0] = halfMD4Transform(secret+8, secret); -+ return *(unsigned long *)secret; -+} -+#endif -diff -urN linux-2.6.5/drivers/char/vt_ioctl.c linux-2.6.5/drivers/char/vt_ioctl.c ---- linux-2.6.5/drivers/char/vt_ioctl.c 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/drivers/char/vt_ioctl.c 2004-04-18 11:05:50.000000000 -0400 -@@ -96,6 +96,12 @@ - case KDSKBENT: - if (!perm) - return -EPERM; -+ -+#ifdef CONFIG_GRKERNSEC -+ if (!capable(CAP_SYS_TTY_CONFIG)) -+ return -EPERM; -+#endif -+ - if (!i && v == K_NOSUCHMAP) { - /* disallocate map */ - key_map = key_maps[s]; -@@ -232,6 +238,13 @@ - goto reterr; - } - -+#ifdef CONFIG_GRKERNSEC -+ if (!capable(CAP_SYS_TTY_CONFIG)) { -+ return -EPERM; -+ goto reterr; -+ } -+#endif -+ - q = func_table[i]; - first_free = funcbufptr + (funcbufsize - funcbufleft); - for (j = i+1; j < MAX_NR_FUNC && !func_table[j]; j++) -diff -urN linux-2.6.5/drivers/pci/proc.c linux-2.6.5/drivers/pci/proc.c ---- linux-2.6.5/drivers/pci/proc.c 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/drivers/pci/proc.c 2004-04-18 11:05:50.000000000 -0400 -@@ -565,7 +565,15 @@ - - static void legacy_proc_init(void) - { -+#ifdef CONFIG_GRKERNSEC_PROC_ADD -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ struct proc_dir_entry * entry = create_proc_entry("pci", S_IRUSR, NULL); -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ struct proc_dir_entry * entry = create_proc_entry("pci", S_IRUSR | S_IRGRP, NULL); -+#endif -+#else - struct proc_dir_entry * entry = create_proc_entry("pci", 0, NULL); -+#endif - if (entry) - entry->proc_fops = &proc_pci_operations; - } -@@ -594,7 +602,15 @@ - { - struct proc_dir_entry *entry; - struct pci_dev *dev = NULL; -+#ifdef CONFIG_GRKERNSEC_PROC_ADD -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ proc_bus_pci_dir = proc_mkdir_mode("pci", S_IRUSR | S_IXUSR, proc_bus); -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ proc_bus_pci_dir = proc_mkdir_mode("pci", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, proc_bus); -+#endif -+#else - proc_bus_pci_dir = proc_mkdir("pci", proc_bus); -+#endif - entry = create_proc_entry("devices", 0, proc_bus_pci_dir); - if (entry) - entry->proc_fops = &proc_bus_pci_dev_operations; -diff -urN linux-2.6.5/drivers/pnp/pnpbios/bioscalls.c linux-2.6.5/drivers/pnp/pnpbios/bioscalls.c ---- linux-2.6.5/drivers/pnp/pnpbios/bioscalls.c 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/drivers/pnp/pnpbios/bioscalls.c 2004-04-18 11:05:50.000000000 -0400 -@@ -79,7 +79,7 @@ - set_limit(cpu_gdt_table[cpu][(selname) >> 3], size); \ - } while(0) - --static struct desc_struct bad_bios_desc = { 0, 0x00409200 }; -+static struct desc_struct bad_bios_desc = { 0, 0x00409300 }; - - /* - * At some point we want to use this stack frame pointer to unwind -@@ -107,6 +107,10 @@ - struct desc_struct save_desc_40; - int cpu; - -+#ifdef CONFIG_PAX_KERNEXEC -+ unsigned long cr3; -+#endif -+ - /* - * PnP BIOSes are generally not terribly re-entrant. - * Also, don't rely on them to save everything correctly. -@@ -115,11 +119,21 @@ - return PNP_FUNCTION_NOT_SUPPORTED; - - cpu = get_cpu(); -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_open_kernel(flags, cr3); -+#endif -+ - save_desc_40 = cpu_gdt_table[cpu][0x40 / 8]; - cpu_gdt_table[cpu][0x40 / 8] = bad_bios_desc; - - /* On some boxes IRQ's during PnP BIOS calls are deadly. */ -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ spin_lock_irq(&pnp_bios_lock); -+#else - spin_lock_irqsave(&pnp_bios_lock, flags); -+#endif - - /* The lock prevents us bouncing CPU here */ - if (ts1_size) -@@ -156,9 +170,19 @@ - "i" (0) - : "memory" - ); -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ spin_unlock_irq(&pnp_bios_lock); -+#else - spin_unlock_irqrestore(&pnp_bios_lock, flags); -+#endif - - cpu_gdt_table[cpu][0x40 / 8] = save_desc_40; -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_close_kernel(flags, cr3); -+#endif -+ - put_cpu(); - - /* If we get here and this is set then the PnP BIOS faulted on us. */ -diff -urN linux-2.6.5/drivers/scsi/scsi_devinfo.c linux-2.6.5/drivers/scsi/scsi_devinfo.c ---- linux-2.6.5/drivers/scsi/scsi_devinfo.c 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/drivers/scsi/scsi_devinfo.c 2004-04-18 11:05:50.000000000 -0400 -@@ -27,7 +27,7 @@ - static const char spaces[] = " "; /* 16 of them */ - static unsigned scsi_default_dev_flags; - static LIST_HEAD(scsi_dev_info_list); --static __init char scsi_dev_flags[256]; -+static __initdata char scsi_dev_flags[256]; - - /* - * scsi_static_device_list: deprecated list of devices that require -diff -urN linux-2.6.5/drivers/video/vesafb.c linux-2.6.5/drivers/video/vesafb.c ---- linux-2.6.5/drivers/video/vesafb.c 2004-04-03 22:36:17.000000000 -0500 -+++ linux-2.6.5/drivers/video/vesafb.c 2004-04-18 11:05:50.000000000 -0400 -@@ -239,7 +239,7 @@ - if (vesafb_fix.smem_len > 16 * 1024 * 1024) - vesafb_fix.smem_len = 16 * 1024 * 1024; - --#ifndef __i386__ -+#if !defined(__i386__) || defined(CONFIG_PAX_KERNEXEC) - screen_info.vesapm_seg = 0; - #endif - -diff -urN linux-2.6.5/fs/Kconfig linux-2.6.5/fs/Kconfig ---- linux-2.6.5/fs/Kconfig 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/fs/Kconfig 2004-04-18 11:05:50.000000000 -0400 -@@ -778,6 +778,7 @@ - - config PROC_KCORE - bool -+ depends on !GRKERNSEC_PROC_ADD - default y if !ARM - - config DEVFS_FS -diff -urN linux-2.6.5/fs/binfmt_aout.c linux-2.6.5/fs/binfmt_aout.c ---- linux-2.6.5/fs/binfmt_aout.c 2004-04-03 22:36:26.000000000 -0500 -+++ linux-2.6.5/fs/binfmt_aout.c 2004-04-18 11:05:50.000000000 -0400 -@@ -24,6 +24,7 @@ - #include <linux/binfmts.h> - #include <linux/personality.h> - #include <linux/init.h> -+#include <linux/grsecurity.h> - - #include <asm/system.h> - #include <asm/uaccess.h> -@@ -118,10 +119,12 @@ - /* If the size of the dump file exceeds the rlimit, then see what would happen - if we wrote the stack, but not the data area. */ - #ifdef __sparc__ -+ gr_learn_resource(current, RLIMIT_CORE, dump.u_dsize+dump.u_ssize, 1); - if ((dump.u_dsize+dump.u_ssize) > - current->rlim[RLIMIT_CORE].rlim_cur) - dump.u_dsize = 0; - #else -+ gr_learn_resource(current, RLIMIT_CORE, (dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE, 1); - if ((dump.u_dsize+dump.u_ssize+1) * PAGE_SIZE > - current->rlim[RLIMIT_CORE].rlim_cur) - dump.u_dsize = 0; -@@ -129,10 +132,12 @@ - - /* Make sure we have enough room to write the stack and data areas. */ - #ifdef __sparc__ -+ gr_learn_resource(current, RLIMIT_CORE, dump.u_ssize, 1); - if ((dump.u_ssize) > - current->rlim[RLIMIT_CORE].rlim_cur) - dump.u_ssize = 0; - #else -+ gr_learn_resource(current, RLIMIT_CORE, (dump.u_ssize+1) * PAGE_SIZE, 1); - if ((dump.u_ssize+1) * PAGE_SIZE > - current->rlim[RLIMIT_CORE].rlim_cur) - dump.u_ssize = 0; -@@ -281,6 +286,8 @@ - rlim = current->rlim[RLIMIT_DATA].rlim_cur; - if (rlim >= RLIM_INFINITY) - rlim = ~0; -+ -+ gr_learn_resource(current, RLIMIT_DATA, ex.a_data + ex.a_bss, 1); - if (ex.a_data + ex.a_bss > rlim) - return -ENOMEM; - -@@ -309,10 +316,33 @@ - (current->mm->start_brk = N_BSSADDR(ex)); - current->mm->free_area_cache = TASK_UNMAPPED_BASE; - -+#ifdef CONFIG_PAX_RANDMMAP -+ if (current->flags & PF_PAX_RANDMMAP) -+ current->mm->free_area_cache += current->mm->delta_mmap; -+#endif -+ - current->mm->rss = 0; - current->mm->mmap = NULL; - compute_creds(bprm); - current->flags &= ~PF_FORKNOEXEC; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (!(N_FLAGS(ex) & F_PAX_PAGEEXEC)) { -+ current->flags |= PF_PAX_PAGEEXEC; -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ if (N_FLAGS(ex) & F_PAX_EMUTRAMP) -+ current->flags |= PF_PAX_EMUTRAMP; -+#endif -+ -+#ifdef CONFIG_PAX_MPROTECT -+ if (!(N_FLAGS(ex) & F_PAX_MPROTECT)) -+ current->flags |= PF_PAX_MPROTECT; -+#endif -+ -+ } -+#endif -+ - #ifdef __sparc__ - if (N_MAGIC(ex) == NMAGIC) { - loff_t pos = fd_offset; -@@ -399,7 +429,7 @@ - - down_write(¤t->mm->mmap_sem); - error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, -- PROT_READ | PROT_WRITE | PROT_EXEC, -+ PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, - fd_offset + ex.a_text); - up_write(¤t->mm->mmap_sem); -diff -urN linux-2.6.5/fs/binfmt_elf.c linux-2.6.5/fs/binfmt_elf.c ---- linux-2.6.5/fs/binfmt_elf.c 2004-04-03 22:36:58.000000000 -0500 -+++ linux-2.6.5/fs/binfmt_elf.c 2004-04-18 11:05:50.000000000 -0400 -@@ -37,11 +37,17 @@ - #include <linux/pagemap.h> - #include <linux/security.h> - #include <linux/syscalls.h> -+#include <linux/random.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/param.h> - #include <asm/pgalloc.h> - -+#ifdef CONFIG_PAX_SEGMEXEC -+#include <asm/desc.h> -+#endif -+ - #include <linux/elf.h> - - static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs); -@@ -85,14 +91,22 @@ - - static int set_brk(unsigned long start, unsigned long end) - { -+ current->mm->start_brk = current->mm->brk = end; - start = ELF_PAGEALIGN(start); - end = ELF_PAGEALIGN(end); - if (end > start) { - unsigned long addr = do_brk(start, end - start); - if (BAD_ADDR(addr)) - return addr; -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ if (current->flags & PF_PAX_RANDEXEC) -+ addr = do_mmap_pgoff(NULL, ELF_PAGEALIGN(start + current->mm->delta_exec), 0UL, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED | MAP_MIRROR, start); -+ if (BAD_ADDR(addr)) -+ return addr; -+#endif -+ - } -- current->mm->start_brk = current->mm->brk = end; - return 0; - } - -@@ -444,6 +458,203 @@ - return elf_entry; - } - -+#if (defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS)) && defined(CONFIG_PAX_SOFTMODE) -+static unsigned long pax_parse_softmode(const struct elf_phdr * const elf_phdata) -+{ -+ unsigned long pax_flags = 0UL; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (elf_phdata->p_flags & PF_PAGEEXEC) -+ pax_flags |= PF_PAX_PAGEEXEC; -+#endif -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (elf_phdata->p_flags & PF_SEGMEXEC) { -+ pax_flags &= ~PF_PAX_PAGEEXEC; -+ pax_flags |= PF_PAX_SEGMEXEC; -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ if (elf_phdata->p_flags & PF_EMUTRAMP) -+ pax_flags |= PF_PAX_EMUTRAMP; -+#endif -+ -+#ifdef CONFIG_PAX_MPROTECT -+ if (elf_phdata->p_flags & PF_MPROTECT) -+ pax_flags |= PF_PAX_MPROTECT; -+#endif -+ -+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ if (pax_aslr) -+#endif -+ -+ if (elf_phdata->p_flags & PF_RANDMMAP) -+ pax_flags |= PF_PAX_RANDMMAP; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ if (pax_aslr) -+#endif -+ -+ if (elf_phdata->p_flags & PF_RANDEXEC) -+ pax_flags |= PF_PAX_RANDEXEC; -+#endif -+ -+ return pax_flags; -+} -+#endif -+ -+#ifdef CONFIG_PAX_PT_PAX_FLAGS -+static unsigned long pax_parse_hardmode(const struct elf_phdr * const elf_phdata) -+{ -+ unsigned long pax_flags = 0UL; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (!(elf_phdata->p_flags & PF_NOPAGEEXEC)) -+ pax_flags |= PF_PAX_PAGEEXEC; -+#endif -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (!(elf_phdata->p_flags & PF_NOSEGMEXEC)) { -+ pax_flags &= ~PF_PAX_PAGEEXEC; -+ pax_flags |= PF_PAX_SEGMEXEC; -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ if (!(elf_phdata->p_flags & PF_NOEMUTRAMP)) -+ pax_flags |= PF_PAX_EMUTRAMP; -+#endif -+ -+#ifdef CONFIG_PAX_MPROTECT -+ if (!(elf_phdata->p_flags & PF_NOMPROTECT)) -+ pax_flags |= PF_PAX_MPROTECT; -+#endif -+ -+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ if (pax_aslr) -+#endif -+ -+ if (!(elf_phdata->p_flags & PF_NORANDMMAP)) -+ pax_flags |= PF_PAX_RANDMMAP; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ if (pax_aslr) -+#endif -+ -+ if (!(elf_phdata->p_flags & PF_NORANDEXEC)) -+ pax_flags |= PF_PAX_RANDEXEC; -+#endif -+ -+ return pax_flags; -+} -+#endif -+ -+#ifdef CONFIG_PAX_EI_PAX -+static int pax_parse_ei_pax(const struct elfhdr * const elf_ex) -+{ -+ unsigned long pax_flags = 0UL; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_PAGEEXEC)) -+ pax_flags |= PF_PAX_PAGEEXEC; -+#endif -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_SEGMEXEC)) { -+ pax_flags &= ~PF_PAX_PAGEEXEC; -+ pax_flags |= PF_PAX_SEGMEXEC; -+ } -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ if ((pax_flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) && (elf_ex->e_ident[EI_PAX] & EF_PAX_EMUTRAMP)) -+ pax_flags |= PF_PAX_EMUTRAMP; -+#endif -+ -+#ifdef CONFIG_PAX_MPROTECT -+ if ((pax_flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) && !(elf_ex->e_ident[EI_PAX] & EF_PAX_MPROTECT)) -+ pax_flags |= PF_PAX_MPROTECT; -+#endif -+ -+#ifdef CONFIG_PAX_ASLR -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ if (pax_aslr) -+#endif -+ -+ if (!(elf_ex->e_ident[EI_PAX] & EF_PAX_RANDMMAP)) -+ pax_flags |= PF_PAX_RANDMMAP; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ if (pax_aslr) -+#endif -+ -+ if ((elf_ex->e_ident[EI_PAX] & EF_PAX_RANDEXEC) && (elf_ex->e_type == ET_EXEC) && (pax_flags & PF_PAX_MPROTECT)) -+ pax_flags |= PF_PAX_RANDEXEC; -+#endif -+ -+ return pax_flags; -+} -+#endif -+ -+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS) -+static int pax_parse_elf_flags(const struct elfhdr * const elf_ex, const struct elf_phdr * const elf_phdata) -+{ -+ unsigned long pax_flags = 0UL; -+ -+#ifdef CONFIG_PAX_PT_PAX_FLAGS -+ unsigned long i; -+#endif -+ -+#ifdef CONFIG_PAX_EI_PAX -+ pax_flags = pax_parse_ei_pax(elf_ex); -+#endif -+ -+#ifdef CONFIG_PAX_PT_PAX_FLAGS -+ for (i = 0UL; i < elf_ex->e_phnum; i++) -+ if (elf_phdata[i].p_type == PT_PAX_FLAGS) { -+ if (((elf_phdata[i].p_flags & PF_PAGEEXEC) && (elf_phdata[i].p_flags & PF_NOPAGEEXEC)) || -+ ((elf_phdata[i].p_flags & PF_SEGMEXEC) && (elf_phdata[i].p_flags & PF_NOSEGMEXEC)) || -+ ((elf_phdata[i].p_flags & PF_EMUTRAMP) && (elf_phdata[i].p_flags & PF_NOEMUTRAMP)) || -+ ((elf_phdata[i].p_flags & PF_MPROTECT) && (elf_phdata[i].p_flags & PF_NOMPROTECT)) || -+ ((elf_phdata[i].p_flags & PF_RANDMMAP) && (elf_phdata[i].p_flags & PF_NORANDMMAP)) || -+ ((elf_phdata[i].p_flags & PF_RANDEXEC) && ((elf_phdata[i].p_flags & PF_NORANDEXEC) || elf_ex->e_type == ET_DYN || !(elf_phdata[i].p_flags & PF_MPROTECT))) || -+ (!(elf_phdata[i].p_flags & PF_NORANDEXEC) && (elf_ex->e_type == ET_DYN || (elf_phdata[i].p_flags & PF_NOMPROTECT)))) -+ return -EINVAL; -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ if (pax_softmode) -+ pax_flags = pax_parse_softmode(&elf_phdata[i]); -+ else -+#endif -+ -+ pax_flags = pax_parse_hardmode(&elf_phdata[i]); -+ break; -+ } -+#endif -+ -+ if (0 > pax_check_flags(&pax_flags)) -+ return -EINVAL; -+ -+ current->flags |= pax_flags; -+ return 0; -+} -+#endif -+ - /* - * These are the functions used to load ELF style executables and shared - * libraries. There is no binary dependent code anywhere else. -@@ -476,7 +687,12 @@ - struct exec interp_ex; - char passed_fileno[6]; - struct files_struct *files; -- -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ unsigned long load_addr_random = 0UL; -+ unsigned long load_bias_random = 0UL; -+#endif -+ - /* Get the exec-header */ - elf_ex = *((struct elfhdr *) bprm->buf); - -@@ -664,8 +880,44 @@ - current->mm->end_data = 0; - current->mm->end_code = 0; - current->mm->mmap = NULL; -+ -+#ifdef CONFIG_PAX_ASLR -+ current->mm->delta_mmap = 0UL; -+ current->mm->delta_exec = 0UL; -+ current->mm->delta_stack = 0UL; -+#endif -+ - current->flags &= ~PF_FORKNOEXEC; - -+#if defined(CONFIG_PAX_EI_PAX) || defined(CONFIG_PAX_PT_PAX_FLAGS) -+ if (0 > pax_parse_elf_flags(&elf_ex, elf_phdata)) { -+ send_sig(SIGKILL, current, 0); -+ goto out_free_dentry; -+ } -+#endif -+ -+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS -+ pax_set_flags(bprm); -+#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS) -+ if (pax_set_flags_func) -+ (pax_set_flags_func)(bprm); -+#endif -+ -+#ifdef CONFIG_PAX_DLRESOLVE -+ if (current->flags & PF_PAX_PAGEEXEC) -+ current->mm->call_dl_resolve = 0UL; -+#endif -+ -+#ifdef CONFIG_PAX_ASLR -+ if (current->flags & PF_PAX_RANDMMAP) { -+#define pax_delta_mask(delta, lsb, len) (((delta) & ((1UL << (len)) - 1)) << (lsb)) -+ -+ current->mm->delta_mmap = pax_delta_mask(pax_get_random_long(), PAX_DELTA_MMAP_LSB(current), PAX_DELTA_MMAP_LEN(current)); -+ current->mm->delta_exec = pax_delta_mask(pax_get_random_long(), PAX_DELTA_EXEC_LSB(current), PAX_DELTA_EXEC_LEN(current)); -+ current->mm->delta_stack = pax_delta_mask(pax_get_random_long(), PAX_DELTA_STACK_LSB(current), PAX_DELTA_STACK_LEN(current)); -+ } -+#endif -+ - /* Do this immediately, since STACK_TOP as used in setup_arg_pages - may depend on the personality. */ - SET_PERSONALITY(elf_ex, ibcs2_interpreter); -@@ -674,6 +926,12 @@ - change some of these later */ - current->mm->rss = 0; - current->mm->free_area_cache = TASK_UNMAPPED_BASE; -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if (current->flags & PF_PAX_RANDMMAP) -+ current->mm->free_area_cache += current->mm->delta_mmap; -+#endif -+ - retval = setup_arg_pages(bprm); - if (retval < 0) { - send_sig(SIGKILL, current, 0); -@@ -729,11 +987,85 @@ - base, as well as whatever program they might try to exec. This - is because the brk will follow the loader, and is not movable. */ - load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ /* PaX: randomize base address at the default exe base if requested */ -+ if (current->flags & PF_PAX_RANDMMAP) { -+ load_bias = ELF_PAGESTART(PAX_ELF_ET_DYN_BASE(current) - vaddr + current->mm->delta_exec); -+ elf_flags |= MAP_FIXED; -+ } -+#endif -+ - } - -- error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); -- if (BAD_ADDR(error)) -- continue; -+#ifdef CONFIG_PAX_RANDEXEC -+ if ((current->flags & PF_PAX_RANDEXEC) && (elf_ex.e_type == ET_EXEC)) { -+ error = -ENOMEM; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (current->flags & PF_PAX_PAGEEXEC) -+ error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot & ~PROT_EXEC, elf_flags); -+#endif -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) { -+ unsigned long addr, len; -+ -+ addr = ELF_PAGESTART(load_bias + vaddr); -+ len = elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr); -+ if (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len) -+ continue; -+ down_write(¤t->mm->mmap_sem); -+ error = do_mmap_pgoff(bprm->file, addr, len, elf_prot, elf_flags, (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr)) >> PAGE_SHIFT); -+ up_write(¤t->mm->mmap_sem); -+ } -+#endif -+ -+ if (BAD_ADDR(error)) -+ continue; -+ -+ /* PaX: mirror at a randomized base */ -+ down_write(¤t->mm->mmap_sem); -+ -+ if (!load_addr_set) { -+ load_addr_random = get_unmapped_area(bprm->file, 0UL, elf_ppnt->p_filesz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr), (elf_ppnt->p_offset - ELF_PAGEOFFSET(elf_ppnt->p_vaddr)) >> PAGE_SHIFT, MAP_PRIVATE); -+ if (BAD_ADDR(load_addr_random)) { -+ up_write(¤t->mm->mmap_sem); -+ continue; -+ } -+ load_bias_random = load_addr_random - vaddr; -+ } -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (current->flags & PF_PAX_PAGEEXEC) -+ load_addr_random = do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr), 0UL, elf_prot, elf_flags | MAP_MIRROR, error); -+#endif -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) { -+ if (elf_prot & PROT_EXEC) { -+ load_addr_random = do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr), elf_ppnt->p_memsz + ELF_PAGEOFFSET(elf_ppnt->p_vaddr), PROT_NONE, MAP_PRIVATE | MAP_FIXED, 0UL); -+ if (!BAD_ADDR(load_addr_random)) { -+ load_addr_random = do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr + SEGMEXEC_TASK_SIZE), 0UL, elf_prot, elf_flags | MAP_MIRROR, error); -+ if (!BAD_ADDR(load_addr_random)) -+ load_addr_random -= SEGMEXEC_TASK_SIZE; -+ } -+ } else -+ load_addr_random = do_mmap_pgoff(NULL, ELF_PAGESTART(load_bias_random + vaddr), 0UL, elf_prot, elf_flags | MAP_MIRROR, error); -+ } -+#endif -+ -+ up_write(¤t->mm->mmap_sem); -+ if (BAD_ADDR(load_addr_random)) -+ continue; -+ } else -+#endif -+ -+ { -+ error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); -+ if (BAD_ADDR(error)) -+ continue; -+ } - - if (!load_addr_set) { - load_addr_set = 1; -@@ -744,6 +1076,11 @@ - load_addr += load_bias; - reloc_func_desc = load_bias; - } -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ current->mm->delta_exec = load_addr_random - load_addr; -+#endif -+ - } - k = elf_ppnt->p_vaddr; - if (k < start_code) start_code = k; -@@ -770,6 +1107,16 @@ - start_data += load_bias; - end_data += load_bias; - -+#ifdef CONFIG_PAX_RANDMMAP -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ if (pax_aslr) -+#endif -+ -+ elf_brk += pax_delta_mask(pax_get_random_long(), 4, PAGE_SHIFT); -+#undef pax_delta_mask -+#endif -+ - /* Calling set_brk effectively mmaps the pages that we need - * for the bss and break sections. We must do this before - * mapping in the interpreter, to make sure it doesn't wind -@@ -850,6 +1197,26 @@ - ELF_PLAT_INIT(regs, reloc_func_desc); - #endif - -+#ifdef CONFIG_PAX_SEGMEXEC -+ i = get_cpu(); -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ { -+ unsigned long flags, cr3; -+ -+ pax_open_kernel(flags, cr3); -+#endif -+ -+ pax_switch_segments(current, i); -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_close_kernel(flags, cr3); -+ } -+#endif -+ -+ put_cpu(); -+#endif -+ - start_thread(regs, elf_entry, bprm->p); - if (unlikely(current->ptrace & PT_PTRACED)) { - if (current->ptrace & PT_TRACE_EXEC) -@@ -1062,8 +1429,11 @@ - #undef DUMP_SEEK - - #define DUMP_WRITE(addr, nr) \ -+ do { \ -+ gr_learn_resource(current, RLIMIT_CORE, size + (nr), 1); \ - if ((size += (nr)) > limit || !dump_write(file, (addr), (nr))) \ -- goto end_coredump; -+ goto end_coredump; \ -+ } while (0); - #define DUMP_SEEK(off) \ - if (!dump_seek(file, (off))) \ - goto end_coredump; -diff -urN linux-2.6.5/fs/binfmt_misc.c linux-2.6.5/fs/binfmt_misc.c ---- linux-2.6.5/fs/binfmt_misc.c 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/fs/binfmt_misc.c 2004-04-18 11:05:50.000000000 -0400 -@@ -108,9 +108,11 @@ - int retval; - - retval = -ENOEXEC; -- if (!enabled) -+ if (!enabled || bprm->misc) - goto _ret; - -+ bprm->misc++; -+ - /* to keep locking time low, we copy the interpreter string */ - read_lock(&entries_lock); - fmt = check_file(bprm); -diff -urN linux-2.6.5/fs/buffer.c linux-2.6.5/fs/buffer.c ---- linux-2.6.5/fs/buffer.c 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/fs/buffer.c 2004-04-18 11:05:50.000000000 -0400 -@@ -37,6 +37,7 @@ - #include <linux/bio.h> - #include <linux/notifier.h> - #include <linux/cpu.h> -+#include <linux/grsecurity.h> - #include <asm/bitops.h> - - static void invalidate_bh_lrus(void); -@@ -2162,6 +2163,9 @@ - int err; - - err = -EFBIG; -+ -+ gr_learn_resource(current, RLIMIT_FSIZE, (unsigned long) size, 1); -+ - limit = current->rlim[RLIMIT_FSIZE].rlim_cur; - if (limit != RLIM_INFINITY && size > (loff_t)limit) { - send_sig(SIGXFSZ, current, 0); -diff -urN linux-2.6.5/fs/dcache.c linux-2.6.5/fs/dcache.c ---- linux-2.6.5/fs/dcache.c 2004-04-03 22:36:24.000000000 -0500 -+++ linux-2.6.5/fs/dcache.c 2004-04-18 11:05:50.000000000 -0400 -@@ -1256,7 +1256,7 @@ - * - * "buflen" should be positive. Caller holds the dcache_lock. - */ --static char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt, -+char * __d_path( struct dentry *dentry, struct vfsmount *vfsmnt, - struct dentry *root, struct vfsmount *rootmnt, - char *buffer, int buflen) - { -diff -urN linux-2.6.5/fs/exec.c linux-2.6.5/fs/exec.c ---- linux-2.6.5/fs/exec.c 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/fs/exec.c 2004-04-18 11:05:50.000000000 -0400 -@@ -46,6 +46,8 @@ - #include <linux/security.h> - #include <linux/syscalls.h> - #include <linux/rmap-locking.h> -+#include <linux/random.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/pgalloc.h> -@@ -62,6 +64,20 @@ - static struct linux_binfmt *formats; - static rwlock_t binfmt_lock = RW_LOCK_UNLOCKED; - -+#ifdef CONFIG_PAX_SOFTMODE -+ -+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) || defined(CONFIG_PAX_RANDKSTACK) -+unsigned int pax_aslr=1; -+#endif -+ -+unsigned int pax_softmode; -+#endif -+ -+#ifdef CONFIG_PAX_HOOK_ACL_FLAGS -+void (*pax_set_flags_func)(struct linux_binprm * bprm); -+EXPORT_SYMBOL(pax_set_flags_func); -+#endif -+ - int register_binfmt(struct linux_binfmt * fmt) - { - struct linux_binfmt ** tmp = &formats; -@@ -303,7 +319,12 @@ - pte_t * pte; - struct pte_chain *pte_chain; - -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (page_count(page) != 1 && (!(tsk->flags & PF_PAX_SEGMEXEC) || page_count(page) != 3)) -+#else - if (page_count(page) != 1) -+#endif -+ - printk(KERN_ERR "mem_map disagrees with %p at %08lx\n", - page, address); - -@@ -322,8 +343,18 @@ - pte_unmap(pte); - goto out; - } -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (page_count(page) == 1) { -+#endif -+ - lru_cache_add_active(page); - flush_dcache_page(page); -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ } -+#endif -+ - set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, prot)))); - pte_chain = page_add_rmap(page, pte, pte_chain); - pte_unmap(pte); -@@ -350,6 +381,10 @@ - int i; - long arg_size; - -+#ifdef CONFIG_PAX_SEGMEXEC -+ struct vm_area_struct *mpnt_m = NULL; -+#endif -+ - #ifdef CONFIG_STACK_GROWSUP - /* Move the argument and environment strings to the bottom of the - * stack space. -@@ -409,6 +444,16 @@ - if (!mpnt) - return -ENOMEM; - -+#ifdef CONFIG_PAX_SEGMEXEC -+ if ((current->flags & PF_PAX_SEGMEXEC) && (VM_STACK_FLAGS & VM_MAYEXEC)) { -+ mpnt_m = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); -+ if (!mpnt_m) { -+ kmem_cache_free(vm_area_cachep, mpnt); -+ return -ENOMEM; -+ } -+ } -+#endif -+ - if (security_vm_enough_memory(arg_size >> PAGE_SHIFT)) { - kmem_cache_free(vm_area_cachep, mpnt); - return -ENOMEM; -@@ -425,6 +470,13 @@ - mpnt->vm_start = PAGE_MASK & (unsigned long) bprm->p; - mpnt->vm_end = STACK_TOP; - #endif -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (!(current->flags & PF_PAX_PAGEEXEC)) -+ mpnt->vm_page_prot = protection_map[(VM_STACK_FLAGS | VM_EXEC) & 0x7]; -+ else -+#endif -+ - mpnt->vm_page_prot = protection_map[VM_STACK_FLAGS & 0x7]; - mpnt->vm_flags = VM_STACK_FLAGS; - mpnt->vm_ops = NULL; -@@ -434,6 +486,26 @@ - mpnt->vm_private_data = (void *) 0; - insert_vm_struct(mm, mpnt); - mm->total_vm = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (mpnt_m) { -+ *mpnt_m = *mpnt; -+ INIT_LIST_HEAD(&mpnt_m->shared); -+ if (!(VM_STACK_FLAGS & VM_EXEC)) { -+ mpnt_m->vm_flags &= ~(VM_READ | VM_WRITE | VM_EXEC); -+ mpnt_m->vm_page_prot = PAGE_NONE; -+ } -+ mpnt_m->vm_start += SEGMEXEC_TASK_SIZE; -+ mpnt_m->vm_end += SEGMEXEC_TASK_SIZE; -+ mpnt_m->vm_flags |= VM_MIRROR; -+ mpnt->vm_flags |= VM_MIRROR; -+ mpnt_m->vm_private_data = (void *)(mpnt->vm_start - mpnt_m->vm_start); -+ mpnt->vm_private_data = (void *)(mpnt_m->vm_start - mpnt->vm_start); -+ insert_vm_struct(mm, mpnt_m); -+ current->mm->total_vm = (mpnt_m->vm_end - mpnt_m->vm_start) >> PAGE_SHIFT; -+ } -+#endif -+ - } - - for (i = 0 ; i < MAX_ARG_PAGES ; i++) { -@@ -442,6 +514,15 @@ - bprm->page[i] = NULL; - put_dirty_page(current, page, stack_base, - mpnt->vm_page_prot); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) && defined(CONFIG_PAX_MPROTECT) -+ if (mpnt_m) { -+ page_cache_get(page); -+ put_dirty_page(current, page, stack_base + SEGMEXEC_TASK_SIZE, -+ mpnt_m->vm_page_prot); -+ } -+#endif -+ - } - stack_base += PAGE_SIZE; - } -@@ -830,6 +911,30 @@ - } - current->comm[i] = '\0'; - -+#ifdef CONFIG_PAX_PAGEEXEC -+ current->flags &= ~PF_PAX_PAGEEXEC; -+#endif -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ current->flags &= ~PF_PAX_EMUTRAMP; -+#endif -+ -+#ifdef CONFIG_PAX_MPROTECT -+ current->flags &= ~PF_PAX_MPROTECT; -+#endif -+ -+#ifdef CONFIG_PAX_ASLR -+ current->flags &= ~PF_PAX_RANDMMAP; -+#endif -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ current->flags &= ~PF_PAX_RANDEXEC; -+#endif -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ current->flags &= ~PF_PAX_SEGMEXEC; -+#endif -+ - flush_thread(); - - if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || -@@ -908,6 +1013,9 @@ - if (retval) - return retval; - -+ if (gr_handle_ptrace_exec(bprm->file->f_dentry, bprm->file->f_vfsmnt)) -+ return -EACCES; -+ - memset(bprm->buf,0,BINPRM_BUF_SIZE); - return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE); - } -@@ -946,8 +1054,13 @@ - } - } - -- current->suid = current->euid = current->fsuid = bprm->e_uid; -- current->sgid = current->egid = current->fsgid = bprm->e_gid; -+ if (!gr_check_user_change(-1, bprm->e_uid, bprm->e_uid)) -+ current->suid = current->euid = current->fsuid = bprm->e_uid; -+ -+ if (!gr_check_group_change(-1, bprm->e_gid, bprm->e_gid)) -+ current->sgid = current->egid = current->fsgid = bprm->e_gid; -+ -+ gr_handle_chroot_caps(current); - - task_unlock(current); - -@@ -1091,6 +1204,11 @@ - struct file *file; - int retval; - int i; -+#ifdef CONFIG_GRKERNSEC -+ struct file *old_exec_file; -+ struct acl_subject_label *old_acl; -+ struct rlimit old_rlim[RLIM_NLIMITS]; -+#endif - - sched_balance_exec(); - -@@ -1100,13 +1218,39 @@ - if (IS_ERR(file)) - return retval; - -+ gr_learn_resource(current, RLIMIT_NPROC, atomic_read(¤t->user->processes), 1); -+ -+ if (gr_handle_nproc()) { -+ allow_write_access(file); -+ fput(file); -+ return -EAGAIN; -+ } -+ -+ if (!gr_acl_handle_execve(file->f_dentry, file->f_vfsmnt)) { -+ allow_write_access(file); -+ fput(file); -+ return -EACCES; -+ } -+ -+ - bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); -+ -+#ifdef CONFIG_PAX_RANDUSTACK -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ if (pax_aslr) -+#endif -+ -+ bprm.p -= (pax_get_random_long() & ~(sizeof(void *)-1)) & ~PAGE_MASK; -+#endif -+ - memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); - - bprm.file = file; - bprm.filename = filename; - bprm.interp = filename; - bprm.sh_bang = 0; -+ bprm.misc = 0; - bprm.loader = 0; - bprm.exec = 0; - bprm.security = NULL; -@@ -1135,11 +1279,26 @@ - if (retval < 0) - goto out; - -+ if (!gr_tpe_allow(file)) { -+ retval = -EACCES; -+ goto out; -+ } -+ -+ if (gr_check_crash_exec(file)) { -+ retval = -EACCES; -+ goto out; -+ } -+ - retval = copy_strings_kernel(1, &bprm.filename, &bprm); - if (retval < 0) - goto out; - - bprm.exec = bprm.p; -+ -+ gr_log_chroot_exec(file->f_dentry, file->f_vfsmnt); -+ -+ gr_handle_exec_args(&bprm, argv); -+ - retval = copy_strings(bprm.envc, envp, &bprm); - if (retval < 0) - goto out; -@@ -1148,8 +1307,22 @@ - if (retval < 0) - goto out; - -+#ifdef CONFIG_GRKERNSEC -+ old_acl = current->acl; -+ memcpy(old_rlim, current->rlim, sizeof(old_rlim)); -+ old_exec_file = current->exec_file; -+ get_file(file); -+ current->exec_file = file; -+#endif -+ -+ gr_set_proc_label(file->f_dentry, file->f_vfsmnt); -+ - retval = search_binary_handler(&bprm,regs); - if (retval >= 0) { -+#ifdef CONFIG_GRKERNSEC -+ if (old_exec_file) -+ fput(old_exec_file); -+#endif - free_arg_pages(&bprm); - - /* execve success */ -@@ -1157,6 +1330,13 @@ - return retval; - } - -+#ifdef CONFIG_GRKERNSEC -+ current->acl = old_acl; -+ memcpy(current->rlim, old_rlim, sizeof(old_rlim)); -+ fput(current->exec_file); -+ current->exec_file = old_exec_file; -+#endif -+ - out: - /* Something went wrong, return the inode and free the argument pages*/ - for (i = 0 ; i < MAX_ARG_PAGES ; i++) { -@@ -1314,6 +1494,128 @@ - *out_ptr = 0; - } - -+int pax_check_flags(unsigned long * flags) -+{ -+ int retval = 0; -+ -+#if !defined(__i386__) || !defined(CONFIG_PAX_SEGMEXEC) -+ if (*flags & PF_PAX_SEGMEXEC) -+ { -+ *flags &= ~PF_PAX_SEGMEXEC; -+ retval = -EINVAL; -+ } -+#endif -+ -+ if ((*flags & PF_PAX_PAGEEXEC) -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ && (*flags & PF_PAX_SEGMEXEC) -+#endif -+ -+ ) -+ { -+ *flags &= ~PF_PAX_PAGEEXEC; -+ retval = -EINVAL; -+ } -+ -+ if ((*flags & PF_PAX_MPROTECT) -+ -+#ifdef CONFIG_PAX_MPROTECT -+ && !(*flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) -+#endif -+ -+ ) -+ { -+ *flags &= ~PF_PAX_MPROTECT; -+ retval = -EINVAL; -+ } -+ -+ if ((*flags & PF_PAX_EMUTRAMP) -+ -+#ifdef CONFIG_PAX_EMUTRAMP -+ && !(*flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) -+#endif -+ -+ ) -+ { -+ *flags &= ~PF_PAX_EMUTRAMP; -+ retval = -EINVAL; -+ } -+ -+ if ((*flags & PF_PAX_RANDEXEC) -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ && !(*flags & PF_PAX_MPROTECT) -+#endif -+ -+ ) -+ { -+ *flags &= ~PF_PAX_RANDEXEC; -+ retval = -EINVAL; -+ } -+ -+ return retval; -+} -+ -+EXPORT_SYMBOL(pax_check_flags); -+ -+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) -+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp) -+{ -+ struct task_struct *tsk = current; -+ struct mm_struct *mm = current->mm; -+ char* buffer_exec = (char*)__get_free_page(GFP_ATOMIC); -+ char* buffer_fault = (char*)__get_free_page(GFP_ATOMIC); -+ char* path_exec=NULL; -+ char* path_fault=NULL; -+ unsigned long start=0UL, end=0UL, offset=0UL; -+ -+ if (buffer_exec && buffer_fault) { -+ struct vm_area_struct* vma, * vma_exec=NULL, * vma_fault=NULL; -+ -+ down_read(&mm->mmap_sem); -+ vma = mm->mmap; -+ while (vma && (!vma_exec || !vma_fault)) { -+ if ((vma->vm_flags & VM_EXECUTABLE) && vma->vm_file) -+ vma_exec = vma; -+ if (vma->vm_start <= (unsigned long)pc && (unsigned long)pc < vma->vm_end) -+ vma_fault = vma; -+ vma = vma->vm_next; -+ } -+ if (vma_exec) { -+ path_exec = d_path(vma_exec->vm_file->f_dentry, vma_exec->vm_file->f_vfsmnt, buffer_exec, PAGE_SIZE); -+ if (IS_ERR(path_exec)) -+ path_exec = "<path too long>"; -+ } -+ if (vma_fault) { -+ start = vma_fault->vm_start; -+ end = vma_fault->vm_end; -+ offset = vma_fault->vm_pgoff << PAGE_SHIFT; -+ if (vma_fault->vm_file) { -+ path_fault = d_path(vma_fault->vm_file->f_dentry, vma_fault->vm_file->f_vfsmnt, buffer_fault, PAGE_SIZE); -+ if (IS_ERR(path_fault)) -+ path_fault = "<path too long>"; -+ } else -+ path_fault = "<anonymous mapping>"; -+ } -+ up_read(&mm->mmap_sem); -+ } -+#ifdef CONFIG_GRKERNSEC -+ if (tsk->curr_ip) -+ printk(KERN_ERR "PAX: execution attempt from %u.%u.%u.%u in: %s, %08lx-%08lx %08lx\n", NIPQUAD(tsk->curr_ip), path_fault, start, end, offset); -+ else -+#endif -+ printk(KERN_ERR "PAX: execution attempt in: %s, %08lx-%08lx %08lx\n", path_fault, start, end, offset); -+ printk(KERN_ERR "PAX: terminating task: %s(%s):%d, uid/euid: %u/%u, " -+ "PC: %p, SP: %p\n", path_exec, tsk->comm, tsk->pid, -+ tsk->uid, tsk->euid, pc, sp); -+ if (buffer_exec) free_page((unsigned long)buffer_exec); -+ if (buffer_fault) free_page((unsigned long)buffer_fault); -+ pax_report_insns(pc, sp); -+ do_coredump(SIGKILL, SIGKILL, regs); -+} -+#endif -+ - static void zap_threads (struct mm_struct *mm) - { - struct task_struct *g, *p; -@@ -1383,6 +1685,7 @@ - current->signal->group_exit_code = exit_code; - coredump_wait(mm); - -+ gr_learn_resource(current, RLIMIT_CORE, binfmt->min_coredump, 1); - if (current->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump) - goto fail_unlock; - -@@ -1402,7 +1705,7 @@ - goto close_fail; - if (!file->f_op->write) - goto close_fail; -- if (do_truncate(file->f_dentry, 0) != 0) -+ if (do_truncate(file->f_dentry, 0, file->f_vfsmnt) != 0) - goto close_fail; - - retval = binfmt->core_dump(signr, regs, file); -diff -urN linux-2.6.5/fs/fcntl.c linux-2.6.5/fs/fcntl.c ---- linux-2.6.5/fs/fcntl.c 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/fs/fcntl.c 2004-04-18 11:05:50.000000000 -0400 -@@ -14,6 +14,7 @@ - #include <linux/module.h> - #include <linux/security.h> - #include <linux/ptrace.h> -+#include <linux/grsecurity.h> - - #include <asm/poll.h> - #include <asm/siginfo.h> -@@ -86,6 +87,9 @@ - int error; - - error = -EINVAL; -+ -+ gr_learn_resource(current, RLIMIT_NOFILE, orig_start, 0); -+ - if (orig_start >= current->rlim[RLIMIT_NOFILE].rlim_cur) - goto out; - -@@ -105,6 +109,9 @@ - } - - error = -EMFILE; -+ -+ gr_learn_resource(current, RLIMIT_NOFILE, newfd, 0); -+ - if (newfd >= current->rlim[RLIMIT_NOFILE].rlim_cur) - goto out; - -@@ -154,6 +161,8 @@ - struct file * file, *tofree; - struct files_struct * files = current->files; - -+ gr_learn_resource(current, RLIMIT_NOFILE, newfd, 0); -+ - spin_lock(&files->file_lock); - if (!(file = fcheck(oldfd))) - goto out_unlock; -@@ -485,13 +494,15 @@ - if (pid > 0) { - p = find_task_by_pid(pid); - if (p) { -- send_sigio_to_task(p, fown, fd, band); -+ if (!gr_check_protected_task(p)) -+ send_sigio_to_task(p, fown, fd, band); - } - } else { - struct list_head *l; - struct pid *pidptr; - for_each_task_pid(-pid, PIDTYPE_PGID, p, l, pidptr) { -- send_sigio_to_task(p, fown, fd, band); -+ if (!gr_check_protected_task(p) && !gr_pid_is_chrooted(p)) -+ send_sigio_to_task(p, fown, fd, band); - } - } - read_unlock(&tasklist_lock); -diff -urN linux-2.6.5/fs/namei.c linux-2.6.5/fs/namei.c ---- linux-2.6.5/fs/namei.c 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/fs/namei.c 2004-04-18 11:05:50.000000000 -0400 -@@ -26,6 +26,7 @@ - #include <linux/personality.h> - #include <linux/security.h> - #include <linux/mount.h> -+#include <linux/grsecurity.h> - #include <asm/namei.h> - #include <asm/uaccess.h> - -@@ -410,6 +411,13 @@ - err = security_inode_follow_link(dentry, nd); - if (err) - goto loop; -+ -+ if (gr_handle_follow_link(dentry->d_parent->d_inode, -+ dentry->d_inode, dentry, nd->mnt)) { -+ err = -EACCES; -+ goto loop; -+ } -+ - current->link_count++; - current->total_link_count++; - touch_atime(nd->mnt, dentry); -@@ -761,6 +769,10 @@ - break; - } - return_base: -+ if (!gr_acl_handle_hidden_file(nd->dentry, nd->mnt)) { -+ path_release(nd); -+ return -ENOENT; -+ } - return 0; - out_dput: - dput(next.dentry); -@@ -1214,7 +1226,7 @@ - if (!error) { - DQUOT_INIT(inode); - -- error = do_truncate(dentry, 0); -+ error = do_truncate(dentry, 0, nd->mnt); - } - put_write_access(inode); - if (error) -@@ -1265,6 +1277,17 @@ - error = path_lookup(pathname, lookup_flags(flag)|LOOKUP_OPEN, nd); - if (error) - return error; -+ -+ if (gr_handle_rawio(nd->dentry->d_inode)) { -+ error = -EPERM; -+ goto exit; -+ } -+ -+ if (!gr_acl_handle_open(nd->dentry, nd->mnt, flag)) { -+ error = -EACCES; -+ goto exit; -+ } -+ - goto ok; - } - -@@ -1298,9 +1321,19 @@ - - /* Negative dentry, just create the file */ - if (!dentry->d_inode) { -+ if (!gr_acl_handle_creat(dentry, nd->dentry, nd->mnt, flag, mode)) { -+ error = -EACCES; -+ up(&dir->d_inode->i_sem); -+ goto exit_dput; -+ } -+ - if (!IS_POSIXACL(dir->d_inode)) - mode &= ~current->fs->umask; - error = vfs_create(dir->d_inode, dentry, mode, nd); -+ -+ if (!error) -+ gr_handle_create(dentry, nd->mnt); -+ - up(&dir->d_inode->i_sem); - dput(nd->dentry); - nd->dentry = dentry; -@@ -1315,6 +1348,25 @@ - /* - * It already exists. - */ -+ -+ if (gr_handle_rawio(dentry->d_inode)) { -+ error = -EPERM; -+ up(&dir->d_inode->i_sem); -+ goto exit_dput; -+ } -+ -+ if (!gr_acl_handle_open(dentry, nd->mnt, flag)) { -+ up(&dir->d_inode->i_sem); -+ error = -EACCES; -+ goto exit_dput; -+ } -+ -+ if (gr_handle_fifo(dentry, nd->mnt, dir, flag, acc_mode)) { -+ up(&dir->d_inode->i_sem); -+ error = -EACCES; -+ goto exit_dput; -+ } -+ - up(&dir->d_inode->i_sem); - - error = -EEXIST; -@@ -1368,6 +1420,13 @@ - error = security_inode_follow_link(dentry, nd); - if (error) - goto exit_dput; -+ -+ if (gr_handle_follow_link(dentry->d_parent->d_inode, dentry->d_inode, -+ dentry, nd->mnt)) { -+ error = -EACCES; -+ goto exit_dput; -+ } -+ - touch_atime(nd->mnt, dentry); - error = dentry->d_inode->i_op->follow_link(dentry, nd); - dput(dentry); -@@ -1475,6 +1534,22 @@ - if (!IS_POSIXACL(nd.dentry->d_inode)) - mode &= ~current->fs->umask; - if (!IS_ERR(dentry)) { -+ if (gr_handle_chroot_mknod(dentry, nd.mnt, mode)) { -+ error = -EPERM; -+ dput(dentry); -+ up(&nd.dentry->d_inode->i_sem); -+ path_release(&nd); -+ goto out; -+ } -+ -+ if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) { -+ error = -EACCES; -+ dput(dentry); -+ up(&nd.dentry->d_inode->i_sem); -+ path_release(&nd); -+ goto out; -+ } -+ - switch (mode & S_IFMT) { - case 0: case S_IFREG: - error = vfs_create(nd.dentry->d_inode,dentry,mode,&nd); -@@ -1492,6 +1567,10 @@ - default: - error = -EINVAL; - } -+ -+ if (!error) -+ gr_handle_create(dentry, nd.mnt); -+ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -@@ -1543,9 +1622,19 @@ - dentry = lookup_create(&nd, 1); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { -+ error = 0; - if (!IS_POSIXACL(nd.dentry->d_inode)) - mode &= ~current->fs->umask; -- error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); -+ -+ if (!gr_acl_handle_mkdir(dentry, nd.dentry, nd.mnt)) -+ error = -EACCES; -+ -+ if (!error) -+ error = vfs_mkdir(nd.dentry->d_inode, dentry, mode); -+ -+ if (!error) -+ gr_handle_create(dentry, nd.mnt); -+ - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -@@ -1629,6 +1718,8 @@ - char * name; - struct dentry *dentry; - struct nameidata nd; -+ ino_t saved_ino = 0; -+ dev_t saved_dev = 0; - - name = getname(pathname); - if(IS_ERR(name)) -@@ -1653,7 +1744,21 @@ - dentry = lookup_hash(&nd.last, nd.dentry); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { -- error = vfs_rmdir(nd.dentry->d_inode, dentry); -+ error = 0; -+ if (dentry->d_inode) { -+ if (dentry->d_inode->i_nlink <= 1) { -+ saved_ino = dentry->d_inode->i_ino; -+ saved_dev = dentry->d_inode->i_sb->s_dev; -+ } -+ -+ if (!gr_acl_handle_rmdir(dentry, nd.mnt)) -+ error = -EACCES; -+ } -+ -+ if (!error) -+ error = vfs_rmdir(nd.dentry->d_inode, dentry); -+ if (!error && (saved_dev || saved_ino)) -+ gr_handle_delete(saved_ino, saved_dev); - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -@@ -1707,6 +1812,8 @@ - struct dentry *dentry; - struct nameidata nd; - struct inode *inode = NULL; -+ ino_t saved_ino = 0; -+ dev_t saved_dev = 0; - - name = getname(pathname); - if(IS_ERR(name)) -@@ -1722,13 +1829,26 @@ - dentry = lookup_hash(&nd.last, nd.dentry); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { -+ error = 0; - /* Why not before? Because we want correct error value */ - if (nd.last.name[nd.last.len]) - goto slashes; - inode = dentry->d_inode; -- if (inode) -+ if (inode) { -+ if (inode->i_nlink <= 1) { -+ saved_ino = inode->i_ino; -+ saved_dev = inode->i_sb->s_dev; -+ } -+ -+ if (!gr_acl_handle_unlink(dentry, nd.mnt)) -+ error = -EACCES; -+ - atomic_inc(&inode->i_count); -- error = vfs_unlink(nd.dentry->d_inode, dentry); -+ } -+ if (!error) -+ error = vfs_unlink(nd.dentry->d_inode, dentry); -+ if (!error && (saved_ino || saved_dev)) -+ gr_handle_delete(saved_ino, saved_dev); - exit2: - dput(dentry); - } -@@ -1792,7 +1912,15 @@ - dentry = lookup_create(&nd, 0); - error = PTR_ERR(dentry); - if (!IS_ERR(dentry)) { -- error = vfs_symlink(nd.dentry->d_inode, dentry, from); -+ error = 0; -+ if (!gr_acl_handle_symlink(dentry, nd.dentry, nd.mnt, from)) -+ error = -EACCES; -+ -+ if (!error) -+ error = vfs_symlink(nd.dentry->d_inode, dentry, from); -+ -+ if (!error) -+ gr_handle_create(dentry, nd.mnt); - dput(dentry); - } - up(&nd.dentry->d_inode->i_sem); -@@ -1876,7 +2004,20 @@ - new_dentry = lookup_create(&nd, 0); - error = PTR_ERR(new_dentry); - if (!IS_ERR(new_dentry)) { -- error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -+ error = 0; -+ if (gr_handle_hardlink(old_nd.dentry, old_nd.mnt, -+ old_nd.dentry->d_inode, -+ old_nd.dentry->d_inode->i_mode, to)) -+ error = -EPERM; -+ if (!gr_acl_handle_link(new_dentry, nd.dentry, nd.mnt, -+ old_nd.dentry, old_nd.mnt, to)) -+ error = -EACCES; -+ if (!error) -+ error = vfs_link(old_nd.dentry, nd.dentry->d_inode, new_dentry); -+ -+ if (!error) -+ gr_handle_create(new_dentry, nd.mnt); -+ - dput(new_dentry); - } - up(&nd.dentry->d_inode->i_sem); -@@ -2098,8 +2239,16 @@ - if (new_dentry == trap) - goto exit5; - -- error = vfs_rename(old_dir->d_inode, old_dentry, -+ error = gr_acl_handle_rename(new_dentry, newnd.dentry, newnd.mnt, -+ old_dentry, old_dir->d_inode, oldnd.mnt, -+ newname); -+ -+ if (!error) -+ error = vfs_rename(old_dir->d_inode, old_dentry, - new_dir->d_inode, new_dentry); -+ if (!error) -+ gr_handle_rename(old_dir->d_inode, newnd.dentry->d_inode, old_dentry, -+ new_dentry, oldnd.mnt, new_dentry->d_inode ? 1 : 0); - exit5: - dput(new_dentry); - exit4: -diff -urN linux-2.6.5/fs/namespace.c linux-2.6.5/fs/namespace.c ---- linux-2.6.5/fs/namespace.c 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/fs/namespace.c 2004-04-18 11:05:50.000000000 -0400 -@@ -21,6 +21,8 @@ - #include <linux/namei.h> - #include <linux/security.h> - #include <linux/mount.h> -+#include <linux/sched.h> -+#include <linux/grsecurity.h> - #include <asm/uaccess.h> - - extern int __init init_rootfs(void); -@@ -334,6 +336,8 @@ - lock_kernel(); - retval = do_remount_sb(sb, MS_RDONLY, 0, 0); - unlock_kernel(); -+ -+ gr_log_remount(mnt->mnt_devname, retval); - } - up_write(&sb->s_umount); - return retval; -@@ -362,6 +366,9 @@ - if (retval) - security_sb_umount_busy(mnt); - up_write(¤t->namespace->sem); -+ -+ gr_log_unmount(mnt->mnt_devname, retval); -+ - return retval; - } - -@@ -780,6 +787,11 @@ - if (retval) - goto dput_out; - -+ if (gr_handle_chroot_mount(nd.dentry, nd.mnt, dev_name)) { -+ retval = -EPERM; -+ goto dput_out; -+ } -+ - if (flags & MS_REMOUNT) - retval = do_remount(&nd, flags & ~MS_REMOUNT, mnt_flags, - data_page); -@@ -792,6 +804,9 @@ - dev_name, data_page); - dput_out: - path_release(&nd); -+ -+ gr_log_mount(dev_name, dir_name, retval); -+ - return retval; - } - -@@ -1014,6 +1029,9 @@ - if (!capable(CAP_SYS_ADMIN)) - return -EPERM; - -+ if (gr_handle_chroot_pivot()) -+ return -EPERM; -+ - lock_kernel(); - - error = __user_walk(new_root, LOOKUP_FOLLOW|LOOKUP_DIRECTORY, &new_nd); -diff -urN linux-2.6.5/fs/open.c linux-2.6.5/fs/open.c ---- linux-2.6.5/fs/open.c 2004-04-03 22:36:16.000000000 -0500 -+++ linux-2.6.5/fs/open.c 2004-04-18 11:05:50.000000000 -0400 -@@ -22,6 +22,7 @@ - #include <asm/uaccess.h> - #include <linux/fs.h> - #include <linux/pagemap.h> -+#include <linux/grsecurity.h> - - int vfs_statfs(struct super_block *sb, struct kstatfs *buf) - { -@@ -180,7 +181,7 @@ - return error; - } - --int do_truncate(struct dentry *dentry, loff_t length) -+int do_truncate(struct dentry *dentry, loff_t length, struct vfsmount *mnt) - { - int err; - struct iattr newattrs; -@@ -189,6 +190,9 @@ - if (length < 0) - return -EINVAL; - -+ if (!gr_acl_handle_truncate(dentry, mnt)) -+ return -EACCES; -+ - newattrs.ia_size = length; - newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; - down(&dentry->d_inode->i_sem); -@@ -247,7 +251,7 @@ - error = locks_verify_truncate(inode, NULL, length); - if (!error) { - DQUOT_INIT(inode); -- error = do_truncate(nd.dentry, length); -+ error = do_truncate(nd.dentry, length, nd.mnt); - } - put_write_access(inode); - -@@ -299,7 +303,7 @@ - - error = locks_verify_truncate(inode, file, length); - if (!error) -- error = do_truncate(dentry, length); -+ error = do_truncate(dentry, length, file->f_vfsmnt); - out_putf: - fput(file); - out: -@@ -378,6 +382,11 @@ - (error = permission(inode,MAY_WRITE,&nd)) != 0) - goto dput_and_out; - } -+ if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) { -+ error = -EACCES; -+ goto dput_and_out; -+ } -+ - down(&inode->i_sem); - error = notify_change(nd.dentry, &newattrs); - up(&inode->i_sem); -@@ -431,6 +440,12 @@ - (error = permission(inode,MAY_WRITE,&nd)) != 0) - goto dput_and_out; - } -+ -+ if (!gr_acl_handle_utime(nd.dentry, nd.mnt)) { -+ error = -EACCES; -+ goto dput_and_out; -+ } -+ - down(&inode->i_sem); - error = notify_change(nd.dentry, &newattrs); - up(&inode->i_sem); -@@ -492,6 +507,10 @@ - if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) - && !special_file(nd.dentry->d_inode->i_mode)) - res = -EROFS; -+ -+ if (!res && !gr_acl_handle_access(nd.dentry, nd.mnt, mode)) -+ res = -EACCES; -+ - path_release(&nd); - } - -@@ -515,6 +534,8 @@ - if (error) - goto dput_and_out; - -+ gr_log_chdir(nd.dentry, nd.mnt); -+ - set_fs_pwd(current->fs, nd.mnt, nd.dentry); - - dput_and_out: -@@ -545,6 +566,13 @@ - goto out_putf; - - error = permission(inode, MAY_EXEC, NULL); -+ -+ if (!error && !gr_chroot_fchdir(dentry, mnt)) -+ error = -EPERM; -+ -+ if (!error) -+ gr_log_chdir(dentry, mnt); -+ - if (!error) - set_fs_pwd(current->fs, mnt, dentry); - out_putf: -@@ -570,8 +598,16 @@ - if (!capable(CAP_SYS_CHROOT)) - goto dput_and_out; - -+ if (gr_handle_chroot_chroot(nd.dentry, nd.mnt)) -+ goto dput_and_out; -+ - set_fs_root(current->fs, nd.mnt, nd.dentry); - set_fs_altroot(); -+ -+ gr_handle_chroot_caps(current); -+ -+ gr_handle_chroot_chdir(nd.dentry, nd.mnt); -+ - error = 0; - dput_and_out: - path_release(&nd); -@@ -600,9 +636,22 @@ - err = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out_putf; -+ -+ if (!gr_acl_handle_fchmod(dentry, file->f_vfsmnt, mode)) { -+ err = -EACCES; -+ goto out_putf; -+ } -+ - down(&inode->i_sem); - if (mode == (mode_t) -1) - mode = inode->i_mode; -+ -+ if (gr_handle_chroot_chmod(dentry, file->f_vfsmnt, mode)) { -+ err = -EPERM; -+ up(&inode->i_sem); -+ goto out_putf; -+ } -+ - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - err = notify_change(dentry, &newattrs); -@@ -634,9 +683,21 @@ - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto dput_and_out; - -+ if (!gr_acl_handle_chmod(nd.dentry, nd.mnt, mode)) { -+ error = -EACCES; -+ goto dput_and_out; -+ } -+ - down(&inode->i_sem); - if (mode == (mode_t) -1) - mode = inode->i_mode; -+ -+ if (gr_handle_chroot_chmod(nd.dentry, nd.mnt, mode)) { -+ error = -EACCES; -+ up(&inode->i_sem); -+ goto dput_and_out; -+ } -+ - newattrs.ia_mode = (mode & S_IALLUGO) | (inode->i_mode & ~S_IALLUGO); - newattrs.ia_valid = ATTR_MODE | ATTR_CTIME; - error = notify_change(nd.dentry, &newattrs); -@@ -648,7 +709,7 @@ - return error; - } - --static int chown_common(struct dentry * dentry, uid_t user, gid_t group) -+static int chown_common(struct dentry * dentry, uid_t user, gid_t group, struct vfsmount *mnt) - { - struct inode * inode; - int error; -@@ -665,6 +726,12 @@ - error = -EPERM; - if (IS_IMMUTABLE(inode) || IS_APPEND(inode)) - goto out; -+ -+ if (!gr_acl_handle_chown(dentry, mnt)) { -+ error = -EACCES; -+ goto out; -+ } -+ - newattrs.ia_valid = ATTR_CTIME; - if (user != (uid_t) -1) { - newattrs.ia_valid |= ATTR_UID; -@@ -690,7 +757,7 @@ - - error = user_path_walk(filename, &nd); - if (!error) { -- error = chown_common(nd.dentry, user, group); -+ error = chown_common(nd.dentry, user, group, nd.mnt); - path_release(&nd); - } - return error; -@@ -703,7 +770,7 @@ - - error = user_path_walk_link(filename, &nd); - if (!error) { -- error = chown_common(nd.dentry, user, group); -+ error = chown_common(nd.dentry, user, group, nd.mnt); - path_release(&nd); - } - return error; -@@ -717,7 +784,8 @@ - - file = fget(fd); - if (file) { -- error = chown_common(file->f_dentry, user, group); -+ error = chown_common(file->f_dentry, user, -+ group, file->f_vfsmnt); - fput(file); - } - return error; -@@ -839,6 +907,7 @@ - * N.B. For clone tasks sharing a files structure, this test - * will limit the total number of files that can be opened. - */ -+ gr_learn_resource(current, RLIMIT_NOFILE, fd, 0); - if (fd >= current->rlim[RLIMIT_NOFILE].rlim_cur) - goto out; - -diff -urN linux-2.6.5/fs/proc/array.c linux-2.6.5/fs/proc/array.c ---- linux-2.6.5/fs/proc/array.c 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/fs/proc/array.c 2004-04-18 11:05:50.000000000 -0400 -@@ -271,6 +271,19 @@ - cap_t(p->cap_effective)); - } - -+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) -+static inline char *task_pax(struct task_struct *p, char *buffer) -+{ -+ return buffer + sprintf(buffer, "PaX:\t%c%c%c%c%c%c\n", -+ p->flags & PF_PAX_PAGEEXEC ? 'P' : 'p', -+ p->flags & PF_PAX_EMUTRAMP ? 'E' : 'e', -+ p->flags & PF_PAX_MPROTECT ? 'M' : 'm', -+ p->flags & PF_PAX_RANDMMAP ? 'R' : 'r', -+ p->flags & PF_PAX_RANDEXEC ? 'X' : 'x', -+ p->flags & PF_PAX_SEGMEXEC ? 'S' : 's'); -+} -+#endif -+ - extern char *task_mem(struct mm_struct *, char *); - int proc_pid_status(struct task_struct *task, char * buffer) - { -@@ -289,9 +302,20 @@ - #if defined(CONFIG_ARCH_S390) - buffer = task_show_regs(task, buffer); - #endif -+ -+#if defined(CONFIG_PAX_NOEXEC) || defined(CONFIG_PAX_ASLR) -+ buffer = task_pax(task, buffer); -+#endif -+ - return buffer - orig; - } - -+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP -+#define PAX_RAND_FLAGS (task->flags & PF_PAX_RANDMMAP || \ -+ task->flags & PF_PAX_SEGMEXEC || \ -+ task->flags & PF_PAX_RANDEXEC) -+#endif -+ - extern unsigned long task_vsize(struct mm_struct *); - int proc_pid_stat(struct task_struct *task, char * buffer) - { -@@ -326,6 +350,19 @@ - - wchan = get_wchan(task); - -+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP -+ if (PAX_RAND_FLAGS) { -+ eip = 0; -+ esp = 0; -+ wchan = 0; -+ } -+#endif -+#ifdef CONFIG_GRKERNSEC_HIDESYM -+ wchan = 0; -+ eip =0; -+ esp =0; -+#endif -+ - sigemptyset(&sigign); - sigemptyset(&sigcatch); - read_lock(&tasklist_lock); -@@ -374,9 +411,15 @@ - vsize, - mm ? mm->rss : 0, /* you might want to shift this left 3 */ - task->rlim[RLIMIT_RSS].rlim_cur, -+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP -+ PAX_RAND_FLAGS ? 0 : (mm ? mm->start_code : 0), -+ PAX_RAND_FLAGS ? 0 : (mm ? mm->end_code : 0), -+ PAX_RAND_FLAGS ? 0 : (mm ? mm->start_stack : 0), -+#else - mm ? mm->start_code : 0, - mm ? mm->end_code : 0, - mm ? mm->start_stack : 0, -+#endif - esp, - eip, - /* The signal information here is obsolete. -@@ -416,3 +459,14 @@ - return sprintf(buffer,"%d %d %d %d %d %d %d\n", - size, resident, shared, text, lib, data, 0); - } -+ -+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR -+int proc_pid_ipaddr(struct task_struct *task, char * buffer) -+{ -+ int len; -+ -+ len = sprintf(buffer, "%u.%u.%u.%u\n", NIPQUAD(task->curr_ip)); -+ return len; -+} -+#endif -+ -diff -urN linux-2.6.5/fs/proc/base.c linux-2.6.5/fs/proc/base.c ---- linux-2.6.5/fs/proc/base.c 2004-04-03 22:37:25.000000000 -0500 -+++ linux-2.6.5/fs/proc/base.c 2004-04-18 11:05:50.000000000 -0400 -@@ -32,6 +32,7 @@ - #include <linux/mount.h> - #include <linux/security.h> - #include <linux/ptrace.h> -+#include <linux/grsecurity.h> - - /* - * For hysterical raisins we keep the same inumbers as in the old procfs. -@@ -67,6 +68,9 @@ - PROC_TGID_ATTR_EXEC, - PROC_TGID_ATTR_FSCREATE, - #endif -+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR -+ PROC_TGID_IPADDR, -+#endif - PROC_TGID_FD_DIR, - PROC_TID_INO, - PROC_TID_STATUS, -@@ -117,6 +121,9 @@ - E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), - E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), - E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), -+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR -+ E(PROC_TGID_IPADDR, "ipaddr", S_IFREG|S_IRUSR), -+#endif - #ifdef CONFIG_SECURITY - E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), - #endif -@@ -181,6 +188,9 @@ - int proc_pid_status(struct task_struct*,char*); - int proc_pid_statm(struct task_struct*,char*); - int proc_pid_cpu(struct task_struct*,char*); -+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR -+int proc_pid_ipaddr(struct task_struct*,char*); -+#endif - - static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) - { -@@ -281,7 +291,7 @@ - (task == current || \ - (task->parent == current && \ - (task->ptrace & PT_PTRACED) && task->state == TASK_STOPPED && \ -- security_ptrace(current,task) == 0)) -+ security_ptrace(current,task) == 0 && !gr_handle_proc_ptrace(task))) - - static int may_ptrace_attach(struct task_struct *task) - { -@@ -296,13 +306,15 @@ - (current->uid != task->uid) || - (current->gid != task->egid) || - (current->gid != task->sgid) || -- (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) -+ (current->gid != task->gid)) && !capable_nolog(CAP_SYS_PTRACE)) - goto out; - rmb(); -- if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE)) -+ if (!task->mm->dumpable && !capable_nolog(CAP_SYS_PTRACE)) - goto out; - if (security_ptrace(current, task)) - goto out; -+ if (gr_handle_proc_ptrace(task)) -+ goto out; - - retval = 1; - out: -@@ -449,9 +461,22 @@ - - static int proc_permission(struct inode *inode, int mask, struct nameidata *nd) - { -+ int ret; -+ struct task_struct *task; -+ - if (vfs_permission(inode, mask) != 0) - return -EACCES; -- return proc_check_root(inode); -+ ret = proc_check_root(inode); -+ -+ if (ret) -+ return ret; -+ -+ task = proc_task(inode); -+ -+ if (!task) -+ return 0; -+ -+ return gr_acl_handle_procpidmem(task); - } - - extern struct seq_operations proc_pid_maps_op; -@@ -962,6 +987,9 @@ - inode->i_uid = task->euid; - inode->i_gid = task->egid; - } -+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP -+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID; -+#endif - security_task_to_inode(task, inode); - - out: -@@ -990,7 +1018,9 @@ - if (pid_alive(task)) { - if (proc_type(inode) == PROC_TGID_INO || proc_type(inode) == PROC_TID_INO || task_dumpable(task)) { - inode->i_uid = task->euid; -+#ifndef CONFIG_GRKERNSEC_PROC_USERGROUP - inode->i_gid = task->egid; -+#endif - } else { - inode->i_uid = 0; - inode->i_gid = 0; -@@ -1334,6 +1364,12 @@ - inode->i_fop = &proc_info_file_operations; - ei->op.proc_read = proc_pid_status; - break; -+#ifdef CONFIG_GRKERNSEC_PROC_IPADDR -+ case PROC_TGID_IPADDR: -+ inode->i_fop = &proc_info_file_operations; -+ ei->op.proc_read = proc_pid_ipaddr; -+ break; -+#endif - case PROC_TID_STAT: - case PROC_TGID_STAT: - inode->i_fop = &proc_info_file_operations; -@@ -1583,6 +1619,22 @@ - if (!task) - goto out; - -+ if (gr_check_hidden_task(task)) { -+ put_task_struct(task); -+ goto out; -+ } -+ -+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP) -+ if (current->uid && (task->uid != current->uid) -+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP -+ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID) -+#endif -+ ) { -+ put_task_struct(task); -+ goto out; -+ } -+#endif -+ - inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO); - - -@@ -1590,7 +1642,15 @@ - put_task_struct(task); - goto out; - } -+ -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR; -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ inode->i_mode = S_IFDIR|S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP; -+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID; -+#else - inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO; -+#endif - inode->i_op = &proc_tgid_base_inode_operations; - inode->i_fop = &proc_tgid_base_operations; - inode->i_nlink = 3; -@@ -1674,6 +1734,9 @@ - static int get_tgid_list(int index, unsigned long version, unsigned int *tgids) - { - struct task_struct *p; -+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP) -+ struct task_struct *tmp = current; -+#endif - int nr_tgids = 0; - - index--; -@@ -1694,6 +1757,18 @@ - int tgid = p->pid; - if (!pid_alive(p)) - continue; -+ if (gr_pid_is_chrooted(p)) -+ continue; -+ if (gr_check_hidden_task(p)) -+ continue; -+#if defined(CONFIG_GRKERNSEC_PROC_USER) || defined(CONFIG_GRKERNSEC_PROC_USERGROUP) -+ if (tmp->uid && (p->uid != tmp->uid) -+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP -+ && !in_group_p(CONFIG_GRKERNSEC_PROC_GID) -+#endif -+ ) -+ continue; -+#endif - if (--index >= 0) - continue; - tgids[nr_tgids] = tgid; -diff -urN linux-2.6.5/fs/proc/inode.c linux-2.6.5/fs/proc/inode.c ---- linux-2.6.5/fs/proc/inode.c 2004-04-03 22:38:14.000000000 -0500 -+++ linux-2.6.5/fs/proc/inode.c 2004-04-18 11:05:50.000000000 -0400 -@@ -205,7 +205,11 @@ - if (de->mode) { - inode->i_mode = de->mode; - inode->i_uid = de->uid; -+#ifdef CONFIG_GRKERNSEC_PROC_USERGROUP -+ inode->i_gid = CONFIG_GRKERNSEC_PROC_GID; -+#else - inode->i_gid = de->gid; -+#endif - } - if (de->size) - inode->i_size = de->size; -diff -urN linux-2.6.5/fs/proc/proc_misc.c linux-2.6.5/fs/proc/proc_misc.c ---- linux-2.6.5/fs/proc/proc_misc.c 2004-04-03 22:36:24.000000000 -0500 -+++ linux-2.6.5/fs/proc/proc_misc.c 2004-04-18 11:05:50.000000000 -0400 -@@ -654,6 +654,8 @@ - void __init proc_misc_init(void) - { - struct proc_dir_entry *entry; -+ int gr_mode = 0; -+ - static struct { - char *name; - int (*read_proc)(char*,char**,off_t,int,int*,void*); -@@ -668,9 +670,13 @@ - #ifdef CONFIG_STRAM_PROC - {"stram", stram_read_proc}, - #endif -+#ifndef CONFIG_GRKERNSEC_PROC_ADD - {"devices", devices_read_proc}, -+#endif - {"filesystems", filesystems_read_proc}, -+#ifndef CONFIG_GRKERNSEC_PROC_ADD - {"cmdline", cmdline_read_proc}, -+#endif - #ifdef CONFIG_SGI_DS1286 - {"rtc", ds1286_read_proc}, - #endif -@@ -681,24 +687,39 @@ - for (p = simple_ones; p->name; p++) - create_proc_read_entry(p->name, 0, NULL, p->read_proc, NULL); - -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ gr_mode = S_IRUSR; -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ gr_mode = S_IRUSR | S_IRGRP; -+#endif -+#ifdef CONFIG_GRKERNSEC_PROC_ADD -+ create_proc_read_entry("devices", gr_mode, NULL, &devices_read_proc, NULL); -+ create_proc_read_entry("cmdline", gr_mode, NULL, &cmdline_read_proc, NULL); -+#endif -+ - proc_symlink("mounts", NULL, "self/mounts"); - - /* And now for trickier ones */ - entry = create_proc_entry("kmsg", S_IRUSR, &proc_root); - if (entry) - entry->proc_fops = &proc_kmsg_operations; -+#ifdef CONFIG_GRKERNSEC_PROC_ADD -+ create_seq_entry("cpuinfo", gr_mode, &proc_cpuinfo_operations); -+ create_seq_entry("slabinfo",gr_mode,&proc_slabinfo_operations); -+#else - create_seq_entry("cpuinfo", 0, &proc_cpuinfo_operations); -+ create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations); -+#endif - create_seq_entry("partitions", 0, &proc_partitions_operations); - create_seq_entry("stat", 0, &proc_stat_operations); - create_seq_entry("interrupts", 0, &proc_interrupts_operations); -- create_seq_entry("slabinfo",S_IWUSR|S_IRUGO,&proc_slabinfo_operations); - create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); - create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations); - create_seq_entry("diskstats", 0, &proc_diskstats_operations); - #ifdef CONFIG_MODULES -- create_seq_entry("modules", 0, &proc_modules_operations); -+ create_seq_entry("modules", gr_mode, &proc_modules_operations); - #endif --#ifdef CONFIG_PROC_KCORE -+#if defined(CONFIG_PROC_KCORE) - proc_root_kcore = create_proc_entry("kcore", S_IRUSR, NULL); - if (proc_root_kcore) { - proc_root_kcore->proc_fops = &proc_kcore_operations; -diff -urN linux-2.6.5/fs/proc/root.c linux-2.6.5/fs/proc/root.c ---- linux-2.6.5/fs/proc/root.c 2004-04-03 22:37:40.000000000 -0500 -+++ linux-2.6.5/fs/proc/root.c 2004-04-18 11:05:50.000000000 -0400 -@@ -52,13 +52,26 @@ - return; - } - proc_misc_init(); -+ -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ proc_net = proc_mkdir_mode("net", S_IRUSR | S_IXUSR, 0); -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ proc_net = proc_mkdir_mode("net", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, 0); -+#else - proc_net = proc_mkdir("net", 0); -+#endif - #ifdef CONFIG_SYSVIPC - proc_mkdir("sysvipc", 0); - #endif - #ifdef CONFIG_SYSCTL -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ proc_sys_root = proc_mkdir_mode("sys", S_IRUSR | S_IXUSR, 0); -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ proc_sys_root = proc_mkdir_mode("sys", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, 0); -+#else - proc_sys_root = proc_mkdir("sys", 0); - #endif -+#endif - #if defined(CONFIG_BINFMT_MISC) || defined(CONFIG_BINFMT_MISC_MODULE) - proc_mkdir("sys/fs", 0); - proc_mkdir("sys/fs/binfmt_misc", 0); -@@ -74,7 +87,15 @@ - #ifdef CONFIG_PROC_DEVICETREE - proc_device_tree_init(); - #endif -+#ifdef CONFIG_GRKERNSEC_PROC_ADD -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ proc_bus = proc_mkdir_mode("bus", S_IRUSR | S_IXUSR, 0); -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ proc_bus = proc_mkdir_mode("bus", S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP, 0); -+#endif -+#else - proc_bus = proc_mkdir("bus", 0); -+#endif - } - - static struct dentry *proc_root_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) -diff -urN linux-2.6.5/fs/proc/task_mmu.c linux-2.6.5/fs/proc/task_mmu.c ---- linux-2.6.5/fs/proc/task_mmu.c 2004-04-03 22:36:24.000000000 -0500 -+++ linux-2.6.5/fs/proc/task_mmu.c 2004-04-18 11:05:51.000000000 -0400 -@@ -76,8 +76,17 @@ - return size; - } - -+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP -+#define PAX_RAND_FLAGS (task->flags & PF_PAX_RANDMMAP || \ -+ task->flags & PF_PAX_SEGMEXEC || \ -+ task->flags & PF_PAX_RANDEXEC) -+#endif -+ - static int show_map(struct seq_file *m, void *v) - { -+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP -+ struct task_struct *task = m->private; -+#endif - struct vm_area_struct *map = v; - struct file *file = map->vm_file; - int flags = map->vm_flags; -@@ -92,8 +101,14 @@ - } - - seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n", -+#ifdef CONFIG_GRKERNSEC_PROC_MEMMAP -+ PAX_RAND_FLAGS ? 0UL : map->vm_start, -+ PAX_RAND_FLAGS ? 0UL : map->vm_end, -+#else - map->vm_start, - map->vm_end, -+#endif -+ - flags & VM_READ ? 'r' : '-', - flags & VM_WRITE ? 'w' : '-', - flags & VM_EXEC ? 'x' : '-', -diff -urN linux-2.6.5/fs/readdir.c linux-2.6.5/fs/readdir.c ---- linux-2.6.5/fs/readdir.c 2004-04-03 22:37:06.000000000 -0500 -+++ linux-2.6.5/fs/readdir.c 2004-04-18 11:05:50.000000000 -0400 -@@ -14,6 +14,8 @@ - #include <linux/fs.h> - #include <linux/dirent.h> - #include <linux/security.h> -+#include <linux/namei.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - -@@ -64,6 +66,7 @@ - struct readdir_callback { - struct old_linux_dirent __user * dirent; - int result; -+ struct nameidata nd; - }; - - static int fillonedir(void * __buf, const char * name, int namlen, loff_t offset, -@@ -74,6 +77,10 @@ - - if (buf->result) - return -EINVAL; -+ -+ if (!gr_acl_handle_filldir(buf->nd.dentry, buf->nd.mnt, ino)) -+ return 0; -+ - buf->result++; - dirent = buf->dirent; - if (!access_ok(VERIFY_WRITE, (unsigned long)dirent, -@@ -106,6 +113,9 @@ - buf.result = 0; - buf.dirent = dirent; - -+ buf.nd.dentry = file->f_dentry; -+ buf.nd.mnt = file->f_vfsmnt; -+ - error = vfs_readdir(file, fillonedir, &buf); - if (error >= 0) - error = buf.result; -@@ -133,6 +143,7 @@ - struct linux_dirent __user * previous; - int count; - int error; -+ struct nameidata nd; - }; - - static int filldir(void * __buf, const char * name, int namlen, loff_t offset, -@@ -145,6 +156,10 @@ - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; -+ -+ if (!gr_acl_handle_filldir(buf->nd.dentry, buf->nd.mnt, ino)) -+ return 0; -+ - dirent = buf->previous; - if (dirent) { - if (__put_user(offset, &dirent->d_off)) -@@ -192,6 +207,9 @@ - buf.count = count; - buf.error = 0; - -+ buf.nd.dentry = file->f_dentry; -+ buf.nd.mnt = file->f_vfsmnt; -+ - error = vfs_readdir(file, filldir, &buf); - if (error < 0) - goto out_putf; -@@ -217,6 +235,7 @@ - struct linux_dirent64 __user * previous; - int count; - int error; -+ struct nameidata nd; - }; - - static int filldir64(void * __buf, const char * name, int namlen, loff_t offset, -@@ -229,6 +248,10 @@ - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; -+ -+ if (!gr_acl_handle_filldir(buf->nd.dentry, buf->nd.mnt, ino)) -+ return 0; -+ - dirent = buf->previous; - if (dirent) { - if (__put_user(offset, &dirent->d_off)) -@@ -278,6 +301,9 @@ - buf.count = count; - buf.error = 0; - -+ buf.nd.mnt = file->f_vfsmnt; -+ buf.nd.dentry = file->f_dentry; -+ - error = vfs_readdir(file, filldir64, &buf); - if (error < 0) - goto out_putf; -diff -urN linux-2.6.5/grsecurity/Kconfig linux-2.6.5/grsecurity/Kconfig ---- linux-2.6.5/grsecurity/Kconfig 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/Kconfig 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,864 @@ -+# -+# grecurity configuration -+# -+ -+menu "Grsecurity" -+ -+config GRKERNSEC -+ bool "Grsecurity" -+ select CRYPTO -+ select CRYPTO_SHA256 -+ help -+ If you say Y here, you will be able to configure many features -+ that will enhance the security of your system. It is highly -+ recommended that you say Y here and read through the help -+ for each option so that you fully understand the features and -+ can evaluate their usefulness for your machine. -+ -+choice -+ prompt "Security Level" -+ depends GRKERNSEC -+ default GRKERNSEC_CUSTOM -+ -+config GRKERNSEC_LOW -+ bool "Low" -+ select GRKERNSEC_LINK -+ select GRKERNSEC_FIFO -+ select GRKERNSEC_RANDPID -+ select GRKERNSEC_EXECVE -+ select GRKERNSEC_RANDNET -+ select GRKERNSEC_RANDISN -+ select GRKERNSEC_DMESG -+ select GRKERNSEC_RANDID -+ select GRKERNSEC_CHROOT_CHDIR -+ help -+ If you choose this option, several of the grsecurity options will -+ be enabled that will give you greater protection against a number -+ of attacks, while assuring that none of your software will have any -+ conflicts with the additional security measures. If you run a lot -+ of unusual software, or you are having problems with the higher -+ security levels, you should say Y here. With this option, the -+ following features are enabled: -+ -+ - Linking Restrictions -+ - FIFO Restrictions -+ - Randomized PIDs -+ - Enforcing RLIMIT_NPROC on execve -+ - Restricted dmesg -+ - Randomized IP IDs -+ - Enforced chdir("/") on chroot -+ -+config GRKERNSEC_MEDIUM -+ bool "Medium" -+ select PAX_EI_PAX -+ select PAX_PT_PAX_FLAGS -+ select PAX_HAVE_ACL_FLAGS -+ select GRKERNSEC_PROC_MEMMAP -+ select GRKERNSEC_CHROOT_SYSCTL -+ select GRKERNSEC_LINK -+ select GRKERNSEC_FIFO -+ select GRKERNSEC_RANDPID -+ select GRKERNSEC_EXECVE -+ select GRKERNSEC_DMESG -+ select GRKERNSEC_RANDID -+ select GRKERNSEC_RANDNET -+ select GRKERNSEC_RANDISN -+ select GRKERNSEC_RANDSRC -+ select GRKERNSEC_RANDRPC -+ select GRKERNSEC_FORKFAIL -+ select GRKERNSEC_TIME -+ select GRKERNSEC_SIGNAL -+ select GRKERNSEC_CHROOT -+ select GRKERNSEC_CHROOT_UNIX -+ select GRKERNSEC_CHROOT_MOUNT -+ select GRKERNSEC_CHROOT_PIVOT -+ select GRKERNSEC_CHROOT_DOUBLE -+ select GRKERNSEC_CHROOT_CHDIR -+ select GRKERNSEC_CHROOT_MKNOD -+ select GRKERNSEC_PROC -+ select GRKERNSEC_PROC_USERGROUP -+ select PAX_RANDUSTACK -+ select PAX_ASLR -+ select PAX_RANDMMAP -+ -+ help -+ If you say Y here, several features in addition to those included -+ in the low additional security level will be enabled. These -+ features provide even more security to your system, though in rare -+ cases they may be incompatible with very old or poorly written -+ software. If you enable this option, make sure that your auth -+ service (identd) is running as gid 1001. With this option, -+ the following features (in addition to those provided in the -+ low additional security level) will be enabled: -+ -+ - Randomized TCP Source Ports -+ - Failed Fork Logging -+ - Time Change Logging -+ - Signal Logging -+ - Deny Mounts in chroot -+ - Deny Double chrooting -+ - Deny Sysctl Writes in chroot -+ - Deny Mknod in chroot -+ - Deny Access to Abstract AF_UNIX Sockets out of chroot -+ - Deny pivot_root in chroot -+ - Denied Writes of /dev/kmem, /dev/mem, and /dev/port -+ - /proc restrictions with special GID set to 10 (usually wheel) -+ - Address Space Layout Randomization (ASLR) -+ -+config GRKERNSEC_HIGH -+ bool "High" -+ select GRKERNSEC_LINK -+ select GRKERNSEC_FIFO -+ select GRKERNSEC_RANDPID -+ select GRKERNSEC_EXECVE -+ select GRKERNSEC_DMESG -+ select GRKERNSEC_RANDID -+ select GRKERNSEC_RANDSRC -+ select GRKERNSEC_RANDRPC -+ select GRKERNSEC_FORKFAIL -+ select GRKERNSEC_TIME -+ select GRKERNSEC_SIGNAL -+ select GRKERNSEC_CHROOT_SHMAT -+ select GRKERNSEC_CHROOT_UNIX -+ select GRKERNSEC_CHROOT_MOUNT -+ select GRKERNSEC_CHROOT_FCHDIR -+ select GRKERNSEC_CHROOT_PIVOT -+ select GRKERNSEC_CHROOT_DOUBLE -+ select GRKERNSEC_CHROOT_CHDIR -+ select GRKERNSEC_CHROOT_MKNOD -+ select GRKERNSEC_CHROOT_CAPS -+ select GRKERNSEC_CHROOT_SYSCTL -+ select GRKERNSEC_CHROOT_FINDTASK -+ select GRKERNSEC_PROC -+ select GRKERNSEC_PROC_MEMMAP -+ select GRKERNSEC_HIDESYM -+ select GRKERNSEC_PROC_USERGROUP -+ select GRKERNSEC_KMEM -+ select GRKERNSEC_RESLOG -+ select GRKERNSEC_RANDNET -+ select GRKERNSEC_RANDISN -+ select GRKERNSEC_PROC_ADD -+ select GRKERNSEC_CHROOT_CHMOD -+ select GRKERNSEC_CHROOT_NICE -+ select GRKERNSEC_AUDIT_MOUNT -+ select PAX_RANDUSTACK -+ select PAX_ASLR -+ select PAX_RANDMMAP -+ select PAX_NOEXEC -+ select PAX_MPROTECT -+ select PAX_EI_PAX -+ select PAX_PT_PAX_FLAGS -+ select PAX_HAVE_ACL_FLAGS -+ select PAX_KERNEXEC -+ select PAX_RANDKSTACK -+ select PAX_RANDEXEC -+ select PAX_SEGMEXEC -+ select PAX_EMUTRAMP -+ select PAX_NOVSYSCALL -+ help -+ If you say Y here, many of the features of grsecurity will be -+ enabled, which will protect you against many kinds of attacks -+ against your system. The heightened security comes at a cost -+ of an increased chance of incompatibilities with rare software -+ on your machine. Since this security level enables PaX, you should -+ view <http://pax.grsecurity.net> and read about the PaX -+ project. While you are there, download chpax and run it on -+ binaries that cause problems with PaX. Also remember that -+ since the /proc restrictions are enabled, you must run your -+ identd as gid 1001. This security level enables the following -+ features in addition to those listed in the low and medium -+ security levels: -+ -+ - Additional /proc Restrictions -+ - Chmod Restrictions in chroot -+ - No Signals, Ptrace, or Viewing of Processes Outside of chroot -+ - Capability Restrictions in chroot -+ - Deny fchdir out of chroot -+ - Priority Restrictions in chroot -+ - Segmentation-based Implementation of PaX -+ - Mprotect Restrictions -+ - Removal of Addresses from /proc/<pid>/[maps|stat] -+ - Kernel Stack Randomization -+ - Mount/Unmount/Remount Logging -+ - Kernel Symbol Hiding -+ -+config GRKERNSEC_CUSTOM -+ bool "Custom" -+ help -+ If you say Y here, you will be able to configure every grsecurity -+ option, which allows you to enable many more features that aren't -+ covered in the basic security levels. These additional features -+ include TPE, socket restrictions, and the sysctl system for -+ grsecurity. It is advised that you read through the help for -+ each option to determine its usefulness in your situation. -+ -+endchoice -+ -+menu "Address Space Protection" -+depends on GRKERNSEC -+ -+config GRKERNSEC_KMEM -+ bool "Deny writing to /dev/kmem, /dev/mem, and /dev/port" -+ help -+ If you say Y here, /dev/kmem and /dev/mem won't be allowed to -+ be written to via mmap or otherwise to modify the running kernel. -+ /dev/port will also not be allowed to be opened. If you have module -+ support disabled, enabling this will close up four ways that are -+ currently used to insert malicious code into the running kernel. -+ Even with all these features enabled, we still highly recommend that -+ you use the ACL system, as it is still possible for an attacker to -+ modify the running kernel through privileged I/O granted by ioperm/iopl. -+ If you are not using XFree86, you may be able to stop this additional -+ case by enabling the 'Disable privileged I/O' option. Though nothing -+ legitimately writes to /dev/kmem, XFree86 does need to write to /dev/mem, -+ but only to video memory, which is the only writing we allow in this -+ case. If /dev/kmem or /dev/mem are mmaped without PROT_WRITE, they will -+ not be allowed to mprotect it with PROT_WRITE later. -+ Enabling this feature could make certain apps like VMWare stop working, -+ as they need to write to other locations in /dev/mem. -+ It is highly recommended that you say Y here if you meet all the -+ conditions above. -+ -+config GRKERNSEC_IO -+ bool "Disable privileged I/O" -+ depends on X86 -+ select RTC -+ help -+ If you say Y here, all ioperm and iopl calls will return an error. -+ Ioperm and iopl can be used to modify the running kernel. -+ Unfortunately, some programs need this access to operate properly, -+ the most notable of which are XFree86 and hwclock. hwclock can be -+ remedied by having RTC support in the kernel, so CONFIG_RTC is -+ enabled if this option is enabled, to ensure that hwclock operates -+ correctly. XFree86 still will not operate correctly with this option -+ enabled, so DO NOT CHOOSE Y IF YOU USE XFree86. If you use XFree86 -+ and you still want to protect your kernel against modification, -+ use the ACL system. -+ -+config GRKERNSEC_PROC_MEMMAP -+ bool "Remove addresses from /proc/<pid>/[maps|stat]" -+ help -+ If you say Y here, the /proc/<pid>/maps and /proc/<pid>/stat files will -+ give no information about the addresses of its mappings if -+ PaX features that rely on random addresses are enabled on the task. -+ If you use PaX it is greatly recommended that you say Y here as it -+ closes up a hole that makes the full ASLR useless for suid -+ binaries. -+ -+config GRKERNSEC_HIDESYM -+ bool "Hide kernel symbols" -+ help -+ If you say Y here, getting information on loaded modules, and -+ displaying all kernel symbols through a syscall will be restricted -+ to users with CAP_SYS_MODULE. This option is only effective -+ provided the following conditions are met: -+ 1) The kernel using grsecurity is not precompiled by some distribution -+ 2) You are using the ACL system and hiding other files such as your -+ kernel image and System.map -+ 3) You have the additional /proc restrictions enabled, which removes -+ /proc/kcore -+ If the above conditions are met, this option will aid to provide a -+ useful protection against local and remote kernel exploitation of -+ overflows and arbitrary read/write vulnerabilities. -+ -+endmenu -+menu "Role Based Access Control Options" -+depends on GRKERNSEC -+ -+config GRKERNSEC_ACL_HIDEKERN -+ bool "Hide kernel processes" -+ help -+ If you say Y here, when the RBAC system is enabled via gradm -E, -+ an additional ACL will be passed to the kernel that hides all kernel -+ processes. These processes will only be viewable by the authenticated -+ admin, or processes that have viewing access set. -+ -+config GRKERNSEC_ACL_MAXTRIES -+ int "Maximum tries before password lockout" -+ default 3 -+ help -+ This option enforces the maximum number of times a user can attempt -+ to authorize themselves with the grsecurity ACL system before being -+ denied the ability to attempt authorization again for a specified time. -+ The lower the number, the harder it will be to brute-force a password. -+ -+config GRKERNSEC_ACL_TIMEOUT -+ int "Time to wait after max password tries, in seconds" -+ default 30 -+ help -+ This option specifies the time the user must wait after attempting to -+ authorize to the ACL system with the maximum number of invalid -+ passwords. The higher the number, the harder it will be to brute-force -+ a password. -+ -+endmenu -+menu "Filesystem Protections" -+depends on GRKERNSEC -+ -+config GRKERNSEC_PROC -+ bool "Proc restrictions" -+ help -+ If you say Y here, the permissions of the /proc filesystem -+ will be altered to enhance system security and privacy. Depending -+ upon the options you choose, you can either restrict users to see -+ only the processes they themselves run, or choose a group that can -+ view all processes and files normally restricted to root if you choose -+ the "restrict to user only" option. NOTE: If you're running identd as -+ a non-root user, you will have to run it as the group you specify here. -+ -+config GRKERNSEC_PROC_USER -+ bool "Restrict /proc to user only" -+ depends on GRKERNSEC_PROC -+ help -+ If you say Y here, non-root users will only be able to view their own -+ processes, and restricts them from viewing network-related information, -+ and viewing kernel symbol and module information. -+ -+config GRKERNSEC_PROC_USERGROUP -+ bool "Allow special group" -+ depends on GRKERNSEC_PROC && !GRKERNSEC_PROC_USER -+ help -+ If you say Y here, you will be able to select a group that will be -+ able to view all processes, network-related information, and -+ kernel and symbol information. This option is useful if you want -+ to run identd as a non-root user. -+ -+config GRKERNSEC_PROC_GID -+ int "GID for special group" -+ depends on GRKERNSEC_PROC_USERGROUP -+ default 1001 -+ -+config GRKERNSEC_PROC_ADD -+ bool "Additional restrictions" -+ depends on GRKERNSEC_PROC_USER || GRKERNSEC_PROC_USERGROUP -+ help -+ If you say Y here, additional restrictions will be placed on -+ /proc that keep normal users from viewing cpu and device information. -+ -+config GRKERNSEC_LINK -+ bool "Linking restrictions" -+ help -+ If you say Y here, /tmp race exploits will be prevented, since users -+ will no longer be able to follow symlinks owned by other users in -+ world-writable +t directories (i.e. /tmp), unless the owner of the -+ symlink is the owner of the directory. users will also not be -+ able to hardlink to files they do not own. If the sysctl option is -+ enabled, a sysctl option with name "linking_restrictions" is created. -+ -+config GRKERNSEC_FIFO -+ bool "FIFO restrictions" -+ help -+ If you say Y here, users will not be able to write to FIFOs they don't -+ own in world-writable +t directories (i.e. /tmp), unless the owner of -+ the FIFO is the same owner of the directory it's held in. If the sysctl -+ option is enabled, a sysctl option with name "fifo_restrictions" is -+ created. -+ -+config GRKERNSEC_CHROOT -+ bool "Chroot jail restrictions" -+ help -+ If you say Y here, you will be able to choose several options that will -+ make breaking out of a chrooted jail much more difficult. If you -+ encounter no software incompatibilities with the following options, it -+ is recommended that you enable each one. -+ -+config GRKERNSEC_CHROOT_MOUNT -+ bool "Deny mounts" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, processes inside a chroot will not be able to -+ mount or remount filesystems. If the sysctl option is enabled, a -+ sysctl option with name "chroot_deny_mount" is created. -+ -+config GRKERNSEC_CHROOT_DOUBLE -+ bool "Deny double-chroots" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, processes inside a chroot will not be able to chroot -+ again outside the chroot. This is a widely used method of breaking -+ out of a chroot jail and should not be allowed. If the sysctl -+ option is enabled, a sysctl option with name -+ "chroot_deny_chroot" is created. -+ -+config GRKERNSEC_CHROOT_PIVOT -+ bool "Deny pivot_root in chroot" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, processes inside a chroot will not be able to use -+ a function called pivot_root() that was introduced in Linux 2.3.41. It -+ works similar to chroot in that it changes the root filesystem. This -+ function could be misused in a chrooted process to attempt to break out -+ of the chroot, and therefore should not be allowed. If the sysctl -+ option is enabled, a sysctl option with name "chroot_deny_pivot" is -+ created. -+ -+config GRKERNSEC_CHROOT_CHDIR -+ bool "Enforce chdir(\"/\") on all chroots" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, the current working directory of all newly-chrooted -+ applications will be set to the the root directory of the chroot. -+ The man page on chroot(2) states: -+ Note that this call does not change the current working -+ directory, so that `.' can be outside the tree rooted at -+ `/'. In particular, the super-user can escape from a -+ `chroot jail' by doing `mkdir foo; chroot foo; cd ..'. -+ -+ It is recommended that you say Y here, since it's not known to break -+ any software. If the sysctl option is enabled, a sysctl option with -+ name "chroot_enforce_chdir" is created. -+ -+config GRKERNSEC_CHROOT_CHMOD -+ bool "Deny (f)chmod +s" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, processes inside a chroot will not be able to chmod -+ or fchmod files to make them have suid or sgid bits. This protects -+ against another published method of breaking a chroot. If the sysctl -+ option is enabled, a sysctl option with name "chroot_deny_chmod" is -+ created. -+ -+config GRKERNSEC_CHROOT_FCHDIR -+ bool "Deny fchdir out of chroot" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, a well-known method of breaking chroots by fchdir'ing -+ to a file descriptor of the chrooting process that points to a directory -+ outside the filesystem will be stopped. If the sysctl option -+ is enabled, a sysctl option with name "chroot_deny_fchdir" is created. -+ -+config GRKERNSEC_CHROOT_MKNOD -+ bool "Deny mknod" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, processes inside a chroot will not be allowed to -+ mknod. The problem with using mknod inside a chroot is that it -+ would allow an attacker to create a device entry that is the same -+ as one on the physical root of your system, which could range from -+ anything from the console device to a device for your harddrive (which -+ they could then use to wipe the drive or steal data). It is recommended -+ that you say Y here, unless you run into software incompatibilities. -+ If the sysctl option is enabled, a sysctl option with name -+ "chroot_deny_mknod" is created. -+ -+config GRKERNSEC_CHROOT_SHMAT -+ bool "Deny shmat() out of chroot" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, processes inside a chroot will not be able to attach -+ to shared memory segments that were created outside of the chroot jail. -+ It is recommended that you say Y here. If the sysctl option is enabled, -+ a sysctl option with name "chroot_deny_shmat" is created. -+ -+config GRKERNSEC_CHROOT_UNIX -+ bool "Deny access to abstract AF_UNIX sockets out of chroot" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, processes inside a chroot will not be able to -+ connect to abstract (meaning not belonging to a filesystem) Unix -+ domain sockets that were bound outside of a chroot. It is recommended -+ that you say Y here. If the sysctl option is enabled, a sysctl option -+ with name "chroot_deny_unix" is created. -+ -+config GRKERNSEC_CHROOT_FINDTASK -+ bool "Protect outside processes" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, processes inside a chroot will not be able to -+ kill, send signals with fcntl, ptrace, capget, setpgid, getpgid, -+ getsid, or view any process outside of the chroot. If the sysctl -+ option is enabled, a sysctl option with name "chroot_findtask" is -+ created. -+ -+config GRKERNSEC_CHROOT_NICE -+ bool "Restrict priority changes" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, processes inside a chroot will not be able to raise -+ the priority of processes in the chroot, or alter the priority of -+ processes outside the chroot. This provides more security than simply -+ removing CAP_SYS_NICE from the process' capability set. If the -+ sysctl option is enabled, a sysctl option with name "chroot_restrict_nice" -+ is created. -+ -+config GRKERNSEC_CHROOT_SYSCTL -+ bool "Deny sysctl writes" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, an attacker in a chroot will not be able to -+ write to sysctl entries, either by sysctl(2) or through a /proc -+ interface. It is strongly recommended that you say Y here. If the -+ sysctl option is enabled, a sysctl option with name -+ "chroot_deny_sysctl" is created. -+ -+config GRKERNSEC_CHROOT_CAPS -+ bool "Capability restrictions" -+ depends on GRKERNSEC_CHROOT -+ help -+ If you say Y here, the capabilities on all root processes within a -+ chroot jail will be lowered to stop module insertion, raw i/o, -+ system and net admin tasks, rebooting the system, modifying immutable -+ files, modifying IPC owned by another, and changing the system time. -+ This is left an option because it can break some apps. Disable this -+ if your chrooted apps are having problems performing those kinds of -+ tasks. If the sysctl option is enabled, a sysctl option with -+ name "chroot_caps" is created. -+ -+endmenu -+menu "Kernel Auditing" -+depends on GRKERNSEC -+ -+config GRKERNSEC_AUDIT_GROUP -+ bool "Single group for auditing" -+ help -+ If you say Y here, the exec, chdir, (un)mount, and ipc logging features -+ will only operate on a group you specify. This option is recommended -+ if you only want to watch certain users instead of having a large -+ amount of logs from the entire system. If the sysctl option is enabled, -+ a sysctl option with name "audit_group" is created. -+ -+config GRKERNSEC_AUDIT_GID -+ int "GID for auditing" -+ depends on GRKERNSEC_AUDIT_GROUP -+ default 1007 -+ -+config GRKERNSEC_EXECLOG -+ bool "Exec logging" -+ help -+ If you say Y here, all execve() calls will be logged (since the -+ other exec*() calls are frontends to execve(), all execution -+ will be logged). Useful for shell-servers that like to keep track -+ of their users. If the sysctl option is enabled, a sysctl option with -+ name "exec_logging" is created. -+ WARNING: This option when enabled will produce a LOT of logs, especially -+ on an active system. -+ -+config GRKERNSEC_RESLOG -+ bool "Resource logging" -+ help -+ If you say Y here, all attempts to overstep resource limits will -+ be logged with the resource name, the requested size, and the current -+ limit. It is highly recommended that you say Y here. -+ -+config GRKERNSEC_CHROOT_EXECLOG -+ bool "Log execs within chroot" -+ help -+ If you say Y here, all executions inside a chroot jail will be logged -+ to syslog. This can cause a large amount of logs if certain -+ applications (eg. djb's daemontools) are installed on the system, and -+ is therefore left as an option. If the sysctl option is enabled, a -+ sysctl option with name "chroot_execlog" is created. -+ -+config GRKERNSEC_AUDIT_CHDIR -+ bool "Chdir logging" -+ help -+ If you say Y here, all chdir() calls will be logged. If the sysctl -+ option is enabled, a sysctl option with name "audit_chdir" is created. -+ -+config GRKERNSEC_AUDIT_MOUNT -+ bool "(Un)Mount logging" -+ help -+ If you say Y here, all mounts and unmounts will be logged. If the -+ sysctl option is enabled, a sysctl option with name "audit_mount" is -+ created. -+ -+config GRKERNSEC_AUDIT_IPC -+ bool "IPC logging" -+ help -+ If you say Y here, creation and removal of message queues, semaphores, -+ and shared memory will be logged. If the sysctl option is enabled, a -+ sysctl option with name "audit_ipc" is created. -+ -+config GRKERNSEC_SIGNAL -+ bool "Signal logging" -+ help -+ If you say Y here, certain important signals will be logged, such as -+ SIGSEGV, which will as a result inform you of when a error in a program -+ occurred, which in some cases could mean a possible exploit attempt. -+ If the sysctl option is enabled, a sysctl option with name -+ "signal_logging" is created. -+ -+config GRKERNSEC_FORKFAIL -+ bool "Fork failure logging" -+ help -+ If you say Y here, all failed fork() attempts will be logged. -+ This could suggest a fork bomb, or someone attempting to overstep -+ their process limit. If the sysctl option is enabled, a sysctl option -+ with name "forkfail_logging" is created. -+ -+config GRKERNSEC_TIME -+ bool "Time change logging" -+ help -+ If you say Y here, any changes of the system clock will be logged. -+ If the sysctl option is enabled, a sysctl option with name -+ "timechange_logging" is created. -+ -+config GRKERNSEC_PROC_IPADDR -+ bool "/proc/<pid>/ipaddr support" -+ help -+ If you say Y here, a new entry will be added to each /proc/<pid> -+ directory that contains the IP address of the person using the task. -+ The IP is carried across local TCP and AF_UNIX stream sockets. -+ This information can be useful for IDS/IPSes to perform remote response -+ to a local attack. The entry is readable by only the owner of the -+ process (and root if he has CAP_DAC_OVERRIDE, which can be removed via -+ the RBAC system), and thus does not create privacy concerns. -+ -+config GRKERNSEC_AUDIT_TEXTREL -+ bool 'ELF text relocations logging (READ HELP)' -+ depends on PAX_MPROTECT -+ help -+ If you say Y here, text relocations will be logged with the filename -+ of the offending library or binary. The purpose of the feature is -+ to help Linux distribution developers get rid of libraries and -+ binaries that need text relocations which hinder the future progress -+ of PaX. Only Linux distribution developers should say Y here, and -+ never on a production machine, as this option creates an information -+ leak that could aid an attacker in defeating the randomization of -+ a single memory region. If the sysctl option is enabled, a sysctl -+ option with name "audit_textrel" is created. -+ -+endmenu -+ -+menu "Executable Protections" -+depends on GRKERNSEC -+ -+config GRKERNSEC_EXECVE -+ bool "Enforce RLIMIT_NPROC on execs" -+ help -+ If you say Y here, users with a resource limit on processes will -+ have the value checked during execve() calls. The current system -+ only checks the system limit during fork() calls. If the sysctl option -+ is enabled, a sysctl option with name "execve_limiting" is created. -+ -+config GRKERNSEC_DMESG -+ bool "Dmesg(8) restriction" -+ help -+ If you say Y here, non-root users will not be able to use dmesg(8) -+ to view up to the last 4kb of messages in the kernel's log buffer. -+ If the sysctl option is enabled, a sysctl option with name "dmesg" is -+ created. -+ -+config GRKERNSEC_RANDPID -+ bool "Randomized PIDs" -+ help -+ If you say Y here, all PIDs created on the system will be -+ pseudo-randomly generated. This is extremely effective along -+ with the /proc restrictions to disallow an attacker from guessing -+ pids of daemons, etc. PIDs are also used in some cases as part -+ of a naming system for temporary files, so this option would keep -+ those filenames from being predicted as well. We also use code -+ to make sure that PID numbers aren't reused too soon. If the sysctl -+ option is enabled, a sysctl option with name "rand_pids" is created. -+ -+config GRKERNSEC_TPE -+ bool "Trusted Path Execution (TPE)" -+ help -+ If you say Y here, you will be able to choose a gid to add to the -+ supplementary groups of users you want to mark as "untrusted." -+ These users will not be able to execute any files that are not in -+ root-owned directories writable only by root. If the sysctl option -+ is enabled, a sysctl option with name "tpe" is created. -+ -+config GRKERNSEC_TPE_ALL -+ bool "Partially restrict non-root users" -+ depends on GRKERNSEC_TPE -+ help -+ If you say Y here, All non-root users other than the ones in the -+ group specified in the main TPE option will only be allowed to -+ execute files in directories they own that are not group or -+ world-writable, or in directories owned by root and writable only by -+ root. If the sysctl option is enabled, a sysctl option with name -+ "tpe_restrict_all" is created. -+ -+config GRKERNSEC_TPE_GID -+ int "GID for untrusted users" -+ depends on GRKERNSEC_TPE -+ default 1005 -+ help -+ Here you can choose the GID to enable trusted path protection for. -+ Remember to add the users you want protection enabled for to the GID -+ specified here. If the sysctl option is enabled, whatever you choose -+ here won't matter. You'll have to specify the GID in your bootup -+ script by echoing the GID to the proper /proc entry. View the help -+ on the sysctl option for more information. If the sysctl option is -+ enabled, a sysctl option with name "tpe_gid" is created. -+ -+endmenu -+menu "Network Protections" -+depends on GRKERNSEC -+ -+config GRKERNSEC_RANDNET -+ bool "Larger entropy pools" -+ help -+ If you say Y here, the entropy pools used for many features of Linux -+ and grsecurity will be doubled in size. Since several grsecurity -+ features use additional randomness, it is recommended that you say Y -+ here. Saying Y here has a similar effect as modifying -+ /proc/sys/kernel/random/poolsize. -+ -+config GRKERNSEC_RANDISN -+ bool "Truly random TCP ISN selection" -+ help -+ If you say Y here, Linux's default selection of TCP Initial Sequence -+ Numbers (ISNs) will be replaced with that of OpenBSD. Linux uses -+ an MD4 hash based on the connection plus a time value to create the -+ ISN, while OpenBSD's selection is random. If the sysctl option is -+ enabled, a sysctl option with name "rand_isns" is created. -+ -+config GRKERNSEC_RANDID -+ bool "Randomized IP IDs" -+ help -+ If you say Y here, all the id field on all outgoing packets -+ will be randomized. This hinders os fingerprinters and -+ keeps your machine from being used as a bounce for an untraceable -+ portscan. Ids are used for fragmented packets, fragments belonging -+ to the same packet have the same id. By default linux only -+ increments the id value on each packet sent to an individual host. -+ We use a port of the OpenBSD random ip id code to achieve the -+ randomness, while keeping the possibility of id duplicates to -+ near none. If the sysctl option is enabled, a sysctl option with name -+ "rand_ip_ids" is created. -+ -+config GRKERNSEC_RANDSRC -+ bool "Randomized TCP source ports" -+ default n if GRKERNSEC_LOW || GRKERNSEC_MID -+ default y if GRKERNSEC_HIGH -+ help -+ If you say Y here, situations where a source port is generated on the -+ fly for the TCP protocol (ie. with connect() ) will be altered so that -+ the source port is generated at random, instead of a simple incrementing -+ algorithm. If the sysctl option is enabled, a sysctl option with name -+ "rand_tcp_src_ports" is created. -+ -+config GRKERNSEC_RANDRPC -+ bool "Randomized RPC XIDs" -+ help -+ If you say Y here, the method of determining XIDs for RPC requests will -+ be randomized, instead of using linux's default behavior of simply -+ incrementing the XID. If you want your RPC connections to be more -+ secure, say Y here. If the sysctl option is enabled, a sysctl option -+ with name "rand_rpc" is created. -+ -+config GRKERNSEC_SOCKET -+ bool "Socket restrictions" -+ help -+ If you say Y here, you will be able to choose from several options. -+ If you assign a GID on your system and add it to the supplementary -+ groups of users you want to restrict socket access to, this patch -+ will perform up to three things, based on the option(s) you choose. -+ -+config GRKERNSEC_SOCKET_ALL -+ bool "Deny any sockets to group" -+ depends on GRKERNSEC_SOCKET -+ help -+ If you say Y here, you will be able to choose a GID of whose users will -+ be unable to connect to other hosts from your machine or run server -+ applications from your machine. If the sysctl option is enabled, a -+ sysctl option with name "socket_all" is created. -+ -+config GRKERNSEC_SOCKET_ALL_GID -+ int "GID to deny all sockets for" -+ depends on GRKERNSEC_SOCKET_ALL -+ default 1004 -+ help -+ Here you can choose the GID to disable socket access for. Remember to -+ add the users you want socket access disabled for to the GID -+ specified here. If the sysctl option is enabled, whatever you choose -+ here won't matter. You'll have to specify the GID in your bootup -+ script by echoing the GID to the proper /proc entry. View the help -+ on the sysctl option for more information. If the sysctl option is -+ enabled, a sysctl option with name "socket_all_gid" is created. -+ -+config GRKERNSEC_SOCKET_CLIENT -+ bool "Deny client sockets to group" -+ depends on GRKERNSEC_SOCKET -+ help -+ If you say Y here, you will be able to choose a GID of whose users will -+ be unable to connect to other hosts from your machine, but will be -+ able to run servers. If this option is enabled, all users in the group -+ you specify will have to use passive mode when initiating ftp transfers -+ from the shell on your machine. If the sysctl option is enabled, a -+ sysctl option with name "socket_client" is created. -+ -+config GRKERNSEC_SOCKET_CLIENT_GID -+ int "GID to deny client sockets for" -+ depends on GRKERNSEC_SOCKET_CLIENT -+ default 1003 -+ help -+ Here you can choose the GID to disable client socket access for. -+ Remember to add the users you want client socket access disabled for to -+ the GID specified here. If the sysctl option is enabled, whatever you -+ choose here won't matter. You'll have to specify the GID in your bootup -+ script by echoing the GID to the proper /proc entry. View the help -+ on the sysctl option for more information. If the sysctl option is -+ enabled, a sysctl option with name "socket_client_gid" is created. -+ -+config GRKERNSEC_SOCKET_SERVER -+ bool "Deny server sockets to group" -+ depends on GRKERNSEC_SOCKET -+ help -+ If you say Y here, you will be able to choose a GID of whose users will -+ be unable to run server applications from your machine. If the sysctl -+ option is enabled, a sysctl option with name "socket_server" is created. -+ -+config GRKERNSEC_SOCKET_SERVER_GID -+ int "GID to deny server sockets for" -+ depends on GRKERNSEC_SOCKET_SERVER -+ default 1002 -+ help -+ Here you can choose the GID to disable server socket access for. -+ Remember to add the users you want server socket access disabled for to -+ the GID specified here. If the sysctl option is enabled, whatever you -+ choose here won't matter. You'll have to specify the GID in your bootup -+ script by echoing the GID to the proper /proc entry. View the help -+ on the sysctl option for more information. If the sysctl option is -+ enabled, a sysctl option with name "socket_server_gid" is created. -+ -+endmenu -+menu "Sysctl support" -+depends on GRKERNSEC && SYSCTL -+ -+config GRKERNSEC_SYSCTL -+ bool "Sysctl support" -+ help -+ If you say Y here, you will be able to change the options that -+ grsecurity runs with at bootup, without having to recompile your -+ kernel. You can echo values to files in /proc/sys/kernel/grsecurity -+ to enable (1) or disable (0) various features. All the sysctl entries -+ are mutable until the "grsec_lock" entry is set to a non-zero value. -+ All features are disabled by default. Please note that this option could -+ reduce the effectiveness of the added security of this patch if an ACL -+ system is not put in place. Your init scripts should be read-only, and -+ root should not have access to adding modules or performing raw i/o -+ operations. All options should be set at startup, and the grsec_lock -+ entry should be set to a non-zero value after all the options are set. -+ *THIS IS EXTREMELY IMPORTANT* -+ -+endmenu -+menu "Logging Options" -+depends on GRKERNSEC -+ -+config GRKERNSEC_FLOODTIME -+ int "Seconds in between log messages (minimum)" -+ default 10 -+ help -+ This option allows you to enforce the number of seconds between -+ grsecurity log messages. The default should be suitable for most -+ people, however, if you choose to change it, choose a value small enough -+ to allow informative logs to be produced, but large enough to -+ prevent flooding. -+ -+config GRKERNSEC_FLOODBURST -+ int "Number of messages in a burst (maximum)" -+ default 4 -+ help -+ This option allows you to choose the maximum number of messages allowed -+ within the flood time interval you chose in a separate option. The -+ default should be suitable for most people, however if you find that -+ many of your logs are being interpreted as flooding, you may want to -+ raise this value. -+ -+endmenu -+ -+endmenu -diff -urN linux-2.6.5/grsecurity/Makefile linux-2.6.5/grsecurity/Makefile ---- linux-2.6.5/grsecurity/Makefile 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/Makefile 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,21 @@ -+# grsecurity's ACL system was originally written in 2001 by Michael Dalton -+# during 2001, 2002, and 2003 it has been completely redesigned by -+# Brad Spengler -+# -+# All code in this directory and various hooks inserted throughout the kernel -+# are copyright Brad Spengler, and released under the GPL, unless otherwise -+# noted (as in obsd_rand.c) -+ -+obj-y = grsec_chdir.o grsec_chroot.o grsec_exec.o grsec_fifo.o grsec_fork.o \ -+ grsec_mount.o grsec_rand.o grsec_sig.o grsec_sock.o grsec_sysctl.o \ -+ grsec_time.o grsec_tpe.o grsec_ipc.o grsec_link.o grsec_textrel.o -+ -+obj-$(CONFIG_GRKERNSEC) += grsec_init.o grsum.o gracl.o gracl_ip.o gracl_segv.o obsd_rand.o \ -+ gracl_cap.o gracl_alloc.o gracl_shm.o grsec_mem.o gracl_fs.o \ -+ gracl_learn.o -+obj-$(CONFIG_GRKERNSEC_RESLOG) += gracl_res.o -+ -+ifndef CONFIG_GRKERNSEC -+obj-y += grsec_disabled.o -+endif -+ -diff -urN linux-2.6.5/grsecurity/gracl.c linux-2.6.5/grsecurity/gracl.c ---- linux-2.6.5/grsecurity/gracl.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/gracl.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,3340 @@ -+/* -+ * grsecurity/gracl.c -+ * Copyright Brad Spengler 2001, 2002, 2003 -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/sched.h> -+#include <linux/mm.h> -+#include <linux/file.h> -+#include <linux/fs.h> -+#include <linux/namei.h> -+#include <linux/mount.h> -+#include <linux/tty.h> -+#include <linux/proc_fs.h> -+#include <linux/smp_lock.h> -+#include <linux/slab.h> -+#include <linux/vmalloc.h> -+#include <linux/types.h> -+#include <linux/capability.h> -+#include <linux/sysctl.h> -+#include <linux/ptrace.h> -+#include <linux/gracl.h> -+#include <linux/gralloc.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+#include <linux/percpu.h> -+ -+#include <asm/uaccess.h> -+#include <asm/errno.h> -+#include <asm/mman.h> -+ -+static struct acl_role_db acl_role_set; -+static struct acl_role_label *role_list_head; -+static struct name_db name_set; -+static struct name_db inodev_set; -+ -+/* for keeping track of userspace pointers used for subjects, so we -+ can share references in the kernel as well -+*/ -+static struct acl_subj_map_db subj_map_set; -+ -+static struct acl_role_label *default_role; -+ -+static u16 acl_sp_role_value; -+ -+extern char *gr_shared_page[4]; -+static DECLARE_MUTEX(gr_dev_sem); -+rwlock_t gr_inode_lock = RW_LOCK_UNLOCKED; -+ -+struct gr_arg *gr_usermode; -+ -+static unsigned long gr_status = GR_STATUS_INIT; -+ -+extern int chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum); -+extern void gr_clear_learn_entries(void); -+ -+#ifdef CONFIG_GRKERNSEC_RESLOG -+extern void gr_log_resource(const struct task_struct *task, -+ const int res, const unsigned long wanted, const int gt); -+#endif -+ -+extern char * __d_path(struct dentry *dentry, struct vfsmount *vfsmnt, -+ struct dentry *root, struct vfsmount *rootmnt, -+ char *buffer, int buflen); -+ -+unsigned char *gr_system_salt; -+unsigned char *gr_system_sum; -+ -+static struct sprole_pw **acl_special_roles = NULL; -+static __u16 num_sprole_pws = 0; -+ -+static struct acl_role_label *kernel_role = NULL; -+ -+/* The following are used to keep a place held in the hash table when we move -+ entries around. They can be replaced during insert. */ -+ -+static struct acl_subject_label *deleted_subject; -+static struct acl_object_label *deleted_object; -+static struct name_entry *deleted_inodev; -+ -+/* for keeping track of the last and final allocated subjects, since -+ nested subject parsing is tricky -+*/ -+static struct acl_subject_label *s_last = NULL; -+static struct acl_subject_label *s_final = NULL; -+ -+static unsigned int gr_auth_attempts = 0; -+static unsigned long gr_auth_expires = 0UL; -+ -+extern int gr_init_uidset(void); -+extern void gr_free_uidset(void); -+extern void gr_remove_uid(uid_t uid); -+extern int gr_find_uid(uid_t uid); -+ -+__inline__ int -+gr_acl_is_enabled(void) -+{ -+ return (gr_status & GR_READY); -+} -+ -+__inline__ int -+gr_acl_tpe_check(void) -+{ -+ if (unlikely(!(gr_status & GR_READY))) -+ return 0; -+ if (current->role->roletype & GR_ROLE_TPE) -+ return 1; -+ else -+ return 0; -+} -+ -+int -+gr_handle_rawio(const struct inode *inode) -+{ -+ if (inode && S_ISBLK(inode->i_mode) && !capable(CAP_SYS_RAWIO) && -+ ((gr_status & GR_READY) -+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS -+ || (grsec_enable_chroot_caps && proc_is_chrooted(current)) -+#endif -+ )) -+ return 1; -+ return 0; -+} -+ -+ -+static __inline__ int -+gr_streq(const char *a, const char *b, const __u16 lena, const __u16 lenb) -+{ -+ int i; -+ unsigned long *l1; -+ unsigned long *l2; -+ unsigned char *c1; -+ unsigned char *c2; -+ int num_longs; -+ -+ if (likely(lena != lenb)) -+ return 0; -+ -+ l1 = (unsigned long *)a; -+ l2 = (unsigned long *)b; -+ -+ num_longs = lena / sizeof(unsigned long); -+ -+ for (i = num_longs; i--; l1++, l2++) { -+ if (unlikely(*l1 != *l2)) -+ return 0; -+ } -+ -+ c1 = (unsigned char *) l1; -+ c2 = (unsigned char *) l2; -+ -+ i = lena - (num_longs * sizeof(unsigned long)); -+ -+ for (; i--; c1++, c2++) { -+ if (unlikely(*c1 != *c2)) -+ return 0; -+ } -+ -+ return 1; -+} -+ -+static __inline__ char * -+__d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt, -+ char *buf, int buflen) -+{ -+ char *res; -+ struct dentry *our_dentry; -+ struct vfsmount *our_mount; -+ struct vfsmount *rootmnt; -+ struct dentry *root; -+ -+ our_dentry = (struct dentry *) dentry; -+ our_mount = (struct vfsmount *) vfsmnt; -+ -+ read_lock(&child_reaper->fs->lock); -+ rootmnt = mntget(child_reaper->fs->rootmnt); -+ root = dget(child_reaper->fs->root); -+ read_unlock(&child_reaper->fs->lock); -+ -+ res = __d_path(our_dentry, our_mount, root, rootmnt, buf, buflen); -+ if (unlikely(IS_ERR(res))) -+ res = strcpy(buf, "<path too long>"); -+ dput(root); -+ mntput(rootmnt); -+ return res; -+} -+ -+char * -+gr_to_filename_nolock(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ return __d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()), -+ PAGE_SIZE); -+} -+ -+static __inline__ char * -+d_real_path(const struct dentry *dentry, const struct vfsmount *vfsmnt, -+ char *buf, int buflen) -+{ -+ char *res; -+ struct dentry *our_dentry; -+ struct vfsmount *our_mount; -+ struct vfsmount *rootmnt; -+ struct dentry *root; -+ -+ our_dentry = (struct dentry *) dentry; -+ our_mount = (struct vfsmount *) vfsmnt; -+ -+ read_lock(&child_reaper->fs->lock); -+ rootmnt = mntget(child_reaper->fs->rootmnt); -+ root = dget(child_reaper->fs->root); -+ read_unlock(&child_reaper->fs->lock); -+ -+ spin_lock(&dcache_lock); -+ res = __d_path(our_dentry, our_mount, root, rootmnt, buf, buflen); -+ spin_unlock(&dcache_lock); -+ if (unlikely(IS_ERR(res))) -+ res = strcpy(buf, "<path too long>"); -+ dput(root); -+ mntput(rootmnt); -+ return res; -+} -+ -+char * -+gr_to_filename(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[0], smp_processor_id()), -+ PAGE_SIZE); -+} -+ -+char * -+gr_to_filename1(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[1], smp_processor_id()), -+ PAGE_SIZE); -+} -+ -+char * -+gr_to_filename2(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[2], smp_processor_id()), -+ PAGE_SIZE); -+} -+ -+char * -+gr_to_filename3(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ return d_real_path(dentry, mnt, per_cpu_ptr(gr_shared_page[3], smp_processor_id()), -+ PAGE_SIZE); -+} -+ -+__inline__ __u32 -+to_gr_audit(const __u32 reqmode) -+{ -+ __u32 retmode = 0; -+ -+ retmode |= (reqmode & GR_READ) ? GR_AUDIT_READ : 0; -+ retmode |= (reqmode & GR_WRITE) ? GR_AUDIT_WRITE | GR_AUDIT_APPEND : 0; -+ retmode |= (reqmode & GR_APPEND) ? GR_AUDIT_APPEND : 0; -+ retmode |= (reqmode & GR_EXEC) ? GR_AUDIT_EXEC : 0; -+ retmode |= (reqmode & GR_INHERIT) ? GR_AUDIT_INHERIT : 0; -+ retmode |= (reqmode & GR_FIND) ? GR_AUDIT_FIND : 0; -+ retmode |= (reqmode & GR_SETID) ? GR_AUDIT_SETID : 0; -+ retmode |= (reqmode & GR_CREATE) ? GR_AUDIT_CREATE : 0; -+ retmode |= (reqmode & GR_DELETE) ? GR_AUDIT_DELETE : 0; -+ -+ return retmode; -+} -+ -+__inline__ struct acl_subject_label * -+lookup_subject_map(const struct acl_subject_label *userp) -+{ -+ unsigned long index = shash(userp, subj_map_set.s_size); -+ struct subject_map *match; -+ __u8 i = 0; -+ -+ match = subj_map_set.s_hash[index]; -+ -+ while (match && match->user != userp) { -+ index = (index + (1 << i)) % subj_map_set.s_size; -+ match = subj_map_set.s_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ if (match) -+ return match->kernel; -+ else -+ return NULL; -+} -+ -+static void -+insert_subj_map_entry(struct subject_map *subjmap) -+{ -+ unsigned long index = shash(subjmap->user, subj_map_set.s_size); -+ struct subject_map **curr; -+ __u8 i = 0; -+ -+ curr = &subj_map_set.s_hash[index]; -+ -+ while (*curr) { -+ index = (index + (1 << i)) % subj_map_set.s_size; -+ curr = &subj_map_set.s_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ *curr = subjmap; -+ -+ return; -+} -+ -+__inline__ struct acl_role_label * -+lookup_acl_role_label(const struct task_struct *task, const uid_t uid, -+ const gid_t gid) -+{ -+ unsigned long index = rhash(uid, GR_ROLE_USER, acl_role_set.r_size); -+ struct acl_role_label *match; -+ struct role_allowed_ip *ipp; -+ __u8 i = 0; -+ -+ match = acl_role_set.r_hash[index]; -+ -+ while (match -+ && (match->uidgid != uid || !(match->roletype & GR_ROLE_USER))) { -+ index = (index + (1 << i)) % acl_role_set.r_size; -+ match = acl_role_set.r_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ if (match == NULL) { -+ try_group: -+ index = rhash(gid, GR_ROLE_GROUP, acl_role_set.r_size); -+ match = acl_role_set.r_hash[index]; -+ i = 0; -+ -+ while (match && (match->uidgid != gid -+ || !(match->roletype & GR_ROLE_GROUP))) { -+ index = (index + (1 << i)) % acl_role_set.r_size; -+ match = acl_role_set.r_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ if (match == NULL) -+ match = default_role; -+ if (match->allowed_ips == NULL) -+ return match; -+ else { -+ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) { -+ if (likely -+ ((task->curr_ip & ipp->netmask) == -+ (ipp->addr & ipp->netmask))) -+ return match; -+ } -+ match = default_role; -+ } -+ } else if (match->allowed_ips == NULL) { -+ return match; -+ } else { -+ for (ipp = match->allowed_ips; ipp; ipp = ipp->next) { -+ if (likely -+ ((task->curr_ip & ipp->netmask) == -+ (ipp->addr & ipp->netmask))) -+ return match; -+ } -+ goto try_group; -+ } -+ -+ return match; -+} -+ -+__inline__ struct acl_subject_label * -+lookup_acl_subj_label(const ino_t ino, const dev_t dev, -+ const struct acl_role_label *role) -+{ -+ unsigned long subj_size = role->subj_hash_size; -+ struct acl_subject_label **s_hash = role->subj_hash; -+ unsigned long index = fhash(ino, dev, subj_size); -+ struct acl_subject_label *match; -+ __u8 i = 0; -+ -+ match = s_hash[index]; -+ -+ while (match && (match->inode != ino || match->device != dev || -+ (match->mode & GR_DELETED))) { -+ index = (index + (1 << i)) % subj_size; -+ match = s_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ if (match && (match != deleted_subject) && !(match->mode & GR_DELETED)) -+ return match; -+ else -+ return NULL; -+} -+ -+static __inline__ struct acl_object_label * -+lookup_acl_obj_label(const ino_t ino, const dev_t dev, -+ const struct acl_subject_label *subj) -+{ -+ unsigned long obj_size = subj->obj_hash_size; -+ struct acl_object_label **o_hash = subj->obj_hash; -+ unsigned long index = fhash(ino, dev, obj_size); -+ struct acl_object_label *match; -+ __u8 i = 0; -+ -+ match = o_hash[index]; -+ -+ while (match && (match->inode != ino || match->device != dev || -+ (match->mode & GR_DELETED))) { -+ index = (index + (1 << i)) % obj_size; -+ match = o_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ if (match && (match != deleted_object) && !(match->mode & GR_DELETED)) -+ return match; -+ else -+ return NULL; -+} -+ -+static __inline__ struct acl_object_label * -+lookup_acl_obj_label_create(const ino_t ino, const dev_t dev, -+ const struct acl_subject_label *subj) -+{ -+ unsigned long obj_size = subj->obj_hash_size; -+ struct acl_object_label **o_hash = subj->obj_hash; -+ unsigned long index = fhash(ino, dev, obj_size); -+ struct acl_object_label *match; -+ __u8 i = 0; -+ -+ match = o_hash[index]; -+ -+ while (match && (match->inode != ino || match->device != dev || -+ !(match->mode & GR_DELETED))) { -+ index = (index + (1 << i)) % obj_size; -+ match = o_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ if (match && (match != deleted_object) && (match->mode & GR_DELETED)) -+ return match; -+ -+ i = 0; -+ index = fhash(ino, dev, obj_size); -+ match = o_hash[index]; -+ -+ while (match && (match->inode != ino || match->device != dev || -+ (match->mode & GR_DELETED))) { -+ index = (index + (1 << i)) % obj_size; -+ match = o_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ if (match && (match != deleted_object) && !(match->mode & GR_DELETED)) -+ return match; -+ else -+ return NULL; -+} -+ -+static __inline__ struct name_entry * -+lookup_name_entry(const char *name) -+{ -+ __u16 len = strlen(name); -+ unsigned long index = nhash(name, len, name_set.n_size); -+ struct name_entry *match; -+ __u8 i = 0; -+ -+ match = name_set.n_hash[index]; -+ -+ while (match && !gr_streq(match->name, name, match->len, len)) { -+ index = (index + (1 << i)) % name_set.n_size; -+ match = name_set.n_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ return match; -+} -+ -+static __inline__ struct name_entry * -+lookup_inodev_entry(const ino_t ino, const dev_t dev) -+{ -+ unsigned long index = fhash(ino, dev, inodev_set.n_size); -+ struct name_entry *match; -+ __u8 i = 0; -+ -+ match = inodev_set.n_hash[index]; -+ -+ while (match && (match->inode != ino || match->device != dev)) { -+ index = (index + (1 << i)) % inodev_set.n_size; -+ match = inodev_set.n_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ if (match && (match != deleted_inodev)) -+ return match; -+ else -+ return NULL; -+} -+ -+static void -+insert_inodev_entry(struct name_entry *nentry) -+{ -+ unsigned long index = fhash(nentry->inode, nentry->device, -+ inodev_set.n_size); -+ struct name_entry **curr; -+ __u8 i = 0; -+ -+ curr = &inodev_set.n_hash[index]; -+ -+ while (*curr && *curr != deleted_inodev) { -+ index = (index + (1 << i)) % inodev_set.n_size; -+ curr = &inodev_set.n_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ *curr = nentry; -+ -+ return; -+} -+ -+static void -+insert_acl_role_label(struct acl_role_label *role) -+{ -+ unsigned long index = -+ rhash(role->uidgid, role->roletype & (GR_ROLE_USER | GR_ROLE_GROUP), acl_role_set.r_size); -+ struct acl_role_label **curr; -+ __u8 i = 0; -+ -+ curr = &acl_role_set.r_hash[index]; -+ -+ while (*curr) { -+ index = (index + (1 << i)) % acl_role_set.r_size; -+ curr = &acl_role_set.r_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ *curr = role; -+ -+ return; -+} -+ -+static int -+insert_name_entry(char *name, const ino_t inode, const dev_t device) -+{ -+ struct name_entry **curr; -+ __u8 i = 0; -+ __u16 len = strlen(name); -+ unsigned long index = nhash(name, len, name_set.n_size); -+ -+ curr = &name_set.n_hash[index]; -+ -+ while (*curr && !gr_streq((*curr)->name, name, (*curr)->len, len)) { -+ index = (index + (1 << i)) % name_set.n_size; -+ curr = &name_set.n_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ if (!(*curr)) { -+ struct name_entry *nentry = -+ acl_alloc(sizeof (struct name_entry)); -+ if (!nentry) -+ return 0; -+ nentry->name = name; -+ nentry->inode = inode; -+ nentry->device = device; -+ nentry->len = len; -+ *curr = nentry; -+ /* insert us into the table searchable by inode/dev */ -+ insert_inodev_entry(nentry); -+ } -+ -+ return 1; -+} -+ -+static void -+insert_acl_obj_label(struct acl_object_label *obj, -+ struct acl_subject_label *subj) -+{ -+ unsigned long index = -+ fhash(obj->inode, obj->device, subj->obj_hash_size); -+ struct acl_object_label **curr; -+ __u8 i = 0; -+ -+ curr = &subj->obj_hash[index]; -+ -+ while (*curr && *curr != deleted_object) { -+ index = (index + (1 << i)) % subj->obj_hash_size; -+ curr = &subj->obj_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ *curr = obj; -+ -+ return; -+} -+ -+static void -+insert_acl_subj_label(struct acl_subject_label *obj, -+ struct acl_role_label *role) -+{ -+ unsigned long subj_size = role->subj_hash_size; -+ struct acl_subject_label **s_hash = role->subj_hash; -+ unsigned long index = fhash(obj->inode, obj->device, subj_size); -+ struct acl_subject_label **curr; -+ __u8 i = 0; -+ -+ curr = &s_hash[index]; -+ -+ while (*curr && *curr != deleted_subject) { -+ index = (index + (1 << i)) % subj_size; -+ curr = &s_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ *curr = obj; -+ -+ return; -+} -+ -+static void ** -+create_table(__u32 * len) -+{ -+ unsigned long table_sizes[] = { -+ 7, 13, 31, 61, 127, 251, 509, 1021, 2039, 4093, 8191, 16381, -+ 32749, 65521, 131071, 262139, 524287, 1048573, 2097143, -+ 4194301, 8388593, 16777213, 33554393, 67108859, 134217689, -+ 268435399, 536870909, 1073741789, 2147483647 -+ }; -+ void *newtable = NULL; -+ unsigned int pwr = 0; -+ -+ while ((pwr < ((sizeof (table_sizes) / sizeof (table_sizes[0])) - 1)) && -+ table_sizes[pwr] <= (2 * (*len))) -+ pwr++; -+ -+ if (table_sizes[pwr] <= (2 * (*len))) -+ return newtable; -+ -+ if ((table_sizes[pwr] * sizeof (void *)) <= PAGE_SIZE) -+ newtable = -+ kmalloc(table_sizes[pwr] * sizeof (void *), GFP_KERNEL); -+ else -+ newtable = vmalloc(table_sizes[pwr] * sizeof (void *)); -+ -+ *len = table_sizes[pwr]; -+ -+ return newtable; -+} -+ -+static int -+init_variables(const unsigned long acl_obj_size, -+ const unsigned long acl_glob_size, -+ const unsigned long acl_subj_size, -+ const unsigned long acl_ip_size, -+ const unsigned long acl_role_size, -+ const unsigned long allowed_ip_size, -+ const unsigned long acl_trans_size, -+ const __u16 num_sprole_pws) -+{ -+ unsigned long stacksize; -+ -+ subj_map_set.s_size = acl_subj_size; -+ acl_role_set.r_size = acl_role_size; -+ name_set.n_size = (acl_obj_size + acl_subj_size); -+ inodev_set.n_size = (acl_obj_size + acl_subj_size); -+ -+ if (!gr_init_uidset()) -+ return 1; -+ -+ /* set up the stack that holds allocation info */ -+ -+ stacksize = (3 * acl_obj_size) + (3 * acl_role_size) + -+ (6 * acl_subj_size) + acl_ip_size + (2 * acl_trans_size) + -+ allowed_ip_size + (2 * num_sprole_pws) + (2 * acl_glob_size) + 5; -+ -+ if (!acl_alloc_stack_init(stacksize)) -+ return 1; -+ -+ /* create our empty, fake deleted acls */ -+ deleted_subject = -+ (struct acl_subject_label *) -+ acl_alloc(sizeof (struct acl_subject_label)); -+ deleted_object = -+ (struct acl_object_label *) -+ acl_alloc(sizeof (struct acl_object_label)); -+ deleted_inodev = -+ (struct name_entry *) acl_alloc(sizeof (struct name_entry)); -+ -+ if (!deleted_subject || !deleted_object || !deleted_inodev) -+ return 1; -+ -+ memset(deleted_subject, 0, sizeof (struct acl_subject_label)); -+ memset(deleted_object, 0, sizeof (struct acl_object_label)); -+ memset(deleted_inodev, 0, sizeof (struct name_entry)); -+ -+ /* We only want 50% full tables for now */ -+ -+ subj_map_set.s_hash = -+ (struct subject_map **) create_table(&subj_map_set.s_size); -+ acl_role_set.r_hash = -+ (struct acl_role_label **) create_table(&acl_role_set.r_size); -+ name_set.n_hash = (struct name_entry **) create_table(&name_set.n_size); -+ inodev_set.n_hash = -+ (struct name_entry **) create_table(&inodev_set.n_size); -+ -+ if (!subj_map_set.s_hash || !acl_role_set.r_hash || -+ !name_set.n_hash || !inodev_set.n_hash) -+ return 1; -+ -+ memset(subj_map_set.s_hash, 0, -+ sizeof(struct subject_map *) * subj_map_set.s_size); -+ memset(acl_role_set.r_hash, 0, -+ sizeof (struct acl_role_label *) * acl_role_set.r_size); -+ memset(name_set.n_hash, 0, -+ sizeof (struct name_entry *) * name_set.n_size); -+ memset(inodev_set.n_hash, 0, -+ sizeof (struct name_entry *) * inodev_set.n_size); -+ -+ return 0; -+} -+ -+/* free information not needed after startup -+ currently contains user->kernel pointer mappings for subjects -+*/ -+ -+static void -+free_init_variables(void) -+{ -+ __u32 i; -+ -+ if (subj_map_set.s_hash) { -+ for (i = 0; i < subj_map_set.s_size; i++) { -+ if (subj_map_set.s_hash[i]) { -+ kfree(subj_map_set.s_hash[i]); -+ subj_map_set.s_hash[i] = NULL; -+ } -+ } -+ -+ if ((subj_map_set.s_size * sizeof (struct subject_map *)) <= -+ PAGE_SIZE) -+ kfree(subj_map_set.s_hash); -+ else -+ vfree(subj_map_set.s_hash); -+ } -+ -+ return; -+} -+ -+static void -+free_variables(void) -+{ -+ struct acl_subject_label *s; -+ struct acl_role_label *r; -+ struct task_struct *task, *task2; -+ -+ gr_clear_learn_entries(); -+ -+ read_lock(&tasklist_lock); -+ for_each_process(task) { -+ task2 = task; -+ do { -+ task2->acl_sp_role = 0; -+ task2->acl_role_id = 0; -+ task2->acl = NULL; -+ task2->role = NULL; -+ } while ((task2 = next_thread(task2)) != task); -+ } -+ read_unlock(&tasklist_lock); -+ -+ /* free all object hash tables */ -+ -+ if (role_list_head) { -+ for (r = role_list_head; r; r = r->next) { -+ if (!r->subj_hash) -+ break; -+ for (s = r->hash->first; s; s = s->next) { -+ if (!s->obj_hash) -+ break; -+ if ((s->obj_hash_size * -+ sizeof (struct acl_object_label *)) <= -+ PAGE_SIZE) -+ kfree(s->obj_hash); -+ else -+ vfree(s->obj_hash); -+ } -+ if ((r->subj_hash_size * -+ sizeof (struct acl_subject_label *)) <= PAGE_SIZE) -+ kfree(r->subj_hash); -+ else -+ vfree(r->subj_hash); -+ } -+ } -+ -+ acl_free_all(); -+ -+ if (acl_role_set.r_hash) { -+ if ((acl_role_set.r_size * sizeof (struct acl_role_label *)) <= -+ PAGE_SIZE) -+ kfree(acl_role_set.r_hash); -+ else -+ vfree(acl_role_set.r_hash); -+ } -+ if (name_set.n_hash) { -+ if ((name_set.n_size * sizeof (struct name_entry *)) <= -+ PAGE_SIZE) -+ kfree(name_set.n_hash); -+ else -+ vfree(name_set.n_hash); -+ } -+ -+ if (inodev_set.n_hash) { -+ if ((inodev_set.n_size * sizeof (struct name_entry *)) <= -+ PAGE_SIZE) -+ kfree(inodev_set.n_hash); -+ else -+ vfree(inodev_set.n_hash); -+ } -+ -+ gr_free_uidset(); -+ -+ memset(&name_set, 0, sizeof (struct name_db)); -+ memset(&inodev_set, 0, sizeof (struct name_db)); -+ memset(&acl_role_set, 0, sizeof (struct acl_role_db)); -+ memset(&subj_map_set, 0, sizeof (struct acl_subj_map_db)); -+ -+ role_list_head = NULL; -+ default_role = NULL; -+ -+ return; -+} -+ -+static __u32 -+count_user_objs(struct acl_object_label *userp) -+{ -+ struct acl_object_label o_tmp; -+ __u32 num = 0; -+ -+ while (userp) { -+ if (copy_from_user(&o_tmp, userp, -+ sizeof (struct acl_object_label))) -+ break; -+ -+ userp = o_tmp.prev; -+ num++; -+ } -+ -+ return num; -+} -+ -+static struct acl_subject_label * -+do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role); -+ -+static int -+copy_user_glob(struct acl_object_label *obj) -+{ -+ struct acl_object_label *g_tmp, **guser, *glast = NULL; -+ unsigned int len; -+ char *tmp; -+ -+ if (obj->globbed == NULL) -+ return 0; -+ -+ guser = &obj->globbed; -+ while (*guser) { -+ g_tmp = (struct acl_object_label *) -+ acl_alloc(sizeof (struct acl_object_label)); -+ if (g_tmp == NULL) -+ return -ENOMEM; -+ -+ if (copy_from_user(g_tmp, *guser, -+ sizeof (struct acl_object_label))) -+ return -EFAULT; -+ -+ len = strnlen_user(g_tmp->filename, PATH_MAX); -+ -+ if (!len || len >= PATH_MAX) -+ return -EINVAL; -+ -+ if ((tmp = (char *) acl_alloc(len)) == NULL) -+ return -ENOMEM; -+ -+ if (copy_from_user(tmp, g_tmp->filename, len)) -+ return -EFAULT; -+ -+ g_tmp->filename = tmp; -+ -+ if (glast) -+ glast->next = g_tmp; -+ g_tmp->prev = glast; -+ *guser = g_tmp; -+ glast = g_tmp; -+ guser = &((*guser)->next); -+ } -+ -+ return 0; -+} -+ -+static int -+copy_user_objs(struct acl_object_label *userp, struct acl_subject_label *subj, -+ struct acl_role_label *role) -+{ -+ struct acl_object_label *o_tmp; -+ unsigned int len; -+ int ret; -+ char *tmp; -+ -+ while (userp) { -+ if ((o_tmp = (struct acl_object_label *) -+ acl_alloc(sizeof (struct acl_object_label))) == NULL) -+ return -ENOMEM; -+ -+ if (copy_from_user(o_tmp, userp, -+ sizeof (struct acl_object_label))) -+ return -EFAULT; -+ -+ userp = o_tmp->prev; -+ -+ len = strnlen_user(o_tmp->filename, PATH_MAX); -+ -+ if (!len || len >= PATH_MAX) -+ return -EINVAL; -+ -+ if ((tmp = (char *) acl_alloc(len)) == NULL) -+ return -ENOMEM; -+ -+ if (copy_from_user(tmp, o_tmp->filename, len)) -+ return -EFAULT; -+ -+ o_tmp->filename = tmp; -+ -+ insert_acl_obj_label(o_tmp, subj); -+ if (!insert_name_entry(o_tmp->filename, o_tmp->inode, -+ o_tmp->device)) -+ return -ENOMEM; -+ -+ ret = copy_user_glob(o_tmp); -+ if (ret) -+ return ret; -+ -+ if (o_tmp->nested) { -+ o_tmp->nested = do_copy_user_subj(o_tmp->nested, role); -+ if (IS_ERR(o_tmp->nested)) -+ return PTR_ERR(o_tmp->nested); -+ -+ s_final = o_tmp->nested; -+ } -+ } -+ -+ return 0; -+} -+ -+static __u32 -+count_user_subjs(struct acl_subject_label *userp) -+{ -+ struct acl_subject_label s_tmp; -+ __u32 num = 0; -+ -+ while (userp) { -+ if (copy_from_user(&s_tmp, userp, -+ sizeof (struct acl_subject_label))) -+ break; -+ -+ userp = s_tmp.prev; -+ /* do not count nested subjects against this count, since -+ they are not included in the hash table, but are -+ attached to objects. We have already counted -+ the subjects in userspace for the allocation -+ stack -+ */ -+ if (!(s_tmp.mode & GR_NESTED)) -+ num++; -+ } -+ -+ return num; -+} -+ -+static int -+copy_user_allowedips(struct acl_role_label *rolep) -+{ -+ struct role_allowed_ip *ruserip, *rtmp = NULL, *rlast; -+ -+ ruserip = rolep->allowed_ips; -+ -+ while (ruserip) { -+ rlast = rtmp; -+ -+ if ((rtmp = (struct role_allowed_ip *) -+ acl_alloc(sizeof (struct role_allowed_ip))) == NULL) -+ return -ENOMEM; -+ -+ if (copy_from_user(rtmp, ruserip, -+ sizeof (struct role_allowed_ip))) -+ return -EFAULT; -+ -+ ruserip = rtmp->prev; -+ -+ if (!rlast) { -+ rtmp->prev = NULL; -+ rolep->allowed_ips = rtmp; -+ } else { -+ rlast->next = rtmp; -+ rtmp->prev = rlast; -+ } -+ -+ if (!ruserip) -+ rtmp->next = NULL; -+ } -+ -+ return 0; -+} -+ -+static int -+copy_user_transitions(struct acl_role_label *rolep) -+{ -+ struct role_transition *rusertp, *rtmp = NULL, *rlast; -+ unsigned int len; -+ char *tmp; -+ -+ rusertp = rolep->transitions; -+ -+ while (rusertp) { -+ rlast = rtmp; -+ -+ if ((rtmp = (struct role_transition *) -+ acl_alloc(sizeof (struct role_transition))) == NULL) -+ return -ENOMEM; -+ -+ if (copy_from_user(rtmp, rusertp, -+ sizeof (struct role_transition))) -+ return -EFAULT; -+ -+ rusertp = rtmp->prev; -+ -+ len = strnlen_user(rtmp->rolename, GR_SPROLE_LEN); -+ -+ if (!len || len >= GR_SPROLE_LEN) -+ return -EINVAL; -+ -+ if ((tmp = (char *) acl_alloc(len)) == NULL) -+ return -ENOMEM; -+ -+ if (copy_from_user(tmp, rtmp->rolename, len)) -+ return -EFAULT; -+ -+ rtmp->rolename = tmp; -+ -+ if (!rlast) { -+ rtmp->prev = NULL; -+ rolep->transitions = rtmp; -+ } else { -+ rlast->next = rtmp; -+ rtmp->prev = rlast; -+ } -+ -+ if (!rusertp) -+ rtmp->next = NULL; -+ } -+ -+ return 0; -+} -+ -+static struct acl_subject_label * -+do_copy_user_subj(struct acl_subject_label *userp, struct acl_role_label *role) -+{ -+ struct acl_subject_label *s_tmp = NULL, *s_tmp2; -+ unsigned int len; -+ char *tmp; -+ __u32 num_objs; -+ struct acl_ip_label **i_tmp, *i_utmp2; -+ struct gr_hash_struct ghash; -+ struct subject_map *subjmap; -+ unsigned long i_num; -+ int err; -+ -+ s_tmp = lookup_subject_map(userp); -+ -+ /* we've already copied this subject into the kernel, just return -+ the reference to it, and don't copy it over again -+ */ -+ if (s_tmp) -+ return(s_tmp); -+ -+ -+ if ((s_tmp = (struct acl_subject_label *) -+ acl_alloc(sizeof (struct acl_subject_label))) == NULL) -+ return ERR_PTR(-ENOMEM); -+ -+ subjmap = (struct subject_map *)kmalloc(sizeof (struct subject_map), GFP_KERNEL); -+ if (subjmap == NULL) -+ return ERR_PTR(-ENOMEM); -+ -+ subjmap->user = userp; -+ subjmap->kernel = s_tmp; -+ insert_subj_map_entry(subjmap); -+ -+ if (copy_from_user(s_tmp, userp, -+ sizeof (struct acl_subject_label))) -+ return ERR_PTR(-EFAULT); -+ -+ if (!s_last) { -+ s_tmp->prev = NULL; -+ role->hash->first = s_tmp; -+ } else { -+ s_last->next = s_tmp; -+ s_tmp->prev = s_last; -+ } -+ -+ s_last = s_tmp; -+ -+ len = strnlen_user(s_tmp->filename, PATH_MAX); -+ -+ if (!len || len >= PATH_MAX) -+ return ERR_PTR(-EINVAL); -+ -+ if ((tmp = (char *) acl_alloc(len)) == NULL) -+ return ERR_PTR(-ENOMEM); -+ -+ if (copy_from_user(tmp, s_tmp->filename, len)) -+ return ERR_PTR(-EFAULT); -+ -+ s_tmp->filename = tmp; -+ -+ if (!strcmp(s_tmp->filename, "/")) -+ role->root_label = s_tmp; -+ -+ if (copy_from_user(&ghash, s_tmp->hash, sizeof(struct gr_hash_struct))) -+ return ERR_PTR(-EFAULT); -+ -+ /* copy user and group transition tables */ -+ -+ if (s_tmp->user_trans_num) { -+ uid_t *uidlist; -+ -+ uidlist = (uid_t *)acl_alloc(s_tmp->user_trans_num * sizeof(uid_t)); -+ if (uidlist == NULL) -+ return ERR_PTR(-ENOMEM); -+ if (copy_from_user(uidlist, s_tmp->user_transitions, s_tmp->user_trans_num * sizeof(uid_t))) -+ return ERR_PTR(-EFAULT); -+ -+ s_tmp->user_transitions = uidlist; -+ } -+ -+ if (s_tmp->group_trans_num) { -+ gid_t *gidlist; -+ -+ gidlist = (gid_t *)acl_alloc(s_tmp->group_trans_num * sizeof(gid_t)); -+ if (gidlist == NULL) -+ return ERR_PTR(-ENOMEM); -+ if (copy_from_user(gidlist, s_tmp->group_transitions, s_tmp->group_trans_num * sizeof(gid_t))) -+ return ERR_PTR(-EFAULT); -+ -+ s_tmp->group_transitions = gidlist; -+ } -+ -+ /* set up object hash table */ -+ num_objs = count_user_objs(ghash.first); -+ -+ s_tmp->obj_hash_size = num_objs; -+ s_tmp->obj_hash = -+ (struct acl_object_label **) -+ create_table(&(s_tmp->obj_hash_size)); -+ -+ if (!s_tmp->obj_hash) -+ return ERR_PTR(-ENOMEM); -+ -+ memset(s_tmp->obj_hash, 0, -+ s_tmp->obj_hash_size * -+ sizeof (struct acl_object_label *)); -+ -+ /* copy before adding in objects, since a nested -+ acl could be found and be the final subject -+ copied -+ */ -+ -+ s_final = s_tmp; -+ -+ /* add in objects */ -+ err = copy_user_objs(ghash.first, s_tmp, role); -+ -+ if (err) -+ return ERR_PTR(err); -+ -+ /* set pointer for parent subject */ -+ if (s_tmp->parent_subject) { -+ s_tmp2 = do_copy_user_subj(s_tmp->parent_subject, role); -+ -+ if (IS_ERR(s_tmp2)) -+ return s_tmp2; -+ -+ s_tmp->parent_subject = s_tmp2; -+ } -+ -+ /* add in ip acls */ -+ -+ if (!s_tmp->ip_num) { -+ s_tmp->ips = NULL; -+ goto insert; -+ } -+ -+ i_tmp = -+ (struct acl_ip_label **) acl_alloc(s_tmp->ip_num * -+ sizeof (struct -+ acl_ip_label *)); -+ -+ if (!i_tmp) -+ return ERR_PTR(-ENOMEM); -+ -+ for (i_num = 0; i_num < s_tmp->ip_num; i_num++) { -+ *(i_tmp + i_num) = -+ (struct acl_ip_label *) -+ acl_alloc(sizeof (struct acl_ip_label)); -+ if (!*(i_tmp + i_num)) -+ return ERR_PTR(-ENOMEM); -+ -+ if (copy_from_user -+ (&i_utmp2, s_tmp->ips + i_num, -+ sizeof (struct acl_ip_label *))) -+ return ERR_PTR(-EFAULT); -+ -+ if (copy_from_user -+ (*(i_tmp + i_num), i_utmp2, -+ sizeof (struct acl_ip_label))) -+ return ERR_PTR(-EFAULT); -+ } -+ -+ s_tmp->ips = i_tmp; -+ -+insert: -+ if (!insert_name_entry(s_tmp->filename, s_tmp->inode, -+ s_tmp->device)) -+ return ERR_PTR(-ENOMEM); -+ -+ return s_tmp; -+} -+ -+static int -+copy_user_subjs(struct acl_subject_label *userp, struct acl_role_label *role) -+{ -+ struct acl_subject_label s_pre; -+ struct acl_subject_label * ret; -+ int err; -+ -+ while (userp) { -+ if (copy_from_user(&s_pre, userp, -+ sizeof (struct acl_subject_label))) -+ return -EFAULT; -+ -+ /* do not add nested subjects here, add -+ while parsing objects -+ */ -+ -+ if (s_pre.mode & GR_NESTED) { -+ userp = s_pre.prev; -+ continue; -+ } -+ -+ ret = do_copy_user_subj(userp, role); -+ -+ err = PTR_ERR(ret); -+ if (IS_ERR(ret)) -+ return err; -+ -+ insert_acl_subj_label(ret, role); -+ -+ userp = s_pre.prev; -+ } -+ -+ s_final->next = NULL; -+ -+ return 0; -+} -+ -+static int -+copy_user_acl(struct gr_arg *arg) -+{ -+ struct acl_role_label *r_tmp = NULL, **r_utmp, *r_utmp2, *r_last; -+ struct sprole_pw *sptmp; -+ struct gr_hash_struct *ghash; -+ unsigned long r_num; -+ unsigned int len; -+ char *tmp; -+ int err = 0; -+ __u16 i; -+ __u32 num_subjs; -+ -+ /* we need a default and kernel role */ -+ if (arg->role_db.r_entries < 2) -+ return -EINVAL; -+ -+ /* copy special role authentication info from userspace */ -+ -+ num_sprole_pws = arg->num_sprole_pws; -+ acl_special_roles = (struct sprole_pw **) acl_alloc(num_sprole_pws * sizeof(struct sprole_pw *)); -+ -+ if (!acl_special_roles) { -+ err = -ENOMEM; -+ goto cleanup; -+ } -+ -+ for (i = 0; i < num_sprole_pws; i++) { -+ sptmp = (struct sprole_pw *) acl_alloc(sizeof(struct sprole_pw)); -+ if (!sptmp) { -+ err = -ENOMEM; -+ goto cleanup; -+ } -+ if (copy_from_user(sptmp, arg->sprole_pws + i, -+ sizeof (struct sprole_pw))) { -+ err = -EFAULT; -+ goto cleanup; -+ } -+ -+ len = -+ strnlen_user(sptmp->rolename, GR_SPROLE_LEN); -+ -+ if (!len || len >= GR_SPROLE_LEN) { -+ err = -EINVAL; -+ goto cleanup; -+ } -+ -+ if ((tmp = (char *) acl_alloc(len)) == NULL) { -+ err = -ENOMEM; -+ goto cleanup; -+ } -+ -+ if (copy_from_user(tmp, sptmp->rolename, len)) { -+ err = -EFAULT; -+ goto cleanup; -+ } -+ -+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG -+ printk(KERN_ALERT "Copying special role %s\n", tmp); -+#endif -+ sptmp->rolename = tmp; -+ acl_special_roles[i] = sptmp; -+ } -+ -+ r_utmp = (struct acl_role_label **) arg->role_db.r_table; -+ -+ for (r_num = 0; r_num < arg->role_db.r_entries; r_num++) { -+ r_last = r_tmp; -+ -+ r_tmp = acl_alloc(sizeof (struct acl_role_label)); -+ -+ if (!r_tmp) { -+ err = -ENOMEM; -+ goto cleanup; -+ } -+ -+ if (copy_from_user(&r_utmp2, r_utmp + r_num, -+ sizeof (struct acl_role_label *))) { -+ err = -EFAULT; -+ goto cleanup; -+ } -+ -+ if (copy_from_user(r_tmp, r_utmp2, -+ sizeof (struct acl_role_label))) { -+ err = -EFAULT; -+ goto cleanup; -+ } -+ -+ if (!r_last) { -+ r_tmp->prev = NULL; -+ role_list_head = r_tmp; -+ } else { -+ r_last->next = r_tmp; -+ r_tmp->prev = r_last; -+ } -+ -+ if (r_num == (arg->role_db.r_entries - 1)) -+ r_tmp->next = NULL; -+ -+ len = strnlen_user(r_tmp->rolename, PATH_MAX); -+ -+ if (!len || len >= PATH_MAX) { -+ err = -EINVAL; -+ goto cleanup; -+ } -+ -+ if ((tmp = (char *) acl_alloc(len)) == NULL) { -+ err = -ENOMEM; -+ goto cleanup; -+ } -+ if (copy_from_user(tmp, r_tmp->rolename, len)) { -+ err = -EFAULT; -+ goto cleanup; -+ } -+ r_tmp->rolename = tmp; -+ -+ if (!strcmp(r_tmp->rolename, "default") -+ && (r_tmp->roletype & GR_ROLE_DEFAULT)) { -+ default_role = r_tmp; -+ } else if (!strcmp(r_tmp->rolename, ":::kernel:::")) { -+ kernel_role = r_tmp; -+ } -+ -+ if ((ghash = (struct gr_hash_struct *) acl_alloc(sizeof(struct gr_hash_struct))) == NULL) { -+ err = -ENOMEM; -+ goto cleanup; -+ } -+ if (copy_from_user(ghash, r_tmp->hash, sizeof(struct gr_hash_struct))) { -+ err = -EFAULT; -+ goto cleanup; -+ } -+ -+ r_tmp->hash = ghash; -+ -+ num_subjs = count_user_subjs(r_tmp->hash->first); -+ -+ r_tmp->subj_hash_size = num_subjs; -+ r_tmp->subj_hash = -+ (struct acl_subject_label **) -+ create_table(&(r_tmp->subj_hash_size)); -+ -+ if (!r_tmp->subj_hash) { -+ err = -ENOMEM; -+ goto cleanup; -+ } -+ -+ err = copy_user_allowedips(r_tmp); -+ if (err) -+ goto cleanup; -+ -+ err = copy_user_transitions(r_tmp); -+ if (err) -+ goto cleanup; -+ -+ memset(r_tmp->subj_hash, 0, -+ r_tmp->subj_hash_size * -+ sizeof (struct acl_subject_label *)); -+ -+ s_last = NULL; -+ -+ err = copy_user_subjs(r_tmp->hash->first, r_tmp); -+ -+ if (err) -+ goto cleanup; -+ -+ insert_acl_role_label(r_tmp); -+ } -+ -+ goto return_err; -+ cleanup: -+ free_variables(); -+ return_err: -+ return err; -+ -+} -+ -+static int -+gracl_init(struct gr_arg *args) -+{ -+ int error = 0; -+ -+ memcpy(gr_system_salt, args->salt, GR_SALT_LEN); -+ memcpy(gr_system_sum, args->sum, GR_SHA_LEN); -+ -+ if (init_variables(args->role_db.o_entries, args->role_db.g_entries, -+ args->role_db.s_entries, args->role_db.i_entries, -+ args->role_db.r_entries, args->role_db.a_entries, -+ args->role_db.t_entries, args->num_sprole_pws)) { -+ security_alert_good(GR_INITF_ACL_MSG, GR_VERSION); -+ error = -ENOMEM; -+ free_variables(); -+ goto out; -+ } -+ -+ error = copy_user_acl(args); -+ free_init_variables(); -+ if (error) { -+ free_variables(); -+ goto out; -+ } -+ -+ if ((error = gr_set_acls(0))) { -+ free_variables(); -+ goto out; -+ } -+ -+ gr_status |= GR_READY; -+ out: -+ return error; -+} -+ -+static int -+glob_match(char *pattern, char *string) -+{ -+ char *p1, *p2; -+ -+ p1 = pattern; -+ p2 = string; -+ -+ while (*p1 != '\0' && *p2 != '\0' && *p1 != '*') { -+ if (*p1 == *p2 || *p1 == '?') { -+ p1++; -+ p2++; -+ } else -+ break; -+ } -+ if (*p1 == '*') { -+ p1++; -+ while (*p2 != '\0') { -+ if (!glob_match(p1, p2)) -+ return 0; -+ else -+ p2++; -+ } -+ } -+ -+ if (*p2 == '\0' && *p1 == '*') -+ while (*p1 == '*') -+ p1++; -+ -+ if (*p1 == '\0' && *p2 == '\0') -+ return 0; -+ else -+ return 1; -+} -+ -+static struct acl_object_label * -+chk_glob_label(struct acl_object_label *globbed, -+ struct dentry *dentry, struct vfsmount *mnt, char **path) -+{ -+ struct acl_object_label *tmp; -+ -+ if (*path == NULL) -+ *path = gr_to_filename_nolock(dentry, mnt); -+ -+ tmp = globbed; -+ -+ while (tmp) { -+ if (!glob_match(tmp->filename, *path)) -+ return tmp; -+ tmp = tmp->next; -+ } -+ -+ return NULL; -+} -+ -+static __inline__ struct acl_object_label * -+full_lookup(const struct dentry *orig_dentry, const struct vfsmount *orig_mnt, -+ struct dentry *curr_dentry, -+ const struct acl_subject_label *subj, char **path) -+{ -+ struct acl_subject_label *tmpsubj; -+ struct acl_object_label *retval; -+ struct acl_object_label *retval2; -+ -+ tmpsubj = (struct acl_subject_label *) subj; -+ read_lock(&gr_inode_lock); -+ do { -+ retval = lookup_acl_obj_label(curr_dentry->d_inode->i_ino, -+ curr_dentry->d_inode->i_sb->s_dev, tmpsubj); -+ if (retval) { -+ if (retval->globbed) { -+ retval2 = chk_glob_label(retval->globbed, (struct dentry *)orig_dentry, -+ (struct vfsmount *)orig_mnt, path); -+ if (retval2) -+ retval = retval2; -+ } -+ break; -+ } -+ } while ((tmpsubj = tmpsubj->parent_subject)); -+ read_unlock(&gr_inode_lock); -+ -+ return retval; -+} -+ -+static struct acl_object_label * -+chk_obj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt, -+ const struct acl_subject_label *subj) -+{ -+ struct dentry *dentry = (struct dentry *) l_dentry; -+ struct vfsmount *mnt = (struct vfsmount *) l_mnt; -+ struct dentry *root; -+ struct vfsmount *rootmnt; -+ struct acl_object_label *retval; -+ char *path = NULL; -+ -+ read_lock(&child_reaper->fs->lock); -+ rootmnt = mntget(child_reaper->fs->rootmnt); -+ root = dget(child_reaper->fs->root); -+ read_unlock(&child_reaper->fs->lock); -+ spin_lock(&dcache_lock); -+ -+ for (;;) { -+ if (dentry == root && mnt == rootmnt) -+ break; -+ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) { -+ if (mnt->mnt_parent == mnt) -+ break; -+ -+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path); -+ if (retval != NULL) -+ goto out; -+ -+ dentry = mnt->mnt_mountpoint; -+ mnt = mnt->mnt_parent; -+ continue; -+ } -+ -+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path); -+ if (retval != NULL) -+ goto out; -+ -+ dentry = dentry->d_parent; -+ } -+ -+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path); -+ -+ if (retval == NULL) -+ retval = full_lookup(l_dentry, l_mnt, root, subj, &path); -+out: -+ spin_unlock(&dcache_lock); -+ dput(root); -+ mntput(rootmnt); -+ -+ return retval; -+} -+ -+static struct acl_object_label * -+chk_obj_create_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt, -+ const struct acl_subject_label *subj, char *path) -+{ -+ struct dentry *dentry = (struct dentry *) l_dentry; -+ struct vfsmount *mnt = (struct vfsmount *) l_mnt; -+ struct dentry *root; -+ struct vfsmount *rootmnt; -+ struct acl_object_label *retval; -+ -+ read_lock(&child_reaper->fs->lock); -+ rootmnt = mntget(child_reaper->fs->rootmnt); -+ root = dget(child_reaper->fs->root); -+ read_unlock(&child_reaper->fs->lock); -+ spin_lock(&dcache_lock); -+ -+ for (;;) { -+ if (dentry == root && mnt == rootmnt) -+ break; -+ if (dentry == mnt->mnt_root || IS_ROOT(dentry)) { -+ if (mnt->mnt_parent == mnt) -+ break; -+ -+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path); -+ if (retval != NULL) -+ goto out; -+ -+ dentry = mnt->mnt_mountpoint; -+ mnt = mnt->mnt_parent; -+ continue; -+ } -+ -+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path); -+ if (retval != NULL) -+ goto out; -+ -+ dentry = dentry->d_parent; -+ } -+ -+ retval = full_lookup(l_dentry, l_mnt, dentry, subj, &path); -+ -+ if (retval == NULL) -+ retval = full_lookup(l_dentry, l_mnt, root, subj, &path); -+out: -+ spin_unlock(&dcache_lock); -+ dput(root); -+ mntput(rootmnt); -+ -+ return retval; -+} -+ -+static struct acl_subject_label * -+chk_subj_label(const struct dentry *l_dentry, const struct vfsmount *l_mnt, -+ const struct acl_role_label *role) -+{ -+ struct dentry *dentry = (struct dentry *) l_dentry; -+ struct vfsmount *mnt = (struct vfsmount *) l_mnt; -+ struct dentry *root; -+ struct vfsmount *rootmnt; -+ struct acl_subject_label *retval; -+ -+ read_lock(&child_reaper->fs->lock); -+ rootmnt = mntget(child_reaper->fs->rootmnt); -+ root = dget(child_reaper->fs->root); -+ read_unlock(&child_reaper->fs->lock); -+ spin_lock(&dcache_lock); -+ -+ for (;;) { -+ if (unlikely(dentry == root && mnt == rootmnt)) -+ break; -+ if (unlikely(dentry == mnt->mnt_root || IS_ROOT(dentry))) { -+ if (mnt->mnt_parent == mnt) -+ break; -+ -+ read_lock(&gr_inode_lock); -+ retval = -+ lookup_acl_subj_label(dentry->d_inode->i_ino, -+ dentry->d_inode->i_sb->s_dev, role); -+ read_unlock(&gr_inode_lock); -+ if (unlikely(retval != NULL)) -+ goto out; -+ -+ dentry = mnt->mnt_mountpoint; -+ mnt = mnt->mnt_parent; -+ continue; -+ } -+ -+ read_lock(&gr_inode_lock); -+ retval = -+ lookup_acl_subj_label(dentry->d_inode->i_ino, -+ dentry->d_inode->i_sb->s_dev, role); -+ read_unlock(&gr_inode_lock); -+ if (unlikely(retval != NULL)) -+ goto out; -+ -+ dentry = dentry->d_parent; -+ } -+ -+ read_lock(&gr_inode_lock); -+ retval = -+ lookup_acl_subj_label(dentry->d_inode->i_ino, -+ dentry->d_inode->i_sb->s_dev, role); -+ read_unlock(&gr_inode_lock); -+ -+ if (unlikely(retval == NULL)) { -+ read_lock(&gr_inode_lock); -+ retval = -+ lookup_acl_subj_label(root->d_inode->i_ino, -+ root->d_inode->i_sb->s_dev, role); -+ read_unlock(&gr_inode_lock); -+ } -+ out: -+ spin_unlock(&dcache_lock); -+ dput(root); -+ mntput(rootmnt); -+ -+ return retval; -+} -+ -+static __inline__ void -+gr_log_learn(const struct acl_role_label *role, const uid_t uid, const gid_t gid, -+ const struct task_struct *task, const char *pathname, -+ const __u32 mode) -+{ -+ security_learn(GR_LEARN_AUDIT_MSG, role->rolename, role->roletype, -+ uid, gid, task->exec_file ? gr_to_filename1(task->exec_file->f_dentry, -+ task->exec_file->f_vfsmnt) : task->acl->filename, task->acl->filename, -+ 1, 1, pathname, (unsigned long) mode, NIPQUAD(task->curr_ip)); -+ -+ return; -+} -+ -+__u32 -+gr_check_link(const struct dentry * new_dentry, -+ const struct dentry * parent_dentry, -+ const struct vfsmount * parent_mnt, -+ const struct dentry * old_dentry, const struct vfsmount * old_mnt) -+{ -+ struct acl_object_label *obj; -+ __u32 oldmode, newmode; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return (GR_WRITE | GR_CREATE); -+ -+ obj = chk_obj_label(old_dentry, old_mnt, current->acl); -+ oldmode = obj->mode; -+ -+ if (current->acl->mode & GR_LEARN) -+ oldmode |= (GR_WRITE | GR_CREATE); -+ newmode = -+ gr_check_create(new_dentry, parent_dentry, parent_mnt, -+ oldmode | GR_CREATE | GR_AUDIT_CREATE | -+ GR_AUDIT_WRITE | GR_SUPPRESS); -+ -+ if ((newmode & oldmode) == oldmode) -+ return newmode; -+ else if (current->acl->mode & GR_LEARN) { -+ gr_log_learn(current->role, current->uid, current->gid, -+ current, gr_to_filename(old_dentry, old_mnt), oldmode); -+ return (GR_WRITE | GR_CREATE); -+ } else if (newmode & GR_SUPPRESS) -+ return GR_SUPPRESS; -+ else -+ return 0; -+} -+ -+__u32 -+gr_search_file(const struct dentry * dentry, const __u32 mode, -+ const struct vfsmount * mnt) -+{ -+ __u32 retval = mode; -+ struct acl_subject_label *curracl; -+ struct acl_object_label *currobj; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return (mode & ~GR_AUDITS); -+ -+ curracl = current->acl; -+ -+ currobj = chk_obj_label(dentry, mnt, curracl); -+ retval = currobj->mode & mode; -+ -+ if (unlikely -+ ((curracl->mode & GR_LEARN) && !(mode & GR_NOPTRACE) -+ && (retval != (mode & ~(GR_AUDITS | GR_SUPPRESS))))) { -+ __u32 new_mode = mode; -+ -+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS); -+ -+ retval = new_mode; -+ -+ if (!(mode & GR_NOLEARN)) -+ gr_log_learn(current->role, current->uid, current->gid, -+ current, gr_to_filename(dentry, mnt), new_mode); -+ } -+ -+ return retval; -+} -+ -+__u32 -+gr_check_create(const struct dentry * new_dentry, const struct dentry * parent, -+ const struct vfsmount * mnt, const __u32 mode) -+{ -+ struct name_entry *match; -+ struct acl_object_label *matchpo; -+ struct acl_subject_label *curracl; -+ char *path; -+ __u32 retval; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return (mode & ~GR_AUDITS); -+ -+ preempt_disable(); -+ path = gr_to_filename(new_dentry, mnt); -+ match = lookup_name_entry(path); -+ -+ if (!match) -+ goto check_parent; -+ -+ curracl = current->acl; -+ -+ read_lock(&gr_inode_lock); -+ matchpo = lookup_acl_obj_label_create(match->inode, match->device, curracl); -+ read_unlock(&gr_inode_lock); -+ -+ if (matchpo) { -+ if ((matchpo->mode & mode) != -+ (mode & ~(GR_AUDITS | GR_SUPPRESS)) -+ && curracl->mode & GR_LEARN) { -+ __u32 new_mode = mode; -+ -+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS); -+ -+ gr_log_learn(current->role, current->uid, current->gid, -+ current, gr_to_filename(new_dentry, mnt), new_mode); -+ -+ preempt_enable(); -+ return new_mode; -+ } -+ preempt_enable(); -+ return (matchpo->mode & mode); -+ } -+ -+ check_parent: -+ curracl = current->acl; -+ -+ matchpo = chk_obj_create_label(parent, mnt, curracl, path); -+ retval = matchpo->mode & mode; -+ -+ if ((retval != (mode & ~(GR_AUDITS | GR_SUPPRESS))) -+ && (curracl->mode & GR_LEARN)) { -+ __u32 new_mode = mode; -+ -+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS); -+ -+ gr_log_learn(current->role, current->uid, current->gid, -+ current, gr_to_filename(new_dentry, mnt), new_mode); -+ preempt_enable(); -+ return new_mode; -+ } -+ -+ preempt_enable(); -+ return retval; -+} -+ -+int -+gr_check_hidden_task(const struct task_struct *task) -+{ -+ if (unlikely(!(gr_status & GR_READY))) -+ return 0; -+ -+ if (!(task->acl->mode & GR_FIND) && !(current->acl->mode & GR_VIEW)) -+ return 1; -+ -+ return 0; -+} -+ -+int -+gr_check_protected_task(const struct task_struct *task) -+{ -+ if (unlikely(!(gr_status & GR_READY) || !task)) -+ return 0; -+ -+ if ((task->acl->mode & GR_PROTECTED) && !(current->acl->mode & GR_KILL)) -+ return 1; -+ -+ return 0; -+} -+ -+__inline__ void -+gr_copy_label(struct task_struct *tsk) -+{ -+ tsk->used_accept = 0; -+ tsk->acl_sp_role = 0; -+ tsk->acl_role_id = current->acl_role_id; -+ tsk->acl = current->acl; -+ tsk->role = current->role; -+ tsk->curr_ip = current->curr_ip; -+ if (current->exec_file) -+ get_file(current->exec_file); -+ tsk->exec_file = current->exec_file; -+ tsk->is_writable = current->is_writable; -+ if (unlikely(current->used_accept)) -+ current->curr_ip = 0; -+ -+ return; -+} -+ -+static __inline__ void -+gr_set_proc_res(void) -+{ -+ struct acl_subject_label *proc; -+ unsigned short i; -+ -+ proc = current->acl; -+ -+ if (proc->mode & GR_LEARN) -+ return; -+ -+ for (i = 0; i < RLIM_NLIMITS; i++) { -+ if (!(proc->resmask & (1 << i))) -+ continue; -+ -+ current->rlim[i].rlim_cur = proc->res[i].rlim_cur; -+ current->rlim[i].rlim_max = proc->res[i].rlim_max; -+ } -+ -+ return; -+} -+ -+static __inline__ void -+do_set_role_label(struct task_struct *task, const uid_t uid, const gid_t gid) -+{ -+ task->role = lookup_acl_role_label(task, uid, gid); -+ -+ return; -+} -+ -+int -+gr_check_user_change(int real, int effective, int fs) -+{ -+ unsigned int i; -+ __u16 num; -+ uid_t *uidlist; -+ int curuid; -+ int realok = 0; -+ int effectiveok = 0; -+ int fsok = 0; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return 0; -+ -+ num = current->acl->user_trans_num; -+ uidlist = current->acl->user_transitions; -+ -+ if (uidlist == NULL) -+ return 0; -+ -+ if (real == -1) -+ realok = 1; -+ if (effective == -1) -+ effectiveok = 1; -+ if (fs == -1) -+ fsok = 1; -+ -+ if (current->acl->user_trans_type & GR_ID_ALLOW) { -+ for (i = 0; i < num; i++) { -+ curuid = (int)uidlist[i]; -+ if (real == curuid) -+ realok = 1; -+ if (effective == curuid) -+ effectiveok = 1; -+ if (fs == curuid) -+ fsok = 1; -+ } -+ } else if (current->acl->user_trans_type & GR_ID_DENY) { -+ for (i = 0; i < num; i++) { -+ curuid = (int)uidlist[i]; -+ if (real == curuid) -+ break; -+ if (effective == curuid) -+ break; -+ if (fs == curuid) -+ break; -+ } -+ /* not in deny list */ -+ if (i == num) { -+ realok = 1; -+ effectiveok = 1; -+ fsok = 1; -+ } -+ } -+ -+ if (realok && effectiveok && fsok) -+ return 0; -+ else { -+ security_alert(GR_USRCHANGE_ACL_MSG, -+ realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real, DEFAULTSECARGS); -+ return 1; -+ } -+} -+ -+int -+gr_check_group_change(int real, int effective, int fs) -+{ -+ unsigned int i; -+ __u16 num; -+ gid_t *gidlist; -+ int curgid; -+ int realok = 0; -+ int effectiveok = 0; -+ int fsok = 0; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return 0; -+ -+ num = current->acl->group_trans_num; -+ gidlist = current->acl->group_transitions; -+ -+ if (gidlist == NULL) -+ return 0; -+ -+ if (real == -1) -+ realok = 1; -+ if (effective == -1) -+ effectiveok = 1; -+ if (fs == -1) -+ fsok = 1; -+ -+ if (current->acl->group_trans_type & GR_ID_ALLOW) { -+ for (i = 0; i < num; i++) { -+ curgid = (int)gidlist[i]; -+ if (real == curgid) -+ realok = 1; -+ if (effective == curgid) -+ effectiveok = 1; -+ if (fs == curgid) -+ fsok = 1; -+ } -+ } else if (current->acl->group_trans_type & GR_ID_DENY) { -+ for (i = 0; i < num; i++) { -+ curgid = (int)gidlist[i]; -+ if (real == curgid) -+ break; -+ if (effective == curgid) -+ break; -+ if (fs == curgid) -+ break; -+ } -+ /* not in deny list */ -+ if (i == num) { -+ realok = 1; -+ effectiveok = 1; -+ fsok = 1; -+ } -+ } -+ -+ if (realok && effectiveok && fsok) -+ return 0; -+ else { -+ security_alert(GR_GRPCHANGE_ACL_MSG, -+ realok ? (effectiveok ? (fsok ? 0 : fs) : effective) : real, DEFAULTSECARGS); -+ return 1; -+ } -+} -+ -+void -+gr_set_role_label(struct task_struct *task, const uid_t uid, const uid_t gid) -+{ -+ struct acl_object_label *obj; -+ struct file *filp; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return; -+ -+ filp = task->exec_file; -+ -+ /* kernel process, we'll give them the kernel role */ -+ if (unlikely(!filp)) { -+ task->role = kernel_role; -+ task->acl = kernel_role->root_label; -+ return; -+ } else if (!task->role || !(task->role->roletype & GR_ROLE_SPECIAL)) -+ do_set_role_label(task, uid, gid); -+ -+ task->acl = -+ chk_subj_label(filp->f_dentry, filp->f_vfsmnt, task->role); -+ -+ task->is_writable = 0; -+ -+ /* ignore additional mmap checks for processes that are writable -+ by the default ACL */ -+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label); -+ if (unlikely(obj->mode & GR_WRITE)) -+ task->is_writable = 1; -+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label); -+ if (unlikely(obj->mode & GR_WRITE)) -+ task->is_writable = 1; -+ -+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG -+ printk(KERN_ALERT "Set role label for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename); -+#endif -+ -+ gr_set_proc_res(); -+ -+ return; -+} -+ -+void -+gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ struct acl_subject_label *newacl; -+ struct acl_object_label *obj; -+ __u32 retmode; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return; -+ -+ newacl = chk_subj_label(dentry, mnt, current->role); -+ -+ obj = chk_obj_label(dentry, mnt, current->acl); -+ retmode = obj->mode & (GR_INHERIT | GR_AUDIT_INHERIT); -+ -+ if ((newacl->mode & GR_LEARN) || !(retmode & GR_INHERIT)) { -+ if (obj->nested) -+ current->acl = obj->nested; -+ else -+ current->acl = newacl; -+ } else if (retmode & GR_INHERIT && retmode & GR_AUDIT_INHERIT) -+ security_audit(GR_INHERIT_ACL_MSG, current->acl->filename, -+ gr_to_filename(dentry, mnt), DEFAULTSECARGS); -+ -+ current->is_writable = 0; -+ -+ /* ignore additional mmap checks for processes that are writable -+ by the default ACL */ -+ obj = chk_obj_label(dentry, mnt, default_role->root_label); -+ if (unlikely(obj->mode & GR_WRITE)) -+ current->is_writable = 1; -+ obj = chk_obj_label(dentry, mnt, current->role->root_label); -+ if (unlikely(obj->mode & GR_WRITE)) -+ current->is_writable = 1; -+ -+ gr_set_proc_res(); -+ -+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG -+ printk(KERN_ALERT "Set subject label for (%s:%d): role:%s, subject:%s\n", current->comm, current->pid, current->role->rolename, current->acl->filename); -+#endif -+ return; -+} -+ -+static __inline__ void -+do_handle_delete(const ino_t ino, const dev_t dev) -+{ -+ struct acl_object_label *matchpo; -+ struct acl_subject_label *matchps; -+ struct acl_subject_label *i; -+ struct acl_role_label *role; -+ -+ for (role = role_list_head; role; role = role->next) { -+ for (i = role->hash->first; i; i = i->next) { -+ if (unlikely((i->mode & GR_NESTED) && -+ (i->inode == ino) && -+ (i->device == dev))) -+ i->mode |= GR_DELETED; -+ if (unlikely((matchpo = -+ lookup_acl_obj_label(ino, dev, i)) != NULL)) -+ matchpo->mode |= GR_DELETED; -+ } -+ -+ if (unlikely((matchps = lookup_acl_subj_label(ino, dev, role)) != NULL)) -+ matchps->mode |= GR_DELETED; -+ } -+ -+ return; -+} -+ -+void -+gr_handle_delete(const ino_t ino, const dev_t dev) -+{ -+ if (unlikely(!(gr_status & GR_READY))) -+ return; -+ -+ write_lock(&gr_inode_lock); -+ if (unlikely((unsigned long)lookup_inodev_entry(ino, dev))) -+ do_handle_delete(ino, dev); -+ write_unlock(&gr_inode_lock); -+ -+ return; -+} -+ -+static __inline__ void -+update_acl_obj_label(const ino_t oldinode, const dev_t olddevice, -+ const ino_t newinode, const dev_t newdevice, -+ struct acl_subject_label *subj) -+{ -+ unsigned long index = fhash(oldinode, olddevice, subj->obj_hash_size); -+ struct acl_object_label **match; -+ struct acl_object_label *tmp; -+ __u8 i = 0; -+ -+ match = &subj->obj_hash[index]; -+ -+ while (*match && ((*match)->inode != oldinode || -+ (*match)->device != olddevice || -+ !((*match)->mode & GR_DELETED))) { -+ index = (index + (1 << i)) % subj->obj_hash_size; -+ match = &subj->obj_hash[index]; -+ i = (i + 1) % 32; -+ } -+ -+ if (*match && ((*match) != deleted_object) -+ && ((*match)->inode == oldinode) -+ && ((*match)->device == olddevice) -+ && ((*match)->mode & GR_DELETED)) { -+ tmp = *match; -+ tmp->inode = newinode; -+ tmp->device = newdevice; -+ tmp->mode &= ~GR_DELETED; -+ -+ *match = deleted_object; -+ -+ insert_acl_obj_label(tmp, subj); -+ } -+ -+ return; -+} -+ -+static __inline__ void -+update_acl_subj_label(const ino_t oldinode, const dev_t olddevice, -+ const ino_t newinode, const dev_t newdevice, -+ struct acl_role_label *role) -+{ -+ struct acl_subject_label **s_hash = role->subj_hash; -+ unsigned long subj_size = role->subj_hash_size; -+ unsigned long index = fhash(oldinode, olddevice, subj_size); -+ struct acl_subject_label **match; -+ struct acl_subject_label *tmp; -+ __u8 i = 0; -+ -+ match = &s_hash[index]; -+ -+ while (*match && ((*match)->inode != oldinode || -+ (*match)->device != olddevice || -+ !((*match)->mode & GR_DELETED))) { -+ index = (index + (1 << i)) % subj_size; -+ i = (i + 1) % 32; -+ match = &s_hash[index]; -+ } -+ -+ if (*match && (*match != deleted_subject) -+ && ((*match)->inode == oldinode) -+ && ((*match)->device == olddevice) -+ && ((*match)->mode & GR_DELETED)) { -+ tmp = *match; -+ -+ tmp->inode = newinode; -+ tmp->device = newdevice; -+ tmp->mode &= ~GR_DELETED; -+ -+ *match = deleted_subject; -+ -+ insert_acl_subj_label(tmp, role); -+ } -+ -+ return; -+} -+ -+static __inline__ void -+update_inodev_entry(const ino_t oldinode, const dev_t olddevice, -+ const ino_t newinode, const dev_t newdevice) -+{ -+ unsigned long index = fhash(oldinode, olddevice, inodev_set.n_size); -+ struct name_entry **match; -+ struct name_entry *tmp; -+ __u8 i = 0; -+ -+ match = &inodev_set.n_hash[index]; -+ -+ while (*match -+ && ((*match)->inode != oldinode -+ || (*match)->device != olddevice)) { -+ index = (index + (1 << i)) % inodev_set.n_size; -+ i = (i + 1) % 32; -+ match = &inodev_set.n_hash[index]; -+ } -+ -+ if (*match && (*match != deleted_inodev) -+ && ((*match)->inode == oldinode) -+ && ((*match)->device == olddevice)) { -+ tmp = *match; -+ -+ tmp->inode = newinode; -+ tmp->device = newdevice; -+ -+ *match = deleted_inodev; -+ -+ insert_inodev_entry(tmp); -+ } -+ -+ return; -+} -+ -+static __inline__ void -+do_handle_create(const struct name_entry *matchn, const struct dentry *dentry, -+ const struct vfsmount *mnt) -+{ -+ struct acl_subject_label *i; -+ struct acl_role_label *role; -+ -+ for (role = role_list_head; role; role = role->next) { -+ update_acl_subj_label(matchn->inode, matchn->device, -+ dentry->d_inode->i_ino, -+ dentry->d_inode->i_sb->s_dev, role); -+ -+ for (i = role->hash->first; i; i = i->next) { -+ if (unlikely((i->mode & GR_NESTED) && -+ (i->inode == dentry->d_inode->i_ino) && -+ (i->device == dentry->d_inode->i_sb->s_dev))) { -+ i->inode = dentry->d_inode->i_ino; -+ i->device = dentry->d_inode->i_sb->s_dev; -+ } -+ update_acl_obj_label(matchn->inode, matchn->device, -+ dentry->d_inode->i_ino, -+ dentry->d_inode->i_sb->s_dev, i); -+ } -+ } -+ -+ update_inodev_entry(matchn->inode, matchn->device, -+ dentry->d_inode->i_ino, dentry->d_inode->i_sb->s_dev); -+ -+ return; -+} -+ -+void -+gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ struct name_entry *matchn; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return; -+ -+ preempt_disable(); -+ matchn = lookup_name_entry(gr_to_filename(dentry, mnt)); -+ preempt_enable(); -+ -+ if (unlikely((unsigned long)matchn)) { -+ write_lock(&gr_inode_lock); -+ do_handle_create(matchn, dentry, mnt); -+ write_unlock(&gr_inode_lock); -+ } -+ -+ return; -+} -+ -+void -+gr_handle_rename(struct inode *old_dir, struct inode *new_dir, -+ struct dentry *old_dentry, -+ struct dentry *new_dentry, -+ struct vfsmount *mnt, const __u8 replace) -+{ -+ struct name_entry *matchn; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return; -+ -+ preempt_disable(); -+ matchn = lookup_name_entry(gr_to_filename(new_dentry, mnt)); -+ preempt_enable(); -+ -+ /* we wouldn't have to check d_inode if it weren't for -+ NFS silly-renaming -+ */ -+ -+ write_lock(&gr_inode_lock); -+ if (unlikely(replace && new_dentry->d_inode)) { -+ if (unlikely(lookup_inodev_entry(new_dentry->d_inode->i_ino, -+ new_dentry->d_inode->i_sb->s_dev) && -+ (old_dentry->d_inode->i_nlink <= 1))) -+ do_handle_delete(new_dentry->d_inode->i_ino, -+ new_dentry->d_inode->i_sb->s_dev); -+ } -+ -+ if (unlikely(lookup_inodev_entry(old_dentry->d_inode->i_ino, -+ old_dentry->d_inode->i_sb->s_dev) && -+ (old_dentry->d_inode->i_nlink <= 1))) -+ do_handle_delete(old_dentry->d_inode->i_ino, -+ old_dentry->d_inode->i_sb->s_dev); -+ -+ if (unlikely((unsigned long)matchn)) -+ do_handle_create(matchn, old_dentry, mnt); -+ write_unlock(&gr_inode_lock); -+ -+ return; -+} -+ -+static int -+lookup_special_role_auth(const char *rolename, unsigned char **salt, -+ unsigned char **sum) -+{ -+ struct acl_role_label *r; -+ struct role_transition *trans; -+ __u16 i; -+ int found = 0; -+ -+ /* check transition table */ -+ -+ for (trans = current->role->transitions; trans; trans = trans->next) { -+ if (!strcmp(rolename, trans->rolename)) { -+ found = 1; -+ break; -+ } -+ } -+ -+ if (!found) -+ return 0; -+ -+ /* handle special roles that do not require authentication */ -+ -+ for (r = role_list_head; r; r = r->next) { -+ if (!strcmp(rolename, r->rolename) -+ && (r->roletype & GR_ROLE_NOPW)) { -+ *salt = NULL; -+ *sum = NULL; -+ return 1; -+ } -+ } -+ -+ for (i = 0; i < num_sprole_pws; i++) { -+ if (!strcmp(rolename, acl_special_roles[i]->rolename)) { -+ *salt = acl_special_roles[i]->salt; -+ *sum = acl_special_roles[i]->sum; -+ return 1; -+ } -+ } -+ -+ return 0; -+} -+ -+static void -+assign_special_role(char *rolename) -+{ -+ struct acl_object_label *obj; -+ struct acl_role_label *r; -+ struct acl_role_label *assigned = NULL; -+ struct task_struct *tsk; -+ struct file *filp; -+ -+ for (r = role_list_head; r; r = r->next) -+ if (!strcmp(rolename, r->rolename) && -+ (r->roletype & GR_ROLE_SPECIAL)) -+ assigned = r; -+ -+ if (!assigned) -+ return; -+ -+ tsk = current->parent; -+ filp = tsk->exec_file; -+ -+ if (tsk && filp) { -+ tsk->is_writable = 0; -+ -+ acl_sp_role_value = (acl_sp_role_value % 65535) + 1; -+ tsk->acl_sp_role = 1; -+ tsk->acl_role_id = acl_sp_role_value; -+ tsk->role = assigned; -+ tsk->acl = -+ chk_subj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role); -+ -+ /* ignore additional mmap checks for processes that are writable -+ by the default ACL */ -+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label); -+ if (unlikely(obj->mode & GR_WRITE)) -+ tsk->is_writable = 1; -+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, tsk->role->root_label); -+ if (unlikely(obj->mode & GR_WRITE)) -+ tsk->is_writable = 1; -+ -+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG -+ printk(KERN_ALERT "Assigning special role:%s subject:%s to process (%s:%d)\n", tsk->role->rolename, tsk->acl->filename, tsk->comm, tsk->pid); -+#endif -+ } -+ -+ return; -+} -+ -+ssize_t -+write_grsec_handler(struct file *file, const char * buf, size_t count, loff_t *ppos) -+{ -+ struct gr_arg *arg; -+ unsigned char *sprole_salt; -+ unsigned char *sprole_sum; -+ int error = sizeof (struct gr_arg); -+ int error2 = 0; -+ -+ down(&gr_dev_sem); -+ -+ arg = (struct gr_arg *) buf; -+ -+ if (count != sizeof (struct gr_arg)) { -+ security_alert_good(GR_DEV_ACL_MSG, count, -+ (int) sizeof (struct gr_arg)); -+ error = -EINVAL; -+ goto out; -+ } -+ -+ if ((gr_auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES) -+ && time_before_eq(gr_auth_expires, get_seconds())) { -+ gr_auth_expires = 0; -+ gr_auth_attempts = 0; -+ } -+ -+ if (copy_from_user(gr_usermode, arg, sizeof (struct gr_arg))) { -+ error = -EFAULT; -+ goto out; -+ } -+ -+ if (gr_usermode->mode != SPROLE && time_after(gr_auth_expires, get_seconds())) { -+ error = -EBUSY; -+ goto out; -+ } -+ -+ /* if non-root trying to do anything other than use a special role, -+ do not attempt authentication, do not count towards authentication -+ locking -+ */ -+ -+ if (gr_usermode->mode != SPROLE && current->uid) { -+ error = -EPERM; -+ goto out; -+ } -+ -+ /* ensure pw and special role name are null terminated */ -+ -+ gr_usermode->pw[GR_PW_LEN - 1] = '\0'; -+ gr_usermode->sp_role[GR_SPROLE_LEN - 1] = '\0'; -+ -+ /* Okay. -+ * We have our enough of the argument structure..(we have yet -+ * to copy_from_user the tables themselves) . Copy the tables -+ * only if we need them, i.e. for loading operations. */ -+ -+ switch (gr_usermode->mode) { -+ case STATUS: -+ if (gr_status & GR_READY) -+ error = 1; -+ else -+ error = 2; -+ goto out; -+ case SHUTDOWN: -+ if ((gr_status & GR_READY) -+ && !(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) { -+ gr_status &= ~GR_READY; -+ security_alert_good(GR_SHUTS_ACL_MSG, DEFAULTSECARGS); -+ free_variables(); -+ memset(gr_usermode, 0, sizeof (struct gr_arg)); -+ memset(gr_system_salt, 0, GR_SALT_LEN); -+ memset(gr_system_sum, 0, GR_SHA_LEN); -+ } else if (gr_status & GR_READY) { -+ security_alert(GR_SHUTF_ACL_MSG, DEFAULTSECARGS); -+ error = -EPERM; -+ } else { -+ security_alert_good(GR_SHUTI_ACL_MSG, DEFAULTSECARGS); -+ error = -EAGAIN; -+ } -+ break; -+ case ENABLE: -+ if (!(gr_status & GR_READY) && !(error2 = gracl_init(gr_usermode))) -+ security_alert_good(GR_ENABLE_ACL_MSG, GR_VERSION); -+ else { -+ if (gr_status & GR_READY) -+ error = -EAGAIN; -+ else -+ error = error2; -+ security_alert(GR_ENABLEF_ACL_MSG, GR_VERSION, -+ DEFAULTSECARGS); -+ } -+ break; -+ case RELOAD: -+ if (!(gr_status & GR_READY)) { -+ security_alert_good(GR_RELOADI_ACL_MSG); -+ error = -EAGAIN; -+ } else if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) { -+ lock_kernel(); -+ gr_status &= ~GR_READY; -+ free_variables(); -+ if (!(error2 = gracl_init(gr_usermode))) { -+ unlock_kernel(); -+ security_alert_good(GR_RELOAD_ACL_MSG, -+ GR_VERSION); -+ } else { -+ unlock_kernel(); -+ error = error2; -+ security_alert(GR_RELOADF_ACL_MSG, GR_VERSION, -+ DEFAULTSECARGS); -+ } -+ } else { -+ security_alert(GR_RELOADF_ACL_MSG, GR_VERSION, -+ DEFAULTSECARGS); -+ error = -EPERM; -+ } -+ break; -+ case SEGVMOD: -+ if (unlikely(!(gr_status & GR_READY))) { -+ security_alert_good(GR_SEGVMODI_ACL_MSG, -+ DEFAULTSECARGS); -+ error = -EAGAIN; -+ break; -+ } -+ -+ if (!(chkpw(gr_usermode, gr_system_salt, gr_system_sum))) { -+ security_alert_good(GR_SEGVMODS_ACL_MSG, -+ DEFAULTSECARGS); -+ if (gr_usermode->segv_device && gr_usermode->segv_inode) { -+ struct acl_subject_label *segvacl; -+ segvacl = -+ lookup_acl_subj_label(gr_usermode->segv_inode, -+ gr_usermode->segv_device, -+ current->role); -+ if (segvacl) { -+ segvacl->crashes = 0; -+ segvacl->expires = 0; -+ } -+ } else if (gr_find_uid(gr_usermode->segv_uid) >= 0) { -+ gr_remove_uid(gr_usermode->segv_uid); -+ } -+ } else { -+ security_alert(GR_SEGVMODF_ACL_MSG, DEFAULTSECARGS); -+ error = -EPERM; -+ } -+ break; -+ case SPROLE: -+ if (unlikely(!(gr_status & GR_READY))) { -+ security_alert_good(GR_SPROLEI_ACL_MSG, DEFAULTSECARGS); -+ error = -EAGAIN; -+ break; -+ } -+ -+ if ((current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES) -+ && time_before_eq(current->role->expires, get_seconds())) { -+ current->role->expires = 0; -+ current->role->auth_attempts = 0; -+ } -+ -+ if (time_after(current->role->expires, get_seconds())) { -+ error = -EBUSY; -+ goto out; -+ } -+ -+ if (lookup_special_role_auth -+ (gr_usermode->sp_role, &sprole_salt, &sprole_sum) -+ && ((!sprole_salt && !sprole_sum) -+ || !(chkpw(gr_usermode, sprole_salt, sprole_sum)))) { -+ assign_special_role(gr_usermode->sp_role); -+ security_alert_good(GR_SPROLES_ACL_MSG, -+ (current->parent) ? current-> -+ parent->role->rolename : "", -+ acl_sp_role_value, DEFAULTSECARGS); -+ } else { -+ security_alert(GR_SPROLEF_ACL_MSG, gr_usermode->sp_role, -+ DEFAULTSECARGS); -+ error = -EPERM; -+ current->role->auth_attempts++; -+ if (current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES) { -+ current->role->expires = -+ get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT; -+ security_alert(GR_MAXROLEPW_ACL_MSG, -+ CONFIG_GRKERNSEC_ACL_MAXTRIES, -+ gr_usermode->sp_role, DEFAULTSECARGS); -+ } -+ -+ goto out; -+ } -+ break; -+ case UNSPROLE: -+ if (unlikely(!(gr_status & GR_READY))) { -+ security_alert_good(GR_UNSPROLEI_ACL_MSG, DEFAULTSECARGS); -+ error = -EAGAIN; -+ break; -+ } -+ -+ if ((current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES) -+ && time_before_eq(current->role->expires, get_seconds())) { -+ current->role->expires = 0; -+ current->role->auth_attempts = 0; -+ } -+ -+ if (time_after(current->role->expires, get_seconds())) { -+ error = -EBUSY; -+ goto out; -+ } -+ -+ if ((current->role->roletype & GR_ROLE_SPECIAL) && -+ lookup_special_role_auth -+ (current->role->rolename, &sprole_salt, &sprole_sum) -+ && ((!sprole_salt && !sprole_sum) -+ || !(chkpw(gr_usermode, sprole_salt, sprole_sum)))) { -+ security_alert_good(GR_UNSPROLES_ACL_MSG, -+ (current->parent) ? current-> -+ parent->role->rolename : "", -+ (current->parent) ? current-> -+ parent->acl_role_id : 0, DEFAULTSECARGS); -+ gr_set_acls(1); -+ if (current->parent) -+ current->parent->acl_sp_role = 0; -+ } else { -+ security_alert(GR_UNSPROLEF_ACL_MSG, current->role->rolename, -+ DEFAULTSECARGS); -+ error = -EPERM; -+ current->role->auth_attempts++; -+ if (current->role->auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES) { -+ current->role->expires = -+ get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT; -+ security_alert(GR_MAXROLEPW_ACL_MSG, -+ CONFIG_GRKERNSEC_ACL_MAXTRIES, -+ current->role->rolename, DEFAULTSECARGS); -+ } -+ -+ goto out; -+ } -+ break; -+ default: -+ security_alert(GR_INVMODE_ACL_MSG, gr_usermode->mode, -+ DEFAULTSECARGS); -+ error = -EINVAL; -+ break; -+ } -+ -+ if (error != -EPERM) -+ goto out; -+ -+ gr_auth_attempts++; -+ -+ if (gr_auth_attempts >= CONFIG_GRKERNSEC_ACL_MAXTRIES) { -+ security_alert(GR_MAXPW_ACL_MSG, CONFIG_GRKERNSEC_ACL_MAXTRIES); -+ gr_auth_expires = get_seconds() + CONFIG_GRKERNSEC_ACL_TIMEOUT; -+ } -+ -+ out: -+ up(&gr_dev_sem); -+ return error; -+} -+ -+int -+gr_set_acls(const int type) -+{ -+ struct acl_object_label *obj; -+ struct task_struct *task, *task2; -+ struct file *filp; -+ unsigned short i; -+ -+ read_lock(&tasklist_lock); -+ for_each_process(task2) { -+ task = task2; -+ do { -+ /* check to see if we're called from the exit handler, -+ if so, only replace ACLs that have inherited the admin -+ ACL */ -+ -+ if (type && (task->role != current->role || -+ task->acl_role_id != current->acl_role_id)) -+ continue; -+ -+ task->acl_role_id = 0; -+ -+ if ((filp = task->exec_file)) { -+ do_set_role_label(task, task->uid, task->gid); -+ -+ task->acl = -+ chk_subj_label(filp->f_dentry, filp->f_vfsmnt, -+ task->role); -+ if (task->acl) { -+ struct acl_subject_label *curr; -+ curr = task->acl; -+ -+ task->is_writable = 0; -+ /* ignore additional mmap checks for processes that are writable -+ by the default ACL */ -+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label); -+ if (unlikely(obj->mode & GR_WRITE)) -+ task->is_writable = 1; -+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, task->role->root_label); -+ if (unlikely(obj->mode & GR_WRITE)) -+ task->is_writable = 1; -+ -+#ifdef CONFIG_GRKERNSEC_ACL_DEBUG -+ printk(KERN_ALERT "gr_set_acls for (%s:%d): role:%s, subject:%s\n", task->comm, task->pid, task->role->rolename, task->acl->filename); -+#endif -+ if (!(curr->mode & GR_LEARN)) -+ for (i = 0; i < RLIM_NLIMITS; i++) { -+ if (!(curr->resmask & (1 << i))) -+ continue; -+ -+ task->rlim[i].rlim_cur = -+ curr->res[i].rlim_cur; -+ task->rlim[i].rlim_max = -+ curr->res[i].rlim_max; -+ } -+ } else { -+ read_unlock(&tasklist_lock); -+ security_alert_good(GR_DEFACL_MSG, task->comm, -+ task->pid); -+ return 1; -+ } -+ } else { -+ // it's a kernel process -+ task->role = kernel_role; -+ task->acl = kernel_role->root_label; -+#ifdef CONFIG_GRKERNSEC_ACL_HIDEKERN -+ task->acl->mode &= ~GR_FIND; -+#endif -+ } -+ } while ((task = next_thread(task)) != task2); -+ } -+ read_unlock(&tasklist_lock); -+ return 0; -+} -+ -+EXPORT_SYMBOL(gr_learn_resource); -+ -+void -+gr_learn_resource(const struct task_struct *task, -+ const int res, const unsigned long wanted, const int gt) -+{ -+ struct acl_subject_label *acl; -+ -+ if (unlikely((gr_status & GR_READY) && -+ task->acl && (task->acl->mode & GR_LEARN))) -+ goto skip_reslog; -+ -+#ifdef CONFIG_GRKERNSEC_RESLOG -+ gr_log_resource(task, res, wanted, gt); -+#endif -+ skip_reslog: -+ -+ if (unlikely(!(gr_status & GR_READY) || !wanted)) -+ return; -+ -+ acl = task->acl; -+ -+ if (likely(!acl || !(acl->mode & GR_LEARN) || -+ !(acl->resmask & (1 << (unsigned short) res)))) -+ return; -+ -+ if (wanted >= acl->res[res].rlim_cur) { -+ unsigned long res_add; -+ -+ res_add = wanted; -+ switch (res) { -+ case RLIMIT_CPU: -+ res_add += GR_RLIM_CPU_BUMP; -+ break; -+ case RLIMIT_FSIZE: -+ res_add += GR_RLIM_FSIZE_BUMP; -+ break; -+ case RLIMIT_DATA: -+ res_add += GR_RLIM_DATA_BUMP; -+ break; -+ case RLIMIT_STACK: -+ res_add += GR_RLIM_STACK_BUMP; -+ break; -+ case RLIMIT_CORE: -+ res_add += GR_RLIM_CORE_BUMP; -+ break; -+ case RLIMIT_RSS: -+ res_add += GR_RLIM_RSS_BUMP; -+ break; -+ case RLIMIT_NPROC: -+ res_add += GR_RLIM_NPROC_BUMP; -+ break; -+ case RLIMIT_NOFILE: -+ res_add += GR_RLIM_NOFILE_BUMP; -+ break; -+ case RLIMIT_MEMLOCK: -+ res_add += GR_RLIM_MEMLOCK_BUMP; -+ break; -+ case RLIMIT_AS: -+ res_add += GR_RLIM_AS_BUMP; -+ break; -+ case RLIMIT_LOCKS: -+ res_add += GR_RLIM_LOCKS_BUMP; -+ break; -+ } -+ -+ acl->res[res].rlim_cur = res_add; -+ -+ if (wanted > acl->res[res].rlim_max) -+ acl->res[res].rlim_max = res_add; -+ -+ security_learn(GR_LEARN_AUDIT_MSG, current->role->rolename, -+ current->role->roletype, acl->filename, -+ acl->res[res].rlim_cur, acl->res[res].rlim_max, -+ "", (unsigned long) res); -+ } -+ -+ return; -+} -+ -+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS -+void -+pax_set_flags(struct linux_binprm *bprm) -+{ -+ struct task_struct *task = current; -+ struct acl_subject_label *proc; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return; -+ -+ proc = task->acl; -+ -+ if (proc->mode & GR_PAXPAGE) -+ task->flags &= ~PF_PAX_PAGEEXEC; -+ if (proc->mode & GR_PAXSEGM) -+ task->flags &= ~PF_PAX_SEGMEXEC; -+ if (proc->mode & GR_PAXGCC) -+ task->flags |= PF_PAX_EMUTRAMP; -+ if (proc->mode & GR_PAXMPROTECT) -+ task->flags &= ~PF_PAX_MPROTECT; -+ if (proc->mode & GR_PAXRANDMMAP) -+ task->flags &= ~PF_PAX_RANDMMAP; -+ if (proc->mode & GR_PAXRANDEXEC) -+ task->flags |= PF_PAX_RANDEXEC; -+ -+ return; -+} -+#endif -+ -+#ifdef CONFIG_SYSCTL -+extern struct proc_dir_entry *proc_sys_root; -+ -+ -+/* the following function is called under the BKL */ -+ -+__u32 -+gr_handle_sysctl(const struct ctl_table *table, const void *oldval, -+ const void *newval) -+{ -+ struct proc_dir_entry *tmp; -+ struct nameidata nd; -+ const char *proc_sys = "/proc/sys"; -+ char *path; -+ struct acl_object_label *obj; -+ unsigned short len = 0, pos = 0, depth = 0, i; -+ __u32 err = 0; -+ __u32 mode = 0; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return 1; -+ -+ path = per_cpu_ptr(gr_shared_page[0], smp_processor_id()); -+ -+ if (oldval) -+ mode |= GR_READ; -+ if (newval) -+ mode |= GR_WRITE; -+ -+ /* convert the requested sysctl entry into a pathname */ -+ -+ for (tmp = table->de; tmp != proc_sys_root; tmp = tmp->parent) { -+ len += strlen(tmp->name); -+ len++; -+ depth++; -+ } -+ -+ if ((len + depth + strlen(proc_sys) + 1) > PAGE_SIZE) -+ return 0; /* deny */ -+ -+ memset(path, 0, PAGE_SIZE); -+ -+ memcpy(path, proc_sys, strlen(proc_sys)); -+ -+ pos += strlen(proc_sys); -+ -+ for (; depth > 0; depth--) { -+ path[pos] = '/'; -+ pos++; -+ for (i = 1, tmp = table->de; tmp != proc_sys_root; -+ tmp = tmp->parent) { -+ if (depth == i) { -+ memcpy(path + pos, tmp->name, -+ strlen(tmp->name)); -+ pos += strlen(tmp->name); -+ } -+ i++; -+ } -+ } -+ -+ err = path_lookup(path, LOOKUP_FOLLOW, &nd); -+ -+ if (err) -+ goto out; -+ -+ obj = chk_obj_label(nd.dentry, nd.mnt, current->acl); -+ err = obj->mode & (mode | to_gr_audit(mode) | GR_SUPPRESS); -+ -+ if (unlikely((current->acl->mode & GR_LEARN) && ((err & mode) != mode))) { -+ __u32 new_mode = mode; -+ -+ new_mode &= ~(GR_AUDITS | GR_SUPPRESS); -+ -+ err = new_mode; -+ gr_log_learn(current->role, current->uid, current->gid, -+ current, path, new_mode); -+ } else if ((err & mode) != mode && !(err & GR_SUPPRESS)) { -+ security_alert(GR_SYSCTL_ACL_MSG, "denied", path, -+ (mode & GR_READ) ? " reading" : "", -+ (mode & GR_WRITE) ? " writing" : "", -+ DEFAULTSECARGS); -+ err = 0; -+ } else if ((err & mode) != mode) { -+ err = 0; -+ } else if (((err & mode) == mode) && (err & GR_AUDITS)) { -+ security_audit(GR_SYSCTL_ACL_MSG, "successful", -+ path, (mode & GR_READ) ? " reading" : "", -+ (mode & GR_WRITE) ? " writing" : "", -+ DEFAULTSECARGS); -+ } -+ -+ path_release(&nd); -+ -+ out: -+ return err; -+} -+#endif -+ -+int -+gr_handle_proc_ptrace(struct task_struct *task) -+{ -+ struct file *filp; -+ struct task_struct *tmp = task; -+ struct task_struct *curtemp = current; -+ __u32 retmode; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return 0; -+ -+ filp = task->exec_file; -+ -+ read_lock(&tasklist_lock); -+ while (tmp->pid > 0) { -+ if (tmp == curtemp) -+ break; -+ tmp = tmp->parent; -+ } -+ read_unlock(&tasklist_lock); -+ -+ if (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE)) -+ return 1; -+ -+ retmode = gr_search_file(filp->f_dentry, GR_NOPTRACE, filp->f_vfsmnt); -+ -+ if (retmode & GR_NOPTRACE) -+ return 1; -+ -+ if (!(current->acl->mode & GR_OVERRIDE) && !(current->role->roletype & GR_ROLE_GOD) -+ && (current->acl != task->acl || (current->acl != current->role->root_label -+ && current->pid != task->pid))) -+ return 1; -+ -+ return 0; -+} -+ -+int -+gr_handle_ptrace(struct task_struct *task, const long request) -+{ -+ struct file *filp; -+ struct task_struct *tmp = task; -+ struct task_struct *curtemp = current; -+ __u32 retmode; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return 0; -+ -+ filp = task->exec_file; -+ -+ if (task->acl->mode & GR_NOPTRACE) { -+ security_alert(GR_PTRACE_ACL_MSG, filp ? -+ gr_to_filename(filp->f_dentry, filp->f_vfsmnt) -+ : "(none)", task->comm, task->pid, -+ DEFAULTSECARGS); -+ return 1; -+ } -+ -+ read_lock(&tasklist_lock); -+ while (tmp->pid > 0) { -+ if (tmp == curtemp) -+ break; -+ tmp = tmp->parent; -+ } -+ read_unlock(&tasklist_lock); -+ -+ if (tmp->pid == 0 && !(current->acl->mode & GR_RELAXPTRACE)) { -+ security_alert(GR_PTRACE_ACL_MSG, filp ? -+ gr_to_filename(filp->f_dentry, filp->f_vfsmnt) -+ : "(none)", task->comm, task->pid, -+ DEFAULTSECARGS); -+ return 1; -+ } -+ -+ if (unlikely(!filp)) -+ return 0; -+ -+ retmode = gr_search_file(filp->f_dentry, GR_PTRACERD | GR_NOPTRACE, filp->f_vfsmnt); -+ -+ if (retmode & GR_NOPTRACE) { -+ security_alert(GR_PTRACE_ACL_MSG, gr_to_filename(filp->f_dentry, filp->f_vfsmnt), -+ task->comm, task->pid, DEFAULTSECARGS); -+ return 1; -+ } -+ -+ if (retmode & GR_PTRACERD) { -+ switch (request) { -+ case PTRACE_POKETEXT: -+ case PTRACE_POKEDATA: -+ case PTRACE_POKEUSR: -+#if !defined(CONFIG_PPC32) && !defined(CONFIG_PARISC) && !defined(CONFIG_ALPHA) -+ case PTRACE_SETREGS: -+ case PTRACE_SETFPREGS: -+#endif -+#ifdef CONFIG_X86 -+ case PTRACE_SETFPXREGS: -+#endif -+#ifdef CONFIG_ALTIVEC -+ case PTRACE_SETVRREGS: -+#endif -+ return 1; -+ default: -+ return 0; -+ } -+ } else if (!(current->acl->mode & GR_OVERRIDE) && -+ !(current->role->roletype & GR_ROLE_GOD) -+ && (current->acl != task->acl -+ || (current->acl != current->role->root_label -+ && current->pid != task->pid))) { -+ security_alert(GR_PTRACE_ACL_MSG, -+ gr_to_filename(filp->f_dentry, filp->f_vfsmnt), -+ task->comm, task->pid, DEFAULTSECARGS); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int -+gr_handle_ptrace_exec(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ __u32 retmode; -+ struct acl_subject_label *subj; -+ -+ if (unlikely(!(gr_status & GR_READY))) -+ return 0; -+ -+ if (unlikely -+ ((current->ptrace & PT_PTRACED) -+ && !(current->acl->mode & GR_OVERRIDE))) -+ retmode = gr_search_file(dentry, GR_PTRACERD, mnt); -+ else -+ return 0; -+ -+ subj = chk_subj_label(dentry, mnt, current->role); -+ -+ if (!(retmode & GR_PTRACERD) && -+ !(current->role->roletype & GR_ROLE_GOD) && -+ (current->acl != subj)) { -+ security_alert(GR_PTRACE_EXEC_ACL_MSG, -+ gr_to_filename(dentry, mnt), DEFAULTSECARGS); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int -+gr_handle_mmap(const struct file *filp, const unsigned long prot) -+{ -+ struct acl_object_label *obj, *obj2; -+ -+ if (unlikely(!(gr_status & GR_READY) || -+ (current->acl->mode & GR_OVERRIDE) || !filp || -+ !(prot & PROT_EXEC))) -+ return 0; -+ -+ if (unlikely(current->is_writable)) -+ return 0; -+ -+ obj = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, default_role->root_label); -+ obj2 = chk_obj_label(filp->f_dentry, filp->f_vfsmnt, -+ current->role->root_label); -+ if (unlikely((obj->mode & GR_WRITE) || (obj2->mode & GR_WRITE))) { -+ security_alert(GR_WRITLIB_ACL_MSG, -+ gr_to_filename(filp->f_dentry, filp->f_vfsmnt), -+ DEFAULTSECARGS); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+int -+gr_acl_handle_mmap(const struct file *file, const unsigned long prot) -+{ -+ __u32 mode; -+ -+ if (unlikely(!file || !(prot & PROT_EXEC))) -+ return 1; -+ -+ mode = -+ gr_search_file(file->f_dentry, -+ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS, -+ file->f_vfsmnt); -+ -+ if (unlikely(!gr_tpe_allow(file) || (!(mode & GR_EXEC) && !(mode & GR_SUPPRESS)))) { -+ security_alert(GR_MMAP_ACL_MSG, "denied", -+ gr_to_filename(file->f_dentry, file->f_vfsmnt), -+ DEFAULTSECARGS); -+ return 0; -+ } else if (unlikely(!gr_tpe_allow(file) || !(mode & GR_EXEC))) { -+ return 0; -+ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) { -+ security_audit(GR_MMAP_ACL_MSG, "successful", -+ gr_to_filename(file->f_dentry, file->f_vfsmnt), -+ DEFAULTSECARGS); -+ return 1; -+ } -+ -+ return 1; -+} -+ -+int -+gr_acl_handle_mprotect(const struct file *file, const unsigned long prot) -+{ -+ __u32 mode; -+ -+ if (unlikely(!file || !(prot & PROT_EXEC))) -+ return 1; -+ -+ mode = -+ gr_search_file(file->f_dentry, -+ GR_EXEC | GR_AUDIT_EXEC | GR_SUPPRESS, -+ file->f_vfsmnt); -+ -+ if (unlikely(!gr_tpe_allow(file) || (!(mode & GR_EXEC) && !(mode & GR_SUPPRESS)))) { -+ security_alert(GR_MPROTECT_ACL_MSG, "denied", -+ gr_to_filename(file->f_dentry, file->f_vfsmnt), -+ DEFAULTSECARGS); -+ return 0; -+ } else if (unlikely(!gr_tpe_allow(file) || !(mode & GR_EXEC))) { -+ return 0; -+ } else if (unlikely(mode & GR_EXEC && mode & GR_AUDIT_EXEC)) { -+ security_audit(GR_MPROTECT_ACL_MSG, "successful", -+ gr_to_filename(file->f_dentry, file->f_vfsmnt), -+ DEFAULTSECARGS); -+ return 1; -+ } -+ -+ return 1; -+} -+ -+void -+gr_acl_handle_psacct(struct task_struct *task, const long code) -+{ -+ u64 runtime64; -+ unsigned long runtime; -+ unsigned long cputime; -+ unsigned int wday, cday; -+ __u8 whr, chr; -+ __u8 wmin, cmin; -+ __u8 wsec, csec; -+ char cur_tty[64] = { 0 }; -+ char parent_tty[64] = { 0 }; -+ -+ if (unlikely(!(gr_status & GR_READY) || !task->acl || -+ !(task->acl->mode & GR_PROCACCT))) -+ return; -+ -+ runtime64 = get_jiffies_64() - task->start_time; -+ do_div(runtime64, HZ); -+ runtime = (unsigned long)runtime64; -+ wday = runtime / (3600 * 24); -+ runtime -= wday * (3600 * 24); -+ whr = runtime / 3600; -+ runtime -= whr * 3600; -+ wmin = runtime / 60; -+ runtime -= wmin * 60; -+ wsec = runtime; -+ -+ cputime = (task->utime + task->stime) / HZ; -+ cday = cputime / (3600 * 24); -+ cputime -= cday * (3600 * 24); -+ chr = cputime / 3600; -+ cputime -= chr * 3600; -+ cmin = cputime / 60; -+ cputime -= cmin * 60; -+ csec = cputime; -+ -+ security_audit(GR_ACL_PROCACCT_MSG, gr_task_fullpath(task), task->comm, -+ task->pid, NIPQUAD(task->curr_ip), tty_name(task->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", -+ code, gr_parent_task_fullpath(task), -+ task->parent->comm, task->parent->pid, -+ NIPQUAD(task->parent->curr_ip), -+ tty_name(task->parent->tty, parent_tty), -+ task->parent->uid, task->parent->euid, task->parent->gid, -+ task->parent->egid); -+ -+ return; -+} -+ -+EXPORT_SYMBOL(gr_set_kernel_label); -+ -+void gr_set_kernel_label(struct task_struct *task) -+{ -+ if (gr_status & GR_READY) { -+ task->role = kernel_role; -+ task->acl = kernel_role->root_label; -+ } -+ return; -+} -diff -urN linux-2.6.5/grsecurity/gracl_alloc.c linux-2.6.5/grsecurity/gracl_alloc.c ---- linux-2.6.5/grsecurity/gracl_alloc.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/gracl_alloc.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,93 @@ -+/* stack-based acl allocation tracking (c) Brad Spengler 2002,2003 */ -+ -+#include <linux/kernel.h> -+#include <linux/mm.h> -+#include <linux/slab.h> -+#include <linux/vmalloc.h> -+#include <linux/gracl.h> -+#include <linux/grsecurity.h> -+ -+static unsigned long alloc_stack_next = 1; -+static unsigned long alloc_stack_size = 1; -+static void **alloc_stack; -+ -+static __inline__ int -+alloc_pop(void) -+{ -+ if (alloc_stack_next == 1) -+ return 0; -+ -+ kfree(alloc_stack[alloc_stack_next - 2]); -+ -+ alloc_stack_next--; -+ -+ return 1; -+} -+ -+static __inline__ void -+alloc_push(void *buf) -+{ -+ if (alloc_stack_next >= alloc_stack_size) -+ BUG(); -+ -+ alloc_stack[alloc_stack_next - 1] = buf; -+ -+ alloc_stack_next++; -+ -+ return; -+} -+ -+void * -+acl_alloc(unsigned long len) -+{ -+ void *ret; -+ -+ if (len > PAGE_SIZE) -+ BUG(); -+ -+ ret = kmalloc(len, GFP_KERNEL); -+ -+ if (ret) -+ alloc_push(ret); -+ -+ return ret; -+} -+ -+void -+acl_free_all(void) -+{ -+ if (gr_acl_is_enabled() || !alloc_stack) -+ return; -+ -+ while (alloc_pop()) ; -+ -+ if (alloc_stack) { -+ if ((alloc_stack_size * sizeof (void *)) <= PAGE_SIZE) -+ kfree(alloc_stack); -+ else -+ vfree(alloc_stack); -+ } -+ -+ alloc_stack = NULL; -+ alloc_stack_size = 1; -+ alloc_stack_next = 1; -+ -+ return; -+} -+ -+int -+acl_alloc_stack_init(unsigned long size) -+{ -+ if ((size * sizeof (void *)) <= PAGE_SIZE) -+ alloc_stack = -+ (void **) kmalloc(size * sizeof (void *), GFP_KERNEL); -+ else -+ alloc_stack = (void **) vmalloc(size * sizeof (void *)); -+ -+ alloc_stack_size = size; -+ -+ if (!alloc_stack) -+ return 0; -+ else -+ return 1; -+} -diff -urN linux-2.6.5/grsecurity/gracl_cap.c linux-2.6.5/grsecurity/gracl_cap.c ---- linux-2.6.5/grsecurity/gracl_cap.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/gracl_cap.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,115 @@ -+/* capability handling routines, (c) Brad Spengler 2002,2003 */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/sched.h> -+#include <linux/capability.h> -+#include <linux/gracl.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+static const char *captab_log[29] = { -+ "CAP_CHOWN", -+ "CAP_DAC_OVERRIDE", -+ "CAP_DAC_READ_SEARCH", -+ "CAP_FOWNER", -+ "CAP_FSETID", -+ "CAP_KILL", -+ "CAP_SETGID", -+ "CAP_SETUID", -+ "CAP_SETPCAP", -+ "CAP_LINUX_IMMUTABLE", -+ "CAP_NET_BIND_SERVICE", -+ "CAP_NET_BROADCAST", -+ "CAP_NET_ADMIN", -+ "CAP_NET_RAW", -+ "CAP_IPC_LOCK", -+ "CAP_IPC_OWNER", -+ "CAP_SYS_MODULE", -+ "CAP_SYS_RAWIO", -+ "CAP_SYS_CHROOT", -+ "CAP_SYS_PTRACE", -+ "CAP_SYS_PACCT", -+ "CAP_SYS_ADMIN", -+ "CAP_SYS_BOOT", -+ "CAP_SYS_NICE", -+ "CAP_SYS_RESOURCE", -+ "CAP_SYS_TIME", -+ "CAP_SYS_TTY_CONFIG", -+ "CAP_MKNOD", -+ "CAP_LEASE" -+}; -+ -+EXPORT_SYMBOL(gr_task_is_capable); -+ -+int -+gr_task_is_capable(struct task_struct *task, const int cap) -+{ -+ struct acl_subject_label *curracl; -+ __u32 cap_drop = 0, cap_mask = 0; -+ -+ if (!gr_acl_is_enabled()) -+ return 1; -+ -+ curracl = task->acl; -+ -+ cap_drop = curracl->cap_lower; -+ cap_mask = curracl->cap_mask; -+ -+ while ((curracl = curracl->parent_subject)) { -+ cap_drop |= curracl->cap_lower & (cap_mask & ~curracl->cap_mask); -+ cap_mask |= curracl->cap_mask; -+ } -+ -+ if (!cap_raised(cap_drop, cap)) -+ return 1; -+ -+ curracl = task->acl; -+ -+ if ((curracl->mode & GR_LEARN) -+ && cap_raised(task->cap_effective, cap)) { -+ security_learn(GR_LEARN_AUDIT_MSG, task->role->rolename, -+ task->role->roletype, task->uid, -+ task->gid, task->exec_file ? -+ gr_to_filename(task->exec_file->f_dentry, -+ task->exec_file->f_vfsmnt) : curracl->filename, -+ curracl->filename, 0UL, -+ 0UL, "", (unsigned long) cap, NIPQUAD(task->curr_ip)); -+ return 1; -+ } -+ -+ if ((cap >= 0) && (cap < 29) && cap_raised(task->cap_effective, cap)) -+ security_alert(GR_CAP_ACL_MSG, captab_log[cap], -+ 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); -+ -+ return 0; -+} -+ -+int -+gr_is_capable_nolog(const int cap) -+{ -+ struct acl_subject_label *curracl; -+ __u32 cap_drop = 0, cap_mask = 0; -+ -+ if (!gr_acl_is_enabled()) -+ return 1; -+ -+ curracl = current->acl; -+ -+ cap_drop = curracl->cap_lower; -+ cap_mask = curracl->cap_mask; -+ -+ while ((curracl = curracl->parent_subject)) { -+ cap_drop |= curracl->cap_lower & (cap_mask & ~curracl->cap_mask); -+ cap_mask |= curracl->cap_mask; -+ } -+ -+ if (!cap_raised(cap_drop, cap)) -+ return 1; -+ -+ return 0; -+} -+ -diff -urN linux-2.6.5/grsecurity/gracl_fs.c linux-2.6.5/grsecurity/gracl_fs.c ---- linux-2.6.5/grsecurity/gracl_fs.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/gracl_fs.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,460 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/types.h> -+#include <linux/fs.h> -+#include <linux/file.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+#include <linux/gracl.h> -+ -+__u32 -+gr_acl_handle_hidden_file(const struct dentry * dentry, -+ const struct vfsmount * mnt) -+{ -+ __u32 mode; -+ -+ if (unlikely(!dentry->d_inode)) -+ return GR_FIND; -+ -+ mode = -+ gr_search_file(dentry, GR_FIND | GR_AUDIT_FIND | GR_SUPPRESS, mnt); -+ -+ if (unlikely(mode & GR_FIND && mode & GR_AUDIT_FIND)) { -+ security_audit(GR_HIDDEN_ACL_MSG, "successful", -+ gr_to_filename(dentry, mnt), DEFAULTSECARGS); -+ return mode; -+ } else if (unlikely(!(mode & GR_FIND) && !(mode & GR_SUPPRESS))) { -+ security_alert(GR_HIDDEN_ACL_MSG, "denied", -+ gr_to_filename(dentry, mnt), -+ DEFAULTSECARGS); -+ return 0; -+ } else if (unlikely(!(mode & GR_FIND))) -+ return 0; -+ -+ return GR_FIND; -+} -+ -+__u32 -+gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt, -+ const int fmode) -+{ -+ __u32 reqmode = GR_FIND; -+ __u32 mode; -+ -+ if (unlikely(!dentry->d_inode)) -+ return reqmode; -+ -+ if (unlikely(fmode & O_APPEND)) -+ reqmode |= GR_APPEND; -+ else if (unlikely(fmode & FMODE_WRITE)) -+ reqmode |= GR_WRITE; -+ if (likely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY))) -+ reqmode |= GR_READ; -+ -+ mode = -+ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, -+ mnt); -+ -+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) { -+ security_audit(GR_OPEN_ACL_MSG, "successful", -+ gr_to_filename(dentry, mnt), -+ reqmode & GR_READ ? " reading" : "", -+ reqmode & GR_WRITE ? " writing" : -+ reqmode & GR_APPEND ? " appending" : "", -+ DEFAULTSECARGS); -+ return reqmode; -+ } else -+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS))) -+ { -+ security_alert(GR_OPEN_ACL_MSG, "denied", -+ gr_to_filename(dentry, mnt), -+ reqmode & GR_READ ? " reading" : "", -+ reqmode & GR_WRITE ? " writing" : reqmode & -+ GR_APPEND ? " appending" : "", DEFAULTSECARGS); -+ return 0; -+ } else if (unlikely((mode & reqmode) != reqmode)) -+ return 0; -+ -+ return reqmode; -+} -+ -+__u32 -+gr_acl_handle_creat(const struct dentry * dentry, -+ const struct dentry * p_dentry, -+ const struct vfsmount * p_mnt, const int fmode, -+ const int imode) -+{ -+ __u32 reqmode = GR_WRITE | GR_CREATE; -+ __u32 mode; -+ -+ if (unlikely(fmode & O_APPEND)) -+ reqmode |= GR_APPEND; -+ if (unlikely((fmode & FMODE_READ) && !(fmode & O_DIRECTORY))) -+ reqmode |= GR_READ; -+ if (unlikely((fmode & O_CREAT) && (imode & (S_ISUID | S_ISGID)))) -+ reqmode |= GR_SETID; -+ -+ mode = -+ gr_check_create(dentry, p_dentry, p_mnt, -+ reqmode | to_gr_audit(reqmode) | GR_SUPPRESS); -+ -+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) { -+ security_audit(GR_CREATE_ACL_MSG, "successful", -+ gr_to_filename(dentry, p_mnt), -+ reqmode & GR_READ ? " reading" : "", -+ reqmode & GR_WRITE ? " writing" : -+ reqmode & GR_APPEND ? " appending" : "", -+ DEFAULTSECARGS); -+ return reqmode; -+ } else -+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS))) -+ { -+ security_alert(GR_CREATE_ACL_MSG, "denied", -+ gr_to_filename(dentry, p_mnt), -+ reqmode & GR_READ ? " reading" : "", -+ reqmode & GR_WRITE ? " writing" : reqmode & -+ GR_APPEND ? " appending" : "", DEFAULTSECARGS); -+ return 0; -+ } else if (unlikely((mode & reqmode) != reqmode)) -+ return 0; -+ -+ return reqmode; -+} -+ -+__u32 -+gr_acl_handle_access(const struct dentry * dentry, const struct vfsmount * mnt, -+ const int fmode) -+{ -+ __u32 mode, reqmode = GR_FIND; -+ -+ if ((fmode & S_IXOTH) && !S_ISDIR(dentry->d_inode->i_mode)) -+ reqmode |= GR_EXEC; -+ if (fmode & S_IWOTH) -+ reqmode |= GR_WRITE; -+ if (fmode & S_IROTH) -+ reqmode |= GR_READ; -+ -+ mode = -+ gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, -+ mnt); -+ -+ if (unlikely(((mode & reqmode) == reqmode) && mode & GR_AUDITS)) { -+ security_audit(GR_ACCESS_ACL_MSG, "successful", -+ gr_to_filename(dentry, mnt), -+ reqmode & GR_READ ? " reading" : "", -+ reqmode & GR_WRITE ? " writing" : "", -+ reqmode & GR_EXEC ? " executing" : "", -+ DEFAULTSECARGS); -+ return reqmode; -+ } else -+ if (unlikely((mode & reqmode) != reqmode && !(mode & GR_SUPPRESS))) -+ { -+ security_alert(GR_ACCESS_ACL_MSG, "denied", -+ gr_to_filename(dentry, mnt), -+ reqmode & GR_READ ? " reading" : "", -+ reqmode & GR_WRITE ? " writing" : "", -+ reqmode & GR_EXEC ? " executing" : "", -+ DEFAULTSECARGS); -+ return 0; -+ } else if (unlikely((mode & reqmode) != reqmode)) -+ return 0; -+ -+ return reqmode; -+} -+ -+#define generic_fs_handler(dentry, mnt, reqmode, fmt) \ -+{ \ -+ __u32 mode; \ -+ \ -+ mode = gr_search_file(dentry, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS, mnt); \ -+ \ -+ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) { \ -+ security_audit(fmt, "successful", \ -+ gr_to_filename(dentry, mnt), DEFAULTSECARGS); \ -+ return mode; \ -+ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) { \ -+ security_alert(fmt, "denied", gr_to_filename(dentry, mnt), \ -+ DEFAULTSECARGS); \ -+ return 0; \ -+ } else if (unlikely((mode & (reqmode)) != (reqmode))) \ -+ return 0; \ -+ \ -+ return (reqmode); \ -+} -+ -+__u32 -+gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt) -+{ -+ generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_RMDIR_ACL_MSG); -+} -+ -+__u32 -+gr_acl_handle_unlink(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ generic_fs_handler(dentry, mnt, GR_WRITE | GR_DELETE , GR_UNLINK_ACL_MSG); -+} -+ -+__u32 -+gr_acl_handle_truncate(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ generic_fs_handler(dentry, mnt, GR_WRITE, GR_TRUNCATE_ACL_MSG); -+} -+ -+__u32 -+gr_acl_handle_utime(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ generic_fs_handler(dentry, mnt, GR_WRITE, GR_ATIME_ACL_MSG); -+} -+ -+__u32 -+gr_acl_handle_fchmod(const struct dentry *dentry, const struct vfsmount *mnt, -+ mode_t mode) -+{ -+ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) { -+ generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID, -+ GR_FCHMOD_ACL_MSG); -+ } else { -+ generic_fs_handler(dentry, mnt, GR_WRITE, GR_FCHMOD_ACL_MSG); -+ } -+} -+ -+__u32 -+gr_acl_handle_chmod(const struct dentry *dentry, const struct vfsmount *mnt, -+ mode_t mode) -+{ -+ if (unlikely((mode != (mode_t)-1) && (mode & (S_ISUID | S_ISGID)))) { -+ generic_fs_handler(dentry, mnt, GR_WRITE | GR_SETID, -+ GR_CHMOD_ACL_MSG); -+ } else { -+ generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHMOD_ACL_MSG); -+ } -+} -+ -+__u32 -+gr_acl_handle_chown(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ generic_fs_handler(dentry, mnt, GR_WRITE, GR_CHOWN_ACL_MSG); -+} -+ -+__u32 -+gr_acl_handle_execve(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ generic_fs_handler(dentry, mnt, GR_EXEC, GR_EXEC_ACL_MSG); -+} -+ -+__u32 -+gr_acl_handle_unix(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ generic_fs_handler(dentry, mnt, GR_READ | GR_WRITE, -+ GR_UNIXCONNECT_ACL_MSG); -+} -+ -+__u32 -+gr_acl_handle_filldir(const struct dentry *dentry, const struct vfsmount *mnt, -+ const ino_t ino) -+{ -+ if (likely((unsigned long)(dentry->d_inode))) { -+ struct dentry d = *dentry; -+ struct inode inode = *(dentry->d_inode); -+ -+ inode.i_ino = ino; -+ d.d_inode = &inode; -+ -+ if (unlikely(!gr_search_file(&d, GR_FIND | GR_NOLEARN, mnt))) -+ return 0; -+ } -+ -+ return 1; -+} -+ -+__u32 -+gr_acl_handle_link(const struct dentry * new_dentry, -+ const struct dentry * parent_dentry, -+ const struct vfsmount * parent_mnt, -+ const struct dentry * old_dentry, -+ const struct vfsmount * old_mnt, const char *to) -+{ -+ __u32 needmode = GR_WRITE | GR_CREATE; -+ __u32 mode; -+ -+ mode = -+ gr_check_link(new_dentry, parent_dentry, parent_mnt, old_dentry, -+ old_mnt); -+ -+ if (unlikely(((mode & needmode) == needmode) && mode & GR_AUDITS)) { -+ security_audit(GR_LINK_ACL_MSG, "successful", -+ gr_to_filename(old_dentry, old_mnt), to, -+ DEFAULTSECARGS); -+ return mode; -+ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) { -+ security_alert(GR_LINK_ACL_MSG, "denied", -+ gr_to_filename(old_dentry, old_mnt), to, -+ DEFAULTSECARGS); -+ return 0; -+ } else if (unlikely((mode & needmode) != needmode)) -+ return 0; -+ -+ return (GR_WRITE | GR_CREATE); -+} -+ -+__u32 -+gr_acl_handle_symlink(const struct dentry * new_dentry, -+ const struct dentry * parent_dentry, -+ const struct vfsmount * parent_mnt, const char *from) -+{ -+ __u32 needmode = GR_WRITE | GR_CREATE; -+ __u32 mode; -+ -+ mode = -+ gr_check_create(new_dentry, parent_dentry, parent_mnt, -+ GR_CREATE | GR_AUDIT_CREATE | -+ GR_WRITE | GR_AUDIT_WRITE | GR_SUPPRESS); -+ -+ if (unlikely(mode & GR_WRITE && mode & GR_AUDITS)) { -+ security_audit(GR_SYMLINK_ACL_MSG, "successful", -+ from, gr_to_filename(new_dentry, parent_mnt), -+ DEFAULTSECARGS); -+ return mode; -+ } else if (unlikely(((mode & needmode) != needmode) && !(mode & GR_SUPPRESS))) { -+ security_alert(GR_SYMLINK_ACL_MSG, "denied", -+ from, gr_to_filename(new_dentry, parent_mnt), -+ DEFAULTSECARGS); -+ return 0; -+ } else if (unlikely((mode & needmode) != needmode)) -+ return 0; -+ -+ return (GR_WRITE | GR_CREATE); -+} -+ -+#define generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt, reqmode, fmt) \ -+{ \ -+ __u32 mode; \ -+ \ -+ mode = gr_check_create(new_dentry, parent_dentry, parent_mnt, reqmode | to_gr_audit(reqmode) | GR_SUPPRESS); \ -+ \ -+ if (unlikely(((mode & (reqmode)) == (reqmode)) && mode & GR_AUDITS)) { \ -+ security_audit(fmt, "successful", \ -+ gr_to_filename(new_dentry, parent_mnt), \ -+ DEFAULTSECARGS); \ -+ return mode; \ -+ } else if (unlikely((mode & (reqmode)) != (reqmode) && !(mode & GR_SUPPRESS))) { \ -+ security_alert(fmt, "denied", \ -+ gr_to_filename(new_dentry, parent_mnt), \ -+ DEFAULTSECARGS); \ -+ return 0; \ -+ } else if (unlikely((mode & (reqmode)) != (reqmode))) \ -+ return 0; \ -+ \ -+ return (reqmode); \ -+} -+ -+__u32 -+gr_acl_handle_mknod(const struct dentry * new_dentry, -+ const struct dentry * parent_dentry, -+ const struct vfsmount * parent_mnt, -+ const int mode) -+{ -+ __u32 reqmode = GR_WRITE | GR_CREATE; -+ if (unlikely(mode & (S_ISUID | S_ISGID))) -+ reqmode |= GR_SETID; -+ -+ generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt, -+ reqmode, GR_MKNOD_ACL_MSG); -+} -+ -+__u32 -+gr_acl_handle_mkdir(const struct dentry *new_dentry, -+ const struct dentry *parent_dentry, -+ const struct vfsmount *parent_mnt) -+{ -+ generic_fs_create_handler(new_dentry, parent_dentry, parent_mnt, -+ GR_WRITE | GR_CREATE, GR_MKDIR_ACL_MSG); -+} -+ -+#define RENAME_CHECK_SUCCESS(old, new) \ -+ (((old & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ)) && \ -+ ((new & (GR_WRITE | GR_READ)) == (GR_WRITE | GR_READ))) -+ -+int -+gr_acl_handle_rename(struct dentry *new_dentry, -+ struct dentry *parent_dentry, -+ const struct vfsmount *parent_mnt, -+ struct dentry *old_dentry, -+ struct inode *old_parent_inode, -+ struct vfsmount *old_mnt, const char *newname) -+{ -+ __u32 comp1, comp2; -+ int error = 0; -+ -+ if (unlikely(!gr_acl_is_enabled())) -+ return 0; -+ -+ if (!new_dentry->d_inode) { -+ comp1 = gr_check_create(new_dentry, parent_dentry, parent_mnt, -+ GR_READ | GR_WRITE | GR_CREATE | GR_AUDIT_READ | -+ GR_AUDIT_WRITE | GR_AUDIT_CREATE | GR_SUPPRESS); -+ comp2 = gr_search_file(old_dentry, GR_READ | GR_WRITE | -+ GR_DELETE | GR_AUDIT_DELETE | -+ GR_AUDIT_READ | GR_AUDIT_WRITE | -+ GR_SUPPRESS, old_mnt); -+ } else { -+ comp1 = gr_search_file(new_dentry, GR_READ | GR_WRITE | -+ GR_CREATE | GR_DELETE | -+ GR_AUDIT_CREATE | GR_AUDIT_DELETE | -+ GR_AUDIT_READ | GR_AUDIT_WRITE | -+ GR_SUPPRESS, parent_mnt); -+ comp2 = -+ gr_search_file(old_dentry, -+ GR_READ | GR_WRITE | GR_AUDIT_READ | -+ GR_DELETE | GR_AUDIT_DELETE | -+ GR_AUDIT_WRITE | GR_SUPPRESS, old_mnt); -+ } -+ -+ if (RENAME_CHECK_SUCCESS(comp1, comp2) && -+ ((comp1 & GR_AUDITS) || (comp2 & GR_AUDITS))) -+ security_audit(GR_RENAME_ACL_MSG, "successful", -+ gr_to_filename(old_dentry, old_mnt), -+ newname, DEFAULTSECARGS); -+ else if (!RENAME_CHECK_SUCCESS(comp1, comp2) && !(comp1 & GR_SUPPRESS) -+ && !(comp2 & GR_SUPPRESS)) { -+ security_alert(GR_RENAME_ACL_MSG, "denied", -+ gr_to_filename(old_dentry, old_mnt), newname, -+ DEFAULTSECARGS); -+ error = -EACCES; -+ } else if (unlikely(!RENAME_CHECK_SUCCESS(comp1, comp2))) -+ error = -EACCES; -+ -+ return error; -+} -+ -+void -+gr_acl_handle_exit(void) -+{ -+ u16 id; -+ char *rolename; -+ -+ if (unlikely(current->acl_sp_role && gr_acl_is_enabled())) { -+ id = current->acl_role_id; -+ rolename = current->role->rolename; -+ gr_set_acls(1); -+ security_alert_good(GR_SPROLEL_ACL_MSG, -+ rolename, id, DEFAULTSECARGS); -+ } -+ -+ if (current->exec_file) { -+ fput(current->exec_file); -+ current->exec_file = NULL; -+ } -+} -+ -+int -+gr_acl_handle_procpidmem(const struct task_struct *task) -+{ -+ if (unlikely(!gr_acl_is_enabled())) -+ return 0; -+ -+ if (task->acl->mode & GR_PROTPROCFD) -+ return -EACCES; -+ -+ return 0; -+} -diff -urN linux-2.6.5/grsecurity/gracl_ip.c linux-2.6.5/grsecurity/gracl_ip.c ---- linux-2.6.5/grsecurity/gracl_ip.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/gracl_ip.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,236 @@ -+/* -+ * grsecurity/gracl_ip.c -+ * Copyright Brad Spengler 2002, 2003 -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <asm/uaccess.h> -+#include <asm/errno.h> -+#include <net/sock.h> -+#include <linux/file.h> -+#include <linux/fs.h> -+#include <linux/net.h> -+#include <linux/in.h> -+#include <linux/skbuff.h> -+#include <linux/ip.h> -+#include <linux/udp.h> -+#include <linux/smp_lock.h> -+#include <linux/types.h> -+#include <linux/sched.h> -+#include <linux/gracl.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+#define GR_BIND 0x01 -+#define GR_CONNECT 0x02 -+ -+static const char * gr_protocols[256] = { -+ "ip", "icmp", "igmp", "ggp", "ipencap", "st", "tcp", "cbt", -+ "egp", "igp", "bbn-rcc", "nvp", "pup", "argus", "emcon", "xnet", -+ "chaos", "udp", "mux", "dcn", "hmp", "prm", "xns-idp", "trunk-1", -+ "trunk-2", "leaf-1", "leaf-2", "rdp", "irtp", "iso-tp4", "netblt", "mfe-nsp", -+ "merit-inp", "sep", "3pc", "idpr", "xtp", "ddp", "idpr-cmtp", "tp++", -+ "il", "ipv6", "sdrp", "ipv6-route", "ipv6-frag", "idrp", "rsvp", "gre", -+ "mhrp", "bna", "ipv6-crypt", "ipv6-auth", "i-nlsp", "swipe", "narp", "mobile", -+ "tlsp", "skip", "ipv6-icmp", "ipv6-nonxt", "ipv6-opts", "unknown:61", "cftp", "unknown:63", -+ "sat-expak", "kryptolan", "rvd", "ippc", "unknown:68", "sat-mon", "visa", "ipcv", -+ "cpnx", "cphb", "wsn", "pvp", "br-sat-mon", "sun-nd", "wb-mon", "wb-expak", -+ "iso-ip", "vmtp", "secure-vmtp", "vines", "ttp", "nfsnet-igp", "dgp", "tcf", -+ "eigrp", "ospf", "sprite-rpc", "larp", "mtp", "ax.25", "ipip", "micp", -+ "scc-sp", "etherip", "encap", "unknown:99", "gmtp", "ifmp", "pnni", "pim", -+ "aris", "scps", "qnx", "a/n", "ipcomp", "snp", "compaq-peer", "ipx-in-ip", -+ "vrrp", "pgm", "unknown:114", "l2tp", "ddx", "iatp", "stp", "srp", -+ "uti", "smp", "sm", "ptp", "isis", "fire", "crtp", "crdup", -+ "sscopmce", "iplt", "sps", "pipe", "sctp", "fc", "unkown:134", "unknown:135", -+ "unknown:136", "unknown:137", "unknown:138", "unknown:139", "unknown:140", "unknown:141", "unknown:142", "unknown:143", -+ "unknown:144", "unknown:145", "unknown:146", "unknown:147", "unknown:148", "unknown:149", "unknown:150", "unknown:151", -+ "unknown:152", "unknown:153", "unknown:154", "unknown:155", "unknown:156", "unknown:157", "unknown:158", "unknown:159", -+ "unknown:160", "unknown:161", "unknown:162", "unknown:163", "unknown:164", "unknown:165", "unknown:166", "unknown:167", -+ "unknown:168", "unknown:169", "unknown:170", "unknown:171", "unknown:172", "unknown:173", "unknown:174", "unknown:175", -+ "unknown:176", "unknown:177", "unknown:178", "unknown:179", "unknown:180", "unknown:181", "unknown:182", "unknown:183", -+ "unknown:184", "unknown:185", "unknown:186", "unknown:187", "unknown:188", "unknown:189", "unknown:190", "unknown:191", -+ "unknown:192", "unknown:193", "unknown:194", "unknown:195", "unknown:196", "unknown:197", "unknown:198", "unknown:199", -+ "unknown:200", "unknown:201", "unknown:202", "unknown:203", "unknown:204", "unknown:205", "unknown:206", "unknown:207", -+ "unknown:208", "unknown:209", "unknown:210", "unknown:211", "unknown:212", "unknown:213", "unknown:214", "unknown:215", -+ "unknown:216", "unknown:217", "unknown:218", "unknown:219", "unknown:220", "unknown:221", "unknown:222", "unknown:223", -+ "unknown:224", "unknown:225", "unknown:226", "unknown:227", "unknown:228", "unknown:229", "unknown:230", "unknown:231", -+ "unknown:232", "unknown:233", "unknown:234", "unknown:235", "unknown:236", "unknown:237", "unknown:238", "unknown:239", -+ "unknown:240", "unknown:241", "unknown:242", "unknown:243", "unknown:244", "unknown:245", "unknown:246", "unknown:247", -+ "unknown:248", "unknown:249", "unknown:250", "unknown:251", "unknown:252", "unknown:253", "unknown:254", "unknown:255", -+ }; -+ -+static const char * gr_socktypes[11] = { -+ "unknown:0", "stream", "dgram", "raw", "rdm", "seqpacket", "unknown:6", -+ "unknown:7", "unknown:8", "unknown:9", "packet" -+ }; -+ -+__inline__ const char * -+gr_proto_to_name(unsigned char proto) -+{ -+ return gr_protocols[proto]; -+} -+ -+__inline__ const char * -+gr_socktype_to_name(unsigned char type) -+{ -+ return gr_socktypes[type]; -+} -+ -+int -+gr_search_socket(const int domain, const int type, const int protocol) -+{ -+ struct acl_subject_label *curr; -+ -+ if (unlikely(!gr_acl_is_enabled())) -+ goto exit; -+ -+ if ((domain < 0) || (type < 0) || (protocol < 0) || (domain != PF_INET) -+ || (domain >= NPROTO) || (type >= SOCK_MAX) || (protocol > 255)) -+ goto exit; // let the kernel handle it -+ -+ curr = current->acl; -+ -+ if (!curr->ips) -+ goto exit; -+ -+ if ((curr->ip_type & (1 << type)) && -+ (curr->ip_proto[protocol / 32] & (1 << (protocol % 32)))) -+ goto exit; -+ -+ if (curr->mode & GR_LEARN) { -+ /* we don't place acls on raw sockets , and sometimes -+ dgram/ip sockets are opened for ioctl and not -+ bind/connect, so we'll fake a bind learn log */ -+ if (type == SOCK_RAW || type == SOCK_PACKET) { -+ __u32 fakeip = 0; -+ security_learn(GR_IP_LEARN_MSG, current->role->rolename, -+ current->role->roletype, current->uid, -+ current->gid, current->exec_file ? -+ gr_to_filename(current->exec_file->f_dentry, -+ current->exec_file->f_vfsmnt) : -+ curr->filename, curr->filename, -+ NIPQUAD(fakeip), 0, type, -+ protocol, GR_CONNECT, NIPQUAD(current->curr_ip)); -+ } else if ((type == SOCK_DGRAM) && (protocol == IPPROTO_IP)) { -+ __u32 fakeip = 0; -+ security_learn(GR_IP_LEARN_MSG, current->role->rolename, -+ current->role->roletype, current->uid, -+ current->gid, current->exec_file ? -+ gr_to_filename(current->exec_file->f_dentry, -+ current->exec_file->f_vfsmnt) : -+ curr->filename, curr->filename, -+ NIPQUAD(fakeip), 0, type, -+ protocol, GR_BIND, NIPQUAD(current->curr_ip)); -+ } -+ /* we'll log when they use connect or bind */ -+ goto exit; -+ } -+ -+ security_alert(GR_SOCK_MSG, "inet", gr_socktype_to_name(type), -+ gr_proto_to_name(protocol), DEFAULTSECARGS); -+ -+ return 0; -+ exit: -+ return 1; -+} -+ -+static __inline__ int -+gr_search_connectbind(const int mode, const struct sock *sk, -+ const struct sockaddr_in *addr, const int type) -+{ -+ struct acl_subject_label *curr; -+ struct acl_ip_label *ip; -+ unsigned long i; -+ __u32 ip_addr = 0; -+ __u16 ip_port = 0; -+ -+ if (unlikely(!gr_acl_is_enabled() || sk->sk_family != PF_INET)) -+ return 1; -+ -+ curr = current->acl; -+ -+ if (!curr->ips) -+ return 1; -+ -+ ip_addr = addr->sin_addr.s_addr; -+ ip_port = ntohs(addr->sin_port); -+ -+ for (i = 0; i < curr->ip_num; i++) { -+ ip = *(curr->ips + i); -+ if ((ip->mode & mode) && -+ (ip_port >= ip->low) && -+ (ip_port <= ip->high) && -+ ((ntohl(ip_addr) & ip->netmask) == -+ (ntohl(ip->addr) & ip->netmask)) -+ && (ip-> -+ proto[sk->sk_protocol / 32] & (1 << (sk->sk_protocol % 32))) -+ && (ip->type & (1 << type))) -+ return 1; -+ } -+ -+ if (curr->mode & GR_LEARN) { -+ security_learn(GR_IP_LEARN_MSG, current->role->rolename, -+ current->role->roletype, current->uid, -+ current->gid, current->exec_file ? -+ gr_to_filename(current->exec_file->f_dentry, -+ current->exec_file->f_vfsmnt) : -+ curr->filename, curr->filename, -+ NIPQUAD(ip_addr), ip_port, type, -+ sk->sk_protocol, mode, NIPQUAD(current->curr_ip)); -+ return 1; -+ } -+ -+ if (mode == GR_BIND) -+ security_alert(GR_BIND_ACL_MSG, NIPQUAD(ip_addr), ip_port, -+ gr_socktype_to_name(type), gr_proto_to_name(sk->sk_protocol), -+ DEFAULTSECARGS); -+ else if (mode == GR_CONNECT) -+ security_alert(GR_CONNECT_ACL_MSG, NIPQUAD(ip_addr), ip_port, -+ gr_socktype_to_name(type), gr_proto_to_name(sk->sk_protocol), -+ DEFAULTSECARGS); -+ -+ return 0; -+} -+ -+int -+gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr) -+{ -+ return gr_search_connectbind(GR_CONNECT, sock->sk, addr, sock->type); -+} -+ -+int -+gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr) -+{ -+ return gr_search_connectbind(GR_BIND, sock->sk, addr, sock->type); -+} -+ -+int -+gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr) -+{ -+ if (addr) -+ return gr_search_connectbind(GR_CONNECT, sk, addr, SOCK_DGRAM); -+ else { -+ struct sockaddr_in sin; -+ const struct inet_opt *inet = inet_sk(sk); -+ -+ sin.sin_addr.s_addr = inet->daddr; -+ sin.sin_port = inet->dport; -+ -+ return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM); -+ } -+} -+ -+int -+gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb) -+{ -+ struct sockaddr_in sin; -+ -+ if (unlikely(skb->len < sizeof (struct udphdr))) -+ return 1; // skip this packet -+ -+ sin.sin_addr.s_addr = skb->nh.iph->saddr; -+ sin.sin_port = skb->h.uh->source; -+ -+ return gr_search_connectbind(GR_CONNECT, sk, &sin, SOCK_DGRAM); -+} -diff -urN linux-2.6.5/grsecurity/gracl_learn.c linux-2.6.5/grsecurity/gracl_learn.c ---- linux-2.6.5/grsecurity/gracl_learn.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/gracl_learn.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,204 @@ -+#include <linux/kernel.h> -+#include <linux/mm.h> -+#include <linux/sched.h> -+#include <linux/poll.h> -+#include <linux/smp_lock.h> -+#include <linux/string.h> -+#include <linux/file.h> -+#include <linux/types.h> -+#include <linux/vmalloc.h> -+#include <linux/grinternal.h> -+ -+extern ssize_t write_grsec_handler(struct file * file, const char * buf, -+ size_t count, loff_t *ppos); -+extern int gr_acl_is_enabled(void); -+ -+static DECLARE_WAIT_QUEUE_HEAD(learn_wait); -+static int gr_learn_attached; -+ -+/* use a 512k buffer */ -+#define LEARN_BUFFER_SIZE (512 * 1024) -+ -+static spinlock_t gr_learn_lock = SPIN_LOCK_UNLOCKED; -+static DECLARE_MUTEX(gr_learn_user_sem); -+ -+/* we need to maintain two buffers, so that the kernel context of grlearn -+ uses a semaphore around the userspace copying, and the other kernel contexts -+ use a spinlock when copying into the buffer, since they cannot sleep -+*/ -+static char *learn_buffer; -+static char *learn_buffer_user; -+static int learn_buffer_len; -+static int learn_buffer_user_len; -+ -+static ssize_t -+read_learn(struct file *file, char * buf, size_t count, loff_t * ppos) -+{ -+ DECLARE_WAITQUEUE(wait, current); -+ ssize_t retval = 0; -+ -+ add_wait_queue(&learn_wait, &wait); -+ set_current_state(TASK_INTERRUPTIBLE); -+ do { -+ down(&gr_learn_user_sem); -+ spin_lock(&gr_learn_lock); -+ if (learn_buffer_len) -+ break; -+ spin_unlock(&gr_learn_lock); -+ up(&gr_learn_user_sem); -+ if (file->f_flags & O_NONBLOCK) { -+ retval = -EAGAIN; -+ goto out; -+ } -+ if (signal_pending(current)) { -+ retval = -ERESTARTSYS; -+ goto out; -+ } -+ -+ schedule(); -+ } while (1); -+ -+ memcpy(learn_buffer_user, learn_buffer, learn_buffer_len); -+ learn_buffer_user_len = learn_buffer_len; -+ retval = learn_buffer_len; -+ learn_buffer_len = 0; -+ -+ spin_unlock(&gr_learn_lock); -+ -+ if (copy_to_user(buf, learn_buffer_user, learn_buffer_user_len)) -+ retval = -EFAULT; -+ -+ up(&gr_learn_user_sem); -+out: -+ set_current_state(TASK_RUNNING); -+ remove_wait_queue(&learn_wait, &wait); -+ return retval; -+} -+ -+static unsigned int -+poll_learn(struct file * file, poll_table * wait) -+{ -+ poll_wait(file, &learn_wait, wait); -+ -+ if (learn_buffer_len) -+ return (POLLIN | POLLRDNORM); -+ -+ return 0; -+} -+ -+void -+gr_clear_learn_entries(void) -+{ -+ char *tmp; -+ -+ down(&gr_learn_user_sem); -+ if (learn_buffer != NULL) { -+ spin_lock(&gr_learn_lock); -+ tmp = learn_buffer; -+ learn_buffer = NULL; -+ spin_unlock(&gr_learn_lock); -+ vfree(learn_buffer); -+ } -+ if (learn_buffer_user != NULL) { -+ vfree(learn_buffer_user); -+ learn_buffer_user = NULL; -+ } -+ learn_buffer_len = 0; -+ up(&gr_learn_user_sem); -+ -+ return; -+} -+ -+void -+gr_add_learn_entry(const char *fmt, ...) -+{ -+ va_list args; -+ unsigned int len; -+ -+ if (!gr_learn_attached) -+ return; -+ -+ spin_lock(&gr_learn_lock); -+ -+ /* leave a gap at the end so we know when it's "full" but don't have to -+ compute the exact length of the string we're trying to append -+ */ -+ if (learn_buffer_len > LEARN_BUFFER_SIZE - 16384) { -+ spin_unlock(&gr_learn_lock); -+ wake_up_interruptible(&learn_wait); -+ return; -+ } -+ if (learn_buffer == NULL) { -+ spin_unlock(&gr_learn_lock); -+ return; -+ } -+ -+ va_start(args, fmt); -+ len = vsnprintf(learn_buffer + learn_buffer_len, LEARN_BUFFER_SIZE - learn_buffer_len, fmt, args); -+ va_end(args); -+ -+ learn_buffer_len += len + 1; -+ -+ spin_unlock(&gr_learn_lock); -+ wake_up_interruptible(&learn_wait); -+ -+ return; -+} -+ -+static int -+open_learn(struct inode *inode, struct file *file) -+{ -+ if (file->f_mode & FMODE_READ && gr_learn_attached) -+ return -EBUSY; -+ if (file->f_mode & FMODE_READ) { -+ down(&gr_learn_user_sem); -+ if (learn_buffer == NULL) -+ learn_buffer = vmalloc(LEARN_BUFFER_SIZE); -+ if (learn_buffer_user == NULL) -+ learn_buffer_user = vmalloc(LEARN_BUFFER_SIZE); -+ if (learn_buffer == NULL) -+ return -ENOMEM; -+ if (learn_buffer_user == NULL) -+ return -ENOMEM; -+ learn_buffer_len = 0; -+ learn_buffer_user_len = 0; -+ gr_learn_attached = 1; -+ up(&gr_learn_user_sem); -+ } -+ return 0; -+} -+ -+static int -+close_learn(struct inode *inode, struct file *file) -+{ -+ char *tmp; -+ -+ if (file->f_mode & FMODE_READ) { -+ down(&gr_learn_user_sem); -+ if (learn_buffer != NULL) { -+ spin_lock(&gr_learn_lock); -+ tmp = learn_buffer; -+ learn_buffer = NULL; -+ spin_unlock(&gr_learn_lock); -+ vfree(tmp); -+ } -+ if (learn_buffer_user != NULL) { -+ vfree(learn_buffer_user); -+ learn_buffer_user = NULL; -+ } -+ learn_buffer_len = 0; -+ learn_buffer_user_len = 0; -+ gr_learn_attached = 0; -+ up(&gr_learn_user_sem); -+ } -+ -+ return 0; -+} -+ -+struct file_operations grsec_fops = { -+ read: read_learn, -+ write: write_grsec_handler, -+ open: open_learn, -+ release: close_learn, -+ poll: poll_learn, -+}; -diff -urN linux-2.6.5/grsecurity/gracl_res.c linux-2.6.5/grsecurity/gracl_res.c ---- linux-2.6.5/grsecurity/gracl_res.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/gracl_res.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,50 @@ -+/* resource handling routines (c) Brad Spengler 2002, 2003 */ -+ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/gracl.h> -+#include <linux/grinternal.h> -+ -+static const char *restab_log[11] = { -+ "RLIMIT_CPU", -+ "RLIMIT_FSIZE", -+ "RLIMIT_DATA", -+ "RLIMIT_STACK", -+ "RLIMIT_CORE", -+ "RLIMIT_RSS", -+ "RLIMIT_NPROC", -+ "RLIMIT_NOFILE", -+ "RLIMIT_MEMLOCK", -+ "RLIMIT_AS", -+ "RLIMIT_LOCKS" -+}; -+ -+__inline__ void -+gr_log_resource(const struct task_struct *task, -+ const int res, const unsigned long wanted, const int gt) -+{ -+ if (unlikely(res == RLIMIT_NPROC && -+ (cap_raised(task->cap_effective, CAP_SYS_ADMIN) || -+ cap_raised(task->cap_effective, CAP_SYS_RESOURCE)))) -+ return; -+ -+ preempt_disable(); -+ -+ if (unlikely(((gt && wanted > task->rlim[res].rlim_cur) || -+ (!gt && wanted >= task->rlim[res].rlim_cur)) && -+ task->rlim[res].rlim_cur != RLIM_INFINITY)) -+ security_alert(GR_RESOURCE_MSG, wanted, restab_log[res], -+ task->rlim[res].rlim_cur, -+ 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); -+ -+ preempt_enable_no_resched(); -+ -+ return; -+} -diff -urN linux-2.6.5/grsecurity/gracl_segv.c linux-2.6.5/grsecurity/gracl_segv.c ---- linux-2.6.5/grsecurity/gracl_segv.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/gracl_segv.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,330 @@ -+/* -+ * grsecurity/gracl_segv.c -+ * Copyright Brad Spengler 2002, 2003 -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/mm.h> -+#include <asm/uaccess.h> -+#include <asm/errno.h> -+#include <asm/mman.h> -+#include <net/sock.h> -+#include <linux/file.h> -+#include <linux/fs.h> -+#include <linux/net.h> -+#include <linux/in.h> -+#include <linux/smp_lock.h> -+#include <linux/slab.h> -+#include <linux/types.h> -+#include <linux/sched.h> -+#include <linux/timer.h> -+#include <linux/gracl.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+static struct crash_uid *uid_set; -+static unsigned short uid_used; -+static rwlock_t gr_uid_lock = RW_LOCK_UNLOCKED; -+extern rwlock_t gr_inode_lock; -+extern struct acl_subject_label * -+ lookup_acl_subj_label(const ino_t inode, const dev_t dev, -+ struct acl_role_label *role); -+extern int specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t); -+ -+int -+gr_init_uidset(void) -+{ -+ uid_set = -+ kmalloc(GR_UIDTABLE_MAX * sizeof (struct crash_uid), GFP_KERNEL); -+ uid_used = 0; -+ -+ return uid_set ? 1 : 0; -+} -+ -+void -+gr_free_uidset(void) -+{ -+ if (uid_set) -+ kfree(uid_set); -+ -+ return; -+} -+ -+int -+gr_find_uid(const uid_t uid) -+{ -+ struct crash_uid *tmp = uid_set; -+ uid_t buid; -+ int low = 0, high = uid_used - 1, mid; -+ -+ while (high >= low) { -+ mid = (low + high) >> 1; -+ buid = tmp[mid].uid; -+ if (buid == uid) -+ return mid; -+ if (buid > uid) -+ high = mid - 1; -+ if (buid < uid) -+ low = mid + 1; -+ } -+ -+ return -1; -+} -+ -+static __inline__ void -+gr_insertsort(void) -+{ -+ unsigned short i, j; -+ struct crash_uid index; -+ -+ for (i = 1; i < uid_used; i++) { -+ index = uid_set[i]; -+ j = i; -+ while ((j > 0) && uid_set[j - 1].uid > index.uid) { -+ uid_set[j] = uid_set[j - 1]; -+ j--; -+ } -+ uid_set[j] = index; -+ } -+ -+ return; -+} -+ -+static __inline__ void -+gr_insert_uid(const uid_t uid, const unsigned long expires) -+{ -+ int loc; -+ -+ if (uid_used == GR_UIDTABLE_MAX) -+ return; -+ -+ loc = gr_find_uid(uid); -+ -+ if (loc >= 0) { -+ uid_set[loc].expires = expires; -+ return; -+ } -+ -+ uid_set[uid_used].uid = uid; -+ uid_set[uid_used].expires = expires; -+ uid_used++; -+ -+ gr_insertsort(); -+ -+ return; -+} -+ -+void -+gr_remove_uid(const unsigned short loc) -+{ -+ unsigned short i; -+ -+ for (i = loc + 1; i < uid_used; i++) -+ uid_set[i - i] = uid_set[i]; -+ -+ uid_used--; -+ -+ return; -+} -+ -+int -+gr_check_crash_uid(const uid_t uid) -+{ -+ int loc; -+ -+ if (unlikely(!gr_acl_is_enabled())) -+ return 0; -+ -+ read_lock(&gr_uid_lock); -+ loc = gr_find_uid(uid); -+ read_unlock(&gr_uid_lock); -+ -+ if (loc < 0) -+ return 0; -+ -+ write_lock(&gr_uid_lock); -+ if (time_before_eq(uid_set[loc].expires, get_seconds())) -+ gr_remove_uid(loc); -+ else { -+ write_unlock(&gr_uid_lock); -+ return 1; -+ } -+ -+ write_unlock(&gr_uid_lock); -+ return 0; -+} -+ -+static __inline__ int -+proc_is_setxid(const struct task_struct *task) -+{ -+ if (task->uid != task->euid || task->uid != task->suid || -+ task->uid != task->fsuid) -+ return 1; -+ if (task->gid != task->egid || task->gid != task->sgid || -+ task->gid != task->fsgid) -+ return 1; -+ -+ return 0; -+} -+static __inline__ int -+gr_fake_force_sig(int sig, struct task_struct *t) -+{ -+ unsigned long int flags; -+ int ret; -+ -+ spin_lock_irqsave(&t->sighand->siglock, flags); -+ if (sigismember(&t->blocked, sig) || t->sighand->action[sig-1].sa.sa_handler == SIG_IGN) { -+ t->sighand->action[sig-1].sa.sa_handler = SIG_DFL; -+ sigdelset(&t->blocked, sig); -+ recalc_sigpending_tsk(t); -+ } -+ ret = specific_send_sig_info(sig, (void*)1L, t); -+ spin_unlock_irqrestore(&t->sighand->siglock, flags); -+ -+ return ret; -+} -+ -+void -+gr_handle_crash(struct task_struct *task, const int sig) -+{ -+ struct acl_subject_label *curr; -+ struct acl_subject_label *curr2; -+ struct task_struct *tsk, *tsk2; -+ -+ if (sig != SIGSEGV && sig != SIGKILL && sig != SIGBUS && sig != SIGILL) -+ return; -+ -+ if (unlikely(!gr_acl_is_enabled())) -+ return; -+ -+ curr = task->acl; -+ -+ if (!(curr->resmask & (1 << GR_CRASH_RES))) -+ return; -+ -+ if (time_before_eq(curr->expires, get_seconds())) { -+ curr->expires = 0; -+ curr->crashes = 0; -+ } -+ -+ curr->crashes++; -+ -+ if (!curr->expires) -+ curr->expires = get_seconds() + curr->res[GR_CRASH_RES].rlim_max; -+ -+ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) && -+ time_after(curr->expires, get_seconds())) { -+ if (task->uid && proc_is_setxid(task)) { -+ security_alert(GR_SEGVSTART_ACL_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, -+ curr->res[GR_CRASH_RES].rlim_max); -+ write_lock(&gr_uid_lock); -+ gr_insert_uid(task->uid, curr->expires); -+ write_unlock(&gr_uid_lock); -+ curr->expires = 0; -+ curr->crashes = 0; -+ read_lock(&tasklist_lock); -+ for_each_process(tsk) { -+ tsk2 = tsk; -+ do { -+ if (tsk2 != task && tsk2->uid == task->uid) -+ gr_fake_force_sig(SIGKILL, tsk2); -+ } while ((tsk2 = next_thread(tsk2)) != tsk); -+ } -+ read_unlock(&tasklist_lock); -+ } else { -+ security_alert(GR_SEGVNOSUID_ACL_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, -+ curr->res[GR_CRASH_RES].rlim_max); -+ read_lock(&tasklist_lock); -+ for_each_process(tsk) { -+ tsk2 = tsk; -+ do { -+ if (likely(tsk2 != task)) { -+ curr2 = tsk2->acl; -+ -+ if (curr2->device == curr->device && -+ curr2->inode == curr->inode) -+ gr_fake_force_sig(SIGKILL, tsk2); -+ } -+ } while ((tsk2 = next_thread(tsk2)) != tsk); -+ } -+ read_unlock(&tasklist_lock); -+ } -+ } -+ -+ return; -+} -+ -+int -+gr_check_crash_exec(const struct file *filp) -+{ -+ struct acl_subject_label *curr; -+ -+ if (unlikely(!gr_acl_is_enabled())) -+ return 0; -+ -+ read_lock(&gr_inode_lock); -+ curr = lookup_acl_subj_label(filp->f_dentry->d_inode->i_ino, -+ filp->f_dentry->d_inode->i_sb->s_dev, -+ current->role); -+ read_unlock(&gr_inode_lock); -+ -+ if (!curr || !(curr->resmask & (1 << GR_CRASH_RES)) || -+ (!curr->crashes && !curr->expires)) -+ return 0; -+ -+ if ((curr->crashes >= curr->res[GR_CRASH_RES].rlim_cur) && -+ time_after(curr->expires, get_seconds())) -+ return 1; -+ else if (time_before_eq(curr->expires, get_seconds())) { -+ curr->crashes = 0; -+ curr->expires = 0; -+ } -+ -+ return 0; -+} -+ -+void -+gr_handle_alertkill(void) -+{ -+ struct acl_subject_label *curracl; -+ __u32 curr_ip; -+ struct task_struct *task, *task2; -+ -+ if (unlikely(!gr_acl_is_enabled())) -+ return; -+ -+ curracl = current->acl; -+ curr_ip = current->curr_ip; -+ -+ if ((curracl->mode & GR_KILLIPPROC) && curr_ip && -+ (curr_ip != 0xffffffff)) { -+ read_lock(&tasklist_lock); -+ for_each_process(task) { -+ task2 = task; -+ do { -+ if (task2->curr_ip == curr_ip) -+ gr_fake_force_sig(SIGKILL, task2); -+ } while ((task2 = next_thread(task2)) != task); -+ } -+ read_unlock(&tasklist_lock); -+ } else if (curracl->mode & GR_KILLPROC) -+ gr_fake_force_sig(SIGKILL, current); -+ -+ return; -+} -diff -urN linux-2.6.5/grsecurity/gracl_shm.c linux-2.6.5/grsecurity/gracl_shm.c ---- linux-2.6.5/grsecurity/gracl_shm.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/gracl_shm.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,36 @@ -+/* shared memory handling routines, (c) Brad Spengler 2002, 2003 */ -+ -+#include <linux/kernel.h> -+#include <linux/mm.h> -+#include <linux/sched.h> -+#include <linux/file.h> -+#include <linux/ipc.h> -+#include <linux/gracl.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+int -+gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid, -+ const time_t shm_createtime, const uid_t cuid, const int shmid) -+{ -+ struct task_struct *task; -+ -+ if (!gr_acl_is_enabled()) -+ return 1; -+ -+ task = find_task_by_pid(shm_cprid); -+ -+ if (unlikely(!task)) -+ task = find_task_by_pid(shm_lapid); -+ -+ if (unlikely(task && ((task->start_time < shm_createtime) || -+ (task->pid == shm_lapid)) && -+ (task->acl->mode & GR_PROTSHM) && -+ (task->acl != current->acl))) { -+ security_alert(GR_SHMAT_ACL_MSG, cuid, shm_cprid, shmid, -+ DEFAULTSECARGS); -+ return 0; -+ } -+ -+ return 1; -+} -diff -urN linux-2.6.5/grsecurity/grsec_chdir.c linux-2.6.5/grsecurity/grsec_chdir.c ---- linux-2.6.5/grsecurity/grsec_chdir.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_chdir.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,20 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/fs.h> -+#include <linux/file.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+void -+gr_log_chdir(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR -+ if ((grsec_enable_chdir && grsec_enable_group && -+ in_group_p(grsec_audit_gid)) || (grsec_enable_chdir && -+ !grsec_enable_group)) { -+ security_audit(GR_CHDIR_AUDIT_MSG, gr_to_filename(dentry, mnt), -+ DEFAULTSECARGS); -+ } -+#endif -+ return; -+} -diff -urN linux-2.6.5/grsecurity/grsec_chroot.c linux-2.6.5/grsecurity/grsec_chroot.c ---- linux-2.6.5/grsecurity/grsec_chroot.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_chroot.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,348 @@ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/sched.h> -+#include <linux/file.h> -+#include <linux/fs.h> -+#include <linux/mount.h> -+#include <linux/types.h> -+#include <linux/grinternal.h> -+ -+int -+gr_handle_chroot_unix(const pid_t pid) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX -+ struct pid *spid = NULL; -+ -+ if (unlikely(!grsec_enable_chroot_unix)) -+ return 1; -+ -+ if (likely(!proc_is_chrooted(current))) -+ return 1; -+ -+ read_lock(&tasklist_lock); -+ -+ spid = find_pid(PIDTYPE_PID, pid); -+ if (spid) { -+ struct task_struct *p; -+ p = pid_task(spid->task_list.next, PIDTYPE_PID); -+ if (unlikely(!have_same_root(current, p))) { -+ read_unlock(&tasklist_lock); -+ security_alert(GR_UNIX_CHROOT_MSG, DEFAULTSECARGS); -+ return 0; -+ } -+ } -+ read_unlock(&tasklist_lock); -+#endif -+ return 1; -+} -+ -+int -+gr_handle_chroot_nice(void) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE -+ if (grsec_enable_chroot_nice && proc_is_chrooted(current)) { -+ security_alert(GR_NICE_CHROOT_MSG, DEFAULTSECARGS); -+ return -EPERM; -+ } -+#endif -+ return 0; -+} -+ -+int -+gr_handle_chroot_setpriority(struct task_struct *p, const int niceval) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE -+ if (grsec_enable_chroot_nice && (!have_same_root(p, current) -+ || (have_same_root(p, current) -+ && (niceval < task_nice(p)) -+ && proc_is_chrooted(current)))) { -+ security_alert(GR_PRIORITY_CHROOT_MSG, p->comm, p->pid, -+ DEFAULTSECARGS); -+ return -ESRCH; -+ } -+#endif -+ return 0; -+} -+ -+int -+gr_handle_chroot_capset(const struct task_struct *target) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS -+ if (grsec_enable_chroot_caps && proc_is_chrooted(current) && -+ !have_same_root(current, target)) { -+ security_alert(GR_CAPSET_CHROOT_MSG, target->comm, target->pid, -+ DEFAULTSECARGS); -+ return 1; -+ } -+#endif -+ return 0; -+} -+ -+int -+gr_handle_chroot_rawio(const struct inode *inode) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS -+ if (grsec_enable_chroot_caps && proc_is_chrooted(current) && -+ inode && S_ISBLK(inode->i_mode) && !capable(CAP_SYS_RAWIO)) -+ return 1; -+#endif -+ return 0; -+} -+ -+int -+gr_pid_is_chrooted(const struct task_struct *p) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK -+ if (!grsec_enable_chroot_findtask || (current->pid <= 1)) -+ return 0; -+ -+ if (p && p->fs && p->fs->root && p->fs->root->d_inode && -+ child_reaper && child_reaper->fs && child_reaper->fs->root && -+ child_reaper->fs->root->d_inode && current && current->fs && -+ current->fs->root && current->fs->root->d_inode) { -+ if (proc_is_chrooted(current) && !have_same_root(current, p)) -+ return 1; -+ } -+#endif -+ return 0; -+} -+ -+EXPORT_SYMBOL(gr_pid_is_chrooted); -+ -+#if defined(CONFIG_GRKERNSEC_CHROOT_DOUBLE) || defined(CONFIG_GRKERNSEC_CHROOT_FCHDIR) -+int gr_is_outside_chroot(const struct dentry *u_dentry, const struct vfsmount *u_mnt) -+{ -+ struct dentry *dentry = (struct dentry *)u_dentry; -+ struct vfsmount *mnt = (struct vfsmount *)u_mnt; -+ struct dentry *realroot; -+ struct vfsmount *realrootmnt; -+ struct dentry *currentroot; -+ struct vfsmount *currentmnt; -+ -+ read_lock(&child_reaper->fs->lock); -+ realrootmnt = mntget(child_reaper->fs->rootmnt); -+ realroot = dget(child_reaper->fs->root); -+ read_unlock(&child_reaper->fs->lock); -+ -+ read_lock(¤t->fs->lock); -+ currentmnt = mntget(current->fs->rootmnt); -+ currentroot = dget(current->fs->root); -+ read_unlock(¤t->fs->lock); -+ -+ spin_lock(&dcache_lock); -+ for (;;) { -+ if (unlikely((dentry == realroot && mnt == realrootmnt) -+ || (dentry == currentroot && mnt == currentmnt))) -+ break; -+ if (unlikely(dentry == mnt->mnt_root || IS_ROOT(dentry))) { -+ if (mnt->mnt_parent == mnt) -+ break; -+ dentry = mnt->mnt_mountpoint; -+ mnt = mnt->mnt_parent; -+ continue; -+ } -+ dentry = dentry->d_parent; -+ } -+ spin_unlock(&dcache_lock); -+ -+ dput(currentroot); -+ mntput(currentmnt); -+ -+ if (dentry == realroot && mnt == realrootmnt) { -+ /* access is outside of chroot */ -+ dput(realroot); -+ mntput(realrootmnt); -+ return 0; -+ } -+ -+ dput(realroot); -+ mntput(realrootmnt); -+ return 1; -+} -+#endif -+ -+int -+gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR -+ if (!grsec_enable_chroot_fchdir) -+ return 1; -+ -+ if (!proc_is_chrooted(current)) -+ return 1; -+ else if (!gr_is_outside_chroot(u_dentry, u_mnt)) { -+ security_alert(GR_CHROOT_FCHDIR_MSG, -+ gr_to_filename(u_dentry, u_mnt), -+ DEFAULTSECARGS); -+ return 0; -+ } -+#endif -+ return 1; -+} -+ -+int -+gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid, -+ const time_t shm_createtime) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT -+ struct pid *pid = NULL; -+ u64 starttime64; -+ time_t starttime; -+ -+ if (unlikely(!grsec_enable_chroot_shmat)) -+ return 1; -+ -+ if (likely(!proc_is_chrooted(current))) -+ return 1; -+ -+ read_lock(&tasklist_lock); -+ -+ pid = find_pid(PIDTYPE_PID, shm_cprid); -+ if (pid) { -+ struct task_struct *p; -+ p = pid_task(pid->task_list.next, PIDTYPE_PID); -+ starttime64 = p->start_time; -+ do_div(starttime64, HZ); -+ starttime = (time_t) starttime64; -+ if (unlikely(!have_same_root(current, p) && -+ time_before((unsigned long)starttime, (unsigned long)shm_createtime))) { -+ read_unlock(&tasklist_lock); -+ security_alert(GR_SHMAT_CHROOT_MSG, DEFAULTSECARGS); -+ return 0; -+ } -+ } else { -+ pid = find_pid(PIDTYPE_PID, shm_lapid); -+ if (pid) { -+ struct task_struct *p; -+ p = pid_task(pid->task_list.next, PIDTYPE_PID); -+ if (unlikely(!have_same_root(current, p))) { -+ read_unlock(&tasklist_lock); -+ security_alert(GR_SHMAT_CHROOT_MSG, DEFAULTSECARGS); -+ return 0; -+ } -+ } -+ } -+ -+ read_unlock(&tasklist_lock); -+#endif -+ return 1; -+} -+ -+void -+gr_log_chroot_exec(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG -+ if (grsec_enable_chroot_execlog && proc_is_chrooted(current)) -+ security_audit(GR_EXEC_CHROOT_MSG, gr_to_filename(dentry, mnt), -+ DEFAULTSECARGS); -+#endif -+ return; -+} -+ -+int -+gr_handle_chroot_mknod(const struct dentry *dentry, -+ const struct vfsmount *mnt, const int mode) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD -+ if (grsec_enable_chroot_mknod && !S_ISFIFO(mode) && !S_ISREG(mode) && -+ proc_is_chrooted(current)) { -+ security_alert(GR_MKNOD_CHROOT_MSG, -+ gr_to_filename(dentry, mnt), DEFAULTSECARGS); -+ return -EPERM; -+ } -+#endif -+ return 0; -+} -+ -+int -+gr_handle_chroot_mount(const struct dentry *dentry, -+ const struct vfsmount *mnt, const char *dev_name) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT -+ if (grsec_enable_chroot_mount && proc_is_chrooted(current)) { -+ security_alert(GR_MOUNT_CHROOT_MSG, dev_name, -+ gr_to_filename(dentry, mnt), DEFAULTSECARGS); -+ return -EPERM; -+ } -+#endif -+ return 0; -+} -+ -+int -+gr_handle_chroot_pivot(void) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT -+ if (grsec_enable_chroot_pivot && proc_is_chrooted(current)) { -+ security_alert(GR_PIVOT_CHROOT_MSG, DEFAULTSECARGS); -+ return -EPERM; -+ } -+#endif -+ return 0; -+} -+ -+int -+gr_handle_chroot_chroot(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE -+ if (grsec_enable_chroot_double && proc_is_chrooted(current) && -+ !gr_is_outside_chroot(dentry, mnt)) { -+ security_alert(GR_CHROOT_CHROOT_MSG, -+ gr_to_filename(dentry, mnt), DEFAULTSECARGS); -+ return -EPERM; -+ } -+#endif -+ return 0; -+} -+ -+void -+gr_handle_chroot_caps(struct task_struct *task) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS -+ if (grsec_enable_chroot_caps && proc_is_chrooted(task)) { -+ task->cap_permitted = -+ cap_drop(task->cap_permitted, GR_CHROOT_CAPS); -+ task->cap_inheritable = -+ cap_drop(task->cap_inheritable, GR_CHROOT_CAPS); -+ task->cap_effective = -+ cap_drop(task->cap_effective, GR_CHROOT_CAPS); -+ } -+#endif -+ return; -+} -+ -+int -+gr_handle_chroot_sysctl(const int op) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL -+ if (grsec_enable_chroot_sysctl && proc_is_chrooted(current) -+ && (op & 002)) -+ return -EACCES; -+#endif -+ return 0; -+} -+ -+void -+gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR -+ if (grsec_enable_chroot_chdir) -+ set_fs_pwd(current->fs, mnt, dentry); -+#endif -+ return; -+} -+ -+int -+gr_handle_chroot_chmod(const struct dentry *dentry, -+ const struct vfsmount *mnt, const int mode) -+{ -+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD -+ if (grsec_enable_chroot_chmod && -+ ((mode & S_ISUID) || (mode & S_ISGID)) && -+ proc_is_chrooted(current)) { -+ security_alert(GR_CHMOD_CHROOT_MSG, -+ gr_to_filename(dentry, mnt), DEFAULTSECARGS); -+ return -EPERM; -+ } -+#endif -+ return 0; -+} -diff -urN linux-2.6.5/grsecurity/grsec_disabled.c linux-2.6.5/grsecurity/grsec_disabled.c ---- linux-2.6.5/grsecurity/grsec_disabled.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_disabled.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,406 @@ -+/* -+ * when grsecurity is disabled, compile all external functions into nothing -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/config.h> -+#include <linux/sched.h> -+#include <linux/file.h> -+#include <linux/fs.h> -+#include <linux/kdev_t.h> -+#include <linux/net.h> -+#include <linux/in.h> -+#include <linux/ip.h> -+#include <linux/skbuff.h> -+#include <linux/sysctl.h> -+ -+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS -+__inline__ void -+pax_set_flags(struct linux_binprm *bprm) -+{ -+ return; -+} -+#endif -+ -+#ifdef CONFIG_SYSCTL -+__inline__ __u32 -+gr_handle_sysctl(const struct ctl_table * table, __u32 mode) -+{ -+ return mode; -+} -+#endif -+ -+__inline__ int -+gr_acl_is_enabled(void) -+{ -+ return 0; -+} -+ -+__inline__ int -+gr_handle_rawio(const struct inode *inode) -+{ -+ return 0; -+} -+ -+__inline__ void -+gr_acl_handle_psacct(struct task_struct *task, const long code) -+{ -+ return; -+} -+ -+__inline__ int -+gr_handle_ptrace_exec(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ return 0; -+} -+ -+__inline__ int -+gr_handle_mmap(const struct file *filp, const unsigned long prot) -+{ -+ return 0; -+} -+ -+__inline__ int -+gr_handle_ptrace(struct task_struct *task, const long request) -+{ -+ return 0; -+} -+ -+__inline__ int -+gr_handle_proc_ptrace(struct task_struct *task) -+{ -+ return 0; -+} -+ -+__inline__ void -+gr_learn_resource(const struct task_struct *task, -+ const int res, const unsigned long wanted, const int gt) -+{ -+ return; -+} -+ -+__inline__ int -+gr_set_acls(const int type) -+{ -+ return 0; -+} -+ -+__inline__ int -+gr_check_hidden_task(const struct task_struct *tsk) -+{ -+ return 0; -+} -+ -+__inline__ int -+gr_check_protected_task(const struct task_struct *task) -+{ -+ return 0; -+} -+ -+__inline__ void -+gr_copy_label(struct task_struct *tsk) -+{ -+ return; -+} -+ -+__inline__ void -+gr_set_pax_flags(struct task_struct *task) -+{ -+ return; -+} -+ -+__inline__ void -+gr_set_proc_label(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ return; -+} -+ -+__inline__ void -+gr_handle_delete(const ino_t ino, const dev_t dev) -+{ -+ return; -+} -+ -+__inline__ void -+gr_handle_create(const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+ return; -+} -+ -+__inline__ void -+gr_handle_crash(struct task_struct *task, const int sig) -+{ -+ return; -+} -+ -+__inline__ int -+gr_check_crash_exec(const struct file *filp) -+{ -+ return 0; -+} -+ -+__inline__ int -+gr_check_crash_uid(const uid_t uid) -+{ -+ return 0; -+} -+ -+__inline__ void -+gr_handle_rename(struct inode *old_dir, struct inode *new_dir, -+ struct dentry *old_dentry, -+ struct dentry *new_dentry, -+ struct vfsmount *mnt, const __u8 replace) -+{ -+ return; -+} -+ -+__inline__ int -+gr_search_socket(const int family, const int type, const int protocol) -+{ -+ return 1; -+} -+ -+__inline__ int -+gr_search_connectbind(const int mode, const struct socket *sock, -+ const struct sockaddr_in *addr) -+{ -+ return 1; -+} -+ -+__inline__ int -+gr_task_is_capable(struct task_struct *task, const int cap) -+{ -+ return 1; -+} -+ -+__inline__ int -+gr_is_capable_nolog(const int cap) -+{ -+ return 1; -+} -+ -+__inline__ void -+gr_handle_alertkill(void) -+{ -+ return; -+} -+ -+__inline__ __u32 -+gr_acl_handle_execve(const struct dentry * dentry, const struct vfsmount * mnt) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_hidden_file(const struct dentry * dentry, -+ const struct vfsmount * mnt) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_open(const struct dentry * dentry, const struct vfsmount * mnt, -+ const int fmode) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_rmdir(const struct dentry * dentry, const struct vfsmount * mnt) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_unlink(const struct dentry * dentry, const struct vfsmount * mnt) -+{ -+ return 1; -+} -+ -+__inline__ int -+gr_acl_handle_mmap(const struct file *file, const unsigned long prot, -+ unsigned int *vm_flags) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_truncate(const struct dentry * dentry, -+ const struct vfsmount * mnt) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_utime(const struct dentry * dentry, const struct vfsmount * mnt) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_access(const struct dentry * dentry, -+ const struct vfsmount * mnt, const int fmode) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_fchmod(const struct dentry * dentry, const struct vfsmount * mnt, -+ mode_t mode) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_chmod(const struct dentry * dentry, const struct vfsmount * mnt, -+ mode_t mode) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_chown(const struct dentry * dentry, const struct vfsmount * mnt) -+{ -+ return 1; -+} -+ -+__inline__ void -+grsecurity_init(void) -+{ -+ return; -+} -+ -+__inline__ __u32 -+gr_acl_handle_mknod(const struct dentry * new_dentry, -+ const struct dentry * parent_dentry, -+ const struct vfsmount * parent_mnt, -+ const int mode) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_mkdir(const struct dentry * new_dentry, -+ const struct dentry * parent_dentry, -+ const struct vfsmount * parent_mnt) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_symlink(const struct dentry * new_dentry, -+ const struct dentry * parent_dentry, -+ const struct vfsmount * parent_mnt, const char *from) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_link(const struct dentry * new_dentry, -+ const struct dentry * parent_dentry, -+ const struct vfsmount * parent_mnt, -+ const struct dentry * old_dentry, -+ const struct vfsmount * old_mnt, const char *to) -+{ -+ return 1; -+} -+ -+__inline__ int -+gr_acl_handle_rename(const struct dentry *new_dentry, -+ const struct dentry *parent_dentry, -+ const struct vfsmount *parent_mnt, -+ const struct dentry *old_dentry, -+ const struct inode *old_parent_inode, -+ const struct vfsmount *old_mnt, const char *newname) -+{ -+ return 0; -+} -+ -+__inline__ __u32 -+gr_acl_handle_filldir(const struct dentry * dentry, -+ const struct vfsmount * mnt, const ino_t ino) -+{ -+ return 1; -+} -+ -+__inline__ int -+gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid, -+ const time_t shm_createtime, const uid_t cuid, const int shmid) -+{ -+ return 1; -+} -+ -+__inline__ int -+gr_search_bind(const struct socket *sock, const struct sockaddr_in *addr) -+{ -+ return 1; -+} -+ -+__inline__ int -+gr_search_connect(const struct socket *sock, const struct sockaddr_in *addr) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_unix(const struct dentry * dentry, const struct vfsmount * mnt) -+{ -+ return 1; -+} -+ -+__inline__ __u32 -+gr_acl_handle_creat(const struct dentry * dentry, -+ const struct dentry * p_dentry, -+ const struct vfsmount * p_mnt, const int fmode, -+ const int imode) -+{ -+ return 1; -+} -+ -+__inline__ void -+gr_acl_handle_exit(void) -+{ -+ return; -+} -+ -+__inline__ int -+gr_acl_handle_mprotect(const struct file *file, const unsigned long prot) -+{ -+ return 1; -+} -+ -+__inline__ void -+gr_set_role_label(const uid_t uid, const gid_t gid) -+{ -+ return; -+} -+ -+__inline__ int -+gr_acl_handle_procpidmem(const struct task_struct *task) -+{ -+ return 0; -+} -+ -+__inline__ int -+gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb) -+{ -+ return 1; -+} -+ -+__inline__ int -+gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr) -+{ -+ return 1; -+} -+ -+__inline__ void -+gr_set_kernel_label(struct task_struct *task) -+{ -+ return; -+} -+ -+EXPORT_SYMBOL(gr_task_is_capable); -+EXPORT_SYMBOL(gr_learn_resource); -+EXPORT_SYMBOL(gr_set_kernel_label); -+ -diff -urN linux-2.6.5/grsecurity/grsec_exec.c linux-2.6.5/grsecurity/grsec_exec.c ---- linux-2.6.5/grsecurity/grsec_exec.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_exec.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,71 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/file.h> -+#include <linux/binfmts.h> -+#include <linux/fs.h> -+#include <linux/types.h> -+#include <linux/grdefs.h> -+#include <linux/grinternal.h> -+#include <linux/capability.h> -+ -+#include <asm/uaccess.h> -+ -+int -+gr_handle_nproc(void) -+{ -+#ifdef CONFIG_GRKERNSEC_EXECVE -+ if (grsec_enable_execve && current->user && -+ (atomic_read(¤t->user->processes) > -+ current->rlim[RLIMIT_NPROC].rlim_cur) && -+ !capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE)) { -+ security_alert(GR_NPROC_MSG, DEFAULTSECARGS); -+ return -EAGAIN; -+ } -+#endif -+ return 0; -+} -+ -+void -+gr_handle_exec_args(struct linux_binprm *bprm, char **argv) -+{ -+#ifdef CONFIG_GRKERNSEC_EXECLOG -+ char grarg[64] = { 0 }; -+ __u8 execlen = 0; -+ unsigned int i; -+ -+ if (!((grsec_enable_execlog && grsec_enable_group && -+ in_group_p(grsec_audit_gid)) -+ || (grsec_enable_execlog && !grsec_enable_group))) -+ return; -+ -+ if (unlikely(!argv)) -+ goto log; -+ -+ for (i = 0; i < bprm->argc && execlen < 62; i++) { -+ char *p; -+ __u8 len; -+ -+ if (get_user(p, argv + i)) -+ goto log; -+ if (!p) -+ goto log; -+ len = strnlen_user(p, 62 - execlen); -+ if (len > 62 - execlen) -+ len = 62 - execlen; -+ else if (len > 0) -+ len--; -+ if (copy_from_user(grarg + execlen, p, len)) -+ goto log; -+ execlen += len; -+ *(grarg + execlen) = ' '; -+ *(grarg + execlen + 1) = '\0'; -+ execlen++; -+ } -+ -+ log: -+ security_audit(GR_EXEC_AUDIT_MSG, gr_to_filename(bprm->file->f_dentry, -+ bprm->file->f_vfsmnt), -+ grarg, DEFAULTSECARGS); -+#endif -+ return; -+} -diff -urN linux-2.6.5/grsecurity/grsec_fifo.c linux-2.6.5/grsecurity/grsec_fifo.c ---- linux-2.6.5/grsecurity/grsec_fifo.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_fifo.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,24 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/fs.h> -+#include <linux/file.h> -+#include <linux/grinternal.h> -+ -+int -+gr_handle_fifo(const struct dentry *dentry, const struct vfsmount *mnt, -+ const struct dentry *dir, const int flag, const int acc_mode) -+{ -+#ifdef CONFIG_GRKERNSEC_FIFO -+ if (grsec_enable_fifo && S_ISFIFO(dentry->d_inode->i_mode) && -+ !(flag & O_EXCL) && (dir->d_inode->i_mode & S_ISVTX) && -+ (dentry->d_inode->i_uid != dir->d_inode->i_uid) && -+ (current->fsuid != dentry->d_inode->i_uid)) { -+ if (!vfs_permission(dentry->d_inode, acc_mode)) -+ security_alert(GR_FIFO_MSG, gr_to_filename(dentry, mnt), -+ dentry->d_inode->i_uid, -+ dentry->d_inode->i_gid, DEFAULTSECARGS); -+ return -EACCES; -+ } -+#endif -+ return 0; -+} -diff -urN linux-2.6.5/grsecurity/grsec_fork.c linux-2.6.5/grsecurity/grsec_fork.c ---- linux-2.6.5/grsecurity/grsec_fork.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_fork.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,14 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+void -+gr_log_forkfail(const int retval) -+{ -+#ifdef CONFIG_GRKERNSEC_FORKFAIL -+ if (grsec_enable_forkfail) -+ security_alert(GR_FAILFORK_MSG, retval, DEFAULTSECARGS); -+#endif -+ return; -+} -diff -urN linux-2.6.5/grsecurity/grsec_init.c linux-2.6.5/grsecurity/grsec_init.c ---- linux-2.6.5/grsecurity/grsec_init.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_init.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,227 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/mm.h> -+#include <linux/smp_lock.h> -+#include <linux/gracl.h> -+#include <linux/slab.h> -+#include <linux/vmalloc.h> -+#include <linux/percpu.h> -+ -+int grsec_enable_link; -+int grsec_enable_dmesg; -+int grsec_enable_fifo; -+int grsec_enable_execve; -+int grsec_enable_execlog; -+int grsec_enable_signal; -+int grsec_enable_forkfail; -+int grsec_enable_time; -+int grsec_enable_audit_textrel; -+int grsec_enable_group; -+int grsec_audit_gid; -+int grsec_enable_chdir; -+int grsec_enable_audit_ipc; -+int grsec_enable_mount; -+int grsec_enable_chroot_findtask; -+int grsec_enable_chroot_mount; -+int grsec_enable_chroot_shmat; -+int grsec_enable_chroot_fchdir; -+int grsec_enable_chroot_double; -+int grsec_enable_chroot_pivot; -+int grsec_enable_chroot_chdir; -+int grsec_enable_chroot_chmod; -+int grsec_enable_chroot_mknod; -+int grsec_enable_chroot_nice; -+int grsec_enable_chroot_execlog; -+int grsec_enable_chroot_caps; -+int grsec_enable_chroot_sysctl; -+int grsec_enable_chroot_unix; -+int grsec_enable_tpe; -+int grsec_tpe_gid; -+int grsec_enable_tpe_all; -+int grsec_enable_randpid; -+int grsec_enable_randid; -+int grsec_enable_randisn; -+int grsec_enable_randsrc; -+int grsec_enable_randrpc; -+int grsec_enable_socket_all; -+int grsec_socket_all_gid; -+int grsec_enable_socket_client; -+int grsec_socket_client_gid; -+int grsec_enable_socket_server; -+int grsec_socket_server_gid; -+int grsec_lock; -+ -+spinlock_t grsec_alert_lock = SPIN_LOCK_UNLOCKED; -+unsigned long grsec_alert_wtime = 0; -+unsigned long grsec_alert_fyet = 0; -+ -+spinlock_t grsec_alertgood_lock = SPIN_LOCK_UNLOCKED; -+unsigned long grsec_alertgood_wtime = 0; -+unsigned long grsec_alertgood_fyet = 0; -+ -+spinlock_t grsec_audit_lock = SPIN_LOCK_UNLOCKED; -+ -+char *gr_shared_page[4]; -+extern struct gr_arg *gr_usermode; -+extern unsigned char *gr_system_salt; -+extern unsigned char *gr_system_sum; -+extern struct task_struct **gr_conn_table; -+extern const unsigned int gr_conn_table_size; -+ -+void -+grsecurity_init(void) -+{ -+ int j; -+ /* create the per-cpu shared pages */ -+ -+ preempt_disable(); -+ for (j = 0; j < 4; j++) { -+ gr_shared_page[j] = (char *)__alloc_percpu(PAGE_SIZE, __alignof__(char *)); -+ if (gr_shared_page[j] == NULL) { -+ panic("Unable to allocate grsecurity shared page"); -+ return; -+ } -+ } -+ preempt_enable(); -+ -+ /* create hash tables for ip tagging */ -+ -+ gr_conn_table = (struct task_struct **) vmalloc(gr_conn_table_size * sizeof(struct task_struct *)); -+ if (gr_conn_table == NULL) { -+ panic("Unable to allocate grsecurity IP tagging table"); -+ return; -+ } -+ memset(gr_conn_table, 0, gr_conn_table_size * sizeof(struct task_struct *)); -+ -+ /* allocate memory for authentication structure */ -+ gr_usermode = kmalloc(sizeof(struct gr_arg), GFP_KERNEL); -+ gr_system_salt = kmalloc(GR_SALT_LEN, GFP_KERNEL); -+ gr_system_sum = kmalloc(GR_SHA_LEN, GFP_KERNEL); -+ -+ if (!gr_usermode || !gr_system_salt || !gr_system_sum) { -+ panic("Unable to allocate grsecurity authentication structure"); -+ return; -+ } -+ -+#ifndef CONFIG_GRKERNSEC_SYSCTL -+ grsec_lock = 1; -+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL -+ grsec_enable_audit_textrel = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP -+ grsec_enable_group = 1; -+ grsec_audit_gid = CONFIG_GRKERNSEC_AUDIT_GID; -+#endif -+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR -+ grsec_enable_chdir = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC -+ grsec_enable_audit_ipc = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT -+ grsec_enable_mount = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_LINK -+ grsec_enable_link = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_DMESG -+ grsec_enable_dmesg = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_FIFO -+ grsec_enable_fifo = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_EXECVE -+ grsec_enable_execve = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_EXECLOG -+ grsec_enable_execlog = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_SIGNAL -+ grsec_enable_signal = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_FORKFAIL -+ grsec_enable_forkfail = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_TIME -+ grsec_enable_time = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK -+ grsec_enable_chroot_findtask = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX -+ grsec_enable_chroot_unix = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT -+ grsec_enable_chroot_mount = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR -+ grsec_enable_chroot_fchdir = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT -+ grsec_enable_chroot_shmat = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE -+ grsec_enable_chroot_double = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT -+ grsec_enable_chroot_pivot = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR -+ grsec_enable_chroot_chdir = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD -+ grsec_enable_chroot_chmod = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD -+ grsec_enable_chroot_mknod = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE -+ grsec_enable_chroot_nice = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG -+ grsec_enable_chroot_execlog = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS -+ grsec_enable_chroot_caps = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL -+ grsec_enable_chroot_sysctl = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_TPE -+ grsec_enable_tpe = 1; -+ grsec_tpe_gid = CONFIG_GRKERNSEC_TPE_GID; -+#ifdef CONFIG_GRKERNSEC_TPE_ALL -+ grsec_enable_tpe_all = 1; -+#endif -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDPID -+ grsec_enable_randpid = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDID -+ grsec_enable_randid = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDISN -+ grsec_enable_randisn = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDSRC -+ grsec_enable_randsrc = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDRPC -+ grsec_enable_randrpc = 1; -+#endif -+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL -+ grsec_enable_socket_all = 1; -+ grsec_socket_all_gid = CONFIG_GRKERNSEC_SOCKET_ALL_GID; -+#endif -+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT -+ grsec_enable_socket_client = 1; -+ grsec_socket_client_gid = CONFIG_GRKERNSEC_SOCKET_CLIENT_GID; -+#endif -+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER -+ grsec_enable_socket_server = 1; -+ grsec_socket_server_gid = CONFIG_GRKERNSEC_SOCKET_SERVER_GID; -+#endif -+#endif -+ -+ return; -+} -diff -urN linux-2.6.5/grsecurity/grsec_ipc.c linux-2.6.5/grsecurity/grsec_ipc.c ---- linux-2.6.5/grsecurity/grsec_ipc.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_ipc.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,81 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/types.h> -+#include <linux/ipc.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+void -+gr_log_msgget(const int ret, const int msgflg) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC -+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) && -+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc && -+ !grsec_enable_group)) && (ret >= 0) -+ && (msgflg & IPC_CREAT)) -+ security_audit(GR_MSGQ_AUDIT_MSG, DEFAULTSECARGS); -+#endif -+ return; -+} -+ -+void -+gr_log_msgrm(const uid_t uid, const uid_t cuid) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC -+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) && -+ grsec_enable_audit_ipc) || -+ (grsec_enable_audit_ipc && !grsec_enable_group)) -+ security_audit(GR_MSGQR_AUDIT_MSG, uid, cuid, DEFAULTSECARGS); -+#endif -+ return; -+} -+ -+void -+gr_log_semget(const int err, const int semflg) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC -+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) && -+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc && -+ !grsec_enable_group)) && (err >= 0) -+ && (semflg & IPC_CREAT)) -+ security_audit(GR_SEM_AUDIT_MSG, DEFAULTSECARGS); -+#endif -+ return; -+} -+ -+void -+gr_log_semrm(const uid_t uid, const uid_t cuid) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC -+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) && -+ grsec_enable_audit_ipc) || -+ (grsec_enable_audit_ipc && !grsec_enable_group)) -+ security_audit(GR_SEMR_AUDIT_MSG, uid, cuid, DEFAULTSECARGS); -+#endif -+ return; -+} -+ -+void -+gr_log_shmget(const int err, const int shmflg, const size_t size) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC -+ if (((grsec_enable_group && in_group_p(grsec_audit_gid) && -+ grsec_enable_audit_ipc) || (grsec_enable_audit_ipc && -+ !grsec_enable_group)) && (err >= 0) -+ && (shmflg & IPC_CREAT)) -+ security_audit(GR_SHM_AUDIT_MSG, size, DEFAULTSECARGS); -+#endif -+ return; -+} -+ -+void -+gr_log_shmrm(const uid_t uid, const uid_t cuid) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC -+ if ((grsec_enable_group && in_group_p(grsec_audit_gid) && -+ grsec_enable_audit_ipc) || -+ (grsec_enable_audit_ipc && !grsec_enable_group)) -+ security_audit(GR_SHMR_AUDIT_MSG, uid, cuid, DEFAULTSECARGS); -+#endif -+ return; -+} -diff -urN linux-2.6.5/grsecurity/grsec_link.c linux-2.6.5/grsecurity/grsec_link.c ---- linux-2.6.5/grsecurity/grsec_link.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_link.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,41 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/fs.h> -+#include <linux/file.h> -+#include <linux/grinternal.h> -+ -+int -+gr_handle_follow_link(const struct inode *parent, -+ const struct inode *inode, -+ const struct dentry *dentry, const struct vfsmount *mnt) -+{ -+#ifdef CONFIG_GRKERNSEC_LINK -+ if (grsec_enable_link && S_ISLNK(inode->i_mode) && -+ (parent->i_mode & S_ISVTX) && (parent->i_uid != inode->i_uid) && -+ (parent->i_mode & S_IWOTH) && (current->fsuid != inode->i_uid)) { -+ security_alert(GR_SYMLINK_MSG, gr_to_filename(dentry, mnt), -+ inode->i_uid, inode->i_gid, DEFAULTSECARGS); -+ return -EACCES; -+ } -+#endif -+ return 0; -+} -+ -+int -+gr_handle_hardlink(const struct dentry *dentry, -+ const struct vfsmount *mnt, -+ struct inode *inode, const int mode, const char *to) -+{ -+#ifdef CONFIG_GRKERNSEC_LINK -+ if (grsec_enable_link && current->fsuid != inode->i_uid && -+ (!S_ISREG(mode) || (mode & S_ISUID) || -+ ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) || -+ (vfs_permission(inode, MAY_READ | MAY_WRITE))) && -+ !capable(CAP_FOWNER) && current->uid) { -+ security_alert(GR_HARDLINK_MSG, gr_to_filename(dentry, mnt), -+ inode->i_uid, inode->i_gid, to, DEFAULTSECARGS); -+ return -EPERM; -+ } -+#endif -+ return 0; -+} -diff -urN linux-2.6.5/grsecurity/grsec_mem.c linux-2.6.5/grsecurity/grsec_mem.c ---- linux-2.6.5/grsecurity/grsec_mem.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_mem.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,54 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/mm.h> -+#include <linux/mman.h> -+#include <linux/grinternal.h> -+ -+void -+gr_handle_ioperm(void) -+{ -+ security_alert(GR_IOPERM_MSG, DEFAULTSECARGS); -+ return; -+} -+ -+void -+gr_handle_iopl(void) -+{ -+ security_alert(GR_IOPL_MSG, DEFAULTSECARGS); -+ return; -+} -+ -+void -+gr_handle_mem_write(void) -+{ -+ security_alert(GR_MEM_WRITE_MSG, DEFAULTSECARGS); -+ return; -+} -+ -+void -+gr_handle_kmem_write(void) -+{ -+ security_alert(GR_KMEM_MSG, DEFAULTSECARGS); -+ return; -+} -+ -+void -+gr_handle_open_port(void) -+{ -+ security_alert(GR_PORT_OPEN_MSG, DEFAULTSECARGS); -+ return; -+} -+ -+int -+gr_handle_mem_mmap(const unsigned long offset, struct vm_area_struct *vma) -+{ -+ if (offset < __pa(high_memory) && (vma->vm_flags & VM_WRITE) && -+ !(offset == 0xf0000 && ((vma->vm_end - vma->vm_start) <= 0x10000)) && -+ !(offset == 0xa0000 && ((vma->vm_end - vma->vm_start) <= 0x20000))) { -+ security_alert(GR_MEM_MMAP_MSG, DEFAULTSECARGS); -+ return -EPERM; -+ } else if (offset < __pa(high_memory)) -+ vma->vm_flags &= ~VM_MAYWRITE; -+ -+ return 0; -+} -diff -urN linux-2.6.5/grsecurity/grsec_mount.c linux-2.6.5/grsecurity/grsec_mount.c ---- linux-2.6.5/grsecurity/grsec_mount.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_mount.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,34 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+void -+gr_log_remount(const char *devname, const int retval) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT -+ if (grsec_enable_mount && (retval >= 0)) -+ security_audit(GR_REMOUNT_AUDIT_MSG, devname ? devname : "none", DEFAULTSECARGS); -+#endif -+ return; -+} -+ -+void -+gr_log_unmount(const char *devname, const int retval) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT -+ if (grsec_enable_mount && (retval >= 0)) -+ security_audit(GR_UNMOUNT_AUDIT_MSG, devname ? devname : "none", DEFAULTSECARGS); -+#endif -+ return; -+} -+ -+void -+gr_log_mount(const char *from, const char *to, const int retval) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT -+ if (grsec_enable_mount && (retval >= 0)) -+ security_audit(GR_MOUNT_AUDIT_MSG, from, to, DEFAULTSECARGS); -+#endif -+ return; -+} -diff -urN linux-2.6.5/grsecurity/grsec_rand.c linux-2.6.5/grsecurity/grsec_rand.c ---- linux-2.6.5/grsecurity/grsec_rand.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_rand.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,22 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/smp_lock.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+extern int pid_max; -+ -+int -+gr_random_pid(void) -+{ -+#ifdef CONFIG_GRKERNSEC_RANDPID -+ int pid; -+ -+ if (grsec_enable_randpid && current->fs->root) { -+ -+ pid = 1 + (get_random_long() % pid_max); -+ return pid; -+ } -+#endif -+ return 0; -+} -diff -urN linux-2.6.5/grsecurity/grsec_sig.c linux-2.6.5/grsecurity/grsec_sig.c ---- linux-2.6.5/grsecurity/grsec_sig.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_sig.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,48 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+void -+gr_log_signal(const int sig, const struct task_struct *t) -+{ -+#ifdef CONFIG_GRKERNSEC_SIGNAL -+ if (grsec_enable_signal && ((sig == SIGSEGV) || (sig == SIGILL) || -+ (sig == SIGABRT) || (sig == SIGBUS))) { -+ if (t->pid == current->pid) { -+ security_alert_good(GR_UNISIGLOG_MSG, sig, -+ DEFAULTSECARGS); -+ } else { -+ security_alert_good(GR_DUALSIGLOG_MSG, sig, -+ gr_task_fullpath0(t), t->comm, -+ t->pid, t->uid, t->euid, t->gid, -+ t->egid, gr_parent_task_fullpath0(t), -+ t->parent->comm, -+ t->parent->pid, t->parent->uid, -+ t->parent->euid, t->parent->gid, -+ t->parent->egid, DEFAULTSECARGS); -+ } -+ } -+#endif -+ return; -+} -+ -+int -+gr_handle_signal(const struct task_struct *p, const int sig) -+{ -+#ifdef CONFIG_GRKERNSEC -+ if (current->pid > 1 && gr_check_protected_task(p)) { -+ security_alert(GR_SIG_ACL_MSG, sig, gr_task_fullpath0(p), -+ p->comm, p->pid, p->uid, -+ p->euid, p->gid, p->egid, -+ gr_parent_task_fullpath0(p), p->parent->comm, -+ p->parent->pid, p->parent->uid, -+ p->parent->euid, p->parent->gid, -+ p->parent->egid, DEFAULTSECARGS); -+ return -EPERM; -+ } else if (gr_pid_is_chrooted(p)) { -+ return -EPERM; -+ } -+#endif -+ return 0; -+} -diff -urN linux-2.6.5/grsecurity/grsec_sock.c linux-2.6.5/grsecurity/grsec_sock.c ---- linux-2.6.5/grsecurity/grsec_sock.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_sock.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,256 @@ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/sched.h> -+#include <linux/file.h> -+#include <linux/net.h> -+#include <linux/in.h> -+#include <linux/ip.h> -+#include <net/sock.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+#include <linux/gracl.h> -+ -+#if defined(CONFIG_IP_NF_MATCH_STEALTH_MODULE) -+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif); -+EXPORT_SYMBOL(udp_v4_lookup); -+#endif -+#if defined(CONFIG_GRKERNSEC_RANDID) -+EXPORT_SYMBOL(ip_randomid); -+#endif -+#if defined(CONFIG_GRKERNSEC_RANDSRC) || defined(CONFIG_GRKERNSEC_RANDRPC) -+EXPORT_SYMBOL(get_random_long); -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDISN -+EXPORT_SYMBOL(ip_randomisn); -+EXPORT_SYMBOL(grsec_enable_randisn); -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDID -+EXPORT_SYMBOL(grsec_enable_randid); -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDSRC -+EXPORT_SYMBOL(grsec_enable_randsrc); -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDRPC -+EXPORT_SYMBOL(grsec_enable_randrpc); -+#endif -+ -+EXPORT_SYMBOL(gr_cap_rtnetlink); -+ -+extern int gr_search_udp_recvmsg(const struct sock *sk, const struct sk_buff *skb); -+extern int gr_search_udp_sendmsg(const struct sock *sk, const struct sockaddr_in *addr); -+ -+EXPORT_SYMBOL(gr_search_udp_recvmsg); -+EXPORT_SYMBOL(gr_search_udp_sendmsg); -+ -+#ifdef CONFIG_UNIX_MODULE -+EXPORT_SYMBOL(gr_acl_handle_unix); -+EXPORT_SYMBOL(gr_acl_handle_mknod); -+EXPORT_SYMBOL(gr_handle_chroot_unix); -+EXPORT_SYMBOL(gr_handle_create); -+#endif -+ -+#ifdef CONFIG_GRKERNSEC -+struct task_struct **gr_conn_table; -+const unsigned int gr_conn_table_size = 65521; -+struct task_struct *deleted_conn = (struct task_struct *)~0; -+spinlock_t gr_conn_table_lock = SPIN_LOCK_UNLOCKED; -+ -+extern __inline__ const char * gr_socktype_to_name(unsigned char type); -+extern __inline__ const char * gr_proto_to_name(unsigned char proto); -+ -+static __inline__ int -+conn_hash(__u32 saddr, __u32 daddr, __u16 sport, __u16 dport, unsigned int size) -+{ -+ return ((daddr + saddr + (sport << 8) + (dport << 16)) % size); -+} -+ -+static __inline__ int -+conn_match(const struct task_struct *task, __u32 saddr, __u32 daddr, -+ __u16 sport, __u16 dport) -+{ -+ if (unlikely(task != deleted_conn && task->gr_saddr == saddr && -+ task->gr_daddr == daddr && task->gr_sport == sport && -+ task->gr_dport == dport)) -+ return 1; -+ else -+ return 0; -+} -+ -+void gr_add_to_task_ip_table(struct task_struct *task) -+{ -+ unsigned int index; -+ -+ if (unlikely(gr_conn_table == NULL)) -+ return; -+ -+ if (!thread_group_leader(task)) -+ task = task->group_leader; -+ -+ index = conn_hash(task->gr_saddr, task->gr_daddr, -+ task->gr_sport, task->gr_dport, -+ gr_conn_table_size); -+ -+ spin_lock(&gr_conn_table_lock); -+ -+ while (gr_conn_table[index] && gr_conn_table[index] != deleted_conn) { -+ index = (index + 1) % gr_conn_table_size; -+ } -+ -+ gr_conn_table[index] = task; -+ -+ spin_unlock(&gr_conn_table_lock); -+ -+ return; -+} -+ -+void gr_del_task_from_ip_table_nolock(struct task_struct *task) -+{ -+ unsigned int index; -+ -+ if (unlikely(gr_conn_table == NULL)) -+ return; -+ -+ if (!thread_group_leader(task)) -+ task = task->group_leader; -+ -+ index = conn_hash(task->gr_saddr, task->gr_daddr, -+ task->gr_sport, task->gr_dport, -+ gr_conn_table_size); -+ -+ while (gr_conn_table[index] && !conn_match(gr_conn_table[index], -+ task->gr_saddr, task->gr_daddr, task->gr_sport, -+ task->gr_dport)) { -+ index = (index + 1) % gr_conn_table_size; -+ } -+ -+ if (gr_conn_table[index]) { -+ if (gr_conn_table[(index + 1) % gr_conn_table_size]) -+ gr_conn_table[index] = deleted_conn; -+ else -+ gr_conn_table[index] = NULL; -+ } -+ -+ return; -+} -+ -+struct task_struct * gr_lookup_task_ip_table(__u32 saddr, __u32 daddr, -+ __u16 sport, __u16 dport) -+{ -+ unsigned int index; -+ -+ if (unlikely(gr_conn_table == NULL)) -+ return NULL; -+ -+ index = conn_hash(saddr, daddr, sport, dport, gr_conn_table_size); -+ -+ while (gr_conn_table[index] && !conn_match(gr_conn_table[index], -+ saddr, daddr, sport, dport)) { -+ index = (index + 1) % gr_conn_table_size; -+ } -+ -+ return gr_conn_table[index]; -+} -+ -+#endif -+ -+void gr_del_task_from_ip_table(struct task_struct *task) -+{ -+#ifdef CONFIG_GRKERNSEC -+ spin_lock(&gr_conn_table_lock); -+ if (!thread_group_leader(task)) -+ gr_del_task_from_ip_table_nolock(task->group_leader); -+ else -+ gr_del_task_from_ip_table_nolock(task); -+ spin_unlock(&gr_conn_table_lock); -+#endif -+ return; -+} -+ -+void -+gr_attach_curr_ip(const struct sock *sk) -+{ -+#ifdef CONFIG_GRKERNSEC -+ struct task_struct *p; -+ struct task_struct *set; -+ const struct inet_opt *inet = inet_sk(sk); -+ -+ if (unlikely(sk->sk_protocol != IPPROTO_TCP)) -+ return; -+ -+ set = current; -+ if (!thread_group_leader(set)) -+ set = set->group_leader; -+ -+ spin_lock(&gr_conn_table_lock); -+ p = gr_lookup_task_ip_table(inet->daddr, inet->rcv_saddr, -+ inet->dport, inet->sport); -+ if (unlikely(p != NULL)) { -+ set->curr_ip = p->curr_ip; -+ set->used_accept = 1; -+ gr_del_task_from_ip_table_nolock(p); -+ spin_unlock(&gr_conn_table_lock); -+ return; -+ } -+ spin_unlock(&gr_conn_table_lock); -+ -+ set->curr_ip = inet->daddr; -+ set->used_accept = 1; -+#endif -+ return; -+} -+ -+int -+gr_handle_sock_all(const int family, const int type, const int protocol) -+{ -+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL -+ if (grsec_enable_socket_all && in_group_p(grsec_socket_all_gid) && -+ (family != AF_UNIX) && (family != AF_LOCAL)) { -+ security_alert(GR_SOCK2_MSG, family, gr_socktype_to_name(type), gr_proto_to_name(protocol), -+ DEFAULTSECARGS); -+ return -EACCES; -+ } -+#endif -+ return 0; -+} -+ -+int -+gr_handle_sock_server(const struct sockaddr *sck) -+{ -+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER -+ if (grsec_enable_socket_server && -+ in_group_p(grsec_socket_server_gid) && -+ sck && (sck->sa_family != AF_UNIX) && -+ (sck->sa_family != AF_LOCAL)) { -+ security_alert(GR_BIND_MSG, DEFAULTSECARGS); -+ return -EACCES; -+ } -+#endif -+ return 0; -+} -+ -+int -+gr_handle_sock_client(const struct sockaddr *sck) -+{ -+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT -+ if (grsec_enable_socket_client && in_group_p(grsec_socket_client_gid) && -+ sck && (sck->sa_family != AF_UNIX) && -+ (sck->sa_family != AF_LOCAL)) { -+ security_alert(GR_CONNECT_MSG, DEFAULTSECARGS); -+ return -EACCES; -+ } -+#endif -+ return 0; -+} -+ -+__u32 -+gr_cap_rtnetlink(void) -+{ -+#ifdef CONFIG_GRKERNSEC -+ if (!gr_acl_is_enabled()) -+ return current->cap_effective; -+ else -+ return (current->cap_effective & ~(current->acl->cap_lower)); -+#else -+ return current->cap_effective; -+#endif -+} -diff -urN linux-2.6.5/grsecurity/grsec_sysctl.c linux-2.6.5/grsecurity/grsec_sysctl.c ---- linux-2.6.5/grsecurity/grsec_sysctl.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_sysctl.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,453 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/sysctl.h> -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+int -+gr_handle_sysctl_mod(const char *dirname, const char *name, const int op) -+{ -+#ifdef CONFIG_GRKERNSEC_SYSCTL -+ if (!strcmp(dirname, "grsecurity") && grsec_lock && (op & 002)) { -+ security_alert(GR_SYSCTL_MSG, name, DEFAULTSECARGS); -+ return -EACCES; -+ } -+#endif -+ return 0; -+} -+ -+#ifdef CONFIG_GRKERNSEC_SYSCTL -+enum {GS_LINK=1, GS_FIFO, GS_EXECVE, GS_EXECLOG, GS_SIGNAL, -+GS_FORKFAIL, GS_TIME, GS_CHROOT_SHMAT, GS_CHROOT_UNIX, GS_CHROOT_MNT, -+GS_CHROOT_FCHDIR, GS_CHROOT_DBL, GS_CHROOT_PVT, GS_CHROOT_CD, GS_CHROOT_CM, -+GS_CHROOT_MK, GS_CHROOT_NI, GS_CHROOT_EXECLOG, GS_CHROOT_CAPS, -+GS_CHROOT_SYSCTL, GS_TPE, GS_TPE_GID, GS_TPE_ALL, GS_SIDCAPS, -+GS_RANDPID, GS_RANDID, GS_RANDSRC, GS_RANDISN, -+GS_SOCKET_ALL, GS_SOCKET_ALL_GID, GS_SOCKET_CLIENT, -+GS_SOCKET_CLIENT_GID, GS_SOCKET_SERVER, GS_SOCKET_SERVER_GID, GS_TTY, GS_TTYS, -+GS_PTY, GS_GROUP, GS_GID, GS_ACHDIR, GS_AMOUNT, GS_AIPC, GS_DMSG, GS_RANDRPC, -+GS_TEXTREL, GS_FINDTASK, GS_LOCK}; -+ -+ -+ctl_table grsecurity_table[] = { -+#ifdef CONFIG_GRKERNSEC_LINK -+ { -+ .ctl_name = GS_LINK, -+ .procname = "linking_restrictions", -+ .data = &grsec_enable_link, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_FIFO -+ { -+ .ctl_name = GS_FIFO, -+ .procname = "fifo_restrictions", -+ .data = &grsec_enable_fifo, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_EXECVE -+ { -+ .ctl_name = GS_EXECVE, -+ .procname = "execve_limiting", -+ .data = &grsec_enable_execve, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_EXECLOG -+ { -+ .ctl_name = GS_EXECLOG, -+ .procname = "exec_logging", -+ .data = &grsec_enable_execlog, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_SIGNAL -+ { -+ .ctl_name = GS_SIGNAL, -+ .procname = "signal_logging", -+ .data = &grsec_enable_signal, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_FORKFAIL -+ { -+ .ctl_name = GS_FORKFAIL, -+ .procname = "forkfail_logging", -+ .data = &grsec_enable_forkfail, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_TIME -+ { -+ .ctl_name = GS_TIME, -+ .procname = "timechange_logging", -+ .data = &grsec_enable_time, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_SHMAT -+ { -+ .ctl_name = GS_CHROOT_SHMAT, -+ .procname = "chroot_deny_shmat", -+ .data = &grsec_enable_chroot_shmat, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX -+ { -+ .ctl_name = GS_CHROOT_UNIX, -+ .procname = "chroot_deny_unix", -+ .data = &grsec_enable_chroot_unix, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_MOUNT -+ { -+ .ctl_name = GS_CHROOT_MNT, -+ .procname = "chroot_deny_mount", -+ .data = &grsec_enable_chroot_mount, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_FCHDIR -+ { -+ .ctl_name = GS_CHROOT_FCHDIR, -+ .procname = "chroot_deny_fchdir", -+ .data = &grsec_enable_chroot_fchdir, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_DOUBLE -+ { -+ .ctl_name = GS_CHROOT_DBL, -+ .procname = "chroot_deny_chroot", -+ .data = &grsec_enable_chroot_double, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_PIVOT -+ { -+ .ctl_name = GS_CHROOT_PVT, -+ .procname = "chroot_deny_pivot", -+ .data = &grsec_enable_chroot_pivot, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_CHDIR -+ { -+ .ctl_name = GS_CHROOT_CD, -+ .procname = "chroot_enforce_chdir", -+ .data = &grsec_enable_chroot_chdir, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_CHMOD -+ { -+ .ctl_name = GS_CHROOT_CM, -+ .procname = "chroot_deny_chmod", -+ .data = &grsec_enable_chroot_chmod, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_MKNOD -+ { -+ .ctl_name = GS_CHROOT_MK, -+ .procname = "chroot_deny_mknod", -+ .data = &grsec_enable_chroot_mknod, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_NICE -+ { -+ .ctl_name = GS_CHROOT_NI, -+ .procname = "chroot_restrict_nice", -+ .data = &grsec_enable_chroot_nice, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_EXECLOG -+ { -+ .ctl_name = GS_CHROOT_EXECLOG, -+ .procname = "chroot_execlog", -+ .data = &grsec_enable_chroot_execlog, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_CAPS -+ { -+ .ctl_name = GS_CHROOT_CAPS, -+ .procname = "chroot_caps", -+ .data = &grsec_enable_chroot_caps, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_SYSCTL -+ { -+ .ctl_name = GS_CHROOT_SYSCTL, -+ .procname = "chroot_deny_sysctl", -+ .data = &grsec_enable_chroot_sysctl, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_TPE -+ { -+ .ctl_name = GS_TPE, -+ .procname = "tpe", -+ .data = &grsec_enable_tpe, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+ { -+ .ctl_name = GS_TPE_GID, -+ .procname = "tpe_gid", -+ .data = &grsec_tpe_gid, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_TPE_ALL -+ { -+ .ctl_name = GS_TPE_ALL, -+ .procname = "tpe_restrict_all", -+ .data = &grsec_enable_tpe_all, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDPID -+ { -+ .ctl_name = GS_RANDPID, -+ .procname = "rand_pids", -+ .data = &grsec_enable_randpid, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDID -+ { -+ .ctl_name = GS_RANDID, -+ .procname = "rand_ip_ids", -+ .data = &grsec_enable_randid, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDSRC -+ { -+ .ctl_name = GS_RANDSRC, -+ .procname = "rand_tcp_src_ports", -+ .data = &grsec_enable_randsrc, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDISN -+ { -+ .ctl_name = GS_RANDISN, -+ .procname = "rand_isns", -+ .data = &grsec_enable_randisn, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_SOCKET_ALL -+ { -+ .ctl_name = GS_SOCKET_ALL, -+ .procname = "socket_all", -+ .data = &grsec_enable_socket_all, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+ { -+ .ctl_name = GS_SOCKET_ALL_GID, -+ .procname = "socket_all_gid", -+ .data = &grsec_socket_all_gid, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_SOCKET_CLIENT -+ { -+ .ctl_name = GS_SOCKET_CLIENT, -+ .procname = "socket_client", -+ .data = &grsec_enable_socket_client, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+ { -+ .ctl_name = GS_SOCKET_CLIENT_GID, -+ .procname = "socket_client_gid", -+ .data = &grsec_socket_client_gid, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_SOCKET_SERVER -+ { -+ .ctl_name = GS_SOCKET_SERVER, -+ .procname = "socket_server", -+ .data = &grsec_enable_socket_server, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+ { -+ .ctl_name = GS_SOCKET_SERVER_GID, -+ .procname = "socket_server_gid", -+ .data = &grsec_socket_server_gid, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_AUDIT_GROUP -+ { -+ .ctl_name = GS_GROUP, -+ .procname = "audit_group", -+ .data = &grsec_enable_group, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+ { -+ .ctl_name = GS_GID, -+ .procname = "audit_gid", -+ .data = &grsec_audit_gid, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_AUDIT_CHDIR -+ { -+ .ctl_name = GS_ACHDIR, -+ .procname = "audit_chdir", -+ .data = &grsec_enable_chdir, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_AUDIT_MOUNT -+ { -+ .ctl_name = GS_AMOUNT, -+ .procname = "audit_mount", -+ .data = &grsec_enable_mount, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_AUDIT_IPC -+ { -+ .ctl_name = GS_AIPC, -+ .procname = "audit_ipc", -+ .data = &grsec_enable_audit_ipc, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL -+ { -+ .ctl_name = GS_TEXTREL, -+ .procname = "audit_textrel", -+ .data = &grsec_enable_audit_textrel, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_DMESG -+ { -+ .ctl_name = GS_DMSG, -+ .procname = "dmesg", -+ .data = &grsec_enable_dmesg, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_RANDRPC -+ { -+ .ctl_name = GS_RANDRPC, -+ .procname = "rand_rpc", -+ .data = &grsec_enable_randrpc, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+#ifdef CONFIG_GRKERNSEC_CHROOT_FINDTASK -+ { -+ .ctl_name = GS_FINDTASK, -+ .procname = "chroot_findtask", -+ .data = &grsec_enable_chroot_findtask, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+ { -+ .ctl_name = GS_LOCK, -+ .procname = "grsec_lock", -+ .data = &grsec_lock, -+ .maxlen = sizeof(int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+ { .ctl_name = 0 } -+}; -+#endif -diff -urN linux-2.6.5/grsecurity/grsec_textrel.c linux-2.6.5/grsecurity/grsec_textrel.c ---- linux-2.6.5/grsecurity/grsec_textrel.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_textrel.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,19 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/mm.h> -+#include <linux/file.h> -+#include <linux/grinternal.h> -+#include <linux/grsecurity.h> -+ -+void -+gr_log_textrel(struct vm_area_struct * vma) -+{ -+#ifdef CONFIG_GRKERNSEC_AUDIT_TEXTREL -+ if (grsec_enable_audit_textrel) -+ security_audit(GR_TEXTREL_AUDIT_MSG, vma->vm_file ? -+ gr_to_filename(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt) -+ : "<anonymous mapping>", vma->vm_start, -+ vma->vm_pgoff, DEFAULTSECARGS); -+#endif -+ return; -+} -diff -urN linux-2.6.5/grsecurity/grsec_time.c linux-2.6.5/grsecurity/grsec_time.c ---- linux-2.6.5/grsecurity/grsec_time.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_time.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,13 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/grinternal.h> -+ -+void -+gr_log_timechange(void) -+{ -+#ifdef CONFIG_GRKERNSEC_TIME -+ if (grsec_enable_time) -+ security_alert_good(GR_TIME_MSG, DEFAULTSECARGS); -+#endif -+ return; -+} -diff -urN linux-2.6.5/grsecurity/grsec_tpe.c linux-2.6.5/grsecurity/grsec_tpe.c ---- linux-2.6.5/grsecurity/grsec_tpe.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsec_tpe.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,35 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/file.h> -+#include <linux/fs.h> -+#include <linux/grinternal.h> -+ -+extern int gr_acl_tpe_check(void); -+ -+int -+gr_tpe_allow(const struct file *file) -+{ -+#ifdef CONFIG_GRKERNSEC -+ struct inode *inode = file->f_dentry->d_parent->d_inode; -+ -+ if (current->uid && ((grsec_enable_tpe && in_group_p(grsec_tpe_gid)) || gr_acl_tpe_check()) && -+ (inode->i_uid || (!inode->i_uid && ((inode->i_mode & S_IWGRP) || -+ (inode->i_mode & S_IWOTH))))) { -+ security_alert(GR_EXEC_TPE_MSG, -+ gr_to_filename(file->f_dentry, file->f_vfsmnt), -+ DEFAULTSECARGS); -+ return 0; -+ } -+#ifdef CONFIG_GRKERNSEC_TPE_ALL -+ if (current->uid && grsec_enable_tpe && grsec_enable_tpe_all && -+ ((inode->i_uid && (inode->i_uid != current->uid)) || -+ (inode->i_mode & S_IWGRP) || (inode->i_mode & S_IWOTH))) { -+ security_alert(GR_EXEC_TPE_MSG, -+ gr_to_filename(file->f_dentry, file->f_vfsmnt), -+ DEFAULTSECARGS); -+ return 0; -+ } -+#endif -+#endif -+ return 1; -+} -diff -urN linux-2.6.5/grsecurity/grsum.c linux-2.6.5/grsecurity/grsum.c ---- linux-2.6.5/grsecurity/grsum.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/grsum.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,59 @@ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/mm.h> -+#include <asm/scatterlist.h> -+#include <linux/crypto.h> -+#include <linux/gracl.h> -+ -+ -+#if !defined(CONFIG_CRYPTO) || defined(CONFIG_CRYPTO_MODULE) || !defined(CONFIG_CRYPTO_SHA256) || defined(CONFIG_CRYPTO_SHA256_MODULE) -+#error "crypto and sha256 must be built into the kernel" -+#endif -+ -+int -+chkpw(struct gr_arg *entry, unsigned char *salt, unsigned char *sum) -+{ -+ char *p; -+ struct crypto_tfm *tfm; -+ unsigned char temp_sum[GR_SHA_LEN]; -+ struct scatterlist sg[2]; -+ volatile int retval = 0; -+ volatile int dummy = 0; -+ unsigned int i; -+ -+ tfm = crypto_alloc_tfm("sha256", 0); -+ if (tfm == NULL) { -+ /* should never happen, since sha256 should be built in */ -+ return 1; -+ } -+ -+ crypto_digest_init(tfm); -+ -+ p = salt; -+ sg[0].page = virt_to_page(p); -+ sg[0].offset = ((long) p & ~PAGE_MASK); -+ sg[0].length = GR_SALT_LEN; -+ -+ crypto_digest_update(tfm, sg, 1); -+ -+ p = entry->pw; -+ sg[0].page = virt_to_page(p); -+ sg[0].offset = ((long) p & ~PAGE_MASK); -+ sg[0].length = strlen(entry->pw); -+ -+ crypto_digest_update(tfm, sg, 1); -+ -+ crypto_digest_final(tfm, temp_sum); -+ -+ memset(entry->pw, 0, GR_PW_LEN); -+ -+ for (i = 0; i < GR_SHA_LEN; i++) -+ if (sum[i] != temp_sum[i]) -+ retval = 1; -+ else -+ dummy = 1; // waste a cycle -+ -+ crypto_free_tfm(tfm); -+ -+ return retval; -+} -diff -urN linux-2.6.5/grsecurity/obsd_rand.c linux-2.6.5/grsecurity/obsd_rand.c ---- linux-2.6.5/grsecurity/obsd_rand.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/grsecurity/obsd_rand.c 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,186 @@ -+ -+/* -+ * Copyright (c) 1996, 1997, 2000-2002 Michael Shalayeff. -+ * -+ * Version 1.89, last modified 19-Sep-99 -+ * -+ * Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. -+ * All rights reserved. -+ * -+ * Copyright 1998 Niels Provos <provos@citi.umich.edu> -+ * All rights reserved. -+ * Theo de Raadt <deraadt@openbsd.org> came up with the idea of using -+ * such a mathematical system to generate more random (yet non-repeating) -+ * ids to solve the resolver/named problem. But Niels designed the -+ * actual system based on the constraints. -+ * -+ * Redistribution and use in source and binary forms, with or without -+ * modification, are permitted provided that the following conditions -+ * are met: -+ * 1. Redistributions of source code must retain the above copyright -+ * notice, this list of conditions and the following disclaimer, -+ * 2. Redistributions in binary form must reproduce the above copyright -+ * notice, this list of conditions and the following disclaimer in the -+ * documentation and/or other materials provided with the distribution. -+ * -+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/sched.h> -+#include <linux/time.h> -+#include <linux/timer.h> -+#include <linux/smp_lock.h> -+#include <linux/random.h> -+#include <linux/grsecurity.h> -+ -+#define RU_OUT 180 -+#define RU_MAX 30000 -+#define RU_GEN 2 -+#define RU_N 32749 -+#define RU_AGEN 7 -+#define RU_M 31104 -+#define PFAC_N 3 -+const static __u16 pfacts[PFAC_N] = { 2, 3, 2729 }; -+ -+static __u16 ru_x; -+static __u16 ru_seed, ru_seed2; -+static __u16 ru_a, ru_b; -+static __u16 ru_g; -+static __u16 ru_counter = 0; -+static __u16 ru_msb = 0; -+static unsigned long ru_reseed = 0; -+static __u32 tmp; -+ -+#define TCP_RNDISS_ROUNDS 15 -+#define TCP_RNDISS_OUT 7200 -+#define TCP_RNDISS_MAX 30000 -+ -+static __u8 tcp_rndiss_sbox[128]; -+static __u16 tcp_rndiss_msb; -+static __u16 tcp_rndiss_cnt; -+static unsigned long tcp_rndiss_reseed; -+ -+static __u16 pmod(__u16, __u16, __u16); -+static void ip_initid(void); -+__u16 ip_randomid(void); -+ -+static __u16 -+pmod(__u16 gen, __u16 exp, __u16 mod) -+{ -+ __u16 s, t, u; -+ -+ s = 1; -+ t = gen; -+ u = exp; -+ -+ while (u) { -+ if (u & 1) -+ s = (s * t) % mod; -+ u >>= 1; -+ t = (t * t) % mod; -+ } -+ return (s); -+} -+ -+static void -+ip_initid(void) -+{ -+ __u16 j, i; -+ int noprime = 1; -+ -+ ru_x = ((tmp = get_random_long()) & 0xFFFF) % RU_M; -+ -+ ru_seed = (tmp >> 16) & 0x7FFF; -+ ru_seed2 = get_random_long() & 0x7FFF; -+ -+ ru_b = ((tmp = get_random_long()) & 0xfffe) | 1; -+ ru_a = pmod(RU_AGEN, (tmp >> 16) & 0xfffe, RU_M); -+ while (ru_b % 3 == 0) -+ ru_b += 2; -+ -+ j = (tmp = get_random_long()) % RU_N; -+ tmp = tmp >> 16; -+ -+ while (noprime) { -+ for (i = 0; i < PFAC_N; i++) -+ if (j % pfacts[i] == 0) -+ break; -+ -+ if (i >= PFAC_N) -+ noprime = 0; -+ else -+ j = (j + 1) % RU_N; -+ } -+ -+ ru_g = pmod(RU_GEN, j, RU_N); -+ ru_counter = 0; -+ -+ ru_reseed = xtime.tv_sec + RU_OUT; -+ ru_msb = ru_msb == 0x8000 ? 0 : 0x8000; -+} -+ -+__u16 -+ip_randomid(void) -+{ -+ int i, n; -+ -+ if (ru_counter >= RU_MAX || time_after(get_seconds(), ru_reseed)) -+ ip_initid(); -+ -+ if (!tmp) -+ tmp = get_random_long(); -+ -+ n = tmp & 0x3; -+ tmp = tmp >> 2; -+ if (ru_counter + n >= RU_MAX) -+ ip_initid(); -+ for (i = 0; i <= n; i++) -+ ru_x = (ru_a * ru_x + ru_b) % RU_M; -+ ru_counter += i; -+ -+ return ((ru_seed ^ pmod(ru_g, ru_seed2 ^ ru_x, RU_N)) | ru_msb); -+} -+ -+__u16 -+tcp_rndiss_encrypt(__u16 val) -+{ -+ __u16 sum = 0, i; -+ -+ for (i = 0; i < TCP_RNDISS_ROUNDS; i++) { -+ sum += 0x79b9; -+ val ^= ((__u16) tcp_rndiss_sbox[(val ^ sum) & 0x7f]) << 7; -+ val = ((val & 0xff) << 7) | (val >> 8); -+ } -+ -+ return val; -+} -+ -+static void -+tcp_rndiss_init(void) -+{ -+ get_random_bytes(tcp_rndiss_sbox, sizeof (tcp_rndiss_sbox)); -+ tcp_rndiss_reseed = get_seconds() + TCP_RNDISS_OUT; -+ tcp_rndiss_msb = tcp_rndiss_msb == 0x8000 ? 0 : 0x8000; -+ tcp_rndiss_cnt = 0; -+} -+ -+__u32 -+ip_randomisn(void) -+{ -+ if (tcp_rndiss_cnt >= TCP_RNDISS_MAX || -+ time_after(get_seconds(), tcp_rndiss_reseed)) -+ tcp_rndiss_init(); -+ -+ return (((tcp_rndiss_encrypt(tcp_rndiss_cnt++) | -+ tcp_rndiss_msb) << 16) | (get_random_long() & 0x7fff)); -+} -diff -urN linux-2.6.5/include/asm-alpha/a.out.h linux-2.6.5/include/asm-alpha/a.out.h ---- linux-2.6.5/include/asm-alpha/a.out.h 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/include/asm-alpha/a.out.h 2004-04-18 11:05:51.000000000 -0400 -@@ -98,7 +98,7 @@ - set_personality (((BFPM->sh_bang || EX.ah.entry < 0x100000000 \ - ? ADDR_LIMIT_32BIT : 0) | PER_OSF4)) - --#define STACK_TOP \ -+#define __STACK_TOP \ - (current->personality & ADDR_LIMIT_32BIT ? 0x80000000 : 0x00120000000UL) - - #endif -diff -urN linux-2.6.5/include/asm-alpha/elf.h linux-2.6.5/include/asm-alpha/elf.h ---- linux-2.6.5/include/asm-alpha/elf.h 2004-04-03 22:37:07.000000000 -0500 -+++ linux-2.6.5/include/asm-alpha/elf.h 2004-04-18 11:05:51.000000000 -0400 -@@ -84,6 +84,17 @@ - - #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x1000000) - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 0x10000 : 0x120000000UL) -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28) -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 28) -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality & ADDR_LIMIT_32BIT ? 14 : 19) -+#endif -+ - /* $0 is set by ld.so to a pointer to a function which might be - registered using atexit. This provides a mean for the dynamic - linker to call DT_FINI functions for shared libraries that have -diff -urN linux-2.6.5/include/asm-alpha/mman.h linux-2.6.5/include/asm-alpha/mman.h ---- linux-2.6.5/include/asm-alpha/mman.h 2004-04-03 22:36:14.000000000 -0500 -+++ linux-2.6.5/include/asm-alpha/mman.h 2004-04-18 11:05:51.000000000 -0400 -@@ -29,6 +29,10 @@ - #define MAP_POPULATE 0x20000 /* populate (prefault) pagetables */ - #define MAP_NONBLOCK 0x40000 /* do not block on IO */ - -+#ifdef CONFIG_PAX_RANDEXEC -+#define MAP_MIRROR 0x20000 -+#endif -+ - #define MS_ASYNC 1 /* sync memory asynchronously */ - #define MS_SYNC 2 /* synchronous memory sync */ - #define MS_INVALIDATE 4 /* invalidate the caches */ -diff -urN linux-2.6.5/include/asm-alpha/page.h linux-2.6.5/include/asm-alpha/page.h ---- linux-2.6.5/include/asm-alpha/page.h 2004-04-03 22:37:40.000000000 -0500 -+++ linux-2.6.5/include/asm-alpha/page.h 2004-04-18 11:05:51.000000000 -0400 -@@ -98,6 +98,15 @@ - #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -+#ifdef CONFIG_PAX_PAGEEXEC -+#ifdef CONFIG_PAX_MPROTECT -+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \ -+ ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#else -+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#endif -+#endif -+ - #endif /* __KERNEL__ */ - - #endif /* _ALPHA_PAGE_H */ -diff -urN linux-2.6.5/include/asm-alpha/pgtable.h linux-2.6.5/include/asm-alpha/pgtable.h ---- linux-2.6.5/include/asm-alpha/pgtable.h 2004-04-03 22:36:54.000000000 -0500 -+++ linux-2.6.5/include/asm-alpha/pgtable.h 2004-04-18 11:05:51.000000000 -0400 -@@ -96,6 +96,17 @@ - #define PAGE_SHARED __pgprot(_PAGE_VALID | __ACCESS_BITS) - #define PAGE_COPY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) - #define PAGE_READONLY __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW) -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOE) -+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE) -+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_VALID | __ACCESS_BITS | _PAGE_FOW | _PAGE_FOE) -+#else -+# define PAGE_SHARED_NOEXEC PAGE_SHARED -+# define PAGE_COPY_NOEXEC PAGE_COPY -+# define PAGE_READONLY_NOEXEC PAGE_READONLY -+#endif -+ - #define PAGE_KERNEL __pgprot(_PAGE_VALID | _PAGE_ASM | _PAGE_KRE | _PAGE_KWE) - - #define _PAGE_NORMAL(x) __pgprot(_PAGE_VALID | __ACCESS_BITS | (x)) -diff -urN linux-2.6.5/include/asm-i386/a.out.h linux-2.6.5/include/asm-i386/a.out.h ---- linux-2.6.5/include/asm-i386/a.out.h 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/a.out.h 2004-04-18 11:05:51.000000000 -0400 -@@ -19,7 +19,11 @@ - - #ifdef __KERNEL__ - --#define STACK_TOP TASK_SIZE -+#ifdef CONFIG_PAX_SEGMEXEC -+#define __STACK_TOP ((current->flags & PF_PAX_SEGMEXEC)?TASK_SIZE/2:TASK_SIZE) -+#else -+#define __STACK_TOP TASK_SIZE -+#endif - - #endif - -diff -urN linux-2.6.5/include/asm-i386/desc.h linux-2.6.5/include/asm-i386/desc.h ---- linux-2.6.5/include/asm-i386/desc.h 2004-04-03 22:36:12.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/desc.h 2004-04-18 11:05:51.000000000 -0400 -@@ -8,11 +8,19 @@ - - #include <linux/preempt.h> - #include <linux/smp.h> -+#include <linux/sched.h> - - #include <asm/mmu.h> -+#include <asm/pgtable.h> -+#include <asm/tlbflush.h> - - extern struct desc_struct cpu_gdt_table[NR_CPUS][GDT_ENTRIES]; - -+static inline void pax_switch_segments(struct task_struct * tsk, int cpu) -+{ -+ cpu_gdt_table[cpu][GDT_ENTRY_DEFAULT_USER_CS].b = tsk->flags & PF_PAX_SEGMEXEC ? 0x60c9fb00U : 0x00cffb00U; -+} -+ - struct Xgt_desc_struct { - unsigned short size; - unsigned long address __attribute__((packed)); -@@ -28,7 +36,7 @@ - * This is the ldt that every process will get unless we need - * something other than this. - */ --extern struct desc_struct default_ldt[]; -+extern const struct desc_struct default_ldt[]; - extern void set_intr_gate(unsigned int irq, void * addr); - - #define _set_tssldt_desc(n,addr,limit,type) \ -@@ -42,16 +50,50 @@ - "rorl $16,%%eax" \ - : "=m"(*(n)) : "a" (addr), "r"(n), "ir"(limit), "i"(type)) - --static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, void *addr) -+static inline void __set_tss_desc(unsigned int cpu, unsigned int entry, const void *addr) - { - _set_tssldt_desc(&cpu_gdt_table[cpu][entry], (int)addr, 235, 0x89); - } - - #define set_tss_desc(cpu,addr) __set_tss_desc(cpu, GDT_ENTRY_TSS, addr) - --static inline void set_ldt_desc(unsigned int cpu, void *addr, unsigned int size) -+static inline void __set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size) -+{ -+ _set_tssldt_desc(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82); -+} -+ -+#define pax_open_kernel(flags, cr3) \ -+do { \ -+ typecheck(unsigned long,flags); \ -+ typecheck(unsigned long,cr3); \ -+ local_irq_save(flags); \ -+ asm("movl %%cr3,%0":"=r" (cr3)); \ -+ load_cr3(kernexec_pg_dir); \ -+} while(0) -+ -+#define pax_close_kernel(flags, cr3) \ -+do { \ -+ typecheck(unsigned long,flags); \ -+ typecheck(unsigned long,cr3); \ -+ asm("movl %0,%%cr3": :"r" (cr3)); \ -+ local_irq_restore(flags); \ -+} while(0) -+ -+static inline void set_ldt_desc(unsigned int cpu, const void *addr, unsigned int size) - { -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ unsigned long flags, cr3; -+ -+ pax_open_kernel(flags, cr3); -+#endif -+ - _set_tssldt_desc(&cpu_gdt_table[cpu][GDT_ENTRY_LDT], (int)addr, ((size << 3)-1), 0x82); -+ -+#ifdef CONFIG_PAX_KERNEXEC -+ pax_close_kernel(flags, cr3); -+#endif -+ - } - - #define LDT_entry_a(info) \ -@@ -67,7 +109,7 @@ - ((info)->seg_32bit << 22) | \ - ((info)->limit_in_pages << 23) | \ - ((info)->useable << 20) | \ -- 0x7000) -+ 0x7100) - - #define LDT_empty(info) (\ - (info)->base_addr == 0 && \ -@@ -104,7 +146,7 @@ - */ - static inline void load_LDT_nolock(mm_context_t *pc, int cpu) - { -- void *segments = pc->ldt; -+ const void *segments = pc->ldt; - int count = pc->size; - - if (likely(!count)) { -@@ -123,6 +165,22 @@ - put_cpu(); - } - -+static inline void _load_LDT(mm_context_t *pc) -+{ -+ int cpu = get_cpu(); -+ const void *segments = pc->ldt; -+ int count = pc->size; -+ -+ if (likely(!count)) { -+ segments = &default_ldt[0]; -+ count = 5; -+ } -+ -+ __set_ldt_desc(cpu, segments, count); -+ load_LDT_desc(); -+ put_cpu(); -+} -+ - #endif /* !__ASSEMBLY__ */ - - #endif -diff -urN linux-2.6.5/include/asm-i386/elf.h linux-2.6.5/include/asm-i386/elf.h ---- linux-2.6.5/include/asm-i386/elf.h 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/elf.h 2004-04-18 11:05:51.000000000 -0400 -@@ -70,7 +70,22 @@ - the loader. We need to make sure that it is out of the way of the program - that it will "exec", and that there is sufficient room for the brk. */ - -+#ifdef CONFIG_PAX_SEGMEXEC -+#define ELF_ET_DYN_BASE ((current->flags & PF_PAX_SEGMEXEC)?SEGMEXEC_TASK_SIZE/3*2:TASK_SIZE/3*2) -+#else - #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) -+#endif -+ -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) 0x08048000UL -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) 16 -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) 16 -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->flags & PF_PAX_SEGMEXEC ? 15 : 16) -+#endif - - /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is - now struct_user_regs, they are different) */ -@@ -113,8 +128,11 @@ - * Architecture-neutral AT_ values in 0-17, leave some room - * for more of them, start the x86-specific ones at 32. - */ -+ -+#ifndef CONFIG_PAX_NOVSYSCALL - #define AT_SYSINFO 32 - #define AT_SYSINFO_EHDR 33 -+#endif - - #ifdef __KERNEL__ - #define SET_PERSONALITY(ex, ibcs2) set_personality((ibcs2)?PER_SVR4:PER_LINUX) -@@ -129,7 +147,14 @@ - - #define VSYSCALL_BASE (__fix_to_virt(FIX_VSYSCALL)) - #define VSYSCALL_EHDR ((const struct elfhdr *) VSYSCALL_BASE) -+ -+#ifndef CONFIG_PAX_NOVSYSCALL -+#ifdef CONFIG_PAX_SEGMEXEC -+#define VSYSCALL_ENTRY ((current->flags & PF_PAX_SEGMEXEC) ? (unsigned long) &__kernel_vsyscall - SEGMEXEC_TASK_SIZE : (unsigned long) &__kernel_vsyscall) -+#else - #define VSYSCALL_ENTRY ((unsigned long) &__kernel_vsyscall) -+#endif -+ - extern void __kernel_vsyscall; - - #define ARCH_DLINFO \ -@@ -185,3 +210,5 @@ - #endif - - #endif -+ -+#endif -diff -urN linux-2.6.5/include/asm-i386/mach-default/apm.h linux-2.6.5/include/asm-i386/mach-default/apm.h ---- linux-2.6.5/include/asm-i386/mach-default/apm.h 2004-04-03 22:36:26.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/mach-default/apm.h 2004-04-18 11:05:51.000000000 -0400 -@@ -36,7 +36,7 @@ - __asm__ __volatile__(APM_DO_ZERO_SEGS - "pushl %%edi\n\t" - "pushl %%ebp\n\t" -- "lcall *%%cs:apm_bios_entry\n\t" -+ "lcall *%%ss:apm_bios_entry\n\t" - "setc %%al\n\t" - "popl %%ebp\n\t" - "popl %%edi\n\t" -@@ -60,7 +60,7 @@ - __asm__ __volatile__(APM_DO_ZERO_SEGS - "pushl %%edi\n\t" - "pushl %%ebp\n\t" -- "lcall *%%cs:apm_bios_entry\n\t" -+ "lcall *%%ss:apm_bios_entry\n\t" - "setc %%bl\n\t" - "popl %%ebp\n\t" - "popl %%edi\n\t" -diff -urN linux-2.6.5/include/asm-i386/mach-pc9800/apm.h linux-2.6.5/include/asm-i386/mach-pc9800/apm.h ---- linux-2.6.5/include/asm-i386/mach-pc9800/apm.h 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/mach-pc9800/apm.h 2004-04-18 11:05:51.000000000 -0400 -@@ -39,7 +39,7 @@ - "pushl %%edi\n\t" - "pushl %%ebp\n\t" - "pushfl\n\t" -- "lcall *%%cs:apm_bios_entry\n\t" -+ "lcall *%%ss:apm_bios_entry\n\t" - "setc %%al\n\t" - "popl %%ebp\n\t" - "popl %%edi\n\t" -@@ -64,7 +64,7 @@ - "pushl %%edi\n\t" - "pushl %%ebp\n\t" - "pushfl\n\t" -- "lcall *%%cs:apm_bios_entry\n\t" -+ "lcall *%%ss:apm_bios_entry\n\t" - "setc %%bl\n\t" - "popl %%ebp\n\t" - "popl %%edi\n\t" -diff -urN linux-2.6.5/include/asm-i386/mman.h linux-2.6.5/include/asm-i386/mman.h ---- linux-2.6.5/include/asm-i386/mman.h 2004-04-03 22:36:24.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/mman.h 2004-04-18 11:05:51.000000000 -0400 -@@ -23,6 +23,10 @@ - #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ - #define MAP_NONBLOCK 0x10000 /* do not block on IO */ - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+#define MAP_MIRROR 0x20000 -+#endif -+ - #define MS_ASYNC 1 /* sync memory asynchronously */ - #define MS_INVALIDATE 2 /* invalidate the caches */ - #define MS_SYNC 4 /* synchronous memory sync */ -diff -urN linux-2.6.5/include/asm-i386/module.h linux-2.6.5/include/asm-i386/module.h ---- linux-2.6.5/include/asm-i386/module.h 2004-04-03 22:36:24.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/module.h 2004-04-18 11:05:51.000000000 -0400 -@@ -60,6 +60,12 @@ - #define MODULE_REGPARM "" - #endif - --#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM -+#ifdef CONFIG_GRKERNSEC -+#define MODULE_GRSEC "GRSECURITY " -+#else -+#define MODULE_GRSEC "" -+#endif -+ -+#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_REGPARM MODULE_GRSEC - - #endif /* _ASM_I386_MODULE_H */ -diff -urN linux-2.6.5/include/asm-i386/page.h linux-2.6.5/include/asm-i386/page.h ---- linux-2.6.5/include/asm-i386/page.h 2004-04-03 22:36:25.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/page.h 2004-04-18 11:05:51.000000000 -0400 -@@ -120,6 +120,19 @@ - #define __PAGE_OFFSET (0xC0000000UL) - #endif - -+#ifdef CONFIG_PAX_KERNEXEC -+#ifdef __ASSEMBLY__ -+#define __KERNEL_TEXT_OFFSET (0xC0400000) -+#else -+#define __KERNEL_TEXT_OFFSET (0xC0400000UL) -+#endif -+#else -+#ifdef __ASSEMBLY__ -+#define __KERNEL_TEXT_OFFSET (0) -+#else -+#define __KERNEL_TEXT_OFFSET (0x0UL) -+#endif -+#endif - - #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET) - #define VMALLOC_RESERVE ((unsigned long)__VMALLOC_RESERVE) -@@ -139,6 +152,15 @@ - #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) -+#ifdef CONFIG_PAX_MPROTECT -+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \ -+ ((current->flags & (PF_PAX_PAGEEXEC|PF_PAX_SEGMEXEC))?0:VM_EXEC)) -+#else -+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & (PF_PAX_PAGEEXEC|PF_PAX_SEGMEXEC))?0:VM_EXEC)) -+#endif -+#endif -+ - #endif /* __KERNEL__ */ - - #endif /* _I386_PAGE_H */ -diff -urN linux-2.6.5/include/asm-i386/pgalloc.h linux-2.6.5/include/asm-i386/pgalloc.h ---- linux-2.6.5/include/asm-i386/pgalloc.h 2004-04-03 22:36:16.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/pgalloc.h 2004-04-18 11:05:51.000000000 -0400 -@@ -8,7 +8,7 @@ - #include <linux/mm.h> /* for struct page */ - - #define pmd_populate_kernel(mm, pmd, pte) \ -- set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))) -+ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte))) - - static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, struct page *pte) - { -diff -urN linux-2.6.5/include/asm-i386/pgtable.h linux-2.6.5/include/asm-i386/pgtable.h ---- linux-2.6.5/include/asm-i386/pgtable.h 2004-04-03 22:37:38.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/pgtable.h 2004-04-18 11:05:51.000000000 -0400 -@@ -32,6 +32,11 @@ - #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) - extern unsigned long empty_zero_page[1024]; - extern pgd_t swapper_pg_dir[1024]; -+ -+#ifdef CONFIG_PAX_KERNEXEC -+extern pgd_t kernexec_pg_dir[1024]; -+#endif -+ - extern kmem_cache_t *pgd_cache; - extern kmem_cache_t *pmd_cache; - extern spinlock_t pgd_lock; -@@ -130,6 +135,16 @@ - #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) - #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) - -+#ifdef CONFIG_PAX_PAGEEXEC -+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED) -+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) -+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED) -+#else -+# define PAGE_SHARED_NOEXEC PAGE_SHARED -+# define PAGE_COPY_NOEXEC PAGE_COPY -+# define PAGE_READONLY_NOEXEC PAGE_READONLY -+#endif -+ - #define _PAGE_KERNEL \ - (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) - -@@ -149,18 +164,18 @@ - * This is the closest we can get.. - */ - #define __P000 PAGE_NONE --#define __P001 PAGE_READONLY --#define __P010 PAGE_COPY --#define __P011 PAGE_COPY -+#define __P001 PAGE_READONLY_NOEXEC -+#define __P010 PAGE_COPY_NOEXEC -+#define __P011 PAGE_COPY_NOEXEC - #define __P100 PAGE_READONLY - #define __P101 PAGE_READONLY - #define __P110 PAGE_COPY - #define __P111 PAGE_COPY - - #define __S000 PAGE_NONE --#define __S001 PAGE_READONLY --#define __S010 PAGE_SHARED --#define __S011 PAGE_SHARED -+#define __S001 PAGE_READONLY_NOEXEC -+#define __S010 PAGE_SHARED_NOEXEC -+#define __S011 PAGE_SHARED_NOEXEC - #define __S100 PAGE_READONLY - #define __S101 PAGE_READONLY - #define __S110 PAGE_SHARED -diff -urN linux-2.6.5/include/asm-i386/processor.h linux-2.6.5/include/asm-i386/processor.h ---- linux-2.6.5/include/asm-i386/processor.h 2004-04-03 22:36:16.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/processor.h 2004-04-18 11:05:51.000000000 -0400 -@@ -296,10 +296,19 @@ - */ - #define TASK_SIZE (PAGE_OFFSET) - -+#ifdef CONFIG_PAX_SEGMEXEC -+#define SEGMEXEC_TASK_SIZE ((PAGE_OFFSET) / 2) -+#endif -+ - /* This decides where the kernel will search for a free chunk of vm - * space during mmap's. - */ -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+#define TASK_UNMAPPED_BASE (PAGE_ALIGN((current->flags & PF_PAX_SEGMEXEC)?SEGMEXEC_TASK_SIZE/3:TASK_SIZE/3)) -+#else - #define TASK_UNMAPPED_BASE (PAGE_ALIGN(TASK_SIZE / 3)) -+#endif - - /* - * Size of io_bitmap, covering ports 0 to 0x3ff. -@@ -624,7 +633,7 @@ - extern inline void prefetch(const void *x) - { - alternative_input(ASM_NOP4, -- "prefetchnta (%1)", -+ "prefetchnta (%2)", - X86_FEATURE_XMM, - "r" (x)); - } -@@ -638,7 +647,7 @@ - extern inline void prefetchw(const void *x) - { - alternative_input(ASM_NOP4, -- "prefetchw (%1)", -+ "prefetchw (%2)", - X86_FEATURE_3DNOW, - "r" (x)); - } -diff -urN linux-2.6.5/include/asm-i386/system.h linux-2.6.5/include/asm-i386/system.h ---- linux-2.6.5/include/asm-i386/system.h 2004-04-03 22:36:13.000000000 -0500 -+++ linux-2.6.5/include/asm-i386/system.h 2004-04-18 11:05:51.000000000 -0400 -@@ -5,6 +5,7 @@ - #include <linux/kernel.h> - #include <asm/segment.h> - #include <asm/cpufeature.h> -+#include <asm/page.h> - #include <linux/bitops.h> /* for LOCK_PREFIX */ - - #ifdef __KERNEL__ -@@ -301,7 +302,7 @@ - asm volatile ("661:\n\t" oldinstr "\n662:\n" \ - ".section .altinstructions,\"a\"\n" \ - " .align 4\n" \ -- " .long 661b\n" /* label */ \ -+ " .long 661b + %c1\n" /* label */ \ - " .long 663f\n" /* new instruction */ \ - " .byte %c0\n" /* feature bit */ \ - " .byte 662b-661b\n" /* sourcelen */ \ -@@ -309,7 +310,7 @@ - ".previous\n" \ - ".section .altinstr_replacement,\"ax\"\n" \ - "663:\n\t" newinstr "\n664:\n" /* replacement */ \ -- ".previous" :: "i" (feature) : "memory") -+ ".previous" :: "i" (feature), "i" (__KERNEL_TEXT_OFFSET) : "memory") - - /* - * Alternative inline assembly with input. -@@ -325,7 +326,7 @@ - asm volatile ("661:\n\t" oldinstr "\n662:\n" \ - ".section .altinstructions,\"a\"\n" \ - " .align 4\n" \ -- " .long 661b\n" /* label */ \ -+ " .long 661b + %c1\n" /* label */ \ - " .long 663f\n" /* new instruction */ \ - " .byte %c0\n" /* feature bit */ \ - " .byte 662b-661b\n" /* sourcelen */ \ -@@ -333,7 +334,7 @@ - ".previous\n" \ - ".section .altinstr_replacement,\"ax\"\n" \ - "663:\n\t" newinstr "\n664:\n" /* replacement */ \ -- ".previous" :: "i" (feature), input) -+ ".previous" :: "i" (feature), "i" (__KERNEL_TEXT_OFFSET), input) - - /* - * Force strict CPU ordering. -diff -urN linux-2.6.5/include/asm-ia64/elf.h linux-2.6.5/include/asm-ia64/elf.h ---- linux-2.6.5/include/asm-ia64/elf.h 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/include/asm-ia64/elf.h 2004-04-18 11:05:51.000000000 -0400 -@@ -162,6 +162,16 @@ - typedef struct ia64_fpreg elf_fpreg_t; - typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) ((tsk)->personality == PER_LINUX32 ? 0x08048000UL : 0x4000000000000000UL) -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 43 - PAGE_SHIFT) -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 43 - PAGE_SHIFT) -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) ((tsk)->personality == PER_LINUX32 ? 16 : 43 - PAGE_SHIFT) -+#endif - - - struct pt_regs; /* forward declaration... */ -diff -urN linux-2.6.5/include/asm-ia64/mman.h linux-2.6.5/include/asm-ia64/mman.h ---- linux-2.6.5/include/asm-ia64/mman.h 2004-04-03 22:37:07.000000000 -0500 -+++ linux-2.6.5/include/asm-ia64/mman.h 2004-04-18 11:05:51.000000000 -0400 -@@ -31,6 +31,10 @@ - #define MAP_POPULATE 0x08000 /* populate (prefault) pagetables */ - #define MAP_NONBLOCK 0x10000 /* do not block on IO */ - -+#ifdef CONFIG_PAX_RANDEXEC -+#define MAP_MIRROR 0x40000 -+#endif -+ - #define MS_ASYNC 1 /* sync memory asynchronously */ - #define MS_INVALIDATE 2 /* invalidate the caches */ - #define MS_SYNC 4 /* synchronous memory sync */ -diff -urN linux-2.6.5/include/asm-ia64/page.h linux-2.6.5/include/asm-ia64/page.h ---- linux-2.6.5/include/asm-ia64/page.h 2004-04-03 22:36:19.000000000 -0500 -+++ linux-2.6.5/include/asm-ia64/page.h 2004-04-18 11:05:51.000000000 -0400 -@@ -187,4 +187,13 @@ - (((current->thread.flags & IA64_THREAD_XSTACK) != 0) \ - ? VM_EXEC : 0)) - -+#ifdef CONFIG_PAX_PAGEEXEC -+#ifdef CONFIG_PAX_MPROTECT -+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \ -+ ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#else -+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#endif -+#endif -+ - #endif /* _ASM_IA64_PAGE_H */ -diff -urN linux-2.6.5/include/asm-ia64/pgtable.h linux-2.6.5/include/asm-ia64/pgtable.h ---- linux-2.6.5/include/asm-ia64/pgtable.h 2004-04-03 22:36:54.000000000 -0500 -+++ linux-2.6.5/include/asm-ia64/pgtable.h 2004-04-18 11:05:51.000000000 -0400 -@@ -120,6 +120,17 @@ - #define PAGE_SHARED __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW) - #define PAGE_READONLY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) - #define PAGE_COPY __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RX) -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+# define PAGE_SHARED_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_RW) -+# define PAGE_READONLY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) -+# define PAGE_COPY_NOEXEC __pgprot(__ACCESS_BITS | _PAGE_PL_3 | _PAGE_AR_R) -+#else -+# define PAGE_SHARED_NOEXEC PAGE_SHARED -+# define PAGE_READONLY_NOEXEC PAGE_READONLY -+# define PAGE_COPY_NOEXEC PAGE_COPY -+#endif -+ - #define PAGE_GATE __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_X_RX) - #define PAGE_KERNEL __pgprot(__DIRTY_BITS | _PAGE_PL_0 | _PAGE_AR_RWX) - #define PAGE_KERNELRX __pgprot(__ACCESS_BITS | _PAGE_PL_0 | _PAGE_AR_RX) -diff -urN linux-2.6.5/include/asm-ia64/ustack.h linux-2.6.5/include/asm-ia64/ustack.h ---- linux-2.6.5/include/asm-ia64/ustack.h 2004-04-03 22:38:21.000000000 -0500 -+++ linux-2.6.5/include/asm-ia64/ustack.h 2004-04-18 11:05:51.000000000 -0400 -@@ -11,6 +11,6 @@ - #define MAX_USER_STACK_SIZE (RGN_MAP_LIMIT/2) - /* Make a default stack size of 2GB */ - #define DEFAULT_USER_STACK_SIZE (1UL << 31) --#define STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT) -+#define __STACK_TOP (0x6000000000000000UL + RGN_MAP_LIMIT) - - #endif /* _ASM_IA64_USTACK_H */ -diff -urN linux-2.6.5/include/asm-mips/a.out.h linux-2.6.5/include/asm-mips/a.out.h ---- linux-2.6.5/include/asm-mips/a.out.h 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/include/asm-mips/a.out.h 2004-04-18 11:05:51.000000000 -0400 -@@ -36,10 +36,10 @@ - #ifdef __KERNEL__ - - #ifdef CONFIG_MIPS32 --#define STACK_TOP TASK_SIZE -+#define __STACK_TOP TASK_SIZE - #endif - #ifdef CONFIG_MIPS64 --#define STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE) -+#define __STACK_TOP (current->thread.mflags & MF_32BIT_ADDR ? TASK_SIZE32 : TASK_SIZE) - #endif - - #endif -diff -urN linux-2.6.5/include/asm-mips/elf.h linux-2.6.5/include/asm-mips/elf.h ---- linux-2.6.5/include/asm-mips/elf.h 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/include/asm-mips/elf.h 2004-04-18 11:05:51.000000000 -0400 -@@ -273,4 +273,15 @@ - #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) - #endif - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 0x00400000UL : 0x00400000UL) -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) (((tsk)->thread.mflags & MF_32BIT_ADDR) ? 27-PAGE_SHIFT : 36-PAGE_SHIFT) -+#endif -+ - #endif /* _ASM_ELF_H */ -diff -urN linux-2.6.5/include/asm-mips/page.h linux-2.6.5/include/asm-mips/page.h ---- linux-2.6.5/include/asm-mips/page.h 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/include/asm-mips/page.h 2004-04-18 11:05:51.000000000 -0400 -@@ -130,6 +130,15 @@ - #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -+#ifdef CONFIG_PAX_PAGEEXEC -+#ifdef CONFIG_PAX_MPROTECT -+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \ -+ ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#else -+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#endif -+#endif -+ - #define UNCAC_ADDR(addr) ((addr) - PAGE_OFFSET + UNCAC_BASE) - #define CAC_ADDR(addr) ((addr) - UNCAC_BASE + PAGE_OFFSET) - -diff -urN linux-2.6.5/include/asm-parisc/a.out.h linux-2.6.5/include/asm-parisc/a.out.h ---- linux-2.6.5/include/asm-parisc/a.out.h 2004-04-03 22:38:18.000000000 -0500 -+++ linux-2.6.5/include/asm-parisc/a.out.h 2004-04-18 11:05:51.000000000 -0400 -@@ -22,7 +22,7 @@ - /* XXX: STACK_TOP actually should be STACK_BOTTOM for parisc. - * prumpf */ - --#define STACK_TOP TASK_SIZE -+#define __STACK_TOP TASK_SIZE - - #endif - -diff -urN linux-2.6.5/include/asm-parisc/elf.h linux-2.6.5/include/asm-parisc/elf.h ---- linux-2.6.5/include/asm-parisc/elf.h 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/include/asm-parisc/elf.h 2004-04-18 11:05:51.000000000 -0400 -@@ -337,6 +337,17 @@ - - #define ELF_ET_DYN_BASE (TASK_UNMAPPED_BASE + 0x01000000) - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000UL -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) 16 -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) 16 -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) 16 -+#endif -+ - /* This yields a mask that user programs can use to figure out what - instruction set this CPU supports. This could be done in user space, - but it's not easy, and we've already done it here. */ -diff -urN linux-2.6.5/include/asm-parisc/mman.h linux-2.6.5/include/asm-parisc/mman.h ---- linux-2.6.5/include/asm-parisc/mman.h 2004-04-03 22:37:24.000000000 -0500 -+++ linux-2.6.5/include/asm-parisc/mman.h 2004-04-18 11:05:51.000000000 -0400 -@@ -23,6 +23,10 @@ - #define MAP_POPULATE 0x10000 /* populate (prefault) pagetables */ - #define MAP_NONBLOCK 0x20000 /* do not block on IO */ - -+#ifdef CONFIG_PAX_RANDEXEC -+#define MAP_MIRROR 0x0400 -+#endif -+ - #define MS_SYNC 1 /* synchronous memory sync */ - #define MS_ASYNC 2 /* sync memory asynchronously */ - #define MS_INVALIDATE 4 /* invalidate the caches */ -diff -urN linux-2.6.5/include/asm-parisc/page.h linux-2.6.5/include/asm-parisc/page.h ---- linux-2.6.5/include/asm-parisc/page.h 2004-04-03 22:36:26.000000000 -0500 -+++ linux-2.6.5/include/asm-parisc/page.h 2004-04-18 11:05:51.000000000 -0400 -@@ -113,6 +113,15 @@ - #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -+#ifdef CONFIG_PAX_PAGEEXEC -+#ifdef CONFIG_PAX_MPROTECT -+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \ -+ ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#else -+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#endif -+#endif -+ - #endif /* __KERNEL__ */ - - #endif /* _PARISC_PAGE_H */ -diff -urN linux-2.6.5/include/asm-parisc/pgtable.h linux-2.6.5/include/asm-parisc/pgtable.h ---- linux-2.6.5/include/asm-parisc/pgtable.h 2004-04-03 22:38:13.000000000 -0500 -+++ linux-2.6.5/include/asm-parisc/pgtable.h 2004-04-18 11:05:51.000000000 -0400 -@@ -179,6 +179,17 @@ - #define PAGE_EXECREAD __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_EXEC |_PAGE_ACCESSED) - #define PAGE_COPY PAGE_EXECREAD - #define PAGE_RWX __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_EXEC |_PAGE_ACCESSED) -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_WRITE | _PAGE_ACCESSED) -+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED) -+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_READ | _PAGE_ACCESSED) -+#else -+# define PAGE_SHARED_NOEXEC PAGE_SHARED -+# define PAGE_COPY_NOEXEC PAGE_COPY -+# define PAGE_READONLY_NOEXEC PAGE_READONLY -+#endif -+ - #define PAGE_KERNEL __pgprot(_PAGE_KERNEL) - #define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT | _PAGE_EXEC | _PAGE_READ | _PAGE_DIRTY | _PAGE_ACCESSED) - #define PAGE_KERNEL_UNC __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) -diff -urN linux-2.6.5/include/asm-ppc/a.out.h linux-2.6.5/include/asm-ppc/a.out.h ---- linux-2.6.5/include/asm-ppc/a.out.h 2004-04-03 22:37:07.000000000 -0500 -+++ linux-2.6.5/include/asm-ppc/a.out.h 2004-04-18 11:05:51.000000000 -0400 -@@ -2,7 +2,7 @@ - #define __PPC_A_OUT_H__ - - /* grabbed from the intel stuff */ --#define STACK_TOP TASK_SIZE -+#define __STACK_TOP TASK_SIZE - - - struct exec -diff -urN linux-2.6.5/include/asm-ppc/elf.h linux-2.6.5/include/asm-ppc/elf.h ---- linux-2.6.5/include/asm-ppc/elf.h 2004-04-03 22:36:13.000000000 -0500 -+++ linux-2.6.5/include/asm-ppc/elf.h 2004-04-18 11:05:51.000000000 -0400 -@@ -87,6 +87,17 @@ - - #define ELF_ET_DYN_BASE (0x08000000) - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000000UL -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) 15 -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) 15 -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) 15 -+#endif -+ - #define USE_ELF_CORE_DUMP - #define ELF_EXEC_PAGESIZE 4096 - -diff -urN linux-2.6.5/include/asm-ppc/mman.h linux-2.6.5/include/asm-ppc/mman.h ---- linux-2.6.5/include/asm-ppc/mman.h 2004-04-03 22:38:28.000000000 -0500 -+++ linux-2.6.5/include/asm-ppc/mman.h 2004-04-18 11:05:51.000000000 -0400 -@@ -24,6 +24,10 @@ - #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ - #define MAP_NONBLOCK 0x10000 /* do not block on IO */ - -+#ifdef CONFIG_PAX_RANDEXEC -+#define MAP_MIRROR 0x0200 -+#endif -+ - #define MS_ASYNC 1 /* sync memory asynchronously */ - #define MS_INVALIDATE 2 /* invalidate the caches */ - #define MS_SYNC 4 /* synchronous memory sync */ -diff -urN linux-2.6.5/include/asm-ppc/page.h linux-2.6.5/include/asm-ppc/page.h ---- linux-2.6.5/include/asm-ppc/page.h 2004-04-03 22:36:53.000000000 -0500 -+++ linux-2.6.5/include/asm-ppc/page.h 2004-04-18 11:05:51.000000000 -0400 -@@ -162,5 +162,14 @@ - #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -+#ifdef CONFIG_PAX_PAGEEXEC -+#ifdef CONFIG_PAX_MPROTECT -+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \ -+ ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#else -+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#endif -+#endif -+ - #endif /* __KERNEL__ */ - #endif /* _PPC_PAGE_H */ -diff -urN linux-2.6.5/include/asm-ppc/pgtable.h linux-2.6.5/include/asm-ppc/pgtable.h ---- linux-2.6.5/include/asm-ppc/pgtable.h 2004-04-03 22:36:26.000000000 -0500 -+++ linux-2.6.5/include/asm-ppc/pgtable.h 2004-04-18 11:05:51.000000000 -0400 -@@ -349,11 +349,21 @@ - - #define PAGE_NONE __pgprot(_PAGE_BASE) - #define PAGE_READONLY __pgprot(_PAGE_BASE | _PAGE_USER) --#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) -+#define PAGE_READONLY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC) - #define PAGE_SHARED __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW) --#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC) -+#define PAGE_SHARED_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_EXEC | _PAGE_HWEXEC) - #define PAGE_COPY __pgprot(_PAGE_BASE | _PAGE_USER) --#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC) -+#define PAGE_COPY_X __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_EXEC | _PAGE_HWEXEC) -+ -+#if defined(CONFIG_PAX_PAGEEXEC) && !defined(CONFIG_40x) && !defined(CONFIG_44x) -+# define PAGE_SHARED_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_RW | _PAGE_GUARDED) -+# define PAGE_COPY_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED) -+# define PAGE_READONLY_NOEXEC __pgprot(_PAGE_BASE | _PAGE_USER | _PAGE_GUARDED) -+#else -+# define PAGE_SHARED_NOEXEC PAGE_SHARED -+# define PAGE_COPY_NOEXEC PAGE_COPY -+# define PAGE_READONLY_NOEXEC PAGE_READONLY -+#endif - - #define PAGE_KERNEL __pgprot(_PAGE_RAM) - #define PAGE_KERNEL_NOCACHE __pgprot(_PAGE_IO) -@@ -365,21 +375,21 @@ - * This is the closest we can get.. - */ - #define __P000 PAGE_NONE --#define __P001 PAGE_READONLY_X --#define __P010 PAGE_COPY --#define __P011 PAGE_COPY_X --#define __P100 PAGE_READONLY -+#define __P001 PAGE_READONLY_NOEXEC -+#define __P010 PAGE_COPY_NOEXEC -+#define __P011 PAGE_COPY_NOEXEC -+#define __P100 PAGE_READONLY_X - #define __P101 PAGE_READONLY_X --#define __P110 PAGE_COPY -+#define __P110 PAGE_COPY_X - #define __P111 PAGE_COPY_X - - #define __S000 PAGE_NONE --#define __S001 PAGE_READONLY_X --#define __S010 PAGE_SHARED --#define __S011 PAGE_SHARED_X --#define __S100 PAGE_READONLY -+#define __S001 PAGE_READONLY_NOEXEC -+#define __S010 PAGE_SHARED_NOEXEC -+#define __S011 PAGE_SHARED_NOEXEC -+#define __S100 PAGE_READONLY_X - #define __S101 PAGE_READONLY_X --#define __S110 PAGE_SHARED -+#define __S110 PAGE_SHARED_X - #define __S111 PAGE_SHARED_X - - #ifndef __ASSEMBLY__ -diff -urN linux-2.6.5/include/asm-sparc/a.out.h linux-2.6.5/include/asm-sparc/a.out.h ---- linux-2.6.5/include/asm-sparc/a.out.h 2004-04-03 22:36:16.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc/a.out.h 2004-04-18 11:05:51.000000000 -0400 -@@ -91,7 +91,7 @@ - - #include <asm/page.h> - --#define STACK_TOP (PAGE_OFFSET - PAGE_SIZE) -+#define __STACK_TOP (PAGE_OFFSET - PAGE_SIZE) - - #endif /* __KERNEL__ */ - -diff -urN linux-2.6.5/include/asm-sparc/elf.h linux-2.6.5/include/asm-sparc/elf.h ---- linux-2.6.5/include/asm-sparc/elf.h 2004-04-03 22:37:43.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc/elf.h 2004-04-18 11:05:51.000000000 -0400 -@@ -145,6 +145,17 @@ - - #define ELF_ET_DYN_BASE (0x08000000) - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) 0x10000UL -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) 16 -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) 16 -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) 16 -+#endif -+ - /* This yields a mask that user programs can use to figure out what - instruction set this cpu supports. This can NOT be done in userspace - on Sparc. */ -diff -urN linux-2.6.5/include/asm-sparc/mman.h linux-2.6.5/include/asm-sparc/mman.h ---- linux-2.6.5/include/asm-sparc/mman.h 2004-04-03 22:38:20.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc/mman.h 2004-04-18 11:05:51.000000000 -0400 -@@ -27,6 +27,10 @@ - #define MAP_DENYWRITE 0x0800 /* ETXTBSY */ - #define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ - -+#ifdef CONFIG_PAX_RANDEXEC -+#define MAP_MIRROR 0x0400 -+#endif -+ - #define MS_ASYNC 1 /* sync memory asynchronously */ - #define MS_INVALIDATE 2 /* invalidate the caches */ - #define MS_SYNC 4 /* synchronous memory sync */ -diff -urN linux-2.6.5/include/asm-sparc/page.h linux-2.6.5/include/asm-sparc/page.h ---- linux-2.6.5/include/asm-sparc/page.h 2004-04-03 22:36:53.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc/page.h 2004-04-18 11:05:51.000000000 -0400 -@@ -176,6 +176,15 @@ - #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -+#ifdef CONFIG_PAX_PAGEEXEC -+#ifdef CONFIG_PAX_MPROTECT -+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \ -+ ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#else -+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#endif -+#endif -+ - #endif /* __KERNEL__ */ - - #endif /* _SPARC_PAGE_H */ -diff -urN linux-2.6.5/include/asm-sparc/pgtable.h linux-2.6.5/include/asm-sparc/pgtable.h ---- linux-2.6.5/include/asm-sparc/pgtable.h 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc/pgtable.h 2004-04-18 11:05:51.000000000 -0400 -@@ -109,6 +109,13 @@ - BTFIXUPDEF_INT(page_shared) - BTFIXUPDEF_INT(page_copy) - BTFIXUPDEF_INT(page_readonly) -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+BTFIXUPDEF_INT(page_shared_noexec) -+BTFIXUPDEF_INT(page_copy_noexec) -+BTFIXUPDEF_INT(page_readonly_noexec) -+#endif -+ - BTFIXUPDEF_INT(page_kernel) - - #define PMD_SHIFT BTFIXUP_SIMM13(pmd_shift) -@@ -130,6 +137,16 @@ - #define PAGE_COPY __pgprot(BTFIXUP_INT(page_copy)) - #define PAGE_READONLY __pgprot(BTFIXUP_INT(page_readonly)) - -+#ifdef CONFIG_PAX_PAGEEXEC -+# define PAGE_SHARED_NOEXEC __pgprot(BTFIXUP_INT(page_shared_noexec)) -+# define PAGE_COPY_NOEXEC __pgprot(BTFIXUP_INT(page_copy_noexec)) -+# define PAGE_READONLY_NOEXEC __pgprot(BTFIXUP_INT(page_readonly_noexec)) -+#else -+# define PAGE_SHARED_NOEXEC PAGE_SHARED -+# define PAGE_COPY_NOEXEC PAGE_COPY -+# define PAGE_READONLY_NOEXEC PAGE_READONLY -+#endif -+ - extern unsigned long page_kernel; - - #ifdef MODULE -diff -urN linux-2.6.5/include/asm-sparc/pgtsrmmu.h linux-2.6.5/include/asm-sparc/pgtsrmmu.h ---- linux-2.6.5/include/asm-sparc/pgtsrmmu.h 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc/pgtsrmmu.h 2004-04-18 11:05:51.000000000 -0400 -@@ -103,6 +103,16 @@ - SRMMU_EXEC | SRMMU_REF) - #define SRMMU_PAGE_RDONLY __pgprot(SRMMU_VALID | SRMMU_CACHE | \ - SRMMU_EXEC | SRMMU_REF) -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+#define SRMMU_PAGE_SHARED_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \ -+ SRMMU_WRITE | SRMMU_REF) -+#define SRMMU_PAGE_COPY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \ -+ SRMMU_REF) -+#define SRMMU_PAGE_RDONLY_NOEXEC __pgprot(SRMMU_VALID | SRMMU_CACHE | \ -+ SRMMU_REF) -+#endif -+ - #define SRMMU_PAGE_KERNEL __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \ - SRMMU_DIRTY | SRMMU_REF) - -diff -urN linux-2.6.5/include/asm-sparc/uaccess.h linux-2.6.5/include/asm-sparc/uaccess.h ---- linux-2.6.5/include/asm-sparc/uaccess.h 2004-04-03 22:38:14.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc/uaccess.h 2004-04-18 11:05:51.000000000 -0400 -@@ -41,7 +41,7 @@ - * No one can read/write anything from userland in the kernel space by setting - * large size and address near to PAGE_OFFSET - a fault will break his intentions. - */ --#define __user_ok(addr,size) ((addr) < STACK_TOP) -+#define __user_ok(addr,size) ((addr) < __STACK_TOP) - #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS)) - #define __access_ok(addr,size) (__user_ok((addr) & get_fs().seg,(size))) - #define access_ok(type,addr,size) __access_ok((unsigned long)(addr),(size)) -diff -urN linux-2.6.5/include/asm-sparc64/a.out.h linux-2.6.5/include/asm-sparc64/a.out.h ---- linux-2.6.5/include/asm-sparc64/a.out.h 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc64/a.out.h 2004-04-18 11:05:51.000000000 -0400 -@@ -95,7 +95,7 @@ - - #ifdef __KERNEL__ - --#define STACK_TOP (test_thread_flag(TIF_32BIT) ? 0xf0000000 : 0x80000000000L) -+#define __STACK_TOP (test_thread_flag(TIF_32BIT) ? 0xf0000000 : 0x80000000000L) - - #endif - -diff -urN linux-2.6.5/include/asm-sparc64/elf.h linux-2.6.5/include/asm-sparc64/elf.h ---- linux-2.6.5/include/asm-sparc64/elf.h 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc64/elf.h 2004-04-18 11:05:51.000000000 -0400 -@@ -140,6 +140,16 @@ - #define ELF_ET_DYN_BASE 0x0000010000000000UL - #endif - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_32BIT) ? 0x10000UL : 0x100000UL) -+ -+#define PAX_DELTA_MMAP_LSB(tsk) (PAGE_SHIFT + 1) -+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 14 : 28 ) -+#define PAX_DELTA_EXEC_LSB(tsk) (PAGE_SHIFT + 1) -+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 14 : 28 ) -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_32BIT) ? 15 : 29 ) -+#endif - - /* This yields a mask that user programs can use to figure out what - instruction set this cpu supports. */ -diff -urN linux-2.6.5/include/asm-sparc64/mman.h linux-2.6.5/include/asm-sparc64/mman.h ---- linux-2.6.5/include/asm-sparc64/mman.h 2004-04-03 22:37:06.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc64/mman.h 2004-04-18 11:05:51.000000000 -0400 -@@ -27,6 +27,10 @@ - #define MAP_DENYWRITE 0x0800 /* ETXTBSY */ - #define MAP_EXECUTABLE 0x1000 /* mark it as an executable */ - -+#ifdef CONFIG_PAX_RANDEXEC -+#define MAP_MIRROR 0x0400 -+#endif -+ - #define MS_ASYNC 1 /* sync memory asynchronously */ - #define MS_INVALIDATE 2 /* invalidate the caches */ - #define MS_SYNC 4 /* synchronous memory sync */ -diff -urN linux-2.6.5/include/asm-sparc64/page.h linux-2.6.5/include/asm-sparc64/page.h ---- linux-2.6.5/include/asm-sparc64/page.h 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc64/page.h 2004-04-18 11:05:51.000000000 -0400 -@@ -174,6 +174,15 @@ - #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -+#ifdef CONFIG_PAX_PAGEEXEC -+#ifdef CONFIG_PAX_MPROTECT -+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \ -+ ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#else -+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#endif -+#endif -+ - #endif /* !(__KERNEL__) */ - - #endif /* !(_SPARC64_PAGE_H) */ -diff -urN linux-2.6.5/include/asm-sparc64/pgtable.h linux-2.6.5/include/asm-sparc64/pgtable.h ---- linux-2.6.5/include/asm-sparc64/pgtable.h 2004-04-03 22:36:14.000000000 -0500 -+++ linux-2.6.5/include/asm-sparc64/pgtable.h 2004-04-18 11:05:51.000000000 -0400 -@@ -124,7 +124,8 @@ - - /* Here are the SpitFire software bits we use in the TTE's. */ - #define _PAGE_FILE 0x0000000000001000 /* Pagecache page */ --#define _PAGE_MODIFIED 0x0000000000000800 /* Modified Page (ie. dirty) */ -+#define _PAGE_MODIFIED 0x0000000000001000 /* Modified Page (ie. dirty) */ -+#define _PAGE_EXEC 0x0000000000000800 /* Executable SW Bit */ - #define _PAGE_ACCESSED 0x0000000000000400 /* Accessed Page (ie. referenced) */ - #define _PAGE_READ 0x0000000000000200 /* Readable SW Bit */ - #define _PAGE_WRITE 0x0000000000000100 /* Writable SW Bit */ -@@ -160,34 +161,48 @@ - - /* Don't set the TTE _PAGE_W bit here, else the dirty bit never gets set. */ - #define PAGE_SHARED __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ -- __ACCESS_BITS | _PAGE_WRITE) -+ __ACCESS_BITS | _PAGE_WRITE | _PAGE_EXEC) - - #define PAGE_COPY __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ -- __ACCESS_BITS) -+ __ACCESS_BITS | _PAGE_EXEC) - - #define PAGE_READONLY __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ -- __ACCESS_BITS) -+ __ACCESS_BITS | _PAGE_EXEC) - - #define PAGE_KERNEL __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ -- __PRIV_BITS | __ACCESS_BITS | __DIRTY_BITS) -+ __PRIV_BITS | __ACCESS_BITS | __DIRTY_BITS | \ -+ _PAGE_EXEC) -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+# define PAGE_SHARED_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ -+ __ACCESS_BITS | _PAGE_WRITE) -+# define PAGE_COPY_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ -+ __ACCESS_BITS) -+# define PAGE_READONLY_NOEXEC __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \ -+ __ACCESS_BITS) -+#else -+# define PAGE_SHARED_NOEXEC PAGE_SHARED -+# define PAGE_COPY_NOEXEC PAGE_COPY -+# define PAGE_READONLY_NOEXEC PAGE_READONLY -+#endif - - #define _PFN_MASK _PAGE_PADDR - - #define pg_iobits (_PAGE_VALID | _PAGE_PRESENT | __DIRTY_BITS | __ACCESS_BITS | _PAGE_E) - - #define __P000 PAGE_NONE --#define __P001 PAGE_READONLY --#define __P010 PAGE_COPY --#define __P011 PAGE_COPY -+#define __P001 PAGE_READONLY_NOEXEC -+#define __P010 PAGE_COPY_NOEXEC -+#define __P011 PAGE_COPY_NOEXEC - #define __P100 PAGE_READONLY - #define __P101 PAGE_READONLY - #define __P110 PAGE_COPY - #define __P111 PAGE_COPY - - #define __S000 PAGE_NONE --#define __S001 PAGE_READONLY --#define __S010 PAGE_SHARED --#define __S011 PAGE_SHARED -+#define __S001 PAGE_READONLY_NOEXEC -+#define __S010 PAGE_SHARED_NOEXEC -+#define __S011 PAGE_SHARED_NOEXEC - #define __S100 PAGE_READONLY - #define __S101 PAGE_READONLY - #define __S110 PAGE_SHARED -diff -urN linux-2.6.5/include/asm-x86_64/a.out.h linux-2.6.5/include/asm-x86_64/a.out.h ---- linux-2.6.5/include/asm-x86_64/a.out.h 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/include/asm-x86_64/a.out.h 2004-04-18 11:05:51.000000000 -0400 -@@ -21,7 +21,7 @@ - - #ifdef __KERNEL__ - #include <linux/thread_info.h> --#define STACK_TOP (test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE) -+#define __STACK_TOP (test_thread_flag(TIF_IA32) ? IA32_PAGE_OFFSET : TASK_SIZE) - #endif - - #endif /* __A_OUT_GNU_H__ */ -diff -urN linux-2.6.5/include/asm-x86_64/elf.h linux-2.6.5/include/asm-x86_64/elf.h ---- linux-2.6.5/include/asm-x86_64/elf.h 2004-04-03 22:37:44.000000000 -0500 -+++ linux-2.6.5/include/asm-x86_64/elf.h 2004-04-18 11:05:51.000000000 -0400 -@@ -89,6 +89,17 @@ - - #define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3) - -+#ifdef CONFIG_PAX_ASLR -+#define PAX_ELF_ET_DYN_BASE(tsk) (test_thread_flag(TIF_IA32) ? 0x08048000UL : 0x400000UL) -+ -+#define PAX_DELTA_MMAP_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_MMAP_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 24) -+#define PAX_DELTA_EXEC_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_EXEC_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 24) -+#define PAX_DELTA_STACK_LSB(tsk) PAGE_SHIFT -+#define PAX_DELTA_STACK_LEN(tsk) (test_thread_flag(TIF_IA32) ? 16 : 24) -+#endif -+ - /* regs is struct pt_regs, pr_reg is elf_gregset_t (which is - now struct_user_regs, they are different). Assumes current is the process - getting dumped. */ -diff -urN linux-2.6.5/include/asm-x86_64/mman.h linux-2.6.5/include/asm-x86_64/mman.h ---- linux-2.6.5/include/asm-x86_64/mman.h 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/include/asm-x86_64/mman.h 2004-04-18 11:05:51.000000000 -0400 -@@ -24,6 +24,10 @@ - #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ - #define MAP_NONBLOCK 0x10000 /* do not block on IO */ - -+#ifdef CONFIG_PAX_RANDEXEC -+#define MAP_MIRROR 0x8000 -+#endif -+ - #define MS_ASYNC 1 /* sync memory asynchronously */ - #define MS_INVALIDATE 2 /* invalidate the caches */ - #define MS_SYNC 4 /* synchronous memory sync */ -diff -urN linux-2.6.5/include/asm-x86_64/page.h linux-2.6.5/include/asm-x86_64/page.h ---- linux-2.6.5/include/asm-x86_64/page.h 2004-04-03 22:36:16.000000000 -0500 -+++ linux-2.6.5/include/asm-x86_64/page.h 2004-04-18 11:05:51.000000000 -0400 -@@ -127,6 +127,16 @@ - - #define __VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+#define VM_DATA_DEFAULT_FLAGS __VM_DATA_DEFAULT_FLAGS -+#ifdef CONFIG_PAX_MPROTECT -+#define __VM_STACK_FLAGS (((current->flags & PF_PAX_MPROTECT)?0:VM_MAYEXEC) | \ -+ ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#else -+#define __VM_STACK_FLAGS (VM_MAYEXEC | ((current->flags & PF_PAX_PAGEEXEC)?0:VM_EXEC)) -+#endif -+#else - #define __VM_STACK_FLAGS (VM_GROWSDOWN | VM_READ | VM_WRITE | VM_EXEC | \ - VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) - -@@ -137,6 +147,8 @@ - #define VM_STACK_DEFAULT_FLAGS \ - (test_thread_flag(TIF_IA32) ? vm_stack_flags32 : vm_stack_flags) - -+#endif -+ - #define CONFIG_ARCH_GATE_AREA 1 - - #ifndef __ASSEMBLY__ -diff -urN linux-2.6.5/include/asm-x86_64/pgalloc.h linux-2.6.5/include/asm-x86_64/pgalloc.h ---- linux-2.6.5/include/asm-x86_64/pgalloc.h 2004-04-03 22:37:07.000000000 -0500 -+++ linux-2.6.5/include/asm-x86_64/pgalloc.h 2004-04-18 11:05:51.000000000 -0400 -@@ -8,7 +8,7 @@ - #include <linux/mm.h> - - #define pmd_populate_kernel(mm, pmd, pte) \ -- set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte))) -+ set_pmd(pmd, __pmd(_KERNPG_TABLE | __pa(pte))) - #define pgd_populate(mm, pgd, pmd) \ - set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pmd))) - -diff -urN linux-2.6.5/include/asm-x86_64/pgtable.h linux-2.6.5/include/asm-x86_64/pgtable.h ---- linux-2.6.5/include/asm-x86_64/pgtable.h 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/include/asm-x86_64/pgtable.h 2004-04-18 11:05:51.000000000 -0400 -@@ -170,6 +170,10 @@ - #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) - #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX) - #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) -+ -+#define PAGE_READONLY_NOEXEC PAGE_READONLY -+#define PAGE_SHARED_NOEXEC PAGE_SHARED -+ - #define __PAGE_KERNEL \ - (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX) - #define __PAGE_KERNEL_EXECUTABLE \ -diff -urN linux-2.6.5/include/linux/a.out.h linux-2.6.5/include/linux/a.out.h ---- linux-2.6.5/include/linux/a.out.h 2004-04-03 22:37:24.000000000 -0500 -+++ linux-2.6.5/include/linux/a.out.h 2004-04-18 11:05:51.000000000 -0400 -@@ -7,6 +7,16 @@ - - #include <asm/a.out.h> - -+#ifdef CONFIG_PAX_RANDUSTACK -+#define __DELTA_STACK (current->mm->delta_stack) -+#else -+#define __DELTA_STACK 0UL -+#endif -+ -+#ifndef STACK_TOP -+#define STACK_TOP (__STACK_TOP - __DELTA_STACK) -+#endif -+ - #endif /* __STRUCT_EXEC_OVERRIDE__ */ - - /* these go in the N_MACHTYPE field */ -@@ -37,6 +47,14 @@ - M_MIPS2 = 152 /* MIPS R6000/R4000 binary */ - }; - -+/* Constants for the N_FLAGS field */ -+#define F_PAX_PAGEEXEC 1 /* Paging based non-executable pages */ -+#define F_PAX_EMUTRAMP 2 /* Emulate trampolines */ -+#define F_PAX_MPROTECT 4 /* Restrict mprotect() */ -+#define F_PAX_RANDMMAP 8 /* Randomize mmap() base */ -+#define F_PAX_RANDEXEC 16 /* Randomize ET_EXEC base */ -+#define F_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */ -+ - #if !defined (N_MAGIC) - #define N_MAGIC(exec) ((exec).a_info & 0xffff) - #endif -diff -urN linux-2.6.5/include/linux/binfmts.h linux-2.6.5/include/linux/binfmts.h ---- linux-2.6.5/include/linux/binfmts.h 2004-04-03 22:37:07.000000000 -0500 -+++ linux-2.6.5/include/linux/binfmts.h 2004-04-18 11:05:51.000000000 -0400 -@@ -36,6 +36,7 @@ - of the time same as filename, but could be - different for binfmt_{misc,script} */ - unsigned long loader, exec; -+ int misc; - }; - - /* -@@ -65,5 +66,8 @@ - extern int do_coredump(long signr, int exit_code, struct pt_regs * regs); - extern int set_binfmt(struct linux_binfmt *new); - -+void pax_report_fault(struct pt_regs *regs, void *pc, void *sp); -+void pax_report_insns(void *pc, void *sp); -+ - #endif /* __KERNEL__ */ - #endif /* _LINUX_BINFMTS_H */ -diff -urN linux-2.6.5/include/linux/elf.h linux-2.6.5/include/linux/elf.h ---- linux-2.6.5/include/linux/elf.h 2004-04-03 22:36:25.000000000 -0500 -+++ linux-2.6.5/include/linux/elf.h 2004-04-18 11:05:51.000000000 -0400 -@@ -35,6 +35,17 @@ - #define PT_HIPROC 0x7fffffff - #define PT_GNU_EH_FRAME 0x6474e550 - -+#define PT_GNU_STACK (PT_LOOS + 0x474e551) -+#define PT_PAX_FLAGS (PT_LOOS + 0x5041580) -+ -+/* Constants for the e_flags field */ -+#define EF_PAX_PAGEEXEC 1 /* Paging based non-executable pages */ -+#define EF_PAX_EMUTRAMP 2 /* Emulate trampolines */ -+#define EF_PAX_MPROTECT 4 /* Restrict mprotect() */ -+#define EF_PAX_RANDMMAP 8 /* Randomize mmap() base */ -+#define EF_PAX_RANDEXEC 16 /* Randomize ET_EXEC base */ -+#define EF_PAX_SEGMEXEC 32 /* Segmentation based non-executable pages */ -+ - /* These constants define the different elf file types */ - #define ET_NONE 0 - #define ET_REL 1 -@@ -121,6 +132,8 @@ - #define DT_DEBUG 21 - #define DT_TEXTREL 22 - #define DT_JMPREL 23 -+#define DT_FLAGS 30 -+ #define DF_TEXTREL 0x00000004 - #define DT_LOPROC 0x70000000 - #define DT_HIPROC 0x7fffffff - -@@ -271,6 +284,19 @@ - #define PF_W 0x2 - #define PF_X 0x1 - -+#define PF_PAGEEXEC (1 << 4) /* Enable PAGEEXEC */ -+#define PF_NOPAGEEXEC (1 << 5) /* Disable PAGEEXEC */ -+#define PF_SEGMEXEC (1 << 6) /* Enable SEGMEXEC */ -+#define PF_NOSEGMEXEC (1 << 7) /* Disable SEGMEXEC */ -+#define PF_MPROTECT (1 << 8) /* Enable MPROTECT */ -+#define PF_NOMPROTECT (1 << 9) /* Disable MPROTECT */ -+#define PF_RANDEXEC (1 << 10) /* Enable RANDEXEC */ -+#define PF_NORANDEXEC (1 << 11) /* Disable RANDEXEC */ -+#define PF_EMUTRAMP (1 << 12) /* Enable EMUTRAMP */ -+#define PF_NOEMUTRAMP (1 << 13) /* Disable EMUTRAMP */ -+#define PF_RANDMMAP (1 << 14) /* Enable RANDMMAP */ -+#define PF_NORANDMMAP (1 << 15) /* Disable RANDMMAP */ -+ - typedef struct elf32_phdr{ - Elf32_Word p_type; - Elf32_Off p_offset; -@@ -363,6 +389,8 @@ - #define EI_OSABI 7 - #define EI_PAD 8 - -+#define EI_PAX 14 -+ - #define ELFMAG0 0x7f /* EI_MAG */ - #define ELFMAG1 'E' - #define ELFMAG2 'L' -@@ -419,6 +447,7 @@ - #define elfhdr elf32_hdr - #define elf_phdr elf32_phdr - #define elf_note elf32_note -+#define elf_dyn Elf32_Dyn - - #else - -@@ -426,6 +455,7 @@ - #define elfhdr elf64_hdr - #define elf_phdr elf64_phdr - #define elf_note elf64_note -+#define elf_dyn Elf64_Dyn - - #endif - -diff -urN linux-2.6.5/include/linux/fs.h linux-2.6.5/include/linux/fs.h ---- linux-2.6.5/include/linux/fs.h 2004-04-03 22:36:52.000000000 -0500 -+++ linux-2.6.5/include/linux/fs.h 2004-04-18 11:05:51.000000000 -0400 -@@ -1134,7 +1134,7 @@ - - /* fs/open.c */ - --extern int do_truncate(struct dentry *, loff_t start); -+extern int do_truncate(struct dentry *, loff_t start, struct vfsmount *); - extern struct file *filp_open(const char *, int, int); - extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); - extern int filp_close(struct file *, fl_owner_t id); -diff -urN linux-2.6.5/include/linux/gracl.h linux-2.6.5/include/linux/gracl.h ---- linux-2.6.5/include/linux/gracl.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/include/linux/gracl.h 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,246 @@ -+#ifndef GR_ACL_H -+#define GR_ACL_H -+#endif -+#include <linux/grdefs.h> -+#include <linux/resource.h> -+#include <linux/dcache.h> -+#include <asm/resource.h> -+ -+/* * * * * * * * * * * * * * * * * * * * * -+ * grsecurity ACL System -+ * Main header file -+ * Purpose: define most gracl data structures -+ * * * * * * * * * * * * * * * * * * * * */ -+ -+/* Major status information */ -+ -+#define GR_VERSION "grsecurity 2.0" -+ -+enum { -+ -+ SHUTDOWN = 0, -+ ENABLE = 1, -+ SPROLE = 2, -+ RELOAD = 3, -+ SEGVMOD = 4, -+ STATUS = 5, -+ UNSPROLE = 6 -+}; -+ -+/* Password setup definitions -+ * kernel/grhash.c */ -+enum { -+ GR_PW_LEN = 128, -+ GR_SALT_LEN = 16, -+ GR_SHA_LEN = 32, -+}; -+ -+enum { -+ GR_SPROLE_LEN = 64, -+}; -+ -+/* Begin Data Structures */ -+ -+struct sprole_pw { -+ unsigned char *rolename; -+ unsigned char salt[GR_SALT_LEN]; -+ unsigned char sum[GR_SHA_LEN]; /* 256-bit SHA hash of the password */ -+}; -+ -+struct name_entry { -+ ino_t inode; -+ dev_t device; -+ char *name; -+ __u16 len; -+}; -+ -+struct acl_role_db { -+ struct acl_role_label **r_hash; -+ __u32 r_size; -+}; -+ -+struct name_db { -+ struct name_entry **n_hash; -+ __u32 n_size; -+}; -+ -+struct crash_uid { -+ uid_t uid; -+ unsigned long expires; -+}; -+ -+struct gr_hash_struct { -+ void **table; -+ void **nametable; -+ void *first; -+ __u32 table_size; -+ __u32 used_size; -+ int type; -+}; -+ -+/* Userspace Grsecurity ACL data structures */ -+struct acl_subject_label { -+ char *filename; -+ ino_t inode; -+ dev_t device; -+ __u32 mode; -+ __u32 cap_mask; -+ __u32 cap_lower; -+ -+ struct rlimit res[RLIM_NLIMITS + 1]; -+ __u16 resmask; -+ -+ __u8 user_trans_type; -+ __u8 group_trans_type; -+ uid_t *user_transitions; -+ gid_t *group_transitions; -+ __u16 user_trans_num; -+ __u16 group_trans_num; -+ -+ __u32 ip_proto[8]; -+ __u32 ip_type; -+ struct acl_ip_label **ips; -+ __u32 ip_num; -+ -+ __u32 crashes; -+ unsigned long expires; -+ -+ struct acl_subject_label *parent_subject; -+ struct gr_hash_struct *hash; -+ struct acl_ip_label *ip_object; -+ struct acl_subject_label *prev; -+ struct acl_subject_label *next; -+ -+ struct acl_object_label **obj_hash; -+ __u32 obj_hash_size; -+}; -+ -+struct role_allowed_ip { -+ __u32 addr; -+ __u32 netmask; -+ -+ struct role_allowed_ip *prev; -+ struct role_allowed_ip *next; -+}; -+ -+struct role_transition { -+ char *rolename; -+ -+ struct role_transition *prev; -+ struct role_transition *next; -+}; -+ -+struct acl_role_label { -+ char *rolename; -+ uid_t uidgid; -+ __u16 roletype; -+ -+ __u16 auth_attempts; -+ unsigned long expires; -+ -+ struct acl_subject_label *root_label; -+ struct gr_hash_struct *hash; -+ -+ struct acl_role_label *prev; -+ struct acl_role_label *next; -+ -+ struct role_transition *transitions; -+ struct role_allowed_ip *allowed_ips; -+ struct acl_subject_label **subj_hash; -+ __u32 subj_hash_size; -+}; -+ -+struct user_acl_role_db { -+ struct acl_role_label **r_table; -+ __u32 r_entries; /* number of entries in table */ -+ __u32 s_entries; /* total number of subject acls */ -+ __u32 i_entries; /* total number of ip acls */ -+ __u32 o_entries; /* Total number of object acls */ -+ __u32 g_entries; /* total number of globbed objects */ -+ __u32 a_entries; /* total number of allowed ips */ -+ __u32 t_entries; /* total number of transitions */ -+}; -+ -+struct acl_object_label { -+ char *filename; -+ ino_t inode; -+ dev_t device; -+ __u32 mode; -+ -+ struct acl_subject_label *nested; -+ struct acl_object_label *globbed; -+ -+ /* next two structures not used */ -+ -+ struct acl_object_label *prev; -+ struct acl_object_label *next; -+}; -+ -+struct acl_ip_label { -+ __u32 addr; -+ __u32 netmask; -+ __u16 low, high; -+ __u8 mode; -+ __u32 type; -+ __u32 proto[8]; -+ -+ /* next two structures not used */ -+ -+ struct acl_ip_label *prev; -+ struct acl_ip_label *next; -+}; -+ -+struct gr_arg { -+ struct user_acl_role_db role_db; -+ unsigned char pw[GR_PW_LEN]; -+ unsigned char salt[GR_SALT_LEN]; -+ unsigned char sum[GR_SHA_LEN]; -+ unsigned char sp_role[GR_SPROLE_LEN]; -+ struct sprole_pw *sprole_pws; -+ dev_t segv_device; -+ ino_t segv_inode; -+ uid_t segv_uid; -+ __u16 num_sprole_pws; -+ __u16 mode; -+}; -+ -+struct subject_map { -+ struct acl_subject_label *user; -+ struct acl_subject_label *kernel; -+}; -+ -+struct acl_subj_map_db { -+ struct subject_map **s_hash; -+ __u32 s_size; -+}; -+ -+/* End Data Structures Section */ -+ -+/* Hash functions generated by empirical testing by Brad Spengler -+ Makes good use of the low bits of the inode. Generally 0-1 times -+ in loop for successful match. 0-3 for unsuccessful match. -+ Shift/add algorithm with modulus of table size and an XOR*/ -+ -+static __inline__ unsigned long -+rhash(const uid_t uid, const __u16 type, const unsigned long sz) -+{ -+ return (((uid << type) + (uid ^ type)) % sz); -+} -+ -+ static __inline__ unsigned long -+shash(const struct acl_subject_label *userp, const unsigned long sz) -+{ -+ return ((const unsigned long)userp % sz); -+} -+ -+static __inline__ unsigned long -+fhash(const ino_t ino, const dev_t dev, const unsigned long sz) -+{ -+ return (((ino + dev) ^ ((ino << 13) + (ino << 23) + (dev << 9))) % sz); -+} -+ -+static __inline__ unsigned long -+nhash(const char *name, const __u16 len, const unsigned long sz) -+{ -+ return full_name_hash(name, len) % sz; -+} -diff -urN linux-2.6.5/include/linux/gralloc.h linux-2.6.5/include/linux/gralloc.h ---- linux-2.6.5/include/linux/gralloc.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/include/linux/gralloc.h 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,8 @@ -+#ifndef __GRALLOC_H -+#define __GRALLOC_H -+ -+void acl_free_all(void); -+int acl_alloc_stack_init(unsigned long size); -+void *acl_alloc(unsigned long len); -+ -+#endif -diff -urN linux-2.6.5/include/linux/grdefs.h linux-2.6.5/include/linux/grdefs.h ---- linux-2.6.5/include/linux/grdefs.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/include/linux/grdefs.h 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,116 @@ -+#ifndef GRDEFS_H -+#define GRDEFS_H -+ -+/* Begin grsecurity status declarations */ -+ -+enum { -+ GR_READY = 0x01, -+ GR_STATUS_INIT = 0x00 // disabled state -+}; -+ -+/* Begin ACL declarations */ -+ -+/* Role flags */ -+ -+enum { -+ GR_ROLE_USER = 0x0001, -+ GR_ROLE_GROUP = 0x0002, -+ GR_ROLE_DEFAULT = 0x0004, -+ GR_ROLE_SPECIAL = 0x0008, -+ GR_ROLE_AUTH = 0x0010, -+ GR_ROLE_NOPW = 0x0020, -+ GR_ROLE_GOD = 0x0040, -+ GR_ROLE_LEARN = 0x0080, -+ GR_ROLE_TPE = 0x0100 -+}; -+ -+/* ACL Subject and Object mode flags */ -+enum { -+ GR_DELETED = 0x00000080 -+}; -+ -+/* ACL Object-only mode flags */ -+enum { -+ GR_READ = 0x00000001, -+ GR_APPEND = 0x00000002, -+ GR_WRITE = 0x00000004, -+ GR_EXEC = 0x00000008, -+ GR_FIND = 0x00000010, -+ GR_INHERIT = 0x00000040, -+ GR_PTRACERD = 0x00000100, -+ GR_SETID = 0x00000200, -+ GR_CREATE = 0x00000400, -+ GR_DELETE = 0x00000800, -+ GR_NOPTRACE = 0x00001000, -+ GR_AUDIT_READ = 0x00002000, -+ GR_AUDIT_APPEND = 0x00004000, -+ GR_AUDIT_WRITE = 0x00008000, -+ GR_AUDIT_EXEC = 0x00010000, -+ GR_AUDIT_FIND = 0x00020000, -+ GR_AUDIT_INHERIT= 0x00040000, -+ GR_AUDIT_SETID = 0x00080000, -+ GR_AUDIT_CREATE = 0x00100000, -+ GR_AUDIT_DELETE = 0x00200000, -+ GR_SUPPRESS = 0x00400000, -+ GR_NOLEARN = 0x00800000 -+}; -+ -+#define GR_AUDITS (GR_AUDIT_READ | GR_AUDIT_WRITE | GR_AUDIT_APPEND | GR_AUDIT_EXEC | \ -+ GR_AUDIT_FIND | GR_AUDIT_INHERIT | GR_AUDIT_SETID | \ -+ GR_AUDIT_CREATE | GR_AUDIT_DELETE) -+ -+/* ACL subject-only mode flags */ -+enum { -+ GR_KILL = 0x00000001, -+ GR_VIEW = 0x00000002, -+ GR_PROTECTED = 0x00000100, -+ GR_LEARN = 0x00000200, -+ GR_OVERRIDE = 0x00000400, -+ /* just a placeholder, this mode is only used in userspace */ -+ GR_DUMMY = 0x00000800, -+ GR_PAXPAGE = 0x00001000, -+ GR_PAXSEGM = 0x00002000, -+ GR_PAXGCC = 0x00004000, -+ GR_PAXRANDMMAP = 0x00008000, -+ GR_PAXRANDEXEC = 0x00010000, -+ GR_PAXMPROTECT = 0x00020000, -+ GR_PROTSHM = 0x00040000, -+ GR_KILLPROC = 0x00080000, -+ GR_KILLIPPROC = 0x00100000, -+ /* just a placeholder, this mode is only used in userspace */ -+ GR_NOTROJAN = 0x00200000, -+ GR_PROTPROCFD = 0x00400000, -+ GR_PROCACCT = 0x00800000, -+ GR_RELAXPTRACE = 0x01000000, -+ GR_NESTED = 0x02000000 -+}; -+ -+enum { -+ GR_ID_USER = 0x01, -+ GR_ID_GROUP = 0x02, -+}; -+ -+enum { -+ GR_ID_ALLOW = 0x01, -+ GR_ID_DENY = 0x02, -+}; -+ -+#define GR_CRASH_RES 11 -+#define GR_UIDTABLE_MAX 500 -+ -+/* begin resource learning section */ -+enum { -+ GR_RLIM_CPU_BUMP = 60, -+ GR_RLIM_FSIZE_BUMP = 50000, -+ GR_RLIM_DATA_BUMP = 10000, -+ GR_RLIM_STACK_BUMP = 1000, -+ GR_RLIM_CORE_BUMP = 10000, -+ GR_RLIM_RSS_BUMP = 500000, -+ GR_RLIM_NPROC_BUMP = 1, -+ GR_RLIM_NOFILE_BUMP = 5, -+ GR_RLIM_MEMLOCK_BUMP = 50000, -+ GR_RLIM_AS_BUMP = 500000, -+ GR_RLIM_LOCKS_BUMP = 2 -+}; -+ -+#endif -diff -urN linux-2.6.5/include/linux/grinternal.h linux-2.6.5/include/linux/grinternal.h ---- linux-2.6.5/include/linux/grinternal.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/include/linux/grinternal.h 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,201 @@ -+#ifndef __GRINTERNAL_H -+#define __GRINTERNAL_H -+ -+#ifdef CONFIG_GRKERNSEC -+ -+#include <linux/fs.h> -+#include <linux/grdefs.h> -+#include <linux/grmsg.h> -+ -+extern void gr_add_learn_entry(const char *fmt, ...); -+extern __u32 gr_search_file(const struct dentry *dentry, const __u32 mode, -+ const struct vfsmount *mnt); -+extern __u32 gr_check_create(const struct dentry *new_dentry, -+ const struct dentry *parent, -+ const struct vfsmount *mnt, const __u32 mode); -+extern int gr_check_protected_task(const struct task_struct *task); -+extern __u32 to_gr_audit(const __u32 reqmode); -+extern int gr_set_acls(const int type); -+ -+extern void gr_handle_alertkill(void); -+extern char *gr_to_filename(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern char *gr_to_filename1(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern char *gr_to_filename2(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern char *gr_to_filename3(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+ -+extern int grsec_enable_link; -+extern int grsec_enable_fifo; -+extern int grsec_enable_execve; -+extern int grsec_enable_forkbomb; -+extern int grsec_forkbomb_gid; -+extern int grsec_forkbomb_sec; -+extern int grsec_forkbomb_max; -+extern int grsec_enable_execlog; -+extern int grsec_enable_signal; -+extern int grsec_enable_forkfail; -+extern int grsec_enable_time; -+extern int grsec_enable_chroot_shmat; -+extern int grsec_enable_chroot_findtask; -+extern int grsec_enable_chroot_mount; -+extern int grsec_enable_chroot_double; -+extern int grsec_enable_chroot_pivot; -+extern int grsec_enable_chroot_chdir; -+extern int grsec_enable_chroot_chmod; -+extern int grsec_enable_chroot_mknod; -+extern int grsec_enable_chroot_fchdir; -+extern int grsec_enable_chroot_nice; -+extern int grsec_enable_chroot_execlog; -+extern int grsec_enable_chroot_caps; -+extern int grsec_enable_chroot_sysctl; -+extern int grsec_enable_chroot_unix; -+extern int grsec_enable_tpe; -+extern int grsec_tpe_gid; -+extern int grsec_enable_tpe_all; -+extern int grsec_enable_sidcaps; -+extern int grsec_enable_randpid; -+extern int grsec_enable_socket_all; -+extern int grsec_socket_all_gid; -+extern int grsec_enable_socket_client; -+extern int grsec_socket_client_gid; -+extern int grsec_enable_socket_server; -+extern int grsec_socket_server_gid; -+extern int grsec_audit_gid; -+extern int grsec_enable_group; -+extern int grsec_enable_audit_ipc; -+extern int grsec_enable_audit_textrel; -+extern int grsec_enable_mount; -+extern int grsec_enable_chdir; -+extern int grsec_lock; -+ -+extern struct task_struct *child_reaper; -+ -+extern spinlock_t grsec_alert_lock; -+extern unsigned long grsec_alert_wtime; -+extern unsigned long grsec_alert_fyet; -+ -+extern spinlock_t grsec_alertgood_lock; -+extern unsigned long grsec_alertgood_wtime; -+extern unsigned long grsec_alertgood_fyet; -+ -+extern spinlock_t grsec_audit_lock; -+ -+#define gr_task_fullpath(tsk) (tsk->exec_file ? \ -+ gr_to_filename2(tsk->exec_file->f_dentry, \ -+ tsk->exec_file->f_vfsmnt) : "/") -+ -+#define gr_parent_task_fullpath(tsk) (tsk->parent->exec_file ? \ -+ gr_to_filename3(tsk->parent->exec_file->f_dentry, \ -+ tsk->parent->exec_file->f_vfsmnt) : "/") -+ -+#define gr_task_fullpath0(tsk) (tsk->exec_file ? \ -+ gr_to_filename(tsk->exec_file->f_dentry, \ -+ tsk->exec_file->f_vfsmnt) : "/") -+ -+#define gr_parent_task_fullpath0(tsk) (tsk->parent->exec_file ? \ -+ gr_to_filename1(tsk->parent->exec_file->f_dentry, \ -+ tsk->parent->exec_file->f_vfsmnt) : "/") -+ -+#define proc_is_chrooted(tsk_a) ((tsk_a->pid > 1) && \ -+ ((tsk_a->fs->root->d_inode->i_sb->s_dev != \ -+ child_reaper->fs->root->d_inode->i_sb->s_dev) || \ -+ (tsk_a->fs->root->d_inode->i_ino != \ -+ child_reaper->fs->root->d_inode->i_ino))) -+ -+#define have_same_root(tsk_a,tsk_b) ((tsk_a->fs->root->d_inode->i_sb->s_dev == \ -+ tsk_b->fs->root->d_inode->i_sb->s_dev) && \ -+ (tsk_a->fs->root->d_inode->i_ino == \ -+ tsk_b->fs->root->d_inode->i_ino)) -+ -+#define DEFAULTSECARGS gr_task_fullpath(current), current->comm, \ -+ current->pid, current->uid, \ -+ current->euid, current->gid, current->egid, \ -+ gr_parent_task_fullpath(current), \ -+ current->parent->comm, current->parent->pid, \ -+ current->parent->uid, current->parent->euid, \ -+ current->parent->gid, current->parent->egid -+ -+#define GR_CHROOT_CAPS ( \ -+ CAP_TO_MASK(CAP_FOWNER) | \ -+ CAP_TO_MASK(CAP_LINUX_IMMUTABLE) | CAP_TO_MASK(CAP_NET_ADMIN) | \ -+ CAP_TO_MASK(CAP_SYS_MODULE) | CAP_TO_MASK(CAP_SYS_RAWIO) | \ -+ CAP_TO_MASK(CAP_SYS_PACCT) | CAP_TO_MASK(CAP_SYS_ADMIN) | \ -+ CAP_TO_MASK(CAP_SYS_BOOT) | CAP_TO_MASK(CAP_SYS_TIME) | \ -+ CAP_TO_MASK(CAP_NET_RAW) | CAP_TO_MASK(CAP_SYS_TTY_CONFIG) | \ -+ CAP_TO_MASK(CAP_IPC_OWNER)) -+ -+#define security_alert_good(normal_msg,args...) \ -+({ \ -+ spin_lock(&grsec_alertgood_lock); \ -+ \ -+ if (!grsec_alertgood_wtime || get_seconds() - grsec_alertgood_wtime > CONFIG_GRKERNSEC_FLOODTIME) { \ -+ grsec_alertgood_wtime = get_seconds(); grsec_alertgood_fyet = 0; \ -+ if (current->curr_ip) \ -+ printk(KERN_ALERT "grsec: From %u.%u.%u.%u: " normal_msg "\n", NIPQUAD(current->curr_ip) , ## args); \ -+ else \ -+ printk(KERN_ALERT "grsec: " normal_msg "\n" , ## args); \ -+ } else if((get_seconds() - grsec_alertgood_wtime < CONFIG_GRKERNSEC_FLOODTIME) && (grsec_alertgood_fyet < CONFIG_GRKERNSEC_FLOODBURST)) { \ -+ grsec_alertgood_fyet++; \ -+ if (current->curr_ip) \ -+ printk(KERN_ALERT "grsec: From %u.%u.%u.%u: " normal_msg "\n", NIPQUAD(current->curr_ip) , ## args); \ -+ else \ -+ printk(KERN_ALERT "grsec: " normal_msg "\n" , ## args); \ -+ } else if (grsec_alertgood_fyet == CONFIG_GRKERNSEC_FLOODBURST) { \ -+ grsec_alertgood_wtime = get_seconds(); grsec_alertgood_fyet++; \ -+ printk(KERN_ALERT "grsec: more alerts, logging disabled for " \ -+ "%d seconds\n", CONFIG_GRKERNSEC_FLOODTIME); \ -+ } \ -+ \ -+ spin_unlock(&grsec_alertgood_lock); \ -+}) -+ -+#define security_alert(normal_msg,args...) \ -+({ \ -+ spin_lock(&grsec_alert_lock); \ -+ \ -+ if (!grsec_alert_wtime || get_seconds() - grsec_alert_wtime > CONFIG_GRKERNSEC_FLOODTIME) { \ -+ grsec_alert_wtime = get_seconds(); grsec_alert_fyet = 0; \ -+ if (current->curr_ip) \ -+ printk(KERN_ALERT "grsec: From %u.%u.%u.%u: " normal_msg "\n", NIPQUAD(current->curr_ip) , ## args); \ -+ else \ -+ printk(KERN_ALERT "grsec: " normal_msg "\n" , ## args); \ -+ } else if((get_seconds() - grsec_alert_wtime < CONFIG_GRKERNSEC_FLOODTIME) && (grsec_alert_fyet < CONFIG_GRKERNSEC_FLOODBURST)) { \ -+ grsec_alert_fyet++; \ -+ if (current->curr_ip) \ -+ printk(KERN_ALERT "grsec: From %u.%u.%u.%u: " normal_msg "\n", NIPQUAD(current->curr_ip) , ## args); \ -+ else \ -+ printk(KERN_ALERT "grsec: " normal_msg "\n" , ## args); \ -+ } else if (grsec_alert_fyet == CONFIG_GRKERNSEC_FLOODBURST) { \ -+ grsec_alert_wtime = get_seconds(); grsec_alert_fyet++; \ -+ printk(KERN_ALERT "grsec: more alerts, logging disabled for " \ -+ "%d seconds\n", CONFIG_GRKERNSEC_FLOODTIME); \ -+ } \ -+ \ -+ gr_handle_alertkill(); \ -+ spin_unlock(&grsec_alert_lock); \ -+}) -+ -+#define security_audit(normal_msg,args...) \ -+({ \ -+ spin_lock(&grsec_audit_lock); \ -+ if (current->curr_ip) \ -+ printk(KERN_INFO "grsec: From %u.%u.%u.%u: " normal_msg "\n", \ -+ NIPQUAD(current->curr_ip) , ## args); \ -+ else \ -+ printk(KERN_INFO "grsec: " normal_msg "\n", ## args); \ -+ spin_unlock(&grsec_audit_lock); \ -+}) -+ -+#define security_learn(normal_msg,args...) \ -+({ \ -+ preempt_disable(); \ -+ gr_add_learn_entry(normal_msg "\n", ## args); \ -+ preempt_enable(); \ -+}) -+ -+#endif -+ -+#endif -diff -urN linux-2.6.5/include/linux/grmsg.h linux-2.6.5/include/linux/grmsg.h ---- linux-2.6.5/include/linux/grmsg.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/include/linux/grmsg.h 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,108 @@ -+#define DEFAULTSECMSG "%.256s[%.16s:%d] uid/euid:%d/%d gid/egid:%d/%d, parent %.256s[%.16s:%d] uid/euid:%d/%d gid/egid:%d/%d" -+#define GR_ACL_PROCACCT_MSG "%.256s[%.16s:%d] IP:%u.%u.%u.%u TTY:%.64s uid/euid:%d/%d gid/egid:%d/%d 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:%d/%d gid/egid:%d/%d" -+#define GR_PTRACE_ACL_MSG "denied ptrace of %.950s(%.16s:%d) by " DEFAULTSECMSG -+#define GR_IOPERM_MSG "denied use of ioperm() by " DEFAULTSECMSG -+#define GR_IOPL_MSG "denied use of iopl() by " DEFAULTSECMSG -+#define GR_SHMAT_ACL_MSG "denied attach of shared memory of UID %u, PID %d, ID %u by " DEFAULTSECMSG -+#define GR_UNIX_CHROOT_MSG "denied connect to abstract AF_UNIX socket outside of chroot by " DEFAULTSECMSG -+#define GR_SHMAT_CHROOT_MSG "denied attach of shared memory outside of chroot by " DEFAULTSECMSG -+#define GR_KMEM_MSG "attempted write to /dev/kmem by " DEFAULTSECMSG -+#define GR_PORT_OPEN_MSG "attempted open of /dev/port by " DEFAULTSECMSG -+#define GR_MEM_WRITE_MSG "attempted write of /dev/mem by " DEFAULTSECMSG -+#define GR_MEM_MMAP_MSG "attempted mmap write of /dev/[k]mem by " DEFAULTSECMSG -+#define GR_SYMLINK_MSG "not following symlink %.950s owned by %d.%d by " DEFAULTSECMSG -+#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" -+#define GR_HIDDEN_ACL_MSG "%s access to hidden file %.950s by " DEFAULTSECMSG -+#define GR_OPEN_ACL_MSG "%s open of %.950s for%s%s by " DEFAULTSECMSG -+#define GR_CREATE_ACL_MSG "%s create of %.950s for%s%s by " DEFAULTSECMSG -+#define GR_FIFO_MSG "denied writing FIFO %.950s of %d.%d by " DEFAULTSECMSG -+#define GR_MKNOD_CHROOT_MSG "refused attempt to mknod %.950s from chroot by " DEFAULTSECMSG -+#define GR_MKNOD_ACL_MSG "%s mknod of %.950s by " DEFAULTSECMSG -+#define GR_UNIXCONNECT_ACL_MSG "%s connect to the unix domain socket %.950s by " DEFAULTSECMSG -+#define GR_MKDIR_ACL_MSG "%s mkdir of %.950s by " DEFAULTSECMSG -+#define GR_RMDIR_ACL_MSG "%s rmdir of %.950s by " DEFAULTSECMSG -+#define GR_UNLINK_ACL_MSG "%s unlink of %.950s by " DEFAULTSECMSG -+#define GR_SYMLINK_ACL_MSG "%s symlink from %.480s to %.480s by " DEFAULTSECMSG -+#define GR_HARDLINK_MSG "denied hardlink of %.930s (owned by %d.%d) to %.30s for " DEFAULTSECMSG -+#define GR_LINK_ACL_MSG "%s link of %.480s to %.480s by " DEFAULTSECMSG -+#define GR_INHERIT_ACL_MSG "successful inherit of %.480s's ACL for %.480s by " DEFAULTSECMSG -+#define GR_RENAME_ACL_MSG "%s rename of %.480s to %.480s by " DEFAULTSECMSG -+#define GR_PTRACE_EXEC_ACL_MSG "denied ptrace of %.950s by " DEFAULTSECMSG -+#define GR_NPROC_MSG "attempt to overstep process limit by " DEFAULTSECMSG -+#define GR_EXEC_ACL_MSG "%s execution of %.950s by " DEFAULTSECMSG -+#define GR_EXEC_TPE_MSG "denied untrusted exec of %.950s by " DEFAULTSECMSG -+#define GR_SEGVSTART_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " Banning uid %u from login for %lu seconds" -+#define GR_SEGVNOSUID_ACL_MSG "possible exploit bruteforcing on " DEFAULTSECMSG " Banning execution for %lu seconds" -+#define GR_MOUNT_CHROOT_MSG "denied attempt to mount %.30s as %.930s from chroot by " DEFAULTSECMSG -+#define GR_PIVOT_CHROOT_MSG "denied attempt to pivot_root from chroot by " DEFAULTSECMSG -+#define GR_TRUNCATE_ACL_MSG "%s truncate of %.950s by " DEFAULTSECMSG -+#define GR_ATIME_ACL_MSG "%s access time change of %.950s by " DEFAULTSECMSG -+#define GR_ACCESS_ACL_MSG "%s access of %.950s for%s%s%s by " DEFAULTSECMSG -+#define GR_CHROOT_CHROOT_MSG "denied attempt to double chroot to %.950s by " DEFAULTSECMSG -+#define GR_FCHMOD_ACL_MSG "%s fchmod of %.950s by " DEFAULTSECMSG -+#define GR_CHMOD_CHROOT_MSG "denied attempt to chmod +s %.950s by " DEFAULTSECMSG -+#define GR_CHMOD_ACL_MSG "%s chmod of %.950s by " DEFAULTSECMSG -+#define GR_CHROOT_FCHDIR_MSG "attempted fchdir outside of chroot to %.950s by " DEFAULTSECMSG -+#define GR_CHOWN_ACL_MSG "%s chown of %.950s by " DEFAULTSECMSG -+#define GR_WRITLIB_ACL_MSG "denied load of writable library %.950s by " DEFAULTSECMSG -+#define GR_INITF_ACL_MSG "init_variables() failed %s" -+#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" -+#define GR_DEV_ACL_MSG "/dev/grsec: being fed garbage %d bytes sent %d required" -+#define GR_SHUTS_ACL_MSG "shutdown auth success for " DEFAULTSECMSG -+#define GR_SHUTF_ACL_MSG "shutdown auth failure for " DEFAULTSECMSG -+#define GR_SHUTI_ACL_MSG "ignoring shutdown for disabled RBAC system for " DEFAULTSECMSG -+#define GR_SEGVMODS_ACL_MSG "segvmod auth success for " DEFAULTSECMSG -+#define GR_SEGVMODF_ACL_MSG "segvmod auth failure for " DEFAULTSECMSG -+#define GR_SEGVMODI_ACL_MSG "ignoring segvmod for disabled RBAC system for " DEFAULTSECMSG -+#define GR_ENABLE_ACL_MSG "Loaded %s" -+#define GR_ENABLEF_ACL_MSG "Unable to load %s for " DEFAULTSECMSG " RBAC system may already be enabled." -+#define GR_RELOADI_ACL_MSG "Ignoring reload request for disabled RBAC system" -+#define GR_RELOAD_ACL_MSG "Reloaded %s" -+#define GR_RELOADF_ACL_MSG "Failed reload of %s for " DEFAULTSECMSG -+#define GR_SPROLEI_ACL_MSG "Ignoring change to special role for disabled RBAC system for " DEFAULTSECMSG -+#define GR_SPROLES_ACL_MSG "successful change to special role %s (id %d) by " DEFAULTSECMSG -+#define GR_SPROLEL_ACL_MSG "special role %s (id %d) exited by " DEFAULTSECMSG -+#define GR_SPROLEF_ACL_MSG "special role %s failure for " DEFAULTSECMSG -+#define GR_UNSPROLEI_ACL_MSG "Ignoring unauth of special role for disabled RBAC system for " DEFAULTSECMSG -+#define GR_UNSPROLES_ACL_MSG "successful unauth of special role %s (id %d) by " DEFAULTSECMSG -+#define GR_UNSPROLEF_ACL_MSG "special role unauth of %s failure for " DEFAULTSECMSG -+#define GR_INVMODE_ACL_MSG "Invalid mode %d by " DEFAULTSECMSG -+#define GR_MAXPW_ACL_MSG "Maximum pw attempts reached (%d), locking password authentication" -+#define GR_MAXROLEPW_ACL_MSG "Maximum pw attempts reached (%d) trying to auth to special role %s, locking auth for role of " DEFAULTSECMSG -+#define GR_PRIORITY_CHROOT_MSG "attempted priority change of process (%.16s:%d) by " DEFAULTSECMSG -+#define GR_CAPSET_CHROOT_MSG "denied capset of (%.16s:%d) within chroot by " DEFAULTSECMSG -+#define GR_FAILFORK_MSG "failed fork with errno %d by " DEFAULTSECMSG -+#define GR_NICE_CHROOT_MSG "attempted priority change by " DEFAULTSECMSG -+#define GR_UNISIGLOG_MSG "signal %d sent to " DEFAULTSECMSG -+#define GR_DUALSIGLOG_MSG "signal %d sent to " DEFAULTSECMSG " by " DEFAULTSECMSG -+#define GR_SIG_ACL_MSG "Attempted send of signal %d to protected task " DEFAULTSECMSG " by " DEFAULTSECMSG -+#define GR_SYSCTL_MSG "attempt to modify grsecurity sysctl value : %.32s by " DEFAULTSECMSG -+#define GR_SYSCTL_ACL_MSG "%s sysctl of %.950s for%s%s by " DEFAULTSECMSG -+#define GR_TIME_MSG "time set by " DEFAULTSECMSG -+#define GR_DEFACL_MSG "Fatal: Unable to find ACL for (%.16s:%d)" -+#define GR_MMAP_ACL_MSG "%s executable mmap of %.950s by " DEFAULTSECMSG -+#define GR_MPROTECT_ACL_MSG "%s executable mprotect of %.950s by " DEFAULTSECMSG -+#define GR_SOCK_MSG "attempted socket(%.16s,%.16s,%.16s) by " DEFAULTSECMSG -+#define GR_SOCK2_MSG "attempted socket(%d,%.16s,%.16s) by " DEFAULTSECMSG -+#define GR_BIND_MSG "attempted bind() by " DEFAULTSECMSG -+#define GR_CONNECT_MSG "attempted connect by " DEFAULTSECMSG -+#define GR_BIND_ACL_MSG "attempted bind to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by " DEFAULTSECMSG -+#define GR_CONNECT_ACL_MSG "attempted connect to %u.%u.%u.%u port %u sock type %.16s protocol %.16s by " DEFAULTSECMSG -+#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" -+#define GR_EXEC_CHROOT_MSG "exec of %.980s within chroot by process " DEFAULTSECMSG -+#define GR_CAP_ACL_MSG "use of %s denied for " DEFAULTSECMSG -+#define GR_USRCHANGE_ACL_MSG "change to uid %d denied for " DEFAULTSECMSG -+#define GR_GRPCHANGE_ACL_MSG "change to gid %d denied for " DEFAULTSECMSG -+#define GR_REMOUNT_AUDIT_MSG "remount of %.30s by " DEFAULTSECMSG -+#define GR_UNMOUNT_AUDIT_MSG "unmount of %.30s by " DEFAULTSECMSG -+#define GR_MOUNT_AUDIT_MSG "mount %.30s to %.64s by " DEFAULTSECMSG -+#define GR_CHDIR_AUDIT_MSG "chdir to %.980s by " DEFAULTSECMSG -+#define GR_EXEC_AUDIT_MSG "exec of %.930s (%.63s) by " DEFAULTSECMSG -+#define GR_MSGQ_AUDIT_MSG "message queue created by " DEFAULTSECMSG -+#define GR_MSGQR_AUDIT_MSG "message queue of uid:%d euid:%d removed by " DEFAULTSECMSG -+#define GR_SEM_AUDIT_MSG "semaphore created by " DEFAULTSECMSG -+#define GR_SEMR_AUDIT_MSG "semaphore of uid:%d euid:%d removed by " DEFAULTSECMSG -+#define GR_SHM_AUDIT_MSG "shared memory of size %d created by " DEFAULTSECMSG -+#define GR_SHMR_AUDIT_MSG "shared memory of uid:%d euid:%d removed by " DEFAULTSECMSG -+#define GR_RESOURCE_MSG "attempted resource overstep by requesting %lu for %.16s against limit %lu by " DEFAULTSECMSG -+#define GR_TEXTREL_AUDIT_MSG "text relocation in %s, VMA:0x%08lx 0x%08lx by " DEFAULTSECMSG -diff -urN linux-2.6.5/include/linux/grsecurity.h linux-2.6.5/include/linux/grsecurity.h ---- linux-2.6.5/include/linux/grsecurity.h 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/include/linux/grsecurity.h 2004-04-18 11:05:51.000000000 -0400 -@@ -0,0 +1,188 @@ -+#ifndef GR_SECURITY_H -+#define GR_SECURITY_H -+#include <linux/fs.h> -+#include <linux/binfmts.h> -+ -+extern int gr_check_user_change(int real, int effective, int fs); -+extern int gr_check_group_change(int real, int effective, int fs); -+ -+extern void gr_add_to_task_ip_table(struct task_struct *p); -+extern void gr_del_task_from_ip_table(struct task_struct *p); -+ -+extern int gr_pid_is_chrooted(const struct task_struct *p); -+extern int gr_handle_chroot_nice(void); -+extern int gr_handle_chroot_sysctl(const int op); -+extern int gr_handle_chroot_capset(const struct task_struct *target); -+extern int gr_handle_chroot_setpriority(struct task_struct *p, -+ const int niceval); -+extern int gr_chroot_fchdir(struct dentry *u_dentry, struct vfsmount *u_mnt); -+extern int gr_handle_chroot_chroot(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern void gr_handle_chroot_caps(struct task_struct *task); -+extern void gr_handle_chroot_chdir(struct dentry *dentry, struct vfsmount *mnt); -+extern int gr_handle_chroot_chmod(const struct dentry *dentry, -+ const struct vfsmount *mnt, const int mode); -+extern int gr_handle_chroot_mknod(const struct dentry *dentry, -+ const struct vfsmount *mnt, const int mode); -+extern int gr_handle_chroot_mount(const struct dentry *dentry, -+ const struct vfsmount *mnt, -+ const char *dev_name); -+extern int gr_handle_chroot_pivot(void); -+extern int gr_handle_chroot_unix(const pid_t pid); -+ -+extern int gr_handle_rawio(const struct inode *inode); -+extern int gr_handle_nproc(void); -+ -+extern void gr_handle_ioperm(void); -+extern void gr_handle_iopl(void); -+ -+extern int gr_tpe_allow(const struct file *file); -+ -+extern int gr_random_pid(void); -+ -+extern void gr_log_forkfail(const int retval); -+extern void gr_log_timechange(void); -+extern void gr_log_signal(const int sig, const struct task_struct *t); -+extern void gr_log_chdir(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern void gr_log_chroot_exec(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern void gr_handle_exec_args(struct linux_binprm *bprm, char **argv); -+extern void gr_log_remount(const char *devname, const int retval); -+extern void gr_log_unmount(const char *devname, const int retval); -+extern void gr_log_mount(const char *from, const char *to, const int retval); -+extern void gr_log_msgget(const int ret, const int msgflg); -+extern void gr_log_msgrm(const uid_t uid, const uid_t cuid); -+extern void gr_log_semget(const int err, const int semflg); -+extern void gr_log_semrm(const uid_t uid, const uid_t cuid); -+extern void gr_log_shmget(const int err, const int shmflg, const size_t size); -+extern void gr_log_shmrm(const uid_t uid, const uid_t cuid); -+extern void gr_log_textrel(struct vm_area_struct *vma); -+ -+extern int gr_handle_follow_link(const struct inode *parent, -+ const struct inode *inode, -+ const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern int gr_handle_fifo(const struct dentry *dentry, -+ const struct vfsmount *mnt, -+ const struct dentry *dir, const int flag, -+ const int acc_mode); -+extern int gr_handle_hardlink(const struct dentry *dentry, -+ const struct vfsmount *mnt, -+ struct inode *inode, -+ const int mode, const char *to); -+ -+extern int gr_task_is_capable(struct task_struct *task, const int cap); -+extern int gr_is_capable_nolog(const int cap); -+extern void gr_learn_resource(const struct task_struct *task, const int limit, -+ const unsigned long wanted, const int gt); -+extern void gr_copy_label(struct task_struct *tsk); -+extern void gr_handle_crash(struct task_struct *task, const int sig); -+extern int gr_handle_signal(const struct task_struct *p, const int sig); -+extern int gr_check_crash_uid(const uid_t uid); -+extern int gr_check_protected_task(const struct task_struct *task); -+extern int gr_acl_handle_mmap(const struct file *file, -+ const unsigned long prot); -+extern int gr_acl_handle_mprotect(const struct file *file, -+ const unsigned long prot); -+extern int gr_check_hidden_task(const struct task_struct *tsk); -+extern __u32 gr_acl_handle_truncate(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern __u32 gr_acl_handle_utime(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern __u32 gr_acl_handle_access(const struct dentry *dentry, -+ const struct vfsmount *mnt, const int fmode); -+extern __u32 gr_acl_handle_fchmod(const struct dentry *dentry, -+ const struct vfsmount *mnt, mode_t mode); -+extern __u32 gr_acl_handle_chmod(const struct dentry *dentry, -+ const struct vfsmount *mnt, mode_t mode); -+extern __u32 gr_acl_handle_chown(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern int gr_handle_ptrace_exec(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern int gr_handle_ptrace(struct task_struct *task, const long request); -+extern int gr_handle_proc_ptrace(struct task_struct *task); -+extern int gr_handle_mmap(const struct file *filp, const unsigned long prot); -+extern __u32 gr_acl_handle_execve(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern int gr_check_crash_exec(const struct file *filp); -+extern int gr_acl_is_enabled(void); -+extern void gr_set_kernel_label(struct task_struct *task); -+extern void gr_set_role_label(struct task_struct *task, const uid_t uid, -+ const gid_t gid); -+extern void gr_set_proc_label(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern __u32 gr_acl_handle_hidden_file(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern __u32 gr_acl_handle_open(const struct dentry *dentry, -+ const struct vfsmount *mnt, const int fmode); -+extern __u32 gr_acl_handle_creat(const struct dentry *dentry, -+ const struct dentry *p_dentry, -+ const struct vfsmount *p_mnt, const int fmode, -+ const int imode); -+extern void gr_handle_create(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern __u32 gr_acl_handle_mknod(const struct dentry *new_dentry, -+ const struct dentry *parent_dentry, -+ const struct vfsmount *parent_mnt, -+ const int mode); -+extern __u32 gr_acl_handle_mkdir(const struct dentry *new_dentry, -+ const struct dentry *parent_dentry, -+ const struct vfsmount *parent_mnt); -+extern __u32 gr_acl_handle_rmdir(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern void gr_handle_delete(const ino_t ino, const dev_t dev); -+extern __u32 gr_acl_handle_unlink(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern __u32 gr_acl_handle_symlink(const struct dentry *new_dentry, -+ const struct dentry *parent_dentry, -+ const struct vfsmount *parent_mnt, -+ const char *from); -+extern __u32 gr_acl_handle_link(const struct dentry *new_dentry, -+ const struct dentry *parent_dentry, -+ const struct vfsmount *parent_mnt, -+ const struct dentry *old_dentry, -+ const struct vfsmount *old_mnt, const char *to); -+extern int gr_acl_handle_rename(struct dentry *new_dentry, -+ struct dentry *parent_dentry, -+ const struct vfsmount *parent_mnt, -+ struct dentry *old_dentry, -+ struct inode *old_parent_inode, -+ struct vfsmount *old_mnt, const char *newname); -+extern void gr_handle_rename(struct inode *old_dir, struct inode *new_dir, -+ struct dentry *old_dentry, -+ struct dentry *new_dentry, -+ struct vfsmount *mnt, const __u8 replace); -+extern __u32 gr_check_link(const struct dentry *new_dentry, -+ const struct dentry *parent_dentry, -+ const struct vfsmount *parent_mnt, -+ const struct dentry *old_dentry, -+ const struct vfsmount *old_mnt); -+extern __u32 gr_acl_handle_filldir(const struct dentry *dentry, -+ const struct vfsmount *mnt, const ino_t ino); -+extern __u32 gr_acl_handle_unix(const struct dentry *dentry, -+ const struct vfsmount *mnt); -+extern void gr_acl_handle_exit(void); -+extern void gr_acl_handle_psacct(struct task_struct *task, const long code); -+extern int gr_acl_handle_procpidmem(const struct task_struct *task); -+extern __u32 gr_cap_rtnetlink(void); -+ -+#ifdef CONFIG_GRKERNSEC -+extern void gr_handle_mem_write(void); -+extern void gr_handle_kmem_write(void); -+extern void gr_handle_open_port(void); -+extern int gr_handle_mem_mmap(const unsigned long offset, -+ struct vm_area_struct *vma); -+ -+extern __u16 ip_randomid(void); -+extern __u32 ip_randomisn(void); -+extern unsigned long get_random_long(void); -+ -+extern int grsec_enable_dmesg; -+extern int grsec_enable_randid; -+extern int grsec_enable_randisn; -+extern int grsec_enable_randsrc; -+extern int grsec_enable_randrpc; -+#endif -+ -+#endif -diff -urN linux-2.6.5/include/linux/mm.h linux-2.6.5/include/linux/mm.h ---- linux-2.6.5/include/linux/mm.h 2004-04-03 22:36:15.000000000 -0500 -+++ linux-2.6.5/include/linux/mm.h 2004-04-18 11:05:51.000000000 -0400 -@@ -25,6 +25,7 @@ - #include <asm/pgtable.h> - #include <asm/processor.h> - #include <asm/atomic.h> -+#include <asm/mman.h> - - #ifndef MM_VM_SIZE - #define MM_VM_SIZE(mm) TASK_SIZE -@@ -115,6 +116,18 @@ - /* It makes sense to apply VM_ACCOUNT to this vma. */ - #define VM_MAYACCT(vma) (!!((vma)->vm_flags & VM_HUGETLB)) - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+#define VM_MIRROR 0x01000000 /* vma is mirroring another */ -+#endif -+ -+#ifdef CONFIG_PAX_MPROTECT -+#define VM_MAYNOTWRITE 0x02000000 /* vma cannot be granted VM_WRITE any more */ -+#endif -+ -+#ifdef __VM_STACK_FLAGS -+#define VM_STACK_DEFAULT_FLAGS (0x00000033 | __VM_STACK_FLAGS) -+#endif -+ - #ifndef VM_STACK_DEFAULT_FLAGS /* arch can override this */ - #define VM_STACK_DEFAULT_FLAGS VM_DATA_DEFAULT_FLAGS - #endif -@@ -549,21 +562,48 @@ - unsigned long len, unsigned long prot, - unsigned long flag, unsigned long pgoff); - -+extern int do_munmap(struct mm_struct *, unsigned long, size_t); -+ - static inline unsigned long do_mmap(struct file *file, unsigned long addr, - unsigned long len, unsigned long prot, - unsigned long flag, unsigned long offset) - { - unsigned long ret = -EINVAL; -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if ((current->flags & PF_PAX_SEGMEXEC) && -+ (len > SEGMEXEC_TASK_SIZE || (addr && addr > SEGMEXEC_TASK_SIZE-len))) -+ goto out; -+#endif -+ - if ((offset + PAGE_ALIGN(len)) < offset) - goto out; - if (!(offset & ~PAGE_MASK)) - ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT); -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if ((current->flags & PF_PAX_SEGMEXEC) && ret < TASK_SIZE && ((flag & MAP_TYPE) == MAP_PRIVATE) -+ -+#ifdef CONFIG_PAX_MPROTECT -+ && (!(current->flags & PF_PAX_MPROTECT) || ((prot & PROT_EXEC) && file && !(prot & PROT_WRITE))) -+#endif -+ -+ ) -+ { -+ unsigned long ret_m; -+ prot = prot & PROT_EXEC ? prot : PROT_NONE; -+ ret_m = do_mmap_pgoff(NULL, ret + SEGMEXEC_TASK_SIZE, 0UL, prot, flag | MAP_MIRROR | MAP_FIXED, ret); -+ if (ret_m >= TASK_SIZE) { -+ do_munmap(current->mm, ret, len); -+ ret = ret_m; -+ } -+ } -+#endif -+ - out: - return ret; - } - --extern int do_munmap(struct mm_struct *, unsigned long, size_t); -- - extern unsigned long do_brk(unsigned long, unsigned long); - - static inline void -@@ -579,6 +619,12 @@ - static inline int - can_vma_merge(struct vm_area_struct *vma, unsigned long vm_flags) - { -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if ((vma->vm_flags | vm_flags) & VM_MIRROR) -+ return 0; -+#endif -+ - #ifdef CONFIG_MMU - if (!vma->vm_file && vma->vm_flags == vm_flags) - return 1; -diff -urN linux-2.6.5/include/linux/mman.h linux-2.6.5/include/linux/mman.h ---- linux-2.6.5/include/linux/mman.h 2004-04-03 22:36:19.000000000 -0500 -+++ linux-2.6.5/include/linux/mman.h 2004-04-18 11:05:51.000000000 -0400 -@@ -56,6 +56,11 @@ - calc_vm_flag_bits(unsigned long flags) - { - return _calc_vm_trans(flags, MAP_GROWSDOWN, VM_GROWSDOWN ) | -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ _calc_vm_trans(flags, MAP_MIRROR, VM_MIRROR) | -+#endif -+ - _calc_vm_trans(flags, MAP_DENYWRITE, VM_DENYWRITE ) | - _calc_vm_trans(flags, MAP_EXECUTABLE, VM_EXECUTABLE) | - _calc_vm_trans(flags, MAP_LOCKED, VM_LOCKED ); -diff -urN linux-2.6.5/include/linux/proc_fs.h linux-2.6.5/include/linux/proc_fs.h ---- linux-2.6.5/include/linux/proc_fs.h 2004-04-03 22:38:28.000000000 -0500 -+++ linux-2.6.5/include/linux/proc_fs.h 2004-04-18 11:05:51.000000000 -0400 -@@ -226,7 +226,7 @@ - - #endif /* CONFIG_PROC_FS */ - --#if !defined(CONFIG_PROC_FS) -+#if !defined(CONFIG_PROC_FS) || !defined(CONFIG_PROC_KCORE) - static inline void kclist_add(struct kcore_list *new, void *addr, size_t size) - { - } -diff -urN linux-2.6.5/include/linux/random.h linux-2.6.5/include/linux/random.h ---- linux-2.6.5/include/linux/random.h 2004-04-03 22:38:24.000000000 -0500 -+++ linux-2.6.5/include/linux/random.h 2004-04-18 11:05:51.000000000 -0400 -@@ -69,6 +69,8 @@ - - extern __u32 secure_ipv6_id(__u32 *daddr); - -+extern unsigned long pax_get_random_long(void); -+ - #ifndef MODULE - extern struct file_operations random_fops, urandom_fops; - #endif -diff -urN linux-2.6.5/include/linux/sched.h linux-2.6.5/include/linux/sched.h ---- linux-2.6.5/include/linux/sched.h 2004-04-03 22:36:18.000000000 -0500 -+++ linux-2.6.5/include/linux/sched.h 2004-04-18 11:05:51.000000000 -0400 -@@ -31,6 +31,7 @@ - #include <linux/percpu.h> - - struct exec_domain; -+struct linux_binprm; - - /* - * cloning flags: -@@ -228,6 +229,21 @@ - struct kioctx *ioctx_list; - - struct kioctx default_kioctx; -+ -+#ifdef CONFIG_PAX_DLRESOLVE -+ unsigned long call_dl_resolve; -+#endif -+ -+#if defined(CONFIG_PPC32) && defined(CONFIG_PAX_EMUSIGRT) -+ unsigned long call_syscall; -+#endif -+ -+#ifdef CONFIG_PAX_ASLR -+ unsigned long delta_mmap; /* randomized offset */ -+ unsigned long delta_exec; /* randomized offset */ -+ unsigned long delta_stack; /* randomized offset */ -+#endif -+ - }; - - extern int mmlist_nr; -@@ -493,6 +509,22 @@ - - unsigned long ptrace_message; - siginfo_t *last_siginfo; /* For ptrace use. */ -+ -+#ifdef CONFIG_GRKERNSEC -+ /* grsecurity */ -+ struct acl_subject_label *acl; -+ struct acl_role_label *role; -+ struct file *exec_file; -+ u32 curr_ip; -+ u32 gr_saddr; -+ u32 gr_daddr; -+ u16 gr_sport; -+ u16 gr_dport; -+ u16 acl_role_id; -+ u8 acl_sp_role:1; -+ u8 used_accept:1; -+ u8 is_writable:1; -+#endif - }; - - static inline pid_t process_group(struct task_struct *tsk) -@@ -530,6 +562,29 @@ - #define PF_LESS_THROTTLE 0x00100000 /* Throttle me less: I clean memory */ - #define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */ - -+#define PF_PAX_PAGEEXEC 0x01000000 /* Paging based non-executable pages */ -+#define PF_PAX_EMUTRAMP 0x02000000 /* Emulate trampolines */ -+#define PF_PAX_MPROTECT 0x04000000 /* Restrict mprotect() */ -+#define PF_PAX_RANDMMAP 0x08000000 /* Randomize mmap() base */ -+#define PF_PAX_RANDEXEC 0x10000000 /* Randomize ET_EXEC base */ -+#define PF_PAX_SEGMEXEC 0x20000000 /* Segmentation based non-executable pages */ -+ -+#ifdef CONFIG_PAX_SOFTMODE -+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) || defined(CONFIG_PAX_RANDKSTACK) -+extern unsigned int pax_aslr; -+#endif -+ -+extern unsigned int pax_softmode; -+#endif -+ -+extern int pax_check_flags(unsigned long *); -+ -+#ifdef CONFIG_PAX_HAVE_ACL_FLAGS -+extern void pax_set_flags(struct linux_binprm * bprm); -+#elif defined(CONFIG_PAX_HOOK_ACL_FLAGS) -+extern void (*pax_set_flags_func)(struct linux_binprm * bprm); -+#endif -+ - #ifdef CONFIG_SMP - extern int set_cpus_allowed(task_t *p, cpumask_t new_mask); - #else -@@ -675,14 +730,29 @@ - : on_sig_stack(sp) ? SS_ONSTACK : 0); - } - -+extern int gr_task_is_capable(struct task_struct *task, const int cap); -+extern int gr_is_capable_nolog(const int cap); - - #ifdef CONFIG_SECURITY - /* code is in security.c */ - extern int capable(int cap); -+static inline int capable_nolog(int cap) -+{ -+ return capable(cap); -+} - #else - static inline int capable(int cap) - { -- if (cap_raised(current->cap_effective, cap)) { -+ if (cap_raised(current->cap_effective, cap) && gr_task_is_capable(current, cap)) { -+ current->flags |= PF_SUPERPRIV; -+ return 1; -+ } -+ return 0; -+} -+ -+static inline int capable_nolog(int cap) -+{ -+ if (cap_raised(current->cap_effective, cap) && gr_is_capable_nolog(cap)) { - current->flags |= PF_SUPERPRIV; - return 1; - } -diff -urN linux-2.6.5/include/linux/shm.h linux-2.6.5/include/linux/shm.h ---- linux-2.6.5/include/linux/shm.h 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/include/linux/shm.h 2004-04-18 11:05:51.000000000 -0400 -@@ -84,6 +84,10 @@ - time_t shm_ctim; - pid_t shm_cprid; - pid_t shm_lprid; -+#ifdef CONFIG_GRKERNSEC -+ time_t shm_createtime; -+ pid_t shm_lapid; -+#endif - }; - - /* shm_mode upper byte flags */ -diff -urN linux-2.6.5/include/linux/sysctl.h linux-2.6.5/include/linux/sysctl.h ---- linux-2.6.5/include/linux/sysctl.h 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/include/linux/sysctl.h 2004-04-18 11:05:51.000000000 -0400 -@@ -131,8 +131,21 @@ - KERN_PRINTK_RATELIMIT_BURST=61, /* int: tune printk ratelimiting */ - KERN_PTY=62, /* dir: pty driver */ - KERN_NGROUPS_MAX=63, /* int: NGROUPS_MAX */ -+ KERN_GRSECURITY=68, /* grsecurity */ -+ -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ KERN_PAX=69, /* PaX control */ -+#endif -+ - }; - -+#ifdef CONFIG_PAX_SOFTMODE -+enum { -+ PAX_ASLR=1, /* PaX: disable/enable all randomization features */ -+ PAX_SOFTMODE=2 /* PaX: disable/enable soft mode */ -+}; -+#endif - - /* CTL_VM names: */ - enum -diff -urN linux-2.6.5/include/net/ip.h linux-2.6.5/include/net/ip.h ---- linux-2.6.5/include/net/ip.h 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/include/net/ip.h 2004-04-18 11:05:51.000000000 -0400 -@@ -33,6 +33,11 @@ - #include <net/route.h> - #include <net/arp.h> - -+#ifdef CONFIG_GRKERNSEC_RANDID -+extern int grsec_enable_randid; -+extern __u16 ip_randomid(void); -+#endif -+ - #ifndef _SNMP_H - #include <net/snmp.h> - #endif -@@ -188,6 +193,13 @@ - - static inline void ip_select_ident(struct iphdr *iph, struct dst_entry *dst, struct sock *sk) - { -+ -+#ifdef CONFIG_GRKERNSEC_RANDID -+ if (grsec_enable_randid) -+ iph->id = htons(ip_randomid()); -+ else -+#endif -+ - if (iph->frag_off & htons(IP_DF)) { - /* This is only to work around buggy Windows95/2000 - * VJ compression implementations. If the ID field -diff -urN linux-2.6.5/init/Kconfig linux-2.6.5/init/Kconfig ---- linux-2.6.5/init/Kconfig 2004-04-03 22:37:44.000000000 -0500 -+++ linux-2.6.5/init/Kconfig 2004-04-18 11:05:51.000000000 -0400 -@@ -193,6 +193,7 @@ - config KALLSYMS - bool "Load all symbols for debugging/kksymoops" if EMBEDDED - default y -+ depends on !GRKERNSEC_HIDESYM - help - Say Y here to let the kernel print out symbolic crash information and - symbolic stack backtraces. This increases the size of the kernel -diff -urN linux-2.6.5/init/do_mounts.c linux-2.6.5/init/do_mounts.c ---- linux-2.6.5/init/do_mounts.c 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/init/do_mounts.c 2004-04-18 11:05:51.000000000 -0400 -@@ -287,6 +287,7 @@ - case -EINVAL: - continue; - } -+ - /* - * Allow the user to distinguish between failed sys_open - * and bad superblock on root device. -diff -urN linux-2.6.5/init/main.c linux-2.6.5/init/main.c ---- linux-2.6.5/init/main.c 2004-04-03 22:36:25.000000000 -0500 -+++ linux-2.6.5/init/main.c 2004-04-18 11:05:51.000000000 -0400 -@@ -89,6 +89,7 @@ - extern void free_initmem(void); - extern void populate_rootfs(void); - extern void driver_init(void); -+extern void grsecurity_init(void); - - #ifdef CONFIG_TC - extern void tc_init(void); -@@ -605,7 +606,7 @@ - do_basic_setup(); - - prepare_namespace(); -- -+ grsecurity_init(); - /* - * Ok, we have completed the initial bootup, and - * we're essentially up and running. Get rid of the -diff -urN linux-2.6.5/ipc/msg.c linux-2.6.5/ipc/msg.c ---- linux-2.6.5/ipc/msg.c 2004-04-03 22:36:13.000000000 -0500 -+++ linux-2.6.5/ipc/msg.c 2004-04-18 11:05:51.000000000 -0400 -@@ -24,6 +24,7 @@ - #include <linux/list.h> - #include <linux/security.h> - #include <linux/sched.h> -+#include <linux/grsecurity.h> - #include <asm/current.h> - #include <asm/uaccess.h> - #include "util.h" -@@ -331,6 +332,9 @@ - msg_unlock(msq); - } - up(&msg_ids.sem); -+ -+ gr_log_msgget(ret, msgflg); -+ - return ret; - } - -@@ -580,6 +584,8 @@ - break; - } - case IPC_RMID: -+ gr_log_msgrm(ipcp->uid, ipcp->cuid); -+ - freeque (msq, msqid); - break; - } -diff -urN linux-2.6.5/ipc/sem.c linux-2.6.5/ipc/sem.c ---- linux-2.6.5/ipc/sem.c 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/ipc/sem.c 2004-04-18 11:05:51.000000000 -0400 -@@ -71,6 +71,7 @@ - #include <linux/time.h> - #include <linux/smp_lock.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - #include <asm/uaccess.h> - #include "util.h" - -@@ -238,6 +239,9 @@ - } - - up(&sem_ids.sem); -+ -+ gr_log_semget(err, semflg); -+ - return err; - } - -@@ -804,6 +808,8 @@ - - switch(cmd){ - case IPC_RMID: -+ gr_log_semrm(ipcp->uid, ipcp->cuid); -+ - freeary(sma, semid); - err = 0; - break; -diff -urN linux-2.6.5/ipc/shm.c linux-2.6.5/ipc/shm.c ---- linux-2.6.5/ipc/shm.c 2004-04-03 22:37:07.000000000 -0500 -+++ linux-2.6.5/ipc/shm.c 2004-04-18 11:05:51.000000000 -0400 -@@ -26,6 +26,7 @@ - #include <linux/proc_fs.h> - #include <linux/shmem_fs.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - #include <asm/uaccess.h> - - #include "util.h" -@@ -50,6 +51,14 @@ - static int sysvipc_shm_read_proc(char *buffer, char **start, off_t offset, int length, int *eof, void *data); - #endif - -+#ifdef CONFIG_GRKERNSEC -+extern int gr_handle_shmat(const pid_t shm_cprid, const pid_t shm_lapid, -+ const time_t shm_createtime, const uid_t cuid, -+ const int shmid); -+extern int gr_chroot_shmat(const pid_t shm_cprid, const pid_t shm_lapid, -+ const time_t shm_createtime); -+#endif -+ - size_t shm_ctlmax = SHMMAX; - size_t shm_ctlall = SHMALL; - int shm_ctlmni = SHMMNI; -@@ -213,6 +222,9 @@ - shp->shm_lprid = 0; - shp->shm_atim = shp->shm_dtim = 0; - shp->shm_ctim = get_seconds(); -+#ifdef CONFIG_GRKERNSEC -+ shp->shm_createtime = get_seconds(); -+#endif - shp->shm_segsz = size; - shp->shm_nattch = 0; - shp->id = shm_buildid(id,shp->shm_perm.seq); -@@ -267,6 +279,8 @@ - } - up(&shm_ids.sem); - -+ gr_log_shmget(err, shmflg, size); -+ - return err; - } - -@@ -567,6 +581,8 @@ - if (err) - goto out_unlock_up; - -+ gr_log_shmrm(shp->shm_perm.uid, shp->shm_perm.cuid); -+ - if (shp->shm_nattch){ - shp->shm_flags |= SHM_DEST; - /* Do not find it any more */ -@@ -705,9 +721,27 @@ - return err; - } - -+#ifdef CONFIG_GRKERNSEC -+ if (!gr_handle_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime, -+ shp->shm_perm.cuid, shmid)) { -+ shm_unlock(shp); -+ return -EACCES; -+ } -+ -+ if (!gr_chroot_shmat(shp->shm_cprid, shp->shm_lapid, shp->shm_createtime)) { -+ shm_unlock(shp); -+ return -EACCES; -+ } -+#endif -+ - file = shp->shm_file; - size = i_size_read(file->f_dentry->d_inode); - shp->shm_nattch++; -+ -+#ifdef CONFIG_GRKERNSEC -+ shp->shm_lapid = current->pid; -+#endif -+ - shm_unlock(shp); - - down_write(¤t->mm->mmap_sem); -diff -urN linux-2.6.5/kernel/capability.c linux-2.6.5/kernel/capability.c ---- linux-2.6.5/kernel/capability.c 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/kernel/capability.c 2004-04-18 11:05:51.000000000 -0400 -@@ -10,6 +10,7 @@ - #include <linux/mm.h> - #include <linux/module.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - #include <asm/uaccess.h> - - unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */ -@@ -168,6 +169,11 @@ - } else - target = current; - -+ if (gr_handle_chroot_capset(target)) { -+ ret = -ESRCH; -+ goto out; -+ } -+ - ret = -EPERM; - - if (security_capset_check(target, &effective, &inheritable, &permitted)) -diff -urN linux-2.6.5/kernel/configs.c linux-2.6.5/kernel/configs.c ---- linux-2.6.5/kernel/configs.c 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/kernel/configs.c 2004-04-18 11:05:51.000000000 -0400 -@@ -81,8 +81,16 @@ - IKCONFIG_VERSION); - - /* create the current config file */ -+#ifdef CONFIG_GRKERNSEC_PROC_ADD -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ entry = create_proc_entry("config.gz", S_IFREG | S_IRUSR, &proc_root); -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ entry = create_proc_entry("config.gz", S_IFREG | S_IRUSR | S_IRGRP, &proc_root); -+#endif -+#else - entry = create_proc_entry("config.gz", S_IFREG | S_IRUGO, - &proc_root); -+#endif - if (!entry) - return -ENOMEM; - -diff -urN linux-2.6.5/kernel/exit.c linux-2.6.5/kernel/exit.c ---- linux-2.6.5/kernel/exit.c 2004-04-03 22:38:13.000000000 -0500 -+++ linux-2.6.5/kernel/exit.c 2004-04-18 11:05:51.000000000 -0400 -@@ -22,6 +22,7 @@ - #include <linux/profile.h> - #include <linux/mount.h> - #include <linux/proc_fs.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/pgtable.h> -@@ -232,6 +233,13 @@ - { - write_lock_irq(&tasklist_lock); - -+#ifdef CONFIG_GRKERNSEC -+ if (current->exec_file) { -+ fput(current->exec_file); -+ current->exec_file = NULL; -+ } -+#endif -+ - ptrace_unlink(current); - /* Reparent to init */ - REMOVE_LINKS(current); -@@ -239,6 +247,8 @@ - current->real_parent = child_reaper; - SET_LINKS(current); - -+ gr_set_kernel_label(current); -+ - /* Set the exit signal to SIGCHLD so we signal init on exit */ - current->exit_signal = SIGCHLD; - -@@ -333,6 +343,15 @@ - vsnprintf(current->comm, sizeof(current->comm), name, args); - va_end(args); - -+#ifdef CONFIG_GRKERNSEC -+ if (current->exec_file) { -+ fput(current->exec_file); -+ current->exec_file = NULL; -+ } -+#endif -+ -+ gr_set_kernel_label(current); -+ - /* - * If we were started as result of loading a module, close all of the - * user space pages. We don't need them, and if we didn't close them -@@ -771,6 +790,11 @@ - } - - acct_process(code); -+ -+ gr_acl_handle_psacct(tsk, code); -+ gr_acl_handle_exit(); -+ gr_del_task_from_ip_table(tsk); -+ - __exit_mm(tsk); - - exit_sem(tsk); -diff -urN linux-2.6.5/kernel/fork.c linux-2.6.5/kernel/fork.c ---- linux-2.6.5/kernel/fork.c 2004-04-03 22:36:18.000000000 -0500 -+++ linux-2.6.5/kernel/fork.c 2004-04-18 11:05:51.000000000 -0400 -@@ -31,6 +31,7 @@ - #include <linux/futex.h> - #include <linux/ptrace.h> - #include <linux/mount.h> -+#include <linux/grsecurity.h> - - #include <asm/pgtable.h> - #include <asm/pgalloc.h> -@@ -274,7 +275,7 @@ - mm->locked_vm = 0; - mm->mmap = NULL; - mm->mmap_cache = NULL; -- mm->free_area_cache = TASK_UNMAPPED_BASE; -+ mm->free_area_cache = oldmm->free_area_cache; - mm->map_count = 0; - mm->rss = 0; - cpus_clear(mm->cpu_vm_mask); -@@ -880,6 +881,9 @@ - goto fork_out; - - retval = -EAGAIN; -+ -+ gr_learn_resource(p, RLIMIT_NPROC, atomic_read(&p->user->processes), 0); -+ - if (atomic_read(&p->user->processes) >= - p->rlim[RLIMIT_NPROC].rlim_cur) { - if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RESOURCE) && -@@ -968,6 +972,8 @@ - if (retval) - goto bad_fork_cleanup_namespace; - -+ gr_copy_label(p); -+ - p->set_child_tid = (clone_flags & CLONE_CHILD_SETTID) ? child_tidptr : NULL; - /* - * Clear TID on mm_release()? -@@ -1101,6 +1107,9 @@ - free_uid(p->user); - bad_fork_free: - free_task(p); -+ -+ gr_log_forkfail(retval); -+ - goto fork_out; - } - -diff -urN linux-2.6.5/kernel/kallsyms.c linux-2.6.5/kernel/kallsyms.c ---- linux-2.6.5/kernel/kallsyms.c 2004-04-03 22:38:21.000000000 -0500 -+++ linux-2.6.5/kernel/kallsyms.c 2004-04-18 11:05:51.000000000 -0400 -@@ -301,7 +301,15 @@ - { - struct proc_dir_entry *entry; - -+#ifdef CONFIG_GRKERNSEC_PROC_ADD -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ entry = create_proc_entry("kallsyms", S_IFREG | S_IRUSR, NULL); -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ entry = create_proc_entry("kallsyms", S_IFREG | S_IRUSR | S_IRGRP, NULL); -+#endif -+#else - entry = create_proc_entry("kallsyms", 0444, NULL); -+#endif - if (entry) - entry->proc_fops = &kallsyms_operations; - return 0; -diff -urN linux-2.6.5/kernel/pid.c linux-2.6.5/kernel/pid.c ---- linux-2.6.5/kernel/pid.c 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/kernel/pid.c 2004-04-18 11:05:51.000000000 -0400 -@@ -25,6 +25,7 @@ - #include <linux/init.h> - #include <linux/bootmem.h> - #include <linux/hash.h> -+#include <linux/grsecurity.h> - - #define pid_hashfn(nr) hash_long((unsigned long)nr, pidhash_shift) - static struct list_head *pid_hash[PIDTYPE_MAX]; -@@ -99,10 +100,12 @@ - - int alloc_pidmap(void) - { -- int pid, offset, max_steps = PIDMAP_ENTRIES + 1; -+ int pid = 0, offset, max_steps = PIDMAP_ENTRIES + 1; - pidmap_t *map; - -- pid = last_pid + 1; -+ pid = gr_random_pid(); -+ if (!pid) -+ pid = last_pid + 1; - if (pid >= pid_max) - pid = RESERVED_PIDS; - -@@ -225,10 +228,16 @@ - task_t *find_task_by_pid(int nr) - { - struct pid *pid = find_pid(PIDTYPE_PID, nr); -+ struct task_struct *task = NULL; - - if (!pid) - return NULL; -- return pid_task(pid->task_list.next, PIDTYPE_PID); -+ task = pid_task(pid->task_list.next, PIDTYPE_PID); -+ -+ if (gr_pid_is_chrooted(task)) -+ return NULL; -+ -+ return task; - } - - EXPORT_SYMBOL(find_task_by_pid); -diff -urN linux-2.6.5/kernel/printk.c linux-2.6.5/kernel/printk.c ---- linux-2.6.5/kernel/printk.c 2004-04-03 22:38:24.000000000 -0500 -+++ linux-2.6.5/kernel/printk.c 2004-04-18 11:05:51.000000000 -0400 -@@ -30,6 +30,7 @@ - #include <linux/smp.h> - #include <linux/security.h> - #include <linux/bootmem.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - -@@ -248,6 +249,11 @@ - char c; - int error = 0; - -+#ifdef CONFIG_GRKERNSEC_DMESG -+ if (!capable(CAP_SYS_ADMIN) && grsec_enable_dmesg) -+ return -EPERM; -+#endif -+ - error = security_syslog(type); - if (error) - return error; -diff -urN linux-2.6.5/kernel/resource.c linux-2.6.5/kernel/resource.c ---- linux-2.6.5/kernel/resource.c 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/kernel/resource.c 2004-04-18 11:05:51.000000000 -0400 -@@ -134,10 +134,27 @@ - { - struct proc_dir_entry *entry; - -+#ifdef CONFIG_GRKERNSEC_PROC_ADD -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ entry = create_proc_entry("ioports", S_IRUSR, NULL); -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ entry = create_proc_entry("ioports", S_IRUSR | S_IRGRP, NULL); -+#endif -+#else - entry = create_proc_entry("ioports", 0, NULL); -+#endif - if (entry) - entry->proc_fops = &proc_ioports_operations; -+ -+#ifdef CONFIG_GRKERNSEC_PROC_ADD -+#ifdef CONFIG_GRKERNSEC_PROC_USER -+ entry = create_proc_entry("iomem", S_IRUSR, NULL); -+#elif CONFIG_GRKERNSEC_PROC_USERGROUP -+ entry = create_proc_entry("iomem", S_IRUSR | S_IRGRP, NULL); -+#endif -+#else - entry = create_proc_entry("iomem", 0, NULL); -+#endif - if (entry) - entry->proc_fops = &proc_iomem_operations; - return 0; -diff -urN linux-2.6.5/kernel/sched.c linux-2.6.5/kernel/sched.c ---- linux-2.6.5/kernel/sched.c 2004-04-03 22:37:42.000000000 -0500 -+++ linux-2.6.5/kernel/sched.c 2004-04-18 11:05:51.000000000 -0400 -@@ -39,6 +39,7 @@ - #include <linux/cpu.h> - #include <linux/percpu.h> - #include <linux/kthread.h> -+#include <linux/grsecurity.h> - - #ifdef CONFIG_NUMA - #define cpu_to_node_mask(cpu) node_to_cpumask(cpu_to_node(cpu)) -@@ -2038,6 +2039,8 @@ - return -EPERM; - if (increment < -40) - increment = -40; -+ if (gr_handle_chroot_nice()) -+ return -EPERM; - } - if (increment > 40) - increment = 40; -diff -urN linux-2.6.5/kernel/signal.c linux-2.6.5/kernel/signal.c ---- linux-2.6.5/kernel/signal.c 2004-04-03 22:36:57.000000000 -0500 -+++ linux-2.6.5/kernel/signal.c 2004-04-18 11:05:51.000000000 -0400 -@@ -21,6 +21,7 @@ - #include <linux/binfmts.h> - #include <linux/security.h> - #include <linux/ptrace.h> -+#include <linux/grsecurity.h> - #include <asm/param.h> - #include <asm/uaccess.h> - #include <asm/siginfo.h> -@@ -750,11 +751,13 @@ - (((sig) < SIGRTMIN) && sigismember(&(sigptr)->signal, (sig))) - - --static int -+int - specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t) - { - int ret = 0; - -+ gr_log_signal(sig, t); -+ - if (!irqs_disabled()) - BUG(); - #ifdef CONFIG_SMP -@@ -805,6 +808,8 @@ - ret = specific_send_sig_info(sig, info, t); - spin_unlock_irqrestore(&t->sighand->siglock, flags); - -+ gr_handle_crash(t, sig); -+ - return ret; - } - -@@ -1063,9 +1068,14 @@ - int err; - - found = 1; -- err = group_send_sig_info(sig, info, p); -- if (!retval) -- retval = err; -+ -+ if (gr_handle_signal(p, sig)) -+ retval = -EPERM; -+ else { -+ err = group_send_sig_info(sig, info, p); -+ if (!retval) -+ retval = err; -+ } - } - return found ? retval : -ESRCH; - } -@@ -1123,8 +1133,12 @@ - read_lock(&tasklist_lock); - p = find_task_by_pid(pid); - error = -ESRCH; -- if (p) -- error = group_send_sig_info(sig, info, p); -+ if (p) { -+ if (gr_handle_signal(p, sig)) -+ error = -EPERM; -+ else -+ error = group_send_sig_info(sig, info, p); -+ } - read_unlock(&tasklist_lock); - return error; - } -@@ -1148,10 +1162,14 @@ - read_lock(&tasklist_lock); - for_each_process(p) { - if (p->pid > 1 && p->tgid != current->tgid) { -- int err = group_send_sig_info(sig, info, p); -- ++count; -- if (err != -EPERM) -- retval = err; -+ if (gr_handle_signal(p, sig)) -+ retval = -EPERM; -+ else { -+ int err = group_send_sig_info(sig, info, p); -+ ++count; -+ if (err != -EPERM) -+ retval = err; -+ } - } - } - read_unlock(&tasklist_lock); -diff -urN linux-2.6.5/kernel/sys.c linux-2.6.5/kernel/sys.c ---- linux-2.6.5/kernel/sys.c 2004-04-03 22:36:18.000000000 -0500 -+++ linux-2.6.5/kernel/sys.c 2004-04-18 11:05:51.000000000 -0400 -@@ -23,6 +23,7 @@ - #include <linux/security.h> - #include <linux/dcookies.h> - #include <linux/suspend.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/io.h> -@@ -279,6 +280,12 @@ - error = -EACCES; - goto out; - } -+ -+ if (gr_handle_chroot_setpriority(p, niceval)) { -+ error = -ESRCH; -+ goto out; -+ } -+ - no_nice = security_task_setnice(p, niceval); - if (no_nice) { - error = no_nice; -@@ -579,6 +586,9 @@ - if (rgid != (gid_t) -1 || - (egid != (gid_t) -1 && egid != old_rgid)) - current->sgid = new_egid; -+ -+ gr_set_role_label(current, current->uid, new_rgid); -+ - current->fsgid = new_egid; - current->egid = new_egid; - current->gid = new_rgid; -@@ -606,6 +616,9 @@ - current->mm->dumpable=0; - wmb(); - } -+ -+ gr_set_role_label(current, current->uid, gid); -+ - current->gid = current->egid = current->sgid = current->fsgid = gid; - } - else if ((gid == current->gid) || (gid == current->sgid)) -@@ -644,6 +657,9 @@ - current->mm->dumpable = 0; - wmb(); - } -+ -+ gr_set_role_label(current, new_ruid, current->gid); -+ - current->uid = new_ruid; - return 0; - } -@@ -744,6 +760,9 @@ - } else if ((uid != current->uid) && (uid != new_suid)) - return -EPERM; - -+ if (gr_check_crash_uid(uid)) -+ return -EPERM; -+ - if (old_euid != uid) - { - current->mm->dumpable = 0; -@@ -843,8 +862,10 @@ - current->egid = egid; - } - current->fsgid = current->egid; -- if (rgid != (gid_t) -1) -+ if (rgid != (gid_t) -1) { -+ gr_set_role_label(current, current->uid, rgid); - current->gid = rgid; -+ } - if (sgid != (gid_t) -1) - current->sgid = sgid; - return 0; -diff -urN linux-2.6.5/kernel/sysctl.c linux-2.6.5/kernel/sysctl.c ---- linux-2.6.5/kernel/sysctl.c 2004-04-03 22:36:18.000000000 -0500 -+++ linux-2.6.5/kernel/sysctl.c 2004-04-18 11:05:51.000000000 -0400 -@@ -46,6 +46,14 @@ - #endif - - #if defined(CONFIG_SYSCTL) -+#include <linux/grsecurity.h> -+#include <linux/grinternal.h> -+ -+extern __u32 gr_handle_sysctl(const ctl_table *table, const void *oldval, -+ const void *newval); -+extern int gr_handle_sysctl_mod(const char *dirname, const char *name, -+ const int op); -+extern int gr_handle_chroot_sysctl(const int op); - - /* External variables not in a header file. */ - extern int panic_timeout; -@@ -139,6 +147,32 @@ - #ifdef CONFIG_UNIX98_PTYS - extern ctl_table pty_table[]; - #endif -+extern ctl_table grsecurity_table[]; -+ -+#ifdef CONFIG_PAX_SOFTMODE -+static ctl_table pax_table[] = { -+ -+#if defined(CONFIG_PAX_RANDMMAP) || defined(CONFIG_PAX_RANDUSTACK) || defined(CONFIG_PAX_RANDKSTACK) -+ { -+ .ctl_name = PAX_ASLR, -+ .procname = "aslr", -+ .data = &pax_aslr, -+ .maxlen = sizeof(unsigned int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ }, -+#endif -+ -+ { -+ .ctl_name = PAX_SOFTMODE, -+ .procname = "softmode", -+ .data = &pax_softmode, -+ .maxlen = sizeof(unsigned int), -+ .mode = 0600, -+ .proc_handler = &proc_dointvec, -+ } -+}; -+#endif - - /* /proc declarations: */ - -@@ -615,6 +649,14 @@ - .mode = 0444, - .proc_handler = &proc_dointvec, - }, -+#ifdef CONFIG_GRKERNSEC_SYSCTL -+ { -+ .ctl_name = KERN_GRSECURITY, -+ .procname = "grsecurity", -+ .mode = 0500, -+ .child = grsecurity_table, -+ }, -+#endif - { .ctl_name = 0 } - }; - -@@ -854,6 +896,16 @@ - .mode = 0644, - .proc_handler = &proc_dointvec, - }, -+ -+#ifdef CONFIG_PAX_SOFTMODE -+ { -+ .ctl_name = KERN_PAX, -+ .procname = "pax", -+ .mode = 0500, -+ .child = pax_table, -+ }, -+#endif -+ - { .ctl_name = 0 } - }; - -@@ -938,6 +990,10 @@ - static inline int ctl_perm(ctl_table *table, int op) - { - int error; -+ if (table->de && gr_handle_sysctl_mod(table->de->parent->name, table->de->name, op)) -+ return -EACCES; -+ if (gr_handle_chroot_sysctl(op)) -+ return -EACCES; - error = security_sysctl(table, op); - if (error) - return error; -@@ -974,6 +1030,10 @@ - table = table->child; - goto repeat; - } -+ -+ if (!gr_handle_sysctl(table, oldval, newval)) -+ return -EACCES; -+ - error = do_sysctl_strategy(table, name, nlen, - oldval, oldlenp, - newval, newlen, context); -diff -urN linux-2.6.5/kernel/time.c linux-2.6.5/kernel/time.c ---- linux-2.6.5/kernel/time.c 2004-04-03 22:36:27.000000000 -0500 -+++ linux-2.6.5/kernel/time.c 2004-04-18 11:05:51.000000000 -0400 -@@ -28,6 +28,7 @@ - #include <linux/timex.h> - #include <linux/errno.h> - #include <linux/smp_lock.h> -+#include <linux/grsecurity.h> - #include <asm/uaccess.h> - - /* -@@ -80,6 +81,9 @@ - - tv.tv_nsec = 0; - do_settimeofday(&tv); -+ -+ gr_log_timechange(); -+ - return 0; - } - -@@ -181,6 +185,8 @@ - return -EFAULT; - } - -+ gr_log_timechange(); -+ - return do_sys_settimeofday(tv ? &new_ts : NULL, tz ? &new_tz : NULL); - } - -diff -urN linux-2.6.5/kernel/timer.c linux-2.6.5/kernel/timer.c ---- linux-2.6.5/kernel/timer.c 2004-04-03 22:37:59.000000000 -0500 -+++ linux-2.6.5/kernel/timer.c 2004-04-18 11:05:51.000000000 -0400 -@@ -31,6 +31,7 @@ - #include <linux/time.h> - #include <linux/jiffies.h> - #include <linux/cpu.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/div64.h> -@@ -688,6 +689,9 @@ - - psecs = (p->utime += user); - psecs += (p->stime += system); -+ -+ gr_learn_resource(p, RLIMIT_CPU, psecs / HZ, 1); -+ - if (psecs / HZ > p->rlim[RLIMIT_CPU].rlim_cur) { - /* Send SIGXCPU every second.. */ - if (!(psecs % HZ)) -diff -urN linux-2.6.5/mm/filemap.c linux-2.6.5/mm/filemap.c ---- linux-2.6.5/mm/filemap.c 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/mm/filemap.c 2004-04-18 11:05:51.000000000 -0400 -@@ -27,6 +27,8 @@ - #include <linux/pagevec.h> - #include <linux/blkdev.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> -+ - /* - * This is needed for the following functions: - * - try_to_release_page -@@ -1356,6 +1358,12 @@ - - if (!mapping->a_ops->readpage) - return -ENOEXEC; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (current->flags & PF_PAX_PAGEEXEC) -+ vma->vm_page_prot = protection_map[vma->vm_flags & 0x0f]; -+#endif -+ - file_accessed(file); - vma->vm_ops = &generic_file_vm_ops; - return 0; -@@ -1654,6 +1662,7 @@ - *pos = i_size_read(inode); - - if (limit != RLIM_INFINITY) { -+ gr_learn_resource(current, RLIMIT_FSIZE,*pos, 0); - if (*pos >= limit) { - send_sig(SIGXFSZ, current, 0); - return -EFBIG; -diff -urN linux-2.6.5/mm/madvise.c linux-2.6.5/mm/madvise.c ---- linux-2.6.5/mm/madvise.c 2004-04-03 22:36:52.000000000 -0500 -+++ linux-2.6.5/mm/madvise.c 2004-04-18 11:05:51.000000000 -0400 -@@ -13,8 +13,42 @@ - * We can potentially split a vm area into separate - * areas, each area with its own behavior. - */ -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+static long __madvise_behavior(struct vm_area_struct * vma, unsigned long start, -+ unsigned long end, int behavior); -+ -+static long madvise_behavior(struct vm_area_struct * vma, unsigned long start, -+ unsigned long end, int behavior) -+{ -+ if (vma->vm_flags & VM_MIRROR) { -+ struct vm_area_struct * vma_m, * prev_m; -+ unsigned long start_m, end_m; -+ int error; -+ -+ start_m = vma->vm_start + (unsigned long)vma->vm_private_data; -+ vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m); -+ if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) { -+ start_m = start + (unsigned long)vma->vm_private_data; -+ end_m = end + (unsigned long)vma->vm_private_data; -+ error = __madvise_behavior(vma_m, start_m, end_m, behavior); -+ if (error) -+ return error; -+ } else { -+ printk("PAX: VMMIRROR: madvise bug in %s, %08lx\n", current->comm, vma->vm_start); -+ return -ENOMEM; -+ } -+ } -+ -+ return __madvise_behavior(vma, start, end, behavior); -+} -+ -+static long __madvise_behavior(struct vm_area_struct * vma, unsigned long start, -+ unsigned long end, int behavior) -+#else - static long madvise_behavior(struct vm_area_struct * vma, unsigned long start, - unsigned long end, int behavior) -+#endif - { - struct mm_struct * mm = vma->vm_mm; - int error; -diff -urN linux-2.6.5/mm/memory.c linux-2.6.5/mm/memory.c ---- linux-2.6.5/mm/memory.c 2004-04-03 22:36:58.000000000 -0500 -+++ linux-2.6.5/mm/memory.c 2004-04-18 11:05:51.000000000 -0400 -@@ -46,6 +46,7 @@ - #include <linux/rmap-locking.h> - #include <linux/module.h> - #include <linux/init.h> -+#include <linux/grsecurity.h> - - #include <asm/pgalloc.h> - #include <asm/rmap.h> -@@ -989,6 +990,69 @@ - update_mmu_cache(vma, address, entry); - } - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+/* PaX: if vma is mirrored, synchronize the mirror's PTE -+ * -+ * mm->page_table_lock is held on entry and is not released on exit or inside -+ * to ensure atomic changes to the PTE states (swapout, mremap, munmap, etc) -+ */ -+struct pte_chain * pax_mirror_fault(struct mm_struct *mm, struct vm_area_struct * vma, -+ unsigned long address, pte_t *pte, struct pte_chain *pte_chain) -+{ -+ unsigned long address_m; -+ struct vm_area_struct * vma_m = NULL; -+ pte_t * pte_m, entry_m; -+ struct page * page_m; -+ -+ address_m = vma->vm_start + (unsigned long)vma->vm_private_data; -+ vma_m = find_vma(mm, address_m); -+ BUG_ON(!vma_m || vma_m->vm_start != address_m); -+ -+ address_m = address + (unsigned long)vma->vm_private_data; -+ -+ { -+ pgd_t *pgd_m; -+ pmd_t *pmd_m; -+ -+ pgd_m = pgd_offset(mm, address_m); -+ pmd_m = pmd_offset(pgd_m, address_m); -+ pte_m = pte_offset_map_nested(pmd_m, address_m); -+ } -+ -+ if (pte_present(*pte_m)) { -+ flush_cache_page(vma_m, address_m); -+ flush_icache_page(vma_m, pte_page(*pte_m)); -+ } -+ entry_m = ptep_get_and_clear(pte_m); -+ if (pte_present(entry_m)) -+ flush_tlb_page(vma_m, address_m); -+ -+ if (pte_none(entry_m)) { -+ ++mm->rss; -+ } else if (pte_present(entry_m)) { -+ page_remove_rmap(pte_page(entry_m), pte_m); -+ page_cache_release(pte_page(entry_m)); -+ } else if (!pte_file(entry_m)) { -+ free_swap_and_cache(pte_to_swp_entry(entry_m)); -+ ++mm->rss; -+ } else { -+ printk(KERN_ERR "PAX: VMMIRROR: bug in mirror_fault: %08lx, %08lx, %08lx, %08lx\n", -+ address, vma->vm_start, address_m, vma_m->vm_start); -+ } -+ -+ page_m = pte_page(*pte); -+ page_cache_get(page_m); -+ entry_m = mk_pte(page_m, vma_m->vm_page_prot); -+ if (pte_write(*pte)) -+ entry_m = pte_mkdirty(pte_mkwrite(entry_m)); -+ pte_chain = page_add_rmap(page_m, pte_m, pte_chain); -+ ptep_establish(vma_m, address_m, pte_m, entry_m); -+ update_mmu_cache(vma_m, address_m, entry_m); -+ pte_unmap_nested(pte_m); -+ return pte_chain; -+} -+#endif -+ - /* - * This routine handles present pages, when users try to write - * to a shared page. It is done by copying the page to a new address -@@ -1017,6 +1081,10 @@ - struct pte_chain *pte_chain; - pte_t entry; - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ struct pte_chain *pte_chain_m = NULL; -+#endif -+ - if (unlikely(!pfn_valid(pfn))) { - /* - * This should really halt the system so it can be debugged or -@@ -1056,6 +1124,13 @@ - pte_chain = pte_chain_alloc(GFP_KERNEL); - if (!pte_chain) - goto no_pte_chain; -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ pte_chain_m = pte_chain_alloc(GFP_KERNEL); -+ if (!pte_chain_m) -+ goto no_new_page; -+#endif -+ - new_page = alloc_page(GFP_HIGHUSER); - if (!new_page) - goto no_new_page; -@@ -1076,16 +1151,32 @@ - - /* Free the old page.. */ - new_page = old_page; -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (vma->vm_flags & VM_MIRROR) -+ pte_chain_m = pax_mirror_fault(mm, vma, address, page_table, pte_chain_m); -+#endif -+ - } - pte_unmap(page_table); - page_cache_release(new_page); - page_cache_release(old_page); - spin_unlock(&mm->page_table_lock); - pte_chain_free(pte_chain); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ pte_chain_free(pte_chain_m); -+#endif -+ - return VM_FAULT_MINOR; - - no_new_page: - pte_chain_free(pte_chain); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ pte_chain_free(pte_chain_m); -+#endif -+ - no_pte_chain: - page_cache_release(old_page); - return VM_FAULT_OOM; -@@ -1187,6 +1278,7 @@ - - do_expand: - limit = current->rlim[RLIMIT_FSIZE].rlim_cur; -+ gr_learn_resource(current, RLIMIT_FSIZE, offset, 1); - if (limit != RLIM_INFINITY && offset > limit) - goto out_sig; - if (offset > inode->i_sb->s_maxbytes) -@@ -1246,6 +1338,10 @@ - int ret = VM_FAULT_MINOR; - struct pte_chain *pte_chain = NULL; - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ struct pte_chain *pte_chain_m = NULL; -+#endif -+ - pte_unmap(page_table); - spin_unlock(&mm->page_table_lock); - page = lookup_swap_cache(entry); -@@ -1279,6 +1375,15 @@ - ret = VM_FAULT_OOM; - goto out; - } -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ pte_chain_m = pte_chain_alloc(GFP_KERNEL); -+ if (!pte_chain_m) { -+ ret = -ENOMEM; -+ goto out; -+ } -+#endif -+ - lock_page(page); - - /* -@@ -1314,10 +1419,21 @@ - - /* No need to invalidate - it was non-present before */ - update_mmu_cache(vma, address, pte); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (vma->vm_flags & VM_MIRROR) -+ pte_chain_m = pax_mirror_fault(mm, vma, address, page_table, pte_chain_m); -+#endif -+ - pte_unmap(page_table); - spin_unlock(&mm->page_table_lock); - out: - pte_chain_free(pte_chain); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ pte_chain_free(pte_chain_m); -+#endif -+ - return ret; - } - -@@ -1336,13 +1452,38 @@ - struct pte_chain *pte_chain; - int ret; - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ struct pte_chain *pte_chain_m = NULL; -+#endif -+ - pte_chain = pte_chain_alloc(GFP_ATOMIC | __GFP_NOWARN); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ pte_chain_m = pte_chain_alloc(GFP_ATOMIC | __GFP_NOWARN); -+#endif -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (!pte_chain || !pte_chain_m) { -+#else - if (!pte_chain) { -+#endif -+ - pte_unmap(page_table); - spin_unlock(&mm->page_table_lock); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (!pte_chain) -+ pte_chain = pte_chain_alloc(GFP_KERNEL); -+ if (!pte_chain_m) -+ pte_chain_m = pte_chain_alloc(GFP_KERNEL); -+ if (!pte_chain || !pte_chain_m) -+ goto no_mem; -+#else - pte_chain = pte_chain_alloc(GFP_KERNEL); - if (!pte_chain) - goto no_mem; -+#endif -+ - spin_lock(&mm->page_table_lock); - page_table = pte_offset_map(pmd, addr); - } -@@ -1382,10 +1523,16 @@ - set_pte(page_table, entry); - /* ignores ZERO_PAGE */ - pte_chain = page_add_rmap(page, page_table, pte_chain); -- pte_unmap(page_table); - - /* No need to invalidate - it was non-present before */ - update_mmu_cache(vma, addr, entry); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (vma->vm_flags & VM_MIRROR) -+ pte_chain_m = pax_mirror_fault(mm, vma, addr, page_table, pte_chain_m); -+#endif -+ -+ pte_unmap(page_table); - spin_unlock(&mm->page_table_lock); - ret = VM_FAULT_MINOR; - goto out; -@@ -1394,6 +1541,11 @@ - ret = VM_FAULT_OOM; - out: - pte_chain_free(pte_chain); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ pte_chain_free(pte_chain_m); -+#endif -+ - return ret; - } - -@@ -1420,6 +1572,10 @@ - int sequence = 0; - int ret = VM_FAULT_MINOR; - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ struct pte_chain *pte_chain_m = NULL; -+#endif -+ - if (!vma->vm_ops || !vma->vm_ops->nopage) - return do_anonymous_page(mm, vma, page_table, - pmd, write_access, address); -@@ -1444,6 +1600,12 @@ - if (!pte_chain) - goto oom; - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ pte_chain_m = pte_chain_alloc(GFP_KERNEL); -+ if (!pte_chain_m) -+ goto oom; -+#endif -+ - /* - * Should we do an early C-O-W break? - */ -@@ -1469,6 +1631,11 @@ - spin_unlock(&mm->page_table_lock); - page_cache_release(new_page); - pte_chain_free(pte_chain); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ pte_chain_free(pte_chain_m); -+#endif -+ - goto retry; - } - page_table = pte_offset_map(pmd, address); -@@ -1493,6 +1660,15 @@ - entry = maybe_mkwrite(pte_mkdirty(entry), vma); - set_pte(page_table, entry); - pte_chain = page_add_rmap(new_page, page_table, pte_chain); -+ -+ /* no need to invalidate: a not-present page shouldn't be cached */ -+ update_mmu_cache(vma, address, entry); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (vma->vm_flags & VM_MIRROR) -+ pte_chain_m = pax_mirror_fault(mm, vma, address, page_table, pte_chain_m); -+#endif -+ - pte_unmap(page_table); - } else { - /* One of our sibling threads was faster, back out. */ -@@ -1502,8 +1678,6 @@ - goto out; - } - -- /* no need to invalidate: a not-present page shouldn't be cached */ -- update_mmu_cache(vma, address, entry); - spin_unlock(&mm->page_table_lock); - goto out; - oom: -@@ -1511,6 +1685,11 @@ - ret = VM_FAULT_OOM; - out: - pte_chain_free(pte_chain); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ pte_chain_free(pte_chain_m); -+#endif -+ - return ret; - } - -@@ -1613,6 +1792,11 @@ - pgd_t *pgd; - pmd_t *pmd; - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ unsigned long address_m = 0UL; -+ struct vm_area_struct * vma_m = NULL; -+#endif -+ - __set_current_state(TASK_RUNNING); - pgd = pgd_offset(mm, address); - -@@ -1626,6 +1810,48 @@ - * and the SMP-safe atomic PTE updates. - */ - spin_lock(&mm->page_table_lock); -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (vma->vm_flags & VM_MIRROR) { -+ pgd_t *pgd_m; -+ pmd_t *pmd_m; -+ pte_t *pte_m; -+ -+ address_m = vma->vm_start + (unsigned long)vma->vm_private_data; -+ vma_m = find_vma(mm, address_m); -+ -+ /* PaX: sanity checks */ -+ if (!vma_m) { -+ spin_unlock(&mm->page_table_lock); -+ printk(KERN_ERR "PAX: VMMIRROR: fault bug, %08lx, %p, %08lx, %p\n", -+ address, vma, address_m, vma_m); -+ return VM_FAULT_SIGBUS; -+ } else if (!(vma_m->vm_flags & VM_MIRROR) || -+ vma_m->vm_start != address_m || -+ vma->vm_end - vma->vm_start != vma_m->vm_end - vma_m->vm_start) -+ { -+ spin_unlock(&mm->page_table_lock); -+ printk(KERN_ERR "PAX: VMMIRROR: fault bug2, %08lx, %08lx, %08lx, %08lx, %08lx\n", -+ address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end); -+ return VM_FAULT_SIGBUS; -+ } -+ -+ address_m = address + (unsigned long)vma->vm_private_data; -+ pgd_m = pgd_offset(mm, address_m); -+ pmd_m = pmd_alloc(mm, pgd_m, address_m); -+ if (!pmd_m) { -+ spin_unlock(&mm->page_table_lock); -+ return VM_FAULT_OOM; -+ } -+ pte_m = pte_alloc_map(mm, pmd_m, address_m); -+ if (!pte_m) { -+ spin_unlock(&mm->page_table_lock); -+ return VM_FAULT_OOM; -+ } -+ pte_unmap(pte_m); -+ } -+#endif -+ - pmd = pmd_alloc(mm, pgd, address); - - if (pmd) { -diff -urN linux-2.6.5/mm/mlock.c linux-2.6.5/mm/mlock.c ---- linux-2.6.5/mm/mlock.c 2004-04-03 22:36:16.000000000 -0500 -+++ linux-2.6.5/mm/mlock.c 2004-04-18 11:05:51.000000000 -0400 -@@ -7,11 +7,43 @@ - - #include <linux/mman.h> - #include <linux/mm.h> -+#include <linux/grsecurity.h> - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+static int __mlock_fixup(struct vm_area_struct * vma, -+ unsigned long start, unsigned long end, unsigned int newflags); - - static int mlock_fixup(struct vm_area_struct * vma, - unsigned long start, unsigned long end, unsigned int newflags) - { -+ if (vma->vm_flags & VM_MIRROR) { -+ struct vm_area_struct * vma_m; -+ unsigned long start_m, end_m; -+ int error; -+ -+ start_m = vma->vm_start + (unsigned long)vma->vm_private_data; -+ vma_m = find_vma(vma->vm_mm, start_m); -+ if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) { -+ start_m = start + (unsigned long)vma->vm_private_data; -+ end_m = end + (unsigned long)vma->vm_private_data; -+ error = __mlock_fixup(vma_m, start_m, end_m, newflags); -+ if (error) -+ return error; -+ } else { -+ printk("PAX: VMMIRROR: mlock bug in %s, %08lx\n", current->comm, vma->vm_start); -+ return -ENOMEM; -+ } -+ } -+ return __mlock_fixup(vma, start, end, newflags); -+} -+ -+static int __mlock_fixup(struct vm_area_struct * vma, -+ unsigned long start, unsigned long end, unsigned int newflags) -+#else -+static int mlock_fixup(struct vm_area_struct * vma, -+ unsigned long start, unsigned long end, unsigned int newflags) -+#endif -+{ - struct mm_struct * mm = vma->vm_mm; - int pages; - int ret = 0; -@@ -65,6 +97,17 @@ - return -EINVAL; - if (end == start) - return 0; -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) { -+ if (end > SEGMEXEC_TASK_SIZE) -+ return -EINVAL; -+ } else -+#endif -+ -+ if (end > TASK_SIZE) -+ return -EINVAL; -+ - vma = find_vma(current->mm, start); - if (!vma || vma->vm_start > start) - return -ENOMEM; -@@ -115,6 +158,7 @@ - lock_limit >>= PAGE_SHIFT; - - /* check against resource limits */ -+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked, 1); - if (locked <= lock_limit) - error = do_mlock(start, len, 1); - up_write(¤t->mm->mmap_sem); -@@ -151,6 +195,16 @@ - for (vma = current->mm->mmap; vma ; vma = vma->vm_next) { - unsigned int newflags; - -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) { -+ if (vma->vm_end > SEGMEXEC_TASK_SIZE) -+ break; -+ } else -+#endif -+ -+ if (vma->vm_end > TASK_SIZE) -+ break; -+ - newflags = vma->vm_flags | VM_LOCKED; - if (!(flags & MCL_CURRENT)) - newflags &= ~VM_LOCKED; -@@ -174,6 +228,7 @@ - lock_limit >>= PAGE_SHIFT; - - ret = -ENOMEM; -+ gr_learn_resource(current, RLIMIT_MEMLOCK, current->mm->total_vm, 1); - if (current->mm->total_vm <= lock_limit) - ret = do_mlockall(flags); - out: -diff -urN linux-2.6.5/mm/mmap.c linux-2.6.5/mm/mmap.c ---- linux-2.6.5/mm/mmap.c 2004-04-03 22:37:25.000000000 -0500 -+++ linux-2.6.5/mm/mmap.c 2004-04-18 11:05:51.000000000 -0400 -@@ -21,6 +21,7 @@ - #include <linux/profile.h> - #include <linux/module.h> - #include <linux/mount.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/pgalloc.h> -@@ -121,6 +122,7 @@ - - /* Check against rlimit.. */ - rlim = current->rlim[RLIMIT_DATA].rlim_cur; -+ gr_learn_resource(current, RLIMIT_DATA, brk - mm->start_data, 1); - if (rlim < RLIM_INFINITY && brk - mm->start_data > rlim) - goto out; - -@@ -327,6 +329,12 @@ - static inline int is_mergeable_vma(struct vm_area_struct *vma, - struct file *file, unsigned long vm_flags) - { -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if ((vma->vm_flags | vm_flags) & VM_MIRROR) -+ return 0; -+#endif -+ - if (vma->vm_ops && vma->vm_ops->close) - return 0; - if (vma->vm_file != file) -@@ -494,6 +502,28 @@ - int accountable = 1; - unsigned long charged = 0; - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ struct vm_area_struct * vma_m = NULL; -+ -+ if (flags & MAP_MIRROR) { -+ /* PaX: sanity checks, to be removed when proved to be stable */ -+ if (file || len || ((flags & MAP_TYPE) != MAP_PRIVATE)) -+ return -EINVAL; -+ -+ vma_m = find_vma(mm, pgoff); -+ -+ if (!vma_m || is_vm_hugetlb_page(vma_m) || -+ vma_m->vm_start != pgoff || -+ (vma_m->vm_flags & VM_MIRROR) || -+ (!(vma_m->vm_flags & VM_WRITE) && (prot & PROT_WRITE))) -+ return -EINVAL; -+ -+ file = vma_m->vm_file; -+ pgoff = vma_m->vm_pgoff; -+ len = vma_m->vm_end - vma_m->vm_start; -+ } -+#endif -+ - if (file) { - if (is_file_hugepages(file)) - accountable = 0; -@@ -535,6 +565,30 @@ - vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) | - mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; - -+ if (file && (file->f_vfsmnt->mnt_flags & MNT_NOEXEC)) -+ vm_flags &= ~VM_MAYEXEC; -+ -+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) -+ if (current->flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) { -+ -+#ifdef CONFIG_PAX_MPROTECT -+ if (current->flags & PF_PAX_MPROTECT) { -+ if (!file || (prot & PROT_WRITE)) -+ vm_flags &= ~(VM_EXEC | VM_MAYEXEC); -+ else -+ vm_flags &= ~VM_MAYWRITE; -+ -+#ifdef CONFIG_PAX_RANDEXEC -+ if (file && (flags & MAP_MIRROR) && (vm_flags & VM_EXEC)) -+ vma_m->vm_flags &= ~VM_MAYWRITE; -+#endif -+ -+ } -+#endif -+ -+ } -+#endif -+ - if (flags & MAP_LOCKED) { - if (!capable(CAP_IPC_LOCK)) - return -EPERM; -@@ -544,6 +598,7 @@ - if (vm_flags & VM_LOCKED) { - unsigned long locked = mm->locked_vm << PAGE_SHIFT; - locked += len; -+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked, 1); - if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur) - return -EAGAIN; - } -@@ -599,6 +654,9 @@ - if (error) - return error; - -+ if (!gr_acl_handle_mmap(file, prot)) -+ return -EACCES; -+ - /* Clear old maps */ - error = -ENOMEM; - munmap_back: -@@ -610,6 +668,7 @@ - } - - /* Check against address space limit. */ -+ gr_learn_resource(current, RLIMIT_AS, (mm->total_vm << PAGE_SHIFT) + len, 1); - if ((mm->total_vm << PAGE_SHIFT) + len - > current->rlim[RLIMIT_AS].rlim_cur) - return -ENOMEM; -@@ -650,6 +709,13 @@ - vma->vm_start = addr; - vma->vm_end = addr + len; - vma->vm_flags = vm_flags; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if ((file || !(current->flags & PF_PAX_PAGEEXEC)) && (vm_flags & (VM_READ|VM_WRITE))) -+ vma->vm_page_prot = protection_map[(vm_flags | VM_EXEC) & 0x0f]; -+ else -+#endif -+ - vma->vm_page_prot = protection_map[vm_flags & 0x0f]; - vma->vm_ops = NULL; - vma->vm_pgoff = pgoff; -@@ -679,6 +745,14 @@ - goto free_vma; - } - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (flags & MAP_MIRROR) { -+ vma_m->vm_flags |= VM_MIRROR; -+ vma_m->vm_private_data = (void *)(vma->vm_start - vma_m->vm_start); -+ vma->vm_private_data = (void *)(vma_m->vm_start - vma->vm_start); -+ } -+#endif -+ - /* We set VM_ACCOUNT in a shared mapping's vm_flags, to inform - * shmem_zero_setup (perhaps called through /dev/zero's ->mmap) - * that memory reservation must be checked; but that reservation -@@ -759,12 +833,28 @@ - struct vm_area_struct *vma; - unsigned long start_addr; - -+#ifdef CONFIG_PAX_SEGMEXEC -+ if ((current->flags & PF_PAX_SEGMEXEC) && len > SEGMEXEC_TASK_SIZE) -+ return -ENOMEM; -+ else -+#endif -+ - if (len > TASK_SIZE) - return -ENOMEM; - -+#ifdef CONFIG_PAX_RANDMMAP -+ if (!(current->flags & PF_PAX_RANDMMAP) || !filp) -+#endif -+ - if (addr) { - addr = PAGE_ALIGN(addr); - vma = find_vma(mm, addr); -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if ((current->flags & PF_PAX_SEGMEXEC) && SEGMEXEC_TASK_SIZE-len < addr) -+ return -ENOMEM; -+#endif -+ - if (TASK_SIZE - len >= addr && - (!vma || addr + len <= vma->vm_start)) - return addr; -@@ -780,6 +870,13 @@ - * some holes. - */ - if (start_addr != TASK_UNMAPPED_BASE) { -+ -+#ifdef CONFIG_PAX_RANDMMAP -+ if (current->flags & PF_PAX_RANDMMAP) -+ start_addr = addr = TASK_UNMAPPED_BASE + mm->delta_mmap; -+ else -+#endif -+ - start_addr = addr = TASK_UNMAPPED_BASE; - goto full_search; - } -@@ -939,10 +1036,18 @@ - spin_unlock(&vma->vm_mm->page_table_lock); - return -ENOMEM; - } -- -+ -+ gr_learn_resource(current, RLIMIT_STACK, address - vma->vm_start, 1); -+ gr_learn_resource(current, RLIMIT_AS, (vma->vm_mm->total_vm + grow) << PAGE_SHIFT, 1); -+ if (vma->vm_flags & VM_LOCKED) -+ gr_learn_resource(current, RLIMIT_MEMLOCK, (vma->vm_mm->locked_vm + grow) << PAGE_SHIFT, 1); -+ - if (address - vma->vm_start > current->rlim[RLIMIT_STACK].rlim_cur || - ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > -- current->rlim[RLIMIT_AS].rlim_cur) { -+ current->rlim[RLIMIT_AS].rlim_cur || -+ ((vma->vm_flags & VM_LOCKED) && -+ ((vma->vm_mm->locked_vm + grow) << PAGE_SHIFT) > -+ current->rlim[RLIMIT_MEMLOCK].rlim_cur)) { - spin_unlock(&vma->vm_mm->page_table_lock); - vm_unacct_memory(grow); - return -ENOMEM; -@@ -993,10 +1098,62 @@ - spin_unlock(&vma->vm_mm->page_table_lock); - return -ENOMEM; - } -- -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (vma->vm_flags & VM_MIRROR) { -+ struct vm_area_struct * vma_m; -+ unsigned long address_m; -+ -+ address_m = vma->vm_start + (unsigned long)vma->vm_private_data; -+ vma_m = find_vma(vma->vm_mm, address_m); -+ if (!vma_m || vma_m->vm_start != address_m || -+ !(vma_m->vm_flags & VM_MIRROR) || -+ vma->vm_end - vma->vm_start != -+ vma_m->vm_end - vma_m->vm_start) { -+ spin_unlock(&vma->vm_mm->page_table_lock); -+ vm_unacct_memory(grow); -+ printk(KERN_ERR "PAX: VMMIRROR: expand bug, %08lx, %08lx, %08lx, %08lx, %08lx\n", -+ address, vma->vm_start, vma_m->vm_start, vma->vm_end, vma_m->vm_end); -+ return -ENOMEM; -+ } -+ -+ address_m = address + (unsigned long)vma->vm_private_data; -+ -+ gr_learn_resource(current, RLIMIT_STACK, vma_m->vm_end - address_m, 1); -+ gr_learn_resource(current, RLIMIT_AS, (vma_m->vm_mm->total_vm + 2*grow) << PAGE_SHIFT, 1); -+ if (vma_m->vm_flags & VM_LOCKED) -+ gr_learn_resource(current, RLIMIT_MEMLOCK, (vma_m->vm_mm->locked_vm + 2*grow) << PAGE_SHIFT, 1); -+ -+ if (vma_m->vm_end - address_m > current->rlim[RLIMIT_STACK].rlim_cur || -+ ((vma_m->vm_mm->total_vm + 2*grow) << PAGE_SHIFT) > -+ current->rlim[RLIMIT_AS].rlim_cur || -+ ((vma_m->vm_flags & VM_LOCKED) && -+ ((vma_m->vm_mm->locked_vm + 2*grow) << PAGE_SHIFT) > -+ current->rlim[RLIMIT_MEMLOCK].rlim_cur)) { -+ spin_unlock(&vma->vm_mm->page_table_lock); -+ vm_unacct_memory(grow); -+ return -ENOMEM; -+ } -+ -+ vma_m->vm_start = address_m; -+ vma_m->vm_pgoff -= grow; -+ vma_m->vm_mm->total_vm += grow; -+ if (vma_m->vm_flags & VM_LOCKED) -+ vma_m->vm_mm->locked_vm += grow; -+ } else -+#endif -+ -+ gr_learn_resource(current, RLIMIT_STACK, vma->vm_end - address, 1); -+ gr_learn_resource(current, RLIMIT_AS, (vma->vm_mm->total_vm + grow) << PAGE_SHIFT, 1); -+ if (vma->vm_flags & VM_LOCKED) -+ gr_learn_resource(current, RLIMIT_MEMLOCK, (vma->vm_mm->locked_vm + grow) << PAGE_SHIFT, 1); -+ - if (vma->vm_end - address > current->rlim[RLIMIT_STACK].rlim_cur || - ((vma->vm_mm->total_vm + grow) << PAGE_SHIFT) > -- current->rlim[RLIMIT_AS].rlim_cur) { -+ current->rlim[RLIMIT_AS].rlim_cur || -+ ((vma->vm_flags & VM_LOCKED) && -+ ((vma->vm_mm->locked_vm + grow) << PAGE_SHIFT) > -+ current->rlim[RLIMIT_MEMLOCK].rlim_cur)) { - spin_unlock(&vma->vm_mm->page_table_lock); - vm_unacct_memory(grow); - return -ENOMEM; -@@ -1108,15 +1265,15 @@ - { - size_t len = area->vm_end - area->vm_start; - -- area->vm_mm->total_vm -= len >> PAGE_SHIFT; -+ mm->total_vm -= len >> PAGE_SHIFT; - if (area->vm_flags & VM_LOCKED) -- area->vm_mm->locked_vm -= len >> PAGE_SHIFT; -+ mm->locked_vm -= len >> PAGE_SHIFT; - /* - * Is this a new hole at the lowest possible address? - */ - if (area->vm_start >= TASK_UNMAPPED_BASE && -- area->vm_start < area->vm_mm->free_area_cache) -- area->vm_mm->free_area_cache = area->vm_start; -+ area->vm_start < mm->free_area_cache) -+ mm->free_area_cache = area->vm_start; - - remove_shared_vm_struct(area); - -@@ -1178,21 +1335,73 @@ - */ - static void - detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, -- struct vm_area_struct *prev, unsigned long end) -+ struct vm_area_struct *prev, unsigned long *start, unsigned long *end) - { - struct vm_area_struct **insertion_point; - struct vm_area_struct *tail_vma = NULL; - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ unsigned long start_m; -+ struct vm_area_struct *vma_m, *head_vma = vma, *mirrors = NULL, *head_vma_m = NULL; -+#endif -+ - insertion_point = (prev ? &prev->vm_next : &mm->mmap); - do { - rb_erase(&vma->vm_rb, &mm->mm_rb); - mm->map_count--; -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if ((vma->vm_flags & VM_MIRROR) && -+ vma->vm_start + (unsigned long)vma->vm_private_data >= *start && -+ vma->vm_start + (unsigned long)vma->vm_private_data < *end) -+ { -+ mm->mmap_cache = NULL; /* Kill the cache. */ -+ start_m = vma->vm_start + (unsigned long)vma->vm_private_data; -+ vma_m = find_vma(mm, start_m); -+ if (vma_m && (vma_m->vm_flags & VM_MIRROR) && vma_m->vm_start == start_m) { -+ vma->vm_flags &= ~VM_MIRROR; -+ vma_m->vm_flags &= ~VM_MIRROR; -+ } else -+ printk("PAX: VMMIRROR: munmap bug in %s, %08lx\n", current->comm, vma->vm_start); -+ } -+#endif -+ - tail_vma = vma; - vma = vma->vm_next; -- } while (vma && vma->vm_start < end); -+ } while (vma && vma->vm_start < *end); - *insertion_point = vma; - tail_vma->vm_next = NULL; - mm->mmap_cache = NULL; /* Kill the cache. */ -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ for (; head_vma; head_vma = head_vma->vm_next) { -+ struct vm_area_struct *prev_m; -+ -+ if (!(head_vma->vm_flags & VM_MIRROR)) -+ continue; -+ -+ start_m = head_vma->vm_start + (unsigned long)head_vma->vm_private_data; -+ vma_m = find_vma_prev(mm, start_m, &prev_m); -+ rb_erase(&vma_m->vm_rb, &mm->mm_rb); -+ mm->map_count--; -+ insertion_point = prev_m ? &prev_m->vm_next : &mm->mmap; -+ *insertion_point = vma_m->vm_next; -+ if (head_vma_m) { -+ mirrors->vm_next = vma_m; -+ mirrors = vma_m; -+ } else -+ head_vma_m = mirrors = vma_m; -+ mirrors->vm_next = NULL; -+ if (vma_m->vm_start < *start) -+ *start = vma_m->vm_start; -+ if (vma_m->vm_end > *end) -+ *end = vma_m->vm_end; -+ mm->mmap_cache = NULL; /* Kill the cache. */ -+ } -+ if (head_vma_m) -+ tail_vma->vm_next = head_vma_m; -+#endif -+ - } - - /* -@@ -1262,6 +1471,10 @@ - unsigned long end; - struct vm_area_struct *mpnt, *prev, *last; - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ struct vm_area_struct *mpnt_m = NULL, *last_m; -+#endif -+ - if ((start & ~PAGE_MASK) || start > TASK_SIZE || len > TASK_SIZE-start) - return -EINVAL; - -@@ -1298,6 +1511,20 @@ - * places tmp vma above, and higher split_vma places tmp vma below. - */ - if (start > mpnt->vm_start) { -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (mpnt->vm_flags & VM_MIRROR) { -+ unsigned long start_m = mpnt->vm_start + (unsigned long)mpnt->vm_private_data; -+ -+ mpnt_m = find_vma(mm, start_m); -+ if (!mpnt_m || (!mpnt_m->vm_flags & VM_MIRROR) || mpnt_m->vm_start != start_m) -+ return -EINVAL; -+ start_m = start + (unsigned long)mpnt->vm_private_data; -+ if (split_vma(mm, mpnt_m, start_m, 0)) -+ return -ENOMEM; -+ } -+#endif -+ - if (split_vma(mm, mpnt, start, 0)) - return -ENOMEM; - prev = mpnt; -@@ -1306,6 +1533,20 @@ - /* Does it split the last one? */ - last = find_vma(mm, end); - if (last && end > last->vm_start) { -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if (last->vm_flags & VM_MIRROR) { -+ unsigned long end_m = last->vm_start + (unsigned long)last->vm_private_data; -+ -+ last_m = find_vma(mm, end_m); -+ if (!last_m || (!last_m->vm_flags & VM_MIRROR) || last_m->vm_start != end_m) -+ return -EINVAL; -+ end_m = end + (unsigned long)last->vm_private_data; -+ if (split_vma(mm, last_m, end_m, 1)) -+ return -ENOMEM; -+ } -+#endif -+ - if (split_vma(mm, last, end, 1)) - return -ENOMEM; - } -@@ -1315,7 +1556,7 @@ - * Remove the vma's, and unmap the actual pages - */ - spin_lock(&mm->page_table_lock); -- detach_vmas_to_be_unmapped(mm, mpnt, prev, end); -+ detach_vmas_to_be_unmapped(mm, mpnt, prev, &start, &end); - unmap_region(mm, mpnt, prev, start, end); - spin_unlock(&mm->page_table_lock); - -@@ -1332,6 +1573,12 @@ - int ret; - struct mm_struct *mm = current->mm; - -+#ifdef CONFIG_PAX_SEGMEXEC -+ if ((current->flags & PF_PAX_SEGMEXEC) && -+ (len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-len)) -+ return -EINVAL; -+#endif -+ - down_write(&mm->mmap_sem); - ret = do_munmap(mm, addr, len); - up_write(&mm->mmap_sem); -@@ -1343,7 +1590,31 @@ - * anonymous maps. eventually we may be able to do some - * brk-specific accounting here. - */ -+#if defined(CONFIG_PAX_SEGMEXEC) && defined(CONFIG_PAX_MPROTECT) -+unsigned long __do_brk(unsigned long addr, unsigned long len); -+ -+unsigned long do_brk(unsigned long addr, unsigned long len) -+{ -+ unsigned long ret; -+ -+ ret = __do_brk(addr, len); -+ if (ret == addr && (current->flags & (PF_PAX_SEGMEXEC | PF_PAX_MPROTECT)) == PF_PAX_SEGMEXEC) { -+ unsigned long ret_m; -+ -+ ret_m = do_mmap_pgoff(NULL, addr + SEGMEXEC_TASK_SIZE, 0UL, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_MIRROR, addr); -+ if (ret_m > TASK_SIZE) { -+ do_munmap(current->mm, addr, len); -+ ret = ret_m; -+ } -+ } -+ -+ return ret; -+} -+ -+unsigned long __do_brk(unsigned long addr, unsigned long len) -+#else - unsigned long do_brk(unsigned long addr, unsigned long len) -+#endif - { - struct mm_struct * mm = current->mm; - struct vm_area_struct * vma, * prev; -@@ -1354,6 +1625,13 @@ - if (!len) - return addr; - -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) { -+ if ((addr + len) > SEGMEXEC_TASK_SIZE || (addr + len) < addr) -+ return -EINVAL; -+ } else -+#endif -+ - if ((addr + len) > TASK_SIZE || (addr + len) < addr) - return -EINVAL; - -@@ -1363,6 +1641,7 @@ - if (mm->def_flags & VM_LOCKED) { - unsigned long locked = mm->locked_vm << PAGE_SHIFT; - locked += len; -+ gr_learn_resource(current, RLIMIT_MEMLOCK, locked, 1); - if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur) - return -EAGAIN; - } -@@ -1379,6 +1658,7 @@ - } - - /* Check against address space limits *after* clearing old maps... */ -+ gr_learn_resource(current, RLIMIT_AS, (mm->total_vm << PAGE_SHIFT) + len, 1); - if ((mm->total_vm << PAGE_SHIFT) + len - > current->rlim[RLIMIT_AS].rlim_cur) - return -ENOMEM; -@@ -1391,6 +1671,18 @@ - - flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; - -+#if defined(CONFIG_PAX_PAGEEXEC) || defined(CONFIG_PAX_SEGMEXEC) -+ if (current->flags & (PF_PAX_PAGEEXEC | PF_PAX_SEGMEXEC)) { -+ flags &= ~VM_EXEC; -+ -+#ifdef CONFIG_PAX_MPROTECT -+ if (current->flags & PF_PAX_MPROTECT) -+ flags &= ~VM_MAYEXEC; -+#endif -+ -+ } -+#endif -+ - /* Can we just expand an old anonymous mapping? */ - if (rb_parent && vma_merge(mm, prev, rb_parent, addr, addr + len, - flags, NULL, 0)) -@@ -1409,6 +1701,13 @@ - vma->vm_start = addr; - vma->vm_end = addr + len; - vma->vm_flags = flags; -+ -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (!(current->flags & PF_PAX_PAGEEXEC) && (flags & (VM_READ|VM_WRITE))) -+ vma->vm_page_prot = protection_map[(flags | VM_EXEC) & 0x0f]; -+ else -+#endif -+ - vma->vm_page_prot = protection_map[flags & 0x0f]; - vma->vm_ops = NULL; - vma->vm_pgoff = 0; -diff -urN linux-2.6.5/mm/mprotect.c linux-2.6.5/mm/mprotect.c ---- linux-2.6.5/mm/mprotect.c 2004-04-03 22:38:28.000000000 -0500 -+++ linux-2.6.5/mm/mprotect.c 2004-04-18 11:05:51.000000000 -0400 -@@ -16,6 +16,12 @@ - #include <linux/fs.h> - #include <linux/highmem.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> -+ -+#ifdef CONFIG_PAX_MPROTECT -+#include <linux/elf.h> -+#include <linux/fs.h> -+#endif - - #include <asm/uaccess.h> - #include <asm/pgalloc.h> -@@ -150,6 +156,46 @@ - return 1; - } - -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, -+ unsigned long start, unsigned long end, unsigned int newflags); -+ -+static int mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, -+ unsigned long start, unsigned long end, unsigned int newflags) -+{ -+ if (vma->vm_flags & VM_MIRROR) { -+ struct vm_area_struct * vma_m, * prev_m; -+ unsigned long start_m, end_m; -+ int error; -+ -+ start_m = vma->vm_start + (unsigned long)vma->vm_private_data; -+ vma_m = find_vma_prev(vma->vm_mm, start_m, &prev_m); -+ if (vma_m && vma_m->vm_start == start_m && (vma_m->vm_flags & VM_MIRROR)) { -+ start_m = start + (unsigned long)vma->vm_private_data; -+ end_m = end + (unsigned long)vma->vm_private_data; -+ if ((current->flags & PF_PAX_SEGMEXEC) && !(newflags & VM_EXEC)) -+ error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, vma_m->vm_flags & ~(PROT_READ | PROT_WRITE | PROT_EXEC)); -+ else -+ error = __mprotect_fixup(vma_m, &prev_m, start_m, end_m, newflags); -+ if (error) -+ return error; -+ } else { -+ printk("PAX: VMMIRROR: mprotect bug in %s, %08lx\n", current->comm, vma->vm_start); -+ return -ENOMEM; -+ } -+ } -+ -+ return __mprotect_fixup(vma, pprev, start, end, newflags); -+} -+ -+static int __mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, -+ unsigned long start, unsigned long end, unsigned int newflags) -+{ -+ struct mm_struct * mm = vma->vm_mm; -+ unsigned long charged = 0; -+ pgprot_t newprot; -+ int error; -+#else - static int - mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, - unsigned long start, unsigned long end, unsigned int newflags) -@@ -163,6 +209,7 @@ - *pprev = vma; - return 0; - } -+#endif - - /* - * If we make a private mapping writable we increase our commit; -@@ -182,6 +229,12 @@ - } - } - -+#ifdef CONFIG_PAX_PAGEEXEC -+ if (!(current->flags & PF_PAX_PAGEEXEC) && (newflags & (VM_READ|VM_WRITE))) -+ newprot = protection_map[(newflags | VM_EXEC) & 0xf]; -+ else -+#endif -+ - newprot = protection_map[newflags & 0xf]; - - if (start == vma->vm_start) { -@@ -222,6 +275,69 @@ - return error; - } - -+#ifdef CONFIG_PAX_MPROTECT -+/* PaX: non-PIC ELF libraries need relocations on their executable segments -+ * therefore we'll grant them VM_MAYWRITE once during their life. -+ * -+ * The checks favour ld-linux.so behaviour which operates on a per ELF segment -+ * basis because we want to allow the common case and not the special ones. -+ */ -+static inline void pax_handle_maywrite(struct vm_area_struct * vma, unsigned long start) -+{ -+ struct elfhdr elf_h; -+ struct elf_phdr elf_p, p_dyn; -+ elf_dyn dyn; -+ unsigned long i, j = 65536UL / sizeof(struct elf_phdr); -+ -+#ifndef CONFIG_PAX_NOELFRELOCS -+ if ((vma->vm_start != start) || -+ !vma->vm_file || -+ !(vma->vm_flags & VM_MAYEXEC) || -+ (vma->vm_flags & VM_MAYNOTWRITE)) -+#endif -+ -+ return; -+ -+ if (0 > kernel_read(vma->vm_file, 0UL, (char*)&elf_h, sizeof(elf_h)) || -+ memcmp(elf_h.e_ident, ELFMAG, SELFMAG) || -+ -+#ifdef CONFIG_PAX_ETEXECRELOCS -+ (elf_h.e_type != ET_DYN && elf_h.e_type != ET_EXEC) || -+#else -+ elf_h.e_type != ET_DYN || -+#endif -+ -+ !elf_check_arch(&elf_h) || -+ elf_h.e_phentsize != sizeof(struct elf_phdr) || -+ elf_h.e_phnum > j) -+ return; -+ -+ for (i = 0UL; i < elf_h.e_phnum; i++) { -+ if (0 > kernel_read(vma->vm_file, elf_h.e_phoff + i*sizeof(elf_p), (char*)&elf_p, sizeof(elf_p))) -+ return; -+ if (elf_p.p_type == PT_DYNAMIC) { -+ p_dyn = elf_p; -+ j = i; -+ } -+ } -+ if (elf_h.e_phnum <= j) -+ return; -+ -+ i = 0UL; -+ do { -+ if (0 > kernel_read(vma->vm_file, p_dyn.p_offset + i*sizeof(dyn), (char*)&dyn, sizeof(dyn))) -+ return; -+ if (dyn.d_tag == DT_TEXTREL || (dyn.d_tag == DT_FLAGS && (dyn.d_un.d_val & DF_TEXTREL))) { -+ vma->vm_flags |= VM_MAYWRITE | VM_MAYNOTWRITE; -+ gr_log_textrel(vma); -+ return; -+ } -+ i++; -+ } while (dyn.d_tag != DT_NULL); -+ return; -+} -+#endif -+ - asmlinkage long - sys_mprotect(unsigned long start, size_t len, unsigned long prot) - { -@@ -239,6 +355,17 @@ - end = start + len; - if (end < start) - return -ENOMEM; -+ -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) { -+ if (end > SEGMEXEC_TASK_SIZE) -+ return -EINVAL; -+ } else -+#endif -+ -+ if (end > TASK_SIZE) -+ return -EINVAL; -+ - if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC | PROT_SEM)) - return -EINVAL; - if (end == start) -@@ -271,6 +398,16 @@ - } - } - -+ if (!gr_acl_handle_mprotect(vma->vm_file, prot)) { -+ error = -EACCES; -+ goto out; -+ } -+ -+#ifdef CONFIG_PAX_MPROTECT -+ if ((current->flags & PF_PAX_MPROTECT) && (prot & PROT_WRITE)) -+ pax_handle_maywrite(vma, start); -+#endif -+ - for (nstart = start ; ; ) { - unsigned int newflags; - int last = 0; -@@ -289,6 +426,12 @@ - goto out; - } - -+#ifdef CONFIG_PAX_MPROTECT -+ /* PaX: disallow write access after relocs are done, hopefully noone else needs it... */ -+ if ((current->flags & PF_PAX_MPROTECT) && (prot & PROT_WRITE) && (vma->vm_flags & VM_MAYNOTWRITE)) -+ newflags &= ~VM_MAYWRITE; -+#endif -+ - error = security_file_mprotect(vma, prot); - if (error) - goto out; -diff -urN linux-2.6.5/mm/mremap.c linux-2.6.5/mm/mremap.c ---- linux-2.6.5/mm/mremap.c 2004-04-03 22:37:23.000000000 -0500 -+++ linux-2.6.5/mm/mremap.c 2004-04-18 11:05:51.000000000 -0400 -@@ -329,6 +329,18 @@ - if (!new_len) - goto out; - -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) { -+ if (new_len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-new_len || -+ old_len > SEGMEXEC_TASK_SIZE || addr > SEGMEXEC_TASK_SIZE-old_len) -+ goto out; -+ } else -+#endif -+ -+ if (new_len > TASK_SIZE || addr > TASK_SIZE-new_len || -+ old_len > TASK_SIZE || addr > TASK_SIZE-old_len) -+ goto out; -+ - /* new_addr is only valid if MREMAP_FIXED is specified */ - if (flags & MREMAP_FIXED) { - if (new_addr & ~PAGE_MASK) -@@ -336,6 +348,13 @@ - if (!(flags & MREMAP_MAYMOVE)) - goto out; - -+#ifdef CONFIG_PAX_SEGMEXEC -+ if (current->flags & PF_PAX_SEGMEXEC) { -+ if (new_len > SEGMEXEC_TASK_SIZE || new_addr > SEGMEXEC_TASK_SIZE-new_len) -+ goto out; -+ } else -+#endif -+ - if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len) - goto out; - -@@ -379,6 +398,16 @@ - ret = -EINVAL; - goto out; - } -+ -+#if defined(CONFIG_PAX_SEGMEXEC) || defined(CONFIG_PAX_RANDEXEC) -+ if ((current->flags & (PF_PAX_SEGMEXEC | PF_PAX_RANDEXEC)) && -+ (vma->vm_flags & VM_MIRROR)) -+ { -+ ret = -EINVAL; -+ goto out; -+ } -+#endif -+ - /* We can't remap across vm area boundaries */ - if (old_len > vma->vm_end - addr) - goto out; -diff -urN linux-2.6.5/net/ipv4/af_inet.c linux-2.6.5/net/ipv4/af_inet.c ---- linux-2.6.5/net/ipv4/af_inet.c 2004-04-03 22:36:24.000000000 -0500 -+++ linux-2.6.5/net/ipv4/af_inet.c 2004-04-18 11:05:52.000000000 -0400 -@@ -87,6 +87,7 @@ - #include <linux/init.h> - #include <linux/poll.h> - #include <linux/netfilter_ipv4.h> -+#include <linux/grsecurity.h> - - #include <asm/uaccess.h> - #include <asm/system.h> -@@ -387,7 +388,12 @@ - else - inet->pmtudisc = IP_PMTUDISC_WANT; - -- inet->id = 0; -+#ifdef CONFIG_GRKERNSEC_RANDID -+ if (grsec_enable_randid) -+ inet->id = htons(ip_randomid()); -+ else -+#endif -+ inet->id = 0; - - sock_init_data(sock, sk); - sk_set_owner(sk, THIS_MODULE); -diff -urN linux-2.6.5/net/ipv4/ip_output.c linux-2.6.5/net/ipv4/ip_output.c ---- linux-2.6.5/net/ipv4/ip_output.c 2004-04-03 22:38:22.000000000 -0500 -+++ linux-2.6.5/net/ipv4/ip_output.c 2004-04-18 11:05:52.000000000 -0400 -@@ -64,6 +64,7 @@ - #include <linux/proc_fs.h> - #include <linux/stat.h> - #include <linux/init.h> -+#include <linux/grsecurity.h> - - #include <net/snmp.h> - #include <net/ip.h> -@@ -1161,6 +1162,12 @@ - iph->tos = inet->tos; - iph->tot_len = htons(skb->len); - iph->frag_off = df; -+ -+#ifdef CONFIG_GRKERNSEC_RANDID -+ if (grsec_enable_randid) -+ iph->id = htons(ip_randomid()); -+ else -+#endif - if (!df) { - __ip_select_ident(iph, &rt->u.dst, 0); - } else { -diff -urN linux-2.6.5/net/ipv4/netfilter/Kconfig linux-2.6.5/net/ipv4/netfilter/Kconfig ---- linux-2.6.5/net/ipv4/netfilter/Kconfig 2004-04-03 22:37:45.000000000 -0500 -+++ linux-2.6.5/net/ipv4/netfilter/Kconfig 2004-04-18 11:05:52.000000000 -0400 -@@ -225,6 +225,21 @@ - - To compile it as a module, choose M here. If unsure, say N. - -+config IP_NF_MATCH_STEALTH -+ tristate "stealth match support" -+ depends on IP_NF_IPTABLES -+ help -+ Enabling this option will drop all syn packets coming to unserved tcp -+ ports as well as all packets coming to unserved udp ports. If you -+ are using your system to route any type of packets (ie. via NAT) -+ you should put this module at the end of your ruleset, since it will -+ drop packets that aren't going to ports that are listening on your -+ machine itself, it doesn't take into account that the packet might be -+ destined for someone on your internal network if you're using NAT for -+ instance. -+ -+ To compile it as a module, choose M here. If unsure, say N. -+ - config IP_NF_MATCH_HELPER - tristate "Helper match support" - depends on IP_NF_CONNTRACK && IP_NF_IPTABLES -diff -urN linux-2.6.5/net/ipv4/netfilter/Makefile linux-2.6.5/net/ipv4/netfilter/Makefile ---- linux-2.6.5/net/ipv4/netfilter/Makefile 2004-04-03 22:36:27.000000000 -0500 -+++ linux-2.6.5/net/ipv4/netfilter/Makefile 2004-04-18 11:05:52.000000000 -0400 -@@ -64,6 +64,8 @@ - obj-$(CONFIG_IP_NF_MATCH_CONNTRACK) += ipt_conntrack.o - obj-$(CONFIG_IP_NF_MATCH_TCPMSS) += ipt_tcpmss.o - -+obj-$(CONFIG_IP_NF_MATCH_STEALTH) += ipt_stealth.o -+ - obj-$(CONFIG_IP_NF_MATCH_PHYSDEV) += ipt_physdev.o - - # targets -diff -urN linux-2.6.5/net/ipv4/netfilter/ipt_stealth.c linux-2.6.5/net/ipv4/netfilter/ipt_stealth.c ---- linux-2.6.5/net/ipv4/netfilter/ipt_stealth.c 1969-12-31 19:00:00.000000000 -0500 -+++ linux-2.6.5/net/ipv4/netfilter/ipt_stealth.c 2004-04-18 11:05:52.000000000 -0400 -@@ -0,0 +1,112 @@ -+/* Kernel module to add stealth support. -+ * -+ * Copyright (C) 2002 Brad Spengler <spender@grsecurity.net> -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/module.h> -+#include <linux/skbuff.h> -+#include <linux/net.h> -+#include <linux/sched.h> -+#include <linux/inet.h> -+#include <linux/stddef.h> -+ -+#include <net/ip.h> -+#include <net/sock.h> -+#include <net/tcp.h> -+#include <net/udp.h> -+#include <net/route.h> -+#include <net/inet_common.h> -+ -+#include <linux/netfilter_ipv4/ip_tables.h> -+ -+MODULE_LICENSE("GPL"); -+ -+extern struct sock *udp_v4_lookup(u32 saddr, u16 sport, u32 daddr, u16 dport, int dif); -+ -+static int -+match(const struct sk_buff *skb, -+ const struct net_device *in, -+ const struct net_device *out, -+ const void *matchinfo, -+ int offset, -+ int *hotdrop) -+{ -+ struct iphdr *ip = skb->nh.iph; -+ struct tcphdr th; -+ struct udphdr uh; -+ struct sock *sk = NULL; -+ -+ if (!ip || offset) return 0; -+ -+ switch(ip->protocol) { -+ case IPPROTO_TCP: -+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &th, sizeof(th)) < 0) { -+ *hotdrop = 1; -+ return 0; -+ } -+ if (!(th.syn && !th.ack)) return 0; -+ sk = tcp_v4_lookup_listener(ip->daddr, ntohs(th.dest), ((struct rtable*)skb->dst)->rt_iif); -+ break; -+ case IPPROTO_UDP: -+ if (skb_copy_bits(skb, skb->nh.iph->ihl*4, &uh, sizeof(uh)) < 0) { -+ *hotdrop = 1; -+ return 0; -+ } -+ sk = udp_v4_lookup(ip->saddr, uh.source, ip->daddr, uh.dest, skb->dev->ifindex); -+ break; -+ default: -+ return 0; -+ } -+ -+ if(!sk) // port is being listened on, match this -+ return 1; -+ else { -+ sock_put(sk); -+ return 0; -+ } -+} -+ -+/* Called when user tries to insert an entry of this type. */ -+static int -+checkentry(const char *tablename, -+ const struct ipt_ip *ip, -+ void *matchinfo, -+ unsigned int matchsize, -+ unsigned int hook_mask) -+{ -+ if (matchsize != IPT_ALIGN(0)) -+ return 0; -+ -+ if(((ip->proto == IPPROTO_TCP && !(ip->invflags & IPT_INV_PROTO)) || -+ ((ip->proto == IPPROTO_UDP) && !(ip->invflags & IPT_INV_PROTO))) -+ && (hook_mask & (1 << NF_IP_LOCAL_IN))) -+ return 1; -+ -+ printk("stealth: Only works on TCP and UDP for the INPUT chain.\n"); -+ -+ return 0; -+} -+ -+ -+static struct ipt_match stealth_match = { -+ .name = "stealth", -+ .match = &match, -+ .checkentry = &checkentry, -+ .destroy = NULL, -+ .me = THIS_MODULE -+}; -+ -+static int __init init(void) -+{ -+ return ipt_register_match(&stealth_match); -+} -+ -+static void __exit fini(void) -+{ -+ ipt_unregister_match(&stealth_match); -+} -+ -+module_init(init); -+module_exit(fini); -diff -urN linux-2.6.5/net/ipv4/tcp_ipv4.c linux-2.6.5/net/ipv4/tcp_ipv4.c ---- linux-2.6.5/net/ipv4/tcp_ipv4.c 2004-04-03 22:36:55.000000000 -0500 -+++ linux-2.6.5/net/ipv4/tcp_ipv4.c 2004-04-18 11:05:52.000000000 -0400 -@@ -62,6 +62,7 @@ - #include <linux/jhash.h> - #include <linux/init.h> - #include <linux/times.h> -+#include <linux/grsecurity.h> - - #include <net/icmp.h> - #include <net/tcp.h> -@@ -224,9 +225,16 @@ - spin_lock(&tcp_portalloc_lock); - rover = tcp_port_rover; - do { -- rover++; -- if (rover < low || rover > high) -- rover = low; -+#ifdef CONFIG_GRKERNSEC_RANDSRC -+ if (grsec_enable_randsrc && (high > low)) { -+ rover = low + (get_random_long() % (high - low)); -+ } else -+#endif -+ { -+ rover++; -+ if (rover < low || rover > high) -+ rover = low; -+ } - head = &tcp_bhash[tcp_bhashfn(rover)]; - spin_lock(&head->lock); - tb_for_each(tb, node, &head->chain) -@@ -537,6 +545,11 @@ - - static inline __u32 tcp_v4_init_sequence(struct sock *sk, struct sk_buff *skb) - { -+#ifdef CONFIG_GRKERNSEC_RANDISN -+ if (likely(grsec_enable_randisn)) -+ return ip_randomisn(); -+ else -+#endif - return secure_tcp_sequence_number(skb->nh.iph->daddr, - skb->nh.iph->saddr, - skb->h.th->dest, -@@ -671,10 +684,17 @@ - rover = tcp_port_rover; - - do { -- rover++; -- if ((rover < low) || (rover > high)) -- rover = low; -- head = &tcp_bhash[tcp_bhashfn(rover)]; -+#ifdef CONFIG_GRKERNSEC_RANDSRC -+ if (grsec_enable_randsrc && (high > low)) { -+ rover = low + (get_random_long() % (high - low)); -+ } else -+#endif -+ { -+ rover++; -+ if ((rover < low) || (rover > high)) -+ rover = low; -+ } -+ head = &tcp_bhash[tcp_bhashfn(rover)]; - spin_lock(&head->lock); - - /* Does not bother with rcv_saddr checks, -@@ -724,6 +744,15 @@ - } - spin_unlock(&head->lock); - -+#ifdef CONFIG_GRKERNSEC -+ gr_del_task_from_ip_table(current); -+ current->gr_saddr = inet_sk(sk)->rcv_saddr; -+ current->gr_daddr = inet_sk(sk)->daddr; -+ current->gr_sport = inet_sk(sk)->sport; -+ current->gr_dport = inet_sk(sk)->dport; -+ gr_add_to_task_ip_table(current); -+#endif -+ - if (tw) { - tcp_tw_deschedule(tw); - tcp_tw_put(tw); -@@ -843,13 +872,24 @@ - tcp_v4_setup_caps(sk, &rt->u.dst); - tp->ext2_header_len = rt->u.dst.header_len; - -- if (!tp->write_seq) -+ if (!tp->write_seq) { -+#ifdef CONFIG_GRKERNSEC_RANDISN -+ if (likely(grsec_enable_randisn)) -+ tp->write_seq = ip_randomisn(); -+ else -+#endif - tp->write_seq = secure_tcp_sequence_number(inet->saddr, - inet->daddr, - inet->sport, - usin->sin_port); -+ } - -- inet->id = tp->write_seq ^ jiffies; -+#ifdef CONFIG_GRKERNSEC_RANDID -+ if (grsec_enable_randid) -+ inet->id = htons(ip_randomid()); -+ else -+#endif -+ inet->id = tp->write_seq ^ jiffies; - - err = tcp_connect(sk); - rt = NULL; -@@ -1593,7 +1633,13 @@ - if (newinet->opt) - newtp->ext_header_len = newinet->opt->optlen; - newtp->ext2_header_len = dst->header_len; -- newinet->id = newtp->write_seq ^ jiffies; -+ -+#ifdef CONFIG_GRKERNSEC_RANDID -+ if (grsec_enable_randid) -+ newinet->id = htons(ip_randomid()); -+ else -+#endif -+ newinet->id = newtp->write_seq ^ jiffies; - - tcp_sync_mss(newsk, dst_pmtu(dst)); - newtp->advmss = dst_metric(dst, RTAX_ADVMSS); -diff -urN linux-2.6.5/net/ipv4/udp.c linux-2.6.5/net/ipv4/udp.c ---- linux-2.6.5/net/ipv4/udp.c 2004-04-03 22:36:25.000000000 -0500 -+++ linux-2.6.5/net/ipv4/udp.c 2004-04-18 11:05:52.000000000 -0400 -@@ -100,6 +100,7 @@ - #include <linux/skbuff.h> - #include <linux/proc_fs.h> - #include <linux/seq_file.h> -+#include <linux/grsecurity.h> - #include <net/sock.h> - #include <net/udp.h> - #include <net/icmp.h> -@@ -108,6 +109,12 @@ - #include <net/checksum.h> - #include <net/xfrm.h> - -+extern int gr_search_udp_recvmsg(const struct sock *sk, -+ const struct sk_buff *skb); -+extern int gr_search_udp_sendmsg(const struct sock *sk, -+ const struct sockaddr_in *addr); -+ -+ - /* - * Snmp MIB for the UDP layer - */ -@@ -538,9 +545,16 @@ - dport = usin->sin_port; - if (dport == 0) - return -EINVAL; -+ -+ if (!gr_search_udp_sendmsg(sk, usin)) -+ return -EPERM; - } else { - if (sk->sk_state != TCP_ESTABLISHED) - return -EDESTADDRREQ; -+ -+ if (!gr_search_udp_sendmsg(sk, NULL)) -+ return -EPERM; -+ - daddr = inet->daddr; - dport = inet->dport; - /* Open fast path for connected socket. -@@ -792,7 +806,12 @@ - if (!skb) - goto out; - -- copied = skb->len - sizeof(struct udphdr); -+ if (!gr_search_udp_recvmsg(sk, skb)) { -+ err = -EPERM; -+ goto out_free; -+ } -+ -+ copied = skb->len - sizeof(struct udphdr); - if (copied > len) { - copied = len; - msg->msg_flags |= MSG_TRUNC; -@@ -901,7 +920,12 @@ - inet->daddr = rt->rt_dst; - inet->dport = usin->sin_port; - sk->sk_state = TCP_ESTABLISHED; -- inet->id = jiffies; -+#ifdef CONFIG_GRKERNSEC_RANDID -+ if (grsec_enable_randid) -+ inet->id = htons(ip_randomid()); -+ else -+#endif -+ inet->id = jiffies; - - sk_dst_set(sk, &rt->u.dst); - return(0); -diff -urN linux-2.6.5/net/socket.c linux-2.6.5/net/socket.c ---- linux-2.6.5/net/socket.c 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/net/socket.c 2004-04-18 11:05:51.000000000 -0400 -@@ -81,6 +81,7 @@ - #include <linux/syscalls.h> - #include <linux/compat.h> - #include <linux/kmod.h> -+#include <linux/in.h> - - #ifdef CONFIG_NET_RADIO - #include <linux/wireless.h> /* Note : will define WIRELESS_EXT */ -@@ -92,6 +93,18 @@ - #include <net/sock.h> - #include <linux/netfilter.h> - -+extern void gr_attach_curr_ip(const struct sock *sk); -+extern int gr_handle_sock_all(const int family, const int type, -+ const int protocol); -+extern int gr_handle_sock_server(const struct sockaddr *sck); -+extern int gr_handle_sock_client(const struct sockaddr *sck); -+extern int gr_search_connect(const struct socket * sock, -+ const struct sockaddr_in * addr); -+extern int gr_search_bind(const struct socket * sock, -+ const struct sockaddr_in * addr); -+extern int gr_search_socket(const int domain, const int type, -+ const int protocol); -+ - static int sock_no_open(struct inode *irrelevant, struct file *dontcare); - static ssize_t sock_aio_read(struct kiocb *iocb, char __user *buf, - size_t size, loff_t pos); -@@ -872,6 +885,7 @@ - printk(KERN_DEBUG "sock_close: NULL inode\n"); - return 0; - } -+ - sock_fasync(-1, filp, 0); - sock_release(SOCKET_I(inode)); - return 0; -@@ -1092,6 +1106,16 @@ - int retval; - struct socket *sock; - -+ if(!gr_search_socket(family, type, protocol)) { -+ retval = -EACCES; -+ goto out; -+ } -+ -+ if (gr_handle_sock_all(family, type, protocol)) { -+ retval = -EACCES; -+ goto out; -+ } -+ - retval = sock_create(family, type, protocol, &sock); - if (retval < 0) - goto out; -@@ -1187,11 +1211,23 @@ - { - struct socket *sock; - char address[MAX_SOCK_ADDR]; -+ struct sockaddr *sck; - int err; - - if((sock = sockfd_lookup(fd,&err))!=NULL) - { - if((err=move_addr_to_kernel(umyaddr,addrlen,address))>=0) { -+ sck = (struct sockaddr *)address; -+ if (!gr_search_bind(sock, (struct sockaddr_in *)sck)) { -+ sockfd_put(sock); -+ return -EACCES; -+ } -+ -+ if (gr_handle_sock_server(sck)) { -+ sockfd_put(sock); -+ return -EACCES; -+ } -+ - err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); - if (err) { - sockfd_put(sock); -@@ -1294,6 +1330,7 @@ - goto out_release; - - security_socket_post_accept(sock, newsock); -+ gr_attach_curr_ip(newsock->sk); - - out_put: - sockfd_put(sock); -@@ -1321,6 +1358,7 @@ - { - struct socket *sock; - char address[MAX_SOCK_ADDR]; -+ struct sockaddr *sck; - int err; - - sock = sockfd_lookup(fd, &err); -@@ -1330,6 +1368,18 @@ - if (err < 0) - goto out_put; - -+ sck = (struct sockaddr *)address; -+ -+ if (!gr_search_connect(sock, (struct sockaddr_in *)sck)) { -+ err = -EACCES; -+ goto out_put; -+ } -+ -+ if (gr_handle_sock_client(sck)) { -+ err = -EACCES; -+ goto out_put; -+ } -+ - err = security_socket_connect(sock, (struct sockaddr *)address, addrlen); - if (err) - goto out_put; -@@ -1583,6 +1633,7 @@ - err=sock->ops->shutdown(sock, how); - sockfd_put(sock); - } -+ - return err; - } - -diff -urN linux-2.6.5/net/sunrpc/xprt.c linux-2.6.5/net/sunrpc/xprt.c ---- linux-2.6.5/net/sunrpc/xprt.c 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/net/sunrpc/xprt.c 2004-04-18 11:05:52.000000000 -0400 -@@ -58,6 +58,7 @@ - #include <linux/file.h> - #include <linux/workqueue.h> - #include <linux/random.h> -+#include <linux/grsecurity.h> - - #include <net/sock.h> - #include <net/checksum.h> -@@ -1322,6 +1323,12 @@ - */ - static inline u32 xprt_alloc_xid(struct rpc_xprt *xprt) - { -+ -+#ifdef CONFIG_GRKERNSEC_RANDRPC -+ if (grsec_enable_randrpc) -+ return (u32) get_random_long(); -+#endif -+ - return xprt->xid++; - } - -diff -urN linux-2.6.5/net/unix/af_unix.c linux-2.6.5/net/unix/af_unix.c ---- linux-2.6.5/net/unix/af_unix.c 2004-04-03 22:37:36.000000000 -0500 -+++ linux-2.6.5/net/unix/af_unix.c 2004-04-18 11:05:52.000000000 -0400 -@@ -120,6 +120,7 @@ - #include <linux/mount.h> - #include <net/checksum.h> - #include <linux/security.h> -+#include <linux/grsecurity.h> - - int sysctl_unix_max_dgram_qlen = 10; - -@@ -683,6 +684,11 @@ - if (err) - goto put_fail; - -+ if (!gr_acl_handle_unix(nd.dentry, nd.mnt)) { -+ err = -EACCES; -+ goto put_fail; -+ } -+ - err = -ECONNREFUSED; - if (!S_ISSOCK(nd.dentry->d_inode->i_mode)) - goto put_fail; -@@ -706,6 +712,13 @@ - if (u) { - struct dentry *dentry; - dentry = unix_sk(u)->dentry; -+ -+ if (!gr_handle_chroot_unix(u->sk_peercred.pid)) { -+ err = -EPERM; -+ sock_put(u); -+ goto fail; -+ } -+ - if (dentry) - touch_atime(unix_sk(u)->mnt, dentry); - } else -@@ -805,9 +818,18 @@ - */ - mode = S_IFSOCK | - (SOCK_INODE(sock)->i_mode & ~current->fs->umask); -+ -+ if (!gr_acl_handle_mknod(dentry, nd.dentry, nd.mnt, mode)) { -+ err = -EACCES; -+ goto out_mknod_dput; -+ } -+ - err = vfs_mknod(nd.dentry->d_inode, dentry, mode, 0); - if (err) - goto out_mknod_dput; -+ -+ gr_handle_create(dentry, nd.mnt); -+ - up(&nd.dentry->d_inode->i_sem); - dput(nd.dentry); - nd.dentry = dentry; -@@ -825,6 +847,10 @@ - goto out_unlock; - } - -+#ifdef CONFIG_GRKERNSEC_CHROOT_UNIX -+ sk->sk_peercred.pid = current->pid; -+#endif -+ - list = &unix_socket_table[addr->hash]; - } else { - list = &unix_socket_table[dentry->d_inode->i_ino & (UNIX_HASH_SIZE-1)]; -diff -urN linux-2.6.5/security/Kconfig linux-2.6.5/security/Kconfig ---- linux-2.6.5/security/Kconfig 2004-04-03 22:37:37.000000000 -0500 -+++ linux-2.6.5/security/Kconfig 2004-04-18 11:05:52.000000000 -0400 -@@ -4,6 +4,407 @@ - - menu "Security options" - -+source grsecurity/Kconfig -+ -+menu "PaX" -+ -+config PAX -+ bool "Enable various PaX features" -+ depends on ALPHA || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || SPARC32 || SPARC64 || X86 || X86_64 -+ help -+ This allows you to enable various PaX features. PaX adds -+ intrusion prevention mechanisms to the kernel that reduce -+ the risks posed by exploitable memory corruption bugs. -+ -+menu "PaX Control" -+ depends on PAX -+ -+config PAX_SOFTMODE -+ bool 'Support soft mode' -+ help -+ Enabling this option will allow you to run PaX in soft mode, that -+ is, PaX features will not be enforced by default, only on executables -+ marked explicitly. You must also enable PT_PAX_FLAGS support as it -+ is the only way to mark executables for soft mode use. -+ -+ Soft mode can be activated by using the "pax_softmode=1" kernel command -+ line option on boot. Furthermore you can control various PaX features -+ at runtime via the entries in /proc/sys/kernel/pax. -+ -+config PAX_EI_PAX -+ bool 'Use legacy ELF header marking' -+ help -+ Enabling this option will allow you to control PaX features on -+ a per executable basis via the 'chpax' utility available at -+ http://pax.grsecurity.net/. The control flags will be read from -+ an otherwise reserved part of the ELF header. This marking has -+ numerous drawbacks (no support for soft-mode, toolchain does not -+ know about the non-standard use of the ELF header) therefore it -+ has been deprecated in favour of PT_PAX_FLAGS support. -+ -+ You should enable this option only if your toolchain does not yet -+ support the new control flag location (PT_PAX_FLAGS) or you still -+ have applications not marked by PT_PAX_FLAGS. -+ -+ Note that if you enable PT_PAX_FLAGS marking support as well, -+ it will override the legacy EI_PAX marks. -+ -+config PAX_PT_PAX_FLAGS -+ bool 'Use ELF program header marking' -+ help -+ Enabling this option will allow you to control PaX features on -+ a per executable basis via the 'paxctl' utility available at -+ http://pax.grsecurity.net/. The control flags will be read from -+ a PaX specific ELF program header (PT_PAX_FLAGS). This marking -+ has the benefits of supporting both soft mode and being fully -+ integrated into the toolchain (the binutils patch is available -+ from http://pax.grsecurity.net). -+ -+ Note that if you enable the legacy EI_PAX marking support as well, -+ it will be overridden by the PT_PAX_FLAGS marking. -+ -+choice -+ prompt 'MAC system integration' -+ default PAX_NO_ACL_FLAGS -+ help -+ Mandatory Access Control systems have the option of controlling -+ PaX flags on a per executable basis, choose the method supported -+ by your particular system. -+ -+ - "none": if your MAC system does not interact with PaX, -+ - "direct": if your MAC system defines pax_set_flags() itself, -+ - "hook": if your MAC system uses the pax_set_flags_func callback. -+ -+ NOTE: this option is for developers/integrators only. -+ -+config PAX_NO_ACL_FLAGS -+ bool 'none' -+ -+config PAX_HAVE_ACL_FLAGS -+ bool 'direct' -+ -+config PAX_HOOK_ACL_FLAGS -+ bool 'hook' -+endchoice -+ -+endmenu -+ -+menu "Non-executable pages" -+ depends on PAX -+ -+config PAX_NOEXEC -+ bool "Enforce non-executable pages" -+ depends on (PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS) && (ALPHA || IA64 || MIPS32 || MIPS64 || PARISC || PPC32 || SPARC32 || SPARC64 || X86 || X86_64) -+ help -+ By design some architectures do not allow for protecting memory -+ pages against execution or even if they do, Linux does not make -+ use of this feature. In practice this means that if a page is -+ readable (such as the stack or heap) it is also executable. -+ -+ There is a well known exploit technique that makes use of this -+ fact and a common programming mistake where an attacker can -+ introduce code of his choice somewhere in the attacked program's -+ memory (typically the stack or the heap) and then execute it. -+ -+ If the attacked program was running with different (typically -+ higher) privileges than that of the attacker, then he can elevate -+ his own privilege level (e.g. get a root shell, write to files for -+ which he does not have write access to, etc). -+ -+ Enabling this option will let you choose from various features -+ that prevent the injection and execution of 'foreign' code in -+ a program. -+ -+ This will also break programs that rely on the old behaviour and -+ expect that dynamically allocated memory via the malloc() family -+ of functions is executable (which it is not). Notable examples -+ are the XFree86 4.x server, the java runtime and wine. -+ -+config PAX_PAGEEXEC -+ bool "Paging based non-executable pages" -+ depends on PAX_NOEXEC && !HIGHPTE && (!X86 || X86_64 || M586 || M586TSC || M586MMX || M686 || MPENTIUMII || MPENTIUMIII || MPENTIUM4 || MK7 || MK8) -+ help -+ This implementation is based on the paging feature of the CPU. -+ On i386 it has a variable performance impact on applications -+ depending on their memory usage pattern. You should carefully -+ test your applications before using this feature in production. -+ On alpha, ia64, parisc, sparc, sparc64 and x86_64 there is no -+ performance impact. On ppc there is a slight performance impact. -+ -+config PAX_SEGMEXEC -+ bool "Segmentation based non-executable pages" -+ depends on PAX_NOEXEC && X86 && !X86_64 -+ help -+ This implementation is based on the segmentation feature of the -+ CPU and has little performance impact, however applications will -+ be limited to a 1.5 GB address space instead of the normal 3 GB. -+ -+config PAX_EMUTRAMP -+ bool "Emulate trampolines" if (PAX_PAGEEXEC || PAX_SEGMEXEC) && (PARISC || PPC || X86) && !X86_64 -+ default y if PARISC || PPC -+ help -+ There are some programs and libraries that for one reason or -+ another attempt to execute special small code snippets from -+ non-executable memory pages. Most notable examples are the -+ signal handler return code generated by the kernel itself and -+ the GCC trampolines. -+ -+ If you enabled CONFIG_PAX_PAGEEXEC or CONFIG_PAX_SEGMEXEC then -+ such programs will no longer work under your kernel. -+ -+ As a remedy you can say Y here and use the 'chpax' or 'paxctl' -+ utilities to enable trampoline emulation for the affected programs -+ yet still have the protection provided by the non-executable pages. -+ -+ On parisc and ppc you MUST enable this option and EMUSIGRT as -+ well, otherwise your system will not even boot. -+ -+ Alternatively you can say N here and use the 'chpax' or 'paxctl' -+ utilities to disable CONFIG_PAX_PAGEEXEC and CONFIG_PAX_SEGMEXEC -+ for the affected files. -+ -+ NOTE: enabling this feature *may* open up a loophole in the -+ protection provided by non-executable pages that an attacker -+ could abuse. Therefore the best solution is to not have any -+ files on your system that would require this option. This can -+ be achieved by not using libc5 (which relies on the kernel -+ signal handler return code) and not using or rewriting programs -+ that make use of the nested function implementation of GCC. -+ Skilled users can just fix GCC itself so that it implements -+ nested function calls in a way that does not interfere with PaX. -+ -+config PAX_EMUSIGRT -+ bool "Automatically emulate sigreturn trampolines" -+ depends on PAX_EMUTRAMP && (PARISC || PPC) -+ default y -+ help -+ Enabling this option will have the kernel automatically detect -+ and emulate signal return trampolines executing on the stack -+ that would otherwise lead to task termination. -+ -+ This solution is intended as a temporary one for users with -+ legacy versions of libc (libc5, glibc 2.0, uClibc before 0.9.17, -+ Modula-3 runtime, etc) or executables linked to such, basically -+ everything that does not specify its own SA_RESTORER function in -+ normal executable memory like glibc 2.1+ does. -+ -+ On parisc and ppc you MUST enable this option, otherwise your -+ system will not even boot. -+ -+ NOTE: this feature cannot be disabled on a per executable basis -+ and since it *does* open up a loophole in the protection provided -+ by non-executable pages, the best solution is to not have any -+ files on your system that would require this option. -+ -+config PAX_MPROTECT -+ bool "Restrict mprotect()" -+ depends on PAX_PAGEEXEC || PAX_SEGMEXEC -+ help -+ Enabling this option will prevent programs from -+ - changing the executable status of memory pages that were -+ not originally created as executable, -+ - making read-only executable pages writable again, -+ - creating executable pages from anonymous memory. -+ -+ You should say Y here to complete the protection provided by -+ the enforcement of non-executable pages. -+ -+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control -+ this feature on a per file basis. -+ -+config PAX_NOELFRELOCS -+ bool "Disallow ELF text relocations" -+ depends on PAX_MPROTECT && (IA64 || X86 || X86_64) -+ help -+ Non-executable pages and mprotect() restrictions are effective -+ in preventing the introduction of new executable code into an -+ attacked task's address space. There remain only two venues -+ for this kind of attack: if the attacker can execute already -+ existing code in the attacked task then he can either have it -+ create and mmap() a file containing his code or have it mmap() -+ an already existing ELF library that does not have position -+ independent code in it and use mprotect() on it to make it -+ writable and copy his code there. While protecting against -+ the former approach is beyond PaX, the latter can be prevented -+ by having only PIC ELF libraries on one's system (which do not -+ need to relocate their code). If you are sure this is your case, -+ then enable this option otherwise be careful as you may not even -+ be able to boot or log on your system (for example, some PAM -+ modules are erroneously compiled as non-PIC by default). -+ -+ NOTE: if you are using dynamic ELF executables (as suggested -+ when using ASLR) then you must have made sure that you linked -+ your files using the PIC version of crt1 (the et_dyn.tar.gz package -+ referenced there has already been updated to support this). -+ -+config PAX_ETEXECRELOCS -+ bool "Allow ELF ET_EXEC text relocations" -+ depends on PAX_MPROTECT && (ALPHA || IA64 || PARISC) -+ default y -+ help -+ On some architectures there are incorrectly created applications -+ that require text relocations and would not work without enabling -+ this option. If you are an alpha, ia64 or parisc user, you should -+ enable this option and disable it once you have made sure that -+ none of your applications need it. -+ -+config PAX_EMUPLT -+ bool "Automatically emulate ELF PLT" -+ depends on PAX_MPROTECT && (ALPHA || PARISC || PPC || SPARC32 || SPARC64) -+ default y -+ help -+ Enabling this option will have the kernel automatically detect -+ and emulate the Procedure Linkage Table entries in ELF files. -+ On some architectures such entries are in writable memory, and -+ become non-executable leading to task termination. Therefore -+ it is mandatory that you enable this option on alpha, parisc, ppc, -+ sparc and sparc64, otherwise your system would not even boot. -+ -+ NOTE: this feature *does* open up a loophole in the protection -+ provided by the non-executable pages, therefore the proper -+ solution is to modify the toolchain to produce a PLT that does -+ not need to be writable. -+ -+config PAX_DLRESOLVE -+ bool -+ depends on PAX_EMUPLT && (SPARC32 || SPARC64) -+ default y -+ -+config PAX_SYSCALL -+ bool -+ depends on PAX_PAGEEXEC && PPC -+ default y -+ -+config PAX_KERNEXEC -+ bool "Enforce non-executable kernel pages" -+ depends on PAX_NOEXEC && X86 && !X86_64 && !MODULES && !HOTPLUG_PCI_COMPAQ_NVRAM -+ help -+ This is the kernel land equivalent of PAGEEXEC and MPROTECT, -+ that is, enabling this option will make it harder to inject -+ and execute 'foreign' code in kernel memory itself. -+ -+endmenu -+ -+menu "Address Space Layout Randomization" -+ depends on PAX -+ -+config PAX_ASLR -+ bool "Address Space Layout Randomization" -+ depends on PAX_EI_PAX || PAX_PT_PAX_FLAGS || PAX_HAVE_ACL_FLAGS || PAX_HOOK_ACL_FLAGS -+ help -+ Many if not most exploit techniques rely on the knowledge of -+ certain addresses in the attacked program. The following options -+ will allow the kernel to apply a certain amount of randomization -+ to specific parts of the program thereby forcing an attacker to -+ guess them in most cases. Any failed guess will most likely crash -+ the attacked program which allows the kernel to detect such attempts -+ and react on them. PaX itself provides no reaction mechanisms, -+ instead it is strongly encouraged that you make use of Nergal's -+ segvguard (ftp://ftp.pl.openwall.com/misc/segvguard/) or grsecurity's -+ (http://www.grsecurity.net/) built-in crash detection features or -+ develop one yourself. -+ -+ By saying Y here you can choose to randomize the following areas: -+ - top of the task's kernel stack -+ - top of the task's userland stack -+ - base address for mmap() requests that do not specify one -+ (this includes all libraries) -+ - base address of the main executable -+ -+ It is strongly recommended to say Y here as address space layout -+ randomization has negligible impact on performance yet it provides -+ a very effective protection. -+ -+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control -+ this feature on a per file basis. -+ -+config PAX_RANDKSTACK -+ bool "Randomize kernel stack base" -+ depends on PAX_ASLR && X86_TSC && !X86_64 -+ help -+ By saying Y here the kernel will randomize every task's kernel -+ stack on every system call. This will not only force an attacker -+ to guess it but also prevent him from making use of possible -+ leaked information about it. -+ -+ Since the kernel stack is a rather scarce resource, randomization -+ may cause unexpected stack overflows, therefore you should very -+ carefully test your system. Note that once enabled in the kernel -+ configuration, this feature cannot be disabled on a per file basis. -+ -+config PAX_RANDUSTACK -+ bool "Randomize user stack base" -+ depends on PAX_ASLR -+ help -+ By saying Y here the kernel will randomize every task's userland -+ stack. The randomization is done in two steps where the second -+ one may apply a big amount of shift to the top of the stack and -+ cause problems for programs that want to use lots of memory (more -+ than 2.5 GB if SEGMEXEC is not active, or 1.25 GB when it is). -+ For this reason the second step can be controlled by 'chpax' or -+ 'paxctl' on a per file basis. -+ -+config PAX_RANDMMAP -+ bool "Randomize mmap() base" -+ depends on PAX_ASLR -+ help -+ By saying Y here the kernel will use a randomized base address for -+ mmap() requests that do not specify one themselves. As a result -+ all dynamically loaded libraries will appear at random addresses -+ and therefore be harder to exploit by a technique where an attacker -+ attempts to execute library code for his purposes (e.g. spawn a -+ shell from an exploited program that is running at an elevated -+ privilege level). -+ -+ Furthermore, if a program is relinked as a dynamic ELF file, its -+ base address will be randomized as well, completing the full -+ randomization of the address space layout. Attacking such programs -+ becomes a guess game. You can find an example of doing this at -+ http://pax.grsecurity.net/et_dyn.tar.gz and practical samples at -+ http://www.grsecurity.net/grsec-gcc-specs.tar.gz . -+ -+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control this -+ feature on a per file basis. -+ -+config PAX_RANDEXEC -+ bool "Randomize ET_EXEC base" -+ depends on PAX_MPROTECT && PAX_RANDMMAP -+ help -+ By saying Y here the kernel will randomize the base address of normal -+ ET_EXEC ELF executables as well. This is accomplished by mapping the -+ executable in memory in a special way which also allows for detecting -+ attackers who attempt to execute its code for their purposes. Since -+ this special mapping causes performance degradation and the attack -+ detection may create false alarms as well, you should carefully test -+ your executables when this feature is enabled. -+ -+ This solution is intended only as a temporary one until you relink -+ your programs as a dynamic ELF file. -+ -+ NOTE: you can use the 'chpax' or 'paxctl' utilities to control this -+ feature on a per file basis. -+ -+config PAX_NOVSYSCALL -+ bool "Disable the vsyscall page" -+ depends on PAX_ASLR && X86 && !X86_64 -+ help -+ The Linux 2.6 kernel introduced a new feature that speeds up or -+ simplifies certain operations, such as system calls or returns -+ from signal handlers. -+ -+ Unfortunately the implementation also gives a powerful instrument -+ into the hands of exploit writers: the so-called vsyscall page exists -+ in every task at the same fixed address and it contains machine code -+ that is very useful in performing the return-to-libc style attack. -+ -+ Since this exploit technique cannot in general be protected against -+ via kernel solutions, this option will allow you to disable the use -+ of the vsyscall page and revert back to the old behaviour. -+ -+endmenu -+ -+endmenu -+ - config SECURITY - bool "Enable different security models" - help -diff -urN linux-2.6.5/security/commoncap.c linux-2.6.5/security/commoncap.c ---- linux-2.6.5/security/commoncap.c 2004-04-03 22:36:56.000000000 -0500 -+++ linux-2.6.5/security/commoncap.c 2004-04-18 11:05:52.000000000 -0400 -@@ -27,7 +27,7 @@ - int cap_capable (struct task_struct *tsk, int cap) - { - /* Derived from include/linux/sched.h:capable. */ -- if (cap_raised (tsk->cap_effective, cap)) -+ if (cap_raised (tsk->cap_effective, cap) && gr_task_is_capable(tsk, cap)) - return 0; - else - return -EPERM; -@@ -37,7 +37,7 @@ - { - /* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */ - if (!cap_issubset (child->cap_permitted, current->cap_permitted) && -- !capable (CAP_SYS_PTRACE)) -+ !capable_nolog (CAP_SYS_PTRACE)) - return -EPERM; - else - return 0; -@@ -338,7 +338,7 @@ - /* - * Leave the last 3% for root - */ -- if (!capable(CAP_SYS_ADMIN)) -+ if (!capable_nolog(CAP_SYS_ADMIN)) - free -= free / 32; - - if (free > pages) -@@ -349,7 +349,7 @@ - * only call if we're about to fail. - */ - n = nr_free_pages(); -- if (!capable(CAP_SYS_ADMIN)) -+ if (!capable_nolog(CAP_SYS_ADMIN)) - n -= n / 32; - free += n; - -diff -urN linux-2.6.5/security/security.c linux-2.6.5/security/security.c ---- linux-2.6.5/security/security.c 2004-04-03 22:36:13.000000000 -0500 -+++ linux-2.6.5/security/security.c 2004-04-18 11:05:52.000000000 -0400 -@@ -206,4 +206,5 @@ - EXPORT_SYMBOL_GPL(mod_reg_security); - EXPORT_SYMBOL_GPL(mod_unreg_security); - EXPORT_SYMBOL(capable); -+EXPORT_SYMBOL(capable_nolog); - EXPORT_SYMBOL(security_ops); |